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

  1. From: decvax!hplabs!hpcnou!dat (Dave Taylor)
  2. Subject: Msg Shar.part.7
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 4, Issue 11
  7. Submitted by: decvax!hplabs!hpcnou!dat (Dave Taylor)
  8.  
  9. # Msg Shar part 7 of 7
  10.  
  11. # Shell Archive created by hpcnou!dat at Wed Feb 26 15:57:03 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. #  utils/cutfile.c  utils/fastmail.c    utils/from.c        utils/newalias.c
  19. #  utils/newmail.c  utils/printmail.c   utils/readmsg.c     utils/Makefile
  20. #  test/test.mail   test/test.notes
  21.  
  22.  
  23. if [ ! -d utils ]
  24. then
  25.   echo creating directory utils
  26.   mkdir utils
  27. fi
  28.  
  29. # ---------- file utils/cutfile.c ----------
  30.  
  31.  
  32. if [ -f utils/cutfile.c ]
  33. then
  34.   echo File 'utils/cutfile.c' already exists\!
  35.   exit 1
  36. fi
  37.  
  38. echo extracting file utils/cutfile.c...
  39. cat << 'END-OF-FILE' > utils/cutfile.c
  40. /**            cutfile.c        **/
  41.  
  42. /** This program is written for the MSG mail system (and other programs
  43.     that could use it's functionality, of course!) for the express purpose
  44.     of allowing a message out of a file of messages to be QUICKLY extracted
  45.     into another file.
  46.  
  47.     Usage: cutfile <filename> <offset-into-file> <number-of-lines> <dest-file>
  48.  
  49.     It is fed to standard output if dest-file = "-".
  50.  
  51.     (C) Copyright 1986 Dave Taylor
  52. **/
  53.  
  54. #include <stdio.h>
  55. #include <errno.h>
  56.  
  57. #define  SLEN        256        /* string length */
  58.  
  59. extern int errno;            /* system errno  */
  60.  
  61. main(argc, argv)
  62. int argc;
  63. char *argv[];
  64. {
  65.     FILE  *infile, *outfile;
  66.     char   buffer[SLEN];
  67.     register lines;
  68.  
  69.     if (argc != 5)
  70.       exit (fprintf(stderr, "Usage: %s <filename> <offset> <lines> <dest-file>\n",
  71.             argv[0]));
  72.  
  73.     if ((infile = fopen(argv[1], "r")) == NULL) 
  74.       exit (fprintf(stderr, "%s cannot open file %s for reading!\n",
  75.         argv[0], argv[1]));
  76.  
  77.     if (argv[4][0] == '-')
  78.        outfile = stdout;
  79.     else
  80.       if ((outfile = fopen(argv[4], "w")) == NULL)
  81.         exit (fprintf(stderr, "%s cannot open file %s for writing!\n",
  82.         argv[0], argv[1]));
  83.  
  84.     if (fseek(infile, atoi(argv[2]), 0L) == -1)
  85.         exit (fprintf(stderr, "%s encountered error %d trying to fseek to %ld\n",
  86.           argv[0], errno, argv[2]));
  87.  
  88.     lines = atoi(argv[3]);
  89.  
  90.     while (fgets(buffer, SLEN, infile) != NULL) {
  91.       fputs(buffer, outfile);
  92.       if (--lines == 0)
  93.         exit(0);
  94.     }
  95.  
  96.     exit(1);    /* 1 indicates read past EOF */
  97. }
  98. END-OF-FILE
  99.  
  100. size=`wc -c < utils/cutfile.c`
  101.  
  102. if [ $size != 1454 ]
  103. then
  104.   echo Warning: utils/cutfile.c changed - should be 1454 bytes, not $size bytes
  105. fi
  106.  
  107. chmod 644 utils/cutfile.c
  108.  
  109. # ---------- file utils/fastmail.c ----------
  110.  
  111.  
  112. if [ -f utils/fastmail.c ]
  113. then
  114.   echo File 'utils/fastmail.c' already exists\!
  115.   exit 1
  116. fi
  117.  
  118. echo extracting file utils/fastmail.c...
  119. cat << 'END-OF-FILE' > utils/fastmail.c
  120. /**            fastmail.c            **/
  121.  
  122. /** This program is specifically written for group mailing lists and
  123.     such batch type mail processing.  It does NOT use aliases at all,
  124.     it does NOT read the /etc/password file to find the From: name
  125.     of the user and does NOT expand any addresses.  It is meant 
  126.     purely as a front-end for either /bin/mail or /usr/lib/sendmail
  127.     (according to what is available on the current system).
  128.  
  129.          **** This program should be used with CAUTION *****
  130.  
  131.     (C) Copyright 1985 Dave Taylor
  132. **/
  133.  
  134. /** The calling sequence for this program is:
  135.  
  136.     fastmail {-d} -f "from string" filename full-email-address 
  137.  
  138. **/
  139.  
  140. #include <stdio.h>
  141. #include <time.h>
  142.  
  143. #define  NLEN        40
  144. #define  SLEN        80
  145.  
  146. #define  READ_ACCESS    04
  147. #define  EXECUTE_ACCESS 01
  148.  
  149. #define  sendmail    "/usr/lib/sendmail"
  150. #define  binrmail    "/bin/rmail"
  151. #define  temphome    "/tmp/fastmail."
  152.  
  153. #define  VERSION     "1.1"
  154.  
  155. #define  usage()    fprintf(stderr, "Usage: fastmail {-d} %s %s\n", \
  156.                    "-f \"from string\" -s \"subject\"", \
  157.                    "filename full-email-address") 
  158.  
  159. #define DONE        0
  160. #define ERROR        -1
  161.  
  162. char *optional_arg;            /* optional argument as we go */
  163. int   opt_index;            /* argnum + 1 when we leave   */
  164.  
  165. char *arpa_dayname[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
  166.           "Fri", "Sat", "" };
  167.  
  168. char *arpa_monname[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  169.           "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""};
  170.  
  171. char *get_arpa_date();
  172.  
  173. main(argc, argv)
  174. int argc;
  175. char *argv[];
  176. {
  177.  
  178.     FILE *tempfile;
  179.     char hostname[NLEN], username[NLEN], from_string[SLEN], subject[SLEN];
  180.     char filename[SLEN], tempfilename[SLEN], command_buffer[256];
  181.     int  c, sendmail_available, debug = 0;
  182.  
  183.     while ((c = get_options(argc, argv, "df:s:")) > 0) {
  184.       switch (c) {
  185.         case 'd' : debug++;                    break;    
  186.         case 'f' : strcpy(from_string, optional_arg);    break;
  187.         case 's' : strcpy(subject, optional_arg);        break;
  188.        }
  189.     }    
  190.  
  191.     if (c == ERROR) exit(usage());
  192.  
  193.     if (opt_index > argc)
  194.       exit(usage());
  195.  
  196.     strcpy(filename, argv[opt_index++]);
  197.  
  198.     if (opt_index > argc)
  199.       exit(usage());
  200.  
  201.     gethostname(hostname, sizeof(hostname));
  202.     strcpy(username, getlogin());
  203.     if (strlen(username) == 0)
  204.       cuserid(username);
  205.  
  206.     if (access(filename, READ_ACCESS) == -1)
  207.       exit(fprintf(stderr, "Error: can't find file %s!\n", filename));
  208.  
  209.     sprintf(tempfilename, "%s%d", temphome, getpid());
  210.  
  211.     if ((tempfile = fopen(tempfilename, "w")) == NULL)
  212.       exit(fprintf(stderr, "Couldn't open temp file %s\n", tempfilename));
  213.  
  214.     if (strlen(from_string) > 0)
  215.       fprintf(tempfile, "From: %s!%s (%s)\n", 
  216.           hostname, username, from_string);
  217.     else
  218.       fprintf(tempfile, "From: %s!%s\n", hostname, username);
  219.  
  220.     fprintf(tempfile, "Date: %s\n", get_arpa_date());
  221.  
  222.     if (strlen(subject) > 0)
  223.       fprintf(tempfile, "Subject: %s\n", subject);
  224.  
  225.         fprintf(tempfile, "To: %s\n", argv[opt_index]);
  226.     fprintf(tempfile, "X-Mailer: fastmail [version %s]\n", VERSION);
  227.     fprintf(tempfile, "\n");
  228.  
  229.     fclose(tempfile);
  230.  
  231.     /** now we'll cat both files to /bin/rmail or sendmail... **/
  232.  
  233.     sendmail_available = (access(sendmail, EXECUTE_ACCESS) != -1);
  234.  
  235.     printf("Mailing to %s [via %s]\n", argv[opt_index],
  236.         sendmail_available? "sendmail" : "rmail");
  237.  
  238.     sprintf(command_buffer, "cat %s %s | %s '%s'", 
  239.         tempfilename, filename, 
  240.             sendmail_available? sendmail : binrmail, 
  241.         argv[opt_index]);
  242.  
  243.     if (debug)
  244.       printf("%s\n", command_buffer);
  245.  
  246.     system(command_buffer);
  247.  
  248.     unlink(tempfilename);
  249. }
  250.  
  251.  
  252. char *get_arpa_date()
  253. {
  254.     /** Returns an ARPA standard date.  The format for the date
  255.         according to DARPA document RFC-822 is exemplified by;
  256.  
  257.                      Mon, 12 Aug 85 6:29:08 MST
  258.     **/
  259.  
  260.     extern char *tzname[];
  261.     static char buffer[SLEN];    /* static character buffer       */
  262.     struct tm *the_time;        /* Time structure, see CTIME(3C) */
  263.     long       junk;        /* time in seconds....         */
  264.  
  265.     junk = time(0);    /* this must be here for it to work! */
  266.     the_time = (struct tm * ) localtime(&junk);
  267.  
  268.     sprintf(buffer, "%s, %d %s %d %d:%02d:%02d %s",
  269.       arpa_dayname[the_time->tm_wday],
  270.       the_time->tm_mday % 32,
  271.       arpa_monname[the_time->tm_mon],
  272.       the_time->tm_year % 100,
  273.       the_time->tm_hour % 24,
  274.       the_time->tm_min  % 61,
  275.       the_time->tm_sec  % 61,
  276.       tzname[the_time->tm_isdst]);
  277.     
  278.     return( (char *) buffer);
  279. }
  280.  
  281. /** Starting argument parsing routine.   
  282.  
  283.     Called as "get_options(argc, argv, options)" where options is a string
  284.     of the form "abc:d" indicating that 'a' 'b' and 'd' are flags and
  285.     'c' is a flag with a trailing argument.   Optional arguments are
  286.     returned in the external char * variable "optional_arg", and the
  287.     external int "opt_index" is set to the first entry in the argv list
  288.     that wasn't processed (ie after the flags). 
  289.  
  290.     For example, the C compiler would have something of the form 
  291.     getopt(argc, argv, "Oo:l:") to allow "cc -O -o output -l lib file.c"
  292.  
  293.     (C) Copyright 1986, Dave Taylor
  294. **/
  295.  
  296. int  _indx = 1, _argnum = 1;
  297.  
  298. int
  299. get_options(argc, argv, options)
  300. int argc;
  301. char *argv[], *options;
  302. {
  303.     /** Returns the character argument next, and optionally instantiates 
  304.         "argument" to the argument associated with the particular option 
  305.     **/
  306.     
  307.     char       *word, *strchr();
  308.  
  309.     if (_indx >= strlen(argv[_argnum])) {
  310.       _argnum++;
  311.       _indx = 1;        /* zeroeth char is '-' */
  312.     }
  313.  
  314.     if (_argnum >= argc) {
  315.       opt_index = argc;
  316.       return(DONE);
  317.     }
  318.     
  319.     if (argv[_argnum][0] != '-') {
  320.       opt_index = _argnum;
  321.       return(DONE);
  322.     }
  323.  
  324.         word = strchr(options, argv[_argnum][_indx++]);
  325.  
  326.     if (strlen(word) == 0) 
  327.       return(ERROR);
  328.     
  329.     if (word[1] == ':') {
  330.  
  331.       /** Two possibilities - either tailing end of this argument or the 
  332.           next argument in the list **/
  333.  
  334.       if (_indx < strlen(argv[_argnum])) { /* first possibility */
  335.         optional_arg = (char *) (argv[_argnum] + _indx);
  336.         _argnum++;
  337.         _indx = 1;
  338.       }
  339.       else {                /* second choice     */
  340.         if (++_argnum >= argc) 
  341.           return(ERROR);            /* no argument!!     */
  342.  
  343.         optional_arg = (char *) argv[_argnum++];
  344.         _indx = 1;
  345.       }
  346.     }
  347.  
  348.     return((int) word[0]);
  349. }
  350. END-OF-FILE
  351.  
  352. size=`wc -c < utils/fastmail.c`
  353.  
  354. if [ $size != 5979 ]
  355. then
  356.   echo Warning: utils/fastmail.c changed - should be 5979 bytes, not $size bytes
  357. fi
  358.  
  359. chmod 644 utils/fastmail.c
  360.  
  361. # ---------- file utils/from.c ----------
  362.  
  363.  
  364. if [ -f utils/from.c ]
  365. then
  366.   echo File 'utils/from.c' already exists\!
  367.   exit 1
  368. fi
  369.  
  370. echo extracting file utils/from.c...
  371. cat << 'END-OF-FILE' > utils/from.c
  372. /**        from.c        **/
  373.  
  374. /** print out whom each message is from in the pending mailbox
  375.     or specified one, including a subject line if available.. **/
  376.  
  377. /** (C) Copyright 1986 Dave Taylor **/
  378.  
  379. #include <stdio.h>
  380. #include "defs.h"
  381.  
  382. #define LINEFEED    (char) 10
  383.  
  384. FILE *mailfile;
  385.  
  386. main(argc, argv)
  387. int argc;
  388. char *argv[];
  389. {
  390.     char infile[LONG_SLEN], username[SLEN];
  391.  
  392.     if (argc > 2)
  393.       exit(printf("Usage: %s {filename}\n", argv[0]));
  394.  
  395.     if (argc == 2) 
  396.       strcpy(infile, argv[1]);
  397.     else {
  398.       strcpy(username, getlogin());
  399.       if (strlen(username) == 0)
  400.         cuserid(username);
  401.       sprintf(infile,"%s/%s",mailhome, username);
  402.     }
  403.  
  404.     if ((mailfile = fopen(infile,"r")) == NULL)
  405.       printf("%s\n", argc==1?"No mail!":"Could not open file!");
  406.     else
  407.       if (read_headers()==0)
  408.         printf("No messages in mailbox!\n");
  409. }
  410.  
  411. int
  412. read_headers()
  413. {
  414.     /** read the headers, output as found **/
  415.  
  416.     char buffer[LONG_SLEN], from_whom[SLEN], subject[SLEN];
  417.     register int subj = 0, in_header = 1, count = 0;
  418.  
  419.     while (fgets(buffer, LONG_SLEN, mailfile) != NULL) {
  420.       if (first_word(buffer,"From ")) {
  421.         if (real_from(buffer, from_whom)) {
  422.           subj = 0;
  423.           in_header = 1;
  424.         }
  425.       }
  426.       else if (in_header) {
  427.         if (first_word(buffer,">From")) 
  428.           forwarded(buffer, from_whom); /* return address */
  429.         else if (first_word(buffer,"Subject:") ||
  430.              first_word(buffer,"Re:")) {
  431.           if (! subj++) {
  432.             remove_first_word(buffer);
  433.         strcpy(subject, buffer);
  434.           }
  435.         }
  436.         else if (first_word(buffer,"From:")) 
  437.           parse_arpa_from(buffer, from_whom);
  438.         else if (buffer[0] == LINEFEED) {
  439.           in_header = 0;    /* in body of message! */
  440.           show_header(from_whom, subject);
  441.           from_whom[0] = 0;
  442.           subject[0] = 0;
  443.           count++;
  444.         }
  445.       }
  446.     }
  447.     return(count);
  448. }
  449.  
  450. int
  451. real_from(buffer, who)
  452. char *buffer, *who;
  453. {
  454.     /***** returns true iff 's' has the seven 'from' fields,
  455.            initializing the who to the sender *****/
  456.  
  457.     char junk[80];
  458.  
  459.     junk[0] = '\0';
  460.     sscanf(buffer, "%*s %s %*s %*s %*s %*s %s",
  461.                 who, junk);
  462.     return(junk[0] != '\0');
  463. }
  464.  
  465. forwarded(buffer, who)
  466. char *buffer, *who;
  467. {
  468.     /** change 'from' and date fields to reflect the ORIGINATOR of 
  469.         the message by iteratively parsing the >From fields... **/
  470.  
  471.     char machine[80], buff[80];
  472.  
  473.     machine[0] = '\0';
  474.     sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s",
  475.                 who, machine);
  476.  
  477.     if (machine[0] == '\0') /* try for srm address */
  478.       sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s",
  479.                 who, machine);
  480.  
  481.     if (machine[0] == '\0')
  482.       sprintf(buff,"anonymous");
  483.     else
  484.       sprintf(buff,"%s!%s", machine, who);
  485.  
  486.     strncpy(who, buff, 80);
  487. }
  488.  
  489.  
  490. remove_first_word(string)
  491. char *string;
  492. {    /** removes first word of string, ie up to first non-white space
  493.         following a white space! **/
  494.  
  495.     register int loc;
  496.  
  497.     for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) 
  498.         ;
  499.  
  500.     while (string[loc] == ' ' || string[loc] == '\t')
  501.       loc++;
  502.     
  503.     move_left(string, loc);
  504. }
  505.  
  506. move_left(string, chars)
  507. char string[];
  508. int  chars;
  509. {
  510.     /** moves string chars characters to the left DESTRUCTIVELY **/
  511.  
  512.     register int i;
  513.  
  514.     chars--; /* index starting at zero! */
  515.  
  516.     for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
  517.       string[i-chars] = string[i];
  518.  
  519.     string[i-chars] = '\0';
  520. }
  521.  
  522. show_header(from, subject)
  523. char *from, *subject;
  524. {
  525.     /** output header in clean format, including abbreviation
  526.         of return address if more than one machine name is
  527.         contained within it! **/
  528.     char buffer[SLEN];
  529.     int  loc, i=0, exc=0;
  530.  
  531.     loc = strlen(from);
  532.  
  533.     while (exc < 2 && loc > 0)
  534.       if (from[--loc] == '!')
  535.         exc++;
  536.  
  537.     if (exc == 2) { /* lots of machine names!  Get last one */
  538.       loc++;
  539.       while (loc < strlen(from) && loc < SLEN)
  540.         buffer[i++] = from[loc++];
  541.       buffer[i] = '\0';
  542.       printf("%-20s  %s\n", buffer, subject);
  543.     }
  544.     else
  545.       printf("%-20s  %s\n", from, subject);
  546. }    
  547.  
  548. parse_arpa_from(buffer, newfrom)
  549. char *buffer, *newfrom;
  550. {
  551.     /** try to parse the 'From:' line given... It can be in one of
  552.         two formats:
  553.         From: Dave Taylor <hpcnou!dat>
  554.         or  From: hpcnou!dat (Dave Taylor)
  555.         Change 'newfrom' ONLY if sucessfully parsed this entry and
  556.         the resulting name is non-null! 
  557.     **/
  558.  
  559.     char temp_buffer[SLEN], *temp;
  560.     register int i, j = 0;
  561.  
  562.     temp = (char *) temp_buffer;
  563.     temp[0] = '\0';
  564.  
  565.     no_ret(buffer);        /* blow away '\n' char! */
  566.  
  567.     if (lastch(buffer) == '>') {
  568.       for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' &&
  569.            buffer[i] != '('; i++)
  570.         temp[j++] = buffer[i];
  571.       temp[j] = '\0';
  572.     }
  573.     else if (lastch(buffer) == ')') {
  574.       for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '(' &&
  575.            buffer[i] != '<'; i--)
  576.         temp[j++] = buffer[i];
  577.       temp[j] = '\0';
  578.       reverse(temp);
  579.     }
  580.       
  581.     if (strlen(temp) > 0) {        /* mess with buffer... */
  582.  
  583.       /* remove leading spaces... */
  584.  
  585.       while (whitespace(temp[0]))
  586.         temp = (char *) (temp + 1);        /* increment address! */
  587.  
  588.       /* remove trailing spaces... */
  589.  
  590.       i = strlen(temp) - 1;
  591.  
  592.       while (whitespace(temp[i]))
  593.        temp[i--] = '\0';
  594.  
  595.       /* if anything is left, let's change 'from' value! */
  596.  
  597.       if (strlen(temp) > 0)
  598.         strcpy(newfrom, temp);
  599.     }
  600. }
  601.  
  602. reverse(string)
  603. char *string;
  604. {
  605.     /** reverse string... pretty trivial routine, actually! **/
  606.  
  607.     char buffer[SLEN];
  608.     register int i, j = 0;
  609.  
  610.     for (i = strlen(string)-1; i >= 0; i--)
  611.       buffer[j++] = string[i];
  612.  
  613.     buffer[j] = '\0';
  614.  
  615.     strcpy(string, buffer);
  616. }
  617. END-OF-FILE
  618.  
  619. size=`wc -c < utils/from.c`
  620.  
  621. if [ $size != 5388 ]
  622. then
  623.   echo Warning: utils/from.c changed - should be 5388 bytes, not $size bytes
  624. fi
  625.  
  626. chmod 644 utils/from.c
  627.  
  628. # ---------- file utils/newalias.c ----------
  629.  
  630.  
  631. if [ -f utils/newalias.c ]
  632. then
  633.   echo File 'utils/newalias.c' already exists\!
  634.   exit 1
  635. fi
  636.  
  637. echo extracting file utils/newalias.c...
  638. cat << 'END-OF-FILE' > utils/newalias.c
  639. /**        newalias.c        **/
  640.  
  641. /** (C) Copyright 1986 Dave Taylor      **/
  642.  
  643. /** Install a new set of aliases for the 'Msg' mailer. 
  644.  
  645.     If invoked with a specific filename, it assumes that
  646.   it is working with an individual users alias tables, and
  647.   generates the .alias.hash and .alias.data files in their
  648.   home directory.
  649.     If, however, it is invoked with no arguments, then
  650.   it assumes that the user is updating the system alias
  651.   file and uses the defaults for everything.
  652.  
  653.   The format for the input file is;
  654.     alias1, alias2, ... : username : address
  655. or  alias1, alias2, ... : groupname: member, member, member, ...
  656.                                      member, member, member, ...
  657. **/
  658.  
  659. #include <fcntl.h>
  660. #include <stdio.h>
  661. #include "defs.h"        /* MSG system definitions */
  662.  
  663. #ifndef TAB
  664. # define TAB         '\t'    /* TAB character!         */
  665. #endif
  666.     
  667. #define alias_hash    ".alias_hash"
  668. #define alias_data    ".alias_data"
  669. #define alias_text    ".alias_text"
  670.  
  671. #define group(string)        (strpbrk(string,", ") != NULL)
  672.  
  673. struct alias_rec
  674. shash_table[MAX_SALIASES];    /* the actual hash table     */
  675.  
  676. struct alias_rec
  677. uhash_table[MAX_UALIASES];    /* the actual hash table     */
  678.  
  679. int  hash_table_loaded=0;    /* is system table actually loaded? */
  680.  
  681. int  buff_loaded;        /* for file input overlap... */
  682. int  error= 0;            /* if errors, don't save!    */
  683. int  system=0;            /* system file updating?     */
  684. int  count=0;            /* how many aliases so far?  */
  685. long offset = 0L;        /* data file line offset!    */
  686.  
  687. main(argc, argv)
  688. int argc;
  689. char *argv[];
  690. {
  691.     FILE *in, *data;
  692.     char inputname[SLEN], hashname[SLEN], dataname[SLEN];
  693.     char home[SLEN], buffer[LONG_STRING];
  694.     int  hash, count = 0, owner;
  695.  
  696.     if (argc != 1)
  697.       exit(printf("Usage: %s\n", argv[0]));
  698.  
  699.     owner = getuid();
  700.  
  701.     if (owner == 0) {    /* being run by root! */
  702.       printf("Would you like to update the system aliases? (y/n)");
  703.       gets(buffer, 2);
  704.       if (buffer[0] == 'y' || buffer[0] == 'Y') {
  705.         printf("Updating the system alias file...\n");
  706.  
  707.         sprintf(inputname, "%s/%s", mailhome, alias_text);
  708.         sprintf(hashname, "%s/%s", mailhome, alias_hash);
  709.         sprintf(dataname, "%s/%s", mailhome, alias_data);
  710.         system++;
  711.         init_table(shash_table, MAX_SALIASES); 
  712.       }
  713.       else 
  714.         printf("Updating your personal alias file...\n");
  715.     }
  716.     
  717.     if (! system) {
  718.       if (strcpy(home, getenv("HOME")) == NULL)
  719.         exit(printf("Confused: No HOME variable in environment!\n"));
  720.  
  721.       sprintf(inputname, "%s/%s", home, alias_text);
  722.       sprintf(hashname,  "%s/%s", home, alias_hash); 
  723.       sprintf(dataname,  "%s/%s", home, alias_data); 
  724.  
  725.       init_table(uhash_table, MAX_UALIASES); 
  726.  
  727.       read_in_system(shash_table, sizeof shash_table);
  728.     }
  729.  
  730.     if ((in = fopen(inputname,"r")) == NULL)
  731.       exit(printf("Couldn't open %s for input!\n", inputname));
  732.  
  733.     if ((hash = open(hashname, O_WRONLY | O_CREAT, 0644)) == -1)
  734.       exit(printf("Couldn't open %s for output!\n", hashname));
  735.  
  736.     if ((data = fopen(dataname,"w")) == NULL)
  737.       exit(printf("Couldn't open %s for output!\n", dataname));
  738.  
  739.     buff_loaded = 0;     /* file buffer empty right now! */
  740.  
  741.     while (get_alias(in, buffer) != -1) {
  742.       if (system)
  743.         put_alias(data, buffer, shash_table, MAX_SALIASES);    
  744.       else
  745.         put_alias(data, buffer, uhash_table, MAX_UALIASES);    
  746.       count++;
  747.     }
  748.  
  749.     if (error) {
  750.       printf("\n** Not saving tables!  Please fix and re-run %s!\n",
  751.          argv[0]);
  752.       exit(1);
  753.     }
  754.     else {
  755.       if (system)
  756.         write(hash, shash_table, sizeof shash_table);
  757.       else
  758.         write(hash, uhash_table, sizeof uhash_table);
  759.  
  760.       close(hash);
  761.       fclose(data);
  762.       close(in);
  763.     
  764.       printf("Processed %d aliases\n", count);
  765.       exit(0);
  766.     }
  767. }
  768.  
  769. int
  770. get_alias(file, buffer)
  771. FILE *file;
  772. char *buffer;
  773. {
  774.     /* load buffer with the next complete alias from the file.
  775.        (this can include reading in multiple lines and appending
  776.        them all together!)  Returns EOF after last entry in file.
  777.     
  778.     Lines that start with '#' are assumed to be comments and are
  779.      ignored.  White space as the first field of a line is taken
  780.     to indicate that this line is a continuation of the previous. */
  781.  
  782.     static char mybuffer[SLEN];
  783.     int    done = 0, first_read = 1;
  784.  
  785.     /** get the first line of the entry... **/
  786.  
  787.     do {
  788.       if (get_line(file, mybuffer, first_read) == -1) 
  789.         return(-1);
  790.       first_read = 0;
  791.       if (mybuffer[0] != '#')
  792.         strcpy(buffer, mybuffer);
  793.     } while (strlen(buffer) == 0);    
  794.  
  795.     /** now read in the rest (if there is any!) **/
  796.  
  797.     do {
  798.       if (get_line(file, mybuffer, first_read) == -1) {
  799.         buff_loaded = 0;    /* force a read next pass! */
  800.         return(0);    /* okay. let's just hand 'buffer' back! */
  801.       }
  802.       done = (mybuffer[0] != ' ' && mybuffer[0] != TAB);
  803.       if (mybuffer[0] != '#' && ! done)
  804.         strcat(buffer, mybuffer);
  805.       done = (done && mybuffer[0] != '#');
  806.     } while (! done);
  807.     
  808.     return(0);    /* no sweat! */
  809. }
  810.  
  811. put_alias(data, buffer, table, size)
  812. FILE *data;
  813. char *buffer;
  814. struct alias_rec table[];
  815. int  size;
  816. {
  817.     /** break buffer down into two pieces: aliases, and address,
  818.         throwing away the username (comment) field. 
  819.         Make the appropriate entries in the table (size) **/
  820.  
  821.     char aliases[LONG_STRING], address[LONG_STRING];
  822.     int  i = 0, j = 0;
  823.  
  824.     remove_all(' ', TAB, buffer);
  825.  
  826.     for (i=0; buffer[i] != ':' && i < LONG_STRING; i++)
  827.       aliases[i] = buffer[i];
  828.     aliases[i] = '\0';
  829.  
  830.     for (i=strlen(buffer)-1; buffer[i] != ':' && i > 0; i--)
  831.       address[j++] = buffer[i];
  832.     address[j] = '\0';
  833.  
  834.     reverse(address);
  835.  
  836.     add_to_table(data, aliases, address, table, size);
  837. }
  838.  
  839. int
  840. get_line(file, buffer, first_line)
  841. FILE *file;
  842. char *buffer;
  843. int  first_line;
  844. {
  845.     /** read line from file.  If first_line and buff_loaded, 
  846.         then just return! **/
  847.     int stat;
  848.  
  849.     if (first_line && buff_loaded) {
  850.       buff_loaded = 1;
  851.       return;
  852.     }
  853.  
  854.     buff_loaded = 1;    /* we're going to get SOMETHING in the buffer */
  855.  
  856.     stat = fgets(buffer, SLEN, file) == NULL ? -1 : 0;
  857.  
  858.     if (stat != -1)
  859.       no_ret(buffer);
  860.  
  861.     return(stat);
  862. }
  863.  
  864. reverse(string)
  865. char *string;
  866. {
  867.     /** reverse the order of the characters in string... 
  868.         uses a bubble-sort type of algorithm!                 **/
  869.     
  870.     register int f, l;
  871.     char     c;
  872.     
  873.     f = 0;
  874.     l = strlen(string) - 1;
  875.     
  876.     while (f < l) {
  877.       c = string[f];
  878.        string[f] = string[l];
  879.       string[l] = c;
  880.       f++;
  881.       l--;
  882.     }
  883. }
  884.  
  885. add_to_table(data, aliases, address, table, size)
  886. FILE *data;
  887. char *aliases, *address;
  888. struct alias_rec table[];
  889. int  size;
  890. {
  891.     /** add address to datafile, incrementing offset count (bytes),
  892.         then for each alias in the aliases string, add to the
  893.         hash table, with the associated pointer value! **/
  894.  
  895.     static char buf[SLEN], *word;
  896.     long additive = 1L;
  897.  
  898.     word = buf;    /* use the allocated space! */
  899.  
  900.     if (group(address)) {
  901.       check_group(address, aliases);
  902.       if (error) return;    /* don't do work if we aren't to save it! */
  903.       fprintf(data, "!%s\n", address);
  904.       additive = 2L;
  905.     }
  906.     else {
  907.       if (error) return;    /* don't do work if we aren't to save it! */
  908.       fprintf(data, "%s\n", address);
  909.     }
  910.  
  911.     while ((word = (char *) strtok(aliases,", ")) != NULL) {
  912.       add_to_hash_table(word, offset, table, size);
  913.       aliases = NULL;    /* let's get ALL entries via 'strtok' */
  914.       count++;
  915.     }
  916.  
  917.     if ((system && count > MAX_SALIASES-35) || count > MAX_UALIASES-21) {
  918.       printf("** Too many aliases in file! **\n");
  919.       error++;
  920.     }
  921.  
  922.     offset = (offset + (long) strlen(address) + additive);
  923. }    
  924.  
  925. remove_all(c1, c2, string)
  926. char c1, c2, *string;
  927. {
  928.     /* remove all occurances of character 'c' from string. */
  929.     char buffer[LONG_STRING];
  930.     register int i = 0, j = 0;
  931.     
  932.     for (i = 0; string[i] != '\0' && i < LONG_STRING; i++)
  933.       if (string[i] != c1 && string[i] != c2)
  934.         buffer[j++] = string[i];
  935.  
  936.     buffer[j] = '\0';
  937.     strcpy(string, buffer);
  938. }
  939.  
  940. add_to_hash_table(word, offset, table, size)
  941. char *word;
  942. long  offset;
  943. struct alias_rec table[];
  944. int   size;
  945. {
  946.     /** add word and offset to current hash table. **/
  947.     register int loc;
  948.     
  949.     if (strlen(word) > 20)
  950.       exit(printf("Bad alias name: %s.  Too long.\n", word));
  951.  
  952.     loc = hash_it(word, size);
  953.  
  954.     while (table[loc].name[0] != '\0' && strcmp(table[loc].name, word) != 0)
  955.       loc = loc + 1 % size; 
  956.  
  957.     if (table[loc].name[0] == '\0') {
  958.       strcpy(table[loc].name, word);
  959.       table[loc].byte = offset;
  960.     }
  961.     else 
  962.       printf("** Duplicate alias '%s' in file.  Multiples ignored.\n",
  963.              word);
  964. }
  965.  
  966. int
  967. hash_it(string, table_size)
  968. char *string;
  969. {
  970.     /** compute the hash function of the string, returning
  971.         it (mod table_size) **/
  972.  
  973.     register int i, sum = 0;
  974.     
  975.     for (i=0; string[i] != '\0'; i++)
  976.       sum += (int) string[i];
  977.  
  978.     return(sum % table_size);
  979. }
  980.  
  981. init_table(table, size)
  982. struct alias_rec table[];
  983. int size;
  984. {
  985.     /** initialize hash table! **/
  986.  
  987.     register int i;
  988.  
  989.     for (i=0; i < size; i++)
  990.       table[i].name[0] = '\0';
  991. }
  992.  
  993. read_in_system(table, size)
  994. struct alias_rec table[];
  995. int size;
  996. {
  997.     /** read in the system hash table...to check for group aliases
  998.         from the user alias file (to ensure that there are no names
  999.         in the user group files that are not purely contained within
  1000.         either alias table) **/
  1001.     
  1002.     int  fd;
  1003.     char fname[SLEN];
  1004.  
  1005.     sprintf(fname, "%s/%s", mailhome, alias_hash);
  1006.  
  1007.     if ((fd = open(fname, O_RDONLY)) == -1)
  1008.       return;    /* no sweat: flag 'hash_table_loaded' not set! */
  1009.  
  1010.     (void) read(fd, table, size);
  1011.     close(fd);
  1012.     hash_table_loaded++;
  1013. }
  1014.     
  1015. check_group(names, groupname)
  1016. char *names, *groupname;
  1017. {
  1018.     /** one by one make sure each name in the group is defined
  1019.         in either the system alias file or the user alias file.
  1020.         This search is linearly dependent, so all group aliases
  1021.         in the source file should appear LAST, after all the user
  1022.         aliases! **/
  1023.  
  1024.     char *word, *bufptr, buffer[LONG_STRING];
  1025.  
  1026.     strcpy(buffer, names);
  1027.     bufptr = (char *) buffer;
  1028.  
  1029.     while ((word = (char *) strtok(bufptr,", ")) != NULL) {
  1030.       if (! can_find(word)) 
  1031.         if (! valid_name(word)) {
  1032.           error++;
  1033.           printf("** Alias %s in group %s is bad!\n", word, groupname);
  1034.         }
  1035.       bufptr = NULL;
  1036.     }
  1037. }
  1038.  
  1039. int
  1040. can_find(name)
  1041. char *name;
  1042. {    
  1043.     /** find name in either hash table...use 'system' variable to
  1044.         determine if we should look in both or just system....    **/
  1045.  
  1046.     register int loc;
  1047.     
  1048.     if (strlen(name) > 20) {
  1049.       error++;
  1050.       printf("** Bad alias name: %s.  Too long.\n", name);
  1051.       return(1);    /* fake out: don't want 2 error messages! */
  1052.     }
  1053.  
  1054.     /** system alias table... **/
  1055.     if (hash_table_loaded || system) {
  1056.       loc = hash_it(name, MAX_SALIASES);
  1057.  
  1058.       while (strcmp(name, shash_table[loc].name) != 0 && 
  1059.                  shash_table[loc].name[0] != '\0')
  1060.         loc = (loc + 1) % MAX_SALIASES; 
  1061.   
  1062.       if (strcmp(name, shash_table[loc].name) == 0)
  1063.         return(1);    /* found it! */
  1064.     }
  1065.  
  1066.     if (! system) {    /* okay! Let's check the user alias file! */
  1067.       loc = hash_it(name, MAX_UALIASES);
  1068.  
  1069.       while (strcmp(name, uhash_table[loc].name) != 0 && 
  1070.                  uhash_table[loc].name[0] != '\0')
  1071.         loc = (loc + 1) % MAX_UALIASES; 
  1072.  
  1073.       if (strcmp(name, uhash_table[loc].name) == 0)
  1074.         return(1);    /* found it! */
  1075.     }
  1076.  
  1077.     return(0);
  1078. }
  1079. END-OF-FILE
  1080.  
  1081. size=`wc -c < utils/newalias.c`
  1082.  
  1083. if [ $size != 10812 ]
  1084. then
  1085.   echo Warning: utils/newalias.c changed - should be 10812 bytes, not $size bytes
  1086. fi
  1087.  
  1088. chmod 644 utils/newalias.c
  1089.  
  1090. # ---------- file utils/newmail.c ----------
  1091.  
  1092.  
  1093. if [ -f utils/newmail.c ]
  1094. then
  1095.   echo File 'utils/newmail.c' already exists\!
  1096.   exit 1
  1097. fi
  1098.  
  1099. echo extracting file utils/newmail.c...
  1100. cat << 'END-OF-FILE' > utils/newmail.c
  1101. /**            newmail.c            **/
  1102.  
  1103. /** Keep track of the mail for the current user...if new mail
  1104.     arrives, output a line of the form;
  1105.  
  1106.        Mail has arrived from <name> - <subject>
  1107.  
  1108.     where <name> is either the persons full name, or machine!login.
  1109.     If there is no subject, it will say.
  1110.  
  1111.     This program also tries to keep track of if the user is still
  1112.     logged in - if they log out it will quit execution.
  1113.  
  1114.     (C) 1986, Dave Taylor
  1115. **/
  1116.  
  1117. #include <stdio.h>
  1118. #include <sys/types.h>
  1119. #include <sys/stat.h>
  1120.  
  1121. #include "defs.h"
  1122.  
  1123. #define LINEFEED    (char) 10
  1124. #define BEGINNING    0            /* seek fseek(3S) */
  1125. #define SLEEP_TIME    60        
  1126.  
  1127. #define NO_SUBJECT    "<no subject>"
  1128.  
  1129. FILE *mailfile;
  1130.  
  1131. long  bytes();
  1132.  
  1133. main(argc, argv)
  1134. int argc;
  1135. char *argv[];
  1136. {
  1137.     char filename[LONG_SLEN];
  1138.     long size, newsize;
  1139.  
  1140.     sprintf(filename,"%s/%s",mailhome, getlogin());
  1141.  
  1142.     size = bytes(filename);
  1143.  
  1144.     mailfile = (FILE *) NULL;
  1145.  
  1146.     while (1) {
  1147.     
  1148.       if (getppid() == 1)     /* we've lost our shell! */
  1149.         exit();
  1150.     
  1151.       if (mailfile == (FILE *) NULL) 
  1152.         mailfile = fopen(filename,"r");
  1153.  
  1154.       if ((newsize = bytes(filename)) > size) {    /* new mail */
  1155.         fseek(mailfile, size, BEGINNING); /* skip all current mail */
  1156.         size = newsize;
  1157.         printf("\n\r");    /* blank lines surrounding message */
  1158.         read_headers();
  1159.         printf("\n\r");
  1160.       }
  1161.       else if (newsize != size) {
  1162.         size = newsize;         /* mail's been removed... */
  1163.         mailfile = (FILE *) NULL;    /* let's reopen the file */
  1164.       }
  1165.  
  1166.       sleep(SLEEP_TIME);
  1167.     }
  1168. }
  1169.  
  1170. int
  1171. read_headers()
  1172. {
  1173.     /** read the headers, output as found **/
  1174.  
  1175.     char buffer[LONG_SLEN], from_whom[SLEN], subject[SLEN];
  1176.     register int subj = 0, in_header = 1, count = 0;
  1177.  
  1178.     while (fgets(buffer, LONG_SLEN, mailfile) != NULL) {
  1179.       if (first_word(buffer,"From ")) {
  1180.         if (real_from(buffer, from_whom)) {
  1181.           subj = 0;
  1182.           in_header = 1;
  1183.         }
  1184.       }
  1185.       else if (in_header) {
  1186.         if (first_word(buffer,">From")) 
  1187.           forwarded(buffer, from_whom); /* return address */
  1188.         else if (first_word(buffer,"Subject:") ||
  1189.              first_word(buffer,"Re:")) {
  1190.           if (! subj++) {
  1191.             remove_first_word(buffer);
  1192.         strcpy(subject, buffer);
  1193.           }
  1194.         }
  1195.         else if (first_word(buffer,"From:")) 
  1196.           parse_arpa_from(buffer, from_whom);
  1197.         else if (buffer[0] == LINEFEED) {
  1198.           in_header = 0;    /* in body of message! */
  1199.           show_header(from_whom, subject);
  1200.           from_whom[0] = 0;
  1201.           subject[0] = 0;
  1202.           count++;
  1203.         }
  1204.       }
  1205.     }
  1206.     return(count);
  1207. }
  1208.  
  1209. int
  1210. real_from(buffer, who)
  1211. char *buffer, *who;
  1212. {
  1213.     /***** returns true iff 's' has the seven 'from' fields,
  1214.            initializing the who to the sender *****/
  1215.  
  1216.     char junk[80];
  1217.  
  1218.     junk[0] = '\0';
  1219.     sscanf(buffer, "%*s %s %*s %*s %*s %*s %s",
  1220.                 who, junk);
  1221.     return(junk[0] != '\0');
  1222. }
  1223.  
  1224. forwarded(buffer, who)
  1225. char *buffer, *who;
  1226. {
  1227.     /** change 'from' and date fields to reflect the ORIGINATOR of 
  1228.         the message by iteratively parsing the >From fields... **/
  1229.  
  1230.     char machine[80], buff[80];
  1231.  
  1232.     machine[0] = '\0';
  1233.     sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s",
  1234.                 who, machine);
  1235.  
  1236.     if (machine[0] == '\0') /* try for srm address */
  1237.       sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s",
  1238.                 who, machine);
  1239.  
  1240.     if (machine[0] == '\0')
  1241.       sprintf(buff,"anonymous");
  1242.     else
  1243.       sprintf(buff,"%s!%s", machine, who);
  1244.  
  1245.     strncpy(who, buff, 80);
  1246. }
  1247.  
  1248.  
  1249. remove_first_word(string)
  1250. char *string;
  1251. {    /** removes first word of string, ie up to first non-white space
  1252.         following a white space! **/
  1253.  
  1254.     register int loc;
  1255.  
  1256.     for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) 
  1257.         ;
  1258.  
  1259.     while (string[loc] == ' ' || string[loc] == '\t')
  1260.       loc++;
  1261.     
  1262.     move_left(string, loc);
  1263. }
  1264.  
  1265. move_left(string, chars)
  1266. char string[];
  1267. int  chars;
  1268. {
  1269.     /** moves string chars characters to the left DESTRUCTIVELY **/
  1270.  
  1271.     register int i;
  1272.  
  1273.     chars--; /* index starting at zero! */
  1274.  
  1275.     for (i=chars; string[i] != '\0' && string[i] != '\n'; i++)
  1276.       string[i-chars] = string[i];
  1277.  
  1278.     string[i-chars] = '\0';
  1279. }
  1280.  
  1281. show_header(from, subject)
  1282. char *from, *subject;
  1283. {
  1284.     /** output header in clean format, including abbreviation
  1285.         of return address if more than one machine name is
  1286.         contained within it! **/
  1287.     char buffer[SLEN];
  1288.     int  loc, i=0, exc=0;
  1289.  
  1290.     loc = strlen(from);
  1291.  
  1292.     while (exc < 2 && loc > 0)
  1293.       if (from[--loc] == '!')
  1294.         exc++;
  1295.  
  1296.     if (exc == 2) { /* lots of machine names!  Get last one */
  1297.       loc++;
  1298.       while (loc < strlen(from) && loc < SLEN)
  1299.         buffer[i++] = from[loc++];
  1300.       buffer[i] = '\0';
  1301.       strcpy(from, buffer);
  1302.     }
  1303.  
  1304.     if (strlen(subject) == 0)
  1305.       strcpy(subject, NO_SUBJECT);
  1306.     
  1307.     printf(">> New mail has arrived from %s - %s\n\r", from, subject);
  1308. }    
  1309.  
  1310. parse_arpa_from(buffer, newfrom)
  1311. char *buffer, *newfrom;
  1312. {
  1313.     /** try to parse the 'From:' line given... It can be in one of
  1314.         two formats:
  1315.         From: Dave Taylor <hpcnou!dat>
  1316.         or  From: hpcnou!dat (Dave Taylor)
  1317.         Change 'newfrom' ONLY if sucessfully parsed this entry and
  1318.         the resulting name is non-null! 
  1319.     **/
  1320.  
  1321.     char temp_buffer[SLEN], *temp;
  1322.     register int i, j = 0;
  1323.  
  1324.     temp = (char *) temp_buffer;
  1325.     temp[0] = '\0';
  1326.  
  1327.     no_ret(buffer);        /* blow away '\n' char! */
  1328.  
  1329.     if (lastch(buffer) == '>') {
  1330.       for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' &&
  1331.            buffer[i] != '('; i++)
  1332.         temp[j++] = buffer[i];
  1333.       temp[j] = '\0';
  1334.     }
  1335.     else if (lastch(buffer) == ')') {
  1336.       for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '(' &&
  1337.            buffer[i] != '<'; i--)
  1338.         temp[j++] = buffer[i];
  1339.       temp[j] = '\0';
  1340.       reverse(temp);
  1341.     }
  1342.       
  1343.     if (strlen(temp) > 0) {        /* mess with buffer... */
  1344.  
  1345.       /* remove leading spaces... */
  1346.  
  1347.       while (whitespace(temp[0]))
  1348.         temp = (char *) (temp + 1);        /* increment address! */
  1349.  
  1350.       /* remove trailing spaces... */
  1351.  
  1352.       i = strlen(temp) - 1;
  1353.  
  1354.       while (whitespace(temp[i]))
  1355.        temp[i--] = '\0';
  1356.  
  1357.       /* if anything is left, let's change 'from' value! */
  1358.  
  1359.       if (strlen(temp) > 0)
  1360.         strcpy(newfrom, temp);
  1361.     }
  1362. }
  1363.  
  1364. reverse(string)
  1365. char *string;
  1366. {
  1367.     /** reverse string... pretty trivial routine, actually! **/
  1368.  
  1369.     char buffer[SLEN];
  1370.     register int i, j = 0;
  1371.  
  1372.     for (i = strlen(string)-1; i >= 0; i--)
  1373.       buffer[j++] = string[i];
  1374.  
  1375.     buffer[j] = '\0';
  1376.  
  1377.     strcpy(string, buffer);
  1378. }
  1379.  
  1380. long
  1381. bytes(name)
  1382. char *name;
  1383. {
  1384.     /** return the number of bytes in the specified file.  This
  1385.         is to check to see if new mail has arrived....  **/
  1386.  
  1387.     int ok = 1;
  1388.     extern int errno;    /* system error number! */
  1389.     struct stat buffer;
  1390.  
  1391.     if (stat(name, &buffer) != 0)
  1392.       if (errno != 2)
  1393.        exit(fprintf(stderr,"Error %d attempting fstat on %s", errno, name));
  1394.       else
  1395.         ok = 0;
  1396.     
  1397.     return(ok ? buffer.st_size : 0);
  1398. }
  1399. END-OF-FILE
  1400.  
  1401. size=`wc -c < utils/newmail.c`
  1402.  
  1403. if [ $size != 6533 ]
  1404. then
  1405.   echo Warning: utils/newmail.c changed - should be 6533 bytes, not $size bytes
  1406. fi
  1407.  
  1408. chmod 644 utils/newmail.c
  1409.  
  1410. # ---------- file utils/printmail.c ----------
  1411.  
  1412.  
  1413. if [ -f utils/printmail.c ]
  1414. then
  1415.   echo File 'utils/printmail.c' already exists\!
  1416.   exit 1
  1417. fi
  1418.  
  1419. echo extracting file utils/printmail.c...
  1420. cat << 'END-OF-FILE' > utils/printmail.c
  1421. /**        printmail.c        **/
  1422.  
  1423. /** print mail, adding a formfeed between each message **/
  1424.  
  1425. /** (C) Copyright 1985, Dave Taylor **/
  1426.  
  1427. #include <stdio.h>
  1428.  
  1429. #define  first_word(s,w)  (strncmp(s,w,strlen(w)) == 0)
  1430. #define  mailhome      "/usr/mail"
  1431. #define  dashes          \
  1432. "\n\n------------------------------------------------------------------------------\n\n"
  1433. #define  FF            "\014"    /* form feed! */
  1434.  
  1435. FILE *mailfile;
  1436. char  separator[80];
  1437.  
  1438. main(argc, argv)
  1439. int argc;
  1440. char *argv[];
  1441. {
  1442.     char infile[80], username[40], c;
  1443.  
  1444.     strcpy(separator, FF);
  1445.  
  1446.     if (argc > 1) 
  1447.       if (strcmp(argv[1], "-d") == 0) {
  1448.         strcpy(separator, dashes);
  1449.         --argc;
  1450.         *argv++;
  1451.       }
  1452.     
  1453.     if (argc > 1)
  1454.       if (argv[1][0] == '-') 
  1455.         exit(fprintf(stderr, "Usage: %s {-d} {filename}\n", argv[0]));
  1456.     
  1457.     if (argc == 1) {
  1458.       strcpy(username, getlogin());
  1459.       if (strlen(username) == 0)
  1460.         cuserid(username);
  1461.       sprintf(infile,"%s/%s",mailhome, username);
  1462.       if ((mailfile = fopen(infile,"r")) == NULL)
  1463.         fprintf(stderr, "No mail!\n");
  1464.       else if (read_headers()==0)
  1465.           fprintf(stderr, "No messages in mailbox!\n");
  1466.     }
  1467.  
  1468.     while (--argc) {
  1469.       if ((mailfile = fopen(*argv,"r")) == NULL)
  1470.         fprintf(stderr, "Could not open file '%s'!", *argv);
  1471.       else
  1472.         if (read_headers()==0)
  1473.           fprintf(stderr, "No messages in mailbox '%s'!\n", *argv);
  1474.       *argv++;
  1475.       if (argc) {
  1476.         printf("%s", separator);
  1477.         printf("%s", separator);
  1478.       }
  1479.     }
  1480. }
  1481.  
  1482. int
  1483. read_headers()
  1484. {
  1485.     char buffer[100];
  1486.     register int count = 0;
  1487.  
  1488.     while (fgets(buffer, 100, mailfile) != NULL) 
  1489.       if (first_word(buffer,"From ")) {
  1490.         if (real_from(buffer)) {
  1491.           printf("%s%s", count ? separator : "", buffer);
  1492.           count++;
  1493.         }
  1494.       }
  1495.       else
  1496.         printf("%s", buffer);
  1497.  
  1498.     return(count);
  1499. }
  1500.  
  1501. int
  1502. real_from(buffer)
  1503. char *buffer;
  1504. {
  1505.     /***** returns true iff 's' has the seven 'from' fields *****/
  1506.  
  1507.     char junk[80];
  1508.  
  1509.     junk[0] = '\0';
  1510.     sscanf(buffer, "%*s %*s %*s %*s %*s %*s %s", junk);
  1511.     return(junk[0] != '\0');
  1512. }
  1513. END-OF-FILE
  1514.  
  1515. size=`wc -c < utils/printmail.c`
  1516.  
  1517. if [ $size != 1937 ]
  1518. then
  1519.   echo Warning: utils/printmail.c changed - should be 1937 bytes, not $size bytes
  1520. fi
  1521.  
  1522. chmod 644 utils/printmail.c
  1523.  
  1524. # ---------- file utils/readmsg.c ----------
  1525.  
  1526.  
  1527. if [ -f utils/readmsg.c ]
  1528. then
  1529.   echo File 'utils/readmsg.c' already exists\!
  1530.   exit 1
  1531. fi
  1532.  
  1533. echo extracting file utils/readmsg.c...
  1534. cat << 'END-OF-FILE' > utils/readmsg.c
  1535. /**            readmsg.c            **/
  1536.  
  1537. /** This is a quick and dirty way to read the specified message (or
  1538.     messages) from the incoming mailbox.  This does no parsing of the
  1539.     header fields other than to simply find where each message starts,
  1540.     and has no options other than to 'q' or '<return>' at then end of 
  1541.     each page of the message.
  1542.  
  1543.     (C) Copyright 1985, Dave Taylor
  1544.  
  1545. **/
  1546.  
  1547. #include <stdio.h>
  1548.  
  1549. #define  mailhome    "/usr/mail"
  1550. #define  SLEN        100
  1551. #define  MAX_LIST    25
  1552.  
  1553. main(argc, argv)
  1554. int argc;
  1555. char *argv[];
  1556. {
  1557.     FILE *file;
  1558.     int read_message[MAX_LIST], filename[SLEN], buffer[SLEN];
  1559.     int messages = 1, current_in_queue = 0, current = 0, num, total;
  1560.  
  1561.     if (argc > MAX_LIST) {
  1562.       printf("Can't have more than %d messages specified!\n", MAX_LIST);
  1563.       exit(1);
  1564.     }
  1565.  
  1566.     *argv++;
  1567.  
  1568.     if (argc == 1)
  1569.       read_message[0] = 0;
  1570.     else 
  1571.       while (--argc > 0) {
  1572.         num = -1;
  1573.         sscanf(*argv,"%d", &num);
  1574.         if (num < 0) {
  1575.           if (strcmp(*argv,"$") == 0)
  1576.             num = 0;
  1577.           else {
  1578.             printf("Can't figure out what '%s' means!\n", *argv);
  1579.         exit(1);
  1580.           }
  1581.         }
  1582.         *argv++; 
  1583.         read_message[messages++] = num;
  1584.       }
  1585.  
  1586.     sprintf(filename, "%s/%s", mailhome, getenv("LOGNAME"));
  1587.  
  1588.     if ((file = fopen(filename, "r")) == NULL) {
  1589.       printf("You have no mail!\n");
  1590.       exit(0);
  1591.     }
  1592.     else {
  1593.           /** one pass to get how many messages there are... **/
  1594.       total = count_messages(file);
  1595.       if (total == 0) {
  1596.         printf("There aren't any messages to read!\n");
  1597.         exit(0);
  1598.       }
  1599.       /** now let's have some fun! **/
  1600.       while (fgets(buffer, SLEN, file) != NULL) {
  1601.         if (strncmp(buffer, "From ", 5) == 0) {
  1602.           if (current == read_message[current_in_queue])
  1603.             current_in_queue++;
  1604.           if (current_in_queue >= messages) exit(0);
  1605.           current++;
  1606.         }
  1607.         if (current == read_message[current_in_queue]) 
  1608.           printf("%s", buffer);
  1609.         else if (current == total && read_message[current_in_queue] == 0)
  1610.           printf("%s", buffer);
  1611.       }
  1612.     }
  1613.     
  1614.     exit(0);
  1615. }
  1616.  
  1617. int
  1618. count_messages(file)
  1619. FILE *file;
  1620. {
  1621.     /** returns the number of messages in the file, and rewinds
  1622.         the file too! **/
  1623.  
  1624.     char buffer[SLEN];
  1625.     int  count = 0;
  1626.  
  1627.     while (fgets(buffer, SLEN, file) != NULL)
  1628.       if (strncmp(buffer, "From ", 5) == 0)
  1629.         count++;
  1630.  
  1631.     rewind(file);
  1632.  
  1633.     return( count );
  1634. }
  1635. END-OF-FILE
  1636.  
  1637. size=`wc -c < utils/readmsg.c`
  1638.  
  1639. if [ $size != 2263 ]
  1640. then
  1641.   echo Warning: utils/readmsg.c changed - should be 2263 bytes, not $size bytes
  1642. fi
  1643.  
  1644. chmod 644 utils/readmsg.c
  1645.  
  1646. # ---------- file utils/Makefile ----------
  1647.  
  1648.  
  1649. if [ -f utils/Makefile ]
  1650. then
  1651.   echo File 'utils/Makefile' already exists\!
  1652.   exit 1
  1653. fi
  1654.  
  1655. echo extracting file utils/Makefile...
  1656. cat << 'END-OF-FILE' > utils/Makefile
  1657. #
  1658. #  Makefile for the MSG system utilities
  1659. #
  1660. #         (C) Copyright 1986, Dave Taylor
  1661. #
  1662. #  Last modification: January 10th, 1986
  1663.  
  1664. CFLAGS= -O -I../hdrs
  1665. CC=    /bin/cc
  1666. RM=     /bin/rm
  1667. ECHO=  /bin/echo
  1668.  
  1669. all:    newalias from newmail answer printmail fastmail readmsg cutfile \
  1670.     checkalias arepdaemon autoreply
  1671.  
  1672. ../bin/newalias:  ../hdrs/defs.h newalias.c ../src/validname.o
  1673.     ${CC} ${CFLAGS} newalias.c ../src/validname.o -o ../bin/newalias 
  1674.  
  1675. ../src/validname.o: ../src/validname.c
  1676.     ${CC} -c ${CFLAGS} ../src/validnames.c -o ../src/validnames.o
  1677.  
  1678. ../bin/from: from.c
  1679.     ${CC} ${CFLAGS} from.c -o ../bin/from
  1680.  
  1681. ../bin/cutfile: cutfile.c
  1682.     ${CC} ${CFLAGS} cutfile.c -o ../bin/cutfile
  1683.  
  1684. ../bin/newmail: newmail.c
  1685.     ${CC} ${CFLAGS} newmail.c -o ../bin/newmail
  1686.  
  1687. ../bin/answer: answer.c
  1688.     ${CC} ${CFLAGS} answer.c -o ../bin/answer
  1689.  
  1690. ../bin/printmail: printmail.c
  1691.     ${CC} ${CFLAGS} printmail.c -o ../bin/printmail
  1692.  
  1693. ../bin/fastmail: fastmail.c
  1694.     ${CC} ${CFLAGS} fastmail.c -o ../bin/fastmail
  1695.  
  1696. ../bin/readmsg: readmsg.c
  1697.     ${CC} ${CFLAGS} readmsg.c -o ../bin/readmsg
  1698.  
  1699. ../bin/arepdaemon: arepdaemon.c
  1700.     ${CC} ${CFLAGS} arepdaemon.c -o ../bin/arepdaemon
  1701.  
  1702. ../bin/autoreply: autoreply.c
  1703.     ${CC} ${CFLAGS} autoreply.c -o ../bin/autoreply
  1704.  
  1705. ../bin/checkalias: 
  1706.     @echo 'msg -c $*' > ../bin/checkalias
  1707.     @chmod +x ../bin/checkalias
  1708.  
  1709. clean:
  1710.     ${RM} *.o
  1711.  
  1712. lint:
  1713.     lint -p -I../hdrs *.c > LINT.OUT
  1714.  
  1715. ## crap to allow "make msg" and so on...
  1716.  
  1717. newalias: ../bin/newalias
  1718. from: ../bin/from
  1719. newmail: ../bin/newmail
  1720. answer: ../bin/answer
  1721. printmail: ../bin/printmail
  1722. fastmail: ../bin/fastmail
  1723. readmsg: ../bin/readmsg
  1724. cutfile: ../bin/cutfile
  1725. checkalias: ../bin/checkalias
  1726. arepdaemon: ../bin/arepdaemon
  1727. autoreply: ../bin/autoreply
  1728. END-OF-FILE
  1729.  
  1730. size=`wc -c < utils/Makefile`
  1731.  
  1732. if [ $size != 1669 ]
  1733. then
  1734.   echo Warning: utils/Makefile changed - should be 1669 bytes, not $size bytes
  1735. fi
  1736.  
  1737. chmod 644 utils/Makefile
  1738.  
  1739. if [ ! -d test ]
  1740. then
  1741.   echo creating directory test
  1742.   mkdir test
  1743. fi
  1744.  
  1745. # ---------- file test/test.mail ----------
  1746.  
  1747.  
  1748. if [ -f test/test.mail ]
  1749. then
  1750.   echo File 'test/test.mail' already exists\!
  1751.   exit 1
  1752. fi
  1753.  
  1754. echo extracting file test/test.mail...
  1755. sed 's/^X//' << 'END-OF-FILE' > test/test.mail
  1756. XFrom root Wed Oct 30 14:03:36 1985
  1757. X>From srmmail Wed Oct 30 14:10:08 1985  remote from veeger
  1758. X>From hplabs Wed Oct 30 14:00:16 1985 remote from hpcnof
  1759. X>From hpl-opus!poulton  Wed Oct 30 02:06:16 1985 remote from hplabs
  1760. XDate: Wed, 30 Oct 85 01:55:05 pst
  1761. XFrom: <hplabs!hpl-opus!poulton>
  1762. XReceived: by HP-VENUS id AA26352; Wed, 30 Oct 85 01:55:05 pst
  1763. XMessage-Id: <8510300955.AA26352@HP-VENUS>
  1764. XTo: hpcnou!dat
  1765. XSubject: Re: announce(1)
  1766. X
  1767. XThe announce I got was shar'd July 8.   NLEN was not defined in that
  1768. Xsource, just used.  LONG_SLEN is not defined in the newmail(1)
  1769. Xthat you sent me.  What system are you running on?
  1770. XMy s500 doesn't have these def's.
  1771. X
  1772. XAs to announce --> newmail: why the switch?
  1773. XSeems like both are useful, in different situations.
  1774. X
  1775. XKen Poulton
  1776. XHPL
  1777. X
  1778. X
  1779. X
  1780. X
  1781. XFrom root Wed Oct 30 14:03:39 1985
  1782. X>From srmmail Wed Oct 30 14:10:12 1985  remote from veeger
  1783. X>From hplabs Wed Oct 30 13:59:53 1985 remote from hpcnof
  1784. X>From fowler  Wed Oct 30 12:57:11 1985 remote from hplabs
  1785. XDate: Wed, 30 Oct 85 12:57:11 pst
  1786. XFrom: Greg Fowler <hplabs!fowler>
  1787. XReceived: by HP-VENUS id AA12562; Wed, 30 Oct 85 12:57:11 pst
  1788. XMessage-Id: <8510302057.AA12562@HP-VENUS>
  1789. XTo: hpcnof!dat
  1790. XSubject: Re: Summary of Network Mail Headers
  1791. XReferences: <36700044@hpcnof.UUCP>
  1792. XPriority: Most Urgent
  1793. X
  1794. XI believe your introduction referred to the uucp network.  usenet is the networXk news
  1795. Xsoftware mechanism and isn't a "network".
  1796. X
  1797. X    Greg
  1798. X
  1799. X
  1800. X
  1801. XFrom root Wed Oct 30 14:13:23 1985
  1802. X>From srmmail Wed Oct 30 14:20:08 1985  remote from veeger
  1803. X>From root Wed Oct 30 14:01:57 1985 remote from hpcnof
  1804. XTo: root
  1805. XSubject: Log of backup tape #1
  1806. X
  1807. XFull Backup starting at Wed Oct 30 12:45:14 MST 1985
  1808. X
  1809. X
  1810. Xbacking up directories: 
  1811. X    ./users/fh ./users/rmd ./users/vince ./users/roberts ./users/row ./users/dt ./Xlost+found ./users/lost+found ./users/scb ./users/kevin ./users/du
  1812. X
  1813. X
  1814. X
  1815. X
  1816. X
  1817. XFrom root Wed Oct 30 15:33:24 1985
  1818. X>From srmmail Wed Oct 30 15:40:26 1985  remote from veeger
  1819. X>From root Wed Oct 30 15:37:17 1985 remote from hpcnof
  1820. XTo: root
  1821. XSubject: Log of backup tape #2
  1822. X
  1823. Xbacking up directories: 
  1824. X    ./users/fh ./users/rmd ./users/vince ./users/roberts ./users/row ./users/dt ./Xlost+found ./users/lost+found ./users/scb ./users/kevin ./users/du
  1825. X
  1826. X
  1827. X
  1828. X
  1829. Xbacking up directories: 
  1830. X    ./users/sbh ./users/ges ./users/cpb ./users/amy ./net ./users/root ./users/balXza ./dev ./users/remple ./users/jr ./users/mwr ./users/larryf
  1831. X
  1832. X
  1833. X
  1834. X
  1835. X
  1836. XFrom root Sun Dec  8 22:50:18 1985
  1837. X>From srmmail Mon Dec  9 00:50:05 1985 remote from veeger
  1838. X>From root Mon Dec  9 00:41:15 1985 remote from hpcnof
  1839. X>From JLarson.pa@Xerox.ARPA  Sun Dec  8 20:45:55 1985 remote from hplabs
  1840. XReceived: from Xerox.ARPA by hplabsd ; Sun, 8 Dec 85 20:45:55 pst
  1841. XReceived: from Cabernet.ms by ArpaGateway.ms ; 08 DEC 85 20:47:19 PST
  1842. XDate: 8 Dec 85 20:36:36 PST (Sunday)
  1843. XFrom: hplabs!JLarson.pa@Xerox.ARPA
  1844. XSubject: How's it going, anyway?
  1845. XTo: hpcnou!dat@HPLABS.ARPA (Dave Taylor)
  1846. XCc: JLarson.pa@Xerox.ARPA
  1847. XMessage-Id: <851208-204719-1063@Xerox>
  1848. X
  1849. XHow are things with you?  Could you send me that paper we were talking
  1850. Xabout?  
  1851. X
  1852. X    Thanks
  1853. X
  1854. XJohn Larson
  1855. XXerox Palo Alto Research Center
  1856. X3333 Coyote Hill Road
  1857. XPalo Alto, Ca  94304
  1858. X
  1859. X
  1860. X
  1861. X
  1862. XFrom root Wed Aug  7 19:58:30 1985
  1863. X>From uucp Wed Aug  7 19:55:12 1985  remote from veeger
  1864. X>From hplabs Wed Aug  7 19:48:10 1985 remote from hpcnof
  1865. X>From RICHER@SUMEX-AIM  Wed Aug  7 09:23:12 1985 remote from hplabs
  1866. XReceived: by HP-VENUS id AA18269; Wed, 7 Aug 85 09:11:48 pdt
  1867. XDate: Tue 6 Aug 85 09:12:37-PDT
  1868. XFrom: Mark Richer <hplabs!RICHER@SUMEX-AIM>
  1869. XReceived: by HP-VENUS via CSNET; 7 Aug 1985 09:11:37-PDT (Wed)
  1870. XReceived: from sumex-aim.arpa by csnet-relay.arpa id a015812; 6 Aug 85 12:14 EDXT
  1871. XTo: hpcnof!veeger!hpcnou!dat%hplabs.csnet@CSNET-RELAY
  1872. XVia:  CSNet; 7 Aug 85 9:11-PDT
  1873. XSubject: Re: AI in Education mailing list...
  1874. XCc: RICHER@SUMEX-AIM
  1875. XIn-Reply-To: <8508030243.AA27641@HP-VENUS>
  1876. XMessage-Id: <12132987812.61.RICHER@SUMEX-AIM.ARPA>
  1877. X
  1878. XI added you to aied.  This message may be of interest to you:
  1879. X
  1880. XArtificial Intelligence in Education Meeting at IJCAI 85
  1881. X---------- ------------ -- --------- ------- -- ----- --
  1882. X
  1883. XPlace: Math Sciences Auditorium (a.k.a. Math 4000A), UCLA campus
  1884. XTime: 6:30 pm, Tuesday, Aug. 20, 1985  (length: 1 - 1 1/4 hr)
  1885. X
  1886. XAgenda:
  1887. X    I have two speakers scheduled to make presentations that
  1888. Xshould stimulate questions and discussions:
  1889. X
  1890. X    (1) Short Announcements
  1891. X
  1892. X    (2) Jeff Bonar, Research Scientist, Learning Research and
  1893. X    Development Center (LRDC), University of Pittsburgh
  1894. X
  1895. X    --- on-going ICAI research projects at LRDC
  1896. X    --- dissemination of ICAI technology in the form of software
  1897. X    tools, workshops, written materials, and video tapes.
  1898. X
  1899. X    (3) Gary Fine, Product Engineering Manager, INTELLICORP,
  1900. X    formerly with a company producing CAI products, also graduate
  1901. X    work in ICAI  
  1902. X
  1903. X    --- bridging the gap between current ICAI technology and the
  1904. X    real world
  1905. X
  1906. X[IJCAI-85, the 9th International Joint Conference on Artificial
  1907. XIntelligence is being held at UCLA Campus, August 18-23, 1985.  This
  1908. Xconference is co-sponsered by the American Association for Artificial
  1909. XIntelligence (AAAI) this year, and I have been told by their office
  1910. Xthat only walk-in registration is available at this time.  For more
  1911. Xinformation, contact AAAI:  AAAI-OFFICE@SUMEX-AIM.ARPA
  1912. X                AAAI, 445 Burgess Drive, Menlo Park, CA 94025
  1913. X                or call (415) 328-3123]
  1914. X
  1915. XDirect questions on the AI in ED meeting (only) to Mark Richer,
  1916. XRICHER@SUMEX-AIM.ARPA
  1917. X-------
  1918. X
  1919. X
  1920. X
  1921. X
  1922. XFrom root Tue Sep 24 09:53:24 1985
  1923. X>From HPMAIL-gateway Tue Sep 24  9:46:47 1985  remote from veeger
  1924. X>From Simon_CINTZ_/_HPD600/TR  Tue Sep 24  9:46:47 1985  remote from hpmail
  1925. XDate:   Tue, 24 Sep 85  9:14:00 MDT
  1926. XFrom:   Simon_CINTZ_/_HPD600/TR  (Simon Cintz)
  1927. XSubject: ITF
  1928. XFrom:   Simon_CINTZ_/_HPD600/TR  (Simon Cintz)
  1929. XTo:     Dave_TAYLOR_/_HPF100/00
  1930. X
  1931. XDave -
  1932. X
  1933. XJust as one programming language doesn't suit the needs of
  1934. Xall programmers, one authoring facility will probably not
  1935. Xsuit the needs of all HP entities that require CBT -- at least
  1936. Xnot in the near future.  Of course, this is my personal opinion
  1937. Xand if I'm wrong, it won't be the first time.
  1938. X
  1939. XGood luck.
  1940. X
  1941. X
  1942. X                                           - Simon
  1943. X
  1944. XFrom root Mon Oct 21 10:43:37 1985
  1945. X>From srmmail Mon Oct 21 10:30:16 1985  remote from veeger
  1946. X>From root Mon Oct 21 10:28:58 1985 remote from hpcnof
  1947. X>From DLS.MDC%office-X.arpa@CSNET-RELAY  Mon Oct 21 01:57:05 1985 remote from hXplabs
  1948. XReceived: by HP-VENUS id AA17376; Mon, 21 Oct 85 01:57:05 pdt
  1949. XDate: 21 Oct 85 01:02 EDT
  1950. XFrom: Duane Stone / McDonnell Douglas / CSC-ASD <hplabs!DLS.MDC%office-1.arpa@CXSNET-RELAY>
  1951. XReceived: by HP-VENUS via CSNET; 21 Oct 1985 01:57:01-PDT (Mon)
  1952. XReceived: from office-1.arpa by CSNET-RELAY.ARPA id a019220; 21 Oct 85 1:18 EDTX
  1953. XTo: Dave Taylor <hpcnou!dat%hplabs.csnet@CSNET-RELAY>
  1954. XVia:  CSNet; 21 Oct 85 1:56-PDT
  1955. XSubject: Re: More Mail Headers...
  1956. XMessage-Id: <MDC-DLS-7W9CS@OFFICE-1>
  1957. XComment: Dave -- this is the body of the message I previously 'sent' to you viaX
  1958. X
  1959. Xa Journal.
  1960. X
  1961. XI might suggest re-wording the para on Author -- my associates might object to X
  1962. X'strange' -- something like:
  1963. X
  1964. X   This is used to credit the original author, or to give credit on article 
  1965. X   excerpts (from Newspapers, magazines, books, etc).
  1966. X
  1967. XOne field which I forgot is:
  1968. X
  1969. X   Length:  This is computed when the message is sent and gives the recipients X
  1970. X   an estimate of the number of pages in the document.
  1971. X
  1972. X   Example:
  1973. X
  1974. X      Length: 6 pages [estimate]
  1975. X
  1976. XAccess:
  1977. X
  1978. X   Used to declare whether a Journal item should be Public or Private (to thoseX
  1979. X   that are on the distribution list or Extended Access list)
  1980. X
  1981. X   Example:
  1982. X
  1983. X      Access: Unrestricted
  1984. X
  1985. XAcknowledge-Delivery:
  1986. X
  1987. X   Used to request the system mailer send back a message when it has 
  1988. X   successfully delivered the item.
  1989. X
  1990. X   Example:
  1991. X
  1992. X      Acknowledge-Delivery: Requested
  1993. X
  1994. XAcknowledge-Receipt:
  1995. X
  1996. X   Used to to ask the recipient to acknowledge receipt of the message.
  1997. X
  1998. X   Example:
  1999. X
  2000. X   Acknowledge-Receipt: Requested
  2001. X
  2002. XAddendum-To:
  2003. X
  2004. X   A pointer to a previously submitted Journal item.
  2005. X
  2006. X   Example:
  2007. X
  2008. X      Addendum-To: <ASD,1234,>
  2009. X
  2010. XDelivery-Timing:
  2011. X
  2012. X   Used by the sender to indicate when the message should be submitted to the 
  2013. X   mailer.
  2014. X
  2015. X      Examples:
  2016. X
  2017. X         Rush:       -   immediate
  2018. X
  2019. X         Soon:       -   as soon as possible
  2020. X
  2021. X         Defer:      -   overnight
  2022. X
  2023. X         Start-Delivery: DATE TIME
  2024. X
  2025. X         Stop-Delivery:  DATE TIME (if not yet delivered)
  2026. X
  2027. XDisposition-Code:
  2028. X
  2029. X   Used by the system to group Journal items into one of several classes for 
  2030. X   eventual archive to tape and as an indicator of how long the archive tapes 
  2031. X   should be retained.
  2032. X
  2033. X   Example:
  2034. X
  2035. X      Disposition-Code: Temporary (2 years)
  2036. X
  2037. XExtended-access:
  2038. X
  2039. X   Used with private Journal items to allow access by other than those on the 
  2040. X   distribution list.
  2041. X
  2042. X   Example:
  2043. X
  2044. X      Extended-access: ASD.MDC
  2045. X
  2046. XLocation:
  2047. X
  2048. X   Used to submit the message to the Journal.  The adressees receive a short 
  2049. X   citation with other header fields and a "Location:" field pointing to a fileX
  2050. X   in an electronic library.
  2051. X
  2052. X   Example:
  2053. X
  2054. X      Location: <MDC,1234,>
  2055. X
  2056. XPart-Of:
  2057. X
  2058. X   A pointer to a previously submitted Journal item.
  2059. X
  2060. X   Example:
  2061. X
  2062. X      Part-Of: <MDC,1234,>
  2063. X
  2064. XRoute-To:
  2065. X
  2066. X   Used to send a message "in-turn" to addressees in the "To:" field -- as 
  2067. X   opposed to the broadcast method of delivery where everyone gets the message X
  2068. X   "simultaneously".  Any addresses in the "Cc:" field receive a copy of the 
  2069. X   message each time it is passed from one adressee to the next in the "To:" 
  2070. X   field.
  2071. X
  2072. X   Example:
  2073. X
  2074. X      Routed-to: {addresses in To field}
  2075. X
  2076. XSigned:
  2077. X
  2078. X   Created when the user employs the Sign command; used to electronically sign X
  2079. X   a message.  It affixes a signature-block to a message.  A "Verify Signature"X
  2080. X   command is available to recipients that lets them find out if anyone has 
  2081. X   changed the body of the message since the message was signed.
  2082. X
  2083. X   Example:
  2084. X
  2085. X          SIGNED
  2086. X      
  2087. X      Duane L. Stone
  2088. X      App. Dev. Mgr.
  2089. X
  2090. XSupersedes:
  2091. X
  2092. X   A pointer to a previously submitted Journal item.
  2093. X
  2094. X   Example:
  2095. X
  2096. X      Supersedes: <MDC,1234,>
  2097. X
  2098. X
  2099. X--- last line of the file --
  2100. END-OF-FILE
  2101.  
  2102. size=`wc -c < test/test.mail`
  2103.  
  2104. if [ $size != 10005 ]
  2105. then
  2106.   echo Warning: test/test.mail changed - should be 10005 bytes, not $size bytes
  2107. fi
  2108.  
  2109. chmod 644 test/test.mail
  2110.  
  2111. # ---------- file test/test.notes ----------
  2112.  
  2113.  
  2114. if [ -f test/test.notes ]
  2115. then
  2116.   echo File 'test/test.notes' already exists\!
  2117.   exit 1
  2118. fi
  2119.  
  2120. echo extracting file test/test.notes...
  2121. cat << 'END-OF-FILE' > test/test.notes
  2122. /***** hpfloat:net.micro.68K / barrett /  2:39 pm  Dec 16, 1985*/
  2123. Does anyone here at this site know anything about hang-gliding? 
  2124.  
  2125. I am thinking of learning to hang-glide, but am afraid of heights.  I
  2126. do fly light planes and love the hairiest roller coaster rides available
  2127. however.  My main question is "is there a way to learn to hang-glide 
  2128. gradually?"  I have seen some films of people learning on big sand dunes
  2129. an such before leaping off of cliffs with the things.  
  2130.  
  2131. Dave Barrett
  2132. hpfcla!barrett
  2133. /* ---------- */
  2134. /***** hpcnof:fsd.rec / hpfcla!ajs /  5:57 pm  Dec 16, 1985*/
  2135. > Does anyone here at this site know anything about hang-gliding? 
  2136.  
  2137. Yeah.  Don't waste your time, don't waste your money, don't risk your life.
  2138.  
  2139. > I am thinking of learning to hang-glide, but am afraid of heights.
  2140.  
  2141. I wasn't, but it still got me a broken arm.
  2142.  
  2143. > My main question is "is there a way to learn to hang-glide gradually?"
  2144.  
  2145. Probably not (yet).  Five years ago, simulators were in practice non-
  2146. existent.  We got twenty seconds hanging in a triangular control bar
  2147. with a person pushing.  Next stop, rocky slopes, real gliders, and cheap
  2148. walkie-talkies.
  2149.  
  2150. You'd be amazed how easy it is to injure yourself.  It's the nature of
  2151. the hobby.  People with plenty of experience die doing it every day,
  2152. due to circumstances often beyond their control.  There are better ways
  2153. to get thrills.
  2154.  
  2155. Alan
  2156. /* ---------- */
  2157. /***** hpcnof:fsd.rec / hpfcms!mpm /  8:58 pm  Dec 16, 1985*/
  2158.  
  2159. >You'd be amazed how easy it is to injure yourself.  It's the nature of
  2160. >the hobby.  People with plenty of experience die doing it every day,
  2161. >due to circumstances often beyond their control.  There are better ways
  2162. >to get thrills.
  2163. >Alan
  2164.  
  2165.      I haven't done any hang-gliding myself, but I would like to try it
  2166. some day.  (I have a moderate fear of heights; it depends on the altitude
  2167. and the apparent stability of my "perch".)
  2168.  
  2169.      I read (or heard) that MOST hang-gliding accidents fall into two
  2170. categories:
  2171.  
  2172.      1) novices attempt something beyond their experience (like jumping
  2173.     off a tall building after one lesson on a gently sloped hill),
  2174.  
  2175.      2) experts attempt VERY dramatic stuff (like jumping off El
  2176.     Capitan in unpredictable thermal up- and down- drafts).
  2177.  
  2178.      Please note:  Alan Silverstein doesn't fall in EITHER category.  I
  2179. took some sport parachuting lessons a few years ago.  It turned out to be
  2180. quite safe GIVEN ADEQUATE TRAINING as I had at the time.  I suspect the
  2181. same would hold true for hang-gliding (or rapelling, or ice climbing, or
  2182. ...).  The best way to find out if you can overcome your fears is by con-
  2183. fronting them in a safe and supportive environment.
  2184.  
  2185.      My recommendation:  check out any "school" before you sign up.  Ask
  2186. about their safety record, the terrain where they offer lessons, amount of
  2187. "ground school" training before first "flight", etc.  Above all, make sure
  2188. that you TRUST any prospective teacher.  Even if you have no logical reason
  2189. to distrust someone, don't try something like this unless you trust them.
  2190. (This is where your rational mind needs to work with your intuition.)
  2191. Otherwise you could easily get hurt.
  2192.  
  2193.      This is likely to be unknown territory for you, so be prepared and
  2194. you will likely have a more enjoyable (and safe) experience.  Of course,
  2195. there is ALWAYS the chance for an accident.
  2196.  
  2197.     -- Mike "no I wasn't crazy at the time; I WANTED to do it" McCarthy
  2198.        hpfcla!mpm
  2199. /* ---------- */
  2200. /***** hpcnof:fsd.rec / dat / 12:12 pm  Dec 19, 1985*/
  2201. >> Does anyone here at this site know anything about hang-gliding? 
  2202. >Yeah.  Don't waste your time, don't waste your money, don't risk your life.
  2203.  
  2204.     Strong stuff!  I think you're out on a limb this time, Alan.
  2205. I've known lots of people who've hang-glided and never gotten hurt.
  2206. (and we're talking the La Jolla cliffs in San Diego!!) (they also
  2207. think it's the best 'high' in the world (and they've tried some
  2208. pretty strange things to compare!))
  2209.  
  2210. >> I am thinking of learning to hang-glide, but am afraid of heights.
  2211. >I wasn't, but it still got me a broken arm.
  2212.  
  2213.     Fine.  So I broke my arm a long time ago jumping off a bunk
  2214. bed.  Does this mean that bunk beds are too dangerous and that I 
  2215. shouldn't ever sleep in one???
  2216.  
  2217.     The point is that anything you do is dangerous and that the
  2218. way to minimize the danger is to take things gradually and only 
  2219. progress when you feel comfortable with your current level of learning.
  2220. At the same time realize that even sitting in a chair in a warm room
  2221. could be dangerous, so don't be so foolishly optimistic to think that
  2222. you cannot get seriously hurt hang-gliding.
  2223.  
  2224.     On the other hand - if you want to go for it - GO FOR IT!!!
  2225.  
  2226.             -- Dave "Cheap Thrills, Inc." Taylor
  2227. /* ---------- */
  2228. /***** hpcnof:fsd.rec / hpfcmp!rjn / 11:33 pm  Dec 16, 1985*/
  2229. re: hang gliding
  2230.  
  2231. I am a licensed [so what] pilot in powered  aircraft and  sailplanes.  I was
  2232. taking  hang  gliding  (HG)  instruction  four years ago (prior to moving to
  2233. Colorado).  I gave it up when I moved here.  My impressions:
  2234.  
  2235. * If your  introduction  to piloting flying machines is via HG, you will not
  2236.   have enough  understanding of aerodynamics to safely operate your craft in
  2237.   calm or steady-wind conditions.
  2238.  
  2239. * HGs which are controlled by weight  shifting do not have adequate  control
  2240.   authority   for   normal   conditions,   unless   you  have  lots  of  the
  2241.   aforementioned  understanding and fly only in ideal  conditions.  HGs with
  2242.   3-axis control offer a little more margin.
  2243.  
  2244. * HGs are typically operated close to the ground.  No HG designs have enough
  2245.   control  authority  to handle  gusty  conditions.  You can  safely  land a
  2246.   parachute in conditions  which are dangerous for HG  operation.  Flying in
  2247.   gusty  conditions  is the most  popular  way to crash a HG.  If you  think
  2248.   jumping is dangerous, don't take up HG.  (I used to room with a jumpmaster
  2249.   and have made one jump myself.  I think jumping is safer.)
  2250.  
  2251. * HGs operated at higher altitudes (away from ground  reference) suffer from
  2252.   lack of  instrumentation.  It is easy to enter a spiral dive, spin or deep
  2253.   stall (luff the sail on Rogallo machines)  without  instruments or lots of
  2254.   experience.  Spiral dives usually  overstress  the airframe; the resulting
  2255.   collection of parts crashes.
  2256.  
  2257. If you  insist on K-Mart  aviating,  I suggest a 2-place  ultra-light  (with
  2258. parachute), a good instructor and a calm day.  At least the ground is level.
  2259. Bring earplugs.
  2260.  
  2261. Bob Niland  TN-226-4014   HP-UX: hpfcla!rjn    DESK: rjn (hpfcla) /HP4000/UX
  2262. /* ---------- */
  2263. /***** hpcnof:fsd.rec / hpfloat!jim /  9:10 am  Dec 17, 1985*/
  2264. Try flying across the waves on a windsurfer!  I once met a guy from
  2265. Denver who said he had tried them all--hang gliding, sky diving.  Windsurfing
  2266. offered just as much thrill with almost no risk.
  2267.  
  2268. The crash landings are rather painless.  I've gotten 5 feet of air right
  2269. here in Colorado.
  2270.  
  2271.         "Jumping Jim" Tear
  2272.  
  2273. /* ---------- */
  2274. /***** hpcnof:fsd.rec / hpfcmt!ron /  7:56 am  Dec 17, 1985*/
  2275.  
  2276.  
  2277. I also am a "regular" aircraft (and sailplane) pilot.
  2278.  
  2279. I have not tried hang gliding however I have a fairly close friend who 
  2280. was into it before he totally demolished his craft. He was only bruised
  2281. by the impact but came away considerably more careful about his sports.
  2282.  
  2283. Besides the previously mentioned drawbacks I would like to mention the 
  2284. following:
  2285.  
  2286. A perfect landing consists of
  2287.  
  2288.    (a) Correct airspeed
  2289.    (b) Level wings ( tolerance to prevent wingtip dragging)
  2290.    (c) Correct yaw alignment   (within tolerance of landing gear)
  2291.    (d) Correct pitch
  2292.    (e) Correct rate of descent  (within tolerance of landing gear)
  2293.    (f) Correct altitude
  2294.    (g) Correct groundspeed (within tolerance of landing gear) 
  2295.  
  2296. Consider that the landing gear on an HG is your legs and gear collapse
  2297. is fairly common due to the low maximum speed for the gear and the 
  2298. airspeed being right in that range at touchdown.
  2299. Consider also that even calm air has some "breezes" going. 
  2300. Add to the "breezes" the fact that your control authority relative to the
  2301. velocity of the breezes is poor and you can wind up with all the ingredients
  2302. for a face plant.
  2303.  
  2304. Now to moderate the above, the idea of simple flight appeals greatly to
  2305. me. Unfortunately my personal risk-taking threshold is below the minimum
  2306. risk for this sport.  
  2307. I agree with Bob, try ultra-lights if you MUST . At least they have wheels.
  2308.  
  2309.  
  2310. Ron Miller
  2311.  
  2312.  
  2313. "Show me a country where the newspapers are filled with good news
  2314. and I'll show you a country where the jails are filled with good people."
  2315.                     -<I forgot>
  2316.  
  2317. Service Engineering  (Hardware Support)
  2318. Hewlett-Packard Co.
  2319. Ft. Collins Systems Div. Home of the HP 9000 Series 200,300 & 500
  2320. Ft. Collins Colorado
  2321. 303-226-3800
  2322.  
  2323. at: {ihnp4}hpfcla!ron
  2324. /* ---------- */
  2325. /***** hpcnof:fsd.rec / hpfcla!ajs /  6:36 pm  Dec 19, 1985*/
  2326. > Strong stuff!  I think you're out on a limb this time, Alan.
  2327. > I've known lots of people who've hang-glided and never gotten hurt.
  2328.  
  2329. Yes, but, --
  2330.  
  2331. > Fine.  So I broke my arm a long time ago jumping off a bunk
  2332. > bed.  Does this mean that bunk beds are too dangerous and that I 
  2333. > shouldn't ever sleep in one???
  2334.  
  2335. I'll be more explicit (and just as strong).  Let's say sleeping is a
  2336. zero (epsilon?) on the risk scale, and flying in a commercial aircraft
  2337. is 1, and driving a car, oh, I'd guess about a 4, and parachuting maybe
  2338. a 6, and SCUBA diving must be maybe a 7 or 8 then, comparable (?) with
  2339. climbing Fourteeners.  Based on my experience with it, I'd rank hang
  2340. gliding at around a 12 or 15.  Don't risk your life.
  2341.  
  2342. One thing I discovered is that being under a "kite" feels very different
  2343. from how you might guess while watching someone fly.  Not nearly as
  2344. comfortable (until airborne); very exposed.  Some people are naturals at
  2345. it; some (like me) are not.  If you are the former, and you are lucky,
  2346. and it appeals to you, you'll go do it anyway, no matter what I or Dave
  2347. say about it; good luck to you.
  2348.  
  2349. But, if you are the latter, you'll likely injure yourself seriously
  2350. trying to learn, because there isn't much margin for error outside a
  2351. simulator.  Look, I was gung-ho, being trained by a "professional"
  2352. training school, determined to overcome inexperience, ignored warnings
  2353. from concerned friends, was certain I could do it safely, paid close
  2354. attention to instructions, studied the subject intensely, and when I
  2355. crashed, I'd been in the air about five seconds, was about ten feet off
  2356. the ground, and was amazed that I'd actually broken anything.  A very
  2357. sobering experience.
  2358.  
  2359. On the way to the hospital, the trainer doing the driving informed me
  2360. that someone was seriously injured in their classes about once a month.
  2361.  
  2362. Gee, Dave, I guess I must be "out on a limb", incapable of giving advice
  2363. on the subject, because I survived the crash.  :-)
  2364.  
  2365. Alan
  2366. /* ---------- */
  2367. /***** hpcnof:fsd.rec / hpfcde!anny /  2:28 pm  Dec 31, 1985*/
  2368. WARNING:  Severe Base Note  D  r   i    f      t
  2369.  
  2370. <. . . and driving a car, oh, I'd guess about a 4, and parachuting maybe
  2371. <a 6, and SCUBA diving must be maybe a 7 or 8 then, . . .
  2372.  
  2373. Come on Alan!  SCUBA diving more dangerous than parachuting?  Maybe if your
  2374. parachuting off a jump tower versus SCUBA diving alone on the Great Barrier
  2375. Reef at night carring shark bait making wounded fish sounds. . . ;-)
  2376.  
  2377. After all, the FIRST time you parachute, you have to jump out of a PLANE! (/.\)
  2378. In the SKY!  You can SCUBA dive in a pool or a shallow lake or inlet.
  2379. If something goes wrong in the water, your buddy's there to help.  If 
  2380. something goes wrong in the sky, so long . . .
  2381.  
  2382. Just defending what I consider to be a fun and safe sport!
  2383.  
  2384. Anny (low altitude (4' or less) sports for me!) Randel
  2385. /* ---------- */
  2386. /***** hpcnof:fsd.rec / hpfcla!ajs /  9:27 am  Jan  2, 1986*/
  2387. > Come on Alan!  SCUBA diving more dangerous than parachuting?
  2388.  
  2389. Forgive me, I was just guessing, to make a point.  I don't know the
  2390. actual statistics, but you're probably right -- if you measure accidents
  2391. per hour.  On the other hand, if you measure accidents per jump or dive,
  2392. it wouldn't surprise me if the rates were similar.  Lotsa people go
  2393. diving without enough training, but skydiving requires decent training
  2394. and the accident rate is surprisingly low.
  2395.  
  2396. Alan "pick your poison" Silverstein
  2397. /* ---------- */
  2398. /***** hpcnof:fsd.rec / hpfcdc!donn /  9:32 am  Jan  3, 1986*/
  2399. The problem with SCUBA diving is the fact that "fly by nites" can
  2400. afford to get into the business.  A reputable dive shop will not
  2401. let you rent a tank unless you have a NAUI card (or ==) (and they'll hold
  2402. it while you have the tanks).  However there are always some who
  2403. will not do this, and some clown tries diving without essentially
  2404. any training ("Gee, I can swim, so I can dive.") and gets into
  2405. trouble.  It's much tougher to be a "fly by night" (or anytime)
  2406. when you need an airplane and a pilot's license.  Actually, the
  2407. accident rate for people with any significant training *and* who
  2408. are doing something more-or-less reasonable is not bad.  (Diving
  2409. below 150ft (or maybe less) is like starting a jump at 50000 feet:
  2410. it might work, but good luck unless you know what you're doing. 
  2411. The problem is that there isn't much reason to start at 50000 feet,
  2412. but there's a lot of interesting and valuable stuff below 150.)
  2413.  
  2414. I like to dive (tropical saltwater only, so I don't do it much),
  2415. and since one of the graduation exercises is diving while someone
  2416. is *trying* to make you screw up (albeit in a pool where there's
  2417. someone to fish you out), you learn to handle problems.  If you're
  2418. gutsy, try the NAUI *instructors* class: the graduation from that
  2419. is a open-water dive with known defective equipment!
  2420.  
  2421. Donn
  2422. /* ---------- */
  2423. END-OF-FILE
  2424.  
  2425. size=`wc -c < test/test.notes`
  2426.  
  2427. if [ $size != 13582 ]
  2428. then
  2429.   echo Warning: test/test.notes changed - should be 13582 bytes, not $size bytes
  2430. fi
  2431.  
  2432. chmod 644 test/test.notes
  2433.  
  2434. echo done
  2435.  
  2436. exit 0
  2437.  
  2438.  
  2439.  
  2440.  
  2441.