home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 239.lha / amiga / src / lib / dnetlib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-02  |  13.0 KB  |  694 lines

  1.  
  2. /*
  3.  *  DNETLIB.C
  4.  *
  5.  *  DNET (c)Copyright 1988, Matthew Dillon, All Rights Reserved.
  6.  *
  7.  *  Library Interface for DNET.
  8.  */
  9.  
  10. #define NOEXT
  11. #include "/dnet/dnet.h"
  12. #include "/lib/dnetlib.h"
  13. #include <stdio.h>
  14.  
  15. #define CHANN    struct _CHANN
  16.  
  17. #define NAMELEN sizeof("DNET.PORT.XXXXX")
  18. #define NAMEPAT "DNET.PORT.%ld"
  19.  
  20. CHANN {
  21.     PORT    port;        /*    receive data, replies        */
  22.     PORT    *dnetport;        /*    dnet's master port          */
  23.     LIST    rdylist;        /*    ready to be read        */
  24.     uword   chan;        /*    channel # for open channels */
  25.     ubyte   eof;        /*    channel remotely closed/eof */
  26.     ubyte   filler;
  27.     int     qlen;        /*    allowed write queue size    */
  28.     int     queued;        /*    current # packets queued    */
  29. };
  30.  
  31. /*BREAKUP   vers.bc    */
  32.  
  33. Version(name, ver, subver)
  34. char *name;
  35. char *ver;
  36. char *subver;
  37. {
  38.     Write(Output(), name, strlen(name));
  39.     Write(Output(), " V", 2);
  40.     Write(Output(), ver, strlen(ver));
  41.     Write(Output(), subver, strlen(subver));
  42.     Write(Output(), "\n", 1);
  43. }
  44.  
  45. /*BREAKUP   dlis.bc    */
  46.  
  47.  
  48. PORT *
  49. DListen(portnum)
  50. uword portnum;
  51. {
  52.     PORT *port = NULL;
  53.     char *ptr;
  54.  
  55.     ptr = AllocMem(NAMELEN, MEMF_PUBLIC);   /*  memory the the name     */
  56.     sprintf(ptr, NAMEPAT, portnum);
  57.     Forbid();                               /*  task-atomic operation   */
  58.     if (FindPort(ptr) || !(port = CreatePort(ptr,0)))
  59.     FreeMem(ptr, NAMELEN);
  60.     Permit();
  61.     return(port);
  62. }
  63.  
  64. /*BREAKUP   dunl.bc    */
  65.  
  66. void
  67. DUnListen(lisport)
  68. PORT *lisport;
  69. {
  70.     if (lisport) {
  71.     register char *ptr = lisport->mp_Node.ln_Name;
  72.     Forbid();                       /*  task-atomic operation       */
  73.     while (DNAAccept(lisport));     /*  remove all pending requests */
  74.     DeletePort(lisport);            /*  gone!                       */
  75.     Permit();
  76.     FreeMem(ptr, NAMELEN);
  77.     }
  78. }
  79.  
  80. /*BREAKUP   dacc.bc    */
  81.  
  82.  
  83. /*
  84.  *  DAccept()
  85.  *
  86.  *  Note:   This call will work even if called by a task which does not
  87.  *        own the listen port.
  88.  */
  89.  
  90. PORT *
  91. DAccept(lisport)
  92. PORT *lisport;
  93. {
  94.     register IOR *ior;
  95.     register CHANN *chan = NULL;
  96.     CHANN *MakeChannel();
  97.  
  98.     while (!chan && (ior = GetMsg(lisport))) {
  99.     switch(ior->io_Command) {
  100.     case DNCMD_SOPEN:
  101.         chan = MakeChannel(ior, NULL);
  102.         break;
  103.     default:
  104.         ior->io_Error = 1;
  105.         break;
  106.     }
  107.     ReplyMsg(ior);
  108.     }
  109.     if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
  110.     SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
  111.     return((PORT *)chan);
  112. }
  113.  
  114. /*BREAKUP   dnaac.bc    */
  115.  
  116.  
  117. /*
  118.  *  Refuse a connection
  119.  */
  120.  
  121. DNAAccept(lisport)
  122. PORT *lisport;
  123. {
  124.     IOR *ior;
  125.  
  126.     if (ior = GetMsg(lisport)) {
  127.     ior->io_Error = 1;
  128.     ReplyMsg(ior);
  129.     }
  130.     if (lisport->mp_MsgList.lh_Head != (NODE *)&lisport->mp_MsgList.lh_Tail)
  131.     SetSignal(1 << lisport->mp_SigBit, 1 << lisport->mp_SigBit);
  132.     return(ior != NULL);
  133. }
  134.  
  135. /*BREAKUP   dpri.bc    */
  136.  
  137.  
  138. DPri(chan, pri)
  139. CHANN *chan;
  140. {
  141. }
  142.  
  143. /*BREAKUP   dopen.bc    */
  144.  
  145. PORT *
  146. DOpen(host, portnum, txpri, rxpri)
  147. char *host;
  148. char txpri, rxpri;
  149. uword portnum;
  150. {
  151.     IOR ior;
  152.     CHANN *chan;
  153.     CHANN *MakeChannel();
  154.  
  155.     if (!host)
  156.     host = "0";
  157.     chan = MakeChannel(&ior, host);
  158.     if (rxpri > 126)
  159.     rxpri = 126;
  160.     if (rxpri < -127)
  161.     rxpri = -127;
  162.     if (txpri > 126)
  163.     txpri = 126;
  164.     if (txpri < -127)
  165.     txpri = -127;
  166.     if (chan->dnetport) {
  167.     ior.io_Command = DNCMD_OPEN;
  168.     ior.io_Unit = (void *)portnum;
  169.     ior.io_Offset = (long)chan;
  170.     ior.io_Message.mn_ReplyPort = (PORT *)chan;
  171.     ior.io_Message.mn_Node.ln_Pri = txpri;
  172.     ior.io_Message.mn_Node.ln_Name= (char *)rxpri;
  173.  
  174.     PutMsg(chan->dnetport, &ior);
  175.     WaitMsg(&ior);
  176.     if (ior.io_Error == 0) {
  177.         chan->chan = (long)ior.io_Unit;
  178.         FixSignal(chan);
  179.         return((PORT *)chan);
  180.     }
  181.     }
  182.     DeleteChannel(chan);
  183.     return(NULL);
  184. }
  185.  
  186. /*BREAKUP   dceof.bc    */
  187.  
  188.  
  189. DCheckEof(chan)
  190. CHANN *chan;
  191. {
  192.     return (chan->eof);
  193. }
  194.  
  195. /*BREAKUP   dgioc.bc    */
  196.  
  197. DGetIoctl(chan, pval, paux)
  198. CHANN *chan;
  199. short *pval;
  200. char *paux;
  201. {
  202.     register IOR *ior;
  203.     short cmd = -1;
  204.  
  205.     if ((ior = GetHead(&chan->rdylist)) || (ior = GetHead(&chan->port.mp_MsgList))) {
  206.     if (ior->io_Command == DNCMD_IOCTL) {
  207.         CIOCTL *cio = (CIOCTL *)ior->io_Data;
  208.         cmd = cio->cmd;
  209.         *pval = (cio->valh << 8) | cio->vall;
  210.         *paux = cio->valaux;
  211.         Forbid();
  212.         Remove(ior);
  213.         ReplyMsg(ior);
  214.         Permit();
  215.     }
  216.     }
  217.     FixSignal(chan);
  218.     if (chan->eof)
  219.     SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
  220.     return(cmd);
  221. }
  222.  
  223. /*BREAKUP   dnread.bc     */
  224.  
  225.  
  226. DNRead(chan, buf, bytes)
  227. CHANN *chan;
  228. char *buf;
  229. {
  230.     register IOR *ior;
  231.     int len = 0;
  232.     long n;
  233.  
  234.     if (chan->eof)
  235.     return(-1);
  236.     while (bytes && ((ior = RemHead(&chan->rdylist)) || (ior = GetMsg(chan)))) {
  237. #ifdef DEBUG
  238.     printf("IOR %08lx cmd %d len %d act %d\n", ior, ior->io_Command, ior->io_Length, ior->io_Actual);
  239. #endif
  240.     if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
  241.         if (!chan->queued)
  242.         puts("DNRead: Software Error");
  243.         else
  244.         --chan->queued;
  245.         if (ior->io_Length)
  246.         FreeMem(ior->io_Data, ior->io_Length);
  247.         FreeMem(ior, sizeof(IOR));
  248.         continue;
  249.     }
  250.     switch(ior->io_Command) {
  251.     case DNCMD_CLOSE:
  252.     case DNCMD_EOF:
  253.         chan->eof = 1;
  254.         ReplyMsg(ior);
  255.         break;
  256.     case DNCMD_IOCTL:
  257.         if (ior->io_Message.mn_Node.ln_Type == NT_REQUEUE)
  258.         AddHead(&chan->rdylist, ior);
  259.         else
  260.         AddTail(&chan->rdylist, ior);
  261.         ior->io_Message.mn_Node.ln_Type = NT_REQUEUE;
  262.         if (len == 0)
  263.         len = -2;
  264.         goto done;
  265.     case DNCMD_WRITE:
  266. #ifdef DEBUG
  267.         printf("IOR LEN/ACT %ld/%ld\n", ior->io_Length, ior->io_Actual);
  268. #endif
  269.         n = ior->io_Length - ior->io_Actual;
  270.         if (n < 0)
  271.         puts("len fail");
  272.         if (n <= bytes) {
  273.         CopyMem((char *)ior->io_Data + ior->io_Actual, buf, n);
  274.         bytes -= n;
  275.         len += n;
  276.         buf += n;
  277.         ReplyMsg(ior);
  278.         } else {
  279.         CopyMem((char *)ior->io_Data + ior->io_Actual, buf, bytes);
  280.         len += bytes;
  281.         ior->io_Actual += bytes;
  282.         bytes = 0;
  283.         if (ior->io_Message.mn_Node.ln_Type == NT_REQUEUE)
  284.             AddHead(&chan->rdylist, ior);
  285.         else
  286.             AddTail(&chan->rdylist, ior);
  287.         ior->io_Message.mn_Node.ln_Type = NT_REQUEUE;
  288.         }
  289.         break;
  290.     default:
  291.         ior->io_Error = 1;
  292.         ReplyMsg(ior);
  293.     }
  294.     }
  295. #ifdef DEBUG
  296.     puts("DONE1");
  297. #endif
  298. done:
  299.     FixSignal(chan);
  300.     if (chan->eof)
  301.     SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
  302. #ifdef DEBUG
  303.     printf("RETURN %ld\n", len);
  304. #endif
  305.     return(len);
  306. }
  307.  
  308. /*BREAKUP   dread.bc    */
  309.  
  310.  
  311. DRead(chan, buf, bytes)
  312. char *buf;
  313. CHANN *chan;
  314. {
  315.     long len = 0;
  316.     long n = -1;
  317.  
  318.     if (chan->eof)
  319.     return(-1);
  320.     while (bytes) {
  321.     if (n == 0)
  322.         WaitPort(chan);
  323.     n = DNRead(chan, buf, bytes);
  324.     if (n < 0)
  325.         break;
  326.     len += n;
  327.     buf += n;
  328.     bytes -= n;
  329.     if (chan->eof)
  330.         break;
  331.     }
  332.     return(len);
  333. }
  334.  
  335. /*BREAKUP   dq.bc    */
  336.  
  337.  
  338. DQueue(chan, n)
  339. CHANN *chan;
  340. {
  341.     chan->qlen = n;
  342. }
  343.  
  344. /*BREAKUP   dwr.bc    */
  345.  
  346.  
  347. DWrite(chan, buf, bytes)
  348. CHANN *chan;
  349. {
  350.     int error = bytes;
  351.  
  352.     if (chan->qlen) {
  353.     if (WaitQueue(chan, NULL) >= 0) {
  354.         register IOR *ior = AllocMem(sizeof(IOR), MEMF_CLEAR|MEMF_PUBLIC);
  355.         ior->io_Command = DNCMD_WRITE;
  356.         ior->io_Unit = (void *)chan->chan;
  357.         ior->io_Offset = (long)chan;
  358.         ior->io_Message.mn_ReplyPort = (PORT *)chan;
  359.         ior->io_Data = AllocMem(bytes, MEMF_PUBLIC);
  360.         ior->io_Length = bytes;
  361.         CopyMem(buf, ior->io_Data, bytes);
  362.         PutMsg(chan->dnetport, ior);
  363.         ++chan->queued;
  364.     } else {
  365.         error = -1;
  366.     }
  367.     } else {
  368.     IOR ior;
  369.     ior.io_Command = DNCMD_WRITE;
  370.     ior.io_Unit = (void *)chan->chan;
  371.     ior.io_Offset = (long)chan;
  372.     ior.io_Message.mn_ReplyPort = (PORT *)chan;
  373.     ior.io_Data = (APTR)buf;
  374.     ior.io_Length = bytes;
  375.     PutMsg(chan->dnetport, &ior);
  376.     WaitMsg(&ior);
  377.     if (ior.io_Error)
  378.         error = -1;
  379.     }
  380.     FixSignal(chan);
  381.     return(error);
  382. }
  383.  
  384. /*BREAKUP   deof.bc    */
  385.  
  386.  
  387. DEof(chan)
  388. CHANN *chan;
  389. {
  390.     IOR ior;
  391.  
  392.     ior.io_Command = DNCMD_EOF;
  393.     ior.io_Unit = (void *)chan->chan;
  394.     ior.io_Offset = (long)chan;
  395.     ior.io_Message.mn_ReplyPort = (PORT *)chan;
  396.     PutMsg(chan->dnetport, &ior);
  397.     WaitMsg(&ior);
  398.     FixSignal(chan);
  399. }
  400.  
  401. /*BREAKUP   dioc.bc    */
  402.  
  403.  
  404. DIoctl(chan, cmd, val, aux)
  405. CHANN *chan;
  406. ubyte cmd;
  407. uword val;
  408. ubyte aux;
  409. {
  410.     IOR ior;
  411.  
  412.     ior.io_Command = DNCMD_IOCTL;
  413.     ior.io_Unit = (void *)chan->chan;
  414.     ior.io_Offset = (long)chan;
  415.     ior.io_Message.mn_ReplyPort = (PORT *)chan;
  416.     ior.io_Data = (APTR)(long)((val<<16)|(aux<<8)|cmd);
  417.     PutMsg(chan->dnetport, &ior);
  418.     WaitMsg(&ior);
  419.     FixSignal(chan);
  420. }
  421.  
  422. /*BREAKUP   dst.bc    */
  423.  
  424.  
  425. DStat(host, buffer, max)
  426. char *host;
  427. APTR buffer;
  428. {
  429.     IOR ior;
  430.     char buf[sizeof(DNETPORTNAME)+32];
  431.     PORT *replyport = CreatePort(NULL, 0);
  432.     PORT *dnetport;
  433.  
  434.     if (!host)
  435.     host = "0";
  436.     sprintf(buf, "%s%s", DNETPORTNAME, host);
  437.     if (dnetport = FindPort(buf)) {
  438.     ior.io_Command = DNCMD_INFO;
  439.     ior.io_Unit = 0;
  440.     ior.io_Offset = 0;
  441.     ior.io_Data = buffer;
  442.     ior.io_Message.mn_ReplyPort = replyport;
  443.     PutMsg(dnetport, &ior);
  444.     WaitMsg(&ior);
  445.     DeletePort(replyport);
  446.     }
  447.     return(dnetport != NULL);
  448. }
  449.  
  450. /*BREAKUP   dqu.bc    */
  451.  
  452.  
  453. DQuit(host)
  454. char *host;
  455. {
  456.     IOR ior;
  457.     char buf[sizeof(DNETPORTNAME)+32];
  458.     PORT *replyport = CreatePort(NULL, 0);
  459.     PORT *dnetport;
  460.  
  461.     if (!host)
  462.     host = "0";
  463.     sprintf(buf, "%s%s", DNETPORTNAME, host);
  464.     if (dnetport = FindPort(buf)) {
  465.     ior.io_Command = DNCMD_QUIT;
  466.     ior.io_Unit = 0;
  467.     ior.io_Offset = 0;
  468.     ior.io_Message.mn_ReplyPort = replyport;
  469.     PutMsg(dnetport, &ior);
  470.     WaitMsg(&ior);
  471.     DeletePort(replyport);
  472.     }
  473.     return(dnetport != NULL);
  474. }
  475.  
  476. /*BREAKUP   dcl.bc    */
  477.  
  478.  
  479. DClose(chan)
  480. CHANN *chan;
  481. {
  482.     IOR ior;
  483.     IOR *io;
  484.  
  485.     ior.io_Command = DNCMD_CLOSE;
  486.     ior.io_Unit = (void *)chan->chan;
  487.     ior.io_Offset = (long)chan;
  488.     ior.io_Message.mn_ReplyPort = (PORT *)chan;
  489.     PutMsg(chan->dnetport, &ior);
  490.     ++chan->queued;
  491.     chan->qlen = 0;
  492.     WaitQueue(chan, &ior);
  493.     while ((io = RemHead(&chan->rdylist)) || (io = GetMsg(chan))) {
  494.     io->io_Error = 1;
  495.     ReplyMsg(io);
  496.     }
  497.     DeleteChannel(chan);
  498. }
  499.  
  500. /*BREAKUP   wq.bc    */
  501.  
  502. WaitQueue(chan, skipior)
  503. CHANN *chan;
  504. IOR *skipior;
  505. {
  506.     register IOR *io;
  507.     short error = 0;
  508.     while (chan->queued > chan->qlen) {     /*  until done  */
  509.     WaitPort(chan);                     /*  something   */
  510.     io = (IOR *)GetMsg(chan);
  511.     if (io->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
  512.         if (error == 0)
  513.         error = io->io_Error;
  514.         if (io != skipior) {
  515.         if (io->io_Length)
  516.             FreeMem(io->io_Data, io->io_Length);
  517.         FreeMem(io, sizeof(IOR));
  518.         }
  519.         --chan->queued;
  520.     } else {
  521.         AddTail(&chan->rdylist, io);
  522.     }
  523.     }
  524.     return(error);
  525. }
  526.  
  527. /*BREAKUP   mkchan.bc    */
  528.  
  529.  
  530. CHANN *
  531. MakeChannel(ior, host)
  532. register IOR *ior;
  533. char *host;
  534. {
  535.     CHANN *chan = AllocMem(sizeof(CHANN), MEMF_PUBLIC|MEMF_CLEAR);
  536.  
  537.     /*    Name, Pri */
  538.     chan->port.mp_Node.ln_Type = NT_MSGPORT;
  539.     chan->port.mp_SigBit = AllocSignal(-1);
  540.     chan->port.mp_SigTask = FindTask(NULL);
  541.     NewList(&chan->port.mp_MsgList);
  542.     NewList(&chan->rdylist);
  543.     chan->chan = (long)ior->io_Unit;
  544.     ior->io_Offset = (long)chan;
  545.     if (host) {
  546.     char buf[sizeof(DNETPORTNAME)+32];
  547.     sprintf(buf, "%s%s", DNETPORTNAME, host);
  548.     ior->io_Message.mn_ReplyPort = FindPort(buf);
  549.     }
  550.     chan->dnetport = ior->io_Message.mn_ReplyPort;
  551.     return(chan);
  552. }
  553.  
  554. /*BREAKUP   delchan.bc      */
  555.  
  556.  
  557. DeleteChannel(chan)
  558. CHANN *chan;
  559. {
  560.     FreeSignal(chan->port.mp_SigBit);
  561.     FreeMem(chan, sizeof(CHANN));
  562. }
  563.  
  564. /*BREAKUP   fixsig.bc    */
  565.  
  566. FixSignal(chan)
  567. register CHANN *chan;
  568. {
  569.     if (chan->port.mp_MsgList.lh_Head != (NODE *)&chan->port.mp_MsgList.lh_Tail ||
  570.     chan->rdylist.lh_Head != (NODE *)&chan->rdylist.lh_Tail)
  571.     SetSignal(1 << chan->port.mp_SigBit, 1 << chan->port.mp_SigBit);
  572. }
  573.  
  574. /*BREAKUP   getev.bc    */
  575.  
  576. GetEnvVal(str)
  577. char *str;
  578. {
  579.     char *ptr = GetDEnv(str);
  580.     long val = 0;
  581.  
  582.     if (ptr)
  583.     val = atoi(ptr);
  584.     free(ptr);
  585.     return(val);
  586. }
  587.  
  588. /*BREAKUP   cfg.bc    */
  589.  
  590. /*
  591.  *  CONFIGURATION FILE EXTRACTION
  592.  */
  593.  
  594. static FILE *Fi;
  595.  
  596. OpenCfgFile()
  597. {
  598.     CloseCfgFile();
  599.     Fi = fopen("s:dnet.config", "r");
  600. }
  601.  
  602. char *
  603. GetCfgLine(what)
  604. char *what;
  605. {
  606.     static char Buf[128];
  607.     register char *ptr;
  608.     if (Fi) {
  609.     while (fgets(Buf, sizeof(Buf), Fi)) {
  610.         if (BCmp(Buf, what, 4) == 0) {
  611.         Buf[strlen(Buf)-1] = 0;
  612.         for (ptr = Buf + 4; *ptr == ' ' || *ptr == 9; ++ptr);
  613.         return(ptr);
  614.         }
  615.     }
  616.     }
  617.     return(NULL);
  618. }
  619.  
  620. CloseCfgFile()
  621. {
  622.     if (Fi)
  623.     fclose(Fi);
  624.     Fi = NULL;
  625. }
  626.  
  627. GetOneCfg(what)
  628. char *what;
  629. {
  630.     char *str;
  631.     OpenCfgFile();
  632.     str = GetCfgLine(what);
  633.     CloseCfgFile();
  634. }
  635.  
  636. ExtractFieldVal(str, field, pidx)
  637. char *str, *field;
  638. short *pidx;
  639. {
  640.     short idx = (pidx) ? *pidx : 0;
  641.     short flen = strlen(field);
  642.  
  643.     while (*str) {
  644.     if (strncmp(str, field, flen) == 0) {
  645.         if (pidx)
  646.         *pidx = idx + flen;    /*  past the field but not the val */
  647.         return(atoi(str + flen));
  648.     }
  649.     ++str;
  650.     ++idx;
  651.     }
  652.     return(-1);
  653. }
  654.  
  655. /*BREAKUP   prg.bc  */
  656.  
  657. char *Program = "";  /*  settable by other progs     */
  658.  
  659. /*BREAKUP   elog.bc    */
  660.  
  661.  
  662. _elog(line, file, how, ctl, data)
  663. char *file;
  664. char *ctl;
  665. {
  666.     static char *logfile;
  667.     FILE *fi;
  668.  
  669.     if (logfile == NULL) {
  670.     OpenCfgFile();
  671.     logfile = GetCfgLine("LOGF");
  672.     CloseCfgFile();
  673.     }
  674.     if (logfile && (fi = fopen(logfile, "a"))) {
  675.     char *hdr = "?";
  676.     switch(how) {
  677.     case EFATAL:
  678.         hdr = "Fatal";
  679.         break;
  680.     case EWARN:
  681.         hdr = "Warn";
  682.         break;
  683.     case EDEBUG:
  684.         hdr = "Debug";
  685.         break;
  686.     }
  687.     fprintf(fi, "%s %s.%s/%ld ", hdr, Program, file, line);
  688.     fprintf(fi, ctl, data);
  689.     putc('\n', fi);
  690.     fclose(fi);
  691.     }
  692. }
  693.  
  694.