home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / src / init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-11  |  17.9 KB  |  576 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: init.c,v 5.16 1993/04/12 03:30:23 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.16 $   $State: Exp $
  6.  *
  7.  *            Copyright (c) 1988-1992 USENET Community Trust
  8.  *            Copyright (c) 1986,1987 Dave Taylor
  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: init.c,v $
  17.  * Revision 5.16  1993/04/12  03:30:23  syd
  18.  * On AIX, __STDC__ is not defined but it does use unistd.h, etc.  In
  19.  * hdrs/def.h, ANS_C already gets defined if __STDC__ or _AIX.  But this
  20.  * variable then needs to be used in src/init.c and hdrs/filter.h in place
  21.  * of the current test for __STDC__.
  22.  * From:    rstory@elegant.com (Robert Story)
  23.  *
  24.  * Revision 5.15  1993/04/12  03:07:57  syd
  25.  * The "window is too small..." message gets printed on the wrong screen. The
  26.  * message also needs \r\n at the end.
  27.  * From: Jan Djarv <Jan.Djarv@sa.erisoft.se>
  28.  *
  29.  * Revision 5.14  1993/04/12  01:52:31  syd
  30.  * Initialize safe_malloc() failure trap just to play it safe.  Although
  31.  * Elm doesn't currently use these routines, do this just in case somebody
  32.  * someday adds a call to a library routine that does use them.
  33.  * From: chip@chinacat.unicom.com (Chip Rosenthal)
  34.  *
  35.  * Revision 5.13  1993/02/03  19:08:03  syd
  36.  * fix extra declares
  37.  * From: syd
  38.  *
  39.  * Revision 5.12  1993/01/20  03:43:37  syd
  40.  * Some systems dont have SIGBUS, make it optional
  41.  *
  42.  * Revision 5.11  1993/01/20  03:02:19  syd
  43.  * Move string declarations to defs.h
  44.  * From: Syd
  45.  *
  46.  * Revision 5.10  1993/01/19  05:07:05  syd
  47.  * Trim erroreous extra log entry
  48.  * From: Syd
  49.  *
  50.  * Revision 5.9  1993/01/19  04:47:12  syd
  51.  * Significant changes to provide consistent Date and From_ header
  52.  * cracking.  Overhauled date utilities and moved into library.  Moved
  53.  * real_from() into library.  Modified frm, newmail, and readmsg utilities
  54.  * to use library version of real_from().  Moved get_word() from Elm
  55.  * source into library.  Added new library routines atonum() and strfcpy().
  56.  * Fixed trailing backslash bug in len_next().
  57.  * From: chip@chinacat.unicom.com (Chip Rosenthal)
  58.  *
  59.  * Revision 5.8  1992/12/07  02:41:21  syd
  60.  * This implements the use of SIGUSR1 and SIGUSR2 as discussed on the
  61.  * mailing list recently, and adds them to the documentation.
  62.  * From: scs@lokkur.dexter.mi.us (Steve Simmons)
  63.  *
  64.  * Revision 5.7  1992/11/26  01:26:04  syd
  65.  * only enter raw mode if not batch and not elm -c, to avoid
  66.  * screen swap and cursor control output
  67.  *
  68.  * Revision 5.6  1992/11/26  00:46:13  syd
  69.  * changes to first change screen back (Raw off) and then issue final
  70.  * error message.
  71.  * From: Syd
  72.  *
  73.  * Revision 5.5  1992/10/30  21:12:40  syd
  74.  * Make patchlevel a text string to allow local additions to the variable
  75.  * From: syd via a request from Dave Wolfe
  76.  *
  77.  * Revision 5.4  1992/10/27  01:34:12  syd
  78.  * It fixes the problem where ti/te was being used (by Raw()),
  79.  * AFTER the command line args had been read but BEFORE the rc files had.
  80.  * From: Graham Hudspith <gwh@inmos.co.uk>
  81.  *
  82.  * Revision 5.3  1992/10/25  02:01:58  syd
  83.  * Here are the patches to support POSIX sigaction().
  84.  * From: tom@osf.org
  85.  *
  86.  * Revision 5.2  1992/10/24  13:35:39  syd
  87.  * changes found by using codecenter on Elm 2.4.3
  88.  * From: Graham Hudspith <gwh@inmos.co.uk>
  89.  *
  90.  * Revision 5.1  1992/10/03  22:58:40  syd
  91.  * Initial checkin as of 2.4 Release at PL0
  92.  *
  93.  *
  94.  ******************************************************************************/
  95.  
  96. /***** Initialize - read in all the defaults etc etc 
  97. *****/
  98.  
  99. #include "headers.h"
  100. #include "patchlevel.h"
  101. #include "s_elm.h"
  102.  
  103. #ifdef TERMIOS
  104. #  include <termios.h>
  105.    typedef struct termios term_buff;
  106. #else
  107. # ifdef TERMIO
  108. #  include <termio.h>
  109. #  define tcgetattr(fd,buf)    ioctl((fd),TCGETA,(buf))
  110.    typedef struct termio term_buff;
  111. # else
  112. #  include <sgtty.h>
  113. #  define tcgetattr(fd,buf)    ioctl((fd),TIOCGETP,(buf))
  114.    typedef struct sgttyb term_buff;
  115. # endif
  116. #endif
  117.  
  118. #ifdef PWDINSYS
  119. #  include <sys/pwd.h>
  120. #else
  121. #  include <pwd.h>
  122. #endif
  123.  
  124. #ifdef I_TIME
  125. #  include <time.h>
  126. #endif
  127. #ifdef I_SYSTIME
  128. #  include <sys/time.h>
  129. #endif
  130.  
  131. #include <ctype.h>
  132. #include <errno.h>
  133.  
  134. #ifdef BSD
  135. #undef toupper
  136. #undef tolower
  137. #endif
  138.  
  139. extern int errno;        /* system error number on failure */
  140. extern char version_buff[];
  141.  
  142. char *error_description();
  143.  
  144. #ifndef ANSI_C /* items are in unistd.h which is included if __STDC__ */
  145. char *getlogin();
  146. unsigned short getgid(), getuid(); 
  147. #endif
  148.  
  149. #ifndef    _POSIX_SOURCE
  150. struct passwd *getpwuid();
  151. #endif
  152. char *get_full_name();
  153.  
  154. SIGHAND_TYPE
  155. #ifdef SIGTSTP
  156.     sig_user_stop(), sig_return_from_user_stop(),
  157. #endif
  158. #ifdef SIGWINCH
  159.     winch_signal(),
  160. #endif
  161.     quit_signal(), term_signal(), ill_signal(),
  162.     fpe_signal(), segv_signal(),
  163. #ifdef SIGBUS
  164.     bus_signal(),
  165. #endif
  166.     alarm_signal(), pipe_signal(), hup_signal(),
  167.     usr1_signal(), usr2_signal() ;
  168.  
  169. extern void init_opts_menu();
  170. extern void malloc_failed_exit();
  171.  
  172. initialize(requestedmfile)
  173. char *requestedmfile;    /* first mail file to open, empty if the default */
  174. {
  175.     /** initialize the whole ball of wax.
  176.     **/
  177.     struct passwd *pass, *getpwnam();
  178.     register int init_scr_return, hostlen, domlen; 
  179.  
  180. #if defined(SIGVEC) & defined(SV_INTERRUPT)
  181.     struct sigvec alarm_vec;
  182. #endif /* defined(SIGVEC) & defined(SV_INTERRUPT) */
  183.     char     buffer[SLEN], *cp;
  184.  
  185.     sprintf(version_buff, "%s PL%s", VERSION, PATCHLEVEL);
  186.     def_ans_yes = catgets(elm_msg_cat, ElmSet, ElmYes, "y");
  187.     def_ans_no = catgets(elm_msg_cat, ElmSet, ElmNo, "n");
  188.     nls_deleted = catgets(elm_msg_cat, ElmSet, ElmTitleDeleted, "[deleted]");
  189.     nls_form = catgets(elm_msg_cat, ElmSet, ElmTitleForm, "Form");
  190.     nls_message = catgets(elm_msg_cat, ElmSet, ElmTitleMessage, "Message");
  191.     nls_to = catgets(elm_msg_cat, ElmSet, ElmTitleTo, "To");
  192.     nls_from = catgets(elm_msg_cat, ElmSet, ElmTitleFrom, "From");
  193.     nls_page = catgets(elm_msg_cat, ElmSet, ElmTitlePage, "  Page %d");
  194.     change_word = catgets(elm_msg_cat, ElmSet, ElmChange, "change");
  195.     save_word = catgets(elm_msg_cat, ElmSet, ElmSave, "save");
  196.     copy_word = catgets(elm_msg_cat, ElmSet, ElmCopy, "copy");
  197.     cap_save_word = catgets(elm_msg_cat, ElmSet, ElmCapSave, "Save");
  198.     cap_copy_word = catgets(elm_msg_cat, ElmSet, ElmCapCopy, "Copy");
  199.     saved_word = catgets(elm_msg_cat, ElmSet, ElmSaved, "saved");
  200.     copied_word = catgets(elm_msg_cat, ElmSet, ElmCopied, "copied");
  201.     strcpy(item, catgets(elm_msg_cat, ElmSet, Elmitem, "message"));
  202.     strcpy(items, catgets(elm_msg_cat, ElmSet, Elmitems, "messages"));
  203.     strcpy(Item, catgets(elm_msg_cat, ElmSet, ElmItem, "Message"));
  204.     strcpy(Items, catgets(elm_msg_cat, ElmSet, ElmItems, "Messages"));
  205.     strcpy(Prompt, catgets(elm_msg_cat, ElmSet, ElmPrompt, "Command: "));
  206.  
  207.     /*
  208.      * Install the error trap to take if xmalloc() or friends fail.
  209.      */
  210.     safe_malloc_fail_handler = malloc_failed_exit;
  211.  
  212.     init_opts_menu();
  213.     init_scr_return = InitScreen();
  214.  
  215.     /* save original user and group ids */
  216.     userid  = getuid();
  217.     groupid = getgid();    
  218. #ifdef SAVE_GROUP_MAILBOX_ID
  219.     mailgroupid = getegid();
  220.     setgid(groupid);
  221. #endif
  222.  
  223.     /* make all newly created files private */
  224.     original_umask = umask(077);
  225.  
  226.     /* Get username (logname), home (login directory), and full_username
  227.      * (part of GCOS) field from the password entry for this user id.
  228.      * Full_username will get overridden by fullname in elmrc, if defined.
  229.      *
  230.      * For those sites that have various user names with the same user
  231.      * ID, use the passwd entry corresponding to the user name as long 
  232.      * as it matches the user ID.  Otherwise fall back on the entry 
  233.      * associated with the user ID alone.
  234.      */
  235.  
  236.     if((cp = getenv("LOGNAME")) == NULL)
  237.         cp = getenv("USER");
  238.     if(cp != NULL && (pass = getpwnam(cp)) != NULL &&
  239.         pass->pw_uid == userid) {
  240.       ;  /* Null body */
  241.     } else if((pass = getpwuid(userid)) == NULL) {
  242.       error(catgets(elm_msg_cat, ElmSet, ElmYouHaveNoPasswordEntry,
  243.         "You have no password entry!\r\n"));
  244.       exit(1);
  245.     }
  246.     strcpy(username, pass->pw_name);
  247.     strcpy(home, pass->pw_dir);
  248.  
  249.     if((cp = get_full_name(username)) != NULL)
  250.       strcpy(full_username, cp);
  251.     else
  252.       strcpy(full_username, username);    /* fall back on logname */
  253.  
  254. #ifdef DEBUG
  255.     if (debug) {        /* setup for dprint() statements! */
  256.       char newfname[SLEN], filename[SLEN];
  257.  
  258.       sprintf(filename, "%s/%s", home, DEBUGFILE);
  259.       if (access(filename, ACCESS_EXISTS) == 0) {    /* already one! */
  260.         sprintf(newfname,"%s/%s", home, OLDEBUG);
  261.         (void) rename(filename, newfname);
  262.       }
  263.  
  264.       /* Note what we just did up there: we always save the old
  265.          version of the debug file as OLDEBUG, so users can mail
  266.          copies of bug files without trashing 'em by starting up
  267.          the mailer.  Dumb, subtle, but easy enough to do!
  268.        */
  269.  
  270.       if ((debugfile = fopen(filename, "w")) == NULL) {
  271.         debug = 0;    /* otherwise 'leave' will try to log! */
  272.         leave(fprintf(stderr, catgets(elm_msg_cat, ElmSet, ElmCouldNotOpenDebugFile,
  273.             "Could not open file %s for debug output!\n"),
  274.           filename));
  275.       }
  276.       chown(filename, userid, groupid); /* file owned by user */
  277.  
  278.       fprintf(debugfile, 
  279.      "Debug output of the ELM program (at debug level %d).  Version %s\n\n",
  280.           debug, version_buff);
  281.     }
  282. #endif
  283.  
  284.     /*
  285.      * If debug level is fairly low, ignore keyboard signals
  286.      * until the screen is set up.
  287.      */
  288.     if (debug < 5) {
  289.       signal(SIGINT,  SIG_IGN);
  290.       signal(SIGQUIT, SIG_IGN);
  291.     }
  292.  
  293.     if(!check_only && !batch_only) {
  294.       if (init_scr_return < 0) {
  295.         if (init_scr_return == -1) {
  296.           printf(catgets(elm_msg_cat, ElmSet, ElmNoTerm,
  297. "Sorry, but you must specify what type of terminal you're on if you want to\n\
  298. run the \"elm\" program. (You need your environment variable \"TERM\" set.)\n"));
  299.           dprint(1,(debugfile,"No $TERM variable in environment!\n"));
  300.         }
  301.         else if (init_scr_return == -2) {
  302.           printf(catgets(elm_msg_cat, ElmSet, ElmBadTerm,
  303. "You need a cursor-addressable terminal to run \"elm\" and I can't find any\n\
  304. kind of termcap entry for \"%s\" - check your \"TERM\" setting...\n"),
  305.            getenv("TERM"));
  306.           dprint(1,
  307.         (debugfile,"$TERM variable is an unknown terminal type!\n"));
  308.         } else {
  309.           printf(catgets(elm_msg_cat, ElmSet, ElmTermInitFailed,
  310.         "Failed trying to initialize your terminal entry: unknown return code %d\n"), init_scr_return);
  311.           dprint(1, (debugfile, "Initscreen returned unknown code: %d\n",
  312.           init_scr_return));
  313.         }
  314.         exit(1);    /* all the errors share this exit statement */
  315.       }
  316.     }
  317.  
  318.     if (debug < 5) {    /* otherwise let the system trap 'em! */
  319.       signal(SIGQUIT, quit_signal);        /* Quit signal                 */
  320.       signal(SIGTERM, term_signal);     /* Terminate signal         */
  321.       signal(SIGILL,  ill_signal);        /* Illegal instruction      */
  322.       signal(SIGFPE,  fpe_signal);        /* Floating point exception */
  323. #ifdef SIGBUS
  324.       signal(SIGBUS,  bus_signal);        /* Bus error              */
  325. #endif
  326.       signal(SIGSEGV, segv_signal);        /* Segmentation Violation   */
  327.       signal(SIGHUP,  hup_signal);        /* HangUp (line dropped)    */
  328.       signal(SIGUSR1, usr1_signal);        /* User request 1        */
  329.       signal(SIGUSR2, usr2_signal);        /* User request 2        */
  330.     }
  331.     else {
  332.       dprint(3,(debugfile,
  333.   "\n*** Elm-Internal Signal Handlers Disabled due to debug level %d ***\n\n",
  334.             debug));
  335.     }
  336. #if !defined(POSIX_SIGNALS) & defined(SIGVEC) & defined(SV_INTERRUPT)
  337.     bzero((char *) &alarm_vec, sizeof(alarm_vec));
  338.     alarm_vec.sv_handler = alarm_signal;
  339.     alarm_vec.sv_flags = SV_INTERRUPT;
  340.     sigvec (SIGALRM, &alarm_vec, (struct sigvec *)0);    /* Process Timer Alarm        */
  341. #else /* defined(SIGVEC) & defined(SV_INTERRUPT) */
  342.     signal(SIGALRM, alarm_signal);        /* Process Timer Alarm      */
  343. #endif /* defined(SIGVEC) & defined(SV_INTERRUPT) */
  344.     signal(SIGPIPE, pipe_signal);        /* Illegal Pipe Operation   */
  345. #ifdef SIGTSTP
  346.     signal(SIGTSTP, sig_user_stop);        /* Suspend signal from tty  */
  347.     signal(SIGCONT, sig_return_from_user_stop);    /* Continue Process */
  348. #endif
  349. #ifdef SIGWINCH
  350.     signal(SIGWINCH, winch_signal);        /* change screen size */
  351. #endif
  352.  
  353.     get_term_chars();
  354.  
  355.     /*
  356.      * Get the host name as per configured behavior.
  357.      */
  358. #ifdef HOSTCOMPILED
  359.     strfcpy(hostname, HOSTNAME, sizeof(hostname));
  360. #else
  361.     gethostname(hostname, sizeof(hostname));
  362. #endif
  363.  
  364.     /*
  365.      * now get the domain name, used to build the full name
  366.      */
  367.     gethostdomain(hostdomain, sizeof(hostdomain));
  368.  
  369.     /*
  370.      * now the tough part:
  371.      *    we need to make three variables out of this stuff:
  372.      *    hostname = just the hostname, as in bangpaths,
  373.      *        this is whatever the user gave us so far,
  374.      *        we wont change this one
  375.      *    hostdomain = this is the domain considered local to this
  376.      *        machine, and should be what we got above.
  377.      *    hostfullname = this is the full FQDN of this machine,
  378.      *        and is a strange combination of the first two.
  379.      *    if tail(hostname) == hostdomain
  380.      *        then hostfullname = hostname
  381.      *            ie: node.ld.domain.type, ld.domain.type -> node.ld.domain.type
  382.      *    else if hostname == hostdomain + 1
  383.      *        then hostfullname = hostname
  384.      *            ie: domain.type, .domain.type -> domain.type
  385.      *    
  386.      *    else hostfullname = hostname + hostdomain
  387.      *            ie: host, .domain.type -> host.domain.type
  388.      * lost yet?
  389.      */
  390.     hostlen = strlen(hostname);
  391.     domlen = strlen(hostdomain);
  392.     if (hostlen >= domlen) {
  393.       if (istrcmp(&hostname[hostlen - domlen], hostdomain) == 0)
  394.         strcpy(hostfullname, hostname);
  395.       else {
  396.         strcpy(hostfullname, hostname);
  397.         strcat(hostfullname, hostdomain);
  398.       }
  399.     } else {
  400.       if (istrcmp(hostname, hostdomain + 1) == 0)
  401.         strcpy(hostfullname, hostname);
  402.       else {
  403.         strcpy(hostfullname, hostname);
  404.         strcat(hostfullname, hostdomain);
  405.       }
  406.     }
  407.  
  408.     /* Determine the default mail file name.
  409.      * 
  410.      * First look for an environment variable MAIL, then
  411.      * use then mailhome if it is not found
  412.      */
  413.     if ((cp = getenv("MAIL")) == NULL)
  414.         sprintf(defaultfile, "%s%s", mailhome, username);
  415.     else
  416.         strcpy(defaultfile, cp);
  417.  
  418.     /* Determine options that might be set in the .elm/elmrc */
  419.     read_rc_file();
  420.  
  421.     /* Now that we've read the rc file we can enter RAW mode */
  422.     if (!batch_only && !check_only)
  423.         Raw(ON);
  424.  
  425.     /* Determine the mail file to read */
  426.     if (*requestedmfile == '\0')
  427.       strcpy(requestedmfile, defaultfile);
  428.     else if(!expand_filename(requestedmfile, FALSE)) {
  429.         Raw(OFF);
  430.         exit(0);
  431.         }
  432.     if (check_size)
  433.       if(check_mailfile_size(requestedmfile) != 0) {
  434.           Raw(OFF);
  435.           exit(0);
  436.       }
  437.  
  438.     /* check for permissions only if not send only mode file */
  439.     if (! mail_only) {
  440.       if ((errno = can_access(requestedmfile, READ_ACCESS)) != 0) {
  441.         if (strcmp(requestedmfile, defaultfile) != 0 || errno != ENOENT) {
  442.           dprint(1, (debugfile,
  443.             "Error: given file %s as folder - unreadable (%s)!\n", 
  444.             requestedmfile, error_description(errno)));
  445.           fprintf(stderr, catgets(elm_msg_cat, ElmSet, ElmCantOpenFolderRead,
  446.             "Can't open folder '%s' for reading!\n"),
  447.             requestedmfile);
  448.           Raw(OFF);
  449.           exit(1);
  450.         }
  451.       }
  452.     }
  453.  
  454.     /** check to see if the user has defined a LINES or COLUMNS
  455.         value different to that in the termcap entry (for
  456.         windowing systems, of course!) **/
  457.  
  458.     ScreenSize(&LINES, &COLUMNS);
  459.  
  460.     if ((cp = getenv("LINES")) != NULL && isdigit(*cp)) {
  461.       sscanf(cp, "%d", &LINES);
  462.       LINES -= 1;    /* kludge for HP Window system? ... */
  463.     }
  464.  
  465.     if ((cp = getenv("COLUMNS")) != NULL && isdigit(*cp))
  466.       sscanf(cp, "%d", &COLUMNS);
  467.  
  468.     /** fix the shell if needed **/
  469.  
  470.     if (shell[0] != '/') {
  471.        sprintf(buffer, "/bin/%s", shell);
  472.        strcpy(shell, buffer);
  473.     }
  474.  
  475.     if (! mail_only && ! check_only) {
  476.  
  477.       /* get the cursor control keys... */
  478.  
  479.       cursor_control = FALSE;
  480.  
  481.       if ((cp = return_value_of("ku")) != NULL) {
  482.         strcpy(up, cp);
  483.         if ((cp = return_value_of("kd")) != NULL) {
  484.           strcpy(down, cp);
  485.           if ((cp = return_value_of("kl")) != NULL) {
  486.         strcpy(left, cp);
  487.         if ((cp = return_value_of("kr")) != NULL) {
  488.           strcpy(right, cp);
  489.           cursor_control = TRUE;
  490.           transmit_functions(ON);
  491.         }
  492.           }
  493.         }
  494.       }
  495.       if (!arrow_cursor)     /* try to use inverse bar instead */
  496.         if (return_value_of("so") != NULL && return_value_of("se") != NULL)
  497.             has_highlighting = TRUE;
  498.     }
  499.  
  500.     /** clear the screen **/
  501.     if(!check_only && !batch_only)
  502.       ClearScreen();
  503.  
  504.     if (! mail_only && ! check_only) {
  505.       if (mini_menu)
  506.         headers_per_page = LINES - 13;
  507.       else
  508.         headers_per_page = LINES -  8;    /* 5 more headers! */
  509.  
  510.       if (headers_per_page <= 0) {
  511.         Raw(OFF);
  512.         error1(catgets(elm_msg_cat, ElmSet, ElmWindowSizeTooSmall,
  513.          "The window is too small to run Elm.  It must have at least %d rows"),
  514.          1 + LINES - headers_per_page);
  515.         exit(1);
  516.       }
  517.       newmbox(requestedmfile, FALSE);    /* read in the folder! */
  518.     }
  519.  
  520. #ifdef DEBUG
  521.     if (debug >= 2 && debug < 10) {
  522.       fprintf(debugfile,
  523. "hostname = %-20s \tusername = %-20s \tfullname = %-20s\n",
  524.              hostname, username, full_username);
  525.  
  526.       fprintf(debugfile,
  527. "home     = %-20s \teditor   = %-20s \trecvd_mail  = %-20s\n",
  528.          home, editor, recvd_mail);
  529.  
  530.       fprintf(debugfile,
  531. "cur_folder   = %-20s \tfolders  = %-20s \tprintout = %-20s\n",
  532.          cur_folder, folders, printout);
  533.     
  534.       fprintf(debugfile,
  535. "sent_mail = %-20s \tprefix   = %-20s \tshell    = %-20s\n\n",
  536.         sent_mail, prefixchars, shell);
  537.     
  538.       if (local_signature[0])
  539.         fprintf(debugfile, "local_signature = \"%s\"\n",
  540.             local_signature);
  541.       if (remote_signature[0])
  542.         fprintf(debugfile, "remote_signature = \"%s\"\n",
  543.             remote_signature);
  544.       if (local_signature[0] || remote_signature[0])
  545.         fprintf(debugfile, "\n");
  546.     }
  547. #endif
  548. }
  549.  
  550. get_term_chars()
  551. {
  552.     /** This routine sucks out the special terminal characters
  553.         ERASE and KILL for use in the input routine.  The meaning 
  554.             of the characters are (dare I say it?) fairly obvious... **/
  555.  
  556.     term_buff term_buffer;
  557.  
  558.     if (tcgetattr(STANDARD_INPUT,&term_buffer) == -1) {
  559.       dprint(1, (debugfile,
  560.            "Error: %s encountered on ioctl call (get_term_chars)\n", 
  561.            error_description(errno)));
  562.       /* set to defaults for terminal driver */
  563.       backspace = BACKSPACE;
  564.       kill_line = ctrl('U');
  565.     }
  566.     else {
  567. #if defined(TERMIO) || defined(TERMIOS)
  568.       backspace = term_buffer.c_cc[VERASE];
  569.       kill_line = term_buffer.c_cc[VKILL];
  570. #else
  571.       backspace = term_buffer.sg_erase;
  572.       kill_line = term_buffer.sg_kill;
  573. #endif
  574.     }
  575. }
  576.