home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume4 / msg / part4 < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  63.5 KB

  1. From: decvax!hplabs!hpcnou!dat (Dave Taylor)
  2. Subject: Msg Shar.part.4
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 4, Issue 8
  7. Submitted by: decvax!hplabs!hpcnou!dat (Dave Taylor)
  8.  
  9. # Msg Shar part 4 of 7
  10.  
  11. # Shell Archive created by hpcnou!dat at Wed Feb 26 15:56:20 1986
  12.  
  13. # To unpack the enclosed files, please use this file as input to the
  14. # Bourne (sh) shell.  This can be most easily done by the command;
  15. #     sh < thisfilename
  16.  
  17. # This archive contains;
  18. #  src/file_utils.c src/fileio.c        src/hdrconfg.c      src/help.c
  19. #  src/initialize.c src/input_utils.c   src/leavembox.c     src/mailout.c
  20. #  src/mailtime.c   src/mkhdrs.c        src/msg.c
  21.  
  22.  
  23. if [ ! -d src ]
  24. then
  25.   echo creating directory src
  26.   mkdir src
  27. fi
  28.  
  29. # ---------- file src/file_utils.c ----------
  30.  
  31.  
  32. if [ -f src/file_utils.c ]
  33. then
  34.   echo File 'src/file_utils.c' already exists\!
  35.   exit 1
  36. fi
  37.  
  38. echo extracting file src/file_utils.c...
  39. cat << 'END-OF-FILE' > src/file_utils.c
  40. /**            file_utils.c            **/
  41.  
  42. /** File oriented utility routines for MSG 
  43.  
  44.     (C) Copyright 1986 Dave Taylor
  45. **/
  46.  
  47. #include "headers.h"
  48. #include <sys/types.h>
  49. #include <sys/stat.h>
  50. #include <ctype.h>
  51.  
  52. #ifdef BSD
  53. #undef tolower
  54. #endif
  55. #include <signal.h>
  56. #include <errno.h>
  57.  
  58. long
  59. bytes(name)
  60. char *name;
  61. {
  62.     /** return the number of bytes in the specified file.  This
  63.         is to check to see if new mail has arrived....  **/
  64.  
  65.     int ok = 1;
  66.     extern int errno;    /* system error number! */
  67.     struct stat buffer;
  68.  
  69.     if (stat(name, &buffer) != 0)
  70.       if (errno != 2) {
  71.         dprint2("\n\n*** bytes() Error %d on fstat(%s)\n\n", errno, name);
  72.         leave(error2("Error %d attempting fstat on %s", errno, name));
  73.       }
  74.       else
  75.         ok = 0;
  76.     
  77.     return(ok ? (long) buffer.st_size : 0L);
  78. }
  79.  
  80. int
  81. can_access(file, mode)
  82. char *file, *mode;
  83. {
  84.     /** returns TRUE iff user can access file **/
  85.  
  86.     int status, pid, w;
  87.     register int (*istat)(), (*qstat)();
  88.     
  89.     if ((pid = fork()) == 0) {
  90.       setuid(userid);        /** back to normal userid **/
  91.       exit(fopen(file, mode) != NULL);
  92.       _exit(127);
  93.     }
  94.  
  95.     istat = signal(SIGINT, SIG_IGN);
  96.     qstat = signal(SIGQUIT, SIG_IGN);
  97.  
  98.     while ((w = wait(&status)) != pid && w != -1)
  99.         ;
  100.  
  101.     if (w == -1) status = FALSE;
  102.     
  103.     signal(SIGINT, istat);
  104.     signal(SIGQUIT, qstat);
  105.  
  106.     return(status);
  107. }
  108.  
  109.  
  110. int
  111. copy(from, to)
  112. char *from, *to;
  113. {
  114.     /** this routine copies a specified file to the destination
  115.         specified.  Non-zero return code indicates that something
  116.         dreadful happened! **/
  117.  
  118.     FILE *from_file, *to_file;
  119.     char buffer[VERY_LONG_STRING];
  120.     
  121.     dprint2("copy(from='%s', to='%s')\n", from, to);
  122.  
  123.     if ((from_file = fopen(from, "r")) == NULL)
  124.       return(error1("could not open file %s", from));
  125.  
  126.     if ((to_file = fopen(to, "w")) == NULL)
  127.       return(error1("could not open file %s", to));
  128.  
  129.     while (fgets(buffer, VERY_LONG_STRING, from_file) != NULL)
  130.       fputs(buffer, to_file);
  131.  
  132.     fclose(from_file);
  133.     fclose(to_file);
  134.  
  135.     return(0);
  136. }
  137.  
  138. check_mailfile_size()
  139. {
  140.     /** Check to ensure we have mail.  Only used with the '-z'
  141.         starting option. **/
  142.  
  143.     char filename[SLEN], username[NLEN];
  144.     struct stat buffer;
  145.  
  146.     strcpy(username,getlogin());
  147.     if (strlen(username) == 0)
  148.       cuserid(username);
  149.  
  150.     sprintf(filename,"%s/%s", mailhome, username);
  151.  
  152.     if (stat(filename, &buffer) == -1) {
  153.       printf(" You have no mail.\n");
  154.       exit(0);
  155.     }
  156.     else if (buffer.st_size < 2) {         /* maybe one byte??? */
  157.       printf("You have no mail to read.\n");
  158.       exit(0);
  159.     }
  160. }
  161. END-OF-FILE
  162.  
  163. size=`wc -c < src/file_utils.c`
  164.  
  165. if [ $size != 2421 ]
  166. then
  167.   echo Warning: src/file_utils.c changed - should be 2421 bytes, not $size bytes
  168. fi
  169.  
  170. chmod 644 src/file_utils.c
  171.  
  172. # ---------- file src/fileio.c ----------
  173.  
  174.  
  175. if [ -f src/fileio.c ]
  176. then
  177.   echo File 'src/fileio.c' already exists\!
  178.   exit 1
  179. fi
  180.  
  181. echo extracting file src/fileio.c...
  182. cat << 'END-OF-FILE' > src/fileio.c
  183. /**            fileio.c            **/
  184.  
  185. /** File I/O routines, including deletion from the mailbox! 
  186.  
  187.     (C) Copyright 1986 Dave Taylor
  188. **/
  189.  
  190. #include "headers.h"
  191. #include <ctype.h>
  192.  
  193. #ifdef BSD
  194. #undef tolower
  195. #endif
  196.  
  197. copy_message(prefix, dest_file, remove_header)
  198. char *prefix;
  199. FILE *dest_file;
  200. int  remove_header;
  201. {
  202.     /** Copy current message to destination file, with optional 'prefix' 
  203.         as the prefix for each line.  If remove_header is true, it will 
  204.         skip lines in the message until it finds the end of header line...
  205.             then it will start copying into the file... **/
  206.  
  207.     char buffer[LONG_SLEN];
  208.     int ok = 1, lines, in_header = 1;
  209.  
  210.     dprint2("copy_message(prefix='%s', <file>, remove-header=%s)\n", prefix,
  211.         remove_header? "ON" : "OFF");
  212.  
  213.     /** get to the first line of the message desired **/
  214.  
  215.     if (fseek(mailfile, header_table[current-1].offset, 0) == -1) {
  216.        error1("msg [seek] failed trying to read %d bytes into file",
  217.          header_table[current-1].offset);
  218.        return;
  219.     }
  220.  
  221.     /* how many lines in message? */
  222.  
  223.     lines = header_table[current-1].lines;
  224.  
  225.     dprint2("\tAbout to read %d lines from msg #%d\n",
  226.         lines, current);
  227.  
  228.     /* now while not EOF & still in message... copy it! */
  229.  
  230.     while (ok && lines--) {
  231.       ok = (int) (fgets(buffer, LONG_SLEN, mailfile) != NULL);
  232.       if (strlen(buffer) < 2) in_header = 0;
  233.       if (ok) 
  234.     if (! (remove_header && in_header))
  235.       fprintf(dest_file, "%s%s", prefix, buffer);
  236.     }
  237. }
  238. END-OF-FILE
  239.  
  240. size=`wc -c < src/fileio.c`
  241.  
  242. if [ $size != 1472 ]
  243. then
  244.   echo Warning: src/fileio.c changed - should be 1472 bytes, not $size bytes
  245. fi
  246.  
  247. chmod 644 src/fileio.c
  248.  
  249. # ---------- file src/hdrconfg.c ----------
  250.  
  251.  
  252. if [ -f src/hdrconfg.c ]
  253. then
  254.   echo File 'src/hdrconfg.c' already exists\!
  255.   exit 1
  256. fi
  257.  
  258. echo extracting file src/hdrconfg.c...
  259. cat << 'END-OF-FILE' > src/hdrconfg.c
  260.  
  261. /**            hdrconfg.c            **/
  262.  
  263. /**   This file contains the routines necessary to be able to modify
  264.       the mail headers of messages on the way off the machine.  The
  265.       headers currently supported for modification are:
  266.  
  267.     Subject:
  268.     To:
  269.     Cc:
  270.  
  271.     Expiration-Date:
  272.     Priority:
  273.         In-Reply-To:
  274.     Action:
  275.     Security:
  276.     
  277.       (C) Copyright 1985, Dave Taylor
  278. **/
  279.  
  280. #include <stdio.h>
  281. #include "headers.h"
  282.  
  283. #include <ctype.h>
  284.  
  285. #ifdef BSD
  286. #undef toupper
  287. #endif
  288.  
  289. /* these are all defined in the mailout file! */
  290.  
  291. extern char subject[SLEN], action[SLEN], reply_to[SLEN], expires[SLEN], 
  292.         priority[SLEN];
  293. extern char to[VERY_LONG_STRING], cc[VERY_LONG_STRING];
  294.  
  295. edit_headers(original_msg_num)
  296. int   original_msg_num;
  297. {
  298.     /** edit headers, R)eturn to continue with mailing **/
  299.  
  300.     int unexpanded_to = TRUE, unexpanded_cc = TRUE;
  301.     char c, expanded_to[VERY_LONG_STRING], expanded_cc[VERY_LONG_STRING];
  302.     
  303.     dprint1("edit_headers(original-msg-number=%d)\n", original_msg_num);
  304.  
  305.  
  306.     if (! edit_outbound || mail_only) goto outta_here;
  307.  
  308.     display_headers();
  309.  
  310.     do {
  311.       PutLine(LINES-1,0,"Choice: ");
  312.       CleartoEOLN();
  313.       c = toupper(getchar());
  314.       clear_error();
  315.       switch (c) {
  316.         case ctrl('M'):
  317.         case 'R' :
  318.         case 'Q' : goto outta_here;
  319.         case ctrl('L') : display_headers();
  320.                break;
  321.         case 'T' : if (optionally_enter(to, 2, 9, TRUE) == -1)
  322.                      goto outta_here;
  323.                    build_address(strip_commas(to), expanded_to);
  324.                unexpanded_to = FALSE; 
  325.                break;
  326.         case 'S' : if (optionally_enter(subject, 3, 9, FALSE) == -1)
  327.              goto outta_here;
  328.                break;
  329.         case 'C' : if (optionally_enter(cc, 4, 9, TRUE) == -1)
  330.              goto outta_here;
  331.                  build_address(strip_commas(cc), expanded_cc);
  332.                unexpanded_cc = FALSE;
  333.                break;
  334.         case 'A' : if (optionally_enter(action, 6, 9, FALSE) == -1)
  335.              goto outta_here;
  336.                break;
  337.         case 'E' : enter_date(7, 17, expires);
  338.                break;
  339.         case 'P' : if (optionally_enter(priority, 9,10, FALSE) == -1)
  340.              goto outta_here;
  341.                break;
  342.         case 'I' : if (original_msg_num != -1) {
  343.                      if (optionally_enter(reply_to, 8,13, FALSE) == -1)
  344.                goto outta_here;
  345.              break;        
  346.                }
  347.                /** else fall through as an error **/
  348.         default  : error("Unknown header being specified!");
  349.       }
  350.     } while (TRUE);
  351.  
  352. outta_here:    /* this section re-expands aliases before we leave... */
  353.  
  354.     if (unexpanded_to)
  355.       build_address(strip_commas(to), expanded_to);
  356.     if (unexpanded_cc)
  357.       build_address(strip_commas(cc), expanded_cc);
  358.  
  359.     strcpy(to, expanded_to);
  360.     strcpy(cc, expanded_cc);
  361.  
  362.     return;
  363. }
  364.  
  365. display_headers()
  366. {
  367.     ClearScreen();
  368.  
  369.     Centerline(0,"Message Header Edit Screen");
  370.  
  371.     PutLine(2,0,"To     : %s", to);
  372.     PutLine(3,0,"Subject: %s", subject);
  373.     PutLine(4,0,"Cc     : %s", cc);
  374.     PutLine(6,0,"Action :");
  375.     PutLine(7,0,"Expiration-Date:");
  376.     if (strlen(reply_to) > 0)
  377.       PutLine(8,0,"In-Reply-To: %s", reply_to);
  378.     PutLine(9,0,"Priority:");
  379.  
  380.     Centerline(LINES-5, 
  381.         "Pick the First Letter of the Header or R)eturn from Editing");
  382. }
  383.  
  384. enter_date(x, y, buffer)
  385. int x, y;
  386. char *buffer;
  387. {
  388.     /** Enter the number of days this message is valid for, then
  389.         display at (x,y) the actual date of expiration.  This 
  390.         routine relies heavily on the routine 'days_ahead()' in
  391.         the file date.c
  392.     **/
  393.  
  394.     int days;
  395.  
  396.     PutLine(LINES-1,0, "How many days in the future should it expire? ");
  397.     CleartoEOLN();
  398.     Raw(OFF);
  399.     gets(buffer, SLEN);
  400.     Raw(ON);
  401.     sscanf(buffer, "%d", &days);
  402.     if (days < 1)
  403.       error("That doesn't make sense!");
  404.     else if (days > 14)
  405.       error("Expiration date must be within two weeks of today");
  406.     else {
  407.       error1("days_ahead(%d)", days);
  408.       days_ahead(days, buffer);
  409.       PutLine(x, y, buffer);
  410.     }
  411. }
  412. END-OF-FILE
  413.  
  414. size=`wc -c < src/hdrconfg.c`
  415.  
  416. if [ $size != 3711 ]
  417. then
  418.   echo Warning: src/hdrconfg.c changed - should be 3711 bytes, not $size bytes
  419. fi
  420.  
  421. chmod 644 src/hdrconfg.c
  422.  
  423. # ---------- file src/help.c ----------
  424.  
  425.  
  426. if [ -f src/help.c ]
  427. then
  428.   echo File 'src/help.c' already exists\!
  429.   exit 1
  430. fi
  431.  
  432. echo extracting file src/help.c...
  433. cat << 'END-OF-FILE' > src/help.c
  434. /**            help.c            **/
  435.  
  436. /*** help routine for MSG program 
  437.  
  438.      (C) Copyright 1985, Dave Taylor
  439.  
  440. ***/
  441.  
  442. #include "headers.h"
  443.  
  444. help()
  445. {
  446.     /*** help me!  Read file 'helpfile' and echo to screen ***/
  447.  
  448.     FILE *hfile;
  449.     char buffer[SLEN];
  450.     int  lines=0;
  451.  
  452.     dprint0("help()\n");
  453.  
  454.     sprintf(buffer, "%s/%s", helphome, helpfile);
  455.     if ((hfile = fopen(buffer,"r")) == NULL) {
  456.       error1("couldn't open helpfile %s",buffer);
  457.       return(FALSE);
  458.     }
  459.     
  460.     ClearScreen();
  461.  
  462.     while (fgets(buffer, SLEN, hfile) != NULL) {
  463.       if (lines > LINES-3) {
  464.         PutLine(LINES,0,"Press any key to continue: ");
  465.         (void) ReadCh();
  466.         lines = 0;
  467.         ClearScreen();
  468.         printf("%s\r", buffer);
  469.       }
  470.       else 
  471.         printf("%s\r", buffer);
  472.       lines++;
  473.     }
  474.  
  475.     PutLine(LINES,0,"Please type <space> to return: ");
  476.  
  477.     (void) ReadCh();
  478.     clear_error();
  479.  
  480.     return(TRUE);
  481. }
  482. END-OF-FILE
  483.  
  484. size=`wc -c < src/help.c`
  485.  
  486. if [ $size != 821 ]
  487. then
  488.   echo Warning: src/help.c changed - should be 821 bytes, not $size bytes
  489. fi
  490.  
  491. chmod 644 src/help.c
  492.  
  493. # ---------- file src/initialize.c ----------
  494.  
  495.  
  496. if [ -f src/initialize.c ]
  497. then
  498.   echo File 'src/initialize.c' already exists\!
  499.   exit 1
  500. fi
  501.  
  502. echo extracting file src/initialize.c...
  503. cat << 'END-OF-FILE' > src/initialize.c
  504. /**        initialize.c        **/
  505.  
  506. /***** Initialize - read in all the defaults etc etc 
  507.        (C) Copyright 1985 Dave Taylor
  508. *****/
  509.  
  510. #include <stdio.h>
  511. #ifndef BSD
  512. #  include <termio.h>
  513. #endif
  514. #include <pwd.h>
  515. #ifdef BSD
  516. #  include <sys/time.h>
  517. #else
  518. #  include <time.h>
  519. #endif
  520. #include <signal.h>
  521. #include <errno.h>
  522. #include <ctype.h>
  523.  
  524. #ifdef BSD
  525. #undef tolower
  526. #endif
  527.  
  528. #include "headers.h"
  529.  
  530. extern int errno;        /* system error number on failure */
  531.  
  532. initialize()
  533. {
  534.     struct passwd *pass, *getpwnam();
  535.  
  536.     register int i;
  537.     int      leave();
  538.     char     buffer[SLEN];
  539.     
  540.     userid = getuid();
  541.     progid = geteuid();    
  542.  
  543.     strcpy(home,getenv("HOME"));
  544.     strcpy(shell,getenv("SHELL"));
  545.  
  546.     if (debug) {        /* setup for dprintf statements! */
  547.       char filename[SLEN];
  548.       sprintf(filename, "%s/%s", home, DEBUG);
  549.       if ((debugfile = fopen(filename, "w")) == NULL) {
  550.         debug = 0;    /* otherwise 'leave' will try to log! */
  551.         leave(fprintf(stderr,"Could not open file %s for debug output!\n",
  552.           filename));
  553.       }
  554.       chown(filename, userid, getgid()); /* file owned by user */
  555.  
  556.       fprintf(stderr,"\r\n** Debug output going to '%s' **\n\r", filename);
  557.       sleep(2);
  558.       fprintf(debugfile, "\nDebug output of MSG program, version %s\n\n",
  559.           VERSION);
  560.     }
  561.  
  562.     signal(SIGINT,  SIG_IGN);
  563.     signal(SIGQUIT, leave);
  564.     signal(SIGTERM, leave); 
  565.  
  566.     read_lsys();
  567.  
  568.     get_term_chars();
  569.     
  570.     gethostname(hostname, sizeof(hostname));
  571.     strcpy(username,getlogin());
  572.     if (strlen(username) == 0)
  573.       cuserid(username);
  574.  
  575.     /* now let's get the full username.. */
  576.  
  577.     if ((pass = getpwnam(username)) == NULL) {
  578.       error("Couldn't read password entry??");
  579.       strcpy(full_username, username);
  580.     }
  581.     else {
  582.       for (i=0; pass->pw_gecos[i] != '\0' && pass->pw_gecos[i] != ',';
  583.            i++)
  584.           full_username[i] = pass->pw_gecos[i];
  585.       full_username[i] = '\0'; 
  586.     }
  587.  
  588.     editor[0] = '\0';
  589.     strcpy(editor,getenv("EDITOR"));
  590.     if (editor[0] == '\0')
  591.       strcpy(editor,default_editor);
  592.  
  593.     if (! mail_only) {
  594.       mailbox[0] = '\0';
  595.       strcpy(prefixchars, "> ");     /* default message prefix */
  596.     }
  597.  
  598.     read_rc_file();        /* reading the .msgrc next... */
  599.  
  600.     /** check to see if the user has defined a LINES or COLUMNS
  601.         value different to that in the termcap entry (for
  602.         windowing systems, of course!) **/
  603.  
  604.     strcpy(buffer, getenv("LINES"));
  605.     if (isdigit(buffer[0]))
  606.       sscanf(buffer, "%d", &LINES);
  607.  
  608.     strcpy(buffer, getenv("COLUMNS"));
  609.     if (isdigit(buffer[0]))
  610.       sscanf(buffer, "%d", &COLUMNS);
  611.  
  612.     /** fix the shell if needed **/
  613.  
  614.     if (shell[0] != '/') {
  615.        sprintf(buffer, "/bin/%s", shell);
  616.        strcpy(shell, buffer);
  617.     }
  618.  
  619.     if (! mail_only) {
  620.       mailbox_defined = (mailbox[0] != '\0'); 
  621.  
  622.       /* now get the inverse video sequences from the termcap... */
  623.     
  624.       strcpy(start_highlight, return_value_of("so"));
  625.       strcpy(end_highlight, return_value_of("se"));
  626.   
  627.       /* get the cursor control keys... */
  628.  
  629.       strcpy(up, return_value_of("ku"));
  630.  
  631.       if (strlen(up) != 2)         /* don't want arbitrary length! */
  632.         cursor_control = FALSE;
  633.       else {
  634.         strcpy(down, return_value_of("kd"));
  635.         cursor_control = TRUE;
  636.         transmit_functions(ON);
  637.       }
  638.     }
  639.  
  640.     if (read_aliases)
  641.         read_alias_files();
  642.  
  643.     if (! mail_only) {
  644.       if (! mbox_specified)
  645.         newmbox(1,FALSE);    /* read the incoming mail mailbox! */
  646.       else
  647.         newmbox(0,FALSE);    /* read the specified mail file!   */
  648.  
  649.       if (mini_menu)
  650.         headers_per_page = LINES - 13;
  651.       else
  652.         headers_per_page = LINES -  8;    /* 5 more headers! */
  653.     }
  654.  
  655.     init_findnode();    /* set up the path alias stuff */
  656.  
  657.     dprint0("\n\n------ Past the Initialization stuff ------\n\n");
  658.  
  659.     dprint3("\nhostname = '%s'   username = '%s'   full_username = '%s'\n",
  660.              hostname, username, full_username);
  661.  
  662.     dprint3("home = '%s'   editor = '%s'   mailbox = '%s'\n",
  663.          home, editor, mailbox);
  664.     
  665.     dprint3("hp_terminal = %s, hp_softkeys = %s, and cursor_control=%s\n\n",
  666.         onoff(hp_terminal), onoff(hp_softkeys), onoff(cursor_control));
  667.  
  668. }
  669.  
  670. get_term_chars()
  671. {
  672.     /** This routine sucks out the special terminal characters
  673.         ERASE and KILL for use in the input routine.  The meaning 
  674.             of the characters are (dare I say it?) fairly obvious... **/
  675.  
  676. #ifndef BSD
  677.     struct termio term_buffer;
  678.  
  679.     if (ioctl(STANDARD_INPUT, TCGETA, &term_buffer) == -1) {
  680.       dprint1("** Error %d encountered on initial ioctl call **\n", errno);
  681.       /* set to defaults for terminal driver */
  682. #endif
  683.       backspace = BACKSPACE;
  684.       kill_line = ctrl('U');
  685. #ifndef BSD
  686.     }
  687.     else {
  688.       backspace = term_buffer.c_cc[VERASE];
  689.       kill_line = term_buffer.c_cc[VKILL];
  690.     }
  691. #endif
  692. }
  693.  
  694. read_lsys()
  695. {
  696.     /** Read the system L.sys file and put all the machine names in
  697.         the talk-to-sys linked list structure! **/
  698.  
  699.     FILE *lsysfile;
  700.     char  buffer[SLEN], sysname[NLEN];
  701.     struct lsys_rec *system_record, *previous_record;
  702.  
  703.     previous_record = NULL;
  704.  
  705.     if ((lsysfile = fopen(Lsys,"r")) == NULL) {
  706.       dprint1("\nCan't open L.sys file '%s' for reading!!\n\n",
  707.           Lsys);
  708.       error("Warning: couldn't read L.sys file...");
  709.       talk_to_sys = NULL;
  710.       return;
  711.     }
  712.  
  713.     while (fgets(buffer, SLEN, lsysfile) != NULL) {
  714.       sscanf(buffer,"%s", sysname);
  715.  
  716.       if (previous_record == NULL) {
  717.         dprint1("\tread '%s' out of L.sys file\n", sysname);
  718.         previous_record = (struct lsys_rec *) malloc(sizeof *talk_to_sys);
  719.  
  720.         strcpy(previous_record->name, sysname);
  721.         previous_record->next = NULL;
  722.         talk_to_sys = previous_record;
  723.       }
  724.       else if (! talk_to(sysname)) {
  725.         dprint1("\tread '%s' out of L.sys file\n", sysname);
  726.         system_record = (struct lsys_rec *) malloc(sizeof *talk_to_sys);
  727.       
  728.         strcpy(system_record->name, sysname);
  729.         system_record->next = NULL;
  730.         previous_record->next = system_record;
  731.         previous_record = system_record;
  732.       }
  733.     }
  734.  
  735.     fclose(lsysfile);
  736. }
  737. END-OF-FILE
  738.  
  739. size=`wc -c < src/initialize.c`
  740.  
  741. if [ $size != 5676 ]
  742. then
  743.   echo Warning: src/initialize.c changed - should be 5676 bytes, not $size bytes
  744. fi
  745.  
  746. chmod 644 src/initialize.c
  747.  
  748. # ---------- file src/input_utils.c ----------
  749.  
  750.  
  751. if [ -f src/input_utils.c ]
  752. then
  753.   echo File 'src/input_utils.c' already exists\!
  754.   exit 1
  755. fi
  756.  
  757. echo extracting file src/input_utils.c...
  758. cat << 'END-OF-FILE' > src/input_utils.c
  759. /**            input_utils.c            **/
  760.  
  761. /** Mindless I/O routines for MSG 
  762.     
  763.     (C) Copyright 1985 Dave Taylor
  764. **/
  765.  
  766. #include "headers.h"
  767.  
  768. int
  769. want_to(s, def, echo_answer)
  770. char *s, def;
  771. int  echo_answer;
  772. {
  773.     /** ask 's' at 20,40, return answer in lower case.
  774.         If 'echo_answer', then echo answer.  'def' is the
  775.           default answer if <return> is pressed.
  776.     **/
  777.     register char ch;
  778.  
  779.     if (strlen(s) < 30)
  780.       MoveCursor(LINES-3, COLUMNS-40);
  781.     else
  782.       MoveCursor(LINES-3, COLUMNS-50);
  783.     printf("%s%c%c", s, def, BACKSPACE);
  784.     fflush(stdout);
  785.     ch = tolower(ReadCh());
  786.  
  787.     if (echo_answer && ch > (char) ' ')
  788.       putchar(ch);
  789.  
  790.     return(ch);
  791. }
  792.  
  793. int
  794. read_number(ch, max)
  795. char ch;
  796. int max;
  797. {
  798.     /** read a number, where 'ch' is the leading digit! 
  799.         If max < 10 then just return 'ch' **/
  800.     
  801.     char buff[SHORT_SLEN];
  802.     int  num;
  803.  
  804.     if (max < 10)
  805.       return( (int) ch - '0' );
  806.     
  807.     buff[0] = ch;
  808.     buff[1] = '\0';
  809.  
  810.     PutLine(LINES-3, COLUMNS-40,"Set current message to :");
  811.     if (optionally_enter(buff, LINES-3, COLUMNS-15, TRUE) == -1)
  812.       return(current);
  813.  
  814.     sscanf(buff,"%d", &num);
  815.     return(num);
  816. }
  817.  
  818. int
  819. optionally_enter(string, x, y, append_current)
  820. char *string;
  821. int  x,y, append_current;
  822. {
  823.     /** Display the string on the screen and if RETURN is pressed, return 
  824.         it.  Otherwise, allow standard text input, including backspaces 
  825.         and such until RETURN is hit.  
  826.         If "append_current" is set, then leave the default string in 
  827.         place and edit AFTER it...assume 'x,y' is placing us at the
  828.         beginning of the string...
  829.         This routine returns zero unless INTERRUPT hit, then it returns
  830.         -1 and must be treated accordingly.
  831.     **/
  832.  
  833.     char ch;
  834.     register index = 0;
  835.  
  836.     MoveCursor(x,y);
  837.     printf("%s", string);    
  838.     CleartoEOLN();
  839.     if (! append_current)
  840.       MoveCursor(x,y);
  841.  
  842.     if (cursor_control)
  843.       transmit_functions(OFF);
  844.  
  845.     ch = getchar();
  846.  
  847.     if (ch == '\n' || ch == '\r') {
  848.       if (cursor_control)
  849.         transmit_functions(ON);
  850.       return(0);    /* we're done.  No change needed */
  851.     }
  852.     
  853.     CleartoEOLN();
  854.  
  855.     index = (append_current? strlen(string) : 0);
  856.  
  857.     if (ch == kill_line) {
  858.       if (! mail_only)
  859.         MoveCursor(x,y);
  860.           CleartoEOLN();
  861.       index = 0;
  862.     }
  863.     else if (ch != backspace) {
  864.       putchar(ch);
  865.       string[index++] = ch;
  866.     }
  867.     else if (index > 0) {
  868.       index--;
  869.       putchar(BACKSPACE);
  870.       putchar(' ');
  871.       putchar(BACKSPACE);
  872.       fflush(stdout);
  873.     }
  874.     else {
  875.       putchar(' ');
  876.       putchar(BACKSPACE);
  877.       fflush(stdout);
  878.     }
  879.  
  880.     do {
  881.       ch = getchar();
  882.  
  883.       /* the following is converted from a case statement to
  884.          allow the variable characters (backspace, kill_line
  885.          and break) to be processed.  Case statements in
  886.          C require constants as labels, so it failed ...
  887.       */
  888.  
  889.         if (ch == backspace) {
  890.               if (index > 0) {
  891.         index--;
  892.         putchar(BACKSPACE);
  893.         putchar(' ');
  894.         putchar(BACKSPACE);
  895.             fflush(stdout);
  896.           }
  897.           else {
  898.         putchar(' ');
  899.         putchar(BACKSPACE);
  900.             fflush(stdout);
  901.           }
  902.         }
  903.         else if (ch == '\n' || ch == '\r') {
  904.           string[index] = '\0';
  905.           if (cursor_control)
  906.             transmit_functions(ON);
  907.           return(0);
  908.         }
  909.         else if (ch == kill_line) {
  910.           if (mail_only)
  911.             back_up(index+1);
  912.           else
  913.             MoveCursor(x,y);
  914.               CleartoEOLN();
  915.           index = 0;
  916.         }
  917.         else if (ch == NULL) {
  918.           if (cursor_control)
  919.             transmit_functions(ON);
  920.           fflush(stdin);     /* remove extraneous chars, if any */
  921.           string[0] = '\0'; /* clean up string, and... */
  922.           return(-1);
  923.         }
  924.         else {  /* default case */
  925.                 
  926.           string[index++] = ch;
  927.           putchar(ch);
  928.        }
  929.     } while (index < SLEN);
  930.  
  931.     string[index] = '\0';
  932.  
  933.     if (cursor_control)
  934.       transmit_functions(ON);
  935.     return(0);
  936. }
  937.  
  938.  
  939. int
  940. pattern_enter(string, alt_string, x, y, alternate_prompt)
  941. char *string, *alt_string, *alternate_prompt;
  942. int  x,y;
  943. {
  944.     /** This function is functionally similar to the routine
  945.         optionally-enter, but if the first character pressed
  946.         is a '/' character, then the alternate prompt and string
  947.         are used rather than the normal one.  This routine 
  948.         returns 1 if alternate was used, 0 if not
  949.     **/
  950.  
  951.     char ch;
  952.     register index = 0;
  953.  
  954.     dprint4("pattern_enter(string='%s', alt_string='%s', x=%d, y=%d,\n", 
  955.         string, alt_string, x, y);
  956.     dprint1("              alt-prompt='%s')\n", alternate_prompt);
  957.  
  958.     MoveCursor(x,y);
  959.     printf("%s", string);    
  960.     CleartoEOLN();
  961.     MoveCursor(x,y);
  962.  
  963.     if (cursor_control)
  964.       transmit_functions(OFF);
  965.  
  966.     ch = getchar();
  967.  
  968.     if (ch == '\n' || ch == '\r') {
  969.       if (cursor_control)
  970.         transmit_functions(ON);
  971.       return(0);    /* we're done.  No change needed */
  972.     }
  973.     
  974.     if (ch == '/') {
  975.       MoveCursor(x, 0);
  976.       CleartoEOLN();
  977.       printf("%s", alternate_prompt);
  978.       (void) optionally_enter(alt_string, x, strlen(alternate_prompt)+1,
  979.          FALSE);
  980.       return(1);
  981.     }
  982.  
  983.     CleartoEOLN();
  984.  
  985.     index = 0;
  986.  
  987.     if (ch == kill_line) {
  988.       MoveCursor(x,y);
  989.           CleartoEOLN();
  990.       index = 0;
  991.     }
  992.     else if (ch != backspace) {
  993.       putchar(ch);
  994.       string[index++] = ch;
  995.     }
  996.     else if (index > 0) {
  997.       index--;
  998.       putchar(BACKSPACE);
  999.       putchar(' ');
  1000.       putchar(BACKSPACE);
  1001.     }
  1002.     else {
  1003.       putchar(' ');
  1004.       putchar(BACKSPACE);
  1005.     }
  1006.  
  1007.     do {
  1008.       fflush(stdout);
  1009.       ch = getchar();
  1010.  
  1011.       /* the following is converted from a case statement to
  1012.          allow the variable characters (backspace, kill_line
  1013.          and break) to be processed.  Case statements in
  1014.          C require constants as labels, so it failed ...
  1015.       */
  1016.  
  1017.         if (ch == backspace) {
  1018.               if (index > 0) {
  1019.         index--;
  1020.         putchar(BACKSPACE);
  1021.         putchar(' ');
  1022.         putchar(BACKSPACE);
  1023.           }
  1024.           else {
  1025.         putchar(' ');
  1026.         putchar(BACKSPACE);
  1027.           }
  1028.         }
  1029.         else if (ch == '\n' || ch == '\r') {
  1030.           string[index] = '\0';
  1031.           if (cursor_control)
  1032.             transmit_functions(ON);
  1033.           return(0);
  1034.         }
  1035.         else if (ch == kill_line) {
  1036.           MoveCursor(x,y);
  1037.               CleartoEOLN();
  1038.           index = 0;
  1039.         }
  1040.         else if (ch == NULL) {
  1041.           if (cursor_control)
  1042.             transmit_functions(ON);
  1043.           fflush(stdin);     /* remove extraneous chars, if any */
  1044.           string[0] = '\0'; /* clean up string, and... */
  1045.           return(-1);
  1046.         }
  1047.         else {  /* default case */
  1048.                 
  1049.           string[index++] = ch;
  1050.           putchar(ch);
  1051.        }
  1052.     } while (index < SLEN);
  1053.  
  1054.     string[index] = '\0';
  1055.  
  1056.     if (cursor_control)
  1057.       transmit_functions(ON);
  1058.     return(0);
  1059. }
  1060.  
  1061. back_up(spaces)
  1062. int spaces;
  1063. {
  1064.     /** this routine is to replace the goto x,y call for when sending
  1065.         mail without starting the entire "msg" system up... **/
  1066.     
  1067.     dprint1("back-up(spaces=%d)\n", spaces);
  1068.  
  1069.     while (spaces--) {
  1070.       putchar(BACKSPACE);
  1071.       putchar(' ');
  1072.       putchar(BACKSPACE);
  1073.     }
  1074.  
  1075.     fflush(stdout);
  1076. }
  1077. END-OF-FILE
  1078.  
  1079. size=`wc -c < src/input_utils.c`
  1080.  
  1081. if [ $size != 6604 ]
  1082. then
  1083.   echo Warning: src/input_utils.c changed - should be 6604 bytes, not $size bytes
  1084. fi
  1085.  
  1086. chmod 644 src/input_utils.c
  1087.  
  1088. # ---------- file src/leavembox.c ----------
  1089.  
  1090.  
  1091. if [ -f src/leavembox.c ]
  1092. then
  1093.   echo File 'src/leavembox.c' already exists\!
  1094.   exit 1
  1095. fi
  1096.  
  1097. echo extracting file src/leavembox.c...
  1098. cat << 'END-OF-FILE' > src/leavembox.c
  1099. /**            leavembox.c            **/
  1100.  
  1101. /** leave current mailbox, updating etc. as needed...
  1102.   
  1103.     (C) Copyright 1985, Dave Taylor
  1104. **/
  1105.  
  1106. #include "headers.h"
  1107. #include <sys/types.h>
  1108. #include <sys/stat.h>
  1109. #include <errno.h>
  1110.  
  1111. #define  ECHOIT     1    /* echo on for prompting! */
  1112.  
  1113. /** added due to a bug in the 2.1 OS **/
  1114.  
  1115. struct utimbuf {
  1116.     time_t    actime;        /** access time **/
  1117.     time_t  modtime;    /** modification */
  1118.        };
  1119.  
  1120. extern int errno;
  1121.  
  1122. int
  1123. leave_mbox(quitting)
  1124. int quitting;
  1125. {
  1126.     /** Exit, saving files into mbox and deleting specified, or simply 
  1127.         delete specified mail... If "quitting" is true, then output status 
  1128.             regardless of what happens.  Returns TRUE iff mailfile was
  1129.         changed (ie messages deleted from file)
  1130.     **/
  1131.  
  1132.     FILE *temp;
  1133.     char outfile[SLEN], buffer[SLEN];
  1134.     struct stat buf;        /* stat command  */
  1135.     struct utimbuf times;        /* utime command */
  1136.     register int to_delete = 0, to_save = 0, i, mode = 00644,
  1137.              pending = 0;
  1138.  
  1139.     dprint0("leave_mbox()\n");
  1140.  
  1141.     if (message_count == 0)
  1142.       return(FALSE);    /* nothing changed */
  1143.  
  1144.     for (i = 0; i < message_count; i++)
  1145.       if (header_table[i].delete) to_delete++;
  1146.       else                        to_save++;
  1147.  
  1148.     dprint2("\t%d messages to delete and %d to save\n", to_delete, to_save);
  1149.  
  1150.     if (mbox_specified == 0) 
  1151.       update_mailtime();
  1152.  
  1153.     if (to_delete)
  1154.       if (to_save) {
  1155.         sprintf(buffer, "Delete message%s? (y/n) ", to_save == 1? "" : "s");
  1156.         if (want_to(buffer, 'n', ECHOIT) != 'y') {
  1157.           if (mbox_specified == 0) unlock();    /* remove lock! */
  1158.           dprint0("\tNothing deleted ('n' to delete messages)\n");
  1159.           error("Nothing deleted");
  1160.           return(FALSE);    /* nothing was deleted! */
  1161.         }
  1162.       }
  1163.       else if (! to_save) 
  1164.         if (want_to("Delete all messages? (y/n) ", 'n', ECHOIT) != 'y') {
  1165.           if (mbox_specified == 0) unlock();    /* remove lock! */
  1166.           dprint0("\tNothing deleted (don't want to delete all msgs)\n");
  1167.           error("Nothing deleted");
  1168.           return(FALSE);   /* nothing was deleted */
  1169.         }
  1170.       
  1171.     if (to_save && mbox_specified == 0) 
  1172.       if (want_to("Keep mail in incoming mailbox? (y/n) ",'n',ECHOIT)=='y') 
  1173.         if (to_delete)    /* okay - keep undeleted as pending! */
  1174.           pending++;
  1175.         else {        /* gag! nothing to delete, don't save!  */    
  1176.           unlock();        /* remove mailfile lock!        */
  1177.           dprint0("\tIncoming mailbox unchanged (nothing to delete\n");
  1178.           error("Mailbox unchanged");
  1179.           return(FALSE);    /* nothing changed! */
  1180.         }
  1181.  
  1182.     /** okay...now lets do it! **/
  1183.  
  1184.     if (to_save > 0) {
  1185.       if (to_delete > 0)
  1186.         sprintf(buffer ,"[%s %d message%s, and deleting %d]", 
  1187.               pending? "keeping" : "storing", 
  1188.           to_save, plural(to_save), to_delete);
  1189.       else if (quitting)
  1190.         sprintf(buffer,"[%s %s]",
  1191.               pending? "keeping" : "storing",
  1192.           to_save > 1? "all messages" : "message");
  1193.       else
  1194.         buffer[0] = '\0';    /* no string! */
  1195.     }
  1196.     else {
  1197.       if (to_delete > 0)
  1198.         sprintf(buffer, "[deleting all messages]");
  1199.       else if (quitting)
  1200.         sprintf(buffer, "[no messages to %s, and none to delete]",
  1201.                 pending? "keep" : "save");
  1202.       else
  1203.         buffer[0] = '\0';
  1204.     }
  1205.  
  1206.     error(buffer);
  1207.  
  1208.     if (! mbox_specified) {
  1209.       if (pending) {                /* keep some messages pending! */
  1210.         sprintf(outfile,"%s%d", temp_mbox, getpid());
  1211.         unlink(outfile);
  1212.       }
  1213.       else if (mailbox_defined)    /* save to specified mailbox */
  1214.         strcpy(outfile, mailbox);
  1215.       else                /* save to $home/mbox */
  1216.         sprintf(outfile,"%s/mbox", home);
  1217.     }
  1218.     else {
  1219.       if (! to_delete) return(FALSE);    /* no work to do! */
  1220.           sprintf(outfile, "%s%d", temp_file, getpid());
  1221.       unlink(outfile); /* ensure it's empty! */
  1222.     }
  1223.  
  1224.     if (to_save) {
  1225.       if ((temp = fopen(outfile,"a")) == NULL) {
  1226.         if (mbox_specified == 0)
  1227.           unlock();        /* remove mailfile lock! */
  1228.         dprint1("\tCould not append to file %s!\n", outfile);
  1229.         sprintf(buffer, "           Could not append to file %s!          ",
  1230.             outfile);
  1231.         leave(Centerline(LINES-1, buffer));
  1232.       }
  1233.   
  1234.       for (i = 0; i < message_count; i++)
  1235.         if (header_table[i].delete == 0) {
  1236.           current = i+1;
  1237.           dprint1("\tsaving message %d\n", current);
  1238.           copy_message("", temp, FALSE);
  1239.         }
  1240.       fclose(temp);
  1241.     }
  1242.  
  1243.     /* remove source file...either default mailbox or original copy of 
  1244.            specified one! */
  1245.  
  1246.     if (mbox_specified == 0) {
  1247.       /** let's grab the original mode and date/time of the mailfile 
  1248.           before removing it **/
  1249.  
  1250.           if (stat(infile, &buf) == 0)
  1251.         mode = buf.st_mode & 00777;
  1252.       else {
  1253.         dprint2("\tencountered error #%d on stat(%s)\n", errno, infile);
  1254.             error2("Error %d on stat(%s)!", errno, infile);
  1255.       }
  1256.     }
  1257.  
  1258.     fclose(mailfile);    /* close the baby... */
  1259.     unlink(infile);     /* and BLAMO!        */
  1260.  
  1261.     if (to_save && (mbox_specified || pending)) {
  1262.       if (link(outfile, infile) != 0) 
  1263.         if (errno == EXDEV) { /** different file devices!  Use copy! **/
  1264.           if (copy(outfile, infile) != 0) {
  1265.             dprint2("\tCouldn't modify mail file: copy(%s, %s) failed!\n",
  1266.             outfile, infile);
  1267.             error("couldn't modify mail file!");
  1268.             sleep(1);
  1269.             sprintf(infile,"%s/%s", home, unedited_mail);
  1270.         if (copy(outfile, infile) != 0) {
  1271.               dprint1("\tcouldn't copy to %s either!!  Help!\n", infile);
  1272.               error("something godawful is happening to me!!!");
  1273.           emergency_exit();
  1274.             }
  1275.         else {
  1276.               dprint1("\tsaved mailbox as file %s\n", infile);
  1277.               error1("saved mailbox as %s", infile);
  1278.             }
  1279.           }    
  1280.         }
  1281.         else {
  1282.           dprint3("\tlink(%s, %s) failed with error %d\n", outfile, 
  1283.               infile, errno);
  1284.           error1("link failed for unknown reasons [errno=%d!!", errno);
  1285.           emergency_exit();
  1286.         }
  1287.       unlink(outfile);
  1288.     }
  1289.  
  1290.     if (mbox_specified == 0) {
  1291.       if (mode != 00644) { /* if not the default mail access mode... */
  1292.         if (! pending) { /* if none still being saved */
  1293.           temp = fopen(infile, "w");
  1294.           fclose(temp);
  1295.         }
  1296.         chmod(infile,mode);
  1297.     
  1298.         /* let's set the access times of the new mail file to be
  1299.            the same as the OLD one (still sitting in 'buf') ! */
  1300.  
  1301.         times.actime = buf.st_atime;
  1302.         times.modtime= buf.st_mtime;
  1303.         if (utime(infile, ×) != 0) {
  1304.           dprint2("\tencountered error %d on utime(%s)\n", 
  1305.               errno, infile);
  1306.           error1("Error %d trying utime", errno);
  1307.         }
  1308.       }
  1309.       unlock();    /* remove the lock on the file ASAP! */
  1310.  
  1311.       /** finally, let's change the ownership of the default
  1312.           outgoing mailbox, if needed **/
  1313.  
  1314.       if (to_save) {
  1315.         dprint3("\tchown(%s, %d, %d)\n", outfile, userid, getgid());
  1316.         chown(outfile, userid, getgid());
  1317.       }
  1318.     }
  1319.  
  1320.     dprint3("\tchown(%s, %d, %d)\n", infile, userid, getgid());
  1321.  
  1322.     chown(infile, userid, getgid());    /* file owned by user */
  1323.  
  1324.     return(to_delete);    
  1325. }
  1326.  
  1327. char lock_name[SLEN];
  1328. extern int errno;    /* system error number! */
  1329.  
  1330. lock(direction)
  1331. int direction;
  1332. {
  1333.     /** Create lock file to ensure that we don't get any mail 
  1334.         while altering the mailbox contents!
  1335.         If it already exists sit and spin until 
  1336.                either the lock file is removed...indicating new mail
  1337.         or
  1338.            we have iterated MAX_ATTEMPTS times, in which case we
  1339.            either fail or remove it and make our own (determined
  1340.            by if REMOVE_AT_LAST is defined in header file
  1341.  
  1342.         If direction == INCOMING then DON'T remove the lock file
  1343.         on the way out!  (It'd mess up whatever created it!).
  1344.     **/
  1345.  
  1346.     register int iteration = 0, stat_val;
  1347.     struct stat buffer;
  1348.  
  1349.     dprint1("lock(direction=%s)\n", direction? "INCOMING" : "OUTGOING");
  1350.  
  1351.     sprintf(lock_name,"%s%s.lock", mailhome, username);
  1352.  
  1353.     stat_val = stat(lock_name, &buffer);
  1354.  
  1355.     while (stat_val != -1 && iteration++ < MAX_ATTEMPTS) {
  1356.       dprint2("\tstat(%s) returned %d\n",
  1357.            lock_name, stat_val);
  1358.       if (direction == INCOMING)
  1359.         fprintf(stderr,"Mail being received!\nwaiting...");
  1360.       else
  1361.         error2("Attempt %d: Mail being received (%d)...waiting", 
  1362.                    iteration, stat_val);
  1363.       sleep(5);
  1364.       stat_val = stat(lock_name, &buffer);
  1365.     }
  1366.     
  1367.     if (stat_val != -1) {
  1368. #ifdef REMOVE_AT_LAST
  1369.       /** time to waste the lock file!  Must be there in error! **/
  1370.       error("Throwing away the current lock file!");
  1371.       dprint0("\tthrowing away current lock file!\n");
  1372.       if (unlink(lock_name) != 0) {
  1373.         dprint0("\tcouldn't unlink!!  Error was %d\n", errno);
  1374.         leave(error("could not remove current lock file!"));
  1375.       }
  1376.       
  1377.       /* everything is okay, so lets act as if nothing had happened... */
  1378. #else
  1379.       /* okay...we die and leave, not updating the mailfile mbox or
  1380.          any of those! */
  1381.       if (direction == INCOMING) {
  1382.         printf("Giving up after %d iterations...\n", iteration);
  1383.         printf("Try again later, please.\n");
  1384.         dprint1("\tbailing out after %d iterations...\n", iteration);
  1385.         leave_locked();
  1386.       }
  1387.       else {
  1388.         dprint1("\ttimed out on lock file reads.  Iterations=%d\n", 
  1389.                 iteration);
  1390.         leave(error("Timed out on lock file reads.  Bye!"));
  1391.       }
  1392. #endif
  1393.     }
  1394.  
  1395.     /* if we get here we can create the lock file, so lets do it! */
  1396.  
  1397.     if (creat(lock_name, 0) == -1) {
  1398.       dprint2("\tCan't create lock file: creat(%s) raises error %d\n", 
  1399.           lock_name, errno);
  1400.       if (errno == EACCES)
  1401.         leave(error(
  1402.                  "Can't create lock file!  Make sure I'm setuid root!\n\r"));
  1403.       else
  1404.         leave(error1("error %d attempting to create lock file!", errno));
  1405.     }
  1406.  
  1407. }
  1408.  
  1409. unlock()
  1410. {
  1411.     /** Remove the lock file!    This must be part of the interrupt
  1412.         processing routine to ensure that the lock file is NEVER
  1413.         left sitting in the mailhome directory! **/
  1414.  
  1415.     dprint0("unlock()\n");
  1416.  
  1417.     (void) unlink(lock_name);
  1418. }
  1419. END-OF-FILE
  1420.  
  1421. size=`wc -c < src/leavembox.c`
  1422.  
  1423. if [ $size != 9540 ]
  1424. then
  1425.   echo Warning: src/leavembox.c changed - should be 9540 bytes, not $size bytes
  1426. fi
  1427.  
  1428. chmod 644 src/leavembox.c
  1429.  
  1430. # ---------- file src/mailout.c ----------
  1431.  
  1432.  
  1433. if [ -f src/mailout.c ]
  1434. then
  1435.   echo File 'src/mailout.c' already exists\!
  1436.   exit 1
  1437. fi
  1438.  
  1439. echo extracting file src/mailout.c...
  1440. cat << 'END-OF-FILE' > src/mailout.c
  1441. /**             mailout.c            **/
  1442.  
  1443. /** Interface to allow mail to be sent to users.  Part of MSG  **/
  1444.  
  1445. /** (C) Copyright 1986, Dave Taylor                    **/
  1446.  
  1447. /** System output is a line of the form;
  1448.  
  1449.     sendmail -oi addresses < tempfile
  1450.     or
  1451.     mailer addresses < tempfile
  1452.  
  1453.     Changed 8/12 to conform to RFC-822 style headers (ARPA and so on)
  1454.     Changed 9/23 to deal with commas, and other bug fixes
  1455.     Changed 9/24 to add reading the users .mailheaders file
  1456.     Changed 10/26 to use the shared subject, to, cc, etc fields
  1457.     Changed 2/20 to use batch_subject, if specified 
  1458. **/
  1459.  
  1460. #include "headers.h"
  1461.  
  1462. /** strings defined for the hdrconfg routines **/
  1463.  
  1464. char subject[SLEN], action[SLEN], reply_to[SLEN], expires[SLEN], priority[SLEN];
  1465. char to[VERY_LONG_STRING], cc[VERY_LONG_STRING];
  1466.  
  1467. char *format_long(), *strip_commas(), *tail_of_string();
  1468.  
  1469. int gotten_key = 0;
  1470.  
  1471. int
  1472. send(given_to, given_subject, edit_message)
  1473. char *given_to, *given_subject;
  1474. int   edit_message;
  1475. {
  1476.     /** Prompt for fields and then call mail() to send the specified
  1477.         message.  If 'edit_message' is true then don't allow the
  1478.             message to be edited. **/
  1479.  
  1480.     char address[VERY_LONG_STRING];  /* BIG address! */
  1481.     char addressII[VERY_LONG_STRING];
  1482.     char *buffer;            /* misc, for I/O */
  1483.  
  1484.     int  copy_msg = FALSE, is_a_response = FALSE;
  1485.  
  1486.     dprint2("send(to='%s', subject='%s')\n", given_to, given_subject);
  1487.  
  1488.     /* zero all current global message strings */
  1489.  
  1490.     cc[0] = action[0] = reply_to[0] = expires[0] = priority[0] = '\0';
  1491.  
  1492.     addressII[0] = '\0';
  1493.  
  1494.     /* initialize 'to' and 'subject' according to what we were given */
  1495.  
  1496.     strcpy(subject, given_subject);
  1497.     strcpy(to, given_to);
  1498.  
  1499.     /** Copy message? **/
  1500.  
  1501.     if (strlen(to) > 0 && !mail_only) {    /* predefined 'to' line! */
  1502.       if (auto_copy) 
  1503.         copy_msg = TRUE;
  1504.       else 
  1505.         copy_msg = (want_to("Copy message? (y/n) ", 'n', TRUE) == 'y');
  1506.       is_a_response = TRUE;
  1507.     }
  1508.     else
  1509.       if (strlen(subject) > 0)      /* predefined 'subject' (Forward) */
  1510.         copy_msg = TRUE;
  1511.  
  1512.     /**  To:  **/
  1513.  
  1514.     if (strlen(to) == 0) {
  1515.       PutLine(LINES-2, 0, "To: ");
  1516.       (void) optionally_enter(to, LINES-2, 4, FALSE); 
  1517.       if (strlen(to) == 0) {
  1518.         MoveCursor(LINES-2,0);    CleartoEOLN();
  1519.         error("mail not sent");
  1520.         return(0);
  1521.       }
  1522.       build_address(strip_commas(to), address); 
  1523.     }
  1524.     else if (mail_only) 
  1525.       build_address(strip_commas(to), address); 
  1526.     else 
  1527.       strcpy(address, to);
  1528.     
  1529.     if (strlen(address) == 0) {    /* bad address!  Removed!! */
  1530.       if (! mail_only)
  1531.         ClearLine(LINES-2);
  1532.       return(0);
  1533.     }
  1534.  
  1535.     if (! mail_only) {
  1536.       MoveCursor(LINES-3, COLUMNS-50);
  1537.       CleartoEOLN();
  1538.       printf("          ");     /* 10 spaces */
  1539.     }
  1540.  
  1541.     if (mail_only && strlen(batch_subject) > 0) {
  1542.  
  1543.       /** User wants to send the mail without editing or anything...
  1544.           just suck in stdin for the file and don't prompt for anything! 
  1545.       **/
  1546.  
  1547.       strcpy(subject, batch_subject);
  1548.  
  1549.       mail(address, NULL, FALSE, FALSE, FALSE, TRUE);
  1550.     
  1551.       return;
  1552.     }
  1553.  
  1554.     if (mail_only && check_only) {
  1555.       printf("Expands to: %s\n", format_long(address, 12));
  1556.       leave();
  1557.     }
  1558.  
  1559.     if (mail_only)
  1560.       printf("To: %s\n\r", format_long(address));
  1561.     else {
  1562.       if (strlen(address) > COLUMNS-50) {
  1563.         buffer = tail_of_string(address, COLUMNS-50);
  1564.         printf("To: (%s)", buffer);
  1565.       }
  1566.       else
  1567.         printf("To: %s", address);
  1568.     }
  1569.   
  1570.     /** Subject: **/
  1571.  
  1572.     if (mail_only)
  1573.       printf("Subject: ");
  1574.     else 
  1575.       PutLine(LINES-2,0,"Subject: ");
  1576.     CleartoEOLN();
  1577.     if (optionally_enter(subject, LINES-2, 9, TRUE) == -1) {
  1578.       MoveCursor(LINES-2,0);     CleartoEOLN();
  1579.       error("mail not sent");
  1580.       return(0);
  1581.     }
  1582.  
  1583.     if (strlen(subject) == 0) {
  1584.       if (mail_only) 
  1585.         printf("\n\rNo subject - Continue with message? (y/n) ");
  1586.       else
  1587.         PutLine(LINES-2,0,"No subject - Continue with message? (y/n) ");
  1588.       printf("n%c", BACKSPACE);
  1589.       fflush(stdout);
  1590.       if (tolower(ReadCh()) != 'y') {
  1591.         if (mail_only) {
  1592.           printf("\n\r\n\rMail Cancelled!\n\r");
  1593.           return(0);
  1594.         }
  1595.         MoveCursor(LINES-2,0);    CleartoEOLN();
  1596.         error("mail not sent");
  1597.         return(0);
  1598.       }
  1599.       else if (! mail_only) {
  1600.         PutLine(LINES-2,0,"Subject: <none>");
  1601.         CleartoEOLN();
  1602.       }
  1603.     }
  1604.  
  1605.     /** Copies to: **/
  1606.  
  1607.     if (mail_only)
  1608.       printf("\n\rCopies To: ");
  1609.     else
  1610.       PutLine(LINES-1,0,"Copies To: ");
  1611.  
  1612.     fflush(stdout);
  1613.  
  1614.     if (optionally_enter(cc, LINES-1, 11, FALSE) == -1) {
  1615.       if (mail_only) {
  1616.         printf("\n\r\n\rMail not sent!\n\r");
  1617.         return(0);
  1618.       }
  1619.       MoveCursor(LINES-2,0);     CleartoEOLN();
  1620.       MoveCursor(LINES-1,0);     CleartoEOLN();
  1621.       error("mail not sent");
  1622.       return(0);
  1623.     }
  1624.       
  1625.     build_address(strip_commas(cc), addressII);
  1626.  
  1627.     if (strlen(address) + strlen(addressII) > VERY_LONG_STRING) {
  1628.       error("Too many people.  Copies ignored");
  1629.       cc[0] = '\0';
  1630.     }
  1631.     
  1632.     if (mail_only) 
  1633.       printf("\n\r");
  1634.     else
  1635.       MoveCursor(LINES,0);    /* you know you're hit <return> ! */
  1636.  
  1637.     /* and mail that puppy outta here! */
  1638.  
  1639.     mail(address, addressII, copy_msg, is_a_response, edit_message, FALSE);
  1640.     
  1641.     return(edit_message);
  1642. }
  1643.  
  1644. mail(expanded_to, expanded_cc, copy_msg, is_a_response, edit_message, batch)
  1645. char *expanded_to, *expanded_cc;
  1646. int  copy_msg, is_a_response, edit_message, batch;
  1647. {
  1648.     /** Given the addresses and various other miscellany (specifically, 
  1649.         'copy-msg' indicates whether a copy of the current message should 
  1650.         be included, 'is-a-response' indicates if 'In-Reply-To:' should be 
  1651.         generated for this message, 'edit_message' indicates whether the
  1652.         message should be edited and 'batch' indicates that the message
  1653.         should be read from stdin) this routine will invoke an editor for
  1654.         the user and then actually mail off the message.
  1655.     **/
  1656.  
  1657.     FILE *reply, *real_reply; /* second is post-input buffer */
  1658.     FILE *headerfile;      /* copy default headers        */
  1659.     char buffer[LONG_SLEN], filename[SLEN], filename2[SLEN],
  1660.              very_long_buffer[VERY_LONG_STRING];
  1661.     char hfname[SLEN], ret_ch;
  1662.     register int i, crypted=0, encoded_lines = 0, retransmit = 0;
  1663.  
  1664.     static int cancelled_msg = 0;
  1665.     
  1666.     dprint6("mail(to='%s', cc='%s', copy-msg=%s, is-a-response=%s, edit-message=%s, batch=%s)\n", 
  1667.              expanded_to, expanded_cc, onoff(copy_msg), 
  1668.              onoff(is_a_response), onoff(edit_message), onoff(batch));
  1669.  
  1670.     sprintf(filename,"%s%d",temp_file, getpid());
  1671.  
  1672.     if (! batch) {
  1673.       if ((reply = fopen(filename,"r")) != NULL && cancelled_msg) {
  1674.         Raw(ON);
  1675.         if (copy_msg)
  1676.           PutLine(LINES-1,0,"Recall last kept message instead? (y/n) ");
  1677.         else
  1678.           PutLine(LINES-1,0,"Recall last kept message? (y/n) ");
  1679.         CleartoEOS();
  1680.         printf("y%c", BACKSPACE);
  1681.         fflush(stdout);
  1682.         if (tolower(ReadCh()) != 'n') {
  1683.           printf("Yes");    fflush(stdout);
  1684.               retransmit++;
  1685.         }
  1686.         else {
  1687.           printf("No");    fflush(stdout);
  1688.               fclose(reply);
  1689.         }
  1690.         cancelled_msg = 0;
  1691.       }
  1692.     }
  1693.  
  1694.     if (! retransmit)
  1695.       if ((reply = fopen(filename,"w")) == NULL)
  1696.         return(error1("Could not create file %s",filename));
  1697.  
  1698.     if (copy_msg) 
  1699.       if (edit_message) 
  1700.         copy_message(prefixchars, reply, noheader);
  1701.       else
  1702.         copy_message("", reply, noheader);
  1703.     
  1704.     if (batch) {
  1705.       Raw(OFF);
  1706.       ret_ch = '\n';
  1707.       if (isatty(fileno(stdin))) {
  1708.         printf("To: %s\nSubject: %s\n", expanded_to, subject);
  1709.         printf("\nPlease enter your message, ending with a ^D:\n\n");
  1710.         ret_ch = '\0';
  1711.       }
  1712.       while (gets(very_long_buffer, VERY_LONG_STRING) != NULL) 
  1713.         fprintf(reply, "%s%c", very_long_buffer, ret_ch);
  1714.  
  1715.       if (isatty(fileno(stdin))) 
  1716.         printf("\n<end-of-message>\n");
  1717.     }
  1718.  
  1719.     fclose(reply);
  1720.  
  1721.     if (edit_message) {
  1722.       sprintf(buffer,"%s %s", editor, filename);
  1723.  
  1724.       Raw(OFF);
  1725.       chown(filename, userid, getgid());
  1726.       if ((i =system_call(buffer,SH)) != 0)    {     /* edit mail as user */
  1727.         error1("Problems with the editor: error %d", i);
  1728.         MoveCursor(LINES-1,0); CleartoEOLN();
  1729.         sleep(2);
  1730.       }
  1731.     
  1732.       Raw(ON);
  1733.     }
  1734.  
  1735.     if ((reply = fopen(filename,"r")) == NULL)
  1736.       return(error("Could not open reply file"));
  1737.  
  1738.     /* make sure this twit really wants to send mail before we go any 
  1739.        further! */
  1740.  
  1741.     generate_reply_to((is_a_response? current-1 : -1));
  1742.  
  1743.     edit_headers((is_a_response? current-1 : -1));
  1744.  
  1745.     if (check_first && ! batch) {
  1746.       if (mail_only) {
  1747.         printf("\n\rAre you sure you want to send this? (y/n) ");
  1748.         CleartoEOLN();
  1749.         printf("y%c", BACKSPACE);
  1750.         fflush(stdin);    /* wait for answer! */
  1751.         fflush(stdout);
  1752.         if (tolower(ReadCh()) == 'n') { /* sigh... */
  1753.           printf("No\n\r\n\r\n\rMail not sent!!\n\r");
  1754.           return(0);
  1755.         }
  1756.         else
  1757.           printf("Yes\n\r\n\r");
  1758.       }
  1759.       else {
  1760.         MoveCursor(LINES,0);
  1761.         CleartoEOLN();
  1762.         MoveCursor(LINES-1,0);
  1763.         printf("Are you sure you want to send this? (y/n) ");
  1764.         CleartoEOLN();
  1765.         printf("y%c", BACKSPACE);
  1766.         fflush(stdin);    /* wait for answer! */
  1767.         fflush(stdout);
  1768.         if (tolower(ReadCh()) == 'n') { /* sigh... */
  1769.           printf("No");
  1770.           set_error(
  1771.            "Message kept - Can be restored at next F)orward, M)ail or R)eply ");
  1772.           cancelled_msg = 1;
  1773.           fclose(reply);
  1774.           return(1);
  1775.         }
  1776.         printf("Yes!");
  1777.         fflush(stdout);
  1778.       }
  1779.     }
  1780.  
  1781.     cancelled_msg = 0;    /* it ain't cancelled, is it? */
  1782.  
  1783.     /** grab a copy if the user so desires... **/
  1784.  
  1785.     if (auto_cc && ! batch)
  1786.       save_copy(subject, expanded_to, expanded_cc, filename, to);
  1787.  
  1788.     /** write all header information into real_reply **/
  1789.  
  1790.     sprintf(filename2,"%s%d",temp_file, getpid()+1);
  1791.     
  1792.     if ((real_reply = fopen(filename2,"w")) == NULL) {
  1793.       /* contingency: use mailx... */
  1794.       if (cc[0] != '\0')          /* copies! */
  1795.         sprintf(to,"%s %s", to, cc);
  1796.  
  1797.       sprintf(very_long_buffer, "(%s -s \"%s\" %s < %s ; %s %s)&",
  1798.                   mailx, subject, strip_commas(to), filename, remove, filename);
  1799.       error1("couldn't open %s for writing!", filename2);
  1800.       sleep(2);    /* ensure time to see this prompt! */
  1801.       
  1802.     }
  1803.     else {
  1804.       /* write header to file then message... */
  1805.  
  1806.       fprintf(real_reply, "To: %s\n", format_long(to, strlen("To:")));
  1807.  
  1808.       fprintf(real_reply,"Date: %s\n", (char *) get_arpa_date());
  1809.  
  1810.       fprintf(real_reply,"From: %s!%s (%s)\n", hostname, username,
  1811.           full_username);
  1812.  
  1813.       fprintf(real_reply, "Subject: %s\n", subject);
  1814.  
  1815.       if (cc[0] != '\0')
  1816.         fprintf(real_reply, "Cc: %s\n", 
  1817.             format_long(cc, strlen("Cc: ")));
  1818.  
  1819.       if (strlen(action) > 0)
  1820.         fprintf(real_reply, "Action: %s\n", action);
  1821.     
  1822.       if (strlen(priority) > 0)
  1823.         fprintf(real_reply, "Priority: %s\n", priority);
  1824.     
  1825.       if (strlen(expires) > 0)
  1826.         fprintf(real_reply, "Expiration-Date: %s\n", expires);
  1827.     
  1828.       if (strlen(reply_to) > 0)
  1829.         fprintf(real_reply, "In-Reply-To: %s\n", reply_to);
  1830.     
  1831.       /*** add the users .mailheaders file if available ***/
  1832.  
  1833.       sprintf(hfname, "%s/%s", home, mailheaders);
  1834.  
  1835.       if ((headerfile = fopen(hfname, "r")) != NULL) {
  1836.         while (fgets(buffer, LONG_SLEN, headerfile) != NULL)
  1837.           fprintf(real_reply, "%s", buffer);
  1838.         fclose(headerfile);
  1839.       }
  1840.  
  1841.       fprintf(real_reply, "X-Mailer: msg [version %s]\n", VERSION);
  1842.       fprintf(real_reply, "\n");
  1843.  
  1844.        /** now copy message across! **/
  1845.  
  1846.       while (fgets(buffer, LONG_SLEN, reply) != NULL) {
  1847.         if (buffer[0] == '[') {
  1848.           if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))==0)
  1849.             crypted = 1;
  1850.            else if (strncmp(buffer, END_ENCODE, strlen(END_ENCODE))==0)
  1851.             crypted = 0;
  1852.            else if (strncmp(buffer, DONT_SAVE, strlen(DONT_SAVE)) == 0)
  1853.             continue;    /* next line? */
  1854.           }
  1855.           else if (crypted) {
  1856.             if (! gotten_key++)
  1857.               getkey(ON);
  1858.             else if (! encoded_lines++)
  1859.               get_key_no_prompt();        /* reinitialize.. */
  1860.             
  1861.         encode(buffer);
  1862.           }
  1863.         fputs(buffer, real_reply);
  1864.       }
  1865.  
  1866.       fclose(reply);
  1867.       fclose(real_reply);
  1868.  
  1869.       if (cc[0] != '\0')  /* copies! */
  1870.         sprintf(to,"%s %s", to, cc);
  1871.  
  1872.       if (access(sendmail, EXECUTE_ACCESS) == 0)    /* yeah!  Sendmail! */
  1873.         sprintf(very_long_buffer,"(%s %s %s < %s ; %s %s) &",
  1874.                   sendmail, sendmailflags, strip_commas(to), filename2, 
  1875.           remove, filename2);
  1876.       else /* oh well, use default mailer... */
  1877.             sprintf(very_long_buffer,"(%s %s < %s ; %s %s) &", 
  1878.                   mailer, strip_commas(to), filename2, 
  1879.           remove, filename2);
  1880.     }
  1881.     
  1882.     if (mail_only) {
  1883.       if (! batch) {
  1884.         printf("sending mail...");
  1885.         fflush(stdout);
  1886.       }
  1887.     }
  1888.     else {    
  1889.       PutLine(LINES,0,"sending mail...");
  1890.       CleartoEOLN();
  1891.     }
  1892.  
  1893.     dprint1("\n\n\t%s\n\n", very_long_buffer);
  1894.     system(very_long_buffer);
  1895.  
  1896.     if (mail_only) {
  1897.       if (! batch)
  1898.         printf("\rmail sent!      \n\r");
  1899.     }
  1900.     else 
  1901.       set_error("Mail sent!");
  1902.  
  1903.     return(TRUE);
  1904. }
  1905. END-OF-FILE
  1906.  
  1907. size=`wc -c < src/mailout.c`
  1908.  
  1909. if [ $size != 12387 ]
  1910. then
  1911.   echo Warning: src/mailout.c changed - should be 12387 bytes, not $size bytes
  1912. fi
  1913.  
  1914. chmod 644 src/mailout.c
  1915.  
  1916. # ---------- file src/mailtime.c ----------
  1917.  
  1918.  
  1919. if [ -f src/mailtime.c ]
  1920. then
  1921.   echo File 'src/mailtime.c' already exists\!
  1922.   exit 1
  1923. fi
  1924.  
  1925. echo extracting file src/mailtime.c...
  1926. cat << 'END-OF-FILE' > src/mailtime.c
  1927. /**            mailtime.c            **/
  1928.  
  1929. /** This set of routines is used to figure out when the user last read
  1930.     their mail and to also figure out if a given message is new or not.
  1931.  
  1932.     (C) Copyright 1986 Dave Taylor
  1933. **/
  1934.  
  1935. #include "headers.h"
  1936.  
  1937. #include <sys/types.h>
  1938. #include <sys/stat.h>
  1939. #ifdef BSD
  1940. #  include <sys/time.h>
  1941. #else
  1942. #  include <time.h>
  1943. #endif
  1944.  
  1945. resolve_received(entry)
  1946. struct header_rec *entry;
  1947. {
  1948.     /** Entry has the data for computing the time and date the 
  1949.         message was received.  Fix it and return **/
  1950.  
  1951.     dprint0("resolve_received(<entry>)\n");
  1952.  
  1953.     switch (tolower(entry->month[0])) {
  1954.       case 'j' : if (tolower(entry->month[1]) == 'a')
  1955.                entry->received.month = JANUARY;
  1956.              else if (tolower(entry->month[2]) == 'n')
  1957.                    entry->received.month = JUNE;
  1958.              else
  1959.                    entry->received.month = JULY;
  1960.                  break;
  1961.       case 'f' : entry->received.month = FEBRUARY;
  1962.               break;
  1963.       case 'm' : if (tolower(entry->month[2]) == 'r')
  1964.                    entry->received.month = MARCH;
  1965.              else
  1966.                entry->received.month = MAY;
  1967.                  break;
  1968.       case 'a' : if (tolower(entry->month[1]) == 'p')
  1969.                    entry->received.month = APRIL;
  1970.                  else
  1971.                    entry->received.month = AUGUST;
  1972.              break;
  1973.       case 's' : entry->received.month = SEPTEMBER;
  1974.              break;
  1975.       case 'o' : entry->received.month = OCTOBER;
  1976.              break;
  1977.       case 'n' : entry->received.month = NOVEMBER;
  1978.                break;
  1979.       case 'd' : entry->received.month = DECEMBER;
  1980.              break;
  1981.     }
  1982.  
  1983.     sscanf(entry->day, "%d", &(entry->received.day));
  1984.  
  1985.     sscanf(entry->year, "%d", &(entry->received.year));
  1986.     if (entry->received.year > 100) entry->received.year -= 1900;
  1987.  
  1988.     sscanf(entry->time, "%d:%d", &(entry->received.hour),
  1989.            &(entry->received.minute));
  1990.  
  1991.     dprint3("\tthis message received %d/%d/%d at", 
  1992.         entry->received.month,
  1993.         entry->received.day,
  1994.         entry->received.year);
  1995.     dprint2("%d:%d\n", entry->received.hour, entry->received.minute);
  1996. }
  1997.  
  1998. get_mailtime()
  1999. {
  2000.     /** Instantiate the values of the last_read_mail stat
  2001.         variable based on the file access time/date of the
  2002.         file mailtime_file.  IF the file doesn't exist,
  2003.         then assume all mail is new. **/
  2004.  
  2005.     struct stat buffer;
  2006.     struct tm   *timebuf;
  2007.     char   filename[SLEN];
  2008.  
  2009.     dprint0("get_mailtime()\n");
  2010.  
  2011.     sprintf(filename, "%s/%s", home, mailtime_file);
  2012.  
  2013.     if (stat(filename, &buffer) == -1) {
  2014.       last_read_mail.month = 0;
  2015.       last_read_mail.day = 0;
  2016.       last_read_mail.year = 0;
  2017.       last_read_mail.hour = 0;
  2018.       last_read_mail.minute = 0;
  2019.     }
  2020.     else {    /* stat okay... */
  2021.       timebuf = (struct tm *) localtime(&(buffer.st_mtime));
  2022.       
  2023.       last_read_mail.month = timebuf->tm_mon;
  2024.       last_read_mail.day = timebuf->tm_mday;
  2025.       last_read_mail.year = timebuf->tm_year;
  2026.       last_read_mail.hour = timebuf->tm_hour;
  2027.       last_read_mail.minute = timebuf->tm_min;
  2028.     }
  2029.  
  2030.     dprint3("\tmail time set to %d/%d/%d at ", last_read_mail.month, 
  2031.             last_read_mail.day, last_read_mail.year);
  2032.     dprint2("%d:%02d\n", last_read_mail.hour, last_read_mail.minute);
  2033. }
  2034.  
  2035. update_mailtime()
  2036. {
  2037.     /** This routine updates the last modified time of the 
  2038.         .last_read_mail file in the users home directory.
  2039.         If the file doesn't exist, it creates it!! **/
  2040.  
  2041.     char filename[SLEN];
  2042.     
  2043.     sprintf(filename, "%s/%s", home, mailtime_file);
  2044.  
  2045.     if (utime(filename, NULL) == -1)
  2046.       creat(filename, 0777);
  2047. }
  2048.  
  2049. new_msg(entry)
  2050. struct header_rec *entry;
  2051. {
  2052.     /** Return true if the current message is NEW.  This can be
  2053.         easily tested by seeing 1) if we're reading the incoming
  2054.         mailbox and then, if so, 2) if the received_on_machine
  2055.         date is more recent than the last_read_mail date.
  2056.     **/
  2057.  
  2058.     if (mbox_specified != 0) return(FALSE);        /* not incoming */
  2059.     
  2060.     /** Two tests - if received is OLDER than last read mail, then
  2061.         immediately return FALSE.  If received is NEWER than last
  2062.         read mail then immediately return TRUE **/
  2063.  
  2064.     if (entry->received.year < last_read_mail.year) 
  2065.       return(FALSE);                
  2066.     
  2067.     if (entry->received.year > last_read_mail.year) 
  2068.       return(TRUE);                
  2069.     
  2070.     if (entry->received.month < last_read_mail.month)
  2071.       return(FALSE);            
  2072.  
  2073.     if (entry->received.month > last_read_mail.month)
  2074.       return(TRUE);            
  2075.  
  2076.     if (entry->received.day < last_read_mail.day)
  2077.       return(FALSE);
  2078.  
  2079.     if (entry->received.day > last_read_mail.day)
  2080.       return(TRUE);
  2081.  
  2082.     if (entry->received.hour < last_read_mail.hour)        
  2083.       return(FALSE);        
  2084.     
  2085.     if (entry->received.hour > last_read_mail.hour)        
  2086.       return(TRUE);        
  2087.     
  2088.     if (entry->received.minute < last_read_mail.minute)
  2089.       return(FALSE);    
  2090.  
  2091.     return(TRUE);
  2092. }
  2093. END-OF-FILE
  2094.  
  2095. size=`wc -c < src/mailtime.c`
  2096.  
  2097. if [ $size != 4529 ]
  2098. then
  2099.   echo Warning: src/mailtime.c changed - should be 4529 bytes, not $size bytes
  2100. fi
  2101.  
  2102. chmod 644 src/mailtime.c
  2103.  
  2104. # ---------- file src/mkhdrs.c ----------
  2105.  
  2106.  
  2107. if [ -f src/mkhdrs.c ]
  2108. then
  2109.   echo File 'src/mkhdrs.c' already exists\!
  2110.   exit 1
  2111. fi
  2112.  
  2113. echo extracting file src/mkhdrs.c...
  2114. cat << 'END-OF-FILE' > src/mkhdrs.c
  2115. /**            mkhdrs.c        **/
  2116.  
  2117. /** This contains all the header generating routines for the MSG
  2118.     program.
  2119.  
  2120.     (C) Copyright 1985 Dave Taylor
  2121.  
  2122. **/
  2123.  
  2124. #include <stdio.h>
  2125. #include "headers.h"
  2126.  
  2127. extern char reply_to[SLEN];
  2128.  
  2129. generate_reply_to(msg)
  2130. int msg;
  2131. {
  2132.     /** Generate an 'in-reply-to' message... **/
  2133.     char buffer[SLEN];
  2134.  
  2135.  
  2136.     if (msg == -1)        /* not a reply! */
  2137.       reply_to[0] = '\0';
  2138.     else {
  2139.       if (chloc(header_table[msg].from, '!') != -1)
  2140.         tail_of(header_table[msg].from, buffer, FALSE);
  2141.       else
  2142.         strcpy(buffer, header_table[msg].from);
  2143.       sprintf(reply_to, "Message from \"%s\" of %s %s, %s at %s",
  2144.           buffer,
  2145.           header_table[msg].month,
  2146.           header_table[msg].day,
  2147.           header_table[msg].year,
  2148.           header_table[msg].time);
  2149.     }
  2150. }
  2151. END-OF-FILE
  2152.  
  2153. size=`wc -c < src/mkhdrs.c`
  2154.  
  2155. if [ $size != 728 ]
  2156. then
  2157.   echo Warning: src/mkhdrs.c changed - should be 728 bytes, not $size bytes
  2158. fi
  2159.  
  2160. chmod 644 src/mkhdrs.c
  2161.  
  2162. # ---------- file src/msg.c ----------
  2163.  
  2164.  
  2165. if [ -f src/msg.c ]
  2166. then
  2167.   echo File 'src/msg.c' already exists\!
  2168.   exit 1
  2169. fi
  2170.  
  2171. echo extracting file src/msg.c...
  2172. cat << 'END-OF-FILE' > src/msg.c
  2173. /**            msg.c            **/
  2174.  
  2175. /* main program of the MSG mail system! 
  2176.  
  2177.    This file and all associated files and documentation:
  2178.     (C) Copyright 1986 Dave Taylor
  2179. */
  2180.  
  2181. #include "msg.h"
  2182.  
  2183. main(argc, argv)
  2184. int argc;
  2185. char *argv[];
  2186. {
  2187.     char ch, address[SLEN], to_whom[LONG_SLEN];
  2188.     int  redraw, /** do we need to rewrite the entire screen? **/
  2189.          nuhead, /** or perhaps just the headers section...   **/
  2190.          nucurr, /** or just the current message pointer...   **/
  2191.          nufoot; /** clear lines 16 thru bottom and new menu  **/
  2192.     int  i, size;/** number of bytes in file.  Only mailbox!  **/
  2193.     int  pageon; /** for when we receive new mail...          **/
  2194.  
  2195.     parse_arguments(argc, argv, to_whom);
  2196.  
  2197.     if (mail_only) {
  2198.  
  2199.        initialize();
  2200.  
  2201.        Raw(ON);
  2202.        dprint1("\n\n\tmail-only: mailing to %s\n\n", to_whom);
  2203.        (void) send(to_whom, "", TRUE); 
  2204.        leave(0);
  2205.     }
  2206.  
  2207.     InitScreen();
  2208.  
  2209.     ScreenSize(&LINES, &COLUMNS);
  2210.  
  2211.     initialize();
  2212.     
  2213.     showscreen();
  2214.  
  2215.     size = bytes(infile);
  2216.  
  2217.     dprint1("\tStarting mailbox size = %d bytes\n", size);
  2218.  
  2219.     Raw(ON);
  2220.     while (1) {
  2221.       redraw = 0;
  2222.       nuhead = 0;
  2223.       nufoot = 0;
  2224.       nucurr = 0;
  2225.       if ((i = bytes(infile)) != size) {
  2226.         if (debug) 
  2227.           error1("New mail in this file: %d bytes more", i - size);
  2228.         else
  2229.           error("New mail has arrived!   Hang on...");
  2230.         dprint1("\tnew mail in mailbox: %d bytes\n", i - size);
  2231.         pageon = header_page;
  2232.         newmbox(2, FALSE);
  2233.         clear_error();
  2234.         header_page = pageon;
  2235.         showscreen();
  2236.         size = i;
  2237.         transmit_functions(ON);    /* insurance */
  2238.       }
  2239.  
  2240.       prompt("Mail :");
  2241.  
  2242.       CleartoEOLN();
  2243.       ch = tolower(ReadCh()); 
  2244.       CleartoEOS();
  2245.       set_error("");    /* clear error buffer */
  2246.       MoveCursor(LINES-3,COLUMNS-74);
  2247.  
  2248.       dprint1("\n\nEntered command: %c\n\n\n", ch);
  2249.  
  2250.       switch (ch) {
  2251.  
  2252.         case '?'     :  redraw = help();            break;
  2253.  
  2254.         case ' '    : 
  2255.         case '+'    :  header_page++; nuhead++;    
  2256.                if (move_when_paged)
  2257.                  current = header_page*headers_per_page + 1;
  2258.                break;
  2259.  
  2260.         case '-'    :  header_page--; nuhead++;    
  2261.                if (move_when_paged)
  2262.                  current = header_page*headers_per_page + 1;
  2263.                break;
  2264.  
  2265.         case '='    :  if (current != 1) {
  2266.                  current = 1;
  2267.                          if (get_page(current))
  2268.                    nuhead++;    
  2269.                  else
  2270.                    nucurr++;
  2271.                }                break;
  2272.  
  2273.         case '*'    :  if (current != message_count) {
  2274.                  current = message_count;    
  2275.                          if (get_page(current))
  2276.                    nuhead++;    
  2277.                  else
  2278.                    nucurr++;
  2279.                }                break;
  2280.  
  2281.         case '|'    :  putchar('|'); 
  2282.                    softkeys_off();
  2283.                            redraw = pipe();        
  2284.                        softkeys_on();         break;
  2285.  
  2286.         case '!'    :  putchar('!'); 
  2287.                    softkeys_off();
  2288.                            redraw = subshell();        
  2289.                        softkeys_on();         break;
  2290.  
  2291.         case '%'    :  get_return(address);
  2292.                clear_error();
  2293.                MoveCursor(LINES,(COLUMNS-strlen(address))/2);
  2294.                printf("%.78s", address);    break;
  2295.         case '/'    :  if (pattern_match()) {
  2296.                           if (get_page(current))
  2297.                     nuhead++;
  2298.                           else
  2299.                             nucurr++;
  2300.                        }
  2301.                else
  2302.                   error("pattern not found!");
  2303.                break;
  2304.  
  2305.         case 'a'    :  alias();     
  2306.                nufoot++;     
  2307.                define_softkeys(MAIN);     break;
  2308.             
  2309.         case 'c'    :  printf("Change mailbox");
  2310.                define_softkeys(CHANGE);
  2311.                file_changed = leave_mbox(FALSE);
  2312.                dprint1("\tleave_mbox returned %s\n",
  2313.                    file_changed? "TRUE": "FALSE");
  2314.                        redraw = newmbox(0, TRUE);
  2315.                size = bytes(infile);    
  2316.                define_softkeys(MAIN);
  2317.                break;
  2318.  
  2319.         case '^'    :
  2320.          case 'd'    :  delete((ch == 'd'));            
  2321.                if (resolve_mode)     /* move after mail resolved */
  2322.                  if (current < message_count) {
  2323.                            current++;          
  2324.                    if (get_page(current))
  2325.                      nuhead++;
  2326.                    else
  2327.                      nucurr++;
  2328.                  }
  2329.                break;
  2330.  
  2331.         case 'f'    :  printf("Forward");
  2332.                define_softkeys(YESNO);
  2333.                if (current > 0)  
  2334.                          redraw = forward();   
  2335.                else
  2336.                          error("No mail to forward!");
  2337.                define_softkeys(MAIN);
  2338.                break;
  2339.  
  2340.         case 'g'    :  printf("Group reply");
  2341.                define_softkeys(YESNO);
  2342.                    fflush(stdout);
  2343.                if (current > 0) {
  2344.                  PutLine(LINES-3,COLUMNS-40,
  2345.                                      "building addresses...");
  2346.                          redraw = reply_to_everyone();    
  2347.                        }
  2348.                else
  2349.                  error("No mail to reply to!"); 
  2350.                define_softkeys(MAIN);
  2351.                break;
  2352.  
  2353.         case 'h'    :  if (filter)
  2354.                          printf("Message with headers...");
  2355.                        else
  2356.                  printf("Next message");
  2357.                fflush(stdout);
  2358.                i = filter;
  2359.                filter = FALSE;
  2360.                redraw = show_msg(current);
  2361.                filter = i;
  2362.                break;
  2363.  
  2364.         case 'm'    :  printf("Mail");
  2365.                redraw = send("", "", TRUE); 
  2366.                break;
  2367.  
  2368.         case ctrl('J'):
  2369.         case ctrl('M'):printf("Read Message");    fflush(stdout);
  2370.                define_softkeys(READ);
  2371.                redraw = show_msg(current);
  2372.                break;
  2373.  
  2374.         case 'n'    :  printf("Next Message");
  2375.                fflush(stdout);
  2376.                define_softkeys(READ);
  2377.                redraw = show_msg(current);  
  2378.                current += redraw;        
  2379.                (void) get_page(current); /* rewrites ANYway */
  2380.                if (current > message_count)
  2381.                  current = message_count;
  2382.                break;
  2383.  
  2384.         case 'j'    :  current++;  
  2385.                if (get_page(current))
  2386.                  nuhead++;
  2387.                else
  2388.                  nucurr++;            break;
  2389.  
  2390.         case 'k'    :  current--;  
  2391.                if (get_page(current))
  2392.                  nuhead++;
  2393.                else
  2394.                  nucurr++;            break;
  2395.  
  2396.         case 'p'    :  printf("Print message");
  2397.                fflush(stdout);
  2398.                printmsg();            break;
  2399.  
  2400.         case 'r'    :  printf("Reply to message");
  2401.                if (current > 0) 
  2402.                          redraw = reply();    
  2403.                else
  2404.                  error("No mail to reply to!"); break;
  2405.  
  2406.         case '>'    : /** backwards compatibility **/
  2407.  
  2408.         case 's'    :  printf("Save Message"); 
  2409.                if (save() && resolve_mode) {
  2410.                  delete(TRUE);        /* mark for deletion */
  2411.                  if (current < message_count) {
  2412.                    current++;    /* move to next message */
  2413.                    if (get_page(current))
  2414.                      nuhead++;
  2415.                    else
  2416.                      nucurr++;        
  2417.                  }
  2418.                }
  2419.                ClearLine(LINES-2);        break;
  2420.  
  2421.         case 't'    :  error1("%s",(char *) get_date());break;
  2422.  
  2423.         case 'q'    :  printf("Quit");  fflush(stdout);
  2424.                if (mbox_specified == 0) {
  2425.                  lock(OUTGOING);
  2426.                  if (size != bytes(infile)) {
  2427.                    error("New Mail!  Quit cancelled...");
  2428.                            unlock();
  2429.                          }
  2430.                      else
  2431.                    quit();        
  2432.                }
  2433.                    else 
  2434.                  quit();
  2435.                break;
  2436.         case 'u'    :  undelete();                
  2437.                if (resolve_mode)     /* move after mail resolved */
  2438.                  if (current < message_count) {
  2439.                            current++;          
  2440.                    if (get_page(current))
  2441.                      nuhead++;
  2442.                    else
  2443.                      nucurr++;
  2444.                  }
  2445.                break;
  2446.  
  2447.         case ctrl('Q') :
  2448.         case ctrl('Z') : /* exit fast! */
  2449.         case ctrl('?') : 
  2450.         case 'x'    :  printf("Exit");  
  2451.                            fflush(stdout);              leave();
  2452.  
  2453.         case ctrl('L') : redraw++;    break;
  2454.         
  2455.         case '@'    : debug_screen();  redraw++;    break;
  2456.     
  2457.         case '#'    : debug_message(); redraw++;    break;
  2458.  
  2459.         case ESCAPE : if (cursor_control) {
  2460.                 ch = ReadCh(); 
  2461.                         if (ch == up[1]) {
  2462.                   current--;
  2463.                   if (get_page(current))
  2464.                     nuhead++;
  2465.                   else
  2466.                     nucurr++;            
  2467.                         }
  2468.                 else if (ch == down[1]) {
  2469.                   current++;
  2470.                   if (get_page(current))
  2471.                     nuhead++;
  2472.                   else
  2473.                     nucurr++;            
  2474.                 }
  2475.                 else if (hp_terminal) {    /* kludge! */
  2476.                   if (ch == 'U') {    /* <NEXT> */
  2477.                     header_page++; 
  2478.                 nuhead++;
  2479.                     if (move_when_paged)
  2480.                       current = header_page*headers_per_page + 1;
  2481.                   }
  2482.                   else if (ch == 'V') {  /* <PREV> */
  2483.                     header_page--; 
  2484.                 nuhead++;
  2485.                     if (move_when_paged)
  2486.                       current = header_page*headers_per_page + 1;
  2487.                   }
  2488.                   else if (ch == 'h') {  /* <HOME UP> */
  2489.                     current = 1;
  2490.                             if (get_page(current))
  2491.                       nuhead++;
  2492.                             else
  2493.                               nucurr++;
  2494.                   }
  2495.                   else if (ch == 'F') {  /* <HOME DOWN> */
  2496.                     current = message_count;
  2497.                             if (get_page(current))
  2498.                       nuhead++;
  2499.                             else
  2500.                               nucurr++;
  2501.                   }
  2502.                   else /* what DID they hit??? */
  2503.                  printf("%c%c", ESCAPE, ch);
  2504.                 }
  2505.                 else /* false hit - output */
  2506.                   printf("%c%c", ESCAPE, ch);
  2507.                 break;
  2508.               }
  2509.                 /* else fall into default.. */
  2510.  
  2511.         default    : if (ch > '0' && ch <= '9') {
  2512.                 printf("New Current Message");
  2513.                 current = read_number(ch, message_count);
  2514.                         if (get_page(current))
  2515.                   nuhead++;
  2516.                         else
  2517.                           nucurr++;
  2518.               }
  2519.               else
  2520.                  error("Unknown command: Use '?' for commands");
  2521.       }
  2522.       if (redraw)
  2523.         showscreen();
  2524.  
  2525.       if (current < 1) {
  2526.         if (message_count > 0) {
  2527.           error("already at message #1!");
  2528.           current = 1;
  2529.         }
  2530.         else if (current < 0) {
  2531.           error("No messages to read!");
  2532.           current = 0;
  2533.         }
  2534.       }
  2535.       else if (current > message_count) {
  2536.         if (message_count > 0) {
  2537.           error2("only %d message%s!", message_count, 
  2538.              plural(message_count));
  2539.           current = message_count;
  2540.         }
  2541.         else {
  2542.           error("No messages to read!");
  2543.           current = 0;
  2544.         }
  2545.       }
  2546.  
  2547.       if (nuhead) 
  2548.         show_headers();
  2549.       else if (nucurr)
  2550.         show_current();
  2551.       else if (nufoot) {
  2552.         MoveCursor(LINES-7, 0);  
  2553.             CleartoEOS();
  2554.         if (mini_menu)
  2555.           show_menu();
  2556.       }
  2557.  
  2558.     } /* the BIG while loop! */
  2559. }
  2560.  
  2561.  
  2562. debug_screen()
  2563. {
  2564.     /**** spit out all the current variable settings and the table
  2565.           entries for the current 'n' items displayed. ****/
  2566.  
  2567.     register int i, j;
  2568.  
  2569.     ClearScreen();
  2570.     Raw(OFF);
  2571.  
  2572.     printf("Current message number = %d\t\t%d message(s) total\n\n",
  2573.             current, message_count);
  2574.     printf("Header_page = %d           \t\t%d possible page(s)\n",
  2575.         header_page, (int) (message_count / headers_per_page) + 1);
  2576.  
  2577.     printf("\nCurrent mailfile is %s.\n\n", infile);
  2578.  
  2579.     i = header_page*headers_per_page;    /* starting header */
  2580.  
  2581.     if ((j = i + (headers_per_page-1)) >= message_count) 
  2582.       j = message_count-1;
  2583.  
  2584.     printf(
  2585. "Num      From                     Subject                         Lines  Offset\n\n");
  2586.  
  2587.     while (i <= j) {
  2588.        printf(
  2589.        "%3d  %-16.16s  %-40.40s  %4d  %d\n",
  2590.             i+1,
  2591.                 header_table[i].from, 
  2592.                 header_table[i].subject,
  2593.             header_table[i].lines,
  2594.             header_table[i].offset);
  2595.       i++;
  2596.     }
  2597.     
  2598.     Raw(ON);
  2599.  
  2600.     PutLine(LINES,0,"Press any key to return: ");
  2601.     (void) ReadCh();
  2602. }
  2603.  
  2604.  
  2605. debug_message()
  2606. {
  2607.     /**** Spit out the current message record.  Include EVERYTHING
  2608.           in the record structure. **/
  2609.  
  2610.     ClearScreen();
  2611.     Raw(OFF);
  2612.  
  2613.     printf("\t\t\t----- Message %d -----\n\n\n\n", 
  2614.         current);
  2615.  
  2616.     printf("Lines : %-5d\t\t\t\tPriority message? %s\n\n",
  2617.         header_table[current-1].lines, 
  2618.         header_table[current-1].priority? "YES" : "NO");
  2619.  
  2620.     printf("Offset: %ld\t\t\t\t  Delete message? %s\n\n\n",
  2621.         header_table[current-1].offset,
  2622.         header_table[current-1].delete? "YES" : "NO");
  2623.  
  2624.     printf("Received on: %d/%d/%d at %d:%02d\n\n",
  2625.             header_table[current-1].received.month+1,
  2626.             header_table[current-1].received.day,
  2627.             header_table[current-1].received.year,
  2628.             header_table[current-1].received.hour,
  2629.             header_table[current-1].received.minute);
  2630.  
  2631.     printf("Msg sent on: %s, %s %s, %s at %s\n\n",
  2632.             header_table[current-1].dayname,
  2633.             header_table[current-1].month,
  2634.             header_table[current-1].day,
  2635.             header_table[current-1].year,
  2636.             header_table[current-1].time);
  2637.     
  2638.     printf("\nFrom: %s\n\nSubject: %s",
  2639.         header_table[current-1].from,
  2640.             header_table[current-1].subject);
  2641.     
  2642.     Raw(ON);
  2643.  
  2644.     PutLine(LINES,0,"Press any key to return: ");
  2645.     (void) ReadCh();
  2646. }
  2647. END-OF-FILE
  2648.  
  2649. size=`wc -c < src/msg.c`
  2650.  
  2651. if [ $size != 12135 ]
  2652. then
  2653.   echo Warning: src/msg.c changed - should be 12135 bytes, not $size bytes
  2654. fi
  2655.  
  2656. chmod 644 src/msg.c
  2657.  
  2658. echo done
  2659.  
  2660. exit 0
  2661.  
  2662.  
  2663.  
  2664.  
  2665.