home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / networking / tcpip / amitcp-support / ncftp-1.5.6 / src / rcs / main.c,v < prev    next >
Encoding:
Text File  |  1994-06-29  |  24.3 KB  |  1,122 lines

  1. head    14020.16;
  2. access;
  3. symbols
  4.     ORIGINAL:14020.15;
  5. locks; strict;
  6. comment    @ * @;
  7.  
  8.  
  9. 14020.16
  10. date    93.10.10.20.03.06;    author alph;    state Exp;
  11. branches;
  12. next    14020.15;
  13.  
  14. 14020.15
  15. date    93.07.09.11.50.12;    author alph;    state Exp;
  16. branches;
  17. next    ;
  18.  
  19.  
  20. desc
  21. @Original version
  22. @
  23.  
  24.  
  25. 14020.16
  26. log
  27. @amigados changes
  28. @
  29. text
  30. @/* main.c */
  31.  
  32. /*  $RCSfile: main.c,v $
  33.  *  $Revision: 1.1 $
  34.  *  $Date: 1993/10/02 10:34:34 $
  35.  */
  36.  
  37. #define _main_c_
  38.  
  39. #define FTP_VERSION "1.5.6 (September 20, 1993)"
  40.  
  41. /* #define BETA 1 */ /* If defined, it prints a little warning message. */
  42.  
  43. #include "sys.h"
  44. #include <sys/types.h>
  45. #include <sys/param.h>
  46. #include <sys/socket.h>
  47. #include <sys/stat.h>
  48. #include <sys/time.h>
  49. #include <arpa/ftp.h>
  50. #include <setjmp.h>
  51. #include <signal.h>
  52. #include <string.h>
  53. #include <errno.h>
  54. #include <ctype.h>
  55. #include <netdb.h>
  56. #include <pwd.h>
  57.  
  58. #ifdef SYSLOG
  59. #    include <syslog.h>
  60. #endif
  61.  
  62. #ifndef NO_UNISTDH
  63. #    include <unistd.h>
  64. #endif
  65.  
  66. #ifdef CURSES
  67. #    undef HZ        /* Collides with HaZeltine ! */
  68. #    include <curses.h>
  69. #    ifdef TERMH
  70. #        include <term.h>
  71. #    endif
  72. #endif    /* CURSES */
  73.  
  74. #include "util.h"
  75. #include "cmds.h"
  76. #include "main.h"
  77. #include "ftp.h"
  78. #include "ftprc.h"
  79. #include "open.h"
  80. #include "set.h"
  81. #include "defaults.h"
  82. #include "copyright.h"
  83.  
  84. /* main.c globals */
  85. int                    slrflag;
  86. int                    fromatty;            /* input is from a terminal */
  87. int                    toatty;                /* output is to a terminal */
  88. int                    doing_script;        /* is a file being <redirected to me? */
  89. char                *altarg;            /* argv[1] with no shell-like preprocessing  */
  90. struct servent        serv;                /* service spec for tcp/ftp */
  91. jmp_buf                toplevel;            /* non-local goto stuff for cmd scanner */
  92. char                *line;                /* input line buffer */
  93. char                *stringbase;        /* current scan point in line buffer */
  94. char                *argbuf;            /* argument storage buffer */
  95. char                *argbase;            /* current storage point in arg buffer */
  96. int                    margc;                /* count of arguments on input line */
  97. char                *margv[20];            /* args parsed from input line */
  98. struct userinfo        uinfo;                /* a copy of their pwent really */
  99. int                    ansi_escapes;        /* for fancy graphics */
  100. int                             startup_msg = 1;        /* TAR: display message on startup? */
  101. int                    ignore_rc;            /* are we supposed to ignore the netrc */
  102. string                progname;            /* simple filename */
  103. string                prompt, prompt2;    /* shell prompt string */
  104. string                anon_password;        /* most likely your email address */
  105. string                pager;                /* program to browse text files */
  106. string                version = FTP_VERSION;
  107. long                eventnumber;        /* number of commands we've done */
  108. FILE                *logf = NULL;        /* log user activity */
  109. longstring            logfname;            /* name of the logfile */
  110. long                logsize = 4096L;    /* max log size. 0 == no limit */
  111. int                    percent_flags;        /* "%" in prompt string? */
  112. int                    at_flags;            /* "@@" in prompt string? */
  113. string                 mail_path;            /* your mailbox */
  114. time_t                mbox_time;            /* last modified time of mbox */
  115. size_t                epromptlen;            /* length of the last line of the
  116.                                          * prompt as it will appear on screen,
  117.                                          * (i.e. no invis escape codes).
  118.                                          */
  119.  
  120. #ifdef HPUX
  121. char                *tcap_normal = "\033&d@@";    /* Default ANSI escapes */
  122. char                *tcap_boldface = "\033&dH";     /* Half Bright */
  123. char                *tcap_underline = "\033&dD";
  124. char                *tcap_reverse = "\033&dB";
  125.  
  126. #else
  127.  
  128. char                            *tcap_normal = "\033[0m";       /* Default ANSI escapes */
  129. char                            *tcap_boldface = "\033[1m";
  130. char                            *tcap_underline = "\033[4m";
  131. char                            *tcap_reverse = "\033[7m";
  132.  
  133. #endif
  134.  
  135. size_t                tcl_normal = 4,        /* lengths of the above strings. */
  136.                     tcl_bold = 4,
  137.                     tcl_uline = 4,
  138.                     tcl_rev = 4;
  139.  
  140. #ifdef CURSES
  141. static char            tcbuf[2048];
  142. #endif
  143.  
  144. /* main.c externs */
  145. extern int            debug, verbose, mprompt;
  146. extern int            options, cpend, data, connected, logged_in;
  147. extern int            curtype, macnum, remote_is_unix;
  148. extern FILE            *cout;
  149. extern struct cmd    cmdtab[];
  150. extern str32        curtypename;
  151. extern char            *macbuf;
  152. extern char            *reply_string;
  153. extern char            *short_verbose_msgs[4];
  154. extern string        vstr;
  155. extern Hostname        hostname;
  156. extern longstring    cwd, lcwd, recent_file;
  157. extern int            Optind;
  158. extern char            *Optarg;
  159. #ifdef GATEWAY
  160. extern string        gate_login;
  161. #endif
  162.  
  163. void main(int argc, char **argv)
  164. {
  165.     register char        *cp;
  166.     int                    top, opt, openopts = 0;
  167.     string                tmp, oline;
  168.     struct servent        *sptr;
  169.  
  170.     if ((cp = rindex(argv[0], '/'))) cp++;
  171.     else cp = argv[0];
  172.     (void) Strncpy(progname, cp);
  173.     
  174.     sptr = getservbyname("ftp", "tcp");
  175.     if (sptr == 0) fatal("ftp/tcp: unknown service");
  176.     serv = *sptr;
  177.  
  178.     if (init_arrays())            /* Reserve large blocks of memory now */
  179.         fatal("could not reserve large amounts of memory.");
  180.  
  181.     /*
  182.      * Set up defaults for FTP.
  183.      */
  184.     mprompt = dMPROMPT;
  185.     debug = dDEBUG;
  186.     verbose = dVERBOSE;
  187.     (void) Strncpy(vstr, short_verbose_msgs[verbose+1]);
  188.  
  189.     (void) Strncpy(curtypename, dTYPESTR);
  190.     curtype = dTYPE;
  191.     (void) Strncpy(prompt, dPROMPT);
  192. #ifdef GATEWAY
  193.     (void) Strncpy(gate_login, dGATEWAY_LOGIN);
  194. #endif
  195.  
  196. #ifdef SOCKS
  197.     SOCKSinit("ncftp");
  198. #endif
  199.     
  200.     /*    Setup our pager variable, before we run through the rc,
  201.         which may change it. */
  202.     set_pager(getenv("PAGER"), 0);
  203. #ifdef CURSES
  204.     ansi_escapes = 1;
  205.     termcap_init();
  206. #else
  207.     ansi_escapes = 0;
  208.     if ((cp = getenv("TERM")) != NULL) {
  209.         if ((*cp == 'v' && cp[1] == 't')        /* vt100, vt102, ... */
  210.             || (strcmp(cp, "xterm") == 0))
  211.             ansi_escapes = 1;
  212.     }
  213. #endif
  214.     (void) getuserinfo();
  215.  
  216.     /* Init the mailbox checking code. */
  217.     (void) time(&mbox_time);
  218.  
  219.     (void) Strncpy(anon_password, uinfo.username);
  220.     if (getlocalhostname(uinfo.hostname, sizeof(uinfo.hostname)) == 0) {
  221.         (void) Strncat(anon_password, "@@");
  222.         (void) Strncat(anon_password, uinfo.hostname);
  223.     }
  224. #if dLOGGING
  225.     (void) Strncpy(logfname, dLOGNAME);
  226.     (void) LocalDotPath(logfname);
  227. #else
  228.     *logfname = 0;
  229. #endif
  230.     (void) Strncpy(recent_file, dRECENTF);
  231.     (void) LocalDotPath(recent_file);
  232.  
  233.     (void) get_cwd(lcwd, (int) sizeof(lcwd));
  234.  
  235. #ifdef SYSLOG
  236. #    ifdef LOG_LOCAL3
  237.     openlog ("NcFTP", LOG_PID, LOG_LOCAL3);
  238. #    else
  239.     openlog ("NcFTP", LOG_PID);
  240. #    endif
  241. #endif                /* SYSLOG */
  242.  
  243.  
  244.     ignore_rc = 0;
  245.     (void) strcpy(oline, "open ");
  246.     while ((opt = Getopt(argc, argv, "D:V:INRHaicmup:rd:g:")) >= 0) {
  247.         switch(opt) {
  248.             case 'a':
  249.             case 'c':
  250.             case 'i':
  251.             case 'm':
  252.             case 'u':
  253.             case 'r':
  254.                 (void) sprintf(tmp, "-%c ", opt);
  255.                 goto cattmp;
  256.  
  257.             case 'p':
  258.             case 'd':
  259.             case 'g':
  260.                 (void) sprintf(tmp, "-%c %s ", opt, Optarg);
  261.             cattmp:
  262.                 (void) strcat(oline, tmp);
  263.                 openopts++;
  264.                 break;
  265.  
  266.             case 'D':
  267.                 debug = atoi(Optarg);
  268.                 break;
  269.             
  270.             case 'V':
  271.                 set_verbose(Optarg, 0);
  272.                 break;
  273.  
  274.             case 'I':
  275.                 mprompt = !mprompt;
  276.                 break;
  277.  
  278.             case 'N':
  279.                 ++ignore_rc;
  280.                 break;
  281.  
  282.             case 'H':
  283.                 (void) show_version(0, NULL);
  284.                 exit (0);
  285.  
  286.             default:
  287.             usage:
  288.                 (void) fprintf(stderr, "Usage: %s [program options] [[open options] site.to.open[:path]]\n\
  289. Program Options:\n\
  290.     -D x   : Set debugging level to x (a number).\n\
  291.     -H     : Show version and compilation information.\n\
  292.     -I     : Toggle interactive (mprompt) mode.\n\
  293.     -N     : Toggle reading of the .netrc/.ncftprc.\n\
  294.     -V x   : Set verbosity to level x (-1,0,1,2).\n\
  295. Open Options:\n\
  296.     -a     : Open anonymously (this is the default).\n\
  297.     -u     : Open, specify user/password.\n\
  298.     -i     : Ignore machine entry in your .netrc.\n\
  299.     -p N   : Use port #N for connection.\n\
  300.     -r     : \"Redial\" until connected.\n\
  301.     -d N   : Redial, pausing N seconds between tries.\n\
  302.     -g N   : Redial, giving up after N tries.\n\
  303.     :path  : ``Colon-mode:'' If \"path\" is a file, it opens site, retrieves\n\
  304.              file \"path,\" then exits; if \"path\" is a remote directory,\n\
  305.              it opens site then starts you in that directory..\n\
  306.     -c     : If you're using colon-mode with a file path, this will cat the\n\
  307.              file to stdout instead of storing on disk.\n\
  308.     -m     : Just like -c, only it pipes the file to your $PAGER.\n\
  309. Examples:\n\
  310.     ncftp ftp.unl.edu:/pub/README (just fetches README then quits)\n\
  311.     ncftp  (just enters ncftp command shell)\n\
  312.     ncftp -V -u ftp.unl.edu\n\
  313.     ncftp -c ftp.unl.edu:/pub/README (cats README to stdout then quits)\n\
  314.     ncftp -D -r -d 120 -g 10 ftp.unl.edu\n", progname);
  315.             exit(1);
  316.         }
  317.     }
  318.  
  319.     cp = argv[Optind];  /* the site to open. */
  320.     if (cp == NULL) {
  321.         if (openopts)
  322.             goto usage;
  323.     } else
  324.         (void) strcat(oline, cp);
  325.  
  326.     if (ignore_rc <= 0)
  327.         (void) thrash_rc();
  328.     if (ignore_rc <= 1)
  329.         ReadRecentSitesFile();
  330.  
  331.     (void) fix_options();    /* adjust "options" according to "debug"  */
  332.     
  333.     fromatty = doing_script = isatty(0);
  334.     toatty = isatty(1);
  335.     (void) UserLoggedIn();    /* Init parent-death detection. */
  336.     cpend = 0;  /* no pending replies */
  337.     
  338.     if (*logfname)
  339.         logf = fopen (logfname, "a");
  340.  
  341.  
  342.     /* The user specified a host, maybe in 'colon-mode', on the command
  343.      * line.  Open it now...
  344.      */
  345.     if (argc > 1 && cp) {
  346.         if (setjmp(toplevel))
  347.             exit(0);
  348.         (void) Signal(SIGINT, intr);
  349.         (void) Signal(SIGPIPE, lostpeer);
  350.         (void) strcpy(line, oline);
  351.         makeargv();
  352.         /* setpeer uses this to tell if it was called from the cmd-line. */
  353.         eventnumber = 0L;
  354.         (void) cmdOpen(margc, margv);
  355.     }
  356.     eventnumber = 1L;
  357.  
  358.     (void) init_prompt();
  359.  
  360.     if (startup_msg) {  /* TAR */
  361.         if (ansi_escapes) {
  362. #ifdef BETA
  363. #    define BETA_MSG "\n\
  364. For testing purposes only.  Do not re-distribute or subject to novice users."
  365. #else
  366. #    define BETA_MSG ""
  367. #endif
  368.  
  369. #ifndef CURSES
  370.         (void) printf("%sNcFTP %s by Mike Gleason, NCEMRSoft.%s%s\n", 
  371.                 tcap_boldface, FTP_VERSION, BETA_MSG, tcap_normal);
  372. #else
  373.         string vis;
  374.         (void) sprintf(vis, "%sNcFTP %s by Mike Gleason, NCEMRSoft.%s%s\n", 
  375.                 tcap_boldface, FTP_VERSION, BETA_MSG, tcap_normal);
  376.         tcap_put(vis);
  377. #endif /* !CURSES */
  378.         }
  379.         else
  380.         (void) printf("%s%s\n", FTP_VERSION, BETA_MSG);
  381.     }  /* TAR */
  382.     if (NOT_VQUIET)
  383.         PrintTip();
  384.     top = setjmp(toplevel) == 0;
  385.     if (top) {
  386.         (void) Signal(SIGINT, intr);
  387.         (void) Signal(SIGPIPE, lostpeer);
  388.     }
  389.     for (;;) {
  390.         (void) cmdscanner(top);
  391.         top = 1;
  392.     }
  393. }    /* main */
  394.  
  395.  
  396.  
  397. /*ARGSUSED*/
  398. void intr SIG_PARAMS
  399. {
  400.     dbprintf("intr()\n");
  401.     (void) Signal(SIGINT, intr);
  402.     (void) longjmp(toplevel, 1);
  403. }    /* intr */
  404.  
  405.  
  406.  
  407. int getuserinfo(void)
  408. {
  409.     extern char                *home;    /* for glob.c */
  410. #ifndef NO_GETPWUID    
  411.     register char            *cp;
  412.     struct passwd            *pw;
  413.     string                    str;
  414.  
  415.     pw = getpwuid(getuid());
  416.     if (pw != NULL) {
  417.         (void) Strncpy(uinfo.username, pw->pw_name);
  418.         (void) Strncpy(uinfo.shell, pw->pw_shell);
  419.         (void) Strncpy(uinfo.homedir, pw->pw_dir);
  420.         uinfo.uid = pw->pw_uid;
  421.         home = uinfo.homedir;    /* for glob.c */
  422.         cp = getenv("MAIL");
  423.         if (cp == NULL)
  424.             cp = getenv("mail");
  425.         if (cp == NULL)
  426.             (void) sprintf(str, "/usr/spool/mail/%s", uinfo.username);
  427.         else
  428.             (void) Strncpy(str, cp);
  429.         cp = str;
  430.  
  431.         /*
  432.          * mbox variable may be like MAIL=(28 /usr/mail/me /usr/mail/you),
  433.          * so try to find the first mail path.
  434.          */
  435.         while ((*cp != '/') && (*cp != 0))
  436.             cp++;
  437.         (void) Strncpy(mail_path, cp);
  438.         if ((cp = index(mail_path, ' ')) != NULL)
  439.             *cp = '\0';
  440.         return (0);
  441.     } else {
  442.         (void) Strncpy(uinfo.username, "unknown");
  443.         (void) Strncpy(uinfo.shell, "/bin/sh");
  444.         (void) Strncpy(uinfo.homedir, ".");    /* current directory */
  445.         uinfo.uid = 999;
  446.         return (-1);
  447.     }
  448. #else
  449.     char *env;
  450.  
  451.     if(env = getenv("USERNAME"))
  452.         (void) Strncpy(uinfo.username, env);
  453.     else
  454.         (void) Strncpy(uinfo.username, "unknown");
  455.     (void) Strncpy(uinfo.shell, ""); /* no shell should give us default */
  456.     (void) Strncpy(uinfo.homedir, HOME_DIR);
  457.     uinfo.uid = 999;
  458.     return (-1);
  459. #endif
  460. }    /* getuserinfo */
  461.  
  462.  
  463.  
  464.  
  465. int init_arrays(void)
  466. {
  467.     if ((macbuf = (char *) malloc((size_t)(MACBUFLEN))) == NULL)
  468.         goto barf;
  469.     if ((line = (char *) malloc((size_t)(CMDLINELEN))) == NULL)
  470.         goto barf;
  471.     if ((argbuf = (char *) malloc((size_t)(CMDLINELEN))) == NULL)
  472.         goto barf;
  473.     if ((reply_string = (char *) malloc((size_t)(RECEIVEDLINELEN))) == NULL)
  474.         goto barf;
  475.     
  476.     *macbuf = '\0';
  477.     init_transfer_buffer();
  478.     return (0);
  479. barf:
  480.     return (-1);
  481. }    /* init_arrays */
  482.  
  483.  
  484.  
  485. #ifndef BUFSIZ
  486. #define BUFSIZ 512
  487. #endif
  488.  
  489. void init_transfer_buffer(void)
  490. {
  491.     extern char *xferbuf;
  492.     extern size_t xferbufsize;
  493.     
  494.     /* Make sure we use a multiple of BUFSIZ for efficiency. */
  495.     xferbufsize = (MAX_XFER_BUFSIZE / BUFSIZ) * BUFSIZ;
  496.     while (1) {
  497.         xferbuf = (char *) malloc (xferbufsize);
  498.         if (xferbuf != NULL || xferbufsize < 1024)
  499.             break;
  500.         xferbufsize >>= 2;
  501.     }
  502.     
  503.     if (xferbuf != NULL) return;
  504.     fatal("out of memory for transfer buffer.");
  505. }    /* init_transfer_buffer */
  506.  
  507.  
  508.  
  509.  
  510. void init_prompt(void)
  511. {
  512.     register char *cp;
  513.     
  514.     percent_flags = at_flags = 0;
  515.     for (cp = prompt; *cp; cp++) {
  516.         if (*cp == '%') percent_flags = 1;
  517.         else if (*cp == '@@') at_flags = 1;
  518.     }
  519. }    /* init_prompt */
  520.  
  521.  
  522.  
  523. /*ARGSUSED*/
  524. void lostpeer SIG_PARAMS
  525. {
  526.     if (connected) {
  527.         close_streams(1);
  528.         if (data >= 0) {
  529.             (void) shutdown(data, 1+1);
  530.             (void) close(data);
  531.             data = -1;
  532.         }
  533.         connected = 0;
  534.     }
  535.     if (connected) {
  536.         close_streams(1);
  537.         connected = 0;
  538.     }
  539.     hostname[0] = cwd[0] = 0;
  540.     logged_in = macnum = 0;
  541. }    /* lostpeer */
  542.  
  543.  
  544. /*
  545.  * Command parser.
  546.  */
  547. void cmdscanner(int top)
  548. {
  549.     register struct cmd *c;
  550. #ifdef CURSES
  551.     string vis, *vp;
  552. #endif
  553.  
  554.     if (!top)
  555.         (void) putchar('\n');
  556.     for (;;) {
  557.         if (!doing_script && !UserLoggedIn())
  558.             (void) quit(0, NULL);
  559.         if (Gets(strprompt(), line, (size_t)CMDLINELEN) == NULL) {
  560.             (void) quit(0, NULL);    /* control-d */
  561.         }
  562.         eventnumber++;
  563.         dbprintf("\"%s\"\n", line);
  564.         (void) makeargv();
  565.         if (margc == 0) {
  566.             continue;    /* blank line... */
  567.         }
  568.         c = getcmd(margv[0]);
  569.         if (c == (struct cmd *) -1) {
  570.             (void) printf("?Ambiguous command\n");
  571.             continue;
  572.         }
  573.         if (c == 0) {
  574.             if (!implicit_cd(margv[0]))
  575.                 (void) printf("?Invalid command\n");
  576.             continue;
  577.         }
  578.         if (c->c_conn && !connected) {
  579.             (void) printf ("Not connected.\n");
  580.             continue;
  581.         }
  582.         if ((*c->c_handler)(margc, margv) == USAGE)
  583.             cmd_usage(c);
  584.         if (c->c_handler != help)
  585.             break;
  586.     }
  587.     (void) Signal(SIGINT, intr);
  588.     (void) Signal(SIGPIPE, lostpeer);
  589. }    /* cmdscanner */
  590.  
  591.  
  592.  
  593.  
  594. char *strprompt(void)
  595. {
  596.     time_t                    tyme;
  597.     char                    eventstr[8];
  598.     char                    *dname, *lastlinestart;
  599.     register char            *p, *q;
  600.     string                    str;
  601.     int                        flag;
  602.  
  603.     if (at_flags == 0 && percent_flags == 0) {
  604.         epromptlen = strlen(prompt);
  605.         return (prompt);    /* But don't overwrite it! */
  606.     }
  607.     epromptlen = 0;
  608.     lastlinestart = prompt2;
  609.     if (at_flags) {
  610.         for (p = prompt, q = prompt2, *q = 0; (*p); p++) {
  611.             if (*p == '@@') switch (flag = *++p) {
  612.                 case '\0':
  613.                     --p;
  614.                     break;
  615.                 case 'M':
  616.                     if (CheckNewMail() > 0)
  617.                         q = Strpcpy(q, "(Mail) ");
  618.                     break;
  619.                 case 'N':
  620.                     q = Strpcpy(q, "\n");
  621.                     lastlinestart = q;
  622.                     epromptlen = 0;
  623.                     break;
  624.                 case 'P':    /* reset to no bold, no uline, no inverse, etc. */
  625.                     if (ansi_escapes) {
  626.                         q = Strpcpy(q, tcap_normal);
  627.                         epromptlen += tcl_normal;
  628.                     }
  629.                     break;
  630.                 case 'B':    /* toggle boldface */
  631.                     if (ansi_escapes) {
  632.                         q = Strpcpy(q, tcap_boldface);
  633.                         epromptlen += tcl_bold;
  634.                     }
  635.                     break;
  636.                 case 'U':    /* toggle underline */
  637.                     if (ansi_escapes) {
  638.                         q = Strpcpy(q, tcap_underline);
  639.                         epromptlen += tcl_uline;
  640.                     }
  641.                     break;
  642.                 case 'R':
  643.                 case 'I':    /* toggle inverse (reverse) video */
  644.                     if (ansi_escapes) {
  645.                         q = Strpcpy(q, tcap_reverse);
  646.                         epromptlen += tcl_rev;
  647.                     }
  648.                     break;
  649.                 case 'D':    /* insert current directory */
  650.                 case 'J':
  651.                     if ((flag == 'J') && (remote_is_unix)) {
  652.                         /* Not the whole path, just the dir name. */
  653.                         dname = rindex(cwd, '/');
  654.                         if (dname == NULL)
  655.                             dname = cwd;
  656.                         else if ((dname != cwd) && (dname[1]))
  657.                             ++dname;
  658.                     } else
  659.                         dname = cwd;
  660.                     if (dname[0]) {
  661.                         q = Strpcpy(q, dname);
  662.                         q = Strpcpy(q, " ");
  663.                     }
  664.                     break;
  665.                 case 'H':    /* insert name of connected host */
  666.                     if (logged_in) {
  667.                         (void) sprintf(str, "%s ", hostname);
  668.                         q = Strpcpy(q, str);
  669.                     }
  670.                     break;
  671.                 case 'C':  /* Insert host:path (colon-mode format. */
  672.                     if (logged_in) {
  673.                         (void) sprintf(str, "%s:%s ", hostname, cwd);
  674.                         q = Strpcpy(q, str);
  675.                     } else
  676.                         q = Strpcpy(q, "(not connected)");
  677.                     break;
  678.                 case 'c':
  679.                     if (logged_in) {
  680.                         (void) sprintf(str, "%s:%s\n", hostname, cwd);
  681.                         q = Strpcpy(q, str);
  682.                         lastlinestart = q;    /* there is a \n at the end. */
  683.                         epromptlen = 0;
  684.                     }
  685.                     break;
  686.                 case '!':
  687.                 case 'E':    /* insert event number */
  688.                     (void) sprintf(eventstr, "%ld", eventnumber);
  689.                     q = Strpcpy(q, eventstr);
  690.                     break;
  691.                 default:
  692.                     *q++ = *p;    /* just copy it; unknown switch */
  693.             } else
  694.                 *q++ = *p;
  695.         }
  696.         *q = '\0';
  697.     } else 
  698.         (void) strcpy(prompt2, prompt);
  699.     
  700. #ifndef NO_STRFTIME
  701.     if (percent_flags) {
  702.         /*    only strftime if the user requested it (with a %something),
  703.             otherwise don't waste time doing nothing. */
  704.         (void) time(&tyme);
  705.         (void) Strncpy(str, prompt2);
  706.         (void) strftime(prompt2, sizeof(str), str, localtime(&tyme));
  707.     }
  708. #endif
  709.     epromptlen = (size_t) ((long) strlen(lastlinestart) - (long) epromptlen);
  710.     return (prompt2);
  711. }    /* strprompt */
  712.  
  713.  
  714. /*
  715.  * Slice a string up into argc/argv.
  716.  */
  717.  
  718. void makeargv(void)
  719. {
  720.     char **argp;
  721.  
  722.     margc = 0;
  723.     argp = margv;
  724.     stringbase = line;        /* scan from first of buffer */
  725.     argbase = argbuf;        /* store from first of buffer */
  726.     slrflag = 0;
  727.     while (*argp++ = slurpstring())
  728.         margc++;
  729. }    /* makeargv */
  730.  
  731.  
  732.  
  733.  
  734. /*
  735.  * Parse string into argbuf;
  736.  * implemented with FSM to
  737.  * handle quoting and strings
  738.  */
  739. char *slurpstring(void)
  740. {
  741.     int got_one = 0;
  742.     register char *sb = stringbase;
  743.     register char *ap = argbase;
  744.     char *tmp = argbase;        /* will return this if token found */
  745.  
  746.     if (*sb == '!' || *sb == '$') {    /* recognize ! as a token for shell */
  747.         switch (slrflag) {    /* and $ as token for macro invoke */
  748.             case 0:
  749.                 slrflag++;
  750.                 stringbase++;
  751.                 return ((*sb == '!') ? "!" : "$");
  752.                 /* NOTREACHED */
  753.             case 1:
  754.                 slrflag++;
  755.                 altarg = stringbase;
  756.                 break;
  757.             default:
  758.                 break;
  759.         }
  760.     }
  761.  
  762. S0:
  763.     switch (*sb) {
  764.  
  765.     case '\0':
  766.         goto OUT;
  767.  
  768.     case ' ':
  769.     case '\t':
  770.     case '\n':
  771.     case '=':
  772.         sb++; goto S0;
  773.  
  774.     default:
  775.         switch (slrflag) {
  776.             case 0:
  777.                 slrflag++;
  778.                 break;
  779.             case 1:
  780.                 slrflag++;
  781.                 altarg = sb;
  782.                 break;
  783.             default:
  784.                 break;
  785.         }
  786.         goto S1;
  787.     }
  788.  
  789. S1:
  790.     switch (*sb) {
  791.  
  792.     case ' ':
  793.     case '\t':
  794.     case '\n':
  795.     case '=':
  796.     case '\0':
  797.         goto OUT;    /* end of token */
  798.  
  799.     case '\\':
  800.         sb++; goto S2;    /* slurp next character */
  801.  
  802.     case '"':
  803.         sb++; goto S3;    /* slurp quoted string */
  804.  
  805.     default:
  806.         *ap++ = *sb++;    /* add character to token */
  807.         got_one = 1;
  808.         goto S1;
  809.     }
  810.  
  811. S2:
  812.     switch (*sb) {
  813.  
  814.     case '\0':
  815.         goto OUT;
  816.  
  817.     default:
  818.         *ap++ = *sb++;
  819.         got_one = 1;
  820.         goto S1;
  821.     }
  822.  
  823. S3:
  824.     switch (*sb) {
  825.  
  826.     case '\0':
  827.         goto OUT;
  828.  
  829.     case '"':
  830.         sb++; goto S1;
  831.  
  832.     default:
  833.         *ap++ = *sb++;
  834.         got_one = 1;
  835.         goto S3;
  836.     }
  837.  
  838. OUT:
  839.     if (got_one)
  840.         *ap++ = '\0';
  841.     argbase = ap;            /* update storage pointer */
  842.     stringbase = sb;        /* update scan pointer */
  843.     if (got_one) {
  844.         return(tmp);
  845.     }
  846.     switch (slrflag) {
  847.         case 0:
  848.             slrflag++;
  849.             break;
  850.         case 1:
  851.             slrflag++;
  852.             altarg = (char *) 0;
  853.             break;
  854.         default:
  855.             break;
  856.     }
  857.     return((char *)0);
  858. }    /* slurpstring */
  859.  
  860. /*
  861.  * Help command.
  862.  * Call each command handler with argc == 0 and argv[0] == name.
  863.  */
  864. int
  865. help(int argc, char **argv)
  866. {
  867.     register struct cmd        *c;
  868.     int                        showall = 0, helpall = 0;
  869.     char                    *arg;
  870.     int                        i, j, k;
  871.     int                     nRows, nCols;
  872.     int                     nCmds2Print;
  873.     int                     screenColumns;
  874.     int                     len, widestName;
  875.     char                     *cp, **cmdnames, spec[16];
  876.  
  877.     if (argc == 2) {
  878.         showall = (strcmp(argv[1], "showall") == 0);
  879.         helpall = (strcmp(argv[1], "helpall") == 0);
  880.     }
  881.     if (argc == 1 || showall)  {
  882.         (void) printf("\
  883. Commands may be abbreviated.  'help showall' shows aliases, invisible and\n\
  884. unsupported commands.  'help <command>' gives a brief description of <command>.\n\n");
  885.  
  886.         for (c = cmdtab, nCmds2Print=0; c->c_name != NULL; c++) 
  887.             if (!c->c_hidden || showall)
  888.                 nCmds2Print++;
  889.  
  890.         if ((cmdnames = (char **) malloc(sizeof(char *) * nCmds2Print)) == NULL)
  891.             fatal("out of memory!");
  892.  
  893.         for (c = cmdtab, i=0, widestName=0; c->c_name != NULL; c++) {
  894.             if (!c->c_hidden || showall) {
  895.                 cmdnames[i++] = c->c_name;
  896.                 len = (int) strlen(c->c_name);
  897.                 if (len > widestName)
  898.                     widestName = len;
  899.             }
  900.         }
  901.  
  902.         if ((cp = getenv("COLUMNS")) == NULL)
  903.             screenColumns = 80;
  904.         else
  905.             screenColumns = atoi(cp);
  906.  
  907.         widestName += 2;    /* leave room for white-space in between cols. */
  908.         nCols = screenColumns / widestName;
  909.         /* if ((screenColumns % widestName) > 0) nCols++; */
  910.         nRows = nCmds2Print / nCols;
  911.         if ((nCmds2Print % nCols) > 0)
  912.             nRows++;
  913.  
  914.         (void) sprintf(spec, "%%-%ds", widestName);
  915.         for (i=0; i<nRows; i++) {
  916.             for (j=0; j<nCols; j++) {
  917.                 k = nRows*j + i;
  918.                 if (k < nCmds2Print)
  919.                     (void) printf(spec, cmdnames[k]);
  920.             }
  921.             (void) printf("\n");
  922.         }
  923.         Free(cmdnames);
  924.     } else if (helpall) {
  925.         /* Really intended to debug the help strings. */
  926.         for (c = cmdtab; c->c_name != NULL; c++) {
  927.             cmd_help(c);
  928.             cmd_usage(c);
  929.         }
  930.     } else while (--argc > 0) {
  931.         arg = *++argv;
  932.         c = getcmd(arg);
  933.         if (c == (struct cmd *)-1)
  934.             (void) printf("?Ambiguous help command %s\n", arg);
  935.         else if (c == (struct cmd *)0)
  936.             (void) printf("?Invalid help command %s\n", arg);
  937.         else {
  938.             cmd_help(c);
  939.             cmd_usage(c);
  940.         }
  941.     }
  942.     return NOERR;
  943. }    /* help */
  944.  
  945.  
  946. /*
  947.  * If the user wants to, s/he can specify the maximum size of the log
  948.  * file, so it doesn't waste too much disk space.  If the log is too
  949.  * fat, trim the older lines (at the top) until we're under the limit.
  950.  */
  951. void trim_log(void)
  952. {
  953.     FILE                *new, *old;
  954.     struct stat            st;
  955.     long                fat;
  956.     string                tmplogname, str;
  957.  
  958.     if (logsize <= 0 || *logfname == 0 || stat(logfname, &st) ||
  959.         (old = fopen(logfname, "r")) == NULL)
  960.         return;    /* never trim, or no log */
  961.     fat = st.st_size - logsize;
  962.     if (fat <= 0L) return;    /* log too small yet */
  963.     while (fat > 0L) {
  964.         if (FGets(str, old) == NULL) return;
  965.         fat -= (long) strlen(str);
  966.     }
  967.     /* skip lines until a new site was opened */
  968.     while (1) {
  969.         if (FGets(str, old) == NULL) {
  970.             (void) fclose(old);
  971.             (void) unlink(logfname);
  972.             return;    /* nothing left, start anew */
  973.         }
  974.         if (*str != '\t') break;
  975.     }
  976.     
  977.     /* copy the remaining lines in "old" to "new" */
  978.     (void) Strncpy(tmplogname, logfname);
  979.     tmplogname[strlen(tmplogname) - 1] = 'T';
  980.     if ((new = fopen(tmplogname, "w")) == NULL) {
  981.         (void) PERROR("trim_log", tmplogname);
  982.         return;
  983.     }
  984.     (void) fputs(str, new);
  985.     while (FGets(str, old))
  986.         (void) fputs(str, new);
  987.     (void) fclose(old); (void) fclose(new);
  988.     if (unlink(logfname) < 0)
  989.         PERROR("trim_log", logfname);
  990.     if (rename(tmplogname, logfname) < 0)
  991.         PERROR("trim_log", tmplogname);
  992. }    /* trim_log */
  993.  
  994.  
  995.  
  996.  
  997. int CheckNewMail(void)
  998. {
  999.     struct stat stbuf;
  1000.  
  1001.     if (*mail_path == '\0') return 0;
  1002.     if (stat(mail_path, &stbuf) < 0) {    /* cant find mail_path so we'll */
  1003.         *mail_path = '\0';                /* never check it again */
  1004.         return 0;
  1005.     }
  1006.  
  1007.     /*
  1008.      * Check if the size is non-zero and the access time is less than
  1009.      * the modify time -- this indicates unread mail.
  1010.      */
  1011.     if ((stbuf.st_size != 0) && (stbuf.st_atime <= stbuf.st_mtime)) {
  1012.         if (stbuf.st_mtime > mbox_time) {
  1013.             (void) printf("%s\n", NEWMAILMESSAGE);
  1014.             mbox_time = stbuf.st_mtime;
  1015.         }
  1016.         return 1;
  1017.     }
  1018.  
  1019.     return 0;
  1020. }    /* CheckNewMail */
  1021.  
  1022.  
  1023.  
  1024. #ifdef CURSES
  1025. int termcap_get(char **dest, char *attr)
  1026. {
  1027.     static char area[1024];
  1028.     static char *s = area, *t;
  1029.     char buf[64], *cp;
  1030.     int i, result = -1;
  1031.  
  1032.     buf[0] = 0;
  1033.     if ((t = tgetstr(attr, &s)) != NULL)
  1034.         (void) Strncpy(buf, t);
  1035.  
  1036.     if (buf[0]) {
  1037.          for (i = 0; (buf[i] <= '9') && (buf[i] >= '0'); )
  1038.             ++i; 
  1039.          if ((*dest = (char *)malloc(strlen(&(buf[i])) + 1)) == NULL) {
  1040.              *dest = "";
  1041.          } else {
  1042.              (void) strcpy(*dest, &(buf[i]));
  1043.             /* Get rid of the terminal delays, like "$<2>". */
  1044.             if ((cp = strstr(*dest, "$<")) != NULL)
  1045.                 *cp = 0;
  1046.             result = 0;
  1047.         }
  1048.      } else { 
  1049.          *dest = "";
  1050.     }
  1051.     return (result);
  1052. }    /* termcap_get */
  1053.  
  1054.  
  1055.   
  1056. void termcap_init(void)
  1057. {
  1058.     static char area[1024];
  1059.     static char *s = area;
  1060.     char *term;
  1061.  
  1062.     if ((term = getenv("TERM")) == NULL) {
  1063.         term = "dumb";  /* TAR */
  1064.         ansi_escapes = 0;
  1065.     }
  1066.     if (tgetent(tcbuf,term) != 1) {
  1067.         (void) fprintf(stderr,"Can't get termcap entry for terminal [%s]\n", term);
  1068.     } else {
  1069.         (void) termcap_get(&tcap_normal, "me");
  1070.         if (termcap_get(&tcap_boldface, "md") < 0) {
  1071.             /* Dim-mode is better than nothing... */
  1072.             (void) termcap_get(&tcap_normal, "mh");
  1073.         }
  1074.         (void) termcap_get(&tcap_underline, "us");
  1075.         (void) termcap_get(&tcap_reverse, "so");
  1076.         tcl_normal = strlen(tcap_normal);
  1077.         tcl_bold = strlen(tcap_boldface);
  1078.         tcl_uline = strlen(tcap_underline);
  1079.         tcl_rev = strlen(tcap_reverse);
  1080.     }
  1081.  
  1082. }    /* termcap_init */
  1083.  
  1084.  
  1085.  
  1086. static int c_output(int c)
  1087. {
  1088.     putchar(c);
  1089. }    /* c_output */
  1090.  
  1091.  
  1092.  
  1093.  
  1094. void tcap_put(char *cap)
  1095. {
  1096.     tputs(cap, 0, c_output);
  1097. }    /* tcap_put */
  1098.  
  1099. #endif /* CURSES */
  1100.  
  1101. /* eof main.c */
  1102.  
  1103. @
  1104.  
  1105.  
  1106. 14020.15
  1107. log
  1108. @checked in with -k by alph at 1993/10/10 19:59:56
  1109. @
  1110. text
  1111. @d4 2
  1112. a5 2
  1113.  *  $Revision: 14020.15 $
  1114.  *  $Date: 93/07/09 11:50:12 $
  1115. d380 2
  1116. d385 1
  1117. a385 2
  1118.     extern char                *home;    /* for glob.c */
  1119.     
  1120. d419 12
  1121. @
  1122.