home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / ckc095.zip / ckiutl.c < prev    next >
C/C++ Source or Header  |  1989-12-05  |  13KB  |  551 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. /* Permission is granted to any individual or institution to use, copy, or   */
  11. /* redistribute this software so long as it is not sold for profit, provided */
  12. /* this copyright notice is retained.                                        */
  13. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  14.  
  15. /*  C K I U T L -- July 17, 1986
  16.  * Utility functions for C-Kermit on the Amiga
  17.  */
  18.  
  19. /*
  20.  Author: Jack Rouse, The Software Distillery
  21.  
  22.  The file status routines assume all file protection modes are real, instead
  23.  of just delete protection on files and write protection on disks.
  24. */
  25.  
  26. #include <stdio.h>
  27. #undef NULL
  28. #include "exec/types.h"
  29. #include "exec/exec.h"
  30. #include "libraries/dos.h"
  31. #include "libraries/dosextens.h"
  32. #define fh_Interact fh_Port
  33. #define fh_Process  fh_Type
  34. #if LAT310 | AZTEC_C
  35. #include "fcntl.h"
  36. #include "signal.h"
  37. #else
  38. #include "lattice/ios1.h"    /* defines ufbs structure */
  39. #endif
  40.  
  41. /* external routine definitions */
  42. APTR AllocMem();
  43. LONG AllocSignal();
  44. struct IORequest *CheckIO();
  45. VOID CloseDevice();
  46. VOID CloseLibrary();
  47. LONG DoIO();
  48. struct MsgPort *FindPort();
  49. struct Task *FindTask();
  50. VOID FreeMem();
  51. VOID FreeSignal();
  52. struct Message *GetMsg();
  53. LONG OpenDevice();
  54. struct Library *OpenLibrary();
  55. VOID PutMsg();
  56. VOID ReplyMsg();
  57. VOID SendIO();
  58. LONG SetSignal();
  59. VOID Signal();
  60. LONG Wait();
  61. LONG WaitIO();
  62. struct Message *WaitPort();
  63.  
  64. struct IORequest *CreateExtIO();
  65. struct MsgPort *CreatePort();
  66.  
  67. VOID Close();
  68. LONG DeleteFile();
  69. LONG Execute();
  70. BPTR Input(), Output();
  71. LONG IoErr();
  72. LONG IsInteractive();
  73. BPTR Lock();
  74. BPTR Open();
  75. LONG Read();
  76. VOID UnLock();   
  77. LONG WaitForChar();
  78.  
  79. /* portable library */
  80. char *malloc();
  81.  
  82. #ifdef AZTEC_C
  83. /* translate Unix file handle (0, 1, or 2) to AmigaDOS file handle */
  84. #define DOSFH(n) (_devtab[n].fd)
  85. /* translate Unix file handle (0, 1, or 2) to Aztec file handle */
  86. #define FILENO(n) (n)
  87. #else
  88. #ifdef LAT310
  89. /* translate Unix file handle (0, 1, or 2) to AmigaDOS file handle */
  90. #define DOSFH(n) fileno(&_iob[n])
  91. /* translate Unix file handle (0, 1, or 2) to Lattice file handle */
  92. #define FILENO(n) fileno(&_iob[n])
  93. #else
  94. /* Lattice runtime externals */
  95. extern struct UFB _ufbs[];
  96. extern int Enable_Abort;
  97. #define DOSFH(n) (_ufbs[n].ufbfh)
  98. #define FILENO(n) (n)
  99. #endif
  100. #endif
  101.  
  102. /* Amiga Kermit externals (defined in ckitio.c) */
  103. extern struct Process *CurProc;
  104. extern struct CommandLineInterface *CurCLI;
  105.  
  106. /*
  107.  * CreatePacket -- allocate and set up a AmigaDOS packet
  108.  */
  109. struct DosPacket *CreatePacket()
  110. {
  111.     register struct StandardPacket *sp;
  112.  
  113.     sp = (struct StandardPacket *)
  114.          AllocMem((LONG)sizeof(struct StandardPacket),
  115.               (LONG)MEMF_PUBLIC|MEMF_CLEAR);
  116.     if (sp == NULL) return(NULL);
  117.     sp->sp_Pkt.dp_Link = &sp->sp_Msg;
  118.     sp->sp_Msg.mn_Node.ln_Type = NT_MESSAGE;
  119.     sp->sp_Msg.mn_Node.ln_Name = (char *)&sp->sp_Pkt;
  120.     sp->sp_Msg.mn_Length = sizeof(struct DosPacket);
  121.     return(&sp->sp_Pkt);
  122. }
  123.  
  124. /*
  125.  * DeletePacket -- deallocate packet from CreatePacket()
  126.  */
  127. VOID DeletePacket(pkt)
  128. struct DosPacket *pkt;
  129. {
  130.     FreeMem(pkt->dp_Link, (LONG)sizeof(struct StandardPacket));
  131. }
  132.  
  133. /*
  134.  * system(cmd) -- execute a command
  135.  *    provides no sensible return value
  136.  */
  137. system(cmd)
  138. char *cmd;
  139. {
  140.     BPTR fh;
  141.  
  142.     fflush(stdout);
  143.     if (cmd == NULL || *cmd == '\0')
  144.     {
  145.         fh = Open("CON:0/0/640/200/Kermit CLI", (LONG)MODE_NEWFILE);
  146.         if (fh)
  147.         {
  148.             Execute("", fh, (BPTR)NULL);
  149.  
  150.             /* fix 'endcli' bug */
  151.             ((struct FileHandle *)BADDR(fh))->fh_Pos = 0;
  152.  
  153.             Close(fh);
  154.         }
  155.     }
  156.     else
  157.         Execute(cmd, (BPTR)NULL, DOSFH(1));
  158. }
  159.  
  160. /*
  161.  * getcwd -- get current working directory text
  162.  */
  163. char *getcwd(buf, len)
  164. register char *buf;
  165. int len;
  166. {
  167.     register UBYTE *dirname;
  168.  
  169.     if (CurCLI == NULL) return(NULL);
  170.     dirname = (UBYTE *)BADDR(CurCLI->cli_SetName);
  171.     if (len < *dirname + 1) return(NULL);
  172.     strncpy(buf, dirname + 1, *dirname);
  173.     buf[*dirname] = 0;
  174.     return(buf);
  175. }
  176.  
  177. /*
  178.  * update the current directory name in the CLI process structure
  179.  *
  180.  * This version generates the new name from the current name and
  181.  * the specified path, something like the CD command does.
  182.  * A much better version could be written using Parent(), Examine(),
  183.  * and VolInfo to reconstitute a name from a lock, but Parent() doesn't
  184.  * work with RAM: in V1.1.  The current implementation, like the CD
  185.  * command, has difficulty with backing up the directory tree.  For example
  186.  * { chdir("c:"); chdir("/"); } results in a dir name of "c:/".  However,
  187.  * this version shouldn't get as far out of sync as the CD command.  (The
  188.  * same sequence with the CD command puts you in the parent dir of "c:" but
  189.  * with a directory name of "c:".)
  190.  */
  191. static void update_dirname(name)
  192. register char *name;
  193. {
  194.     register UBYTE *dirname;        /* DOS directory name BSTR */
  195.     char buf[100];                /* about same size as DOS */
  196.     register char *tail;
  197.     char *strrchr();
  198.  
  199.     /* locate the DOS copy of the directory name */
  200.     if (CurCLI == NULL) return;
  201.     dirname = (UBYTE *)BADDR(CurCLI->cli_SetName);
  202.  
  203.     /* if the name is anchored (like "DF1:") simply replace the name */
  204.     if (strrchr(name, ':') != NULL)
  205.     {
  206.         *dirname = strlen(name);
  207.         strncpy(&dirname[1], name, *dirname);
  208.         return;
  209.     }
  210.  
  211.     /* name is relative to current directory, copy name to work with */
  212.     strncpy(buf, &dirname[1], *dirname);
  213.     tail = &buf[*dirname];
  214.  
  215.     /* traverse the path in the name */
  216.     while (*name)
  217.     {
  218.         /* go to parent dir? */
  219.         if (*name == '/')
  220.         {    /* remove a component from the directory path */
  221.  
  222.             /* advance past parent slash */
  223.             ++name;
  224.  
  225.             /* if at colon, can't back up */
  226.             if (tail[-1] == ':')
  227.             {
  228.                 *tail++ = '/';
  229.                 continue;
  230.             }
  231.  
  232.             /* if at slash, see if name given */
  233.             if (tail[-1] == '/')
  234.             {
  235.                 /* if no name, can't back up */
  236.                 if (tail[-2] == '/' || tail[-2] == ':')
  237.                 {
  238.                     *tail++ = '/';
  239.                     continue;
  240.                 }
  241.  
  242.                 /* remove trailing slash */
  243.                 --tail;
  244.             }
  245.  
  246.             /* remove remainder of component */
  247.             while (tail[-1] != '/' && tail[-1] != ':')
  248.                 --tail;
  249.         }
  250.         else
  251.         {    /* add component to directory path */
  252.             /* add slash if necessary to separate name */
  253.             if (tail[-1] != ':' && tail[-1] != '/')
  254.                 *tail++ = '/';
  255.  
  256.             /* add component name */
  257.             while (*name && *name != '/')
  258.                 *tail++ = *name++;
  259.  
  260.             /* add trailing slash if specified */
  261.             if (*name == '/')
  262.                 *tail++ = *name++;
  263.         }
  264.     }
  265.  
  266.     /* set BSTR to derived name */
  267.     *dirname = tail - buf;
  268.     strncpy(&dirname[1], buf, *dirname);
  269. }
  270.  
  271. /*
  272.  * change current directory
  273.  */
  274. int chdir(name)
  275. char *name;
  276. {
  277.     BPTR lock;
  278.     BPTR oldlock;
  279.     struct FileInfoBlock *fib;
  280.  
  281.     /* ignore chdir("") */
  282.     if (*name == 0) return(0);
  283.  
  284.     /* try to look at the object */ 
  285.     lock = Lock(name, (LONG)ACCESS_READ);
  286.     if (lock == NULL) return(-1);
  287.  
  288.     /* make sure the file is a directory */
  289.     fib = (struct FileInfoBlock *)malloc(sizeof(*fib));
  290.     if (fib == NULL || !Examine(lock, fib) || fib->fib_DirEntryType <= 0)
  291.     {
  292.         if (fib) free(fib);
  293.         UnLock(lock);
  294.         return(-1);
  295.     }
  296.  
  297.     /* don't need file info any more */
  298.     free(fib);
  299.  
  300.     /* change the current directory */
  301.     oldlock = CurrentDir(lock);
  302.  
  303.     /* update the DOS copy of the directory name */
  304.     update_dirname(name);
  305.  
  306.     /* unlock the previous current directory */
  307.     if (oldlock) UnLock(oldlock);
  308.  
  309.     return(0);
  310. }
  311.  
  312. #if !LAT310 & !AZTEC_C
  313. /*
  314.  * print an error message with explanation
  315.  * (no explanation currently)
  316.  */
  317. int perror(str)
  318. char *str;
  319. {
  320.     extern int errno;
  321.     LONG oserr = IoErr();
  322.  
  323.     printf("%s: errno=%d, oserr=%ld\n", str, errno, oserr);
  324. }
  325. #endif
  326.  
  327. /*
  328.  * isatty(fd) -- determine if given file is a (virtual) terminal
  329.  *    only works for fd=0, 1, or 2 (stdin, stdout, and stderr resp.)
  330.  */ 
  331. int isatty(fd)
  332. int fd;
  333. {
  334.     return(IsInteractive(DOSFH(fd)) != 0);
  335. }
  336.  
  337. /*
  338.  * readstat -- determine file's read status
  339.  *    returns -3 if file read protected
  340.  *    returns -2 if file is a directory
  341.  *    returns -1 if file doesn't exist
  342.  *    returns file size otherwise
  343.  */
  344. long readstat(name)
  345. char *name;
  346. {
  347.     BPTR lock;
  348.     struct FileInfoBlock *fib;
  349.     long size;
  350.  
  351.     /* locate the file */ 
  352.     if ((lock = Lock(name, (LONG)ACCESS_READ)) == NULL) return(-1);
  353.  
  354.     /* allocate a file info block */
  355.     if ((fib = (struct FileInfoBlock *)malloc(sizeof(*fib))) == NULL)
  356.     {    size = -1; goto exit; }
  357.  
  358.     /* make sure it's not a directory */
  359.     if (!Examine(lock, fib) || fib->fib_DirEntryType >= 0)
  360.     {    size = -2; goto exit; }
  361.  
  362.     /* make sure it's readable */
  363.     if (fib->fib_Protection & FIBF_READ)
  364.     {    size = -3; goto exit; }
  365.  
  366.     size = fib->fib_Size;
  367. exit:
  368.     if (fib) free(fib);
  369.     UnLock(lock);
  370.     return(size);
  371. }
  372.  
  373. /*
  374.  * writestat -- determines file's write status
  375.  *    returns 0 if file should be writable, -1 otherwise
  376.  *
  377.  * The following logic is used to determine if a file is writable:
  378.  *    1.  If the file exists, it must not be write or delete protected.
  379.  *        (Delete protection subsumes write protection for overwriting.)
  380.  *    2.  The parent directory must not be write protected ???
  381.  *    3.  The volume that the parent directory resides on must be
  382.  *        validated and not write protected.
  383.  */
  384. int writestat(name)
  385. register char *name;
  386. {
  387.     register char *p;
  388.     char *lastslash;
  389.     char path[100];
  390.     BPTR lock;
  391.     struct FileInfoBlock *fib;
  392.     struct InfoData *id = NULL;
  393.     int rc = -1;
  394.  
  395.     /* allocate a FileInfoBlock */
  396.     fib = (struct FileInfoBlock *)malloc(sizeof(*fib));
  397.     if (fib == NULL) goto exit;
  398.  
  399.     /* see if the file exists */
  400.     if ((lock = Lock(name, (LONG)ACCESS_READ)) != NULL)
  401.     {
  402.         /* make sure it's not a directory or write protected */
  403.         if (!Examine(lock, fib) ||
  404.             fib->fib_DirEntryType >= 0 ||
  405.             (fib->fib_Protection & (FIBF_WRITE|FIBF_DELETE)) )
  406.             goto exit;
  407.         UnLock(lock);
  408.     }
  409.  
  410.     /* strip path from name */
  411.     lastslash = NULL;
  412.     for (p = path; *p = *name; ++p, ++name)
  413.         if (*p == '/' || *p == ':')
  414.             lastslash = p;
  415.  
  416.     /* make sure the path exists */
  417.     if (lastslash)
  418.     {
  419.         lastslash[1] = 0;
  420.         lock = Lock(path, (LONG)ACCESS_READ);
  421.     }
  422.     else
  423.         lock = (CurProc->pr_CurrentDir)
  424.                ? DupLock(CurProc->pr_CurrentDir)
  425.                : NULL;
  426.  
  427.     /* make sure it is a directory that is not write protected */
  428.     if (lock == NULL || !Examine(lock, fib) ||
  429.         fib->fib_DirEntryType <= 0 ||
  430.         (fib->fib_Protection & FIBF_WRITE) )
  431.         goto exit;
  432.  
  433.     /* get device info */    
  434.     if ((id = (struct InfoData *)malloc(sizeof(*id))) == NULL) goto exit;
  435.  
  436.     /* make sure the disk is writeable */
  437.     if (Info(lock, id) && id->id_DiskState == ID_VALIDATED)
  438.         rc = 0;
  439.  
  440.     /* clean up */
  441. exit:
  442.     if (id) free(id);
  443.     if (fib) free(fib);
  444.     if (lock) UnLock(lock);
  445.         return(rc);
  446. }
  447.  
  448. /*
  449.  * pipeopen -- execute command to read output like a file
  450.  */
  451. #define PIPEHOLDER "RAM:Pipe-Holder"
  452. FILE *pipeopen(command)
  453. char *command;
  454. {
  455.     BPTR fh;
  456.  
  457.     /* create holder file */
  458.     fh = Open(PIPEHOLDER, (LONG)MODE_NEWFILE);
  459.     if (fh == NULL) return(0);
  460.  
  461.     /* execute the command */
  462.     Execute(command, (BPTR)NULL, fh);
  463.  
  464.     /* close the holder file */
  465.     Close(fh);
  466.  
  467.     /* reopen it for input */
  468.     return(fopen(PIPEHOLDER, "r"));
  469. }
  470.  
  471. /*
  472.  * pipeclose -- clean up after pipe open
  473.  */
  474. pipeclose(f)
  475. FILE *f;
  476. {
  477.     fclose(f);
  478.     DeleteFile(PIPEHOLDER);
  479. }
  480.  
  481. /*
  482.  * existobj -- return true if file system object exists
  483.  */
  484. int existobj(name)
  485. char *name;
  486. {
  487.     BPTR lock;
  488.  
  489.     if (*name == 0) return(CurProc->pr_CurrentDir != NULL);
  490.     if ((lock = Lock(name, (LONG)ACCESS_READ)) == NULL)
  491.         return(0);
  492.     UnLock(lock);
  493.     return(1);
  494. }
  495.  
  496. /* opendir handle structure */
  497. struct DirHandle {
  498.     struct FileInfoBlock fib;
  499.     BPTR lock;
  500. };
  501.  
  502. /*
  503.  * attempt to open a directory, fill in a handle structure
  504.  */
  505. struct DirHandle *opendir(name)
  506. char *name;
  507. {
  508.     BPTR lock;
  509.     struct DirHandle *dh;
  510.  
  511.     /* get lock on name ("" is current dir) */
  512.     lock = (*name != 0)        ? Lock(name, (LONG)ACCESS_READ) :
  513.            (CurProc->pr_CurrentDir) ? DupLock(CurProc->pr_CurrentDir)
  514.                     : NULL;
  515.     if (lock == NULL) return(NULL);
  516.     dh = (struct DirHandle *)malloc(sizeof(*dh));
  517.     if (dh == NULL)
  518.     {
  519.         UnLock(lock);
  520.         return(NULL);
  521.     }
  522.     if (!Examine(lock, &dh->fib) || dh->fib.fib_DirEntryType <= 0)
  523.     {
  524.         UnLock(lock);
  525.         free(dh);
  526.         return(NULL);
  527.     }
  528.     /* pass it into the caller's care */
  529.     dh->lock = lock;
  530.     return(dh);
  531. }
  532.  
  533. /*
  534.  * return name for next entry in dir
  535.  */
  536. char *readdir(dh)
  537. struct DirHandle *dh;
  538. {
  539.     return(ExNext(dh->lock, &dh->fib) ? dh->fib.fib_FileName : NULL);
  540. }
  541.  
  542. /*
  543.  * finish accessing a directory
  544.  */
  545. VOID closedir(dh)
  546. struct DirHandle *dh;
  547. {
  548.     UnLock(dh->lock);
  549.     free(dh);
  550. }
  551.