diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 09:25:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 09:25:10 +0000 |
commit | 5dced3d1b3deca80e01415a2e35dc7972dcbfae7 (patch) | |
tree | 6a403684e0978f0287d7f0ec0e5aab1fd31a59e1 /lib/ss/listen.c | |
parent | Initial commit. (diff) | |
download | e2fsprogs-5dced3d1b3deca80e01415a2e35dc7972dcbfae7.tar.xz e2fsprogs-5dced3d1b3deca80e01415a2e35dc7972dcbfae7.zip |
Adding upstream version 1.47.0.upstream/1.47.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/ss/listen.c')
-rw-r--r-- | lib/ss/listen.c | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/lib/ss/listen.c b/lib/ss/listen.c new file mode 100644 index 0000000..9578c3e --- /dev/null +++ b/lib/ss/listen.c @@ -0,0 +1,200 @@ +/* + * 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 <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; +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 + |