]> code.citadel.org Git - citadel.git/blobdiff - citadel/commands.c
* The size constant "256" which shows up everywhere as a buffer size has now
[citadel.git] / citadel / commands.c
index 6186f3fd98d8096726f903d17f9488b2304963eb..3a67eb77eff00991902fe841f57841fef638d30b 100644 (file)
@@ -40,6 +40,7 @@
 #include "routines.h"
 #include "routines2.h"
 #include "tools.h"
+#include "rooms.h"
 #ifndef HAVE_SNPRINTF
 #include "snprintf.h"
 #endif
@@ -55,18 +56,23 @@ struct citcmd {
 
 
 int rc_exp_beep;
-char rc_exp_cmd[256];
+char rc_exp_cmd[1024];
 int rc_allow_attachments;
 int rc_display_message_numbers;
 int rc_force_mail_prompts;
+int rc_remember_passwords;
 int rc_ansi_color;
 int num_urls = 0;
-char urls[MAXURLS][256];
-char rc_url_cmd[256];
+char urls[MAXURLS][1024];
+char rc_url_cmd[1024];
 
 char *gl_string;
 int next_lazy_cmd = 5;
 
+int lines_printed = 0;         /* line count for paginator */
+extern int screenwidth, screenheight;
+extern int termn8;
+
 struct citcmd *cmdlist = NULL;
 
 
@@ -77,43 +83,223 @@ time_t AnsiDetect;                 /* when did we send the detect code? */
 int enable_color = 0;                  /* nonzero for ANSI color */
 
 
+
+
+/*
+ * If an interesting key has been pressed, return its value, otherwise 0
+ */
+char was_a_key_pressed(void) {
+       fd_set rfds;
+       struct timeval tv;
+       int the_character;
+       int retval;
+
+       FD_ZERO(&rfds);
+       FD_SET(0, &rfds);
+       tv.tv_sec = 0;
+       tv.tv_usec = 0;
+       retval = select(1, &rfds, NULL, NULL, &tv); 
+
+       /* Careful!  Disable keepalives during keyboard polling; we're probably
+        * in the middle of a data transfer from the server, in which case
+        * sending a NOOP would throw the client protocol out of sync.
+        */
+       if (FD_ISSET(0, &rfds)) {
+               set_keepalives(KA_NO);
+               the_character = inkey();
+               set_keepalives(KA_YES);
+       }
+       else {
+               the_character = 0;
+       }
+       return(the_character);
+}
+
+
+
+
+
+/*
+ * Check to see if we need to pause at the end of a screen.
+ * If we do, we have to disable server keepalives during the pause because
+ * we are probably in the middle of a server operation and the NOOP command
+ * would confuse everything.
+ */
+int checkpagin(int lp, int pagin, int height)
+{
+       int thekey;
+
+       if (sigcaught) return(lp);
+       thekey = was_a_key_pressed();
+       if ( (thekey == NEXT_KEY) || (thekey == STOP_KEY)) sigcaught = thekey;
+       if (sigcaught) return(lp);
+
+       if (!pagin) return(0);
+       if (lp>=(height-1)) {
+               set_keepalives(KA_NO);
+               hit_any_key();
+               set_keepalives(KA_YES);
+               return(0);
+       }
+       return(lp);
+}
+
+
+
+
+/*
+ * pprintf()  ...   paginated version of printf()
+ */
+void pprintf(const char *format, ...) {   
+        va_list arg_ptr;
+       static char buf[4096];  /* static for performance, change if needed */
+       int i;
+
+       /* If sigcaught is nonzero, a keypress has interrupted this and we
+        * should just drain output.
+        */
+       if (sigcaught) return;
+       /* Otherwise, start spewing... */ 
+        va_start(arg_ptr, format);   
+        vsprintf(buf, format, arg_ptr);   
+        va_end(arg_ptr);   
+
+       for (i=0; i<strlen(buf); ++i) {
+               putc(buf[i], stdout);
+               if (buf[i]==10) {
+                       ++lines_printed;
+                       lines_printed = checkpagin(lines_printed,
+                               (userflags & US_PAGINATOR),
+                               screenheight);
+               }
+       }
+}   
+
+
+
 /*
  * print_express()  -  print express messages if there are any
  */
 void print_express(void)
 {
-       char buf[256];
+       char buf[1024];
        FILE *outpipe;
+       time_t timestamp;
+       struct tm *stamp;
+       int flags = 0;
+       char sender[64];
+       char node[64];
 
        if (express_msgs == 0)
                return;
-       express_msgs = 0;
-       serv_puts("PEXP");
-       serv_gets(buf);
-       if (buf[0] != '1')
-               return;
 
-       if (strlen(rc_exp_cmd) > 0) {
-               outpipe = popen(rc_exp_cmd, "w");
-               if (outpipe != NULL) {
-                       while (serv_gets(buf), strcmp(buf, "000")) {
-                               fprintf(outpipe, "%s\n", buf);
-                       }
-                       pclose(outpipe);
-                       return;
-               }
-       }
-       /* fall back to built-in express message display */
        if (rc_exp_beep) {
                putc(7, stdout);
        }
-       color(BRIGHT_RED);
-       printf("\r---\n");
-       while (serv_gets(buf), strcmp(buf, "000")) {
-               printf("%s\n", buf);
+       if (strlen(rc_exp_cmd) == 0) {
+               color(BRIGHT_RED);
+               printf("\r---");
        }
-       printf("---\n");
+       
+       while (express_msgs != 0) {
+               serv_puts("GEXP");
+               serv_gets(buf);
+               if (buf[0] != '1')
+                       return;
+       
+               express_msgs = extract_int(&buf[4], 0);
+               timestamp = extract_long(&buf[4], 1);
+               flags = extract_int(&buf[4], 2);
+               extract(sender, &buf[4], 3);
+               extract(node, &buf[4], 4);
+       
+               stamp = localtime(&timestamp);
+
+               /* If the page is a Logoff Request, honor it. */
+               if (flags & 2) {
+                       termn8 = 1;
+                       return;
+               }
+       
+               if (strlen(rc_exp_cmd) > 0) {
+                       outpipe = popen(rc_exp_cmd, "w");
+                       if (outpipe != NULL) {
+                               /* Header derived from flags */
+                               if (flags & 2)
+                                       fprintf(outpipe,
+                                              "Please log off now, as requested ");
+                               else if (flags & 1)
+                                       fprintf(outpipe, "Broadcast message ");
+                               else if (flags & 4)
+                                       fprintf(outpipe, "Chat request ");
+                               else
+                                       fprintf(outpipe, "Message ");
+                               /* Timestamp.  Can this be improved? */
+                               if (stamp->tm_hour == 0 || stamp->tm_hour == 12)
+                                       fprintf(outpipe, "at 12:%02d%cm",
+                                               stamp->tm_min, 
+                                               stamp->tm_hour ? 'p' : 'a');
+                               else if (stamp->tm_hour > 12)           /* pm */
+                                       fprintf(outpipe, "at %d:%02dpm",
+                                               stamp->tm_hour - 12,
+                                               stamp->tm_min);
+                               else                                    /* am */
+                                       fprintf(outpipe, "at %d:%02dam",
+                                               stamp->tm_hour, stamp->tm_min);
+                               fprintf(outpipe, " from %s", sender);
+                               if (strncmp(serv_info.serv_nodename, node, 32))
+                                       fprintf(outpipe, " @%s", node);
+                               fprintf(outpipe, ":\n");
+                               while (serv_gets(buf), strcmp(buf, "000")) {
+                                       fprintf(outpipe, "%s\n", buf);
+                               }
+                               pclose(outpipe);
+                               if (express_msgs == 0)
+                                       return;
+                               continue;
+                       }
+               }
+               /* fall back to built-in express message display */
+               printf("\n");
+
+               /* Header derived from flags */
+               if (flags & 2)
+                       printf("Please log off now, as requested ");
+               else if (flags & 1)
+                       printf("Broadcast message ");
+               else if (flags & 4)
+                       printf("Chat request ");
+               else
+                       printf("Message ");
+       
+               /* Timestamp.  Can this be improved? */
+               if (stamp->tm_hour == 0 || stamp->tm_hour == 12)/* 12am/12pm */
+                       printf("at 12:%02d%cm", stamp->tm_min, 
+                               stamp->tm_hour ? 'p' : 'a');
+               else if (stamp->tm_hour > 12)                   /* pm */
+                       printf("at %d:%02dpm",
+                               stamp->tm_hour - 12, stamp->tm_min);
+               else                                            /* am */
+                       printf("at %d:%02dam", stamp->tm_hour, stamp->tm_min);
+               
+               /* Sender */
+               printf(" from %s", sender);
+       
+               /* Remote node, if any */
+               if (strncmp(serv_info.serv_nodename, node, 32))
+                       printf(" @%s", node);
+       
+               printf(":\n");
+       
+               while (serv_gets(buf), strcmp(buf, "000")) {
+                       printf("%s", buf);
+               }
+       }
+       printf("\n---\n");
        color(BRIGHT_WHITE);
+
+
 }
 
 
@@ -128,22 +314,20 @@ void set_keepalives(int s)
 
 static time_t idlet = 0;
 static void really_do_keepalive(void) {
-       char buf[256];
+       char buf[1024];
 
        time(&idlet);
-       if (keepalives_enabled != KA_NO) {
+       if (keepalives_enabled == KA_YES) {
                serv_puts("NOOP");
-               if (keepalives_enabled == KA_YES) {
-                       serv_gets(buf);
-                       if (buf[3] == '*') {
-                               express_msgs = 1;
-                               if (ok_to_interrupt == 1) {
-                                       printf("\r%64s\r", "");
-                                       print_express();
-                                       printf("%s%c ", room_name,
-                                              room_prompt(room_flags));
-                                       fflush(stdout);
-                               }
+               serv_gets(buf);
+               if (buf[3] == '*') {
+                       express_msgs = 1;
+                       if (ok_to_interrupt == 1) {
+                               printf("\r%64s\r", "");
+                               print_express();
+                               printf("%s%c ", room_name,
+                                      room_prompt(room_flags));
+                               fflush(stdout);
                        }
                }
        }
@@ -234,6 +418,7 @@ int inkey(void)
        char inbuf[2];
 
        fflush(stdout);
+       lines_printed = 0;
        time(&start_time);
 
        do {
@@ -431,7 +616,9 @@ int intprompt(char *prompt, int ival, int imin, int imax)
                strprompt(prompt, buf, 15);
                i = atoi(buf);
                for (p=0; p<strlen(buf); ++p) {
-                       if (!isdigit(buf[p])) i = imin - 1;
+                       if ( (!isdigit(buf[p]))
+                          && ( (buf[p]!='-') || (p!=0) )  )
+                               i = imin - 1;
                }
                if (i < imin)
                        printf("*** Must be no less than %d.\n", imin);
@@ -470,7 +657,7 @@ int lkey(void)
 void load_command_set(void)
 {
        FILE *ccfile;
-       char buf[256];
+       char buf[1024];
        struct citcmd *cptr;
        struct citcmd *lastcmd = NULL;
        int a, d;
@@ -486,6 +673,7 @@ void load_command_set(void)
        rc_floor_mode = 0;
        rc_exp_beep = 1;
        rc_allow_attachments = 0;
+       rc_remember_passwords = 0;
        strcpy(rc_exp_cmd, "");
        rc_display_message_numbers = 0;
        rc_force_mail_prompts = 0;
@@ -513,60 +701,63 @@ void load_command_set(void)
                perror("commands: cannot open citadel.rc");
                logoff(errno);
        }
-       while (fgets(buf, 256, ccfile) != NULL) {
+       while (fgets(buf, sizeof buf, ccfile) != NULL) {
                while ((strlen(buf) > 0) ? (isspace(buf[strlen(buf) - 1])) : 0)
                        buf[strlen(buf) - 1] = 0;
 
-               if (!struncmp(buf, "editor=", 7))
+               if (!strncasecmp(buf, "editor=", 7))
                        strcpy(editor_path, &buf[7]);
 
-               if (!struncmp(buf, "printcmd=", 9))
+               if (!strncasecmp(buf, "printcmd=", 9))
                        strcpy(printcmd, &buf[9]);
 
-               if (!struncmp(buf, "expcmd=", 7))
+               if (!strncasecmp(buf, "expcmd=", 7))
                        strcpy(rc_exp_cmd, &buf[7]);
 
-               if (!struncmp(buf, "local_screen_dimensions=", 24))
+               if (!strncasecmp(buf, "local_screen_dimensions=", 24))
                        have_xterm = (char) atoi(&buf[24]);
 
-               if (!struncmp(buf, "use_floors=", 11)) {
-                       if (!strucmp(&buf[11], "yes"))
+               if (!strncasecmp(buf, "use_floors=", 11)) {
+                       if (!strcasecmp(&buf[11], "yes"))
                                rc_floor_mode = RC_YES;
-                       if (!strucmp(&buf[11], "no"))
+                       if (!strcasecmp(&buf[11], "no"))
                                rc_floor_mode = RC_NO;
-                       if (!strucmp(&buf[11], "default"))
+                       if (!strcasecmp(&buf[11], "default"))
                                rc_floor_mode = RC_DEFAULT;
                }
-               if (!struncmp(buf, "beep=", 5)) {
+               if (!strncasecmp(buf, "beep=", 5)) {
                        rc_exp_beep = atoi(&buf[5]);
                }
-               if (!struncmp(buf, "allow_attachments=", 18)) {
+               if (!strncasecmp(buf, "allow_attachments=", 18)) {
                        rc_allow_attachments = atoi(&buf[18]);
                }
-               if (!struncmp(buf, "display_message_numbers=", 24)) {
+               if (!strncasecmp(buf, "remember_passwords=", 19)) {
+                       rc_remember_passwords = atoi(&buf[19]);
+               }
+               if (!strncasecmp(buf, "display_message_numbers=", 24)) {
                        rc_display_message_numbers = atoi(&buf[24]);
                }
-               if (!struncmp(buf, "force_mail_prompts=", 19)) {
+               if (!strncasecmp(buf, "force_mail_prompts=", 19)) {
                        rc_force_mail_prompts = atoi(&buf[19]);
                }
-               if (!struncmp(buf, "ansi_color=", 11)) {
-                       if (!struncmp(&buf[11], "on", 2))
+               if (!strncasecmp(buf, "ansi_color=", 11)) {
+                       if (!strncasecmp(&buf[11], "on", 2))
                                rc_ansi_color = 1;
-                       if (!struncmp(&buf[11], "auto", 4))
+                       if (!strncasecmp(&buf[11], "auto", 4))
                                rc_ansi_color = 2;      /* autodetect */
-                       if (!struncmp(&buf[11], "user", 4))
+                       if (!strncasecmp(&buf[11], "user", 4))
                                rc_ansi_color = 3;      /* user config */
                }
-               if (!struncmp(buf, "username=", 9))
+               if (!strncasecmp(buf, "username=", 9))
                        strcpy(rc_username, &buf[9]);
 
-               if (!struncmp(buf, "password=", 9))
+               if (!strncasecmp(buf, "password=", 9))
                        strcpy(rc_password, &buf[9]);
 
-               if (!struncmp(buf, "urlcmd=", 7))
+               if (!strncasecmp(buf, "urlcmd=", 7))
                        strcpy(rc_url_cmd, &buf[7]);
 
-               if (!struncmp(buf, "cmd=", 4)) {
+               if (!strncasecmp(buf, "cmd=", 4)) {
                        strcpy(buf, &buf[4]);
 
                        cptr = (struct citcmd *) malloc(sizeof(struct citcmd));
@@ -638,7 +829,7 @@ char *cmd_expand(char *strbuf, int mode)
 {
        int a;
        static char exp[64];
-       char buf[256];
+       char buf[1024];
 
        strcpy(exp, strbuf);
 
@@ -729,6 +920,13 @@ int getcmd(char *argbuf)
        int this_lazy_cmd;
        struct citcmd *cptr;
 
+       /*
+        * Starting a new command now, so set sigcaught to 0.  This variable
+        * is set to nonzero (usually NEXT_KEY or STOP_KEY) if a command has
+        * been interrupted by a keypress.
+        */
+       sigcaught = 0;
+
        /* Switch color support on or off if we're in user mode */
        if (rc_ansi_color == 3) {
                if (userflags & US_COLOR)
@@ -860,8 +1058,7 @@ int getcmd(char *argbuf)
 /*
  * set tty modes.  commands are:
  * 
- * 0 - set to bbs mode, intr/quit disabled
- * 1 - set to bbs mode, intr/quit enabled
+ * 01- set to bbs mode
  * 2 - save current settings for later restoral
  * 3 - restore saved settings
  */
@@ -883,17 +1080,13 @@ void sttybbs(int cmd)
                live.c_oflag = OPOST | ONLCR;
                live.c_lflag = ISIG | NOFLSH;
 
-               if (cmd == SB_YES_INTR) {
-                       live.c_cc[VINTR] = NEXT_KEY;
-                       live.c_cc[VQUIT] = STOP_KEY;
-                       signal(SIGINT, *sighandler);
-                       signal(SIGQUIT, *sighandler);
-               } else {
-                       signal(SIGINT, SIG_IGN);
-                       signal(SIGQUIT, SIG_IGN);
-                       live.c_cc[VINTR] = (-1);
-                       live.c_cc[VQUIT] = (-1);
-               }
+               live.c_cc[VINTR] = (-1);
+               live.c_cc[VQUIT] = (-1);
+
+#ifdef hpux
+               live.c_cc[VMIN] = 0;
+               live.c_cc[VTIME] = 0;
+#endif
 
                /* do we even need this stuff anymore? */
                /* live.c_line=0; */
@@ -950,13 +1143,13 @@ void display_help(char *name)
 /*
  * fmout()  -  Citadel text formatter and paginator
  */
-int fmout(int width, FILE * fp, char pagin, int height, int starting_lp, char subst)
-                       /* screen width to use */
-                       /* file to read from, or NULL to read from server */
-                       /* nonzero if we should use the paginator */
-                       /* screen height to use */
-                       /* starting value for lines_printed, -1 for global */
-                       /* nonzero if we should use hypertext mode */
+int fmout(
+       int width,      /* screen width to use */
+       FILE *fp,       /* file to read from, or NULL to read from server */
+       char pagin,     /* nonzero if we should use the paginator */
+       int height,     /* screen height to use */
+       int starting_lp,/* starting value for lines_printed, -1 for global */
+       char subst)     /* nonzero if we should use hypertext mode */
 {
        int a, b, c, d, old;
        int real = (-1);
@@ -974,13 +1167,7 @@ int fmout(int width, FILE * fp, char pagin, int height, int starting_lp, char su
        strcpy(buffer, "");
        c = 1;                  /* c is the current pos */
 
-       sigcaught = 0;
-       sttybbs(1);
-
 FMTA:  while ((eof_flag == 0) && (strlen(buffer) < 126)) {
-       
-               if (sigcaught)
-                       goto OOPS;
                if (fp != NULL) {       /* read from file */
                        if (feof(fp))
                                eof_flag = 1;
@@ -1006,8 +1193,8 @@ FMTA:     while ((eof_flag == 0) && (strlen(buffer) < 126)) {
                }
        }
 
-       if ( (!struncmp(buffer, "http://", 7))
-          || (!struncmp(buffer, "ftp://", 6)) ) {
+       if ( (!strncasecmp(buffer, "http://", 7))
+          || (!strncasecmp(buffer, "ftp://", 6)) ) {
                safestrncpy(urls[num_urls], buffer, 255);
                for (a=0; a<strlen(urls[num_urls]); ++a) {
                        b = urls[num_urls][a];
@@ -1068,17 +1255,18 @@ FMTA:   while ((eof_flag == 0) && (strlen(buffer) < 126)) {
                c = 1;
                ++lines_printed;
                lines_printed = checkpagin(lines_printed, pagin, height);
+               if (sigcaught) goto OOPS;
                strcpy(aaa, "");
                goto FMTA;
        }
        goto FMTA;
 
-       /* signal caught; drain the server */
-      OOPS:do {
+       /* keypress caught; drain the server */
+OOPS:  do {
                serv_gets(aaa);
        } while (strcmp(aaa, "000"));
 
-      FMTEND:printf("\n");
+FMTEND:        printf("\n");
        ++lines_printed;
        lines_printed = checkpagin(lines_printed, pagin, height);
        return (sigcaught);
@@ -1105,7 +1293,15 @@ void color(int colornum)
 
        current_color = colornum;
        if (enable_color) {
-               printf("\033[3%dm", (colornum % 8));
+               /* When switching to dim white, actually output an 'original
+                * pair' sequence -- this looks better on black-on-white
+                * terminals.
+                */
+               if (colornum == DIM_WHITE)
+                       printf("\033[39;49m");
+               else
+                       printf("\033[3%d;40m", (colornum & 7));
+
                if ((colornum >= 8) && (is_bold == 0)) {
                        printf("\033[1m");
                        is_bold = 1;
@@ -1213,7 +1409,7 @@ char keymenu(char *menuprompt, char *menustring) {
        int i, c, a;
        int choices;
        int do_prompt = 0;
-       char buf[256];
+       char buf[1024];
        int ch;
        int display_prompt = 1;