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

Defined functions

call defined in line 488; used 4 times
cmdscanner defined in line 196; used 1 times
getcmd defined in line 245; used 7 times
help defined in line 423; used 5 times
intr defined in line 139; used 4 times
lostpeer defined in line 145; used 13 times
main defined in line 41; never used
makeargv defined in line 280; used 26 times
slurpstring defined in line 299; used 2 times

Defined variables

copyright defined in line 8; never used
sccsid defined in line 14; never used
slrflag defined in line 278; used 10 times

Defined macros

HELPINDENT defined in line 417; used 1 times
Last modified: 1986-03-07
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2038
Valid CSS Valid XHTML 1.0 Strict