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