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