home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / UUCPbb_2_1_src.lzh / UUCPBB21 / mail.c < prev    next >
Text File  |  1994-09-27  |  26KB  |  946 lines

  1. /*  mail.c   This is the main mail program, Mailx, for the UUCPbb package.
  2.     Copyright (C) 1990, 1993  Rick Adams and Bob Billson
  3.  
  4.     This file is part of the OS-9 UUCP package, UUCPbb.
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  
  20.     The author of UUCPbb, Bob Billson, can be contacted at:
  21.     bob@kc2wz.bubble.org  or  uunet!kc2wz!bob  or  by snail mail:
  22.     21 Bates Way, Westfield, NJ 07090
  23. */
  24.  
  25.  
  26. /* mailx [-r]                                       ...read mail
  27.         opt:    r              -read mail in reverse order
  28.  
  29.    mailx [opts] [<address>...] [opts]               ...send mail
  30.         opts: a <file>         -file replying to
  31.               s "subject"      -Subject: "subject"
  32.               x N              -N = debug level
  33.               d                -don't add signature
  34.               n                -use alt_signature
  35.               c [<user>...]    -check for our waiting mail and that
  36.                                   of 'user' (superuser only)
  37.               p                -don't prompt for carbon copy (Cc:)
  38.               v                -toggle using pager, default [ON|OFF]
  39.               ?                -this message
  40.  
  41.    When used with Shell+, non-superusers need to use '*' instead of '@' in
  42.    command line addresses.  */
  43.  
  44. #define MAIN
  45.  
  46. #include "uucp.h"
  47. #include "mail.h"
  48. #include <signal.h>
  49. #include <modes.h>
  50. #include <ctype.h>
  51. #include <sgstat.h>
  52. #ifndef _OSK
  53. #include <os9.h>
  54. #include "dir_6809.h"
  55. #else
  56. #include <dir.h>
  57. #endif
  58.  
  59. #define ARGVAL()    (*++(*names) || (--count && *++names))
  60.  
  61. extern QQ int childid;                               /* defined in docmd.c */
  62.  
  63. QQ flag readmail = FORWARD;
  64.  
  65. /* Declarations */
  66. long _gs_pos(), _gs_size();
  67. void usage();
  68. int interrupt();
  69.  
  70.  
  71. main (argc, argv)
  72. int argc;
  73. char **argv;
  74. {
  75.      char *ptmp;
  76. #ifndef TERMCAP
  77.      winopen = FALSE;
  78. #endif
  79.  
  80.      /* initialize defaults */
  81.      ltrfile = NULL;
  82.      homedir = NULL;
  83.      *subject = '\0';
  84.      *address = '\0';
  85.      *tempfile = '\0';
  86.      reply = FALSE,                                  /* not replying */
  87.      debug = 0,                                      /* debug is off */
  88.      usesig = USESIG,                                /* use signature file  */
  89.      forward = FALSE,                                /* not forwarding mail */
  90.      childid = -1;                                   /* no children yet */
  91.      pname = *argv;
  92.      usedotilde = FALSE;
  93.      rmailin = FALSE;
  94.      quiet = FALSE;
  95.  
  96. #ifndef _OSK
  97.      pflinit();                                      /* longs will be print */
  98. #endif
  99.      intercept (interrupt);                          /* signal handler */
  100.  
  101.      if (getparam() == FALSE)
  102.           exit (0);
  103.  
  104.      userparam();
  105.  
  106.      /* Look for the environment MAIL.  If that doesn't exist, look for the
  107.         parameter 'maildir' in the Parameters file. */
  108.  
  109.      if ((maildir = getenv ("MAIL")) != NULL)
  110.           maildir = strdup (maildir);
  111.      else
  112.           if ((maildir = getdirs ("maildir")) == NULL)
  113.                fatal ("MAIL undefined");
  114.  
  115.      if ((logdir = getenv ("LOGDIR")) != NULL)
  116.           logdir = strdup (logdir);
  117.      else
  118.           logdir = LOGDIR;
  119.  
  120.      if (parse_addr (--argc, ++argv) == ABORT)
  121.           exit (0);
  122.  
  123. #ifndef TERMCAP
  124.      t2flag = t2test();
  125. #else
  126.      init_term_cap();
  127. #endif
  128.  
  129.      if (readmail == SEND)
  130.        {
  131.           /* Is stdin redirected from a file?  Try to position to
  132.              beginning of file.  If it works, must be file. */
  133.  
  134.           redirect = (_gs_pos (0) == -1) ? FALSE : TRUE;
  135.           asetuid (0);
  136.  
  137. #ifndef _OSK
  138.           /* Load dotilde and rmail.  This should speed things up a bit */
  139.           if (nmlink (dotilde, 0, 0) == -1)
  140.                if (nmload (dotilde, 0, 0) == -1)
  141.                     fatal ("can't load dotilde");
  142.  
  143.           if (nmlink (rmail, 0, 0) == -1)
  144.                if (nmload (rmail, 0, 0) == -1)
  145.                  {
  146.                     munload (dotilde, 0);
  147.                     fatal ("can't load rmail");
  148.                  }
  149.           usedotilde = TRUE;
  150. #else
  151.           /* for OSK just load rmail */
  152.           if (modlink (rmail, 0) == -1)
  153.             {
  154.                char tmp[64];
  155.  
  156.                if (modloadp (rmail, 0, tmp) == -1)
  157.                     fatal ("can't load rmail");
  158.             }
  159. #endif
  160.           rmailin = TRUE;
  161.           asetuid (myuid);
  162.           sendmail();
  163.           munload (rmail, 0);
  164.           rmailin = FALSE;
  165.        }
  166.      else
  167.        {
  168.           /* read our mail */
  169. #ifndef _OSK
  170.           if (usepager  &&  *pager != '\0')
  171.                loadpager (TRUE);
  172. #endif
  173.           recvmail (readmail == FORWARD ? TRUE : FALSE);
  174.        }
  175.  
  176. #ifndef _OSK
  177.      if (usedotilde)
  178.           munload (dotilde, 0);
  179. #endif
  180.      putchar ('\n');
  181.      exit (0);
  182. }
  183.  
  184.  
  185.  
  186.  
  187. /* Parse the command line.  Returns TRUE if sending mail.  Returns FALSE
  188.    otherwise. */
  189.  
  190. int parse_addr (count, names)
  191. int count;
  192. register char **names;
  193. {
  194.      FILE *file;
  195.  
  196.      for (; count; count--, names++)
  197.        {
  198.           if (**names == '-')
  199.             {
  200.                while (*++(*names))
  201.                  {
  202.                     switch (**names)
  203.                       {
  204.                          /* Subject */
  205.                          case 's':
  206.                               if (!ARGVAL() )
  207.                                    return (argerr ("s"));
  208.  
  209.                               strcpy (subject, *names);
  210.                               readmail = SEND;
  211.                               goto nextarg;
  212.  
  213.                          /* debug */
  214.                          case 'x':
  215.                               if (!ARGVAL() || !isdigit (**names))
  216.                                    return (argerr ("x"));
  217.  
  218.                               debug = atoi (*names);
  219.  
  220.                               if (debug > 9)
  221.                                    debug = 9;
  222.  
  223.                               goto nextarg;
  224.  
  225.                          /* File replying to */
  226.                          case 'a':
  227.                               if ( !ARGVAL() )
  228.                                    return (argerr ("a"));
  229.  
  230.                               strcpy (message, *names);
  231.                               readmail = SEND;
  232.                               goto nextarg;
  233.  
  234.                          /* Check for waiting mail for ourself and possibly
  235.                             another user.  Only superuser can check mail of
  236.                             other users. */
  237.  
  238.                          case 'c':
  239.                               /* check for our own mail... */
  240.                               checkmail (TRUE, user);
  241.  
  242.                               /* ...and that of other users */
  243.                               if (myuid == 0)
  244.                                    if ( ARGVAL() )
  245.                                      {
  246.                                         printf ("\n%s: ", *names);
  247.                                         checkmail (TRUE, *names);
  248.  
  249.                                         while (--count && *++names)
  250.                                           {
  251.                                              printf ("%s: ", *names);
  252.                                              checkmail (TRUE, *names);
  253.                                           }
  254.                                      }
  255.                               exit (0);
  256.  
  257.                          /* don't use signature */
  258.                          case 'd':
  259.                               usesig = NOSIG;
  260.                               readmail = SEND;
  261.                               break;
  262.  
  263.                          /* use alt_signature */
  264.                          case 'n':
  265.                               usesig = ALTSIG;
  266.                               readmail = SEND;
  267.                               break;
  268.  
  269.                          /* don't prompt for Cc:, overrides mailrc
  270.                             parameter */
  271.                          case 'p':
  272.                               cc_prompt = FALSE;
  273.                               readmail = SEND;
  274.                               break;
  275.  
  276.                          /* read last in, first out order */
  277.                          case 'r':
  278.                               readmail = REVERSE;
  279.                               break;
  280.  
  281.                          /* just want help */
  282.                          case '?':
  283.                               usage();
  284.                               return (ABORT);
  285.                               break;
  286.  
  287.                          default:
  288.                               fprintf (stderr, "%s: bad option: %c ...for help use: %s -?\n", 
  289.                                                pname, **names, pname);
  290.                               return (ABORT);
  291.                               break;
  292.  
  293.                     } /* end switch */
  294.                  } /* end while processing this argument */
  295.             } /* end if option parameter */
  296.  
  297.           /* must be mailing list or address */
  298.           else
  299.             {
  300.                readmail = SEND;
  301.  
  302.                if (**names == '@'  ||  **names == '*')
  303.                  {
  304.                     char list[128];
  305.  
  306.                     /* read names from mailing list */
  307.                     ++(*names);
  308. #ifdef _OSK
  309.                     sprintf (fname, "%s/%s", homedir, *names);
  310. #else
  311.                     sprintf (fname, "%s/%s/%s", homedir, uudir, *names);
  312. #endif
  313.                     if ((file = fopen (fname, "r")) == NULL)
  314.                       {
  315.                          char tmp[80];
  316.  
  317.                          sprintf (tmp, "can't open mailing list: %s", *names);
  318.                          fatal (tmp);
  319.                       }
  320.  
  321.                     while (mfgets (list, sizeof (list), file) != NULL)
  322.                       {
  323.                          doalias (list);
  324.                          strcat (strcat (address, " "), list);
  325.                       }
  326.                     fclose (file);
  327.                  }
  328.  
  329.                /* address or alias */
  330.                else
  331.                  {
  332.                     strcpy (temp, *names);
  333. #ifndef _OSK
  334.                     fixstar (temp);
  335. #endif
  336.                     doalias (temp);
  337.                     strcat (strcat (address, " "), temp);
  338.                  }
  339.             }
  340. nextarg:  continue;                              /* process next argument */
  341.        }
  342.      return (OK);
  343. }
  344.  
  345.  
  346.  
  347. #ifndef _OSK
  348. /* Shell+ strips out command line '@' when used by anyone but the superuser
  349.    This fixes it so non-superuser can use the form:  user*node or '*list'
  350.    instead of 'user@node' or '@list'.  I know it is a kludge... :-) --REB */
  351.  
  352. int fixstar (adrs)
  353. char *adrs;
  354. {
  355.      register char *p;
  356.  
  357.      for (p = adrs; *p; ++p)
  358.           if (*p == '*')
  359.                *p = '@';
  360. }
  361. #endif
  362.  
  363.  
  364.  
  365. int argerr (arg)
  366. char *arg;
  367. {
  368.      _errmsg (0, "option requires an argument -- %s\n", arg);
  369.      return (ABORT);
  370. }
  371.  
  372.  
  373.  
  374.  
  375. /* Open user's mailbox to check for waiting mail.  If mail is waiting, the
  376.    number of messages is returned.  If no mail is waiting, a message to this
  377.    effect is displayed.  If 'checkflag' is TRUE, the -c option was on the
  378.    command line.  Just count the messages waiting and report it.  If
  379.    'checkflag' is FALSE, count the message in the mailbox.  Compare it with
  380.    the count given in the mail..list file.  If the two counts disagree
  381.    reconstruct mail..list first.  Then return the number of messages waiting
  382.    to the caller.
  383. */
  384.  
  385. int checkmail (checkflag, whosemail)
  386. flag checkflag;
  387. char *whosemail;
  388. {
  389.      DIR *dirptr;
  390.      struct direct *list;                            /* defined in dir.h */
  391.      register int count_1;
  392.      int count_2;
  393.      FILE *fp;
  394.  
  395.      /* become super user and change current data directory to user's mailbox
  396.         directory */
  397.  
  398.      sprintf (fname, "%s/%s", maildir, whosemail);
  399.      asetuid (0);
  400.  
  401.      if (chdir (fname) == ERROR)
  402.        {
  403.           char tmp[75];
  404.  
  405.           sprintf (tmp, "can't change to your mailbox directory: '%s'",
  406.                         whosemail);
  407.           fatal (tmp);
  408.        }
  409.      asetuid (myuid);
  410.  
  411.      if ((dirptr = opendir (".")) == NULL)   
  412.           fatal ("checkmail: can't open your mailbox");
  413.  
  414.      /* now count our letters */
  415.      count_1 = 0;
  416.      while ((list = readdir (dirptr)) != NULL) 
  417.           if ((list->d_name[0] != '.') 
  418.                &&  (strncmp (list->d_name, mail_list, 6) != 0))
  419.             {
  420.                ++count_1;
  421.             }
  422.      closedir (dirptr);
  423.  
  424.      /* report our findings... */
  425.      if (count_1 == 0)
  426.        {
  427.           Bell();
  428.           puts ("no mail waiting");
  429.           return (count_1);
  430.        }
  431.  
  432.      if (checkflag) 
  433.        {
  434.           if (count_1 > 0)
  435.                printf ("You have mail (%d message%s)\n",
  436.                         count_1, count_1 > 1 ? "s" : "");
  437.        }
  438.      else
  439.        {
  440.           /* Compare count_1 with mail..list file.  If the two disagree or
  441.              mail..list file does not exist, it probably got munged.  We need
  442.              to rebuild mail..list before returning. */
  443.  
  444.           if ((fp = fopen (mail_list, "r")) != NULL)
  445.             {
  446.                char buff[MLINE];
  447.  
  448.                count_2 = 0;
  449.  
  450.                while (mfgets (buff, MLINE, fp) != NULL)
  451.                     ++count_2;
  452.  
  453.                fclose (fp);
  454.             }
  455.  
  456.           if (fp == NULL  ||  count_1 != count_2)
  457.             {
  458.                fputs ("\nERROR--rebuilding 'mail..list' file...", stderr);
  459.                count_1 = rebuildmail (count_1);
  460.             }
  461.        }
  462.      return (count_1);
  463. }
  464.  
  465.  
  466.  
  467. /* mail..list file got munged somehow.  Reconstruct it. */
  468.  
  469. int rebuildmail (mailcount)
  470. int mailcount;
  471. {
  472.      FILE *mptr, *lptr, *omptr;
  473.      DIR *dirptr;
  474.      struct direct *mbox;                           /* defined in dir.h */
  475.      register int i;
  476.      int newmailcount = 0;
  477.      static struct mbag  {
  478.                 char letter[32];
  479.               } *ltrs, *ltrsp, *eltrs;
  480.  
  481.      omptr = NULL;
  482.      ltrs = (struct mbag *) malloc (mailcount * sizeof (struct mbag));
  483.  
  484.      if (ltrs == NULL)
  485.           fatal ("rebuildmail: can't malloc() ltrs array");
  486.  
  487.      dirptr = opendir (".");
  488.  
  489.      if (dirptr == NULL)
  490.           fatal ("rebuildmail: not enough memory...too much mail in mailbox directory");
  491.  
  492.      /* read in the letter filenames */
  493.      i = 0;
  494.      while ((mbox = readdir (dirptr)) != NULL)
  495.           if ((mbox->d_name[0] != '.')
  496.                && (strncmp (mbox->d_name, mail_list, 6) != 0))
  497.             {
  498.                strcpy ((ltrs + i)->letter, mbox->d_name);
  499.                ++i;
  500.             }
  501.      closedir (dirptr);
  502.      qsort (ltrs, mailcount, sizeof (struct mbag), strucmp);
  503.      sprintf (fname, "%s.tmp", mail_list);
  504.  
  505.      if ((mptr = fopen (fname, "w")) == NULL)
  506.        {
  507.           fputs ("rebuildmail: can't create 'mail..list.tmp'", stderr);
  508.  
  509.           if (errno == 253)
  510.                fputs ("...same user updating file", stderr);
  511.  
  512.           putc ('\n', stderr);
  513.           exit (0);
  514.        }
  515.  
  516.      /* make sure nobody else can mess with us for now */
  517.      _ss_attr (fileno (mptr), S_ISHARE|S_IREAD|S_IWRITE);
  518.      asetuid (myuid);
  519.  
  520.      /* extract header info */
  521.      ltrsp = ltrs;
  522.      eltrs = ltrs + mailcount;
  523.  
  524.      /* open original mail..list for comparison */
  525.      omptr = fopen (mail_list, "r");
  526.  
  527.      do
  528.        {
  529.           if ((lptr = fopen (ltrsp->letter, "r")) == NULL)
  530.             {
  531.                fprintf (stderr, "rebuildmail: can't open '%s'\n",
  532.                                 ltrsp->letter);
  533.                continue;
  534.             }
  535.  
  536.           /* If the letter file is 0 bytes, something got trashed.  Delete
  537.              the file and continue on. */
  538.  
  539.           if (_gs_size (fileno (lptr)) <= 0)
  540.             {
  541.                fclose (lptr);
  542.                unlink (ltrsp->letter);
  543.             }
  544.           else
  545.             {
  546.                getheader (lptr, mptr, ltrsp->letter, omptr);
  547.                fclose (lptr);
  548.                ++newmailcount;
  549.             }
  550.        }
  551.      while (++ltrsp < eltrs);
  552.  
  553.      if (omptr != NULL)
  554.           fclose (omptr);
  555.  
  556.      free (ltrs);
  557.      fixupdate ("rebuildmail", mptr);
  558.      return (newmailcount);
  559. }
  560.  
  561.  
  562.  
  563. /* Extract header information for the mail..list entry. */
  564.  
  565.  
  566. int getheader (fp, mptr, filename, omptr)
  567. FILE *fp, *mptr, *omptr;
  568. char *filename;
  569. {
  570.      char mline[256], subj[SUBJSIZE], from[FRMSIZE], resentfrm[128];
  571.      char resentrply[128], *grabfrom();
  572.      register char *p;
  573.      int linecount;
  574.  
  575.      *subj = *from = *resentfrm = *resentrply = '\0';
  576.      p = mline;
  577.  
  578.      while (mfgets (p, sizeof (mline), fp) != NULL  &&  *p)
  579.           if (*p == 'F'  &&   strnucmp ("From: ", p, 6) == 0)
  580.             {
  581.                strncpy (from, grabfrom (p), FRMSIZE);
  582.                from[FRMSIZE-1] = '\0';
  583.             }
  584.           else if (*p == 'R')
  585.             {
  586.                if (strnucmp (p, "Resent-From: ", 13) == 0)
  587.                  {
  588.                     strncpy (resentfrm, grabfrom (p), sizeof (resentfrm));
  589.                     resentfrm[sizeof (resentfrm) - 1] = '\0';
  590.                  }
  591.                else
  592.                     if (strnucmp (p, "Resent-Reply-To: ", 17) == 0)
  593.                       {
  594.                          strncpy (resentrply, grabfrom (p), sizeof (resentrply));
  595.                          resentrply[sizeof (resentrply) - 1] = '\0';
  596.                       }
  597.             }
  598.           else if (*p == 'S'  && (strncmp ("Subject: ", p, 9) == 0)
  599.                               || (strncmp ("Subj: ", p, 6) == 0))
  600.             {
  601.                strncpy (subj, getstring (p), SUBJSIZE);
  602.                subj[SUBJSIZE - 1] = '\0';
  603.             }
  604.  
  605.      if (*resentrply != '\0')
  606.           strncpy (from, resentrply, sizeof (from));
  607.      else
  608.           if (*resentfrm != '\0')
  609.                strncpy (from, resentfrm, sizeof (from));
  610.  
  611.      /* be sure from is properly terminated */
  612.      from[sizeof (from) - 1] = '\0';
  613.  
  614.      /* count the lines */
  615.      linecount = 0;
  616.      p = mline;
  617.      while (mfgets (p, sizeof (mline), fp) != NULL)
  618.           ++linecount;
  619.  
  620.      sprintf (temp, "N%s|%s|%s|%d|%ld",
  621.                     filename, *from != '\0' ? from : " ",
  622.                     *subj != '\0' ? subj : " ",
  623.                     linecount, _gs_size (fileno (fp)));
  624.  
  625.      /* see if this line matches the original mail..list line */
  626.      if (omptr != NULL)
  627.        {
  628.           /* if the lines match use the old status */
  629.           while (mfgets (p, sizeof (mline), omptr) != NULL)
  630.                if (strcmp ((temp + 1), (p + 1)) == 0)
  631.                  {
  632.                     *temp = *p;
  633.                     break;
  634.                  }
  635.           rewind (omptr);
  636.        }
  637.      fprintf (mptr, "%s\n", temp);
  638. }
  639.  
  640.  
  641.  
  642. /* Extract the user name from the From: line.  Returns a pointer to the char
  643.    string containing the name. */
  644.  
  645. char *grabfrom (fromline)
  646. char *fromline;
  647. {
  648.      char *realname;
  649.  
  650.      realname = getrealname (fromline);
  651.  
  652.      if (*realname == '\0')
  653.           realname = getval (fromline);
  654.  
  655.      return (realname);
  656. }
  657.  
  658.  
  659.  
  660. /* Update the user's mail..list file.  Kill deleted mail as we go. */
  661.  
  662. void updatemail_list (envelop, numltrs)
  663. MAILPTR envelop;
  664. int numltrs;
  665. {
  666.      char buff[MLINE];
  667.      FILE *mptr, *mtptr;
  668.      register char *p;
  669.  
  670.      p = buff;
  671.  
  672.      /* original mail..list */
  673.      if ((mptr = fopen (mail_list, "r")) == NULL)
  674.           fatal ("updatemail: can't read your 'mail..list'");
  675.  
  676.      sprintf (fname, "%s.tmp", mail_list);
  677.  
  678.      if ((mtptr = fopen (fname, "w")) == NULL)
  679.        {
  680.           fputs ("updatemail_list: can't create 'mail..list.tmp'", stderr);
  681.  
  682.           if (errno == 253)
  683.                fputs ("...same user updating file", stderr);
  684.  
  685.           putc ('\n', stderr);
  686.  
  687.           /* quit */
  688.           interrupt (0);
  689.        }
  690.  
  691.      /* make sure nobody else can mess with us for now */
  692.      _ss_attr (fileno (mtptr), S_ISHARE|S_IREAD|S_IWRITE);
  693.  
  694.      /* write out new mail..list, skip deleted mail */
  695.      while (mfgets (p, MLINE, mptr) != NULL)
  696.        {
  697.           /* just in case new mail arrived */
  698.           if (envelop != ENDMAIL)
  699.             {
  700.                switch (envelop->status)
  701.                  {
  702.                     case 'D':
  703.                     case 'B':
  704.                          unlink (envelop->letter);
  705.                          free (envelop->mline);
  706.                          envelop = envelop->next;
  707.                          continue;
  708.  
  709.                     case 'N':
  710.                          *p = 'U';
  711.                          free (envelop->mline);
  712.                          break;
  713.  
  714.                     case 'P':
  715.                          *p = ' ';
  716.                          free (envelop->mline);
  717.                          break;
  718.  
  719.                     default:
  720.                          *p = envelop->status;
  721.                          free (envelop->mline);
  722.                          break;
  723.                  }
  724.                envelop = envelop->next;
  725.             }
  726.           fprintf (mtptr, "%s\n", p);
  727.        }
  728.      fclose (mptr);
  729.  
  730.      if (envelop != ENDMAIL  &&  numltrs)
  731.        {
  732.           fclose (mtptr);
  733.           rebuildmail (numltrs);
  734.           return;
  735.        }
  736.      fclose (mptr);
  737.      fixupdate ("updatemail_list", mtptr);
  738. }
  739.  
  740.  
  741.  
  742. int fixupdate (func, fp)
  743. char *func;
  744. FILE *fp;
  745. {
  746.      char buff[65];
  747.  
  748.      /* for our eyes only */
  749.      fixperms (fp);
  750.      fclose (fp);
  751.  
  752.      /* make sure the same owner owns new mail..list file */
  753.      sprintf (fname, "%s.tmp", mail_list);
  754.      chown (fname, myuid);
  755.  
  756.      /* remove the old mail..list file */
  757.      unlink (mail_list);
  758.      asetuid (0);
  759.  
  760.      if (docmd_na ("rename mail..list.tmp mail..list") != 0)
  761.        {
  762.           if (strcmp (func, "rebuildmail") == 0)
  763.                strcpy (buff, "rebuildmail");
  764.           else
  765.                strcpy (buff, "updatemail_list");
  766.  
  767.           strcat (buff, "fixupdate: can't rename 'mail..list.tmp' to 'mail..list'");
  768.           fatal (buff);
  769.        }
  770.  
  771.      asetuid (myuid);
  772. }
  773.  
  774.  
  775.  
  776. /* Get a string skipping over leading spaces.  Returns pointer to first
  777.    non-space character.  skipspace() is in parse.c. */
  778.  
  779. char *getinput (p, size)
  780. register char *p;
  781. int size;
  782. {
  783.      if (mfgets (p, size, stdin) != NULL)
  784.           return (skipspace (p));
  785.      else
  786.           return (NULL);
  787. }
  788.  
  789.  
  790.  
  791. /* Turn off or on echo on the standard input path */
  792.  
  793. int echo (onoroff)
  794. int onoroff;
  795. {
  796.      struct sgbuf stdinpath;
  797.  
  798.      _gs_opt (1, &stdinpath);
  799.      stdinpath.sg_echo = onoroff;             /* switch standard input echo */
  800.      _ss_opt (1, &stdinpath);                 /* update the path descriptor */
  801. }
  802.  
  803.  
  804.  
  805. #ifndef _OSK
  806. /* load or unload the file viewer */
  807.  
  808. int loadpager (loadit)
  809. int loadit;
  810. {
  811.      if (loadit)
  812.        {
  813.           if (nmlink (pager, 0, 0) == -1)
  814.                if (nmload (pager, 0, 0) == -1)
  815.                  {
  816.                     usepager = FALSE;
  817.                     return;
  818.                  }
  819.           usepager = TRUE;
  820.        }
  821.      else
  822.        {
  823.           munload (pager, 0);
  824.           usepager = FALSE;
  825.        }
  826. }
  827. #endif
  828.  
  829.  
  830.  
  831. /* print a message and exit */
  832.  
  833. int fatal (msg)
  834. char *msg;
  835. {
  836.      fprintf (stderr, "\n%s: %s", pname, msg);
  837.  
  838.      if (errno != 0)
  839.           fprintf (stderr, "...error %d", errno);
  840.  
  841.      putc ('\n', stderr);
  842.      interrupt (0);
  843. }
  844.  
  845.  
  846.  
  847. /* Cleanup if we get a keyboard interrupt and get out. */
  848.  
  849. int interrupt (sig)
  850. int sig;
  851. {
  852. #ifndef TERMCAP
  853.      if (winopen)
  854.        {
  855.           closedoublewindow();
  856.           return;
  857.        }
  858. #endif
  859.  
  860.      asetuid (0);
  861.  
  862.      /* kill off any children */
  863.      if (childid > -1)
  864.        {
  865.           kill (childid, SIGKILL);
  866.           childid = -1;
  867.        }
  868.  
  869.      /* unlink RMAIL if we loaded it */
  870.      if (rmailin)
  871.           munload (rmail, 0);
  872.  
  873. #ifndef _OSK
  874.      /* unlink pager and dotilde if we loaded them */
  875.      if (usepager)
  876.           loadpager (FALSE);
  877.  
  878.      if (usedotilde)
  879.           munload (dotilde);
  880. #endif
  881.      /* clean up --REB */
  882.      if (ltrfile != NULL)
  883.           fclose (ltrfile);
  884.  
  885.      if (*tempfile != '\0')
  886.           unlink (tempfile);
  887.  
  888.      /* put things back the way we found them */
  889.      echo (ON);
  890.      CurOn();
  891.      putchar ('\n');
  892.      exit (sig);
  893. }
  894.  
  895.  
  896.  
  897. void usage()
  898. {
  899.      char *strdetab();
  900.      register char **ptr;
  901.      static char *usetxt[] = {
  902.          "mail [-r]\t\t\t\t\t...read mail",
  903.          "     opt:  r\t\t   -read mail in reverse order",
  904.          " ",
  905.          "mail [opts] [<address>...] [opts]\t\t...send mail",
  906.          "     opts: a <file>\t    -file replying to",
  907.          "\t   s \"subject\"\t -Subject: \"subject\"",
  908.          "\t   x N\t\t -N = debug level",
  909. #ifndef _OSK
  910.          "\t   d\t\t   -don't add signature",
  911.          "\t   n\t\t   -use alt_signature",
  912. #else
  913.          "\t   d\t\t   -don't add .signature",
  914.          "\t   n\t\t   -use .alt_signature",
  915. #endif
  916.          "\t   p\t\t   -don't prompt for carbon copy (Cc:)",
  917.          "\t   q\t\t   -work quietly when sending mail",
  918.          "\t   ?\t\t   -this message",
  919.          NULL
  920.        };
  921.      static char *usetxt1 = "\t    v\t\t   -toggle file viewer...";
  922.      static char *usetxt2 = "\t   c [<user>...]       -check for our waiting mail and that of user\n";
  923.      static char *usetxt3 = "\t   c\t\t   -check for waiting mail";
  924.  
  925.      fprintf (stdout, "mailx v%s (%s)  --send and receive e-mail\n\n",
  926.                       version, VERDATE);
  927.  
  928.      for (ptr = usetxt; *ptr != NULL; ++ptr)
  929.           fprintf (stderr, " %s\n", strdetab (strcpy (temp, *ptr), 8));
  930.  
  931.      fprintf (stderr, "%sdefault %s\n",
  932.                strdetab (strcpy (temp, usetxt1), 8), usepager ? "ON" : "OFF");
  933.  
  934.      strcpy (temp, (myuid == 0) ? usetxt2 : usetxt3);
  935.      fprintf (stderr, " %s\n", strdetab (temp, 8));
  936.  
  937. #ifndef _OSK
  938.      fputs ("  When used with Shell+, non-superusers need to use ", stderr);
  939.      fputs ("'*' instead of '@' in\n  command line addresses.\n\n", stderr);
  940. #endif
  941.      fputs ("This is free software released under the GNU General Public License.  Please",
  942.             stderr);
  943.      fputs ("Please send suggestions/bug reports to:  bob@kc2wz.bubble.org\n",
  944.             stderr);
  945. }
  946.