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