xref: /onnv-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/os/promptusr.c (revision 781:57319a72b15f)
1  #pragma ident	"%Z%%M%	%I%	%E% SMI"
2  /*
3   * promptusr.c --- prompt user for input/output
4   */
5  
6  #include <k5-int.h>
7  #if !defined(_WIN32)
8  
9  #include <stdio.h>
10  #include <stdlib.h>
11  #ifdef HAVE_UNISTD_H
12  #include <unistd.h>
13  #endif
14  #include <termios.h>
15  #include <signal.h>
16  #include <setjmp.h>
17  
18  typedef struct _krb5_uio {
19      krb5_magic		magic;
20      int 		flags;
21      char *		prompt;
22      char *		response;
23      struct _krb5_uio	*next;
24  } *krb5_uio;
25  
26  #define KRB5_UIO_GETRESPONSE	0x0001
27  #define KRB5_UIO_ECHORESPONSE	0x0002
28  #define KRB5_UIO_FREE_PROMPT	0x0004
29  
30  static jmp_buf pwd_jump;
31  
32  /*ARGSUSED*/
33  static krb5_sigtype
intr_routine(int signo)34  intr_routine(int signo)
35  {
36      longjmp(pwd_jump, 1);
37      /*NOTREACHED*/
38  }
39  
40  /*ARGSUSED*/
41  krb5_error_code
krb5_os_get_tty_uio(krb5_context context,krb5_uio uio)42  krb5_os_get_tty_uio(krb5_context context, krb5_uio uio)
43  {
44      volatile krb5_error_code 	retval;
45      krb5_sigtype	(*volatile ointrfunc)();
46      krb5_uio		p;
47      struct termios 	echo_control, save_control;
48      int 		fd;
49      char		read_string[BUFSIZ];
50      char		*cp;
51      int			ch;
52  
53      /* get the file descriptor associated with stdin */
54      fd=fileno(stdin);
55  
56      if (tcgetattr(fd, &echo_control) == -1)
57  	return errno;
58  
59      save_control = echo_control;
60      echo_control.c_lflag &= ~(ECHO|ECHONL);
61  
62      if (setjmp(pwd_jump)) {
63  	retval = KRB5_LIBOS_PWDINTR; 	/* we were interrupted... */
64  	goto cleanup;
65      }
66      /* save intrfunc */
67      ointrfunc = signal(SIGINT, intr_routine);
68  
69      for (p = uio; p; p = p->next) {
70  	if (p->prompt) {
71  	    fputs(p->prompt, stdout);
72  	    fflush(stdout);
73  	}
74  	if ((p->flags & KRB5_UIO_GETRESPONSE) == 0)
75  	    continue;
76  
77  	if ((p->flags & KRB5_UIO_ECHORESPONSE) == 0)
78  	    if (tcsetattr(fd, TCSANOW, &echo_control) == -1)
79  		return errno;
80  
81  	if (fgets(read_string, sizeof(read_string), stdin) == NULL) {
82  	    (void) putchar('\n');
83  	    retval = KRB5_LIBOS_CANTREADPWD;
84  	    goto cleanup;
85  	}
86  
87  	/* replace newline with null */
88  	if ((cp = strchr(read_string, '\n')))
89  	    *cp = '\0';
90  	else /* flush rest of input line */
91  	    do {
92  		ch = getchar();
93  	    } while (ch != EOF && ch != '\n');
94  	read_string[sizeof(read_string)-1] = 0;
95  
96  	if ((p->response = malloc(strlen(read_string)+1)) == NULL) {
97  	    errno = ENOMEM;
98  	    goto cleanup;
99  	}
100  	strcpy(p->response, read_string);
101  
102  	if ((p->flags & KRB5_UIO_ECHORESPONSE) == 0) {
103  	    (void) putchar('\n');
104  	    if (tcsetattr(fd, TCSANOW, &save_control) == -1) {
105  		retval = errno;
106  		goto cleanup;
107  	    }
108  	}
109      }
110      retval = 0;
111  
112   cleanup:
113      (void) signal(SIGINT, ointrfunc);
114      if (retval) {
115  	for (p = uio; p; p = p->next) {
116  	    if (p->response) {
117  		memset(p->response, 0, strlen(p->response));
118  		free(p->response);
119  		p->response = 0;
120  	    }
121  	}
122      }
123      memset(read_string, 0, sizeof(read_string));
124      tcsetattr(fd, TCSANOW, &save_control);
125      return retval;
126  }
127  
128  /*ARGSUSED*/
129  void
krb5_free_uio(krb5_context context,krb5_uio uio)130  krb5_free_uio(krb5_context context, krb5_uio uio)
131  {
132      krb5_uio		p, next;
133  
134      for (p = uio; p; p = next) {
135  	next = p->next;
136  	if (p->prompt && (p->flags & KRB5_UIO_FREE_PROMPT))
137  	    free(p->prompt);
138  	if (p->response)
139  	    free(p->response);
140  	free(p);
141      }
142  }
143  
144  #ifdef TEST_DRIVER
145  
146  struct _krb5_uio uio_a = { 0, KRB5_UIO_GETRESPONSE, "Password 1: " };
147  struct _krb5_uio uio_b = { 0, KRB5_UIO_GETRESPONSE |
148  			       KRB5_UIO_ECHORESPONSE, "Password 2: " };
149  struct _krb5_uio uio_c = { 0, KRB5_UIO_GETRESPONSE, "Password 3: " };
150  
151  
152  void
main(int argc,char ** argv)153  main(int argc, char **argv)
154  {
155      uio_a.next = &uio_b;
156      uio_b.next = &uio_c;
157  
158      krb5_os_get_tty_uio(0, &uio_a);
159      exit(0);
160  }
161  
162  #endif
163  
164  #endif /* !_MSODS */
165