0
|
1 /* mshcmds.c - command handlers in msh */
|
|
2 #ifndef lint
|
12
|
3 static char ident[] = "@(#)$Id: mshcmds.c,v 1.2 2006/12/05 18:18:13 kono Exp $";
|
0
|
4 #endif /* lint */
|
|
5
|
|
6 #include "../h/mh.h"
|
|
7 #include "../h/dropsbr.h"
|
|
8 #include "../h/formatsbr.h"
|
|
9 #include "../h/scansbr.h"
|
|
10 #include "../zotnet/tws.h"
|
|
11 #ifdef _AIX /* AIX 1.2.1 <stdio.h> declares getws() */
|
|
12 #define getws _getws
|
|
13 #endif
|
|
14 #include <stdio.h>
|
12
|
15 #include <unistd.h>
|
0
|
16 #ifdef _AIX
|
|
17 #undef getws
|
|
18 #endif
|
|
19 #include "../zotnet/mts.h"
|
|
20 #include <ctype.h>
|
|
21 #include <errno.h>
|
|
22 #include <setjmp.h>
|
|
23 #include <signal.h>
|
|
24 #include <sys/types.h>
|
|
25 #include <sys/stat.h>
|
|
26 #include "../h/mshsbr.h"
|
|
27 #ifdef MIME
|
|
28 #include "../h/mhn.h"
|
|
29 #endif /* MIME */
|
|
30
|
|
31 /* */
|
|
32
|
|
33
|
|
34 /* BURST */
|
|
35 static char delim3[] = "-------";/* from burst.c */
|
|
36
|
|
37
|
|
38 /* SHOW */
|
|
39 static int mhlnum;
|
|
40 static FILE *mhlfp;
|
|
41
|
|
42 void clear_screen ();
|
|
43 static int eom_action ();
|
|
44 static FP mhl_action ();
|
|
45 #ifdef MIME
|
|
46 static int nontext();
|
|
47 #endif
|
|
48
|
|
49
|
|
50 static burst(), forw(), rmm(), show(), ask(), copy_message(), copy_digest();
|
|
51 static int process();
|
|
52 /* SORTM */
|
|
53 static int msgsort (), subsort();
|
|
54 static int getws ();
|
|
55 static char *sosmash ();
|
|
56
|
|
57 #if defined(NNTP) && defined(MPOP)
|
|
58 #undef MPOP
|
|
59 #endif
|
|
60 #ifdef MPOP
|
|
61 #ifdef BPOP
|
|
62 extern int pmsh;
|
|
63 extern char response[];
|
|
64 #endif
|
|
65 #endif /* MPOP */
|
|
66
|
|
67 /* */
|
|
68
|
|
69 forkcmd (args, pgm)
|
|
70 char **args,
|
|
71 *pgm;
|
|
72 {
|
|
73 int child_id;
|
|
74 char *vec[MAXARGS];
|
|
75
|
|
76 vec[0] = r1bindex (pgm, '/');
|
|
77 (void) copyip (args, vec + 1);
|
|
78
|
|
79 if (fmsh) {
|
|
80 (void) m_delete (pfolder);
|
|
81 m_replace (pfolder, fmsh);
|
|
82 m_sync (mp);
|
|
83 m_update ();
|
|
84 }
|
|
85 (void) fflush (stdout);
|
|
86 switch (child_id = fork ()) {
|
|
87 case NOTOK:
|
|
88 advise ("fork", "unable to");
|
|
89 return;
|
|
90
|
|
91 case OK:
|
|
92 closefds (3);
|
|
93 (void) signal (SIGINT, istat);
|
|
94 (void) signal (SIGQUIT, qstat);
|
|
95
|
|
96 execvp (pgm, vec);
|
|
97 fprintf (stderr, "unable to exec ");
|
|
98 perror (cmd_name);
|
|
99 _exit (1);
|
|
100
|
|
101 default:
|
|
102 (void) pidXwait (child_id, NULLCP);
|
|
103 break;
|
|
104 }
|
|
105 if (fmsh) { /* assume the worst case */
|
|
106 mp -> msgflags |= MODIFIED;
|
|
107 modified++;
|
|
108 }
|
|
109 }
|
|
110
|
|
111 /* */
|
|
112
|
|
113 static struct swit distswit[] = {
|
|
114 #define DIANSW 0
|
|
115 "annotate", 0,
|
|
116 #define DINANSW 1
|
|
117 "noannotate", 0,
|
|
118 #define DIDFSW 2
|
|
119 "draftfolder +folder", 0,
|
|
120 #define DIDMSW 3
|
|
121 "draftmessage msg", 0,
|
|
122 #define DINDFSW 4
|
|
123 "nodraftfolder", 0,
|
|
124 #define DIEDTSW 5
|
|
125 "editor editor", 0,
|
|
126 #define DINEDSW 6
|
|
127 "noedit", 0,
|
|
128 #define DIFRMSW 7
|
|
129 "form formfile", 0,
|
|
130 #define DIINSW 8
|
|
131 "inplace", 0,
|
|
132 #define DININSW 9
|
|
133 "noinplace", 0,
|
|
134 #define DIWHTSW 10
|
|
135 "whatnowproc program", 0,
|
|
136 #define DINWTSW 11
|
|
137 "nowhatnowproc", 0,
|
|
138 #define DIHELP 12
|
|
139 "help", 4,
|
|
140
|
|
141 NULL, 0
|
|
142 };
|
|
143
|
|
144 /* */
|
|
145
|
|
146 distcmd (args)
|
|
147 char **args;
|
|
148 {
|
|
149 int vecp = 1;
|
|
150 char *cp,
|
|
151 *msg = NULL,
|
|
152 buf[BUFSIZ],
|
|
153 *vec[MAXARGS];
|
|
154
|
|
155 if (fmsh) {
|
|
156 forkcmd (args, cmd_name);
|
|
157 return;
|
|
158 }
|
|
159
|
|
160 while (cp = *args++) {
|
|
161 if (*cp == '-')
|
|
162 switch (smatch (++cp, distswit)) {
|
|
163 case AMBIGSW:
|
|
164 ambigsw (cp, distswit);
|
|
165 return;
|
|
166 case UNKWNSW:
|
|
167 fprintf (stderr, "-%s unknown\n", cp);
|
|
168 return;
|
|
169 case DIHELP:
|
|
170 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
|
|
171 help (buf, distswit);
|
|
172 return;
|
|
173
|
|
174 case DIANSW: /* not implemented */
|
|
175 case DINANSW:
|
|
176 case DIINSW:
|
|
177 case DININSW:
|
|
178 continue;
|
|
179
|
|
180 case DINDFSW:
|
|
181 case DINEDSW:
|
|
182 case DINWTSW:
|
|
183 vec[vecp++] = --cp;
|
|
184 continue;
|
|
185
|
|
186 case DIEDTSW:
|
|
187 case DIFRMSW:
|
|
188 case DIDFSW:
|
|
189 case DIDMSW:
|
|
190 case DIWHTSW:
|
|
191 vec[vecp++] = --cp;
|
|
192 if (!(cp = *args++) || *cp == '-') {
|
|
193 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
194 return;
|
|
195 }
|
|
196 vec[vecp++] = cp;
|
|
197 continue;
|
|
198 }
|
|
199 if (*cp == '+' || *cp == '@') {
|
|
200 advise (NULLCP, "sorry, no folders allowed!");
|
|
201 return;
|
|
202 }
|
|
203 else
|
|
204 if (msg) {
|
|
205 advise (NULLCP, "only one message at a time!");
|
|
206 return;
|
|
207 }
|
|
208 else
|
|
209 msg = cp;
|
|
210 }
|
|
211
|
|
212 vec[0] = cmd_name;
|
|
213 vec[vecp++] = "-file";
|
|
214 vec[vecp] = NULL;
|
|
215 if (!msg)
|
|
216 msg = "cur";
|
|
217 if (!m_convert (mp, msg))
|
|
218 return;
|
|
219 m_setseq (mp);
|
|
220
|
|
221 if (mp -> numsel > 1) {
|
|
222 advise (NULLCP, "only one message at a time!");
|
|
223 return;
|
|
224 }
|
|
225 (void) process (mp -> hghsel, cmd_name, vecp, vec);
|
|
226 m_setcur (mp, mp -> hghsel);
|
|
227 }
|
|
228
|
|
229 /* */
|
|
230
|
|
231 static struct swit explswit[] = {
|
|
232 #define EXINSW 0
|
|
233 "inplace", 0,
|
|
234 #define EXNINSW 1
|
|
235 "noinplace", 0,
|
|
236 #define EXQISW 2
|
|
237 "quiet", 0,
|
|
238 #define EXNQISW 3
|
|
239 "noquiet", 0,
|
|
240 #define EXVBSW 4
|
|
241 "verbose", 0,
|
|
242 #define EXNVBSW 5
|
|
243 "noverbose", 0,
|
|
244 #define EXHELP 6
|
|
245 "help", 4,
|
|
246
|
|
247 NULL, 0
|
|
248 };
|
|
249
|
|
250 /* */
|
|
251
|
|
252 explcmd (args)
|
|
253 char **args;
|
|
254 {
|
|
255 int inplace = 0,
|
|
256 quietsw = 0,
|
|
257 verbosw = 0,
|
|
258 msgp = 0,
|
|
259 hi,
|
|
260 msgnum;
|
|
261 char *cp,
|
|
262 buf[BUFSIZ],
|
|
263 *msgs[MAXARGS];
|
|
264 struct Msg *smsgs;
|
|
265
|
|
266 if (fmsh) {
|
|
267 forkcmd (args, cmd_name);
|
|
268 return;
|
|
269 }
|
|
270
|
|
271 while (cp = *args++) {
|
|
272 if (*cp == '-')
|
|
273 switch (smatch (++cp, explswit)) {
|
|
274 case AMBIGSW:
|
|
275 ambigsw (cp, explswit);
|
|
276 return;
|
|
277 case UNKWNSW:
|
|
278 fprintf (stderr, "-%s unknown\n", cp);
|
|
279 return;
|
|
280 case EXHELP:
|
|
281 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
|
|
282 help (buf, explswit);
|
|
283 return;
|
|
284
|
|
285 case EXINSW:
|
|
286 inplace++;
|
|
287 continue;
|
|
288 case EXNINSW:
|
|
289 inplace = 0;
|
|
290 continue;
|
|
291 case EXQISW:
|
|
292 quietsw++;
|
|
293 continue;
|
|
294 case EXNQISW:
|
|
295 quietsw = 0;
|
|
296 continue;
|
|
297 case EXVBSW:
|
|
298 verbosw++;
|
|
299 continue;
|
|
300 case EXNVBSW:
|
|
301 verbosw = 0;
|
|
302 continue;
|
|
303 }
|
|
304 if (*cp == '+' || *cp == '@') {
|
|
305 advise (NULLCP, "sorry, no folders allowed!");
|
|
306 return;
|
|
307 }
|
|
308 else
|
|
309 msgs[msgp++] = cp;
|
|
310 }
|
|
311
|
|
312 if (!msgp)
|
|
313 msgs[msgp++] = "cur";
|
|
314 for (msgnum = 0; msgnum < msgp; msgnum++)
|
|
315 if (!m_convert (mp, msgs[msgnum]))
|
|
316 return;
|
|
317 m_setseq (mp);
|
|
318
|
|
319 smsgs = (struct Msg *)
|
|
320 calloc ((unsigned) (MAXFOLDER + 2), sizeof *smsgs);
|
|
321 if (smsgs == NULL)
|
|
322 adios (NULLCP, "unable to allocate folder storage");
|
|
323
|
|
324 hi = mp -> hghmsg + 1;
|
|
325 interrupted = 0;
|
|
326 for (msgnum = mp -> lowsel;
|
|
327 msgnum <= mp -> hghsel && !interrupted;
|
|
328 msgnum++)
|
|
329 if (mp -> msgstats[msgnum] & SELECTED)
|
|
330 if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK)
|
|
331 break;
|
|
332
|
|
333 free ((char *) smsgs);
|
|
334
|
|
335 if (inplace)
|
|
336 m_setcur (mp, mp -> lowsel);
|
|
337 else
|
|
338 if (hi <= mp -> hghmsg)
|
|
339 m_setcur (mp, hi);
|
|
340
|
|
341 mp -> msgflags |= MODIFIED;
|
|
342 modified++;
|
|
343 }
|
|
344
|
|
345 /* */
|
|
346
|
|
347 static burst (smsgs, msgnum, inplace, quietsw, verbosw)
|
|
348 struct Msg *smsgs;
|
|
349 int msgnum,
|
|
350 inplace,
|
|
351 quietsw,
|
|
352 verbosw;
|
|
353 {
|
|
354 int i,
|
|
355 j,
|
|
356 ld3,
|
|
357 wasdlm,
|
|
358 msgp;
|
|
359 long pos;
|
|
360 char c,
|
|
361 cc,
|
|
362 buffer[BUFSIZ];
|
|
363 register FILE *zp;
|
|
364
|
|
365 ld3 = strlen (delim3);
|
|
366
|
|
367 if (Msgs[msgnum].m_scanl) {
|
|
368 free (Msgs[msgnum].m_scanl);
|
|
369 Msgs[msgnum].m_scanl = NULL;
|
|
370 }
|
|
371
|
|
372 pos = ftell (zp = msh_ready (msgnum, 1));
|
|
373 for (msgp = 0; msgp <= MAXFOLDER;) {
|
|
374 while (fgets (buffer, sizeof buffer, zp) != NULL
|
|
375 && buffer[0] == '\n'
|
|
376 && pos < Msgs[msgnum].m_stop)
|
|
377 pos += (long) strlen (buffer);
|
|
378 if (feof (zp) || pos >= Msgs[msgnum].m_stop)
|
|
379 break;
|
|
380 (void) fseek (zp, pos, 0);
|
|
381 smsgs[msgp].m_start = pos;
|
|
382
|
|
383 for (c = 0;
|
|
384 pos < Msgs[msgnum].m_stop
|
|
385 && fgets (buffer, sizeof buffer, zp) != NULL;
|
|
386 c = buffer[0])
|
|
387 if (strncmp (buffer, delim3, ld3) == 0
|
|
388 && (msgp == 1 || c == '\n')
|
|
389 && peekc (zp) == '\n')
|
|
390 break;
|
|
391 else
|
|
392 pos += (long) strlen (buffer);
|
|
393
|
|
394 wasdlm = strncmp (buffer, delim3, ld3) == 0;
|
|
395 if (smsgs[msgp].m_start != pos)
|
|
396 smsgs[msgp++].m_stop = (c == '\n' && wasdlm) ? pos - 1 : pos;
|
|
397 if (feof (zp) || pos >= Msgs[msgnum].m_stop) {
|
|
398 if (wasdlm)
|
|
399 smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1);
|
|
400 break;
|
|
401 }
|
|
402 pos += (long) strlen (buffer);
|
|
403 }
|
|
404
|
|
405 switch (msgp--) { /* toss "End of XXX Digest" */
|
|
406 case 0:
|
|
407 adios (NULLCP, "burst() botch -- you lose big");
|
|
408
|
|
409 case 1:
|
|
410 if (!quietsw)
|
|
411 printf ("message %d not in digest format\n", msgnum);
|
|
412 return OK;
|
|
413
|
|
414 default:
|
|
415 if (verbosw)
|
|
416 printf ("%d message%s exploded from digest %d\n",
|
|
417 msgp, msgp != 1 ? "s" : "", msgnum);
|
|
418 break;
|
|
419 }
|
|
420
|
|
421 if ((i = msgp + mp -> hghmsg) > MAXFOLDER) {
|
|
422 advise (NULLCP, "more than %d messages", MAXFOLDER);
|
|
423 return NOTOK;
|
|
424 }
|
|
425 if ((mp = m_remsg (mp, 0, i)) == NULL)
|
|
426 adios (NULLCP, "unable to allocate folder storage");
|
|
427
|
|
428 j = mp -> hghmsg;
|
|
429 mp -> hghmsg += msgp;
|
|
430 mp -> nummsg += msgp;
|
|
431 if (mp -> hghsel > msgnum)
|
|
432 mp -> hghsel += msgp;
|
|
433
|
|
434 if (inplace)
|
|
435 for (i = mp -> hghmsg; j > msgnum; i--, j--) {
|
|
436 if (verbosw)
|
|
437 printf ("message %d becomes message %d\n", j, i);
|
|
438
|
|
439 Msgs[i].m_bboard_id = Msgs[j].m_bboard_id;
|
|
440 Msgs[i].m_top = Msgs[j].m_top;
|
|
441 Msgs[i].m_start = Msgs[j].m_start;
|
|
442 Msgs[i].m_stop = Msgs[j].m_stop;
|
|
443 Msgs[i].m_scanl = NULL;
|
|
444 if (Msgs[j].m_scanl) {
|
|
445 free (Msgs[j].m_scanl);
|
|
446 Msgs[j].m_scanl = NULL;
|
|
447 }
|
|
448 mp -> msgstats[i] = mp -> msgstats[j];
|
|
449 }
|
|
450
|
|
451 if (Msgs[msgnum].m_bboard_id == 0)
|
|
452 (void) readid (msgnum);
|
|
453
|
|
454 mp -> msgstats[msgnum] &= ~SELECTED;
|
|
455 i = inplace ? msgnum + msgp : mp -> hghmsg;
|
|
456 for (j = msgp; j >= (inplace ? 0 : 1); i--, j--) {
|
|
457 if (verbosw && i != msgnum)
|
|
458 printf ("message %d of digest %d becomes message %d\n",
|
|
459 j, msgnum, i);
|
|
460
|
|
461 Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id;
|
|
462 Msgs[i].m_top = Msgs[j].m_top;
|
|
463 Msgs[i].m_start = smsgs[j].m_start;
|
|
464 Msgs[i].m_stop = smsgs[j].m_stop;
|
|
465 Msgs[i].m_scanl = NULL;
|
|
466 mp -> msgstats[i] = mp -> msgstats[msgnum];
|
|
467 }
|
|
468
|
|
469 return OK;
|
|
470 }
|
|
471
|
|
472 /* */
|
|
473
|
|
474 static struct swit fileswit[] = {
|
|
475 #define FIDRFT 0
|
|
476 "draft", 0,
|
|
477 #define FILINK 1
|
|
478 "link", 0,
|
|
479 #define FINLINK 2
|
|
480 "nolink", 0,
|
|
481 #define FIPRES 3
|
|
482 "preserve", 0,
|
|
483 #define FINPRES 4
|
|
484 "nopreserve", 0,
|
|
485 #define FISRC 5
|
|
486 "src +folder", 0,
|
|
487 #define FIFILE 6
|
|
488 "file file", 0,
|
|
489 #define FIPROC 7
|
|
490 "rmmproc program", 0,
|
|
491 #define FINPRC 8
|
|
492 "normmproc", 0,
|
|
493 #define FIHELP 9
|
|
494 "help", 4,
|
|
495
|
|
496 NULL, 0
|
|
497 };
|
|
498
|
|
499 /* */
|
|
500
|
|
501 filecmd (args)
|
|
502 char **args;
|
|
503 {
|
|
504 int linksw = 0,
|
|
505 msgp = 0,
|
|
506 vecp = 1,
|
|
507 i,
|
|
508 msgnum;
|
|
509 char *cp,
|
|
510 buf[BUFSIZ],
|
|
511 *msgs[MAXARGS],
|
|
512 *vec[MAXARGS];
|
|
513
|
|
514 if (fmsh) {
|
|
515 forkcmd (args, cmd_name);
|
|
516 return;
|
|
517 }
|
|
518
|
|
519 while (cp = *args++) {
|
|
520 if (*cp == '-')
|
|
521 switch (i = smatch (++cp, fileswit)) {
|
|
522 case AMBIGSW:
|
|
523 ambigsw (cp, fileswit);
|
|
524 return;
|
|
525 case UNKWNSW:
|
|
526 fprintf (stderr, "-%s unknown\n", cp);
|
|
527 return;
|
|
528 case FIHELP:
|
|
529 (void) sprintf (buf, "%s +folder... [msgs] [switches]",
|
|
530 cmd_name);
|
|
531 help (buf, fileswit);
|
|
532 return;
|
|
533
|
|
534 case FILINK:
|
|
535 linksw++;
|
|
536 continue;
|
|
537 case FINLINK:
|
|
538 linksw = 0;
|
|
539 continue;
|
|
540
|
|
541 case FIPRES:
|
|
542 case FINPRES:
|
|
543 continue;
|
|
544
|
|
545 case FISRC:
|
|
546 case FIDRFT:
|
|
547 case FIFILE:
|
|
548 case FIPROC:
|
|
549 case FINPRC:
|
|
550 advise (NULLCP, "sorry, -%s not allowed!", fileswit[i].sw);
|
|
551 return;
|
|
552 }
|
|
553 if (*cp == '+' || *cp == '@')
|
|
554 vec[vecp++] = cp;
|
|
555 else
|
|
556 msgs[msgp++] = cp;
|
|
557 }
|
|
558
|
|
559 vec[0] = cmd_name;
|
|
560 vec[vecp++] = "-file";
|
|
561 vec[vecp] = NULL;
|
|
562 if (!msgp)
|
|
563 msgs[msgp++] = "cur";
|
|
564 for (msgnum = 0; msgnum < msgp; msgnum++)
|
|
565 if (!m_convert (mp, msgs[msgnum]))
|
|
566 return;
|
|
567 m_setseq (mp);
|
|
568
|
|
569 interrupted = 0;
|
|
570 for (msgnum = mp -> lowsel;
|
|
571 msgnum <= mp -> hghsel && !interrupted;
|
|
572 msgnum++)
|
|
573 if (mp -> msgstats[msgnum] & SELECTED)
|
|
574 if (process (msgnum, fileproc, vecp, vec)) {
|
|
575 mp -> msgstats[msgnum] &= ~SELECTED;
|
|
576 mp -> numsel--;
|
|
577 }
|
|
578
|
|
579 if (mp -> numsel != mp -> nummsg || linksw)
|
|
580 m_setcur (mp, mp -> hghsel);
|
|
581 if (!linksw)
|
|
582 rmm ();
|
|
583 }
|
|
584
|
|
585 /* */
|
|
586
|
|
587 int filehak (args)
|
|
588 char **args;
|
|
589 {
|
|
590 int result,
|
|
591 vecp = 0;
|
|
592 char *cp,
|
|
593 *cwd,
|
|
594 *vec[MAXARGS];
|
|
595
|
|
596 while (cp = *args++) {
|
|
597 if (*cp == '-')
|
|
598 switch (smatch (++cp, fileswit)) {
|
|
599 case AMBIGSW:
|
|
600 case UNKWNSW:
|
|
601 case FIHELP:
|
|
602 return NOTOK;
|
|
603
|
|
604 case FILINK:
|
|
605 case FINLINK:
|
|
606 case FIPRES:
|
|
607 case FINPRES:
|
|
608 continue;
|
|
609
|
|
610 case FISRC:
|
|
611 case FIDRFT:
|
|
612 case FIFILE:
|
|
613 return NOTOK;
|
|
614 }
|
|
615 if (*cp == '+' || *cp == '@')
|
|
616 vec[vecp++] = cp;
|
|
617 }
|
|
618 vec[vecp] = NULL;
|
|
619
|
|
620 result = NOTOK;
|
|
621 cwd = NULL;
|
|
622 for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) {
|
|
623 if (cwd == NULL)
|
|
624 cwd = getcpy (pwd ());
|
|
625 (void) chdir (m_maildir (""));
|
|
626 cp = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
|
|
627 if (access (m_maildir (cp), 0) == NOTOK)
|
|
628 result = OK;
|
|
629 free (cp);
|
|
630 }
|
|
631 if (cwd)
|
|
632 (void) chdir (cwd);
|
|
633
|
|
634 return result;
|
|
635 }
|
|
636
|
|
637 /* */
|
|
638
|
|
639 static struct swit foldswit[] = {
|
|
640 #define FLALSW 0
|
|
641 "all", 0,
|
|
642 #define FLFASW 1
|
|
643 "fast", 0,
|
|
644 #define FLNFASW 2
|
|
645 "nofast", 0,
|
|
646 #define FLHDSW 3
|
|
647 "header", 0,
|
|
648 #define FLNHDSW 4
|
|
649 "noheader", 0,
|
|
650 #define FLPKSW 5
|
|
651 "pack", 0,
|
|
652 #define FLNPKSW 6
|
|
653 "nopack", 0,
|
|
654 #define FLRCSW 7
|
|
655 "recurse", 0,
|
|
656 #define FLNRCSW 8
|
|
657 "norecurse", 0,
|
|
658 #define FLTLSW 9
|
|
659 "total", 0,
|
|
660 #define FLNTLSW 10
|
|
661 "nototal", 0,
|
|
662 #define FLPRSW 11
|
|
663 "print", 0,
|
|
664 #define FLPUSW 12
|
|
665 "push", 0,
|
|
666 #define FLPOSW 13
|
|
667 "pop", 0,
|
|
668 #define FLLISW 14
|
|
669 "list", 0,
|
|
670 #define FLHELP 15
|
|
671 "help", 4,
|
|
672
|
|
673 NULL, 0
|
|
674 };
|
|
675
|
|
676 /* */
|
|
677
|
|
678 foldcmd (args)
|
|
679 char **args;
|
|
680 {
|
|
681 int fastsw = 0,
|
|
682 headersw = 0,
|
|
683 packsw = 0,
|
|
684 hole,
|
|
685 msgnum;
|
|
686 char *cp,
|
|
687 *folder = NULL,
|
|
688 *msg = NULL,
|
|
689 buf[BUFSIZ],
|
|
690 **vec = args;
|
|
691
|
|
692 if (args == NULL)
|
|
693 goto fast;
|
|
694
|
|
695 while (cp = *args++) {
|
|
696 if (*cp == '-')
|
|
697 switch (smatch (++cp, foldswit)) {
|
|
698 case AMBIGSW:
|
|
699 ambigsw (cp, foldswit);
|
|
700 return;
|
|
701 case UNKWNSW:
|
|
702 fprintf (stderr, "-%s unknown\n", cp);
|
|
703 return;
|
|
704 case FLHELP:
|
|
705 (void) sprintf (buf, "%s [+folder] [msg] [switches]",
|
|
706 cmd_name);
|
|
707 help (buf, foldswit);
|
|
708 return;
|
|
709
|
|
710 case FLALSW: /* not implemented */
|
|
711 case FLRCSW:
|
|
712 case FLNRCSW:
|
|
713 case FLTLSW:
|
|
714 case FLNTLSW:
|
|
715 case FLPRSW:
|
|
716 case FLPUSW:
|
|
717 case FLPOSW:
|
|
718 case FLLISW:
|
|
719 continue;
|
|
720
|
|
721 case FLFASW:
|
|
722 fastsw++;
|
|
723 continue;
|
|
724 case FLNFASW:
|
|
725 fastsw = 0;
|
|
726 continue;
|
|
727 case FLHDSW:
|
|
728 headersw++;
|
|
729 continue;
|
|
730 case FLNHDSW:
|
|
731 headersw = 0;
|
|
732 continue;
|
|
733 case FLPKSW:
|
|
734 packsw++;
|
|
735 continue;
|
|
736 case FLNPKSW:
|
|
737 packsw = 0;
|
|
738 continue;
|
|
739 }
|
|
740 if (*cp == '+' || *cp == '@')
|
|
741 if (folder) {
|
|
742 advise (NULLCP, "only one folder at a time!\n");
|
|
743 return;
|
|
744 }
|
|
745 else
|
|
746 folder = fmsh ? path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF)
|
|
747 : cp + 1;
|
|
748 else
|
|
749 if (msg) {
|
|
750 advise (NULLCP, "only one message at a time!\n");
|
|
751 return;
|
|
752 }
|
|
753 else
|
|
754 msg = cp;
|
|
755 }
|
|
756
|
|
757 if (folder) {
|
|
758 if (*folder == 0) {
|
|
759 advise (NULLCP, "null folder names are not permitted");
|
|
760 return;
|
|
761 }
|
|
762 if (fmsh) {
|
|
763 if (access (m_maildir (folder), 04) == NOTOK) {
|
|
764 advise (folder, "unable to read");
|
|
765 return;
|
|
766 }
|
|
767 }
|
|
768 else {
|
|
769 (void) strcpy (buf, folder);
|
|
770 if (expand (buf) == NOTOK)
|
|
771 return;
|
|
772 folder = buf;
|
|
773 if (access (folder, 04) == NOTOK) {
|
|
774 advise (folder, "unable to read");
|
|
775 return;
|
|
776 }
|
|
777 }
|
|
778 m_reset ();
|
|
779
|
|
780 if (fmsh)
|
|
781 fsetup (folder);
|
|
782 else
|
|
783 setup (folder);
|
|
784 readids (0);
|
|
785 display_info (0);
|
|
786 }
|
|
787
|
|
788 if (msg) {
|
|
789 if (!m_convert (mp, msg))
|
|
790 return;
|
|
791 m_setseq (mp);
|
|
792
|
|
793 if (mp -> numsel > 1) {
|
|
794 advise (NULLCP, "only one message at a time!");
|
|
795 return;
|
|
796 }
|
|
797 m_setcur (mp, mp -> hghsel);
|
|
798 }
|
|
799
|
|
800 if (packsw) {
|
|
801 if (fmsh) {
|
|
802 forkcmd (vec, cmd_name);
|
|
803 return;
|
|
804 }
|
|
805
|
|
806 if (mp -> lowmsg > 1 && (mp = m_remsg (mp, 1, mp -> hghmsg)) == NULL)
|
|
807 adios (NULLCP, "unable to allocate folder storage");
|
|
808 for (msgnum = mp -> lowmsg, hole = 1; msgnum <= mp -> hghmsg; msgnum++)
|
|
809 if (mp -> msgstats[msgnum] & EXISTS) {
|
|
810 if (msgnum != hole) {
|
|
811 Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id;
|
|
812 Msgs[hole].m_top = Msgs[msgnum].m_top;
|
|
813 Msgs[hole].m_start = Msgs[msgnum].m_start;
|
|
814 Msgs[hole].m_stop = Msgs[msgnum].m_stop;
|
|
815 Msgs[hole].m_scanl = NULL;
|
|
816 if (Msgs[msgnum].m_scanl) {
|
|
817 free (Msgs[msgnum].m_scanl);
|
|
818 Msgs[msgnum].m_scanl = NULL;
|
|
819 }
|
|
820 mp -> msgstats[hole] = mp -> msgstats[msgnum];
|
|
821 if (mp -> curmsg == msgnum)
|
|
822 m_setcur (mp, hole);
|
|
823 }
|
|
824 hole++;
|
|
825 }
|
|
826 if (mp -> nummsg > 0) {
|
|
827 mp -> lowmsg = 1;
|
|
828 mp -> hghmsg = hole - 1;
|
|
829 }
|
|
830 mp -> msgflags |= MODIFIED;
|
|
831 modified++;
|
|
832 }
|
|
833
|
|
834 fast: ;
|
|
835 if (fastsw)
|
|
836 printf ("%s\n", fmsh ? fmsh : mp -> foldpath);
|
|
837 else {
|
|
838 if (headersw)
|
|
839 printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n",
|
|
840 DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
|
|
841 DMAXFOLDER - 2, "");
|
|
842 printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp -> foldpath);
|
|
843 if (mp -> hghmsg == 0)
|
|
844 printf ("has no messages%*s",
|
|
845 mp -> msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
|
|
846 else {
|
|
847 printf ("has %*d message%s (%*d-%*d)",
|
|
848 DMAXFOLDER, mp -> nummsg, mp -> nummsg != 1 ? "s" : "",
|
|
849 DMAXFOLDER, mp -> lowmsg, DMAXFOLDER, mp -> hghmsg);
|
|
850 if (mp -> curmsg >= mp -> lowmsg
|
|
851 && mp -> curmsg <= mp -> hghmsg)
|
|
852 printf ("; cur=%*d", DMAXFOLDER, mp -> curmsg);
|
|
853 }
|
|
854 printf (".\n");
|
|
855 }
|
|
856 }
|
|
857
|
|
858 /* */
|
|
859
|
|
860 #ifndef MIME
|
|
861 #define MIMEminc(a) (a)
|
|
862 #else /* MIME */
|
|
863 #define MIMEminc(a) 0
|
|
864 #endif /* MIME */
|
|
865
|
|
866 static struct swit forwswit[] = {
|
|
867 #define FOANSW 0
|
|
868 "annotate", 0,
|
|
869 #define FONANSW 1
|
|
870 "noannotate", 0,
|
|
871 #define FODFSW 2
|
|
872 "draftfolder +folder", 0,
|
|
873 #define FODMSW 3
|
|
874 "draftmessage msg", 0,
|
|
875 #define FONDFSW 4
|
|
876 "nodraftfolder", 0,
|
|
877 #define FOEDTSW 5
|
|
878 "editor editor", 0,
|
|
879 #define FONEDSW 6
|
|
880 "noedit", 0,
|
|
881 #define FOFTRSW 7
|
|
882 "filter filterfile", 0,
|
|
883 #define FOFRMSW 8
|
|
884 "form formfile", 0,
|
|
885 #define FOFTSW 9
|
|
886 "format", 5,
|
|
887 #define FONFTSW 10
|
|
888 "noformat", 7,
|
|
889 #define FOINSW 11
|
|
890 "inplace", 0,
|
|
891 #define FONINSW 12
|
|
892 "noinplace", 0,
|
|
893 #define FOMISW 13
|
|
894 "mime", MIMEminc(-4),
|
|
895 #define FONMISW 14
|
|
896 "nomime", MIMEminc(-6),
|
|
897 #define FOWHTSW 15
|
|
898 "whatnowproc program", 0,
|
|
899 #define FONWTSW 16
|
|
900 "nowhatnow", 0,
|
|
901 #define FOHELP 17
|
|
902 "help", 4,
|
|
903
|
|
904 NULL, 0
|
|
905 };
|
|
906
|
|
907 /* */
|
|
908
|
|
909 forwcmd (args)
|
|
910 char **args;
|
|
911 {
|
|
912 int msgp = 0,
|
|
913 vecp = 1,
|
|
914 mime = 0,
|
|
915 msgnum;
|
|
916 char *cp,
|
|
917 *filter = NULL,
|
|
918 buf[BUFSIZ],
|
|
919 *msgs[MAXARGS],
|
|
920 *vec[MAXARGS];
|
|
921 char *mktemp ();
|
|
922
|
|
923 if (fmsh) {
|
|
924 forkcmd (args, cmd_name);
|
|
925 return;
|
|
926 }
|
|
927
|
|
928 while (cp = *args++) {
|
|
929 if (*cp == '-')
|
|
930 switch (smatch (++cp, forwswit)) {
|
|
931 case AMBIGSW:
|
|
932 ambigsw (cp, forwswit);
|
|
933 return;
|
|
934 case UNKWNSW:
|
|
935 fprintf (stderr, "-%s unknown\n", cp);
|
|
936 return;
|
|
937 case FOHELP:
|
|
938 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
|
|
939 help (buf, forwswit);
|
|
940 return;
|
|
941
|
|
942 case FOANSW: /* not implemented */
|
|
943 case FONANSW:
|
|
944 case FOINSW:
|
|
945 case FONINSW:
|
|
946 continue;
|
|
947
|
|
948 case FOMISW:
|
|
949 #ifdef MIME
|
|
950 mime = 1;
|
|
951 filter = NULL;
|
|
952 #endif /* MIME */
|
|
953 continue;
|
|
954 case FONMISW:
|
|
955 mime = 0;
|
|
956 continue;
|
|
957
|
|
958 case FONDFSW:
|
|
959 case FONEDSW:
|
|
960 case FONWTSW:
|
|
961 vec[vecp++] = --cp;
|
|
962 continue;
|
|
963
|
|
964 case FOEDTSW:
|
|
965 case FOFRMSW:
|
|
966 case FODFSW:
|
|
967 case FODMSW:
|
|
968 case FOWHTSW:
|
|
969 vec[vecp++] = --cp;
|
|
970 if (!(cp = *args++) || *cp == '-') {
|
|
971 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
972 return;
|
|
973 }
|
|
974 vec[vecp++] = cp;
|
|
975 continue;
|
|
976 case FOFTRSW:
|
|
977 if (!(filter = *args++) || *filter == '-') {
|
|
978 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
979 return;
|
|
980 }
|
|
981 mime = 0;
|
|
982 continue;
|
|
983 case FOFTSW:
|
|
984 if (access (filter = myfilter, 04) == NOTOK) {
|
|
985 advise (filter, "unable to read default filter file");
|
|
986 return;
|
|
987 }
|
|
988 continue;
|
|
989 case FONFTSW:
|
|
990 filter = NULL;
|
|
991 continue;
|
|
992 }
|
|
993 if (*cp == '+' || *cp == '@') {
|
|
994 advise (NULLCP, "sorry, no folders allowed!");
|
|
995 return;
|
|
996 }
|
|
997 else
|
|
998 msgs[msgp++] = cp;
|
|
999 }
|
|
1000
|
|
1001 /* foil search of .mh_profile */
|
|
1002 (void) sprintf (buf, "%sXXXXXX", invo_name);
|
|
1003 vec[0] = (char *)mktemp (buf);
|
|
1004 vec[vecp++] = "-file";
|
|
1005 vec[vecp] = NULL;
|
|
1006 if (!msgp)
|
|
1007 msgs[msgp++] = "cur";
|
|
1008 for (msgnum = 0; msgnum < msgp; msgnum++)
|
|
1009 if (!m_convert (mp, msgs[msgnum]))
|
|
1010 return;
|
|
1011 m_setseq (mp);
|
|
1012
|
|
1013 if (filter) {
|
|
1014 (void) strcpy (buf, filter);
|
|
1015 if (expand (buf) == NOTOK)
|
|
1016 return;
|
|
1017 if (access (filter = getcpy (libpath (buf)), 04) == NOTOK) {
|
|
1018 advise (filter, "unable to read");
|
|
1019 free (filter);
|
|
1020 return;
|
|
1021 }
|
|
1022 }
|
|
1023 forw (cmd_name, filter, vecp, vec, mime);
|
|
1024 m_setcur (mp, mp -> hghsel);
|
|
1025 if (filter)
|
|
1026 free (filter);
|
|
1027 }
|
|
1028
|
|
1029 /* */
|
|
1030
|
|
1031 static forw (proc, filter, vecp, vec, mime)
|
|
1032 int vecp,
|
|
1033 mime;
|
|
1034 char *proc,
|
|
1035 *filter,
|
|
1036 **vec;
|
|
1037 {
|
|
1038 int i,
|
|
1039 child_id,
|
|
1040 msgnum,
|
|
1041 msgcnt;
|
|
1042 char tmpfil[80],
|
|
1043 *args[MAXARGS];
|
|
1044 FILE *out;
|
|
1045 #ifdef MIME
|
|
1046 int nedit = 0;
|
|
1047 char *ed = NULL;
|
|
1048 #endif /* MIME */
|
|
1049
|
|
1050 (void) strcpy (tmpfil, m_tmpfil (invo_name));
|
|
1051 interrupted = 0;
|
|
1052 if (filter)
|
|
1053 switch (child_id = fork ()) {
|
|
1054 case NOTOK:
|
|
1055 advise ("fork", "unable to");
|
|
1056 return;
|
|
1057
|
|
1058 case OK: /* "trust me" */
|
|
1059 if (freopen (tmpfil, "w", stdout) == NULL) {
|
|
1060 fprintf (stderr, "unable to create ");
|
|
1061 perror (tmpfil);
|
|
1062 _exit (1);
|
|
1063 }
|
|
1064 args[0] = r1bindex (mhlproc, '/');
|
|
1065 i = 1;
|
|
1066 args[i++] = "-forwall";
|
|
1067 args[i++] = "-form";
|
|
1068 args[i++] = filter;
|
|
1069 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
|
|
1070 if (mp -> msgstats[msgnum] & SELECTED)
|
|
1071 args[i++] = getcpy (m_name (msgnum));
|
|
1072 args[i] = NULL;
|
|
1073 (void) mhlsbr (i, args, mhl_action);
|
|
1074 m_eomsbr ((int (*) ()) 0);
|
|
1075 (void) fclose (stdout);
|
|
1076 _exit (0);
|
|
1077
|
|
1078 default:
|
|
1079 if (pidXwait (child_id, NULLCP))
|
|
1080 interrupted++;
|
|
1081 break;
|
|
1082 }
|
|
1083 #ifdef MIME
|
|
1084 else if (mime) {
|
|
1085 int isdf = 0,
|
|
1086 len,
|
|
1087 nwhat = 0;
|
|
1088 #define INITIAL_PREFIX "----- =_aaaaaaaaaa"
|
|
1089 char *cp,
|
|
1090 *form = NULL,
|
|
1091 buffer[BUFSIZ],
|
|
1092 prefix[sizeof INITIAL_PREFIX];
|
|
1093 FILE *zp;
|
|
1094
|
|
1095 proc = whatnowproc;
|
|
1096 for (vecp = 1; cp = vec[vecp++]; )
|
|
1097 if (*cp == '-')
|
|
1098 switch (smatch (++cp, forwswit)) {
|
|
1099 case FOEDTSW:
|
|
1100 ed = vec[vecp++];
|
|
1101 nedit = 0;
|
|
1102 continue;
|
|
1103 case FONEDSW:
|
|
1104 nedit++;
|
|
1105 continue;
|
|
1106
|
|
1107 case FOFRMSW:
|
|
1108 form = vec[vecp++];
|
|
1109 continue;
|
|
1110
|
|
1111 case FOWHTSW:
|
|
1112 proc = vec[vecp++];
|
|
1113 nwhat = 0;
|
|
1114 continue;
|
|
1115 case FONWTSW:
|
|
1116 nwhat++;
|
|
1117 continue;
|
|
1118
|
|
1119 /* ignore -draftfolder / -draftmessage / -nodraftfolder */
|
|
1120 case FODFSW:
|
|
1121 case FODMSW:
|
|
1122 vecp++;
|
|
1123 case FONDFSW:
|
|
1124 continue;
|
|
1125 }
|
|
1126 (void) strcpy (tmpfil, m_draft (NULLCP, NULLCP, NOUSE, &isdf));
|
|
1127 if (!ed && !(ed = m_find ("editor")))
|
|
1128 ed = sysed;
|
|
1129
|
|
1130 (void) strcpy (prefix, INITIAL_PREFIX);
|
|
1131 cp = index (prefix, 'a');
|
|
1132 len = strlen (prefix);
|
|
1133
|
|
1134 for (;;) {
|
|
1135 int hit = 0;
|
|
1136 long pos;
|
|
1137
|
|
1138 for (msgnum = mp -> lowsel;
|
|
1139 msgnum <= mp -> hghsel && !interrupted && !hit;
|
|
1140 msgnum++)
|
|
1141 if (mp -> msgstats[msgnum] & SELECTED) {
|
|
1142 zp = msh_ready (msgnum, 1);
|
|
1143 if (!fmsh)
|
|
1144 pos = ftell (zp);
|
|
1145 while (fgets (buffer, sizeof buffer, zp) != NULL
|
|
1146 && !fmsh
|
|
1147 && pos < Msgs[msgnum].m_stop) {
|
|
1148 register char *pp;
|
|
1149
|
|
1150 if (buffer[0] != '-' || buffer[1] != '-')
|
|
1151 continue;
|
|
1152
|
|
1153 for (pp = buffer + strlen (buffer) - 1;
|
|
1154 pp >= buffer;
|
|
1155 pp--)
|
|
1156 if (!isspace (*pp))
|
|
1157 break;
|
|
1158 *pp++ = '\0';
|
|
1159
|
|
1160 if (strncmp (buffer + 2, prefix, len))
|
|
1161 continue;
|
|
1162
|
|
1163 hit = 1;
|
|
1164 break;
|
|
1165 }
|
|
1166 }
|
|
1167
|
|
1168 if (!hit)
|
|
1169 break;
|
|
1170
|
|
1171 if (*cp < 'z')
|
|
1172 (*cp)++;
|
|
1173 else
|
|
1174 if (*++cp == 0) {
|
|
1175 advise (NULLCP,
|
|
1176 "unable to determine unique delimiter string?!?");
|
|
1177 return;
|
|
1178 }
|
|
1179 else
|
|
1180 (*cp)++;
|
|
1181 }
|
|
1182
|
|
1183 if ((out = fopen (tmpfil, "w")) == NULL) {
|
|
1184 advise (tmpfil, "unable to create temporary file");
|
|
1185 return;
|
|
1186 }
|
|
1187 (void) chmod (tmpfil, m_gmprot ());
|
|
1188
|
|
1189 fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
|
|
1190 fprintf (out, "%s: multipart/digest; boundary=\"%s\"\n", TYPE_FIELD,
|
|
1191 prefix);
|
|
1192
|
|
1193 if (!(zp = fopen (libpath (form ? form : forwcomps), "r"))) {
|
|
1194 if (form)
|
|
1195 advise (form, "unable to open form file");
|
|
1196 else
|
|
1197 advise (forwcomps, "unable to open default components file");
|
|
1198 (void) fclose (out);
|
|
1199 (void) unlink (tmpfil);
|
|
1200 return;
|
|
1201 }
|
|
1202 while (fgets (buffer, sizeof buffer, zp))
|
|
1203 (void) fputs (buffer, out);
|
|
1204 (void) fclose (zp);
|
|
1205
|
|
1206 for (msgnum = mp -> lowsel;
|
|
1207 msgnum <= mp -> hghsel && !interrupted;
|
|
1208 msgnum++)
|
|
1209 if (mp -> msgstats[msgnum] & SELECTED) {
|
|
1210 fprintf (out, "\n--%s\n%s: message/rfc822\n\n", prefix,
|
|
1211 TYPE_FIELD);
|
|
1212
|
|
1213 copy_message (msgnum, out);
|
|
1214 }
|
|
1215 fprintf (out, "\n--%s--\n", prefix);
|
|
1216
|
|
1217 (void) fclose (out);
|
|
1218 if (nwhat)
|
|
1219 return;
|
|
1220 }
|
|
1221 #endif /* MIME */
|
|
1222 else {
|
|
1223 if ((out = fopen (tmpfil, "w")) == NULL) {
|
|
1224 advise (tmpfil, "unable to create temporary file");
|
|
1225 return;
|
|
1226 }
|
|
1227
|
|
1228 msgcnt = 1;
|
|
1229 for (msgnum = mp -> lowsel;
|
|
1230 msgnum <= mp -> hghsel && !interrupted;
|
|
1231 msgnum++)
|
|
1232 if (mp -> msgstats[msgnum] & SELECTED) {
|
|
1233 fprintf (out, "\n\n-------");
|
|
1234 if (msgnum == mp -> lowsel)
|
|
1235 fprintf (out, " Forwarded Message%s",
|
|
1236 mp -> numsel > 1 ? "s" : "");
|
|
1237 else
|
|
1238 fprintf (out, " Message %d", msgcnt);
|
|
1239 fprintf (out, "\n\n");
|
|
1240 copy_digest (msgnum, out);
|
|
1241 msgcnt++;
|
|
1242 }
|
|
1243
|
|
1244 fprintf (out, "\n\n------- End of Forwarded Message%s\n",
|
|
1245 mp -> numsel > 1 ? "s" : "");
|
|
1246 (void) fclose (out);
|
|
1247 }
|
|
1248
|
|
1249 (void) fflush (stdout);
|
|
1250 if (!interrupted)
|
|
1251 switch (child_id = fork ()) {
|
|
1252 case NOTOK:
|
|
1253 advise ("fork", "unable to");
|
|
1254 break;
|
|
1255
|
|
1256 case OK:
|
|
1257 closefds (3);
|
|
1258 (void) signal (SIGINT, istat);
|
|
1259 (void) signal (SIGQUIT, qstat);
|
|
1260
|
|
1261 #ifdef MIME
|
|
1262 if (mime) {
|
|
1263 vecp = 0;
|
|
1264 vec[vecp++] = r1bindex (proc, '/');
|
|
1265 (void) m_putenv ("mhdraft", tmpfil);
|
|
1266 (void) unputenv ("mhfolder");
|
|
1267 (void) unputenv ("mhaltmsg");
|
|
1268 (void) m_putenv ("mhdist", "0");
|
|
1269 if (nedit)
|
|
1270 (void) unputenv ("mheditor");
|
|
1271 else
|
|
1272 (void) m_putenv ("mheditor", ed);
|
|
1273 (void) m_putenv ("mhuse", "0");
|
|
1274 (void) unputenv ("mhmessages");
|
|
1275 (void) unputenv ("mhannotate");
|
|
1276 (void) unputenv ("mhinplace");
|
|
1277 }
|
|
1278 else
|
|
1279 #endif /* MIME */
|
|
1280
|
|
1281 vec[vecp++] = tmpfil;
|
|
1282 vec[vecp] = NULL;
|
|
1283
|
|
1284 execvp (proc, vec);
|
|
1285 fprintf (stderr, "unable to exec ");
|
|
1286 perror (proc);
|
|
1287 _exit (1);
|
|
1288
|
|
1289 default:
|
|
1290 (void) pidXwait (child_id, NULLCP);
|
|
1291 break;
|
|
1292 }
|
|
1293
|
|
1294 #ifdef MIME
|
|
1295 if (!mime)
|
|
1296 #endif /* MIME */
|
|
1297 (void) unlink (tmpfil);
|
|
1298 }
|
|
1299
|
|
1300 /* */
|
|
1301
|
|
1302 static char *hlpmsg[] = {
|
|
1303 "The %s program emulates many of the commands found in the Rand MH",
|
|
1304 "system. Instead of operating on MH folders, commands to %s concern",
|
|
1305 "a single file.",
|
|
1306 "",
|
|
1307 "To see the list of commands available, just type a ``?'' followed by",
|
|
1308 "the RETURN key. To find out what switches each command takes, type",
|
|
1309 "the name of the command followed by ``-help''. To leave %s, use the",
|
|
1310 "``quit'' command.",
|
|
1311 "",
|
|
1312 "Although a lot of MH commands are found in %s, not all are fully",
|
|
1313 "implemented. %s will always recognize all legal switches for a",
|
|
1314 "given command though, and will let you know when you ask for an",
|
|
1315 "option that it is unable to perform.",
|
|
1316 "",
|
|
1317 "Running %s is fun, but using MH from your shell is far superior.",
|
|
1318 "After you have familiarized yourself with the MH style by using %s,",
|
|
1319 "you should try using MH from the shell. You can still use %s for",
|
|
1320 "message files that aren't in MH format, such as BBoard files.",
|
|
1321 NULL
|
|
1322 };
|
|
1323
|
|
1324
|
|
1325 /* ARGSUSED */
|
|
1326
|
|
1327 helpcmd (args)
|
|
1328 char **args;
|
|
1329 {
|
|
1330 int i;
|
|
1331
|
|
1332 for (i = 0; hlpmsg[i]; i++) {
|
|
1333 printf (hlpmsg[i], invo_name);
|
|
1334 (void) putchar ('\n');
|
|
1335 }
|
|
1336 }
|
|
1337
|
|
1338 /* */
|
|
1339
|
|
1340 static struct swit markswit[] = {
|
|
1341 #define MADDSW 0
|
|
1342 "add", 0,
|
|
1343 #define MDELSW 1
|
|
1344 "delete", 0,
|
|
1345 #define MLSTSW 2
|
|
1346 "list", 0,
|
|
1347 #define MSEQSW 3
|
|
1348 "sequence name", 0,
|
|
1349 #define MPUBSW 4
|
|
1350 "public", 0,
|
|
1351 #define MNPUBSW 5
|
|
1352 "nopublic", 0,
|
|
1353 #define MZERSW 6
|
|
1354 "zero", 0,
|
|
1355 #define MNZERSW 7
|
|
1356 "nozero", 0,
|
|
1357 #define MHELP 8
|
|
1358 "help", 4,
|
|
1359 #define MDBUGSW 9
|
|
1360 "debug", -5,
|
|
1361
|
|
1362 NULL, 0
|
|
1363 };
|
|
1364
|
|
1365 /* */
|
|
1366
|
|
1367 markcmd (args)
|
|
1368 char **args;
|
|
1369 {
|
|
1370 int addsw = 0,
|
|
1371 deletesw = 0,
|
|
1372 debugsw = 0,
|
|
1373 listsw = 0,
|
|
1374 zerosw = 0,
|
|
1375 seqp = 0,
|
|
1376 msgp = 0,
|
|
1377 i,
|
|
1378 msgnum;
|
|
1379 char *cp,
|
|
1380 buf[BUFSIZ],
|
|
1381 *seqs[NATTRS + 1],
|
|
1382 *msgs[MAXARGS];
|
|
1383
|
|
1384 while (cp = *args++) {
|
|
1385 if (*cp == '-')
|
|
1386 switch (smatch (++cp, markswit)) {
|
|
1387 case AMBIGSW:
|
|
1388 ambigsw (cp, markswit);
|
|
1389 return;
|
|
1390 case UNKWNSW:
|
|
1391 fprintf (stderr, "-%s unknown\n", cp);
|
|
1392 return;
|
|
1393 case MHELP:
|
|
1394 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
|
|
1395 help (buf, markswit);
|
|
1396 return;
|
|
1397
|
|
1398 case MADDSW:
|
|
1399 addsw++;
|
|
1400 deletesw = listsw = 0;
|
|
1401 continue;
|
|
1402 case MDELSW:
|
|
1403 deletesw++;
|
|
1404 addsw = listsw = 0;
|
|
1405 continue;
|
|
1406 case MLSTSW:
|
|
1407 listsw++;
|
|
1408 addsw = deletesw = 0;
|
|
1409 continue;
|
|
1410
|
|
1411 case MSEQSW:
|
|
1412 if (!(cp = *args++) || *cp == '-') {
|
|
1413 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
1414 return;
|
|
1415 }
|
|
1416 if (seqp < NATTRS)
|
|
1417 seqs[seqp++] = cp;
|
|
1418 else {
|
|
1419 advise (NULLCP, "only %d sequences allowed!", NATTRS);
|
|
1420 return;
|
|
1421 }
|
|
1422 continue;
|
|
1423
|
|
1424 case MPUBSW: /* not implemented */
|
|
1425 case MNPUBSW:
|
|
1426 continue;
|
|
1427
|
|
1428 case MDBUGSW:
|
|
1429 debugsw++;
|
|
1430 continue;
|
|
1431
|
|
1432 case MZERSW:
|
|
1433 zerosw++;
|
|
1434 continue;
|
|
1435 case MNZERSW:
|
|
1436 zerosw = 0;
|
|
1437 continue;
|
|
1438 }
|
|
1439 if (*cp == '+' || *cp == '@') {
|
|
1440 advise (NULLCP, "sorry, no folders allowed!");
|
|
1441 return;
|
|
1442 }
|
|
1443 else
|
|
1444 msgs[msgp++] = cp;
|
|
1445 }
|
|
1446
|
|
1447 if (!addsw && !deletesw && !listsw)
|
|
1448 if (seqp)
|
|
1449 addsw++;
|
|
1450 else
|
|
1451 if (debugsw)
|
|
1452 listsw++;
|
|
1453 else {
|
|
1454 seqs[seqp++] = "unseen";
|
|
1455 deletesw++;
|
|
1456 zerosw = 0;
|
|
1457 if (!msgp)
|
|
1458 msgs[msgp++] = "all";
|
|
1459 }
|
|
1460
|
|
1461 if (!msgp)
|
|
1462 msgs[msgp++] = listsw ? "all" :"cur";
|
|
1463 for (msgnum = 0; msgnum < msgp; msgnum++)
|
|
1464 if (!m_convert (mp, msgs[msgnum]))
|
|
1465 return;
|
|
1466
|
|
1467 if (debugsw) {
|
|
1468 printf ("invo_name=%s mypath=%s defpath=%s\n",
|
|
1469 invo_name, mypath, defpath);
|
|
1470 printf ("ctxpath=%s context flags=%s\n",
|
|
1471 ctxpath, sprintb (buf, (unsigned) ctxflags, DBITS));
|
|
1472 printf ("foldpath=%s flags=%s\n",
|
|
1473 mp -> foldpath,
|
|
1474 sprintb (buf, (unsigned) mp -> msgflags, FBITS));
|
|
1475 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
|
|
1476 mp -> hghmsg, mp -> lowmsg, mp -> nummsg, mp -> curmsg);
|
|
1477 printf ("lowsel=%d hghsel=%d numsel=%d\n",
|
|
1478 mp -> lowsel, mp -> hghsel, mp -> numsel);
|
|
1479 #ifndef MTR
|
|
1480 printf ("lowoff=%d hghoff=%d\n",
|
|
1481 mp -> lowoff, mp -> hghoff);
|
|
1482 #else /* MTR */
|
|
1483 printf ("lowoff=%d hghoff=%d msgbase=0x%x msgstats=0x%x\n",
|
|
1484 mp -> lowoff, mp -> hghoff, mp -> msgbase, mp -> msgstats);
|
|
1485 #endif /* MTR */
|
|
1486 }
|
|
1487
|
|
1488 if (seqp == 0 && (addsw || deletesw)) {
|
|
1489 advise (NULLCP, "-%s requires at least one -sequence argument",
|
|
1490 addsw ? "add" : "delete");
|
|
1491 return;
|
|
1492 }
|
|
1493 seqs[seqp] = NULL;
|
|
1494
|
|
1495 if (addsw)
|
|
1496 for (seqp = 0; seqs[seqp]; seqp++) {
|
|
1497 if (zerosw && !m_seqnew (mp, seqs[seqp], 0))
|
|
1498 return;
|
|
1499 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
|
|
1500 if (mp -> msgstats[msgnum] & SELECTED)
|
|
1501 if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
|
|
1502 return;
|
|
1503 }
|
|
1504
|
|
1505 if (deletesw)
|
|
1506 for (seqp = 0; seqs[seqp]; seqp++) {
|
|
1507 if (zerosw)
|
|
1508 for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
|
|
1509 if (mp -> msgstats[msgnum] & EXISTS)
|
|
1510 if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
|
|
1511 return;
|
|
1512 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
|
|
1513 if (mp -> msgstats[msgnum] & SELECTED)
|
|
1514 if (!m_seqdel (mp, seqs[seqp], msgnum))
|
|
1515 return;
|
|
1516 }
|
|
1517
|
|
1518 if (listsw) {
|
|
1519 int bits = FFATTRSLOT;
|
|
1520
|
|
1521 #define empty(s) ((s) ? (s) : "")
|
|
1522 if (seqp == 0)
|
|
1523 for (i = 0; mp -> msgattrs[i]; i++)
|
|
1524 printf ("%s%s: %s\n", mp -> msgattrs[i],
|
|
1525 mp -> attrstats & (1 << (bits + i))
|
|
1526 ? " (private)" : "",
|
|
1527 empty(m_seq (mp, mp -> msgattrs[i])));
|
|
1528 else
|
|
1529 for (seqp = 0; seqs[seqp]; seqp++)
|
|
1530 printf ("%s%s: %s\n", seqs[seqp],
|
12
|
1531 empty(m_seq (mp, seqs[seqp])),"");
|
0
|
1532 #undef empty
|
|
1533
|
|
1534 interrupted = 0;
|
|
1535 if (debugsw)
|
|
1536 for (msgnum = mp -> lowsel;
|
|
1537 msgnum <= mp -> hghsel && !interrupted;
|
|
1538 msgnum++)
|
|
1539 if (mp -> msgstats[msgnum] & SELECTED) {
|
|
1540 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
|
|
1541 DMAXFOLDER, msgnum,
|
|
1542 Msgs[msgnum].m_bboard_id, Msgs[msgnum].m_top,
|
|
1543 Msgs[msgnum].m_start, Msgs[msgnum].m_stop,
|
|
1544 sprintb (buf, (unsigned) mp -> msgstats[msgnum],
|
|
1545 m_seqbits (mp)));
|
|
1546 if (Msgs[msgnum].m_scanl)
|
|
1547 printf ("%s", Msgs[msgnum].m_scanl);
|
|
1548 }
|
|
1549 }
|
|
1550 }
|
|
1551
|
|
1552 /* */
|
|
1553
|
|
1554 #ifdef MIME
|
|
1555 static struct swit mhnswit[] = {
|
|
1556 #define MHNAUTOSW 0
|
|
1557 "auto", 0,
|
|
1558 #define MHNNAUTOSW 1
|
|
1559 "noauto", 0,
|
|
1560 #define MHNDEBUGSW 2
|
|
1561 "debug", -5,
|
|
1562 #define MHNEBCDICSW 3
|
|
1563 "ebcdicsafe", 0,
|
|
1564 #define MHNNEBCDICSW 4
|
|
1565 "noebcdicsafe", 0,
|
|
1566 #define MHNFORMSW 5
|
|
1567 "form formfile", 4,
|
|
1568 #define MHNHEADSW 6
|
|
1569 "headers", 0,
|
|
1570 #define MHNNHEADSW 7
|
|
1571 "noheaders", 0,
|
|
1572 #define MHNLISTSW 8
|
|
1573 "list", 0,
|
|
1574 #define MHNNLISTSW 9
|
|
1575 "nolist", 0,
|
|
1576 #define MHNPARTSW 10
|
|
1577 "part number", 0,
|
|
1578 #define MHNSIZESW 11
|
|
1579 "realsize", 0,
|
|
1580 #define MHNNSIZESW 12
|
|
1581 "norealsize", 0,
|
|
1582 #define MHNRFC934SW 13
|
|
1583 "rfc934mode", 0,
|
|
1584 #define MHNNRFC934SW 14
|
|
1585 "norfc934mode", 0,
|
|
1586 #define MHNSERIALSW 15
|
|
1587 "serialonly", 0,
|
|
1588 #define MHNNSERIALSW 16
|
|
1589 "noserialonly", 0,
|
|
1590 #define MHNSHOWSW 17
|
|
1591 "show", 0,
|
|
1592 #define MHNNSHOWSW 18
|
|
1593 "noshow", 0,
|
|
1594 #define MHNSTORESW 19
|
|
1595 "store", 0,
|
|
1596 #define MHNNSTORESW 20
|
|
1597 "nostore", 0,
|
|
1598 #define MHNTYPESW 21
|
|
1599 "type content", 0,
|
|
1600 #define MHNVERBSW 22
|
|
1601 "verbose", 0,
|
|
1602 #define MHNNVERBSW 23
|
|
1603 "noverbose", 0,
|
|
1604 #define MHNHELPSW 24
|
|
1605 "help", 4,
|
|
1606 #define MHNPROGSW 25
|
|
1607 "moreproc program", -4,
|
|
1608 #define MHNNPROGSW 26
|
|
1609 "nomoreproc", -3,
|
|
1610 #define MHNLENSW 27
|
|
1611 "length lines", -4,
|
|
1612 #define MHNWIDSW 28
|
|
1613 "width columns", -4,
|
|
1614
|
|
1615 NULL, 0
|
|
1616 };
|
|
1617
|
|
1618 /* */
|
|
1619
|
|
1620 mhncmd (args)
|
|
1621 char **args;
|
|
1622 {
|
|
1623 int msgp = 0,
|
|
1624 vecp = 1,
|
|
1625 i,
|
|
1626 msgnum;
|
|
1627 char *cp,
|
|
1628 buf[BUFSIZ],
|
|
1629 *msgs[MAXARGS],
|
|
1630 *vec[MAXARGS];
|
|
1631
|
|
1632 if (fmsh) {
|
|
1633 forkcmd (args, cmd_name);
|
|
1634 return;
|
|
1635 }
|
|
1636
|
|
1637 while (cp = *args++) {
|
|
1638 if (*cp == '-')
|
|
1639 switch (smatch (++cp, mhnswit)) {
|
|
1640 case AMBIGSW:
|
|
1641 ambigsw (cp, mhnswit);
|
|
1642 return;
|
|
1643 case UNKWNSW:
|
|
1644 fprintf (stderr, "-%s unknown\n", cp);
|
|
1645 return;
|
|
1646 case MHNHELPSW:
|
|
1647 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
|
|
1648 help (buf, mhnswit);
|
|
1649 return;
|
|
1650
|
|
1651 case MHNAUTOSW:
|
|
1652 case MHNNAUTOSW:
|
|
1653 case MHNDEBUGSW:
|
|
1654 case MHNEBCDICSW:
|
|
1655 case MHNNEBCDICSW:
|
|
1656 case MHNHEADSW:
|
|
1657 case MHNNHEADSW:
|
|
1658 case MHNLISTSW:
|
|
1659 case MHNNLISTSW:
|
|
1660 case MHNSIZESW:
|
|
1661 case MHNNSIZESW:
|
|
1662 case MHNRFC934SW:
|
|
1663 case MHNNRFC934SW:
|
|
1664 case MHNSERIALSW:
|
|
1665 case MHNNSERIALSW:
|
|
1666 case MHNSHOWSW:
|
|
1667 case MHNNSHOWSW:
|
|
1668 case MHNSTORESW:
|
|
1669 case MHNNSTORESW:
|
|
1670 case MHNVERBSW:
|
|
1671 case MHNNVERBSW:
|
|
1672 case MHNNPROGSW:
|
|
1673 vec[vecp++] = --cp;
|
|
1674 continue;
|
|
1675
|
|
1676 case MHNFORMSW:
|
|
1677 case MHNPARTSW:
|
|
1678 case MHNTYPESW:
|
|
1679 case MHNPROGSW:
|
|
1680 case MHNLENSW:
|
|
1681 case MHNWIDSW:
|
|
1682 vec[vecp++] = --cp;
|
|
1683 if (!(cp = *args++) || *cp == '-') {
|
|
1684 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
1685 return;
|
|
1686 }
|
|
1687 vec[vecp++] = cp;
|
|
1688 continue;
|
|
1689 }
|
|
1690 if (*cp == '+' || *cp == '@') {
|
|
1691 advise (NULLCP, "sorry, no folders allowed!");
|
|
1692 return;
|
|
1693 }
|
|
1694 else
|
|
1695 msgs[msgp++] = cp;
|
|
1696 }
|
|
1697
|
|
1698 vec[0] = cmd_name;
|
|
1699 vec[vecp++] = "-file";
|
|
1700 vec[vecp] = NULL;
|
|
1701 if (!msgp)
|
|
1702 msgs[msgp++] = "cur";
|
|
1703 for (msgnum = 0; msgnum < msgp; msgnum++)
|
|
1704 if (!m_convert (mp, msgs[msgnum]))
|
|
1705 return;
|
|
1706 m_setseq (mp);
|
|
1707
|
|
1708 interrupted = 0;
|
|
1709 for (msgnum = mp -> lowsel;
|
|
1710 msgnum <= mp -> hghsel && !interrupted;
|
|
1711 msgnum++)
|
|
1712 if (mp -> msgstats[msgnum] & SELECTED)
|
|
1713 if (process (msgnum, cmd_name, vecp, vec)) {
|
|
1714 mp -> msgstats[msgnum] &= ~SELECTED;
|
|
1715 mp -> numsel--;
|
|
1716 }
|
|
1717
|
|
1718 m_setcur (mp, mp -> hghsel);
|
|
1719 }
|
|
1720
|
|
1721 /* */
|
|
1722
|
|
1723 #endif /* MIME */
|
|
1724 static struct swit packswit[] = {
|
|
1725 #define PAFISW 0
|
|
1726 "file name", 0,
|
|
1727
|
|
1728 #define PAHELP 1
|
|
1729 "help", 4,
|
|
1730
|
|
1731 NULL, 0
|
|
1732 };
|
|
1733
|
|
1734 /* */
|
|
1735
|
|
1736 packcmd (args)
|
|
1737 char **args;
|
|
1738 {
|
|
1739 int msgp = 0,
|
|
1740 md,
|
|
1741 msgnum;
|
|
1742 char *cp,
|
|
1743 *file = NULL,
|
|
1744 buf[BUFSIZ],
|
|
1745 *msgs[MAXARGS];
|
|
1746 struct stat st;
|
|
1747
|
|
1748 if (fmsh) {
|
|
1749 forkcmd (args, cmd_name);
|
|
1750 return;
|
|
1751 }
|
|
1752
|
|
1753 while (cp = *args++) {
|
|
1754 if (*cp == '-')
|
|
1755 switch (smatch (++cp, packswit)) {
|
|
1756 case AMBIGSW:
|
|
1757 ambigsw (cp, packswit);
|
|
1758 return;
|
|
1759 case UNKWNSW:
|
|
1760 fprintf (stderr, "-%s unknown\n", cp);
|
|
1761 return;
|
|
1762 case PAHELP:
|
|
1763 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
|
|
1764 help (buf, packswit);
|
|
1765 return;
|
|
1766
|
|
1767 case PAFISW:
|
|
1768 if (!(file = *args++) || *file == '-') {
|
|
1769 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
1770 return;
|
|
1771 }
|
|
1772 continue;
|
|
1773 }
|
|
1774 if (*cp == '+' || *cp == '@') {
|
|
1775 advise (NULLCP, "sorry, no folders allowed!");
|
|
1776 return;
|
|
1777 }
|
|
1778 else
|
|
1779 msgs[msgp++] = cp;
|
|
1780 }
|
|
1781
|
|
1782 if (!file)
|
|
1783 file = "./msgbox";
|
|
1784 file = path (file, TFILE);
|
|
1785 if (stat (file, &st) == NOTOK) {
|
|
1786 if (errno != ENOENT) {
|
|
1787 advise (file, "error on file");
|
|
1788 goto done_pack;
|
|
1789 }
|
|
1790 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULLCP));
|
|
1791 free (cp);
|
|
1792 if (!md)
|
|
1793 goto done_pack;
|
|
1794 }
|
|
1795
|
|
1796 if (!msgp)
|
|
1797 msgs[msgp++] = "all";
|
|
1798 for (msgnum = 0; msgnum < msgp; msgnum++)
|
|
1799 if (!m_convert (mp, msgs[msgnum]))
|
|
1800 goto done_pack;
|
|
1801 m_setseq (mp);
|
|
1802
|
|
1803 if ((md = mbx_open (file, getuid (), getgid (), m_gmprot ())) == NOTOK) {
|
|
1804 advise (file, "unable to open");
|
|
1805 goto done_pack;
|
|
1806 }
|
|
1807 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
|
|
1808 if (mp -> msgstats[msgnum] & SELECTED)
|
|
1809 if (pack (file, md, msgnum) == NOTOK)
|
|
1810 break;
|
|
1811 (void) mbx_close (file, md);
|
|
1812
|
|
1813 if (mp -> hghsel != mp -> curmsg)
|
|
1814 m_setcur (mp, mp -> lowsel);
|
|
1815
|
|
1816 done_pack: ;
|
|
1817 free (file);
|
|
1818 }
|
|
1819
|
|
1820 /* */
|
|
1821
|
|
1822 int pack (mailbox, md, msgnum)
|
|
1823 char *mailbox;
|
|
1824 int md,
|
|
1825 msgnum;
|
|
1826 {
|
|
1827 register FILE *zp;
|
|
1828
|
|
1829 if (Msgs[msgnum].m_bboard_id == 0)
|
|
1830 (void) readid (msgnum);
|
|
1831
|
|
1832 zp = msh_ready (msgnum, 1);
|
|
1833 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
|
|
1834 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
|
|
1835 }
|
|
1836
|
|
1837 /* */
|
|
1838
|
|
1839 int packhak (args)
|
|
1840 char **args;
|
|
1841 {
|
|
1842 int result;
|
|
1843 char *cp,
|
|
1844 *file = NULL;
|
|
1845
|
|
1846 while (cp = *args++) {
|
|
1847 if (*cp == '-')
|
|
1848 switch (smatch (++cp, packswit)) {
|
|
1849 case AMBIGSW:
|
|
1850 case UNKWNSW:
|
|
1851 case PAHELP:
|
|
1852 return NOTOK;
|
|
1853
|
|
1854 case PAFISW:
|
|
1855 if (!(file = *args++) || *file == '-')
|
|
1856 return NOTOK;
|
|
1857 continue;
|
|
1858 }
|
|
1859 if (*cp == '+' || *cp == '@')
|
|
1860 return NOTOK;
|
|
1861 }
|
|
1862
|
|
1863 file = path (file ? file : "./msgbox", TFILE);
|
|
1864 result = access (file, 0) == NOTOK ? OK : NOTOK;
|
|
1865 free (file);
|
|
1866
|
|
1867 return result;
|
|
1868 }
|
|
1869
|
|
1870 /* */
|
|
1871
|
|
1872 static struct swit pickswit[] = {
|
|
1873 #define PIANSW 0
|
|
1874 "and", 0,
|
|
1875 #define PIORSW 1
|
|
1876 "or", 0,
|
|
1877 #define PINTSW 2
|
|
1878 "not", 0,
|
|
1879 #define PILBSW 3
|
|
1880 "lbrace", 0,
|
|
1881 #define PIRBSW 4
|
|
1882 "rbrace", 0,
|
|
1883
|
|
1884 #define PICCSW 5
|
|
1885 "cc pattern", 0,
|
|
1886 #define PIDASW 6
|
|
1887 "date pattern", 0,
|
|
1888 #define PIFRSW 7
|
|
1889 "from pattern", 0,
|
|
1890 #define PISESW 8
|
|
1891 "search pattern", 0,
|
|
1892 #define PISUSW 9
|
|
1893 "subject pattern", 0,
|
|
1894 #define PITOSW 10
|
|
1895 "to pattern", 0,
|
|
1896 #define PIOTSW 11
|
|
1897 "-othercomponent pattern", 15,
|
|
1898 #define PIAFSW 12
|
|
1899 "after date", 0,
|
|
1900 #define PIBFSW 13
|
|
1901 "before date", 0,
|
|
1902 #define PIDFSW 14
|
|
1903 "datefield field", 5,
|
|
1904 #define PISQSW 15
|
|
1905 "sequence name", 0,
|
|
1906 #define PIPUSW 16
|
|
1907 "public", 0,
|
|
1908 #define PINPUSW 17
|
|
1909 "nopublic", 0,
|
|
1910 #define PIZRSW 18
|
|
1911 "zero", 0,
|
|
1912 #define PINZRSW 19
|
|
1913 "nozero", 0,
|
|
1914 #define PILISW 20
|
|
1915 "list", 0,
|
|
1916 #define PINLISW 21
|
|
1917 "nolist", 0,
|
|
1918 #define PIHELP 22
|
|
1919 "help", 4,
|
|
1920
|
|
1921 NULL, 0
|
|
1922 };
|
|
1923
|
|
1924 /* */
|
|
1925
|
|
1926 pickcmd (args)
|
|
1927 char **args;
|
|
1928 {
|
|
1929 int zerosw = 1,
|
|
1930 msgp = 0,
|
|
1931 seqp = 0,
|
|
1932 vecp = 0,
|
|
1933 hi,
|
|
1934 lo,
|
|
1935 msgnum;
|
|
1936 char *cp,
|
|
1937 buf[BUFSIZ],
|
|
1938 *msgs[MAXARGS],
|
|
1939 *seqs[NATTRS],
|
|
1940 *vec[MAXARGS];
|
|
1941 register FILE *zp;
|
|
1942
|
|
1943 while (cp = *args++) {
|
|
1944 if (*cp == '-') {
|
|
1945 if (*++cp == '-') {
|
|
1946 vec[vecp++] = --cp;
|
|
1947 goto pattern;
|
|
1948 }
|
|
1949 switch (smatch (cp, pickswit)) {
|
|
1950 case AMBIGSW:
|
|
1951 ambigsw (cp, pickswit);
|
|
1952 return;
|
|
1953 case UNKWNSW:
|
|
1954 fprintf (stderr, "-%s unknown\n", cp);
|
|
1955 return;
|
|
1956 case PIHELP:
|
|
1957 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
|
|
1958 help (buf, pickswit);
|
|
1959 return;
|
|
1960
|
|
1961 case PICCSW:
|
|
1962 case PIDASW:
|
|
1963 case PIFRSW:
|
|
1964 case PISUSW:
|
|
1965 case PITOSW:
|
|
1966 case PIDFSW:
|
|
1967 case PIAFSW:
|
|
1968 case PIBFSW:
|
|
1969 case PISESW:
|
|
1970 vec[vecp++] = --cp;
|
|
1971 pattern: ;
|
|
1972 if (!(cp = *args++)) {/* allow -xyz arguments */
|
|
1973 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
1974 return;
|
|
1975 }
|
|
1976 vec[vecp++] = cp;
|
|
1977 continue;
|
|
1978 case PIOTSW:
|
|
1979 advise (NULLCP, "internal error!");
|
|
1980 return;
|
|
1981 case PIANSW:
|
|
1982 case PIORSW:
|
|
1983 case PINTSW:
|
|
1984 case PILBSW:
|
|
1985 case PIRBSW:
|
|
1986 vec[vecp++] = --cp;
|
|
1987 continue;
|
|
1988
|
|
1989 case PISQSW:
|
|
1990 if (!(cp = *args++) || *cp == '-') {
|
|
1991 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
1992 return;
|
|
1993 }
|
|
1994 if (seqp < NATTRS)
|
|
1995 seqs[seqp++] = cp;
|
|
1996 else {
|
|
1997 advise (NULLCP, "only %d sequences allowed!", NATTRS);
|
|
1998 return;
|
|
1999 }
|
|
2000 continue;
|
|
2001 case PIZRSW:
|
|
2002 zerosw++;
|
|
2003 continue;
|
|
2004 case PINZRSW:
|
|
2005 zerosw = 0;
|
|
2006 continue;
|
|
2007
|
|
2008 case PIPUSW: /* not implemented */
|
|
2009 case PINPUSW:
|
|
2010 case PILISW:
|
|
2011 case PINLISW:
|
|
2012 continue;
|
|
2013 }
|
|
2014 }
|
|
2015 if (*cp == '+' || *cp == '@') {
|
|
2016 advise (NULLCP, "sorry, no folders allowed!");
|
|
2017 return;
|
|
2018 }
|
|
2019 else
|
|
2020 msgs[msgp++] = cp;
|
|
2021 }
|
|
2022 vec[vecp] = NULL;
|
|
2023
|
|
2024 if (!msgp)
|
|
2025 msgs[msgp++] = "all";
|
|
2026 for (msgnum = 0; msgnum < msgp; msgnum++)
|
|
2027 if (!m_convert (mp, msgs[msgnum]))
|
|
2028 return;
|
|
2029 m_setseq (mp);
|
|
2030
|
|
2031 interrupted = 0;
|
|
2032 if (!pcompile (vec, NULLCP))
|
|
2033 return;
|
|
2034
|
|
2035 lo = mp -> lowsel;
|
|
2036 hi = mp -> hghsel;
|
|
2037
|
|
2038 for (msgnum = mp -> lowsel;
|
|
2039 msgnum <= mp -> hghsel && !interrupted;
|
|
2040 msgnum++)
|
|
2041 if (mp -> msgstats[msgnum] & SELECTED) {
|
|
2042 zp = msh_ready (msgnum, 1);
|
|
2043 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
|
|
2044 fmsh ? 0L : Msgs[msgnum].m_stop)) {
|
|
2045 if (msgnum < lo)
|
|
2046 lo = msgnum;
|
|
2047 if (msgnum > hi)
|
|
2048 hi = msgnum;
|
|
2049 }
|
|
2050 else {
|
|
2051 mp -> msgstats[msgnum] &= ~SELECTED;
|
|
2052 mp -> numsel--;
|
|
2053 }
|
|
2054 }
|
|
2055
|
|
2056 if (interrupted)
|
|
2057 return;
|
|
2058
|
|
2059 mp -> lowsel = lo;
|
|
2060 mp -> hghsel = hi;
|
|
2061
|
|
2062 if (mp -> numsel <= 0) {
|
|
2063 advise (NULLCP, "no messages match specification");
|
|
2064 return;
|
|
2065 }
|
|
2066
|
|
2067 seqs[seqp] = NULL;
|
|
2068 for (seqp = 0; seqs[seqp]; seqp++) {
|
|
2069 if (zerosw && !m_seqnew (mp, seqs[seqp], 0))
|
|
2070 return;
|
|
2071 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
|
|
2072 if (mp -> msgstats[msgnum] & SELECTED)
|
|
2073 if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
|
|
2074 return;
|
|
2075 }
|
|
2076
|
|
2077 printf ("%d hit%s\n", mp -> numsel, mp -> numsel == 1 ? "" : "s");
|
|
2078 }
|
|
2079
|
|
2080 /* */
|
|
2081
|
|
2082 static struct swit replswit[] = {
|
|
2083 #define REANSW 0
|
|
2084 "annotate", 0,
|
|
2085 #define RENANSW 1
|
|
2086 "noannotate", 0,
|
|
2087 #define RECCSW 2
|
|
2088 "cc type", 0,
|
|
2089 #define RENCCSW 3
|
|
2090 "nocc type", 0,
|
|
2091 #define REDFSW 4
|
|
2092 "draftfolder +folder", 0,
|
|
2093 #define REDMSW 5
|
|
2094 "draftmessage msg", 0,
|
|
2095 #define RENDFSW 6
|
|
2096 "nodraftfolder", 0,
|
|
2097 #define REEDTSW 7
|
|
2098 "editor editor", 0,
|
|
2099 #define RENEDSW 8
|
|
2100 "noedit", 0,
|
|
2101 #define REFCCSW 9
|
|
2102 "fcc +folder", 0,
|
|
2103 #define REFLTSW 10
|
|
2104 "filter filterfile", 0,
|
|
2105 #define REFRMSW 11
|
|
2106 "form formfile", 0,
|
|
2107 #define REINSW 12
|
|
2108 "inplace", 0,
|
|
2109 #define RENINSW 13
|
|
2110 "noinplace", 0,
|
|
2111 #define REQUSW 14
|
|
2112 "query", 0,
|
|
2113 #define RENQUSW 15
|
|
2114 "noquery", 0,
|
|
2115 #define REWHTSW 16
|
|
2116 "whatnowproc program", 0,
|
|
2117 #define RENWTSW 17
|
|
2118 "nowhatnow", 0,
|
|
2119 #define REWIDSW 19
|
|
2120 "width columns", 0,
|
|
2121 #define REHELP 20
|
|
2122 "help", 4,
|
|
2123
|
|
2124 NULL, 0
|
|
2125 };
|
|
2126
|
|
2127 /* */
|
|
2128
|
|
2129 replcmd (args)
|
|
2130 char **args;
|
|
2131 {
|
|
2132 int vecp = 1;
|
|
2133 char *cp,
|
|
2134 *msg = NULL,
|
|
2135 buf[BUFSIZ],
|
|
2136 *vec[MAXARGS];
|
|
2137
|
|
2138 if (fmsh) {
|
|
2139 forkcmd (args, cmd_name);
|
|
2140 return;
|
|
2141 }
|
|
2142
|
|
2143 while (cp = *args++) {
|
|
2144 if (*cp == '-')
|
|
2145 switch (smatch (++cp, replswit)) {
|
|
2146 case AMBIGSW:
|
|
2147 ambigsw (cp, replswit);
|
|
2148 return;
|
|
2149 case UNKWNSW:
|
|
2150 fprintf (stderr, "-%s unknown\n", cp);
|
|
2151 return;
|
|
2152 case REHELP:
|
|
2153 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
|
|
2154 help (buf, replswit);
|
|
2155 return;
|
|
2156
|
|
2157 case REANSW: /* not implemented */
|
|
2158 case RENANSW:
|
|
2159 case REINSW:
|
|
2160 case RENINSW:
|
|
2161 continue;
|
|
2162
|
|
2163 case REQUSW:
|
|
2164 case RENQUSW:
|
|
2165 case RENDFSW:
|
|
2166 case RENEDSW:
|
|
2167 case RENWTSW:
|
|
2168 vec[vecp++] = --cp;
|
|
2169 continue;
|
|
2170
|
|
2171 case RECCSW:
|
|
2172 case RENCCSW:
|
|
2173 case REEDTSW:
|
|
2174 case REFCCSW:
|
|
2175 case REFLTSW:
|
|
2176 case REFRMSW:
|
|
2177 case REWIDSW:
|
|
2178 case REDFSW:
|
|
2179 case REDMSW:
|
|
2180 case REWHTSW:
|
|
2181 vec[vecp++] = --cp;
|
|
2182 if (!(cp = *args++) || *cp == '-') {
|
|
2183 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
2184 return;
|
|
2185 }
|
|
2186 vec[vecp++] = cp;
|
|
2187 continue;
|
|
2188 }
|
|
2189 if (*cp == '+' || *cp == '@') {
|
|
2190 advise (NULLCP, "sorry, no folders allowed!");
|
|
2191 return;
|
|
2192 }
|
|
2193 else
|
|
2194 if (msg) {
|
|
2195 advise (NULLCP, "only one message at a time!");
|
|
2196 return;
|
|
2197 }
|
|
2198 else
|
|
2199 msg = cp;
|
|
2200 }
|
|
2201
|
|
2202 vec[0] = cmd_name;
|
|
2203 vec[vecp++] = "-file";
|
|
2204 vec[vecp] = NULL;
|
|
2205 if (!msg)
|
|
2206 msg = "cur";
|
|
2207 if (!m_convert (mp, msg))
|
|
2208 return;
|
|
2209 m_setseq (mp);
|
|
2210
|
|
2211 if (mp -> numsel > 1) {
|
|
2212 advise (NULLCP, "only one message at a time!");
|
|
2213 return;
|
|
2214 }
|
|
2215 (void) process (mp -> hghsel, cmd_name, vecp, vec);
|
|
2216 m_setcur (mp, mp -> hghsel);
|
|
2217 }
|
|
2218
|
|
2219 /* */
|
|
2220
|
|
2221 static struct swit rmmswit[] = {
|
|
2222 #define RMHELP 0
|
|
2223 "help", 4,
|
|
2224
|
|
2225 NULL, 0
|
|
2226 };
|
|
2227
|
|
2228 /* */
|
|
2229
|
|
2230 rmmcmd (args)
|
|
2231 char **args;
|
|
2232 {
|
|
2233 int msgp = 0,
|
|
2234 msgnum;
|
|
2235 char *cp,
|
|
2236 buf[BUFSIZ],
|
|
2237 *msgs[MAXARGS];
|
|
2238
|
|
2239 while (cp = *args++) {
|
|
2240 if (*cp == '-')
|
|
2241 switch (smatch (++cp, rmmswit)) {
|
|
2242 case AMBIGSW:
|
|
2243 ambigsw (cp, rmmswit);
|
|
2244 return;
|
|
2245 case UNKWNSW:
|
|
2246 fprintf (stderr, "-%s unknown\n", cp);
|
|
2247 return;
|
|
2248 case RMHELP:
|
|
2249 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
|
|
2250 help (buf, rmmswit);
|
|
2251 return;
|
|
2252 }
|
|
2253 if (*cp == '+' || *cp == '@') {
|
|
2254 advise (NULLCP, "sorry, no folders allowed!");
|
|
2255 return;
|
|
2256 }
|
|
2257 else
|
|
2258 msgs[msgp++] = cp;
|
|
2259 }
|
|
2260
|
|
2261 if (!msgp)
|
|
2262 msgs[msgp++] = "cur";
|
|
2263 for (msgnum = 0; msgnum < msgp; msgnum++)
|
|
2264 if (!m_convert (mp, msgs[msgnum]))
|
|
2265 return;
|
|
2266 m_setseq (mp);
|
|
2267
|
|
2268 rmm ();
|
|
2269 }
|
|
2270
|
|
2271 /* */
|
|
2272
|
|
2273 #ifdef MH_PLUS
|
|
2274 struct msgs *opntrashf ();
|
|
2275 struct msgs *trash ();
|
|
2276 #endif /* MH_PLUS */
|
|
2277
|
|
2278 static rmm () {
|
|
2279 register int msgnum,
|
|
2280 vecp;
|
|
2281 register char *cp;
|
|
2282 char buffer[BUFSIZ],
|
|
2283 *vec[MAXARGS];
|
|
2284
|
|
2285 if (fmsh) {
|
|
2286 if (rmmproc) {
|
|
2287 if (mp -> numsel > MAXARGS - 1) {
|
|
2288 advise (NULLCP, "more than %d messages for %s exec",
|
|
2289 MAXARGS - 1, rmmproc);
|
|
2290 return;
|
|
2291 }
|
|
2292 vecp = 0;
|
|
2293 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
|
|
2294 if (mp -> msgstats[msgnum] & SELECTED)
|
|
2295 vec[vecp++] = getcpy (m_name (msgnum));
|
|
2296 vec[vecp] = NULL;
|
|
2297 forkcmd (vec, rmmproc);
|
|
2298 for (vecp = 0; vec[vecp]; vecp++)
|
|
2299 free (vec[vecp]);
|
|
2300 }
|
|
2301 else {
|
|
2302 #ifdef MH_PLUS
|
|
2303 int rmp;
|
|
2304 char *tfold;
|
|
2305 struct msgs *tmp;
|
|
2306
|
|
2307 if ((tfold = m_find ("Trash-Folder")))
|
|
2308 tmp = opntrashf (tfold, m_maildir (fmsh), &rmp);
|
|
2309 #endif /* MH_PLUS */
|
|
2310 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
|
|
2311 if (mp -> msgstats[msgnum] & SELECTED) {
|
|
2312 #ifdef MH_PLUS
|
|
2313 if (tfold) {
|
|
2314 tmp = trash (msgnum, tmp, rmp);
|
|
2315 continue;
|
|
2316 }
|
|
2317 #endif /* MH_PLUS */
|
|
2318 (void) strcpy (buffer, m_backup (cp = m_name (msgnum)));
|
|
2319 if (rename (cp, buffer) == NOTOK)
|
|
2320 admonish (buffer, "unable to rename %s to", cp);
|
|
2321 }
|
|
2322 }
|
|
2323 }
|
|
2324
|
|
2325 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
|
|
2326 if (mp -> msgstats[msgnum] & SELECTED) {
|
|
2327 mp -> msgstats[msgnum] |= DELETED;
|
|
2328 mp -> msgstats[msgnum] &= ~EXISTS;
|
|
2329 #ifdef MPOP
|
|
2330 #ifdef BPOP
|
|
2331 if (pmsh && pop_dele (msgnum) != OK)
|
|
2332 fprintf (stderr, "%s", response);
|
|
2333 #endif
|
|
2334 #endif /* MPOP */
|
|
2335 }
|
|
2336
|
|
2337 if ((mp -> nummsg -= mp -> numsel) <= 0) {
|
|
2338 if (fmsh)
|
|
2339 admonish (NULLCP, "no messages remaining in +%s", fmsh);
|
|
2340 else
|
|
2341 admonish (NULLCP, "no messages remaining in %s", mp -> foldpath);
|
|
2342 mp -> lowmsg = mp -> hghmsg = mp -> nummsg = 0;
|
|
2343 }
|
|
2344 if (mp -> lowsel == mp -> lowmsg) {
|
|
2345 for (msgnum = mp -> lowmsg + 1; msgnum <= mp -> hghmsg; msgnum++)
|
|
2346 if (mp -> msgstats[msgnum] & EXISTS)
|
|
2347 break;
|
|
2348 mp -> lowmsg = msgnum;
|
|
2349 }
|
|
2350 if (mp -> hghsel == mp -> hghmsg) {
|
|
2351 for (msgnum = mp -> hghmsg - 1; msgnum >= mp -> lowmsg; msgnum--)
|
|
2352 if (mp -> msgstats[msgnum] & EXISTS)
|
|
2353 break;
|
|
2354 mp -> hghmsg = msgnum;
|
|
2355 }
|
|
2356
|
|
2357 mp -> msgflags |= MODIFIED;
|
|
2358 modified++;
|
|
2359 }
|
|
2360
|
|
2361 /* */
|
|
2362
|
|
2363 #ifdef MH_PLUS
|
|
2364 struct msgs *
|
|
2365 opntrashf (tfold, cwd, rmp)
|
|
2366 char *tfold,
|
|
2367 *cwd;
|
|
2368 int *rmp;
|
|
2369 {
|
|
2370 int len;
|
|
2371 char *tf,
|
|
2372 *cp,
|
|
2373 *trashdir;
|
|
2374 struct stat st;
|
|
2375 struct msgs *tmp;
|
|
2376
|
|
2377 tf = path (*tfold == '+' || *tfold == '@' ? tfold + 1 : tfold,
|
|
2378 *tfold != '@' ? TFOLDER : TSUBCWF);
|
|
2379 if (*tfold == '@' && *(tfold + 1) != '/') {
|
|
2380 cp = tfold + 1;
|
|
2381 while (*cp) {
|
|
2382 if (strncmp (cp, "./", 2) == 0)
|
|
2383 cp += 2;
|
|
2384 else if (strncmp (cp, "../", 3) == 0)
|
|
2385 cp += 3;
|
|
2386 else
|
|
2387 break;
|
|
2388 }
|
|
2389 len = strlen(cp);
|
|
2390 if (strncmp(cwd + strlen(cwd) - len, cp, len) == 0) {
|
|
2391 trashdir = ".";
|
|
2392 tf = path ("./", TSUBCWF);
|
|
2393 } else
|
|
2394 trashdir = m_maildir (tf);
|
|
2395 } else
|
|
2396 trashdir = m_maildir (tf);
|
|
2397 if (strcmp(cwd, trashdir) == 0)
|
|
2398 trashdir = ".";
|
|
2399 *rmp = strcmp(trashdir, ".") ? 0 : 1;
|
|
2400
|
|
2401 if (stat (trashdir, &st) == NOTOK) {
|
|
2402 if (errno != ENOENT)
|
|
2403 adios (trashdir, "error on folder");
|
|
2404 cp = concat ("Create folder \"", trashdir, "\"? ", NULLCP);
|
|
2405 if (!getanswer (cp))
|
|
2406 done (1);
|
|
2407 free (cp);
|
|
2408 if (!makedir (trashdir))
|
|
2409 adios (NULLCP, "unable to create folder %s", trashdir);
|
|
2410 }
|
|
2411 if (chdir (trashdir) == NOTOK)
|
|
2412 adios (trashdir, "unable to change directory to");
|
|
2413 if (!(tmp = m_gmsg (tf)))
|
|
2414 adios (NULLCP, "unable to read folder %s", tfold);
|
|
2415 tmp -> curmsg = 0;
|
|
2416 chdir (cwd);
|
|
2417 return tmp;
|
|
2418 }
|
|
2419
|
|
2420 struct msgs *
|
|
2421 trash (msgnum, tmp, rmp)
|
|
2422 struct msgs *tmp;
|
|
2423 int msgnum,
|
|
2424 rmp;
|
|
2425 {
|
|
2426 int newnum;
|
|
2427 char *msg,
|
|
2428 newmsg[BUFSIZ];
|
|
2429
|
|
2430 if (rmp) {
|
|
2431 msg = m_name (msgnum);
|
|
2432 if (unlink (msg) == NOTOK)
|
|
2433 admonish (msg, "unable to unlink");
|
|
2434 return tmp;
|
|
2435 }
|
|
2436
|
|
2437 if (tmp -> hghmsg >= tmp -> hghoff)
|
|
2438 if (!(tmp = m_remsg (tmp, 0, tmp -> hghoff + MAXFOLDER)))
|
|
2439 adios (NULLCP, "unable to allocate folder storage");
|
|
2440
|
|
2441 newnum = ++tmp -> hghmsg;
|
|
2442 tmp -> nummsg++;
|
|
2443 tmp -> msgstats[newnum] |= EXISTS | SELECTED;
|
|
2444 if (tmp -> lowmsg == 0)
|
|
2445 tmp -> lowmsg = newnum;
|
|
2446 if (tmp -> lowsel == 0 || newnum < tmp -> lowsel)
|
|
2447 tmp -> lowsel = newnum;
|
|
2448 if (newnum > tmp -> hghsel)
|
|
2449 tmp -> hghsel = newnum;
|
|
2450
|
|
2451 (void) sprintf (newmsg, "%s/%s", tmp -> foldpath, m_name (newnum));
|
|
2452 msg = m_name (msgnum);
|
|
2453 if (rename (msg, newmsg) == NOTOK) {
|
|
2454 int in, out;
|
|
2455 struct stat st;
|
|
2456 if (stat (newmsg, &st) != NOTOK) {
|
|
2457 admonish (newmsg, "unable to rename %s to", msg);
|
|
2458 return tmp;
|
|
2459 }
|
|
2460 if ((in = open(msg, 0)) == NOTOK) {
|
|
2461 admonish (msg, "unable to open message");
|
|
2462 return tmp;
|
|
2463 }
|
|
2464 (void) fstat (in, &st);
|
|
2465 if ((out = creat (newmsg, (int) st.st_mode & 0777)) == NOTOK) {
|
|
2466 admonish (newmsg, "unable to create");
|
|
2467 (void) close (in);
|
|
2468 return tmp;
|
|
2469 }
|
|
2470 cpydata (in, out, msg, newmsg);
|
|
2471 (void) close (in);
|
|
2472 (void) close (out);
|
|
2473 if (unlink (msg) == NOTOK)
|
|
2474 admonish (msg, "unable to unlink");
|
|
2475 }
|
|
2476 return tmp;
|
|
2477 }
|
|
2478 #endif /* MH_PLUS */
|
|
2479
|
|
2480
|
|
2481 /* */
|
|
2482
|
|
2483 static struct swit scanswit[] = {
|
|
2484 #define SCCLR 0
|
|
2485 "clear", 0,
|
|
2486 #define SCNCLR 1
|
|
2487 "noclear", 0,
|
|
2488 #define SCFORM 2
|
|
2489 "form formatfile", 0,
|
|
2490 #define SCFMT 3
|
|
2491 "format string", 5,
|
|
2492 #define SCHEAD 4
|
|
2493 "header", 0,
|
|
2494 #define SCNHEAD 5
|
|
2495 "noheader", 0,
|
|
2496 #define SCWID 6
|
|
2497 "width columns", 0,
|
|
2498 #define SCHELP 7
|
|
2499 "help", 4,
|
|
2500
|
|
2501 NULL, 0
|
|
2502 };
|
|
2503
|
|
2504 /* */
|
|
2505
|
|
2506 scancmd (args)
|
|
2507 char **args;
|
|
2508 {
|
|
2509 #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
|
|
2510
|
|
2511 int clearsw = 0,
|
|
2512 headersw = 0,
|
|
2513 width = 0,
|
|
2514 msgp = 0,
|
|
2515 msgnum,
|
|
2516 optim,
|
|
2517 state;
|
|
2518 char *cp,
|
|
2519 *form = NULL,
|
|
2520 *format = NULL,
|
|
2521 buf[BUFSIZ],
|
|
2522 *nfs,
|
|
2523 *msgs[MAXARGS];
|
|
2524 register FILE *zp;
|
|
2525 #ifdef MPOP
|
|
2526 #ifdef BPOP
|
|
2527 static int p_optim = 0;
|
|
2528 #endif
|
|
2529 #endif /* MPOP */
|
|
2530 static int s_optim = 0;
|
|
2531 static char *s_form = NULL,
|
|
2532 *s_format = NULL;
|
|
2533
|
|
2534 while (cp = *args++) {
|
|
2535 if (*cp == '-')
|
|
2536 switch (smatch (++cp, scanswit)) {
|
|
2537 case AMBIGSW:
|
|
2538 ambigsw (cp, scanswit);
|
|
2539 return;
|
|
2540 case UNKWNSW:
|
|
2541 fprintf (stderr, "-%s unknown\n", cp);
|
|
2542 return;
|
|
2543 case SCHELP:
|
|
2544 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
|
|
2545 help (buf, scanswit);
|
|
2546 return;
|
|
2547
|
|
2548 case SCCLR:
|
|
2549 clearsw++;
|
|
2550 continue;
|
|
2551 case SCNCLR:
|
|
2552 clearsw = 0;
|
|
2553 continue;
|
|
2554 case SCHEAD:
|
|
2555 headersw++;
|
|
2556 continue;
|
|
2557 case SCNHEAD:
|
|
2558 headersw = 0;
|
|
2559 continue;
|
|
2560 case SCFORM:
|
|
2561 if (!(form = *args++) || *form == '-') {
|
|
2562 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
2563 return;
|
|
2564 }
|
|
2565 format = NULL;
|
|
2566 continue;
|
|
2567 case SCFMT:
|
|
2568 if (!(format = *args++) || *format == '-') {
|
|
2569 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
2570 return;
|
|
2571 }
|
|
2572 form = NULL;
|
|
2573 continue;
|
|
2574 case SCWID:
|
|
2575 if (!(cp = *args++) || *cp == '-') {
|
|
2576 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
2577 return;
|
|
2578 }
|
|
2579 width = atoi (cp);
|
|
2580 continue;
|
|
2581 }
|
|
2582 if (*cp == '+' || *cp == '@') {
|
|
2583 advise (NULLCP, "sorry, no folders allowed!");
|
|
2584 return;
|
|
2585 }
|
|
2586 else
|
|
2587 msgs[msgp++] = cp;
|
|
2588 }
|
|
2589
|
|
2590 if (!msgp)
|
|
2591 msgs[msgp++] = "all";
|
|
2592 for (msgnum = 0; msgnum < msgp; msgnum++)
|
|
2593 if (!m_convert (mp, msgs[msgnum]))
|
|
2594 return;
|
|
2595 m_setseq (mp);
|
|
2596
|
|
2597 nfs = new_fs (form, format, FORMAT);
|
|
2598 if (scanl) { /* force scansbr to (re)compile format */
|
|
2599 (void) free (scanl);
|
|
2600 scanl = NULL;
|
|
2601 }
|
|
2602
|
|
2603 if (s_optim == 0) {
|
|
2604 s_optim = optim = 1;
|
|
2605 s_form = form ? getcpy (form) : NULL;
|
|
2606 s_format = format ? getcpy (format) : NULL;
|
|
2607
|
|
2608 #ifdef MPOP
|
|
2609 #ifdef BPOP
|
|
2610 if (pmsh) {
|
|
2611 int i;
|
|
2612 char *dp,
|
|
2613 *ep,
|
|
2614 *fp;
|
|
2615
|
|
2616 if (width == 0)
|
|
2617 width = sc_width ();
|
|
2618
|
|
2619 for (dp = nfs, i = 0; *dp; dp++, i++)
|
|
2620 if (*dp == '\\' || *dp == '"' || *dp == '\n')
|
|
2621 i++;
|
|
2622 i++;
|
|
2623 if ((ep = malloc ((unsigned) i)) == NULL)
|
|
2624 adios (NULLCP, "out of memory");
|
|
2625 for (dp = nfs, fp = ep; *dp; dp++) {
|
|
2626 if (*dp == '\n') {
|
|
2627 *fp++ = '\\', *fp++ = 'n';
|
|
2628 continue;
|
|
2629 }
|
|
2630 if (*dp == '"' || *dp == '\\')
|
|
2631 *fp++ = '\\';
|
|
2632 *fp++ = *dp;
|
|
2633 }
|
|
2634 *fp = '\0';
|
|
2635
|
|
2636 if (pop_command ("XTND SCAN %d \"%s\"", width, ep) == OK)
|
|
2637 p_optim = 1;
|
|
2638
|
|
2639 free (ep);
|
|
2640 }
|
|
2641 #endif
|
|
2642 #endif /* MPOP */
|
|
2643 }
|
|
2644 else
|
|
2645 optim = equiv (s_form, form) && equiv (s_format, format);
|
|
2646
|
|
2647 #ifdef MPOP
|
|
2648 #ifdef BPOP
|
|
2649 if (p_optim && optim) {
|
|
2650 for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
|
|
2651 if (!(mp -> msgstats[msgnum] & SELECTED) || Msgs[msgnum].m_scanl)
|
|
2652 break;
|
|
2653 if (msgnum > mp -> hghmsg && pop_command ("LIST") == OK) {
|
|
2654 fprintf (stderr, "Stand-by...");
|
|
2655 fflush (stderr);
|
|
2656
|
|
2657 for (;;) {
|
|
2658 int size;
|
|
2659
|
|
2660 switch (pop_multiline ()) {
|
|
2661 case NOTOK:
|
|
2662 fprintf (stderr, "%s", response);
|
|
2663 /* and fall... */
|
|
2664 case DONE:
|
|
2665 fprintf (stderr,"\n");
|
|
2666 break;
|
|
2667
|
|
2668 case OK:
|
|
2669 if (sscanf (response, "%d %d", &msgnum, &size) == 2
|
|
2670 && mp -> lowmsg <= msgnum
|
|
2671 && msgnum <= mp -> hghmsg
|
|
2672 && (cp = index (response, '#'))
|
|
2673 && *++cp)
|
|
2674 Msgs[msgnum].m_scanl = concat (cp, "\n", NULLCP);
|
|
2675 continue;
|
|
2676 }
|
|
2677 break;
|
|
2678 }
|
|
2679 }
|
|
2680 }
|
|
2681 #endif
|
|
2682 #endif /* MPOP */
|
|
2683
|
|
2684 interrupted = 0;
|
|
2685 for (msgnum = mp -> lowsel;
|
|
2686 msgnum <= mp -> hghsel && !interrupted;
|
|
2687 msgnum++)
|
|
2688 if (mp -> msgstats[msgnum] & SELECTED) {
|
|
2689 if (optim && Msgs[msgnum].m_scanl)
|
|
2690 printf ("%s", Msgs[msgnum].m_scanl);
|
|
2691 else {
|
|
2692 #ifdef MPOP
|
|
2693 #ifdef BPOP
|
|
2694 if (p_optim
|
|
2695 && optim
|
|
2696 && (mp -> msgstats[msgnum] & VIRTUAL)
|
|
2697 && pop_command ("LIST %d", msgnum) == OK
|
|
2698 && (cp = index (response, '#'))
|
|
2699 && *++cp) {
|
|
2700 Msgs[msgnum].m_scanl = concat (cp, "\n", NULLCP);
|
|
2701 printf ("%s", Msgs[msgnum].m_scanl);
|
|
2702 continue;
|
|
2703 }
|
|
2704 #endif
|
|
2705 #endif /* MPOP */
|
|
2706
|
|
2707 zp = msh_ready (msgnum, 0);
|
|
2708 switch (state = scan (zp, msgnum, 0, nfs, width,
|
|
2709 msgnum == mp -> curmsg,
|
|
2710 mp -> msgstats[msgnum] & UNSEEN, /* ?? */
|
|
2711 headersw, fmsh ? fmsh : mp -> foldpath,
|
|
2712 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
|
|
2713 1)) {
|
|
2714 case SCNMSG:
|
|
2715 case SCNENC:
|
|
2716 case SCNERR:
|
|
2717 if (optim)
|
|
2718 Msgs[msgnum].m_scanl = getcpy (scanl);
|
|
2719 break;
|
|
2720
|
|
2721 default:
|
|
2722 advise (NULLCP, "scan() botch (%d)", state);
|
|
2723 return;
|
|
2724
|
|
2725 case SCNEOF:
|
|
2726 printf ("%*d empty\n", DMAXFOLDER, msgnum);
|
|
2727 break;
|
|
2728 }
|
|
2729 }
|
|
2730 headersw = 0;
|
|
2731 }
|
|
2732
|
|
2733 if (clearsw)
|
|
2734 clear_screen ();
|
|
2735 }
|
|
2736
|
|
2737 /* */
|
|
2738
|
|
2739 static struct swit showswit[] = {
|
|
2740 #define SHDRAFT 0
|
|
2741 "draft", 5,
|
|
2742 #define SHFORM 1
|
|
2743 "form formfile", 4,
|
|
2744 #define SHPROG 2
|
|
2745 "moreproc program", 4,
|
|
2746 #define SHNPROG 3
|
|
2747 "nomoreproc", 3,
|
|
2748 #define SHLEN 4
|
|
2749 "length lines", 4,
|
|
2750 #define SHWID 5
|
|
2751 "width columns", 4,
|
|
2752 #define SHSHOW 6
|
|
2753 "showproc program", 4,
|
|
2754 #define SHNSHOW 7
|
|
2755 "noshowproc", 3,
|
|
2756 #define SHHEAD 8
|
|
2757 "header", 4,
|
|
2758 #define SHNHEAD 9
|
|
2759 "noheader", 3,
|
|
2760 #define SHHELP 10
|
|
2761 "help", 4,
|
|
2762
|
|
2763 NULL, 0
|
|
2764 };
|
|
2765
|
|
2766 /* */
|
|
2767
|
|
2768 showcmd (args)
|
|
2769 char **args;
|
|
2770 {
|
|
2771 int headersw = 1,
|
|
2772 nshow = 0,
|
|
2773 msgp = 0,
|
|
2774 vecp = 1,
|
|
2775 mhl = 0,
|
|
2776 seen = 0,
|
|
2777 mode = 0,
|
|
2778 i,
|
|
2779 msgnum;
|
|
2780 char *cp,
|
|
2781 *proc = showproc,
|
|
2782 buf[BUFSIZ],
|
|
2783 *msgs[MAXARGS],
|
|
2784 *vec[MAXARGS];
|
|
2785
|
|
2786 if (uleq (cmd_name, "next"))
|
|
2787 mode = 1;
|
|
2788 else
|
|
2789 if (uleq (cmd_name, "prev"))
|
|
2790 mode = -1;
|
|
2791 while (cp = *args++) {
|
|
2792 if (*cp == '-')
|
|
2793 switch (i = smatch (++cp, showswit)) {
|
|
2794 case AMBIGSW:
|
|
2795 ambigsw (cp, showswit);
|
|
2796 return;
|
|
2797 case UNKWNSW:
|
|
2798 case SHNPROG:
|
|
2799 vec[vecp++] = --cp;
|
|
2800 continue;
|
|
2801 case SHHELP:
|
|
2802 (void) sprintf (buf,
|
|
2803 "%s %s[switches] [switches for showproc]",
|
|
2804 cmd_name, mode ? NULL : "[msgs] ");
|
|
2805 help (buf, showswit);
|
|
2806 return;
|
|
2807
|
|
2808 case SHFORM:
|
|
2809 case SHPROG:
|
|
2810 case SHLEN:
|
|
2811 case SHWID:
|
|
2812 vec[vecp++] = --cp;
|
|
2813 if (!(cp = *args++) || *cp == '-') {
|
|
2814 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
2815 return;
|
|
2816 }
|
|
2817 vec[vecp++] = cp;
|
|
2818 continue;
|
|
2819 case SHHEAD:
|
|
2820 headersw++;
|
|
2821 continue;
|
|
2822 case SHNHEAD:
|
|
2823 headersw = 0;
|
|
2824 continue;
|
|
2825 case SHSHOW:
|
|
2826 if (!(proc = *args++) || *proc == '-') {
|
|
2827 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
2828 return;
|
|
2829 }
|
|
2830 nshow = 0;
|
|
2831 continue;
|
|
2832 case SHNSHOW:
|
|
2833 nshow++;
|
|
2834 continue;
|
|
2835
|
|
2836 case SHDRAFT:
|
|
2837 advise (NULLCP, "sorry, -%s not allowed!", showswit[i].sw);
|
|
2838 return;
|
|
2839 }
|
|
2840 if (*cp == '+' || *cp == '@') {
|
|
2841 advise (NULLCP, "sorry, no folders allowed!");
|
|
2842 return;
|
|
2843 }
|
|
2844 else
|
|
2845 if (mode) {
|
|
2846 fprintf (stderr,
|
|
2847 "usage: %s [switches] [switches for showproc]\n",
|
|
2848 cmd_name);
|
|
2849 return;
|
|
2850 }
|
|
2851 else
|
|
2852 msgs[msgp++] = cp;
|
|
2853 }
|
|
2854 vec[vecp] = NULL;
|
|
2855
|
|
2856 if (!msgp)
|
|
2857 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
|
|
2858 for (msgnum = 0; msgnum < msgp; msgnum++)
|
|
2859 if (!m_convert (mp, msgs[msgnum]))
|
|
2860 return;
|
|
2861 m_setseq (mp);
|
|
2862
|
|
2863 #ifdef MIME
|
|
2864 if (!nshow && !getenv ("NOMHNPROC"))
|
|
2865 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
|
|
2866 if ((mp -> msgstats[msgnum] & SELECTED) && nontext (msgnum)) {
|
|
2867 proc = (cp = m_find ("mhnproc")) ? cp : "mhn";
|
|
2868 vec[vecp++] = "-show";
|
|
2869 vec[vecp++] = "-file";
|
|
2870 vec[vecp] = NULL;
|
|
2871 goto finish;
|
|
2872 }
|
|
2873 #endif /* MIME */
|
|
2874
|
|
2875 if (nshow)
|
|
2876 proc = "cat";
|
|
2877 else
|
|
2878 if (strcmp (showproc, "mhl") == 0) {
|
|
2879 proc = mhlproc;
|
|
2880 mhl++;
|
|
2881 }
|
|
2882
|
|
2883 finish: ;
|
|
2884 seen = m_seqflag (mp, "unseen");
|
|
2885 vec[0] = r1bindex (proc, '/');
|
|
2886 if (mhl) {
|
|
2887 msgp = vecp;
|
|
2888 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
|
|
2889 if (mp -> msgstats[msgnum] & SELECTED) {
|
|
2890 vec[vecp++] = getcpy (m_name (msgnum));
|
|
2891 if (seen)
|
|
2892 (void) m_seqdel (mp, "unseen", msgnum);
|
|
2893 }
|
|
2894 vec[vecp] = NULL;
|
|
2895 if (mp -> numsel == 1 && headersw)
|
|
2896 show (mp -> lowsel);
|
|
2897 (void) mhlsbr (vecp, vec, mhl_action);
|
|
2898 if (!fmsh)
|
|
2899 m_eomsbr ((int (*)()) 0);
|
|
2900 while (msgp < vecp)
|
|
2901 free (vec[msgp++]);
|
|
2902 }
|
|
2903 else {
|
|
2904 interrupted = 0;
|
|
2905 for (msgnum = mp -> lowsel;
|
|
2906 msgnum <= mp -> hghsel && !interrupted;
|
|
2907 msgnum++)
|
|
2908 if (mp -> msgstats[msgnum] & SELECTED) {
|
|
2909 switch (ask (msgnum)) {
|
|
2910 case NOTOK: /* QUIT */
|
|
2911 break;
|
|
2912
|
|
2913 case OK: /* INTR */
|
|
2914 continue;
|
|
2915
|
|
2916 default:
|
|
2917 if (mp -> numsel == 1 && headersw)
|
|
2918 show (msgnum);
|
|
2919 if (nshow)
|
|
2920 copy_message (msgnum, stdout);
|
|
2921 else
|
|
2922 (void) process (msgnum, proc, vecp, vec);
|
|
2923
|
|
2924 if (seen)
|
|
2925 (void) m_seqdel (mp, "unseen", msgnum);
|
|
2926 continue;
|
|
2927 }
|
|
2928 break;
|
|
2929 }
|
|
2930 }
|
|
2931
|
|
2932 m_setcur (mp, mp -> hghsel);
|
|
2933 }
|
|
2934
|
|
2935 /* */
|
|
2936
|
|
2937 static show (msgnum)
|
|
2938 int msgnum;
|
|
2939 {
|
|
2940 if (Msgs[msgnum].m_bboard_id == 0)
|
|
2941 (void) readid (msgnum);
|
|
2942
|
|
2943 printf ("(Message %d", msgnum);
|
|
2944 if (Msgs[msgnum].m_bboard_id > 0)
|
|
2945 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
|
|
2946 printf (")\n");
|
|
2947 }
|
|
2948
|
|
2949
|
|
2950 /* ARGSUSED */
|
|
2951
|
|
2952 static int eom_action (c)
|
|
2953 int c;
|
|
2954 {
|
|
2955 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
|
|
2956 }
|
|
2957
|
|
2958
|
|
2959 static FP mhl_action (name)
|
|
2960 char *name;
|
|
2961 {
|
|
2962 int msgnum;
|
|
2963
|
|
2964 if ((msgnum = m_atoi (name)) < mp -> lowmsg
|
|
2965 || msgnum > mp -> hghmsg
|
|
2966 || !(mp -> msgstats[msgnum] & EXISTS))
|
|
2967 return NULL;
|
|
2968 mhlnum = msgnum;
|
|
2969
|
|
2970 mhlfp = msh_ready (msgnum, 1);
|
|
2971 if (!fmsh)
|
|
2972 m_eomsbr (eom_action);
|
|
2973
|
|
2974 return mhlfp;
|
|
2975 }
|
|
2976
|
|
2977
|
|
2978 /* */
|
|
2979
|
|
2980 static ask (msgnum)
|
|
2981 int msgnum;
|
|
2982 {
|
|
2983 char buf[BUFSIZ];
|
|
2984
|
|
2985 if (mp -> numsel == 1 || !interactive || redirected)
|
|
2986 return DONE;
|
|
2987
|
|
2988 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
|
|
2989 if (mp -> lowsel != msgnum)
|
|
2990 printf ("\n\n\n");
|
|
2991 printf ("Press <return> to list \"%d\"...", msgnum);
|
|
2992 }
|
|
2993 (void) fflush (stdout);
|
|
2994 buf[0] = 0;
|
|
2995 #if !defined(BSD42) && !defined(SVR4)
|
|
2996 (void) read (fileno (stdout), buf, sizeof buf);
|
|
2997 #else /* BSD42 || SVR4 */
|
|
2998 switch (setjmp (sigenv)) {
|
|
2999 case OK:
|
|
3000 should_intr = 1;
|
|
3001 (void) read (fileno (stdout), buf, sizeof buf);/* fall... */
|
|
3002
|
|
3003 default:
|
|
3004 should_intr = 0;
|
|
3005 break;
|
|
3006 }
|
|
3007 #endif /* BSD42 || SVR4 */
|
|
3008 if (index (buf, '\n') == NULL)
|
|
3009 (void) putchar ('\n');
|
|
3010
|
|
3011 if (told_to_quit) {
|
|
3012 told_to_quit = interrupted = 0;
|
|
3013 return NOTOK;
|
|
3014 }
|
|
3015 if (interrupted) {
|
|
3016 interrupted = 0;
|
|
3017 return OK;
|
|
3018 }
|
|
3019
|
|
3020 return DONE;
|
|
3021 }
|
|
3022
|
|
3023 /* */
|
|
3024
|
|
3025 #ifdef MIME
|
|
3026 #include "../h/mhn.h"
|
|
3027
|
|
3028
|
|
3029 static int nontext (msgnum)
|
|
3030 int msgnum;
|
|
3031 {
|
|
3032 int result,
|
|
3033 state;
|
|
3034 register char *bp,
|
|
3035 *dp;
|
|
3036 char *chset,
|
|
3037 *cp,
|
|
3038 buf[BUFSIZ],
|
|
3039 name[NAMESZ];
|
|
3040 FILE *fp;
|
|
3041
|
|
3042 if (Msgs[msgnum].m_flags & MHNCHK)
|
|
3043 return (Msgs[msgnum].m_flags & MHNYES);
|
|
3044 Msgs[msgnum].m_flags |= MHNCHK;
|
|
3045
|
|
3046 fp = msh_ready (msgnum, 1);
|
|
3047
|
|
3048 if (!(chset = getenv ("MM_CHARSET")))
|
|
3049 #ifdef JAPAN
|
|
3050 chset = "iso-2022-jp";
|
|
3051 #else
|
|
3052 chset = "us-ascii";
|
|
3053 #endif /* JAPAN */
|
|
3054
|
|
3055 for (state = FLD;;)
|
|
3056 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
|
|
3057 case FLD:
|
|
3058 case FLDPLUS:
|
|
3059 case FLDEOF:
|
|
3060 if (uleq (name, TYPE_FIELD)) {
|
|
3061 int passno;
|
|
3062 char c;
|
|
3063
|
|
3064 cp = add (buf, NULLCP);
|
|
3065 while (state == FLDPLUS) {
|
|
3066 state = m_getfld (state, name, buf, sizeof buf, fp);
|
|
3067 cp = add (buf, cp);
|
|
3068 }
|
|
3069 bp = cp;
|
|
3070 passno = 1;
|
|
3071
|
|
3072 again: ;
|
|
3073 for (; isspace (*bp); bp++)
|
|
3074 continue;
|
|
3075 if (*bp == '(') {
|
|
3076 int i;
|
|
3077
|
|
3078 for (bp++, i = 0;;) {
|
|
3079 switch (*bp++) {
|
|
3080 case '\0':
|
|
3081 invalid: ;
|
|
3082 result = 0;
|
|
3083 goto out;
|
|
3084 case '\\':
|
|
3085 if (*bp++ == '\0')
|
|
3086 goto invalid;
|
|
3087 continue;
|
|
3088 case '(':
|
|
3089 i++;
|
|
3090 /* and fall... */
|
|
3091 default:
|
|
3092 continue;
|
|
3093 case ')':
|
|
3094 if (--i < 0)
|
|
3095 break;
|
|
3096 continue;
|
|
3097 }
|
|
3098 break;
|
|
3099 }
|
|
3100 for (; isspace (*bp); bp++)
|
|
3101 continue;
|
|
3102 }
|
|
3103 if (passno == 2) {
|
|
3104 if (*bp != '/')
|
|
3105 goto invalid;
|
|
3106 bp++;
|
|
3107 passno = 3;
|
|
3108 goto again;
|
|
3109 }
|
|
3110 else if (passno == 4) {
|
|
3111 if (*bp != ';')
|
|
3112 goto invalid;
|
|
3113 bp++;
|
|
3114 passno = 5;
|
|
3115 goto again;
|
|
3116 }
|
|
3117 for (dp = bp; istoken (*dp); dp++)
|
|
3118 continue;
|
|
3119 c = *dp, *dp = '\0';
|
|
3120 if (*bp == '\0')
|
|
3121 goto invalid;
|
|
3122 if (passno == 3) {
|
|
3123 if (result = !uleq (bp, "plain"))
|
|
3124 goto out;
|
|
3125 *dp = c;
|
|
3126 bp = dp;
|
|
3127 passno = 4;
|
|
3128 goto again;
|
|
3129 }
|
|
3130 if (passno > 1) {
|
|
3131 if (result = !uprf (bp, "charset"))
|
|
3132 goto invalid;
|
|
3133 *dp = c;
|
|
3134 while (isspace (*dp))
|
|
3135 dp++;
|
|
3136 if (*dp++ != '=')
|
|
3137 goto invalid;
|
|
3138 while (isspace (*dp))
|
|
3139 dp++;
|
|
3140 if (*dp == '"') {
|
|
3141 if (bp = index (++dp, '"'))
|
|
3142 *bp = '\0';
|
|
3143 }
|
|
3144 else
|
|
3145 for (bp = dp; *bp; bp++)
|
|
3146 if (!istoken (*bp)) {
|
|
3147 *bp = '\0';
|
|
3148 break;
|
|
3149 }
|
|
3150 if ((result = !uleq (dp, chset))
|
|
3151 && uleq (dp, "us-ascii")
|
|
3152 #ifdef JAPAN
|
|
3153 && (uleq (chset, "iso-2022-jp")
|
|
3154 || uleq (chset, "euc-jp")
|
|
3155 || uleq (chset, "shift_jis")
|
|
3156 || (uprf (chset, "iso-8859-")
|
|
3157 && m_atoi (chset+9) >= 1)))
|
|
3158 #else /* JAPAN */
|
|
3159 /* && uleq (chset, "iso-8859-1")) */
|
|
3160 && uprf (chset, "iso-8859-")
|
|
3161 && m_atoi (chset+9) >= 1)
|
|
3162 #endif /* JAPAN */
|
|
3163 result = 0;
|
|
3164 }
|
|
3165 else
|
|
3166 if (!(result = !uleq (bp, "text"))) {
|
|
3167 *dp = c;
|
|
3168 bp = dp;
|
|
3169 passno = 2;
|
|
3170 goto again;
|
|
3171 }
|
|
3172
|
|
3173 out: ;
|
|
3174 free (cp);
|
|
3175
|
|
3176 if (result) {
|
|
3177 Msgs[msgnum].m_flags |= MHNYES;
|
|
3178 return result;
|
|
3179 }
|
|
3180 break;
|
|
3181 }
|
|
3182 if (uleq (name, ENCODING_FIELD)) {
|
|
3183 cp = add (buf, NULLCP);
|
|
3184 while (state == FLDPLUS) {
|
|
3185 state = m_getfld (state, name, buf, sizeof buf, fp);
|
|
3186 cp = add (buf, cp);
|
|
3187 }
|
|
3188 for (bp = cp; isspace (*bp); bp++)
|
|
3189 continue;
|
|
3190 for (dp = bp; istoken (*dp); dp++)
|
|
3191 continue;
|
|
3192 *dp = '\0';
|
|
3193 result = !uleq (bp, "7bit")
|
|
3194 && !uleq (bp, "8bit")
|
|
3195 && !uleq (bp, "binary");
|
|
3196
|
|
3197 free (cp);
|
|
3198 if (result) {
|
|
3199 Msgs[msgnum].m_flags |= MHNYES;
|
|
3200 return result;
|
|
3201 }
|
|
3202 break;
|
|
3203 }
|
|
3204 while (state == FLDPLUS)
|
|
3205 state = m_getfld (state, name, buf, sizeof buf, fp);
|
|
3206 break;
|
|
3207
|
|
3208 default:
|
|
3209 return 0;
|
|
3210 }
|
|
3211 }
|
|
3212 #endif /* MIME */
|
|
3213
|
|
3214 /* */
|
|
3215
|
|
3216 static struct swit sortswit[] = {
|
|
3217 #define SODATE 0
|
|
3218 "datefield field", 0,
|
|
3219 #define SOSUBJ 1
|
|
3220 "textfield field", 0,
|
|
3221 #define SONSUBJ 2
|
|
3222 "notextfield", 0,
|
|
3223 #define SOLIMT 3
|
|
3224 "limit days", 0,
|
|
3225 #define SONLIMT 4
|
|
3226 "nolimit", 0,
|
|
3227 #define SOVERB 5
|
|
3228 "verbose", 0,
|
|
3229 #define SONVERB 6
|
|
3230 "noverbose", 0,
|
|
3231 #define SOHELP 7
|
|
3232 "help", 4,
|
|
3233
|
|
3234 NULL, 0
|
|
3235 };
|
|
3236
|
|
3237 /* */
|
|
3238
|
|
3239 sortcmd (args)
|
|
3240 char **args;
|
|
3241 {
|
|
3242 int msgp = 0,
|
|
3243 msgnum;
|
|
3244 char *cp,
|
|
3245 *datesw = NULL,
|
|
3246 *subjsw = NULL,
|
|
3247 buf[BUFSIZ],
|
|
3248 *msgs[MAXARGS];
|
|
3249 struct tws tb,
|
|
3250 *tw;
|
|
3251
|
|
3252 if (fmsh) {
|
|
3253 forkcmd (args, cmd_name);
|
|
3254 return;
|
|
3255 }
|
|
3256
|
|
3257 while (cp = *args++) {
|
|
3258 if (*cp == '-')
|
|
3259 switch (smatch (++cp, sortswit)) {
|
|
3260 case AMBIGSW:
|
|
3261 ambigsw (cp, sortswit);
|
|
3262 return;
|
|
3263 case UNKWNSW:
|
|
3264 fprintf (stderr, "-%s unknown\n", cp);
|
|
3265 return;
|
|
3266 case SOHELP:
|
|
3267 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
|
|
3268 help (buf, sortswit);
|
|
3269 return;
|
|
3270
|
|
3271 case SODATE:
|
|
3272 if (datesw) {
|
|
3273 advise (NULLCP, "only one date field at a time!");
|
|
3274 return;
|
|
3275 }
|
|
3276 if (!(datesw = *args++) || *datesw == '-') {
|
|
3277 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
3278 return;
|
|
3279 }
|
|
3280 continue;
|
|
3281
|
|
3282 case SOSUBJ:
|
|
3283 if (subjsw) {
|
|
3284 advise (NULLCP, "only one text field at a time!");
|
|
3285 return;
|
|
3286 }
|
|
3287 if (!(subjsw = *args++) || *subjsw == '-') {
|
|
3288 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
3289 return;
|
|
3290 }
|
|
3291 continue;
|
|
3292 case SONSUBJ:
|
|
3293 subjsw = (char *)0;
|
|
3294 continue;
|
|
3295
|
|
3296 case SOLIMT: /* too hard */
|
|
3297 if (!(cp = *args++) || *cp == '-') {
|
|
3298 advise (NULLCP, "missing argument to %s", args[-2]);
|
|
3299 return;
|
|
3300 }
|
|
3301 case SONLIMT:
|
|
3302 case SOVERB: /* not implemented */
|
|
3303 case SONVERB:
|
|
3304 continue;
|
|
3305 }
|
|
3306 if (*cp == '+' || *cp == '@') {
|
|
3307 advise (NULLCP, "sorry, no folders allowed!");
|
|
3308 return;
|
|
3309 }
|
|
3310 else
|
|
3311 msgs[msgp++] = cp;
|
|
3312 }
|
|
3313
|
|
3314 if (!msgp)
|
|
3315 msgs[msgp++] = "all";
|
|
3316 if (!datesw)
|
|
3317 datesw = "Date";
|
|
3318 for (msgnum = 0; msgnum < msgp; msgnum++)
|
|
3319 if (!m_convert (mp, msgs[msgnum]))
|
|
3320 return;
|
|
3321 m_setseq (mp);
|
|
3322
|
|
3323 twscopy (&tb, dtwstime ());
|
|
3324
|
|
3325 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) {
|
|
3326 if (Msgs[msgnum].m_scanl) {
|
|
3327 free (Msgs[msgnum].m_scanl);
|
|
3328 Msgs[msgnum].m_scanl = NULL;
|
|
3329 }
|
|
3330 if (mp -> msgstats[msgnum] & SELECTED) {
|
|
3331 if (getws (datesw, subjsw, msgnum, &Msgs[msgnum]))
|
|
3332 twscopy (&Msgs[msgnum].m_tb,
|
|
3333 msgnum != mp -> lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
|
|
3334 }
|
|
3335 else /* m_scaln is already NULL */
|
|
3336 twscopy (&Msgs[msgnum].m_tb, &tb);
|
|
3337 Msgs[msgnum].m_stats = mp -> msgstats[msgnum];
|
|
3338 if (mp -> curmsg == msgnum)
|
|
3339 Msgs[msgnum].m_stats |= CUR;
|
|
3340 }
|
|
3341
|
|
3342 qsort ((char *) &Msgs[mp -> lowsel], mp -> hghsel - mp -> lowsel + 1,
|
|
3343 sizeof (struct Msg),
|
|
3344 subjsw ? subsort : msgsort);
|
|
3345
|
|
3346 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) {
|
|
3347 if (subjsw && Msgs[msgnum].m_scanl) {
|
|
3348 free (Msgs[msgnum].m_scanl); /* from subjsort */
|
|
3349 Msgs[msgnum].m_scanl = NULL;
|
|
3350 }
|
|
3351 mp -> msgstats[msgnum] = Msgs[msgnum].m_stats & ~CUR;
|
|
3352 if (Msgs[msgnum].m_stats & CUR)
|
|
3353 m_setcur (mp, msgnum);
|
|
3354 }
|
|
3355
|
|
3356 mp -> msgflags |= MODIFIED;
|
|
3357 modified++;
|
|
3358 }
|
|
3359
|
|
3360 /* */
|
|
3361
|
|
3362 /*
|
|
3363 * getws - parse message, and get date and subject if needed. We'll use
|
|
3364 * the msgp->m_tb tws struct for the date, and overload the msgp->m_scanl
|
|
3365 * field with our subject string.
|
|
3366 */
|
|
3367 static int getws (datesw, subjsw, msgnum, msgp)
|
|
3368 char *datesw,
|
|
3369 *subjsw;
|
|
3370 int msgnum;
|
|
3371 struct Msg *msgp;
|
|
3372 {
|
|
3373 int state,
|
|
3374 gotdate = 0;
|
|
3375 char *bp,
|
|
3376 buf[BUFSIZ],
|
|
3377 name[NAMESZ];
|
|
3378 struct tws *tw = (struct tws *)0;
|
|
3379 register FILE *zp;
|
|
3380
|
|
3381 zp = msh_ready (msgnum, 0);
|
|
3382 for (state = FLD;;) {
|
|
3383 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
|
|
3384 case FLD:
|
|
3385 case FLDEOF:
|
|
3386 case FLDPLUS:
|
|
3387 if (uleq (name, datesw)) {
|
|
3388 bp = getcpy (buf);
|
|
3389 while (state == FLDPLUS) {
|
|
3390 state = m_getfld (state, name, buf, sizeof buf, zp);
|
|
3391 bp = add (buf, bp);
|
|
3392 }
|
|
3393 if ((tw = dparsetime (bp)) == NULL)
|
|
3394 admonish (NULLCP,
|
|
3395 "unable to parse %s field in message %d",
|
|
3396 datesw, msgnum);
|
|
3397 else
|
|
3398 twscopy (&(msgp->m_tb), tw);
|
|
3399 free (bp);
|
|
3400 if (!subjsw) /* not using this, or already done */
|
|
3401 break; /* all done! */
|
|
3402 gotdate++;
|
|
3403 }
|
|
3404 else if (subjsw && uleq(name, subjsw)) {
|
|
3405 bp = getcpy (buf);
|
|
3406 while (state == FLDPLUS) {
|
|
3407 state = m_getfld (state, name, buf, sizeof buf, zp);
|
|
3408 bp = add (buf, bp);
|
|
3409 }
|
|
3410 msgp->m_scanl = sosmash(subjsw, bp);
|
|
3411 if (gotdate)
|
|
3412 break; /* date done so we're done */
|
|
3413 else
|
|
3414 subjsw = (char *)0;/* subject done, need date */
|
|
3415 } else {
|
|
3416 while (state == FLDPLUS) /* flush this one */
|
|
3417 state = m_getfld (state, name, buf, sizeof buf, zp);
|
|
3418 }
|
|
3419 continue;
|
|
3420
|
|
3421 case BODY:
|
|
3422 case BODYEOF:
|
|
3423 case FILEEOF:
|
|
3424 break;
|
|
3425
|
|
3426 case LENERR:
|
|
3427 case FMTERR:
|
|
3428 admonish (NULLCP, "format error in message %d", msgnum);
|
|
3429 if (msgp->m_scanl) { /* this might need free'd */
|
|
3430 free (msgp->m_scanl); /* probably can't use subj anyway */
|
|
3431 msgp->m_scanl = NULL;
|
|
3432 }
|
|
3433 return NOTOK;
|
|
3434
|
|
3435 default:
|
|
3436 adios (NULLCP, "internal error -- you lose");
|
|
3437 }
|
|
3438 break;
|
|
3439 }
|
|
3440 if (tw)
|
|
3441 return OK; /* not an error if subj not found */
|
|
3442
|
|
3443 admonish (NULLCP, "no %s field in message %d", datesw, msgnum);
|
|
3444 return NOTOK; /* NOTOK means use some other date */
|
|
3445 }
|
|
3446
|
|
3447 /* sort routines */
|
|
3448
|
|
3449 static int msgsort (a, b)
|
|
3450 struct Msg *a,
|
|
3451 *b;
|
|
3452 {
|
|
3453 return twsort (&a -> m_tb, &b -> m_tb);
|
|
3454 }
|
|
3455
|
|
3456 static int subsort (a, b)
|
|
3457 struct Msg *a,
|
|
3458 *b;
|
|
3459 {
|
|
3460 register int i;
|
|
3461
|
|
3462 if (a->m_scanl && b->m_scanl)
|
|
3463 if (i = strcmp (a->m_scanl, b->m_scanl))
|
|
3464 return (i);
|
|
3465
|
|
3466 return twsort (&a -> m_tb, &b -> m_tb);
|
|
3467 }
|
|
3468
|
|
3469 /*
|
|
3470 * try to make the subject "canonical": delete leading "re:", everything
|
|
3471 * but letters & smash letters to lower case.
|
|
3472 */
|
|
3473 static char *
|
|
3474 sosmash (subj, s)
|
|
3475 char *subj;
|
|
3476 register char *s;
|
|
3477 {
|
|
3478 register char *cp,
|
|
3479 *dp,
|
|
3480 c;
|
|
3481 if (s) {
|
|
3482 cp = s;
|
|
3483 dp = s; /* dst pointer */
|
|
3484 if (uleq (subj, "subject"))
|
|
3485 while (c = *cp) {
|
|
3486 if (! isspace(c)) {
|
|
3487 if(uprf(cp, "re:"))
|
|
3488 cp += 2;
|
|
3489 else {
|
|
3490 if (isalnum(c))
|
|
3491 *dp++ = isupper(c) ? tolower(c) : c;
|
|
3492 break;
|
|
3493 }
|
|
3494 }
|
|
3495 cp++;
|
|
3496 }
|
|
3497 while (c = *cp++) {
|
|
3498 if (isalnum(c))
|
|
3499 *dp++ = isupper(c) ? tolower(c) : c;
|
|
3500
|
|
3501 }
|
|
3502 *dp = '\0';
|
|
3503 }
|
|
3504 return s;
|
|
3505 }
|
|
3506
|
|
3507 /* */
|
|
3508
|
|
3509 static int process (msgnum, proc, vecp, vec)
|
|
3510 int msgnum,
|
|
3511 vecp;
|
|
3512 char *proc,
|
|
3513 **vec;
|
|
3514 {
|
|
3515 int child_id,
|
|
3516 status;
|
|
3517 char tmpfil[80];
|
|
3518 FILE *out;
|
|
3519
|
|
3520 if (fmsh) {
|
|
3521 (void) strcpy (tmpfil, m_name (msgnum));
|
|
3522 (void) m_delete (pfolder);
|
|
3523 m_replace (pfolder, fmsh);
|
|
3524 m_sync (mp);
|
|
3525 m_update ();
|
|
3526 goto ready;
|
|
3527 }
|
|
3528
|
|
3529 (void) strcpy (tmpfil, m_scratch ("", invo_name));
|
|
3530 if ((out = fopen (tmpfil, "w")) == NULL) {
|
|
3531 int olderr;
|
|
3532 extern int errno;
|
|
3533 char newfil[80];
|
|
3534
|
|
3535 olderr = errno;
|
|
3536 (void) strcpy (newfil, m_tmpfil (invo_name));
|
|
3537 if ((out = fopen (newfil, "w")) == NULL) {
|
|
3538 errno = olderr;
|
|
3539 advise (tmpfil, "unable to create temporary file");
|
|
3540 return NOTOK;
|
|
3541 }
|
|
3542 else
|
|
3543 (void) strcpy (tmpfil, newfil);
|
|
3544 }
|
|
3545 copy_message (msgnum, out);
|
|
3546 (void) fclose (out);
|
|
3547
|
|
3548 ready: ;
|
|
3549 (void) fflush (stdout);
|
|
3550 switch (child_id = fork ()) {
|
|
3551 case NOTOK:
|
|
3552 advise ("fork", "unable to");
|
|
3553 status = NOTOK;
|
|
3554 break;
|
|
3555
|
|
3556 case OK:
|
|
3557 closefds (3);
|
|
3558 (void) signal (SIGINT, istat);
|
|
3559 (void) signal (SIGQUIT, qstat);
|
|
3560
|
|
3561 vec[vecp++] = tmpfil;
|
|
3562 vec[vecp] = NULL;
|
|
3563
|
|
3564 execvp (proc, vec);
|
|
3565 fprintf (stderr, "unable to exec ");
|
|
3566 perror (proc);
|
|
3567 _exit (1);
|
|
3568
|
|
3569 default:
|
|
3570 status = pidXwait (child_id, NULLCP);
|
|
3571 break;
|
|
3572 }
|
|
3573
|
|
3574 if (!fmsh)
|
|
3575 (void) unlink (tmpfil);
|
|
3576 return status;
|
|
3577 }
|
|
3578
|
|
3579 /* */
|
|
3580
|
|
3581 static copy_message (msgnum, out)
|
|
3582 int msgnum;
|
|
3583 FILE * out;
|
|
3584 {
|
|
3585 long pos;
|
|
3586 static char buffer[BUFSIZ];
|
|
3587 register FILE * zp;
|
|
3588
|
|
3589 zp = msh_ready (msgnum, 1);
|
|
3590 if (fmsh) {
|
|
3591 while (fgets (buffer, sizeof buffer, zp) != NULL) {
|
|
3592 fputs (buffer, out);
|
|
3593 if (interrupted && out == stdout)
|
|
3594 break;
|
|
3595 }
|
|
3596 }
|
|
3597 else {
|
|
3598 pos = ftell (zp);
|
|
3599 while (fgets (buffer, sizeof buffer, zp) != NULL
|
|
3600 && pos < Msgs[msgnum].m_stop) {
|
|
3601 fputs (buffer, out);
|
|
3602 pos += (long) strlen (buffer);
|
|
3603 if (interrupted && out == stdout)
|
|
3604 break;
|
|
3605 }
|
|
3606 }
|
|
3607 }
|
|
3608
|
|
3609
|
|
3610 static copy_digest (msgnum, out)
|
|
3611 int msgnum;
|
|
3612 FILE * out;
|
|
3613 {
|
|
3614 char c;
|
|
3615 long pos;
|
|
3616 static char buffer[BUFSIZ];
|
|
3617 register FILE *zp;
|
|
3618
|
|
3619 c = '\n';
|
|
3620 zp = msh_ready (msgnum, 1);
|
|
3621 if (!fmsh)
|
|
3622 pos = ftell (zp);
|
|
3623 while (fgets (buffer, sizeof buffer, zp) != NULL
|
|
3624 && !fmsh && pos < Msgs[msgnum].m_stop) {
|
|
3625 if (c == '\n' && *buffer == '-')
|
|
3626 (void) fputc (' ', out);
|
|
3627 fputs (buffer, out);
|
|
3628 c = buffer[strlen (buffer) - 1];
|
|
3629 if (!fmsh)
|
|
3630 pos += (long) strlen (buffer);
|
|
3631 if (interrupted && out == stdout)
|
|
3632 break;
|
|
3633 }
|
|
3634 }
|