forked from mirrors/tftp-hpa-google
Command-line parsing that doesn't depend on getopt()
This commit is contained in:
parent
b38a61cf70
commit
0eea078aec
3 changed files with 92 additions and 64 deletions
130
tftp/main.c
130
tftp/main.c
|
@ -183,54 +183,79 @@ char *tail(char *);
|
|||
|
||||
char *xstrdup(const char *);
|
||||
|
||||
const char *program;
|
||||
|
||||
static inline void usage(int errcode)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-v][-m mode] [host [port]] [-c command]\n", program);
|
||||
exit(errcode);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct sockaddr_in s_in;
|
||||
int o;
|
||||
int pargc;
|
||||
int iscmd = 0;
|
||||
int arg;
|
||||
static int pargc, peerargc;
|
||||
static int iscmd = 0;
|
||||
char **pargv;
|
||||
const char *optx;
|
||||
char *peerargv[3];
|
||||
|
||||
program = argv[0];
|
||||
|
||||
mode = MODE_DEFAULT;
|
||||
|
||||
while ((o = getopt(argc, argv, "chm:Vv")) != -1) {
|
||||
switch (o) {
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'V':
|
||||
/* Print version and configuration to stdout and exit */
|
||||
printf("%s\n", TFTP_CONFIG_STR);
|
||||
exit(0);
|
||||
case 'm':
|
||||
{
|
||||
const struct modes *p;
|
||||
peerargv[0] = argv[0];
|
||||
peerargc = 1;
|
||||
|
||||
for ( p = modes ; p->m_name ; p++ ) {
|
||||
if (!strcmp(optarg, p->m_name))
|
||||
break;
|
||||
}
|
||||
if (p->m_name) {
|
||||
settftpmode(p);
|
||||
} else {
|
||||
fprintf(stderr, "%s: invalid mode: %s\n", argv[0], optarg);
|
||||
exit(EX_USAGE);
|
||||
for ( arg = 1 ; !iscmd && arg < argc ; arg++ ) {
|
||||
if ( argv[arg][0] == '-' ) {
|
||||
for ( optx = &argv[arg][1] ; *optx ; optx++ ) {
|
||||
switch ( *optx ) {
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'V':
|
||||
/* Print version and configuration to stdout and exit */
|
||||
printf("%s\n", TFTP_CONFIG_STR);
|
||||
exit(0);
|
||||
case 'm':
|
||||
if ( ++arg >= argc )
|
||||
usage(EX_USAGE);
|
||||
{
|
||||
const struct modes *p;
|
||||
|
||||
for ( p = modes ; p->m_name ; p++ ) {
|
||||
if (!strcmp(argv[arg], p->m_name))
|
||||
break;
|
||||
}
|
||||
if (p->m_name) {
|
||||
settftpmode(p);
|
||||
} else {
|
||||
fprintf(stderr, "%s: invalid mode: %s\n", argv[0], argv[arg]);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
iscmd = 1;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage(*optx == 'h' ? 0 : EX_USAGE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
iscmd = 1;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
fprintf(stderr, "Usage: %s [-v][-m mode] [-c command|host]\n", argv[0]);
|
||||
exit(o == 'h' ? 0 : EX_USAGE);
|
||||
} else {
|
||||
if ( peerargc >= 3 )
|
||||
usage(EX_USAGE);
|
||||
|
||||
peerargv[peerargc++] = argv[arg];
|
||||
}
|
||||
}
|
||||
|
||||
pargc = argc - (optind-1);
|
||||
pargv = argv + (optind-1);
|
||||
pargv = argv + arg;
|
||||
pargc = argc - arg;
|
||||
|
||||
sp = getservbyname("tftp", "udp");
|
||||
if (sp == 0) {
|
||||
|
@ -256,27 +281,28 @@ main(int argc, char *argv[])
|
|||
exit(EX_OSERR);
|
||||
}
|
||||
bsd_signal(SIGINT, intr);
|
||||
if (pargc > 1) {
|
||||
if ( iscmd ) {
|
||||
/* -c specified; execute command and exit */
|
||||
struct cmd *c;
|
||||
|
||||
if (sigsetjmp(toplevel,1) != 0)
|
||||
exit(EX_UNAVAILABLE);
|
||||
if ( peerargc ) {
|
||||
/* Set peer */
|
||||
if (sigsetjmp(toplevel,1) != 0)
|
||||
exit(EX_NOHOST);
|
||||
setpeer(peerargc, peerargv);
|
||||
}
|
||||
|
||||
c = getcmd(pargv[1]);
|
||||
if ( c == (struct cmd *)-1 || c == (struct cmd *)0 ) {
|
||||
fprintf(stderr, "%s: invalid command: %s\n", argv[0], pargv[1]);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
(*c->handler)(pargc-1, pargv+1);
|
||||
exit(0);
|
||||
} else {
|
||||
/* No -c */
|
||||
if (sigsetjmp(toplevel,1) != 0)
|
||||
exit(0);
|
||||
setpeer(pargc, pargv);
|
||||
if ( iscmd && pargc ) {
|
||||
/* -c specified; execute command and exit */
|
||||
struct cmd *c;
|
||||
|
||||
if (sigsetjmp(toplevel,1) != 0)
|
||||
exit(EX_UNAVAILABLE);
|
||||
|
||||
c = getcmd(pargv[0]);
|
||||
if ( c == (struct cmd *)-1 || c == (struct cmd *)0 ) {
|
||||
fprintf(stderr, "%s: invalid command: %s\n", argv[0], pargv[1]);
|
||||
exit(EX_USAGE);
|
||||
}
|
||||
(*c->handler)(pargc, pargv);
|
||||
exit(0);
|
||||
}
|
||||
if (sigsetjmp(toplevel,1) != 0)
|
||||
(void)putchar('\n');
|
||||
|
|
|
@ -37,8 +37,9 @@
|
|||
\- IPv4 Trivial File Transfer Protocol client
|
||||
.SH SYNOPSIS
|
||||
.B tftp
|
||||
.RI [ options... ]
|
||||
.RI [ host ]
|
||||
[ \fIoptions...\fP ]
|
||||
[\fIhost\fP [\fIport\fP]]
|
||||
[\fB\-c\fP \fIcommand\fP]
|
||||
.br
|
||||
.SH DESCRIPTION
|
||||
.B tftp
|
||||
|
@ -57,6 +58,7 @@ command below.)
|
|||
.TP
|
||||
\fB\-c\fP \fIcommand\fP
|
||||
Execute \fIcommand\fP as if it had been entered on the tftp prompt.
|
||||
Must be specified last on the command line.
|
||||
.TP
|
||||
\fB\-m\fP \fImode\fP
|
||||
Set the default transfer mode to \fImode\fP. This is usually used with \-c.
|
||||
|
|
16
tftp/tftp.c
16
tftp/tftp.c
|
@ -421,14 +421,14 @@ static void
|
|||
printstats(const char *direction, unsigned long amount)
|
||||
{
|
||||
double delta;
|
||||
/* compute delta in 1/10's second units */
|
||||
delta = ((tstop.tv_sec*10.)+(tstop.tv_usec/100000)) -
|
||||
((tstart.tv_sec*10.)+(tstart.tv_usec/100000));
|
||||
delta = delta/10.; /* back to seconds */
|
||||
printf("%s %lu bytes in %.1f seconds", direction, amount, delta);
|
||||
if (verbose)
|
||||
printf(" [%.0f bits/sec]", (amount*8.)/delta);
|
||||
putchar('\n');
|
||||
|
||||
delta = (tstop.tv_sec+(tstop.tv_usec/100000.0)) -
|
||||
(tstart.tv_sec+(tstart.tv_usec/100000.0));
|
||||
if (verbose) {
|
||||
printf("%s %lu bytes in %.1f seconds", direction, amount, delta);
|
||||
printf(" [%.0f bit/s]", (amount*8.)/delta);
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue