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