home *** CD-ROM | disk | FTP | other *** search
/ Columbia Kermit / kermit.zip / archives / gkermit68k.tar.gz / gkermit68.tar / gkermit68 / gcmdline.c < prev    next >
C/C++ Source or Header  |  2002-03-12  |  10KB  |  373 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[], *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. #ifdef CPM68K
  197.       /* CP/M doesn't support case-sensitive args so allow 't' */
  198.       case 't':
  199. #endif
  200.       case 'T':            /* Text file transfer */
  201.         manual = 1;
  202.         text = 1;
  203.         break;
  204.  
  205.       case 'p':            /* Parity */
  206.         if (*(xp+1)) fatal("invalid argument bundling");
  207.         *xargv++, xargc--;
  208.         if ((xargc < 1) || (**xargv == '-'))
  209.           fatal("missing parity");
  210.         switch(x = **xargv) {
  211.           case 'e':            /* Even */
  212.           case 'o':            /* Odd */
  213.           case 'm':            /* Mark */
  214.           case 's': parity = x; break; /* Space */
  215.           case 'n': parity = 0; break; /* None */
  216.           default:  fatal("invalid parity");
  217.         }
  218.         break;
  219.  
  220.       case 'w':            /* Writeover */
  221.         backup = 0;            /* Don't back up existing files */
  222.         break;
  223.  
  224.       case 'd':            /* Debug */
  225.         p = xargv;
  226.         *p++;
  227.         if ((xargc < 2) || (**p == '-')) {
  228.         db = fopen("debug.log","w");
  229.         } else {
  230.         *xargv++, xargc--;
  231.         db = fopen(*xargv,"w");
  232.         }
  233.         if (db) {
  234.         extern char * versio, * build;
  235.         if (versio == (char *)NULL) versio = "";
  236.         if (build == (char *)NULL) build = "";
  237.         debug = 1;
  238.         setbuf(db,NULL);
  239.         fprintf(db,"%s: %s\n",
  240.             (*versio ? versio : "GKERMIT VERSION UNKNOWN"),
  241.             (*build ? build : "BUILD UNKNOWN")
  242.             );
  243.         fprintf(db,"MAXPATHLEN = %d\n",MAXPATHLEN);
  244. #ifndef NOGETENV
  245.         if (gptr) fprintf(db,"GKERMIT=\"%s\"\n",gptr);
  246. #endif
  247.         }
  248.         break;
  249.  
  250.       case 'a':            /* As-name */
  251.         if (*(xp+1)) fatal("invalid argument bundling after -a");
  252.         *xargv++, xargc--;
  253.         if ((xargc == 0) || (**xargv == '-'))
  254.           fatal("missing name for -a");
  255.         cmarg2 = *xargv;
  256.         if (debug) fprintf(db,"as-name: %s\n",cmarg2);
  257.         break;
  258.  
  259.       case 'e':
  260.         if (*(xp+1)) fatal("invalid argument bundling after -e");
  261.         xargv++, xargc--;
  262.         if ((xargc < 1) || (**xargv == '-'))
  263.           fatal("missing length");
  264.         z = atoi(*xargv);        /* Convert to number. */
  265.         if (z >= 40 && z <= MAXRP) {
  266.         rpsiz = urpsiz = z;
  267.         if (z > 94) rpsiz = 94;    /* Fallback if other Kermit can't */
  268.         } else {            /* do long packets. */
  269.         fatal("Unsupported packet length");
  270.         }
  271.         break;
  272.  
  273.       case 'b':            /* Timeout */
  274.         if (*(xp+1)) fatal("invalid argument bundling after -b");
  275.         xargv++, xargc--;
  276.         if ((xargc < 1) || (**xargv == '-'))
  277.           fatal("missing value");
  278.         z = atoi(*xargv);        /* Convert to number */
  279.         if (z < 0) z = 0;
  280.         if (z > 90) z = 90;
  281.         timint = z;
  282.         break;
  283.  
  284.       case 'P':            /* Path (file) names literal */
  285.         literal = 1;
  286.         break;
  287.  
  288.       case 'q':            /* Quiet */
  289.         quiet = 1;
  290.         break;
  291.  
  292.       case 'K':            /* Keep incompletely received files */
  293.         keep = 1;
  294.         break;
  295.  
  296.       case 'S':            /* Disable streaming */
  297.         streamok = -1;
  298.         break;
  299.  
  300.       case 'X':            /* gkermit is an external protocol */
  301.         quiet = 1;            /* No messages */
  302.             nomodes = 1;        /* Don't set tty modes */
  303.         break;
  304.  
  305.       case 'x':            /* Force Xon/Xoff */
  306.         xonxoff = 1;
  307.         noxonxoff = 0;
  308.         break;
  309.  
  310.       case '-':            /* Don't force Xon/Xoff */
  311.         if (*(xp+1) == 'x') {
  312.         xonxoff = 0;
  313.         noxonxoff = 1;
  314.         } else {
  315.         fatal("invalid argument, type 'gkermit -h' for help");
  316.         }
  317.         xp++;
  318.         break;
  319.  
  320.       default:            /* Anything else */
  321.         fatal("invalid argument, type 'gkermit -h' for help");
  322.         }
  323.     x = *++xp;            /* See if options are bundled */
  324.     }
  325.     if (debug) {
  326.     if (action)
  327.       fprintf(db,"cmdlin action = %c\n",action);
  328.     else
  329.       fprintf(db,"cmdlin action = (none)\n");
  330.     }
  331.     return(action);
  332. }
  333.  
  334. VOID
  335. fatal(msg) char *msg; {            /* Fatal error message */
  336.     fprintf(stderr,"\r\nFatal: %s",msg); /* doexit supplies crlf.. */
  337.     doexit(1);                /* Exit indicating failure */
  338. }
  339.  
  340. VOID
  341. usage() {
  342.     extern char * versio, * build, * url, * email;
  343.     if (versio == (char *)NULL) versio = "";
  344.     if (!*versio) versio = "gkermit UNKNOWN VERSION";
  345.     if (build == (char *)NULL) build = "UNKNOWN BUILD";
  346.     if (url == (char *)NULL) url = "";
  347.     if (email == (char *)NULL) email = "";
  348.     fprintf(stderr,"%s: %s.\n",versio,build);
  349.     fprintf(stderr,"Usage:  gkermit [ options ]\n");
  350.     fprintf(stderr,"Options:\n");
  351.     fprintf(stderr," -r      Receive files\n");
  352.     fprintf(stderr," -s fn   Send files\n");
  353.     fprintf(stderr," -g fn   Get files from server\n");
  354.     fprintf(stderr," -a fn   As-name for single file\n");
  355.     fprintf(stderr," -i      Image (binary) mode transfer\n");
  356.     fprintf(stderr," -T      Text mode transfer\n");
  357.     fprintf(stderr," -P      Path/filename conversion disabled\n");
  358.     fprintf(stderr," -w      Write over existing files with same name\n");
  359.     fprintf(stderr," -K      Keep incompletely received files\n");
  360.     fprintf(stderr," -p x    Parity: x = o[dd],e[ven],m[ark],s[pace],n[one]\n")
  361.       ;
  362.     fprintf(stderr," -e n    Receive packet-length (40-%d)\n",MAXRP);
  363.     fprintf(stderr," -b n    Timeout (sec, 0 = none)\n");
  364.     fprintf(stderr," -x      Force Xon/Xoff (--x = Don't force Xon/Xoff)\n");
  365.     fprintf(stderr," -S      Disable streaming\n");
  366.     fprintf(stderr," -X      External protocol\n");
  367.     fprintf(stderr," -q      Quiet (suppress messages)\n");
  368.     fprintf(stderr," -d [fn] Debug to ./debug.log [or specified file]\n");
  369.     fprintf(stderr," -h      Help (this message)\n");
  370.     if (*url || *email)
  371.       fprintf(stderr,"More info: %s <%s>",url,email);
  372. }
  373.