/* * Listener loop for subsystem library libss.a. * * $Header$ * $Locker$ * * Copyright 1987, 1988 by MIT Student Information Processing Board * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose is hereby granted, provided that * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in * advertising or publicity pertaining to distribution of the software * without specific, written prior permission. M.I.T. and the * M.I.T. S.I.P.B. make no representations about the suitability of * this software for any purpose. It is provided "as is" without * express or implied warranty. */ #include "config.h" #include "ss_internal.h" #include #include #include #include typedef void sigret_t; static ss_data *current_info; static jmp_buf listen_jmpb; static sigret_t (*sig_cont)(int); static sigret_t print_prompt(int sig __SS_ATTR((unused))) { if (current_info->redisplay) (*current_info->redisplay)(); else { (void) fputs(current_info->prompt, stdout); (void) fflush(stdout); } } static sigret_t listen_int_handler(int sig __SS_ATTR((unused))) { putc('\n', stdout); signal(SIGINT, listen_int_handler); longjmp(listen_jmpb, 1); } int ss_listen (int sci_idx) { char *cp; ss_data *info; sigret_t (*sig_int)(int), (*old_sig_cont)(int); char input[BUFSIZ]; sigset_t omask, igmask; int code; jmp_buf old_jmpb; ss_data *old_info = current_info; char *line; current_info = info = ss_info(sci_idx); sig_cont = (sigret_t (*)(int)) 0; info->abort = 0; sigemptyset(&igmask); sigaddset(&igmask, SIGINT); sigprocmask(SIG_BLOCK, &igmask, &omask); memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf)); sig_int = signal(SIGINT, listen_int_handler); setjmp(listen_jmpb); sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); while(!info->abort) { old_sig_cont = sig_cont; sig_cont = signal(SIGCONT, print_prompt); if (sig_cont == print_prompt) sig_cont = old_sig_cont; if (info->readline) { line = (*info->readline)(current_info->prompt); } else { print_prompt(0); if (fgets(input, BUFSIZ, stdin) == input) line = input; else line = NULL; input[BUFSIZ-1] = 0; } if (line == NULL) { code = SS_ET_EOF; (void) signal(SIGCONT, sig_cont); goto egress; } cp = strchr(line, '\n'); if (cp) { *cp = '\0'; if (cp == line) continue; } (void) signal(SIGCONT, sig_cont); if (info->add_history) (*info->add_history)(line); code = ss_execute_line (sci_idx, line); if (code == SS_ET_COMMAND_NOT_FOUND) { register char *c = line; while (*c == ' ' || *c == '\t') c++; cp = strchr (c, ' '); if (cp) *cp = '\0'; cp = strchr (c, '\t'); if (cp) *cp = '\0'; ss_error (sci_idx, 0, "Unknown request \"%s\". Type \"?\" for a request list.", c); } if (info->readline) free(line); } code = 0; egress: (void) signal(SIGINT, sig_int); memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf)); current_info = old_info; return code; } void ss_abort_subsystem(int sci_idx, int code) { ss_info(sci_idx)->abort = 1; ss_info(sci_idx)->exit_status = code; } void ss_quit(int argc __SS_ATTR((unused)), const char * const *argv __SS_ATTR((unused)), int sci_idx, pointer infop __SS_ATTR((unused))) { ss_abort_subsystem(sci_idx, 0); } #ifdef HAVE_DLOPEN #define get_request(tbl,idx) ((tbl) -> requests + (idx)) static char *cmd_generator(const char *text, int state) { static int len; static ss_request_table **rqtbl; static int curr_rqt; static char const * const * name; ss_request_entry *request; char *ret; if (state == 0) { len = strlen(text); rqtbl = current_info->rqt_tables; if (!rqtbl || !*rqtbl) return 0; curr_rqt = 0; name = 0; } while (1) { if (!name || !*name) { request = get_request(*rqtbl, curr_rqt++); name = request->command_names; if (!name) { rqtbl++; if (*rqtbl) { curr_rqt = 0; continue; } else break; } } if (strncmp(*name, text, len) == 0) { ret = malloc(strlen(*name)+1); if (ret) strcpy(ret, *name); name++; return ret; } name++; } return 0; } char **ss_rl_completion(const char *text, int start, int end __SS_ATTR((unused))) { if ((start == 0) && current_info->rl_completion_matches) return (*current_info->rl_completion_matches) (text, cmd_generator); return 0; } #endif