/* G C M D L I N -- gkermit command line parser */ /* Author: Frank da Cruz Originally at: The Kermit Project Columbia University 612 West 115th Street New York NY 10025-7799 USA http://www.columbia.edu/kermit/ kermit@columbia.edu As of October 2011: The New Open-Source Kermit Project Bronx NY http://kermitproject.org kermit@kermitproject.org Copyright (C) 1999, 2021, The Trustees of Columbia University in the City of New York. Issued under the GNU General Public License as it existed in 1999. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include #include "gkermit.h" /* Externals */ extern int nfils, parity, text, backup, rpsiz, urpsiz, timint; extern int literal, quiet, keep, streamok, nomodes, manual, xonxoff, noxonxoff; extern char ttname[], *cmerrp, *cmarg, *cmarg2; extern FILE * db; /* Variables exported from this module */ extern char **cmlist; /* Pointer to file list in argv */ extern char **xargv; /* Global copies of argv */ extern int xargc; /* and argc */ /* Variables and symbols local to this module */ static int action = 0; /* Action selected on command line */ _MYPROTOTYPE( static int doarg, (char) ); _MYPROTOTYPE( VOID fatal, (char *) ); _MYPROTOTYPE( VOID usage, (void) ); #ifndef NOGETENV /* getenv prototype commented out in G-Kermit 2.0 */ /* _MYPROTOTYPE( char * getenv, (char *) ); */ #define GARGC 32 #define GBUFSIZ 256 static char gbuf[GBUFSIZ], *gargs[GARGC], *gptr = NULL; static int gargc; #endif /* NOGETENV */ int /* Command-line parser */ cmdlin() { char c; int x; #ifndef NOGETENV char * p = NULL; #endif /* NOGETENV */ cmarg = ""; /* Initialize results */ cmlist = NULL; action = 0; #ifndef NOGETENV if ((p = getenv("GKERMIT"))) { int i, xc, flag = 0; char **xv = NULL; strncpy(gbuf,p,GBUFSIZ-1); /* Make a pokeable copy */ gbuf[GBUFSIZ-1] = NUL; gptr = p; p = gbuf; /* Turn it into an argument vector */ for (i = 0; gbuf[i] && i < GBUFSIZ && gargc < GARGC; i++) { if (!flag) { if (gbuf[i] <= SP) continue; flag = 1; gargs[gargc++] = &gbuf[i]; } else if (flag && gbuf[i] <= SP) { gbuf[i] = NUL; flag = 0; continue; } } xv = xargv; /* Save original argument vector */ xc = xargc; xargv = gargs; /* Redirect it to the one we made */ xargc = gargc; while (xargc-- > 0) { /* Go through the words */ if (**xargv == '-') { /* Got an option (begins with dash) */ c = *(*xargv+1); /* Get the option letter */ x = doarg(c); /* Go handle the option */ if (x < 0) doexit(1); } else { /* No dash where expected */ fprintf(stderr, "?GKERMIT variable option error: \"%s\"\n", *xargv ); usage(); /* Give usage message */ doexit(0); } xargv++; } xargv = xv; /* Restore original argument vector */ xargc = xc; } #endif /* NOGETENV */ while (--xargc > 0) { /* Go through command line words */ xargv++; if (**xargv == '-') { /* Got an option (begins with dash) */ c = *(*xargv+1); /* Get the option letter */ x = doarg(c); /* Go handle the option */ if (x < 0) doexit(1); } else { /* No dash where expected */ fprintf(stderr,"?Command-line option error: \"%s\"\n", *xargv); usage(); /* Give usage message */ doexit(1); } } return(action); /* Then do any requested protocol */ } /* D O A R G -- Do a command-line argument. */ static int #ifdef __STDC__ doarg(char x) #else doarg(x) char x; #endif /* __STDC__ */ { int z; char *xp, **p; xp = *xargv+1; /* Pointer for bundled args */ while (x) { switch (x) { case 'r': /* Receive */ if (action) fatal("conflicting actions"); action = 'v'; break; case 's': /* Send */ if (action) fatal("conflicting actions"); if (*(xp+1)) fatal("invalid argument bundling after -s"); nfils = 0; /* Initialize file counter, flag */ cmlist = xargv+1; /* Remember this pointer */ if (zchki(*cmlist) < 0) fatal("file not found or not accessible"); while (--xargc > 0) { /* Traverse the list */ *xargv++; if (**xargv == '-') break; nfils++; } xargc++, *xargv--; /* Adjust argv/argc */ if (nfils < 1) fatal("missing filename for -s"); action = 's'; break; case 'g': /* get */ if (action) fatal("conflicting actions"); if (*(xp+1)) fatal("invalid argument bundling after -g"); *xargv++, xargc--; if ((xargc == 0) || (**xargv == '-')) fatal("missing filename for -g"); cmarg = *xargv; action = 'r'; break; case 'h': /* Help */ case '?': usage(); doexit(0); case 'i': /* Binary (image) file transfer */ manual = 1; text = 0; break; case 'T': /* Text file transfer */ manual = 1; text = 1; break; case 'p': /* Parity */ if (*(xp+1)) fatal("invalid argument bundling"); *xargv++, xargc--; if ((xargc < 1) || (**xargv == '-')) fatal("missing parity"); switch(x = **xargv) { case 'e': /* Even */ case 'o': /* Odd */ case 'm': /* Mark */ case 's': parity = x; break; /* Space */ case 'n': parity = 0; break; /* None */ default: fatal("invalid parity"); } break; case 'w': /* Writeover */ backup = 0; /* Don't back up existing files */ break; case 'd': /* Debug */ p = xargv; *p++; if ((xargc < 2) || (**p == '-')) { db = fopen("debug.log","w"); } else { *xargv++, xargc--; db = fopen(*xargv,"w"); } if (db) { extern char * versio, * build; if (!versio) versio = ""; if (!build) build = ""; debug = 1; setbuf(db,NULL); fprintf(db,"%s: %s\n", (*versio ? versio : "GKERMIT VERSION UNKNOWN"), (*build ? build : "BUILD UNKNOWN") ); fprintf(db,"MAXPATHLEN = %d\n",MAXPATHLEN); if (gptr) fprintf(db,"GKERMIT=\"%s\"\n",gptr); } break; case 'a': /* As-name */ if (*(xp+1)) fatal("invalid argument bundling after -a"); *xargv++, xargc--; if ((xargc == 0) || (**xargv == '-')) fatal("missing name for -a"); cmarg2 = *xargv; if (debug) fprintf(db,"as-name: %s\n",cmarg2); break; case 'e': if (*(xp+1)) fatal("invalid argument bundling after -e"); xargv++, xargc--; if ((xargc < 1) || (**xargv == '-')) fatal("missing length"); z = atoi(*xargv); /* Convert to number. */ if (z >= 40 && z <= MAXRP) { rpsiz = urpsiz = z; if (z > 94) rpsiz = 94; /* Fallback if other Kermit can't */ } else { /* do long packets. */ fatal("Unsupported packet length"); } break; case 'b': /* Timeout */ if (*(xp+1)) fatal("invalid argument bundling after -b"); xargv++, xargc--; if ((xargc < 1) || (**xargv == '-')) fatal("missing value"); z = atoi(*xargv); /* Convert to number */ if (z < 0) z = 0; if (z > 90) z = 90; timint = z; break; case 'P': /* Path (file) names literal */ literal = 1; break; case 'q': /* Quiet */ quiet = 1; break; case 'K': /* Keep incompletely received files */ keep = 1; break; case 'S': /* Disable streaming */ streamok = -1; break; case 'X': /* gkermit is an external protocol */ quiet = 1; /* No messages */ nomodes = 1; /* Don't set tty modes */ break; case 'x': /* Force Xon/Xoff */ xonxoff = 1; noxonxoff = 0; break; case '-': /* Don't force Xon/Xoff */ if (*(xp+1) == 'x') { xonxoff = 0; noxonxoff = 1; } else { fatal("invalid argument, type 'gkermit -h' for help"); } xp++; break; default: /* Anything else */ fatal("invalid argument, type 'gkermit -h' for help"); } x = *++xp; /* See if options are bundled */ } if (debug) { if (action) fprintf(db,"cmdlin action = %c\n",action); else fprintf(db,"cmdlin action = (none)\n"); } return(action); } VOID fatal(msg) char *msg; { /* Fatal error message */ fprintf(stderr,"\r\nFatal: %s",msg); /* doexit supplies crlf.. */ doexit(1); /* Exit indicating failure */ } VOID usage() { extern char * versio, * build, * url, * email; if (!versio) versio = ""; if (!*versio) versio = "gkermit UNKNOWN VERSION"; if (!build) build = "UNKNOWN BUILD"; if (!url) url = ""; if (!email) email = ""; fprintf(stderr,"%s: %s.\n",versio,build); fprintf(stderr,"Usage: gkermit [ options ]\n"); fprintf(stderr,"Options:\n"); fprintf(stderr," -r Receive files\n"); fprintf(stderr," -s fn Send files\n"); fprintf(stderr," -g fn Get files from server\n"); fprintf(stderr," -a fn As-name for single file\n"); fprintf(stderr," -i Image (binary) mode transfer\n"); fprintf(stderr," -T Text mode transfer\n"); fprintf(stderr," -P Path/filename conversion disabled\n"); fprintf(stderr," -w Write over existing files with same name\n"); fprintf(stderr," -K Keep incompletely received files\n"); fprintf(stderr," -p x Parity: x = o[dd],e[ven],m[ark],s[pace],n[one]\n") ; fprintf(stderr," -e n Receive packet-length (40-%d)\n",MAXRP); fprintf(stderr," -b n Timeout (sec, 0 = none)\n"); fprintf(stderr," -x Force Xon/Xoff (--x = Don't force Xon/Xoff)\n"); fprintf(stderr," -S Disable streaming\n"); fprintf(stderr," -X External protocol\n"); fprintf(stderr," -q Quiet (suppress messages)\n"); fprintf(stderr," -d [fn] Debug to ./debug.log [or specified file]\n"); fprintf(stderr," -h Help (this message)\n"); if (*url) fprintf(stderr, "Web: %s\n",url); if (*email) fprintf(stderr,"Email: %s\n",email); }