1: /*
   2:  * Copyright (c) 1983 Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms are permitted
   6:  * provided that: (1) source distributions retain this entire copyright
   7:  * notice and comment, and (2) distributions including binaries display
   8:  * the following acknowledgement:  ``This product includes software
   9:  * developed by the University of California, Berkeley and its contributors''
  10:  * in the documentation or other materials provided with the distribution
  11:  * and in all advertising materials mentioning features or use of this
  12:  * software. Neither the name of the University nor the names of its
  13:  * contributors may be used to endorse or promote products derived
  14:  * from this software without specific prior written permission.
  15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  16:  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18:  */
  19: 
  20: #ifndef lint
  21: char copyright[] =
  22: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  23:  All rights reserved.\n";
  24: #endif /* not lint */
  25: 
  26: #ifndef lint
  27: static char sccsid[] = "@(#)main.c	5.9 (Berkeley) 6/1/90";
  28: #endif /* not lint */
  29: 
  30: /* Many bug fixes are from Jim Guyton <guyton@rand-unix> */
  31: 
  32: /*
  33:  * TFTP User Program -- Command Interface.
  34:  */
  35: #include <sys/types.h>
  36: #include <sys/socket.h>
  37: #include <sys/file.h>
  38: 
  39: #include <netinet/in.h>
  40: 
  41: #include <signal.h>
  42: #include <stdio.h>
  43: #include <errno.h>
  44: #include <setjmp.h>
  45: #include <ctype.h>
  46: #include <netdb.h>
  47: 
  48: #define TIMEOUT     5       /* secs between rexmt's */
  49: 
  50: struct  sockaddr_in sin;
  51: int f;
  52: short   port;
  53: int trace;
  54: int verbose;
  55: #ifdef  pdp11
  56: #define connected Xconnected
  57: #endif
  58: int connected;
  59: char    mode[32];
  60: char    line[200];
  61: int margc;
  62: char    *margv[20];
  63: char    *prompt = "tftp";
  64: jmp_buf toplevel;
  65: int intr();
  66: struct  servent *sp;
  67: 
  68: int quit(), help(), setverbose(), settrace(), status();
  69: int     get(), put(), setpeer(), modecmd(), setrexmt(), settimeout();
  70: int     setbinary(), setascii();
  71: 
  72: #define HELPINDENT (sizeof("connect"))
  73: 
  74: struct cmd {
  75:     char    *name;
  76:     char    *help;
  77:     int (*handler)();
  78: };
  79: 
  80: char    vhelp[] = "toggle verbose mode";
  81: char    thelp[] = "toggle packet tracing";
  82: char    chelp[] = "connect to remote tftp";
  83: char    qhelp[] = "exit tftp";
  84: char    hhelp[] = "print help information";
  85: char    shelp[] = "send file";
  86: char    rhelp[] = "receive file";
  87: char    mhelp[] = "set file transfer mode";
  88: char    sthelp[] = "show current status";
  89: char    xhelp[] = "set per-packet retransmission timeout";
  90: char    ihelp[] = "set total retransmission timeout";
  91: char    ashelp[] = "set mode to netascii";
  92: char    bnhelp[] = "set mode to octet";
  93: 
  94: struct cmd cmdtab[] = {
  95:     { "connect",    chelp,      setpeer },
  96:     { "mode",       mhelp,          modecmd },
  97:     { "put",    shelp,      put },
  98:     { "get",    rhelp,      get },
  99:     { "quit",   qhelp,      quit },
 100:     { "verbose",    vhelp,      setverbose },
 101:     { "trace",  thelp,      settrace },
 102:     { "status", sthelp,     status },
 103:     { "binary",     bnhelp,         setbinary },
 104:     { "ascii",      ashelp,         setascii },
 105:     { "rexmt",  xhelp,      setrexmt },
 106:     { "timeout",    ihelp,      settimeout },
 107:     { "?",      hhelp,      help },
 108:     0
 109: };
 110: 
 111: struct  cmd *getcmd();
 112: char    *tail();
 113: char    *index();
 114: char    *rindex();
 115: 
 116: main(argc, argv)
 117:     char *argv[];
 118: {
 119:     struct sockaddr_in sin;
 120:     int top;
 121: 
 122:     sp = getservbyname("tftp", "udp");
 123:     if (sp == 0) {
 124:         fprintf(stderr, "tftp: udp/tftp: unknown service\n");
 125:         exit(1);
 126:     }
 127:     f = socket(AF_INET, SOCK_DGRAM, 0);
 128:     if (f < 0) {
 129:         perror("tftp: socket");
 130:         exit(3);
 131:     }
 132:     bzero((char *)&sin, sizeof (sin));
 133:     sin.sin_family = AF_INET;
 134:     if (bind(f, &sin, sizeof (sin)) < 0) {
 135:         perror("tftp: bind");
 136:         exit(1);
 137:     }
 138:     strcpy(mode, "netascii");
 139:     signal(SIGINT, intr);
 140:     if (argc > 1) {
 141:         if (setjmp(toplevel) != 0)
 142:             exit(0);
 143:         setpeer(argc, argv);
 144:     }
 145:     top = setjmp(toplevel) == 0;
 146:     for (;;)
 147:         command(top);
 148: }
 149: 
 150: char    hostname[100];
 151: 
 152: setpeer(argc, argv)
 153:     int argc;
 154:     char *argv[];
 155: {
 156:     struct hostent *host;
 157: 
 158:     if (argc < 2) {
 159:         strcpy(line, "Connect ");
 160:         printf("(to) ");
 161:         gets(&line[strlen(line)]);
 162:         makeargv();
 163:         argc = margc;
 164:         argv = margv;
 165:     }
 166:     if (argc > 3) {
 167:         printf("usage: %s host-name [port]\n", argv[0]);
 168:         return;
 169:     }
 170:     host = gethostbyname(argv[1]);
 171:     if (host) {
 172:         sin.sin_family = host->h_addrtype;
 173:         bcopy(host->h_addr, &sin.sin_addr, host->h_length);
 174:         strcpy(hostname, host->h_name);
 175:     } else {
 176:         sin.sin_family = AF_INET;
 177:         sin.sin_addr.s_addr = inet_addr(argv[1]);
 178:         if (sin.sin_addr.s_addr == -1) {
 179:             connected = 0;
 180:             printf("%s: unknown host\n", argv[1]);
 181:             return;
 182:         }
 183:         strcpy(hostname, argv[1]);
 184:     }
 185:     port = sp->s_port;
 186:     if (argc == 3) {
 187:         port = atoi(argv[2]);
 188:         if (port < 0) {
 189:             printf("%s: bad port number\n", argv[2]);
 190:             connected = 0;
 191:             return;
 192:         }
 193:         port = htons(port);
 194:     }
 195:     connected = 1;
 196: }
 197: 
 198: struct  modes {
 199:     char *m_name;
 200:     char *m_mode;
 201: } modes[] = {
 202:     { "ascii",  "netascii" },
 203:     { "netascii",   "netascii" },
 204:     { "binary",     "octet" },
 205:     { "image",      "octet" },
 206:     { "octet",     "octet" },
 207: /*      { "mail",       "mail" },       */
 208:     { 0,        0 }
 209: };
 210: 
 211: modecmd(argc, argv)
 212:     char *argv[];
 213: {
 214:     register struct modes *p;
 215:     char *sep;
 216: 
 217:     if (argc < 2) {
 218:         printf("Using %s mode to transfer files.\n", mode);
 219:         return;
 220:     }
 221:     if (argc == 2) {
 222:         for (p = modes; p->m_name; p++)
 223:             if (strcmp(argv[1], p->m_name) == 0)
 224:                 break;
 225:         if (p->m_name) {
 226:             setmode(p->m_mode);
 227:             return;
 228:         }
 229:         printf("%s: unknown mode\n", argv[1]);
 230:         /* drop through and print usage message */
 231:     }
 232: 
 233:     printf("usage: %s [", argv[0]);
 234:     sep = " ";
 235:     for (p = modes; p->m_name; p++) {
 236:         printf("%s%s", sep, p->m_name);
 237:         if (*sep == ' ')
 238:             sep = " | ";
 239:     }
 240:     printf(" ]\n");
 241:     return;
 242: }
 243: 
 244: setbinary(argc, argv)
 245: char *argv[];
 246: {       setmode("octet");
 247: }
 248: 
 249: setascii(argc, argv)
 250: char *argv[];
 251: {       setmode("netascii");
 252: }
 253: 
 254: setmode(newmode)
 255: char *newmode;
 256: {
 257:     strcpy(mode, newmode);
 258:     if (verbose)
 259:         printf("mode set to %s\n", mode);
 260: }
 261: 
 262: 
 263: /*
 264:  * Send file(s).
 265:  */
 266: put(argc, argv)
 267:     char *argv[];
 268: {
 269:     int fd;
 270:     register int n;
 271:     register char *cp, *targ;
 272: 
 273:     if (argc < 2) {
 274:         strcpy(line, "send ");
 275:         printf("(file) ");
 276:         gets(&line[strlen(line)]);
 277:         makeargv();
 278:         argc = margc;
 279:         argv = margv;
 280:     }
 281:     if (argc < 2) {
 282:         putusage(argv[0]);
 283:         return;
 284:     }
 285:     targ = argv[argc - 1];
 286:     if (index(argv[argc - 1], ':')) {
 287:         char *cp;
 288:         struct hostent *hp;
 289: 
 290:         for (n = 1; n < argc - 1; n++)
 291:             if (index(argv[n], ':')) {
 292:                 putusage(argv[0]);
 293:                 return;
 294:             }
 295:         cp = argv[argc - 1];
 296:         targ = index(cp, ':');
 297:         *targ++ = 0;
 298:         hp = gethostbyname(cp);
 299:         if (hp == NULL) {
 300:             fprintf(stderr, "tftp: %s: ", cp);
 301:             herror((char *)NULL);
 302:             return;
 303:         }
 304:         bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
 305:         sin.sin_family = hp->h_addrtype;
 306:         connected = 1;
 307:         strcpy(hostname, hp->h_name);
 308:     }
 309:     if (!connected) {
 310:         printf("No target machine specified.\n");
 311:         return;
 312:     }
 313:     if (argc < 4) {
 314:         cp = argc == 2 ? tail(targ) : argv[1];
 315:         fd = open(cp, O_RDONLY);
 316:         if (fd < 0) {
 317:             fprintf(stderr, "tftp: "); perror(cp);
 318:             return;
 319:         }
 320:         if (verbose)
 321:             printf("putting %s to %s:%s [%s]\n",
 322:                 cp, hostname, targ, mode);
 323:         sin.sin_port = port;
 324:         sendfile(fd, targ, mode);
 325:         return;
 326:     }
 327:                 /* this assumes the target is a directory */
 328:                 /* on a remote unix system.  hmmmm.  */
 329:     cp = index(targ, '\0');
 330:     *cp++ = '/';
 331:     for (n = 1; n < argc - 1; n++) {
 332:         strcpy(cp, tail(argv[n]));
 333:         fd = open(argv[n], O_RDONLY);
 334:         if (fd < 0) {
 335:             fprintf(stderr, "tftp: "); perror(argv[n]);
 336:             continue;
 337:         }
 338:         if (verbose)
 339:             printf("putting %s to %s:%s [%s]\n",
 340:                 argv[n], hostname, targ, mode);
 341:         sin.sin_port = port;
 342:         sendfile(fd, targ, mode);
 343:     }
 344: }
 345: 
 346: putusage(s)
 347:     char *s;
 348: {
 349:     printf("usage: %s file ... host:target, or\n", s);
 350:     printf("       %s file ... target (when already connected)\n", s);
 351: }
 352: 
 353: /*
 354:  * Receive file(s).
 355:  */
 356: get(argc, argv)
 357:     char *argv[];
 358: {
 359:     int fd;
 360:     register int n;
 361:     register char *cp;
 362:     char *src;
 363: 
 364:     if (argc < 2) {
 365:         strcpy(line, "get ");
 366:         printf("(files) ");
 367:         gets(&line[strlen(line)]);
 368:         makeargv();
 369:         argc = margc;
 370:         argv = margv;
 371:     }
 372:     if (argc < 2) {
 373:         getusage(argv[0]);
 374:         return;
 375:     }
 376:     if (!connected) {
 377:         for (n = 1; n < argc ; n++)
 378:             if (index(argv[n], ':') == 0) {
 379:                 getusage(argv[0]);
 380:                 return;
 381:             }
 382:     }
 383:     for (n = 1; n < argc ; n++) {
 384:         src = index(argv[n], ':');
 385:         if (src == NULL)
 386:             src = argv[n];
 387:         else {
 388:             struct hostent *hp;
 389: 
 390:             *src++ = 0;
 391:             hp = gethostbyname(argv[n]);
 392:             if (hp == NULL) {
 393:                 fprintf(stderr, "tftp: %s: ", argv[n]);
 394:                 herror((char *)NULL);
 395:                 continue;
 396:             }
 397:             bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
 398:             sin.sin_family = hp->h_addrtype;
 399:             connected = 1;
 400:             strcpy(hostname, hp->h_name);
 401:         }
 402:         if (argc < 4) {
 403:             cp = argc == 3 ? argv[2] : tail(src);
 404:             fd = creat(cp, 0644);
 405:             if (fd < 0) {
 406:                 fprintf(stderr, "tftp: "); perror(cp);
 407:                 return;
 408:             }
 409:             if (verbose)
 410:                 printf("getting from %s:%s to %s [%s]\n",
 411:                     hostname, src, cp, mode);
 412:             sin.sin_port = port;
 413:             recvfile(fd, src, mode);
 414:             break;
 415:         }
 416:         cp = tail(src);         /* new .. jdg */
 417:         fd = creat(cp, 0644);
 418:         if (fd < 0) {
 419:             fprintf(stderr, "tftp: "); perror(cp);
 420:             continue;
 421:         }
 422:         if (verbose)
 423:             printf("getting from %s:%s to %s [%s]\n",
 424:                 hostname, src, cp, mode);
 425:         sin.sin_port = port;
 426:         recvfile(fd, src, mode);
 427:     }
 428: }
 429: 
 430: getusage(s)
 431: char * s;
 432: {
 433:     printf("usage: %s host:file host:file ... file, or\n", s);
 434:     printf("       %s file file ... file if connected\n", s);
 435: }
 436: 
 437: int rexmtval = TIMEOUT;
 438: 
 439: setrexmt(argc, argv)
 440:     char *argv[];
 441: {
 442:     int t;
 443: 
 444:     if (argc < 2) {
 445:         strcpy(line, "Rexmt-timeout ");
 446:         printf("(value) ");
 447:         gets(&line[strlen(line)]);
 448:         makeargv();
 449:         argc = margc;
 450:         argv = margv;
 451:     }
 452:     if (argc != 2) {
 453:         printf("usage: %s value\n", argv[0]);
 454:         return;
 455:     }
 456:     t = atoi(argv[1]);
 457:     if (t < 0)
 458:         printf("%s: bad value\n", t);
 459:     else
 460:         rexmtval = t;
 461: }
 462: 
 463: int maxtimeout = 5 * TIMEOUT;
 464: 
 465: settimeout(argc, argv)
 466:     char *argv[];
 467: {
 468:     int t;
 469: 
 470:     if (argc < 2) {
 471:         strcpy(line, "Maximum-timeout ");
 472:         printf("(value) ");
 473:         gets(&line[strlen(line)]);
 474:         makeargv();
 475:         argc = margc;
 476:         argv = margv;
 477:     }
 478:     if (argc != 2) {
 479:         printf("usage: %s value\n", argv[0]);
 480:         return;
 481:     }
 482:     t = atoi(argv[1]);
 483:     if (t < 0)
 484:         printf("%s: bad value\n", t);
 485:     else
 486:         maxtimeout = t;
 487: }
 488: 
 489: status(argc, argv)
 490:     char *argv[];
 491: {
 492:     if (connected)
 493:         printf("Connected to %s.\n", hostname);
 494:     else
 495:         printf("Not connected.\n");
 496:     printf("Mode: %s Verbose: %s Tracing: %s\n", mode,
 497:         verbose ? "on" : "off", trace ? "on" : "off");
 498:     printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n",
 499:         rexmtval, maxtimeout);
 500: }
 501: 
 502: intr()
 503: {
 504:     signal(SIGALRM, SIG_IGN);
 505:     alarm(0);
 506:     longjmp(toplevel, -1);
 507: }
 508: 
 509: char *
 510: tail(filename)
 511:     char *filename;
 512: {
 513:     register char *s;
 514: 
 515:     while (*filename) {
 516:         s = rindex(filename, '/');
 517:         if (s == NULL)
 518:             break;
 519:         if (s[1])
 520:             return (s + 1);
 521:         *s = '\0';
 522:     }
 523:     return (filename);
 524: }
 525: 
 526: /*
 527:  * Command parser.
 528:  */
 529: command(top)
 530:     int top;
 531: {
 532:     register struct cmd *c;
 533: 
 534:     if (!top)
 535:         putchar('\n');
 536:     for (;;) {
 537:         printf("%s> ", prompt);
 538:         if (gets(line) == 0) {
 539:             if (feof(stdin)) {
 540:                 quit();
 541:             } else {
 542:                 continue;
 543:             }
 544:         }
 545:         if (line[0] == 0)
 546:             continue;
 547:         makeargv();
 548:         c = getcmd(margv[0]);
 549:         if (c == (struct cmd *)-1) {
 550:             printf("?Ambiguous command\n");
 551:             continue;
 552:         }
 553:         if (c == 0) {
 554:             printf("?Invalid command\n");
 555:             continue;
 556:         }
 557:         (*c->handler)(margc, margv);
 558:     }
 559: }
 560: 
 561: struct cmd *
 562: getcmd(name)
 563:     register char *name;
 564: {
 565:     register char *p, *q;
 566:     register struct cmd *c, *found;
 567:     register int nmatches, longest;
 568: 
 569:     longest = 0;
 570:     nmatches = 0;
 571:     found = 0;
 572:     for (c = cmdtab; p = c->name; c++) {
 573:         for (q = name; *q == *p++; q++)
 574:             if (*q == 0)        /* exact match? */
 575:                 return (c);
 576:         if (!*q) {          /* the name was a prefix */
 577:             if (q - name > longest) {
 578:                 longest = q - name;
 579:                 nmatches = 1;
 580:                 found = c;
 581:             } else if (q - name == longest)
 582:                 nmatches++;
 583:         }
 584:     }
 585:     if (nmatches > 1)
 586:         return ((struct cmd *)-1);
 587:     return (found);
 588: }
 589: 
 590: /*
 591:  * Slice a string up into argc/argv.
 592:  */
 593: makeargv()
 594: {
 595:     register char *cp;
 596:     register char **argp = margv;
 597: 
 598:     margc = 0;
 599:     for (cp = line; *cp;) {
 600:         while (isspace(*cp))
 601:             cp++;
 602:         if (*cp == '\0')
 603:             break;
 604:         *argp++ = cp;
 605:         margc += 1;
 606:         while (*cp != '\0' && !isspace(*cp))
 607:             cp++;
 608:         if (*cp == '\0')
 609:             break;
 610:         *cp++ = '\0';
 611:     }
 612:     *argp++ = 0;
 613: }
 614: 
 615: /*VARARGS*/
 616: quit()
 617: {
 618:     exit(0);
 619: }
 620: 
 621: /*
 622:  * Help command.
 623:  */
 624: help(argc, argv)
 625:     int argc;
 626:     char *argv[];
 627: {
 628:     register struct cmd *c;
 629: 
 630:     if (argc == 1) {
 631:         printf("Commands may be abbreviated.  Commands are:\n\n");
 632:         for (c = cmdtab; c->name; c++)
 633:             printf("%-*s\t%s\n", HELPINDENT, c->name, c->help);
 634:         return;
 635:     }
 636:     while (--argc > 0) {
 637:         register char *arg;
 638:         arg = *++argv;
 639:         c = getcmd(arg);
 640:         if (c == (struct cmd *)-1)
 641:             printf("?Ambiguous help command %s\n", arg);
 642:         else if (c == (struct cmd *)0)
 643:             printf("?Invalid help command %s\n", arg);
 644:         else
 645:             printf("%s\n", c->help);
 646:     }
 647: }
 648: 
 649: /*VARARGS*/
 650: settrace()
 651: {
 652:     trace = !trace;
 653:     printf("Packet tracing %s.\n", trace ? "on" : "off");
 654: }
 655: 
 656: /*VARARGS*/
 657: setverbose()
 658: {
 659:     verbose = !verbose;
 660:     printf("Verbose mode %s.\n", verbose ? "on" : "off");
 661: }

