char *ckzv = "MS-DOS file support, 4LC (001) 01 Jul 85"; /* F. da Cruz, Columbia University Center for Computing Activities */ /* Modified for use with MS-DOS by: Jan A. van der Eijk, NUS Corp., July 1985 */ /* Copyright (C) 1985, Trustees of Columbia University in the City of New York. Permission is granted to any individual or institution to use, copy, or redistribute this software so long as it is not sold for profit, provided this copyright notice is retained. */ char *ckzsys = "MS-DOS 3.1"; /* Functions (n is one of the predefined file numbers from ckcker.h): zopeni(n,name) -- Opens an existing file for input. zopeno(n,name) -- Opens a new file for output. zclose(n) -- Closes a file. zchin(n,&c) -- Gets the next character from an input file. zsout(n,s) -- Write a null-terminated string to output file, buffered. zsoutl(n,s) -- Like zsout, but appends a line terminator. zsoutx(n,s,x) -- Write x characters to output file, unbuffered. zchout(n,c) -- Add a character to an output file, unbuffered. zchki(name) -- Check if named file exists and is readable, return size. zchko(name) -- Check if named file can be created. znewn(name,s) -- Make a new unique file name based on the given name. zdelet(name) -- Delete the named file. zxpand(string) -- Expands the given wildcard string into a list of files. znext(string) -- Returns the next file from the list in "string". zrtol(n1,n2) -- Convert remote filename into local form. zltor(n1,n2) -- Convert local filename into remote form. */ /* Includes */ #include "stdios.h" /* stdio for small model */ #include #include "lckerm.h" /* Kermit definitions, ctype, stdio */ #include "lckdeb.h" #include "cdisk.h" /* Greenleaf header file */ #include "timedate.h" /* Greenleaf header file */ #define MAXWLD 500 /* Maximum wildcard filenames */ /* Declarations */ FILE *fp[ZNFILS] = { /* File pointers */ NULL, NULL, NULL, NULL, NULL, NULL, NULL }; static int fcount; /* Number of files in wild group */ char *strcpy(), *stpchr(); extern errno; /* System error code */ extern binary; /* Flag for RAW mode, use for Lattice when opening file, JAV * static char *mtchs[MAXWLD], /* Matches found for filename */ **mtchptr; /* Pointer to current match */ /* Z O P E N I -- Open an existing file for input. */ /* Return 1 if successful */ zopeni(n,name) int n; char *name; { debug(F111," zopeni",name,n); debug(F101," fp","",(int) fp[n]); if (chkfn(n) != 0) return(0); if (n == ZSTDIO) { /* Standard input? */ fp[ZIFILE] = stdin; return(1); } if ( n == ZIFILE && binary ) { fp[n] = fopen(name,"rb"); /* Lattice RAW mode */ } else { fp[n] = fopen(name,"r"); /* Real file. */ } debug(F111," zopeni", name, (int) fp[n]); if (fp[n] == NULL) { perror("zopeni"); printf("%s \n",name); } return((fp[n] != NULL) ? 1 : 0); } /* Z O P E N O -- Open a new file for output. */ /* Return 1 if successful */ zopeno(n,name) int n; char *name; { debug(F111," zopeno",name,n); if (chkfn(n) != 0) return(0); if ((n == ZCTERM) || (n == ZSTDIO)) { /* Terminal or standard output */ fp[ZOFILE] = stdout; debug(F101," fp[]=stdout", "", (int) fp[n]); return(1); } if ( n == ZOFILE && binary ) { fp[n] = fopen(name,"wb"); /* Lattice RAW mode */ } else { fp[n] = fopen(name,"w"); /* Real file. */ } if (fp[n] == NULL) perror("zopeno"); if (n == ZDFILE) setbuf(fp[n],NULL); /* Make debugging file unbuffered */ debug(F101, " fp[n]", "", (int) fp[n]); return((fp[n] != NULL) ? 1 : 0); } /* Z C L O S E -- Close the given file. */ /* Return 1 if successful */ zclose(n) int n; { if (chkfn(n) < 1) return(0); if ((fp[n] != stdout) && (fp[n] != stdin)) fclose(fp[n]); fp[n] = NULL; return(1); } /* Z C H I N -- Get a character from the input file. */ /* Returns -1 if EOF, 0 otherwise with character returned in argument */ zchin(n,c) int n; char *c; { int a; if (chkfn(n) < 1) return(-1); a = getc(fp[n]); if (a == EOF) return(-1); *c = a & 0377; return(0); } /* Z S O U T -- Write a string to the given file, buffered. */ /* Returns -1 if ERROR, 0 otherwise */ zsout(n,s) int n; char *s; { if (chkfn(n) < 1) return(-1); fprintf(fp[n],s); return(0); } /* Z S O U T L -- Write string to file, with line terminator, buffered */ /* Returns -1 if ERROR, 0 otherwise */ zsoutl(n,s) int n; char *s; { if (chkfn(n) < 1) return(-1); fprintf(fp[n],"%s\n",s); return(0); } /* Z S O U T X -- Write x characters to file, unbuffered. */ /* Returns -1 if ERROR, 0 otherwise */ zsoutx(n,s,x) int n, x; char *s; { if (chkfn(n) < 1) return(-1); return(write(fp[n]->_file,s,x)); } /* Z C H O U T -- Add a character to the given file. */ /* Returns -1 if ERROR, 0 otherwise */ zchout(n,c) int n; char c; { if (chkfn(n) < 1) return(-1); if (n == ZSFILE) return(write(fp[n]->_file,&c,1)); /* Use unbuffered for session log */ else { putc(c,fp[n]); /* Buffered for everything else */ return(0); } } /* C H K F N -- Internal function to verify file number is ok */ /* Returns: -1: File number n is out of range 0: n is in range, but file is not open 1: n in range and file is open */ chkfn(n) int n; { switch (n) { case ZCTERM: case ZSTDIO: case ZIFILE: case ZOFILE: case ZDFILE: case ZTFILE: case ZPFILE: case ZSFILE: break; default: debug(F101,"chkfn: file number out of range","",n); fprintf(stderr,"?File number out of range - %d\n",n); return(-1); } return( (fp[n] == NULL) ? 0 : 1 ); } /* Z C H K I -- Check if input file exists and is readable */ /* Returns: >= 0 if the file can be read (returns the size). -1 if file doesn't exist or can't be accessed, -2 if file exists but is not readable (e.g. a directory file). -3 if file exists but protected against read access. */ /* Directory files, special files, and symbolic links are not readable. */ long zchki(name) char *name; { long int flen; char fname[40]; long lseek(); int foo; stccpy(fname,name,39); if((foo=open(fname,O_RDONLY)) == -1 ) { return(0L); } flen = lseek(foo,0L,2); close(foo); return( (flen > -1L) ? flen : 0L ); } /* Z C H K O -- Check if output file can be created */ /* Returns -1 if write permission for the file would be denied, 0 otherwise. */ zchko(name) char *name; { int i, x; char s[50], *sp; sp = s; /* Make a copy, get length */ x = 0; while ((*sp++ = *name++) != '\0') x++; if (x == 0) return(-1); /* If no filename, fail. */ debug(F101," length","",x); for (i = x; i > 0; i--) /* Strip filename. */ if (s[i-1] == '/') break; debug(F101," i","",i); if (i == 0) /* If no path, use current directory */ strcpy(s,"./"); else /* Otherwise, use given one. */ s[i] = '\0'; /* x = access(s,W_OK); */ /* Check access of path. */ x = 0; /* assume it is ok to open file under DOS */ if (x < 0) { debug(F111,"zchko access failed:",s,errno); return(-1); } else { debug(F111,"zchko access ok:",s,x); return(0); } } /* Z D E L E T -- Delete the named file. */ zdelet(name) char *name; { unlink(name); } /* Z R T O L -- Convert remote filename into local form */ /* For DOS, this means changing lowercase letters to uppercase. */ zrtol(name,name2) char *name, *name2; { for ( ; *name != '\0'; name++) { *name2++ = islower(*name) ? toupper(*name) : *name; } *name2 = '\0'; } /* Z L T O R -- Convert filename from local format to common form. */ zltor(name,name2) char *name, *name2; { char work[100], *cp, *pp; int dc = 0; strcpy(work,name); for (cp = pp = work; *cp != '\0'; cp++) { /* strip path name */ if (*cp == '\\' || *cp == ':') { pp = cp; pp++; } else if (islower(*cp)) *cp = toupper(*cp); /* Uppercase letters */ else if (*cp == '~') *cp = 'X'; /* Change tilde to 'X' */ else if ((*cp == '.') && (++dc > 1)) *cp = 'X'; /* & extra dots */ } cp = name2; /* If nothing before dot, */ if (*pp == '.') *cp++ = 'X'; /* insert 'X' */ strcpy(cp,pp); } /* Z N E X T -- Get name of next file from list created by zxpand(). */ /* Returns >0 if there's another file, with its name copied into the arg string, or 0 if no more files in list. */ znext(fn) char *fn; { if (fcount-- > 0) strcpy(fn,*mtchptr++); else *fn = '\0'; debug(F111,"znext",fn,fcount+1); return(fcount+1); } /* Z N E W N -- Make a new name for the given file */ znewn(fn,s) char *fn, **s; { static char buf[100]; char *bp, *xp; int len = 0, n = 0, d = 0, t; bp = buf; while (*fn) { *bp++ = *fn; len++; if ( *fn++ == '.') break; /* Ignore anything after dot */ } *bp++ = '*'; /* Put a star on the end */ *bp-- = '\0'; n = zxpand(buf); /* Expand the resulting wild name */ while (n-- > 0) { /* Find any existing name~d files */ xp = *mtchptr++; xp += len; if (*xp == '~') { t = atoi(xp+1); if (t > d) d = t; /* Get maximum d */ } } if (len <= 8 && buf[len-1] != '.') sprintf(bp,".~%d ",d+1); /* JRM Add else sprintf(bp,"~%d ",d+1); /* Make and return name~(d+1) */ *s = buf; } /* Z X P A N D -- Expand a wildcard string into an array of strings */ /* Returns the number of files that match fn1, with data structures set up so that first file (if any) will be returned by the next znext() call. */ zxpand(fn) char *fn; { fcount = fgen(fn,mtchs,MAXWLD); /* Look up the file. */ if (fcount > 0) { mtchptr = mtchs; /* Save pointer for next. */ } debug(F111,"zxpand",mtchs[0],fcount); return(fcount); } /* ===================================================================== The following functions use the Greenleaf libaries. ======================================================================== */ #define SSPACE 2000 /* size of string-generating buffer */ static char sspace[SSPACE]; /* buffer to generate names in */ static char *freeptr,**resptr; /* copies of caller's arguments */ static int remlen; /* remaining length in caller's array*/ static int numfnd; /* number of matches found */ /* * fgen: * This is the actual name generator. It is passed a string, * possibly containing wildcards, and an array of character pointers. * It finds all the matching filenames and stores them into the array. * The returned strings are allocated from a static buffer local to * this module (so the caller doesn't have to worry about deallocating * them); this means that successive calls to fgen will wipe out * the results of previous calls. This isn't a problem here * because we process one wildcard string at a time. * * Input: a wildcard string, an array to write names to, the * length of the array. * Returns: the number of matches. The array is filled with filenames * that matched the pattern. If there wasn't enough room in the * array, -1 is returned. * By: Jeff Damens, CUCCA, 1984. */ fgen(fname,resarry,len) char *fname,*resarry[]; int len; { char *ptr; unsigned attr = 0; int stat,len1,len2; char dest[15],path[100],result[120]; numfnd = 0; /* none found yet */ freeptr = sspace; /* this is where matches are copied */ resptr = resarry; /* static copies of these so*/ remlen = len; /* recursive calls can alter them */ if ( (ptr=stpchr(fname,'*')) == NULL ) { if (( ptr = stpchr(fname,'?')) == NULL) { addresult(fname); /* No wild card */ return(numfnd); } } zltor(fname,dest); len1 = strlen(fname); /* get length of whole file */ len2 = strlen(dest); /* length of file */ strcpy(path,fname); /* get the pathname part */ path[len1-len2] = '\0'; stat = dosfirst(fname,attr,dest); /* Greenleaf Function */ if ( stat) return(0); strcpy(result,path); strcat(result,dest); addresult(result); while (TRUE) { stat = dosnext(fname,attr,dest); /* Greenleaf function */ if ( stat) return(numfnd); strcpy(result,path); /* make a complete file name */ strcat(result,dest); addresult(result); } } /* * addresult: * Adds a result string to the result array. Increments the number * of matches found, copies the found string into our string * buffer, and puts a pointer to the buffer into the caller's result * array. Our free buffer pointer is updated. If there is no * more room in the caller's array, the number of matches is set to -1. * Input: a result string. * Returns: nothing. */ addresult(str) char *str; { int l; if (--remlen < 0) { numfnd = -1; return; } l = strlen(str) + 1; /* size this will take up */ if ((freeptr + l) > &sspace[SSPACE-1]) { numfnd = -1; /* do not record if not enough space */ return; } strcpy(freeptr,str); *resptr++ = freeptr; freeptr += l; numfnd++; } /* Z F C D A T -- Return file creation date/time */ zfcdat(fname,str) char *fname,*str; { struct TIMEDATE td; /* Greenleaf function */ if (( getfstamp( &td,fname)) != 0) return(0); /* return false if not */ /* able to get file date */ sprintf(str,"%-4.4d%02.2d%02.2d %002.2d:%002.2d:%002.2d", td.year,td.month,td.day,td.hours,td.minutes,td.seconds); return(1); } /* Z F R E E -- Return total number of free bytes on drive specified */ long zfree(drive) char *drive; { long diskfree(); int driveno; long stat; if (drive[0] != '\0' && drive[1]== ':' ) { driveno = islower(*drive) ? toupper(*drive) : *drive; driveno = driveno - 'A' + 1; } else { driveno = 0; /* Default drive */ } stat = diskfree(driveno,0); /* Greenleaf function */ return(stat); } /* Z F P D A T -- Stamp a given file name with the given date */ zfpdat(fname,dattim) char *fname, *dattim;{ struct TIMEDATE td; /* Greenleaf function */ int i; char date[20],time[20], *dp; i = 0; for ( dp=dattim; *dp != '\0' && *dp != ' '; dp++) { date[i++] = *dp; } date[i] = '\0'; /* delimted date string */ if ( i <= 5 ) return; /* not ISO standard */ td.day = atoi(&date[i-2]); /* convert the day to int */ date[i-2] = '\0'; td.month = atoi(&date[i-4]); /* convert the month to int */ date[i-4] = '\0'; td.year = atoi(date); /* convert the year to int */ if ( td.day <= 0 || td.month <=0 || td.year < 0 ) return; if ( td.year < 1900 ) td.year += 1900; /* check date range */ i= 0; if ( *dp++ == ' ') { /* get the time if given */ for ( i=0; *dp != '\0';dp++){ time[i++] = *dp; } time[i] = '\0'; } td.seconds = 0; td.minutes = 0; td.hours = 0; switch (i){ case 8: td.seconds = atoi(&time[6]); time[5] ='\0'; /* fall through */ case 5: td.minutes = atoi(&time[3]); time[2] = '\0'; /* fall through */ case 2: td.hours = atoi(time); default: break; } /* Greenleaf function */ putfstamp(&td,fname); /* change the creation date */ }