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