home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD2.iso / Misc / PIPE3310.LHA / pipe3310 / src / pipe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-30  |  9.3 KB  |  450 lines

  1. /*
  2.  * pipe.c
  3.  *
  4.  * Copyright (c) 1992, 1994 Ville Saari
  5.  * All rights reserved
  6.  *
  7.  * Created: 30-Oct-92
  8.  * Updated: 27-Dec-94
  9.  */
  10.  
  11. #define UNAME "PIPE"
  12. #define NAME "pipe"
  13. #define COPYRSIGN "\251"
  14. #define CSI(command) "\233" command
  15.  
  16. #include "version.h"
  17.  
  18. static volatile char version[]="$VER: " NAME " " RELEASE "." VERSION " (" VERDATE ")";
  19.  
  20. #define COPYRIGHT \
  21.     CSI("1m") UNAME CSI("0m") " V" RELEASE "." VERSION "\n"\
  22.     "Copyright " COPYRSIGN " 1992, 1994 Ville Saari\n"\
  23.     "All rights reserved\n"
  24. #define USAGE \
  25.     COPYRIGHT \
  26.     "\n" \
  27.     "Usage: " NAME " <command> [ | <command> ] ...\n"
  28.  
  29. #include <stdlib.h>
  30. #include <string.h>
  31.  
  32. #include <proto/exec.h>
  33. #include <exec/memory.h>
  34. #include <exec/execbase.h>
  35.  
  36. #include <proto/dos.h>
  37. #include <dos/dosextens.h>
  38. #include <dos/dostags.h>
  39. #include <dos/rdargs.h>
  40.  
  41. #include <stdlib.h>
  42. #include <string.h>
  43.  
  44. struct handle
  45.     {
  46.     struct FileHandle *fh;
  47.     struct DosPacket *pkt;
  48.     char *ptr;
  49.     int bytes, isoutput;
  50.     struct handle *link;
  51.     enum { UNUSED, INUSE, CLOSED } state;
  52.     };
  53.  
  54. struct prochandle
  55.     {
  56.     struct Task *task;
  57.     struct handle input, output;
  58.     };
  59.  
  60. static void rwreturn(struct handle *, long);
  61. static int makeproc(struct prochandle *, char *);
  62. static struct FileHandle *initfh(struct handle *, struct MsgPort *);
  63.  
  64. struct DosLibrary *DOSBase;
  65.  
  66. void __asm main(register __a0 char *cmdp)
  67.     {
  68.     int f, copysize, iodisabled=0, commands=0, opencount=0;
  69.     char *p;
  70.     struct Message *msg;
  71.     struct DosPacket *pkt;
  72.     struct MsgPort *port;
  73.     struct handle *handle, *rhandle, *whandle;
  74.     struct prochandle *proctab;
  75.  
  76.     if(DOSBase=(struct DosLibrary *)OpenLibrary("dos.library", 37))
  77.         {
  78.         p=cmdp;
  79.  
  80.         while(*p && *p!='\n' && *p!='\r')
  81.             {
  82.             enum { OUT, IN, ESC } state=OUT;
  83.  
  84.             commands++;
  85.  
  86.             while(*p && *p!='\n' && *p!='\r' && (state!=OUT || *p!='|'))
  87.                 {
  88.                 switch(state)
  89.                     {
  90.                     case OUT:
  91.                         if(*p=='"') state=IN;
  92.                         break;
  93.  
  94.                     case IN:
  95.                         if(*p=='*') state=ESC;
  96.                         else if(*p=='"') state=OUT;
  97.                         break;
  98.  
  99.                     case ESC:
  100.                         state=IN;
  101.                     }
  102.  
  103.                 p++;
  104.                 }
  105.  
  106.             if(*p=='|') *p++=0;
  107.             }
  108.  
  109.         *p=0;
  110.  
  111.         if(!commands)
  112.             {
  113.             BPTR stderr;
  114.  
  115.             if(stderr=Open("CONSOLE:", MODE_NEWFILE))
  116.                 {
  117.                 FPuts(stderr, USAGE);
  118.                 Close(stderr);
  119.                 }
  120.             }
  121.         else
  122.             {
  123.             if(port=CreateMsgPort())
  124.                 {
  125.                 if(proctab=AllocMem(commands*sizeof *proctab, MEMF_CLEAR))
  126.                     {
  127.                     for(f=0; f<commands; f++)
  128.                         {
  129.                         if(!(proctab[f].input.fh=initfh(&proctab[f].input, port)) ||
  130.                             !(proctab[f].output.fh=initfh(&proctab[f].output, port)))
  131.                             break;
  132.  
  133.                         proctab[f].output.isoutput=1;
  134.  
  135.                         if(f) proctab[f].input.link=&proctab[f-1].output;
  136.                         if(f<commands-1) proctab[f].output.link=&proctab[f+1].input;
  137.                         }
  138.  
  139.                     if(f==commands)
  140.                         {
  141.                         for(f=0; f<commands; f++)
  142.                             {
  143.                             char *ncmdp=cmdp+strlen(cmdp)+1;
  144.  
  145.                             while(*cmdp==' ' || *cmdp=='\t') cmdp++;
  146.  
  147.                             if(*cmdp=='"')
  148.                                 {
  149.                                 char *q;
  150.  
  151.                                 p=q=++cmdp;
  152.  
  153.                                 for(;;)
  154.                                     {
  155.                                     switch(*q)
  156.                                         {
  157.                                         case '*':
  158.                                             if(*(q+1)) q++;
  159.                                             break;
  160.  
  161.                                         case '"':
  162.                                             q++;
  163.  
  164.                                         case 0:
  165.                                             goto out;
  166.                                         }
  167.  
  168.                                     *p++=*q++;                            
  169.                                     }
  170.                                 out:
  171.  
  172.                                 while(*p++=*q++);
  173.                                 }
  174.  
  175.                             if(makeproc(proctab+f, cmdp))
  176.                                 {
  177.                                 opencount+=2;
  178.                                 proctab[f].input.state=proctab[f].output.state=INUSE;
  179.                                 }
  180.  
  181.                             cmdp=ncmdp;
  182.                             }
  183.  
  184.                         while(opencount>0)
  185.                             {
  186.                             unsigned long sigs;
  187.  
  188.                             if(sigs=(Wait(1<<port->mp_SigBit|
  189.                                 SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)&
  190.                                 (SIGBREAKF_CTRL_C|SIGBREAKF_CTRL_D|SIGBREAKF_CTRL_E|SIGBREAKF_CTRL_F)))
  191.                                     {
  192.                                     for(f=0; f<commands; f++)
  193.                                         if(proctab[f].task &&
  194.                                             proctab[f].input.state==INUSE &&
  195.                                             proctab[f].output.state==INUSE)
  196.                                             Signal(proctab[f].task, sigs);
  197.  
  198.                                     if(sigs&SIGBREAKF_CTRL_C) iodisabled=1;
  199.                                     }
  200.  
  201.                             while(msg=GetMsg(port))
  202.                                 {
  203.                                 pkt=(struct DosPacket *)msg->mn_Node.ln_Name;
  204.  
  205.                                 handle=(struct handle *)pkt->dp_Arg1;
  206.  
  207.                                 if(handle->isoutput)
  208.                                     whandle=handle, rhandle=handle->link;
  209.                                 else
  210.                                     rhandle=handle, whandle=handle->link;
  211.  
  212.                                 switch(pkt->dp_Type)
  213.                                     {
  214.                                     case ACTION_READ:
  215.                                         if(handle->isoutput)
  216.                                             {
  217.                                             ReplyPkt(pkt, 0, ERROR_READ_PROTECTED);
  218.                                             break;
  219.                                             }
  220.  
  221.                                         if(!handle->link)
  222.                                             {
  223.                                             ReplyPkt(pkt,
  224.                                                 Read(Input(), (void *)pkt->dp_Arg2, pkt->dp_Arg3),
  225.                                                 IoErr());
  226.                                             break;
  227.                                             }
  228.  
  229.                                         goto READ_and_WRITE;
  230.  
  231.                                     case ACTION_WRITE:
  232.                                         if(!handle->isoutput)
  233.                                             {
  234.                                             ReplyPkt(pkt, 0, ERROR_WRITE_PROTECTED);
  235.                                             break;
  236.                                             }
  237.  
  238.                                         if(!handle->link)
  239.                                             {
  240.                                             ReplyPkt(pkt,
  241.                                                 Write(Output(), (void *)pkt->dp_Arg2, pkt->dp_Arg3),
  242.                                                 IoErr());
  243.                                             break;
  244.                                             }
  245.  
  246.                                     READ_and_WRITE:
  247.                                         if(!pkt->dp_Arg2 || pkt->dp_Arg3<0)
  248.                                             {
  249.                                             ReplyPkt(pkt, 0, ERROR_BAD_NUMBER);
  250.                                             break;
  251.                                             }
  252.  
  253.                                         if(iodisabled)
  254.                                             {
  255.                                             ReplyPkt(pkt, 0, ERROR_INVALID_LOCK);
  256.                                             break;
  257.                                             }
  258.  
  259.                                         if(handle->pkt)
  260.                                             {
  261.                                             ReplyPkt(pkt, 0, ERROR_OBJECT_IN_USE);
  262.                                             break;
  263.                                             }
  264.  
  265.                                         handle->pkt=pkt;
  266.                                         handle->ptr=(char *)pkt->dp_Arg2;
  267.                                         handle->bytes=pkt->dp_Arg3;
  268.  
  269.                                         if(rhandle->pkt && whandle->pkt)
  270.                                             {
  271.                                             copysize=rhandle->bytes<whandle->bytes?
  272.                                                 rhandle->bytes:whandle->bytes;
  273.  
  274.                                             CopyMem(whandle->ptr, rhandle->ptr, copysize);
  275.  
  276.                                             whandle->ptr+=copysize;
  277.                                             whandle->bytes-=copysize;
  278.                                             rhandle->ptr+=copysize;
  279.                                             rhandle->bytes-=copysize;
  280.                                             }
  281.  
  282.                                         if(rhandle->pkt)
  283.                                             if(!rhandle->bytes)
  284.                                                 rwreturn(rhandle, 0);
  285.                                             else if(whandle->state!=INUSE)
  286.                                                 rwreturn(rhandle, 0);
  287.  
  288.                                         if(whandle->pkt)
  289.                                             if(!whandle->bytes)
  290.                                                 rwreturn(whandle, 0);
  291.                                             else if(rhandle->state!=INUSE)
  292.                                                 rwreturn(whandle, ERROR_INVALID_LOCK);
  293.  
  294.                                         break;
  295.  
  296.                                     case ACTION_END:
  297.                                         if(handle->pkt)
  298.                                             {
  299.                                             ReplyPkt(pkt, 0, ERROR_OBJECT_IN_USE);
  300.                                             break;
  301.                                             }
  302.  
  303.                                         if(handle->state!=INUSE)
  304.                                             {
  305.                                             ReplyPkt(pkt, 0, ERROR_INVALID_LOCK);
  306.                                             break;
  307.                                             }
  308.  
  309.                                         opencount--;
  310.                                         handle->state=CLOSED;
  311.  
  312.                                         if(handle->link && handle->link->pkt)
  313.                                             rwreturn(handle->link, 0);
  314.  
  315.                                         ReplyPkt(pkt, 1, 0);
  316.                                         break;
  317.  
  318.                                     default:
  319.                                         ReplyPkt(pkt, 0, ERROR_ACTION_NOT_KNOWN);
  320.                                     }
  321.                                 }
  322.                             }
  323.                         }
  324.  
  325.                     for(f=0; f<commands; f++)
  326.                         {
  327.                         if(proctab[f].input.state==UNUSED && proctab[f].input.fh)
  328.                             FreeDosObject(DOS_FILEHANDLE, proctab[f].input.fh);
  329.  
  330.                         if(proctab[f].output.state==UNUSED && proctab[f].output.fh)
  331.                             FreeDosObject(DOS_FILEHANDLE, proctab[f].output.fh);
  332.                         }
  333.  
  334.                     FreeMem(proctab, commands*sizeof *proctab);
  335.                     }
  336.  
  337.                 DeleteMsgPort(port);
  338.                 }
  339.             }
  340.  
  341.         CloseLibrary((struct Library *)DOSBase);
  342.         }
  343.     }
  344.  
  345. static struct FileHandle *initfh(struct handle *h, struct MsgPort *port)
  346.     {
  347.     struct FileHandle *fh;
  348.  
  349.     if(!(fh=AllocDosObjectTags(DOS_FILEHANDLE, ADO_FH_Mode, MODE_OLDFILE, TAG_END)))
  350.         return 0;
  351.  
  352.     fh->fh_Type=port;
  353.     fh->fh_Port=0;
  354.     fh->fh_Link=0;
  355.     fh->fh_Arg1=(long)h;
  356.  
  357.     return fh;
  358.     }
  359.  
  360. static void rwreturn(struct handle *handle, long error)
  361.     {
  362.     int size;
  363.  
  364.     if(handle->state==INUSE)
  365.         size=handle->ptr-(char *)handle->pkt->dp_Arg2;
  366.     else
  367.         size=0;
  368.  
  369.     if(!size && error)
  370.         size=-1;
  371.  
  372.     ReplyPkt(handle->pkt, size, error);
  373.  
  374.     handle->pkt=0;
  375.     }
  376.  
  377. extern char addtaskfunc, mytaskptr, newtaskptrptr, origaddtask;
  378.  
  379. #define ADDTASKPTR       ((unsigned long (*)())(semaphore+1))
  380. #define ADDTASKSIZE      (&origaddtask-&addtaskfunc)
  381. #define MYTASKPTR        (*(struct Task **)((char *)ADDTASKPTR+(&mytaskptr-&addtaskfunc)))
  382. #define NEWTASKPTRPTR    (*(struct Task ***)((char *)ADDTASKPTR+(&newtaskptrptr-&addtaskfunc)))
  383. #define ORIGADDTASKPTR   (*(unsigned long (**)())((char *)ADDTASKPTR+ADDTASKSIZE))
  384. #define SEMAPHORENAME    "pipe addtask patch"
  385. #define SEMAPHORENAMEPTR ((char *)ADDTASKPTR+ADDTASKSIZE+4)
  386. #define ALLOCSIZE        (sizeof(struct SignalSemaphore)+ADDTASKSIZE+4+sizeof(SEMAPHORENAME))
  387.  
  388. static int makeproc(struct prochandle *ph, char *cmd)
  389.     {
  390.     struct SignalSemaphore *semaphore;
  391.     int rc=1;
  392.  
  393. #ifdef DEBUG
  394.     int mysemaphore=0;
  395. #endif
  396.  
  397.     Forbid();
  398.  
  399.     if(!(semaphore=FindSemaphore(SEMAPHORENAME)) &&
  400.         (semaphore=AllocMem(ALLOCSIZE, MEMF_CLEAR|MEMF_PUBLIC)))
  401.         {
  402.         memcpy(ADDTASKPTR, &addtaskfunc, ADDTASKSIZE);
  403.         ORIGADDTASKPTR=SetFunction(*(struct Library **)4, -282, ADDTASKPTR);
  404.         memcpy(SEMAPHORENAMEPTR, SEMAPHORENAME, sizeof(SEMAPHORENAME));
  405.         semaphore->ss_Link.ln_Name=SEMAPHORENAMEPTR;
  406.         AddSemaphore(semaphore);
  407.  
  408. #ifdef DEBUG
  409.         mysemaphore=1;
  410. #endif
  411.         }
  412.  
  413.     Permit();
  414.  
  415.     ph->task=0;
  416.  
  417.     if(!semaphore) return 0;
  418.  
  419.     ObtainSemaphore(semaphore);
  420.  
  421.     NEWTASKPTRPTR=&ph->task;
  422.     MYTASKPTR=FindTask(0);
  423.     CacheClearU();
  424.  
  425.     if(SystemTags(cmd,
  426.         SYS_Input,  MKBADDR(ph->input.fh),
  427.         SYS_Output, MKBADDR(ph->output.fh),
  428.         SYS_Asynch, 1,
  429.         TAG_DONE)<0)
  430.         ph->task=0, rc=0;
  431.  
  432.     MYTASKPTR=0;
  433.     CacheClearU();
  434.  
  435. #ifdef DEBUG
  436.     if(mysemaphore)
  437.         {
  438.         RemSemaphore(semaphore);
  439.         SetFunction(*(struct Library **)4, -282, ORIGADDTASKPTR);
  440.         FreeMem(semaphore, ALLOCSIZE);
  441. PutStr("Semrem\n");
  442.         }
  443.     else
  444. #endif
  445.  
  446.     ReleaseSemaphore(semaphore);
  447.  
  448.     return rc;
  449.     }
  450.