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 < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-23  |  10.2 KB  |  542 lines

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