home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-B.05 / NETKIT-B / NetKit-B-0.05 / ftp / main.c,v < prev    next >
Encoding:
Text File  |  1994-05-23  |  9.9 KB  |  539 lines

  1. head    1.1;
  2. access;
  3. symbols;
  4. locks
  5.     rzsfl:1.1; strict;
  6. comment    @ * @;
  7.  
  8.  
  9. 1.1
  10. date    94.05.23.09.03.42;    author rzsfl;    state Exp;
  11. branches;
  12. next    ;
  13.  
  14.  
  15. desc
  16. @Original
  17. @
  18.  
  19.  
  20. 1.1
  21. log
  22. @Initial revision
  23. @
  24. text
  25. @/*
  26.  * Copyright (c) 1985, 1989 Regents of the University of California.
  27.  * All rights reserved.
  28.  *
  29.  * Redistribution and use in source and binary forms, with or without
  30.  * modification, are permitted provided that the following conditions
  31.  * are met:
  32.  * 1. Redistributions of source code must retain the above copyright
  33.  *    notice, this list of conditions and the following disclaimer.
  34.  * 2. Redistributions in binary form must reproduce the above copyright
  35.  *    notice, this list of conditions and the following disclaimer in the
  36.  *    documentation and/or other materials provided with the distribution.
  37.  * 3. All advertising materials mentioning features or use of this software
  38.  *    must display the following acknowledgement:
  39.  *    This product includes software developed by the University of
  40.  *    California, Berkeley and its contributors.
  41.  * 4. Neither the name of the University nor the names of its contributors
  42.  *    may be used to endorse or promote products derived from this software
  43.  *    without specific prior written permission.
  44.  *
  45.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  46.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  47.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  48.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  49.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  50.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  51.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  52.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  53.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  54.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  55.  * SUCH DAMAGE.
  56.  */
  57.  
  58. #ifndef lint
  59. char copyright[] =
  60. "@@(#) Copyright (c) 1985, 1989 Regents of the University of California.\n\
  61.  All rights reserved.\n";
  62. #endif /* not lint */
  63.  
  64. #ifndef lint
  65. /*static char sccsid[] = "from: @@(#)main.c    5.18 (Berkeley) 3/1/91";*/
  66. static char rcsid[] = "$Id: main.c,v 1.2 1993/08/01 18:15:26 mycroft Exp $";
  67. #endif /* not lint */
  68.  
  69. /*
  70.  * FTP User Program -- Command Interface.
  71.  */
  72. #include "ftp_var.h"
  73. #include <sys/socket.h>
  74. #include <sys/ioctl.h>
  75. #include <sys/types.h>
  76.  
  77. #include <arpa/ftp.h>
  78.  
  79. #include <signal.h>
  80. #include <stdio.h>
  81. #include <errno.h>
  82. #include <ctype.h>
  83. #include <netdb.h>
  84. #include <pwd.h>
  85.  
  86. uid_t    getuid();
  87. void    intr(), lostpeer();
  88. extern    char *home;
  89. char    *getlogin();
  90.  
  91. main(argc, argv)
  92.     char *argv[];
  93. {
  94.     register char *cp;
  95.     int top;
  96.     struct passwd *pw = NULL;
  97.     char homedir[MAXPATHLEN];
  98.  
  99.     sp = getservbyname("ftp", "tcp");
  100.     if (sp == 0) {
  101.         fprintf(stderr, "ftp: ftp/tcp: unknown service\n");
  102.         exit(1);
  103.     }
  104.     doglob = 1;
  105.     interactive = 1;
  106.     autologin = 1;
  107.     argc--, argv++;
  108.     while (argc > 0 && **argv == '-') {
  109.         for (cp = *argv + 1; *cp; cp++)
  110.             switch (*cp) {
  111.  
  112.             case 'd':
  113.                 options |= SO_DEBUG;
  114.                 debug++;
  115.                 break;
  116.             
  117.             case 'v':
  118.                 verbose++;
  119.                 break;
  120.  
  121.             case 't':
  122.                 trace++;
  123.                 break;
  124.  
  125.             case 'i':
  126.                 interactive = 0;
  127.                 break;
  128.  
  129.             case 'n':
  130.                 autologin = 0;
  131.                 break;
  132.  
  133.             case 'g':
  134.                 doglob = 0;
  135.                 break;
  136.  
  137.             default:
  138.                 fprintf(stdout,
  139.                   "ftp: %c: unknown option\n", *cp);
  140.                 exit(1);
  141.             }
  142.         argc--, argv++;
  143.     }
  144.     fromatty = isatty(fileno(stdin));
  145.     if (fromatty)
  146.         verbose++;
  147.     cpend = 0;    /* no pending replies */
  148.     proxy = 0;    /* proxy not active */
  149.     crflag = 1;    /* strip c.r. on ascii gets */
  150.     sendport = -1;    /* not using ports */
  151.     /*
  152.      * Set up the home directory in case we're globbing.
  153.      */
  154.     cp = getlogin();
  155.     if (cp != NULL) {
  156.         pw = getpwnam(cp);
  157.     }
  158.     if (pw == NULL)
  159.         pw = getpwuid(getuid());
  160.     if (pw != NULL) {
  161.         home = homedir;
  162.         (void) strcpy(home, pw->pw_dir);
  163.     }
  164.     if (argc > 0) {
  165.         if (setjmp(toplevel))
  166.             exit(0);
  167.         (void) signal(SIGINT, intr);
  168.         (void) signal(SIGPIPE, lostpeer);
  169.         setpeer(argc + 1, argv - 1);
  170.     }
  171.     top = setjmp(toplevel) == 0;
  172.     if (top) {
  173.         (void) signal(SIGINT, intr);
  174.         (void) signal(SIGPIPE, lostpeer);
  175.     }
  176.     for (;;) {
  177.         cmdscanner(top);
  178.         top = 1;
  179.     }
  180. }
  181.  
  182. void
  183. intr()
  184. {
  185.  
  186.     longjmp(toplevel, 1);
  187. }
  188.  
  189. void
  190. lostpeer()
  191. {
  192.     extern FILE *cout;
  193.     extern int data;
  194.  
  195.     if (connected) {
  196.         if (cout != NULL) {
  197.             (void) shutdown(fileno(cout), 1+1);
  198.             (void) fclose(cout);
  199.             cout = NULL;
  200.         }
  201.         if (data >= 0) {
  202.             (void) shutdown(data, 1+1);
  203.             (void) close(data);
  204.             data = -1;
  205.         }
  206.         connected = 0;
  207.     }
  208.     pswitch(1);
  209.     if (connected) {
  210.         if (cout != NULL) {
  211.             (void) shutdown(fileno(cout), 1+1);
  212.             (void) fclose(cout);
  213.             cout = NULL;
  214.         }
  215.         connected = 0;
  216.     }
  217.     proxflag = 0;
  218.     pswitch(0);
  219. }
  220.  
  221. /*char *
  222. tail(filename)
  223.     char *filename;
  224. {
  225.     register char *s;
  226.     
  227.     while (*filename) {
  228.         s = rindex(filename, '/');
  229.         if (s == NULL)
  230.             break;
  231.         if (s[1])
  232.             return (s + 1);
  233.         *s = '\0';
  234.     }
  235.     return (filename);
  236. }
  237. */
  238. /*
  239.  * Command parser.
  240.  */
  241. cmdscanner(top)
  242.     int top;
  243. {
  244.     register struct cmd *c;
  245.     register int l;
  246.     struct cmd *getcmd();
  247.     extern int help();
  248.  
  249.     if (!top)
  250.         (void) putchar('\n');
  251.     for (;;) {
  252.         if (fromatty) {
  253.             printf("ftp> ");
  254.             (void) fflush(stdout);
  255.         }
  256.         if (fgets(line, sizeof line, stdin) == NULL)
  257.             quit();
  258.         l = strlen(line);
  259.         if (l == 0)
  260.             break;
  261.         if (line[--l] == '\n') {
  262.             if (l == 0)
  263.                 break;
  264.             line[l] = '\0';
  265.         } else if (l == sizeof(line) - 2) {
  266.             printf("sorry, input line too long\n");
  267.             while ((l = getchar()) != '\n' && l != EOF)
  268.                 /* void */;
  269.             break;
  270.         } /* else it was a line without a newline */
  271.         makeargv();
  272.         if (margc == 0) {
  273.             continue;
  274.         }
  275.         c = getcmd(margv[0]);
  276.         if (c == (struct cmd *)-1) {
  277.             printf("?Ambiguous command\n");
  278.             continue;
  279.         }
  280.         if (c == 0) {
  281.             printf("?Invalid command\n");
  282.             continue;
  283.         }
  284.         if (c->c_conn && !connected) {
  285.             printf("Not connected.\n");
  286.             continue;
  287.         }
  288.         (*c->c_handler)(margc, margv);
  289.         if (bell && c->c_bell)
  290.             (void) putchar('\007');
  291.         if (c->c_handler != help)
  292.             break;
  293.     }
  294.     (void) signal(SIGINT, intr);
  295.     (void) signal(SIGPIPE, lostpeer);
  296. }
  297.  
  298. struct cmd *
  299. getcmd(name)
  300.     register char *name;
  301. {
  302.     extern struct cmd cmdtab[];
  303.     register char *p, *q;
  304.     register struct cmd *c, *found;
  305.     register int nmatches, longest;
  306.  
  307.     longest = 0;
  308.     nmatches = 0;
  309.     found = 0;
  310.     for (c = cmdtab; p = c->c_name; c++) {
  311.         for (q = name; *q == *p++; q++)
  312.             if (*q == 0)        /* exact match? */
  313.                 return (c);
  314.         if (!*q) {            /* the name was a prefix */
  315.             if (q - name > longest) {
  316.                 longest = q - name;
  317.                 nmatches = 1;
  318.                 found = c;
  319.             } else if (q - name == longest)
  320.                 nmatches++;
  321.         }
  322.     }
  323.     if (nmatches > 1)
  324.         return ((struct cmd *)-1);
  325.     return (found);
  326. }
  327.  
  328. /*
  329.  * Slice a string up into argc/argv.
  330.  */
  331.  
  332. int slrflag;
  333.  
  334. makeargv()
  335. {
  336.     char **argp;
  337.     char *slurpstring();
  338.  
  339.     margc = 0;
  340.     argp = margv;
  341.     stringbase = line;        /* scan from first of buffer */
  342.     argbase = argbuf;        /* store from first of buffer */
  343.     slrflag = 0;
  344.     while (*argp++ = slurpstring())
  345.         margc++;
  346. }
  347.  
  348. /*
  349.  * Parse string into argbuf;
  350.  * implemented with FSM to
  351.  * handle quoting and strings
  352.  */
  353. char *
  354. slurpstring()
  355. {
  356.     int got_one = 0;
  357.     register char *sb = stringbase;
  358.     register char *ap = argbase;
  359.     char *tmp = argbase;        /* will return this if token found */
  360.  
  361.     if (*sb == '!' || *sb == '$') {    /* recognize ! as a token for shell */
  362.         switch (slrflag) {    /* and $ as token for macro invoke */
  363.             case 0:
  364.                 slrflag++;
  365.                 stringbase++;
  366.                 return ((*sb == '!') ? "!" : "$");
  367.                 /* NOTREACHED */
  368.             case 1:
  369.                 slrflag++;
  370.                 altarg = stringbase;
  371.                 break;
  372.             default:
  373.                 break;
  374.         }
  375.     }
  376.  
  377. S0:
  378.     switch (*sb) {
  379.  
  380.     case '\0':
  381.         goto OUT;
  382.  
  383.     case ' ':
  384.     case '\t':
  385.         sb++; goto S0;
  386.  
  387.     default:
  388.         switch (slrflag) {
  389.             case 0:
  390.                 slrflag++;
  391.                 break;
  392.             case 1:
  393.                 slrflag++;
  394.                 altarg = sb;
  395.                 break;
  396.             default:
  397.                 break;
  398.         }
  399.         goto S1;
  400.     }
  401.  
  402. S1:
  403.     switch (*sb) {
  404.  
  405.     case ' ':
  406.     case '\t':
  407.     case '\0':
  408.         goto OUT;    /* end of token */
  409.  
  410.     case '\\':
  411.         sb++; goto S2;    /* slurp next character */
  412.  
  413.     case '"':
  414.         sb++; goto S3;    /* slurp quoted string */
  415.  
  416.     default:
  417.         *ap++ = *sb++;    /* add character to token */
  418.         got_one = 1;
  419.         goto S1;
  420.     }
  421.  
  422. S2:
  423.     switch (*sb) {
  424.  
  425.     case '\0':
  426.         goto OUT;
  427.  
  428.     default:
  429.         *ap++ = *sb++;
  430.         got_one = 1;
  431.         goto S1;
  432.     }
  433.  
  434. S3:
  435.     switch (*sb) {
  436.  
  437.     case '\0':
  438.         goto OUT;
  439.  
  440.     case '"':
  441.         sb++; goto S1;
  442.  
  443.     default:
  444.         *ap++ = *sb++;
  445.         got_one = 1;
  446.         goto S3;
  447.     }
  448.  
  449. OUT:
  450.     if (got_one)
  451.         *ap++ = '\0';
  452.     argbase = ap;            /* update storage pointer */
  453.     stringbase = sb;        /* update scan pointer */
  454.     if (got_one) {
  455.         return(tmp);
  456.     }
  457.     switch (slrflag) {
  458.         case 0:
  459.             slrflag++;
  460.             break;
  461.         case 1:
  462.             slrflag++;
  463.             altarg = (char *) 0;
  464.             break;
  465.         default:
  466.             break;
  467.     }
  468.     return((char *)0);
  469. }
  470.  
  471. #define HELPINDENT (sizeof ("directory"))
  472.  
  473. /*
  474.  * Help command.
  475.  * Call each command handler with argc == 0 and argv[0] == name.
  476.  */
  477. help(argc, argv)
  478.     int argc;
  479.     char *argv[];
  480. {
  481.     extern struct cmd cmdtab[];
  482.     register struct cmd *c;
  483.  
  484.     if (argc == 1) {
  485.         register int i, j, w, k;
  486.         int columns, width = 0, lines;
  487.         extern int NCMDS;
  488.  
  489.         printf("Commands may be abbreviated.  Commands are:\n\n");
  490.         for (c = cmdtab; c < &cmdtab[NCMDS]; c++) {
  491.             int len = strlen(c->c_name);
  492.  
  493.             if (len > width)
  494.                 width = len;
  495.         }
  496.         width = (width + 8) &~ 7;
  497.         columns = 80 / width;
  498.         if (columns == 0)
  499.             columns = 1;
  500.         lines = (NCMDS + columns - 1) / columns;
  501.         for (i = 0; i < lines; i++) {
  502.             for (j = 0; j < columns; j++) {
  503.                 c = cmdtab + j * lines + i;
  504.                 if (c->c_name && (!proxy || c->c_proxy)) {
  505.                     printf("%s", c->c_name);
  506.                 }
  507.                 else if (c->c_name) {
  508.                     for (k=0; k < strlen(c->c_name); k++) {
  509.                         (void) putchar(' ');
  510.                     }
  511.                 }
  512.                 if (c + lines >= &cmdtab[NCMDS]) {
  513.                     printf("\n");
  514.                     break;
  515.                 }
  516.                 w = strlen(c->c_name);
  517.                 while (w < width) {
  518.                     w = (w + 8) &~ 7;
  519.                     (void) putchar('\t');
  520.                 }
  521.             }
  522.         }
  523.         return;
  524.     }
  525.     while (--argc > 0) {
  526.         register char *arg;
  527.         arg = *++argv;
  528.         c = getcmd(arg);
  529.         if (c == (struct cmd *)-1)
  530.             printf("?Ambiguous help command %s\n", arg);
  531.         else if (c == (struct cmd *)0)
  532.             printf("?Invalid help command %s\n", arg);
  533.         else
  534.             printf("%-*s\t%s\n", HELPINDENT,
  535.                 c->c_name, c->c_help);
  536.     }
  537. }
  538. @
  539.