home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-03-05 | 35.6 KB | 1,130 lines |
- /*
-
- FLIST -- Generates file lists based on privilege levels and keys
-
- Version 2.6 (3/05/93)
-
- Written by Bob Quinlan of Austin, Texas, USA
- Sysop of Red October at 512-834-2593 (1:382/111)
- Special thanks to David Powers for suggestions and code.
-
- Copyright 1993 by Bob Quinlan
-
- Compatible with Maximus 2.00 and 2.01
-
-
- This program generates a list of files that a user with a particular
- privilege level and set of keys could access. It is intended to make
- the procedure independent of changes to the structure of your file
- areas. Instead of specifying which areas should be included you just
- specify what sort of user you want the list to apply to.
-
- You can also create lists of new files. Just use /D to specify how many
- days of files you want to list.
-
- /Afile Area file. You can use this to specify a path to
- AREA.DAT or to refer to another file (although it must
- follow the AREA.DAT format). The filename must be
- included along with the path. Defaults to AREA.DAT in
- the current directory.
-
- /B Include barricaded areas. If this switch is not
- included no barricaded areas will be included.
-
- /C Include comments from the FILES.BBS file lists. By
- default only files and their descriptions are included.
-
- Using this switch has one side-effect! Normally area
- headers are only generated for areas that have files in
- them. /C will cause them to be generated for any area
- that has comments as well. Do not use /C if you only
- want areas that have files in them to appear! (I
- recommend not using /C with /D so that you don't show
- lots of apparently empty file areas.)
-
- /Ddays Days. Excludes all files more than this many days old.
- Use this switch to create lists of new files. You
- cannot use both this and the /M switch at the same time.
-
- /Ffile Output file. The pathname of the file you want the file
- list written to. Defaults to FLIST.TXT in the current
- area.
-
- /HAfile Area header file. The contents of this file will be
- added to the report for each area header. There are
- several sequences you can embed in the file that have
- special meanings. All of the codes explained under /HS
- are allowed except for %C and %B.
-
- If no area header file is specified a default header
- will be used.
-
- /HBfile Beginning header file. The contents of this file will
- be added to the beginning of the report. There are
- several sequences you can embed in the file that have
- special meanings. The codes %D, %T, and %A (explained
- under /HS) are allowed.
-
- /HEfile End header file. The contents of this file will be
- added to the end of the report. There are several
- sequences you can embed in the file that have special
- meanings. The codes %F, %S, %D, %T, and %A (explained
- under /HS) are allowed.
-
- /HSfile Area summary header file. The contents of this file
- will be added to the report after each area. There are
- several sequences you can embed in the file that have
- special meanings:
-
- %N will be replaced with the area name.
- %I will be replaced with the area information.
- %C will be replaced with the area file count.
- %B will be replaced with the area file size total (bytes).
- %F will be replaced with the overall file count.
- %S will be replaced with the overall file size total.
- %D will be replaced with the report date.
- %T will be replaced with the report time.
- %A will be replaced with the age of the files
- included (or marked) in the report. Do not use
- this except with the /D or /M command line
- parameters!
-
- Any of these may be followed by an L, R, or C
- immediately followed by a number. These will left,
- right, or center justify the value in a field of the
- specified width.
-
- You can also follow any of the above with an NF or
- with an Fx. NF stands for "no fill" and has no
- effect (see examples). Fx stands for "fill" and
- will cause the entire field to be replaced by an
- equivalent number of the character 'x'. This is
- useful when drawing boxes.
-
- /Icode International country code. This allows you to override
- the system's country code and pick another format. Give
- the DOS country code for the country you want to use.
-
- /Kkeys Keys to use for access to locked areas. Keys are
- represented by 1-8 and A-X. An asterisk (*) turns on
- all of the keys. Multiple keys can be specified in one
- /K argument (such as /K12B).
-
- /Mdays Mark new files. Marks all files less than or equal to
- this many days old. You cannot use both this and the /D
- switch at the same time.
-
- /N No-wrap. Leave long description lines intact. The
- default is to wrap them.
-
- /O Include offline files. By default files that are listed
- but not present are not included in the list.
-
- /Ppriv Privilege to use for access to areas. Only the first
- letter of the level name is required. Legal values are:
- Twit
- Disgrace
- Limited
- Normal
- Worthy
- Privil
- Favored
- Extra
- Clerk
- AsstSysop
- Sysop
- Hidden
- Defaults to Normal.
-
- /T Truncate long description lines. The default is to wrap
- them.
-
- /Vcount Volume. 'count' is the number of files each dot stands
- for in the progress indicator. Zero will turn off all
- progress displays.
-
- /Wcolumn Wrap column. Sets line wrapping to the specified column
- relative to the left margin.
-
- Let me show you an example of how to use the %N and %I parameters in an
- area header file (defined with the /HA switch). The purpose of those
- parameters is to let you build boxes that will conform to the size of
- the text produced by %N and %I. Here is an example of a simple header
- box using these parameters:
-
- ┌──%NF───┬──%IF───┐
- │ %NNF │ %INF │
- └──%NF───┴──%IF───┘
-
- Note that the characters following the %NF and %IF look like a part of
- the regular text, but are actually the characters that will be used to
- fill out the parameters to the desired length.
-
- This will expand to something that looks like this:
-
- ┌───────┬───────────────────────────────────────────┐
- │ MAX │ Maximus BBS files and related utilities │
- └───────┴───────────────────────────────────────────┘
-
- Now you can see why the apparently useless NF modifier can be useful. It
- pads out the shorter embedded codes so that they visually match those in
- the surrounding lines. The following would produce exactly the same
- result as the previous example, but it is a lot harder to figure out how
- everything will match up:
-
- ┌──%NF───┬──%IF───┐
- │ %N │ %I │
- └──%NF───┴──%IF───┘
-
- Here is an example using fixed width fields. This also right justifies
- the area name and left justifies the area information:
-
- ┌─%NR9F──┬─%IL50F──┐
- │ %NR9NF │ %IL50NF │
- └─%NR9F──┴─%IL50F──┘
-
- Which will expand to something that looks like this:
-
- ┌───────────┬────────────────────────────────────────────────────┐
- │ MAX │ Maximus BBS files and related utilities │
- └───────────┴────────────────────────────────────────────────────┘
-
-
- FLIST returns the following ERRORLEVELS:
- 0 = success
- 1 = bad command line parameter
- 2 = unable to open AREA.DAT
- 3 = unable to open header file
- 4 = unable to open output file
- 5 = not enough memory to run
- 6 = string overflow processing header
-
- NOTICE: You may use, copy, and distribute this program freely as long
- as you insure that both the executable and the documentation (.DOC)
- files are included in the distribution package. The source code does
- not need to be included. You may modify this program and document, so
- long as reasonable credit is given to the original author if a
- substantial portion of the original remains intact. The author is not
- responsible for any losses which may occur either directly or indirectly
- as a result of using this program.
-
- This program uses the Maximus structures written by Scott J. Dudley.
-
- HISTORY:
- Version 2.6 (3/05/93) -- Added support for international date formats.
- FLIST now reads the country code and uses the
- appropriate formats automatically. The /I
- options can be used to override the system's
- country code.
- Version 2.5 (1/18/93) -- Added the /M option to mark new files. Fixed
- counting of files not present in the list.
- Version 2.4 (1/10/93) -- Added the /HS option to allow customized area
- summary headers in the report. Added new
- embedded variables for total and area file
- counts and file sizes. Fixed a bug that
- occurred when inappropriate replacement codes
- were used in a header.
- Version 2.3 (1/10/93) -- Added /W parameter to allow line-wrapping to
- different lengths. List "offline" as the
- size for offline file entries.
- Version 2.2 (11/04/92) -- Fixed minor date offsets caused by default
- timezone and daylight savings adjustments.
- Added the /V switch to limit screen output.
- /V0 replaces the /Q switch.
- Version 2.1 (8/26/92) -- Added the /Q switch to eliminate the progress
- display. Now returns different errorlevels
- for each possible error. Fixed problem with
- headers before comments.
- Version 2.0 (8/23/92) -- Added more error checking.
- Version 1.9 (8/22/92) -- Added a progress display. Fixed a memory
- corruption bug.
- Version 1.8 (8/20/92) -- Added fixed width fields with left, right,
- and centered justification for embedded
- variables. Changed the previous codes for
- embedded variables! Removed built-in help to
- reduce memory requirements.
- Version 1.7 (8/10/92) -- Added embedded variables to the begin and end
- headers. Note: This eliminated the automatic
- file age comment that used to be included for
- newfile lists.
- Version 1.6 (8/10/92) -- Added the /HA option to allow customized area
- headers in the report. This is an expansion
- of an idea and code by David Powers.
- Version 1.5 (8/09/92) -- Added the /HB and /HE options to allow
- customized beginning and end text in the
- report. Added /? help option to print the
- parameter list. Added a clearer explanation
- of /C's effect on area headers.
- Version 1.4 (8/07/92) -- Added the /C option to include file list
- comments. Added code to recognize free
- switches so they do not show up in the
- descriptions. Fixed error if first entry in
- AREA.DAT did not include a file area.
- Version 1.3 (8/06/92) -- Read the file list filename from AREA.DAT
- instead of assuming FILES.BBS.
- Version 1.2 (8/02/92) -- Added days header for new files list.
- Version 1.1 (7/30/92) -- Added file age cutoff.
- Version 1.0 (6/30/92) -- Original release. Written in Borland C.
-
- Large memory model
- */
-
-
- #include <ctype.h>
- #include <dos.h>
- #include <fcntl.h>
- #include <io.h>
- #include <share.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys\stat.h>
- #include <time.h>
- #include <mstruct.h> /* Maximus structures by Scott J. Dudley */
-
-
- #define VERSION "2.6"
- #define DATE "3/05/93"
-
- #define MAXWIDTH 79
- #define MAXDATE 16
- #define MAXPATH 128
- #define MAXLINE 256
- #define MAXDESC 4096
-
- #define DEFINDENT 31
-
- #define UNITED_STATES 001
-
- #ifndef FALSE
- #define FALSE 0
- #define TRUE 1
- #endif
-
-
- struct _arealist
- {
- char name[40];
- char info[80];
- char path[80];
- char filesbbs[80];
- sword priv;
- dword locks;
- byte barricade;
- struct _arealist *next;
- };
-
-
- typedef struct _arealist __arealist;
- typedef struct _area __area;
-
-
- void process_args(int argc, char *argv[]);
- sword get_priv(char priv);
- dword get_keys(char *key_list);
- __arealist *read_areas(void);
- void process_header(char type, char *hfile, char *name, char *info, FILE *out);
- void process_entry(char *entry, char *path, char *name, char *info,
- int *header, FILE *out);
-
-
- char areafile[MAXPATH] = {"area.dat"};
- char hareafile[MAXPATH] = {""};
- char hbeginfile[MAXPATH] = {""};
- char hendfile[MAXPATH] = {""};
- char hsummaryfile[MAXPATH] = {""};
- char outfile[MAXPATH] = {"flist.txt"};
- sword priv = NORMAL;
- dword keys = 0x00000000;
- int barricade = FALSE;
- int comment = FALSE;
- long days = -1L;
- int mark = FALSE;
- int offline = FALSE;
- int wrap = DEFINDENT;
- int volume = 1;
- int vloop;
- long age = -1L;
- int total_count = 0;
- int area_count;
- long total_bytes = 0L;
- long area_bytes;
- int country_code = 0;
- struct COUNTRY cp;
-
-
- int main(int argc, char *argv[])
- {
-
- char filespath[MAXPATH];
-
- int header;
-
- FILE *out;
- FILE *files;
-
- __arealist *areas;
- __arealist *cur;
- __arealist *prev;
-
- char line[MAXDESC];
-
-
- printf("FLIST %s -- Copyright 1993 by Bob Quinlan (%s)\n\n", VERSION, DATE);
- printf("Special thanks to David Powers for suggestions and code.\n\n");
-
- process_args(argc, argv);
-
- areas = read_areas();
-
- if ((out = _fsopen(outfile, "wt", SH_DENYWR)) == NULL)
- {
- fprintf(stderr, "Unable to open %s\n", outfile);
- exit(4);
- }
-
- /* Get country-specific formatting information */
- if (country(country_code, &cp) == NULL)
- {
- cp.co_date = 0;
- strcpy(cp.co_curr, "$");
- strcpy(cp.co_thsep, ",");
- strcpy(cp.co_desep, ".");
- strcpy(cp.co_dtsep, "-");
- strcpy(cp.co_tmsep, ":");
- cp.co_currstyle = 0;
- cp.co_digits = 2;
- cp.co_time = 0;
- cp.co_case = 0x1160cf5L;
- strcpy(cp.co_dasep, ",");
- }
-
- if (hbeginfile[0] != '\0')
- {
- process_header('b', hbeginfile, NULL, NULL, out);
- }
-
- cur = areas;
- while (cur != NULL)
- {
- if ((priv >= (cur->priv)) && (((~keys)&(cur->locks)) == 0) &&
- ((cur->barricade == 0) || (barricade)))
- {
- if (volume)
- {
- vloop = -1;
- printf("%s -- %s", cur->name, cur->info);
- }
- strcpy(filespath, cur->filesbbs);
- if (filespath[0] == '\0')
- {
- strcpy(filespath, cur->path);
- strcat(filespath, "files.bbs");
- }
- if ((files = _fsopen(filespath, "rt", SH_DENYNONE)) != NULL)
- {
- area_count = 0;
- area_bytes = 0L;
- header = FALSE;
- while (fgets(line, MAXDESC, files) != NULL)
- {
- process_entry(line, cur->path, cur->name, cur->info,
- &header, out);
- if (volume)
- {
- if ((vloop = (vloop+1)%volume) == 0)
- {
- printf(".");
- }
- }
- }
- fclose(files);
- if (header)
- {
- if (hsummaryfile[0] != '\0')
- {
- process_header('s', hsummaryfile, cur->name,
- cur->info, out);
- }
- }
- }
- if (volume)
- {
- printf("\n");
- }
- }
- /* Increment to next link and free previous link */
- prev = cur;
- cur = cur->next;
- free(prev);
- }
-
- if (hendfile[0] != '\0')
- {
- process_header('e', hendfile, NULL, NULL, out);
- }
-
- fclose(out);
-
- return 0;
- }
-
-
- void process_args(int argc, char *argv[])
- {
- int i;
-
- for (i = 1; i < argc; i++)
- {
- if ((argv[i][0] == '/') || (argv[i][0] == '-'))
- {
- switch (tolower(argv[i][1]))
- {
- case 'a': /* area.dat */
- strncpy(areafile, argv[i]+2, MAXPATH);
- break;
- case 'b': /* include barricaded areas */
- barricade = TRUE;
- break;
- case 'c': /* include file list comment lines */
- comment = TRUE;
- break;
- case 'd': /* days (of file date) */
- mark = FALSE;
- days = atol(argv[i]+2);
- age = time(NULL)-(days*24*60*60);
- break;
- case 'f': /* output file */
- strncpy(outfile, argv[i]+2, MAXPATH);
- break;
- case 'h': /* headers */
- switch(tolower(argv[i][2]))
- {
- case 'a':
- strncpy(hareafile, argv[i]+3, MAXPATH);
- break;
- case 'b':
- strncpy(hbeginfile, argv[i]+3, MAXPATH);
- break;
- case 'e':
- strncpy(hendfile, argv[i]+3, MAXPATH);
- break;
- case 's':
- strncpy(hsummaryfile, argv[i]+3, MAXPATH);
- break;
- default:
- fprintf(stderr, "Unknown switch: %s\n", argv[i]);
- exit(1);
- break;
- }
- break;
- case 'i': /* international country code */
- country_code = atoi(argv[i]+2);
- break;
- case 'k': /* keys */
- keys |= get_keys(argv[i]+2);
- break;
- case 'm': /* mark new files */
- mark = TRUE;
- days = atol(argv[i]+2);
- age = time(NULL)-(days*24*60*60);
- break;
- case 'n': /* no-wrap */
- wrap = -1;
- break;
- case 'o': /* offline files allowed */
- offline = TRUE;
- break;
- case 'p': /* privilege */
- priv = get_priv(argv[i][2]);
- if (priv < TWIT)
- {
- priv = TWIT;
- fprintf(stderr, "Invalid privilege: %c\n", argv[i][2]);
- }
- break;
- case 't': /* truncate lines */
- wrap = -2;
- break;
- case 'v': /* volume */
- volume = max(atoi(argv[i]+2), 0);
- break;
- case 'w': /* wrap column */
- wrap = min(max(atoi(argv[i]+2), 0),
- MAXWIDTH-((MAXWIDTH-DEFINDENT)/2));
- break;
- default:
- fprintf(stderr, "Unknown switch: %s\n", argv[i]);
- exit(1);
- break;
- }
- }
- else
- {
- fprintf(stderr, "Not a switch: %s\n", argv[i]);
- exit(1);
- }
- }
- }
-
-
- sword get_priv(char priv)
- {
- char priv_name[] = {"tdlnwpfecash"};
- sword priv_code[] =
- {
- TWIT,
- DISGRACE,
- LIMITED,
- NORMAL,
- WORTHY,
- PRIVIL,
- FAVORED,
- EXTRA,
- CLERK,
- ASSTSYSOP,
- SYSOP,
- HIDDEN
- };
-
- char *where;
-
- where = strchr(priv_name, tolower(priv));
- if (where == NULL)
- {
- return TWIT-1;
- }
-
- return priv_code[(int)(where-priv_name)];
- }
-
-
- dword get_keys(char *key_list)
- {
- char *key;
- dword mask = 0x00000000;
- int keylen;
- int i;
-
- key = strupr(strdup(key_list));
-
- keylen = strlen(key);
- for (i = 0; i < keylen; i++)
- {
- if (key[i] == '*')
- {
- mask = 0xFFFFFFFFL;
- break;
- }
- else if ((key[i] >= '1') && (key[i] <= '8'))
- {
- mask |= 0x00000001L<<(key[i]-'1');
- }
- else if ((key[i] >= 'A') && (key[i] <= 'X'))
- {
- mask |= 0x00000100L<<(key[i]-'A');
- }
- }
-
- free(key);
-
- return mask;
- }
-
-
- __arealist *read_areas(void)
- {
- FILE *areadat;
- __area area;
- __arealist *tmp;
- __arealist *first;
- __arealist *cur = NULL;
- dword slen;
- dword offset = 0;
-
- if ((areadat = _fsopen(areafile, "rb", SH_DENYNONE)) == NULL)
- {
- fprintf(stderr, "Unable to open %s\n", areafile);
- exit(2);
- }
-
- while (fread(&area, sizeof(__area), 1, areadat) > 0)
- {
- if (offset == 0)
- {
- slen = (dword)(area.struct_len);
- }
- if (area.filepath[0] != '\0')
- {
- if ((tmp = (__arealist *)malloc(sizeof(__arealist))) == NULL)
- {
- fprintf(stderr, "Out of memory!\n");
- exit(5);
- }
- if (cur == NULL)
- {
- first = tmp;
- }
- else
- {
- cur->next = tmp;
- }
- cur = tmp;
- strcpy(cur->name, (char *)area.name);
- strcpy(cur->info, (char *)area.fileinfo);
- strcpy(cur->path, (char *)area.filepath);
- strcpy(cur->filesbbs, (char *)area.filesbbs);
- cur->priv = area.filepriv;
- cur->locks = area.filelock;
- cur->barricade = (area.filebar[0] != '\0');
- }
- offset += slen;
- if (fseek(areadat, offset, SEEK_SET) != 0)
- {
- break;
- }
- }
-
- cur->next = NULL;
- fclose(areadat);
-
- return first;
- }
-
-
- void process_header(char type, char *hfile, char *name, char *info, FILE *out)
- {
- FILE *h;
- char buf[MAXLINE];
- char tbuf[MAXLINE];
- char filler[MAXLINE];
- int flen;
- char *param;
- int plen;
- int fwidth;
- char *stopper;
- char c;
- int j, k;
-
- if ((h = _fsopen(hfile, "rt", SH_DENYNONE)) == NULL)
- {
- fprintf(stderr, "Unable to open %s\n", hfile);
- exit(3);
- }
- /* Read data from the header file */
- while (fgets(buf, MAXLINE, h) != NULL)
- {
- /* Process special replacement characters */
- param = buf;
- while ((param = strchr(param, '%')) != NULL)
- {
- filler[0] = '\0';
- plen = 2;
- /* Check the basic parameter type */
- switch (tolower(param[1]))
- {
- case 'a': /* age */
- if (days != -1L)
- {
- ltoa(days, filler, 10);
- }
- break;
- case 'd': /* date */
- _strdate(filler);
- break;
- case 't': /* time */
- _strtime(filler);
- break;
- }
- /* Do not allow totals in beginning headers */
- if (type != 'b')
- {
- switch (tolower(param[1]))
- {
- case 'f': /* total file count */
- itoa(total_count, filler, 10);
- break;
- case 's': /* file size total */
- ltoa(total_bytes, filler, 10);
- break;
- }
- }
- /* Only allow area name and information in area and summary headers */
- if ((type == 'a') || (type == 's'))
- {
- switch (tolower(param[1]))
- {
- case 'n': /* name */
- strcpy(filler, name);
- break;
- case 'i': /* information */
- strcpy(filler, info);
- break;
- }
- }
- /* Only allow area count and area bytes in summary headers */
- if (type == 's')
- {
- switch (tolower(param[1]))
- {
- case 'c': /* area file count */
- itoa(area_count, filler, 10);
- break;
- case 'b': /* area file size total (bytes) */
- ltoa(area_bytes, filler, 10);
- break;
- }
- }
-
- /* If any replacements were found... */
- if (filler[0] != '\0')
- {
- /* Process width values if present */
- c = tolower(param[plen]);
- if (strchr("lrc", c) != NULL)
- {
- ++plen;
- /* Convert the width value and find where it stops */
- fwidth = (int)strtol(param+plen, &stopper, 10);
- plen += (int)(stopper-(param+plen));
- /* If the field is wider than the filler string... */
- if (fwidth >= MAXLINE)
- {
- fprintf(stderr, "Width %d too wide! Ignored.\n",
- fwidth);
- }
- /* If the field is wider than the current data... */
- else if (strlen(filler) < fwidth)
- {
- switch (c)
- {
- case 'l': /* left justify */
- /* Pad on the right */
- for (j = strlen(filler); j < fwidth; j++)
- {
- filler[j] = ' ';
- }
- break;
- case 'r': /* right justify */
- flen = strlen(filler);
- /* Shift the string right */
- for (j = 1; j <= flen; j++)
- {
- filler[fwidth-j] = filler[flen-j];
- }
- /* Pad on the left */
- for (j = 0; j < fwidth-flen; j++)
- {
- filler[j] = ' ';
- }
- break;
- case 'c': /* center */
- flen = strlen(filler);
- /* Pad on the right */
- k = (fwidth-flen+1)/2;
- for (j = 1; j <= k; j++)
- {
- filler[fwidth-j] = ' ';
- }
- /* Shift the string to center */
- for (j = 1; j <= flen; j++)
- {
- filler[fwidth-k-j] = filler[flen-j];
- }
- /* Pad on the left */
- k = (fwidth-flen)/2;
- for (j = 0; j < k; j++)
- {
- filler[j] = ' ';
- }
- break;
- }
- /* Terminate the adjusted string */
- filler[fwidth] = '\0';
- }
- }
-
- /* Process fill character if present */
- if (tolower(param[plen]) == 'f')
- {
- strset(filler, param[++plen]);
- ++plen;
- }
- /* Skip "no fill" parameter if present */
- else if (strncmpi(param+plen, "nf", 2) == 0)
- {
- plen += 2;
- }
-
- /* Perform the replacment */
- if ((strlen(buf)+strlen(filler)-plen) >= MAXLINE)
- {
- fprintf(stderr, "String overflow!\n");
- exit(6);
- }
- param[0] = '\0';
- strcpy(tbuf, buf);
- strcat(tbuf, filler);
- strcat(tbuf, param+plen);
- strcpy(buf, tbuf);
- param = param+strlen(filler);
- }
- else
- {
- param++;
- }
- }
-
- /* Output header */
- fputs(buf, out);
- }
-
- fclose(h);
- }
-
-
- void process_entry(char *entry, char *path, char *name, char *info,
- int *header, FILE *out)
- {
- char filepath[MAXPATH];
- int file;
-
- long fsize;
- struct ftime ftimep;
- struct tm ftm;
- char datestr[MAXDATE];
- int fdata;
-
- char line[MAXDESC];
- char fill[MAXWIDTH+1];
- char extra[MAXWIDTH+1];
- char filemark;
- char *descrip;
- char *end;
- char *ch;
- int length;
- int nameline;
- int i;
-
- filemark = ' ';
- strcpy(line, entry);
-
- /* Trim newline */
- end = strchr(line, '\n');
- if (end != NULL)
- {
- end[0] = '\0';
- }
- else
- {
- end = strchr(line, '\0');
- }
-
- /* Check for comment lines */
- if (strchr(" -", line[0]) != NULL)
- {
- if (comment)
- {
- /* Output area header if not already done */
- if (!(*header))
- {
- if (hareafile[0] != '\0')
- {
- process_header('a', hareafile, name, info, out);
- }
- else
- {
- fprintf(out, "\n\n Area %s -- %s\n\n", name, info);
- }
- *header = TRUE;
- }
-
- /* Output comment line */
- fprintf(out, "%s\n", line);
- }
- }
- else
- {
- /* Parse into filename and description, skipping switches */
- descrip = line;
- do
- {
- ch = strpbrk(descrip, " \t");
- if (ch == NULL)
- {
- descrip = end;
- }
- else
- {
- ch[0] = '\0';
- i = strspn(++ch, " \t");
- descrip = ch+i;
- }
- } while (descrip[0] == '/');
-
- /* Get file size and date */
- strcpy(filepath, path);
- strcat(filepath, line);
- if ((file = sopen(filepath, O_RDONLY, SH_DENYNONE)) == -1)
- {
- if (offline)
- {
- fdata = FALSE;
- }
- else
- {
- return;
- }
- }
- else
- {
- fsize = filelength(file);
- getftime(file, &ftimep);
- close(file);
- fdata = TRUE;
-
- /* Generate date string */
- switch (cp.co_date)
- {
- case 0: /* month, day, year */
- sprintf(datestr, "%2.2u%s%2.2u%s%2.2u",
- ftimep.ft_month,
- cp.co_dtsep,
- ftimep.ft_day,
- cp.co_dtsep,
- (ftimep.ft_year+80)%100);
- break;
- case 1: /* day, month, year */
- sprintf(datestr, "%2.2u%s%2.2u%s%2.2u",
- ftimep.ft_day,
- cp.co_dtsep,
- ftimep.ft_month,
- cp.co_dtsep,
- (ftimep.ft_year+80)%100);
- break;
- case 2: /* year, month, day */
- sprintf(datestr, "%2.2u%s%2.2u%s%2.2u",
- (ftimep.ft_year+80)%100,
- cp.co_dtsep,
- ftimep.ft_month,
- cp.co_dtsep,
- ftimep.ft_day);
- break;
- }
-
- /* Calculate datestamp offset */
- timezone = 0L;
- daylight = 0;
- memset(&ftm, 0, sizeof(struct tm));
- ftm.tm_sec = ftimep.ft_tsec*2;
- ftm.tm_min = ftimep.ft_min;
- ftm.tm_hour = ftimep.ft_hour;
- ftm.tm_mday = ftimep.ft_day;
- ftm.tm_mon = ftimep.ft_month-1;
- ftm.tm_year = ftimep.ft_year+80;
- if (mktime(&ftm) < age)
- {
- if (!mark)
- {
- return;
- }
- }
- else
- {
- if (mark)
- {
- filemark = '*';
- }
- }
- }
-
- /* Output area header if not already done */
- if (!(*header))
- {
- if (hareafile[0] != '\0')
- {
- process_header('a', hareafile, name, info, out);
- }
- else
- {
- fprintf(out, "\n\n Area %s -- %s\n\n", name, info);
- }
- *header = TRUE;
- }
-
- /* Update file counts */
- total_count++;
- area_count++;
-
- /* Output file entry */
- if (fdata)
- {
- /* Update file sizes */
- total_bytes += fsize;
- area_bytes += fsize;
- /* Output file data */
- fprintf(out, "%-12s %7lu %s%c ", line, fsize, datestr, filemark);
- }
- else
- {
- fprintf(out, "%-12s offline %c ", line, filemark);
- }
- /* Output description */
- switch (wrap)
- {
- case -2: /* truncate */
- descrip[MAXWIDTH-DEFINDENT] = '\0';
- fprintf(out, "%s\n", descrip);
- break;
- case -1: /* no-wrap */
- fprintf(out, "%s\n", descrip);
- break;
- default: /* wrap */
- length = MAXWIDTH-DEFINDENT;
- fill[0] = '\0';
- nameline = TRUE;
- /* Set initial length */
- while (strlen(descrip) > length)
- {
- for (i = length; i > length/2; i--)
- {
- if (strchr(" \t", descrip[i]) != NULL)
- {
- break;
- }
- }
- /* If there are no breaks... */
- if (i == length/2)
- {
- strncpy(extra, descrip, length);
- extra[length] = '\0';
- fprintf(out, "%s%s\n", fill, extra);
- descrip += length;
- }
- else
- {
- descrip[i++] = '\0';
- fprintf(out, "%s%s\n", fill, descrip);
- descrip += i;
- while (strchr(" \t", descrip[0]) != NULL)
- {
- descrip++;
- }
- }
- if (nameline == TRUE)
- {
- /* Recalculate length */
- length = MAXWIDTH-wrap;
- memset(fill, ' ', wrap);
- fill[wrap] = '\0';
- nameline = FALSE;
- }
- }
- fprintf(out, "%s%s\n", fill, descrip);
- break;
- }
- }
- }
-
-
-