/* Version 0.9(37) - Paul Placeway at Ohio State, Jan 1988 */ /* reformatted all of the code so that it would be 79 or fewer colums */ /* May 88 - Added dummy zgtdir() function, Frank, CU. /* Version 0.8(35) - Jim Noble at Planning Research Corporation, June 1987. */ /* Ported to Megamax native Macintosh C compiler. */ /* Edit by Bill on Thu May 30, 00:18 */ /* Do error handling, neaten up comments, and some code. */ /* Edit by Bill on Wed May 15, 16:09 */ /* Make zrtol call common sfprtol, .RSRC overrides default settings */ /* ckmfio.c, Mon Apr 29 17:48, Edit by Bill*2 */ /* Put null in translated name to tie it off. */ /* Make author text of new file to ???? instead of random string */ /* Do flushvol after closing a file */ /* Bill C., Apr 24 */ /* Change zchin to allow sending of files with high order bits on */ /* Bill C., Apr 22 */ /* Add error handling (informing) for more cases, e.g. can't delete */ /* Bill C., Apr 22 */ /* Fix Resource/Data fork stuff. Uppercase things where needed */ /* ckzmac.c, Thu Apr 21 17:19, Edit by Bill */ /* Ignore trying to close an not-openend file, driver does it alot */ /* ckzmac.c, Thu Apr 11 21:18, Edit by Bill */ /* Catch error in ZOPENO when trying to open an existing file */ /* ckzmac.c, Thu Apr 14 20:07, Edit by Bill */ /* Translate calls with ZCTERM to go to the console routines */ /* * File ckmfio -- Kermit file system support for the Macintosh * * 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. * */ /* Definitions of some Unix system commands */ #define DIRCMDSTR "ls" #define DELCMDSTR "rm" #define SPCCMDSTR "sp" char *DIRCMD = DIRCMDSTR; /* For directory listing */ char *DELCMD = DELCMDSTR; /* For file deletion */ char *SPACMD = SPCCMDSTR; /* Space for all available volumes */ char *TYPCMD = ""; /* For typing a file */ char *SPACM2 = ""; /* For space in specified directory */ char *WHOCMD = ""; /* For seeing who's logged in */ /* Functions (n is one of the predefined file numbers from ckermi.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) -- 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". zxcmd(cmd) -- Execute the command in a lower fork. zclosf() -- Close input file associated with zxcmd()'s lower fork. zrtol(n1,n2) -- Convert remote filename into local form. zltor(n1,n2) -- Convert local filename into remote form. */ #include "ckcdeb.h" /* Debug() and tlog() defs */ #include "ckcker.h" /* Kermit definitions */ #define __SEG__ ckmfio #include #include #include #include #include #include #include #include /* needed for ckmasm.h */ #include "ckmdef.h" /* Common Mac module definitions */ #include "ckmres.h" /* Resource defs */ #include "ckmasm.h" /* Assembler code */ /* These should all be settable by the File Settings Menu */ OSType authortext = 'MACA'; /* set creator to "MacWrite" */ #define FS_WIND 1 /* file is a text edit buffer */ #define FS_OPEN 2 /* file has been opened */ #define FS_RSRC 4 /* opened in resource fork */ #define FS_DATA 8 #define FS_PIPE 16 /* file is a memory buffer */ #define PIPESIZE 128 typedef struct { int charsleft; /* nuber of unread characters in the buffer */ ProcPtr refill; /* pointer to the refill procedure */ char *currptr; /* characters left before next pipe refill */ char pipebuf[PIPESIZE]; /* buffer to keep the pipes content */ } MACPIPE; typedef struct { short frefnum; /* file reference number (pascal) */ int fstatus; /* file status bits */ MACPIPE *fpipe; /* pointer to a pipe */ } MACFILE; MACFILE fp[ZNFILS] = { /* File information */ {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0} }; /****************************************************************************/ /* Z O P E N I -- Open an existing file for input. * * The file name has been returned from and the volume reference * number set by SFGetFile. * * Returns: * TRUE: file opened ok * FALSE: some error. */ /****************************************************************************/ zopeni (n, name) int n; char *name; { int err; register MACFILE *fpp; if (chkfn (n)) { printerr ("At zopeni file is already open ", n); return (FALSE); } fpp = &fp[n]; if (n == ZCTERM) { /* Terminal open? */ if (chkfn (ZIFILE)) /* Check current ZOFILE */ printerr ("ZIFILE already open...: ", n); fp[ZIFILE].fstatus = FS_WIND; /* redirect... here it is */ fpp->fstatus = FS_WIND; /* Indicate this is open too */ return (conopen ()); /* Return from low level open */ } if (n == ZSYSFN) /* trying to open a pipe? */ return (zxcmd (name)); /* yes... */ if (n == ZIFILE && /* opening input file? */ (filargs.filflg & FIL_RSRC)) /* and they said resource? */ err = OpenRF (name, filargs.filvol, &fpp->frefnum); else /* else some other channel or data */ err = FSOpen (name, filargs.filvol, &fpp->frefnum); if (err != noErr) /* check for open error */ return (ioutil (err)); /* failed... */ fpp->fstatus = FS_OPEN | ( /* set flags */ (filargs.filflg & FIL_RSRC) ? FS_RSRC : FS_DATA); GetEOF (fpp->frefnum, &filargs.filsiz); /* set size for screen */ return (TRUE); /* Return success */ } /* zopeni */ /****************************************************************************/ /* Z O P E N O -- Open a new file for output. * * Returns: * TRUE: File opened ok * FALSE: some error has occured or channel occupied. * */ /****************************************************************************/ zopeno (n, name) int n; char *name; { OSType forktext; int err; FInfo finfo; register MACFILE *fpp; if (chkfn (n)) { printerr ("zopeno - file is already open: ", n); return (FALSE); } fpp = &fp[n]; if (n == ZCTERM || n == ZSTDIO) { /* Terminal open? */ if (chkfn (ZOFILE)) /* Check current ZOFILE */ printerr ("ZOFILE already open...: ", n); fp[ZOFILE].fstatus = FS_WIND; /* yes, redirect... here it is */ fpp->fstatus = FS_WIND; /* Indicate this is open too */ return (conopen ()); /* Return from low level open */ } if (n == ZOFILE && (filargs.filflg & FIL_RSRC)) forktext = 'APPL'; else forktext = 'TEXT'; /* Make fork reflect fork choice */ err = Create (name, filargs.filvol, authortext, forktext); if (err == dupFNErr) { /* duplicate file? */ if (!ioutil (FSDelete (name, /* Try to delete it */ filargs.filvol))) /* checking for failure */ return (FALSE); /* failed... */ err = Create (name, filargs.filvol, /* recreate */ authortext, forktext); } if (err != noErr) /* some error? */ return (ioutil (err)); /* yes, do message and return */ /* set file's folder from filargs.filfldr which is either the */ /* applications folder or the settings file folder */ GetFInfo (name, filargs.filvol, &finfo); /* read current finder info */ finfo.fdFldr = filargs.filfldr; /* set new folder */ SetFInfo (name, filargs.filvol, &finfo); /* and tell system about it */ if (n == ZOFILE && /* is it our transferred file? */ (filargs.filflg & FIL_RSRC)) /* want to use resource fork? */ err = OpenRF (name, filargs.filvol, /* yes... */ &fpp->frefnum); else /* else data, or some other file */ err = FSOpen (name, filargs.filvol, &fpp->frefnum); if (err != noErr) /* able to open? */ return (ioutil (err)); /* no. fail return now */ fp[n].fstatus = FS_OPEN | ((filargs.filflg & FIL_RSRC) ? FS_RSRC : FS_DATA); return (TRUE); /* done ok */ } /* zopeno */ /****************************************************************************/ /* Z C L O S E -- Close the given file. * * Returns: * TRUE: file closed ok. * FLASE: some error has occured. * */ /****************************************************************************/ zclose (n) int n; { int err = noErr; register MACFILE *fpp; if (!chkfn (n)) /* is it opened? */ return (FALSE); /* no return now */ fpp = &fp[n]; if (fpp->fstatus == FS_WIND)/* is this a window? */ fp[ZCTERM].fstatus = 0; /* yes, clear ZCTERM */ else if (fpp->fstatus == FS_PIPE) /* is this a pipe? */ fp[ZSYSFN].fstatus = 0; /* yes, no pipe now, clear ZSYSFN */ else { err = FSClose (fpp->frefnum); /* else use OS close */ if (err == noErr) /* and if that worked */ /* i PWP: the above if should be ==, NOT != !!!!! */ err = FlushVol (NILPTR, /* flush buffers in case write worked */ filargs.filvol); } fpp->fstatus = 0; /* clear out status word */ if (n == ZOFILE || n == ZIFILE) /* turn off both flags */ filargs.filflg &= ~(FIL_RSRC | FIL_DATA); return (ioutil (err)); /* return according to io operations */ } /* zclose */ /****************************************************************************/ /* Z C H I N -- Get a character from the input file. * * Returns: * 0: Ok * -1: EOF (or other error). * */ /****************************************************************************/ zchin (n, c) int n; char *c; { int err; long rdcnt; /* pascal long */ register MACFILE *fpp; register MACPIPE *pipe; if (!chkfn (n)) return (0); fpp = &fp[n]; if (fpp->fstatus == FS_WIND) { /* a window? */ printerr ("zchin called for FS_WIND file: ", n); return (0); } if (fpp->fstatus == FS_PIPE) { /* a pipe? */ pipe = fpp->fpipe; if (pipe->charsleft <= 0) { /* test for characters left */ pipe->currptr = pipe->pipebuf; /* restart at the beginning * of the buffer */ if (pipe->refill != NILPROC) { /* refill the pipe if * possible */ saveA0 (); /* push content of A0 to stack */ loadA0 (*(pipe->refill)); /* load the content of refill * to A0 */ execute (); /* call the refill procedure */ restoreA0 (); /* get A0 back from the stack */ } else *(pipe->currptr) = '\0'; /* make it end otherwise */ } if (*(pipe->currptr) == '\0') /* is this eo-pipe? */ return (-1); /* yes, fail return */ *c = *(pipe->currptr)++;/* read character */ (pipe->charsleft)--; /* decrement characters left */ return (0); /* success */ } rdcnt = 1; err = FSRead (fpp->frefnum, &rdcnt, c); if (err == eofErr) return (-1); /* Failure return */ return (ioutil (err) ? 0 : -1); /* success or unknown failure */ } /* zchin */ /****************************************************************************/ /* Z S O U T -- Write a string to the given file, buffered. * * Returns: * 0: OK * -1: Error * */ /****************************************************************************/ zsout (n, s) int n; char *s; { long wrcnt; /* pascal long */ if (n == ZCTERM || fp[n].fstatus == FS_WIND) return (conol (s)); wrcnt = (long) strlen (s); return (ioutil (FSWrite (fp[n].frefnum, &wrcnt, s)) ? 0 : -1); } /* zsout */ /****************************************************************************/ /* Z S O U T L -- Write string to file, with line terminator, buffered. * * Returns: * 0: OK * -1: Error * */ /****************************************************************************/ zsoutl (n, s) int n; char *s; { long wrcnt; /* pascal long */ int err; if (n == ZCTERM || fp[n].fstatus == FS_WIND) return (conoll (s)); wrcnt = (long) strlen (s); err = FSWrite (fp[n].frefnum, &wrcnt, s); if (err == noErr) { wrcnt = 2; err = FSWrite (fp[n].frefnum, &wrcnt, "\r\n"); } return (ioutil (err) ? 0 : -1); } /* zsoutl */ /****************************************************************************/ /* Z S O U T X -- Write x characters to file, unbuffered. * * Returns: * 0: OK * -1: Error */ /****************************************************************************/ zsoutx (n, s, x) int n, x; char *s; { long size; if (n == ZCTERM || fp[n].fstatus == FS_WIND) return (conxo (s, x)); size = x; return (ioutil (FSWrite (fp[n].frefnum, &size, s)) ? 0 : -1); } /* zsoutx */ /****************************************************************************/ /* Z C H O U T -- Add a character to the given file. */ /* */ /* Returns: */ /* 0: OK */ /* -1: Error */ /****************************************************************************/ zchout (n, c) int n; char c; { long wrcnt; /* pascal long */ int err; if (n == ZCTERM || fp[n].fstatus == FS_WIND) { conoc (c); /* Then send to console routine */ return (0); /* Then send to console routine */ } wrcnt = 1; err = FSWrite (fp[n].frefnum, &wrcnt, &c); if (err != noErr) /* error occured? */ sstate = 'a'; /* yes, abort protocol */ return (ioutil (err) ? 0 : -1); /* else return code */ } /* zchout */ /****************************************************************************/ /* C H K F N -- Internal function to verify file number is ok. * * Returns: * TRUE - file is open * FALSE - file is not open * * Issues an error message if the file number is not in range. * */ /****************************************************************************/ chkfn (n) int n; { switch (n) { case ZCTERM: case ZSTDIO: case ZIFILE: case ZOFILE: case ZDFILE: case ZTFILE: case ZPFILE: case ZSYSFN: case ZSFILE: break; default: debug (F101, "chkfn: file number out of range", "", n); printerr ("chkfn - file number not in range: ", n); return (FALSE); /* ugh */ } return ((fp[n].fstatus != 0)); /* if open, fstatus is nonzero */ } /* chkfn */ /****************************************************************************/ /* 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. */ /****************************************************************************/ long zchki (name) char *name; { long size; int err; FileParam info; if (strcmp (name, "stdin") == 0) /* stdin is a pipe */ return (PIPESIZE); /* return size of buffer */ c2pstr (name); /* convert to a pascal string */ info.ioFVersNum = 0; /* No version number */ info.ioFDirIndex = 0; /* Use the file name */ info.ioNamePtr = name; /* Point to the file name */ info.ioVRefNum = filargs.filvol; /* Volume number */ err = PBGetFInfo (&info, FALSE); /* Get info on file */ p2cstr (name); /* put the name back */ if (err == fnfErr) /* file not found? */ return (-1); /* then that is what they want */ if (err != noErr) { /* any other error? */ printerr ("zchki failed: ", err); /* tell me about it */ return (-1); } size = (filargs.filflg & FIL_RSRC) ? /* if thinking about RSRC */ info.ioFlRPyLen : /* return that size, */ info.ioFlPyLen; /* else DATA */ return (size); /* did ok */ } /* zchki */ /****************************************************************************/ /* Z C H K O -- Check if output file can be created. * * Returns * 0: Write OK * -1: write permission for the file should be denied. */ /****************************************************************************/ zchko (name) char *name; { char volname[100]; VolumeParam info; info.ioVolIndex = 0; /* Use the vol ref num only */ info.ioNamePtr = volname; /* Pointer to the volume name */ info.ioVRefNum = filargs.filvol; /* Volume reference number */ if (!ioutil (PBGetVInfo (&info, 0))) /* Get info on vol, * synchronously */ return (-1); /* failed... */ if ((info.ioVAtrb & 0x8000) != 0) /* Write locked? */ return (-1); /* yes... */ return (0); /* else success */ } /* zchko */ /****************************************************************************/ /* Z D E L E T -- Delete the named file and return TRUE if successful */ /****************************************************************************/ zdelet (name) char *name; { return (ioutil (FSDelete (name, filargs.filvol))); } /* zdelet */ /****************************************************************************/ /* Z R T O L -- Convert remote filename into local form. * * Check here to see if this should go into the resource fork (.rsrc) * or into the data fork (.data). * */ /****************************************************************************/ zrtol (name, name2) char *name, *name2; { strcpy (name2, name); /* copy name to destination */ if (filargs.filflg & (FIL_DODLG)) /* selected by user? */ return; /* won't be called but... */ filargs.filflg &= ~(FIL_RBDT); /* clear out flags */ filargs.filflg |= sfprtol (name2); /* convert name2 and set flags */ binary = (filargs.filflg & FIL_BINA); /* selected binary mode? */ return; } /* zrtol */ /****************************************************************************/ /* Z L T O R -- Convert filename from local format to common form. */ /****************************************************************************/ zltor (name, name2) char *name, *name2; { int dc = 0; while (*name != '\0') { if (*name == ' ') name++; /* Skip spaces */ else if ((*name == '.') && (++dc > 1)) { *name2++ = 'X'; /* Just 1 dot */ name++; } else *name2++ = (islower (*name)) ? toupper (*name++) : *name++; } *name2++ = '\0'; /* deposit final null */ return; } /* zltor */ /****************************************************************************/ /* Z C H D I R -- Change directory or volumes */ /****************************************************************************/ zchdir (dirnam) char *dirnam; { int err; int volnum; WDPBRec vinfo; short *FSFCBLen = 0x3F6; if (*FSFCBLen < 0) { /* if no HFS ROM's */ err = SetVol (dirnam, 0); volnum = 0; } else { /* use HFS calls */ c2pstr (dirnam); vinfo.ioVRefNum = 0; /* open a workimg directory */ vinfo.ioWDDirID = 0; vinfo.ioWDProcID = 'ERIK'; vinfo.ioNamePtr = dirnam; err = PBOpenWD (&vinfo, FALSE); p2cstr (dirnam); if (err != noErr) return (FALSE); err = SetVol (NIL, vinfo.ioVRefNum); volnum = vinfo.ioVRefNum; } if (err == noErr) { /* set default volume */ screen (SCR_TN, 0, 0l, dirnam); filargs.filvol = volnum;/* make default */ } else screen (SCR_TN, 0, 0l, "Can't set directory"); return (err == noErr); /* return ok or fail */ } /* zchdir */ /****************************************************************************/ /* Z G T D I R -- Get name of current directory or volume */ /****************************************************************************/ char * zgtdir () { return("(unknown)"); } /****************************************************************************/ /* initialize the fields of a pipe */ /****************************************************************************/ zinitpipe (pipe, refillproc) MACPIPE *pipe; ProcPtr refillproc; { pipe->refill = refillproc; pipe->currptr = pipe->pipebuf; pipe->charsleft = 0; *(pipe->currptr) = '\0'; } /* zinitpipe */ /****************************************************************************/ /* fill the pipe; last is TRUE if it is the */ /* last time the pipe has to be filled */ /****************************************************************************/ zfillpipe (pipe, str, last) MACPIPE *pipe; char *str; Boolean last; { int len; len = strlen (str); if (last) len++; if (len > PIPESIZE) { len = PIPESIZE; if (last) str[PIPESIZE - 1] = '\0'; /* make sure we keep the eop * character */ printerr ("pipe overflow! characters may be lost"); } memcpy (pipe->pipebuf, str, len); pipe->charsleft = len; } /* zfillpipe */ /****************************************************************************/ /* sprintf uses 12 kByte. This is the reason to use a simpler formatter here */ /* formatnum returns a right adjusted numberstring padded with fillc */ /* Numbers which do not fit into width are truncated on the left. */ /* Make sure str is at least 'width+1' bytes wide */ /****************************************************************************/ formatnum (num, fillc, width, str) char *str; long num; char fillc; int width; { int i; char numstr[12]; /* -2147483647 is the longest string */ /* that can be returned from NumToString */ NumToString (num, numstr); i = strlen (numstr); while ((i >= 0) && (width >= 0)) str[width--] = numstr[i--]; while (width >= 0) str[width--] = fillc; } /* formatnum */ MACPIPE cmdpipe; int volindex; char spaceheader[60] = "\ Free Name\n\ --------- --------------------\n"; /****************************************************************************/ /* loop through all available volumes and display the space left */ /****************************************************************************/ zlspace () { int err; Str255 name; long free; char outstr[60]; VolumeParam vinfo; name.length = 0; vinfo.ioVolIndex = volindex; vinfo.ioNamePtr = &name; err = PBGetVInfo (&vinfo, FALSE); if (err == noErr) { free = vinfo.ioVFrBlk * vinfo.ioVAlBlkSiz; formatnum (free, ' ', 9, outstr); strcat (outstr, " "); p2cstr (&name); strcat (outstr, &name); strcat (outstr, "\n"); zfillpipe (&cmdpipe, outstr, FALSE); volindex++; } else zfillpipe (&cmdpipe, "", TRUE); } /* zlspace */ int fileindex; char dirheader[100] = "\ Size Type Crea Last Modification Name\n\ ------- ---- ---- ----------------- --------------------\n"; /****************************************************************************/ /* loop through all the files on the current volume / directory */ /****************************************************************************/ zldir () { int err; CInfoPBRec info; WDPBRec vinfo; Str255 name; DateTimeRec dtrec; char outstr[60]; char type[10]; char tmpstr[11]; char datestr[11]; char hourstr[3]; char minutestr[3]; unsigned long secs; long size; short *FSFCBLen = 0x3F6; if (*FSFCBLen < 0) { errpkt ("Sorry, the server uses 64 kByte ROM's"); zfillpipe (&cmdpipe, "", TRUE); return; } PBHGetVol (&vinfo, FALSE); /* loop through all the files starting at the first one */ name.length = 0; info.hfileInfo.ioFDirIndex = fileindex; /* Get next file name */ info.hfileInfo.ioNamePtr = &name; /* Point to the empty file name */ info.hfileInfo.ioVRefNum = vinfo.ioWDVRefNum; /* Directory / Volume * number */ info.hfileInfo.ioDirID = vinfo.ioWDDirID; /* Directory / Volume number */ err = PBGetCatInfo (&info, FALSE); /* Get info on file */ if (err == noErr) { if (info.hfileInfo.ioFlAttrib & ioDirMask) { /* a directory if it's * true */ secs = info.dirInfo.ioDrMdDat; strcpy (type, "#########"); strcpy (outstr, " "); } else { /* a file otherwise */ secs = info.hfileInfo.ioFlMdDat; size = info.hfileInfo.ioFlLgLen + info.hfileInfo.ioFlRLgLen; strcpy (type, " "); memcpy (type, &info.hfileInfo.ioFlFndrInfo.fdType, 4); memcpy (type + 5, &info.hfileInfo.ioFlFndrInfo.fdCreator, 4); formatnum (size, ' ', 7, outstr); } IUDateString (secs, shortDate, tmpstr); strcpy (datestr, " "); datestr[10 - strlen (tmpstr)] = '\0'; strcat (datestr, tmpstr); Secs2Date (secs, &dtrec); formatnum (dtrec.hour, ' ', 2, hourstr); formatnum (dtrec.minute, '0', 2, minutestr); p2cstr (&name); strcat (outstr, " "); strcat (outstr, type); strcat (outstr, " "); strcat (outstr, datestr); strcat (outstr, " "); strcat (outstr, hourstr); strcat (outstr, ":"); strcat (outstr, minutestr); strcat (outstr, " "); strcat (outstr, &name); strcat (outstr, "\n"); zfillpipe (&cmdpipe, outstr, FALSE); fileindex++; } else zfillpipe (&cmdpipe, "", TRUE); } /* zldir */ #define CMD_RSRC 1 #define CMD_DATA 2 #define CMD_TEXT 3 #define CMD_BINA 4 #define CMD_DIR 5 #define CMD_DEL 6 #define CMD_SPC 7 #define CMD_UNK 255 char *cmdtab[] = { "fork rsrc", "fork data", "mode binary", "mode text", DIRCMDSTR, DELCMDSTR, SPCCMDSTR }; int toktab[] = { CMD_RSRC, CMD_DATA, CMD_BINA, CMD_TEXT, CMD_DIR, CMD_DEL, CMD_SPC }; #define NTOKS (sizeof (toktab)/sizeof(int)) /****************************************************************************/ /* Z X C M D -- Run a system command so its output can be read like a file. * * Used on the MAC to implement MAC settings commands -- commands from a * remote system when in server mode that change internal variables. * */ /****************************************************************************/ int zxcmd (comand) char *comand; { int sc; char theStr[120]; int retCd; fp[ZIFILE].fstatus = FS_PIPE; /* set input from pipe */ fp[ZIFILE].fpipe = &cmdpipe;/* init pointer to command pipe */ switch (sc = getcmd (comand)) { case CMD_RSRC: case CMD_DATA: zinitpipe (&cmdpipe, NILPROC); zfillpipe (&cmdpipe, "Default Fork set OK\n", TRUE); filargs.filflg &= ~(FIL_RSRC | FIL_DATA); /* turn off */ filargs.filflg |= (sc == CMD_RSRC) ? FIL_RSRC : FIL_DATA; return (TRUE); /* ok */ case CMD_TEXT: case CMD_BINA: zinitpipe (&cmdpipe, NILPROC); zfillpipe (&cmdpipe, "Default Mode set OK\n", TRUE); filargs.filflg &= ~(FIL_TEXT | FIL_BINA); filargs.filflg |= (sc == CMD_BINA) ? FIL_BINA : FIL_TEXT; return (TRUE); /* ok */ case CMD_DIR: zinitpipe (&cmdpipe, zldir); zfillpipe (&cmdpipe, dirheader, FALSE); fileindex = 1; /* start at the first file on */ /* the current volume / directory */ return (TRUE); /* always ok */ case CMD_DEL: strcpy (theStr, comand + strlen (DELCMDSTR)); /* the filename * immediately */ retCd = zdelet (theStr);/* follows the command name */ if (retCd) { zinitpipe (&cmdpipe, NILPROC); strcat (theStr, " deleted."); zfillpipe (&cmdpipe, theStr, true); } return (retCd); case CMD_SPC: zinitpipe (&cmdpipe, zlspace); /* init pipe for space listing */ zfillpipe (&cmdpipe, spaceheader, FALSE); /* copy the header to * the pipe */ volindex = 1; /* start with the first volume */ return (TRUE); /* always ok */ default: return (FALSE); /* fail, unknown */ } } /* zxcmd */ /****************************************************************************/ /****************************************************************************/ getcmd (cmd) char *cmd; { int k; for (k = 0; k < NTOKS; k++) if (strncmp (cmdtab[k], cmd, strlen (cmdtab[k])) == 0) return (toktab[k]); /* and return ID */ return (CMD_UNK); /* else unknown */ } /* getcmd */ /****************************************************************************/ /* Z C L O S F - wait for the child fork to terminate and close the pipe. */ /****************************************************************************/ zclosf () { return; } /* zclosf */ int zindex; int zfiles; char *zname; /****************************************************************************/ /* Z X P A N D -- Expand a wildcard string into an array of strings * * Returns the number of files that match fn, with data structures set up * so that first file (if any) will be returned by the next znext() call. */ /****************************************************************************/ zxpand (fn) char *fn; { int err; FileParam info; zfiles = 1; if ((filargs.filflg & FIL_ALLFL) || /* all files check box on or */ (strcmp (fn, ":") == 0)) { /* server 'get' with filname = ':' */ /* the ioVNmFls field of the VolumeParam returns the number of files */ /* * !and! directories after PBGetInfo. This is why we have to count * here. */ info.ioFVersNum = 0; /* No version number */ info.ioNamePtr = NIL; /* Point to the file name */ info.ioVRefNum = filargs.filvol; /* Volume number */ do { info.ioFDirIndex = zfiles; /* Get next file name */ err = PBGetFInfo (&info, FALSE); /* Get info on file */ zfiles++; } while (err == noErr); zname = NIL; /* no specific file */ zfiles -= 2; /* we counted 2 too high */ } else zname = fn; /* keep a pointer to that name */ zindex = 0; /* init the files sent counter */ return (zfiles); } /* zxpand */ /****************************************************************************/ /* 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; { int err; Str255 name; FileParam info; zindex++; /* next file */ if (zindex > zfiles) return (0); /* no more files */ if (zname != NIL) strcpy (fn, zname); /* Get the file's name */ else { info.ioFVersNum = 0; /* No version number */ info.ioFDirIndex = zindex; /* Get next file name */ info.ioNamePtr = &name; /* Point to the file name */ info.ioVRefNum = filargs.filvol; /* VolRefNum of the selected * folder */ err = PBGetFInfo (&info, FALSE); /* Get info on file */ if (err == noErr) { p2cstr (&name); strcpy (fn, &name); /* Return the file's name */ *filargs.filrem = '\0'; /* reset remote name for folder * transfer */ } else { printerr ("Error on reading next file name: ", err); return (0); } } return (1); /* fn contains the next file */ } /* znext */ /****************************************************************************/ /* Z N E W N -- Make a new name for the given file */ /****************************************************************************/ znewn (fn, s) char *fn, **s; { char *extp; int ver; strcpy (*s, fn); /* copy in the name */ if (strlen (*s) > 59) /* don't allow long names */ *s[59] = '\0'; /* it breaks the finder */ extp = *s + strlen (*s); /* find position of extension */ *extp++ = '.'; /* add in the dot now */ for (ver = 0; ver < 99; ver++) { /* I'll try this many names */ NumToString ((long) ver, extp); /* add in the number */ if (zchki (*s) == -1) /* is this file known? */ return; /* no, made a good one! */ } fatal ("znewn failed to find unique name in 64 attempts", 0); return; } /* znewn */ /****************************************************************************/ pascal void reset () /****************************************************************************/ extern 0x4E70; /****************************************************************************/ /* zkself() - Kill self (reboot). On other machines does a logout. * Flush volumes and reboot. Called by remote BYE. * */ /****************************************************************************/ zkself () { DrvQEl *drvqe; char vname[255]; long vfreeb; short vrefnum; int err; /* handle on drive q */ for (drvqe = (DrvQEl *) ((QHdr *) GetDrvQHdr ())->qHead; drvqe != NULL; /* while still something */ drvqe = drvqe->qLink) {/* step to next *//* for each drive */ err = GetVInfo (drvqe->dQDrive, vname, &vrefnum, &vfreeb); if (err == noErr) err = FlushVol (NILPTR, vrefnum); /* flush the volume given * refnum */ else if (err != nsvErr) screen (SCR_TN,0,0l,"Remote cmd: GetVinfo returned unknown code"); } mac_cleanup (); /* clean up before leaving */ reset (); } /* zkself */ struct { int errnum; char *errstr; } ioerrs[] = { { dirFulErr, "Directory is full" }, { dskFulErr, "Disk is full" }, { wPrErr, "Diskette is write protected" }, { fLckdErr, "File is software locked" }, { vLckdErr, "Volume is software locked" }, { fBsyErr, "File is busy" }, { opWrErr, "File is already open with write permission" }, { 0, NILPTR } }; /****************************************************************************/ /* ioutil - handle the result from an IO call, checking for an * error return and displaying an appropriate error * message. Returns TRUE if no error occured, FALSE * otherwise. */ /****************************************************************************/ int ioutil (err) int err; { int e; if (err == noErr) return (TRUE); for (e = 0; ioerrs[e].errnum != 0 && ioerrs[e].errnum != err; e++); if (ioerrs[e].errstr == NILPTR) /* anything there? */ printerr ("Unknown IO error: ", err); else printerr (ioerrs[e].errstr, 0); return (FALSE); } /* ioutil */ #ifdef COMMENT PWP: my copy of IM 2 says that this _is_ a standard toolbox call, so we don't need this at all. /****************************************************************************/ /* * OpenRF is not a standard Toolbox routine but acts identically to FSOpen * except that it opens the resource fork instead of the data fork. */ /****************************************************************************/ int OpenRF (fileName, vRefNum, refNum) char *fileName; int vRefNum; short *refNum; { IOParam pb; c2pstr (fileName); pb.ioNamePtr = fileName; pb.ioVRefNum = vRefNum; pb.ioVersNum = 0; pb.ioPermssn = 0; pb.ioMisc = (Ptr) 0; PBOpenRF (&pb, 0); *refNum = pb.ioRefNum; p2cstr (fileName); return pb.ioResult; } /* OpenRF */ #endif COMMENT extern short dfltVol; #ifdef TLOG short tlogfile; char tlogname[] = "Kermit Transaction"; /****************************************************************************/ /****************************************************************************/ opentlog () { return (openlogfile("Transaction log name:", tlogname, &tlogfile)); } /****************************************************************************/ /****************************************************************************/ closetlog () { FSClose (tlogfile); FlushVol (NIL, dfltVol); } /* closetlog */ /****************************************************************************/ /****************************************************************************/ tlog (f, s1, s2, n) int f; long n; char *s1; char *s2; { char numstr[12]; char outstr[256]; long count; if (tralog) { strcpy (outstr, s1); if (strlen (s2)) { strcat (outstr, " "); strcat (outstr, s2); } if (n) { NumToString (n, numstr); strcat (outstr, " "); strcat (outstr, numstr); } strcat (outstr, "\r"); count = strlen (outstr); FSWrite (tlogfile, &count, &outstr); } } /* tlog */ #endif short slogfile; char slogname[] = "Kermit Session"; /****************************************************************************/ /****************************************************************************/ openslog () { return (openlogfile("Session log name:", slogname, &slogfile)); } /****************************************************************************/ /****************************************************************************/ openlogfile(prompt, name, fdp) char *prompt, *name; short *fdp; { int err; FInfo info; SFReply sfr; /* holds file info */ Point where; SetPt(&where, 75, 80); SFPutFile (&where, prompt, name, NILPROC, &sfr); if (!sfr.good) /* if canceled */ return (0); p2cstr(&sfr.fName); err = Create (&sfr.fName, sfr.vRefNum, 'MACA', 'TEXT'); if (err != dupFNErr) if (!ioutil (err)) return (0); err = FSOpen (&sfr.fName, sfr.vRefNum, fdp); /* open the logfile */ if (!ioutil (err)) return (0); SetFPos (*fdp, fsFromLEOF, 0); /* set file pointer to eof */ return (1); } /* openslog */ /****************************************************************************/ /****************************************************************************/ closeslog () { int err; /* scrtolog (); */ /* dump the rest of the screen to the logfile */ err = FSClose (slogfile); if (!ioutil (err)) return (0); FlushVol (NIL, dfltVol); } /* closeslog */ /****************************************************************************/ /* write a maximum of n characters from s to the session log file */ /* skip all trailing blanks */ /****************************************************************************/ slog (s, n) char *s; int n; { long count; char *c; /* skip all non visible characters */ for (c = s + n - 1; (*c <= ' ') && (c >= s); c--); /* adjust count and write to file */ count = (long) (c - s + 1); FSWrite (slogfile, &count, s); /* write a cr at end of line */ count = 1; FSWrite (slogfile, &count, "\r"); } /* slog */