]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/folder.c
Always check that mktemp()/mktemp2() succeeds before trying to
[nmh] / docs / historical / mh-6.8.5 / uip / folder.c
1 /* folder(s).c - report on folders */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: folder.c,v 2.11 1993/08/27 23:23:06 jromine Exp $";
4 #endif /* lint */
5
6 #include "../h/mh.h"
7 #include "../h/local.h"
8 #include <errno.h>
9 #include <stdio.h>
10 #ifdef LOCALE
11 #include <locale.h>
12 #endif
13
14 static dodir(), addir(), addfold(), dother();
15 static int pfold(), sfold(), compare();
16 /* \f */
17
18 static struct swit switches[] = {
19 #define ALLSW 0
20 "all", 0,
21
22 #define CREATSW 1
23 "create", 0,
24 #define NCREATSW 2
25 "nocreate", 0,
26
27 #define FASTSW 3
28 "fast", 0,
29 #define NFASTSW 4
30 "nofast", 0,
31
32 #define HDRSW 5
33 "header", 0,
34 #define NHDRSW 6
35 "noheader", 0,
36
37 #define PACKSW 7
38 "pack", 0,
39 #define NPACKSW 8
40 "nopack", 0,
41 #define VERBSW 9
42 "verbose", 0,
43 #define NVERBSW 10
44 "noverbose", 0,
45
46 #define RECURSW 11
47 "recurse", 0,
48 #define NRECRSW 12
49 "norecurse", 0,
50
51 #define TOTALSW 13
52 "total", 0,
53 #define NTOTLSW 14
54 "nototal", 0,
55
56 #define PRNTSW 15
57 "print", 0,
58 #define NPRNTSW 16
59 "noprint", -4,
60 #define LISTSW 17
61 "list", 0,
62 #define NLISTSW 18
63 "nolist", 0,
64 #define PUSHSW 19
65 "push", 0,
66 #define POPSW 20
67 "pop", 0,
68
69 #define HELPSW 21
70 "help", 4,
71
72 NULL, 0
73 };
74
75 /* \f */
76
77 extern int errno;
78
79 static int fshort = 0;
80 static int fcreat = 0;
81 static int fpack = 0;
82 static int fverb = 0;
83 static int fheader = 0;
84 static int frecurse = 0;
85 static int ftotonly = 0;
86 static int msgtot = 0;
87 static int foldtot = 0;
88 static int start = 0;
89 static int foldp = 0;
90
91 static char *mhdir;
92 static char *stack = "Folder-Stack";
93 static char folder[BUFSIZ];
94 static char *folds[NFOLDERS + 1];
95
96 struct msgs *tfold ();
97
98 /* \f */
99
100 /* ARGSUSED */
101
102 main (argc, argv)
103 char *argv[];
104 {
105 int all = 0,
106 printsw = 0,
107 listsw = 0,
108 pushsw = 0,
109 popsw = 0;
110 char *cp,
111 *dp,
112 *msg = NULL,
113 *argfolder = NULL,
114 **ap,
115 **argp,
116 buf[100],
117 *arguments[MAXARGS];
118 struct stat st;
119
120 #ifdef LOCALE
121 setlocale(LC_ALL, "");
122 #endif
123 invo_name = r1bindex (argv[0], '/');
124 if (argv[0][strlen (argv[0]) - 1] == 's')
125 all++;
126 if ((cp = m_find (invo_name)) != NULL) {
127 ap = brkstring (cp = getcpy (cp), " ", "\n");
128 ap = copyip (ap, arguments);
129 }
130 else
131 ap = arguments;
132 (void) copyip (argv + 1, ap);
133 argp = arguments;
134
135 /* \f */
136
137 while (cp = *argp++) {
138 if (*cp == '-')
139 switch (smatch (++cp, switches)) {
140 case AMBIGSW:
141 ambigsw (cp, switches);
142 done (1);
143 case UNKWNSW:
144 adios (NULLCP, "-%s unknown", cp);
145 case HELPSW:
146 (void) sprintf (buf, "%s [+folder] [msg] [switches]",
147 invo_name);
148 help (buf, switches);
149 done (1);
150
151 case ALLSW:
152 all++;
153 continue;
154
155 case CREATSW:
156 fcreat = 1;
157 continue;
158 case NCREATSW:
159 fcreat = -1;
160 continue;
161
162 case FASTSW:
163 fshort++;
164 continue;
165 case NFASTSW:
166 fshort = 0;
167 continue;
168
169 case HDRSW:
170 fheader = -1;
171 continue;
172 case NHDRSW:
173 fheader++;
174 continue;
175
176 case PACKSW:
177 fpack++;
178 continue;
179 case NPACKSW:
180 fpack = 0;
181 continue;
182
183 case VERBSW:
184 fverb++;
185 continue;
186 case NVERBSW:
187 fverb = 0;
188 continue;
189
190 case RECURSW:
191 frecurse++;
192 continue;
193 case NRECRSW:
194 frecurse = 0;
195 continue;
196
197 case TOTALSW:
198 all++;
199 ftotonly++;
200 continue;
201 case NTOTLSW:
202 if (ftotonly)
203 all = 0;
204 ftotonly = 0;
205 continue;
206
207 case PRNTSW:
208 printsw++;
209 continue;
210 case NPRNTSW:
211 printsw = 0;
212 continue;
213
214 case LISTSW:
215 listsw++;
216 continue;
217 case NLISTSW:
218 listsw = 0;
219 continue;
220
221 case PUSHSW:
222 pushsw++;
223 listsw++;
224 popsw = 0;
225 continue;
226 case POPSW:
227 popsw++;
228 listsw++;
229 pushsw = 0;
230 continue;
231 }
232 if (*cp == '+' || *cp == '@')
233 if (argfolder)
234 adios (NULLCP, "only one folder at a time!");
235 else
236 argfolder = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
237 else
238 if (msg)
239 adios (NULLCP, "only one (current) message at a time!");
240 else
241 msg = cp;
242 }
243
244 /* \f */
245
246 if (!m_find ("path"))
247 free (path ("./", TFOLDER));
248 mhdir = concat (m_maildir (""), "/", NULLCP);
249
250 if (pushsw == 0 && popsw == 0 && listsw == 0)
251 printsw++;
252 if (pushsw) {
253 if (!argfolder) {
254 if ((cp = m_find (stack)) == NULL
255 || (ap = brkstring (dp = getcpy (cp), " ", "\n")) == NULL
256 || (argfolder = *ap++) == NULL)
257 adios (NULLCP, "no other folder");
258 for (cp = getcpy (m_getfolder ()); *ap; ap++)
259 cp = add (*ap, add (" ", cp));
260 free (dp);
261 m_replace (stack, cp);
262 }
263 else
264 m_replace (stack,
265 (cp = m_find (stack))
266 ? concat (m_getfolder (), " ", cp, NULLCP)
267 : getcpy (m_getfolder ()));
268 }
269 if (popsw) {
270 if (argfolder)
271 adios (NULLCP, "sorry, no folders allowed with -pop");
272 if ((cp = m_find (stack)) == NULL
273 || (ap = brkstring (dp = getcpy (cp), " ", "\n")) == NULL
274 || (argfolder = *ap++) == NULL)
275 adios (NULLCP, "folder stack empty");
276 for (cp = NULL; *ap; ap++)
277 cp = cp ? add (*ap, add (" ", cp)) : getcpy (*ap);
278 free (dp);
279 if (cp)
280 m_replace (stack, cp);
281 else
282 (void) m_delete (stack);
283 }
284 if (pushsw || popsw) {
285 if (access (cp = m_maildir (argfolder), 0) == NOTOK)
286 adios (cp, "unable to find folder");
287 m_replace (pfolder, argfolder);
288 m_update ();
289 argfolder = NULL;
290 }
291 if (listsw) {
292 printf ("%s", argfolder ? argfolder : m_getfolder ());
293 if (cp = m_find (stack)) {
294 for (ap = brkstring (dp = getcpy (cp), " ", "\n"); *ap; ap++)
295 printf (" %s", *ap);
296 free (dp);
297 }
298 printf ("\n");
299
300 if (!printsw)
301 done (0);
302 }
303
304 /* \f */
305
306 if (all) {
307 fheader = 0;
308 if (argfolder) {
309 (void) strcpy (folder, argfolder);
310 if (pfold (argfolder, msg)) {
311 m_replace (pfolder, argfolder);
312 m_update ();
313 }
314 if (!frecurse) /* recurse not done in pfold(), */
315 dodir (folder); /* so just list all level-1 sub-folders */
316 }
317 else {
318 if (msg)
319 admonish (NULLCP, "no folder given for message %s", msg);
320 dother ();
321
322 (void) strcpy (folder, (cp = m_find (pfolder)) ? cp : "");
323 dodir (".");
324 }
325
326 if (!fshort) {
327 if (!ftotonly)
328 printf ("\n\t\t ");
329 printf ("TOTAL= %*d message%c in %d folder%s.\n",
330 DMAXFOLDER, msgtot, msgtot != 1 ? 's' : ' ',
331 foldtot, foldtot != 1 ? "s" : "");
332 }
333 }
334 else {
335 fheader++;
336
337 (void) strcpy (folder, argfolder ? argfolder : m_getfolder ());
338 if (stat (strcpy (buf, m_maildir (folder)), &st) == NOTOK) {
339 if (errno != ENOENT)
340 adios (buf, "error on folder");
341 switch (fcreat) {
342 case 0: /* ask before create */
343 cp = concat ("Create folder \"", buf, "\"? ", NULLCP);
344 if (!getanswer (cp))
345 done (1);
346 free (cp);
347 break;
348 case -1: /* do not create */
349 done (1);
350 break;
351 }
352 if (!makedir (buf))
353 adios (NULLCP, "unable to create folder %s", buf);
354 }
355
356 if (pfold (folder, msg) && argfolder)
357 m_replace (pfolder, argfolder);
358 }
359
360 m_update ();
361
362 done (0);
363 }
364
365 /* \f */
366
367 static dodir (dir)
368 register char *dir;
369 {
370 int i;
371 int os = start;
372 int of = foldp;
373 char buffer[BUFSIZ];
374
375 start = foldp;
376 if (chdir (mhdir) == NOTOK)
377 adios (mhdir, "unable to change directory to");
378
379 addir (strcpy (buffer, dir));
380 for (i = start; i < foldp; i++)
381 (void) pfold (folds[i], NULLCP), (void) fflush (stdout);
382
383 start = os;
384 foldp = of;
385 }
386
387 /* \f */
388
389 static int pfold (fold, msg)
390 register char *fold,
391 *msg;
392 {
393 int hack,
394 others,
395 retval = 1;
396 register char *mailfile;
397 register struct msgs *mp = NULL;
398
399 mailfile = m_maildir (fold);
400 if (chdir (mailfile) == NOTOK) {
401 if (errno != EACCES)
402 admonish (mailfile, "unable to change directory to");
403 else
404 printf ("%22s%c unreadable\n",
405 fold, strcmp (folder, fold) ? ' ' : '+');
406 return 0;
407 }
408
409 if (fshort) {
410 printf ("%s\n", fold);
411
412 if (!msg && !fpack) {
413 if (frecurse)
414 dodir (fold);
415 return retval;
416 }
417 }
418
419 if (!(mp = m_gmsg (fold))) {
420 admonish (NULLCP, "unable to read folder %s", fold);
421 return 0;
422 }
423
424 if (msg && !sfold (mp, msg))
425 retval = 0;
426 if (fpack)
427 mp = tfold (mp);
428
429 if (fshort)
430 goto out;
431 foldtot++;
432 msgtot += mp -> nummsg;
433
434 if (ftotonly)
435 goto out;
436
437 if (!fheader++)
438 printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg (other files)\n",
439 DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
440 DMAXFOLDER - 2, "");
441
442 printf ("%22s%c ", fold, strcmp (folder, fold) ? ' ' : '+');
443
444 hack = 0;
445 if (mp -> hghmsg == 0)
446 printf ("has no messages%*s",
447 mp -> msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
448 else {
449 printf ("has %*d message%s (%*d-%*d)",
450 DMAXFOLDER, mp -> nummsg, (mp -> nummsg == 1) ? " " : "s",
451 DMAXFOLDER, mp -> lowmsg, DMAXFOLDER, mp -> hghmsg);
452 if (mp -> curmsg >= mp -> lowmsg && mp -> curmsg <= mp -> hghmsg)
453 printf ("; cur=%*d", DMAXFOLDER, hack = mp -> curmsg);
454 }
455
456 if (mp -> msgflags & OTHERS)
457 printf (";%*s (others)", hack ? 0 : DMAXFOLDER + 6, "");
458 printf (".\n");
459
460 out: ;
461 others = mp -> msgflags & OTHERS;
462 m_fmsg (mp);
463
464 if (frecurse && others)
465 dodir (fold);
466
467 return retval;
468 }
469
470 /* \f */
471
472 static int sfold (mp, msg)
473 register struct msgs *mp;
474 char *msg;
475 {
476 if (!m_convert (mp, msg))
477 return 0;
478
479 if (mp -> numsel > 1) {
480 admonish (NULLCP, "only one message at a time!");
481 return 0;
482 }
483 m_setseq (mp);
484 m_setcur (mp, mp -> lowsel);
485 m_sync (mp);
486 m_update ();
487
488 return 1;
489 }
490
491
492 struct msgs *tfold (mp)
493 register struct msgs *mp;
494 {
495 register int hole,
496 msgnum;
497 char newmsg[BUFSIZ],
498 oldmsg[BUFSIZ];
499
500 if (mp -> lowmsg > 1 && (mp = m_remsg (mp, 1, mp -> hghmsg)) == NULL)
501 adios (NULLCP, "unable to allocate folder storage");
502
503 for (msgnum = mp -> lowmsg, hole = 1; msgnum <= mp -> hghmsg; msgnum++)
504 if (mp -> msgstats[msgnum] & EXISTS) {
505 if (msgnum != hole) {
506 (void) strcpy (newmsg, m_name (hole));
507 (void) strcpy (oldmsg, m_name (msgnum));
508 if (fverb)
509 printf ("message %s becomes %s\n", oldmsg, newmsg);
510 if (rename (oldmsg, newmsg) == NOTOK)
511 adios (newmsg, "unable to rename %s to", oldmsg);
512 if (msgnum == mp -> curmsg)
513 m_setcur (mp, mp -> curmsg = hole);
514 mp -> msgstats[hole] = mp -> msgstats[msgnum];
515 mp -> msgflags |= SEQMOD;
516 if (msgnum == mp -> lowsel)
517 mp -> lowsel = hole;
518 if (msgnum == mp -> hghsel)
519 mp -> hghsel = hole;
520 }
521 hole++;
522 }
523 if (mp -> nummsg > 0) {
524 mp -> lowmsg = 1;
525 mp -> hghmsg = hole - 1;
526 }
527 m_sync (mp);
528 m_update ();
529
530 return mp;
531 }
532
533 /* \f */
534
535 static addir (name)
536 register char *name;
537 {
538 register char *base,
539 *cp;
540 struct stat st;
541 #ifdef SYS5DIR
542 register struct dirent *dp;
543 #else /* SYS5DIR */
544 register struct direct *dp;
545 #endif /* SYS5DIR */
546 register DIR * dd;
547
548 cp = name + strlen (name);
549 *cp++ = '/';
550 *cp = '\0';
551
552 base = strcmp (name, "./") ? name : name + 2;/* hack */
553
554 if ((dd = opendir (name)) == NULL) {
555 admonish (name, "unable to read directory ");
556 return;
557 }
558 while (dp = readdir (dd))
559 if (strcmp (dp -> d_name, ".") && strcmp (dp -> d_name, "..")) {
560 #ifdef SYS5DIR
561 if (cp + dp -> d_reclen + 2 >= name + BUFSIZ)
562 #else /* SYS5DIR */
563 if (cp + strlen (dp -> d_name) + 2 >= name + BUFSIZ)
564 #endif /* SYS5DIR */
565 continue;
566 (void) strcpy (cp, dp -> d_name);
567 if (stat (name, &st) != NOTOK && (st.st_mode & S_IFMT) == S_IFDIR)
568 addfold (base);
569 }
570 closedir (dd);
571
572 *--cp = '\0';
573 }
574
575 /* \f */
576
577 static addfold (fold)
578 register char *fold;
579 {
580 register int i,
581 j;
582 register char *cp;
583
584 if (foldp > NFOLDERS)
585 adios (NULLCP, "more than %d folders to report on", NFOLDERS);
586
587 cp = getcpy (fold);
588 for (i = start; i < foldp; i++)
589 if (compare (cp, folds[i]) < 0) {
590 for (j = foldp - 1; j >= i; j--)
591 folds[j + 1] = folds[j];
592 foldp++;
593 folds[i] = cp;
594 return;
595 }
596
597 folds[foldp++] = cp;
598 }
599
600 /* \f */
601
602 static int compare (s1, s2)
603 register char *s1,
604 *s2;
605 {
606 register int i;
607
608 while (*s1 || *s2)
609 if (i = *s1++ - *s2++)
610 return i;
611
612 return 0;
613 }
614
615 /* \f */
616
617 static dother () {
618 int atrlen;
619 char atrcur[BUFSIZ];
620 register struct node *np;
621
622 (void) sprintf (atrcur, "atr-%s-", current);
623 atrlen = strlen (atrcur);
624
625 m_getdefs ();
626 for (np = m_defs; np; np = np -> n_next)
627 if (ssequal (atrcur, np -> n_name)
628 && !ssequal (mhdir, np -> n_name + atrlen))
629 (void) pfold (np -> n_name + atrlen, NULLCP);
630 }