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