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