1997-04-26 17:21:57 +04:00
|
|
|
/*
|
|
|
|
* Listener loop for subsystem library libss.a.
|
|
|
|
*
|
|
|
|
* $Header$
|
|
|
|
* $Locker$
|
|
|
|
*
|
|
|
|
* Copyright 1987, 1988 by MIT Student Information Processing Board
|
|
|
|
*
|
1999-10-23 05:16:22 +04:00
|
|
|
* 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.
|
1997-04-26 17:21:57 +04:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "ss_internal.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <setjmp.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <sys/param.h>
|
|
|
|
|
|
|
|
typedef void sigret_t;
|
|
|
|
|
|
|
|
static ss_data *current_info;
|
|
|
|
static jmp_buf listen_jmpb;
|
2002-03-08 07:52:56 +03:00
|
|
|
static sigret_t (*sig_cont)(int);
|
1997-04-26 17:21:57 +04:00
|
|
|
|
2003-12-07 09:28:50 +03:00
|
|
|
static sigret_t print_prompt(int sig __SS_ATTR((unused)))
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
2003-03-16 14:26:25 +03:00
|
|
|
if (current_info->redisplay)
|
|
|
|
(*current_info->redisplay)();
|
|
|
|
else {
|
|
|
|
(void) fputs(current_info->prompt, stdout);
|
|
|
|
(void) fflush(stdout);
|
|
|
|
}
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
|
2003-12-07 09:28:50 +03:00
|
|
|
static sigret_t listen_int_handler(int sig __SS_ATTR((unused)))
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
|
|
|
putc('\n', stdout);
|
|
|
|
signal(SIGINT, listen_int_handler);
|
|
|
|
longjmp(listen_jmpb, 1);
|
|
|
|
}
|
|
|
|
|
1997-04-29 18:53:37 +04:00
|
|
|
int ss_listen (int sci_idx)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
|
|
|
char *cp;
|
|
|
|
ss_data *info;
|
2002-03-08 07:52:56 +03:00
|
|
|
sigret_t (*sig_int)(int), (*old_sig_cont)(int);
|
1997-04-26 17:21:57 +04:00
|
|
|
char input[BUFSIZ];
|
1997-04-26 17:34:30 +04:00
|
|
|
sigset_t omask, igmask;
|
1997-04-26 17:21:57 +04:00
|
|
|
int code;
|
|
|
|
jmp_buf old_jmpb;
|
|
|
|
ss_data *old_info = current_info;
|
2003-03-16 14:26:25 +03:00
|
|
|
char *line;
|
1997-04-26 17:21:57 +04:00
|
|
|
|
|
|
|
current_info = info = ss_info(sci_idx);
|
1997-04-29 18:53:37 +04:00
|
|
|
sig_cont = (sigret_t (*)(int)) 0;
|
1997-04-26 17:21:57 +04:00
|
|
|
info->abort = 0;
|
1997-04-26 17:34:30 +04:00
|
|
|
sigemptyset(&igmask);
|
|
|
|
sigaddset(&igmask, SIGINT);
|
|
|
|
sigprocmask(SIG_BLOCK, &igmask, &omask);
|
1997-04-26 17:21:57 +04:00
|
|
|
memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf));
|
|
|
|
sig_int = signal(SIGINT, listen_int_handler);
|
|
|
|
setjmp(listen_jmpb);
|
1997-04-26 17:34:30 +04:00
|
|
|
sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
|
2003-03-31 07:26:13 +04:00
|
|
|
|
1997-04-26 17:21:57 +04:00
|
|
|
while(!info->abort) {
|
|
|
|
old_sig_cont = sig_cont;
|
|
|
|
sig_cont = signal(SIGCONT, print_prompt);
|
|
|
|
if (sig_cont == print_prompt)
|
|
|
|
sig_cont = old_sig_cont;
|
2003-03-16 14:26:25 +03:00
|
|
|
if (info->readline) {
|
|
|
|
line = (*info->readline)(current_info->prompt);
|
|
|
|
} else {
|
|
|
|
print_prompt(0);
|
|
|
|
if (fgets(input, BUFSIZ, stdin) == input)
|
|
|
|
line = input;
|
|
|
|
else
|
|
|
|
line = NULL;
|
2002-03-08 07:52:56 +03:00
|
|
|
|
2003-03-16 14:26:25 +03:00
|
|
|
input[BUFSIZ-1] = 0;
|
|
|
|
}
|
|
|
|
if (line == NULL) {
|
|
|
|
code = SS_ET_EOF;
|
|
|
|
(void) signal(SIGCONT, sig_cont);
|
|
|
|
goto egress;
|
|
|
|
}
|
|
|
|
|
|
|
|
cp = strchr(line, '\n');
|
1997-04-26 17:21:57 +04:00
|
|
|
if (cp) {
|
|
|
|
*cp = '\0';
|
2003-03-16 14:26:25 +03:00
|
|
|
if (cp == line)
|
1997-04-26 17:21:57 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
(void) signal(SIGCONT, sig_cont);
|
2003-03-16 14:26:25 +03:00
|
|
|
if (info->add_history)
|
|
|
|
(*info->add_history)(line);
|
1997-04-26 17:21:57 +04:00
|
|
|
|
2003-03-16 14:26:25 +03:00
|
|
|
code = ss_execute_line (sci_idx, line);
|
1997-04-26 17:21:57 +04:00
|
|
|
if (code == SS_ET_COMMAND_NOT_FOUND) {
|
2003-03-16 14:26:25 +03:00
|
|
|
register char *c = line;
|
1997-04-26 17:21:57 +04:00
|
|
|
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);
|
|
|
|
}
|
2003-03-16 14:26:25 +03:00
|
|
|
if (info->readline)
|
|
|
|
free(line);
|
1997-04-26 17:21:57 +04:00
|
|
|
}
|
|
|
|
code = 0;
|
|
|
|
egress:
|
|
|
|
(void) signal(SIGINT, sig_int);
|
|
|
|
memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf));
|
|
|
|
current_info = old_info;
|
|
|
|
return code;
|
|
|
|
}
|
|
|
|
|
1997-04-29 18:53:37 +04:00
|
|
|
void ss_abort_subsystem(int sci_idx, int code)
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
|
|
|
ss_info(sci_idx)->abort = 1;
|
|
|
|
ss_info(sci_idx)->exit_status = code;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2003-12-07 09:28:50 +03:00
|
|
|
void ss_quit(int argc __SS_ATTR((unused)),
|
|
|
|
const char * const *argv __SS_ATTR((unused)),
|
|
|
|
int sci_idx, pointer infop __SS_ATTR((unused)))
|
1997-04-26 17:21:57 +04:00
|
|
|
{
|
|
|
|
ss_abort_subsystem(sci_idx, 0);
|
|
|
|
}
|
2003-03-16 14:26:25 +03:00
|
|
|
|
|
|
|
#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;
|
|
|
|
}
|
|
|
|
|
2003-12-07 09:28:50 +03:00
|
|
|
char **ss_rl_completion(const char *text, int start,
|
|
|
|
int end __SS_ATTR((unused)))
|
2003-03-16 14:26:25 +03:00
|
|
|
{
|
|
|
|
if ((start == 0) && current_info->rl_completion_matches)
|
|
|
|
return (*current_info->rl_completion_matches)
|
|
|
|
(text, cmd_generator);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|