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
print_prompt(int sig __SS_ATTR ((unused)))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
listen_int_handler(int sig __SS_ATTR ((unused)))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
ss_listen(int sci_idx)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
ss_abort_subsystem(int sci_idx,int code)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
ss_quit(int argc __SS_ATTR ((unused)),const char * const * argv __SS_ATTR ((unused)),int sci_idx,pointer infop __SS_ATTR ((unused)))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
cmd_generator(const char * text,int state)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
ss_rl_completion(const char * text,int start,int end __SS_ATTR ((unused)))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