Ultrix-3.1/src/cmd/ltf/filenames.c
/**********************************************************************
* Copyright (c) Digital Equipment Corporation 1984, 1985, 1986. *
* All Rights Reserved. *
* Reference "/usr/src/COPYRIGHT" for applicable restrictions. *
**********************************************************************/
#ifndef lint
static char *sccsid = "@(#)filenames.c 3.0 (ULTRIX) 4/21/86";
#endif lint
/**/
/*
*
* File name:
*
* filenames.c
*
* Source file description:
*
* This module contains the various routines that
* deal with file name and character string handling.
* Define "handling" to imply string conversions,
* string filtration, etc..
*
* Generally, but not always, this will be done
* on behalf of filenames. One exception is for
* volume label name strings. Other cases may be
* added as development proceeds.
*
* Functions:
*
* filter_to_a() Filter a character string to contain
* only "a"characters.
* (see ltfdefs.h -or- filter_to_a() )
*
* Lookup() Looks up a given ANSI file name
* among user-input file arguments.
*
* make_name() Convert a user file name to correct
* format for FILESTAT structure
*
* rec_args() Records file name command line arguments
* in FILESTAT linked list.
*
* rec_file() Records file name arguments in FILESTAT
* list entered from an input file,
* or line-by-line from stdin.
*
* term_string() Terminate a string in the requested
* fashion
*
* Usage:
*
* n/a
*
*
* Compile:
*
* cc -O -c filenames.c <- For Ultrix-32/32m
*
* cc CFLAGS=-DU11-O filenames.c <- For Ultrix-11
*
*
* Modification history:
* ~~~~~~~~~~~~~~~~~~~~
*
* revision comments
* -------- -----------------------------------------------
* 01.0 14-April-85 Ray Glaser
* Create original version.
*
* 01.1 22-August-85 Suzanne Logcher
* Debug and fix rec_file.
*/
/*
* -> Local includes
*/
#include "ltfdefs.h" /* Common GLOBAL constants & structs */
/**/
/*
*
* Function:
*
* filter_to_a
*
* Function Description:
*
* Function "filter_to_a" is called to filter a
* given string to "a"chracters as defined below.
*
*
* Arguments:
*
* char *string Pointer to "null-terminated"
* character string to be filtered
*
* int report_errors BOOLEAN flag (TRUE/FALSE) to
* indicate if the caller wants
* to know if any non-a chctrs
* were found.
*
* TRUE implies that the caller
* wants to be notified of the
* occurance of any non-"a"character
* seen in the given string..
*
* FALSE implies the caller does
* not care if non-"a"characters were
* seen but desires the conversion
* to be made regardless.
*
* Return values:
*
* Return values are the BOOLEAN flags TRUE or FALSE.
*
* Side Effects:
*
* If the caller indicates that errors are to be
* returned, invalid non-"a"characters seen in
* the given string will be converted to upper case Z
* for subsequent user level error messages.
*
* Normally, all lower case characters will be converted
* to upper case. Lower case letters are not allowable
* "a"characters. However, if the report_errors flag is
* set, the lower to upper case conversion is not made.
*
*/
filter_to_a (string,report_errors)
char *string;
int report_errors;
{
/**/
/*
* "a"characters - Refers to the set of characters consisting of:
*
* Uppercase A-Z, numerals 0-9, & the following
* special characters:
*
* space ! " % & ' ( ) * + , - _
* . / : ; < = > ?
*
*/
/*
* -> Local variables
*/
short a_flag;
short i;
short non_a = FALSE; /* Default is a good string */
char *o_string;
/*------*\
Code
\*------*/
o_string = string; /* Save pointer to orginal string */
while (*string) {
if (islower(*string))
;
else if (isdigit(*string))
;
else if (isupper(*string))
;
else {
a_flag = FALSE; /* Default to not valid chctr */
for (i=0; i < A_SPECIALS; i++) {
if (*string == A_specials[i]) {
a_flag = TRUE;
break;
}
}
if (a_flag == FALSE) {
non_a = TRUE;
*string = 'Z';
}
}/*E if else string*/
string++;
}/*E while *string */
/* Convert string to upper case.
*/
while (*o_string) {
*o_string = islower(*o_string) ? *o_string-'a'+'A' : *o_string;
o_string++;
}
/* If invalid chctrs were found, return FALSE
*/
if (non_a && report_errors)
return(FALSE);
return(TRUE);
}/*E filter_to_a()*/
/**/
/*
*
* Function:
*
* Lookup
*
* Function Description:
*
* This function looks up a given ANSI volume file name
* entry among user-input file name arguments
*
* Arguments:
*
* char *name Pointer to the name string to be found
*
* Return values:
*
* Returns a FILESTAT structure pointer if the name is
* found. Else, returns NULL if the name was not found.
*
*
* Side Effects:
*
* none
*/
struct FILESTAT * Lookup(name)
char *name; /* file name */
{
/*
* +--> Local variables
*/
struct FILESTAT *fstat;
char *d;
char *n;
char *x;
char *y;
/*------*\
Code
\*------*/
for (fstat = F_head; fstat; fstat = fstat->f_next) {
int i, length;
/*
* If this file has been extracted,
* go to the next entry.
*/
if (!fstat->f_numleft)
continue;
/*
* If this is the desired file, return a pointer
* to its' FILESTAT structure.
*/
if (!mstrcmp(name, fstat->f_src)) {
fstat->f_found++;
return(fstat);
}
/* ?_?
* check if the volume entry is a file
* (recursively) under a requested directory. ?_?
*/
n = name;
d = fstat->f_src;
while (*n == *d) {
n++; d++;
}
x = n;
y = d;
if (*d == '.' && *(d+1) == 0 && (*(d-1) == '/' || *n == '/'))
return(fstat);
if (*y == 0 && *x == '/' && *(x+1) == 0) {
fstat->f_found++;
return(fstat);
}
}/*E for fstat = F_head ..*/
return(NULL);
}/*E Lookup() */
/**/
/*
*
* Function:
*
* make_name
*
* Function Description:
*
* Converts a file name from user input to a
* file name format appropriate to the current function
* & inserts it into a FILESTAT structure.
* Case conversions are performed as required.
*
* Arguments:
*
* char *file
* char **dest
*
* Return values:
*
* The converted file name is stored as indicated above
* if successful and a non-zero value is returned,
* else an error message is printed to stderr &
* an exit to the system is taken.
*
*
* Side Effects:
*
* If an error is detected, no return is made to the caller.
*
*/
make_name(file, dest)
char *file;
char **dest;
{
/*------*\
Code
\*------*/
if (strlen(file) > MAXPATHLEN) {
PERROR "\n%s: %s %s\n", Progname, FNTL, file);
exit(FAIL);
}
#if 0
if (Func == EXTRACT || Func == TABLE)
/* Convert destination filename to lower case.
*/
while(*file) {
*file = isupper(*file) ? *file-'A'+'a' : *file;
file++;
}
#endif
*dest = (char *) malloc (strlen(file) + 1);
if (!*dest) {
PERROR "\n%s: %s\n", Progname, TMA);
exit(FAIL);
}
strcpy(*dest, file);
return(TRUE);
}/*E make_name() */
/**/
/*
*
* Function:
*
* rec_args
*
* Function Description:
*
* Records (saves) command line argument file names in the
* linked list "FILESTAT" structure(s) for future reference.
*
* Arguments:
*
* int dumpflag Flags associated with this command line
* char *longname Path name_+_filename
*
* Return values:
*
* none
*
* Side Effects:
*
* If an error is dectected in a filename, a message is output
* to stderr and an exit to the system is taken.
*
*/
rec_args(longname, dumpflag)
char *longname;
int dumpflag;
{
/*
* -> Local variables
*/
struct FILESTAT *fstat;
/*------*\
Code
\*------*/
fstat = (struct FILESTAT *) malloc(sizeof(*fstat));
if (!fstat) {
PERROR "\n%s: %s\n", Progname, TMA);
exit(FAIL);
}
/* Link another file name structure to our current list.
*/
fstat->f_next = F_head;
/* Last in, first out que.
*/
F_head = fstat;
fstat->f_numleft = 1;
fstat->f_found = 0;
fstat->f_flags = dumpflag;
/*
* Make final version of file name.
*/
make_name(longname, &fstat->f_src);
/* Count another file desired.
*/
Numrecs++;
return;
}/*E rec_args() */
/**/
/*
*
* Function:
*
* rec_file
*
* Function Description:
*
* If the Func = EXTRACT or TABLE, records (saves) argument
* file names in the linked list FILESTAT structure(s) which
* were entered from "stdin" or from a specified file.
* If the Func = CREATE, saves one filename in the argument
* crname, and returns to the calling routine.
*
* Arguments:
*
* FILE *fp Pointer to an input file, or stdin
* int iflag Input flag, -1 = stdin, 1 = file
* char *crname Will contain a filename if Func =
* CREATE
*
* Return values:
*
* EOF - unsuccessful = 0
* TRUE - successful = 1
*
* Side Effects:
*
* If errors are encountered, the routine will output a message
* to stderr and exit to system control. ie. No return to caller.
*
*/
rec_file(fp, iflag, crname)
FILE *fp; /* Pointer to file of file names or stdin */
int iflag; /* Input flag, -1 = stdin, 1 = file */
char *crname;/* CREATE filename */
{
/*
* -> Local variables
*/
int dumpflag = 0;
struct FILESTAT *fstat;
char *l, line[MAXPATHLEN];
/*------*\
Code
\*------*/
if (Func == CREATE || Func == WRITE) {
/* Test if iflag = -1 for stdin.
*/
if (iflag == -1) {
/*
* Process a list of file names entered from "stdin".
*/
PROMPT "\n%s: %s ", Progname, ENFNAM);
if (!(fgets(line, sizeof(line), fp)) || line[0] == '\n') {
return(EOF);
}
/* Remove newline and truncate the string after
* the first non-white space character.
*/
term_string(line,DELNL,TRUNCATE);
if (strlen(line) < MAXPATHLEN-1)
strcpy(crname, line);
else {
PERROR "\n%s: %s %s", Progname, FNTL, line);
exit(FAIL);
return(EOF);
}
return(TRUE);
}/*F if iflag */
else {
if (fgets((l=line), sizeof(line), fp) != NULL) {
Dfiletype = 0;
term_string(l,NULL,TRUNCATE);
if (strlen(l) < MAXPATHLEN-1)
strcpy(crname,l);
else {
PERROR "\n%s: %s %s", Progname, FNTL, line);
exit(FAIL);
}
if (*crname == 0)
return(EOF);
else
return(TRUE);
}/* if fgets l=line etc ..*/
else
return(EOF);
}/* else */
}/*E if Func == CREATE || WRITE */
/* Func should be either TABLE or EXTRACT to get here.
*/
fstat = (struct FILESTAT *) malloc(sizeof(*fstat));
if (!fstat) {
PERROR "\n%s: %s\n", Progname, TMA);
exit(FAIL);
}
/*
* Link another file name arg into the list
*/
fstat->f_next = F_head;
F_head = fstat;
for (;;) {
if (iflag == -1) {
PROMPT "\n%s: %s ", Progname, ENFNAM);
if (!fgets(line, sizeof(line), fp) || line[0] == '\n') {
F_head = fstat->f_next;
free((char *)fstat);
return(EOF);
}
term_string(line,DELNL,TRUNCATE);
fstat->f_numleft = 1;
make_name(line, &fstat->f_src);
Numrecs++;
fstat++;
}/*T if iflag */
else
if (fgets(l=line, sizeof(line), fp) != NULL) {
term_string(l,DELNL,NULL);
make_name(l, &fstat->f_src);
fstat->f_numleft = 1;
fstat->f_flags = dumpflag;
Numrecs++;
fstat++;
}/*T if !fgets ..*/
else {
F_head = fstat->f_next;
free((char *)fstat);
return(TRUE);
}
fstat = (struct FILESTAT *) malloc(sizeof(*fstat));
if (!fstat) {
PERROR "\n%s: %s\n", Progname, TMA);
exit(FAIL);
}
fstat->f_next = F_head;
F_head = fstat;
}/*E for ;; */
}/*E rec_file() */
/**/
/*
*
* Function:
*
* term_string
*
* Function Description:
*
* This function terminates a given input string according
* to the calling parameters.
*
* Arguments:
*
* char *string Pointer to input string
* int delnl True is trailing new line to be replaced
* with a NULL
* int truncate If true - truncate string after the 1st
* non-white space character
*
* Return values:
*
* The altered in place string.
*
* Side Effects:
*
* none
*
*/
term_string(string,delnl,truncate)
char *string;
int delnl;
int truncate;
{
/*------*\
Code
\*------*/
if (delnl) {
i = strlen(string) -1;
if (string[i] == '\n')
string[i] = NULL;
}/*E if delnl */
if (truncate) {
while (*string && !isspace(*string))
string++;
if (isspace(*string))
*string = NULL;
}/*E if truncate */
}/*E term_string() */
/* expnum() routine was moved here from ltf.c */
/*
*
* Function:
*
* expnum
*
* Function Description:
*
* Expand a numeric character string into an integer
* multiple of the format expressed. ie.. Allow the user
* to input a value in blocks (or k) and we convert it
* to the real number of bytes implied.
*
* For example -> 10b = ten 512 byte blocks
* -or- 3k = three 1024 byte blocks
*
* Arguments:
*
* char *numstring Pointer to the null terminated numeric
* character string.
* int error_status TRUE indicates invalid numeric string
* FALSE indicates no error
*
* Return values:
*
* Returns a numeric value if the conversion was valid.
*
*
*/
expnum(numstring)
char *numstring;
{
/*------*\
Code
\*------*/
j = 0;
error_status = FALSE;
if (*numstring == '-') {
j++;
numstring++;
}
for (i = 0; isdigit(*numstring); numstring++)
i = (10 * i) + (*numstring - '0');
switch (*numstring) {
case '\0':
if (!j)
return(i);
else
return(0 - i);
case 'b':
return(i * 512);
case 'k':
return(i * 1024);
default:
error_status = TRUE;
return(0);
}/*E switch *numstring */
}/*E expnum() */
/* showhelp() routine was moved here from ltf.c module */
/**/
/*
*
* Function:
*
* showhelp()
*
* Function Description:
*
* Prints a help message with a description of all functions,
* switches, and qualifiers and their definitions, then exits
*
* Arguments:
*
* n/a
*
* Return values:
*
* none
*
* Side Effects:
*
* This function never returns to the caller.
* It always exits to the system.
*
*/
showhelp()
{
#ifndef U11
PERROR "\n%s: %s\n", Progname, USE1);
PERROR "%s: %s\n", Progname, USE2);
PERROR "%s: %s\n", Progname, HELP1);
PERROR "%s: %s\n", Progname, HELP2);
PERROR "%s: %s\n", Progname, HELP3);
PERROR "%s: %s\n", Progname, HELP4);
PERROR "%s: %s\n", Progname, HELP5);
PERROR "%s: %s\n", Progname, HELP6);
PERROR "%s: %s\n", Progname, HELP7);
PERROR "%s: %s\n", Progname, HELP9);
PERROR "%s: %s\n", Progname, HELP10);
PERROR "%s: %s\n", Progname, HELP11);
PERROR "%s: %s\n", Progname, HELP12);
PERROR "%s: %s\n", Progname, HELP13);
PERROR "%s: %s\n", Progname, HELP14);
PERROR "%s: %s\n\n", Progname, HELP30);
PERROR "%s: %s ", Progname, HELP20);
response();
PERROR "\n%s: %s\n", Progname, USE1);
PERROR "%s: %s\n", Progname, USE2);
PERROR "%s: %s\n", Progname, HELP31);
PERROR "%s: %s\n", Progname, HELP15);
PERROR "%s: %s\n", Progname, HELP16);
PERROR "%s: %s\n", Progname, HELP17);
PERROR "%s: %s\n", Progname, HELP18);
PERROR "%s: %s\n", Progname, HELP19);
PERROR "%s: %s\n", Progname, HELP21);
PERROR "%s: %s\n", Progname, HELP22);
PERROR "%s: %s\n", Progname, HELP23);
PERROR "%s: %s\n", Progname, HELP24);
PERROR "%s: %s\n", Progname, HELP25);
PERROR "%s: %s\n", Progname, HELP26);
PERROR "%s: %s\n", Progname, HELP27);
PERROR "%s: %s\n", Progname, HELP28);
PERROR "%s: %s\n", Progname, HELP29);
#else U11
PERROR "\n%s: %s\n", Progname, USE1);
PERROR "%s: %s\n\n", Progname, USE2);
PERROR "%s: %s\n\n", Progname, TRYHELP);
#endif U11
exit(FAIL);
}/*E showhelp() */
/* usage() routine was moved here from ltf.c */
/**/
/*
*
* Function:
*
* usage()
*
* Function Description:
*
* Prints a summary of the command line format,
* allowable functions, qualifiers, etc..
*
* Arguments:
*
* n/a
*
* Return values:
*
* none
*
* Side Effects:
*
* This function never returns to the caller.
* It always exits to the system.
*
*/
usage()
{
PERROR "\n%s: %s%c", Progname, USE1, BELL);
PERROR "\n%s: %s", Progname, USE2);
PERROR "\n%s: %s\n\n", Progname, TRYHELP);
exit(FAIL);
}/*E usage() */
/**\\**\\**\\**\\**\\** EOM filenames.c **\\**\\**\\**\\**\\*/
/**\\**\\**\\**\\**\\** EOM filenames.c **\\**\\**\\**\\**\\*/