]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/console/console.c
Implement Qmsg() + conio linking
[bacula/bacula] / bacula / src / console / console.c
index e424a4300f480319197d00b0b210d78439706bc3..614951411754f432c660b06e794e292173aa19aa 100644 (file)
 #include "bacula.h"
 #include "console_conf.h"
 #include "jcr.h"
-/* Imported functions */
-int authenticate_director(JCR *jcr, DIRRES *director);
 
-       
+#ifdef HAVE_CONIO
+#include "conio.h"
+#else
+#define con_init(x) 
+#define con_term()
+#define con_set_zed_keys();
+#define trapctlc()
+#define clrbrk()
+#define usrbrk() 0  
+#endif
 /* Exported variables */
 
-
 #ifdef HAVE_CYGWIN
 int rl_catch_signals;
 #else
 extern int rl_catch_signals;
 #endif
 
+/* Imported functions */
+int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons);
+
+
+
 /* Forward referenced functions */
 static void terminate_console(int sig);
 int get_cmd(FILE *input, char *prompt, BSOCK *sock, int sec);
 static int do_outputcmd(FILE *input, BSOCK *UA_sock);
-static void sendit(char *fmt, ...);
+void senditf(char *fmt, ...);
+void sendit(char *buf);
 
 /* Static variables */
 static char *configfile = NULL;
 static BSOCK *UA_sock = NULL;
 static DIRRES *dir; 
 static FILE *output = stdout;
-int tee = 0;                         /* output to output and stdout */
-static int stop = FALSE;
+static bool tee = false;                 /* output to output and stdout */
+static bool stop = false;
 static int argc;
 static POOLMEM *args;
 static char *argk[MAX_CMD_ARGS];
 static char *argv[MAX_CMD_ARGS];
 
+
 /* Command prototypes */
 static int versioncmd(FILE *input, BSOCK *UA_sock);
 static int inputcmd(FILE *input, BSOCK *UA_sock);
@@ -72,44 +85,50 @@ static int timecmd(FILE *input, BSOCK *UA_sock);
 static int sleepcmd(FILE *input, BSOCK *UA_sock);
 
 
-#define CONFIG_FILE "./console.conf"   /* default configuration file */
+#define CONFIG_FILE "./bconsole.conf"   /* default configuration file */
 
 static void usage()
 {
    fprintf(stderr, _(
 "\nVersion: " VERSION " (" BDATE ") %s %s %s\n\n"
-"Usage: console [-s] [-c config_file] [-d debug_level] [config_file]\n"
+"Usage: bconsole [-s] [-c config_file] [-d debug_level] [config_file]\n"
 "       -c <file>   set configuration file to file\n"
 "       -dnn        set debug level to nn\n"
 "       -s          no signals\n"
 "       -t          test - read configuration and exit\n"
 "       -?          print this message.\n"  
 "\n"), HOST_OS, DISTNAME, DISTVER);
-
-   exit(1);
 }
 
-
-void got_stop(int sig)
+void got_sigstop(int sig)
 {
-   stop = TRUE;
+   stop = true;
 }
 
-void got_continue(int sig)
+void got_sigcontinue(int sig)
 {
-   stop = FALSE;
+   stop = false;
 }
 
-void got_tout(int sig) 
+void got_sigtout(int sig) 
 {
 // printf("Got tout\n");
 }
 
-void got_tin(int sig)
+void got_sigtin(int sig)
 {   
 // printf("Got tin\n");
 }
 
+static int zed_keyscmd(FILE *input, BSOCK *UA_sock)
+{
+   con_set_zed_keys();
+   return 1;
+}
+
+/*
+ * These are the @command
+ */
 struct cmdstruct { char *key; int (*func)(FILE *input, BSOCK *UA_sock); char *help; }; 
 static struct cmdstruct commands[] = {
  { N_("input"),      inputcmd,     _("input from file")},
@@ -120,6 +139,7 @@ static struct cmdstruct commands[] = {
  { N_("time"),       timecmd,      _("print current time")},
  { N_("version"),    versioncmd,   _("print Console's version")},
  { N_("exit"),       quitcmd,      _("exit = quit")},
+ { N_("zed_keyst"),  zed_keyscmd,  _("zed_keys = use zed keys instead of bash keys")},
             };
 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
 
@@ -154,8 +174,7 @@ static int do_a_command(FILE *input, BSOCK *UA_sock)
    if (!found) {
       pm_strcat(&UA_sock->msg, _(": is an illegal command\n"));
       UA_sock->msglen = strlen(UA_sock->msg);
-      fputs(UA_sock->msg, output);
-      fflush(output);
+      sendit(UA_sock->msg);
    }
    return stat;
 }
