home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / c-kermit / ckiutl.c < prev    next >
C/C++ Source or Header  |  2020-01-01  |  13KB  |  506 lines

  1. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  2. /* |_o_o|\\ Copyright (c) 1986 The Software Distillery.  All Rights Reserved */
  3. /* |. o.| || This program may not be distributed without the permission of   */
  4. /* | .  | || the authors.                                                    */
  5. /* | o  | ||    Dave Baker     Ed Burnette  Stan Chow    Jay Denebeim        */
  6. /* |  . |//     Gordon Keener  Jack Rouse   John Toebes  Doug Walker         */
  7. /* ======          BBS:(919)-471-6436      VOICE:(919)-469-4210              */ 
  8. /*                                                                           */
  9. /* Contributed to Columbia University for inclusion in C-Kermit.             */
  10. /*
  11.   Permission is granted to any individual or institution to use this
  12.   software as long as it is not sold for profit.  This copyright notice must be
  13.   retained.  This software may not be included in commercial products without
  14.   written permission of Columbia University.
  15. */
  16. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  17.  
  18. /*  C K I U T L -- July 17, 1986
  19.  * Utility functions for C-Kermit on the Amiga
  20.  */
  21.  
  22. #ifndef _lint
  23. static char *ckuv = "Amiga utility functions, $Id: ckiutl.c,v 1.10 1999/09/12 00:50:38 swalton Exp swalton $";
  24. #endif
  25.  
  26. /*
  27.  Author: Jack Rouse, The Software Distillery
  28.  
  29.  The file status routines assume all file protection modes are real, instead
  30.  of just delete protection on files and write protection on disks.
  31.  
  32.  * $Log: ckiutl.c,v $
  33.  * Revision 1.10  1999/09/12 00:50:38  swalton
  34.  * Changed some quotes on include files to angle brackets, since they
  35.  * are really system files.  Also deleted a few trailing spaces and tabs.
  36.  *
  37.  * Revision 1.9  1993/08/03  08:37:10  swalton
  38.  * Changes from Olaf Barthel:  Use standard include files and add handling
  39.  * for the NIL: handler
  40.  * 
  41.  * Revision 1.8  92/10/30  16:18:58  swalton
  42.  * Added code to call the V37 routine System() rather than the old Execute()
  43.  * routine in the system() utility.  It is conditional on the extern int
  44.  * v37 being TRUE.  This value is set in ckitio.c.
  45.  * 
  46.  * Revision 1.7  92/01/15  17:15:22  swalton
  47.  * Use Id rather than Header in the RCS ID string.
  48.  * 
  49.  * Revision 1.6  91/07/18  16:05:28  swalton
  50.  * pipeopen() fixed---it was inadvertently broken somewhere.  A system()
  51.  * call was written to replace the no-longer-working Manx one.  Both
  52.  * pipeopen() and system() will use the new AmigaOS System() call if
  53.  * the switch V37 was defined to be non-zero when Kermit was compiled.
  54.  * 
  55.  * Revision 1.5  91/05/29  09:09:21  swalton
  56.  * 1.  Changed function definitions to prototype style.  Required adding
  57.  *     a few forward declarations.
  58.  * 2.  Removed includes of stdio.h, stdlib.h, and string.h, as they are
  59.  *     now pulled in by ckcdeb.h, provided we compile with -DCK_ANSILIBS.
  60.  * 
  61.  * Revision 1.4  90/11/19  21:47:38  swalton
  62.  * Modifications for compiling with SAS/C Version 5.10, courtesy of
  63.  * Larry Rosenman (ler@lerami.lonestar.org, ler on BIX)
  64.  * 
  65.  * Revision 1.3  90/11/07  14:42:33  swalton
  66.  * Version 1.3--released to world as first beta test version simultaneously
  67.  * with release of edit 5A(160).
  68.  * 
  69.  * Revision 1.2  90/08/10  10:05:01  swalton
  70.  * A few changes for edit 150 of C Kermit.  Also deleted the include of
  71.  * ckipro.h, as it is confusing and somewhat unnecessary right now.
  72.  * 
  73.  * Revision 1.1  90/07/12  22:31:24  swalton
  74.  * Minor changes were made to ckiutl.c, mainly to maintain Manx Aztec C
  75.  * compatibility.
  76.  * 
  77.  * Revision 1.0  90/04/30  11:54:40  swalton
  78.  * Initial revision
  79.  * 
  80. */
  81.  
  82. #include "ckcasc.h"            /* ASCII symbols */
  83. #include "ckcdeb.h"            /* Debug formats, typedefs, etc. */
  84. #include "ckcker.h"            /* Symbol definitions for Kermit */
  85. #undef ULONG
  86. #undef UWORD
  87. #undef USHORT
  88.  
  89. #include <string.h>
  90. #include <exec/types.h>
  91. #include <exec/exec.h>
  92. #include <libraries/dos.h>
  93. #include <libraries/dosextens.h>
  94. #define fh_Interact fh_Port
  95. #define fh_Process  fh_Type
  96. #include <fcntl.h>
  97. #include <signal.h>
  98.  
  99. #include <clib/exec_protos.h>
  100. #include <clib/alib_protos.h>
  101. #include <clib/dos_protos.h>
  102.  
  103. #if __SASC
  104. #include <ios1.h>
  105. #include <time.h>
  106. #endif
  107.  
  108.  
  109. #ifdef AZTEC_C
  110. /* translate Unix file handle (0, 1, or 2) to AmigaDOS file handle */
  111. #define DOSFH(n) (_devtab[n].fd)
  112. /* translate Unix file handle (0, 1, or 2) to Aztec file handle */
  113. #define FILENO(n) (n)
  114. #endif
  115. #ifdef __SASC
  116. #define DOSFH(n) (chkufb(n)->ufbfh)
  117. #define FILENO(n) (n)
  118. #endif
  119.  
  120. /* Amiga Kermit externals (defined in ckitio.c) */
  121. extern struct Process *CurProc;
  122. extern struct CommandLineInterface *CurCLI;
  123.  
  124. /*
  125.  * CreatePacket -- allocate and set up a AmigaDOS packet
  126.  */
  127. struct DosPacket *
  128. CreatePacket(void)
  129. {
  130.     register struct StandardPacket *sp;
  131.  
  132.     sp = (struct StandardPacket *)
  133.          AllocMem((LONG)sizeof(struct StandardPacket),
  134.               (LONG)MEMF_PUBLIC|MEMF_CLEAR);
  135.     if (sp == NULL) return(NULL);
  136.     sp->sp_Pkt.dp_Link = &sp->sp_Msg;
  137.     sp->sp_Msg.mn_Node.ln_Type = NT_MESSAGE;
  138.     sp->sp_Msg.mn_Node.ln_Name = (char *)&sp->sp_Pkt;
  139.     sp->sp_Msg.mn_Length = sizeof(struct DosPacket);
  140.     return(&sp->sp_Pkt);
  141. }
  142.  
  143. /*
  144.  * DeletePacket -- deallocate packet from CreatePacket()
  145.  */
  146. void
  147. DeletePacket(struct DosPacket *pkt) {
  148.     FreeMem(pkt->dp_Link, (LONG)sizeof(struct StandardPacket));
  149. }
  150.  
  151. /*
  152.  * zsyscmd(cmd) -- execute a command.
  153.  *   Identical to system except it makes sure that all priveleges are off,
  154.  *   so cmd is executed as a system process.
  155.  */
  156. int system(const char *cmd);
  157.  
  158. int
  159. zsyscmd(char *cmd) {
  160.     return(system(cmd));
  161. }
  162.  
  163.  
  164.  
  165. /*
  166.  * readstat -- determine file's read status
  167.  *    returns -3 if file read protected
  168.  *    returns -2 if file is a directory
  169.  *    returns -1 if file doesn't exist
  170.  *    returns file size otherwise
  171.  */
  172. long
  173. readstat(char *name) {
  174.     BPTR lock;
  175.     struct FileInfoBlock *fib;
  176.     long size;
  177.  
  178.     /* locate the file */
  179.     if ((lock = Lock(name, (LONG)ACCESS_READ)) == 0) return(-1);
  180.  
  181.     /* allocate a file info block */
  182.     if ((fib = (struct FileInfoBlock *)malloc(sizeof(*fib))) == NULL)
  183.     {    size = -1; goto quit; }
  184.  
  185.     /* make sure it's not a directory */
  186.     if (!Examine(lock, fib) || fib->fib_DirEntryType >= 0)
  187.     {    size = -2; goto quit; }
  188.  
  189.     /* make sure it's readable */
  190.     if (fib->fib_Protection & FIBF_READ)
  191.     {    size = -3; goto quit; }
  192.  
  193.     size = fib->fib_Size;
  194. quit:
  195.     if (fib) free(fib);
  196.     UnLock(lock);
  197.     return(size);
  198. }
  199.  
  200. /*
  201.  * writestat -- determines file's write status
  202.  *    returns 0 if file should be writable, -1 otherwise
  203.  *
  204.  * The following logic is used to determine if a file is writable:
  205.  *    1.  If the file exists, it must not be write or delete protected.
  206.  *        (Delete protection subsumes write protection for overwriting.)
  207.  *    2.  The parent directory must not be write protected ???
  208.  *    3.  The volume that the parent directory resides on must be
  209.  *        validated and not write protected.
  210.  */
  211. int
  212. writestat(char *name) {
  213.     register char *p;
  214.     char *lastslash;
  215.     char path[100];
  216.     BPTR lock;
  217.     struct FileInfoBlock *fib;
  218.     struct InfoData *id = NULL;
  219.     int rc = -1;
  220.  
  221.     /* allocate a FileInfoBlock */
  222.     fib = (struct FileInfoBlock *)malloc(sizeof(*fib));
  223.     if (fib == NULL) goto quit;
  224.  
  225.     /* see if the file exists */
  226.     if ((lock = Lock(name, (LONG)ACCESS_READ)) != 0)
  227.     {
  228.         /* make sure it's not a directory or write protected */
  229.         if (!Examine(lock, fib) ||
  230.             fib->fib_DirEntryType >= 0 ||
  231.             (fib->fib_Protection & (FIBF_WRITE|FIBF_DELETE)) )
  232.             goto quit;
  233.         UnLock(lock);
  234.     } else if (IoErr() == ERROR_ACTION_NOT_KNOWN ||
  235.            stricmp(name, "NIL:") == 0) {
  236.         rc = 0;
  237.         goto quit;
  238.     }
  239.  
  240.     /* strip path from name */
  241.     lastslash = NULL;
  242.     for (p = path; *p = *name; ++p, ++name)
  243.         if (*p == '/' || *p == ':')
  244.             lastslash = p;
  245.  
  246.     /* make sure the path exists */
  247.     if (lastslash)
  248.     {
  249.         lastslash[1] = 0;
  250.         lock = Lock(path, (LONG)ACCESS_READ);
  251.     }
  252.     else
  253.         lock = (CurProc->pr_CurrentDir)
  254.                ? DupLock(CurProc->pr_CurrentDir)
  255.                : 0;
  256.  
  257.     /* make sure it is a directory that is not write protected */
  258.     if (lock == 0 || !Examine(lock, fib) ||
  259.         fib->fib_DirEntryType <= 0 ||
  260.         (fib->fib_Protection & FIBF_WRITE) )
  261.         goto quit;
  262.  
  263.     /* get device info */
  264.     if ((id = (struct InfoData *)malloc(sizeof(*id))) == NULL) goto quit;
  265.  
  266.     /* make sure the disk is writeable */
  267.     if (Info(lock, id) && id->id_DiskState == ID_VALIDATED)
  268.         rc = 0;
  269.  
  270.     /* clean up */
  271. quit:
  272.     if (id) free(id);
  273.     if (fib) free(fib);
  274.     if (lock) UnLock(lock);
  275.         return(rc);
  276. }
  277.  
  278. #include <dos/dostags.h>
  279.  
  280. static struct TagItem MyTags[] = {
  281.    { SYS_Output, 0L},
  282.    { TAG_END, 0L}
  283. };
  284. extern short v37;
  285.  
  286. /*
  287.  * pipeopen -- execute command to read output like a file
  288.  */
  289. #define PIPEHOLDER "RAM:Pipe-Holder"
  290. FILE *
  291. pipeopen(char *command) {
  292.     BPTR fh;
  293.  
  294.     /* create holder file */
  295.     fh = Open(PIPEHOLDER, (LONG)MODE_NEWFILE);
  296.     if (fh == 0) return(0);
  297.     if (v37) {
  298.         /* execute the command */
  299.         MyTags[0].ti_Data = fh;
  300.         if (System(command, MyTags) != 0)
  301.             return NULL;
  302.     } else
  303.         Execute(command, 0, fh);
  304.  
  305.     /* close the holder file */
  306.     Close(fh);
  307.  
  308.     /* reopen it for input */
  309.     return(fopen(PIPEHOLDER, "r"));
  310. }
  311.  
  312. /*
  313.  * pipeclose -- clean up after pipe open
  314.  */
  315. void
  316. pipeclose(FILE *f) {
  317.     fclose(f);
  318.     DeleteFile(PIPEHOLDER);
  319. }
  320.  
  321. /*
  322.  * existobj -- return true if file system object exists
  323.  */
  324. int
  325. existobj(char *name) {
  326.     BPTR lock;
  327.  
  328.     if (*name == 0) return(CurProc->pr_CurrentDir != 0);
  329.     if ((lock = Lock(name, (LONG)ACCESS_READ)) == 0)
  330.         return(0);
  331.     UnLock(lock);
  332.     return(1);
  333. }
  334.  
  335. /* opendir handle structure */
  336. struct DirHandle {
  337.     struct FileInfoBlock fib;
  338.     BPTR lock;
  339. };
  340.  
  341. /*
  342.  * attempt to open a directory, fill in a handle structure
  343.  */
  344. struct DirHandle *
  345. opendir(char *name) {
  346.     BPTR lock;
  347.     struct DirHandle *dh;
  348.  
  349.     /* get lock on name ("" is current dir) */
  350.     lock = (*name != 0)        ? Lock(name, (LONG)ACCESS_READ) :
  351.            (CurProc->pr_CurrentDir) ? DupLock(CurProc->pr_CurrentDir)
  352.                     : 0;
  353.     if (lock == 0) return(NULL);
  354.     dh = (struct DirHandle *)malloc(sizeof(*dh));
  355.     if (dh == NULL)
  356.     {
  357.         UnLock(lock);
  358.         return(NULL);
  359.     }
  360.     if (!Examine(lock, &dh->fib) || dh->fib.fib_DirEntryType <= 0)
  361.     {
  362.         UnLock(lock);
  363.         free(dh);
  364.         return(NULL);
  365.     }
  366.     /* pass it into the caller's care */
  367.     dh->lock = lock;
  368.     return(dh);
  369. }
  370.  
  371. /*
  372.  * return name for next entry in dir
  373.  */
  374. char *
  375. readdir(struct DirHandle *dh) {
  376.     return(ExNext(dh->lock, &dh->fib) ? dh->fib.fib_FileName : NULL);
  377. }
  378.  
  379. /*
  380.  * finish accessing a directory
  381.  */
  382. void
  383. closedir(struct DirHandle *dh) {
  384.     UnLock(dh->lock);
  385.     free(dh);
  386. }
  387. #ifdef __SASC
  388. /***
  389.   Based on sendpkt.c from AmigaMail Volume 1, Page II-17ff.
  390.  
  391. ***/
  392.  
  393. LONG dos_packet(struct MsgPort *pid,LONG action, LONG a1, LONG a2,
  394.                                     LONG a3, LONG a4, LONG a5,
  395.                                     LONG a6, LONG a7)
  396. {
  397. struct MsgPort *replyport;
  398. struct StandardPacket *packet;
  399. LONG res1;
  400.  
  401. replyport=(struct MsgPort *)CreatePort(NULL,0);
  402. if (!replyport) return(NULL);
  403.  
  404. packet=(struct StandardPacket *)
  405.    AllocMem((long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
  406.    if (!packet) {
  407.          DeletePort(replyport);
  408.          return(NULL);
  409.    }
  410.  
  411. packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
  412. packet->sp_Pkt.dp_Link         = &(packet->sp_Msg);
  413. packet->sp_Pkt.dp_Port         = replyport;
  414. packet->sp_Pkt.dp_Type         = action;
  415.  
  416. packet->sp_Pkt.dp_Arg1         = a1;
  417. packet->sp_Pkt.dp_Arg2         = a2;
  418. packet->sp_Pkt.dp_Arg3         = a3;
  419. packet->sp_Pkt.dp_Arg4         = a4;
  420. packet->sp_Pkt.dp_Arg5         = a5;
  421. packet->sp_Pkt.dp_Arg6         = a6;
  422. packet->sp_Pkt.dp_Arg7         = a7;
  423.  
  424.  
  425. PutMsg(pid,(struct Message *)packet);
  426.  
  427. WaitPort(replyport);
  428.  
  429. GetMsg(replyport);
  430.  
  431. res1 = packet->sp_Pkt.dp_Res1;
  432.  
  433. FreeMem(packet,(long)sizeof(struct StandardPacket));
  434. DeletePort(replyport);
  435.  
  436. return(res1);
  437. }
  438.  
  439. /* Return 1 if `y' is a leap year, 0 otherwise.
  440.  */
  441.  
  442. static int
  443. leap (int y) {
  444.     y += 1900;
  445.     if (y % 400 == 0)
  446.         return (1);
  447.     if (y % 100 == 0)
  448.         return (0);
  449.     return (y % 4 == 0);
  450. }
  451.  
  452. /* Return the number of days between Jan 1, 1970 and the given
  453.  * broken-down time.
  454.  */
  455.  
  456. static int
  457. ndays (struct tm *p) {
  458.     register n = p->tm_mday;
  459.     register m, y;
  460.     register char *md = "\37\34\37\36\37\36\37\37\36\37\36\37";
  461.  
  462.     for (y = 70; y < p->tm_year; ++y) {
  463.         n += 365;
  464.         if (leap (y)) ++n;
  465.     }
  466.     for (m = 0; m < p->tm_mon; ++m)
  467.         n += md[m] + (m == 1 && leap (y));
  468.     return (n);
  469. }
  470.  
  471. /* Convert a broken-down time (such as returned by localtime())
  472.  * back into a `time_t'.
  473.  */
  474.  
  475. time_t
  476. mktime(struct tm *tp) {
  477.     register int m1, m2;
  478.     time_t t;
  479.     struct tm otm;
  480.  
  481.     t = (ndays (tp) - 1) * 86400L + tp->tm_hour * 3600L
  482.         + tp->tm_min * 60 + tp->tm_sec;
  483.     /*
  484.      * Now the hard part -- correct for the time zone:
  485.      */
  486.     otm = *tp;
  487.     tp = localtime (&t);
  488.     m1 = tp->tm_hour * 60 + tp->tm_min;
  489.     m2 = otm.tm_hour * 60 + otm.tm_min;
  490.     t -= ((m1 - m2 + 720 + 1440) % 1440 - 720) * 60L;
  491.     return (t);
  492. }
  493. #endif
  494.  
  495. int
  496. system(const char *command) {
  497.     debug(F110, "system called with command", command, 0L);
  498.        if (v37) {
  499.         MyTags[0].ti_Data = DOSFH(1);
  500.            return(System((UBYTE *)  command, MyTags));
  501.        } else {
  502.         Execute((UBYTE *) command, 0, DOSFH(1));
  503.         return 0;
  504.     }
  505. }
  506.