|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)main.c 4.9 (Berkeley) 7/18/83"; ! 3: #endif ! 4: ! 5: /* ! 6: * FTP User Program -- Command Interface. ! 7: */ ! 8: #include <sys/param.h> ! 9: #include <sys/socket.h> ! 10: #include <sys/ioctl.h> ! 11: ! 12: #include <arpa/ftp.h> ! 13: ! 14: #include <signal.h> ! 15: #include <stdio.h> ! 16: #include <errno.h> ! 17: #include <ctype.h> ! 18: #include <netdb.h> ! 19: #include <pwd.h> ! 20: ! 21: #include "ftp_var.h" ! 22: ! 23: int intr(); ! 24: int lostpeer(); ! 25: extern char *home; ! 26: ! 27: main(argc, argv) ! 28: char *argv[]; ! 29: { ! 30: register char *cp; ! 31: int top; ! 32: struct passwd *pw; ! 33: char homedir[MAXPATHLEN]; ! 34: ! 35: sp = getservbyname("ftp", "tcp"); ! 36: if (sp == 0) { ! 37: fprintf(stderr, "ftp: ftp/tcp: unknown service\n"); ! 38: exit(1); ! 39: } ! 40: doglob = 1; ! 41: interactive = 1; ! 42: autologin = 1; ! 43: argc--, argv++; ! 44: while (argc > 0 && **argv == '-') { ! 45: for (cp = *argv + 1; *cp; cp++) ! 46: switch (*cp) { ! 47: ! 48: case 'd': ! 49: options |= SO_DEBUG; ! 50: debug++; ! 51: break; ! 52: ! 53: case 'v': ! 54: verbose++; ! 55: break; ! 56: ! 57: case 't': ! 58: trace++; ! 59: break; ! 60: ! 61: case 'i': ! 62: interactive = 0; ! 63: break; ! 64: ! 65: case 'n': ! 66: autologin = 0; ! 67: break; ! 68: ! 69: case 'g': ! 70: doglob = 0; ! 71: break; ! 72: ! 73: default: ! 74: fprintf(stderr, ! 75: "ftp: %c: unknown option\n", *cp); ! 76: exit(1); ! 77: } ! 78: argc--, argv++; ! 79: } ! 80: fromatty = isatty(fileno(stdin)); ! 81: /* ! 82: * Set up defaults for FTP. ! 83: */ ! 84: strcpy(typename, "ascii"), type = TYPE_A; ! 85: strcpy(formname, "non-print"), form = FORM_N; ! 86: strcpy(modename, "stream"), mode = MODE_S; ! 87: strcpy(structname, "file"), stru = STRU_F; ! 88: strcpy(bytename, "8"), bytesize = 8; ! 89: if (fromatty) ! 90: verbose++; ! 91: /* ! 92: * Set up the home directory in case we're globbing. ! 93: */ ! 94: pw = getpwnam(getlogin()); ! 95: if (pw == NULL) ! 96: pw = getpwuid(getuid()); ! 97: if (pw != NULL) { ! 98: home = homedir; ! 99: strcpy(home, pw->pw_dir); ! 100: } ! 101: if (argc > 0) { ! 102: if (setjmp(toplevel)) ! 103: exit(0); ! 104: signal(SIGINT, intr); ! 105: signal(SIGPIPE, lostpeer); ! 106: setpeer(argc + 1, argv - 1); ! 107: } ! 108: top = setjmp(toplevel) == 0; ! 109: if (top) { ! 110: signal(SIGINT, intr); ! 111: signal(SIGPIPE, lostpeer); ! 112: } ! 113: for (;;) { ! 114: cmdscanner(top); ! 115: top = 1; ! 116: } ! 117: } ! 118: ! 119: intr() ! 120: { ! 121: ! 122: longjmp(toplevel, 1); ! 123: } ! 124: ! 125: lostpeer() ! 126: { ! 127: extern FILE *cout; ! 128: extern int data; ! 129: ! 130: if (connected) { ! 131: if (cout != NULL) { ! 132: shutdown(fileno(cout), 1+1); ! 133: fclose(cout); ! 134: cout = NULL; ! 135: } ! 136: if (data >= 0) { ! 137: shutdown(data, 1+1); ! 138: (void) close(data); ! 139: data = -1; ! 140: } ! 141: connected = 0; ! 142: } ! 143: longjmp(toplevel, 1); ! 144: } ! 145: ! 146: char * ! 147: tail(filename) ! 148: char *filename; ! 149: { ! 150: register char *s; ! 151: ! 152: while (*filename) { ! 153: s = rindex(filename, '/'); ! 154: if (s == NULL) ! 155: break; ! 156: if (s[1]) ! 157: return (s + 1); ! 158: *s = '\0'; ! 159: } ! 160: return (filename); ! 161: } ! 162: ! 163: /* ! 164: * Command parser. ! 165: */ ! 166: cmdscanner(top) ! 167: int top; ! 168: { ! 169: register struct cmd *c; ! 170: struct cmd *getcmd(); ! 171: extern struct cmd cmdtab[]; ! 172: extern int help(); ! 173: ! 174: if (!top) ! 175: putchar('\n'); ! 176: for (;;) { ! 177: if (fromatty) { ! 178: printf("ftp> "); ! 179: fflush(stdout); ! 180: } ! 181: if (gets(line) == 0) { ! 182: if (feof(stdin)) { ! 183: clearerr(stdin); ! 184: putchar('\n'); ! 185: } ! 186: break; ! 187: } ! 188: if (line[0] == 0) ! 189: break; ! 190: makeargv(); ! 191: c = getcmd(margv[0]); ! 192: if (c == (struct cmd *)-1) { ! 193: printf("?Ambiguous command\n"); ! 194: continue; ! 195: } ! 196: if (c == 0) { ! 197: printf("?Invalid command\n"); ! 198: continue; ! 199: } ! 200: if (c->c_conn && !connected) { ! 201: printf ("Not connected.\n"); ! 202: continue; ! 203: } ! 204: (*c->c_handler)(margc, margv); ! 205: if (bell && c->c_bell) ! 206: putchar(CTRL(g)); ! 207: if (c->c_handler != help) ! 208: break; ! 209: } ! 210: longjmp(toplevel, 0); ! 211: } ! 212: ! 213: struct cmd * ! 214: getcmd(name) ! 215: register char *name; ! 216: { ! 217: register char *p, *q; ! 218: register struct cmd *c, *found; ! 219: register int nmatches, longest; ! 220: ! 221: longest = 0; ! 222: nmatches = 0; ! 223: found = 0; ! 224: for (c = cmdtab; p = c->c_name; c++) { ! 225: for (q = name; *q == *p++; q++) ! 226: if (*q == 0) /* exact match? */ ! 227: return (c); ! 228: if (!*q) { /* the name was a prefix */ ! 229: if (q - name > longest) { ! 230: longest = q - name; ! 231: nmatches = 1; ! 232: found = c; ! 233: } else if (q - name == longest) ! 234: nmatches++; ! 235: } ! 236: } ! 237: if (nmatches > 1) ! 238: return ((struct cmd *)-1); ! 239: return (found); ! 240: } ! 241: ! 242: /* ! 243: * Slice a string up into argc/argv. ! 244: */ ! 245: makeargv() ! 246: { ! 247: char **argp; ! 248: char *slurpstring(); ! 249: ! 250: margc = 0; ! 251: argp = margv; ! 252: stringbase = line; /* scan from first of buffer */ ! 253: argbase = argbuf; /* store from first of buffer */ ! 254: while (*argp++ = slurpstring()) ! 255: margc++; ! 256: } ! 257: ! 258: /* ! 259: * Parse string into argbuf; ! 260: * implemented with FSM to ! 261: * handle quoting and strings ! 262: */ ! 263: char * ! 264: slurpstring() ! 265: { ! 266: int got_one = 0; ! 267: register char *sb = stringbase; ! 268: register char *ap = argbase; ! 269: char *tmp = argbase; /* will return this if token found */ ! 270: ! 271: if (*sb == '!') { /* recognize ! as a token for shell */ ! 272: stringbase++; ! 273: return ("!"); ! 274: } ! 275: S0: ! 276: switch (*sb) { ! 277: ! 278: case '\0': ! 279: goto OUT; ! 280: ! 281: case ' ': ! 282: case '\t': ! 283: sb++; goto S0; ! 284: ! 285: default: ! 286: goto S1; ! 287: } ! 288: ! 289: S1: ! 290: switch (*sb) { ! 291: ! 292: case ' ': ! 293: case '\t': ! 294: case '\0': ! 295: goto OUT; /* end of token */ ! 296: ! 297: case '\\': ! 298: sb++; goto S2; /* slurp next character */ ! 299: ! 300: case '"': ! 301: sb++; goto S3; /* slurp quoted string */ ! 302: ! 303: default: ! 304: *ap++ = *sb++; /* add character to token */ ! 305: got_one = 1; ! 306: goto S1; ! 307: } ! 308: ! 309: S2: ! 310: switch (*sb) { ! 311: ! 312: case '\0': ! 313: goto OUT; ! 314: ! 315: default: ! 316: *ap++ = *sb++; ! 317: got_one = 1; ! 318: goto S1; ! 319: } ! 320: ! 321: S3: ! 322: switch (*sb) { ! 323: ! 324: case '\0': ! 325: goto OUT; ! 326: ! 327: case '"': ! 328: sb++; goto S1; ! 329: ! 330: default: ! 331: *ap++ = *sb++; ! 332: got_one = 1; ! 333: goto S3; ! 334: } ! 335: ! 336: OUT: ! 337: if (got_one) ! 338: *ap++ = '\0'; ! 339: argbase = ap; /* update storage pointer */ ! 340: stringbase = sb; /* update scan pointer */ ! 341: if (got_one) ! 342: return(tmp); ! 343: return((char *)0); ! 344: } ! 345: ! 346: #define HELPINDENT (sizeof ("directory")) ! 347: ! 348: /* ! 349: * Help command. ! 350: * Call each command handler with argc == 0 and argv[0] == name. ! 351: */ ! 352: help(argc, argv) ! 353: int argc; ! 354: char *argv[]; ! 355: { ! 356: register struct cmd *c; ! 357: ! 358: if (argc == 1) { ! 359: register int i, j, w; ! 360: int columns, width = 0, lines; ! 361: extern int NCMDS; ! 362: ! 363: printf("Commands may be abbreviated. Commands are:\n\n"); ! 364: for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { ! 365: int len = strlen(c->c_name); ! 366: ! 367: if (len > width) ! 368: width = len; ! 369: } ! 370: width = (width + 8) &~ 7; ! 371: columns = 80 / width; ! 372: if (columns == 0) ! 373: columns = 1; ! 374: lines = (NCMDS + columns - 1) / columns; ! 375: for (i = 0; i < lines; i++) { ! 376: for (j = 0; j < columns; j++) { ! 377: c = cmdtab + j * lines + i; ! 378: printf("%s", c->c_name); ! 379: if (c + lines >= &cmdtab[NCMDS]) { ! 380: printf("\n"); ! 381: break; ! 382: } ! 383: w = strlen(c->c_name); ! 384: while (w < width) { ! 385: w = (w + 8) &~ 7; ! 386: putchar('\t'); ! 387: } ! 388: } ! 389: } ! 390: return; ! 391: } ! 392: while (--argc > 0) { ! 393: register char *arg; ! 394: arg = *++argv; ! 395: c = getcmd(arg); ! 396: if (c == (struct cmd *)-1) ! 397: printf("?Ambiguous help command %s\n", arg); ! 398: else if (c == (struct cmd *)0) ! 399: printf("?Invalid help command %s\n", arg); ! 400: else ! 401: printf("%-*s\t%s\n", HELPINDENT, ! 402: c->c_name, c->c_help); ! 403: } ! 404: } ! 405: ! 406: /* ! 407: * Call routine with argc, argv set from args (terminated by 0). ! 408: */ ! 409: /* VARARGS2 */ ! 410: call(routine, args) ! 411: int (*routine)(); ! 412: int args; ! 413: { ! 414: register int *argp; ! 415: register int argc; ! 416: ! 417: for (argc = 0, argp = &args; *argp++ != 0; argc++) ! 418: ; ! 419: (*routine)(argc, &args); ! 420: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.