Submitted by: Damon Harper Date: 2006-08-28, 2007-09-21 Summary: Run comsatd exec actions even if user is not logged in Currently, comsatd's child process simply exits if it cannot find a tty where the user to be notified is logged in. This is fine for the default action, or echo and beep actions; however, this also prevents exec actions from running unless the user is actively logged in at the time of notification. This should not be the desired behaviour. A user might use exec to perform an action that should fire off even if that user is not logged in to a tty. In the comsatd documentation, an example is given of an exec command that will run xmessage to show a message in x-windows. With the current behaviour, that example will only work if the user is also logged in to a tty (perhaps via xterm) at the time of the message. This patch changes tty to a global variable (ttyfp). This global is set to a tty file pointer if a suitable tty is found, but otherwise is set to NULL. run_user_action, open_rc, and action_* functions are now reworked to assume that global ttyfp could be NULL. action_beep and action_echo both return immediately if this is the case, but action_exec simply continues with all output directed to /dev/null. This patch also fixes all functions to use the cr string (also made global) instead of hard-coded \r\n when writing to the tty. NOTE: This patch applies on top of: mailutils-1.2-comsatd-new-escapes-f+o-3.patch It will NOT apply cleanly to stock mailutils-1.2. diff -urN mailutils-1.2.orig-new-escapes/comsat/action.c mailutils-1.2/comsat/action.c --- mailutils-1.2.orig-new-escapes/comsat/action.c 2007-09-21 02:47:36.000000000 -0700 +++ mailutils-1.2/comsat/action.c 2007-09-21 02:45:34.000000000 -0700 @@ -253,35 +253,41 @@ #define LB(c) ((c)&0x7f) static void -action_beep (FILE *tty) +action_beep () { - fprintf (tty, "\a\a"); + if (ttyfp == NULL) + return; + fprintf (ttyfp, "\a\a"); } static void -echo_string (FILE *tty, const char *cr, char *str) +echo_string (char *str) { if (!str) return; + if (ttyfp == NULL) + return; for (; *str; str++) { if (*str == '\n') - fprintf (tty, "%s", cr); + fprintf (ttyfp, "%s", cr); else { char c = LB (*str); - putc (c, tty); + putc (c, ttyfp); } } - fflush (tty); + fflush (ttyfp); } static void -action_echo (FILE *tty, const char *cr, int omit_newline, - int argc, char **argv) +action_echo (int omit_newline, int argc, char **argv) { int i; + if (ttyfp == NULL) + return; + if (omit_newline) { argc--; @@ -290,20 +296,20 @@ for (i = 0;;) { - echo_string (tty, cr, argv[i]); + echo_string (argv[i]); if (++i < argc) - echo_string (tty, cr, " "); + echo_string (" "); else { if (!omit_newline) - echo_string (tty, cr, "\n"); + echo_string ("\n"); break; } } } static void -action_exec (FILE *tty, int line, int argc, char **argv) +action_exec (int line, int argc, char **argv) { pid_t pid; struct stat stb; @@ -338,11 +344,14 @@ pid = fork (); if (pid == 0) { - close (1); - close (2); - dup2 (fileno (tty), 1); - dup2 (fileno (tty), 2); - fclose (tty); + if (ttyfp != NULL) + { + close (1); + close (2); + dup2 (fileno (ttyfp), 1); + dup2 (fileno (ttyfp), 2); + fclose (ttyfp); + } execv (argv[0], argv); syslog (LOG_ERR, _("Cannot execute %s: %s"), argv[0], strerror (errno)); exit (0); @@ -350,7 +359,7 @@ } static FILE * -open_rc (const char *filename, FILE *tty) +open_rc (const char *filename) { struct stat stb; struct passwd *pw = getpwnam (username); @@ -368,8 +377,9 @@ } if ((stb.st_mode & 0777) != 0600) { - fprintf (tty, "%s\r\n", - _("Warning: your .biffrc has wrong permissions")); + if (ttyfp != NULL) + fprintf (ttyfp, "%s%s", + _("Warning: your .biffrc has wrong permissions"), cr); syslog (LOG_NOTICE, _("%s's %s has wrong permissions"), username, filename); return NULL; @@ -379,14 +389,14 @@ } void -run_user_action (FILE *tty, const char *cr, mu_message_t msg) +run_user_action (mu_message_t msg) { FILE *fp; int nact = 0; char *stmt = NULL; size_t size = 0; - fp = open_rc (BIFF_RC, tty); + fp = open_rc (BIFF_RC); if (fp) { unsigned line = 1, n; @@ -403,7 +413,7 @@ if (strcmp (argv[0], "beep") == 0) { /* FIXME: excess arguments are ignored */ - action_beep (tty); + action_beep (); nact++; } else @@ -423,18 +433,21 @@ if (strcmp (argv[0], "echo") == 0) { - action_echo (tty, cr, n_option, argc - 1, argv + 1); + action_echo (n_option, argc - 1, argv + 1); nact++; } else if (strcmp (argv[0], "exec") == 0) { - action_exec (tty, line, argc - 1, argv + 1); + action_exec (line, argc - 1, argv + 1); nact++; } else { - fprintf (tty, _(".biffrc:%d: unknown keyword"), line); - fprintf (tty, "\r\n"); + if (ttyfp != NULL) + { + fprintf (ttyfp, _(".biffrc:%d: unknown keyword"), line); + fprintf (ttyfp, "%s", cr); + } syslog (LOG_ERR, _("%s:.biffrc:%d: unknown keyword %s"), username, line, argv[0]); break; @@ -448,5 +461,5 @@ } if (nact == 0) - echo_string (tty, cr, expand_line (default_action, msg)); + echo_string (expand_line (default_action, msg)); } diff -urN mailutils-1.2.orig-new-escapes/comsat/comsat.c mailutils-1.2/comsat/comsat.c --- mailutils-1.2.orig-new-escapes/comsat/comsat.c 2007-09-21 02:47:36.000000000 -0700 +++ mailutils-1.2/comsat/comsat.c 2007-09-21 02:45:40.000000000 -0700 @@ -228,6 +228,8 @@ char *path = NULL; /* Will contain the mailbox filename */ size_t offset; /* Will contain the offset of message within mailbox */ +FILE *ttyfp = NULL; /* Will hold chosen TTY's file pointer if one is found */ +const char *cr; /* Will hold the newline string */ void comsat_daemon (int port) @@ -326,6 +328,7 @@ char buffer[216]; /*FIXME: Arbitrary size */ pid_t pid; char tty[MAX_TTY_SIZE]; + int use_tty; char *p, *endp; len = sizeof sin_from; @@ -375,8 +378,7 @@ syslog (LOG_ERR, _("Malformed input: address@hidden (near %s)"), buffer, p, endp); } - if (find_user (buffer, tty) != SUCCESS) - return 0; + use_tty = find_user (buffer, tty) == SUCCESS; /* All I/O is done by child process. This is to avoid various blocking problems. */ @@ -400,7 +402,7 @@ } /* Child: do actual I/O */ - notify_user (buffer, tty); + notify_user (buffer, use_tty ? tty : NULL); exit (0); } @@ -425,8 +427,6 @@ static void notify_user (const char *user, const char *device) { - FILE *fp; - const char *cr; char *blurb; mu_mailbox_t mbox = NULL, tmp = NULL; mu_message_t msg; @@ -436,13 +436,14 @@ size_t count, n; change_user (user); - if ((fp = fopen (device, "w")) == NULL) + if (device == NULL) + ttyfp = NULL; + else if ((ttyfp = fopen (device, "w")) == NULL) { - syslog (LOG_ERR, _("Cannot open device %s: %m"), device); - exit (0); + syslog (LOG_WARNING, _("Cannot open device %s: %m; continuing with no TTY"), device); } - cr = get_newline_str (fp); + cr = ttyfp == NULL ? "\r\n" : get_newline_str (ttyfp); if (!path) { @@ -502,8 +501,9 @@ mu_mailbox_messages_count (tmp, &count); mu_mailbox_get_message (tmp, 1, &msg); - run_user_action (fp, cr, msg); - fclose (fp); + run_user_action (msg); + if (ttyfp != NULL) + fclose (ttyfp); } /* Search utmp for the local user */ diff -urN mailutils-1.2.orig-new-escapes/comsat/comsat.h mailutils-1.2/comsat/comsat.h --- mailutils-1.2.orig-new-escapes/comsat/comsat.h 2007-09-21 02:47:36.000000000 -0700 +++ mailutils-1.2/comsat/comsat.h 2007-09-21 02:45:46.000000000 -0700 @@ -78,7 +78,9 @@ extern struct daemon_param daemon_param; extern char *path; extern size_t offset; +extern FILE *ttyfp; +extern const char *cr; extern void read_config (const char *config_file); int acl_match (struct sockaddr_in *sa_in); -void run_user_action (FILE *tty, const char *cr, mu_message_t msg); +void run_user_action (mu_message_t msg);