xref: /illumos-gate/usr/src/lib/krb5/ss/listen.c (revision 56a424cca6b3f91f31bdab72a4626c48c779fe8b)
1 /*
2  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /*
9  * Listener loop for subsystem library libss.a.
10  *
11  *	util/ss/listen.c
12  *
13  * Copyright 1987, 1988 by MIT Student Information Processing Board
14  *
15  * For copyright information, see copyright.h.
16  */
17 
18 #include "copyright.h"
19 #include "ss_internal.h"
20 #include <stdio.h>
21 #include <setjmp.h>
22 #include <signal.h>
23 #include <termios.h>
24 #include <libintl.h>
25 #include <sys/param.h>
26 
27 static ss_data *current_info;
28 static jmp_buf listen_jmpb;
29 
30 static RETSIGTYPE print_prompt()
31 {
32     struct termios termbuf;
33 
34     if (tcgetattr(STDIN_FILENO, &termbuf) == 0) {
35 	termbuf.c_lflag |= ICANON|ISIG|ECHO;
36 	tcsetattr(STDIN_FILENO, TCSANOW, &termbuf);
37     }
38     (void) fputs(current_info->prompt, stdout);
39     (void) fflush(stdout);
40 }
41 
42 static RETSIGTYPE listen_int_handler(signo)
43     int signo;
44 {
45     putc('\n', stdout);
46     longjmp(listen_jmpb, 1);
47 }
48 
49 int ss_listen (sci_idx)
50     int sci_idx;
51 {
52     register char *cp;
53     register ss_data *info;
54     char input[BUFSIZ];
55     char buffer[BUFSIZ];
56     char *volatile end = buffer;
57     int code;
58     jmp_buf old_jmpb;
59     ss_data *old_info = current_info;
60 #ifdef POSIX_SIGNALS
61     struct sigaction isig, csig, nsig, osig;
62     sigset_t nmask, omask;
63 #else
64     register RETSIGTYPE (*sig_cont)();
65     RETSIGTYPE (*sig_int)(), (*old_sig_cont)();
66     int mask;
67 #endif
68 
69     current_info = info = ss_info(sci_idx);
70     info->abort = 0;
71 
72 #ifdef POSIX_SIGNALS
73     csig.sa_handler = (RETSIGTYPE (*)())0;
74     sigemptyset(&nmask);
75     sigaddset(&nmask, SIGINT);
76     sigprocmask(SIG_BLOCK, &nmask, &omask);
77 #else
78     sig_cont = (RETSIGTYPE (*)())0;
79     mask = sigblock(sigmask(SIGINT));
80 #endif
81 
82     memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf));
83 
84 #ifdef POSIX_SIGNALS
85     nsig.sa_handler = listen_int_handler;
86     sigemptyset(&nsig.sa_mask);
87     nsig.sa_flags = 0;
88     sigaction(SIGINT, &nsig, &isig);
89 #else
90     sig_int = signal(SIGINT, listen_int_handler);
91 #endif
92 
93     setjmp(listen_jmpb);
94 
95 #ifdef POSIX_SIGNALS
96     sigprocmask(SIG_SETMASK, &omask, (sigset_t *)0);
97 #else
98     (void) sigsetmask(mask);
99 #endif
100     while(!info->abort) {
101 	print_prompt();
102 	*end = '\0';
103 #ifdef POSIX_SIGNALS
104 	nsig.sa_handler = listen_int_handler;	/* fgets is not signal-safe */
105 	osig = csig;
106 	sigaction(SIGCONT, &nsig, &csig);
107 	if ((RETSIGTYPE (*)())csig.sa_handler==(RETSIGTYPE (*)())listen_int_handler)
108 	    csig = osig;
109 #else
110 	old_sig_cont = sig_cont;
111 	sig_cont = signal(SIGCONT, print_prompt);
112 	if (sig_cont == print_prompt)
113 	    sig_cont = old_sig_cont;
114 #endif
115 	if (fgets(input, BUFSIZ, stdin) != input) {
116 	    code = SS_ET_EOF;
117 	    goto egress;
118 	}
119 	cp = strchr(input, '\n');
120 	if (cp) {
121 	    *cp = '\0';
122 	    if (cp == input)
123 		continue;
124 	}
125 #ifdef POSIX_SIGNALS
126 	sigaction(SIGCONT, &csig, (struct sigaction *)0);
127 #else
128 	(void) signal(SIGCONT, sig_cont);
129 #endif
130 	for (end = input; *end; end++)
131 	    ;
132 
133 	code = ss_execute_line (sci_idx, input);
134 	if (code == SS_ET_COMMAND_NOT_FOUND) {
135 	    register char *c = input;
136 	    while (*c == ' ' || *c == '\t')
137 		c++;
138 	    cp = strchr (c, ' ');
139 	    if (cp)
140 		*cp = '\0';
141 	    cp = strchr (c, '\t');
142 	    if (cp)
143 		*cp = '\0';
144 	    ss_error (sci_idx, 0, dgettext(TEXT_DOMAIN,
145 		    "Unknown request \"%s\".  Type \"?\" for a request list."),
146 		       c);
147 	}
148     }
149     code = 0;
150 egress:
151 #ifdef POSIX_SIGNALS
152     sigaction(SIGINT, &isig, (struct sigaction *)0);
153 #else
154     (void) signal(SIGINT, sig_int);
155 #endif
156     memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf));
157     current_info = old_info;
158     return code;
159 }
160 
161 void ss_abort_subsystem(sci_idx, code)
162     int sci_idx;
163     int code;
164 {
165     ss_info(sci_idx)->abort = 1;
166     ss_info(sci_idx)->exit_status = code;
167 
168 }
169 
170 void ss_quit(argc, argv, sci_idx, infop)
171     int argc;
172     char const * const *argv;
173     int sci_idx;
174     pointer infop;
175 {
176     ss_abort_subsystem(sci_idx, 0);
177 }
178