home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / DataScope 2.0.3 / DataScope2l / DSSource / fnet.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-04  |  20.4 KB  |  887 lines  |  [TEXT/MPS ]

  1. /*
  2. *
  3. *  This code depends on MacTCP, Apple's TCP/IP driver for the Mac.
  4. *  It uses the NCSA Telnet networking kernel and session services.  As such,
  5. *  it requires a config.tel file in the system folder or the same folder as
  6. *  the application.
  7. *
  8. */
  9.  
  10. #include <resources.h>
  11. #include "macfview.h"
  12. #include "DScope.h"
  13.  
  14. #define CNONE 0
  15. #define CWAIT 1
  16. #define COPEN 2
  17. #define CSIZE 3
  18. #define CREAD 4
  19. #define CSEND 5
  20. #define CDONE 6
  21.  
  22. struct nets {
  23. int 
  24.     pnum,                     /* port number */
  25.     toread,                    /* remaining data to be read */
  26.     constat;                /* status of connection */
  27.     struct fdatawin *td;    /* keeper of window data */
  28. char 
  29.     replace,                /* boolean for replacing dataset */
  30.     image,                    /* boolean for generating images */
  31.     interp,
  32.     polar,
  33.     filesave,                /* boolean flag for saving to a file */
  34.     flags[20],                /* flags for what to do with data */
  35.     *whereread;                /* keep track of data reading/writing */
  36. };
  37.  
  38. static struct nets gin,gout,*gcur;    /* keeping track */
  39. static char buf[128];
  40. char netfailed=0;
  41.  
  42.  
  43. #define GETPORT 7799
  44.  
  45. /**********************************************************************/
  46. /*  donetevents
  47. *   This routine should be called in the main event loop.  It handles
  48. *   background networking tasks like the data server which accepts data
  49. *   from other hosts.  It reads the network event queue to discover what
  50. *   to do this time around.
  51. */
  52. donetevents()
  53. {
  54.     int code;
  55.     
  56.     if (netfailed)
  57.         return;
  58.  
  59.     if (gin.constat == CNONE) {
  60.         startlisten();
  61.         return;
  62.     }
  63.     
  64.     code = handlenet();
  65.     
  66.     gcur = &gin;
  67.     if (gin.constat >= COPEN)
  68.         processevents();                /* background data receiver */
  69. }
  70.  
  71. /**********************************************************************/
  72. /*  processevents
  73. *   Implement the DataScope data server.
  74. *   As soon as the connection opens and data begins to arrive, this
  75. *   procedure is called. Data must fit the required protocol, or the connection
  76. *   is closed automatically.
  77. *
  78. *   Numbers must be in Motorola (network) byte order before they arrive.
  79. *   Floating point numbers must be in IEEE32 bit format before they arrive.
  80. *   ASCII strings (nul terminated) are used for flags and var names.
  81. *
  82. *   Command-period stops any of the network waits used.  Otherwise, there
  83. *   are no internal time-outs.
  84. *
  85. *   The only check for illegal numbers used in the protocol is whether
  86. *   you run out of memory on the array allocate.  Otherwise the data goes
  87. *   where it may.
  88. */
  89.  
  90. processevents()
  91. {
  92.     int cnt,i,xd,yd;
  93.     char checktype[5];
  94.     float *flp;
  95.     struct fdatawin *ttd;
  96.     
  97.  
  98.     if (gcur->constat == COPEN/* && 4 <= netqlen(gcur->pnum)*/) {
  99.         
  100.         while (4 > netqlen (gcur->pnum))
  101.             ;
  102.     
  103.         cnt = netread(gcur->pnum,checktype,4);        /* tag type */
  104.         
  105.         if (cnt == 4 && !strncmp(checktype,"DSa1",4)) {/* DS data array */
  106.             gcur->constat = CSIZE;
  107.             readtonul(gcur->pnum,buf,100);            /* read var name */
  108.             readtonul(gcur->pnum,gcur->flags,20);    /* read flags field */
  109.             checkflags(gcur);
  110.         }
  111.     }
  112.     else if (gcur->constat == CSIZE && 16 <= netqlen(gcur->pnum)) {
  113.  
  114. /*
  115. *  Get particulars about array to be read.
  116. *  Dimensions first.  Must be 2-D arrays.
  117. */
  118.         cnt = 0;
  119.         cnt += netread(gcur->pnum,&yd,4);        /* array dimensions */
  120.         cnt += netread(gcur->pnum,&xd,4);        /* array dimensions */
  121.         
  122.         if (xd <= 1 || yd <= 1 ||                /* illegal values ? */
  123.             getpointers(gcur,buf,xd,yd)) {        /* decide where to put data */
  124.             gcur->constat = CNONE;
  125.             netclose(gcur->pnum);
  126.             return(-1);
  127.         }
  128. /*
  129. *  Maximum and minimum values of interest are first floats to arrive.
  130. */
  131.         ttd = gcur->td;
  132.         cnt += netread(gcur->pnum,&gcur->td->valmax,4);
  133.         cnt += netread(gcur->pnum,&gcur->td->valmin,4);
  134. /*
  135. *  read row and column labels all at once.
  136. */
  137.         if (fullread(gcur->pnum,gcur->td->yvals,4*yd) ||
  138.             fullread(gcur->pnum,gcur->td->xvals,4*xd)) {
  139.             gcur->constat = CNONE;
  140.             netclose(gcur->pnum);
  141.             return(-1);
  142.         }
  143. /*
  144. *  read array in the background, using events to keep us alive.
  145. *  Setting up status bytes for the read here.
  146. */
  147.         gcur->constat = CREAD;
  148.         gcur->whereread = (char *)gcur->td->vals;
  149.         gcur->toread = xd*yd*4;            /* number of bytes to read from net */
  150.             
  151.                 
  152.     }
  153.     
  154. /*
  155. *  Control is returned to us for a background read.
  156. *  Read whatever is in the incoming buffer and return control to event loop.
  157. */
  158.     else if (gcur->constat == CREAD) {
  159.         cnt = netread(gcur->pnum,gcur->whereread,gcur->toread);
  160.         if (cnt < 0) {
  161.             gcur->constat = CNONE;
  162.             losedat(gcur->td);
  163.             netclose(gcur->pnum);
  164.             return(-1);
  165.         }
  166.         gcur->toread -= cnt;                /* update state counters */
  167.         gcur->whereread += cnt;                /* where data goes */
  168.         
  169. /*
  170. *   If we have all of the data, install it into the window list.
  171. */
  172.         if (gcur->toread <= 0) {
  173.             gcur->constat = COPEN;
  174.             
  175.             if (gcur->replace && gcur->td->text) {
  176.                 setwtitle(gcur->td->text->win,gcur->td->dvar);
  177.                 drawfloat(gcur->td->text,0,0);    /* update old window */
  178.             }
  179.             else
  180.                 ctextwin(gcur->td);                /* create a new one */
  181.  
  182. /*
  183. *  If max and min are wrong, re-calculate.
  184. */
  185.             if (gcur->td->valmax <= gcur->td->valmin) {
  186.                 maxmin( gcur->td->vals, gcur->td->xdim, gcur->td->ydim,
  187.                         &gcur->td->valmax, &gcur->td->valmin, 0,0, 
  188.                         gcur->td->ydim, gcur->td->xdim);
  189.             }
  190.             
  191. /*
  192. *  If image generate is on, generate an image from it.
  193. */
  194.             if (gcur->image && gcur->td->text)
  195.                 makeimage(gcur->td->text);
  196.  
  197. /*
  198. *  If interp generate is on, generate a smoothed image from it.
  199. */
  200.             if (gcur->interp && gcur->td->text)
  201.                 interpit(gcur->td->text);
  202. /*
  203. *  If polar generate is on, generate a polar image from it.
  204. */
  205.             if (gcur->polar && gcur->td->text)
  206.                 polarit(gcur->td->text);
  207. /*
  208. *  If filesave is on, save a copy to a file.
  209. */
  210.             if (gcur->filesave && gcur->td->text) {
  211.                 short v;
  212.                 char s[256];
  213.                 getvol(s,&v);
  214.                 create(gcur->td->dvar, v, 'NCSf', '_HDF');
  215.                 savedf(gcur->td->dvar,gcur->td);
  216.             }
  217.         }
  218.     }
  219.     
  220.     return(0);
  221.         
  222. }
  223.  
  224. /**********************************************************************/
  225. /*  getpointers
  226. *   If the replace flag is on, see if the variable can be replaced.
  227. *   If not, or if no replace flag, allocate memory for a new window.
  228. *   Installs variable name and fname if allocating new memory.
  229. */
  230. getpointers(g,name,xd,yd)
  231.     struct nets *g;
  232.     char *name;
  233.     int xd,yd;
  234. {
  235.     struct Mwin *m;
  236.     extern struct Mwin *Mlist;
  237.     int i;
  238.     
  239.     m = NULL;
  240.  
  241. /*
  242. *  Do filename munging similar to what newdatawin does to put in
  243. *  underscores where needed.
  244. */
  245.     for (i=strlen(name)-1; i > 0 && name[i] == ' '; i--)    /* trim trailing spaces */
  246.             name[i] = 0;
  247.     name[sizeof(gcur->td->dvar)-1] = 0;        /* trim it to required length */
  248.     
  249.     for (i=0; i< strlen(name); i++)
  250.         if (!isalnum(name[i]))
  251.             name[i] = '_';            /* translate periods and spaces to _ */
  252.  
  253. /*
  254. *  If replace flag is on and all checks out, don't allocate the memory.
  255. */
  256.     if (g->replace) {
  257.  
  258. /*
  259. *  Search for matching variable name and check dimensions.
  260. */
  261.         m = Mlist;
  262.         
  263.         while (m) {
  264.             if (!replacecmp(m->dat->dvar,name) &&
  265.                 m->dat->xdim == xd &&
  266.                 m->dat->ydim == yd)    {
  267.                 gcur->td = m->dat;                    /* set struct pointer */
  268.                 strcpy(gcur->td->dvar,name);        /* save new name */
  269.                 break;
  270.             }
  271.             m = m->next;
  272.         }
  273.     }
  274.  
  275. /*
  276. *    don't have it, have to allocate memory
  277. */
  278.     if (!m) {
  279.  
  280.         gcur->replace = 0;                    /* we cannot do replace */
  281.         
  282.         gcur->td = newdatawin(name,xd,yd);    /* allocates all mem */
  283.         if (NULL == gcur->td)                 /* we failed */
  284.             return(-1);
  285.                                 
  286.         strcpy(gcur->td->fname,gcur->td->dvar);
  287.     }
  288.     
  289.     return(0);
  290.         
  291. }
  292.  
  293. /************************************************************************/
  294. /*  replacecmp
  295. *   Ignore upper and lower case, but only check as far as the alphanumerics
  296. *   match.  Allows filenames like xx.001, xx.002, xx.003  etc. to replace
  297. *
  298. *   Only returns 0=match, 1=no match, does not compare greater or less
  299. *   There is a tiny bit of overlap with the | 32 trick, but shouldn't be
  300. *   a problem.  It causes some different symbols to match.
  301. */
  302. replacecmp(sa,sb)
  303.     char *sa,*sb;
  304.     {
  305.  
  306.     while (*sa && *sa < 33)        /* don't compare leading spaces */
  307.         sa++;
  308.     while (*sb && *sb < 33)
  309.         sb++;
  310.  
  311.     while (*sa && *sb && isalnum(*sa) && isalnum(*sb)) {
  312.         if ((*sa != *sb) && ((*sa | 32) != (*sb | 32)))
  313.             return(1);
  314.         sa++;sb++;
  315.     }
  316.     if ((!*sa && !*sb) ||        /* if both at end of string */
  317.         (*sa == *sb))            /* or hit identical non-alnums */
  318.         return(0);
  319.     else
  320.         return(1);
  321. }
  322.  
  323. /**********************************************************************/
  324. /*  checkflags
  325. *  Taking the string of one-character flags, set booleans in the
  326. *  net structure according to what flags are found.  Set flags to 
  327. *  the default settings otherwise.
  328. *
  329. */
  330. checkflags(g)
  331.     struct nets *g;
  332. {
  333.     char *p;
  334.     
  335.     p = g->flags;
  336.     
  337.     g->replace = 0;
  338.     g->image = 0;
  339.     g->interp = 0;
  340.     g->filesave = 0;
  341.     g->polar = 0;
  342.     
  343.     while (*p) {                /* search flags string, set booleans */
  344.         if (*p == 'R')
  345.             g->replace = 1;
  346.         if (*p == 'G')            /* most are same as command-keys in DS */
  347.             g->image = 1;
  348.         if (*p == 'S')
  349.             g->filesave = 1;
  350.         if (*p == 'I')
  351.             g->interp = 1;
  352.         if (*p == 'P')
  353.             g->polar = 1;
  354.         p++;
  355.     }
  356.     
  357. }
  358.             
  359.  
  360. /**********************************************************************/
  361. /*
  362. *  netfunction
  363. *  Used to execute a DataScope notebook function when we don't have the
  364. *  function on the local machine.
  365. *  Send the parameters to a remote machine to be executed.
  366. *  Get the answer back.
  367. *
  368. *  Uses rexecd to submit a password-checked job request.
  369. */
  370. extern 
  371.     char *exuser,*exmachine,*expass;
  372. extern
  373.     int exconnect;
  374.     
  375. netfunction(name,lft,rgt,answer)
  376.     char            *name;
  377.     scope_array        *lft,*rgt,*answer;
  378. {
  379.     int                itemp,code,i,cnt,ac,ar,startanswer;
  380.     char            checktype[256];
  381.     void            ErrorAlert();
  382.     
  383.     gcur = &gout;
  384.     
  385.     /* get setup info, Mac style */
  386.     
  387.     if (exremote(name) || !exuser || !exmachine) {    /* User canceled dialog */
  388.         answer->kind = DS_ERROR;
  389.         ErrorAlert(GetResource('STR ',1007));
  390.         return(-1);
  391.     }
  392.         
  393.     tryconnect(exmachine,exconnect);
  394.  
  395.     while (gcur->constat != COPEN) {
  396.         code = handlenet();
  397.         
  398.         /*  if either network rejects it or user quits */
  399.         
  400.         if (gcur->constat == CNONE || calcidle()) {
  401.             answer->kind = DS_ERROR;
  402.             ErrorAlert(GetResource('STR ',1008));
  403.             
  404.             if (gcur->constat != CNONE)
  405.                 netclose(gcur->pnum);
  406.             return(-1);
  407.         }
  408.     }
  409.     
  410.     netwrite(gcur->pnum,"0\0",2);                    /* write opening */
  411.     netwrite(gcur->pnum,exuser,strlen(exuser)+1);    /* write user name */
  412.     netwrite(gcur->pnum,expass,strlen(expass)+1);    /* and password */
  413.     netwrite(gcur->pnum,"./DS_serve\0",11);            /* the command to run */
  414.  
  415. /*
  416. *  We now sit and wait for TWO zero characters.
  417. *  The first zero character comes from the rexecd to show that it could
  418. *  launch the shell successfully.
  419. *  The second one comes from the DataScope server which is required to send
  420. *  one zero character to indicate that it is ready to receive a function 
  421. *  and its data.
  422. *  If either the shell or the server returns an error message, this
  423. *  section will determine that there are not two zeros and report the 
  424. *  characters, whatever they may be to the user.  It is assumed to be a
  425. *  human-readable error message.
  426. */
  427.     cnt = 0;
  428.     memset(checktype, 0, 255);
  429.  
  430.     do {                                        /* look for go-ahead signal */
  431.         if (calcidle()) {
  432.             answer->kind = DS_ERROR;
  433.             ErrorAlert(GetResource('STR ',1007));
  434.             netclose(gcur->pnum);
  435.             return(-1);
  436.         }
  437.     
  438.         code = handlenet();
  439.         cnt = netqlen(gcur->pnum);                /* how much data has arrived? */
  440.  
  441.     } while (gcur->constat == COPEN && cnt >= 0 && cnt < 2);
  442.     
  443.     cnt = netqlen(gcur->pnum);
  444.     netread(gcur->pnum,checktype,cnt);
  445.  
  446.     if (checktype[0] || checktype[1]) {
  447.         answer->kind = DS_ERROR;
  448.         netclose(gcur->pnum);
  449.         if (!checktype[0])
  450.             checktype[0] = ':';                    /* indicate shell was OK */
  451.         ErrorAlert(GetResource('STR ',1004));
  452.         netalert(checktype);                    /* tell user */
  453.         return(-1);
  454.     }
  455.  
  456. /*
  457. *  Start sending over the stuff we need to transfer.
  458. *
  459. *  1. The transfer code 'DSfn'
  460. *  2. The name of the function to be calculated.
  461. *  3. The left parameter.  Could be an array or constant.
  462. *  4. The right parameter.  Could be an array or constant.
  463. *
  464. *  If there is an error at any time, check to see if the other side sent
  465. *  us any type of error message about it.
  466. */
  467.  
  468.     if ((4 > netwrite(gcur->pnum,"DSfn",4)) ||                /* transfer code */
  469.         (0 > netwrite(gcur->pnum,name,strlen(name)+1)) ||     /* nul terminated name */    
  470.         netparm(gcur->pnum,lft) ||    /* send one parm */
  471.         netparm(gcur->pnum,rgt)) {    /* send other parm */
  472.  
  473.         if (0 < (i = netqlen(gcur->pnum)))            /* received any messages? */
  474.             netread(gcur->pnum,checktype,i);
  475.             
  476.         answer->kind = DS_ERROR;
  477.         ErrorAlert(GetResource('STR ',1006));
  478.         netclose(gcur->pnum);
  479.         
  480.         if (i > 0)
  481.             netalert(checktype);                    /* tell the user */
  482.  
  483.         return(-1);
  484.     }
  485.  
  486. /**************************************************************************/
  487. /*
  488. *  This is the pause while we wait for the other side to do the
  489. *  computation.  It could be awhile.
  490. */
  491.     startanswer = 0;
  492.  
  493.     do {                            /* look for answer */
  494.         if (calcidle()) {
  495.             answer->kind = DS_ERROR;
  496.             netclose(gcur->pnum);
  497.             ErrorAlert(GetResource('STR ',1007));
  498.             return(-1);
  499.         }
  500.     
  501.         code = handlenet();
  502.  
  503.         if (code == 4)                 /* got some data back */
  504.             startanswer = 1;
  505.             
  506.         if (startanswer) {            /* keep checking until we are done now */
  507.                     
  508.             if (gcur->constat == COPEN && 4 <= netqlen(gcur->pnum)) {
  509.             
  510.                 cnt = netread(gcur->pnum,checktype,4);        /* tag type */
  511.                 
  512.                 if (cnt == 4  && !strncmp(checktype,"DSfn",4))    {            /* DS data array */
  513.                     gcur->constat = CSIZE;
  514.                 }
  515.                 else {                        
  516.                     if (0 < (i = netqlen(gcur->pnum)))        /* received any messages? */
  517.                         netread(gcur->pnum,&checktype[4],i);
  518.                     answer->kind = DS_ERROR;
  519.                     netclose(gcur->pnum);
  520.                     netalert(checktype);                    /* tell the user */
  521.                     ErrorAlert(GetResource('STR ',1006));
  522.                     return(-1);
  523.                 }
  524.             }
  525.             else if (gcur->constat == CSIZE && 13 <= netqlen(gcur->pnum)) {
  526.             
  527.                 cnt = netread(gcur->pnum,&answer->kind,1);
  528.                 cnt = netread(gcur->pnum,&answer->cval,4);
  529.                 cnt = netread(gcur->pnum,&ar,4);
  530.                 cnt = netread(gcur->pnum,&ac,4);
  531.     /*
  532.     *  receive answering array, if we have one
  533.     */
  534.                 if (answer->kind == DS_ARRAY) {
  535.                     answer->kind = DS_ERROR;
  536.                     itemp = 1;
  537.                     if (answer->ncols == ac &&
  538.                         answer->nrows == ar &&
  539.                         !fullread(gcur->pnum,answer->rows,4*answer->nrows) &&
  540.                         !fullread(gcur->pnum,answer->cols,4*answer->ncols) &&
  541.                         !fullread(gcur->pnum,
  542.                                   answer->vals,
  543.                                   4*answer->nrows*answer->ncols))
  544.                        {answer->kind = DS_ARRAY;
  545.                         itemp = 0;
  546.                        }
  547.                 }    
  548.                 
  549.                 gcur->constat = CDONE;
  550.                 netclose(gcur->pnum);            /* done with calcs */
  551.                 if (itemp == 1)    ErrorAlert(GetResource('STR ',1005));
  552.                 return(0);
  553.             }
  554.         }
  555.     
  556.     } while (gcur->constat != CNONE);
  557.     
  558.     answer->kind = DS_ERROR;
  559.     ErrorAlert(GetResource('STR ',1004));
  560.     netclose(gcur->pnum);
  561.     return(-1);
  562.     
  563. }
  564.  
  565. /**********************************************************************/
  566. /* readtonul
  567. *  read from the stream until reaching a NUL
  568. *
  569. *  limit includes the NULL byte at end, will not overrun, lim==0 is not
  570. *  allowed.
  571. */
  572. readtonul(skt,p,lim)
  573.     int skt,lim;
  574.     char *p;
  575.     {
  576.     char cc;
  577.     int ret;
  578.  
  579.     *p = 0;
  580.  
  581.     do {
  582.         if (calcidle())            /* allow processor time */
  583.             return(-1);
  584.         handlenet();            /* take care of net events */
  585.  
  586.         while ((ret = netread(skt,&cc,1)) == 0);
  587.         
  588.         if (0 > ret)
  589.             return(-1);
  590.             
  591.         *p++ = cc;
  592.  
  593.         if (--lim <= 0)
  594.             p--;                /* keep from overrunning */
  595.  
  596.     } while (ret && cc);
  597.  
  598.     return(0);
  599. }
  600.  
  601. /**********************************************************************/
  602. /*  fullwrite
  603. *   write a full segment to the network.
  604. *   Check for user interrupt while doing so.
  605. *   returns 0 for successful send, -1 for error in sending or user interrupt.
  606. */
  607. fullwrite(skt,wherewrite,towrite)
  608.     int skt,towrite;
  609.     char *wherewrite;
  610. {
  611.     int cnt;
  612.  
  613.     while (towrite > 0) {            /* count of remaining bytes to send */
  614.         if (calcidle())                /* check for user interrupt */
  615.             return(-1);
  616.  
  617.         cnt = netwrite(skt,wherewrite,towrite);        /* send a chunk */
  618.         if (cnt < 0)                /* connection broken */
  619.             return(-1);
  620.  
  621.         towrite -= cnt;                /* adjust counters for what was sent */
  622.         wherewrite += cnt;
  623.     }
  624.  
  625.     return(0);
  626. }
  627.  
  628. /**********************************************************************/
  629. /*  fullread
  630. *   read a full segment from the network.
  631. *   Check for user interrupt while doing so.
  632. *   returns 0 for success, -1 for error in reading or user interrupt.
  633. */
  634. fullread(skt,whereread,toread)
  635.     int skt,toread;
  636.     char *whereread;
  637. {
  638.     int cnt;
  639.  
  640.     while (toread > 0) {            /* count of remaining bytes to read */
  641.         if (calcidle())                /* check for user interrupt */
  642.             return(-1);
  643.         handlenet();                /* take care of net events */
  644.  
  645.         cnt = netread(skt,whereread,toread);        /* read a chunk */
  646.         if (cnt < 0)                /* connection broken */
  647.             return(-1);
  648.  
  649.         toread -= cnt;                /* adjust counters for what was read */
  650.         whereread += cnt;
  651.     }
  652.  
  653.     return(0);
  654. }
  655.  
  656. /**********************************************************************/
  657. /*  netparm
  658. *  Write one of the function parameters to the remote host.
  659. */
  660. netparm(skt,sar)
  661.     int skt;
  662.     scope_array *sar;
  663. {
  664.     
  665.     while (16 > netroom(skt))        /* room for small stuff? */
  666.         if (calcidle())
  667.             return(-1);
  668.     
  669.     netwrite(skt,&sar->kind,1);        /* type of argument */
  670.     netwrite(skt,&sar->cval,4);        /* constant value, 0.0 if not used */
  671.     netwrite(skt,&sar->nrows,4);    /* number of rows */
  672.     netwrite(skt,&sar->ncols,4);    /* number of columns, 0 if not used? */
  673.  
  674.     if (sar->kind == DS_ARRAY) {    /* send the array over */
  675.     
  676.         if (fullwrite(skt,(char *)sar->rows, 4*sar->nrows))
  677.             return(-1);
  678.             
  679.         if (fullwrite(skt,(char *)sar->cols, 4*sar->ncols))
  680.             return(-1);
  681.  
  682.         if (fullwrite(skt,(char *)sar->vals, 4*sar->ncols*sar->nrows))
  683.             return(-1);
  684.     
  685.     }
  686.     
  687.     return(0);
  688. }
  689.  
  690. /**********************************************************************/
  691. /*
  692. *   fnet.c
  693. *   TCP/IP stubs for the NCSA TCP/IP kernel.
  694. *
  695. *   This version assumes MacTCP support.
  696. */
  697. #include "whatami.h"
  698. #include "hostform.h"
  699.  
  700. struct machinfo *mp;
  701. char *neterrstring();
  702.  
  703. startnet() {
  704. /*
  705. *  assumes MacTCP because we didn't worry about setting IP number.
  706. */
  707.     if (Snetinit()) {            /* call session initialization */
  708.         errhandle();            /* Snetinit() reads config.tel file */
  709.         netfailed = 1;
  710.         return(-1);
  711.     }
  712.     
  713.     return(0);
  714. }
  715.  
  716. stopnet()
  717. {
  718.     if (gin.constat > 1)
  719.         netclose(gin.pnum);
  720.         
  721.     netshut();
  722.     
  723.     gin.constat = 0;
  724. }
  725.  
  726. startlisten()
  727.     {
  728.     
  729.     gin.pnum = netlisten(GETPORT);
  730.     gin.constat = CWAIT;
  731.     gin.toread = 0;
  732.     
  733.     SetCursor(&qd.arrow);
  734. }
  735.  
  736. tryconnect(m,tcport)
  737.     char *m;
  738.     int tcport;
  739. {
  740.  
  741.     gcur->constat=CWAIT;        /* attempting connection */
  742.     
  743.     mp = Sgethost(m);            /* look up in hosts cache */
  744.     if (!mp)
  745.         gcur->pnum = Sdomain(m);        /* not in hosts, try domain */
  746.     else {
  747.         if (0 > (gcur->pnum = Snetopen(mp,tcport))) {
  748.             errhandle();
  749.             netshut();
  750.             return(-1);
  751.         }
  752.     }
  753.     
  754.     return(0);
  755.     
  756. }
  757.  
  758.  
  759. handlenet()
  760. {
  761.     int i,cnt,ev,what,dat;
  762.     char *errmsg;
  763.  
  764. /*
  765. *  get event from network, these two classes return all of the events
  766. *  of user interest.
  767. */
  768.     ev = Sgetevent(USERCLASS | CONCLASS | ERRCLASS,&what,&dat);
  769.     if (!ev)
  770.         return(0);
  771.  
  772.     if (what == ERRCLASS) {                /* error event */
  773.         errmsg = neterrstring(dat);
  774.         putln(errmsg);
  775.     }
  776.     else if (what == CONCLASS) {        /* event of user interest */
  777.         switch (ev) {
  778.             case CONOPEN:                /* connection opened or closed */
  779.                 if (dat == gin.pnum)
  780.                     gin.constat = COPEN;
  781.                 else if (dat == gout.pnum)
  782.                     gout.constat = COPEN;
  783.                 break;
  784.             default:
  785.                 break;
  786.             case CONDATA:                /* data arrived for me */
  787.                 if (dat == gin.pnum)
  788.                     return(3);
  789.                 else if (dat == gout.pnum)
  790.                     return(4);
  791.                 else
  792.                     return(-1);
  793.                 break;
  794.                 
  795.             case CONFAIL:
  796.                 if (dat == gin.pnum)
  797.                     gin.constat = CNONE;
  798.                 else if (dat == gout.pnum)
  799.                     gout.constat = CNONE;
  800.                 netalert("Cannot connect to requested host");
  801.                 return(-1);
  802.                 
  803.             case CONCLOSE:
  804.                 if (0 < netqlen(dat))
  805.                     netputuev(CONCLASS,CONCLOSE,dat);    /* repost back to me */
  806.                     
  807.                 else if (dat == gin.pnum) {
  808.                     netclose(gin.pnum);
  809.                     startlisten();            /* restart listener */
  810.                 }
  811.                 else if (dat == gout.pnum)
  812.                     gout.constat = CNONE;    /* indicate close */
  813.                 return(-1);
  814.  
  815.         }
  816.     }
  817.     else if (what == USERCLASS) {
  818.         switch (ev) {
  819.             case DOMOK:                        /* domain worked */
  820.                 mp = Slooknum(dat);            /* get machine info */
  821.                 i = Snetopen(mp,exconnect);    /* open to host name */
  822.                 if (dat == gin.pnum)
  823.                     gin.pnum = i;
  824.                 else if (dat == gout.pnum)
  825.                     gout.pnum = i;
  826.                 break;
  827.             case DOMFAIL:    /* domain failed */
  828.                 if (dat == gin.pnum)
  829.                     gin.constat = CNONE;
  830.                 else if (dat == gout.pnum)
  831.                     gout.constat = CNONE;
  832.                 netalert("Cannot find address of requested host");
  833.                 return(-1);
  834.             default:
  835.                 break;
  836.         }
  837.     }
  838.  
  839.     return(0);
  840.  
  841. }
  842.  
  843.  
  844. /*********************************************************************/
  845. /*  errhandle
  846. *   write error messages to the console window
  847. */
  848. errhandle()
  849.     {
  850.     char *errmsg;
  851.     int i,j;
  852.  
  853.     while (ERR1 == Sgetevent(ERRCLASS,&i,&j)) {
  854.         errmsg = neterrstring(j);
  855.         netalert(errmsg);                /* tell user */
  856.     }
  857.  
  858. }
  859.  
  860. putln(s)
  861.     char *s;
  862.     {
  863.     
  864.     /* puts(s); */
  865.     
  866. }
  867.  
  868. quit()
  869.     { /* exit(2) ; */
  870.         netfailed = 1;
  871.         }
  872.     
  873. isHFS()
  874.     {
  875.     return(1);
  876.     }
  877.     
  878. DisplayMacBinary()
  879.     {  }
  880.     
  881.  
  882. initipnum()
  883.     { }
  884.     
  885.  
  886. int KIP=0;
  887.