Defined functions

command defined in line 529; used 1 times
get defined in line 356; used 2 times
getcmd defined in line 561; used 3 times
getusage defined in line 430; used 2 times
help defined in line 624; used 5 times
intr defined in line 502; used 2 times
main defined in line 116; never used
makeargv defined in line 593; used 6 times
modecmd defined in line 211; used 2 times
put defined in line 266; used 2 times
putusage defined in line 346; used 2 times
quit defined in line 616; used 3 times
setascii defined in line 249; used 2 times
setbinary defined in line 244; used 2 times
setmode defined in line 254; used 3 times
setpeer defined in line 152; used 3 times
setrexmt defined in line 439; used 2 times
settimeout defined in line 465; used 2 times
settrace defined in line 650; used 2 times
setverbose defined in line 657; used 2 times
status defined in line 489; used 2 times
tail defined in line 509; used 5 times

Defined variables

ashelp defined in line 91; used 1 times
bnhelp defined in line 92; used 1 times
chelp defined in line 82; used 1 times
  • in line 95
cmdtab defined in line 94; used 2 times
connected defined in line 58; never used
copyright defined in line 21; never used
f defined in line 51; used 11 times
hhelp defined in line 84; used 1 times
hostname defined in line 150; used 9 times
ihelp defined in line 90; used 1 times
line defined in line 60; used 18 times
margc defined in line 61; used 8 times
margv defined in line 62; used 8 times
maxtimeout defined in line 463; used 3 times
mhelp defined in line 87; used 1 times
  • in line 96
mode defined in line 59; used 13 times
modes defined in line 201; used 2 times
port defined in line 52; used 9 times
prompt defined in line 63; used 1 times
qhelp defined in line 83; used 1 times
  • in line 99
rexmtval defined in line 437; used 5 times
rhelp defined in line 86; used 1 times
  • in line 98
sccsid defined in line 27; never used
shelp defined in line 85; used 1 times
  • in line 97
sin defined in line 50; used 29 times
sp defined in line 66; used 3 times
sthelp defined in line 88; used 1 times
thelp defined in line 81; used 1 times
toplevel defined in line 64; used 3 times
trace defined in line 53; used 11 times
verbose defined in line 54; used 10 times
vhelp defined in line 80; used 1 times
xhelp defined in line 89; used 1 times

Defined struct's

cmd defined in line 74; used 20 times
modes defined in line 198; used 2 times
  • in line 214(2)

Defined macros

HELPINDENT defined in line 72; used 1 times
TIMEOUT defined in line 48; used 2 times
connected defined in line 56; used 8 times
Last modified: 1992-09-10
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 6223
Valid CSS Valid XHTML 1.0 Strict