Whamcloud - gitweb
Align function prototypes for libss's request handler function
[tools/e2fsprogs.git] / lib / ss / listen.c
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              ss_argv_t 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