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 "config.h" 20 #include "ss_internal.h" 21 #include <stdio.h> 22 #include <setjmp.h> 23 #include <signal.h> 24 #include <sys/param.h> 25 26 typedef void sigret_t; 27 28 static ss_data *current_info; 29 static jmp_buf listen_jmpb; 30 static sigret_t (*sig_cont)(int); 31 32 static sigret_t print_prompt(int sig __SS_ATTR((unused))) 33 { 34 if (current_info->redisplay) 35 (*current_info->redisplay)(); 36 else { 37 (void) fputs(current_info->prompt, stdout); 38 (void) fflush(stdout); 39 } 40 } 41 42 static sigret_t listen_int_handler(int sig __SS_ATTR((unused))) 43 { 44 putc('\n', stdout); 45 signal(SIGINT, listen_int_handler); 46 longjmp(listen_jmpb, 1); 47 } 48 49 int ss_listen (int sci_idx) 50 { 51 char *cp; 52 ss_data *info; 53 sigret_t (*sig_int)(int), (*old_sig_cont)(int); 54 char input[BUFSIZ]; 55 sigset_t omask, igmask; 56 int code; 57 jmp_buf old_jmpb; 58 ss_data *old_info = current_info; 59 char *line; 60 61 current_info = info = ss_info(sci_idx); 62 sig_cont = (sigret_t (*)(int)) 0; 63 info->abort = 0; 64 sigemptyset(&igmask); 65 sigaddset(&igmask, SIGINT); 66 sigprocmask(SIG_BLOCK, &igmask, &omask); 67 memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf)); 68 sig_int = signal(SIGINT, listen_int_handler); 69 setjmp(listen_jmpb); 70 sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); 71 72 while(!info->abort) { 73 old_sig_cont = sig_cont; 74 sig_cont = signal(SIGCONT, print_prompt); 75 if (sig_cont == print_prompt) 76 sig_cont = old_sig_cont; 77 if (info->readline) { 78 line = (*info->readline)(current_info->prompt); 79 } else { 80 print_prompt(0); 81 if (fgets(input, BUFSIZ, stdin) == input) 82 line = input; 83 else 84 line = NULL; 85 86 input[BUFSIZ-1] = 0; 87 } 88 if (line == NULL) { 89 code = SS_ET_EOF; 90 (void) signal(SIGCONT, sig_cont); 91 goto egress; 92 } 93 94 cp = strchr(line, '\n'); 95 if (cp) { 96 *cp = '\0'; 97 if (cp == line) 98 continue; 99 } 100 (void) signal(SIGCONT, sig_cont); 101 if (info->add_history) 102 (*info->add_history)(line); 103 104 code = ss_execute_line (sci_idx, line); 105 if (code == SS_ET_COMMAND_NOT_FOUND) { 106 register char *c = line; 107 while (*c == ' ' || *c == '\t') 108 c++; 109 cp = strchr (c, ' '); 110 if (cp) 111 *cp = '\0'; 112 cp = strchr (c, '\t'); 113 if (cp) 114 *cp = '\0'; 115 ss_error (sci_idx, 0, 116 "Unknown request \"%s\". Type \"?\" for a request list.", 117 c); 118 } 119 if (info->readline) 120 free(line); 121 } 122 code = 0; 123 egress: 124 (void) signal(SIGINT, sig_int); 125 memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf)); 126 current_info = old_info; 127 return code; 128 } 129 130 void ss_abort_subsystem(int sci_idx, int code) 131 { 132 ss_info(sci_idx)->abort = 1; 133 ss_info(sci_idx)->exit_status = code; 134 135 } 136 137 void ss_quit(int argc __SS_ATTR((unused)), 138 const char * const *argv __SS_ATTR((unused)), 139 int sci_idx, pointer infop __SS_ATTR((unused))) 140 { 141 ss_abort_subsystem(sci_idx, 0); 142 } 143 144 #ifdef HAVE_DLOPEN 145 #define get_request(tbl,idx) ((tbl) -> requests + (idx)) 146 147 static char *cmd_generator(const char *text, int state) 148 { 149 static int len; 150 static ss_request_table **rqtbl; 151 static int curr_rqt; 152 static char const * const * name; 153 ss_request_entry *request; 154 char *ret; 155 156 if (state == 0) { 157 len = strlen(text); 158 rqtbl = current_info->rqt_tables; 159 if (!rqtbl || !*rqtbl) 160 return 0; 161 curr_rqt = 0; 162 name = 0; 163 } 164 165 while (1) { 166 if (!name || !*name) { 167 request = get_request(*rqtbl, curr_rqt++); 168 name = request->command_names; 169 if (!name) { 170 rqtbl++; 171 if (*rqtbl) { 172 curr_rqt = 0; 173 continue; 174 } else 175 break; 176 } 177 } 178 if (strncmp(*name, text, len) == 0) { 179 ret = malloc(strlen(*name)+1); 180 if (ret) 181 strcpy(ret, *name); 182 name++; 183 return ret; 184 } 185 name++; 186 } 187 188 return 0; 189 } 190 191 char **ss_rl_completion(const char *text, int start, 192 int end __SS_ATTR((unused))) 193 { 194 if ((start == 0) && current_info->rl_completion_matches) 195 return (*current_info->rl_completion_matches) 196 (text, cmd_generator); 197 return 0; 198 } 199 #endif 200 201