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