Whamcloud - gitweb
Update changelogs for 1.22.
[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 "ss_internal.h"
20 #include <stdio.h>
21 #include <setjmp.h>
22 #include <signal.h>
23 #include <sys/param.h>
24 #ifdef BSD
25 #include <sgtty.h>
26 #endif
27
28 #ifndef lint
29 static char const rcs_id[] =
30     "$Header$";
31 #endif
32
33 typedef void sigret_t;
34
35 static ss_data *current_info;
36 static jmp_buf listen_jmpb;
37
38 static sigret_t print_prompt(int sig)
39 {
40 #ifdef BSD
41     /* put input into a reasonable mode */
42     struct sgttyb ttyb;
43     if (ioctl(fileno(stdin), TIOCGETP, &ttyb) != -1) {
44         if (ttyb.sg_flags & (CBREAK|RAW)) {
45             ttyb.sg_flags &= ~(CBREAK|RAW);
46             (void) ioctl(0, TIOCSETP, &ttyb);
47         }
48     }
49 #endif
50     (void) fputs(current_info->prompt, stdout);
51     (void) fflush(stdout);
52 }
53
54 static sigret_t listen_int_handler(int sig)
55 {
56     putc('\n', stdout);
57     signal(SIGINT, listen_int_handler);
58     longjmp(listen_jmpb, 1);
59 }
60
61 int ss_listen (int sci_idx)
62 {
63     char *cp;
64     ss_data *info;
65     sigret_t (*sig_int)(int), (*sig_cont)(int), (*old_sig_cont)(int);
66     char input[BUFSIZ];
67     char buffer[BUFSIZ];
68     char *end = buffer;
69 #ifdef POSIX_SIGNALS
70     sigset_t omask, igmask;
71 #else
72     int mask;
73 #endif
74     int code;
75     jmp_buf old_jmpb;
76     ss_data *old_info = current_info;
77     
78     current_info = info = ss_info(sci_idx);
79     sig_cont = (sigret_t (*)(int)) 0;
80     info->abort = 0;
81 #ifdef POSIX_SIGNALS
82     sigemptyset(&igmask);
83     sigaddset(&igmask, SIGINT);
84     sigprocmask(SIG_BLOCK, &igmask, &omask);
85 #else
86     mask = sigblock(sigmask(SIGINT));
87 #endif
88     memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf));
89     sig_int = signal(SIGINT, listen_int_handler);
90     setjmp(listen_jmpb);
91 #ifdef POSIX_SIGNALS
92     sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
93 #else
94     (void) sigsetmask(mask);
95 #endif
96     while(!info->abort) {
97         print_prompt(0);
98         *end = '\0';
99         old_sig_cont = sig_cont;
100         sig_cont = signal(SIGCONT, print_prompt);
101         if (sig_cont == print_prompt)
102             sig_cont = old_sig_cont;
103         if (fgets(input, BUFSIZ, stdin) != input) {
104             code = SS_ET_EOF;
105             goto egress;
106         }
107         cp = strchr(input, '\n');
108         if (cp) {
109             *cp = '\0';
110             if (cp == input)
111                 continue;
112         }
113         (void) signal(SIGCONT, sig_cont);
114         for (end = input; *end; end++)
115             ;
116
117         code = ss_execute_line (sci_idx, input);
118         if (code == SS_ET_COMMAND_NOT_FOUND) {
119             register char *c = input;
120             while (*c == ' ' || *c == '\t')
121                 c++;
122             cp = strchr (c, ' ');
123             if (cp)
124                 *cp = '\0';
125             cp = strchr (c, '\t');
126             if (cp)
127                 *cp = '\0';
128             ss_error (sci_idx, 0,
129                     "Unknown request \"%s\".  Type \"?\" for a request list.",
130                        c);
131         }
132     }
133     code = 0;
134 egress:
135     (void) signal(SIGINT, sig_int);
136     memcpy(listen_jmpb, old_jmpb, sizeof(jmp_buf));
137     current_info = old_info;
138     return code;
139 }
140
141 void ss_abort_subsystem(int sci_idx, int code)
142 {
143     ss_info(sci_idx)->abort = 1;
144     ss_info(sci_idx)->exit_status = code;
145     
146 }
147
148 void ss_quit(int argc, const char * const *argv, int sci_idx, pointer infop)
149 {
150     ss_abort_subsystem(sci_idx, 0);
151 }