home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / gkermit.tar.gz / gku100.tar / gcmdline.c < prev    next >
C/C++ Source or Header  |  1999-12-26  |  10KB  |  367 lines

  1. /*  G C M D L I N  --  gkermit command line parser  */
  2.  
  3. /*
  4.   Author:
  5.     Frank da Cruz
  6.     The Kermit Project
  7.     Columbia University
  8.     612 West 115th Street
  9.     New York NY 10025-7799  USA
  10.     http://www.columbia.edu/kermit/
  11.     kermit@columbia.edu
  12.  
  13.   Copyright (C) 1999,
  14.   The Trustees of Columbia University in the City of New York.
  15.  
  16.   This program is free software; you can redistribute it and/or modify
  17.   it under the terms of the GNU General Public License as published by
  18.   the Free Software Foundation; either version 2 of the License, or
  19.   (at your option) any later version.
  20.  
  21.   This program is distributed in the hope that it will be useful,
  22.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  23.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  24.   GNU General Public License for more details.
  25.  
  26.   You should have received a copy of the GNU General Public License
  27.   along with this program; if not, write to the Free Software
  28.   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  29. */
  30.  
  31. #include <stdio.h>
  32. #include "gkermit.h"
  33.  
  34. /* Externals */
  35.  
  36. extern int nfils, parity, text, backup, rpsiz, urpsiz, timint;
  37. extern int literal, quiet, keep, streamok, nomodes, manual, xonxoff, noxonxoff;
  38. extern char ttname[], *cmerrp, *cmarg, *cmarg2;
  39. extern FILE * db;
  40.  
  41. /* Variables exported from this module */
  42.  
  43. extern char **cmlist;            /* Pointer to file list in argv */
  44. extern char **xargv;            /* Global copies of argv */
  45. extern int xargc;            /* and argc  */
  46.  
  47. /* Variables and symbols local to this module */
  48.  
  49. static int action = 0;            /* Action selected on command line */
  50.  
  51. _MYPROTOTYPE( static int doarg, (char) );
  52. _MYPROTOTYPE( VOID fatal, (char *) );
  53. _MYPROTOTYPE( VOID usage, (void) );
  54.  
  55. #ifndef NOGETENV
  56. _MYPROTOTYPE( char * getenv, (char *) );
  57. #define GARGC 32
  58. #define GBUFSIZ 256
  59. static char gbuf[GBUFSIZ], *gargs[GARGC], *gptr = NULL;
  60. static int gargc;
  61. #endif /* NOGETENV */
  62.  
  63. int                    /* Command-line parser */
  64. cmdlin() {
  65.     char c;
  66.     int x;
  67. #ifndef NOGETENV
  68.     char * p = NULL;
  69. #endif /* NOGETENV */
  70.  
  71.     cmarg = "";                /* Initialize results */
  72.     cmlist = NULL;
  73.     action = 0;
  74.  
  75. #ifndef NOGETENV
  76.     if ((p = getenv("GKERMIT"))) {
  77.     int i, xc, flag = 0;
  78.     char **xv = NULL;
  79.  
  80.     strncpy(gbuf,p,GBUFSIZ-1);    /* Make a pokeable copy */
  81.     gbuf[GBUFSIZ-1] = NUL;
  82.     gptr = p;
  83.     p = gbuf;
  84.  
  85.     /* Turn it into an argument vector */
  86.  
  87.     for (i = 0; gbuf[i] && i < GBUFSIZ && gargc < GARGC; i++) {
  88.         if (!flag) {
  89.         if (gbuf[i] <= SP)
  90.           continue;
  91.         flag = 1;
  92.         gargs[gargc++] = &gbuf[i];
  93.         } else if (flag && gbuf[i] <= SP) {
  94.         gbuf[i] = NUL;
  95.         flag = 0;
  96.         continue;
  97.         }
  98.     }
  99.     xv = xargv;            /* Save original argument vector */
  100.     xc = xargc;
  101.     xargv = gargs;            /* Redirect it to the one we made */
  102.     xargc = gargc;
  103.  
  104.     while (xargc-- > 0) {        /* Go through the words */
  105.         if (**xargv == '-') {    /* Got an option (begins with dash) */
  106.         c = *(*xargv+1);    /* Get the option letter */
  107.         x = doarg(c);        /* Go handle the option */
  108.         if (x < 0) doexit(1);
  109.         } else {            /* No dash where expected */
  110.         fprintf(stderr,
  111.             "?GKERMIT variable option error: \"%s\"\n",
  112.             *xargv
  113.             );
  114.         usage();        /* Give usage message */
  115.         doexit(0);
  116.         }
  117.         xargv++;
  118.     }
  119.     xargv = xv;            /* Restore original argument vector */
  120.     xargc = xc;
  121.     }
  122. #endif /* NOGETENV */
  123.  
  124.     while (--xargc > 0) {        /* Go through command line words */
  125.     xargv++;
  126.         if (**xargv == '-') {        /* Got an option (begins with dash) */
  127.         c = *(*xargv+1);        /* Get the option letter */
  128.         x = doarg(c);        /* Go handle the option */
  129.         if (x < 0) doexit(1);
  130.         } else {            /* No dash where expected */
  131.         fprintf(stderr,"?Command-line option error: \"%s\"\n", *xargv);
  132.         usage();            /* Give usage message */
  133.         doexit(1);
  134.     }
  135.     }
  136.     return(action);            /* Then do any requested protocol */
  137. }
  138.  
  139. /*  D O A R G  --  Do a command-line argument.  */
  140.  
  141. static int
  142. #ifdef __STDC__
  143. doarg(char x)
  144. #else
  145. doarg(x) char x;
  146. #endif /* __STDC__ */
  147. {
  148.     int z; char *xp, **p;
  149.  
  150.     xp = *xargv+1;            /* Pointer for bundled args */
  151.     while (x) {
  152.     switch (x) {
  153.       case 'r':            /* Receive */
  154.         if (action) fatal("conflicting actions");
  155.         action = 'v';
  156.         break;
  157.  
  158.       case 's':            /* Send */
  159.         if (action) fatal("conflicting actions");
  160.         if (*(xp+1)) fatal("invalid argument bundling after -s");
  161.         nfils = 0;            /* Initialize file counter, flag */
  162.         cmlist = xargv+1;        /* Remember this pointer */
  163.         if (zchki(*cmlist) < 0)
  164.           fatal("file not found or not accessible");
  165.         while (--xargc > 0) {    /* Traverse the list */
  166.         *xargv++;
  167.         if (**xargv == '-')
  168.           break;
  169.         nfils++;
  170.         }
  171.         xargc++, *xargv--;        /* Adjust argv/argc */
  172.         if (nfils < 1) fatal("missing filename for -s");
  173.         action = 's';
  174.         break;
  175.  
  176.       case 'g':            /* get */
  177.         if (action) fatal("conflicting actions");
  178.         if (*(xp+1)) fatal("invalid argument bundling after -g");
  179.         *xargv++, xargc--;
  180.         if ((xargc == 0) || (**xargv == '-'))
  181.           fatal("missing filename for -g");
  182.         cmarg = *xargv;
  183.         action = 'r';
  184.         break;
  185.  
  186.       case 'h':            /* Help */
  187.       case '?':
  188.         usage();
  189.         doexit(0);
  190.  
  191.       case 'i':            /* Binary (image) file transfer */
  192.         manual = 1;
  193.         text = 0;
  194.         break;
  195.  
  196.       case 'T':            /* Text file transfer */
  197.         manual = 1;
  198.         text = 1;
  199.         break;
  200.  
  201.       case 'p':            /* Parity */
  202.         if (*(xp+1)) fatal("invalid argument bundling");
  203.         *xargv++, xargc--;
  204.         if ((xargc < 1) || (**xargv == '-'))
  205.           fatal("missing parity");
  206.         switch(x = **xargv) {
  207.           case 'e':            /* Even */
  208.           case 'o':            /* Odd */
  209.           case 'm':            /* Mark */
  210.           case 's': parity = x; break; /* Space */
  211.           case 'n': parity = 0; break; /* None */
  212.           default:  fatal("invalid parity");
  213.         }
  214.         break;
  215.  
  216.       case 'w':            /* Writeover */
  217.         backup = 0;            /* Don't back up existing files */
  218.         break;
  219.  
  220.       case 'd':            /* Debug */
  221.         p = xargv;
  222.         *p++;
  223.         if ((xargc < 2) || (**p == '-')) {
  224.         db = fopen("debug.log","w");
  225.         } else {
  226.         *xargv++, xargc--;
  227.         db = fopen(*xargv,"w");
  228.         }
  229.         if (db) {
  230.         extern char * versio, * build;
  231.         if (!versio) versio = "";
  232.         if (!build) build = "";
  233.         debug = 1;
  234.         setbuf(db,NULL);
  235.         fprintf(db,"%s: %s\n",
  236.             (*versio ? versio : "GKERMIT VERSION UNKNOWN"),
  237.             (*build ? build : "BUILD UNKNOWN")
  238.             );
  239.         fprintf(db,"MAXPATHLEN = %d\n",MAXPATHLEN);
  240.         if (gptr) fprintf(db,"GKERMIT=\"%s\"\n",gptr);
  241.         }
  242.         break;
  243.  
  244.       case 'a':            /* As-name */
  245.         if (*(xp+1)) fatal("invalid argument bundling after -a");
  246.         *xargv++, xargc--;
  247.         if ((xargc == 0) || (**xargv == '-'))
  248.           fatal("missing name for -a");
  249.         cmarg2 = *xargv;
  250.         if (debug) fprintf(db,"as-name: %s\n",cmarg2);
  251.         break;
  252.  
  253.       case 'e':
  254.         if (*(xp+1)) fatal("invalid argument bundling after -e");
  255.         xargv++, xargc--;
  256.         if ((xargc < 1) || (**xargv == '-'))
  257.           fatal("missing length");
  258.         z = atoi(*xargv);        /* Convert to number. */
  259.         if (z >= 40 && z <= MAXRP) {
  260.         rpsiz = urpsiz = z;
  261.         if (z > 94) rpsiz = 94;    /* Fallback if other Kermit can't */
  262.         } else {            /* do long packets. */
  263.         fatal("Unsupported packet length");
  264.         }
  265.         break;
  266.  
  267.       case 'b':            /* Timeout */
  268.         if (*(xp+1)) fatal("invalid argument bundling after -b");
  269.         xargv++, xargc--;
  270.         if ((xargc < 1) || (**xargv == '-'))
  271.           fatal("missing value");
  272.         z = atoi(*xargv);        /* Convert to number */
  273.         if (z < 0) z = 0;
  274.         if (z > 90) z = 90;
  275.         timint = z;
  276.         break;
  277.  
  278.       case 'P':            /* Path (file) names literal */
  279.         literal = 1;
  280.         break;
  281.  
  282.       case 'q':            /* Quiet */
  283.         quiet = 1;
  284.         break;
  285.  
  286.       case 'K':            /* Keep incompletely received files */
  287.         keep = 1;
  288.         break;
  289.  
  290.       case 'S':            /* Disable streaming */
  291.         streamok = -1;
  292.         break;
  293.  
  294.       case 'X':            /* gkermit is an external protocol */
  295.         quiet = 1;            /* No messages */
  296.             nomodes = 1;        /* Don't set tty modes */
  297.         break;
  298.  
  299.       case 'x':            /* Force Xon/Xoff */
  300.         xonxoff = 1;
  301.         noxonxoff = 0;
  302.         break;
  303.  
  304.       case '-':            /* Don't force Xon/Xoff */
  305.         if (*(xp+1) == 'x') {
  306.         xonxoff = 0;
  307.         noxonxoff = 1;
  308.         } else {
  309.         fatal("invalid argument, type 'gkermit -h' for help");
  310.         }
  311.         xp++;
  312.         break;
  313.  
  314.       default:            /* Anything else */
  315.         fatal("invalid argument, type 'gkermit -h' for help");
  316.         }
  317.     x = *++xp;            /* See if options are bundled */
  318.     }
  319.     if (debug) {
  320.     if (action)
  321.       fprintf(db,"cmdlin action = %c\n",action);
  322.     else
  323.       fprintf(db,"cmdlin action = (none)\n");
  324.     }
  325.     return(action);
  326. }
  327.  
  328. VOID
  329. fatal(msg) char *msg; {            /* Fatal error message */
  330.     fprintf(stderr,"\r\nFatal: %s",msg); /* doexit supplies crlf.. */
  331.     doexit(1);                /* Exit indicating failure */
  332. }
  333.  
  334. VOID
  335. usage() {
  336.     extern char * versio, * build, * url, * email;
  337.     if (!versio) versio = "";
  338.     if (!*versio) versio = "gkermit UNKNOWN VERSION";
  339.     if (!build) build = "UNKNOWN BUILD";
  340.     if (!url) url = "";
  341.     if (!email) email = "";
  342.     fprintf(stderr,"%s: %s.\n",versio,build);
  343.     fprintf(stderr,"Usage:  gkermit [ options ]\n");
  344.     fprintf(stderr,"Options:\n");
  345.     fprintf(stderr," -r      Receive files\n");
  346.     fprintf(stderr," -s fn   Send files\n");
  347.     fprintf(stderr," -g fn   Get files from server\n");
  348.     fprintf(stderr," -a fn   As-name for single file\n");
  349.     fprintf(stderr," -i      Image (binary) mode transfer\n");
  350.     fprintf(stderr," -T      Text mode transfer\n");
  351.     fprintf(stderr," -P      Path/filename conversion disabled\n");
  352.     fprintf(stderr," -w      Write over existing files with same name\n");
  353.     fprintf(stderr," -K      Keep incompletely received files\n");
  354.     fprintf(stderr," -p x    Parity: x = o[dd],e[ven],m[ark],s[pace],n[one]\n")
  355.       ;
  356.     fprintf(stderr," -e n    Receive packet-length (40-%d)\n",MAXRP);
  357.     fprintf(stderr," -b n    Timeout (sec, 0 = none)\n");
  358.     fprintf(stderr," -x      Force Xon/Xoff (--x = Don't force Xon/Xoff)\n");
  359.     fprintf(stderr," -S      Disable streaming\n");
  360.     fprintf(stderr," -X      External protocol\n");
  361.     fprintf(stderr," -q      Quiet (suppress messages)\n");
  362.     fprintf(stderr," -d [fn] Debug to ./debug.log [or specified file]\n");
  363.     fprintf(stderr," -h      Help (this message)\n");
  364.     if (*url || *email)
  365.       fprintf(stderr,"More info: %s <%s>",url,email);
  366. }
  367.