@@ -164,7 +183,7 @@ static int do_a_command(FILE *input, BSOCK *UA_sock)
 static void read_and_process_input(FILE *input, BSOCK *UA_sock) 
 {
    char *prompt = "*";
-   int at_prompt = FALSE;
+   bool at_prompt = false;
    int tty_input = isatty(fileno(input));
    int stat;
 
@@ -173,23 +192,33 @@ static void read_and_process_input(FILE *input, BSOCK *UA_sock)
          prompt = "";
       } else {
          prompt = "*";
-        at_prompt = TRUE;
+        at_prompt = true;
       }
       if (tty_input) {
         stat = get_cmd(input, prompt, UA_sock, 30);
+        if (usrbrk() == 1) {
+           clrbrk();
+        }
+        if (usrbrk()) {
+           break;
+        }
       } else {
+        /* Reading input from a file */
         int len = sizeof_pool_memory(UA_sock->msg) - 1;
+        if (usrbrk()) {
+           break;
+        }
         if (fgets(UA_sock->msg, len, input) == NULL) {
            stat = -1;
         } else {
-            sendit("%s", UA_sock->msg);  /* echo to terminal */
+           sendit(UA_sock->msg);  /* echo to terminal */
            strip_trailing_junk(UA_sock->msg);
            UA_sock->msglen = strlen(UA_sock->msg);
            stat = 1;
         }
       }
       if (stat < 0) {
-        break;                       /* error */
+        break;                       /* error or interrupt */
       } else if (stat == 0) {        /* timeout */
          if (strcmp(prompt, "*") == 0) {
             bnet_fsend(UA_sock, ".messages");
@@ -218,12 +247,18 @@ static void read_and_process_input(FILE *input, BSOCK *UA_sock)
            if (!stop) {
                sendit("\n");
            }
-           at_prompt = FALSE;
+           at_prompt = false;
         }
-        if (!stop) {
-            sendit("%s", UA_sock->msg);
+        /* Suppress output if running in background or user hit ctl-c */
+        if (!stop && !usrbrk()) {
+           sendit(UA_sock->msg);
         }
       }
+      if (usrbrk() > 1) {
+        break;
+      } else {
+        clrbrk();
+      }
       if (!stop) {
         fflush(stdout);
       }
@@ -231,7 +266,7 @@ static void read_and_process_input(FILE *input, BSOCK *UA_sock)
         break;                       /* error or term */
       } else if (stat == BNET_SIGNAL) {
         if (UA_sock->msglen == BNET_PROMPT) {
-           at_prompt = TRUE;
+           at_prompt = true;
         }
          Dmsg1(100, "Got poll %s\n", bnet_sig_to_ascii(UA_sock));
       }
