home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume34 / ncftp / part02 / main.c < prev   
Encoding:
C/C++ Source or Header  |  1992-12-08  |  16.9 KB  |  828 lines

  1. /* main.c */
  2.  
  3. #define _main_c_
  4.  
  5. #include "sys.h"
  6. #include <sys/types.h>
  7. #include <sys/param.h>
  8. #include <sys/socket.h>
  9. #include <sys/ioctl.h>
  10. #include <sys/stat.h>
  11. #include <sys/time.h>
  12. #include <arpa/ftp.h>
  13. #include <setjmp.h>
  14. #include <signal.h>
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <errno.h>
  19. #include <ctype.h>
  20. #include <netdb.h>
  21. #include <unistd.h>
  22. #include <pwd.h>
  23. #ifdef TCAP
  24. #    undef HZ        /* Collides with HaZeltine ! */
  25. #    include <tcap.h>
  26. #endif    /* TCAP */
  27. #include "ftpdefs.h"
  28. #include "defaults.h"
  29. #include "cmds.h"
  30. #include "main.h"
  31. #include "ftp.h"
  32. #include "ftprc.h"
  33. #include "copyright.h"
  34.  
  35. /* main.c globals */
  36. int                    slrflag;
  37. int                    fromatty;            /* input is from a terminal */
  38. char                *altarg;            /* argv[1] with no shell-like preprocessing  */
  39. struct    servent        *sp;                /* service spec for tcp/ftp */
  40. jmp_buf                toplevel;            /* non-local goto stuff for cmd scanner */
  41. char                *line;                /* input line buffer */
  42. char                *stringbase;        /* current scan point in line buffer */
  43. char                *argbuf;            /* argument storage buffer */
  44. char                *argbase;            /* current storage point in arg buffer */
  45. int                    margc;                /* count of arguments on input line */
  46. char                *margv[20];            /* args parsed from input line */
  47. struct userinfo        uinfo;                /* a copy of their pwent really */
  48. int                    ansi_escapes;        /* for fancy graphics */
  49. int                    ignore_rc;            /* are we supposed to ignore the netrc */
  50. string                progname;            /* simple filename */
  51. string                prompt, prompt2;    /* shell prompt string */
  52. string                anon_password;        /* most likely your email address */
  53. string                pager;                /* program to browse text files */
  54. string                version = FTP_VERSION;
  55. long                eventnumber;        /* number of commands we've done */
  56. FILE                *logf = NULL;        /* log user activity */
  57. string                logfname;            /* name of the logfile */
  58. long                logsize = 4096L;    /* max log size. 0 == no limit */
  59. int                    percent_flags;        /* "%" in prompt string? */
  60. int                    at_flags;            /* "@" in prompt string? */
  61. string                 mail_path;            /* your mailbox */
  62. int                    newmail;            /* how many new letters you have */
  63. time_t                mbox_time;            /* last modified time of mbox */
  64.  
  65. static char            *tcap_normal = "\033[0m";    /* Default ANSI escapes */
  66. static char            *tcap_boldface = "\033[1m";
  67. static char            *tcap_underline = "\033[4m";
  68. static char            *tcap_reverse = "\033[7m";
  69.  
  70. #ifdef TCAP
  71. static char            tcbuf[2048];
  72. #endif
  73.  
  74. /* main.c externs */
  75. extern int            debug, verbose, mprompt;
  76. extern int            options, cpend, data, connected;
  77. extern int            curtype, macnum;
  78. extern FILE            *cout;
  79. extern struct cmd    cmdtab[];
  80. extern str32        curtypename;
  81. extern char            *macbuf;
  82. extern char            *reply_string;
  83. extern string        hostname, cwd, lcwd;
  84. extern int            optind;
  85. extern char            *optarg;
  86.  
  87. main(int argc, char **argv)
  88. {
  89.     register char        *cp;
  90.     int                    top, opt;
  91.  
  92.     if ((cp = rindex(argv[0], '/'))) cp++;
  93.     else cp = argv[0];
  94.     (void) Strncpy(progname, cp);
  95.     
  96.     sp = getservbyname("ftp", "tcp");
  97.     if (sp == 0) fatal("ftp/tcp: unknown service");
  98.  
  99.     if (init_arrays())            /* Reserve large blocks of memory now */
  100.         fatal("could not reserve large amounts of memory.");
  101.  
  102.     /*
  103.      * Set up defaults for FTP.
  104.      */
  105.     mprompt = dMPROMPT;
  106.     verbose = dVERBOSE;
  107.     debug = dDEBUG;
  108.  
  109.     (void) Strncpy(curtypename, dTYPESTR);
  110.     curtype = dTYPE;
  111.     (void) Strncpy(prompt, dPROMPT);
  112.     
  113.     /*    Setup our pager variable, before we run through the rc,
  114.         which may change it. */
  115.     set_pager(getenv("PAGER"), 0);
  116.  
  117.     ansi_escapes = 0;
  118.     if ((cp = getenv("TERM")) != NULL && *cp++ == 'v' && *cp++ == 't')
  119.         ansi_escapes = 1;    /* only if a vt100ish terminal */
  120.     (void) getuserinfo();
  121.     newmail = 0;
  122.     (void) time(&mbox_time);
  123.     (void) Strncpy(anon_password, uinfo.username);
  124.     if (getlocalhostname(uinfo.hostname, sizeof(uinfo.hostname)) == 0) {
  125.         (void) Strncat(anon_password, "@");
  126.         (void) Strncat(anon_password, uinfo.hostname);
  127.     }
  128. #if dLOGGING
  129.     (void) sprintf(logfname, "%s/%s", uinfo.homedir, dLOGNAME);
  130. #else
  131.     *logfname = 0;
  132. #endif
  133.     (void) get_cwd(lcwd, (int) sizeof(lcwd));
  134.  
  135.     ignore_rc = 0;
  136.  
  137.     while ((opt = getopt(argc, argv, "dvinr0hH")) >= 0) {
  138.         switch(opt) {
  139.             case 'd':
  140.                 /* options |= SO_DEBUG; done below... */
  141.                 debug++;
  142.                 break;
  143.             
  144.             case 'v':
  145.                 verbose++;
  146.                 break;
  147.  
  148.             case 'i':
  149.                 mprompt = !mprompt;
  150.                 break;
  151.  
  152.             case 'n':
  153.             case 'r':
  154.             case '0':
  155.                 ignore_rc = !ignore_rc;
  156.                 break;
  157.  
  158.             case 'H':
  159.             case 'h':
  160.                 show_version(0, NULL);
  161.                 exit (0);
  162.  
  163.             default:
  164.                 (void) fprintf(stderr,
  165.                   "%s: unknown option \"%c\"\n", progname, (int) *cp);
  166.         }
  167.     }
  168.  
  169.     if (ignore_rc == 0)
  170.         (void) thrash_rc();
  171.  
  172.     (void) fix_options();    /* adjust "options" according to "debug"  */
  173.     
  174.     fromatty = isatty(fileno(stdin));
  175.     cpend = 0;  /* no pending replies */
  176.     
  177.     if (*logfname)
  178.         logf = fopen (logfname, "a");
  179.  
  180.     eventnumber = 0L;
  181.     cp = argv[optind];
  182.     /* The user specified a host on the command line.  Open it now... */
  183.     if (argc > 1 && cp) {
  184.         if (setjmp(toplevel))
  185.             exit(0);
  186.         (void) signal(SIGINT, intr);
  187.         (void) signal(SIGPIPE, lostpeer);
  188.         (void) strcpy(line, "open ");
  189.         (void) strcat(line, cp);
  190.         makeargv();
  191.         (void) setpeer(margc, margv);
  192.     }
  193.  
  194.     (void) init_prompt();
  195.  
  196.     eventnumber = 1L;
  197.     if (ansi_escapes) {
  198. #ifndef TCAP
  199.         (void) printf("%s%s Ready.%s\n", 
  200.                 tcap_boldface, FTP_VERSION, tcap_normal);
  201. #else
  202.         char vis[BUFSIZ];
  203.         (void) sprintf(vis, "%s%s Ready.%s\n", 
  204.                 tcap_boldface, FTP_VERSION, tcap_normal);
  205.         tcap_put(vis);
  206. #endif /* !TCAP */
  207.     }
  208.     else
  209.         (void) printf("%s Ready.\n", FTP_VERSION);
  210.     top = setjmp(toplevel) == 0;
  211.     if (top) {
  212.         (void) signal(SIGINT, intr);
  213.         (void) signal(SIGPIPE, lostpeer);
  214.     }
  215.     for (;;) {
  216.         (void) cmdscanner(top);
  217.         top = 1;
  218.     }
  219. }    /* main */
  220.  
  221.  
  222.  
  223. /*ARGSUSED*/
  224. void intr(int unused)
  225. {
  226.     (void) longjmp(toplevel, 1);
  227. }    /* intr */
  228.  
  229.  
  230.  
  231. int getuserinfo(void)
  232. {
  233.     register char            *cp;
  234.     struct passwd            *pw = NULL;
  235.     string                    str;
  236.     extern char                *home;    /* for glob.c */
  237.     
  238.     cp = getlogin();
  239.     if (cp != NULL)
  240.         pw = getpwnam(cp);
  241.     if (pw == NULL)
  242.         pw = getpwuid(getuid());
  243.     if (pw != NULL) {
  244.         (void) Strncpy(uinfo.username, pw->pw_name);
  245.         (void) Strncpy(uinfo.shell, pw->pw_shell);
  246.         (void) Strncpy(uinfo.homedir, pw->pw_dir);
  247.         uinfo.uid = pw->pw_uid;
  248.         home = uinfo.homedir;    /* for glob.c */
  249.         if (((cp = getenv("MAIL")) == NULL) && ((cp = getenv("mail")) == NULL)) {
  250.             (void) sprintf(str, "/usr/spool/mail/%s", uinfo.username);
  251.             cp = str;
  252.         }
  253.         /*    mbox variable may be like MAIL=(28 /usr/mail/me /usr/mail/you),
  254.             so try to find the first mail path.  */
  255.         while (*cp != '/')
  256.             cp++;
  257.         (void) Strncpy(mail_path, cp);
  258.         if ((cp = index(mail_path, ' ')) != NULL)
  259.             *cp = '\0';
  260.         return (0);
  261.     } else {
  262.         (void) Strncpy(uinfo.username, "unknown");
  263.         (void) Strncpy(uinfo.shell, "/bin/sh");
  264.         (void) Strncpy(uinfo.homedir, ".");    /* current directory */
  265.         uinfo.uid = 999;
  266.         return (-1);
  267.     }
  268. }    /* getuserinfo */
  269.  
  270.  
  271.  
  272.  
  273. int init_arrays(void)
  274. {
  275.     if ((macbuf = (char *) malloc((size_t)(MACBUFLEN))) == NULL)
  276.         goto barf;
  277.     if ((line = (char *) malloc((size_t)(CMDLINELEN))) == NULL)
  278.         goto barf;
  279.     if ((argbuf = (char *) malloc((size_t)(CMDLINELEN))) == NULL)
  280.         goto barf;
  281.     if ((reply_string = (char *) malloc((size_t)(RECEIVEDLINELEN))) == NULL)
  282.         goto barf;
  283.     
  284.     *macbuf = '\0';
  285.     init_transfer_buffer();
  286.     return (0);
  287. barf:
  288.     return (-1);
  289. }    /* init_arrays */
  290.  
  291.  
  292.  
  293. void init_transfer_buffer(void)
  294. {
  295.     extern char *xferbuf;
  296.     extern size_t xferbufsize;
  297.     
  298.     xferbufsize = MAX_XFER_BUFSIZE;
  299.     while (1) {
  300.         xferbuf = (char *) malloc (xferbufsize);
  301.         if (xferbuf != NULL || xferbufsize < 1024)
  302.             break;
  303.         xferbufsize >>= 2;
  304.     }
  305.     
  306.     if (xferbuf != NULL) return;
  307.     fatal("out of memory for transfer buffer.");
  308. }    /* init_transfer_buffer */
  309.  
  310.  
  311.  
  312.  
  313. void init_prompt(void)
  314. {
  315.     register char *cp;
  316.     
  317.     percent_flags = at_flags = 0;
  318.     for (cp = prompt; *cp; cp++) {
  319.         if (*cp == '%') percent_flags = 1;
  320.         else if (*cp == '@') at_flags = 1;
  321.     }
  322. }    /* init_prompt */
  323.  
  324.  
  325.  
  326. /*ARGSUSED*/
  327. void lostpeer(int unused)
  328. {
  329.     if (connected) {
  330.         close_streams(1);
  331.         if (data >= 0) {
  332.             (void) shutdown(data, 1+1);
  333.             (void) close(data);
  334.             data = -1;
  335.         }
  336.         connected = 0;
  337.     }
  338.     if (connected) {
  339.         close_streams(1);
  340.         connected = 0;
  341.     }
  342.     hostname[0] = cwd[0] = 0;
  343.     macnum = 0;
  344. }    /* lostpeer */
  345.  
  346.  
  347.  
  348. /*
  349.  * Command parser.
  350.  */
  351. void cmdscanner(int top)
  352. {
  353.     register struct cmd *c;
  354. #ifdef TCAP
  355.     char vis[BUFSIZ], *vp;
  356. #endif
  357.  
  358.     if (!top)
  359.         (void) putchar('\n');
  360.     for (;;) {
  361.         if (fromatty) {
  362. #ifndef TCAP
  363.             (void) printf(strprompt());
  364. #else
  365.             (void) sprintf(vis, "%s", strprompt());
  366.             tcap_put(vis);
  367.  
  368. #endif /* !TCAP */
  369.             (void) fflush(stdout);
  370.         }
  371.         if (gets(line) == 0) {
  372.             if (feof(stdin) || ferror(stdin))
  373.                 (void) quit(0, NULL);    /* control-d */
  374.             break;
  375.         }
  376.         if (line[0] == 0)    /* blank line */
  377.             break;
  378.         eventnumber++;
  379.         if (debug > 1)
  380.             (void) printf("---> \"%s\"\n", line);
  381.         (void) makeargv();
  382.         if (margc == 0) {
  383.             continue;    /* blank line... */
  384.         }
  385.         c = getcmd(margv[0]);
  386.         if (c == (struct cmd *) -1) {
  387.             (void) printf("?Ambiguous command\n");
  388.             continue;
  389.         }
  390.         if (c == 0) {
  391.             if (!implicit_cd(margv[0]))
  392.                 (void) printf("?Invalid command\n");
  393.             continue;
  394.         }
  395.         if (c->c_conn && !connected) {
  396.             (void) printf ("Not connected.\n");
  397.             continue;
  398.         }
  399.         (*c->c_handler)(margc, margv);
  400.         if (c->c_handler != help)
  401.             break;
  402.     }
  403.     (void) signal(SIGINT, intr);
  404.     (void) signal(SIGPIPE, lostpeer);
  405. }    /* cmdscanner */
  406.  
  407.  
  408.  
  409.  
  410. char *strprompt(void)
  411. {
  412.     time_t                    tyme;
  413.     char                    eventstr[8];
  414.     register char            *p, *q;
  415.     string                    str;
  416.     extern int                percent_flags, at_flags;
  417. #ifdef TCAP
  418.     static int                 virgin = 0;
  419.  
  420.     if (!virgin++ && ansi_escapes)
  421.         termcap_init();
  422. #endif /* TCAP */
  423.  
  424.  
  425.     if (at_flags == 0 && percent_flags == 0)
  426.         return (prompt);    /* But don't overwrite it! */
  427.  
  428.     if (at_flags) {
  429.         for (p = prompt, q = prompt2, *q = 0; (*p); p++)
  430.             if (*p == '@') switch ((toupper(*++p))) {
  431.                 case '\0':
  432.                     --p;
  433.                     break;
  434.                 case 'M':
  435.                     if (CheckNewMail() > 0)
  436.                         q = Strpcpy(q, "(Mail) ");
  437.                     break;
  438.                 case 'P':    /* reset to no bold, no uline, no inverse, etc. */
  439.                     if (ansi_escapes)
  440.                         q = Strpcpy(q, tcap_normal);
  441.                     break;
  442.                 case 'B':    /* toggle boldface */
  443.                     if (ansi_escapes)
  444.                         q = Strpcpy(q, tcap_boldface);
  445.                     break;
  446.                 case 'U':    /* toggle underline */
  447.                     if (ansi_escapes)
  448.                         q = Strpcpy(q, tcap_underline);
  449.                     break;
  450.                 case 'R':
  451.                 case 'I':    /* toggle inverse (reverse) video */
  452.                     if (ansi_escapes)
  453.                         q = Strpcpy(q, tcap_reverse);
  454.                     break;
  455.                 case 'D':    /* insert current directory */
  456.                     if (cwd != NULL)
  457.                         q = Strpcpy(q, cwd);
  458.                     break;
  459.                 case 'H':    /* insert name of connected host */
  460.                     if (hostname != NULL)
  461.                         q = Strpcpy(q, hostname);
  462.                     break;
  463.                 case '!':
  464.                 case 'E':    /* insert event number */
  465.                     (void) sprintf(eventstr, "%ld", eventnumber);
  466.                     q = Strpcpy(q, eventstr);
  467.                     break;
  468.                 default:
  469.                     *q++ = *p;    /* just copy it; unknown switch */
  470.             } else
  471.                 *q++ = *p;
  472.         *q = '\0';
  473.     } else 
  474.         (void) strcpy(prompt2, prompt);
  475.     
  476.     if (percent_flags) {
  477.         /*    only strftime if the user requested it (with a %something),
  478.             otherwise don't waste time doing nothing. */
  479.         (void) time(&tyme);
  480.         (void) Strncpy(str, prompt2);
  481.         (void) strftime(prompt2, sizeof(str), str, localtime(&tyme));
  482.     }        
  483.     return (prompt2);
  484. }    /* strprompt */
  485.  
  486.  
  487.  
  488. char *Strpcpy(char *dst, char *src)
  489. {
  490.     while (*dst++ = *src++)
  491.         ;
  492.     return (--dst);    /* return current value of dst, NOT original value! */
  493. }    /* Strpcpy */
  494.  
  495.  
  496.  
  497.  
  498. struct cmd *getcmd(char *name)
  499. {
  500.     register char *p, *q;
  501.     register struct cmd *c, *found;
  502.     register int nmatches, longest;
  503.  
  504.     if (name == NULL)
  505.         return (NULL);
  506.     longest = 0;
  507.     nmatches = 0;
  508.     found = 0;
  509.     for (c = cmdtab; p = c->c_name; c++) {
  510.         for (q = name; *q == *p++; q++)
  511.             if (*q == 0)        /* exact match? */
  512.                 return (c);
  513.         if (!*q) {            /* the name was a prefix */
  514.             if (q - name > longest) {
  515.                 longest = q - name;
  516.                 nmatches = 1;
  517.                 found = c;
  518.             } else if (q - name == longest)
  519.                 nmatches++;
  520.         }
  521.     }
  522.     if (nmatches > 1)
  523.         return ((struct cmd *)-1);
  524.     return (found);
  525. }    /* getcmd */
  526.  
  527.  
  528.  
  529.  
  530. /*
  531.  * Slice a string up into argc/argv.
  532.  */
  533.  
  534. void makeargv(void)
  535. {
  536.     char **argp;
  537.  
  538.     margc = 0;
  539.     argp = margv;
  540.     stringbase = line;        /* scan from first of buffer */
  541.     argbase = argbuf;        /* store from first of buffer */
  542.     slrflag = 0;
  543.     while (*argp++ = slurpstring())
  544.         margc++;
  545. }    /* makeargv */
  546.  
  547.  
  548.  
  549.  
  550. /*
  551.  * Parse string into argbuf;
  552.  * implemented with FSM to
  553.  * handle quoting and strings
  554.  */
  555. char *slurpstring(void)
  556. {
  557.     int got_one = 0;
  558.     register char *sb = stringbase;
  559.     register char *ap = argbase;
  560.     char *tmp = argbase;        /* will return this if token found */
  561.  
  562.     if (*sb == '!' || *sb == '$') {    /* recognize ! as a token for shell */
  563.         switch (slrflag) {    /* and $ as token for macro invoke */
  564.             case 0:
  565.                 slrflag++;
  566.                 stringbase++;
  567.                 return ((*sb == '!') ? "!" : "$");
  568.                 /* NOTREACHED */
  569.             case 1:
  570.                 slrflag++;
  571.                 altarg = stringbase;
  572.                 break;
  573.             default:
  574.                 break;
  575.         }
  576.     }
  577.  
  578. S0:
  579.     switch (*sb) {
  580.  
  581.     case '\0':
  582.         goto OUT;
  583.  
  584.     case ' ':
  585.     case '\t':
  586.     case '\n':
  587.     case '=':
  588.         sb++; goto S0;
  589.  
  590.     default:
  591.         switch (slrflag) {
  592.             case 0:
  593.                 slrflag++;
  594.                 break;
  595.             case 1:
  596.                 slrflag++;
  597.                 altarg = sb;
  598.                 break;
  599.             default:
  600.                 break;
  601.         }
  602.         goto S1;
  603.     }
  604.  
  605. S1:
  606.     switch (*sb) {
  607.  
  608.     case ' ':
  609.     case '\t':
  610.     case '\n':
  611.     case '=':
  612.     case '\0':
  613.         goto OUT;    /* end of token */
  614.  
  615.     case '\\':
  616.         sb++; goto S2;    /* slurp next character */
  617.  
  618.     case '"':
  619.         sb++; goto S3;    /* slurp quoted string */
  620.  
  621.     default:
  622.         *ap++ = *sb++;    /* add character to token */
  623.         got_one = 1;
  624.         goto S1;
  625.     }
  626.  
  627. S2:
  628.     switch (*sb) {
  629.  
  630.     case '\0':
  631.         goto OUT;
  632.  
  633.     default:
  634.         *ap++ = *sb++;
  635.         got_one = 1;
  636.         goto S1;
  637.     }
  638.  
  639. S3:
  640.     switch (*sb) {
  641.  
  642.     case '\0':
  643.         goto OUT;
  644.  
  645.     case '"':
  646.         sb++; goto S1;
  647.  
  648.     default:
  649.         *ap++ = *sb++;
  650.         got_one = 1;
  651.         goto S3;
  652.     }
  653.  
  654. OUT:
  655.     if (got_one)
  656.         *ap++ = '\0';
  657.     argbase = ap;            /* update storage pointer */
  658.     stringbase = sb;        /* update scan pointer */
  659.     if (got_one) {
  660.         return(tmp);
  661.     }
  662.     switch (slrflag) {
  663.         case 0:
  664.             slrflag++;
  665.             break;
  666.         case 1:
  667.             slrflag++;
  668.             altarg = (char *) 0;
  669.             break;
  670.         default:
  671.             break;
  672.     }
  673.     return((char *)0);
  674. }    /* slurpstring */
  675.  
  676.  
  677.  
  678.  
  679. #define HELPINDENT (sizeof ("directory"))
  680.  
  681. /*
  682.  * Help command.
  683.  * Call each command handler with argc == 0 and argv[0] == name.
  684.  */
  685. help(int argc, char **argv)
  686. {
  687.     register struct cmd        *c;
  688.     int                        i, showall = 0;
  689.     char                    *arg;
  690.  
  691.     if (argc == 2)
  692.         showall = strcmp(argv[1], "all") == 0;
  693.     if (argc == 1 || showall)  {
  694.         (void) printf("Commands may be abbreviated.  'help all' shows aliases,\ninvisible and unsupported commands.  'help <command>' \ngives a brief description of <command>.  Commands are:\n");
  695.         for (c = cmdtab, i=0; c->c_name != NULL; c++) {
  696.             if (c->c_hidden && !showall) continue;
  697.             (void) printf("%-13s", c->c_name);
  698.             if (++i == 6) {
  699.                 i = 0;
  700.                 putchar('\n');
  701.             }
  702.         }
  703.         if (i < 6)
  704.             putchar('\n');
  705.     } else while (--argc > 0) {
  706.         arg = *++argv;
  707.         c = getcmd(arg);
  708.         if (c == (struct cmd *)-1)
  709.             (void) printf("?Ambiguous help command %s\n", arg);
  710.         else if (c == (struct cmd *)0)
  711.             (void) printf("?Invalid help command %s\n", arg);
  712.         else
  713.             (void) printf("%-*s\t%s\n", HELPINDENT,
  714.                 c->c_name, c->c_help);
  715.     }
  716. }    /* help */
  717.  
  718.  
  719. /*
  720.  * If the user wants to, s/he can specify the maximum size of the log
  721.  * file, so it doesn't waste too much disk space.  If the log is too
  722.  * fat, trim the older lines (at the top) until we're under the limit.
  723.  */
  724. void trim_log(void)
  725. {
  726.     FILE                *new, *old;
  727.     struct stat            st;
  728.     long                fat;
  729.     string                tmplogname, str;
  730.  
  731.     if (logsize <= 0 || *logfname == 0 || stat(logfname, &st) ||
  732.         (old = fopen(logfname, "r")) == NULL)
  733.         return;    /* never trim, or no log */
  734.     fat = st.st_size - logsize;
  735.     if (fat <= 0L) return;    /* log too small yet */
  736.     while (fat > 0L) {
  737.         if (FGets(str, old) == NULL) return;
  738.         fat -= (long) strlen(str);
  739.     }
  740.     /* skip lines until a new site was opened */
  741.     while (1) {
  742.         if (FGets(str, old) == NULL) {
  743.             (void) fclose(old);
  744.             (void) unlink(logfname);
  745.             return;    /* nothing left, start anew */
  746.         }
  747.         if (*str != '\t') break;
  748.     }
  749.     
  750.     /* copy the remaining lines in "old" to "new" */
  751.     (void) Strncpy(tmplogname, logfname);
  752.     tmplogname[strlen(tmplogname) - 1] = 'T';
  753.     if ((new = fopen(tmplogname, "w")) == NULL) {
  754.         (void) Perror(tmplogname);
  755.         return;
  756.     }
  757.     (void) fputs(str, new);
  758.     while (FGets(str, old))
  759.         (void) fputs(str, new);
  760.     (void) fclose(old); (void) fclose(new);
  761.     if (unlink(logfname) < 0)
  762.         Perror(logfname);
  763.     if (rename(tmplogname, logfname) < 0)
  764.         Perror(tmplogname);
  765. }    /* trim_log */
  766.  
  767.  
  768.  
  769.  
  770. int CheckNewMail(void)
  771. {
  772.     struct stat stbuf;
  773.  
  774.     if (*mail_path == '\0') return 0;
  775.     if (stat(mail_path, &stbuf) < 0) {    /* cant find mail_path so we'll */
  776.         *mail_path = '\0';                /* never check it again */
  777.         return 0;
  778.     }
  779.  
  780.     if (stbuf.st_mtime > mbox_time) {
  781.         newmail++;
  782.         (void) printf("%s\n", NEWMAILMESSAGE);
  783.         (void) time(&mbox_time);                /* only notify once. */
  784.     }
  785.     
  786.     return newmail;
  787. }    /* CheckNewMail */
  788.  
  789.  
  790. #ifdef TCAP
  791. termcap_init()
  792. {
  793.     static char area[1024];
  794.     static char *s = area;
  795.     char *getenv(), *tgetstr();
  796.     char *term;
  797.  
  798.     if (tgetent(tcbuf,(term = getenv("TERM"))) != 1)
  799.     {
  800.         (void) fprintf(stderr,"Can't get termcap entry for terminal [%s]\n", term);
  801.         return (0);
  802.     }
  803.  
  804.     if (!(tcap_normal = tgetstr("se", &s)))
  805.         tcap_normal = "";
  806.     if (!(tcap_boldface = tgetstr("md", &s)))
  807.         tcap_boldface = "";
  808.     if (!(tcap_underline = tgetstr("us", &s)))
  809.         tcap_underline = "";
  810.     if (!(tcap_reverse = tgetstr("so", &s)))
  811.         tcap_reverse = "";
  812. }
  813.  
  814. static int c_output(c)
  815. int c;
  816. {
  817.     putchar(c);
  818. }
  819.  
  820. tcap_put(cap)
  821. char *cap;
  822. {
  823.     tputs(cap, 0, c_output);
  824. }
  825.  
  826. #endif /* TCAP */
  827. /* eof main.c */
  828.