0
|
1 /* mhlsbr.c - implement the "nifty" message lister */
|
|
2 #ifndef lint
|
|
3 static char ident[] = "@(#)$Id$";
|
|
4 #endif /* lint */
|
|
5
|
|
6 #include "../h/mh.h"
|
|
7 #include "../h/addrsbr.h"
|
|
8 #include "../h/formatsbr.h"
|
|
9 #include "../zotnet/tws.h"
|
|
10 #ifdef SVR4
|
|
11 #undef NULLVP /* XXX */
|
|
12 #endif
|
|
13 #if defined(SYS5) && defined(AUX)
|
|
14 #define u_short ushort
|
|
15 #define u_long ulong
|
|
16 #endif
|
|
17 #include <ctype.h>
|
|
18 #include <setjmp.h>
|
|
19 #include <signal.h>
|
|
20 #include <stdio.h>
|
|
21 #include <sys/types.h>
|
|
22 #include <sys/stat.h>
|
|
23 #ifdef UNISTD
|
|
24 #include <unistd.h>
|
|
25 #endif
|
|
26
|
|
27
|
|
28 /* MAJOR BUG:
|
|
29 for a component containing addresses, ADDRFMT, if COMPRESS is also
|
|
30 set, then addresses get split wrong (not at the spaces between commas).
|
|
31 To fix this correctly, putstr() should know about "atomic" strings that
|
|
32 must NOT be broken across lines. That's too difficult for right now
|
|
33 (it turns out that there are a number of degernate cases), so in
|
|
34 oneline(), instead of
|
|
35
|
|
36 (*onelp == '\n' && !onelp[1])
|
|
37
|
|
38 being a terminating condition,
|
|
39
|
|
40 (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT)))
|
|
41
|
|
42 is used instead. This cuts the line prematurely, and gives us a much
|
|
43 better chance of getting things right.
|
|
44 */
|
|
45
|
|
46
|
|
47 #ifdef SYS5
|
|
48 #define u_short ushort
|
|
49 #endif /* SYS5 */
|
|
50
|
|
51 #define ONECOMP 0
|
|
52 #define TWOCOMP 1
|
|
53 #define BODYCOMP 2
|
|
54
|
|
55 #define adios mhladios
|
|
56 #define done mhldone
|
|
57
|
|
58 #define QUOTE '\\'
|
|
59
|
|
60 /* */
|
|
61
|
|
62 static struct swit mhlswitches[] = {
|
|
63 #define BELLSW 0
|
|
64 "bell", 0,
|
|
65 #define NBELLSW 1
|
|
66 "nobell", 0,
|
|
67
|
|
68 #define CLRSW 2
|
|
69 "clear", 0,
|
|
70 #define NCLRSW 3
|
|
71 "noclear", 0,
|
|
72
|
|
73 #define FACESW 4
|
|
74 "faceproc program", 0,
|
|
75 #define NFACESW 5
|
|
76 "nofaceproc", 0,
|
|
77
|
|
78 #define FOLDSW 6
|
|
79 "folder +folder", 0,
|
|
80 #define FORMSW 7
|
|
81 "form formfile", 0,
|
|
82
|
|
83 #define PROGSW 8
|
|
84 "moreproc program", 0,
|
|
85 #define NPROGSW 9
|
|
86 "nomoreproc", 0,
|
|
87
|
|
88 #define LENSW 10
|
|
89 "length lines", 0,
|
|
90 #define WIDSW 11
|
|
91 "width columns", 0,
|
|
92
|
|
93 #define SLEEPSW 12
|
|
94 "sleep seconds", 0,
|
|
95
|
|
96 #define DASHSW 13
|
|
97 "dashmunging", -4,
|
|
98 #define NDASHSW 14
|
|
99 "nodashmunging", -6,
|
|
100
|
|
101 #define HELPSW 15
|
|
102 "help", 4,
|
|
103
|
|
104 #define FORW1SW 16
|
|
105 "forward", -7, /* interface from forw */
|
|
106 #define FORW2SW 17
|
|
107 "forwall", -7, /* .. */
|
|
108 #define DGSTSW 18
|
|
109 "digest list", -6,
|
|
110 #define VOLUMSW 19
|
|
111 "volume number", -6,
|
|
112 #define ISSUESW 20
|
|
113 "issue number", -5,
|
|
114 #define NBODYSW 21
|
|
115 "nobody", -6,
|
|
116
|
|
117 NULL, 0
|
|
118 };
|
|
119
|
|
120 /* */
|
|
121
|
|
122 struct mcomp {
|
|
123 char *c_name; /* component name */
|
|
124 char *c_text; /* component text */
|
|
125 char *c_ovtxt; /* text overflow indicator */
|
|
126 char *c_nfs; /* iff FORMAT */
|
|
127 struct format *c_fmt; /* .. */
|
|
128 char *c_face; /* face designator */
|
|
129
|
|
130 int c_offset; /* left margin indentation */
|
|
131 int c_ovoff; /* overflow indentation */
|
|
132 int c_width; /* width of field */
|
|
133 int c_cwidth; /* width of component */
|
|
134 int c_length; /* length in lines */
|
|
135
|
|
136 long c_flags;
|
|
137 #define NOCOMPONENT 0x000001/* don't show component name */
|
|
138 #define UPPERCASE 0x000002/* display in all upper case */
|
|
139 #define CENTER 0x000004/* center line */
|
|
140 #define CLEARTEXT 0x000008/* cleartext */
|
|
141 #define EXTRA 0x000010/* an "extra" component */
|
|
142 #define HDROUTPUT 0x000020/* already output */
|
|
143 #define CLEARSCR 0x000040/* clear screen */
|
|
144 #define LEFTADJUST 0x000080/* left justify multiple lines */
|
|
145 #define COMPRESS 0x000100/* compress text */
|
|
146 #define ADDRFMT 0x000200/* contains addresses */
|
|
147 #define BELL 0x000400/* sound bell at EOP */
|
|
148 #define DATEFMT 0x000800/* contains dates */
|
|
149 #define FORMAT 0x001000/* parse address/date */
|
|
150 #define INIT 0x002000/* initialize component */
|
|
151 #define FACEFMT 0x004000/* contains face */
|
|
152 #define FACEDFLT 0x008000/* default for face */
|
|
153 #define SPLIT 0x010000/* split headers (don't concatenate) */
|
|
154 #define NONEWLINE 0x020000/* don't write trailing newline */
|
|
155 #ifdef MIME_HEADERS
|
|
156 #define DECODE 0x040000/* decode MIME header */
|
|
157 #define LBITS "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07CLEARSCR\010LEFTADJUST\011COMPRESS\012ADDRFMT\013BELL\014DATEFMT\015FORMAT\016INIT\017FACEFMT\020FACEDFLT\021SPLIT\022NONEWLINE\023DECODE"
|
|
158 #else /* MIME_HEADERS */
|
|
159 #define LBITS "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07CLEARSCR\010LEFTADJUST\011COMPRESS\012ADDRFMT\013BELL\014DATEFMT\015FORMAT\016INIT\017FACEFMT\020FACEDFLT\021SPLIT\022NONEWLINE"
|
|
160 #endif /* MIME_HEADERS */
|
|
161 #define GFLAGS (NOCOMPONENT | UPPERCASE | CENTER | LEFTADJUST | COMPRESS \
|
|
162 | SPLIT)
|
|
163
|
|
164 struct mcomp *c_next;
|
|
165 };
|
|
166
|
|
167 static struct mcomp *msghd = NULL;
|
|
168 static struct mcomp *msgtl = NULL;
|
|
169 static struct mcomp *fmthd = NULL;
|
|
170 static struct mcomp *fmttl = NULL;
|
|
171
|
|
172 static struct mcomp global = {
|
|
173 NULL, NULL, "", NULL, NULL, 0, -1, 80, -1, 40, BELL, 0
|
|
174 };
|
|
175 static struct mcomp holder =
|
|
176 {
|
|
177 NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NOCOMPONENT, 0
|
|
178 };
|
|
179
|
|
180
|
|
181 static struct pair {
|
|
182 char *p_name;
|
|
183 long p_flags;
|
|
184 } pairs[] = {
|
|
185 "Date", DATEFMT,
|
|
186 "From", ADDRFMT | FACEDFLT,
|
|
187 "Sender", ADDRFMT,
|
|
188 "Reply-To", ADDRFMT,
|
|
189 "To", ADDRFMT,
|
|
190 "cc", ADDRFMT,
|
|
191 "Bcc", ADDRFMT,
|
|
192 "Resent-Date", DATEFMT,
|
|
193 "Resent-From", ADDRFMT,
|
|
194 "Resent-Sender", ADDRFMT,
|
|
195 "Resent-Reply-To", ADDRFMT,
|
|
196 "Resent-To", ADDRFMT,
|
|
197 "Resent-cc", ADDRFMT,
|
|
198 "Resent-Bcc", ADDRFMT,
|
|
199 "Face", FACEFMT,
|
|
200
|
|
201 NULL
|
|
202 };
|
|
203
|
|
204 static struct triple {
|
|
205 char *t_name;
|
|
206 long t_on;
|
|
207 long t_off;
|
|
208 } triples[] = {
|
|
209 "nocomponent", NOCOMPONENT, 0,
|
|
210 "uppercase", UPPERCASE, 0,
|
|
211 "nouppercase", 0, UPPERCASE,
|
|
212 "center", CENTER, 0,
|
|
213 "nocenter", 0, CENTER,
|
|
214 "clearscreen", CLEARSCR, 0,
|
|
215 "noclearscreen", 0, CLEARSCR,
|
|
216 "noclear", 0, CLEARSCR,
|
|
217 "leftadjust", LEFTADJUST, 0,
|
|
218 "noleftadjust", 0, LEFTADJUST,
|
|
219 "compress", COMPRESS, 0,
|
|
220 "nocompress", 0, COMPRESS,
|
|
221 "split", SPLIT, 0,
|
|
222 "nosplit", 0, SPLIT,
|
|
223 "addrfield", ADDRFMT, DATEFMT,
|
|
224 "bell", BELL, 0,
|
|
225 "nobell", 0, BELL,
|
|
226 "datefield", DATEFMT, ADDRFMT,
|
|
227 "newline", 0, NONEWLINE,
|
|
228 "nonewline", NONEWLINE, 0,
|
|
229 #ifdef MIME_HEADERS
|
|
230 "decode", DECODE, 0,
|
|
231 #endif /* MIME_HEADERS */
|
|
232
|
|
233 NULL
|
|
234 };
|
|
235
|
5
|
236 /* from mhn */
|
|
237
|
|
238 static int content_encoding; /* internal form */
|
|
239 #define CE_UNKNOWN 0x00
|
|
240 #define CE_BASE64 0x01
|
|
241 #define CE_QUOTED 0x02
|
|
242 #define CE_8BIT 0x03
|
|
243 #define CE_7BIT 0x04
|
|
244 #define CE_BINARY 0x05
|
|
245 #define CE_EXTENSION 0x06
|
|
246 #define CE_EXTERNAL 0x07 /* for external-body */
|
|
247
|
|
248 #define ENCODING_FIELD "Content-Transfer-Encoding"
|
|
249
|
|
250 struct str2init {
|
|
251 char *mhnsi_key;
|
|
252 int mhnsi_value;
|
|
253 };
|
|
254
|
|
255 static struct str2init str2ces[] = {
|
|
256 {"base64", CE_BASE64},
|
|
257 {"quoted-printable", CE_QUOTED},
|
|
258 {"8bit", CE_8BIT},
|
|
259 {"7bit", CE_7BIT},
|
|
260 {"binary", CE_BINARY},
|
|
261
|
|
262 {NULL, CE_EXTENSION},
|
|
263 {NULL, CE_UNKNOWN},
|
|
264 };
|
|
265
|
7
|
266 #define CS_DEFAULT 0
|
|
267 #define CS_JIS7 1
|
|
268 #define CS_JEUC 2
|
|
269 #define CS_SJIS 3
|
|
270 #define CS_UTF8 4
|
|
271 #define CS_NOCONV 99
|
|
272
|
|
273 static int content_type; /* internal form */
|
|
274 #define TYPE_FIELD "Content-Type"
|
|
275 static struct str2init str2charset[] = {
|
|
276 {"utf-8", CS_UTF8},
|
|
277 {"iso-2022-jp", CS_JIS7},
|
|
278 {"euc-jp", CS_JEUC},
|
|
279 {"xsjis", CS_SJIS},
|
|
280 {"shift_jis", CS_SJIS},
|
|
281 };
|
|
282
|
|
283
|
5
|
284 #define istoken(c) \
|
|
285 (!isspace (c) \
|
|
286 && !iscntrl (c) \
|
|
287 && !((c) & 0x80) \
|
|
288 && (c) != '(' \
|
|
289 && (c) != ')' \
|
|
290 && (c) != '<' \
|
|
291 && (c) != '>' \
|
|
292 && (c) != '@' \
|
|
293 && (c) != ',' \
|
|
294 && (c) != ';' \
|
|
295 && (c) != ':' \
|
|
296 && (c) != '\\' \
|
|
297 && (c) != '"' \
|
|
298 && (c) != '/' \
|
|
299 && (c) != '[' \
|
|
300 && (c) != ']' \
|
|
301 && (c) != '?' \
|
|
302 && (c) != '=')
|
|
303
|
0
|
304 /* */
|
|
305
|
|
306 static int bellflg = 0;
|
|
307 static int clearflg = 0;
|
|
308 static int dashflg = 1;
|
|
309 static int dobody = 1;
|
|
310 static int forwflg = 0;
|
|
311 static int forwall = 0;
|
|
312
|
|
313 static int sleepsw = NOTOK;
|
|
314
|
|
315 static char *digest = NULL;
|
|
316 static int volume = 0;
|
|
317 static int issue = 0;
|
|
318
|
|
319 static int exitstat = 0;
|
|
320 static int mhldebug = 0;
|
|
321
|
|
322 #define PITTY (-1)
|
|
323 #define NOTTY 0
|
|
324 #define ISTTY 1
|
|
325 static int ontty = NOTTY;
|
|
326
|
|
327 static int row;
|
|
328 static int column;
|
|
329
|
|
330 static int lm;
|
|
331 static int llim;
|
|
332 static int ovoff;
|
|
333 static int term;
|
|
334 static int wid;
|
|
335
|
|
336
|
|
337 static char *ovtxt;
|
|
338
|
|
339 static char *onelp;
|
|
340
|
|
341
|
|
342 static char *parptr;
|
|
343 static char *ignores[MAXARGS];
|
|
344
|
|
345
|
|
346 static jmp_buf env;
|
|
347 static jmp_buf mhlenv;
|
|
348
|
|
349
|
|
350 static char delim3[] = /* from forw.c */
|
|
351 "\n----------------------------------------------------------------------\n\n";
|
|
352 static char delim4[] = "\n------------------------------\n\n";
|
|
353
|
|
354
|
|
355 static FP (*mhl_action) () = (FP (*) ()) 0;
|
|
356
|
|
357
|
|
358 static void mhladios (), mhldone ();
|
|
359 static TYPESIG intrser (), pipeser (), quitser ();
|
|
360 static char *mcomp_add (), *oneline (), *parse ();
|
|
361 static struct mcomp *add_queue ();
|
|
362
|
|
363 static mhl_format(), evalvar(), process(), mhlfile(), free_queue(), putcomp();
|
|
364 static putstr(), putch(), face_format(), m_popen();
|
|
365 static int ptoi(), ptos(), doface();
|
|
366
|
|
367 void clear_screen ();
|
|
368
|
|
369 #ifdef JAPAN
|
|
370 static char mlbuf[BUFSIZ];
|
|
371 static char *mlcp;
|
|
372 static int ml_cont_p;
|
|
373 static void putstr_sbr();
|
|
374 #endif /* JAPAN */
|
|
375
|
|
376 /* */
|
|
377
|
|
378 /* ARGSUSED */
|
|
379
|
|
380 int mhl (argc, argv)
|
|
381 int argc;
|
|
382 char *argv[];
|
|
383 {
|
|
384 int length = 0,
|
|
385 nomore = 0,
|
|
386 width = 0,
|
|
387 vecp = 0,
|
|
388 i;
|
|
389 register char *cp,
|
|
390 *folder = NULL,
|
|
391 *form = NULL,
|
|
392 **ap,
|
|
393 **argp;
|
|
394 char buf[80],
|
|
395 *arguments[MAXARGS],
|
|
396 *files[MAXARGS];
|
|
397
|
|
398 invo_name = r1bindex (argv[0], '/');
|
|
399 if ((cp = getenv ("MHLDEBUG")) && *cp)
|
|
400 mhldebug++;
|
|
401 if ((cp = m_find (invo_name)) != NULL) {
|
|
402 ap = brkstring (getcpy (cp), " ", "\n");
|
|
403 ap = copyip (ap, arguments);
|
|
404 }
|
|
405 else
|
|
406 ap = arguments;
|
|
407 (void) copyip (argv + 1, ap);
|
|
408 argp = arguments;
|
|
409
|
|
410 /* */
|
|
411
|
|
412 if (cp = getenv ("FACEPROC"))
|
|
413 faceproc = cp;
|
|
414
|
|
415 vecp = 0;
|
|
416 while (cp = *argp++) {
|
|
417 if (*cp == '-')
|
|
418 switch (smatch (++cp, mhlswitches)) {
|
|
419 case AMBIGSW:
|
|
420 ambigsw (cp, mhlswitches);
|
|
421 done (1);
|
|
422 case UNKWNSW:
|
|
423 adios (NULLCP, "-%s unknown\n", cp);
|
|
424 case HELPSW:
|
|
425 (void) sprintf (buf, "%s [switches] [files ...]",
|
|
426 invo_name);
|
|
427 help (buf, mhlswitches);
|
|
428 done (1);
|
|
429
|
|
430 case BELLSW:
|
|
431 bellflg = 1;
|
|
432 continue;
|
|
433 case NBELLSW:
|
|
434 bellflg = -1;
|
|
435 continue;
|
|
436
|
|
437 case CLRSW:
|
|
438 clearflg = 1;
|
|
439 continue;
|
|
440 case NCLRSW:
|
|
441 clearflg = -1;
|
|
442 continue;
|
|
443
|
|
444 case FOLDSW:
|
|
445 if (!(folder = *argp++) || *folder == '-')
|
|
446 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
447 continue;
|
|
448 case FORMSW:
|
|
449 if (!(form = *argp++) || *form == '-')
|
|
450 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
451 continue;
|
|
452
|
|
453 case FACESW:
|
|
454 if (!(faceproc = *argp++) || *faceproc == '-')
|
|
455 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
456 continue;
|
|
457 case NFACESW:
|
|
458 faceproc = NULL;
|
|
459 continue;
|
|
460 case SLEEPSW:
|
|
461 if (!(cp = *argp++) || *cp == '-')
|
|
462 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
463 sleepsw = atoi (cp);/* ZERO ok! */
|
|
464 continue;
|
|
465
|
|
466 case PROGSW:
|
|
467 if (!(moreproc = *argp++) || *moreproc == '-')
|
|
468 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
469 continue;
|
|
470 case NPROGSW:
|
|
471 nomore++;
|
|
472 continue;
|
|
473
|
|
474 case LENSW:
|
|
475 if (!(cp = *argp++) || *cp == '-')
|
|
476 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
477 if ((length = atoi (cp)) < 1)
|
|
478 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
|
|
479 continue;
|
|
480 case WIDSW:
|
|
481 if (!(cp = *argp++) || *cp == '-')
|
|
482 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
483 if ((width = atoi (cp)) < 1)
|
|
484 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
|
|
485 continue;
|
|
486
|
|
487 case DGSTSW:
|
|
488 if (!(digest = *argp++) || *digest == '-')
|
|
489 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
490 continue;
|
|
491 case ISSUESW:
|
|
492 if (!(cp = *argp++) || *cp == '-')
|
|
493 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
494 if ((issue = atoi (cp)) < 1)
|
|
495 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
|
|
496 continue;
|
|
497 case VOLUMSW:
|
|
498 if (!(cp = *argp++) || *cp == '-')
|
|
499 adios (NULLCP, "missing argument to %s", argp[-2]);
|
|
500 if ((volume = atoi (cp)) < 1)
|
|
501 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
|
|
502 continue;
|
|
503
|
|
504 case FORW2SW:
|
|
505 forwall++; /* fall */
|
|
506 case FORW1SW:
|
|
507 forwflg++;
|
|
508 clearflg = -1;/* XXX */
|
|
509 continue;
|
|
510
|
|
511 case DASHSW:
|
|
512 dashflg++;
|
|
513 continue;
|
|
514 case NDASHSW:
|
|
515 dashflg = 0;
|
|
516 continue;
|
|
517
|
|
518 case NBODYSW:
|
|
519 dobody = 0;
|
|
520 continue;
|
|
521 }
|
|
522 files[vecp++] = cp;
|
|
523 }
|
|
524
|
|
525 /* */
|
|
526
|
|
527 if (!folder)
|
|
528 folder = getenv ("mhfolder");
|
|
529
|
|
530 if (isatty (fileno (stdout)))
|
|
531 if (!nomore && !sc_hardcopy () && moreproc && *moreproc) {
|
|
532 if (mhl_action) {
|
|
533 setsig (SIGINT, SIG_IGN);
|
|
534 setsig (SIGQUIT, quitser);
|
|
535 }
|
|
536 m_popen (moreproc);
|
|
537 ontty = PITTY;
|
|
538 }
|
|
539 else {
|
|
540 setsig (SIGINT, SIG_IGN);
|
|
541 setsig (SIGQUIT, quitser);
|
|
542 ontty = ISTTY;
|
|
543 }
|
|
544 else
|
|
545 ontty = NOTTY;
|
|
546
|
|
547 mhl_format (form ? form : mhlformat, length, width);
|
|
548
|
|
549 if (vecp == 0)
|
|
550 process (folder, NULLCP, 1, vecp = 1);
|
|
551 else
|
|
552 for (i = 0; i < vecp; i++)
|
|
553 process (folder, files[i], i + 1, vecp);
|
|
554
|
|
555 if (forwall) {
|
|
556 if (digest) {
|
|
557 printf ("%s", delim4);
|
|
558 if (volume == 0) {
|
|
559 (void) sprintf (buf, "End of %s Digest\n", digest);
|
|
560 }
|
|
561 else
|
|
562 (void) sprintf (buf, "End of %s Digest [Volume %d Issue %d]\n", digest, volume, issue);
|
|
563 i = strlen (buf);
|
|
564 for (cp = buf + i; i > 1; i--)
|
|
565 *cp++ = '*';
|
|
566 *cp++ = '\n';
|
|
567 *cp = 0;
|
|
568 printf ("%s", buf);
|
|
569 }
|
|
570 else
|
|
571 printf ("\n------- End of Forwarded Message%s\n\n",
|
|
572 vecp > 1 ? "s" : "");
|
|
573 }
|
|
574
|
|
575 if (clearflg > 0 && ontty == NOTTY)
|
|
576 clear_screen ();
|
|
577
|
|
578 if (ontty == PITTY)
|
|
579 m_pclose ();
|
|
580
|
|
581 return exitstat;
|
|
582 }
|
|
583
|
|
584 /* */
|
|
585
|
|
586 static mhl_format (file, length, width)
|
|
587 register char *file;
|
|
588 int length,
|
|
589 width;
|
|
590 {
|
|
591 int i;
|
|
592 register char *bp,
|
|
593 *cp,
|
|
594 **ip;
|
|
595 char *ap,
|
|
596 buffer[BUFSIZ],
|
|
597 name[NAMESZ];
|
|
598 register struct mcomp *c1;
|
|
599 struct stat st;
|
|
600 register FILE *fp;
|
|
601 static dev_t dev = 0;
|
|
602 static ino_t ino = 0;
|
|
603 static time_t mtime = 0;
|
|
604
|
|
605 if (fmthd != NULL)
|
|
606 if (stat (libpath (file), &st) != NOTOK
|
|
607 && mtime == st.st_mtime
|
|
608 && dev == st.st_dev
|
|
609 && ino == st.st_ino)
|
|
610 goto out;
|
|
611 else
|
|
612 free_queue (&fmthd, &fmttl);
|
|
613
|
|
614 if ((fp = fopen (libpath (file), "r")) == NULL)
|
|
615 adios (file, "unable to open format file");
|
|
616
|
|
617 if (fstat (fileno (fp), &st) != NOTOK)
|
|
618 mtime = st.st_mtime, dev = st.st_dev, ino = st.st_ino;
|
|
619
|
|
620 global.c_ovtxt = global.c_nfs = NULL;
|
|
621 global.c_fmt = NULL;
|
|
622 global.c_offset = 0;
|
|
623 global.c_ovoff = -1;
|
|
624 if ((i = sc_width ()) > 5)
|
|
625 global.c_width = i;
|
|
626 global.c_cwidth = -1;
|
|
627 if ((i = sc_length ()) > 5)
|
|
628 global.c_length = i - 1;
|
|
629 global.c_flags = BELL; /* BELL is default */
|
|
630 *(ip = ignores) = NULL;
|
|
631
|
|
632 while (vfgets (fp, &ap) == OK) {
|
|
633 #ifdef JAPAN
|
|
634 (void) ml_conv(ap);
|
|
635 #endif /* JAPAN */
|
|
636 bp = ap;
|
|
637 if (*bp == ';')
|
|
638 continue;
|
|
639
|
|
640 if (cp = index (bp, '\n'))
|
|
641 *cp = 0;
|
|
642
|
|
643 if (*bp == ':') {
|
|
644 c1 = add_queue (&fmthd, &fmttl, NULLCP, bp + 1, CLEARTEXT);
|
|
645 continue;
|
|
646 }
|
|
647
|
|
648 parptr = bp;
|
|
649 (void) strcpy (name, parse ());
|
|
650 switch (*parptr) {
|
|
651 case '\0':
|
|
652 case ',':
|
|
653 case '=':
|
|
654 if (uleq (name, "ignores")) {
|
|
655 ip = copyip (brkstring (getcpy (++parptr), ",", NULLCP), ip);
|
|
656 continue;
|
|
657 }
|
|
658 parptr = bp;
|
|
659 while (*parptr) {
|
|
660 if (evalvar (&global))
|
|
661 adios (NULLCP, "format file syntax error: %s", bp);
|
|
662 if (*parptr)
|
|
663 parptr++;
|
|
664 }
|
|
665 continue;
|
|
666
|
|
667 case ':':
|
|
668 c1 = add_queue (&fmthd, &fmttl, name, NULLCP, INIT);
|
|
669 while (*parptr == ':' || *parptr == ',') {
|
|
670 parptr++;
|
|
671 if (evalvar (c1))
|
|
672 adios (NULLCP, "format file syntax error: %s", bp);
|
|
673 }
|
|
674 if (!c1 -> c_nfs && global.c_nfs)
|
|
675 if (c1 -> c_flags & DATEFMT) {
|
|
676 if (global.c_flags & DATEFMT)
|
|
677 c1 -> c_nfs = getcpy (global.c_nfs);
|
|
678 }
|
|
679 else
|
|
680 if (c1 -> c_flags & ADDRFMT) {
|
|
681 if (global.c_flags & ADDRFMT)
|
|
682 c1 -> c_nfs = getcpy (global.c_nfs);
|
|
683 }
|
|
684 continue;
|
|
685
|
|
686 default:
|
|
687 adios (NULLCP, "format file syntax error: %s", bp);
|
|
688 }
|
|
689 }
|
|
690 (void) fclose (fp);
|
|
691
|
|
692 if (mhldebug)
|
|
693 for (c1 = fmthd; c1; c1 = c1 -> c_next) {
|
|
694 fprintf (stderr, "c1: name=\"%s\" text=\"%s\" ovtxt=\"%s\"\n",
|
|
695 c1 -> c_name, c1 -> c_text, c1 -> c_ovtxt);
|
|
696 fprintf (stderr, "\tnfs=0x%x fmt=0x%x\n",
|
|
697 c1 -> c_nfs, c1 -> c_fmt);
|
|
698 fprintf (stderr, "\toffset=%d ovoff=%d width=%d cwidth=%d length=%d\n",
|
|
699 c1 -> c_offset, c1 -> c_ovoff, c1 -> c_width,
|
|
700 c1 -> c_cwidth, c1 -> c_length);
|
|
701 fprintf (stderr, "\tflags=%s\n",
|
|
702 sprintb (buffer, (unsigned) c1 -> c_flags, LBITS));
|
|
703 }
|
|
704
|
|
705 out: ;
|
|
706 if (clearflg == 1)
|
|
707 global.c_flags |= CLEARSCR;
|
|
708 else
|
|
709 if (clearflg == -1)
|
|
710 global.c_flags &= ~CLEARSCR;
|
|
711
|
|
712 switch (bellflg) { /* command line may override format file */
|
|
713 case 1:
|
|
714 global.c_flags |= BELL;
|
|
715 break;
|
|
716 case -1:
|
|
717 global.c_flags &= ~BELL;
|
|
718 break;
|
|
719 }
|
|
720
|
|
721 if (length)
|
|
722 global.c_length = length;
|
|
723 if (width)
|
|
724 global.c_width = width;
|
|
725 if (global.c_length < 5)
|
|
726 global.c_length = 10000;
|
|
727 if (global.c_width < 5)
|
|
728 global.c_width = 10000;
|
|
729 }
|
|
730
|
|
731 /* */
|
|
732
|
|
733 static evalvar (c1)
|
|
734 register struct mcomp *c1;
|
|
735 {
|
|
736 char *cp,
|
|
737 name[NAMESZ];
|
|
738 register struct triple *ap;
|
|
739
|
|
740 if (!*parptr)
|
|
741 return 0;
|
|
742 (void) strcpy (name, parse ());
|
|
743
|
|
744 if (uleq (name, "component")) {
|
|
745 if (ptos (name, &c1 -> c_text))
|
|
746 return 1;
|
|
747 c1 -> c_flags &= ~NOCOMPONENT;
|
|
748 return 0;
|
|
749 }
|
|
750 if (uleq (name, "overflowtext"))
|
|
751 return ptos (name, &c1 -> c_ovtxt);
|
|
752 if (uleq (name, "formatfield")) {
|
|
753 if (ptos (name, &cp))
|
|
754 return 1;
|
|
755 c1 -> c_nfs = getcpy (new_fs (NULLCP, NULLCP, cp));
|
|
756 c1 -> c_flags |= FORMAT;
|
|
757 return 0;
|
|
758 }
|
|
759
|
|
760 if (uleq (name, "offset"))
|
|
761 return ptoi (name, &c1 -> c_offset);
|
|
762 if (uleq (name, "overflowoffset"))
|
|
763 return ptoi (name, &c1 -> c_ovoff);
|
|
764 if (uleq (name, "width"))
|
|
765 return ptoi (name, &c1 -> c_width);
|
|
766 if (uleq (name, "compwidth"))
|
|
767 return ptoi (name, &c1 -> c_cwidth);
|
|
768 if (uleq (name, "length"))
|
|
769 return ptoi (name, &c1 -> c_length);
|
|
770 if (uleq (name, "nodashmunging"))
|
|
771 return (dashflg = 0);
|
|
772
|
|
773 for (ap = triples; ap -> t_name; ap++)
|
|
774 if (uleq (ap -> t_name, name)) {
|
|
775 c1 -> c_flags |= ap -> t_on;
|
|
776 c1 -> c_flags &= ~ap -> t_off;
|
|
777 return 0;
|
|
778 }
|
|
779
|
|
780 return 1;
|
|
781 }
|
|
782
|
|
783 /* */
|
|
784
|
|
785 static int ptoi (name, i)
|
|
786 register char *name;
|
|
787 register int *i;
|
|
788 {
|
|
789 char *cp;
|
|
790
|
|
791 if (*parptr++ != '=' || !*(cp = parse ())) {
|
|
792 advise (NULLCP, "missing argument to variable %s", name);
|
|
793 return 1;
|
|
794 }
|
|
795
|
|
796 *i = atoi (cp);
|
|
797 return 0;
|
|
798 }
|
|
799
|
|
800
|
|
801 static int ptos (name, s)
|
|
802 register char *name,
|
|
803 **s;
|
|
804 {
|
|
805 char c,
|
|
806 *cp;
|
|
807
|
|
808 if (*parptr++ != '=') {
|
|
809 advise (NULLCP, "missing argument to variable %s", name);
|
|
810 return 1;
|
|
811 }
|
|
812
|
|
813 if (*parptr != '"')
|
|
814 for (cp = parptr;
|
|
815 *parptr && *parptr != ':' && *parptr != ',';
|
|
816 parptr++)
|
|
817 continue;
|
|
818 else
|
|
819 for (cp = ++parptr; *parptr && *parptr != '"'; parptr++)
|
|
820 if (*parptr == QUOTE)
|
|
821 if (!*++parptr)
|
|
822 parptr--;
|
|
823 c = *parptr;
|
|
824 *parptr = 0;
|
|
825 *s = getcpy (cp);
|
|
826 if ((*parptr = c) == '"')
|
|
827 parptr++;
|
|
828 return 0;
|
|
829 }
|
|
830
|
|
831 /* */
|
|
832
|
|
833 static char *parse () {
|
|
834 unsigned int c;
|
|
835 register char *cp;
|
|
836 static char result[NAMESZ];
|
|
837
|
|
838 for (cp = result; c = *parptr; parptr++)
|
|
839 if (isalnum (c)
|
|
840 || c == '.'
|
|
841 || c == '-'
|
|
842 || c == '_'
|
|
843 || c =='['
|
|
844 || c == ']')
|
|
845 *cp++ = c;
|
|
846 else
|
|
847 break;
|
|
848 *cp = 0;
|
|
849
|
|
850 return result;
|
|
851 }
|
|
852
|
|
853 /* */
|
|
854
|
|
855 static process (folder, fname, ofilen, ofilec)
|
|
856 char *folder,
|
|
857 *fname;
|
|
858 int ofilen,
|
|
859 ofilec;
|
|
860 {
|
|
861 char *cp;
|
|
862 FILE *fp;
|
|
863 struct mcomp *c1;
|
|
864
|
|
865 switch (setjmp (env)) {
|
|
866 case OK:
|
|
867 if (fname) {
|
|
868 fp = mhl_action ? (*mhl_action) (fname) : fopen (fname, "r");
|
|
869 if (fp == NULL) {
|
|
870 advise (fname, "unable to open");
|
|
871 exitstat++;
|
|
872 return;
|
|
873 }
|
|
874 }
|
|
875 else {
|
|
876 fname = "(stdin)";
|
|
877 fp = stdin;
|
|
878 }
|
|
879 cp = folder ? concat (folder, ":", fname, NULLCP) : getcpy (fname);
|
|
880 if (ontty != PITTY)
|
|
881 (void) signal (SIGINT, intrser);
|
|
882 mhlfile (fp, cp, ofilen, ofilec);/* fall */
|
|
883
|
|
884 default:
|
|
885 if (ontty != PITTY)
|
|
886 (void) signal (SIGINT, SIG_IGN);
|
|
887 if (mhl_action == NULL && fp != stdin)
|
|
888 (void) fclose (fp);
|
|
889 free (cp);
|
|
890 if (holder.c_text) {
|
|
891 free (holder.c_text);
|
|
892 holder.c_text = NULL;
|
|
893 }
|
|
894 free_queue (&msghd, &msgtl);
|
|
895 for (c1 = fmthd; c1; c1 = c1 -> c_next)
|
|
896 c1 -> c_flags &= ~HDROUTPUT;
|
|
897 break;
|
|
898 }
|
|
899 }
|
|
900
|
|
901 /* */
|
|
902
|
|
903 static mhlfile (fp, mname, ofilen, ofilec)
|
|
904 register FILE *fp;
|
|
905 register char *mname;
|
|
906 int ofilen,
|
|
907 ofilec;
|
|
908 {
|
|
909 int state;
|
|
910 register struct mcomp *c1,
|
|
911 *c2,
|
|
912 *c3;
|
|
913 register char **ip;
|
|
914 char name[NAMESZ],
|
|
915 buf[BUFSIZ];
|
|
916
|
|
917 if (forwall) {
|
|
918 if (digest)
|
|
919 printf ("%s", ofilen == 1 ? delim3 : delim4);
|
|
920 else {
|
|
921 printf ("\n-------");
|
|
922 if (ofilen == 1)
|
|
923 printf (" Forwarded Message%s", ofilec > 1 ? "s" : "");
|
|
924 else
|
|
925 printf (" Message %d", ofilen);
|
|
926 printf ("\n\n");
|
|
927 }
|
|
928 }
|
|
929 else
|
|
930 switch (ontty) {
|
|
931 case PITTY:
|
|
932 if (ofilec > 1) {
|
|
933 if (ofilen > 1) {
|
|
934 if ((global.c_flags & CLEARSCR))
|
|
935 clear_screen ();
|
|
936 else
|
|
937 printf ("\n\n\n");
|
|
938 }
|
|
939 printf (">>> %s\n\n", mname);
|
|
940 }
|
|
941 break;
|
|
942
|
|
943 case ISTTY:
|
|
944 (void) strcpy (buf, "\n");
|
|
945 if (ofilec > 1) {
|
|
946 if (SOprintf ("Press <return> to list \"%s\"...", mname)) {
|
|
947 if (ofilen > 1)
|
|
948 printf ("\n\n\n");
|
|
949 printf ("Press <return> to list \"%s\"...", mname);
|
|
950 }
|
|
951 (void) fflush (stdout);
|
|
952 buf[0] = 0;
|
|
953 (void) read (fileno (stdout), buf, sizeof buf);
|
|
954 }
|
|
955 if (index (buf, '\n')) {
|
|
956 if ((global.c_flags & CLEARSCR))
|
|
957 clear_screen ();
|
|
958 }
|
|
959 else
|
|
960 printf ("\n");
|
|
961 break;
|
|
962
|
|
963 default:
|
|
964 if (ofilec > 1) {
|
|
965 if (ofilen > 1) {
|
|
966 printf ("\n\n\n");
|
|
967 if (clearflg > 0)
|
|
968 clear_screen ();
|
|
969 }
|
|
970 printf (">>> %s\n\n", mname);
|
|
971 }
|
|
972 break;
|
|
973 }
|
|
974
|
|
975 /* */
|
|
976
|
|
977 for (state = FLD;;)
|
5
|
978 next:
|
0
|
979 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
|
|
980 case FLD:
|
|
981 case FLDPLUS:
|
5
|
982 #ifdef ENCODING_FIELD
|
|
983 /* form mhn */
|
7
|
984 /* We had better to check Content-Type, */
|
|
985 /* because in case of short utf-8 text, nkf mail fail to */
|
|
986 /* correct code */
|
5
|
987 if (uleq (name, ENCODING_FIELD)) {
|
|
988 char *cp,
|
|
989 *dp;
|
|
990 char c;
|
|
991 register struct str2init *s2i;
|
|
992
|
|
993 cp = add (buf, NULLCP);
|
|
994 while (state == FLDPLUS) {
|
|
995 state = m_getfld (state, name, buf, sizeof buf, fp);
|
|
996 cp = add (buf, cp);
|
|
997 }
|
|
998 while (isspace (*cp))
|
|
999 cp++;
|
|
1000 for (dp = index (cp, '\n'); dp; dp = index (dp, '\n'))
|
|
1001 *dp++ = ' ';
|
|
1002 if (*cp == '(' ) { /* comment */
|
|
1003 int i;
|
|
1004 for (i = 1;i;) {
|
|
1005 switch (*cp++) {
|
|
1006 case '(': i++; break;
|
|
1007 case ')': --i; break;
|
|
1008 case '\\': if ((*cp++) != '\0') break;
|
|
1009 case '\0': goto next;
|
|
1010 }
|
|
1011 }
|
|
1012 }
|
|
1013 for (dp = cp; istoken (*dp); dp++);
|
|
1014 c = *dp, *dp = '\0';
|
|
1015 for (s2i = str2ces; s2i -> mhnsi_key; s2i++)
|
|
1016 if (uleq (cp, s2i -> mhnsi_key))
|
|
1017 break;
|
|
1018 if (!s2i -> mhnsi_key && !uprf (cp, "X-"))
|
|
1019 s2i++;
|
|
1020 *dp = c;
|
|
1021 content_encoding = s2i -> mhnsi_value;
|
7
|
1022 } else if (uleq (name, TYPE_FIELD)) {
|
|
1023 char *cp,
|
|
1024 *dp;
|
|
1025 char c;
|
|
1026 register struct str2init *s2i;
|
|
1027
|
|
1028 cp = add (buf, NULLCP);
|
|
1029 while (state == FLDPLUS) {
|
|
1030 state = m_getfld (state, name, buf, sizeof buf, fp);
|
|
1031 cp = add (buf, cp);
|
|
1032 }
|
|
1033 while (isspace (*cp))
|
|
1034 cp++;
|
|
1035 while(cp) {
|
|
1036 cp = index (cp, 'c');
|
|
1037 if (!strncasecmp(cp,"charset",7)) {
|
|
1038 cp+=7;
|
|
1039 break;
|
|
1040 } else {
|
|
1041 cp++;
|
|
1042 }
|
|
1043 }
|
|
1044 while (isspace (*cp)||*cp=='=') cp++;
|
|
1045
|
|
1046 for (dp = cp; istoken (*dp); dp++);
|
|
1047 c = *dp, *dp = '\0';
|
|
1048 for (s2i = str2charset; s2i -> mhnsi_key; s2i++)
|
|
1049 if (uleq (cp, s2i -> mhnsi_key))
|
|
1050 break;
|
|
1051 if (!s2i -> mhnsi_key && !uprf (cp, "X-"))
|
|
1052 s2i++;
|
|
1053 *dp = c;
|
|
1054 content_type = s2i -> mhnsi_value;
|
5
|
1055 }
|
|
1056 #endif
|
0
|
1057 for (ip = ignores; *ip; ip++)
|
|
1058 if (uleq (name, *ip)) {
|
|
1059 while (state == FLDPLUS)
|
|
1060 state = m_getfld (state, name, buf, sizeof buf, fp);
|
|
1061 break;
|
|
1062 }
|
|
1063 if (*ip)
|
|
1064 continue;
|
|
1065
|
|
1066 for (c2 = fmthd; c2; c2 = c2 -> c_next)
|
|
1067 if (uleq (c2 -> c_name, name))
|
|
1068 break;
|
|
1069 c1 = NULL;
|
|
1070 if (!((c3 = c2 ? c2 : &global) -> c_flags & SPLIT))
|
|
1071 for (c1 = msghd; c1; c1 = c1 -> c_next)
|
|
1072 if (uleq (c1 -> c_name, c3 -> c_name)) {
|
|
1073 c1 -> c_text =
|
|
1074 mcomp_add (c1 -> c_flags, buf, c1 -> c_text);
|
|
1075 break;
|
|
1076 }
|
|
1077 if (c1 == NULL)
|
|
1078 c1 = add_queue (&msghd, &msgtl, name, buf, 0);
|
|
1079 while (state == FLDPLUS) {
|
|
1080 state = m_getfld (state, name, buf, sizeof buf, fp);
|
|
1081 c1 -> c_text = add (buf, c1 -> c_text);
|
|
1082 }
|
|
1083 if (c2 == NULL)
|
|
1084 c1 -> c_flags |= EXTRA;
|
|
1085 #ifdef JAPAN
|
|
1086 (void) ml_conv(c1 -> c_text);
|
|
1087 #endif /* JAPAN */
|
|
1088 if (*(c1 -> c_text) == ' ') {
|
|
1089 char *cp;
|
|
1090 cp = getcpy((c1 -> c_text) + 1);
|
|
1091 free(c1 -> c_text);
|
|
1092 c1 -> c_text = cp;
|
|
1093 }
|
|
1094 continue;
|
|
1095
|
|
1096 case BODY:
|
|
1097 case FILEEOF:
|
|
1098 row = column = 0;
|
|
1099 for (c1 = fmthd; c1; c1 = c1 -> c_next) {
|
|
1100 if (c1 -> c_flags & CLEARTEXT) {
|
|
1101 putcomp (c1, c1, ONECOMP);
|
|
1102 continue;
|
|
1103 }
|
|
1104 if (uleq (c1 -> c_name, "messagename")) {
|
|
1105 holder.c_text = concat ("(Message ", mname, ")\n",
|
|
1106 NULLCP);
|
|
1107 putcomp (c1, &holder, ONECOMP);
|
|
1108 free (holder.c_text);
|
|
1109 holder.c_text = NULL;
|
|
1110 continue;
|
|
1111 }
|
|
1112 if (uleq (c1 -> c_name, "extras")) {
|
|
1113 for (c2 = msghd; c2; c2 = c2 -> c_next)
|
|
1114 if (c2 -> c_flags & EXTRA)
|
|
1115 putcomp (c1, c2, TWOCOMP);
|
|
1116 continue;
|
|
1117 }
|
|
1118 if (dobody && uleq (c1 -> c_name, "body")) {
|
|
1119 #ifdef JAPAN
|
|
1120 int buflen = sizeof(buf);
|
|
1121 #endif /* JAPAN */
|
|
1122 if ((holder.c_text = malloc (sizeof buf)) == NULL)
|
|
1123 adios (NULLCP, "unable to allocate buffer memory");
|
|
1124 (void) strcpy (holder.c_text, buf);
|
|
1125 #ifdef JAPAN
|
|
1126 /* ... (-_-; */
|
|
1127 while (state == BODY) {
|
|
1128 char *cp;
|
|
1129 cp = rindex(holder.c_text, '\n');
|
|
1130 if (cp == NULL) {
|
|
1131 cp = holder.c_text + strlen(holder.c_text);
|
|
1132 } else {
|
|
1133 strcpy(buf, ++cp);
|
|
1134 *cp = 0;
|
7
|
1135 (void) ml_conv_decode(holder.c_text,content_encoding,content_type);
|
0
|
1136 /* putcomp() may change the address
|
|
1137 of holder.c_text */
|
|
1138 putcomp(c1, &holder, BODYCOMP);
|
|
1139 cp = copy(buf, holder.c_text);
|
|
1140 }
|
|
1141 if (cp - holder.c_text >= buflen - 1) {
|
|
1142 /* buffer overflow */
|
|
1143 state = m_getfld(state, name,
|
|
1144 buf, sizeof buf, fp);
|
|
1145 holder.c_text = add(buf, holder.c_text);
|
|
1146 buflen = strlen(holder.c_text) + 1;
|
|
1147 } else
|
|
1148 state = m_getfld(state, name, cp,
|
|
1149 holder.c_text + buflen - cp,
|
|
1150 fp);
|
|
1151 }
|
7
|
1152 (void) ml_conv_decode(holder.c_text,content_encoding,content_type);
|
0
|
1153 putcomp(c1, &holder, BODYCOMP);
|
|
1154 #else /* JAPAN */
|
|
1155 while (state == BODY) {
|
|
1156 putcomp (c1, &holder, BODYCOMP);
|
|
1157 state = m_getfld (state, name, holder.c_text,
|
|
1158 sizeof buf, fp);
|
|
1159 }
|
|
1160 #endif /* JAPAN */
|
|
1161 free (holder.c_text);
|
|
1162 holder.c_text = NULL;
|
|
1163 continue;
|
|
1164 }
|
|
1165 for (c2 = msghd; c2; c2 = c2 -> c_next)
|
|
1166 if (uleq (c2 -> c_name, c1 -> c_name)) {
|
|
1167 putcomp (c1, c2, ONECOMP);
|
|
1168 if (!(c1 -> c_flags & SPLIT))
|
|
1169 break;
|
|
1170 }
|
|
1171 if (faceproc && c2 == NULL && (c1 -> c_flags & FACEFMT))
|
|
1172 for (c2 = msghd; c2; c2 = c2 -> c_next)
|
|
1173 if (c2 -> c_flags & FACEDFLT) {
|
|
1174 if (c2 -> c_face == NULL)
|
|
1175 face_format (c2);
|
|
1176 if (holder.c_text = c2 -> c_face) {
|
|
1177 putcomp (c1, &holder, ONECOMP);
|
|
1178 holder.c_text = NULL;
|
|
1179 }
|
|
1180 break;
|
|
1181 }
|
|
1182 }
|
|
1183 return;
|
|
1184
|
|
1185 case LENERR:
|
|
1186 case FMTERR:
|
|
1187 advise (NULLCP, "format error in message %s", mname);
|
|
1188 exitstat++;
|
|
1189 return;
|
|
1190
|
|
1191 default:
|
|
1192 adios (NULLCP, "getfld() returned %d", state);
|
|
1193 }
|
|
1194 }
|
|
1195
|
|
1196 /* */
|
|
1197
|
|
1198 static int mcomp_flags (name)
|
|
1199 register char *name;
|
|
1200 {
|
|
1201 register struct pair *ap;
|
|
1202
|
|
1203 for (ap = pairs; ap -> p_name; ap++)
|
|
1204 if (uleq (ap -> p_name, name))
|
|
1205 return (ap -> p_flags);
|
|
1206
|
|
1207 return 0;
|
|
1208 }
|
|
1209
|
|
1210
|
|
1211 static char *mcomp_add (flags, s1, s2)
|
|
1212 long flags;
|
|
1213 register char *s1,
|
|
1214 *s2;
|
|
1215 {
|
|
1216 register char *dp;
|
|
1217
|
|
1218 if (!(flags & ADDRFMT))
|
|
1219 return add (s1, s2);
|
|
1220
|
|
1221 if (s2 && *(dp = s2 + strlen (s2) - 1) == '\n')
|
|
1222 *dp = 0;
|
|
1223
|
|
1224 return add (s1, add (",\n", s2));
|
|
1225 }
|
|
1226
|
|
1227 /* */
|
|
1228
|
|
1229 struct pqpair {
|
|
1230 char *pq_text;
|
|
1231 char *pq_error;
|
|
1232 struct pqpair *pq_next;
|
|
1233 };
|
|
1234
|
|
1235
|
|
1236 static mcomp_format (c1, c2)
|
|
1237 register struct mcomp *c1,
|
|
1238 *c2;
|
|
1239 {
|
|
1240 int dat[5];
|
|
1241 register char *ap,
|
|
1242 *cp;
|
|
1243 char error[BUFSIZ];
|
|
1244 register struct comp *cptr;
|
|
1245 register struct pqpair *p,
|
|
1246 *q;
|
|
1247 struct pqpair pq;
|
|
1248 register struct mailname *mp;
|
|
1249 char *buffer;
|
|
1250 int buflen;
|
|
1251
|
|
1252 ap = c2 -> c_text;
|
|
1253 c2 -> c_text = NULL;
|
|
1254 buflen = ap ? strlen(ap)*5 : 0;
|
|
1255 if ((buffer = malloc(buflen = (buflen > BUFSIZ) ? buflen : BUFSIZ))
|
|
1256 == NULLCP)
|
|
1257 adios(NULLCP, "out of memory");
|
|
1258 dat[0] = dat[1] = dat[2] = dat[4] = 0;
|
|
1259 dat[3] = buflen - 1;
|
|
1260 (void) fmt_compile (c1 -> c_nfs, &c1 -> c_fmt);
|
|
1261
|
|
1262 if (!(c1 -> c_flags & ADDRFMT)) {
|
|
1263 FINDCOMP (cptr, "text");
|
|
1264 if (cptr)
|
|
1265 cptr -> c_text = ap;
|
|
1266 if (cp = rindex(ap, '\n')) /* drop ending newline */
|
|
1267 if (!cp[1])
|
|
1268 *cp = 0;
|
|
1269
|
|
1270 (void) fmtscan (c1 -> c_fmt, buffer, buflen - 1, dat);
|
|
1271 c2 -> c_text = getcpy (buffer);
|
|
1272 #ifndef JLR
|
|
1273 /* Don't need to append a newline, dctime() already did */
|
|
1274 #else
|
|
1275 if (!(c1 -> c_flags & NONEWLINE))
|
|
1276 c2 -> c_text = add ("\n", c2 -> c_text);
|
|
1277 #endif
|
|
1278
|
|
1279 free (ap);
|
|
1280 return;
|
|
1281 }
|
|
1282
|
|
1283 (q = &pq) -> pq_next = NULL;
|
|
1284 while (cp = getname (ap)) {
|
|
1285 if ((p = (struct pqpair *) calloc ((unsigned) 1, sizeof *p)) == NULL)
|
|
1286 adios (NULLCP, "unable to allocate pqpair memory");
|
|
1287
|
|
1288 if ((mp = getm (cp, NULLCP, 0, AD_NAME, error)) == NULL) {
|
|
1289 p -> pq_text = getcpy (cp);
|
|
1290 p -> pq_error = getcpy (error);
|
|
1291 }
|
|
1292 else {
|
|
1293 if ((c1 -> c_flags & FACEDFLT) && c2 -> c_face == NULL) {
|
|
1294 char *h, *o;
|
|
1295 if ((h = mp -> m_host) == NULL)
|
|
1296 h = LocalName ();
|
|
1297 if (o = OfficialName (h))
|
|
1298 h = o;
|
|
1299 c2 -> c_face = concat ("address ", h, " ", mp -> m_mbox,
|
|
1300 NULLCP);
|
|
1301 }
|
|
1302 p -> pq_text = getcpy (mp -> m_text);
|
|
1303 mnfree (mp);
|
|
1304 }
|
|
1305 q = (q -> pq_next = p);
|
|
1306 }
|
|
1307
|
|
1308 for (p = pq.pq_next; p; p = q) {
|
|
1309 FINDCOMP (cptr, "text");
|
|
1310 if (cptr)
|
|
1311 cptr -> c_text = p -> pq_text;
|
|
1312 FINDCOMP (cptr, "error");
|
|
1313 if (cptr)
|
|
1314 cptr -> c_text = p -> pq_error;
|
|
1315
|
|
1316 (void) fmtscan (c1 -> c_fmt, buffer, buflen - 1, dat);
|
|
1317 if (*buffer) {
|
|
1318 if (c2 -> c_text)
|
|
1319 c2 -> c_text = add (",\n", c2 -> c_text);
|
|
1320 if (*(cp = buffer + strlen (buffer) - 1) == '\n')
|
|
1321 *cp = 0;
|
|
1322 c2 -> c_text = add (buffer, c2 -> c_text);
|
|
1323 }
|
|
1324
|
|
1325 free (p -> pq_text);
|
|
1326 if (p -> pq_error)
|
|
1327 free (p -> pq_error);
|
|
1328 q = p -> pq_next;
|
|
1329 free ((char *) p);
|
|
1330 }
|
|
1331
|
|
1332 c2 -> c_text = add ("\n", c2 -> c_text);
|
|
1333 free (ap);
|
|
1334 free (buffer);
|
|
1335 }
|
|
1336
|
|
1337 /* */
|
|
1338
|
|
1339 static struct mcomp *add_queue (head, tail, name, text, flags)
|
|
1340 register struct mcomp **head,
|
|
1341 **tail;
|
|
1342 register char *name,
|
|
1343 *text;
|
|
1344 int flags;
|
|
1345 {
|
|
1346 register struct mcomp *c1;
|
|
1347
|
|
1348 if ((c1 = (struct mcomp *) calloc ((unsigned) 1, sizeof *c1)) == NULL)
|
|
1349 adios (NULLCP, "unable to allocate comp memory");
|
|
1350
|
|
1351 c1 -> c_flags = flags & ~INIT;
|
|
1352 if (c1 -> c_name = name ? getcpy (name) : NULL)
|
|
1353 c1 -> c_flags |= mcomp_flags (c1 -> c_name);
|
|
1354 c1 -> c_text = text ? getcpy (text) : NULL;
|
|
1355 if (flags & INIT) {
|
|
1356 if (global.c_ovtxt)
|
|
1357 c1 -> c_ovtxt = getcpy (global.c_ovtxt);
|
|
1358 c1 -> c_offset = global.c_offset;
|
|
1359 c1 -> c_ovoff = global. c_ovoff;
|
|
1360 c1 -> c_width = c1 -> c_length = 0;
|
|
1361 c1 -> c_cwidth = global.c_cwidth;
|
|
1362 c1 -> c_flags |= global.c_flags & GFLAGS;
|
|
1363 }
|
|
1364 if (*head == NULL)
|
|
1365 *head = c1;
|
|
1366 if (*tail != NULL)
|
|
1367 (*tail) -> c_next = c1;
|
|
1368 *tail = c1;
|
|
1369
|
|
1370 return c1;
|
|
1371 }
|
|
1372
|
|
1373
|
|
1374 static free_queue (head, tail)
|
|
1375 register struct mcomp **head,
|
|
1376 **tail;
|
|
1377 {
|
|
1378 register struct mcomp *c1,
|
|
1379 *c2;
|
|
1380
|
|
1381 for (c1 = *head; c1; c1 = c2) {
|
|
1382 c2 = c1 -> c_next;
|
|
1383 if (c1 -> c_name)
|
|
1384 free (c1 -> c_name);
|
|
1385 if (c1 -> c_text)
|
|
1386 free (c1 -> c_text);
|
|
1387 if (c1 -> c_ovtxt)
|
|
1388 free (c1 -> c_ovtxt);
|
|
1389 if (c1 -> c_nfs)
|
|
1390 free (c1 -> c_nfs);
|
|
1391 if (c1 -> c_fmt)
|
|
1392 free ((char *) c1 -> c_fmt);
|
|
1393 if (c1 -> c_face)
|
|
1394 free (c1 -> c_face);
|
|
1395 free ((char *) c1);
|
|
1396 }
|
|
1397
|
|
1398 *head = *tail = NULL;
|
|
1399 }
|
|
1400
|
|
1401 /* */
|
|
1402
|
|
1403 static putcomp (c1, c2, flag)
|
|
1404 register struct mcomp *c1,
|
|
1405 *c2;
|
|
1406 int flag;
|
|
1407 {
|
|
1408 int count,
|
|
1409 cchdr;
|
|
1410 register char *cp;
|
|
1411
|
|
1412 cchdr = 0;
|
|
1413 lm = 0;
|
|
1414 llim = c1 -> c_length ? c1 -> c_length : -1;
|
|
1415 wid = c1 -> c_width ? c1 -> c_width : global.c_width;
|
|
1416 ovoff = (c1 -> c_ovoff >= 0 ? c1 -> c_ovoff : global.c_ovoff)
|
|
1417 + c1 -> c_offset;
|
|
1418 if ((ovtxt = c1 -> c_ovtxt ? c1 -> c_ovtxt : global.c_ovtxt) == NULL)
|
|
1419 ovtxt = "";
|
|
1420 if (wid < ovoff + strlen (ovtxt) + 5)
|
|
1421 adios (NULLCP, "component: %s width(%d) too small for overflow(%d)",
|
|
1422 c1 -> c_name, wid, ovoff + strlen (ovtxt) + 5);
|
|
1423 onelp = NULL;
|
|
1424
|
|
1425 if (c1 -> c_flags & CLEARTEXT) {
|
|
1426 putstr (c1 -> c_text);
|
|
1427 putstr ("\n");
|
|
1428 return;
|
|
1429 }
|
|
1430
|
|
1431 if (c1 -> c_flags & FACEFMT)
|
|
1432 switch (doface (c2)) {
|
|
1433 case NOTOK: /* error */
|
|
1434 case OK: /* async faceproc */
|
|
1435 return;
|
|
1436
|
|
1437 default: /* sync faceproc */
|
|
1438 break;
|
|
1439 }
|
|
1440
|
|
1441 #ifdef MIME_HEADERS
|
|
1442 if (c1 -> c_flags & DECODE) {
|
|
1443 char *ep;
|
|
1444 if ((ep = malloc((unsigned)strlen(c2 -> c_text)+1)) == NULL)
|
|
1445 adios(NULLCP, "out of memory");
|
|
1446 (void) exthdr_decode(c2 -> c_text, ep);
|
|
1447 free(c2 -> c_text);
|
|
1448 c2 -> c_text = ep;
|
|
1449 }
|
|
1450 #endif /* MIME_HEADERS */
|
|
1451
|
|
1452 if (c1 -> c_nfs && (c1 -> c_flags & (ADDRFMT | DATEFMT | FORMAT)))
|
|
1453 mcomp_format (c1, c2);
|
|
1454
|
|
1455 if (c1 -> c_flags & CENTER) {
|
|
1456 count = (c1 -> c_width ? c1 -> c_width : global.c_width)
|
|
1457 - c1 -> c_offset - strlen (c2 -> c_text);
|
|
1458 if (!(c1 -> c_flags & HDROUTPUT) && !(c1 -> c_flags & NOCOMPONENT))
|
|
1459 count -= strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) + 2;
|
|
1460 lm = c1 -> c_offset + (count / 2);
|
|
1461 }
|
|
1462 else
|
|
1463 if (c1 -> c_offset)
|
|
1464 lm = c1 -> c_offset;
|
|
1465
|
|
1466 if (!(c1 -> c_flags & HDROUTPUT) && !(c1 -> c_flags & NOCOMPONENT)) {
|
|
1467 if (c1 -> c_flags & UPPERCASE) /* uppercase component also */
|
|
1468 for (cp = (c1 -> c_text ? c1 -> c_text : c1 -> c_name); *cp; cp++)
|
|
1469 if (islower (*cp & 0xff))
|
|
1470 *cp = toupper (*cp);
|
|
1471 putstr (c1 -> c_text ? c1 -> c_text : c1 -> c_name);
|
|
1472 if (flag != BODYCOMP) {
|
|
1473 putstr (": ");
|
|
1474 if (!(c1 -> c_flags & SPLIT))
|
|
1475 c1 -> c_flags |= HDROUTPUT;
|
|
1476
|
|
1477 cchdr++;
|
|
1478 if ((count = c1 -> c_cwidth -
|
|
1479 strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) - 2) > 0)
|
|
1480 while (count--)
|
|
1481 putstr (" ");
|
|
1482 }
|
|
1483 else
|
|
1484 c1 -> c_flags |= HDROUTPUT; /* for BODYCOMP */
|
|
1485 }
|
|
1486
|
|
1487 if (flag == TWOCOMP
|
|
1488 && !(c2 -> c_flags & HDROUTPUT)
|
|
1489 && !(c2 -> c_flags & NOCOMPONENT)) {
|
|
1490 if (c1 -> c_flags & UPPERCASE)
|
|
1491 for (cp = c2 -> c_name; *cp; cp++)
|
|
1492 if (islower (*cp & 0xff))
|
|
1493 *cp = toupper (*cp);
|
|
1494 putstr (c2 -> c_name);
|
|
1495 putstr (": ");
|
|
1496 if (!(c1 -> c_flags & SPLIT))
|
|
1497 c2 -> c_flags |= HDROUTPUT;
|
|
1498
|
|
1499 cchdr++;
|
|
1500 if ((count = c1 -> c_cwidth - strlen (c2 -> c_name) - 2) > 0)
|
|
1501 while (count--)
|
|
1502 putstr (" ");
|
|
1503 }
|
|
1504 if (c1 -> c_flags & UPPERCASE)
|
|
1505 for (cp = c2 -> c_text; *cp; cp++)
|
|
1506 if (islower (*cp & 0xff))
|
|
1507 *cp = toupper (*cp);
|
|
1508
|
|
1509 count = 0;
|
|
1510 if (cchdr)
|
|
1511 if (flag == TWOCOMP)
|
|
1512 count = (c1 -> c_cwidth >= 0) ? c1 -> c_cwidth
|
|
1513 : strlen (c2 -> c_name) + 2;
|
|
1514 else
|
|
1515 count = (c1 -> c_cwidth >= 0) ? c1 -> c_cwidth
|
|
1516 : strlen (c1->c_text ? c1->c_text : c1->c_name) + 2;
|
|
1517 count += c1 -> c_offset;
|
|
1518
|
|
1519 if (cp = oneline (c2 -> c_text, c1 -> c_flags))
|
|
1520 putstr(cp);
|
|
1521 if (term == '\n')
|
|
1522 putstr ("\n");
|
|
1523 while (cp = oneline (c2 -> c_text, c1 -> c_flags)) {
|
|
1524 lm = count;
|
|
1525 if (flag == BODYCOMP
|
|
1526 && !(c1 -> c_flags & NOCOMPONENT))
|
|
1527 putstr (c1 -> c_text ? c1 -> c_text : c1 -> c_name);
|
|
1528 if (*cp)
|
|
1529 putstr (cp);
|
|
1530 if (term == '\n')
|
|
1531 putstr ("\n");
|
|
1532 }
|
|
1533 if (term != -1 && flag == BODYCOMP
|
|
1534 && !(c1 -> c_flags & NOCOMPONENT))
|
|
1535 c1 -> c_flags &= ~HDROUTPUT;
|
|
1536 }
|
|
1537
|
|
1538 /* */
|
|
1539
|
|
1540 static char *oneline (stuff, flags)
|
|
1541 register char *stuff;
|
|
1542 long flags;
|
|
1543 {
|
|
1544 int spc;
|
|
1545 register char *cp,
|
|
1546 *ret;
|
|
1547
|
|
1548 if (onelp == NULL)
|
|
1549 onelp = stuff;
|
|
1550 if (*onelp == 0)
|
|
1551 return (onelp = NULL);
|
|
1552
|
|
1553 ret = onelp;
|
|
1554 term = -1;
|
|
1555 if (flags & COMPRESS) {
|
|
1556 for (spc = 1, cp = ret; *onelp; onelp++)
|
|
1557 if (isspace (*onelp)) {
|
|
1558 if (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT))) {
|
|
1559 term = '\n';
|
|
1560 *onelp++ = 0;
|
|
1561 break;
|
|
1562 }
|
|
1563 else
|
|
1564 if (!spc) {
|
|
1565 *cp++ = ' ';
|
|
1566 spc++;
|
|
1567 }
|
|
1568 }
|
|
1569 else {
|
|
1570 *cp++ = *onelp;
|
|
1571 spc = 0;
|
|
1572 }
|
|
1573
|
|
1574 *cp = 0;
|
|
1575 }
|
|
1576 else {
|
|
1577 while (*onelp && *onelp != '\n')
|
|
1578 onelp++;
|
|
1579 if (*onelp == '\n') {
|
|
1580 term = '\n';
|
|
1581 *onelp++ = 0;
|
|
1582 }
|
|
1583 if (flags & LEFTADJUST)
|
|
1584 while (*ret == ' ' || *ret == '\t')
|
|
1585 ret++;
|
|
1586 }
|
|
1587 if (*onelp == 0 && term == '\n' && (flags & NONEWLINE))
|
|
1588 term = 0;
|
|
1589
|
|
1590 return ret;
|
|
1591 }
|
|
1592
|
|
1593 /* */
|
|
1594
|
|
1595 #ifdef JAPAN
|
|
1596 static
|
|
1597 putstr(string)
|
|
1598 char *string;
|
|
1599 {
|
|
1600 mlcp = mlbuf;
|
|
1601 ml_cont_p = 0;
|
|
1602 putstr_sbr(string);
|
|
1603 *mlcp = 0;
|
|
1604 ml_fputs(mlbuf, stdout);
|
|
1605 }
|
|
1606
|
|
1607 static void
|
|
1608 putstr_sbr(string)
|
|
1609 char *string;
|
|
1610 {
|
|
1611 if (!column && lm > 0)
|
|
1612 while (lm > 0)
|
|
1613 if (lm >= 8) {
|
|
1614 putch('\t'); lm -= 8;
|
|
1615 } else {
|
|
1616 putch(' '); lm--;
|
|
1617 }
|
|
1618 lm = 0;
|
|
1619 while (*string)
|
|
1620 putch(*string++);
|
|
1621 }
|
|
1622
|
|
1623 /* */
|
|
1624
|
|
1625 static
|
|
1626 putch(ch)
|
|
1627 char ch;
|
|
1628 {
|
|
1629 char buf[BUFSIZ];
|
|
1630
|
|
1631 if (llim == 0) return;
|
|
1632
|
|
1633 switch (ch) {
|
|
1634 case '\n':
|
|
1635 if (llim > 0) llim--;
|
|
1636 ml_cont_p = 0;
|
|
1637 column = 0;
|
|
1638 row++;
|
|
1639 if (ontty != ISTTY || row != global.c_length)
|
|
1640 break;
|
|
1641 if (global.c_flags & BELL) *mlcp++ = '\007';
|
|
1642 *mlcp = 0;
|
|
1643 ml_fputs(mlbuf, stdout);
|
|
1644 mlcp = mlbuf;
|
|
1645 (void) fflush(stdout);
|
|
1646 buf[0] = 0;
|
|
1647 (void) read (fileno (stdout), buf, sizeof buf);
|
|
1648 if (index (buf, '\n')) {
|
|
1649 if (global.c_flags & CLEARSCR) clear_screen ();
|
|
1650 row = 0;
|
|
1651 } else {
|
|
1652 (void) putchar('\n');
|
|
1653 row = global.c_length / 3;
|
|
1654 }
|
|
1655 return;
|
|
1656 case '\t':
|
|
1657 ml_cont_p = 0;
|
|
1658 column |= 07;
|
|
1659 column++;
|
|
1660 break;
|
|
1661 case '\b':
|
|
1662 ml_cont_p = 0;
|
|
1663 column--;
|
|
1664 break;
|
|
1665 case '\r':
|
|
1666 ml_cont_p = 0;
|
|
1667 column = 0;
|
|
1668 break;
|
|
1669 default:
|
|
1670 if (column == 0 && forwflg && dashflg && ch == '-') {
|
|
1671 *mlcp++ = '-'; *mlcp++ = ' '; column += 2;
|
|
1672 }
|
|
1673 if (ml_ismlchar(ch)) {
|
|
1674 ml_cont_p = ml_cont_p ? 0 : 1;
|
|
1675 column++;
|
|
1676 } else if ((ch & 0xff) >= ' ') {
|
|
1677 ml_cont_p = 0;
|
|
1678 column++;
|
|
1679 }
|
|
1680 break;
|
|
1681 }
|
|
1682 if (((column >= wid-1) && ml_cont_p) || (column >= wid)) {
|
|
1683 putch ('\n');
|
|
1684 if (ovoff > 0) lm = ovoff;
|
|
1685 putstr_sbr(ovtxt ? ovtxt : "");
|
|
1686 putch(ch);
|
|
1687 return;
|
|
1688 }
|
|
1689 *mlcp++ = ch;
|
|
1690 if ((mlcp > mlbuf + sizeof(mlbuf) - 3) && ! ml_cont_p) {
|
|
1691 *mlcp = 0;
|
|
1692 ml_fputs(mlbuf, stdout);
|
|
1693 mlcp = mlbuf;
|
|
1694 }
|
|
1695 }
|
|
1696
|
|
1697 #else /* JAPAN */
|
|
1698
|
|
1699 static putstr (string)
|
|
1700 register char *string;
|
|
1701 {
|
|
1702 if (!column && lm > 0)
|
|
1703 while (lm > 0)
|
|
1704 if (lm >= 8) {
|
|
1705 putch ('\t');
|
|
1706 lm -= 8;
|
|
1707 }
|
|
1708 else {
|
|
1709 putch (' ');
|
|
1710 lm--;
|
|
1711 }
|
|
1712 lm = 0;
|
|
1713 while (*string)
|
|
1714 putch (*string++);
|
|
1715 }
|
|
1716
|
|
1717 /* */
|
|
1718
|
|
1719 static putch (ch)
|
|
1720 register char ch;
|
|
1721 {
|
|
1722 char buf[BUFSIZ];
|
|
1723
|
|
1724 if (llim == 0)
|
|
1725 return;
|
|
1726
|
|
1727 switch (ch) {
|
|
1728 case '\n':
|
|
1729 if (llim > 0)
|
|
1730 llim--;
|
|
1731 column = 0;
|
|
1732 row++;
|
|
1733 if (ontty != ISTTY || row != global.c_length)
|
|
1734 break;
|
|
1735 if (global.c_flags & BELL)
|
|
1736 (void) putchar ('\007');
|
|
1737 (void) fflush (stdout);
|
|
1738 buf[0] = 0;
|
|
1739 (void) read (fileno (stdout), buf, sizeof buf);
|
|
1740 if (index (buf, '\n')) {
|
|
1741 if (global.c_flags & CLEARSCR)
|
|
1742 clear_screen ();
|
|
1743 row = 0;
|
|
1744 }
|
|
1745 else {
|
|
1746 (void) putchar ('\n');
|
|
1747 row = global.c_length / 3;
|
|
1748 }
|
|
1749 return;
|
|
1750
|
|
1751 case '\t':
|
|
1752 column |= 07;
|
|
1753 column++;
|
|
1754 break;
|
|
1755
|
|
1756 case '\b':
|
|
1757 column--;
|
|
1758 break;
|
|
1759
|
|
1760 case '\r':
|
|
1761 column = 0;
|
|
1762 break;
|
|
1763
|
|
1764 default:
|
|
1765 if (column == 0 && forwflg && dashflg && ch == '-')
|
|
1766 (void) putchar ('-'), putchar (' ');
|
|
1767 if (ch >= ' ')
|
|
1768 column++;
|
|
1769 break;
|
|
1770 }
|
|
1771
|
|
1772 if (column >= wid) {
|
|
1773 putch ('\n');
|
|
1774 if (ovoff > 0)
|
|
1775 lm = ovoff;
|
|
1776 putstr (ovtxt ? ovtxt : "");
|
|
1777 putch (ch);
|
|
1778 return;
|
|
1779 }
|
|
1780
|
|
1781 (void) putchar (ch);
|
|
1782 }
|
|
1783 #endif /* JAPAN */
|
|
1784
|
|
1785 /* */
|
|
1786
|
|
1787 /* ARGSUSED */
|
|
1788
|
|
1789 static TYPESIG intrser (i)
|
|
1790 int i;
|
|
1791 {
|
|
1792 #ifndef BSD42
|
|
1793 (void) signal (SIGINT, intrser);
|
|
1794 #endif /* BSD42 */
|
|
1795
|
|
1796 discard (stdout);
|
|
1797 (void) putchar ('\n');
|
|
1798
|
|
1799 longjmp (env, DONE);
|
|
1800 }
|
|
1801
|
|
1802
|
|
1803 /* ARGSUSED */
|
|
1804
|
|
1805 static TYPESIG pipeser (i)
|
|
1806 int i;
|
|
1807 {
|
|
1808 #ifndef BSD42
|
|
1809 (void) signal (SIGPIPE, pipeser);
|
|
1810 #endif /* BSD42 */
|
|
1811
|
|
1812 done (NOTOK);
|
|
1813 }
|
|
1814
|
|
1815
|
|
1816 /* ARGSUSED */
|
|
1817
|
|
1818 static TYPESIG quitser (i)
|
|
1819 int i;
|
|
1820 {
|
|
1821 #ifndef BSD42
|
|
1822 (void) signal (SIGQUIT, quitser);
|
|
1823 #endif /* BSD42 */
|
|
1824
|
|
1825 (void) putchar ('\n');
|
|
1826 (void) fflush (stdout);
|
|
1827
|
|
1828 done (NOTOK);
|
|
1829 }
|
|
1830
|
|
1831 /* */
|
|
1832
|
|
1833 static face_format (c1)
|
|
1834 register struct mcomp *c1;
|
|
1835 {
|
|
1836 register char *cp;
|
|
1837 register struct mailname *mp;
|
|
1838
|
|
1839 if ((cp = c1 -> c_text) == NULL)
|
|
1840 return;
|
|
1841
|
|
1842 if (cp = getname (cp)) {
|
|
1843 if (mp = getm (cp, NULLCP, 0, AD_NAME, NULLCP)) {
|
|
1844 char *h, *o;
|
|
1845 if ((h = mp -> m_host) == NULL)
|
|
1846 h = LocalName ();
|
|
1847 if (o = OfficialName (h))
|
|
1848 h = o;
|
|
1849 c1 -> c_face = concat ("address ", h, " ", mp -> m_mbox, NULLCP);
|
|
1850 }
|
|
1851
|
|
1852 while (cp = getname (cp))
|
|
1853 continue;
|
|
1854 }
|
|
1855 }
|
|
1856
|
|
1857 /* */
|
|
1858
|
|
1859 #if defined(BSD42) || defined(SOCKETS)
|
|
1860
|
|
1861 /* faceproc is two elements defining the image agent's location:
|
|
1862 Internet host
|
|
1863 UDP port
|
|
1864 */
|
|
1865
|
|
1866 #include <sys/socket.h>
|
|
1867 #include <netinet/in.h>
|
|
1868 #include <netdb.h>
|
|
1869 #ifndef hpux
|
|
1870 #include <arpa/inet.h>
|
|
1871 #endif
|
|
1872
|
|
1873 struct hostent *gethostbystring ();
|
|
1874
|
|
1875
|
|
1876 static int doface (c1)
|
|
1877 register struct mcomp *c1;
|
|
1878 {
|
|
1879 int i,
|
|
1880 result,
|
|
1881 sd;
|
|
1882 struct sockaddr_in in_socket;
|
|
1883 register struct sockaddr_in *isock = &in_socket;
|
|
1884 static int inited = OK;
|
|
1885 static int addrlen;
|
|
1886 static struct in_addr addr;
|
|
1887 static u_short portno;
|
|
1888
|
|
1889 if (inited == OK) {
|
|
1890 #ifndef __alpha
|
|
1891 u_long iaddr;
|
|
1892 #else
|
|
1893 u_int iaddr;
|
|
1894 #endif
|
|
1895 char *cp;
|
|
1896 char **ap = brkstring (cp = getcpy (faceproc), " ", "\n");
|
|
1897 struct hostent *hp;
|
|
1898
|
|
1899 if (ap[0] == NULL || ap[1] == NULL) {
|
|
1900 bad_faceproc: ;
|
|
1901 free (cp);
|
|
1902 return (inited = NOTOK);
|
|
1903 }
|
|
1904
|
|
1905 if (!(hp = gethostbystring (ap[0])))
|
|
1906 goto bad_faceproc;
|
|
1907 bcopy (hp -> h_addr, (char *) &addr, addrlen = hp -> h_length);
|
|
1908
|
|
1909 portno = htons ((u_short) atoi (ap[1]));
|
|
1910 free (cp);
|
|
1911
|
|
1912 inited = DONE;
|
|
1913 }
|
|
1914 if (inited == NOTOK)
|
|
1915 return NOTOK;
|
|
1916
|
|
1917 isock -> sin_family = AF_INET;
|
|
1918 isock -> sin_port = portno;
|
|
1919 bcopy ((char *) &addr, (char *) &isock -> sin_addr, addrlen);
|
|
1920
|
|
1921 if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == NOTOK)
|
|
1922 return NOTOK;
|
|
1923
|
|
1924 result = sendto (sd, c1 -> c_text, strlen (c1 -> c_text), 0,
|
|
1925 (struct sockaddr *) isock, sizeof *isock);
|
|
1926
|
|
1927 (void) close (sd);
|
|
1928
|
|
1929 return (result != NOTOK ? OK : NOTOK);
|
|
1930 }
|
|
1931
|
|
1932 #else /* not BSD42 and not SOCKETS */
|
|
1933
|
|
1934 static int doface (c1)
|
|
1935 register struct mcomp *c1;
|
|
1936 {
|
|
1937 register int i,
|
|
1938 len,
|
|
1939 vecp;
|
|
1940 int child_id,
|
|
1941 result,
|
|
1942 pdi[2],
|
|
1943 pdo[2];
|
|
1944 register char *bp,
|
|
1945 *cp;
|
|
1946 char buffer[BUFSIZ],
|
|
1947 *vec[10];
|
|
1948
|
|
1949 if (pipe (pdi) == NOTOK)
|
|
1950 return NOTOK;
|
|
1951 if (pipe (pdo) == NOTOK) {
|
|
1952 (void) close (pdi[0]);
|
|
1953 (void) close (pdi[1]);
|
|
1954 return NOTOK;
|
|
1955 }
|
|
1956
|
|
1957 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
|
|
1958 sleep (5);
|
|
1959
|
|
1960 switch (child_id) {
|
|
1961 case NOTOK:
|
|
1962 return NOTOK;
|
|
1963
|
|
1964 case OK:
|
|
1965 (void) signal (SIGINT, SIG_IGN);
|
|
1966 (void) signal (SIGQUIT, SIG_IGN);
|
|
1967 if (pdi[0] != fileno (stdin)) {
|
|
1968 (void) dup2 (pdi[0], fileno (stdin));
|
|
1969 (void) close (pdi[0]);
|
|
1970 }
|
|
1971 (void) close (pdi[1]);
|
|
1972 (void) close (pdo[0]);
|
|
1973 if (pdo[1] != fileno (stdout)) {
|
|
1974 (void) dup2 (pdo[1], fileno (stdout));
|
|
1975 (void) close (pdo[1]);
|
|
1976 }
|
|
1977 vecp = 0;
|
|
1978 vec[vecp++] = r1bindex (faceproc, '/');
|
|
1979 vec[vecp++] = "-e";
|
|
1980 if (sleepsw != NOTOK) {
|
|
1981 vec[vecp++] = "-s";
|
|
1982 (void) sprintf (buffer, "%d", sleepsw);
|
|
1983 vec[vecp++] = buffer;
|
|
1984 }
|
|
1985 vec[vecp] = NULL;
|
|
1986 execvp (faceproc, vec);
|
|
1987 fprintf (stderr, "unable to exec ");
|
|
1988 perror (faceproc);
|
|
1989 _exit (-1); /* NOTREACHED */
|
|
1990
|
|
1991 default:
|
|
1992 (void) close (pdi[0]);
|
|
1993 i = strlen (c1 -> c_text);
|
|
1994 if (write (pdi[1], c1 -> c_text, i) != i)
|
|
1995 adios ("pipe", "error writing to");
|
|
1996 free (c1 -> c_text), c1 -> c_text = NULL;
|
|
1997 (void) close (pdi[1]);
|
|
1998
|
|
1999 (void) close (pdo[1]);
|
|
2000 cp = NULL, len = 0;
|
|
2001 result = DONE;
|
|
2002 while ((i = read (pdo[0], buffer, strlen (buffer))) > 0) {
|
|
2003 if (cp) {
|
|
2004 register int j;
|
|
2005 register char *dp;
|
|
2006 if ((dp = realloc (cp, (unsigned) (j = len + i))) == NULL)
|
|
2007 adios (NULLCP, "unable to allocate face storage");
|
|
2008 bcopy (buffer, dp + len, i);
|
|
2009 cp = dp, len = j;
|
|
2010 }
|
|
2011 else {
|
|
2012 if ((cp = malloc ((unsigned) i)) == NULL)
|
|
2013 adios (NULLCP, "unable to allocate face storage");
|
|
2014 bcopy (buffer, cp, i);
|
|
2015 len = i;
|
|
2016 }
|
|
2017 if (result == DONE)
|
|
2018 for (bp = buffer + i - 1; bp >= buffer; bp--)
|
|
2019 if (!isascii (*bp) || iscntrl (*bp)) {
|
|
2020 result = OK;
|
|
2021 break;
|
|
2022 }
|
|
2023 }
|
|
2024 (void) close (pdo[0]);
|
|
2025
|
|
2026 /* no waiting for child... */
|
|
2027
|
|
2028 if (result == OK) { /* binary */
|
|
2029 if (write (1, cp, len) != len)
|
|
2030 adios ("writing", "error");
|
|
2031 free (cp);
|
|
2032 }
|
|
2033 else /* empty */
|
|
2034 if ((c1 -> c_text = cp) == NULL)
|
|
2035 result = OK;
|
|
2036 break;
|
|
2037 }
|
|
2038
|
|
2039 return result;
|
|
2040 }
|
|
2041 #endif /* not BSD42 and not SOCKETS */
|
|
2042
|
|
2043 /* */
|
|
2044
|
|
2045 #undef adios
|
|
2046 #undef done
|
|
2047
|
|
2048 int mhlsbr (argc, argv, action)
|
|
2049 int argc;
|
|
2050 char **argv;
|
|
2051 FP (*action) ();
|
|
2052 {
|
|
2053 TYPESIG (*istat) (), (*pstat) (), (*qstat) ();
|
|
2054 char *cp;
|
|
2055 struct mcomp *c1;
|
|
2056
|
|
2057 switch (setjmp (mhlenv)) {
|
|
2058 case OK:
|
|
2059 cp = invo_name;
|
|
2060 sleepsw = 0; /* XXX */
|
|
2061 bellflg = clearflg = forwflg = forwall = exitstat = 0;
|
|
2062 digest = NULL;
|
|
2063 ontty = NOTTY;
|
|
2064 mhl_action = action;
|
|
2065 if ((istat = signal (SIGINT, SIG_IGN)) != SIG_DFL)
|
|
2066 (void) signal (SIGINT, istat);
|
|
2067 if ((qstat = signal (SIGQUIT, SIG_IGN)) != SIG_DFL)
|
|
2068 (void) signal (SIGQUIT, qstat);
|
|
2069 pstat = signal (SIGPIPE, pipeser);
|
|
2070 (void) mhl (argc, argv); /* fall */
|
|
2071
|
|
2072 default:
|
|
2073 (void) signal (SIGINT, istat);
|
|
2074 (void) signal (SIGQUIT, qstat);
|
|
2075 (void) signal (SIGPIPE, SIG_IGN);/* XXX */
|
|
2076 if (ontty == PITTY)
|
|
2077 m_pclose ();
|
|
2078 (void) signal (SIGPIPE, pstat);
|
|
2079 invo_name = cp;
|
|
2080 if (holder.c_text) {
|
|
2081 free (holder.c_text);
|
|
2082 holder.c_text = NULL;
|
|
2083 }
|
|
2084 free_queue (&msghd, &msgtl);
|
|
2085 for (c1 = fmthd; c1; c1 = c1 -> c_next)
|
|
2086 c1 -> c_flags &= ~HDROUTPUT;
|
|
2087 return exitstat;
|
|
2088 }
|
|
2089 }
|
|
2090
|
|
2091 /* */
|
|
2092
|
|
2093 /* VARARGS2 */
|
|
2094
|
|
2095 static void mhladios (what, fmt, a, b, c, d, e, f)
|
|
2096 char *what,
|
|
2097 *fmt,
|
|
2098 *a,
|
|
2099 *b,
|
|
2100 *c,
|
|
2101 *d,
|
|
2102 *e,
|
|
2103 *f;
|
|
2104 {
|
|
2105 advise (what, fmt, a, b, c, d, e, f);
|
|
2106 mhldone (1);
|
|
2107 }
|
|
2108
|
|
2109
|
|
2110 static void mhldone (status)
|
|
2111 int status;
|
|
2112 {
|
|
2113 exitstat = status;
|
|
2114 if (mhl_action)
|
|
2115 longjmp (mhlenv, DONE);
|
|
2116 else
|
|
2117 done (exitstat);
|
|
2118 }
|
|
2119
|
|
2120 /* */
|
|
2121
|
|
2122 static int m_pid = NOTOK;
|
|
2123 static int sd = NOTOK;
|
|
2124
|
|
2125
|
|
2126 static m_popen (name)
|
|
2127 char *name;
|
|
2128 {
|
|
2129 int pd[2];
|
|
2130
|
|
2131 if (mhl_action && (sd = dup (fileno (stdout))) == NOTOK)
|
|
2132 adios ("standard output", "unable to dup()");
|
|
2133
|
|
2134 if (pipe (pd) == NOTOK)
|
|
2135 adios ("pipe", "unable to");
|
|
2136
|
|
2137 switch (m_pid = vfork ()) {
|
|
2138 case NOTOK:
|
|
2139 adios ("fork", "unable to");
|
|
2140
|
|
2141 case OK:
|
|
2142 (void) signal (SIGINT, SIG_DFL);
|
|
2143 (void) signal (SIGQUIT, SIG_DFL);
|
|
2144
|
|
2145 (void) close (pd[1]);
|
|
2146 if (pd[0] != fileno (stdin)) {
|
|
2147 (void) dup2 (pd[0], fileno (stdin));
|
|
2148 (void) close (pd[0]);
|
|
2149 }
|
|
2150 execlp (name, r1bindex (name, '/'), NULLCP);
|
|
2151 fprintf (stderr, "unable to exec ");
|
|
2152 perror (name);
|
|
2153 _exit (-1);
|
|
2154
|
|
2155 default:
|
|
2156 (void) close (pd[0]);
|
|
2157 if (pd[1] != fileno (stdout)) {
|
|
2158 (void) dup2 (pd[1], fileno (stdout));
|
|
2159 (void) close (pd[1]);
|
|
2160 }
|
|
2161 }
|
|
2162 }
|
|
2163
|
|
2164
|
|
2165 m_pclose () {
|
|
2166 if (m_pid == NOTOK)
|
|
2167 return;
|
|
2168
|
|
2169 if (sd != NOTOK) {
|
|
2170 (void) fflush (stdout);
|
|
2171 if (dup2 (sd, fileno (stdout)) == NOTOK)
|
|
2172 adios ("standard output", "unable to dup2()");
|
|
2173
|
|
2174 clearerr (stdout);
|
|
2175 (void) close (sd);
|
|
2176 sd = NOTOK;
|
|
2177 }
|
|
2178 else
|
|
2179 (void) fclose (stdout);
|
|
2180
|
|
2181 (void) pidwait (m_pid, OK);
|
|
2182 m_pid = NOTOK;
|
|
2183 }
|