home *** CD-ROM | disk | FTP | other *** search
/ kermit.columbia.edu / kermit.columbia.edu.tar / kermit.columbia.edu / uniflex / ufutil.c < prev   
C/C++ Source or Header  |  1993-08-22  |  16KB  |  636 lines

  1. #include "ufk.h"
  2. #include <pwd.h>
  3. #include <sgtty.h>
  4. #include <signal.h>
  5. #include <setjmp.h>
  6. #include <stat.h>
  7.  
  8. /*
  9.  * split command line into seperate strings
  10.  */
  11.  
  12. split(cmd_str)
  13. char  *cmd_str;
  14. {
  15.    char  *malloc();
  16.    char  pass,
  17.          *p,
  18.          *q,
  19.          result[128];
  20.  
  21.    numprm = 0;                          /* no parameters yet */
  22.    for (pass = 0; pass < 2; pass++)     /* find # of params in pass 1 */
  23.    {                                    /* alloc pointer array and store */
  24.       if (pass > 0)                     /* pointers in pass 2 */
  25.       {
  26.          if ((params = malloc(numprm * sizeof(char *))) == NULL)
  27.          {               /* allocate space for pointer array to parameters */
  28.             prterr(ER_NOMEM);
  29.             kerm_exit();
  30.          }
  31.          numprm = 0;                    /* restart scan */
  32.       }
  33.       p = cmd_str;                      /* setup pointer to input string */
  34.       while (*p && (*p != COMMENT))     /* do till end of string */
  35.       {
  36.          while (isspace(*p))              /* strip leading white space */
  37.             p++;
  38.          if (pass > 0)
  39.          {
  40.             sscanf(p, "%s", result);      /* get part of input string */
  41.             if ((q = malloc(strlen(result) + 1)) == NULL) /* get str space */
  42.             {
  43.                prterr(ER_NOMEM);
  44.                kerm_exit();
  45.             }
  46.             strcpy(q, result);            /* copy part to allocated memory */
  47.             params[numprm] = q;           /* save pointer to string */
  48.          }
  49.          numprm++;                        /* one more */
  50.          while ((!isspace(*p)) && *p)     /* skip to end of this string */
  51.             p++;
  52.       }
  53.    }
  54.    return (TRUE);
  55. }
  56.  
  57. /*
  58.  * parse command components
  59.  */
  60.  
  61. parse(command_string, table)
  62. char *command_string;
  63. TABLE table[];
  64. {
  65.    char  i = 0,
  66.          j;
  67.    int   mstat,
  68.          cmd_num = 0,
  69.          tv = 0,
  70.          unique = FALSE;
  71.  
  72.    make_lower(command_string);         /* convert to lower case */
  73.    while (*table[i].string)            /* do until end of command table */
  74.    {
  75.       mstat = match(table[i].string, command_string); /* do compare */
  76.       if (mstat == -1)
  77.          return (table[i].funcadr);    /* exact match found */
  78.       if (mstat != 0)                  /* some characters did match */
  79.       {
  80.          if (mstat > tv)               /* longer than so far ? */
  81.          {
  82.             tv = mstat;                /* save longest length */
  83.             cmd_num = i;               /* remember which command */
  84.             unique = TRUE;             /* it's unique so far */
  85.          }
  86.          j = i;
  87.          while (*table[++j].string)    /* start new search from next entry */
  88.          {
  89.             mstat = match(table[j].string, command_string); /* other match ? */
  90.             if (mstat == -1)
  91.                return (table[j].funcadr); /* exact match */
  92.             if (mstat != 0)            /* some characters did match */
  93.             {
  94.                if (mstat > tv)         /* longer than so far ? */
  95.                {
  96.                   tv = mstat;          /* save greatest length */
  97.                   cmd_num = i;         /* remember which command */
  98.                   unique = TRUE;       /* it's unique so far */
  99.                }
  100.                if (mstat == tv)        /* another one of the same length ? */
  101.                   unique = FALSE;      /* yes, it's not unique anymore */
  102.             }
  103.          }
  104.          if (!unique)                  /* if it was'nt unique it's ambiguous */
  105.             return (NULL);
  106.          else
  107.             return (table[cmd_num].funcadr); /* else it's a valid command */
  108.       }
  109.       i++;                             /* try next entry */
  110.    }
  111.    if (cmd_num == 0)
  112.       return (ERROR);                  /* no such command */
  113.    else return (table[cmd_num].funcadr); /* return command number */
  114. }
  115.  
  116. match(s, t)
  117. char *s, *t;
  118. {
  119.    int   len = 0,
  120.          inputlen;
  121.  
  122.    inputlen = strlen(t);               /* length of input command */
  123.    while (*s)                          /* do until end of string */
  124.    {
  125.       if (*s++ != *t++)                /* if no match */
  126.       {
  127.          if (inputlen == 0)            /* total command checked */
  128.             return (len);              /* return matched length */
  129.          else
  130.             return (0);                /* no match for this command */
  131.       }
  132.       len++;                           /* one more character done */
  133.       --inputlen;                      /* count down input string length */
  134.    }
  135.    return (-1);                        /* full match found */
  136. }
  137.  
  138. /*
  139.  *  m a k e _ u p p e r
  140.  *
  141.  *  Convert string to upper case
  142.  */
  143.  
  144. make_upper(p)
  145. char  *p;
  146. {
  147.    while (*p)
  148.    {
  149.       if (islower(*p))
  150.          *p = toupper(*p);
  151.       p++;
  152.    }
  153. }
  154.  
  155. /*
  156.  *  m a k e _ l o w e r
  157.  *
  158.  *  Convert string to lower case
  159.  */
  160.  
  161. make_lower(p)
  162. char *p;
  163. {
  164.    while (*p)
  165.    {
  166.       if (isupper(*p))
  167.          *p = tolower(*p);
  168.       p++;
  169.    }
  170. }
  171.  
  172. /*
  173.  *  p r e r r p k t
  174.  *
  175.  *  Print contents of error packet received from remote host.
  176.  */
  177. prerrpkt(msg)
  178. char  *msg;
  179. {
  180.    if (!nooutput)
  181.    {
  182.       disp(0,19,"Kermit aborting with following error from remote host:");
  183.       foreground();
  184.       disp(0,20,msg);
  185.       background();
  186.       beep();
  187.    }
  188. }
  189.  
  190. /*
  191.  * send ASCII file to remote without protocol.
  192.  * handshake is used.
  193.  */
  194.  
  195. jmp_buf trn_env;
  196.  
  197. trnsmit()
  198. {
  199.    FILE *xmitfp;
  200.    char c1;
  201.    int  c, trnsm_int();
  202.    struct sgttyb mode;
  203.  
  204.    if (numprm <= 1)                       /* check for parameters */
  205.       prterr(ER_FSPCREQ);
  206.    else
  207.    {
  208.       if ((xmitfp = fopen(params[1], "r")) == NULL)
  209.          prterr(ER_OPENERR);
  210.       else
  211.       {
  212.          if (!open_port(FALSE,FALSE))
  213.             prterr(ER_POPNERR);
  214.          else
  215.          {
  216.             signal(SIGINT,trnsm_int);
  217.             if (!setjmp(trn_env))
  218.                while ((c = getc(xmitfp)) != EOF) /* get character from file */
  219.                {
  220.                   if (debug)
  221.                      putc(c, stdout);         /* send to console as well */
  222.                   gtty(ttyfd,&mode);
  223.                   if (mode.sg_speed & INCHR)
  224.                   {
  225.                      read(ttyfd,&c1,1);       /* Check received character */
  226.                      if ((c1 & 0177) == dstop && dstop != 0)/* Stop chr ? */
  227.                         do                    /* Yes */
  228.                            read(ttyfd,&c1,1); /* Wait for next character */
  229.                         while ((c1 & 0177) != dstart);/* Wait for start chr */
  230.                   }
  231.                   c1 = c;       /* Only high byte of int would be send (=0) */
  232.                   write(ttyfd,&c1,1);         /* Send to output port */
  233.                }
  234.             else
  235.                if (debug)
  236.                   fputs("\n",stdout);
  237.             fclose(xmitfp);
  238.             kdelay(1);                      /* Give the port time to finish */
  239.             close_port(FALSE,FALSE);
  240.          }
  241.       }
  242.    }
  243. }
  244.  
  245. trnsm_int()
  246. {
  247.    longjmp(trn_env,TRUE);               /* Transmit interrupted... */
  248. }
  249.  
  250.  
  251. /*
  252.  * Read KERMIT commands from file
  253.  */
  254.  
  255. take(fspec,echo)
  256. char *fspec, echo;
  257. {
  258.    FILE *tfp;
  259.    char  data[133],                       /* Command input */
  260.          fname[80];
  261.  
  262.    if (fspec == NULL)
  263.    {
  264.       if (numprm > 1)
  265.          strcpy(fname, params[1]);
  266.       else
  267.          return(prterr(ER_FSPCREQ));
  268.    }
  269.    else
  270.       strcpy(fname,fspec);
  271.  
  272.    if ((tfp = fopen(fname,"r")) != NULL)    /* Look for command file */
  273.    {                                        /* Found file, read commands */
  274.       while (fgets(data,132,tfp))
  275.       {
  276.          if (echo)
  277.          {
  278.             fputs(prompt,stdout);           /* Echo prompt */
  279.             fputs(data,stdout);             /* Echo command */
  280.          }
  281.          data[strlen(data) - 1] = '\0';     /* Zap newline */
  282.          if (data[0] && data[0] != COMMENT) /* Not a blank line */
  283.             kerm_command(data);             /* Do command */
  284.       }
  285.       fclose(tfp);
  286.    }
  287.    else
  288.    {
  289.       if (fspec == NULL)
  290.          return(prterr(ER_OPENERR));
  291.       else
  292.          return(ER_OPENERR);
  293.    }
  294.    return(NULL);
  295. }
  296.  
  297. /*
  298.  * call UniFLEX to perform external command
  299.  */
  300.  
  301. do_uniflex()
  302. {
  303.    static char *shell = { "/bin/shell" };
  304.    static char *opt = { "+xc" };
  305.    char *prm[4],
  306.         *p,
  307.         cmdline[256];
  308.    int i,
  309.        kerm_exit();
  310.  
  311.    prm[0] = &shell[5];                  /* setup program name */
  312.    prm[1] = prm[3] = 0;                 /* end of parameters pointer */
  313.    if (numprm > 1)
  314.    {
  315.       prm[1] = opt;                     /* one shot option */
  316.       prm[2] = p = cmdline;             /* pointers to start of commandline */
  317.       for (i = 1; i < numprm; i++)
  318.       {
  319.          strcpy(p,params[i]);           /* copy params into one line */
  320.          p += strlen(p);                /* point after command */
  321.          *p++ = ' ';                    /* separator */
  322.       }
  323.       *p = '\0';                        /* end of string */
  324.    }
  325.    if (!fork())                         /* duplicate myself */
  326.    {
  327.       execvp(shell,prm);                /* execute command in child */
  328.       prterr(ER_SPAWN);                 /* should not come here */
  329.    }
  330.    else
  331.    {
  332.       signal(SIGTERM,SIG_IGN);          /* Ignore this signals */
  333.       signal(SIGHUP,SIG_IGN);
  334.       signal(SIGQUIT,SIG_IGN);
  335.       signal(SIGINT,SIG_IGN);
  336.       wait(0);                          /* wait for child to die */
  337.       signal(SIGTERM,kerm_exit);        /* Set signals again */
  338.       signal(SIGHUP,kerm_exit);
  339.       signal(SIGQUIT,SIG_DFL);          /* Make these default */
  340.       signal(SIGINT,SIG_DFL);
  341.    }
  342. }
  343.  
  344. disk_free()
  345. {
  346.    char dev[30];
  347.    long size;
  348.  
  349.    if (numprm <= 1)
  350.       strcpy(dev,".");               /* use current place if not specified */
  351.    else
  352.       strcpy(dev,params[1]);         /* use specified place */
  353.    if ((size = get_free(dev)) != -1l)/* if no error... */
  354.       printf("Number of free blocks: %ld (%ld bytes)\n",size, size * 512);
  355. }
  356.  
  357.  
  358. chd()
  359. {
  360.    struct passwd *p;
  361.  
  362.    if (numprm <= 1)
  363.    {
  364.       if ((p = getpwuid(getuid())) == NULL)
  365.          prterr(ER_GETPWDID);
  366.       chdir(p->pw_dir);
  367.       set_dir(p->pw_dir);
  368.    }
  369.    else
  370.    {
  371.       if (chdir(params[1]) == ERROR)
  372.          prterr(ER_INVDIR);
  373.       else
  374.          set_dir(params[1]);
  375.    }
  376. }
  377.  
  378.  
  379. /*
  380.  * show statistics about connection
  381.  */
  382.  
  383. statistics()
  384. {
  385.    static char s1[] = "Characters sent:\t\t%ld\n";
  386.    static char s2[] = "Data characters sent:\t\t%ld\n";
  387.    static char s3[] = "NAK's sent:\t\t\t%d\n";
  388.    static char s4[] = "Packets sent:\t\t\t%d\n";
  389.    static char s5[] = "Characters received:\t\t%ld\n";
  390.    static char s6[] = "Data characters received:\t%ld\n";
  391.    static char s7[] = "NAK's received:\t\t\t%d\n";
  392.    static char s8[] = "Packets received:\t\t%d\n";
  393.  
  394.    printf("Totals for the last transfer:\n\n");
  395.    printf(s1, chr_sent);
  396.    printf(s2, dchr_sent);
  397.    printf(s3, nak_sent);
  398.    printf(s4, pack_sent);
  399.    printf(s5, chr_rec);
  400.    printf(s6, dchr_rec);
  401.    printf(s7, nak_rec);
  402.    printf(s8, pack_rec);
  403.    printf("Effective data rate:\t\t%d baud\n", data_rate);
  404.    printf("\nTotals since KERMIT was started:\n\n");
  405.    printf(s1, t_chr_sent);
  406.    printf(s2, t_dchr_sent);
  407.    printf(s3, t_nak_sent);
  408.    printf(s4, t_pack_sent);
  409.    printf(s5, t_chr_rec);
  410.    printf(s6, t_dchr_rec);
  411.    printf(s7, t_nak_rec);
  412.    printf(s8, t_pack_rec);
  413.    printf("Mean effective data rate:\t%d baud\n", t_data_rate);
  414. }
  415.  
  416. #define  POLYIT  0x8408       /* Polynomial for CRC-CCITT */
  417. #define  POLY16  0xa001       /* Polynomial for CRC-16 (not used here) */
  418.  
  419. unsigned int crc_value, crc[256];    /* Global accessible variables */
  420.  
  421. init_crc_table()
  422. {
  423.    int count, nr;
  424.    unsigned int accum, crcch;
  425.  
  426.    for (count = 0; count < 256; count++)     /* Build CRC lookup table */
  427.    {
  428.       accum = 0;
  429.       crcch = count;
  430.       for (nr = 0; nr < 8; nr++)
  431.       {
  432.          if (((accum & 0xff) ^ crcch) & 1)
  433.             accum = (accum / 2) ^ POLYIT;
  434.          else
  435.             accum = (accum / 2);
  436.          crcch = (crcch / 2);
  437.       }
  438.       crc[count] = accum;                 /* Save calculated value in table */
  439.    }
  440. }
  441.  
  442. zero_crc()
  443. {
  444.    crc_value = 0;                         /* Initial value is zero */
  445. }
  446.  
  447. unsigned int calc_crc(value)
  448. unsigned char value;
  449. {
  450.    crc_value = crc[value ^ (crc_value & 0xff)] ^ ((crc_value >> 8) & 0xff);
  451.    return crc_value;                      /* Return accumulated value so far */
  452. }
  453.  
  454. beep()
  455. {
  456.    if (!remote && !nooutput)
  457.       putc(BELL,stdout);
  458. }
  459.  
  460. disp(x,y,string)
  461. int x,y;
  462. char *string;
  463. {
  464.    if (!remote)
  465.    {
  466.       posit(x,y);
  467.       fputs(string,stdout);
  468.       if (!screen && !nooutput)
  469.          fputs("\n",stdout);
  470.    }
  471. }
  472.  
  473. set_frame()
  474. {
  475.    if (screen && !remote && !nooutput)
  476.    {
  477.       clear_screen();
  478.       posit(28,0);
  479.       foreground();
  480.       fprintf(stdout," KERMIT version %s ",VERSION);
  481.       background();
  482.       if (sflg || rflg)
  483.       {
  484.          disp(0,4,"Transferred:");
  485.          disp(27,4,"Percentage:");
  486.       }
  487.       disp(0,6,"Packet received:");
  488.       disp(0,7,"Packet transmitted:");
  489.       if (debug >= 1)
  490.       {
  491.          disp(0,9,"Data received:");
  492.          disp(0,11,"Data transmitted:");
  493.          disp(0,13,"Receive state:");
  494.          disp(36,13,"Send state:");
  495.          disp(27,6,"Type:");
  496.          disp(27,7,"Type:");
  497.          disp(37,6,"Length:");
  498.          disp(37,7,"Length:");
  499.          disp(50,6,"Checksum:");
  500.          disp(50,7,"Checksum:");
  501.       }
  502.       curs_off();                       /* Turn off cursor */
  503.    }
  504. }
  505.  
  506. disp_state(x,y,state)
  507. int x,y;
  508. char state;
  509. {
  510.    static char sa[] = "Attribute   ";
  511.    static char sb[] = "Break       ";
  512.    static char sc[] = "Complete    ";
  513.    static char sd[] = "Data        ";
  514.    static char sf[] = "Filename    ";
  515.    static char sq[] = "Abort       ";
  516.    static char sr[] = "Receive init";
  517.    static char ss[] = "Send init   ";
  518.    static char st[] = "Timeout     ";
  519.    static char sz[] = "End of file ";
  520.    static char un[] = "Unknown     ";
  521.    char dsc[5];
  522.  
  523.    if (debug == 2)
  524.       strcpy(dsc,"%s\r");
  525.    else
  526.       strcpy(dsc,"%s\r\l");
  527.    posit(x,y);
  528.    switch(state)
  529.    {
  530.       case 'A':
  531.                   prtdbg(dsc,sa);
  532.                   break;
  533.       case 'B':
  534.                   prtdbg(dsc,sb);
  535.                   break;
  536.       case 'C':
  537.                   prtdbg(dsc,sc);
  538.                   break;
  539.       case 'D':
  540.                   prtdbg(dsc,sd);
  541.                   break;
  542.       case 'F':
  543.                   prtdbg(dsc,sf);
  544.                   break;
  545.       case 'Q':
  546.                   prtdbg(dsc,sq);
  547.                   break;
  548.       case 'R':
  549.                   prtdbg(dsc,sr);
  550.                   break;
  551.       case 'S':
  552.                   prtdbg(dsc,ss);
  553.                   break;
  554.       case 'T':
  555.                   prtdbg(dsc,st);
  556.                   break;
  557.       case 'Z':
  558.                   prtdbg(dsc,sz);
  559.                   break;
  560.       default:
  561.                   prtdbg(dsc,un);
  562.    }
  563. }
  564.  
  565. prtdbg(fmt, a1, a2, a3, a4, a5, a6)
  566. char *fmt;
  567. {
  568.    if ((debug >= 1) && !remote)
  569.       fprintf(stdout,fmt,a1,a2,a3,a4,a5,a6);
  570.    if (debug == 2)
  571.       fprintf(dbgfil,fmt,a1,a2,a3,a4,a5,a6);
  572. }
  573.  
  574. prtdbgf(fmt, a1, a2, a3, a4, a5, a6)
  575. char *fmt;
  576. {
  577.    if (debug == 2)
  578.       fprintf(dbgfil,fmt,a1,a2,a3,a4,a5,a6);
  579. }
  580.  
  581. map_case(name,mode)
  582. char *name;
  583. int mode;
  584. {
  585.    if (mapping)
  586.    {
  587.       if (mode == IN)
  588.          make_lower(name);
  589.       else if (mode == OUT)
  590.          make_upper(name);
  591.    }
  592. }
  593.  
  594. new_name(s)
  595. char *s;
  596. {
  597.    struct stat buf;
  598.    int num;
  599.    char new_str[15],
  600.         num_str[5];
  601.  
  602.    num = 0;
  603.    do                                   /* Construct new filename */
  604.    {                                    /* until new name not found */
  605.       if (num++ > 4095)                 /* Bump counter */
  606.       {
  607.          error(PER_CREATE,"%s",new_str);/* FATAL error */
  608.          kerm_exit();                   /* More than 4096 files ??? */
  609.       }
  610.       strncpy(new_str,s,10);            /* Copy 10 characters at most */
  611.       new_str[10] = '\0';               /* Truncate at position 10 */
  612.       sprintf(num_str,".%03x",num);     /* Format new filename */
  613.       strcat(new_str,num_str);
  614.    }
  615.    while (!stat(new_str,&buf));         /* If it exists, try again */
  616.    strcpy(s,new_str);                   /* Save new filename */
  617. }
  618.  
  619. synerr(threshold)
  620. int threshold;
  621. {
  622.    if ((threshold != 0) && (numprm >= threshold))
  623.       return FALSE;
  624.    prterr(ER_SYNERR);
  625.    return TRUE;
  626. }
  627.  
  628. check_bg()
  629. {
  630.    int oldsig;
  631.  
  632.    oldsig = signal(SIGINT,SIG_IGN);     /* Get old KBD signal */
  633.    signal(SIGINT,oldsig);               /* Restore */
  634.    return oldsig;                       /* TRUE if we're in the background */
  635. }
  636.