home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3339 / getpass.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-17  |  3.3 KB  |  169 lines

  1. /*
  2.  * Copyright 1990, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Permission is granted to copy and create derivative works for any
  6.  * non-commercial purpose, provided this copyright notice is preserved
  7.  * in all copies of source code, or included in human readable form
  8.  * and conspicuously displayed on all copies of object code or
  9.  * distribution media.
  10.  */
  11.  
  12. #include <sys/signal.h>
  13. #include <stdio.h>
  14. #include "config.h"
  15.  
  16. #ifdef    BSD
  17. #include <sgtty.h>
  18. #include <strings.h>
  19. #else
  20. #include <termio.h>
  21. #include <string.h>
  22. #endif
  23.  
  24. #ifndef    lint
  25. static    char    sccsid[] = "@(#)getpass.c    3.2    08:19:03    2/5/91";
  26. #endif
  27.  
  28. /*
  29.  * limits.h may be kind enough to specify the length of a prompted
  30.  * for password.
  31.  */
  32.  
  33. #if defined(__STDC__) || defined(_POSIX_SOURCE)
  34. #include <limits.h>
  35. #endif
  36.  
  37. /*
  38.  * This is really a giant mess.  On the one hand, it would be nice
  39.  * if PASS_MAX were real big so that DOUBLESIZE isn't needed.  But
  40.  * if it is defined we must honor it because some idiot might use
  41.  * this in a routine expecting some standard behavior.
  42.  */
  43.  
  44. #ifndef    PASS_MAX
  45. #ifdef    DOUBLESIZE
  46. #define    PASS_MAX    16
  47. #else
  48. #define    PASS_MAX    8
  49. #endif
  50. #endif
  51.  
  52. #ifdef    BSD
  53. #define    STTY(fd,termio)    stty(fd, termio)
  54. #define    GTTY(fd,termio) gtty(fd, termio)
  55. #define    TERMIO    struct    sgttyb
  56. #define    INDEX    index
  57. #else
  58. #define    STTY(fd,termio) ioctl(fd, TCSETA, termio)
  59. #define    GTTY(fd,termio) ioctl(fd, TCGETA, termio)
  60. #define    TERMIO    struct    termio
  61. #define    INDEX    strchr
  62. #endif
  63.  
  64. static    int    sig_caught;
  65.  
  66. static void
  67. sig_catch ()
  68. {
  69.     sig_caught = 1;
  70. }
  71.  
  72. char *
  73. getpass (prompt)
  74. char    *prompt;
  75. {
  76.     static    char    input[PASS_MAX+1];
  77.     char    *return_value = 0;
  78.     char    *cp;
  79.     FILE    *fp;
  80.     int    tty_opened = 0;
  81.     void    (*old_signal)();
  82.     TERMIO    new_modes;
  83.     TERMIO    old_modes;
  84.  
  85.     /*
  86.      * set a flag so the SIGINT signal can be re-sent if it
  87.      * is caught
  88.      */
  89.  
  90.     sig_caught = 0;
  91.  
  92.     /*
  93.      * if /dev/tty can't be opened, getpass() needs to read
  94.      * from stdin instead.
  95.      */
  96.  
  97.     if ((fp = fopen ("/dev/tty", "r")) == 0) {
  98.         fp = stdin;
  99.         setbuf (fp, (char *) 0);
  100.     } else {
  101.         tty_opened = 1;
  102.     }
  103.  
  104.     /*
  105.      * the current tty modes must be saved so they can be
  106.      * restored later on.  echo will be turned off, except
  107.      * for the newline character (BSD has to punt on this)
  108.      */
  109.  
  110.     if (GTTY (fileno (fp), &new_modes))
  111.         return 0;
  112.  
  113.     old_modes = new_modes;
  114.     old_signal = signal (SIGINT, sig_catch);
  115.  
  116. #ifdef    BSD
  117.     new_modes.sg_flags &= ~ECHO ;
  118. #else
  119.     new_modes.c_lflag &= ~(ECHO|ECHOE|ECHOK);
  120.     new_modes.c_lflag |= ECHONL;
  121. #endif
  122.  
  123.     if (STTY (fileno (fp), &new_modes))
  124.         goto out;
  125.  
  126.     /*
  127.      * the prompt is output, and the response read without
  128.      * echoing.  the trailing newline must be removed.  if
  129.      * the fgets() returns an error, a NULL pointer is
  130.      * returned.
  131.      */
  132.  
  133.     if (fputs (prompt, stdout) == EOF)
  134.         goto out;
  135.  
  136.     if (fgets (input, sizeof input, fp) == input) {
  137.         if (cp = INDEX (input, '\n'))
  138.             *cp = '\0';
  139.         else
  140.             input[sizeof input - 1] = '\0';
  141.  
  142.         return_value = input;
  143. #ifdef    BSD
  144.         putc ('\n', stdout);
  145. #endif
  146.     }
  147. out:
  148.     /*
  149.      * the old SIGINT handler is restored after the tty
  150.      * modes.  then /dev/tty is closed if it was opened in
  151.      * the beginning.  finally, if a signal was caught it
  152.      * is sent to this process for normal processing.
  153.      */
  154.  
  155.     if (STTY (fileno (fp), &old_modes))
  156.         return_value = 0;
  157.  
  158.     signal (SIGINT, old_signal);
  159.  
  160.     if (tty_opened)
  161.         fclose (fp);
  162.  
  163.     if (sig_caught) {
  164.         kill (getpid (), SIGINT);
  165.         return_value = 0;
  166.     }
  167.     return return_value;
  168. }
  169.