Whamcloud - gitweb
libss: fix function delcaration in the test_ss regression test
[tools/e2fsprogs.git] / lib / ss / listen.c
index 04b8302..df1311d 100644 (file)
@@ -3,7 +3,7 @@
  *
  *     $Header$
  *     $Locker$
- * 
+ *
  * Copyright 1987, 1988 by MIT Student Information Processing Board
  *
  * Permission to use, copy, modify, and distribute this software and
  * express or implied warranty.
  */
 
+#include "config.h"
 #include "ss_internal.h"
 #include <stdio.h>
 #include <setjmp.h>
 #include <signal.h>
 #include <sys/param.h>
-#ifdef BSD
-#include <sgtty.h>
-#endif
-
-#ifndef        lint
-static char const rcs_id[] =
-    "$Header$";
-#endif
 
 typedef void sigret_t;
 
@@ -36,23 +29,17 @@ static ss_data *current_info;
 static jmp_buf listen_jmpb;
 static sigret_t (*sig_cont)(int);
 
-static sigret_t print_prompt(int sig)
+static sigret_t print_prompt(int sig __SS_ATTR((unused)))
 {
-#ifdef BSD
-    /* put input into a reasonable mode */
-    struct sgttyb ttyb;
-    if (ioctl(fileno(stdin), TIOCGETP, &ttyb) != -1) {
-       if (ttyb.sg_flags & (CBREAK|RAW)) {
-           ttyb.sg_flags &= ~(CBREAK|RAW);
-           (void) ioctl(0, TIOCSETP, &ttyb);
-       }
+    if (current_info->redisplay)
+           (*current_info->redisplay)();
+    else {
+           (void) fputs(current_info->prompt, stdout);
+           (void) fflush(stdout);
     }
-#endif
-    (void) fputs(current_info->prompt, stdout);
-    (void) fflush(stdout);
 }
 
-static sigret_t listen_int_handler(int sig)
+static sigret_t listen_int_handler(int sig __SS_ATTR((unused)))
 {
     putc('\n', stdout);
     signal(SIGINT, listen_int_handler);
@@ -65,57 +52,58 @@ int ss_listen (int sci_idx)
     ss_data *info;
     sigret_t (*sig_int)(int), (*old_sig_cont)(int);
     char input[BUFSIZ];
-#ifdef POSIX_SIGNALS
     sigset_t omask, igmask;
-#else
-    int mask;
-#endif
     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;
-#ifdef POSIX_SIGNALS
     sigemptyset(&igmask);
     sigaddset(&igmask, SIGINT);
     sigprocmask(SIG_BLOCK, &igmask, &omask);
-#else
-    mask = sigblock(sigmask(SIGINT));
-#endif
     memcpy(old_jmpb, listen_jmpb, sizeof(jmp_buf));
     sig_int = signal(SIGINT, listen_int_handler);
     setjmp(listen_jmpb);
-#ifdef POSIX_SIGNALS
     sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0);
-#else
-    (void) sigsetmask(mask);
-#endif
+
     while(!info->abort) {
-       print_prompt(0);
        old_sig_cont = sig_cont;
        sig_cont = signal(SIGCONT, print_prompt);
        if (sig_cont == print_prompt)
            sig_cont = old_sig_cont;
-       if (fgets(input, BUFSIZ, stdin) != input) {
-           code = SS_ET_EOF;
-           (void) signal(SIGCONT, sig_cont);
-           goto egress;
+       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;
        }
-       input[BUFSIZ-1] = 0;
-       
-       cp = strchr(input, '\n');
+       if (line == NULL) {
+               code = SS_ET_EOF;
+               (void) signal(SIGCONT, sig_cont);
+               goto egress;
+       }
+
+       cp = strchr(line, '\n');
        if (cp) {
            *cp = '\0';
-           if (cp == input)
+           if (cp == line)
                continue;
        }
        (void) signal(SIGCONT, sig_cont);
+       if (info->add_history)
+               (*info->add_history)(line);
 
-       code = ss_execute_line (sci_idx, input);
+       code = ss_execute_line (sci_idx, line);
        if (code == SS_ET_COMMAND_NOT_FOUND) {
-           register char *c = input;
+           register char *c = line;
            while (*c == ' ' || *c == '\t')
                c++;
            cp = strchr (c, ' ');
@@ -128,6 +116,8 @@ int ss_listen (int sci_idx)
                    "Unknown request \"%s\".  Type \"?\" for a request list.",
                       c);
        }
+       if (info->readline)
+               free(line);
     }
     code = 0;
 egress:
@@ -141,10 +131,70 @@ 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, const char * const *argv, int sci_idx, pointer infop)
+void ss_quit(int argc __SS_ATTR((unused)),
+            ss_argv_t 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
+