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

Defined functions

cmdscanner defined in line 204; used 1 times
getcmd defined in line 252; used 7 times
help defined in line 431; used 5 times
intr defined in line 147; used 4 times
lostpeer defined in line 153; used 13 times
main defined in line 49; never used
slurpstring defined in line 307; used 2 times

Defined variables

copyright defined in line 19; never used
sccsid defined in line 23; never used
slrflag defined in line 286; used 10 times

Defined macros

HELPINDENT defined in line 425; used 1 times
Last modified: 1997-10-03
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4047
Valid CSS Valid XHTML 1.0 Strict