Commit 2cbe825e 2cbe825eb999f224ce756510dbd7123bc76ec924 by Sergey Poznyakoff

comsat: add a way to specify alternative biffrc file name; new biffrc statement: tty

* comsat/comsat.c (options): New option --file.
(biffrc): New variable.
(comsatd_parse_opt): Handle the --file option.
(open_tty): New function.
(notify_user): Open the tty using open_tty function and a default
set of filters.
(main): Hanlde --file option.
* comsat/action.c (run_user_action): Implement the `tty' statement.
* comsat/comsat.h (biffrc): New extern.
(open_tty): New function.

mu: accept a chain of filters.

* mu/filter.c (filter_doc, filter_docstring): Update.
(mutool_filter): Accept a filter chain.
1 parent 04c2931b
...@@ -331,7 +331,7 @@ run_user_action (mu_stream_t tty, mu_message_t msg) ...@@ -331,7 +331,7 @@ run_user_action (mu_stream_t tty, mu_message_t msg)
331 mu_stream_t input; 331 mu_stream_t input;
332 int nact = 0; 332 int nact = 0;
333 333
334 input = open_rc (BIFF_RC, tty); 334 input = open_rc (biffrc, tty);
335 if (input) 335 if (input)
336 { 336 {
337 char *stmt = NULL; 337 char *stmt = NULL;
...@@ -384,8 +384,23 @@ run_user_action (mu_stream_t tty, mu_message_t msg) ...@@ -384,8 +384,23 @@ run_user_action (mu_stream_t tty, mu_message_t msg)
384 if (!ws.ws_wordv[i]) 384 if (!ws.ws_wordv[i])
385 break; 385 break;
386 } 386 }
387 387
388 if (strcmp (ws.ws_wordv[0], "echo") == 0) 388 if (strcmp (ws.ws_wordv[0], "tty") == 0)
389 {
390 mu_stream_t ntty = open_tty (ws.ws_wordv[1],
391 ws.ws_wordc - 2,
392 ws.ws_wordv + 2);
393 if (!ntty)
394 {
395 mu_stream_printf (tty,
396 _(".biffrc:%d: cannot open tty\n"),
397 locus.mu_line);
398 break;
399 }
400 mu_stream_destroy (&tty);
401 tty = ntty;
402 }
403 else if (strcmp (ws.ws_wordv[0], "echo") == 0)
389 { 404 {
390 int argc = ws.ws_wordc - 1; 405 int argc = ws.ws_wordc - 1;
391 char **argv = ws.ws_wordv + 1; 406 char **argv = ws.ws_wordv + 1;
......
...@@ -66,6 +66,8 @@ static struct argp_option options[] = ...@@ -66,6 +66,8 @@ static struct argp_option options[] =
66 { "inetd", 'i', 0, 0, N_("run in inetd mode"), 0 }, 66 { "inetd", 'i', 0, 0, N_("run in inetd mode"), 0 },
67 { "daemon", 'd', N_("NUMBER"), OPTION_ARG_OPTIONAL, 67 { "daemon", 'd', N_("NUMBER"), OPTION_ARG_OPTIONAL,
68 N_("runs in daemon mode with a maximum of NUMBER children"), 0 }, 68 N_("runs in daemon mode with a maximum of NUMBER children"), 0 },
69 { "file", 'f', N_("FILE"), 0,
70 N_("read FILE instead of .biffrc"), 0 },
69 { NULL, 0, NULL, 0, NULL, 0 } 71 { NULL, 0, NULL, 0, NULL, 0 }
70 }; 72 };
71 73
...@@ -110,6 +112,7 @@ static int change_user (const char *user); ...@@ -110,6 +112,7 @@ static int change_user (const char *user);
110 112
111 static int reload = 0; 113 static int reload = 0;
112 int test_mode; 114 int test_mode;
115 char *biffrc = BIFF_RC;
113 116
114 struct mu_cfg_param comsat_cfg_param[] = { 117 struct mu_cfg_param comsat_cfg_param[] = {
115 { "allow-biffrc", mu_cfg_bool, &allow_biffrc, 0, NULL, 118 { "allow-biffrc", mu_cfg_bool, &allow_biffrc, 0, NULL,
...@@ -147,6 +150,10 @@ comsatd_parse_opt (int key, char *arg, struct argp_state *state) ...@@ -147,6 +150,10 @@ comsatd_parse_opt (int key, char *arg, struct argp_state *state)
147 mu_argp_node_list_new (lst, "max-children", arg); 150 mu_argp_node_list_new (lst, "max-children", arg);
148 break; 151 break;
149 152
153 case 'f':
154 biffrc = arg;
155 break;
156
150 case 'i': 157 case 'i':
151 mu_argp_node_list_new (lst, "mode", "inetd"); 158 mu_argp_node_list_new (lst, "mode", "inetd");
152 break; 159 break;
...@@ -236,7 +243,7 @@ comsat_process (char *buffer, size_t rdlen) ...@@ -236,7 +243,7 @@ comsat_process (char *buffer, size_t rdlen)
236 { 243 {
237 if (require_tty) 244 if (require_tty)
238 return; 245 return;
239 strcpy (tty, "/dev/null"); 246 tty[0] = 0;
240 } 247 }
241 248
242 /* Child: do actual I/O */ 249 /* Child: do actual I/O */
...@@ -377,50 +384,112 @@ need_crlf (mu_stream_t str) ...@@ -377,50 +384,112 @@ need_crlf (mu_stream_t str)
377 #endif 384 #endif
378 } 385 }
379 386
387 static mu_stream_t
388 _open_tty (const char *device, int argc, char **argv)
389 {
390 mu_stream_t dev, base_dev, prev_stream;
391 int status;
392
393 status = mu_file_stream_create (&dev, device, MU_STREAM_WRITE);
394 if (status)
395 {
396 mu_error (_("cannot open device %s: %s"),
397 device, mu_strerror (status));
398 return NULL;
399 }
400 mu_stream_set_buffer (dev, mu_buffer_line, 0);
401
402 prev_stream = base_dev = dev;
403 while (argc)
404 {
405 int i;
406 int mode;
407 int qmark;
408 char *fltname;
409
410 fltname = argv[0];
411 if (fltname[0] == '?')
412 {
413 qmark = 1;
414 fltname++;
415 }
416 else
417 qmark = 0;
418
419 if (fltname[0] == '~')
420 {
421 mode = MU_FILTER_DECODE;
422 fltname++;
423 }
424 else
425 {
426 mode = MU_FILTER_ENCODE;
427 }
428
429 for (i = 1; i < argc; i++)
430 if (strcmp (argv[i], "+") == 0)
431 break;
432
433 if (qmark == 0 || need_crlf (base_dev))
434 {
435 status = mu_filter_create_args (&dev, prev_stream, fltname,
436 i, (const char **)argv,
437 mode, MU_STREAM_WRITE);
438 mu_stream_unref (prev_stream);
439 if (status)
440 {
441 mu_error (_("cannot open filter stream: %s"),
442 mu_strerror (status));
443 return NULL;
444 }
445 prev_stream = dev;
446 }
447 argc -= i;
448 argv += i;
449 if (argc)
450 {
451 argc--;
452 argv++;
453 }
454 }
455 return dev;
456 }
457
458 mu_stream_t
459 open_tty (const char *device, int argc, char **argv)
460 {
461 mu_stream_t dev;
462
463 if (!device || !*device || strcmp (device, "null") == 0)
464 {
465 int rc = mu_nullstream_create (&dev, MU_STREAM_WRITE);
466 if (rc)
467 mu_error (_("cannot open null stream: %s"), mu_strerror (rc));
468 }
469 else
470 dev = _open_tty (device, argc, argv);
471 return dev;
472 }
473
380 /* NOTE: Do not bother to free allocated memory, as the program exits 474 /* NOTE: Do not bother to free allocated memory, as the program exits
381 immediately after executing this */ 475 immediately after executing this */
382 static void 476 static void
383 notify_user (const char *user, const char *device, const char *path, 477 notify_user (const char *user, const char *device, const char *path,
384 mu_message_qid_t qid) 478 mu_message_qid_t qid)
385 { 479 {
386 mu_stream_t out, dev; 480 mu_stream_t dev;
387 mu_mailbox_t mbox = NULL; 481 mu_mailbox_t mbox = NULL;
388 mu_message_t msg; 482 mu_message_t msg;
483 static char *default_filters[] = { "7bit", "+", "?CRLF", NULL };
389 int status; 484 int status;
390 485
391 if (change_user (user)) 486 if (change_user (user))
392 return; 487 return;
393 status = mu_file_stream_create (&dev, device, MU_STREAM_WRITE);
394 if (status)
395 {
396 mu_error (_("cannot open device %s: %s"), device, mu_strerror (status));
397 return;
398 }
399 mu_stream_set_buffer (dev, mu_buffer_line, 0);
400
401 status = mu_filter_create (&out, dev, "7bit", MU_FILTER_ENCODE,
402 MU_STREAM_WRITE);
403 mu_stream_unref (dev);
404 if (status)
405 {
406 mu_error (_("cannot create 7bit filter: %s"), mu_strerror (status));
407 return;
408 }
409
410 if (need_crlf (out))
411 {
412 mu_stream_t str;
413 status = mu_filter_create (&str, out, "CRLF", MU_FILTER_ENCODE,
414 MU_STREAM_WRITE);
415 mu_stream_unref (out);
416 if (status)
417 {
418 mu_error (_("cannot create crlf filter: %s"), mu_strerror (status));
419 return;
420 }
421 out = str;
422 }
423 488
489 dev = open_tty (device, MU_ARRAY_SIZE (default_filters) - 1,
490 default_filters);
491 if (!dev)
492 return;
424 if (!path) 493 if (!path)
425 { 494 {
426 path = mailbox_path (user); 495 path = mailbox_path (user);
...@@ -445,8 +514,8 @@ notify_user (const char *user, const char *device, const char *path, ...@@ -445,8 +514,8 @@ notify_user (const char *user, const char *device, const char *path,
445 return; /* FIXME: Notify the user, anyway */ 514 return; /* FIXME: Notify the user, anyway */
446 } 515 }
447 516
448 run_user_action (out, msg); 517 run_user_action (dev, msg);
449 mu_stream_destroy (&out); 518 mu_stream_destroy (&dev);
450 } 519 }
451 520
452 /* Search utmp for the local user */ 521 /* Search utmp for the local user */
...@@ -613,7 +682,20 @@ main (int argc, char **argv) ...@@ -613,7 +682,20 @@ main (int argc, char **argv)
613 user = pw->pw_name; 682 user = pw->pw_name;
614 } 683 }
615 } 684 }
616 685
686 if (biffrc[0] == '.')
687 {
688 char *cwd = mu_getcwd ();
689 biffrc = mu_make_file_name (cwd, biffrc);
690 if (!biffrc)
691 {
692 mu_error ("%s", mu_strerror (ENOMEM));
693 exit (1);
694 }
695 mu_normalize_path (biffrc);
696 free (cwd);
697 }
698
617 notify_user (user, "/dev/tty", argv[0], argv[1]); 699 notify_user (user, "/dev/tty", argv[0], argv[1]);
618 exit (0); 700 exit (0);
619 } 701 }
...@@ -655,4 +737,3 @@ main (int argc, char **argv) ...@@ -655,4 +737,3 @@ main (int argc, char **argv)
655 737
656 return c != 0; 738 return c != 0;
657 } 739 }
658
......
...@@ -77,6 +77,8 @@ extern int maxlines; ...@@ -77,6 +77,8 @@ extern int maxlines;
77 extern const char *username; 77 extern const char *username;
78 extern char *hostname; 78 extern char *hostname;
79 extern struct daemon_param daemon_param; 79 extern struct daemon_param daemon_param;
80 extern char *biffrc;
80 81
81 void run_user_action (mu_stream_t str, mu_message_t msg); 82 void run_user_action (mu_stream_t str, mu_message_t msg);
83 mu_stream_t open_tty (const char *device, int argc, char **argv);
82 84
......
...@@ -23,9 +23,9 @@ ...@@ -23,9 +23,9 @@
23 #include "argp.h" 23 #include "argp.h"
24 #include "mu.h" 24 #include "mu.h"
25 25
26 static char filter_doc[] = N_("mu filter - apply a filter to the input"); 26 static char filter_doc[] = N_("mu filter - apply a chain of filters to the input");
27 char filter_docstring[] = N_("apply a filter to the input"); 27 char filter_docstring[] = N_("apply a chain of filters to the input");
28 static char filter_args_doc[] = N_("NAME [ARGS]"); 28 static char filter_args_doc[] = N_("[~]NAME [ARGS] [+ [~]NAME [ARGS]...]");
29 29
30 static struct argp_option filter_options[] = { 30 static struct argp_option filter_options[] = {
31 { "encode", 'e', NULL, 0, N_("encode the input (default)") }, 31 { "encode", 'e', NULL, 0, N_("encode the input (default)") },
...@@ -126,12 +126,23 @@ list_filters () ...@@ -126,12 +126,23 @@ list_filters ()
126 return mu_list_do (list, filter_printer, NULL); 126 return mu_list_do (list, filter_printer, NULL);
127 } 127 }
128 128
129 static int
130 negate_filter_mode (int mode)
131 {
132 if (mode == MU_FILTER_DECODE)
133 return MU_FILTER_ENCODE;
134 else if (mode == MU_FILTER_ENCODE)
135 return MU_FILTER_DECODE;
136 abort ();
137 }
138
129 int 139 int
130 mutool_filter (int argc, char **argv) 140 mutool_filter (int argc, char **argv)
131 { 141 {
132 int rc, index; 142 int rc, index;
133 mu_stream_t flt; 143 mu_stream_t flt, prev_stream;
134 const char *fltname; 144 const char *fltname;
145 int mode;
135 146
136 if (argp_parse (&filter_argp, argc, argv, ARGP_IN_ORDER, &index, NULL)) 147 if (argp_parse (&filter_argp, argc, argv, ARGP_IN_ORDER, &index, NULL))
137 return 1; 148 return 1;
...@@ -155,20 +166,47 @@ mutool_filter (int argc, char **argv) ...@@ -155,20 +166,47 @@ mutool_filter (int argc, char **argv)
155 return 1; 166 return 1;
156 } 167 }
157 168
158 fltname = argv[0]; 169 prev_stream = mu_strin;
159 170 do
160 if (line_length_option)
161 reset_line_length (fltname, line_length);
162
163 rc = mu_filter_create_args (&flt, mu_strin, fltname,
164 argc, (const char **)argv,
165 filter_mode, MU_STREAM_READ);
166 if (rc)
167 { 171 {
168 mu_error (_("cannot open filter stream: %s"), mu_strerror (rc)); 172 int i;
169 return 1; 173
170 } 174 fltname = argv[0];
175 if (fltname[0] == '~')
176 {
177 mode = negate_filter_mode (filter_mode);
178 fltname++;
179 }
180 else
181 mode = filter_mode;
171 182
183 for (i = 1; i < argc; i++)
184 if (strcmp (argv[i], "+") == 0)
185 break;
186
187 if (line_length_option)
188 reset_line_length (fltname, line_length);
189
190 rc = mu_filter_create_args (&flt, prev_stream, fltname,
191 i, (const char **)argv,
192 mode, MU_STREAM_READ);
193 mu_stream_unref (prev_stream);
194 if (rc)
195 {
196 mu_error (_("cannot open filter stream: %s"), mu_strerror (rc));
197 return 1;
198 }
199 prev_stream = flt;
200 argc -= i;
201 argv += i;
202 if (argc)
203 {
204 argc--;
205 argv++;
206 }
207 }
208 while (argc);
209
172 rc = mu_stream_copy (mu_strout, flt, 0, NULL); 210 rc = mu_stream_copy (mu_strout, flt, 0, NULL);
173 211
174 if (rc) 212 if (rc)
......