This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
magicka/deps/odoors/ODList.c

566 lines
16 KiB
C
Raw Permalink Normal View History

2016-12-03 05:08:50 +00:00
/* OpenDoors Online Software Programming Toolkit
* (C) Copyright 1991 - 1999 by Brian Pirie.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* File: ODList.c
*
* Description: Implements the od_list_files() function for displaying
* a FILES.BBS file.
*
* Revisions: Date Ver Who Change
* ---------------------------------------------------------------
* Oct 13, 1994 6.00 BP New file header format.
* Oct 21, 1994 6.00 BP Further isolated com routines.
* Dec 09, 1994 6.00 BP Use new directory access functions.
* Dec 31, 1994 6.00 BP Remove #ifndef USEINLINE DOS code.
* Aug 19, 1995 6.00 BP 32-bit portability.
* Nov 11, 1995 6.00 BP Moved functions from odcore.c
* Nov 11, 1995 6.00 BP Removed register keyword.
* Nov 16, 1995 6.00 BP Removed oddoor.h, added odcore.h.
* Dec 12, 1995 6.00 BP Added entry, exit and kernel macros.
* Dec 30, 1995 6.00 BP Added ODCALL for calling convention.
* Feb 19, 1996 6.00 BP Changed version number to 6.00.
* Mar 03, 1996 6.10 BP Begin version 6.10.
* Aug 10, 2003 6.23 SH *nix support
*/
#define BUILDING_OPENDOORS
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "OpenDoor.h"
#include "ODCore.h"
#include "ODGen.h"
#include "ODCom.h"
#include "ODPlat.h"
#include "ODKrnl.h"
#include "ODUtil.h"
/* Filename component identifies. */
#define WILDCARDS 0x01
#define EXTENSION 0x02
#define FILENAME 0x04
#define DIRECTORY 0x08
#define DRIVE 0x10
/* Local private helper function prototypes. */
static void ODListFilenameMerge(char *pszEntirePath, const char *pszDrive,
const char *pszDir, const char *pszName, const char *pszExtension);
static char *ODListGetFirstWord(char *pszInStr, char *pszOutStr);
static char *ODListGetRemainingWords(char *pszInStr);
static INT ODListFilenameSplit(const char *pszEntirePath, char *pszDrive,
char *pszDir, char *pszName, char *pszExtension);
/* ----------------------------------------------------------------------------
* od_list_files()
*
* Displays a list of files available for download, using an extended version
* of the standard FILES.BBS format index file.
*
* Parameters: pszFileSpec - Directory name where the FILES.BBS file can be
* found, or full path and filename of a FILES.BBS
* format index file.
*
* Return: TRUE on success or FALSE on failure.
*/
ODAPIDEF BOOL ODCALL od_list_files(char *pszFileSpec)
{
BYTE btLineCount = 2;
BOOL bPausing;
static char szLine[513];
static char szFilename[80];
static char szDrive[3];
static char szDir[70];
static char szTemp1[9];
static char szTemp2[5];
static char szBaseName[9];
static char szExtension[5];
static char szDirectory[100];
INT nFilenameInfo;
FILE *pfFilesBBS;
static char *pszCurrent;
BOOL bIsDir;
BOOL bUseNextLine = TRUE;
tODDirHandle hDir;
tODDirEntry DirEntry;
/* Log function entry if running in trace mode. */
TRACE(TRACE_API, "od_list_files()");
/* Initialize OpenDoors if it hasn't already been done. */
if(!bODInitialized) od_init();
OD_API_ENTRY();
/* Check user's page pausing setting. */
bPausing = od_control.od_page_pausing;
if(od_control.od_extended_info) bPausing = od_control.user_attribute & 0x04;
/* Parse directory parameter. */
if(pszFileSpec == NULL)
{
strcpy(szODWorkString, ".");
strcpy(szDirectory, "."DIRSEP_STR);
}
else if(*pszFileSpec == '\0')
{
strcpy(szODWorkString, ".");
strcpy(szDirectory, "."DIRSEP_STR);
}
else
{
strcpy(szODWorkString, pszFileSpec);
strcpy(szDirectory, pszFileSpec);
if(szODWorkString[strlen(szODWorkString) - 1] == DIRSEP)
{
szODWorkString[strlen(szODWorkString) - 1] = '\0';
}
}
/* Get directory information on path. */
if(ODDirOpen(szODWorkString, DIR_ATTRIB_ARCH | DIR_ATTRIB_RDONLY
| DIR_ATTRIB_DIREC, &hDir) != kODRCSuccess)
{
od_control.od_error = ERR_FILEOPEN;
OD_API_EXIT();
return(FALSE);
}
if(ODDirRead(hDir, &DirEntry) != kODRCSuccess)
{
ODDirClose(hDir);
od_control.od_error = ERR_FILEOPEN;
OD_API_EXIT();
return(FALSE);
}
ODDirClose(hDir);
/* If it is a directory. */
if(DirEntry.wAttributes & DIR_ATTRIB_DIREC)
{
/* Append FILES.BBS to directory name & open. */
bIsDir = TRUE;
ODMakeFilename(szODWorkString, szODWorkString, "FILES.BBS",
sizeof(szODWorkString));
if((pfFilesBBS = fopen(szODWorkString, "r")) == NULL)
{
od_control.od_error = ERR_FILEOPEN;
OD_API_EXIT();
return(FALSE);
}
}
/* If it is not a directory. */
else
{
bIsDir = FALSE;
if((pfFilesBBS = fopen(szODWorkString,"r")) == NULL)
{
od_control.od_error = ERR_FILEOPEN;
OD_API_EXIT();
return(FALSE);
}
}
/* Ignore previously pressed control keys. */
chLastControlKey = 0;
/* Loop until the end of the FILES.BBS file has been reached. */
for(;;)
{
if(fgets(szLine, 512, pfFilesBBS) == NULL) break;
if(!bUseNextLine)
{
if(szLine[strlen(szLine) - 1] == '\n')
{
bUseNextLine = TRUE;
}
continue;
}
if(szLine[strlen(szLine) - 1] == '\n')
{
szLine[strlen(szLine) - 1] = '\0';
}
else
{
bUseNextLine = FALSE;
}
if(szLine[strlen(szLine) - 1] == '\r')
{
szLine[strlen(szLine) - 1] = '\0';
}
if(chLastControlKey != 0)
{
switch(chLastControlKey)
{
case 's':
if(od_control.od_list_stop)
{
if(od_control.baud)
{
ODComClearOutbound(hSerialPort);
}
od_clear_keybuffer();
fclose(pfFilesBBS);
OD_API_EXIT();
return(TRUE);
}
break;
case 'p':
if(od_control.od_list_pause)
{
od_clear_keybuffer();
od_get_key(TRUE);
}
}
chLastControlKey = 0;
}
/* Determine whether or not this is a comment line. */
if(szLine[0] == ' ' || strlen(szLine) == 0)
{
/* If so, display the line in comment color. */
od_set_attrib(od_control.od_list_title_col);
od_disp_str(szLine);
od_disp_str("\n\r");
++btLineCount;
}
/* If the line is not a comment. */
else
{
/* Extract the first word of the line, */
ODListGetFirstWord(szLine, szFilename);
/* And extract the filename. */
nFilenameInfo = ODListFilenameSplit(szFilename, szDrive, szDir,
szBaseName, szExtension);
if(!((nFilenameInfo & DRIVE) || (nFilenameInfo & DIRECTORY)))
{
if(bIsDir)
{
ODMakeFilename(szDirectory, szDirectory, szFilename,
sizeof(szDirectory));
strcpy(szFilename, szDirectory);
}
else
{
ODListFilenameSplit(szDirectory, szDrive, szDir, szTemp1,
szTemp2);
ODListFilenameMerge(szFilename, szDrive, szDir, szBaseName,
szExtension);
}
}
/* Search for the filespec in directory. */
if(ODDirOpen(szFilename, DIR_ATTRIB_ARCH | DIR_ATTRIB_RDONLY, &hDir)
== kODRCSuccess)
{
/* Display information on every file that matches. */
while(ODDirRead(hDir, &DirEntry) == kODRCSuccess)
{
od_set_attrib(od_control.od_list_name_col);
od_printf("%-12.12s ", DirEntry.szFileName);
od_set_attrib(od_control.od_list_size_col);
od_printf("%-6ld ", DirEntry.dwFileSize);
od_set_attrib(od_control.od_list_comment_col);
pszCurrent = ODListGetRemainingWords(szLine);
if(strlen(pszCurrent) <= 56)
{
od_disp_str(pszCurrent);
od_disp_str("\n\r");
}
else
{
od_printf("%-56.56s\n\r", pszCurrent);
}
++btLineCount;
}
ODDirClose(hDir);
}
/* Otherwise, indicate that the file is "Offline". */
else
{
ODListFilenameMerge(szFilename, "", "", szBaseName, szExtension);
od_set_attrib(od_control.od_list_name_col);
od_printf("%-12.12s ", szFilename);
od_set_attrib(od_control.od_list_offline_col);
od_disp_str(od_control.od_offline);
od_set_attrib(od_control.od_list_comment_col);
od_printf("%-56.56s\n\r", ODListGetRemainingWords(szLine));
++btLineCount;
}
}
/* Check for end of screen & page pausing. */
if(btLineCount >= od_control.user_screen_length && bPausing)
{
/* Provide page pausing at end of each screen. */
if(ODPagePrompt(&bPausing))
{
fclose(pfFilesBBS);
OD_API_EXIT();
return(TRUE);
}
/* Reset the line number counter. */
btLineCount = 2;
}
}
/* When finished, close the file. */
fclose(pfFilesBBS);
/* Return with success. */
OD_API_EXIT();
return(TRUE);
}
/* ----------------------------------------------------------------------------
* ODListFilenameMerge() *** PRIVATE FUNCTION ***
*
* Builds a fully-qualified path name from the provided path component
* strings.
*
* Parameters: pszEntirePath - Pointer to the destination string where the
* generated path should be stored.
*
* pszDrive - Pointer to the drive string.
*
* pszDir - Pointer to the directory string.
*
* pszName - Pointer to the base filename string.
*
* pszExtension - Pointer to the extension name string.
*
* Return: void
*/
static void ODListFilenameMerge(char *pszEntirePath, const char *pszDrive,
const char *pszDir, const char *pszName, const char *pszExtension)
{
if(pszEntirePath == NULL) return;
pszEntirePath[0] = '\0';
if(pszDrive != NULL)
{
strcpy(pszEntirePath, pszDrive);
}
if(pszDir != NULL)
{
strcat(pszEntirePath, pszDir);
}
if(pszName != NULL)
{
strcat(pszEntirePath,pszName);
}
if(pszExtension != NULL)
{
strcat(pszEntirePath,pszExtension);
}
}
/* ----------------------------------------------------------------------------
* ODListFilenameSplit() *** PRIVATE FUNCTION ***
*
* Splits the provided path string into drive, directory name, file base name
* and file extension components.
*
* Parameters: pszEntirePath - A string containing the path to split.
*
* pszDrive - A string where the drive letter should be stored.
*
* pszDir - A string where the directory name should be
* stored.
*
* pszName - A string where the base filename should be
* stored.
*
* pszExtension - A string where the filename extension should be
* stored.
*
* Return: One or more flags indicating which components where found in the
* provided path name.
*/
static INT ODListFilenameSplit(const char *pszEntirePath, char *pszDrive,
char *pszDir, char *pszName, char *pszExtension)
{
char *pchCurrentPos;
char *pchStart;
BYTE btSize;
INT nToReturn;
ASSERT(pszEntirePath != NULL);
ASSERT(pszDrive != NULL);
ASSERT(pszDir != NULL);
ASSERT(pszName != NULL);
ASSERT(pszExtension != NULL);
pchStart = (char *)pszEntirePath;
nToReturn = 0;
if((pchCurrentPos = strrchr(pchStart,':')) == NULL)
{
pszDrive[0] = '\0';
}
else
{
btSize = (int)(pchCurrentPos - pchStart) + 1;
if(btSize > 2) btSize = 2;
strncpy(pszDrive, pchStart, btSize);
pszDrive[btSize] = '\0';
pchStart = pchCurrentPos + 1;
nToReturn |= DRIVE;
}
if((pchCurrentPos = strrchr(pchStart, DIRSEP))==NULL)
{
pszDir[0] = '\0';
}
else
{
btSize = (int)(pchCurrentPos - pchStart) + 1;
strncpy(pszDir,pchStart,btSize);
pszDir[btSize] = '\0';
pchStart = pchCurrentPos + 1;
nToReturn |= DIRECTORY;
}
if(strchr(pchStart,'*') != NULL || strchr(pchStart, '?') != NULL)
{
nToReturn |= WILDCARDS;
}
if((pchCurrentPos = strrchr(pchStart, '.')) == NULL)
{
if(pchStart =='\0')
{
pszExtension[0] = '\0';
pszName[0] = '\0';
}
else
{
pszExtension[0] = '\0';
btSize = strlen(pchStart);
if (btSize > 8) btSize = 0;
strncpy(pszName, pchStart, btSize);
pszName[btSize] = '\0';
nToReturn |= FILENAME;
}
}
else
{
nToReturn |= FILENAME;
nToReturn |= EXTENSION;
btSize = (int)(pchCurrentPos - pchStart);
if(btSize > 8) btSize = 8;
strncpy(pszName, pchStart, btSize);
pszName[btSize] = '\0';
btSize = strlen(pchCurrentPos);
if(btSize > 4) btSize = 4;
strncpy(pszExtension, pchCurrentPos, btSize);
pszExtension[btSize]='\0';
}
return(nToReturn);
}
/* ----------------------------------------------------------------------------
* ODListGetFirstWord() *** PRIVATE FUNCTION ***
*
* Returns the first word in a string containing a series of words separated by
* one or more spaced.
*
* Parameters: pszInStr - String to look in.
*
* pszOutStr - Buffer to store result in. This buffer should be at
* least as long as the pszInStr string.
*
* Return: Pointer to the pszOutStr that was passed in.
*/
static char *ODListGetFirstWord(char *pszInStr, char *pszOutStr)
{
char *pchOut = (char *)pszOutStr;
ASSERT(pszInStr != NULL);
ASSERT(pszOutStr != NULL);
while(*pszInStr && *pszInStr != ' ')
{
*pchOut++ = *pszInStr++;
}
*pchOut = '\0';
return(pszOutStr);
}
/* ----------------------------------------------------------------------------
* ODListGetRemainingWords() *** PRIVATE FUNCTION ***
*
* Obtains the remaining words in a string, after the first word. This function
* is a companion to ODListGetFirstWord(), which obtains just the first word
* in a string of many words.
*
* Parameters: pszInStr - String to look at.
*
* Return: A pointer to the position in a string of the second word.
*/
static char *ODListGetRemainingWords(char *pszInStr)
{
char *pchStartOfRemaining = (char *)pszInStr;
/* Skip over the first word in the string. */
while(*pchStartOfRemaining && *pchStartOfRemaining != ' ')
{
++pchStartOfRemaining;
}
/* Skip over any spaces after the first word. */
while(*pchStartOfRemaining && *pchStartOfRemaining == ' ')
{
++pchStartOfRemaining;
}
/* Return pointer to the rest of the string. */
return((char *)pchStartOfRemaining);
}