home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / old / ckermit4e / ckmfio.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  38KB  |  1,372 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. /*  May 88 - Added dummy zgtdir() function, Frank, CU.
  4. /* Version 0.8(35) - Jim Noble at Planning Research Corporation, June 1987. */
  5. /* Ported to Megamax native Macintosh C compiler. */
  6. /* Edit by Bill on Thu May 30, 00:18 */
  7. /* Do error handling, neaten up comments, and some code. */
  8. /* Edit by Bill on Wed May 15, 16:09 */
  9. /* Make zrtol call common sfprtol, .RSRC overrides default settings */
  10. /* ckmfio.c, Mon Apr 29 17:48, Edit by Bill*2 */
  11. /* Put null in translated name to tie it off. */
  12. /* Make author text of new file to ???? instead of random string */
  13. /* Do flushvol after closing a file */
  14. /* Bill C., Apr 24 */
  15. /* Change zchin to allow sending of files with high order bits on */
  16. /* Bill C., Apr 22 */
  17. /* Add error handling (informing) for more cases, e.g. can't delete */
  18. /* Bill C., Apr 22 */
  19. /* Fix Resource/Data fork stuff.  Uppercase things where needed */
  20. /* ckzmac.c, Thu Apr 21 17:19, Edit by Bill */
  21. /*  Ignore trying to close an not-openend file, driver does it alot */
  22. /* ckzmac.c, Thu Apr 11 21:18, Edit by Bill */
  23. /*  Catch error in ZOPENO when trying to open an existing file */
  24. /* ckzmac.c, Thu Apr 14 20:07, Edit by Bill */
  25. /*  Translate calls with ZCTERM to go to the console routines */
  26.  
  27. /*
  28.  * File ckmfio  --  Kermit file system support for the Macintosh
  29.  *
  30.  * Copyright (C) 1985, Trustees of Columbia University in the City of
  31.  * New York.  Permission is granted to any individual or institution to
  32.  * use, copy, or redistribute this software so long as it is not sold
  33.  * for profit, provided this copyright notice is retained.
  34.  *
  35.  */
  36.  
  37. /* Definitions of some Unix system commands */
  38.  
  39. #define DIRCMDSTR "ls"
  40. #define DELCMDSTR "rm"
  41. #define SPCCMDSTR "sp"
  42.  
  43. char *DIRCMD = DIRCMDSTR;    /* For directory listing */
  44. char *DELCMD = DELCMDSTR;    /* For file deletion */
  45. char *SPACMD = SPCCMDSTR;    /* Space for all available volumes */
  46. char *TYPCMD = "";        /* For typing a file */
  47. char *SPACM2 = "";        /* For space in specified directory */
  48. char *WHOCMD = "";        /* For seeing who's logged in */
  49.  
  50. /*
  51.   Functions (n is one of the predefined file numbers from ckermi.h):
  52.  
  53.    zopeni(n,name)   -- Opens an existing file for input.
  54.    zopeno(n,name)   -- Opens a new file for output.
  55.    zclose(n)        -- Closes a file.
  56.    zchin(n)         -- Gets the next character from an input file.
  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.  */
  72.  
  73. #include "ckcdeb.h"        /* Debug() and tlog() defs */
  74. #include "ckcker.h"        /* Kermit definitions */
  75.  
  76. #define    __SEG__ ckmfio
  77. #include <ctype.h>
  78. #include <files.h>
  79. #include <errors.h>
  80. #include <devices.h>
  81. #include <packages.h>
  82. #include <osutils.h>
  83. #include <toolutils.h>
  84. #include <events.h>        /* needed for ckmasm.h */
  85.  
  86. #include "ckmdef.h"        /* Common Mac module definitions */
  87. #include "ckmres.h"        /* Resource defs */
  88. #include "ckmasm.h"        /* Assembler code */
  89.  
  90. /* These should all be settable by the File Settings Menu */
  91.  
  92. OSType authortext = 'MACA';    /* set creator to "MacWrite" */
  93.  
  94. #define FS_WIND 1        /* file is a text edit buffer */
  95. #define FS_OPEN 2        /* file has been opened */
  96. #define FS_RSRC 4        /* opened in resource fork */
  97. #define FS_DATA 8
  98. #define FS_PIPE 16        /* file is a memory buffer */
  99.  
  100. #define PIPESIZE 128
  101. typedef struct {
  102.     int charsleft;        /* nuber of unread characters in the buffer */
  103.     ProcPtr refill;        /* pointer to the refill procedure */
  104.     char *currptr;        /* characters left before next pipe refill */
  105.     char pipebuf[PIPESIZE];    /* buffer to keep the pipes content */
  106. }   MACPIPE;
  107.  
  108. typedef struct {
  109.     short frefnum;        /* file reference number (pascal) */
  110.     int fstatus;        /* file status bits */
  111.     MACPIPE *fpipe;        /* pointer to a pipe */
  112. }   MACFILE;
  113.  
  114. MACFILE fp[ZNFILS] = {        /* File information */
  115.     {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}
  116. };
  117.  
  118.  
  119.  
  120. /****************************************************************************/
  121. /*  Z O P E N I --  Open an existing file for input.
  122.  *
  123.  * The file name has been returned from and the volume reference
  124.  * number set by SFGetFile.
  125.  *
  126.  * Returns:
  127.  *  TRUE: file opened ok
  128.  *  FALSE: some error.
  129.  */
  130. /****************************************************************************/
  131. zopeni (n, name)
  132. int n;
  133. char *name;
  134. {
  135.     int err;
  136.     register MACFILE *fpp;
  137.  
  138.     if (chkfn (n)) {
  139.     printerr ("At zopeni file is already open ", n);
  140.     return (FALSE);
  141.     }
  142.     fpp = &fp[n];
  143.  
  144.     if (n == ZCTERM) {        /* Terminal open? */
  145.     if (chkfn (ZIFILE))    /* Check current ZOFILE */
  146.         printerr ("ZIFILE already open...: ", n);
  147.     fp[ZIFILE].fstatus = FS_WIND;    /* redirect... here it is */
  148.     fpp->fstatus = FS_WIND;    /* Indicate this is open too */
  149.     return (conopen ());    /* Return from low level open */
  150.     }
  151.     if (n == ZSYSFN)        /* trying to open a pipe? */
  152.     return (zxcmd (name));    /* yes... */
  153.  
  154.     if (n == ZIFILE &&        /* opening input file? */
  155.     (filargs.filflg & FIL_RSRC))    /* and they said resource? */
  156.     err = OpenRF (name, filargs.filvol, &fpp->frefnum);
  157.     else            /* else some other channel or data */
  158.     err = FSOpen (name, filargs.filvol, &fpp->frefnum);
  159.  
  160.     if (err != noErr)        /* check for open error */
  161.     return (ioutil (err));    /* failed... */
  162.  
  163.     fpp->fstatus = FS_OPEN | (    /* set flags */
  164.                (filargs.filflg & FIL_RSRC) ? FS_RSRC : FS_DATA);
  165.  
  166.     GetEOF (fpp->frefnum, &filargs.filsiz);    /* set size for screen */
  167.     return (TRUE);        /* Return success */
  168. }                /* zopeni */
  169.  
  170.  
  171.  
  172. /****************************************************************************/
  173. /*  Z O P E N O  --  Open a new file for output.
  174.  *
  175.  * Returns:
  176.  *  TRUE: File opened ok
  177.  *  FALSE: some error has occured or channel occupied.
  178.  *
  179.  */
  180. /****************************************************************************/
  181. zopeno (n, name)
  182. int n;
  183. char *name;
  184. {
  185.     OSType forktext;
  186.     int err;
  187.     FInfo finfo;
  188.     register MACFILE *fpp;
  189.  
  190.     if (chkfn (n)) {
  191.     printerr ("zopeno - file is already open: ", n);
  192.     return (FALSE);
  193.     }
  194.     fpp = &fp[n];
  195.  
  196.     if (n == ZCTERM || n == ZSTDIO) {    /* Terminal open? */
  197.     if (chkfn (ZOFILE))    /* Check current ZOFILE */
  198.         printerr ("ZOFILE already open...: ", n);
  199.     fp[ZOFILE].fstatus = FS_WIND;    /* yes, redirect... here it is */
  200.     fpp->fstatus = FS_WIND;    /* Indicate this is open too */
  201.     return (conopen ());    /* Return from low level open */
  202.     }
  203.     if (n == ZOFILE && (filargs.filflg & FIL_RSRC))
  204.     forktext = 'APPL';
  205.     else
  206.     forktext = 'TEXT';    /* Make fork reflect fork choice */
  207.  
  208.     err = Create (name, filargs.filvol, authortext, forktext);
  209.     if (err == dupFNErr) {    /* duplicate file? */
  210.     if (!ioutil (FSDelete (name,    /* Try to delete it */
  211.                    filargs.filvol)))    /* checking for failure */
  212.         return (FALSE);    /* failed... */
  213.     err = Create (name, filargs.filvol,    /* recreate */
  214.               authortext, forktext);
  215.     }
  216.     if (err != noErr)        /* some error? */
  217.     return (ioutil (err));    /* yes, do message and return */
  218.  
  219. /* set file's folder from filargs.filfldr which is either the */
  220. /* applications folder or the settings file folder */
  221.  
  222.     GetFInfo (name, filargs.filvol, &finfo);    /* read current finder info */
  223.     finfo.fdFldr = filargs.filfldr;    /* set new folder */
  224.     SetFInfo (name, filargs.filvol, &finfo);    /* and tell system about it */
  225.  
  226.     if (n == ZOFILE &&        /* is it our transferred file? */
  227.     (filargs.filflg & FIL_RSRC))    /* want to use resource fork?  */
  228.     err = OpenRF (name, filargs.filvol,    /* yes... */
  229.               &fpp->frefnum);
  230.     else            /* else data, or some other file */
  231.     err = FSOpen (name, filargs.filvol, &fpp->frefnum);
  232.  
  233.     if (err != noErr)        /* able to open? */
  234.     return (ioutil (err));    /* no. fail return now */
  235.  
  236.     fp[n].fstatus = FS_OPEN |
  237.     ((filargs.filflg & FIL_RSRC) ? FS_RSRC : FS_DATA);
  238.  
  239.     return (TRUE);        /* done ok */
  240. }                /* zopeno */
  241.  
  242.  
  243.  
  244. /****************************************************************************/
  245. /*  Z C L O S E  --  Close the given file.
  246.  *
  247.  * Returns:
  248.  *  TRUE: file closed ok.
  249.  *  FLASE: some error has occured.
  250.  *
  251.  */
  252. /****************************************************************************/
  253. zclose (n)
  254. int n;
  255. {
  256.     int err = noErr;
  257.     register MACFILE *fpp;
  258.  
  259.     if (!chkfn (n))        /* is it opened? */
  260.     return (FALSE);        /* no return now */
  261.  
  262.     fpp = &fp[n];
  263.  
  264.     if (fpp->fstatus == FS_WIND)/* is this a window? */
  265.     fp[ZCTERM].fstatus = 0;    /* yes, clear ZCTERM */
  266.     else if (fpp->fstatus == FS_PIPE)    /* is this a pipe? */
  267.     fp[ZSYSFN].fstatus = 0;    /* yes, no pipe now, clear ZSYSFN */
  268.     else {
  269.     err = FSClose (fpp->frefnum);    /* else use OS close */
  270.     if (err == noErr)    /* and if that worked */
  271.         /* i PWP: the above if should be ==, NOT != !!!!! */
  272.         err = FlushVol (NILPTR,    /* flush buffers in case write worked */
  273.                 filargs.filvol);
  274.     }
  275.  
  276.     fpp->fstatus = 0;        /* clear out status word */
  277.     if (n == ZOFILE || n == ZIFILE)    /* turn off both flags */
  278.     filargs.filflg &= ~(FIL_RSRC | FIL_DATA);
  279.  
  280.     return (ioutil (err));    /* return according to io operations */
  281. }                /* zclose */
  282.  
  283.  
  284.  
  285. /****************************************************************************/
  286. /*  Z C H I N  --  Get a character from the input file.
  287.  *
  288.  * Returns:
  289.  *  0: Ok
  290.  * -1: EOF (or other error).
  291.  *
  292.  */
  293. /****************************************************************************/
  294. zchin (n, c)
  295. int n;
  296. char *c;
  297. {
  298.     int err;
  299.     long rdcnt;            /* pascal long */
  300.     register MACFILE *fpp;
  301.     register MACPIPE *pipe;
  302.  
  303.     if (!chkfn (n))
  304.     return (0);
  305.  
  306.     fpp = &fp[n];
  307.  
  308.     if (fpp->fstatus == FS_WIND) {    /* a window? */
  309.     printerr ("zchin called for FS_WIND file: ", n);
  310.     return (0);
  311.     }
  312.     if (fpp->fstatus == FS_PIPE) {    /* a pipe? */
  313.     pipe = fpp->fpipe;
  314.  
  315.     if (pipe->charsleft <= 0) {    /* test for characters left */
  316.         pipe->currptr = pipe->pipebuf;    /* restart at the beginning
  317.                          * of the buffer */
  318.  
  319.         if (pipe->refill != NILPROC) {    /* refill the pipe if
  320.                          * possible */
  321.         saveA0 ();    /* push content of A0 to stack */
  322.         loadA0 (*(pipe->refill));    /* load the content of refill
  323.                          * to A0 */
  324.         execute ();    /* call the refill procedure */
  325.         restoreA0 ();    /* get A0 back from the stack */
  326.         } else
  327.         *(pipe->currptr) = '\0';    /* make it end otherwise */
  328.     }
  329.     if (*(pipe->currptr) == '\0')    /* is this eo-pipe? */
  330.         return (-1);    /* yes, fail return */
  331.  
  332.     *c = *(pipe->currptr)++;/* read character */
  333.     (pipe->charsleft)--;    /* decrement characters left */
  334.  
  335.     return (0);        /* success */
  336.     }
  337.     rdcnt = 1;
  338.     err = FSRead (fpp->frefnum, &rdcnt, c);
  339.     if (err == eofErr)
  340.     return (-1);        /* Failure return */
  341.     return (ioutil (err) ? 0 : -1);    /* success or unknown failure */
  342. }                /* zchin */
  343.  
  344.  
  345.  
  346. /****************************************************************************/
  347. /*  Z S O U T  --  Write a string to the given file, buffered.
  348.  *
  349.  * Returns:
  350.  *  0: OK
  351.  * -1: Error
  352.  *
  353.  */
  354. /****************************************************************************/
  355. zsout (n, s)
  356. int n;
  357. char *s;
  358. {
  359.     long wrcnt;            /* pascal long */
  360.  
  361.     if (n == ZCTERM || fp[n].fstatus == FS_WIND)
  362.     return (conol (s));
  363.  
  364.     wrcnt = (long) strlen (s);
  365.     return (ioutil (FSWrite (fp[n].frefnum, &wrcnt, s)) ? 0 : -1);
  366. }                /* zsout */
  367.  
  368.  
  369.  
  370. /****************************************************************************/
  371. /*  Z S O U T L  --  Write string to file, with line terminator, buffered.
  372.  *
  373.  * Returns:
  374.  *  0: OK
  375.  * -1: Error
  376.  *
  377.  */
  378. /****************************************************************************/
  379. zsoutl (n, s)
  380. int n;
  381. char *s;
  382. {
  383.     long wrcnt;            /* pascal long */
  384.     int err;
  385.  
  386.     if (n == ZCTERM || fp[n].fstatus == FS_WIND)
  387.     return (conoll (s));
  388.  
  389.     wrcnt = (long) strlen (s);
  390.     err = FSWrite (fp[n].frefnum, &wrcnt, s);
  391.     if (err == noErr) {
  392.     wrcnt = 2;
  393.     err = FSWrite (fp[n].frefnum, &wrcnt, "\r\n");
  394.     }
  395.     return (ioutil (err) ? 0 : -1);
  396. }                /* zsoutl */
  397.  
  398.  
  399.  
  400. /****************************************************************************/
  401. /*  Z S O U T X  --  Write x characters to file, unbuffered.
  402.  *
  403.  * Returns:
  404.  *  0: OK
  405.  * -1: Error
  406.  */
  407. /****************************************************************************/
  408. zsoutx (n, s, x)
  409. int n, x;
  410. char *s;
  411. {
  412.     long size;
  413.  
  414.     if (n == ZCTERM || fp[n].fstatus == FS_WIND)
  415.     return (conxo (s, x));
  416.  
  417.     size = x;
  418.     return (ioutil (FSWrite (fp[n].frefnum, &size, s)) ? 0 : -1);
  419. }                /* zsoutx */
  420.  
  421.  
  422.  
  423. /****************************************************************************/
  424. /*  Z C H O U T  --  Add a character to the given file. */
  425. /*                        */
  426. /* Returns:        */
  427. /*  0: OK            */
  428. /* -1: Error    */
  429. /****************************************************************************/
  430. zchout (n, c)
  431. int n;
  432. char c;
  433. {
  434.     long wrcnt;            /* pascal long */
  435.     int err;
  436.  
  437.     if (n == ZCTERM || fp[n].fstatus == FS_WIND) {
  438.     conoc (c);        /* Then send to console routine */
  439.     return (0);        /* Then send to console routine */
  440.     }
  441.     wrcnt = 1;
  442.     err = FSWrite (fp[n].frefnum, &wrcnt, &c);
  443.     if (err != noErr)        /* error occured? */
  444.     sstate = 'a';        /* yes, abort protocol */
  445.     return (ioutil (err) ? 0 : -1);    /* else return code */
  446. }                /* zchout */
  447.  
  448.  
  449.  
  450. /****************************************************************************/
  451. /*  C H K F N  --  Internal function to verify file number is ok.
  452.  *
  453.  * Returns:
  454.  *   TRUE  - file is open
  455.  *  FALSE  - file is not open
  456.  *
  457.  * Issues an error message if the file number is not in range.
  458.  *
  459.  */
  460. /****************************************************************************/
  461. chkfn (n)
  462. int n;
  463. {
  464.     switch (n) {
  465.       case ZCTERM:
  466.       case ZSTDIO:
  467.       case ZIFILE:
  468.       case ZOFILE:
  469.       case ZDFILE:
  470.       case ZTFILE:
  471.       case ZPFILE:
  472.       case ZSYSFN:
  473.       case ZSFILE:
  474.     break;
  475.       default:
  476.     debug (F101, "chkfn: file number out of range", "", n);
  477.     printerr ("chkfn - file number not in range: ", n);
  478.     return (FALSE);        /* ugh */
  479.     }
  480.     return ((fp[n].fstatus != 0));    /* if open, fstatus is nonzero */
  481. }                /* chkfn */
  482.  
  483.  
  484.  
  485. /****************************************************************************/
  486. /*  Z C H K I  --  Check if input file exists and is readable.
  487.  *
  488.  * Returns:
  489.  *  >= 0 if the file can be read (returns the size).
  490.  *    -1 if file doesn't exist or can't be accessed,
  491.  *    -2 if file exists but is not readable (e.g. a directory file).
  492.  *    -3 if file exists but protected against read access.
  493.  */
  494. /****************************************************************************/
  495. long
  496. zchki (name)
  497. char *name;
  498. {
  499.     long size;
  500.     int err;
  501.     FileParam info;
  502.  
  503.     if (strcmp (name, "stdin") == 0)    /* stdin is a pipe */
  504.     return (PIPESIZE);    /* return size of buffer */
  505.  
  506.     c2pstr (name);        /* convert to a pascal string */
  507.     info.ioFVersNum = 0;    /* No version number */
  508.     info.ioFDirIndex = 0;    /* Use the file name */
  509.     info.ioNamePtr = name;    /* Point to the file name */
  510.     info.ioVRefNum = filargs.filvol;    /* Volume number */
  511.     err = PBGetFInfo (&info, FALSE);    /* Get info on file */
  512.     p2cstr (name);        /* put the name back */
  513.  
  514.     if (err == fnfErr)        /* file not found? */
  515.     return (-1);        /* then that is what they want */
  516.  
  517.     if (err != noErr) {        /* any other error? */
  518.     printerr ("zchki failed: ", err);    /* tell me about it */
  519.     return (-1);
  520.     }
  521.     size = (filargs.filflg & FIL_RSRC) ?    /* if thinking about RSRC */
  522.     info.ioFlRPyLen :    /* return that size, */
  523.     info.ioFlPyLen;        /* else DATA */
  524.     return (size);        /* did ok */
  525. }                /* zchki */
  526.  
  527.  
  528.  
  529. /****************************************************************************/
  530. /*  Z C H K O  --  Check if output file can be created.
  531.  *
  532.  * Returns
  533.  *  0: Write OK
  534.  * -1: write permission for the file should be denied.
  535.  */
  536. /****************************************************************************/
  537. zchko (name)
  538. char *name;
  539. {
  540.     char volname[100];
  541.     VolumeParam info;
  542.  
  543.     info.ioVolIndex = 0;    /* Use the vol ref num only */
  544.     info.ioNamePtr = volname;    /* Pointer to the volume name */
  545.     info.ioVRefNum = filargs.filvol;    /* Volume reference number */
  546.     if (!ioutil (PBGetVInfo (&info, 0)))    /* Get info on vol,
  547.                          * synchronously */
  548.     return (-1);        /* failed... */
  549.  
  550.     if ((info.ioVAtrb & 0x8000) != 0)    /* Write locked? */
  551.     return (-1);        /* yes... */
  552.  
  553.     return (0);            /* else success */
  554. }                /* zchko */
  555.  
  556.  
  557.  
  558. /****************************************************************************/
  559. /*  Z D E L E T  --  Delete the named file and return TRUE if successful */
  560. /****************************************************************************/
  561. zdelet (name)
  562. char *name;
  563. {
  564.     return (ioutil (FSDelete (name, filargs.filvol)));
  565. }                /* zdelet */
  566.  
  567.  
  568.  
  569. /****************************************************************************/
  570. /*  Z R T O L  --  Convert remote filename into local form.
  571.  *
  572.  * Check here to see if this should go into the resource fork (.rsrc)
  573.  * or into the data fork (.data).
  574.  *
  575.  */
  576. /****************************************************************************/
  577. zrtol (name, name2)
  578. char *name, *name2;
  579. {
  580.  
  581.     strcpy (name2, name);    /* copy name to destination */
  582.  
  583.     if (filargs.filflg & (FIL_DODLG))    /* selected by user? */
  584.     return;            /* won't be called but... */
  585.  
  586.     filargs.filflg &= ~(FIL_RBDT);    /* clear out flags */
  587.     filargs.filflg |= sfprtol (name2);    /* convert name2 and set flags */
  588.     binary = (filargs.filflg & FIL_BINA);    /* selected binary mode? */
  589.     return;
  590. }                /* zrtol */
  591.  
  592.  
  593.  
  594. /****************************************************************************/
  595. /*  Z L T O R  --  Convert filename from local format to common form. */
  596. /****************************************************************************/
  597. zltor (name, name2)
  598. char *name, *name2;
  599. {
  600.     int dc = 0;
  601.  
  602.     while (*name != '\0') {
  603.     if (*name == ' ')
  604.         name++;        /* Skip spaces */
  605.     else if ((*name == '.') && (++dc > 1)) {
  606.         *name2++ = 'X';    /* Just 1 dot */
  607.         name++;
  608.     } else
  609.         *name2++ = (islower (*name)) ? toupper (*name++) : *name++;
  610.     }
  611.     *name2++ = '\0';        /* deposit final null */
  612.     return;
  613. }                /* zltor */
  614.  
  615.  
  616.  
  617. /****************************************************************************/
  618. /*  Z C H D I R  --  Change directory or volumes */
  619. /****************************************************************************/
  620. zchdir (dirnam)
  621. char *dirnam;
  622. {
  623.     int err;
  624.     int volnum;
  625.     WDPBRec vinfo;
  626.     short *FSFCBLen = 0x3F6;
  627.  
  628.     if (*FSFCBLen < 0) {    /* if no HFS ROM's */
  629.     err = SetVol (dirnam, 0);
  630.     volnum = 0;
  631.     } else {            /* use HFS calls */
  632.     c2pstr (dirnam);
  633.     vinfo.ioVRefNum = 0;    /* open a workimg directory */
  634.     vinfo.ioWDDirID = 0;
  635.     vinfo.ioWDProcID = 'ERIK';
  636.     vinfo.ioNamePtr = dirnam;
  637.     err = PBOpenWD (&vinfo, FALSE);
  638.     p2cstr (dirnam);
  639.     if (err != noErr)
  640.         return (FALSE);
  641.  
  642.     err = SetVol (NIL, vinfo.ioVRefNum);
  643.     volnum = vinfo.ioVRefNum;
  644.     }
  645.  
  646.     if (err == noErr) {        /* set default volume */
  647.     screen (SCR_TN, 0, 0l, dirnam);
  648.     filargs.filvol = volnum;/* make default */
  649.     } else
  650.     screen (SCR_TN, 0, 0l, "Can't set directory");
  651.  
  652.     return (err == noErr);    /* return ok or fail */
  653. }                /* zchdir */
  654.  
  655. /****************************************************************************/
  656. /*  Z G T D I R  --  Get name of current directory or volume */
  657. /****************************************************************************/
  658. char *
  659. zgtdir ()
  660. {
  661.     return("(unknown)");
  662. }
  663.  
  664. /****************************************************************************/
  665. /* initialize the fields of a pipe */
  666. /****************************************************************************/
  667. zinitpipe (pipe, refillproc)
  668. MACPIPE *pipe;
  669. ProcPtr refillproc;
  670. {
  671.     pipe->refill = refillproc;
  672.     pipe->currptr = pipe->pipebuf;
  673.     pipe->charsleft = 0;
  674.     *(pipe->currptr) = '\0';
  675. }                /* zinitpipe */
  676.  
  677.  
  678.  
  679. /****************************************************************************/
  680. /* fill the pipe; last is TRUE if it is the */
  681. /* last time the pipe has to be filled  */
  682. /****************************************************************************/
  683. zfillpipe (pipe, str, last)
  684. MACPIPE *pipe;
  685. char *str;
  686. Boolean last;
  687. {
  688.     int len;
  689.  
  690.     len = strlen (str);
  691.     if (last)
  692.     len++;
  693.  
  694.     if (len > PIPESIZE) {
  695.     len = PIPESIZE;
  696.     if (last)
  697.         str[PIPESIZE - 1] = '\0';    /* make sure we keep the eop
  698.                      * character */
  699.     printerr ("pipe overflow! characters may be lost");
  700.     }
  701.     memcpy (pipe->pipebuf, str, len);
  702.     pipe->charsleft = len;
  703. }                /* zfillpipe */
  704.  
  705.  
  706.  
  707. /****************************************************************************/
  708. /* sprintf uses 12 kByte. This is the reason to use a simpler formatter here */
  709. /* formatnum returns a right adjusted numberstring padded with fillc */
  710. /* Numbers which do not fit into width are truncated on the left. */
  711. /* Make sure str is at least 'width+1' bytes wide */
  712. /****************************************************************************/
  713. formatnum (num, fillc, width, str)
  714. char *str;
  715. long num;
  716. char fillc;
  717. int width;
  718. {
  719.     int i;
  720.     char numstr[12];        /* -2147483647 is the longest string */
  721.     /* that can be returned from NumToString */
  722.  
  723.     NumToString (num, numstr);
  724.     i = strlen (numstr);
  725.  
  726.     while ((i >= 0) && (width >= 0))
  727.     str[width--] = numstr[i--];
  728.  
  729.     while (width >= 0)
  730.     str[width--] = fillc;
  731. }                /* formatnum */
  732.  
  733.  
  734.  
  735. MACPIPE cmdpipe;
  736.  
  737. int volindex;
  738. char spaceheader[60] = "\
  739. Free      Name\n\
  740. --------- --------------------\n";
  741.  
  742. /****************************************************************************/
  743. /* loop through all available volumes and display the space left */
  744. /****************************************************************************/
  745. zlspace ()
  746. {
  747.     int err;
  748.     Str255 name;
  749.     long free;
  750.     char outstr[60];
  751.     VolumeParam vinfo;
  752.  
  753.     name.length = 0;
  754.     vinfo.ioVolIndex = volindex;
  755.     vinfo.ioNamePtr = &name;
  756.     err = PBGetVInfo (&vinfo, FALSE);
  757.  
  758.     if (err == noErr) {
  759.     free = vinfo.ioVFrBlk * vinfo.ioVAlBlkSiz;
  760.     formatnum (free, ' ', 9, outstr);
  761.     strcat (outstr, " ");
  762.     p2cstr (&name);
  763.     strcat (outstr, &name);
  764.     strcat (outstr, "\n");
  765.     zfillpipe (&cmdpipe, outstr, FALSE);
  766.     volindex++;
  767.     } else
  768.     zfillpipe (&cmdpipe, "", TRUE);
  769.  
  770. }                /* zlspace */
  771.  
  772.  
  773.  
  774. int fileindex;
  775. char dirheader[100] = "\
  776. Size    Type Crea Last Modification Name\n\
  777. ------- ---- ---- ----------------- --------------------\n";
  778.  
  779. /****************************************************************************/
  780. /* loop through all the files on the current volume / directory */
  781. /****************************************************************************/
  782. zldir ()
  783. {
  784.     int err;
  785.     CInfoPBRec info;
  786.     WDPBRec vinfo;
  787.  
  788.     Str255 name;
  789.     DateTimeRec dtrec;
  790.  
  791.     char outstr[60];
  792.     char type[10];
  793.     char tmpstr[11];
  794.     char datestr[11];
  795.     char hourstr[3];
  796.     char minutestr[3];
  797.  
  798.     unsigned long secs;
  799.     long size;
  800.  
  801.     short *FSFCBLen = 0x3F6;
  802.  
  803.     if (*FSFCBLen < 0) {
  804.     errpkt ("Sorry, the server uses 64 kByte ROM's");
  805.     zfillpipe (&cmdpipe, "", TRUE);
  806.     return;
  807.     }
  808.     PBHGetVol (&vinfo, FALSE);
  809.  
  810.     /* loop through all the files starting at the first one */
  811.     name.length = 0;
  812.     info.hfileInfo.ioFDirIndex = fileindex;    /* Get next file name */
  813.     info.hfileInfo.ioNamePtr = &name;    /* Point to the empty file name */
  814.     info.hfileInfo.ioVRefNum = vinfo.ioWDVRefNum;    /* Directory / Volume
  815.                              * number */
  816.     info.hfileInfo.ioDirID = vinfo.ioWDDirID;    /* Directory / Volume number */
  817.     err = PBGetCatInfo (&info, FALSE);    /* Get info on file */
  818.  
  819.     if (err == noErr) {
  820.     if (info.hfileInfo.ioFlAttrib & ioDirMask) {    /* a directory if it's
  821.                              * true */
  822.         secs = info.dirInfo.ioDrMdDat;
  823.         strcpy (type, "#########");
  824.         strcpy (outstr, "       ");
  825.     } else {        /* a file otherwise */
  826.         secs = info.hfileInfo.ioFlMdDat;
  827.         size = info.hfileInfo.ioFlLgLen + info.hfileInfo.ioFlRLgLen;
  828.         strcpy (type, "         ");
  829.         memcpy (type, &info.hfileInfo.ioFlFndrInfo.fdType, 4);
  830.         memcpy (type + 5, &info.hfileInfo.ioFlFndrInfo.fdCreator, 4);
  831.         formatnum (size, ' ', 7, outstr);
  832.     }
  833.     IUDateString (secs, shortDate, tmpstr);
  834.     strcpy (datestr, "   ");
  835.     datestr[10 - strlen (tmpstr)] = '\0';
  836.     strcat (datestr, tmpstr);
  837.  
  838.     Secs2Date (secs, &dtrec);
  839.     formatnum (dtrec.hour, ' ', 2, hourstr);
  840.     formatnum (dtrec.minute, '0', 2, minutestr);
  841.  
  842.     p2cstr (&name);
  843.  
  844.     strcat (outstr, " ");
  845.     strcat (outstr, type);
  846.     strcat (outstr, " ");
  847.     strcat (outstr, datestr);
  848.     strcat (outstr, " ");
  849.     strcat (outstr, hourstr);
  850.     strcat (outstr, ":");
  851.     strcat (outstr, minutestr);
  852.     strcat (outstr, "  ");
  853.     strcat (outstr, &name);
  854.     strcat (outstr, "\n");
  855.  
  856.     zfillpipe (&cmdpipe, outstr, FALSE);
  857.     fileindex++;
  858.     } else
  859.     zfillpipe (&cmdpipe, "", TRUE);
  860.  
  861. }                /* zldir */
  862.  
  863.  
  864.  
  865. #define CMD_RSRC    1
  866. #define CMD_DATA    2
  867. #define CMD_TEXT    3
  868. #define CMD_BINA    4
  869. #define CMD_DIR        5
  870. #define CMD_DEL        6
  871. #define CMD_SPC        7
  872. #define CMD_UNK 255
  873.  
  874. char *cmdtab[] = {
  875.     "fork rsrc",
  876.     "fork data",
  877.     "mode binary",
  878.     "mode text",
  879.     DIRCMDSTR,
  880.     DELCMDSTR,
  881.     SPCCMDSTR
  882. };
  883.  
  884. int toktab[] = {
  885.     CMD_RSRC,
  886.     CMD_DATA,
  887.     CMD_BINA,
  888.     CMD_TEXT,
  889.     CMD_DIR,
  890.     CMD_DEL,
  891.     CMD_SPC
  892. };
  893.  
  894. #define NTOKS (sizeof (toktab)/sizeof(int))
  895.  
  896. /****************************************************************************/
  897. /*  Z X C M D -- Run a system command so its output can be read like a file.
  898.  *
  899.  * Used on the MAC to implement MAC settings commands -- commands from a
  900.  * remote system when in server mode that change internal variables.
  901.  *
  902.  */
  903. /****************************************************************************/
  904. int
  905. zxcmd (comand)
  906. char *comand;
  907. {
  908.     int sc;
  909.     char theStr[120];
  910.     int retCd;
  911.  
  912.     fp[ZIFILE].fstatus = FS_PIPE;    /* set input from pipe */
  913.     fp[ZIFILE].fpipe = &cmdpipe;/* init pointer to command pipe */
  914.  
  915.     switch (sc = getcmd (comand)) {
  916.       case CMD_RSRC:
  917.       case CMD_DATA:
  918.     zinitpipe (&cmdpipe, NILPROC);
  919.     zfillpipe (&cmdpipe, "Default Fork set OK\n", TRUE);
  920.     filargs.filflg &= ~(FIL_RSRC | FIL_DATA);    /* turn off  */
  921.     filargs.filflg |= (sc == CMD_RSRC) ? FIL_RSRC : FIL_DATA;
  922.     return (TRUE);        /* ok */
  923.  
  924.       case CMD_TEXT:
  925.       case CMD_BINA:
  926.     zinitpipe (&cmdpipe, NILPROC);
  927.     zfillpipe (&cmdpipe, "Default Mode set OK\n", TRUE);
  928.     filargs.filflg &= ~(FIL_TEXT | FIL_BINA);
  929.     filargs.filflg |= (sc == CMD_BINA) ? FIL_BINA : FIL_TEXT;
  930.     return (TRUE);        /* ok */
  931.  
  932.       case CMD_DIR:
  933.     zinitpipe (&cmdpipe, zldir);
  934.     zfillpipe (&cmdpipe, dirheader, FALSE);
  935.     fileindex = 1;        /* start at the first file on */
  936.     /* the current volume / directory */
  937.     return (TRUE);        /* always ok */
  938.  
  939.       case CMD_DEL:
  940.     strcpy (theStr, comand + strlen (DELCMDSTR));    /* the filename
  941.                              * immediately  */
  942.     retCd = zdelet (theStr);/* follows the command name */
  943.     if (retCd) {
  944.         zinitpipe (&cmdpipe, NILPROC);
  945.         strcat (theStr, " deleted.");
  946.         zfillpipe (&cmdpipe, theStr, true);
  947.     }
  948.     return (retCd);
  949.  
  950.       case CMD_SPC:
  951.     zinitpipe (&cmdpipe, zlspace);    /* init pipe for space listing */
  952.     zfillpipe (&cmdpipe, spaceheader, FALSE);    /* copy the header to
  953.                              * the pipe */
  954.     volindex = 1;        /* start with the first volume */
  955.     return (TRUE);        /* always ok */
  956.  
  957.       default:
  958.     return (FALSE);        /* fail, unknown */
  959.     }
  960. }                /* zxcmd */
  961.  
  962.  
  963.  
  964. /****************************************************************************/
  965. /****************************************************************************/
  966. getcmd (cmd)
  967. char *cmd;
  968. {
  969.     int k;
  970.  
  971.     for (k = 0; k < NTOKS; k++)
  972.     if (strncmp (cmdtab[k], cmd, strlen (cmdtab[k])) == 0)
  973.         return (toktab[k]);    /* and return ID */
  974.     return (CMD_UNK);        /* else unknown */
  975.  
  976. }                /* getcmd */
  977.  
  978.  
  979.  
  980. /****************************************************************************/
  981. /*  Z C L O S F  - wait for the child fork to terminate and close the pipe. */
  982. /****************************************************************************/
  983. zclosf ()
  984. {
  985.     return;
  986. }                /* zclosf */
  987.  
  988.  
  989.  
  990. int zindex;
  991. int zfiles;
  992. char *zname;
  993.  
  994. /****************************************************************************/
  995. /*  Z X P A N D  --  Expand a wildcard string into an array of strings
  996.  *
  997.  * Returns the number of files that match fn, with data structures set up
  998.  * so that first file (if any) will be returned by the next znext() call.
  999.  */
  1000. /****************************************************************************/
  1001. zxpand (fn)
  1002. char *fn;
  1003. {
  1004.     int err;
  1005.     FileParam info;
  1006.  
  1007.     zfiles = 1;
  1008.  
  1009.     if ((filargs.filflg & FIL_ALLFL) ||    /* all files check box on or */
  1010.     (strcmp (fn, ":") == 0)) {    /* server 'get' with filname = ':' */
  1011.  
  1012.     /* the ioVNmFls field of the VolumeParam returns the number of files */
  1013.  
  1014.     /*
  1015.      * !and! directories after PBGetInfo. This is why we have to count
  1016.      * here.
  1017.      */
  1018.  
  1019.     info.ioFVersNum = 0;    /* No version number */
  1020.     info.ioNamePtr = NIL;    /* Point to the file name */
  1021.     info.ioVRefNum = filargs.filvol;    /* Volume number */
  1022.     do {
  1023.         info.ioFDirIndex = zfiles;    /* Get next file name */
  1024.         err = PBGetFInfo (&info, FALSE);    /* Get info on file */
  1025.         zfiles++;
  1026.     } while (err == noErr);
  1027.     zname = NIL;        /* no specific file */
  1028.     zfiles -= 2;        /* we counted 2 too high */
  1029.  
  1030.     } else
  1031.     zname = fn;        /* keep a pointer to that name */
  1032.  
  1033.     zindex = 0;            /* init the files sent counter */
  1034.     return (zfiles);
  1035. }                /* zxpand */
  1036.  
  1037.  
  1038.  
  1039. /****************************************************************************/
  1040. /*  Z N E X T  --  Get name of next file from list created by zxpand().
  1041.  *
  1042.  * Returns >0 if there's another file, with its name copied into the
  1043.  * arg string, or 0 if no more files in list.
  1044.  */
  1045. /****************************************************************************/
  1046. znext (fn)
  1047. char *fn;
  1048. {
  1049.     int err;
  1050.     Str255 name;
  1051.     FileParam info;
  1052.  
  1053.     zindex++;            /* next file */
  1054.  
  1055.     if (zindex > zfiles)
  1056.     return (0);        /* no more files */
  1057.  
  1058.     if (zname != NIL)
  1059.     strcpy (fn, zname);    /* Get the file's name */
  1060.     else {
  1061.     info.ioFVersNum = 0;    /* No version number */
  1062.     info.ioFDirIndex = zindex;    /* Get next file name */
  1063.     info.ioNamePtr = &name;    /* Point to the file name */
  1064.     info.ioVRefNum = filargs.filvol;    /* VolRefNum of the selected
  1065.                          * folder */
  1066.     err = PBGetFInfo (&info, FALSE);    /* Get info on file */
  1067.     if (err == noErr) {
  1068.         p2cstr (&name);
  1069.         strcpy (fn, &name);    /* Return the file's name */
  1070.         *filargs.filrem = '\0';    /* reset remote name for folder
  1071.                      * transfer */
  1072.     } else {
  1073.         printerr ("Error on reading next file name: ", err);
  1074.         return (0);
  1075.     }
  1076.     }
  1077.     return (1);            /* fn contains the next file */
  1078. }                /* znext */
  1079.  
  1080.  
  1081.  
  1082. /****************************************************************************/
  1083. /*  Z N E W N  --  Make a new name for the given file  */
  1084. /****************************************************************************/
  1085. znewn (fn, s)
  1086. char *fn, **s;
  1087. {
  1088.     char *extp;
  1089.     int ver;
  1090.  
  1091.     strcpy (*s, fn);        /* copy in the name */
  1092.     if (strlen (*s) > 59)    /* don't allow long names */
  1093.     *s[59] = '\0';        /* it breaks the finder */
  1094.     extp = *s + strlen (*s);    /* find position of extension */
  1095.     *extp++ = '.';        /* add in the dot now */
  1096.  
  1097.     for (ver = 0; ver < 99; ver++) {    /* I'll try this many names */
  1098.     NumToString ((long) ver, extp);    /* add in the number */
  1099.     if (zchki (*s) == -1)    /* is this file known? */
  1100.         return;        /* no, made a good one! */
  1101.     }
  1102.     fatal ("znewn failed to find unique name in 64 attempts", 0);
  1103.     return;
  1104. }                /* znewn */
  1105.  
  1106.  
  1107.  
  1108. /****************************************************************************/
  1109. pascal void
  1110. reset ()
  1111. /****************************************************************************/
  1112. extern 0x4E70;
  1113.  
  1114. /****************************************************************************/
  1115. /* zkself() - Kill self (reboot).  On other machines does a logout.
  1116.  *              Flush volumes and reboot.  Called by remote BYE.
  1117.  *
  1118.  */
  1119. /****************************************************************************/
  1120. zkself ()
  1121. {
  1122.     DrvQEl *drvqe;
  1123.     char vname[255];
  1124.     long vfreeb;
  1125.     short vrefnum;
  1126.     int err;
  1127.  
  1128.     /* handle on drive q */
  1129.     for (drvqe = (DrvQEl *) ((QHdr *) GetDrvQHdr ())->qHead;
  1130.      drvqe != NULL;        /* while still something */
  1131.      drvqe = drvqe->qLink) {/* step to next *//* for each drive */
  1132.     err = GetVInfo (drvqe->dQDrive, vname, &vrefnum, &vfreeb);
  1133.     if (err == noErr)
  1134.         err = FlushVol (NILPTR, vrefnum);    /* flush the volume given
  1135.                          * refnum */
  1136.     else if (err != nsvErr)
  1137.         screen (SCR_TN,0,0l,"Remote cmd: GetVinfo returned unknown code");
  1138.     }
  1139.  
  1140.     mac_cleanup ();        /* clean up before leaving */
  1141.     reset ();
  1142. }                /* zkself */
  1143.  
  1144.  
  1145.  
  1146. struct {
  1147.     int errnum;
  1148.     char *errstr;
  1149. }   ioerrs[] = {
  1150.  
  1151.     {
  1152.     dirFulErr, "Directory is full"
  1153.     },
  1154.     {
  1155.     dskFulErr, "Disk is full"
  1156.     },
  1157.     {
  1158.     wPrErr, "Diskette is write protected"
  1159.     },
  1160.     {
  1161.     fLckdErr, "File is software locked"
  1162.     },
  1163.     {
  1164.     vLckdErr, "Volume is software locked"
  1165.     },
  1166.     {
  1167.     fBsyErr, "File is busy"
  1168.     },
  1169.     {
  1170.     opWrErr, "File is already open with write permission"
  1171.     },
  1172.     {
  1173.     0, NILPTR
  1174.     }
  1175. };
  1176.  
  1177. /****************************************************************************/
  1178. /* ioutil - handle the result from an IO call, checking for an
  1179.  *            error return and displaying an appropriate error
  1180.  *            message.  Returns TRUE if no error occured, FALSE
  1181.  *            otherwise.
  1182.  */
  1183. /****************************************************************************/
  1184. int
  1185. ioutil (err)
  1186. int err;
  1187. {
  1188.     int e;
  1189.  
  1190.     if (err == noErr)
  1191.     return (TRUE);
  1192.  
  1193.     for (e = 0; ioerrs[e].errnum != 0 && ioerrs[e].errnum != err; e++);
  1194.  
  1195.     if (ioerrs[e].errstr == NILPTR)    /* anything there? */
  1196.     printerr ("Unknown IO error: ", err);
  1197.     else
  1198.     printerr (ioerrs[e].errstr, 0);
  1199.  
  1200.     return (FALSE);
  1201. }                /* ioutil */
  1202.  
  1203.  
  1204. #ifdef COMMENT
  1205. PWP: my copy of IM 2 says that this _is_ a standard toolbox call, so we
  1206. don't need this at all.
  1207.  
  1208. /****************************************************************************/
  1209. /*
  1210.  * OpenRF is not a standard Toolbox routine but acts identically to FSOpen
  1211.  * except that it opens the resource fork instead of the data fork.
  1212.  */
  1213. /****************************************************************************/
  1214. int 
  1215. OpenRF (fileName, vRefNum, refNum)
  1216. char *fileName;
  1217. int vRefNum;
  1218. short *refNum;
  1219. {
  1220.     IOParam pb;
  1221.  
  1222.     c2pstr (fileName);
  1223.     pb.ioNamePtr = fileName;
  1224.     pb.ioVRefNum = vRefNum;
  1225.     pb.ioVersNum = 0;
  1226.     pb.ioPermssn = 0;
  1227.     pb.ioMisc = (Ptr) 0;
  1228.     PBOpenRF (&pb, 0);
  1229.     *refNum = pb.ioRefNum;
  1230.     p2cstr (fileName);
  1231.     return pb.ioResult;
  1232. }                /* OpenRF */
  1233. #endif COMMENT
  1234.  
  1235. extern short dfltVol;
  1236.  
  1237. #ifdef TLOG
  1238. short tlogfile;
  1239. char tlogname[] = "Kermit Transaction";
  1240.  
  1241. /****************************************************************************/
  1242. /****************************************************************************/
  1243. opentlog ()
  1244. {
  1245.     return (openlogfile("Transaction log name:", tlogname, &tlogfile));
  1246. }
  1247.  
  1248. /****************************************************************************/
  1249. /****************************************************************************/
  1250. closetlog ()
  1251. {
  1252.     FSClose (tlogfile);
  1253.     FlushVol (NIL, dfltVol);
  1254. }                /* closetlog */
  1255.  
  1256.  
  1257.  
  1258. /****************************************************************************/
  1259. /****************************************************************************/
  1260. tlog (f, s1, s2, n)
  1261. int f;
  1262. long n;
  1263. char *s1;
  1264. char *s2;
  1265. {
  1266.     char numstr[12];
  1267.     char outstr[256];
  1268.     long count;
  1269.  
  1270.     if (tralog) {
  1271.     strcpy (outstr, s1);
  1272.  
  1273.     if (strlen (s2)) {
  1274.         strcat (outstr, " ");
  1275.         strcat (outstr, s2);
  1276.     }
  1277.     if (n) {
  1278.         NumToString (n, numstr);
  1279.         strcat (outstr, " ");
  1280.         strcat (outstr, numstr);
  1281.     }
  1282.     strcat (outstr, "\r");
  1283.  
  1284.     count = strlen (outstr);
  1285.     FSWrite (tlogfile, &count, &outstr);
  1286.     }
  1287. }                /* tlog */
  1288.  
  1289. #endif
  1290.  
  1291.  
  1292.  
  1293. short slogfile;
  1294. char slogname[] = "Kermit Session";
  1295.  
  1296. /****************************************************************************/
  1297. /****************************************************************************/
  1298. openslog ()
  1299. {
  1300.     return (openlogfile("Session log name:", slogname, &slogfile));
  1301. }
  1302.  
  1303.  
  1304. /****************************************************************************/
  1305. /****************************************************************************/
  1306. openlogfile(prompt, name, fdp)
  1307. char *prompt, *name;
  1308. short *fdp;
  1309. {
  1310.     int err;
  1311.     FInfo info;
  1312.     SFReply sfr;    /* holds file info */
  1313.     Point where;
  1314.     
  1315.     SetPt(&where, 75, 80);
  1316.     SFPutFile (&where, prompt, name, NILPROC, &sfr);
  1317.     if (!sfr.good)    /* if canceled */
  1318.         return (0);
  1319.  
  1320.     p2cstr(&sfr.fName);
  1321.     err = Create (&sfr.fName, sfr.vRefNum, 'MACA', 'TEXT');
  1322.     if (err != dupFNErr)
  1323.     if (!ioutil (err))
  1324.         return (0);
  1325.  
  1326.     err = FSOpen (&sfr.fName, sfr.vRefNum, fdp); /* open the logfile */
  1327.     if (!ioutil (err))
  1328.     return (0);
  1329.  
  1330.     SetFPos (*fdp, fsFromLEOF, 0);    /* set file pointer to eof */
  1331.     return (1);
  1332. }                /* openslog */
  1333.  
  1334.  
  1335.  
  1336. /****************************************************************************/
  1337. /****************************************************************************/
  1338. closeslog ()
  1339. {
  1340.     int err;
  1341.     /* scrtolog (); */    /* dump the rest of the screen to the logfile */
  1342.     err = FSClose (slogfile);
  1343.     if (!ioutil (err))
  1344.     return (0);
  1345.     FlushVol (NIL, dfltVol);
  1346. }                /* closeslog */
  1347.  
  1348.  
  1349.  
  1350. /****************************************************************************/
  1351. /* write a maximum of n characters from s to the session log file */
  1352. /* skip all trailing blanks */
  1353. /****************************************************************************/
  1354. slog (s, n)
  1355. char *s;
  1356. int n;
  1357. {
  1358.     long count;
  1359.     char *c;
  1360.  
  1361.     /* skip all non visible characters */
  1362.     for (c = s + n - 1; (*c <= ' ') && (c >= s); c--);
  1363.  
  1364.     /* adjust count and write to file */
  1365.     count = (long) (c - s + 1);
  1366.     FSWrite (slogfile, &count, s);
  1367.  
  1368.     /* write a cr at end of line */
  1369.     count = 1;
  1370.     FSWrite (slogfile, &count, "\r");
  1371. }                /* slog */
  1372.