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

  1. Subject: v06i035:  Elm mail system (elm), Part10/14
  2. Newsgroups: mod.sources
  3. Approved: rs@mirror.UUCP
  4.  
  5. Submitted by: Dave Taylor <pyramid!hplabs!hpldat!taylor>
  6. Mod.sources: Volume 6, Issue 35
  7. Archive-name: elm/Part10
  8.  
  9. # Continuation of Shell Archive, created by hpldat!taylor
  10.  
  11. # This is part 10
  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.  
  18. if [ ! -d src ]
  19. then
  20.   echo creating directory src
  21.   mkdir src
  22. fi
  23.  
  24. # ---------- file src/mailmsg1.c ----------
  25.  
  26. filename="src/mailmsg1.c"
  27.  
  28. if [ -f $filename ]
  29. then
  30.   echo File \"$filename\" already exists\!  Skipping...
  31.   filename=/dev/null        # throw it away
  32. else
  33.   echo extracting file src/mailmsg1.c...
  34. fi
  35.  
  36. cat << 'END-OF-FILE' > $filename
  37. /**             mailmsg1.c            **/
  38.  
  39. /** Interface to allow mail to be sent to users.  Part of ELM  **/
  40.  
  41. /** (C) Copyright 1986, Dave Taylor                    **/
  42.  
  43. #include "headers.h"
  44.  
  45. /** strings defined for the hdrconfg routines **/
  46.  
  47. char subject[SLEN], action[SLEN], reply_to[SLEN], expires[SLEN], priority[SLEN];
  48. char to[VERY_LONG_STRING], cc[VERY_LONG_STRING], in_reply_to[SLEN];
  49.  
  50. char *format_long(), *strip_commas(), *tail_of_string();
  51.  
  52. int
  53. send(given_to, given_subject, edit_message)
  54. char *given_to, *given_subject;
  55. int   edit_message;
  56. {
  57.     /** Prompt for fields and then call mail() to send the specified
  58.         message.  If 'edit_message' is true then don't allow the
  59.             message to be edited. **/
  60.  
  61.     char address[VERY_LONG_STRING], addressII[VERY_LONG_STRING];
  62.     int  copy_msg = FALSE, is_a_response = FALSE;
  63.  
  64.     /* First: zero all current global message strings */
  65.  
  66.     cc[0] = action[0] = reply_to[0] = expires[0] = priority[0] = '\0';
  67.     in_reply_to[0] = address[0] = addressII[0] = '\0';
  68.  
  69.     strcpy(subject, given_subject);        /* copy given subject */
  70.     strcpy(to, given_to);            /* copy given to:     */
  71.  
  72.     /******* And now the real stuff! *******/
  73.  
  74.     copy_msg=copy_the_msg(&is_a_response); /* copy msg into edit buffer? */
  75.  
  76.     if (get_to(to, address) == 0)        /* get the To: address and expand */
  77.       return(0);
  78.  
  79.     /** are we by any chance just checking the addresses? **/
  80.  
  81.     if (check_only) {
  82.       printf("Expands to: %s\n", format_long(address, 12));
  83.       putchar('\r');    /* don't ask... */
  84.       leave();
  85.     }
  86.  
  87.     /** if we're batchmailing, let's send it and GET OUTTA HERE! **/
  88.  
  89.     if (mail_only && strlen(batch_subject) > 0) { 
  90.       strcpy(subject, batch_subject);    /* get the batch subject */
  91.       return(mail(address, NULL, FALSE, FALSE, TRUE));
  92.     }
  93.  
  94.     display_to(address);    /* display the To: field on screen... */
  95.  
  96.     dprint1(3,"\nMailing to %s\n", address);
  97.   
  98.     if (get_subject(subject) == 0)        /* get the Subject: field */
  99.       return(0);
  100.  
  101.     dprint1(4,"Subject is %s\n", subject);
  102.  
  103.     if (get_copies(cc, address, addressII) == 0)    /* get the cc: field */
  104.       return(0);
  105.  
  106.     if (strlen(cc) > 0)
  107.       dprint1(4,"Copies to %s\n", cc);
  108.  
  109.     if (mail_only)                 /* indicate next step... */
  110.       printf("\n\r");
  111.     else
  112.       MoveCursor(LINES,0);    /* you know you're hit <return> ! */
  113.  
  114.     /** generate the In-Reply-To: header... **/
  115.  
  116.     if (is_a_response)
  117.       generate_reply_to(current-1);
  118.  
  119.     /* and mail that puppy outta here! */
  120.  
  121.     mail(address, addressII, copy_msg, edit_message, FALSE);
  122.     
  123.     return(edit_message);
  124. }
  125.  
  126. get_to(to_field, address)
  127. char *to_field, *address;
  128. {
  129.     /** prompt for the "To:" field, expanding into address if possible.
  130.         This routine returns ZERO if errored, or non-zero if okay **/
  131.  
  132.     if (strlen(to_field) == 0) {
  133.       PutLine0(LINES-2, 0, "To: ");
  134.       (void) optionally_enter(to_field, LINES-2, 4, FALSE); 
  135.       if (strlen(to_field) == 0) {
  136.         ClearLine(LINES-2);    
  137.         return(0);
  138.       }
  139.       build_address(strip_commas(to_field), address); 
  140.     }
  141.     else if (mail_only) 
  142.       build_address(strip_commas(to_field), address); 
  143.     else 
  144.       strcpy(address, to_field);
  145.     
  146.     if (strlen(address) == 0) {    /* bad address!  Removed!! */
  147.       if (! mail_only)
  148.         ClearLine(LINES-2);
  149.       return(0);
  150.     }
  151.  
  152.     return(1);        /* everything is okay... */
  153. }
  154.  
  155. get_subject(subject_field)
  156. char *subject_field;
  157. {
  158.     /** get the subject and return non-zero if all okay... **/
  159.  
  160.     if (mail_only)
  161.       printf("Subject: ");
  162.     else 
  163.       PutLine0(LINES-2,0,"Subject: ");
  164.  
  165.     CleartoEOLN();
  166.  
  167.     if (optionally_enter(subject_field, LINES-2, 9, TRUE) == -1) {
  168.       /** User hit the BREAK key! **/
  169.       MoveCursor(LINES-2,0);     
  170.       CleartoEOLN();
  171.       dprint0(3,"User responded to \"Subject:\" with BREAK (get_subject)\n");
  172.       error("mail not sent");
  173.       return(0);
  174.     }
  175.  
  176.     if (strlen(subject_field) == 0) {    /* zero length subject?? */
  177.       if (mail_only) 
  178.         printf("\n\rNo subject - Continue with message? (y/n) n%c",
  179.           BACKSPACE);
  180.       else
  181.         PutLine1(LINES-2,0,"No subject - Continue with message? (y/n) n%c",
  182.           BACKSPACE);
  183.  
  184.       if (tolower(ReadCh()) != 'y') {    /* user says no! */
  185.         if (mail_only) {
  186.           printf("\n\r\n\rMail Cancelled!\n\r");
  187.           return(0);
  188.         }
  189.         ClearLine(LINES-2);
  190.         dprint0(3,
  191.         "User reponded to \"Subject:\" with RETURN (get_subject)\n");
  192.         error("mail not sent");
  193.         return(0);
  194.       }
  195.       else if (! mail_only) {
  196.         PutLine0(LINES-2,0,"Subject: <none>");
  197.         CleartoEOLN();
  198.       }
  199.     }
  200.  
  201.     return(1);        /** everything is cruising along okay **/
  202. }
  203.  
  204. get_copies(cc_field, address, addressII)
  205. char *cc_field, *address, *addressII;
  206. {
  207.     /** Get the list of people that should be cc'd, returning ZERO if
  208.         any problems arise.  Address and AddressII are for expanding
  209.         the aliases out after entry! 
  210.         If 'bounceback' is nonzero, add a cc to ourselves via the remote
  211.         site, but only if hops to machine are > bounceback threshold.
  212.     **/
  213.  
  214.     if (mail_only)
  215.       printf("\n\rCopies To: ");
  216.     else
  217.       PutLine0(LINES-1,0,"Copies To: ");
  218.  
  219.     fflush(stdout);
  220.  
  221.     if (optionally_enter(cc_field, LINES-1, 11, FALSE) == -1) {
  222.       if (mail_only) {
  223.         printf("\n\r\n\rMail not sent!\n\r");
  224.         return(0);
  225.       }
  226.       ClearLine(LINES-2);
  227.       ClearLine(LINES-1);
  228.       
  229.       dprint0(3,
  230.  "User responded to \"Copies To:\" with BREAK.  Mail cancelled (get_copies)\n");
  231.       error("mail not sent");
  232.       return(0);
  233.     }
  234.     
  235.     build_address(strip_commas(cc_field), addressII);
  236.  
  237.     if (strlen(address) + strlen(addressII) > VERY_LONG_STRING) {
  238.       dprint0(2,
  239.         "String length of \"To:\" + \"Cc\" too long! (get_copies)\n");
  240.       error("Too many people.  Copies ignored");
  241.       sleep(2);
  242.       cc_field[0] = '\0';
  243.     }
  244.  
  245.     return(1);        /* everything looks okay! */
  246. }
  247.     
  248. int
  249. copy_the_msg(is_a_response)
  250. int *is_a_response;
  251. {
  252.     /** Returns True iff the user wants to copy the message being
  253.         replied to into the edit buffer before invoking the editor! 
  254.         Sets "is_a_response" to true if message is a response...
  255.     **/
  256.  
  257.     int answer = FALSE;
  258.  
  259.     if (strlen(to) > 0 && !mail_only) {    /* predefined 'to' line! */
  260.       if (auto_copy) 
  261.         answer = TRUE;
  262.       else 
  263.         answer = (want_to("Copy message? (y/n) ", 'n', TRUE) == 'y');
  264.       *is_a_response = TRUE;
  265.     }
  266.     else
  267.       if (strlen(subject) > 0)      /* predefined 'subject' (Forward) */
  268.         answer = TRUE;
  269.  
  270.     return(answer);
  271. }
  272.  
  273. display_to(address)
  274. char *address;
  275. {
  276.     /** Simple routine to display the "To:" line according to the
  277.         current configuration (etc)                   
  278.      **/
  279.  
  280.     if (mail_only)
  281.       printf("To: %s\n\r", format_long(address));
  282.     else {
  283.       if (strlen(address) > COLUMNS-50) 
  284.         PutLine1(LINES-3, COLUMNS-50, "To: (%s)", 
  285.         tail_of_string(address, COLUMNS-50));
  286.       else {
  287.         PutLine1(LINES-3, COLUMNS-50, "          To: %s", address);
  288.         CleartoEOLN();
  289.       }
  290.     }
  291. }
  292. END-OF-FILE
  293.  
  294. if [ "$filename" != "/dev/null" ]
  295. then
  296.   size=`wc -c < $filename`
  297.  
  298.   if [ $size != 6587 ]
  299.   then
  300.     echo $filename changed - should be 6587 bytes, not $size bytes
  301.   fi
  302.  
  303.   chmod 644 $filename
  304. fi
  305.  
  306. # ---------- file src/connect_to.c ----------
  307.  
  308. filename="src/connect_to.c"
  309.  
  310. if [ -f $filename ]
  311. then
  312.   echo File \"$filename\" already exists\!  Skipping...
  313.   filename=/dev/null        # throw it away
  314. else
  315.   echo extracting file src/connect_to.c...
  316. fi
  317.  
  318. cat << 'END-OF-FILE' > $filename
  319. /**            connect_to.c            **/
  320.  
  321. /** This contains the routine(s) needed to have the Elm mailer figure
  322.     out what machines the current machine can talk to.   This can be
  323.     done in one of two ways - either the program can read the L.sys
  324.     file, or (if it fails or "UUNAME" define is present) will invoke
  325.     uuname to a file, then read the file in!
  326.  
  327.     (C) Copyright Dave Taylor, 1986
  328. **/
  329.  
  330. #include "headers.h"
  331.  
  332. get_connections()
  333. {
  334.  
  335.     /** get the direct connections that this machine has, by hook
  336.         or by crook (so to speak) 
  337.     **/
  338.  
  339. #ifndef USE_UUNAME
  340.     FILE *lsysfile;
  341.     char  buffer[SLEN], sysname[NLEN];
  342.     struct lsys_rec *system_record, *previous_record;
  343.     int    loc_on_line;
  344.  
  345.     previous_record = NULL;
  346.     if ((lsysfile = fopen(Lsys,"r")) == NULL) {
  347.       dprint1(1, "Warning: Can't open L.sys file %s (read_lsys)\n", Lsys);
  348. #endif
  349.  
  350.       if (read_uuname() == -1) {
  351.         error("Warning: couldn't figure out system connections...");
  352.         talk_to_sys = NULL;
  353.       }
  354.  
  355. #ifndef USE_UUNAME
  356.       /** ELSE: already read in uuname() output if we're here!! **/
  357.       return;
  358.     }
  359.  
  360.     while (fgets(buffer, SLEN, lsysfile) != NULL) {
  361.       sscanf(buffer,"%s", sysname);
  362.  
  363.       if (previous_record == NULL) {
  364.         dprint1(2, "L.sys\tdirect connection to %s, ", sysname);
  365.         loc_on_line = 30 + strlen(sysname);  
  366.         previous_record = (struct lsys_rec *) malloc(sizeof *talk_to_sys);
  367.  
  368.         strcpy(previous_record->name, sysname);
  369.         previous_record->next = NULL;
  370.         talk_to_sys = previous_record;
  371.       }
  372.       else if (! talk_to(sysname) && sysname[0] != '#') {
  373.         if (loc_on_line + strlen(sysname) > 80) {
  374.           dprint0(2, "\n\t");
  375.           loc_on_line = 8;
  376.         }
  377.         dprint1(2, "%s, ", sysname);
  378.         loc_on_line += (strlen(sysname) + 2);
  379.         system_record = (struct lsys_rec *) malloc(sizeof *talk_to_sys);
  380.       
  381.         strcpy(system_record->name, sysname);
  382.         system_record->next = NULL;
  383.         previous_record->next = system_record;
  384.         previous_record = system_record;
  385.       }
  386.     }
  387.  
  388.     fclose(lsysfile);
  389.  
  390.     if (loc_on_line != 8)
  391.       dprint0(2, "\n");
  392.  
  393.     dprint0(2, "\n");            /* for a nice format! Yeah! */
  394. #endif
  395. }
  396.  
  397. int
  398. read_uuname()
  399. {
  400.     /** This routine trys to use the uuname routine to get the names of
  401.         all the machines that this machine connects to...it returns
  402.         -1 on failure.
  403.     **/
  404.  
  405.     FILE *fd;
  406.     char  buffer[SLEN], filename[SLEN];
  407.     struct lsys_rec *system_record, *previous_record;
  408.     int   loc_on_line;
  409.  
  410.     sprintf(filename, "%s%d", temp_file, getpid());
  411.     sprintf(buffer,"%s > %s", uuname, filename);
  412.  
  413.     if (system_call(buffer, SH) != 0) {
  414.       dprint0(1, "Can't get uuname info - system call failed!\n");
  415.       unlink(filename);    /* insurance */
  416.       return(-1);
  417.     }
  418.     
  419.     if ((fd = fopen(filename, "r")) == NULL) {
  420.       dprint1(1, "Can't get uuname info - can't open file %s for reading\n",
  421.            filename);
  422.       unlink(filename);    /* insurance */
  423.       return(-1);
  424.     }
  425.     
  426.     previous_record = NULL;
  427.  
  428.     while (fgets(buffer, SLEN, fd) != NULL) {
  429.       no_ret(buffer);
  430.       if (previous_record == NULL) {
  431.         dprint1(2, "uuname\tdirect connection to %s, ", buffer);
  432.         loc_on_line = 30 + strlen(buffer);
  433.         previous_record = (struct lsys_rec *) malloc(sizeof *talk_to_sys);
  434.  
  435.         strcpy(previous_record->name, buffer);
  436.         previous_record->next = NULL;
  437.         talk_to_sys = previous_record;
  438.       }
  439.       else {    /* don't have to check uniqueness - uuname does that! */
  440.         if (loc_on_line + strlen(buffer) > 80) {
  441.           dprint0(2, "\n\t");
  442.           loc_on_line = 8;
  443.         }
  444.         dprint1(2, "%s, ", buffer);
  445.         loc_on_line += (strlen(buffer) + 2);
  446.         system_record = (struct lsys_rec *) malloc(sizeof *talk_to_sys);
  447.       
  448.         strcpy(system_record->name, buffer);
  449.         system_record->next = NULL;
  450.         previous_record->next = system_record;
  451.         previous_record = system_record;
  452.       }
  453.     }
  454.  
  455.     fclose(fd);
  456.  
  457.     (void) unlink(filename);        /* kill da temp file!! */
  458.  
  459.     dprint0(2, "\n");            /* for a nice format! Yeah! */
  460.  
  461.     return(0);                /* it all went okay... */
  462. }
  463. END-OF-FILE
  464.  
  465. if [ "$filename" != "/dev/null" ]
  466. then
  467.   size=`wc -c < $filename`
  468.  
  469.   if [ $size != 3887 ]
  470.   then
  471.     echo $filename changed - should be 3887 bytes, not $size bytes
  472.   fi
  473.  
  474.   chmod 644 $filename
  475. fi
  476.  
  477. # ---------- file src/remail.c ----------
  478.  
  479. filename="src/remail.c"
  480.  
  481. if [ -f $filename ]
  482. then
  483.   echo File \"$filename\" already exists\!  Skipping...
  484.   filename=/dev/null        # throw it away
  485. else
  486.   echo extracting file src/remail.c...
  487. fi
  488.  
  489. cat << 'END-OF-FILE' > $filename
  490. /**            remail.c            **/
  491.  
  492. /** For those cases when you want to have a message continue along
  493.     to another person in such a way as they end up receiving it with
  494.     the return address the person YOU received the mail from (does
  495.     this comment make any sense yet??)...
  496.  
  497.     (C) Copyright 1986  Dave Taylor
  498. **/
  499.  
  500. #include "headers.h"
  501. #include <errno.h>
  502.  
  503. extern int errno;
  504.  
  505. int
  506. remail()
  507. {
  508.     /** remail a message... returns TRUE if new foot needed ... **/
  509.     
  510.     FILE *mailfd;
  511.     char entered[VERY_LONG_STRING], expanded[VERY_LONG_STRING];
  512.     char filename[SLEN], buffer[VERY_LONG_STRING];
  513.  
  514.     entered[0] = '\0';
  515.  
  516.     get_to(entered, expanded);
  517.     if (strlen(entered) == 0)
  518.       return(0);
  519.  
  520.     display_to(expanded);
  521.  
  522.     /** now the munge... **/
  523.  
  524.     sprintf(filename, "%s%d", temp_file, getpid());
  525.  
  526.     if ((mailfd = fopen(filename, "w")) == NULL) {
  527.       dprint1(1,"couldn't open temp file %s! (remail)\n", filename);
  528.       dprint2(1,"** %s - %s **\n", error_name(errno),
  529.           error_description(errno));
  530.       sprintf(buffer, "Sorry - couldn't open file %s for writing (%s)",
  531.           error_name(errno));
  532.       set_error(buffer);
  533.       return(1);
  534.     }
  535.  
  536.     /** now let's copy the message into the newly opened
  537.         buffer... **/
  538.  
  539.     copy_message("", mailfd, FALSE, TRUE);  
  540.  
  541.     fclose(mailfd);
  542.  
  543.     /** Got the messsage, now let's ensure the person really wants to 
  544.         remail it... **/
  545.  
  546.     ClearLine(LINES-1);
  547.     ClearLine(LINES);
  548.     PutLine1(LINES-1,0,
  549.         "Are you sure you want to remail this message (y/n) ? y%c",
  550.         BACKSPACE);
  551.     fflush(stdin);
  552.     fflush(stdout);
  553.     if (tolower(ReadCh()) == 'n') { /* another day, another No... */
  554.       Write_to_screen("No", 0);
  555.       set_error("Bounce of message cancelled");
  556.           return(1);
  557.     }
  558.     Write_to_screen("Yes!", 0);
  559.  
  560.     sprintf(buffer, "%s %s < %s", mailer, expanded, filename);
  561.  
  562.     PutLine0(LINES,0,"resending mail...");
  563.  
  564.     if ((errno = system_call(buffer)) != 0) 
  565.       set_error("Remail failed with error %d!", errno);
  566.     else
  567.       set_error("mail resent");
  568.  
  569.     return(1);
  570. }
  571. END-OF-FILE
  572.  
  573. if [ "$filename" != "/dev/null" ]
  574. then
  575.   size=`wc -c < $filename`
  576.  
  577.   if [ $size != 1940 ]
  578.   then
  579.     echo $filename changed - should be 1940 bytes, not $size bytes
  580.   fi
  581.  
  582.   chmod 644 $filename
  583. fi
  584.  
  585. # ---------- file src/signals.c ----------
  586.  
  587. filename="src/signals.c"
  588.  
  589. if [ -f $filename ]
  590. then
  591.   echo File \"$filename\" already exists\!  Skipping...
  592.   filename=/dev/null        # throw it away
  593. else
  594.   echo extracting file src/signals.c...
  595. fi
  596.  
  597. cat << 'END-OF-FILE' > $filename
  598. /**            signals.c        **/
  599.  
  600. /** This set of routines traps various signals and informs the
  601.     user of the error, leaving the program in a nice, graceful
  602.     manner.
  603.  
  604.     (C) Copyright 1986 Dave Taylor
  605. **/
  606.  
  607. #include "headers.h"
  608. #include <signal.h>
  609.  
  610. extern int pipe_abort;        /* set to TRUE if receive SIGPIPE */
  611.  
  612. quit_signal()
  613. {
  614.     dprint0(2,"\n** Received SIGQUIT **\n\n");
  615.     leave();
  616. }
  617.  
  618. term_signal() 
  619. {
  620.     dprint0(2,"\n** Received SIGTERM **\n\n");
  621.     leave();
  622. }
  623.  
  624. ill_signal()
  625. {
  626.     dprint0(1,"\n** Received SIGILL **\n\n");
  627.     PutLine0(LINES, 0, "\n\rIllegal Instruction signal!\n\r");
  628.     emergency_exit();
  629. }
  630.  
  631. fpe_signal()  
  632. {
  633.     dprint0(1,"\n** Received SIGFPE **\n\n");
  634.     PutLine0(LINES, 0,"\n\rFloating Point Exception signal!\n\r");
  635.     emergency_exit();
  636. }
  637.  
  638. bus_signal()
  639. {
  640.     dprint0(1,"\n** Received SIGBUS **\n\n");
  641.     PutLine0(LINES, 0,"\n\rBus Error signal!\n\r");
  642.     emergency_exit();
  643. }
  644.  
  645. segv_signal()
  646. {
  647.     dprint0(1,"\n** Received SIGSEGV **\n\n");
  648.     PutLine0(LINES, 0,"\n\rSegment Violation signal!\n\r");
  649.     emergency_exit();
  650. }
  651.  
  652. alarm_signal()
  653. {    
  654.     /** silently process alarm signal for timeouts... **/
  655.  
  656.     int alarm_signal();
  657.  
  658.     signal(SIGALRM, alarm_signal);
  659. }
  660.  
  661. pipe_signal()
  662. {
  663.     /** silently process pipe signal... **/
  664.  
  665.     int pipe_signal();
  666.  
  667.     dprint0(2,"*** received SIGPIPE ***\n");
  668.     
  669.     pipe_abort = TRUE;    /* internal signal ... wheeee!  */
  670.  
  671.     signal(SIGPIPE, pipe_signal);
  672. }
  673. END-OF-FILE
  674.  
  675. if [ "$filename" != "/dev/null" ]
  676. then
  677.   size=`wc -c < $filename`
  678.  
  679.   if [ $size != 1346 ]
  680.   then
  681.     echo $filename changed - should be 1346 bytes, not $size bytes
  682.   fi
  683.  
  684.   chmod 644 $filename
  685. fi
  686.  
  687. # ---------- file src/curses.q ----------
  688.  
  689. filename="src/curses.q"
  690.  
  691. if [ -f $filename ]
  692. then
  693.   echo File \"$filename\" already exists\!  Skipping...
  694.   filename=/dev/null        # throw it away
  695. else
  696.   echo extracting file src/curses.q...
  697. fi
  698.  
  699. cat << 'END-OF-FILE' > $filename
  700. /**             curses.c        **/
  701.  
  702. /**  This library gives programs the ability to easily access the
  703.      termcap information and write screen oriented and raw input
  704.      programs.  The routines can be called as needed, except that
  705.      to use the cursor / screen routines there must be a call to
  706.      InitScreen() first.  The 'Raw' input routine can be used
  707.      independently, however.
  708.  
  709.      Modified 2/86 to work (hopefully) on Berkeley systems.  If
  710.      there are any problems with BSD Unix, please report them to
  711.      the author at hpcnoe!dat@HPLABS (fixed, if possible!)
  712.  
  713.      (C) Copyright 1985 Dave Taylor, HP Colorado Networks
  714. **/
  715.  
  716. #include "headers.h"
  717.  
  718. #ifdef RAWMODE
  719. # ifdef BSD
  720. #  include <sgtty.h>
  721. # else
  722. #  include <termio.h>
  723. # endif
  724. #endif
  725.  
  726. #include <ctype.h>
  727.  
  728. #ifdef BSD
  729. #undef tolower
  730. #endif
  731. #include "curses.h"
  732.  
  733. #ifdef BSD
  734. # include "/usr/include/curses.h"      /* don't ask! */
  735. #endif
  736.  
  737. #ifdef RAWMODE
  738. # define TTYIN    0
  739. #endif
  740.  
  741. extern int debug;
  742.  
  743. #ifdef RAWMODE
  744. #  ifndef BSD
  745.     struct termio _raw_tty, 
  746.                 _original_tty;
  747. #  endif
  748.  
  749. static int _inraw = 0;                  /* are we IN rawmode?    */
  750. static int _line  = -1,            /* initialize to "trash" */
  751.        _col   = -1;
  752.  
  753. #ifdef UTS
  754. static int _clear_screen = 0;        /* Next i/o clear screen? */
  755. static char _null_string[SLEN];        /* a string of nulls...   */
  756. #endif
  757.  
  758. #endif
  759.  
  760. static int _intransmit;            /* are we transmitting keys? */
  761.  
  762. static
  763. char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
  764.      *_setbold, *_clearbold, *_setunderline, *_clearunderline, 
  765.      *_sethalfbright, *_clearhalfbright, *_setinverse, *_clearinverse,
  766.      *_cleartoeoln, *_cleartoeos, *_transmit_on, *_transmit_off;
  767. static
  768. int
  769.      _lines, _columns;
  770.  
  771. static char _terminal[1024];              /* Storage for terminal entry */
  772. static char _capabilities[256];           /* String for cursor motion */
  773.  
  774. static char *ptr = _capabilities;    /* for buffering         */
  775.  
  776. int    outchar();            /* char output for tputs */
  777.  
  778. InitScreen()
  779. {
  780.    /* Set up all this fun stuff: returns zero if all okay, or;
  781.         -1 indicating no terminal name associated with this shell,
  782.         -2..-n  No termcap for this terminal type known
  783.    */
  784.  
  785.    int  tgetent(),      /* get termcap entry */
  786.         error;
  787.    char *tgetstr(),     /* Get termcap capability */
  788.         termname[40];
  789.  
  790. #ifdef SUN
  791.    if (getenv("TERM") == NULL)
  792.      return(-1);
  793. #endif
  794.  
  795. #ifdef UTS
  796.  
  797.     /* use _line for lack of a better variable, what the heck! */
  798.  
  799.     for (_line = 0; _line < SLEN; _line++)
  800.     _null_string[_line] = '\0';
  801. #endif
  802.  
  803.    if (strcpy(termname, getenv("TERM")) == NULL)
  804.      return(-1);
  805.  
  806.    if ((error = tgetent(_terminal, termname)) != 1)
  807.      return(error-2);
  808.  
  809.    _line  =  1;        /* where are we right now?? */
  810.    _col   =  1;        /* assume zero, zero...     */
  811.  
  812.    /* load in all those pesky values */
  813.    _clearscreen       = tgetstr("cl", &ptr);
  814.    _moveto            = tgetstr("cm", &ptr);
  815.    _up                = tgetstr("up", &ptr);
  816.    _down              = tgetstr("do", &ptr);
  817.    _right             = tgetstr("nd", &ptr);
  818.    _left              = tgetstr("bs", &ptr); 
  819.    _setbold           = tgetstr("so", &ptr);
  820.    _clearbold         = tgetstr("se", &ptr);
  821.    _setunderline      = tgetstr("us", &ptr);
  822.    _clearunderline    = tgetstr("ue", &ptr);
  823.    _setinverse        = tgetstr("so", &ptr);
  824.    _clearinverse      = tgetstr("se", &ptr);
  825.    _sethalfbright     = tgetstr("hs", &ptr);
  826.    _clearhalfbright   = tgetstr("he", &ptr);
  827.    _cleartoeoln       = tgetstr("ce", &ptr);
  828.    _cleartoeos        = tgetstr("cd", &ptr);
  829.    _lines          = tgetnum("li");
  830.    _columns          = tgetnum("co");
  831.    _transmit_on          = tgetstr("ks", &ptr);
  832.    _transmit_off      = tgetstr("ke", &ptr);
  833.  
  834.  
  835.    if (!_left) {
  836.       _left = ptr;
  837.       *ptr++ = '\b';
  838.       *ptr++ = '\0';
  839.    }
  840.  
  841. #ifdef BSD
  842.     initscr();    /* initalize curses too! */
  843. #endif
  844.  
  845.    return(0);
  846. }
  847.  
  848. char *return_value_of(termcap_label)
  849. char *termcap_label;
  850. {
  851.     /** This will return the string kept by termcap for the 
  852.         specified capability. Modified to ensure that if 
  853.         tgetstr returns a pointer to a transient address    
  854.         that we won't bomb out with a later segmentation
  855.         fault (thanks to Dave@Infopro for this one!) **/
  856.  
  857.     static char escape_sequence[20];    
  858.  
  859.        char *tgetstr();             /* Get termcap capability */
  860.  
  861.     strcpy(escape_sequence, tgetstr(termcap_label, &ptr));
  862.     return( (char *) escape_sequence);
  863. }
  864.  
  865. transmit_functions(newstate)
  866. int newstate;
  867. {
  868.     /** turn function key transmission to ON | OFF **/
  869.     
  870.     if (newstate != _intransmit) {
  871.       _intransmit = ! _intransmit;
  872.       if (newstate == ON)
  873.            tputs(_transmit_on, 1, outchar);
  874.       else 
  875.            tputs(_transmit_off, 1, outchar);
  876.  
  877.          fflush(stdout);      /* clear the output buffer */
  878.     }
  879. }
  880.  
  881. /****** now into the 'meat' of the routines...the cursor stuff ******/
  882.  
  883. ScreenSize(lines, columns)
  884. int *lines, *columns;
  885. {
  886.     /** returns the number of lines and columns on the display. **/
  887.  
  888.     *lines = _lines - 1;        /* assume index from zero */
  889.     *columns = _columns;
  890. }
  891.  
  892. ClearScreen()
  893. {
  894.         /* clear the screen: returns -1 if not capable */
  895.  
  896. #ifdef UTS
  897.    if (isatube) {
  898.      _clear_screen++;    /* queue up for clearing... */
  899.      return(0);
  900.    }
  901. #endif
  902.  
  903.    if (!_clearscreen) 
  904.      return(-1);
  905.  
  906.    tputs(_clearscreen, 1, outchar);
  907.    fflush(stdout);      /* clear the output buffer */
  908.    return(0);
  909. }
  910.  
  911. MoveCursor(row, col)
  912. int row, col;
  913. {
  914.         /** move cursor to the specified row column on the screen.
  915.             0,0 is the top left! **/
  916.  
  917.            char *tgoto();
  918.        char *stuff;
  919.  
  920.     _line = row;        /* update current location... */
  921.     _col  = col;
  922.  
  923. #ifdef UTS
  924.     if (isatube) {
  925.       at row, col;
  926.       return(0);
  927.     }
  928. #endif
  929.         if (!_moveto) 
  930.           return(-1);
  931.  
  932.         stuff = (char *) tgoto(_moveto, col, row);
  933.     tputs(stuff, 1, outchar);
  934.         fflush(stdout);
  935.         return(0);
  936. }
  937.  
  938.  
  939. CursorUp()
  940. {
  941.         /** move the cursor up one line **/
  942.  
  943.     _line = (_line> 0? _line - 1: _line);    /* up one line... */
  944.  
  945. #ifdef UTS
  946.     if (isatube) {
  947.       at _line, _col;
  948.       return(0);
  949.     }
  950. #endif
  951.         if (!_up)
  952.            return(-1);
  953.  
  954.        tputs(_up, 1, outchar);
  955.     fflush(stdout);
  956.         return(0);
  957. }
  958.  
  959.  
  960. CursorDown()
  961. {
  962.         /** move the cursor down one line **/
  963.  
  964.     _line = (_line< LINES? _line + 1: _line);    /* up one line... */
  965.  
  966. #ifdef UTS
  967.     if (isatube) {
  968.       at _line, _col ;
  969.       return(0);
  970.     }
  971. #endif
  972.  
  973.        if (!_down) 
  974.           return(-1);
  975.  
  976.        tputs(_down, 1, outchar);
  977.        fflush(stdout);
  978.        return(0);
  979. }
  980.  
  981.  
  982. CursorLeft()
  983. {
  984.         /** move the cursor one character to the left **/
  985.  
  986.     _col = (_col > 0? _col - 1: _col);    /* up one line... */
  987.  
  988. #ifdef UTS
  989.     if (isatube) {
  990.       at _line, _col;
  991.       return(0);
  992.     }
  993. #endif
  994.  
  995.        if (!_left) 
  996.           return(-1);
  997.  
  998.        tputs(_left, 1, outchar);
  999.        fflush(stdout);
  1000.        return(0);
  1001. }
  1002.  
  1003.  
  1004. CursorRight()
  1005. {
  1006.         /** move the cursor one character to the right (nondestructive) **/
  1007.  
  1008.     _col = (_col < COLUMNS? _col + 1: _col);    /* up one line... */
  1009.  
  1010. #ifdef UTS
  1011.     if (isatube) {
  1012.       at _line, _col;
  1013.       return(0);
  1014.     }
  1015. #endif
  1016.  
  1017.        if (!_right) 
  1018.           return(-1);
  1019.  
  1020.        tputs(_right, 1, outchar);
  1021.        fflush(stdout);
  1022.        return(0);
  1023. }
  1024.  
  1025.  
  1026. StartBold()
  1027. {
  1028.         /** start boldface/standout mode **/
  1029.  
  1030.        if (!_setbold) 
  1031.          return(-1);
  1032.  
  1033.        tputs(_setbold, 1, outchar);
  1034.        fflush(stdout);
  1035.        return(0);
  1036. }
  1037.  
  1038.  
  1039. EndBold()
  1040. {
  1041.         /** compliment of startbold **/
  1042.  
  1043.         if (!_clearbold) 
  1044.            return(-1);
  1045.  
  1046.        tputs(_clearbold, 1, outchar);
  1047.        fflush(stdout);
  1048.        return(0);
  1049. }
  1050.  
  1051.  
  1052. StartUnderline()
  1053. {
  1054.         /** start underline mode **/
  1055.  
  1056.        if (!_setunderline) 
  1057.           return(-1);
  1058.  
  1059.        tputs(_setunderline, 1, outchar);
  1060.        fflush(stdout);
  1061.        return(0);
  1062. }
  1063.  
  1064.  
  1065. EndUnderline()
  1066. {
  1067.         /** the compliment of start underline mode **/
  1068.  
  1069.        if (!_clearunderline) 
  1070.           return(-1);
  1071.  
  1072.        tputs(_clearunderline, 1, outchar);
  1073.        fflush(stdout);
  1074.        return(0);
  1075. }
  1076.  
  1077.  
  1078. StartHalfbright()
  1079. {
  1080.         /** start half intensity mode **/
  1081.  
  1082.        if (!_sethalfbright) 
  1083.          return(-1);
  1084.  
  1085.        tputs(_sethalfbright, 1, outchar);
  1086.        fflush(stdout);
  1087.        return(0);
  1088. }
  1089.  
  1090. EndHalfbright()
  1091. {
  1092.         /** compliment of starthalfbright **/
  1093.  
  1094.        if (!_clearhalfbright) 
  1095.           return(-1);
  1096.  
  1097.        tputs(_clearhalfbright, 1, outchar);
  1098.        fflush(stdout);
  1099.        return(0);
  1100. }
  1101.  
  1102. StartInverse()
  1103. {
  1104.         /** set inverse video mode **/
  1105.  
  1106.        if (!_setinverse) 
  1107.          return(-1);
  1108.  
  1109.        tputs(_setinverse, 1, outchar);
  1110.        fflush(stdout);
  1111.        return(0);
  1112. }
  1113.  
  1114.  
  1115. EndInverse()
  1116. {
  1117.         /** compliment of startinverse **/
  1118.  
  1119.        if (!_clearinverse) 
  1120.          return(-1);
  1121.  
  1122.        tputs(_clearinverse, 1, outchar);
  1123.        fflush(stdout);
  1124.        return(0);
  1125. }
  1126.  
  1127. PutLine0(x, y, line)
  1128. int x,y;
  1129. char *line;
  1130. {
  1131.     /** Write a zero argument line at location x,y **/
  1132.  
  1133.     _line = x;
  1134.     _col  = y;
  1135.  
  1136. #ifdef UTS
  1137.     if (isatube) {
  1138.       panel (erase=_clear_screen, cursor=_line, _col) {
  1139.         #ON, line, strlen(line)-1#
  1140.       }
  1141.       _clear_screen = 0;
  1142.       _col += (printable_chars(line) - 1);
  1143.       return(0);
  1144.     }
  1145. #endif
  1146.     MoveCursor(x,y);
  1147.     printf("%s", line);    /* to avoid '%' problems */
  1148.     fflush(stdout);
  1149.     _col += (printable_chars(line) - 1);
  1150. }
  1151.  
  1152. PutLine1(x,y, line, arg1)
  1153. int x,y;
  1154. char *line;
  1155. char *arg1;
  1156. {
  1157.     /** write line at location x,y - one argument... **/
  1158.  
  1159.     char buffer[SLEN];
  1160.     
  1161.     sprintf(buffer, line, arg1);
  1162.  
  1163.     PutLine0(x, y, buffer);
  1164. }
  1165.  
  1166. PutLine2(x,y, line, arg1, arg2)
  1167. int x,y;
  1168. char *line;
  1169. char *arg1, *arg2;
  1170. {
  1171.     /** write line at location x,y - one argument... **/
  1172.  
  1173.     char buffer[SLEN];
  1174.     
  1175.     sprintf(buffer, line, arg1, arg2);
  1176.  
  1177.     PutLine0(x, y, buffer);
  1178. }
  1179.  
  1180. PutLine3(x,y, line, arg1, arg2, arg3)
  1181. int x,y;
  1182. char *line;
  1183. char *arg1, *arg2, *arg3;
  1184. {
  1185.     /** write line at location x,y - one argument... **/
  1186.  
  1187.     char buffer[SLEN];
  1188.     
  1189.     sprintf(buffer, line, arg1, arg2, arg3);
  1190.  
  1191.     PutLine0(x, y, buffer);
  1192. }
  1193.  
  1194. CleartoEOLN()
  1195. {
  1196.         /** clear to end of line **/
  1197. #ifdef UTS
  1198.     char buffer[SLEN];
  1199.     register int cols, i = 0;
  1200.  
  1201.     if (isatube) {
  1202.  
  1203.       for (cols = _col; cols < COLUMNS; cols++)
  1204.         buffer[i++] = ' ';
  1205.  
  1206.       buffer[i] = '\0';
  1207.     
  1208.       panel (noerase, cursor=_line, _col) {
  1209.         #ON, buffer, strlen(buffer)-1#
  1210.       }
  1211.     }
  1212. #endif
  1213.  
  1214.        if (!_cleartoeoln) 
  1215.          return(-1);
  1216.  
  1217.        tputs(_cleartoeoln, 1, outchar);
  1218.        fflush(stdout);  /* clear the output buffer */
  1219.        return(0);
  1220. }
  1221.  
  1222. CleartoEOS()
  1223. {
  1224.         /** clear to end of screen **/
  1225.  
  1226. #ifdef UTS
  1227.     register int line_at;
  1228.  
  1229.     for (line_at = _line; line_at < LINES-1; line_at++) {
  1230.       panel (noerase) { 
  1231.         #ON, _null_string, COLUMNS# 
  1232.       }
  1233.     }
  1234.     return(0);
  1235.  
  1236. #endif
  1237.  
  1238.        if (!_cleartoeos) 
  1239.          return(-1);
  1240.  
  1241.        tputs(_cleartoeos, 1, outchar);
  1242.        fflush(stdout);  /* clear the output buffer */
  1243.        return(0);
  1244. }
  1245.  
  1246. #ifdef RAWMODE
  1247.  
  1248. Raw(state)
  1249. int state;
  1250. {
  1251.     /** state is either ON or OFF, as indicated by call **/
  1252.  
  1253.         if (state == OFF && _inraw) {
  1254. #ifdef BSD
  1255.       echo();
  1256.       nocrmode();
  1257. #else
  1258.       (void) ioctl(TTYIN, TCSETAW, &_original_tty);
  1259. #endif
  1260.           _inraw = 0;
  1261.     }
  1262.         else if (state == ON && ! _inraw) {
  1263. #ifdef BSD
  1264.        noecho();
  1265.        crmode();
  1266. #else
  1267.       (void) ioctl(TTYIN, TCGETA, &_original_tty);    /** current setting **/
  1268.           
  1269.       (void) ioctl(TTYIN, TCGETA, &_raw_tty);    /** again! **/
  1270.       _raw_tty.c_iflag &= ~(INLCR | ICRNL |BRKINT);
  1271.       _raw_tty.c_iflag |= IXON;
  1272.       _raw_tty.c_oflag |= OPOST;
  1273.       _raw_tty.c_oflag &= ~(OLCUC | ONLCR | OCRNL | ONOCR | ONLRET);
  1274.       _raw_tty.c_lflag &= ~(ICANON | ECHO);
  1275.       _raw_tty.c_cc[VMIN] = '\01';
  1276.       _raw_tty.c_cc[VTIME] = '\0';
  1277.       (void) ioctl(TTYIN, TCSETAW, &_raw_tty);
  1278. #endif
  1279.  
  1280.           _inraw = 1;
  1281.         }
  1282. }
  1283.  
  1284. int
  1285. ReadCh()
  1286. {
  1287.         /** read a character with Raw mode set! **/
  1288.  
  1289.         register int result;
  1290.         char ch;
  1291.  
  1292.         result = read(0, &ch, 1);
  1293.     
  1294.     return(result == 0? EOF : ch);
  1295. }
  1296.  
  1297. #endif
  1298.  
  1299. outchar(c)
  1300. char c;
  1301. {
  1302.     /** output the given character.  From tputs... **/
  1303.     /** Note: this CANNOT be a macro!              **/
  1304.  
  1305.     putc(c, stdout);
  1306. }
  1307. END-OF-FILE
  1308.  
  1309. if [ "$filename" != "/dev/null" ]
  1310. then
  1311.   size=`wc -c < $filename`
  1312.  
  1313.   if [ $size != 11832 ]
  1314.   then
  1315.     echo $filename changed - should be 11832 bytes, not $size bytes
  1316.   fi
  1317.  
  1318.   chmod 644 $filename
  1319. fi
  1320.  
  1321. # ---------- file src/initialize.uts ----------
  1322.  
  1323. filename="src/initialize.uts"
  1324.  
  1325. if [ -f $filename ]
  1326. then
  1327.   echo File \"$filename\" already exists\!  Skipping...
  1328.   filename=/dev/null        # throw it away
  1329. else
  1330.   echo extracting file src/initialize.uts...
  1331. fi
  1332.  
  1333. sed 's/^X//' << 'END-OF-FILE' > $filename
  1334. XFrom hpccc!mcgregor@hplabs.ARPA Fri May  9 16:05:10 1986
  1335. XReceived: from hplabs.ARPA by hpldat ; Fri, 9 May 86 16:05:01 pdt
  1336. XMessage-Id: <8605092305.AA00689@hpldat>
  1337. XReceived: by hplabs.ARPA ; Fri, 9 May 86 16:01:29 pdt
  1338. XFrom: Scott McGregor <hpccc!mcgregor@hplabs.ARPA>
  1339. XTo: taylor@hplabs
  1340. XDate: Fri, 9 May 86 15:23:16 PDT
  1341. XSubject: initialize.c
  1342. XX-Mailer: msg [version 3.3a]
  1343. X
  1344. X/**        initialize.c        **/
  1345. X
  1346. X/***** Initialize - read in all the defaults etc etc 
  1347. X       (C) Copyright 1985 Dave Taylor
  1348. X*****/
  1349. X
  1350. X#include "headers.h"
  1351. X
  1352. X#ifdef BSD
  1353. X#  include <sgtty.h>
  1354. X#else
  1355. X#  include <termio.h>
  1356. X#endif
  1357. X
  1358. X#include <pwd.h>
  1359. X
  1360. X#ifdef BSD
  1361. X#  include <sys/time.h>
  1362. X#else
  1363. X#  include <time.h>
  1364. X#endif
  1365. X
  1366. X#include <signal.h>
  1367. X#include <ctype.h>
  1368. X#include <errno.h>
  1369. X
  1370. X#ifdef BSD
  1371. X#undef tolower
  1372. X#endif
  1373. X
  1374. X
  1375. Xextern int errno;        /* system error number on failure */
  1376. X
  1377. Xchar *error_name(), *error_description();
  1378. X
  1379. Xchar *expand_logname(), *getenv(), *getlogin();
  1380. X
  1381. Xinitialize(InitScreen_to)
  1382. Xint InitScreen_to;
  1383. X{
  1384. X    struct passwd *pass, *getpwnam();
  1385. X
  1386. X    register int i;
  1387. X    int      quit_signal(), term_signal(), ill_signal(),
  1388. X         fpe_signal(),  bus_signal(),  segv_signal(),
  1389. X             alarm_signal();
  1390. X    char     buffer[SLEN], *cp;
  1391. X    
  1392. X    userid  = getuid();
  1393. X    groupid = getgid();    
  1394. X
  1395. X    strcpy(home,((cp = getenv("HOME")) == NULL)? "" : cp);
  1396. X    strcpy(shell,((cp = getenv("SHELL")) == NULL)? "" : cp);
  1397. X
  1398. X    if (debug) {        /* setup for dprintf statements! */
  1399. X      char filename[SLEN];
  1400. X      sprintf(filename, "%s/%s", home, DEBUG);
  1401. X      if ((debugfile = fopen(filename, "w")) == NULL) {
  1402. X        debug = 0;    /* otherwise 'leave' will try to log! */
  1403. X        leave(fprintf(stderr,"Could not open file %s for debug output!\n",
  1404. X          filename));
  1405. X      }
  1406. X      if (InitScreen_to) {
  1407. X          InitScreen();
  1408. X      }
  1409. X      chown(filename, userid, groupid); /* file owned by user */
  1410. X
  1411. X      fprintf(debugfile, "Debug output of the MSG program.  Version %s\n\n",
  1412. X          VERSION);
  1413. X    }
  1414. X#ifndef UTS
  1415. X    signal(SIGINT,  SIG_IGN);
  1416. X    signal(SIGQUIT, quit_signal);        /* Quit signal                 */
  1417. X    signal(SIGTERM, term_signal);         /* Terminate signal         */
  1418. X    signal(SIGILL,  ill_signal);        /* Illegal instruction      */
  1419. X    signal(SIGFPE,  fpe_signal);        /* Floating point exception */
  1420. X    signal(SIGBUS,  bus_signal);        /* Bus error              */
  1421. X    signal(SIGSEGV, segv_signal);        /* Segmentation Violation   */
  1422. X#endif
  1423. X    signal(SIGALRM, alarm_signal);        /* Process Timer Alarm        */
  1424. X
  1425. X    if (isa3270()) {
  1426. X      isatube++;
  1427. X      dprint0(1, "** We're using a 3270 tube!! **\n");
  1428. X    }
  1429. X
  1430. X#ifndef UTS
  1431. X    get_connections();          /* who do we talk to directly?? */
  1432. X#endif
  1433. X    open_domain_file();        /* if we got it, we want it!  */
  1434. X
  1435. X    get_term_chars();
  1436. X    
  1437. X    gethostname(hostname, sizeof(hostname));
  1438. X    if ((cp = getlogin()) == NULL)
  1439. X      cuserid(username);
  1440. X    else
  1441. X      strcpy(username, cp);
  1442. X
  1443. X    /* now let's get the full username.. */
  1444. X
  1445. X    if ((pass = getpwnam(username)) == NULL) {
  1446. X      error("Couldn't read password entry??");
  1447. X      strcpy(full_username, username);
  1448. X    }
  1449. X    else {
  1450. X      for (i=0; pass->pw_gecos[i] != '\0' && pass->pw_gecos[i] != ',';
  1451. X           i++)
  1452. X          if (pass->pw_gecos[i] == '&') {
  1453. X            full_username[i] = '\0';
  1454. X            strcat(full_username, expand_logname());
  1455. X            i = strlen(full_username) - 2;
  1456. X          }
  1457. X          else
  1458. X            full_username[i] = pass->pw_gecos[i];
  1459. X      full_username[i] = '\0'; 
  1460. X    }
  1461. X
  1462. X    if ((cp = getenv("EDITOR")) == NULL)
  1463. X      strcpy(editor,default_editor);
  1464. X    else
  1465. X      strcpy(editor, cp);
  1466. X
  1467. X    if (! mail_only) {
  1468. X      mailbox[0] = '\0';
  1469. X      strcpy(prefixchars, "> ");     /* default message prefix */
  1470. X    }
  1471. X
  1472. X    read_rc_file();        /* reading the .msgrc next... */
  1473. X
  1474. X    /** now try to expand the specified filename... **/
  1475. X
  1476. X    if (strlen(infile) > 0) {
  1477. X      (void) expand_filename(infile);
  1478. X      if ((errno = can_access(infile, READ_ACCESS))) {
  1479. X        dprint2(1,"Error: given file %s as mailbox - unreadable (%s)!\n", 
  1480. X             infile, error_name(errno));
  1481. X        fprintf(stderr,"Can't open mailbox '%s' for reading!\n", infile);
  1482. X        exit(1);
  1483. X      }
  1484. X    }
  1485. X
  1486. X    /** check to see if the user has defined a LINES or COLUMNS
  1487. X        value different to that in the termcap entry (for
  1488. X        windowing systems, of course!) **/
  1489. X
  1490. X    if ((cp = getenv("LINES")) != NULL && isdigit(*cp)) {
  1491. X      sscanf(cp, "%d", &LINES);
  1492. X      LINES -= 1;    /* kludge for HP Window system? ... */
  1493. X    }
  1494. X
  1495. X    if ((cp = getenv("COLUMNS")) != NULL && isdigit(*cp))
  1496. X      sscanf(cp, "%d", &COLUMNS);
  1497. X
  1498. X    /** fix the shell if needed **/
  1499. X
  1500. X    if (shell[0] != '/') {
  1501. X       sprintf(buffer, "/bin/%s", shell);
  1502. X       strcpy(shell, buffer);
  1503. X    }
  1504. X
  1505. X    if (! mail_only) {
  1506. X      mailbox_defined = (mailbox[0] != '\0'); 
  1507. X
  1508. X      /* get the cursor control keys... */
  1509. X
  1510. X      if ((cp = return_value_of("ku")) == NULL || strlen(cp) != 2)
  1511. X        cursor_control = FALSE;
  1512. X      else {
  1513. X        strcpy(up, cp);
  1514. X        if ((cp = return_value_of("kd")) == NULL || strlen(cp) != 2)
  1515. X          cursor_control = FALSE;
  1516. X        else {
  1517. X          strcpy(down, cp);
  1518. X          cursor_control = TRUE;
  1519. X          transmit_functions(ON);
  1520. X        }
  1521. X      }
  1522. X
  1523. X      strcpy(start_highlight, "->");
  1524. X      end_highlight[0] = '\0';
  1525. X
  1526. X      if (!arrow_cursor) {    /* try to use inverse bar instead */
  1527. X        if ((cp = return_value_of("so")) != NULL) {
  1528. X          strcpy(start_highlight, cp);
  1529. X          if ((cp = return_value_of("se")) == NULL)
  1530. X            strcpy(start_highlight, "->");
  1531. X          else {
  1532. X            strcpy(end_highlight, cp);
  1533. X            has_highlighting = TRUE;
  1534. X          }
  1535. X        }
  1536. X      }
  1537. X    }
  1538. X
  1539. X    if (read_aliases)
  1540. X        read_alias_files();
  1541. X
  1542. X    if (! mail_only) {
  1543. X      if (mini_menu)
  1544. X        headers_per_page = LINES - 13;
  1545. X      else
  1546. X        headers_per_page = LINES -  8;    /* 5 more headers! */
  1547. X
  1548. X      newmbox(1,FALSE, TRUE);    /* read in the mailbox! */
  1549. X    }
  1550. X
  1551. X    init_findnode();    /* set up the path alias stuff */
  1552. X
  1553. X    dprint0(2,"\n-- end of initialization phase --\n");
  1554. X
  1555. X    dprint3(2,"\thostname = %s\n\tusername = %s\n\tfull_username = \"%s\"\n",
  1556. X             hostname, username, full_username);
  1557. X
  1558. X    dprint3(2,"\thome = %s\n\teditor = %s\n\tmailbox = %s\n",
  1559. X         home, editor, mailbox);
  1560. X
  1561. X    dprint3(2,"\tinfile = %s\n\tfolder-dir = %s\n\tprintout = \"%s\"\n",
  1562. X         infile, folders, printout);
  1563. X    
  1564. X    dprint3(2,"\tsavefile = %s\n\tprefix = \"%s\"\n\tshell = %s\n",
  1565. X        savefile, prefixchars, shell);
  1566. X    
  1567. X    dprint0(1,"-- beginning execution phase --\n\n");
  1568. X}
  1569. X
  1570. Xget_term_chars()
  1571. X{
  1572. X    /** This routine sucks out the special terminal characters
  1573. X        ERASE and KILL for use in the input routine.  The meaning 
  1574. X            of the characters are (dare I say it?) fairly obvious... **/
  1575. X
  1576. X#ifdef BSD
  1577. X    struct sgttyb term_buffer;
  1578. X
  1579. X# define TCGETA    TIOCGETP
  1580. X
  1581. X#else 
  1582. X    struct termio term_buffer;
  1583. X#endif
  1584. X
  1585. X    if (ioctl(STANDARD_INPUT, TCGETA, &term_buffer) == -1) {
  1586. X      dprint1(1,"Error: %s encountered on ioctl call (get_term_chars)\n", 
  1587. X           error_name(errno));
  1588. X      /* set to defaults for terminal driver */
  1589. X      backspace = BACKSPACE;
  1590. X      kill_line = ctrl('U');
  1591. X    }
  1592. X    else {
  1593. X#ifdef BSD
  1594. X      backspace = term_buffer.sg_erase;
  1595. X      kill_line = term_buffer.sg_kill;
  1596. X#else
  1597. X      backspace = term_buffer.c_cc[VERASE];
  1598. X      kill_line = term_buffer.c_cc[VKILL];
  1599. X#endif
  1600. X    }
  1601. X}
  1602. X
  1603. Xchar *expand_logname()
  1604. X{
  1605. X    /** Return logname in a nice format (for expanding "&" in the
  1606. X        /etc/passwd file) **/
  1607. X
  1608. X    static char buffer[SLEN];
  1609. X    register int i;
  1610. X
  1611. X    if (strlen(username) == 0)
  1612. X      buffer[0] = '\0';
  1613. X    else {
  1614. X      buffer[0] = toupper(username[0]);
  1615. X
  1616. X      for (i=1; username[i] != '\0'; i++)
  1617. X        buffer[i] = tolower(username[i]);
  1618. X
  1619. X      buffer[i] = '\0';
  1620. X    }
  1621. X
  1622. X    return( (char *) buffer);    
  1623. X}
  1624. X
  1625. END-OF-FILE
  1626.  
  1627. if [ "$filename" != "/dev/null" ]
  1628. then
  1629.   size=`wc -c < $filename`
  1630.  
  1631.   if [ $size != 7197 ]
  1632.   then
  1633.     echo $filename changed - should be 7197 bytes, not $size bytes
  1634.   fi
  1635.  
  1636.   chmod 666 $filename
  1637. fi
  1638.  
  1639. # ---------- file src/edit.c ----------
  1640.  
  1641. filename="src/edit.c"
  1642.  
  1643. if [ -f $filename ]
  1644. then
  1645.   echo File \"$filename\" already exists\!  Skipping...
  1646.   filename=/dev/null        # throw it away
  1647. else
  1648.   echo extracting file src/edit.c...
  1649. fi
  1650.  
  1651. cat << 'END-OF-FILE' > $filename
  1652. /**            edit.c            **/
  1653.  
  1654. /** This routine is for allowing the user to edit their current mailbox
  1655.     as they wish. 
  1656.  
  1657.     (C) Copyright 1986 Dave Taylor
  1658. **/
  1659.  
  1660. #include "headers.h"
  1661. #include <errno.h>
  1662.  
  1663. extern int errno;
  1664.  
  1665. char   *error_name(), *error_description();
  1666.  
  1667. edit_mailbox()
  1668. {
  1669.     /** Allow the user to edit their mailbox, always resynchronizing
  1670.         afterwards.   Due to intense laziness on the part of the
  1671.         programmer, this routine will invoke $EDITOR on the entire
  1672.         file.  The mailer will ALWAYS resync on the mailbox file
  1673.         even if nothing has changed since, not unreasonably, it's
  1674.         hard to figure out what occurred in the edit session...
  1675.     
  1676.         Also note that if the user wants to edit their incoming
  1677.         mailbox they'll actually be editing the tempfile that is
  1678.         an exact copy.  More on how we resync in that case later
  1679.         in this code.
  1680.     **/
  1681.  
  1682.     FILE     *real_mailbox, *temp_mailbox;
  1683.     char     filename[SLEN], buffer[LONG_SLEN], temp_infile[SLEN];
  1684.  
  1685.     PutLine0(LINES-1,0,"invoking editor...");
  1686.  
  1687.     if (mbox_specified == 0)
  1688.       sprintf(filename, "%s%s", temp_mbox, username);
  1689.     else
  1690.       strcpy(filename, infile);
  1691.  
  1692.     sprintf(buffer, "%s %s", editor, filename);
  1693.  
  1694.     Raw(OFF);
  1695.  
  1696.     if (system_call(buffer, SH) != 0) {
  1697.       error1("Problems invoking editor %s!", editor);
  1698.       Raw(ON);
  1699.       sleep(2);
  1700.       return(0);
  1701.     }
  1702.  
  1703.     Raw(ON);
  1704.  
  1705.     if (mbox_specified == 0) {    /* uh oh... now the toughie...  */
  1706.  
  1707.       sprintf(temp_infile, "%s%s.temp", mailhome, username);
  1708.       unlink(temp_infile);    /* remove it if it's there... */
  1709.  
  1710.       if (bytes(infile) != mailfile_size) {
  1711.  
  1712.          /* SIGH.  We've received mail since we invoked the editor
  1713.         on the mailbox.  We'll have to do some strange stuff to
  1714.             remedy the problem... */
  1715.  
  1716.          PutLine0(LINES, 0, "Warning: new mail received...");
  1717.          CleartoEOLN();
  1718.  
  1719.          if ((temp_mailbox = fopen(filename, "a")) == NULL) {
  1720.         dprint2(1, "Attempt to open %s to append failed! (%s)\n", 
  1721.             filename, "edit_mailbox");
  1722.            set_error("Couldn't reopen tempfile.  Edit LOST!");
  1723.            return(1);
  1724.          }
  1725.          /** Now let's lock the mailbox up and stream the new stuff 
  1726.          into the temp file... **/
  1727.  
  1728.          lock();    
  1729.          if ((real_mailbox = fopen(infile, "r")) == NULL) {
  1730.            dprint2(1, 
  1731.                "Attempt to open %s for reading new mail failed! (%s)\n",
  1732.               infile, "edit_mailbox");
  1733.            sprintf(buffer, "Couldn't open %s for reading!  Edit LOST!", 
  1734.                infile);
  1735.            set_error(buffer);
  1736.            unlock();
  1737.            return(1);
  1738.          }
  1739.          if (fseek(real_mailbox, mailfile_size, 0) != 0) {
  1740.            dprint2(1, "Couldn't seek to end of infile (offset %ld) (%s)\n",
  1741.             mailfile_size, "edit_mailbox");
  1742.            set_error("Couldn't seek to end of mailbox.  Edit LOST!");
  1743.            unlock();
  1744.            return(1);
  1745.          }
  1746.     
  1747.          /** Now we can finally stream the new mail into the tempfile **/
  1748.  
  1749.          while (fgets(buffer, LONG_SLEN, real_mailbox) != NULL)
  1750.            fprintf(temp_mailbox, "%s", buffer);
  1751.  
  1752.          fclose(real_mailbox);
  1753.          fclose(temp_mailbox);
  1754.         }
  1755.        else
  1756.          lock();    /* create a lock file if we're replacing mailbox */
  1757.  
  1758.        /** link to the temporary mailbox in the mailhome directory... **/
  1759.  
  1760.        if (link(filename, temp_infile) != 0) 
  1761.          if (errno == EXDEV) {   /* attempt to link across file systems */
  1762.               if (copy(filename, temp_infile) != 0) {
  1763.              error("Couldn't copy temp file to mailbox!");
  1764.             emergency_exit();
  1765.            }
  1766.          }
  1767.          else {
  1768.         Write_to_screen("\n\rCouldn't link %s to mailfile %s...\n\r",2,
  1769.             filename, temp_infile);
  1770.         Write_to_screen("** %s - %s **\n\r", 2,
  1771.             error_name(errno), error_description(errno));
  1772.             emergency_exit();
  1773.          }
  1774.     
  1775.        /***  G U L P ... let's remove the incoming mail file... ***/
  1776.          
  1777.        unlink(infile);
  1778.  
  1779.        /** and quickly now... **/
  1780.  
  1781.        if (link(temp_infile, infile) != 0) {
  1782.          Write_to_screen(
  1783.             "\n\rCouldn't internally link %s to mailfile %s...\n\r",
  1784.             2, temp_infile, infile);
  1785.          Write_to_screen(
  1786.             "\n\rYou'll need to check out %s for your mail...\n\r",
  1787.             1, temp_infile);
  1788.          Write_to_screen("** %s - %s **\n\r", 2,
  1789.             error_name(errno), error_description(errno));
  1790.          emergency_exit();
  1791.        }
  1792.  
  1793.        /** And let's remove the lock file!  We're DONE!!!  **/
  1794.  
  1795.        unlock();
  1796.        unlink(temp_infile);    /* remove the temp file too */
  1797.        error("edit changes incorporated into new mail...");
  1798.     }
  1799.     else
  1800.       error("Resynchronizing with new version of mailbox...");
  1801.  
  1802.     sleep(2);
  1803.     resync();
  1804.  
  1805.     return(1);
  1806. }
  1807. END-OF-FILE
  1808.  
  1809. if [ "$filename" != "/dev/null" ]
  1810. then
  1811.   size=`wc -c < $filename`
  1812.  
  1813.   if [ $size != 4451 ]
  1814.   then
  1815.     echo $filename changed - should be 4451 bytes, not $size bytes
  1816.   fi
  1817.  
  1818.   chmod 644 $filename
  1819. fi
  1820.  
  1821. # ---------- file src/errno.c ----------
  1822.  
  1823. filename="src/errno.c"
  1824.  
  1825. if [ -f $filename ]
  1826. then
  1827.   echo File \"$filename\" already exists\!  Skipping...
  1828.   filename=/dev/null        # throw it away
  1829. else
  1830.   echo extracting file src/errno.c...
  1831. fi
  1832.  
  1833. cat << 'END-OF-FILE' > $filename
  1834. /**        errno.c            **/
  1835.  
  1836. /** This routine maps error numbers to error names and error messages.
  1837.     These are all directly ripped out of the include file errno.h, and
  1838.     are HOPEFULLY standardized across the different breeds of Unix!!
  1839.  
  1840.     If (alas) yours are different, you should be able to use awk to
  1841.     mangle your errno.h file quite simply...
  1842.  
  1843.    (C) Copyright 1986 Dave Taylor
  1844. **/
  1845.  
  1846. #include "headers.h"
  1847.  
  1848. char *err_name[] = { 
  1849. /* 0 */            "NOERROR", "No error status currently",
  1850. /* 1 */        "EPERM",   "Not super-user",
  1851. /* 2 */        "ENOENT",  "No such file or directory",
  1852. /* 3 */        "ESRCH",   "No such process",
  1853. /* 4 */        "EINTR",   "Interrupted system call",
  1854. /* 5 */        "EIO",     "I/O error",
  1855. /* 6 */        "ENXIO",   "No such device or address",
  1856. /* 7 */        "E2BIG",   "Arg list too long",
  1857. /* 8 */        "ENOEXEC", "Exec format error",
  1858. /* 9 */        "EBADF",   "Bad file number",
  1859. /* 10 */    "ECHILD",  "No children",
  1860. /* 11 */    "EAGAIN",  "No more processes",
  1861. /* 12 */    "ENOMEM",  "Not enough core",
  1862. /* 13 */    "EACCES",  "Permission denied",
  1863. /* 14 */    "EFAULT",  "Bad address",
  1864. /* 15 */    "ENOTBLK", "Block device required",
  1865. /* 16 */    "EBUSY",   "Mount device busy",
  1866. /* 17 */    "EEXIST",  "File exists",
  1867. /* 18 */    "EXDEV",   "Cross-device link",
  1868. /* 19 */    "ENODEV",  "No such device",
  1869. /* 20 */    "ENOTDIR", "Not a directory",
  1870. /* 21 */    "EISDIR",  "Is a directory",
  1871. /* 22 */    "EINVAL",  "Invalid argument",
  1872. /* 23 */    "ENFILE",  "File table overflow",
  1873. /* 24 */    "EMFILE",  "Too many open files",
  1874. /* 25 */    "ENOTTY",  "Not a typewriter",
  1875. /* 26 */    "ETXTBSY", "Text file busy",
  1876. /* 27 */    "EFBIG",   "File too large",
  1877. /* 28 */    "ENOSPC",  "No space left on device",
  1878. /* 29 */    "ESPIPE",  "Illegal seek",
  1879. /* 30 */    "EROFS",   "Read only file system",
  1880. /* 31 */    "EMLINK",  "Too many links",
  1881. /* 32 */    "EPIPE",   "Broken pipe",
  1882. /* 33 */    "EDOM",    "Math arg out of domain of func",
  1883. /* 34 */    "ERANGE",  "Math result not representable",
  1884. /* 35 */    "ENOMSG",  "No message of desired type",
  1885. /* 36 */    "EIDRM",   "Identifier removed"
  1886.     };
  1887.  
  1888. char *error_name(errnumber)
  1889. int errnumber;
  1890. {
  1891.     static char buffer[50];
  1892.  
  1893.     dprint1(1,"Error Name called with error %d\n", errnumber);
  1894.  
  1895.     if (errnumber < 0 || errnumber > 36) 
  1896.       sprintf(buffer,"ERR-UNKNOWN (%d)", errnumber);
  1897.     else
  1898.       strcpy(buffer, err_name[2*errnumber]);
  1899.  
  1900.     return( (char *) buffer);
  1901. }
  1902.  
  1903. char *error_description(errnumber)
  1904. int errnumber;
  1905. {
  1906.     static char buffer[50];
  1907.  
  1908.     dprint1(1,"Error Description called with error %d\n", errnumber);
  1909.  
  1910.     if (errnumber < 0 || errnumber > 36) 
  1911.       sprintf(buffer,"Unknown error - %d - No description", errnumber);
  1912.     else
  1913.       strcpy(buffer, err_name[2*errnumber + 1]);
  1914.  
  1915.     return ( (char *) buffer);
  1916. }
  1917. END-OF-FILE
  1918.  
  1919. if [ "$filename" != "/dev/null" ]
  1920. then
  1921.   size=`wc -c < $filename`
  1922.  
  1923.   if [ $size != 2612 ]
  1924.   then
  1925.     echo $filename changed - should be 2612 bytes, not $size bytes
  1926.   fi
  1927.  
  1928.   chmod 644 $filename
  1929. fi
  1930.  
  1931. # ---------- file src/sort.c ----------
  1932.  
  1933. filename="src/sort.c"
  1934.  
  1935. if [ -f $filename ]
  1936. then
  1937.   echo File \"$filename\" already exists\!  Skipping...
  1938.   filename=/dev/null        # throw it away
  1939. else
  1940.   echo extracting file src/sort.c...
  1941. fi
  1942.  
  1943. cat << 'END-OF-FILE' > $filename
  1944. /**            sort.c                **/
  1945.  
  1946. /** Sort mailbox header table by the field specified in the global
  1947.     variable "sortby"...if we're sorting by something other than
  1948.     the default SENT_DATE, also put some sort of indicator on the
  1949.     screen.
  1950.  
  1951.     (C) Copyright 1986, Dave Taylor
  1952. **/
  1953.  
  1954. #include "headers.h"
  1955.  
  1956. char *sort_name();
  1957.  
  1958. sort_mailbox(entries, visible)
  1959. int entries, visible;
  1960. {
  1961.     /** Sort the header_table definitions... If 'visible', then
  1962.         put the status lines etc **/
  1963.     
  1964.     int last_index = -1;
  1965.     int compare_headers();    /* for sorting */
  1966.  
  1967.     dprint1(2,"\n** sorting mailbox by %s **\n\n", sort_name(FALSE));
  1968.  
  1969.     if (entries > 0)
  1970.       last_index = header_table[current-1].index_number;
  1971.  
  1972.     if (entries > 30 && visible)  
  1973.       error1("sorting messages by %s", sort_name(FALSE));
  1974.     
  1975.     qsort(header_table, entries, sizeof (struct header_rec), 
  1976.           compare_headers);
  1977.  
  1978.     if (last_index > -1)
  1979.       find_old_current(last_index);
  1980.  
  1981.     clear_error();
  1982. }
  1983.  
  1984. int
  1985. compare_headers(first, second)
  1986. struct header_rec *first, *second;
  1987. {
  1988.     /** compare two headers according to the sortby value.
  1989.  
  1990.         Sent Date uses a routine to compare two dates,
  1991.         Received date is keyed on the file offsets (think about it)
  1992.         Sender uses the truncated from line, same as "build headers",
  1993.         and size and subject are trivially obvious!!
  1994.      **/
  1995.  
  1996.     char from1[SLEN], from2[SLEN];    /* sorting buffers... */
  1997.     int  sign = 1;
  1998.  
  1999.     
  2000.     if (sortby < 0)
  2001.       sign = -1;
  2002.  
  2003.     switch (abs(sortby)) {
  2004.  
  2005.       case SENT_DATE : return( sign*compare_dates(first, second) );
  2006.  
  2007.       case RECEIVED_DATE: return ( 
  2008.            sign*(first->index_number - second->index_number) );
  2009.  
  2010.       case SENDER    : tail_of(first->from, from1, TRUE);
  2011.                tail_of(second->from, from2, TRUE);
  2012.                  return( sign*strcmp(from1, from2));
  2013.  
  2014.       case SIZE      : return( sign*(first->lines - second->lines));
  2015.  
  2016.       case SUBJECT   : return( sign*strcmp(first->subject,second->subject));
  2017.  
  2018.       case STATUS    : return( sign*(first->status - second->status));
  2019.     }
  2020. }
  2021.  
  2022. char *sort_name(pad)
  2023. int pad;
  2024. {
  2025.     /** return the name of the current sort option...
  2026.         If 'pad' is set, then ensure all are the same length by
  2027.         using trailing spaces... 
  2028.     **/
  2029.  
  2030.     if (sortby < 0) {
  2031.       switch (- sortby) {
  2032.         case SENT_DATE    : return( 
  2033.                       pad?     "Reverse Date Mail Sent  " : 
  2034.                        "Reverse Date Mail Sent");
  2035.         case RECEIVED_DATE: return("Reverse Date Mail Rec'vd");
  2036.         case SENDER       : return(
  2037.                   pad?     "Reverse Message Sender  " : 
  2038.                        "Reverse Message Sender");
  2039.         case SIZE         : return("Reverse Lines in Message");
  2040.         case SUBJECT      : return(
  2041.                   pad?     "Reverse Message Subject " : 
  2042.                        "Reverse Message Subject");
  2043.         case STATUS          : return(
  2044.                   pad?     "Reverse Message Status  " :
  2045.                            "Reverse Message Status");
  2046.       }
  2047.     }
  2048.     else {
  2049.       switch (sortby) {
  2050.         case SENT_DATE    : return( 
  2051.                         pad?   "Date Mail Sent          " : 
  2052.                        "Date Mail Sent");
  2053.         case RECEIVED_DATE: return(
  2054.                             pad?   "Date Mail Rec'vd        " :
  2055.                                    "Date Mail Rec'vd");
  2056.         case SENDER       : return(
  2057.                     pad?   "Message Sender          " : 
  2058.                        "Message Sender");
  2059.         case SIZE         : return(
  2060.                     pad?   "Lines in Message        " :
  2061.                            "Lines in Message");
  2062.         case SUBJECT      : return(
  2063.                     pad?   "Message Subject         " : 
  2064.                        "Message Subject");
  2065.         case STATUS          : return(
  2066.                   pad?     "Message Status          " :
  2067.                            "Message Status");
  2068.       }
  2069.     }
  2070.  
  2071.     return("*UNKNOWN-SORT-PARAMETER*");
  2072. }
  2073.  
  2074. find_old_current(index)
  2075. int index;
  2076. {
  2077.     /** Set current to the message that has "index" as it's 
  2078.         index number.  This is to track the current message
  2079.         when we resync... **/
  2080.  
  2081.     register int i;
  2082.  
  2083.     dprint1(2,"find-old-current(%d)\n", index);
  2084.  
  2085.     for (i = 0; i < message_count; i++)
  2086.       if (header_table[i].index_number == index) {
  2087.         current = i+1;
  2088.         dprint1(2,"\tset current to %d!\n", current);
  2089.         return;
  2090.       }
  2091.  
  2092.     dprint1(2,"\tcouldn't find current index.  Current left as %d\n",
  2093.         current);
  2094.     return;        /* can't be found.  Leave it alone, then */
  2095. }
  2096. END-OF-FILE
  2097.  
  2098. if [ "$filename" != "/dev/null" ]
  2099. then
  2100.   size=`wc -c < $filename`
  2101.  
  2102.   if [ $size != 4136 ]
  2103.   then
  2104.     echo $filename changed - should be 4136 bytes, not $size bytes
  2105.   fi
  2106.  
  2107.   chmod 666 $filename
  2108. fi
  2109.  
  2110. # ---------- file src/showmsg_cmd.c ----------
  2111.  
  2112. filename="src/showmsg_cmd.c"
  2113.  
  2114. if [ -f $filename ]
  2115. then
  2116.   echo File \"$filename\" already exists\!  Skipping...
  2117.   filename=/dev/null        # throw it away
  2118. else
  2119.   echo extracting file src/showmsg_cmd.c...
  2120. fi
  2121.  
  2122. cat << 'END-OF-FILE' > $filename
  2123. /**            showmsg_cmd.c            **/
  2124.  
  2125. /** This is an interface for the showmsg command line.  The possible
  2126.     functions that could be invoked from the showmsg command line are
  2127.     almost as numerous as those from the main command line and include
  2128.     the following;
  2129.  
  2130.        |    = pipe this message to command...
  2131.        !    = call Unix command
  2132.        <    = scan message for calendar info
  2133.        b    = bounce (remail) message
  2134.        d    = mark message for deletion
  2135.        e    = edit entire mailbox
  2136.        f    = forward message
  2137.        g    = group reply
  2138.        j,n  = move to body of next message
  2139.        k    = move to body of previous message
  2140.        p    = print this (all tagged) message
  2141.        r    = reply to this message
  2142.        s    = save this message to a maibox/folder 
  2143.        t    = tag this message
  2144.        x    = Exit Elm NOW
  2145.  
  2146.     all commands not explicitly listed here are returned as unprocessed
  2147.     to be dealt with at the main command level.
  2148.  
  2149.     This function returns 0 if it dealt with the command, or the command
  2150.     otherwise.
  2151. **/
  2152.  
  2153. #include "headers.h"
  2154.  
  2155. process_showmsg_command(command)
  2156. char command;
  2157. {
  2158.     switch (command) {
  2159.       case '|' : clear_bottom_of_screen();
  2160.              PutLine0(LINES-3,0,"Command: pipe");
  2161.              softkeys_off();
  2162.              (void) pipe();    /* do pipe regardless */
  2163.              softkeys_on();
  2164.              return(0);        /* must have new screen */
  2165.  
  2166.       case '!' : clear_bottom_of_screen();
  2167.              PutLine0(LINES-3,0,"Command: system call");
  2168.              softkeys_off();
  2169.              (void) subshell();    /* do shell regardless */
  2170.              softkeys_on();
  2171.              return(0);        /* must have new screen */
  2172.  
  2173.       case '<' : 
  2174. #ifdef ENABLE_CALENDAR
  2175.              scan_calendar();
  2176. #else
  2177.              error("can't scan for calendar entries!");
  2178. #endif
  2179.             break;
  2180.  
  2181.       case 'b' : clear_bottom_of_screen();
  2182.              PutLine0(LINES-3,0,"Command: bounce message");
  2183.              remail();
  2184.              return(0);        /* must have new screen */
  2185.  
  2186.       case 'd' : delete(TRUE);
  2187.              break;
  2188.  
  2189.       case 'e' : edit_mailbox();
  2190.              return(0);        /* must have new screen */
  2191.  
  2192.       case 'f' : clear_bottom_of_screen();
  2193.              PutLine0(LINES-3,0,"Command: forward message");
  2194.              (void) forward();
  2195.              return(0);        /* must have new screen */
  2196.  
  2197.       case 'g' : clear_bottom_of_screen();
  2198.              PutLine0(LINES-3,0,"Command: group reply");
  2199.              (void) reply_to_everyone();
  2200.              return(0);        /* must have new screen */
  2201.  
  2202.       case 'j' :
  2203.       case 'n' : if (current < message_count)
  2204.                show_msg(++current);
  2205.              return(0);    
  2206.  
  2207.       case 'k' : if (current > 0)
  2208.                show_msg(--current);
  2209.              return(0);
  2210.  
  2211.  
  2212.       case 'p' : printmsg();    
  2213.              break;
  2214.  
  2215.       case 'r' : clear_bottom_of_screen();
  2216.              PutLine0(LINES-3,0,"Command: reply to message");
  2217.              (void) reply();
  2218.              return(0);        /* must have new screen */
  2219.  
  2220.       case 's' : clear_bottom_of_screen();
  2221.              PutLine0(LINES-3,0,"Command: save message");
  2222.              (void) save();
  2223.              break;
  2224.  
  2225.       case 't' : tag_message();    
  2226.              break;
  2227.  
  2228.       case 'x' : leave();
  2229.  
  2230.       case '\n':
  2231.       case '\r': return(0);        /* avoid <return> looping */
  2232.  
  2233.       default  : return(command);    /* couldn't deal with it! */
  2234.     }
  2235.  
  2236.     return(1);    /* done with it! */
  2237. }
  2238.  
  2239. clear_bottom_of_screen()
  2240. {
  2241.     /** clear the last 4 lines of the screen... **/
  2242.  
  2243.     MoveCursor(LINES-4, 0);
  2244.     CleartoEOS();
  2245. }
  2246. END-OF-FILE
  2247.  
  2248. if [ "$filename" != "/dev/null" ]
  2249. then
  2250.   size=`wc -c < $filename`
  2251.  
  2252.   if [ $size != 3188 ]
  2253.   then
  2254.     echo $filename changed - should be 3188 bytes, not $size bytes
  2255.   fi
  2256.  
  2257.   chmod 666 $filename
  2258. fi
  2259.  
  2260. echo end of this archive file....
  2261. exit 0
  2262.  
  2263.