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