home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume38 / shadow / part11 / getpass.c < prev    next >
C/C++ Source or Header  |  1993-08-14  |  4KB  |  188 lines

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