NetBSD/gnu/dist/gkermit/gcmdline.c
apb 7de1273d3e Fix some compiler warnings by including some headers and
not defining our own prototype for getenv.
2006-11-01 17:25:30 +00:00

368 lines
10 KiB
C

/* G C M D L I N -- gkermit command line parser */
/*
Author:
Frank da Cruz
The Kermit Project
Columbia University
612 West 115th Street
New York NY 10025-7799 USA
http://www.columbia.edu/kermit/
kermit@columbia.edu
Copyright (C) 1999,
The Trustees of Columbia University in the City of New York.
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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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
#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 || *email)
fprintf(stderr,"More info: %s <%s>",url,email);
}