1 /* 2 * Listener loop for subsystem library libss.a. 3 * 4 * $Header$ 5 * $Locker$ 6 * 7 * Copyright 1987, 1988 by MIT Student Information Processing Board 8 * 9 * Permission to use, copy, modify, and distribute this software and 10 * its documentation for any purpose is hereby granted, provided that 11 * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in 12 * advertising or publicity pertaining to distribution of the software 13 * without specific, written prior permission. M.I.T. and the 14 * M.I.T. S.I.P.B. make no representations about the suitability of 15 * this software for any purpose. It is provided "as is" without 16 * express or implied warranty. 17 */ 18 19 #include "ss_internal.h" 20 #include <stdio.h> 21 #include <setjmp.h> 22 #include <signal.h> 23 #include <sys/param.h> 24 25 typedef void sigret_t; 26 27 static ss_data *current_info; 28 static jmp_buf listen_jmpb; 29 static sigret_t (*sig_cont)(int); 30 31 static sigret_t print_prompt(int sig __SS_ATTR((unused))) 32 { 33 if (current_info->redisplay) 34 (*current_info->redisplay)(); 35 else { 36 (void) fputs(current_info->prompt, stdout); 37 (void) fflush(stdout); 38 } 39 } 40 41 static sigret_t listen_int_handler(int sig __SS_ATTR((unused))) 42 { 43 putc('\n', stdout); 44 signal(SIGINT, listen_int_handler); 45 longjmp(listen_jmpb, 1); 46 } 47 48 int ss_listen (int sci_idx) 49 { 50 char *cp; 51 ss_data *info; 52 sigret_t (*sig_int)(int), (*old_sig_cont)(int); 53 char input[BUFSIZ]; 54 sigset_t omask, igmask; 55 int code; 56 jmp_buf old_jmpb; 57 ss_data *old_info = current_info; 58 char *line; 59 60 current_info = info = ss_info(sci_idx); 61 sig_cont = (sigret_t (*)(int)) 0; 62 info->abort = 0; 63 sigemptyset(&igmask); 64 sigaddset(&igmask, SIGINT); 65 sigprocmask(SIG_BLOCK, &igmask, &omask); 66 memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf)); 67 sig_int = signal(SIGINT, listen_int_handler); 68 setjmp(listen_jmpb); 69 sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 70 71 while(!info->abort) { 72 old_sig_cont = sig_cont; 73 sig_cont = signal(SIGCONT, print_prompt); 74 if (sig_cont == print_prompt) 75 sig_cont = old_sig_cont; 76 if (info->readline) { 77 line = (*info->readline)(current_info->prompt); 78 } else { 79 print_prompt(0); 80 if (fgets(input, BUFSIZ, stdin) == input) 81 line = input; 82 else 83 line = NULL; 84 85 input[BUFSIZ-1] = 0; 86 } 87 if (line == NULL) { 88 code = SS_ET_EOF; 89 (void) signal(SIGCONT, sig_cont); 90 goto egress; 91 } 92 93 cp = strchr(line, '\n'); 94 if (cp) { 95 *cp = '\0'; 96 if (cp == line) 97 continue; 98 } 99 (void) signal(SIGCONT, sig_cont); 100 if (info->add_history) 101 (*info->add_history)(line); 102 103 code = ss_execute_line (sci_idx, line); 104 if (code == SS_ET_COMMAND_NOT_FOUND) { 105 register char *c = line; 106 while (*c == ' ' || *c == '\t') 107 c++; 108 cp = strchr (c, ' '); 109 if (cp) 110 *cp = '\0'; 111 cp = strchr (c, '\t'); 112 if (cp) 113 *cp = '\0'; 114 ss_error (sci_idx, 0, 115 "Unknown request \"%s\". Type \"?\" for a request list.", 116 c); 117 } 118 if (info->readline) 119 free(line); 120 } 121 code = 0; 122 egress: 123 (void) signal(SIGINT, sig_int); 124 memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf)); 125 current_info = old_info; 126 return code; 127 } 128 129 void ss_abort_subsystem(int sci_idx, int code) 130 { 131 ss_info(sci_idx)->abort = 1; 132 ss_info(sci_idx)->exit_status = code; 133 134 } 135 136 void ss_quit(int argc __SS_ATTR((unused)), 137 const char * const *argv __SS_ATTR((unused)), 138 int sci_idx, pointer infop __SS_ATTR((unused))) 139 { 140 ss_abort_subsystem(sci_idx, 0); 141 } 142 143 #ifdef HAVE_DLOPEN 144 #define get_request(tbl,idx) ((tbl) -> requests + (idx)) 145 146 static char *cmd_generator(const char *text, int state) 147 { 148 static int len; 149 static ss_request_table **rqtbl; 150 static int curr_rqt; 151 static char const * const * name; 152 ss_request_entry *request; 153 char *ret; 154 155 if (state == 0) { 156 len = strlen(text); 157 rqtbl = current_info->rqt_tables; 158 if (!rqtbl || !*rqtbl) 159 return 0; 160 curr_rqt = 0; 161 name = 0; 162 } 163 164 while (1) { 165 if (!name || !*name) { 166 request = get_request(*rqtbl, curr_rqt++); 167 name = request->command_names; 168 if (!name) { 169 rqtbl++; 170 if (*rqtbl) { 171 curr_rqt = 0; 172 continue; 173 } else 174 break; 175 } 176 } 177 if (strncmp(*name, text, len) == 0) { 178 ret = malloc(strlen(*name)+1); 179 if (ret) 180 strcpy(ret, *name); 181 name++; 182 return ret; 183 } 184 name++; 185 } 186 187 return 0; 188 } 189 190 char **ss_rl_completion(const char *text, int start, 191 int end __SS_ATTR((unused))) 192 { 193 if ((start == 0) && current_info->rl_completion_matches) 194 return (*current_info->rl_completion_matches) 195 (text, cmd_generator); 196 return 0; 197 } 198 #endif 199 200