home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / APPS / elm.lzh / ELM / SRC / ALIAS.C < prev    next >
Text File  |  1991-01-11  |  19KB  |  732 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: alias.c,v 4.1.1.1 90/06/05 21:20:26 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 4.1.1.1 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1986, 1987 Dave Taylor
  8.  *             Copyright (c) 1988, 1989, 1990 USENET Community Trust
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log:    alias.c,v $
  17.  * Revision 4.1.1.1  90/06/05  21:20:26  syd
  18.  * Make temp file name less than 14 chars to allow deleting
  19.  * aliases on a 14 char limit file system
  20.  * From: Syd
  21.  * 
  22.  * Revision 4.1  90/04/28  22:42:25  syd
  23.  * checkin of Elm 2.3 as of Release PL0
  24.  * 
  25.  *
  26.  ******************************************************************************/
  27.  
  28. /** This file contains alias stuff
  29.  
  30. **/
  31.  
  32. #include "headers.h"
  33. #include <errno.h>
  34. #include <ctype.h>
  35. #include <sys/types.h>
  36. #include <sys/stat.h>
  37.  
  38. #ifdef BSD
  39. #undef        tolower
  40. #endif
  41.  
  42. #define    ECHOIT    1     /* echo on for prompting */
  43.  
  44. char *get_alias_address();
  45. char *error_name(), *error_description(), *strip_parens(), *index();
  46.  
  47. extern int errno;
  48.  
  49. #ifndef DONT_TOUCH_ADDRESSES
  50. char *expand_system();
  51.  
  52. extern int  findnode_has_been_initialized;
  53. #endif
  54.  
  55. int
  56. ok_alias_name(name)
  57. char *name;
  58. {
  59.     while ( *name != '\0' && ok_alias_char(*name) )
  60.       ++name;
  61.     return ( *name == '\0' );
  62. }
  63.  
  64.  
  65. read_alias_files()
  66. {
  67.     /** read the system and user alias files, if present, and if they
  68.         have changed since last we read them.
  69.     **/
  70.  
  71.     read_system_aliases();
  72.     read_user_aliases();
  73. }
  74.  
  75. read_system_aliases()
  76. {
  77.     /** read the system alias file, if present,
  78.         and if it has changed since last we read it.
  79.     **/
  80.  
  81.     struct stat hst;
  82.     static time_t system_ctime, system_mtime;
  83.  
  84.     /* If hash file hasn't changed, don't bother re-reading. */
  85.  
  86.     if (system_data != -1
  87.      && stat(system_hash_file, &hst) == 0
  88.      && hst.st_ctime == system_ctime
  89.      && hst.st_mtime == system_mtime)
  90.       return;
  91.  
  92.     /* Close system data file if it was open. */
  93.  
  94.     if (system_data != -1) {
  95.       close(system_data);
  96.       system_data = -1;
  97.     }
  98.  
  99.     /* Read system hash table.  If we can't, just return. */
  100.  
  101.     if (read_hash_file(system_hash_file, (char *) system_hash_table,
  102.                 sizeof system_hash_table) < 0)
  103.       return;
  104.  
  105.     /* Open system data table. */
  106.  
  107.     if ((system_data = open(system_data_file, O_RDONLY)) == -1) {
  108.       dprint(1, (debugfile,
  109.               "Warning: Can't open system alias data file %s\n",
  110.               system_data_file));
  111.       return;
  112.     }
  113.  
  114.     /* Remember hash file times. */
  115.  
  116.     system_ctime = hst.st_ctime;
  117.     system_mtime = hst.st_mtime;
  118. }
  119.  
  120. read_user_aliases()
  121. {
  122.     /** read the system alias file, if present,
  123.         and if it has changed since last we read it.
  124.     **/
  125.  
  126.     struct stat hst;
  127.     char fname[SLEN];
  128.     static time_t user_ctime, user_mtime;
  129.  
  130.     /* If hash file hasn't changed, don't bother re-reading. */
  131.  
  132.     sprintf(fname, "%s/%s", home, ALIAS_HASH);
  133.  
  134.     if (user_data != -1
  135.      && stat(fname, &hst) == 0
  136.      && hst.st_ctime == user_ctime
  137.      && hst.st_mtime == user_mtime)
  138.       return;
  139.  
  140.     /* Close user data file if it was open. */
  141.  
  142.     if (user_data != -1) {
  143.       close(user_data);
  144.       user_data = -1;
  145.     }
  146.  
  147.     /* Read user hash table.  If we can't, just return. */
  148.  
  149.     if (read_hash_file(fname, (char *) user_hash_table,
  150.                   sizeof user_hash_table) < 0)
  151.       return;
  152.  
  153.     /* Open user data table. */
  154.  
  155.     sprintf(fname, "%s/%s", home, ALIAS_DATA);
  156.     if ((user_data = open(fname, O_RDONLY)) == -1) {
  157.       dprint(1, (debugfile,
  158.          "Warning: Can't open user alias data file %s\n", fname));
  159.       return;
  160.     }
  161.  
  162.     /* Remember hash file times. */
  163.  
  164.     user_ctime = hst.st_ctime;
  165.     user_mtime = hst.st_mtime;
  166. }
  167.  
  168. int
  169. read_hash_file(file, table, table_size)
  170. char *file, *table;
  171. int table_size;
  172. {
  173.     /** read the specified alias hash file into the specified table.
  174.         it must be _exactly_ the right size or forget it.
  175.     **/
  176.  
  177.     struct stat st;
  178.     int hash;
  179.  
  180.     /* Open the hash file. */
  181.  
  182.     if ((hash = open(file, O_RDONLY)) == -1) {
  183.       dprint(2, (debugfile,
  184.         "Warning: Can't open alias hash file %s\n", file));
  185.       return -1;
  186.     }
  187.  
  188.     /* Be sure the hash file is the correct size. */
  189.  
  190.     if (fstat(hash, &st) == 0 && st.st_size != table_size) {
  191.       dprint(2, (debugfile,
  192.         "Warning: Alias hash file %s is wrong size (%ld/%d)\n",
  193.         file, st.st_size, table_size));
  194.       close(hash);
  195.       return -1;
  196.     }
  197.  
  198.     /* Read the hash file into memory. */
  199.  
  200.     if (read(hash, (char *) table, table_size) != table_size) {
  201.       dprint(2, (debugfile,
  202.         "Warning: Can't read alias hash file %s\n", file));
  203.       close(hash);
  204.       return -1;
  205.     }
  206.  
  207.     /* Close the hash file; return success. */
  208.  
  209.     close(hash);
  210.     return 0;
  211. }
  212.  
  213. int
  214. add_alias()
  215. {
  216.     /** add an alias to the user alias text file.  Return zero 
  217.         if alias not added in actuality **/
  218.  
  219.     char name[SLEN], *address, address1[LONG_STRING], buffer[LONG_STRING];
  220.     char comment[SLEN], ch;
  221.     char *strcpy();
  222.  
  223.     strcpy(buffer, "Enter alias name: ");
  224.     PutLine0(LINES-2,0, buffer);
  225.     CleartoEOLN();
  226.     *name = '\0';
  227.     optionally_enter(name, LINES-2, strlen(buffer), FALSE, FALSE);
  228.     if (strlen(name) == 0) 
  229.       return(0);
  230.         if ( !ok_alias_name(name) ) {
  231.       error1("Bad character(s) in alias name %s.", name);
  232.       return(0);
  233.     }
  234.     if ((address = get_alias_address(name, FALSE)) != NULL) {
  235.       dprint(3, (debugfile, 
  236.          "Attempt to add a duplicate alias [%s] in add_alias\n",
  237.          address)); 
  238.       if (address[0] == '!') {
  239.         address[0] = ' ';
  240.         error1("Already a group with name %s.", address);
  241.       }
  242.       else
  243.         error1("Already an alias for %s.", address);
  244.       return(0);
  245.     }
  246.  
  247.     sprintf(buffer, "Enter full name for %s: ", name);
  248.     PutLine0(LINES-2,0, buffer);
  249.     CleartoEOLN();
  250.     *comment = '\0';
  251.     optionally_enter(comment, LINES-2, strlen(buffer), FALSE, FALSE);
  252.     if (strlen(comment) == 0) strcpy(comment, name);  
  253.  
  254.     sprintf(buffer, "Enter address for %s: ", name);
  255.     PutLine0(LINES-2,0, buffer);
  256.     CleartoEOLN();
  257.     *address1 = '\0';
  258.     optionally_enter(address1, LINES-2, strlen(buffer), FALSE, FALSE);
  259.     Raw(ON);
  260.     if (strlen(address1) == 0) {
  261.       error("No address specified!");
  262.       return(0);
  263.     }
  264.     PutLine3(LINES-2,0,"%s (%s) = %s", comment, name, address1);
  265.     CleartoEOLN();
  266.     if((ch = want_to("Accept new alias? (y/n) ",'y')) == 'y')
  267.       add_to_alias_text(name, comment, address1);
  268.     ClearLine(LINES-2);
  269.     return(ch == 'y' ? 1 : 0);
  270. }
  271.  
  272. int
  273. delete_alias()
  274. {
  275.     /** delete an alias from the user alias text file.  Return zero 
  276.         if alias not deleted in actuality **/
  277.  
  278.     char name[SLEN], *address, buffer[LONG_STRING];
  279.     char *strcpy();
  280.  
  281.     strcpy(buffer, "Enter alias name for deletion: ");
  282.     PutLine0(LINES-2,0, buffer);
  283.     CleartoEOLN();
  284.     *name = '\0';
  285.     optionally_enter(name, LINES-2, strlen(buffer), FALSE, FALSE);
  286.     if (strlen(name) == 0) 
  287.       return(0);
  288.         if ((address = get_alias_address(name, FALSE))!=NULL)
  289.         {
  290.                 if (address[0] == '!')
  291.                 {
  292.                   address[0] = ' ';
  293.                   PutLine1(LINES-1,0,"Group alias: %-60.60s", address);
  294.                   CleartoEOLN();
  295.             }
  296.         else
  297.           PutLine1(LINES-1,0,"Aliased address: %-60.60s", address);
  298.     }
  299.         else 
  300.     {
  301.           dprint(3, (debugfile, 
  302.          "Attempt to delete a non-existent alias [%s] in delete_alias\n",
  303.          name)); 
  304.          error1("No alias for %s.", name);
  305.           return(0);
  306.     }
  307.     if (want_to("Delete this alias? (y/n) ", 'y') == 'y')
  308.     {
  309.         if (!delete_from_alias_text(name))
  310.         {
  311.             CleartoEOS();
  312.             return(1);
  313.         }
  314.     }
  315.     CleartoEOS();
  316.     return(0);
  317. }
  318.  
  319. int
  320. add_current_alias()
  321. {
  322.     /** alias the current message to the specified name and
  323.         add it to the alias text file, for processing as
  324.         the user leaves the program.  Returns non-zero iff
  325.         alias actually added to file **/
  326.  
  327.     char name[SLEN], address1[LONG_STRING], buffer[LONG_STRING], *address;
  328.     char comment[SLEN], ch;
  329.     struct header_rec *current_header;
  330.  
  331.     if (current == 0) {
  332.      dprint(4, (debugfile, 
  333.         "Add current alias called without any current message!\n"));
  334.      error("No message to alias to!");
  335.      return(0);
  336.     }
  337.     current_header = headers[current - 1];
  338.     
  339.     strcpy(buffer, "Current message address aliased to: ");
  340.     PutLine0(LINES-2,0, buffer);
  341.     CleartoEOLN();
  342.     *name = '\0';
  343.     optionally_enter(name, LINES-2, strlen(buffer), FALSE, FALSE);
  344.     if (strlen(name) == 0)    /* cancelled... */
  345.       return(0);
  346.         if ( !ok_alias_name(name) ) {
  347.       error1("Bad character(s) in alias name %s.", name);
  348.       return(0);
  349.     }
  350.     if ((address = get_alias_address(name, FALSE)) != NULL) {
  351.      dprint(3, (debugfile,
  352.              "Attempt to add a duplicate alias [%s] in add_current_alias\n",
  353.          address)); 
  354.       if (address[1] == '!') {
  355.         address[0] = ' ';
  356.         error1("Already a group with name %s.", address);
  357.       }
  358.       else 
  359.         error1("Already an alias for %s.", address); 
  360.           return(0);
  361.     }
  362.  
  363.     sprintf(buffer, "Enter full name for %s: ", name);
  364.     PutLine0(LINES-2,0, buffer);
  365.     CleartoEOLN();
  366.  
  367.     /* use full name in current message for default comment */
  368.     tail_of(current_header->from, comment, current_header->to);
  369.     if(index(comment, '!') || index(comment, '@'))
  370.       /* never mind - it's an address not a full name */
  371.       *comment = '\0';
  372.  
  373.     optionally_enter(comment, LINES-2, strlen(buffer), FALSE, FALSE);
  374.  
  375.     /* grab the return address of this message */
  376.     get_return(address1, current-1);
  377.  
  378.     strcpy(address1, strip_parens(address1));    /* remove parens! */
  379. #ifdef OPTIMIZE_RETURN
  380.     optimize_return(address1);
  381. #endif
  382.     PutLine3(LINES-2,0,"%s (%s) = %s", comment, name, address1);
  383.     CleartoEOLN();
  384.     if((ch = want_to("Accept new alias? (y/n) ",'y')) == 'y')
  385.       add_to_alias_text(name, comment, address1);
  386.     ClearLine(LINES-2);
  387.     return(ch == 'y' ? 1 : 0);
  388. }
  389.  
  390. add_to_alias_text(name, comment, address)
  391. char *name, *comment, *address;
  392. {
  393.     /** Add the data to the user alias text file.  Return zero if we
  394.         succeeded, 1 if not **/
  395.     
  396.     FILE *file;
  397.     char fname[SLEN];
  398.     
  399.     sprintf(fname,"%s/%s", home, ALIAS_TEXT);
  400.     
  401.     save_file_stats(fname);
  402.     if ((file = fopen(fname, "a")) == NULL) {
  403.       dprint(2, (debugfile, 
  404.          "Failure attempting to add alias to file %s within %s",
  405.            fname, "add_to_alias_text"));
  406.       dprint(2, (debugfile, "** %s - %s **\n", error_name(errno), 
  407.            error_description(errno)));
  408.       error1("Couldn't open %s to add new alias!", fname);
  409.       return(1);
  410.     }
  411.  
  412.     if (fprintf(file,"%s = %s = %s\n", name, comment, address) == EOF) {
  413.         dprint(2, (debugfile,
  414.                "Failure attempting to write alias to file within %s",
  415.                fname, "add_to_alias_text"));
  416.         dprint(2, (debugfile, "** %s - %s **\n", error_name(errno),
  417.                error_description(errno)));
  418.         error1("Couldn't write alias to file %s!", fname);
  419.         fclose(file);
  420.         return(1);
  421.     }
  422.  
  423.     fclose(file);
  424.  
  425.     restore_file_stats(fname);
  426.  
  427.     return(0);
  428. }
  429.  
  430. delete_from_alias_text(name)
  431. char *name;
  432. {
  433.     /** Delete the data from the user alias text file.  Return zero if we
  434.         succeeded, 1 if not **/
  435.     
  436.     FILE *file, *tmp_file;
  437.     char fname[SLEN], tmpfname[SLEN];
  438.     char line_in_file[SLEN+3+SLEN+3+LONG_STRING]; /* name = comment = address */
  439.     char name_with_equals[SLEN+2];
  440.  
  441.     strcpy(name_with_equals, name);
  442.     strcat(name_with_equals, " ="); 
  443.  
  444.     sprintf(fname,"%s/%s", home, ALIAS_TEXT);
  445.     sprintf(tmpfname,"%s/%s.t", home, ALIAS_TEXT);
  446.     
  447.     save_file_stats(fname);
  448.  
  449.     if ((file = fopen(fname, "r")) == NULL) {
  450.       dprint(2, (debugfile, 
  451.          "Failure attempting to delete alias from file %s within %s",
  452.            fname, "delete_from_alias_text"));
  453.       dprint(2, (debugfile, "** %s - %s **\n", error_name(errno), 
  454.            error_description(errno)));
  455.       error1("Couldn't open %s to delete alias!", fname);
  456.       return(1);
  457.     }
  458.  
  459.     if ((tmp_file = fopen(tmpfname, "w")) == NULL) {
  460.       dprint(2, (debugfile, 
  461.          "Failure attempting to open temp file %s within %s",
  462.            tmpfname, "delete_from_alias_text"));
  463.       dprint(2, (debugfile, "** %s - %s **\n", error_name(errno), 
  464.            error_description(errno)));
  465.       error1("Couldn't open tempfile %s to delete alias!", tmpfname);
  466.       return(1);
  467.     }
  468.  
  469.     while (fgets(line_in_file, sizeof(line_in_file), file) != (char *)NULL)
  470.     {
  471.         if (strncmp(name_with_equals, line_in_file,
  472.                 strlen(name_with_equals)) != 0)
  473.             if (fprintf(tmp_file,"%s", line_in_file) == EOF) {
  474.                 dprint(2, (debugfile, 
  475.                        "Failure attempting to write to temp file %s within %s",
  476.                        tmpfname, "delete_from_alias_text"));
  477.                 dprint(2, (debugfile, "** %s - %s **\n", error_name(errno), 
  478.                        error_description(errno)));
  479.                 error1("Couldn't write to tempfile %s!", tmpfname);
  480.                 fclose(file);
  481.                 fclose(tmp_file);
  482.                 unlink(tmpfname);
  483.                 return(1);
  484.             }
  485.     }
  486.     fclose(file);
  487.     fclose(tmp_file);
  488.     unlink(fname);        /* ?? */
  489.     if (rename(tmpfname, fname) != 0)
  490.     {
  491.         error1("Couldn't rename tempfile %s after deleting alias!", tmpfname);
  492.         return(1);
  493.     }
  494.  
  495.     restore_file_stats(fname);
  496.  
  497.     return(0);
  498. }
  499.  
  500. show_alias_menu()
  501. {
  502.     MoveCursor(LINES-7,0); CleartoEOS();    
  503.         
  504.     PutLine0(LINES-7,COLUMNS-45, "Alias commands");
  505.     Centerline(LINES-6,
  506.       "a)lias current message, d)elete an alias, check a p)erson or s)ystem,");
  507.     Centerline(LINES-5,
  508.       "l)ist existing aliases, m)ake new alias, or r)eturn");
  509. }
  510.  
  511. alias()
  512. {
  513.     /** work with alias commands... **/
  514.     /** return non-0 if main part of screen overwritten, else 0 **/
  515.  
  516.     char name[NLEN], *address, ch, buffer[SLEN];
  517.     int  newaliases = 0, redraw = 0;
  518.  
  519.     if (mini_menu)
  520.       show_alias_menu();
  521.  
  522.     /** now let's ensure that we've initialized everything! **/
  523.  
  524. #ifndef DONT_TOUCH_ADDRESSES
  525.     
  526.     if (! findnode_has_been_initialized) {
  527.       if (warnings)
  528.         error("Initializing internal tables...");
  529. #ifndef USE_DBM
  530.       get_connections();
  531.       open_domain_file();
  532. #endif
  533.       init_findnode();
  534.       clear_error();
  535.           findnode_has_been_initialized = TRUE;
  536.     }
  537.  
  538. #endif
  539.  
  540.     define_softkeys(ALIAS);
  541.  
  542.     while (1) {
  543.       prompt("Alias: ");
  544.       CleartoEOLN();
  545.       ch = ReadCh();
  546.       MoveCursor(LINES-1,0); CleartoEOS();
  547.       
  548.       dprint(3, (debugfile, "\n-- Alias command: %c\n\n", ch));
  549.  
  550.       switch (tolower(ch)) {
  551.         case '?': redraw += alias_help();            break;
  552.  
  553.         case 'a': newaliases += add_current_alias();    break;
  554.         case 'd': if (delete_alias()) install_aliases();    break;
  555.         case 'l': display_aliases();
  556.               redraw++;
  557.               if (mini_menu) show_alias_menu();
  558.               break;
  559.         case 'm': newaliases += add_alias();         break;
  560.  
  561.         case RETURN:
  562.         case LINE_FEED:
  563.         case 'q':
  564.         case 'x':
  565.         case 'r': if (newaliases) install_aliases();
  566.               clear_error();
  567.               return(redraw);
  568.         case 'p': if (newaliases) 
  569.             error("Warning: new aliases not installed yet!");
  570.  
  571.               strcpy(buffer, "Check for person: ");
  572.               PutLine0(LINES-2,0, buffer);
  573.               CleartoEOLN();
  574.               *name = '\0';
  575.               optionally_enter(name, LINES-2, strlen(buffer),
  576.             FALSE, FALSE);
  577.  
  578.               if ((address = get_alias_address(name, FALSE))!=NULL) {
  579.                     if (address[0] == '!') {
  580.                       address[0] = ' ';
  581.                       PutLine1(LINES-1,0,"Group alias:%-60.60s", address);
  582.                       CleartoEOLN();
  583.                 }
  584.             else
  585.               PutLine1(LINES-1,0,"Aliased address: %-60.60s", 
  586.               address);
  587.               }
  588.                   else 
  589.             error("Not found.");
  590.               break;
  591.  
  592.         case 's': strcpy(buffer, "Check for system: ");
  593.               PutLine0(LINES-2,0, buffer);
  594.               CleartoEOLN();
  595.               *name = '\0';
  596.               optionally_enter(name, LINES-2, strlen(buffer),
  597.             FALSE, FALSE);
  598.               if (talk_to(name)) 
  599. #ifdef INTERNET
  600.             PutLine1(LINES-1,0,
  601.         "You have a direct connection. The address is USER@%s.", 
  602.             name);
  603. #else
  604.             PutLine1(LINES-1,0,
  605.         "You have a direct connection. The address is %s!USER.", 
  606.             name);
  607. #endif
  608.               else {
  609.                 sprintf(buffer, "USER@%s", name);
  610. #ifdef DONT_TOUCH_ADDRESSES
  611.                  address = buffer;
  612. #else
  613.                  address = expand_system(buffer, FALSE);
  614. #endif
  615.                 if (strlen(address) > strlen(name) + 7)
  616.                   PutLine1(LINES-1,0,"Address is: %.65s", address);
  617.                 else
  618.                   error1("Couldn't expand system %s.", name);
  619.               }
  620.               break;
  621.  
  622.         case '@': strcpy(buffer, "Fully expand alias: ");
  623.               PutLine0(LINES-2,0, buffer);
  624.               CleartoEOS();
  625.               *name = '\0';
  626.               optionally_enter(name, LINES-2, strlen(buffer),
  627.             FALSE, FALSE);
  628.               if ((address = get_alias_address(name, TRUE)) != NULL) {
  629.                     ClearScreen();
  630.             PutLine1(3,0,"Aliased address:\l\r%s", address);
  631.                     PutLine0(LINES-1,0,"Press <return> to continue.");
  632. /*            (void) getchar();    */
  633.             ReadCh();
  634.             redraw++;
  635.               }
  636.                   else 
  637.             error("Not found.");
  638.               if (mini_menu) show_alias_menu();
  639.               break;
  640.         default : error("Invalid input!");
  641.       }
  642.     }
  643. }
  644.  
  645. install_aliases()
  646. {
  647.     /** run the 'newalias' program and update the
  648.         aliases before going back to the main program! 
  649.     **/
  650.  
  651.  
  652.     error("Updating aliases...");
  653.     sleep(2);
  654.  
  655.     if (system_call(newalias, SH, FALSE, FALSE) == 0) {
  656.       error("Re-reading the database in...");
  657.       sleep(2);
  658.       read_alias_files();
  659.       set_error("Aliases updated successfully.");
  660.     }
  661.     else
  662.       set_error("'Newalias' failed.  Please check alias_text.");
  663. }
  664.  
  665. alias_help()
  666. {
  667.     /** help section for the alias menu... **/
  668.     /** return non-0 if main part of screen overwritten, else 0 */
  669.     
  670.     char ch;
  671.     int  redraw=0;
  672.     char *alias_prompt = mini_menu ? "Key: " : "Key you want help for: ";
  673.  
  674.     MoveCursor(LINES-3, 0);    CleartoEOS();
  675.  
  676.     if (mini_menu) {
  677.       Centerline(LINES-3,
  678.  "Press the key you want help for, '?' for a key list, or '.' to exit help");
  679.     }
  680.  
  681.     lower_prompt(alias_prompt);
  682.  
  683.     while ((ch = ReadCh()) != '.') {
  684.       ch = tolower(ch);
  685.       switch(ch) {
  686.         case '?' : display_helpfile(ALIAS_HELP);    
  687.                redraw++;
  688.                    if (mini_menu) show_alias_menu();
  689.                return(redraw);
  690.         case 'a': error(
  691.         "a = Add (return) address of current message to alias database.");
  692.               break;
  693.         case 'd': error("d = Delete a user alias from alias database.");
  694.               break;
  695.         case 'l': error("l = List all aliases in database.");
  696.               break;
  697.         case 'm': error(
  698.         "m = Make a new user alias, adding to alias database when done.");
  699.               break;
  700.  
  701.         case RETURN:
  702.         case LINE_FEED:
  703.         case 'q':
  704.         case 'x':
  705.         case 'r': error("Return from alias menu.");
  706.                  break;
  707.               
  708.         case 'p': error("p = Check for a person in the alias database.");
  709.               break;
  710.     
  711.         case 's': error(
  712.         "s = Check for a system in the host routing/domain database.");
  713.               break;
  714.     
  715.         default : error("That key isn't used in this section.");
  716.                  break;
  717.       }
  718.       lower_prompt(alias_prompt);
  719.     }
  720.     return(redraw);
  721. }
  722.  
  723. display_aliases()
  724. {
  725.     char fname[SLEN];
  726.     
  727.     sprintf(fname,"%s/%s", home, ALIAS_TEXT);
  728.     display_file(fname);
  729.     ClearScreen();
  730.     return;
  731. }
  732.