home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc095.zip / ckmfio.c < prev    next >
C/C++ Source or Header  |  1989-08-22  |  58KB  |  1,959 lines

  1. /* Version 0.9(37) - Paul Placeway at Ohio State, Jan 1988 */
  2. /*  reformatted all of the code so that it would be 79 or fewer colums */
  3. /* Version 0.8(35) - Jim Noble at Planning Research Corporation, June 1987. */
  4. /* Ported to Megamax native Macintosh C compiler. */
  5. /* Edit by Bill on Thu May 30, 00:18 */
  6. /* Do error handling, neaten up comments, and some code. */
  7. /* Edit by Bill on Wed May 15, 16:09 */
  8. /* Make zrtol call common sfprtol, .RSRC overrides default settings */
  9. /* ckmfio.c, Mon Apr 29 17:48, Edit by Bill*2 */
  10. /* Put null in translated name to tie it off. */
  11. /* Make author text of new file to ???? instead of random string */
  12. /* Do flushvol after closing a file */
  13. /* Bill C., Apr 24 */
  14. /* Change zchin to allow sending of files with high order bits on */
  15. /* Bill C., Apr 22 */
  16. /* Add error handling (informing) for more cases, e.g. can't delete */
  17. /* Bill C., Apr 22 */
  18. /* Fix Resource/Data fork stuff.  Uppercase things where needed */
  19. /* ckzmac.c, Thu Apr 21 17:19, Edit by Bill */
  20. /*  Ignore trying to close an not-openend file, driver does it alot */
  21. /* ckzmac.c, Thu Apr 11 21:18, Edit by Bill */
  22. /*  Catch error in ZOPENO when trying to open an existing file */
  23. /* ckzmac.c, Thu Apr 14 20:07, Edit by Bill */
  24. /*  Translate calls with ZCTERM to go to the console routines */
  25.  
  26. /*
  27.  * File ckmfio  --  Kermit file system support for the Macintosh
  28.  *
  29.  * Copyright (C) 1985, Trustees of Columbia University in the City of
  30.  * New York.  Permission is granted to any individual or institution to
  31.  * use, copy, or redistribute this software so long as it is not sold
  32.  * for profit, provided this copyright notice is retained.
  33.  *
  34.  */
  35.  
  36. /* Definitions of some Unix system commands */
  37.  
  38. #define DIRCMDSTR "ls"
  39. #define DELCMDSTR "rm"
  40. #define SPCCMDSTR "sp"
  41.  
  42. char *DIRCMD = DIRCMDSTR;    /* For directory listing */
  43. char *DELCMD = DELCMDSTR;    /* For file deletion */
  44. char *SPACMD = SPCCMDSTR;    /* Space for all available volumes */
  45. char *TYPCMD = "";        /* For typing a file */
  46. char *SPACM2 = "";        /* For space in specified directory */
  47. char *WHOCMD = "";        /* For seeing who's logged in */
  48.  
  49. /*
  50.   Functions (n is one of the predefined file numbers from ckermi.h):
  51.  
  52.    zopeni(n,name)   -- Opens an existing file for input.
  53.    zopeno(n,name)   -- Opens a new file for output.
  54.    zclose(n)        -- Closes a file.
  55.    zchin(n)         -- Gets the next character from an input file.
  56.    zinfill()        -- (re) fill the file input buffer, and return the first character
  57.    zsout(n,s)       -- Write a null-terminated string to output file, buffered.
  58.    zsoutl(n,s)      -- Like zsout, but appends a line terminator.
  59.    zsoutx(n,s,x)    -- Write x characters to output file, unbuffered.
  60.    zchout(n,c)      -- Add a character to an output file, unbuffered.
  61.    zchki(name)      -- Check if named file exists and is readable, return size.
  62.    zchko(name)      -- Check if named file can be created.
  63.    znewn(name,s)    -- Make a new unique file name based on the given name.
  64.    zdelet(name)     -- Delete the named file.
  65.    zxpand(string)   -- Expands the given wildcard string into a list of files.
  66.    znext(string)    -- Returns the next file from the list in "string".
  67.    zxcmd(cmd)       -- Execute the command in a lower fork.
  68.    zclosf()         -- Close input file associated with zxcmd()'s lower fork.
  69.    zrtol(n1,n2)     -- Convert remote filename into local form.
  70.    zltor(n1,n2)     -- Convert local filename into remote form.
  71.    zchdir(dirnam)   -- Change working directory.
  72.    zhome()          -- Return pointer to home directory name string.
  73.    zkself()         -- Kill self, log out own job.
  74.  */
  75.  
  76. #include "ckcdeb.h"        /* Debug() and tlog() defs */
  77. #include "ckcker.h"        /* Kermit definitions */
  78.  
  79. #define    __SEG__ ckmfio
  80. #include <ctype.h>
  81. #include <files.h>
  82. #include <errors.h>
  83. #include <devices.h>
  84. #include <packages.h>
  85. #include <osutils.h>
  86. #include <toolutils.h>
  87. #include <events.h>        /* needed for ckmasm.h */
  88.  
  89. #include "ckmdef.h"        /* Common Mac module definitions */
  90. #include "ckmres.h"        /* Resource defs */
  91. #include "ckmasm.h"        /* Assembler code */
  92.  
  93. /* (PWP) external def. of things used in buffered file input and output */
  94. extern CHAR zinbuffer[], zoutbuffer[];
  95. extern CHAR *zinptr, *zoutptr;
  96. extern int zincnt, zoutcnt;
  97. static long zcnt_written;
  98.  
  99. /* These should all be settable by the File Settings Menu */
  100.  
  101. #define FS_WIND 1        /* file is a text edit buffer */
  102. #define FS_OPEN 2        /* file has been opened */
  103. #define FS_RSRC 4        /* opened in resource fork */
  104. #define FS_DATA 8
  105. #define FS_PIPE 16        /* file is a memory buffer */
  106. #define FS_MACB 32        /* we are sending a file in MacBinary format */
  107.  
  108. #define PIPESIZE 128
  109. typedef struct {
  110.     int charsleft;        /* nuber of unread characters in the buffer */
  111.     ProcPtr refill;        /* pointer to the refill procedure */
  112.     char *currptr;        /* characters left before next pipe refill */
  113.     char pipebuf[PIPESIZE];    /* buffer to keep the pipes content */
  114. }   MACPIPE;
  115.  
  116. typedef struct {
  117.     short frefnum;        /* file reference number (pascal) */
  118.     int fstatus;        /* file status bits */
  119.     MACPIPE *fpipe;        /* pointer to a pipe */
  120. }   MACFILE;
  121.  
  122. MACFILE fp[ZNFILS] = {        /* File information */
  123.     {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}
  124. };
  125.  
  126. static long iflen = -1;            /* Input file length */
  127. static long oflen = -1;            /* Output file length */
  128.  
  129. char printfbuf[256];
  130.  
  131. /****************************************************************************/
  132. /*  Z O P E N I --  Open an existing file for input.
  133.  *
  134.  * The file name has been returned from and the volume reference
  135.  * number set by SFGetFile.
  136.  *
  137.  * Returns:
  138.  *  TRUE: file opened ok
  139.  *  FALSE: some error.
  140.  */
  141. /****************************************************************************/
  142. zopeni (n, name)
  143. int n;
  144. char *name;
  145. {
  146.     int err;
  147.     register MACFILE *fpp;
  148.  
  149.     if (chkfn (n)) {
  150.     printerr ("At zopeni file is already open ", n);
  151.     return (FALSE);
  152.     }
  153.     zincnt = 0;        /* (PWP) clear buffer input count */
  154.     fpp = &fp[n];
  155.  
  156.     if (n == ZCTERM) {        /* Terminal open? */
  157.     if (chkfn (ZIFILE))    /* Check current ZOFILE */
  158.         printerr ("ZIFILE already open...: ", n);
  159.     fp[ZIFILE].fstatus = FS_WIND;    /* redirect... here it is */
  160.     fpp->fstatus = FS_WIND;    /* Indicate this is open too */
  161.     return (conopen ());    /* Return from low level open */
  162.     }
  163.     if (n == ZSYSFN)        /* trying to open a pipe? */
  164.     return (zxcmd (name));    /* yes... */
  165.  
  166.     if (n == ZIFILE) {        /* opening input file? */
  167.         /* if we are doing MacBinary format */
  168.     if ((filargs.filflg & (FIL_RSRC|FIL_DATA)) == (FIL_RSRC|FIL_DATA)) {
  169.         err = macbinopen(name, fpp);
  170.         if (err == noErr)
  171.             return (TRUE);
  172.         else
  173.             return (ioutil (err));
  174.     } else {
  175.         if (filargs.filflg & FIL_RSRC)    /* and they said resource? */
  176.         err = OpenRF (name, filargs.filvol, &fpp->frefnum);
  177.         else            /* else some other channel or data */
  178.         err = FSOpen (name, filargs.filvol, &fpp->frefnum);
  179.         if (err != noErr)        /* check for open error */
  180.         return (ioutil (err));    /* failed... */
  181.     }
  182.     }
  183.  
  184.     fpp->fstatus = FS_OPEN | (    /* set flags */
  185.                (filargs.filflg & FIL_RSRC) ? FS_RSRC : FS_DATA);
  186.  
  187.     GetEOF (fpp->frefnum, &filargs.filsiz);    /* set size for screen */
  188.     fsize = filargs.filsiz;    /* PWP: set size for screen */
  189.     return (TRUE);        /* Return success */
  190. }                /* zopeni */
  191.  
  192. MBHead filHead;
  193. static char MBname[64];
  194.  
  195. void
  196. bzero (b, n)
  197. register char *b;
  198. register int n;
  199. {
  200.     while (n-- > 0)
  201.     *b++ = 0;
  202. }
  203.  
  204. void
  205. bcopy (a, b, n)
  206. register char *a, *b;
  207. register int n;
  208. {
  209.     while (n-- > 0)
  210.     *b++ = *a++;
  211. }
  212.  
  213. /* these next three taken from NCSA Telnet 2.2 */
  214. int
  215. GetFileInfo(vol,name,iop)
  216. short vol;
  217. char *name;
  218. FileParam *iop;
  219. {
  220.     char thename[64];
  221.     
  222.     strncpy (thename, name, 64);    /* make my own copy of this */
  223.     thename[63] = '\0';
  224.     c2pstr(thename);
  225.     
  226.     iop->ioNamePtr = thename;
  227.     iop->ioVRefNum=vol;
  228.     iop->ioFVersNum=iop->ioFDirIndex=0;
  229.     PBGetFInfo(iop, FALSE);
  230.     return (iop->ioResult);
  231. }
  232.  
  233. int
  234. SetFileInfo(vol,name,iop)
  235. short vol;
  236. char *name;
  237. FileParam *iop;
  238. {
  239.     char thename[64];
  240.     
  241.     strncpy (thename, name, 64);    /* make my own copy of this */
  242.     thename[63] = '\0';
  243.     c2pstr(thename);
  244.     
  245.     iop->ioNamePtr = thename;
  246.     iop->ioVRefNum=vol;
  247.     iop->ioFVersNum=iop->ioFDirIndex=0;
  248.     PBSetFInfo(iop, FALSE);
  249.     return (iop->ioResult);
  250. }
  251.  
  252. int
  253. MakeTextFile(vol,name,iop)
  254. short vol;
  255. char *name;
  256. FileParam *iop;
  257. {
  258.     GetFileInfo(vol,name,iop);
  259.     iop->ioFlFndrInfo.fdType='TEXT';
  260.     iop->ioFlFndrInfo.fdCreator='EDIT';
  261.     SetFileInfo(vol,name,iop);
  262.     return (iop->ioResult);
  263. }
  264.  
  265. int
  266. macbinopen(name, fpp)
  267. char *name;
  268. MACFILE *fpp;
  269. {
  270.     FileParam finfo;
  271.     char *cp;
  272.     int i, err;
  273.     
  274.     /* open first fork of name for reading and fill input buffer
  275.        with MacBinary header */
  276.     /* save file name for later */
  277.     strncpy (MBname, name, 64);
  278.     MBname[64] = 0;
  279.     
  280.     /* clear out the header */
  281.     bzero (&filHead, sizeof(MBHead));
  282.     
  283.     /* put the name into place */
  284.     strncpy (&filHead.name[0], name, 64);
  285.     filHead.name[63] = '\0';
  286.     c2pstr(filHead.name);
  287.     
  288.     /* get the file info */
  289.     if ((err = GetFileInfo( filargs.filvol, name, &finfo)) != noErr) {
  290.     printerr("macbinopen: problem with GetFileInfo", err);
  291.     return (err);
  292.     }
  293.  
  294.     bcopy( &finfo.ioFlFndrInfo, &filHead.type[0], sizeof(FInfo) );
  295.     filHead.protected = (filHead.zero2 & 0x40)?1:0;
  296.     filHead.zero2 = 0;
  297.     bcopy(&finfo.ioFlLgLen, &filHead.dflen[0], 4);
  298.     bcopy(&finfo.ioFlRLgLen, &filHead.rflen[0], 4);
  299.     bcopy(&finfo.ioFlCrDat, &filHead.cdate[0], 4);
  300.     bcopy(&finfo.ioFlMdDat, &filHead.mdate[0], 4);
  301.  
  302.     filargs.filsiz=finfo.ioFlLgLen;
  303.     filargs.rsrcsiz=finfo.ioFlRLgLen;
  304.     
  305.     fsize = ((filargs.filsiz + 127) & ~127) +
  306.         ((filargs.rsrcsiz + 127) & ~127) + 128;
  307.     
  308.     bcopy (&filHead, zinbuffer, 128);    /* put header in xfer buffer */
  309.     zincnt = 128;            /* init buffer to 128 to send */
  310.     zinptr = zinbuffer;       /* set pointer to beginning, (== &zinbuffer[0]) */
  311.  
  312.     if (filargs.filsiz <= 0) {
  313.     /* we do the data fork first, then the resource fork */
  314.     if ((err = OpenRF (name, filargs.filvol, &fpp->frefnum)) != noErr) {
  315.          printerr("macbinopen: problem with OpenRF", err);
  316.          return (err);
  317.     }
  318.     fpp->fstatus = FS_OPEN | FS_RSRC | FS_MACB;
  319.     } else {
  320.     /* we do the data fork first, then the resource fork */
  321.     if ((err = FSOpen (name, filargs.filvol, &fpp->frefnum)) != noErr) {
  322.          printerr("macbinopen: problem with FSOpen", err);
  323.          return (err);
  324.     }
  325.     fpp->fstatus = FS_OPEN | FS_DATA | FS_MACB;
  326.     }
  327.     return (noErr);
  328. }
  329.  
  330. /* is this a MacBinary I header -- see standard-macbinary-ii.txt (on Sumex) */
  331. is_macbinary(h)
  332. MBHead h;
  333. {
  334.     register int i;
  335.     long l;
  336.     
  337.     if ((h.zero1 != 0) || (h.zero2 != 0) || (h.zero3 != 0)) {
  338.     printerr("zeros", 0);
  339.         return (0);
  340.     }
  341.     if ((h.name[0] == 0) || (h.name[0] & 0xc0)) {
  342.     printerr("name length", h.name[0]);
  343.         return (0);
  344.     }
  345.     bcopy (&h.dflen[0], &l, 4);
  346.     if ((l < 0) || (l > 0x7fffff)) {
  347.     printerr("data length", l);
  348.         return (0);
  349.     }
  350.     bcopy (&h.rflen[0], &l, 4);
  351.     if ((l < 0) || (l > 0x7fffff))  {
  352.     printerr("rsrc length", l);
  353.         return (0);
  354.     }
  355. #ifdef COMMENT
  356.     /* MacBinary II uses this area for more stuff, so don't check it */
  357.     for (i = 2; i < 27; i++) {
  358.         if (h.filler[i] != 0) {
  359.         printerr("filler index:", i);
  360.         return (0);
  361.     }
  362.     }
  363. #endif /* COMMENT */
  364.     return (1);
  365. }
  366.  
  367.  
  368. /****************************************************************************/
  369. /*  Z O P E N O  --  Open a new file for output.
  370.  *
  371.  * Returns:
  372.  *  TRUE: File opened ok
  373.  *  FALSE: some error has occured or channel occupied.
  374.  *
  375.  */
  376. /****************************************************************************/
  377. zopeno (n, name)
  378. int n;
  379. char *name;
  380. {
  381.     OSType forktext, authortext;
  382.     int err;
  383.     FInfo finfo;
  384.     register MACFILE *fpp;
  385.  
  386.     if (chkfn (n)) {
  387.     printerr ("zopeno - file is already open: ", n);
  388.     return (FALSE);
  389.     }
  390.     fpp = &fp[n];
  391.  
  392.     if (n == ZCTERM || n == ZSTDIO) {    /* Terminal open? */
  393.     if (chkfn (ZOFILE))    /* Check current ZOFILE */
  394.         printerr ("ZOFILE already open...: ", n);
  395.     fp[ZOFILE].fstatus = FS_WIND;    /* yes, redirect... here it is */
  396.     fpp->fstatus = FS_WIND;    /* Indicate this is open too */
  397.     zoutcnt = 0;        /* (PWP) reset output buffer */
  398.     zoutptr = zoutbuffer;
  399.     return (conopen ());    /* Return from low level open */
  400.     }
  401.     if (n == ZOFILE) {
  402.     zoutcnt = 0;        /* (PWP) reset output buffer */
  403.     zoutptr = zoutbuffer;
  404.     if ((filargs.filflg & (FIL_RSRC|FIL_DATA)) == (FIL_RSRC|FIL_DATA)) {
  405.         /* if MacBinary */
  406.         forktext = 'rsrc';
  407.         authortext = 'RSED';    /* a ResEdit document (for the moment) */
  408.     } else if (filargs.filflg & FIL_RSRC) {
  409.         forktext = 'APPL';
  410.         authortext = '????';
  411.     } else {
  412.         forktext = 'TEXT';        /* Make fork reflect fork choice */
  413.         authortext = 'MACA';    /* set creator to "MacWrite" */
  414.     }
  415.     }
  416.  
  417.     err = Create (name, filargs.filvol, authortext, forktext);
  418.     if (err == dupFNErr) {    /* duplicate file? */
  419.     if (!ioutil (FSDelete (name,    /* Try to delete it */
  420.                    filargs.filvol)))    /* checking for failure */
  421.         return (FALSE);    /* failed... */
  422.     err = Create (name, filargs.filvol,    /* recreate */
  423.               authortext, forktext);
  424.     }
  425.     if (err != noErr)        /* some error? */
  426.     return (ioutil (err));    /* yes, do message and return */
  427.  
  428. /* set file's folder from filargs.filfldr which is either the */
  429. /* applications folder or the settings file folder */
  430.  
  431.     GetFInfo (name, filargs.filvol, &finfo);    /* read current finder info */
  432.     finfo.fdFldr = filargs.filfldr;    /* set new folder */
  433.     SetFInfo (name, filargs.filvol, &finfo);    /* and tell system about it */
  434.  
  435.     if (n == ZOFILE) {        /* is it our transferred file? */
  436.     zcnt_written = 0;
  437.         /* if we are doing MacBinary format */
  438.     if ((filargs.filflg & (FIL_RSRC|FIL_DATA)) == (FIL_RSRC|FIL_DATA)) {
  439.         /* save file name for later */
  440.         strncpy (MBname, name, 64);
  441.         MBname[64] = 0;
  442.         /* we delay opening any forks until we have the MacBin header */
  443.         fp[n].fstatus = FS_OPEN | FS_MACB;    /* neither DATA nor RSRC yet */
  444.         return (TRUE);        /* done ok */
  445.     } else {     /* not MacBinary */
  446.         if (filargs.filflg & FIL_RSRC)    /* want to use resource fork?  */
  447.         err = OpenRF (name, filargs.filvol,    /* yes... */
  448.               &fpp->frefnum);
  449.         else            /* else data, or some other file */
  450.         err = FSOpen (name, filargs.filvol, &fpp->frefnum);
  451.     }
  452.     } else {
  453.     err = FSOpen (name, filargs.filvol, &fpp->frefnum);
  454.     }
  455.     
  456.     if (err != noErr)        /* able to open? */
  457.     return (ioutil (err));    /* no. fail return now */
  458.  
  459.     fp[n].fstatus = FS_OPEN |
  460.     ((filargs.filflg & FIL_RSRC) ? FS_RSRC : FS_DATA);
  461.  
  462.     return (TRUE);        /* done ok */
  463. }                /* zopeno */
  464.  
  465.  
  466.  
  467. /****************************************************************************/
  468. /*  Z C L O S E  --  Close the given file.
  469.  *
  470.  * Returns:
  471.  *  TRUE: file closed ok.
  472.  *  FLASE: some error has occured.
  473.  *
  474.  */
  475. /****************************************************************************/
  476. zclose (n)
  477. int n;
  478. {
  479.     int err = noErr, e2 = 0;
  480.     register MACFILE *fpp;
  481.     FileParam finfo;
  482.     Point old_location;
  483.  
  484.     if (!chkfn (n))        /* is it opened? */
  485.     return (FALSE);        /* no return now */
  486.  
  487.     if ((n == ZOFILE) && (zoutcnt > 0))    /* (PWP) output leftovers */
  488.     e2 = zoutdump();
  489.  
  490.     fpp = &fp[n];
  491.  
  492.     if (fpp->fstatus == FS_WIND)/* is this a window? */
  493.     fp[ZCTERM].fstatus = 0;    /* yes, clear ZCTERM */
  494.     else if (fpp->fstatus == FS_PIPE)    /* is this a pipe? */
  495.     fp[ZSYSFN].fstatus = 0;    /* yes, no pipe now, clear ZSYSFN */
  496.     else {
  497.     if (fpp->fstatus & FS_MACB) {    /* if MacBinary format */
  498.         if (!cxseen && !czseen &&
  499.             (zcnt_written > ((filargs.rsrcsiz + 127) & ~127)) ||
  500.         (zcnt_written < filargs.rsrcsiz)) {
  501.         sprintf(printfbuf, "Resource fork size mismatch: should be %d is %d",
  502.             filargs.rsrcsiz, zcnt_written);
  503.         printerr(printfbuf, 0);
  504.         }
  505.         SetEOF (fpp->frefnum, filargs.rsrcsiz);    /* trim padding off */
  506.     }
  507.     err = FSClose (fpp->frefnum);    /* else use OS close */
  508.     if (err == noErr)    /* and if that worked */
  509.         /* PWP: the above if should be ==, NOT != !!!!! */
  510.         err = FlushVol (NILPTR,    /* flush buffers in case write worked */
  511.                 filargs.filvol);
  512.     if (err != noErr)
  513.         printerr("zclose(): problem closing/flushing:", err);
  514.         
  515.     if (fpp->fstatus & FS_MACB) {
  516.                 /* if MacBinary and no error */
  517.         if ((err = GetFileInfo(filargs.filvol, MBname, &finfo)) != noErr) {
  518.         sprintf(printfbuf, "Could not GetFileInfo on \"%s\": error %d",
  519.             MBname, err);
  520.         printerr(printfbuf,0);
  521.         } else {
  522.         old_location = finfo.ioFlFndrInfo.fdLocation;
  523.         
  524.         filHead.protected &= 01;    /* nuke all but low order bit */
  525.         
  526.         bcopy(&filHead.type[0], &finfo.ioFlFndrInfo, sizeof(FInfo));
  527.         bcopy(&filHead.cdate[0], &finfo.ioFlCrDat, 4);
  528.         bcopy(&filHead.mdate[0], &finfo.ioFlMdDat, 4);
  529.  
  530.         /* As per the MacBinary II doc, I clear the following flags:
  531.          *
  532.          *  0 - Set if file/folder is on the desktop (Finder 5.0 and later)
  533.          *  1 - bFOwnAppl (used internally)
  534.          *  8 - Inited (seen by Finder)
  535.          *  9 - Changed (used internally by Finder)
  536.          * 10 - Busy (copied from File System busy bit)
  537.          */
  538.         finfo.ioFlFndrInfo.fdFlags &= 0xf8fc;
  539.  
  540.         /* finfo.ioFlFndrInfo.fdFldr = filargs.filfldr; */    /* set new folder */
  541.         finfo.ioFlFndrInfo.fdFldr = 0;    /* set new folder */
  542.         finfo.ioFlFndrInfo.fdLocation = old_location;    /* old_location */
  543.         
  544.         if (finfo.ioFlLgLen != filargs.filsiz) {
  545.             sprintf(printfbuf, "%s: Data fork size mismatch: should be %d is %d",
  546.                 MBname, filargs.filsiz, finfo.ioFlLgLen);
  547.             printerr(printfbuf, 0);
  548.         }
  549.         if (finfo.ioFlRLgLen != filargs.rsrcsiz) {
  550.             sprintf(printfbuf, "%s: Resource fork size mismatch: should be %d is %d",
  551.                 MBname, filargs.rsrcsiz, finfo.ioFlRLgLen);
  552.             printerr(printfbuf, 0);
  553.         }
  554.         /* finfo.ioFlRLgLen=out->rlen; */
  555.         /* finfo.ioFlLgLen =out->dlen; */
  556.     
  557.         if ((err = SetFileInfo(filargs.filvol, MBname, &finfo)) != noErr)
  558.             printerr("Could not SetFileInfo:", err);
  559.         /* make sure the new data got to disk */
  560.         p2cstr(filHead.name);
  561.         if ((err = Rename(MBname, filargs.filvol, filHead.name)) != noErr)
  562.             printerr("Could not rename file:", err);
  563.         err = FlushVol (NILPTR, filargs.filvol);
  564.         }
  565.     }
  566.     }
  567.  
  568.     fpp->fstatus = 0;        /* clear out status word */
  569.     if (n == ZOFILE || n == ZIFILE)    /* turn off both flags */
  570.     filargs.filflg &= ~(FIL_RSRC | FIL_DATA);
  571.  
  572.     iflen = -1;            /* Invalidate file length */
  573.  
  574.     if (e2 < 0) {
  575.     (void) ioutil (err);
  576.     return (FALSE);
  577.     } else {
  578.     return (ioutil (err));    /* return according to io operations */
  579.     }
  580. }                /* zclose */
  581.  
  582.  
  583.  
  584. /****************************************************************************/
  585. /*  Z C H I N  --  Get a character from the input file.
  586.  *
  587.  * Returns:
  588.  *  0: Ok
  589.  * -1: EOF (or other error).
  590.  *
  591.  */
  592. /****************************************************************************/
  593. zchin (n, c)
  594. int n;
  595. char *c;
  596. {
  597.     int err;
  598.     long rdcnt;            /* pascal long */
  599.     register MACFILE *fpp;
  600.     register MACPIPE *pipe;
  601.  
  602.     if (n == ZIFILE)
  603.     return (zminchar());    /* (PWP) go through the macro */
  604.  
  605.     if (!chkfn (n))
  606.     return (0);
  607.  
  608.     fpp = &fp[n];
  609.  
  610.     if (fpp->fstatus == FS_WIND) {    /* a window? */
  611.     printerr ("zchin called for FS_WIND file: ", n);
  612.     return (0);
  613.     }
  614.     if (fpp->fstatus == FS_PIPE) {    /* a pipe? */
  615.     pipe = fpp->fpipe;
  616.  
  617.     if (pipe->charsleft <= 0) {    /* test for characters left */
  618.         pipe->currptr = pipe->pipebuf;    /* restart at the beginning
  619.                          * of the buffer */
  620.  
  621.         if (pipe->refill != NILPROC) {    /* refill the pipe if
  622.                          * possible */
  623.         saveA0 ();    /* push content of A0 to stack */
  624.         loadA0 (*(pipe->refill));    /* load the content of refill
  625.                          * to A0 */
  626.         execute ();    /* call the refill procedure */
  627.         restoreA0 ();    /* get A0 back from the stack */
  628.         } else
  629.         *(pipe->currptr) = '\0';    /* make it end otherwise */
  630.     }
  631.     if (*(pipe->currptr) == '\0')    /* is this eo-pipe? */
  632.         return (-1);    /* yes, fail return */
  633.  
  634.     *c = *(pipe->currptr)++;/* read character */
  635.     (pipe->charsleft)--;    /* decrement characters left */
  636.  
  637.     return (0);        /* success */
  638.     }
  639.     rdcnt = 1;
  640.     err = FSRead (fpp->frefnum, &rdcnt, c);
  641.     if (err == eofErr)
  642.     return (-1);        /* Failure return */
  643.     return (ioutil (err) ? 0 : -1);    /* success or unknown failure */
  644. }                /* zchin */
  645.  
  646. /*
  647.  * (PWP) (re)fill the buffered input buffer with data.  All file
  648.  * input should go through this routine, usually by calling the
  649.  * zminchar() macro
  650.  */
  651.  
  652. zinfill() {
  653.     int err;
  654.     long rdcnt;            /* pascal long */
  655.     register MACFILE *fpp;
  656.     char *cp;
  657.  
  658.     fpp = &fp[ZIFILE];
  659.  
  660.     /* if not an open file; just get one character */
  661.     if (!(fpp->fstatus & FS_OPEN)) {
  662.     zincnt = 0;
  663.     if (zchin (ZIFILE, zinbuffer) < 0)
  664.         return (-1);
  665.     return (zinbuffer[0]);
  666.     }
  667.     
  668.     rdcnt = INBUFSIZE;
  669.     err = FSRead (fpp->frefnum, &rdcnt, zinbuffer);
  670.     zincnt = rdcnt;            /* set number actually read */
  671.  
  672.     /* check for any errors */
  673.     if ((err != noErr) && (err != eofErr) && (!ioutil(err)))
  674.     return (-1);
  675.  
  676.     /*
  677.      * PWP: FSRead will return eofErr when it reads the last
  678.      * partial block of data.  If rdcnt > 0, then we still have
  679.      * the last bit of the file to send out...
  680.      */
  681.     if (err == eofErr) {
  682.     if (rdcnt == 0) {    /* if actual EOF */
  683.         return (-1);        /* EOF return */
  684.     } else {        /* last real block */
  685.         if (fpp->fstatus & FS_MACB) {    /* if MacBinary format */
  686.         /* pad out things */
  687.         rdcnt = (128 - (filargs.filsiz % 128)) % 128;
  688.         for (cp = &zinbuffer[zincnt]; rdcnt > 0; rdcnt--)
  689.             *cp++ = 0;
  690.             
  691.         zincnt = (zincnt + 127) & ~127;    /* pad out to 128 bytes */
  692.             
  693.         if (fpp->fstatus & FS_DATA) {    /* if we were doing the data fork */
  694.             fpp->fstatus &= ~FS_DATA;
  695.             
  696.             if (filargs.rsrcsiz != 0) {    /* if a resource fork */
  697.             if ((err = FSClose (fpp->frefnum)) != noErr) {
  698.                 printerr("zinfill: trouble closing data fork:", err);
  699.                 return (-1);
  700.             }
  701.  
  702.             /* open the resource fork 'cause we do that next */
  703.             if ((err = OpenRF (MBname, filargs.filvol,
  704.                                &fpp->frefnum)) != noErr) {
  705.                 printerr("zinfill: trouble closing data fork:", err);
  706.                 return (-1);
  707.             }
  708.  
  709.             /* in case anyone else needs to know */
  710.             fpp->fstatus |= FS_RSRC;
  711.             }
  712.         }
  713.         }
  714.     }
  715.     }
  716.     
  717.     zinptr = zinbuffer;       /* set pointer to beginning, (== &zinbuffer[0]) */
  718.     zincnt--;            /* one less char in buffer */
  719.     return((int)(*zinptr++) & 0377); /* because we return the first */
  720. }
  721.  
  722.  
  723. /****************************************************************************/
  724. /*  Z S O U T  --  Write a string to the given file, buffered.
  725.  *
  726.  * Returns:
  727.  *  0: OK
  728.  * -1: Error
  729.  *
  730.  */
  731. /****************************************************************************/
  732. zsout (n, s)
  733. int n;
  734. char *s;
  735. {
  736.     long wrcnt;            /* pascal long */
  737.  
  738.     if (n == ZCTERM || fp[n].fstatus == FS_WIND)
  739.     return (conol (s));
  740.  
  741.     wrcnt = (long) strlen (s);
  742.     return (ioutil (FSWrite (fp[n].frefnum, &wrcnt, s)) ? 0 : -1);
  743. }                /* zsout */
  744.  
  745.  
  746.  
  747. /****************************************************************************/
  748. /*  Z S O U T L  --  Write string to file, with line terminator, buffered.
  749.  *
  750.  * Returns:
  751.  *  0: OK
  752.  * -1: Error
  753.  *
  754.  */
  755. /****************************************************************************/
  756. zsoutl (n, s)
  757. int n;
  758. char *s;
  759. {
  760.     long wrcnt;            /* pascal long */
  761.     int err;
  762.  
  763.     if (n == ZCTERM || fp[n].fstatus == FS_WIND)
  764.     return (conoll (s));
  765.  
  766.     wrcnt = (long) strlen (s);
  767.     err = FSWrite (fp[n].frefnum, &wrcnt, s);
  768.     if (err == noErr) {
  769.     wrcnt = 2;
  770.     err = FSWrite (fp[n].frefnum, &wrcnt, "\r\n");
  771.     }
  772.     return (ioutil (err) ? 0 : -1);
  773. }                /* zsoutl */
  774.  
  775.  
  776.  
  777. /****************************************************************************/
  778. /*  Z S O U T X  --  Write x characters to file, unbuffered.
  779.  *
  780.  * Returns:
  781.  *  0: OK
  782.  * -1: Error
  783.  */
  784. /****************************************************************************/
  785. zsoutx (n, s, x)
  786. int n, x;
  787. char *s;
  788. {
  789.     long size;
  790.  
  791.     if (n == ZCTERM || fp[n].fstatus == FS_WIND)
  792.     return (conxo (s, x));
  793.  
  794.     size = x;
  795.     return (ioutil (FSWrite (fp[n].frefnum, &size, s)) ? 0 : -1);
  796. }                /* zsoutx */
  797.  
  798.  
  799.  
  800. /****************************************************************************/
  801. /*  Z C H O U T  --  Add a character to the given file. */
  802. /*                        */
  803. /* Returns:        */
  804. /*  0: OK            */
  805. /* -1: Error    */
  806. /****************************************************************************/
  807. zchout (n, c)
  808. int n;
  809. char c;
  810. {
  811.     long wrcnt;            /* pascal long */
  812.     int err;
  813.  
  814.     if (n == ZCTERM || fp[n].fstatus == FS_WIND) {
  815.     conoc (c);        /* Then send to console routine */
  816.     return (0);        /* Then send to console routine */
  817.     }
  818.     
  819.     if (n == ZOFILE)    /* (PWP) just in case */
  820.     return (zmchout(c));
  821.     
  822.     wrcnt = 1;
  823.     err = FSWrite (fp[n].frefnum, &wrcnt, &c);
  824.     if (err != noErr)        /* error occured? */
  825.     sstate = 'a';        /* yes, abort protocol */
  826.     return (ioutil (err) ? 0 : -1);    /* else return code */
  827. }                /* zchout */
  828.  
  829. /* (PWP) buffered character output routine to speed up file IO */
  830. zoutdump()
  831. {
  832.     long wrcnt, tmpcnt;            /* pascal long */
  833.     int err;
  834.     FileParam finfo;
  835.     char *outp;
  836.     
  837.     if ((wrcnt = zoutcnt) <= 0)
  838.         return (0);
  839.  
  840.     if (fp[ZOFILE].fstatus == FS_WIND) {    /* if console output */
  841.     conxo(zoutbuffer, zoutcnt);
  842.     zoutcnt = 0;
  843.     zoutptr = zoutbuffer;
  844.     return(0);
  845.     }
  846.  
  847.     outp = zoutbuffer;
  848.     if (fp[ZOFILE].fstatus & FS_MACB) {    /* if MacBinary format */
  849.     if (!(fp[ZOFILE].fstatus & (FS_RSRC | FS_DATA))) {  /* looking for header */
  850.         if (zoutcnt < 128)    /* we don't have all of the header yet */
  851.         return (0);
  852.  
  853.         bcopy(zoutbuffer, &filHead, 128);
  854.  
  855.         if (!is_macbinary(filHead)) {
  856.         screen(SCR_WM, 0, 0l, "Not a MacBinary file, reverting to binary, data fork");
  857.         screen(SCR_AN,0,0l,MBname);    /* stop saying MacBinary mode */
  858.         err = FSOpen (MBname, filargs.filvol, &fp[ZOFILE].frefnum);
  859.         if (err != noErr) {
  860.             printerr("zoutdump(): trouble with FSOpen:", err);
  861.             (void) ioutil(err);
  862.             return (-1);
  863.         }
  864.         fp[ZOFILE].fstatus = FS_OPEN | FS_DATA;    /* unset FS_MACB */
  865.         goto norm_file;
  866.         }
  867.  
  868.         /* adjust pointers */
  869.         wrcnt = zoutcnt - 128;
  870.         outp = &zoutbuffer[128];
  871.         
  872.         /* get the sizes from header */
  873.         bcopy(&filHead.dflen[0], &filargs.filsiz, 4);
  874.         bcopy(&filHead.rflen[0], &filargs.rsrcsiz, 4);
  875.  
  876.         if (filargs.filsiz > 0) {    /* is there a data fork?  */
  877.         err = FSOpen (MBname, filargs.filvol, &fp[ZOFILE].frefnum);
  878.         if (err != noErr) printerr("zoutdump(): trouble with FSOpen:", err);
  879.         fp[ZOFILE].fstatus |= FS_DATA;
  880.         } else {            /* else data, or some other file */
  881.         err = OpenRF (MBname, filargs.filvol,    /* yes... */
  882.               &fp[ZOFILE].frefnum);
  883.         if (err != noErr) printerr("zoutdump(): trouble with OpenRF:", err);
  884.         fp[ZOFILE].fstatus |= FS_RSRC;
  885.         }
  886.         
  887.         if (err != noErr) {
  888.         sstate = 'a';        /* yes, abort protocol */
  889.         return (ioutil (err) ? 0 : -1);
  890.         }
  891.         
  892.         zcnt_written = 0;
  893.  
  894.         /* screen(SCR_AN,0,0l,MBname); */    /* Make screen say MacBinary mode */
  895.         
  896.         if (wrcnt <= 0) {    /* if nothing to write */
  897.         zoutcnt = 0;
  898.         zoutptr = zoutbuffer;
  899.         return (0);    /* we are done this time */
  900.         }
  901.     }
  902.     
  903.     /* can't be "else if" here, above if may feed this if */
  904.     if (fp[ZOFILE].fstatus & FS_DATA) {    /* if doing data fork */
  905.         if (zcnt_written + wrcnt > filargs.filsiz) {
  906.         tmpcnt = wrcnt;        /* save old amount of data */
  907.  
  908.         /* figure how how much we really should write */
  909.         wrcnt = filargs.filsiz - zcnt_written;
  910.         err = FSWrite (fp[ZOFILE].frefnum, &wrcnt, outp);
  911.         zcnt_written += wrcnt;
  912.         outp += wrcnt;
  913.         
  914.         wrcnt = tmpcnt - wrcnt;    /* adjust to reflect the write */
  915.         
  916.         /* close data fork, open rsrc fork */
  917.         if (err == noErr)
  918.             err = FSClose (fp[ZOFILE].frefnum);
  919.         if (err == noErr)    /* and if that worked */
  920.             err = FlushVol (NILPTR,    /* flush  OS buffers */
  921.                 filargs.filvol);
  922.         if (err == noErr)
  923.             err = OpenRF (MBname, filargs.filvol,    /* yes... */
  924.                   &fp[ZOFILE].frefnum);
  925.         if (err != noErr) {        /* error occured? */
  926.             zoutcnt = 0;
  927.             zoutptr = zoutbuffer;
  928.             sstate = 'a';        /* yes, abort protocol */
  929.             return (ioutil (err) ? 0 : -1);    /* else return code */
  930.         }
  931.         
  932.         fp[ZOFILE].fstatus &= ~FS_DATA;
  933.         fp[ZOFILE].fstatus |= FS_RSRC;
  934.         
  935.         /* skip padding */
  936.         while (zcnt_written & 127) {
  937.             outp++;
  938.             wrcnt--;
  939.             zcnt_written++;
  940.         }
  941.         zcnt_written = 0;    /* restart counter for rsrc fork */
  942.  
  943.         if (wrcnt <= 0) {    /* if nothing to write */
  944.             zoutcnt = 0;
  945.             zoutptr = zoutbuffer;
  946.             return (0);        /* we are done this time */
  947.         }
  948.         }
  949.     }
  950.     }
  951.   norm_file:
  952.     err = FSWrite (fp[ZOFILE].frefnum, &wrcnt, outp);
  953.     zcnt_written += wrcnt;
  954.     zoutcnt = 0;
  955.     zoutptr = zoutbuffer;
  956.     if (err != noErr) {        /* error occured? */
  957.     sstate = 'a';        /* yes, abort protocol */
  958.     return (ioutil (err) ? 0 : -1);    /* else return code */
  959.     }
  960.     return (0);        /* no problems */
  961. }
  962.  
  963. /****************************************************************************/
  964. /*  C H K F N  --  Internal function to verify file number is ok.
  965.  *
  966.  * Returns:
  967.  *   TRUE  - file is open
  968.  *  FALSE  - file is not open
  969.  *
  970.  * Issues an error message if the file number is not in range.
  971.  *
  972.  */
  973. /****************************************************************************/
  974. chkfn (n)
  975. int n;
  976. {
  977.     switch (n) {
  978.       case ZCTERM:
  979.       case ZSTDIO:
  980.       case ZIFILE:
  981.       case ZOFILE:
  982.       case ZDFILE:
  983.       case ZTFILE:
  984.       case ZPFILE:
  985.       case ZSYSFN:
  986.       case ZSFILE:
  987.     break;
  988.       default:
  989.     debug (F101, "chkfn: file number out of range", "", n);
  990.     printerr ("chkfn - file number not in range: ", n);
  991.     return (FALSE);        /* ugh */
  992.     }
  993.     return ((fp[n].fstatus != 0));    /* if open, fstatus is nonzero */
  994. }                /* chkfn */
  995.  
  996.  
  997.  
  998. /****************************************************************************/
  999. /*  Z C H K I  --  Check if input file exists and is readable.
  1000.  *
  1001.  * Returns:
  1002.  *  >= 0 if the file can be read (returns the size).
  1003.  *    -1 if file doesn't exist or can't be accessed,
  1004.  *    -2 if file exists but is not readable (e.g. a directory file).
  1005.  *    -3 if file exists but protected against read access.
  1006.  */
  1007. /****************************************************************************/
  1008. long
  1009. zchki (name)
  1010. char *name;
  1011. {
  1012.     int err;
  1013.     FileParam info;
  1014.  
  1015.     if (strcmp (name, "stdin") == 0)    /* stdin is a pipe */
  1016.     return (PIPESIZE);    /* return size of buffer */
  1017.  
  1018.     c2pstr (name);        /* convert to a pascal string */
  1019.     info.ioFVersNum = 0;    /* No version number */
  1020.     info.ioFDirIndex = 0;    /* Use the file name */
  1021.     info.ioNamePtr = name;    /* Point to the file name */
  1022.     info.ioVRefNum = filargs.filvol;    /* Volume number */
  1023.     err = PBGetFInfo (&info, FALSE);    /* Get info on file */
  1024.     p2cstr (name);        /* put the name back */
  1025.  
  1026.     if (err == fnfErr)        /* file not found? */
  1027.     return (-1);        /* then that is what they want */
  1028.  
  1029.     if (err != noErr) {        /* any other error? */
  1030.     printerr ("zchki failed: ", err);    /* tell me about it */
  1031.     return (-1);
  1032.     }
  1033.     iflen = (filargs.filflg & FIL_RSRC) ?    /* if thinking about RSRC */
  1034.     info.ioFlRPyLen :    /* return that size, */
  1035.     info.ioFlPyLen;        /* else DATA */
  1036.  
  1037.     return (iflen);        /* did ok */
  1038. }                /* zchki */
  1039.  
  1040.  
  1041.  
  1042. /****************************************************************************/
  1043. /*  Z C H K O  --  Check if output file can be created.
  1044.  *
  1045.  * Returns
  1046.  *  0: Write OK
  1047.  * -1: write permission for the file should be denied.
  1048.  */
  1049. /****************************************************************************/
  1050. zchko (name)
  1051. char *name;
  1052. {
  1053.     char volname[100];
  1054.     VolumeParam info;
  1055.  
  1056.     info.ioVolIndex = 0;    /* Use the vol ref num only */
  1057.     info.ioNamePtr = volname;    /* Pointer to the volume name */
  1058.     info.ioVRefNum = filargs.filvol;    /* Volume reference number */
  1059.     if (!ioutil (PBGetVInfo (&info, 0)))    /* Get info on vol,
  1060.                          * synchronously */
  1061.     return (-1);        /* failed... */
  1062.  
  1063.     if ((info.ioVAtrb & 0x8000) != 0)    /* Write locked? */
  1064.     return (-1);        /* yes... */
  1065.  
  1066.     return (0);            /* else success */
  1067. }                /* zchko */
  1068.  
  1069.  
  1070.  
  1071. /****************************************************************************/
  1072. /*  Z D E L E T  --  Delete the named file and return TRUE if successful */
  1073. /****************************************************************************/
  1074. zdelet (name)
  1075. char *name;
  1076. {
  1077.     return (ioutil (FSDelete (name, filargs.filvol)));
  1078. }                /* zdelet */
  1079.  
  1080.  
  1081.  
  1082. /****************************************************************************/
  1083. /*  Z R T O L  --  Convert remote filename into local form.
  1084.  *
  1085.  * Check here to see if this should go into the resource fork (.rsrc)
  1086.  * or into the data fork (.data).
  1087.  *
  1088.  */
  1089. /****************************************************************************/
  1090. zrtol (name, name2)
  1091. char *name, *name2;
  1092. {
  1093.  
  1094.     strcpy (name2, name);    /* copy name to destination */
  1095.  
  1096.     if (filargs.filflg & (FIL_DODLG))    /* selected by user? */
  1097.     return;            /* won't be called but... */
  1098.  
  1099.     filargs.filflg &= ~(FIL_RBDT);    /* clear out flags */
  1100.     filargs.filflg |= sfprtol (name2);    /* convert name2 and set flags */
  1101.     binary = (filargs.filflg & FIL_BINA);    /* selected binary mode? */
  1102.     return;
  1103. }                /* zrtol */
  1104.  
  1105.  
  1106.  
  1107. /****************************************************************************/
  1108. /*  Z L T O R  --  Convert filename from local format to common form. */
  1109. /****************************************************************************/
  1110. zltor (name, name2)
  1111. char *name, *name2;
  1112. {
  1113.     int dc = 0;
  1114.  
  1115.     while (*name != '\0') {
  1116.     if (*name == ' ')
  1117.         name++;        /* Skip spaces */
  1118.     else if ((*name == '.') && (++dc > 1)) {
  1119.         *name2++ = 'X';    /* Just 1 dot */
  1120.         name++;
  1121.     } else
  1122.         *name2++ = (islower (*name)) ? toupper (*name++) : *name++;
  1123.     }
  1124.     *name2++ = '\0';        /* deposit final null */
  1125.     return;
  1126. }                /* zltor */
  1127.  
  1128.  
  1129.  
  1130. /****************************************************************************/
  1131. /*  Z C H D I R  --  Change directory or volumes */
  1132. /****************************************************************************/
  1133. zchdir (dirnam)
  1134. char *dirnam;
  1135. {
  1136.     int err;
  1137.     int volnum;
  1138.     WDPBRec vinfo;
  1139.     short *FSFCBLen = (short *)0x3F6;
  1140.  
  1141.     if (*FSFCBLen < 0) {    /* if no HFS ROM's */
  1142.     err = SetVol (dirnam, 0);
  1143.     volnum = 0;
  1144.     } else {            /* use HFS calls */
  1145.     c2pstr (dirnam);
  1146.     vinfo.ioVRefNum = 0;    /* open a workimg directory */
  1147.     vinfo.ioWDDirID = 0;
  1148.     vinfo.ioWDProcID = 'ERIK';
  1149.     vinfo.ioNamePtr = dirnam;
  1150.     err = PBOpenWD (&vinfo, FALSE);
  1151.     p2cstr (dirnam);
  1152.     if (err != noErr)
  1153.         return (FALSE);
  1154.  
  1155.     err = SetVol (NIL, vinfo.ioVRefNum);
  1156.     volnum = vinfo.ioVRefNum;
  1157.     }
  1158.  
  1159.     if (err == noErr) {        /* set default volume */
  1160.     screen (SCR_TN, 0, 0l, dirnam);
  1161.     filargs.filvol = volnum;/* make default */
  1162.     } else
  1163.     screen (SCR_TN, 0, 0l, "Can't set directory");
  1164.  
  1165.     return (err == noErr);    /* return ok or fail */
  1166. }                /* zchdir */
  1167.  
  1168. /****************************************************************************/
  1169. /*  Z H O M E  --  Return pointer to user's home directory  */
  1170. /****************************************************************************/
  1171.  
  1172. char *
  1173. zhome() {
  1174.     return("(directory unknown)");    /* PWP: for now */
  1175. }
  1176.  
  1177. /****************************************************************************/
  1178. /*  Z G T D I R  --  Return pointer to user's current directory  */
  1179. /****************************************************************************/
  1180.  
  1181. char *
  1182. zgtdir() {
  1183.     return ("(directory unknown)");    /* PWP: for now */
  1184. }
  1185.  
  1186. /****************************************************************************/
  1187. /* initialize the fields of a pipe */
  1188. /****************************************************************************/
  1189. zinitpipe (pipe, refillproc)
  1190. MACPIPE *pipe;
  1191. ProcPtr refillproc;
  1192. {
  1193.     pipe->refill = refillproc;
  1194.     pipe->currptr = pipe->pipebuf;
  1195.     pipe->charsleft = 0;
  1196.     *(pipe->currptr) = '\0';
  1197. }                /* zinitpipe */
  1198.  
  1199.  
  1200.  
  1201. /****************************************************************************/
  1202. /* fill the pipe; last is TRUE if it is the */
  1203. /* last time the pipe has to be filled  */
  1204. /****************************************************************************/
  1205. zfillpipe (pipe, str, last)
  1206. MACPIPE *pipe;
  1207. char *str;
  1208. Boolean last;
  1209. {
  1210.     int len;
  1211.  
  1212.     len = strlen (str);
  1213.     if (last)
  1214.     len++;
  1215.  
  1216.     if (len > PIPESIZE) {
  1217.     len = PIPESIZE;
  1218.     if (last)
  1219.         str[PIPESIZE - 1] = '\0';    /* make sure we keep the eop
  1220.                      * character */
  1221.     printerr ("pipe overflow! characters may be lost");
  1222.     }
  1223.     memcpy (pipe->pipebuf, str, len);
  1224.     pipe->charsleft = len;
  1225. }                /* zfillpipe */
  1226.  
  1227.  
  1228.  
  1229. /****************************************************************************/
  1230. /* sprintf uses 12 kByte. This is the reason to use a simpler formatter here */
  1231. /* formatnum returns a right adjusted numberstring padded with fillc */
  1232. /* Numbers which do not fit into width are truncated on the left. */
  1233. /* Make sure str is at least 'width+1' bytes wide */
  1234. /****************************************************************************/
  1235. formatnum (num, fillc, width, str)
  1236. char *str;
  1237. long num;
  1238. char fillc;
  1239. int width;
  1240. {
  1241.     int i;
  1242.     char numstr[12];        /* -2147483647 is the longest string */
  1243.     /* that can be returned from NumToString */
  1244.  
  1245.     NumToString (num, numstr);
  1246.     i = strlen (numstr);
  1247.  
  1248.     while ((i >= 0) && (width >= 0))
  1249.     str[width--] = numstr[i--];
  1250.  
  1251.     while (width >= 0)
  1252.     str[width--] = fillc;
  1253. }                /* formatnum */
  1254.  
  1255.  
  1256.  
  1257. MACPIPE cmdpipe;
  1258.  
  1259. int volindex;
  1260. char spaceheader[60] = "\
  1261. Free      Name\n\
  1262. --------- --------------------\n";
  1263.  
  1264. /****************************************************************************/
  1265. /* loop through all available volumes and display the space left */
  1266. /****************************************************************************/
  1267. zlspace ()
  1268. {
  1269.     int err;
  1270.     Str255 name;
  1271.     long free;
  1272.     char outstr[60];
  1273.     VolumeParam vinfo;
  1274.  
  1275.     name.length = 0;
  1276.     vinfo.ioVolIndex = volindex;
  1277.     vinfo.ioNamePtr = &name;
  1278.     err = PBGetVInfo (&vinfo, FALSE);
  1279.  
  1280.     if (err == noErr) {
  1281.     free = vinfo.ioVFrBlk * vinfo.ioVAlBlkSiz;
  1282.     formatnum (free, ' ', 9, outstr);
  1283.     strcat (outstr, " ");
  1284.     p2cstr (&name);
  1285.     strcat (outstr, &name);
  1286.     strcat (outstr, "\n");
  1287.     zfillpipe (&cmdpipe, outstr, FALSE);
  1288.     volindex++;
  1289.     } else
  1290.     zfillpipe (&cmdpipe, "", TRUE);
  1291.  
  1292. }                /* zlspace */
  1293.  
  1294.  
  1295.  
  1296. int fileindex;
  1297. char dirheader[100] = "\
  1298. Size    Type Crea Last Modification Name\n\
  1299. ------- ---- ---- ----------------- --------------------\n";
  1300.  
  1301. /****************************************************************************/
  1302. /* loop through all the files on the current volume / directory */
  1303. /****************************************************************************/
  1304. zldir ()
  1305. {
  1306.     int err;
  1307.     CInfoPBRec info;
  1308.     WDPBRec vinfo;
  1309.  
  1310.     Str255 name;
  1311.     DateTimeRec dtrec;
  1312.  
  1313.     char outstr[60];
  1314.     char type[10];
  1315.     char tmpstr[11];
  1316.     char datestr[11];
  1317.     char hourstr[3];
  1318.     char minutestr[3];
  1319.  
  1320.     unsigned long secs;
  1321.     long size;
  1322.  
  1323.     short *FSFCBLen = (short *) 0x3F6;
  1324.  
  1325.     if (*FSFCBLen < 0) {
  1326.     errpkt ("Sorry, the server uses 64 kByte ROM's");
  1327.     zfillpipe (&cmdpipe, "", TRUE);
  1328.     return;
  1329.     }
  1330.     PBHGetVol (&vinfo, FALSE);
  1331.  
  1332.     /* loop through all the files starting at the first one */
  1333.     name.length = 0;
  1334.     info.hfileInfo.ioFDirIndex = fileindex;    /* Get next file name */
  1335.     info.hfileInfo.ioNamePtr = &name;    /* Point to the empty file name */
  1336.     info.hfileInfo.ioVRefNum = vinfo.ioWDVRefNum;    /* Directory / Volume
  1337.                              * number */
  1338.     info.hfileInfo.ioDirID = vinfo.ioWDDirID;    /* Directory / Volume number */
  1339.     err = PBGetCatInfo (&info, FALSE);    /* Get info on file */
  1340.  
  1341.     if (err == noErr) {
  1342.     if (info.hfileInfo.ioFlAttrib & ioDirMask) {    /* a directory if it's
  1343.                              * true */
  1344.         secs = info.dirInfo.ioDrMdDat;
  1345.         strcpy (type, "#########");
  1346.         strcpy (outstr, "       ");
  1347.     } else {        /* a file otherwise */
  1348.         secs = info.hfileInfo.ioFlMdDat;
  1349.         size = info.hfileInfo.ioFlLgLen + info.hfileInfo.ioFlRLgLen;
  1350.         strcpy (type, "         ");
  1351.         memcpy (type, &info.hfileInfo.ioFlFndrInfo.fdType, 4);
  1352.         memcpy (type + 5, &info.hfileInfo.ioFlFndrInfo.fdCreator, 4);
  1353.         formatnum (size, ' ', 7, outstr);
  1354.     }
  1355.     IUDateString (secs, shortDate, tmpstr);
  1356.     strcpy (datestr, "   ");
  1357.     datestr[10 - strlen (tmpstr)] = '\0';
  1358.     strcat (datestr, tmpstr);
  1359.  
  1360.     Secs2Date (secs, &dtrec);
  1361.     formatnum (dtrec.hour, ' ', 2, hourstr);
  1362.     formatnum (dtrec.minute, '0', 2, minutestr);
  1363.  
  1364.     p2cstr (&name);
  1365.  
  1366.     strcat (outstr, " ");
  1367.     strcat (outstr, type);
  1368.     strcat (outstr, " ");
  1369.     strcat (outstr, datestr);
  1370.     strcat (outstr, " ");
  1371.     strcat (outstr, hourstr);
  1372.     strcat (outstr, ":");
  1373.     strcat (outstr, minutestr);
  1374.     strcat (outstr, "  ");
  1375.     strcat (outstr, &name);
  1376.     strcat (outstr, "\n");
  1377.  
  1378.     zfillpipe (&cmdpipe, outstr, FALSE);
  1379.     fileindex++;
  1380.     } else
  1381.     zfillpipe (&cmdpipe, "", TRUE);
  1382.  
  1383. }                /* zldir */
  1384.  
  1385.  
  1386.  
  1387. #define CMD_RSRC    1
  1388. #define CMD_DATA    2
  1389. #define CMD_TEXT    3
  1390. #define CMD_BINA    4
  1391. #define CMD_DIR        5
  1392. #define CMD_DEL        6
  1393. #define CMD_SPC        7
  1394. #define CMD_UNK 255
  1395.  
  1396. char *cmdtab[] = {
  1397.     "fork rsrc",
  1398.     "fork data",
  1399.     "mode binary",
  1400.     "mode text",
  1401.     DIRCMDSTR,
  1402.     DELCMDSTR,
  1403.     SPCCMDSTR
  1404. };
  1405.  
  1406. int toktab[] = {
  1407.     CMD_RSRC,
  1408.     CMD_DATA,
  1409.     CMD_BINA,
  1410.     CMD_TEXT,
  1411.     CMD_DIR,
  1412.     CMD_DEL,
  1413.     CMD_SPC
  1414. };
  1415.  
  1416. #define NTOKS (sizeof (toktab)/sizeof(int))
  1417.  
  1418. /****************************************************************************/
  1419. /*  Z X C M D -- Run a system command so its output can be read like a file.
  1420.  *
  1421.  * Used on the MAC to implement MAC settings commands -- commands from a
  1422.  * remote system when in server mode that change internal variables.
  1423.  *
  1424.  */
  1425. /****************************************************************************/
  1426. int
  1427. zxcmd (comand)
  1428. char *comand;
  1429. {
  1430.     int sc;
  1431.     char theStr[120];
  1432.     int retCd;
  1433.  
  1434.     fp[ZIFILE].fstatus = FS_PIPE;    /* set input from pipe */
  1435.     fp[ZIFILE].fpipe = &cmdpipe;/* init pointer to command pipe */
  1436.  
  1437.     switch (sc = getcmd (comand)) {
  1438.       case CMD_RSRC:
  1439.       case CMD_DATA:
  1440.     zinitpipe (&cmdpipe, NILPROC);
  1441.     zfillpipe (&cmdpipe, "Default Fork set OK\n", TRUE);
  1442.     filargs.filflg &= ~(FIL_RSRC | FIL_DATA);    /* turn off  */
  1443.     filargs.filflg |= (sc == CMD_RSRC) ? FIL_RSRC : FIL_DATA;
  1444.     return (TRUE);        /* ok */
  1445.  
  1446.       case CMD_TEXT:
  1447.       case CMD_BINA:
  1448.     zinitpipe (&cmdpipe, NILPROC);
  1449.     zfillpipe (&cmdpipe, "Default Mode set OK\n", TRUE);
  1450.     filargs.filflg &= ~(FIL_TEXT | FIL_BINA);
  1451.     filargs.filflg |= (sc == CMD_BINA) ? FIL_BINA : FIL_TEXT;
  1452.     return (TRUE);        /* ok */
  1453.  
  1454.       case CMD_DIR:
  1455.     zinitpipe (&cmdpipe, zldir);
  1456.     zfillpipe (&cmdpipe, dirheader, FALSE);
  1457.     fileindex = 1;        /* start at the first file on */
  1458.     /* the current volume / directory */
  1459.     return (TRUE);        /* always ok */
  1460.  
  1461.       case CMD_DEL:
  1462.     strcpy (theStr, comand + strlen (DELCMDSTR));    /* the filename
  1463.                              * immediately  */
  1464.     retCd = zdelet (theStr);/* follows the command name */
  1465.     if (retCd) {
  1466.         zinitpipe (&cmdpipe, NILPROC);
  1467.         strcat (theStr, " deleted.");
  1468.         zfillpipe (&cmdpipe, theStr, true);
  1469.     }
  1470.     return (retCd);
  1471.  
  1472.       case CMD_SPC:
  1473.     zinitpipe (&cmdpipe, zlspace);    /* init pipe for space listing */
  1474.     zfillpipe (&cmdpipe, spaceheader, FALSE);    /* copy the header to
  1475.                              * the pipe */
  1476.     volindex = 1;        /* start with the first volume */
  1477.     return (TRUE);        /* always ok */
  1478.  
  1479.       default:
  1480.     return (FALSE);        /* fail, unknown */
  1481.     }
  1482. }                /* zxcmd */
  1483.  
  1484.  
  1485.  
  1486. /****************************************************************************/
  1487. /****************************************************************************/
  1488. getcmd (cmd)
  1489. char *cmd;
  1490. {
  1491.     int k;
  1492.  
  1493.     for (k = 0; k < NTOKS; k++)
  1494.     if (strncmp (cmdtab[k], cmd, strlen (cmdtab[k])) == 0)
  1495.         return (toktab[k]);    /* and return ID */
  1496.     return (CMD_UNK);        /* else unknown */
  1497.  
  1498. }                /* getcmd */
  1499.  
  1500.  
  1501.  
  1502. /****************************************************************************/
  1503. /*  Z C L O S F  - wait for the child fork to terminate and close the pipe. */
  1504. /****************************************************************************/
  1505. zclosf ()
  1506. {
  1507.     return;
  1508. }                /* zclosf */
  1509.  
  1510.  
  1511.  
  1512. int zindex;
  1513. int zfiles;
  1514. char *zname;
  1515.  
  1516. /****************************************************************************/
  1517. /*  Z X P A N D  --  Expand a wildcard string into an array of strings
  1518.  *
  1519.  * Returns the number of files that match fn, with data structures set up
  1520.  * so that first file (if any) will be returned by the next znext() call.
  1521.  */
  1522. /****************************************************************************/
  1523. zxpand (fn)
  1524. char *fn;
  1525. {
  1526.     int err;
  1527.     FileParam info;
  1528.  
  1529.     zfiles = 1;
  1530.  
  1531.     if ((filargs.filflg & FIL_ALLFL) ||    /* all files check box on or */
  1532.     (strcmp (fn, ":") == 0)) {    /* server 'get' with filname = ':' */
  1533.  
  1534.     /* the ioVNmFls field of the VolumeParam returns the number of files */
  1535.  
  1536.     /*
  1537.      * !and! directories after PBGetInfo. This is why we have to count
  1538.      * here.
  1539.      */
  1540.  
  1541.     info.ioFVersNum = 0;    /* No version number */
  1542.     info.ioNamePtr = NIL;    /* Point to the file name */
  1543.     info.ioVRefNum = filargs.filvol;    /* Volume number */
  1544.     do {
  1545.         info.ioFDirIndex = zfiles;    /* Get next file name */
  1546.         err = PBGetFInfo (&info, FALSE);    /* Get info on file */
  1547.         zfiles++;
  1548.     } while (err == noErr);
  1549.     zname = NIL;        /* no specific file */
  1550.     zfiles -= 2;        /* we counted 2 too high */
  1551.  
  1552.     } else
  1553.     zname = fn;        /* keep a pointer to that name */
  1554.  
  1555.     zindex = 0;            /* init the files sent counter */
  1556.     return (zfiles);
  1557. }                /* zxpand */
  1558.  
  1559.  
  1560.  
  1561. /****************************************************************************/
  1562. /*  Z N E X T  --  Get name of next file from list created by zxpand().
  1563.  *
  1564.  * Returns >0 if there's another file, with its name copied into the
  1565.  * arg string, or 0 if no more files in list.
  1566.  */
  1567. /****************************************************************************/
  1568. znext (fn)
  1569. char *fn;
  1570. {
  1571.     int err;
  1572.     Str255 name;
  1573.     FileParam info;
  1574.  
  1575.     zindex++;            /* next file */
  1576.  
  1577.     if (zindex > zfiles)
  1578.     return (0);        /* no more files */
  1579.  
  1580.     if (zname != NIL)
  1581.     strcpy (fn, zname);    /* Get the file's name */
  1582.     else {
  1583.     info.ioFVersNum = 0;    /* No version number */
  1584.     info.ioFDirIndex = zindex;    /* Get next file name */
  1585.     info.ioNamePtr = &name;    /* Point to the file name */
  1586.     info.ioVRefNum = filargs.filvol;    /* VolRefNum of the selected
  1587.                          * folder */
  1588.     err = PBGetFInfo (&info, FALSE);    /* Get info on file */
  1589.     if (err == noErr) {
  1590.         p2cstr (&name);
  1591.         strcpy (fn, &name);    /* Return the file's name */
  1592.         *filargs.filrem = '\0';    /* reset remote name for folder
  1593.                      * transfer */
  1594.     } else {
  1595.         printerr ("Error on reading next file name: ", err);
  1596.         return (0);
  1597.     }
  1598.     }
  1599.     return (1);            /* fn contains the next file */
  1600. }                /* znext */
  1601.  
  1602.  
  1603.  
  1604. /****************************************************************************/
  1605. /*  Z N E W N  --  Make a new name for the given file  */
  1606. /****************************************************************************/
  1607. znewn (fn, s)
  1608. char *fn, **s;
  1609. {
  1610.     char *extp;
  1611.     int ver;
  1612.  
  1613.     strcpy (*s, fn);        /* copy in the name */
  1614.     if (strlen (*s) > 59)    /* don't allow long names */
  1615.     *s[59] = '\0';        /* it breaks the finder */
  1616.     extp = *s + strlen (*s);    /* find position of extension */
  1617.     *extp++ = '.';        /* add in the dot now */
  1618.  
  1619.     for (ver = 0; ver < 99; ver++) {    /* I'll try this many names */
  1620.     NumToString ((long) ver, extp);    /* add in the number */
  1621.     if (zchki (*s) == -1)    /* is this file known? */
  1622.         return;        /* no, made a good one! */
  1623.     }
  1624.     printerr ("znewn failed to find unique name in 99 attempts", 0);
  1625.     return;
  1626. }                /* znewn */
  1627.  
  1628. /*  Z S A T T R */
  1629. /*
  1630.  Fills in a Kermit file attribute structure for the file which is to be sent.
  1631.  Returns 0 on success with the structure filled in, or -1 on failure.
  1632.  If any string member is null, then it should be ignored.
  1633.  If any numeric member is -1, then it should be ignored.
  1634. */
  1635. zsattr(xx) struct zattr *xx; {
  1636.     long k;
  1637.  
  1638.     k = iflen % 1024L;                  /* File length in K */
  1639.     if (k != 0L) k = 1L;
  1640.     xx->lengthk = (iflen / 1024L) + k;
  1641.     xx->type.len = 0;                   /* File type can't be filled in here */
  1642.     xx->type.val = "";
  1643.     xx->date.len = 0;                   /* File creation date */
  1644.     xx->date.val = "";
  1645.     xx->creator.len = 0;                /* File creator */
  1646.     xx->creator.val = "";
  1647.     xx->account.len = 0;                /* File account */
  1648.     xx->account.val = "";
  1649.     xx->area.len = 0;                   /* File area */
  1650.     xx->area.val = "";
  1651.     xx->passwd.len = 0;                 /* Area password */
  1652.     xx->passwd.val = "";
  1653.     xx->blksize = -1L;                  /* File blocksize */
  1654.     xx->access.len = 0;                 /* File access */
  1655.     xx->access.val = "";
  1656.     xx->encoding.len = 0;               /* Transfer syntax */
  1657.     xx->encoding.val = 0;
  1658.     xx->disp.len = 0;                   /* Disposition upon arrival */
  1659.     xx->disp.val = "";
  1660.     xx->lprotect.len = 0;               /* Local protection */
  1661.     xx->lprotect.val = "";
  1662.     xx->gprotect.len = 0;               /* Generic protection */
  1663.     xx->gprotect.val = "";
  1664.     xx->systemid.len = 2;               /* System ID */
  1665.     xx->systemid.val = "A3";        /* (A3: Apple Macintosh) */
  1666.     xx->recfm.len = 0;                  /* Record format */
  1667.     xx->recfm.val = "";
  1668.     xx->sysparam.len = 0;               /* System-dependent parameters */
  1669.     xx->sysparam.val = "";
  1670.     xx->length = iflen;                 /* Length */
  1671.     return(0);
  1672. }
  1673.  
  1674. /* Find initialization file. */
  1675.  
  1676. zkermini() {
  1677. /*  nothing yet...  this function added for benefit of VMS Kermit.  */
  1678.     return(0);
  1679. }
  1680.  
  1681. /****************************************************************************/
  1682. pascal void
  1683. reset ()
  1684. /****************************************************************************/
  1685. extern 0x4E70;
  1686.  
  1687. /****************************************************************************/
  1688. /* zkself() - Kill self (reboot).  On other machines does a logout.
  1689.  *              Flush volumes and reboot.  Called by remote BYE.
  1690.  *
  1691.  */
  1692. /****************************************************************************/
  1693. zkself ()
  1694. {
  1695.     DrvQEl *drvqe;
  1696.     char vname[255];
  1697.     long vfreeb;
  1698.     short vrefnum;
  1699.     int err;
  1700.  
  1701.     /* handle on drive q */
  1702.     for (drvqe = (DrvQEl *) ((QHdr *) GetDrvQHdr ())->qHead;
  1703.      drvqe != NULL;        /* while still something */
  1704.      drvqe = drvqe->qLink) {/* step to next *//* for each drive */
  1705.     err = GetVInfo (drvqe->dQDrive, vname, &vrefnum, &vfreeb);
  1706.     if (err == noErr)
  1707.         err = FlushVol (NILPTR, vrefnum);    /* flush the volume given
  1708.                          * refnum */
  1709.     else if (err != nsvErr)
  1710.         screen (SCR_TN,0,0l,"Remote cmd: GetVinfo returned unknown code");
  1711.     }
  1712.  
  1713.     mac_cleanup ();        /* clean up before leaving */
  1714.     reset ();
  1715. }                /* zkself */
  1716.  
  1717. zmail(p,f) char *p; char *f; {        /* Send file f as mail to address p */
  1718.     screen (SCR_WM,0,0l,"There is no mail support in Mac Kermit.");
  1719. }
  1720.  
  1721. zprint(p,f) char *p; char *f; {        /* Print file f with options p */
  1722.     screen (SCR_WM,0,0l,"There is no printer support in Mac Kermit yet.");
  1723. }
  1724.  
  1725. struct {
  1726.     int errnum;
  1727.     char *errstr;
  1728. }   ioerrs[] = {
  1729.  
  1730.     {
  1731.     dirFulErr, "Directory is full"
  1732.     },
  1733.     {
  1734.     dskFulErr, "Disk is full"
  1735.     },
  1736.     {
  1737.     wPrErr, "Diskette is write protected"
  1738.     },
  1739.     {
  1740.     fLckdErr, "File is software locked"
  1741.     },
  1742.     {
  1743.     vLckdErr, "Volume is software locked"
  1744.     },
  1745.     {
  1746.     fBsyErr, "File is busy"
  1747.     },
  1748.     {
  1749.     opWrErr, "File is already open with write permission"
  1750.     },
  1751.     {
  1752.     fnfErr, "File does not exist"
  1753.     },
  1754.     {
  1755.     0, NILPTR
  1756.     }
  1757. };
  1758.  
  1759. /****************************************************************************/
  1760. /* ioutil - handle the result from an IO call, checking for an
  1761.  *            error return and displaying an appropriate error
  1762.  *            message.  Returns TRUE if no error occured, FALSE
  1763.  *            otherwise.
  1764.  */
  1765. /****************************************************************************/
  1766. int
  1767. ioutil (err)
  1768. int err;
  1769. {
  1770.     int e;
  1771.  
  1772.     if (err == noErr)
  1773.     return (TRUE);
  1774.  
  1775.     for (e = 0; ioerrs[e].errnum != 0 && ioerrs[e].errnum != err; e++);
  1776.  
  1777.     if (ioerrs[e].errstr == NILPTR)    /* anything there? */
  1778.     printerr ("Unknown IO error: ", err);
  1779.     else
  1780.     printerr (ioerrs[e].errstr, 0);
  1781.  
  1782.     return (FALSE);
  1783. }                /* ioutil */
  1784.  
  1785.  
  1786. #ifdef COMMENT
  1787. PWP: my copy of IM 2 says that this _is_ a standard toolbox call, so we
  1788. don't need this at all.
  1789.  
  1790. /****************************************************************************/
  1791. /*
  1792.  * OpenRF is not a standard Toolbox routine but acts identically to FSOpen
  1793.  * except that it opens the resource fork instead of the data fork.
  1794.  */
  1795. /****************************************************************************/
  1796. int 
  1797. OpenRF (fileName, vRefNum, refNum)
  1798. char *fileName;
  1799. int vRefNum;
  1800. short *refNum;
  1801. {
  1802.     IOParam pb;
  1803.  
  1804.     c2pstr (fileName);
  1805.     pb.ioNamePtr = fileName;
  1806.     pb.ioVRefNum = vRefNum;
  1807.     pb.ioVersNum = 0;
  1808.     pb.ioPermssn = 0;
  1809.     pb.ioMisc = (Ptr) 0;
  1810.     PBOpenRF (&pb, 0);
  1811.     *refNum = pb.ioRefNum;
  1812.     p2cstr (fileName);
  1813.     return pb.ioResult;
  1814. }                /* OpenRF */
  1815. #endif COMMENT
  1816.  
  1817. extern short dfltVol;
  1818.  
  1819. #ifdef TLOG
  1820. short tlogfile;
  1821. char tlogname[] = "Kermit Transaction";
  1822.  
  1823. /****************************************************************************/
  1824. /****************************************************************************/
  1825. opentlog ()
  1826. {
  1827.     return (openlogfile("Transaction log name:", tlogname, &tlogfile));
  1828. }
  1829.  
  1830. /****************************************************************************/
  1831. /****************************************************************************/
  1832. closetlog ()
  1833. {
  1834.     FSClose (tlogfile);
  1835.     FlushVol (NIL, dfltVol);
  1836. }                /* closetlog */
  1837.  
  1838.  
  1839.  
  1840. /****************************************************************************/
  1841. /****************************************************************************/
  1842. tlog (f, s1, s2, n)
  1843. int f;
  1844. long n;
  1845. char *s1;
  1846. char *s2;
  1847. {
  1848.     char numstr[12];
  1849.     char outstr[256];
  1850.     long count;
  1851.  
  1852.     if (tralog) {
  1853.     strcpy (outstr, s1);
  1854.  
  1855.     if (strlen (s2)) {
  1856.         strcat (outstr, " ");
  1857.         strcat (outstr, s2);
  1858.     }
  1859.     if (n) {
  1860.         NumToString (n, numstr);
  1861.         strcat (outstr, " ");
  1862.         strcat (outstr, numstr);
  1863.     }
  1864.     strcat (outstr, "\r");
  1865.  
  1866.     count = strlen (outstr);
  1867.     FSWrite (tlogfile, &count, outstr);
  1868.     }
  1869. }                /* tlog */
  1870.  
  1871. #endif
  1872.  
  1873.  
  1874.  
  1875. short slogfile;
  1876. char slogname[] = "Kermit Session";
  1877.  
  1878. /****************************************************************************/
  1879. /****************************************************************************/
  1880. openslog ()
  1881. {
  1882.     return (openlogfile("Session log name:", slogname, &slogfile));
  1883. }
  1884.  
  1885.  
  1886. /****************************************************************************/
  1887. /****************************************************************************/
  1888. openlogfile(prompt, name, fdp)
  1889. char *prompt, *name;
  1890. short *fdp;
  1891. {
  1892.     int err;
  1893.     FInfo info;
  1894.     SFReply sfr;    /* holds file info */
  1895.     Point where;
  1896.     
  1897.     SetPt(&where, 75, 80);
  1898.     SFPutFile (&where, prompt, name, NILPROC, &sfr);
  1899.     if (!sfr.good)    /* if canceled */
  1900.         return (0);
  1901.  
  1902.     p2cstr(&sfr.fName);
  1903.     err = Create (&sfr.fName, sfr.vRefNum, 'MACA', 'TEXT');
  1904.     if (err != dupFNErr)
  1905.     if (!ioutil (err))
  1906.         return (0);
  1907.  
  1908.     err = FSOpen (&sfr.fName, sfr.vRefNum, fdp); /* open the logfile */
  1909.     if (!ioutil (err))
  1910.     return (0);
  1911.  
  1912.     SetFPos (*fdp, fsFromLEOF, 0);    /* set file pointer to eof */
  1913.     return (1);
  1914. }                /* openslog */
  1915.  
  1916.  
  1917.  
  1918. /****************************************************************************/
  1919. /****************************************************************************/
  1920. closeslog ()
  1921. {
  1922.     int err;
  1923.     /* scrtolog (); */    /* dump the rest of the screen to the logfile */
  1924.     err = FSClose (slogfile);
  1925.     if (!ioutil (err))
  1926.     return (0);
  1927.     FlushVol (NIL, dfltVol);
  1928. }                /* closeslog */
  1929.  
  1930.  
  1931.  
  1932. /****************************************************************************/
  1933. /* write a maximum of n characters from s to the session log file */
  1934. /* skip all trailing blanks */
  1935. /****************************************************************************/
  1936. slog (s, n)
  1937. char *s;
  1938. int n;
  1939. {
  1940.     long count;
  1941.     char *c;
  1942.  
  1943.     /* skip all non visible characters */
  1944.     for (c = s + n - 1; (*c <= ' ') && (c >= s); c--);
  1945.  
  1946.     /* adjust count and write to file */
  1947.     count = (long) (c - s + 1);
  1948.     FSWrite (slogfile, &count, s);
  1949.  
  1950.     /* write a cr at end of line */
  1951.     count = 1;
  1952.     FSWrite (slogfile, &count, "\r");
  1953. }                /* slog */
  1954.  
  1955. char *
  1956. tilde_expand(dirname) char *dirname; {
  1957.     return("");
  1958. }
  1959.