gno/usr.orca.bin/udl/common.c
gdr 85008f04ca Soenke's initial checkins for v1.14, dated 30 Jan 95.
The temp file is now created in the same directory as the original file,
then renamed after the conversion is done.

Some small doc changes were made as well, mostly typos and addresses.
1995-02-08 05:15:36 +00:00

895 lines
21 KiB
C

/*
* udl - Convert EOL formats freely between MS-DOS (CR/LF), Unix/Amiga (LF),
* and Apple (CR).
*
* Routines common to both the Unix and Apple IIgs versions.
*
* $Id: common.c,v 1.3 1995/02/08 05:15:26 gdr Exp $
*
* Copyright (c) 1993-1995 Soenke Behrens, Devin Glyn Reade
*/
#include "common.h"
extern char *strdup(const char *);
/*
* convert_gs() ... convert files to use CR as EOL
*
* Inputs:
* FILE *infile File to read from
* FILE *outfile File to write to
*
* Outputs:
* None
*/
void convert_gs(FILE *infile, FILE *outfile) {
unsigned char a;
unsigned char *in_bufpos;
unsigned char *out_bufpos;
unsigned char *in_bufend;
unsigned char *out_bufend;
size_t file_remain;
in_bufpos = in_buffer;
out_bufpos = out_buffer;
(void) fseek(infile,0L,SEEK_END);
file_remain = ftell(infile);
rewind(infile);
in_bufend = in_buffer + my_fread(infile,BUFFERSIZE);
out_bufend = out_buffer + BUFFERSIZE;
while (file_remain != 0) {
a = *in_bufpos;
in_bufpos++;
if (in_bufpos >= in_bufend) {
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile,BUFFERSIZE);
in_bufpos = in_buffer;
}
/* a = fgetc (infile); */
if(a == '\n') {
*out_bufpos = '\r';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\r',outfile); */
} else if(a == '\r') {
*out_bufpos = '\r';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\r',outfile); */
if (*in_bufpos == '\n' && file_remain != 0) {
in_bufpos++;
if (in_bufpos >= in_bufend) {
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
in_bufpos = in_buffer;
}
}
/* if ((a = fgetc (infile)) != '\n')
ungetc (a,infile); */
} else {
*out_bufpos = a;
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc(a,outfile); */
}
}
/* Check for remainder in output buffer */
if (out_bufpos != out_buffer)
my_fwrite(out_buffer,outfile,out_bufpos - out_buffer);
}
/*
* convert_messy() ... convert files to use CR/LF as EOL
*
* Inputs:
* FILE *infile File to read from
* FILE *outfile File to write to
*
* Outputs:
* None
*/
void convert_messy (FILE *infile, FILE *outfile) {
unsigned char a;
unsigned char *in_bufpos;
unsigned char *out_bufpos;
unsigned char *in_bufend;
unsigned char *out_bufend;
size_t file_remain;
in_bufpos = in_buffer;
out_bufpos = out_buffer;
(void) fseek(infile,0L,SEEK_END);
file_remain = ftell(infile);
rewind(infile);
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
out_bufend = out_buffer + BUFFERSIZE;
while (file_remain != 0) {
a = *in_bufpos;
in_bufpos++;
if (in_bufpos >= in_bufend) {
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
in_bufpos = in_buffer;
}
/* a = fgetc (infile); */
if(a == '\n') {
*out_bufpos = '\r';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\r',outfile); */
*out_bufpos = '\n';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\n',outfile); */
} else if(a == '\r') {
*out_bufpos = '\r';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\r',outfile); */
*out_bufpos = '\n';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\n',outfile); */
if (*in_bufpos == '\n' && file_remain != 0) {
in_bufpos++;
if (in_bufpos >= in_bufend) {
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
in_bufpos = in_buffer;
}
}
/* if ((a = fgetc (infile)) != '\n')
ungetc (a,infile); */
} else {
*out_bufpos = a;
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc(a,outfile); */
}
}
/* Check for remained in output buffer */
if (out_bufpos != out_buffer)
my_fwrite(out_buffer,outfile,out_bufpos - out_buffer);
}
/*
* convert_tunix() ... convert files to use LF as EOL
*
* Inputs:
* FILE *infile File to read from
* FILE *outfile File to write to
*
* Outputs:
* None
*/
void convert_tunix (FILE *infile, FILE *outfile) {
unsigned char a;
unsigned char *in_bufpos;
unsigned char *out_bufpos;
unsigned char *in_bufend;
unsigned char *out_bufend;
size_t file_remain;
in_bufpos = in_buffer;
out_bufpos = out_buffer;
(void) fseek(infile,0L,SEEK_END);
file_remain = ftell(infile);
rewind(infile);
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
out_bufend = out_buffer + BUFFERSIZE;
while (file_remain != 0) {
a = *in_bufpos;
in_bufpos++;
if (in_bufpos >= in_bufend) {
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
in_bufpos = in_buffer;
}
/* a = fgetc (infile); */
if(a == '\r') {
*out_bufpos = '\n';
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc('\n',outfile); */
if (*in_bufpos == '\n' && file_remain != 0) {
in_bufpos++;
if (in_bufpos >= in_bufend) {
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
in_bufpos = in_buffer;
}
}
/* if ((a = fgetc (infile)) != '\n')
ungetc (a,infile); */
} else {
*out_bufpos = a;
out_bufpos++;
if (out_bufpos == out_bufend) {
my_fwrite(out_buffer,outfile,BUFFERSIZE);
out_bufpos = out_buffer;
}
/* fputc(a,outfile); */
}
}
/* Check for remainder in output buffer */
if (out_bufpos != out_buffer)
my_fwrite(out_buffer,outfile,out_bufpos - out_buffer);
}
/*
* convert_fast_gs() ... convert files to use CR as EOL
* Do not care about differing EOL chars in the same file,
* do not allow '\0' bytes, and replace in-vitro if possible.
*
* Inputs:
* FILE *infile File to read from
* FILE *outfile File to write to
*
* Outputs:
* int FALSE if no conversion took place, TRUE otherwise
*/
int convert_fast_gs(FILE *infile, FILE *outfile) {
unsigned char a;
unsigned char *in_bufpos;
unsigned char *out_bufpos;
unsigned char *in_bufend;
unsigned char *out_bufend;
size_t file_remain;
enum file_format infile_type;
in_bufpos = in_buffer;
out_bufpos = out_buffer;
(void) fseek(infile,0L,SEEK_END);
file_remain = ftell(infile);
rewind(infile);
in_bufend = in_buffer + my_fread(infile,BUFFERSIZE);
out_bufend = out_buffer + BUFFERSIZE;
*in_bufend = '\0';
infile_type = get_file_format (in_buffer);
switch (infile_type) {
case apple:
if (verbose)
printf("%s: %s is already in Apple format, skipping.\n",
program_name,current_file);
return (FALSE);
break;
case tunix:
/* Replace "in-vitro", so out_buffer isn't used */
while (file_remain != 0) {
a = *in_bufpos;
if (a == '\n')
*in_bufpos++ = '\r';
else if (a == '\0') { /* End of buffer reached */
/* Write changed buffer out */
my_fwrite(in_buffer,outfile,in_bufend - in_buffer);
/* And reload it */
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
*in_bufend = '\0';
in_bufpos = in_buffer;
} else in_bufpos++;
}
return (TRUE);
break;
case dos:
/* This I couldn't speed up, so use the existing thing */
convert_gs (infile, outfile);
return (TRUE);
break;
case binary:
return (FALSE);
break;
default:
fprintf(stderr,"%s: Fatal internal error\n",program_name);
exit (EXIT_FAILURE);
break;
} /* switch */
}
/*
* convert_fast_messy() ... convert files to use CR/LF as EOL
* Just check if it's already in DOS format.
*
* Inputs:
* FILE *infile File to read from
* FILE *outfile File to write to
*
* Outputs:
* int FALSE if no conversion took place, TRUE otherwise
*/
int convert_fast_messy (FILE *infile, FILE *outfile) {
unsigned char *in_bufpos;
unsigned char *out_bufpos;
unsigned char *in_bufend;
unsigned char *out_bufend;
size_t file_remain;
enum file_format infile_type;
in_bufpos = in_buffer;
out_bufpos = out_buffer;
(void) fseek(infile,0L,SEEK_END);
file_remain = ftell(infile);
rewind(infile);
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
out_bufend = out_buffer + BUFFERSIZE;
*in_bufend = '\0';
infile_type = get_file_format (in_buffer);
switch (infile_type) {
case dos:
if (verbose)
printf("%s: %s is already in MS-DOS format, skipping.\n",
program_name,current_file);
return (FALSE);
break;
case tunix: /* drop through */
case apple:
/* Wasn't able to speed this up, call old routine */
convert_messy (infile, outfile);
return (TRUE);
break;
case binary:
return (FALSE);
break;
default:
fprintf(stderr,"%s: Fatal internal error\n",program_name);
exit (EXIT_FAILURE);
break;
} /* switch */
}
/*
* convert_fast_tunix() ... convert files to use LF as EOL
* Do not care about differing EOL chars in the same file,
* do not allow '\0' bytes, and replace in-vitro if possible.
*
* Inputs:
* FILE *infile File to read from
* FILE *outfile File to write to
*
* Outputs:
* int FALSE if no conversion took place, TRUE otherwise
*/
int convert_fast_tunix (FILE *infile, FILE *outfile) {
unsigned char a;
unsigned char *in_bufpos;
unsigned char *out_bufpos;
unsigned char *in_bufend;
unsigned char *out_bufend;
size_t file_remain;
enum file_format infile_type;
in_bufpos = in_buffer;
out_bufpos = out_buffer;
(void) fseek(infile,0L,SEEK_END);
file_remain = ftell(infile);
rewind(infile);
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
out_bufend = out_buffer + BUFFERSIZE;
*in_bufend = '\0';
infile_type = get_file_format (in_buffer);
switch (infile_type) {
case tunix:
if (verbose)
printf("%s: %s is already in Unix format, skipping.\n",
program_name,current_file);
return (FALSE);
break;
case apple:
/* Replace "in-vitro", so out_buffer isn't used */
while (file_remain != 0) {
a = *in_bufpos;
if (a == '\r')
*in_bufpos++ = '\n';
else if (a == '\0'){ /* End of buffer reached */
/* Write changed buffer out */
my_fwrite(in_buffer,outfile,in_bufend - in_buffer);
/* And reload */
file_remain -= in_bufend - in_buffer;
in_bufend = in_buffer + my_fread(infile, BUFFERSIZE);
*in_bufend = '\0';
in_bufpos = in_buffer;
} else in_bufpos++;
}
return (TRUE);
break;
case dos:
/* Couldn't speed it up, so use old routine */
convert_tunix (infile, outfile);
return (TRUE);
break;
case binary:
return (FALSE);
break;
default:
fprintf(stderr,"%s: Fatal internal error\n", program_name);
exit (EXIT_FAILURE);
break;
} /* switch */
}
/*
* get_file_format() ... look at a buffer and find out what the EOL
* character is. If no EOL character is found, print an error message
* and exit.
*
* Inputs:
* unsigned char *buffer Buffer to search through, terminated
* by '\0'.
*
* Output:
* enum file_format tunix, dos, apple, or binary
*/
enum file_format get_file_format (unsigned char *buffer) {
unsigned char c;
enum file_format result = 0;
while ((c = *buffer++) != '\0') {
if (c == '\n') {
result = tunix;
break;
} else if (c == '\r') {
if (*buffer == '\n')
result = dos;
else
result = apple;
break;
}
}
if (result == 0) {
if (verbose)
printf("%s: No EOL found on the first %d bytes "
"of %s. Might be a binary file. File skipped\n",
program_name,BUFFERSIZE, current_file);
result = binary;
}
return (result);
}
/*
* tryopen() ... try to open a file, exit if unsuccesful
*
* Inputs:
* char *name Name of file to be opened
* char *mode Mode string for fopen() call
*
* Output:
* FILE * File identifier of successful fopen()
*/
FILE *tryopen (char *name, char *mode) {
FILE *tmp;
if ((tmp = fopen(name,mode)) == NULL) {
fprintf(stderr,"%s: Unable to open file %s\n",program_name, name);
exit (EXIT_FAILURE);
} else
return (tmp);
}
/*
* my_fread() ... read data into global buffer and exit if I fail
*
* Inputs:
* FILE *infile File to read from
* int howmuch Number of bytes to read
*
* Output:
* int Number of bytes actually read
*/
int my_fread(FILE *infile, int howmuch) {
int result;
result = fread(in_buffer, 1, howmuch, infile);
if (ferror(infile)) {
fprintf(stderr,"%s: Error while reading data\n",program_name);
exit (EXIT_FAILURE);
}
return (result);
}
/*
* my_fwrite() ... write data from global buffer to file
*
* Inputs:
* unsigned char *buffer Buffer to write out
* FILE *outfile File to write to
* int howmuch Number of bytes to write
*
* Output:
* None
*/
void my_fwrite (unsigned char *buffer, FILE *outfile, int howmuch) {
fwrite(buffer, 1, howmuch, outfile);
if (ferror(outfile)) {
fprintf(stderr,"%s: Error while writing data\n",program_name);
exit (EXIT_FAILURE);
}
return;
}
/*
* cleanup() ... called in case of an exit(). Frees memory I allocated.
*
* Inputs:
* None
*
* Output:
* None
*/
void cleanup (void) {
char **p;
free (program_name);
free (current_file);
free (in_buffer);
free (out_buffer);
free (tempfile);
if (pathList) {
p = pathList;
while(*p) free(*p++);
free (pathList);
}
if (tempfile)
remove (tempfile);
}
/*
* usage() ... print out a usage string gotten from udluse.c
*
* Inputs:
* None
*
* Outputs:
* None
*/
void usage (void) {
extern char use1[]; /* from udluse.c */
extern char use2[];
fprintf(stderr,"%s",use1);
#ifdef GNO
if(!needsgno())
fprintf(stderr,"%s",use2);
#endif
return;
}
/*
* build_file_list() build the list of files to process
*
* Precondition:
* file is the file name to be added to the pathList
* recurse if non-zero, directories will be recursed
*
* Postcondition:
* pathList will be a NULL-terminated array of strings. Each
* string is a partial pathname (relative to rootdir) of a file
* to convert.
*
* Note: This is a recursive routine that uses up (3 * sizeof(char *))
* bytes of stack with each level of subdirectories.
*/
void build_file_list(char *file, short recurse) {
char *thisdir;
DIR *dir;
struct dirent *entry;
/* check for stack overflow */
recursionDepth++;
#ifdef OVERFLOW_CHECK
if ((recursionDepth * BYTES_PER_DEPTH + BASESIZE) > STACKSIZE) {
fprintf(stderr,"%s: Exceeded permitted nesting depth (%d levels)\n"
"Aborted.\n",program_name,recursionDepth);
exit(EXIT_FAILURE);
}
#endif
if (stat(file,&tstat)!=0) {
fprintf(stderr,"%s: Couldn't stat %s. File skipped\n",program_name,file);
--recursionDepth;
return;
}
if (recurse && S_ISDIR(tstat.st_mode)) {
char tstr[2];
/*
* It is a directory. recurse through it.
*/
/* save our state */
tstr[0] = dirbrk;
tstr[1] = '\0';
if (*currentDirectory) {
thisdir = strdup(currentDirectory);
} else {
thisdir = malloc(1);
if (thisdir != NULL) *thisdir='\0';
}
if (thisdir == NULL) {
perror("Couldn't duplicate current directory");
exit (EXIT_FAILURE);
}
if (*currentDirectory) strcat(currentDirectory,tstr);
strcat(currentDirectory,file);
/* recurse */
if ((dir = opendir(file)) == NULL) {
fprintf(stderr,"%s: Couldn't open %s. Directory skipped.\n",
program_name,currentDirectory);
} else {
if (chdir(file) !=0) {
fprintf(stderr,"couldn't cd to %s\n",currentDirectory);
exit (EXIT_FAILURE);
}
#ifdef READDIR_RETURNS_DOT
entry = readdir(dir); /* for "." */
entry = readdir(dir); /* for ".." */
#endif
while ((entry = readdir(dir))!=NULL) {
/* ignore hidden files */
if (*(entry->d_name)!='.') build_file_list(entry->d_name,1);
}
if (*thisdir) {
if ((chdir(rootdir)!=0) || (chdir(thisdir)!=0)) {
fprintf(stderr,"couldn't cd to %s\n",thisdir);
exit (EXIT_FAILURE);
}
} else {
if (chdir(rootdir)!=0) {
fprintf(stderr,"couldn't cd to calling directory\n");
exit (EXIT_FAILURE);
}
}
}
/* restore our state */
strcpy(currentDirectory,thisdir);
free(thisdir);
} else if (S_ISREG(tstat.st_mode)) {
/* It is a normal file. Add it to the pathList */
add_to_pathList(currentDirectory, file);
}
--recursionDepth;
return;
}
void add_to_pathList(char *thisdir, char *file) {
char **p;
/* expand the pathList if necessary */
if (pathSlotsUsed >= pathSlots) {
pathSlots += PATHLIST_QUANTUM;
#if BROKEN_REALLOC
if ((pathList==NULL) &&
((pathList = malloc((pathSlots+1) * sizeof(char *)))==NULL)) {
fprintf(stderr,"%s: Couldn't expand pathList\n",program_name);
exit (EXIT_FAILURE);
} else {
if ((p = realloc(pathList, (pathSlots+1) * sizeof(char *)))==NULL) {
fprintf(stderr,"%s: Couldn't expand pathList\n",program_name);
exit (EXIT_FAILURE);
}
pathList = p;
}
#else
if ((p = realloc(pathList,(pathSlots+1) * sizeof(char *)))==NULL) {
fprintf(stderr,"%s: Couldn't expand pathList\n",program_name);
exit (EXIT_FAILURE);
} else pathList = p;
#endif
}
/* add in the current directory and filename to the pathList */
pathList[pathSlotsUsed] = malloc(strlen(thisdir)+strlen(file)+2);
if (pathList[pathSlotsUsed] == NULL) {
fprintf(stderr,"%s: Couldn't duplicate filename %s%c%s\n",program_name,
thisdir,dirbrk,file);
exit (EXIT_FAILURE);
}
if (*thisdir) {
sprintf(pathList[pathSlotsUsed],"%s%c%s",thisdir,dirbrk,file);
} else {
strcpy(pathList[pathSlotsUsed],file);
}
pathSlotsUsed++;
pathList[pathSlotsUsed] = NULL;
return;
}
/* mktemp() construct a unique file name
*
* Inputs:
* base Template to construct the name upon. It should
* be in the format "nameXXXXXX" where all "X" are replaced
* in such a way that the resulting name is unique. There
* should be at least one, at most 15 "X" in the base name.
* base may contain a full or partial path.
*
* Outputs:
* mktemp() returns a pointer to a dynamically allocated string
* containing a unique file name.
*
*/
char *mktemp(const char *base)
{
static char id[16] = "AAAAAAAAAAAAAAA";
char *p1,*p2,*st;
if ((st = malloc(strlen(base) + 1)) == NULL)
{
fprintf(stderr,"%s: memory allocation failure\n", program_name);
exit (EXIT_FAILURE);
}
st = strcpy(st,base);
if (*st == '\0')
{
free (st);
if ((st = strdup("TXXXXXXX")) == NULL)
{
fprintf(stderr,"%s: memory allocation failure\n", program_name);
exit (EXIT_FAILURE);
}
}
/* Replace all "X" with part if ID string */
for(p1 = st + strlen(st) - 1,p2 = &id[14];
p1 >= st && p2 >= id && *p1 == 'X';
p1--,p2--)
*p1 = *p2;
/* Update ID string to "count" one further */
for(p1 = &id[14];p1 >= id;)
if(*p1 == 'Z')
{
*p1 = 'A';
p1--;
} else {
*p1++;
break;
}
/* Make sure the file name does not already exist */
if (stat(st,&tstat) == 0)
{
free (st);
st = mktemp (base);
}
return st;
}
/* get_path() ... extract path from filename
*
* Inputs:
* name A file name containing a full, partial or no path.
*
* Outputs:
* Pointer to a string in static memory containing the path
* to the given file, or an empty string if "name" contained
* no path. The string can hold MAXPATHLEN characters.
*/
char *get_path (const char *name)
{
int i;
strcpy(filebuffer, name);
for (i = strlen(filebuffer) - 1; i >= 0 && filebuffer[i] != dirbrk; i--)
; /* empty loop to find end of path in name */
if (i != 0)
++i;
filebuffer[i] = '\0';
return filebuffer;
}
/* End Of File */