@@ -247,16 +282,17 @@ static void read_and_process_input(FILE *input, BSOCK *UA_sock)
 int main(int argc, char *argv[])
 {
    int ch, i, ndir, item;
-   int no_signals = FALSE;
-   int test_config = FALSE;
+   bool no_signals = false;
+   bool test_config = false;
    JCR jcr;
 
    init_stack_dump();
-   my_name_is(argc, argv, "console");
+   my_name_is(argc, argv, "bconsole");
    textdomain("bacula-console");
    init_msg(NULL, NULL);
    working_directory = "/tmp";
    args = get_pool_memory(PM_FNAME);
+   con_init(stdin);
 
    while ((ch = getopt(argc, argv, "bc:d:r:st?")) != -1) {
       switch (ch) {
@@ -275,17 +311,18 @@ int main(int argc, char *argv[])
         break;
 
       case 's':                    /* turn off signals */
-        no_signals = TRUE;
+        no_signals = true;
         break;
 
       case 't':
-        test_config = TRUE;
+        test_config = true;
         break;
 
       case '?':
       default:
         usage();
-
+        con_term();
+        exit(1);
       }  
    }
    argc -= optind;
@@ -294,14 +331,19 @@ int main(int argc, char *argv[])
    if (!no_signals) {
       init_signals(terminate_console);
    }
+
+   /* Override Bacula default signals */
    signal(SIGCHLD, SIG_IGN);
-   signal(SIGTSTP, got_stop);
-   signal(SIGCONT, got_continue);
-   signal(SIGTTIN, got_tin);
-   signal(SIGTTOU, got_tout);
+   signal(SIGTSTP, got_sigstop);
+   signal(SIGCONT, got_sigcontinue);
+   signal(SIGTTIN, got_sigtin);
+   signal(SIGTTOU, got_sigtout);
+   trapctlc();
 
    if (argc) {
       usage();
+      con_term();
+      exit(1);
    }
 
    if (configfile == NULL) {
@@ -312,11 +354,12 @@ int main(int argc, char *argv[])
 
    LockRes();
    ndir = 0;
-   for (dir=NULL; (dir = (DIRRES *)GetNextRes(R_DIRECTOR, (RES *)dir)); ) {
+   foreach_res(dir, R_DIRECTOR) {
       ndir++;
    }
    UnlockRes();
    if (ndir == 0) {
+      con_term();
       Emsg1(M_ERROR_TERM, 0, _("No Director resource defined in %s\n\
 Without that I don't how to speak to the Director :-(\n"), configfile);
    }
@@ -328,14 +371,17 @@ Without that I don't how to speak to the Director :-(\n"), configfile);
 
    memset(&jcr, 0, sizeof(jcr));
 
+
    if (ndir > 1) {
-      UA_sock = init_bsock(NULL, 0, "", "", 0);
+      struct sockaddr_in client_addr;
+      memset(&client_addr, 0, sizeof(client_addr));
+      UA_sock = init_bsock(NULL, 0, "", "", 0, &client_addr);
 try_again:
       sendit(_("Available Directors:\n"));
       LockRes();
       ndir = 0;
-      for (dir = NULL; (dir = (DIRRES *)GetNextRes(R_DIRECTOR, (RES *)dir)); ) {
-         fprintf(output, _("%d  %s at %s:%d\n"), 1+ndir++, dir->hdr.name, dir->address,
+      foreach_res(dir, R_DIRECTOR) {
+         senditf( _("%d  %s at %s:%d\n"), 1+ndir++, dir->hdr.name, dir->address,
            dir->DIRport);
       }
       UnlockRes();
@@ -344,7 +390,7 @@ try_again:
       }
       item = atoi(UA_sock->msg);
       if (item < 0 || item > ndir) {
-         sendit(_("You must enter a number between 1 and %d\n"), ndir);
+         senditf(_("You must enter a number between 1 and %d\n"), ndir);
         goto try_again;
       }
       LockRes();
@@ -360,8 +406,7 @@ try_again:
       UnlockRes();
    }
       
-
-   sendit(_("Connecting to Director %s:%d\n"), dir->address,dir->DIRport);
+   senditf(_("Connecting to Director %s:%d\n"), dir->address,dir->DIRport);
    UA_sock = bnet_connect(NULL, 5, 15, "Director daemon", dir->address, 
                          NULL, dir->DIRport, 0);
    if (UA_sock == NULL) {
@@ -369,7 +414,12 @@ try_again:
       return 1;
    }
    jcr.dir_bsock = UA_sock;
-   if (!authenticate_director(&jcr, dir)) {
+
+   LockRes();
+   CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
+   UnlockRes();
+   /* If cons==NULL, default console will be used */
+   if (!authenticate_director(&jcr, dir, cons)) {
       fprintf(stderr, "ERR=%s", UA_sock->msg);
       terminate_console(0);
       return 1;
@@ -379,6 +429,19 @@ try_again:
 
    sendit(_("Enter a period to cancel a command.\n"));
 
+   /* Run commands in ~/.bconsolerc if any */
+   char *env = getenv("HOME");
+   if (env) {
+      FILE *fd;
+      pm_strcpy(&UA_sock->msg, env);
+      pm_strcat(&UA_sock->msg, "/.bconsolerc");
+      fd = fopen(UA_sock->msg, "r");
+      if (fd) {
+        read_and_process_input(fd, UA_sock);
+        fclose(fd);
+      }
+   }
+
    read_and_process_input(stdin, UA_sock);
 
    if (UA_sock) {
@@ -394,13 +457,14 @@ try_again:
 /* Cleanup and then exit */
 static void terminate_console(int sig)
 {
-   static int already_here = FALSE;
+   static bool already_here = false;
 
    if (already_here) {               /* avoid recursive temination problems */
       exit(1);
    }
-   already_here = TRUE;
+   already_here = true;
    free_pool_memory(args);
+   con_term();
    if (sig != 0) {
       exit(1);
    }
@@ -479,8 +543,7 @@ get_cmd(FILE *input, char *prompt, BSOCK *sock, int sec)
    int len;  
    if (!stop) {
       if (output == stdout || tee) {
-        fputs(prompt, stdout);
-        fflush(stdout);
+        sendit(prompt);
       }
    }
 again:
@@ -495,11 +558,20 @@ again:
         sleep(1);
         goto again;
       }
+#ifdef HAVE_CONIO
+      if (isatty(fileno(input))) {
+        input_line(sock->msg, len);
+        break;
+      }
+#endif
       if (fgets(sock->msg, len, input) == NULL) {
         return -1;
       }
       break;
    }
+   if (usrbrk()) {
+      clrbrk();
+   }
    strip_trailing_junk(sock->msg);
    sock->msglen = strlen(sock->msg);
    return 1;
@@ -509,7 +581,7 @@ again:
 
 static int versioncmd(FILE *input, BSOCK *UA_sock)
 {
-   sendit("Version: " VERSION " (" BDATE ") %s %s %s\n",
+   senditf("Version: " VERSION " (" BDATE ") %s %s %s\n",
       HOST_OS, DISTNAME, DISTVER);
    return 1;
 }
@@ -528,7 +600,7 @@ static int inputcmd(FILE *input, BSOCK *UA_sock)
    }
    fd = fopen(argk[1], "r");
    if (!fd) {
-      sendit(_("Cannot open file %s for input. ERR=%s\n"), 
+      senditf(_("Cannot open file %s for input. ERR=%s\n"), 
         argk[1], strerror(errno));
       return 1; 
    }
@@ -537,15 +609,17 @@ static int inputcmd(FILE *input, BSOCK *UA_sock)
    return 1;
 }
 
+/* Send output to both termina and specified file */
 static int teecmd(FILE *input, BSOCK *UA_sock)
 {
-   tee = 1;
+   tee = true;
    return do_outputcmd(input, UA_sock);
 }
 
+/* Send output to specified "file" */
 static int outputcmd(FILE *input, BSOCK *UA_sock)
 {
-   tee = 0;
+   tee = false;
    return do_outputcmd(input, UA_sock);
 }
 
@@ -563,7 +637,7 @@ static int do_outputcmd(FILE *input, BSOCK *UA_sock)
       if (output != stdout) {
         fclose(output);
         output = stdout;
-        tee = 0;
+        tee = false;
       }
       return 1;
    }
@@ -572,7 +646,7 @@ static int do_outputcmd(FILE *input, BSOCK *UA_sock)
    }
    fd = fopen(argk[1], mode);
    if (!fd) {
-      sendit(_("Cannot open file %s for output. ERR=%s\n"), 
+      senditf(_("Cannot open file %s for output. ERR=%s\n"), 
         argk[1], strerror(errno));
       return 1; 
    }
@@ -601,12 +675,14 @@ static int timecmd(FILE *input, BSOCK *UA_sock)
    struct tm tm;
    localtime_r(&ttime, &tm);
    strftime(sdt, sizeof(sdt), "%d-%b-%Y %H:%M:%S", &tm);
-   sendit(sdt);
    sendit("\n");
    return 1;
 }
 
-static void sendit(char *fmt,...)
+/*
+ * Send a line to the output file and or the terminal
+ */
+void senditf(char *fmt,...)
 {
     char buf[3000];
     va_list arg_ptr;
@@ -614,9 +690,38 @@ static void sendit(char *fmt,...)
     va_start(arg_ptr, fmt);
     bvsnprintf(buf, sizeof(buf), (char *)fmt, arg_ptr);
     va_end(arg_ptr);
+    sendit(buf);
+}
+
+void sendit(char *buf)
+{
+#ifdef xHAVE_CONIO
+    if (output == stdout || tee) {
+       char *p, *q;    
+       /*
+        * Here, we convert every \n into \r\n because the
+       *  terminal is in raw mode when we are using 
+       *  conio.
+       */
+       for (p=q=buf; (p=strchr(q, '\n')); ) {
+         if (p-q > 0) {
+            t_sendl(q, p-q);
+         }
+          t_sendl("\r\n", 2);
+          q = ++p;                    /* point after \n */
+       }
+       if (*q) {
+         t_send(q);
+       }
+    }
+    if (output != stdout) {
+       fputs(buf, output);
+    }
+#else
     fputs(buf, output);
     if (tee) {
        fputs(buf, stdout);
     }
     fflush(stdout);
+#endif
 }