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