]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/bbl.c
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / uip / bbl.c
1 /* bbl.c - ease the tasks of a BBleader */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: bbl.c,v 2.4 1992/11/04 00:39:25 jromine Exp $";
4 #endif lint
5
6 #include "../h/mh.h"
7 #include "../h/local.h"
8 #include "../zotnet/bboards.h"
9 #include <ctype.h>
10 #include <pwd.h>
11 #include <stdio.h>
12 #ifdef LOCALE
13 #include <locale.h>
14 #endif
15
16 /* \f */
17
18 static struct swit switches[] = {
19 #define SHELLSW 0
20 "shell program", 0,
21
22 #define VERBSW 1
23 "verbose", 0,
24 #define NVERBSW 2
25 "noverbose", 0,
26
27 #define HELPSW 3
28 "help", 4,
29
30 NULL, NULL
31 };
32
33 /* \f */
34
35 static int verbosw = 0;
36
37 static int sub_ok = 0;
38
39 static char *bboards = BBOARDS;
40
41 static char *cwd = NULL;
42
43 static char *current_folder = NULL;
44
45 static char *bbfolder = NULL;
46 static char subfolder[BUFSIZ];
47
48 static struct stat bbstat;
49 static struct stat substat;
50
51 static char *shell = "/bin/sh";
52
53 static struct bboard *bb = NULL;
54
55
56 #ifndef __STDC__
57 #ifdef SYS5
58 struct passwd *getpwnam (), *getpwuid ();
59 #endif /* SYS5 */
60 #endif
61
62 /* \f */
63
64 /* ARGSUSED */
65
66 main (argc, argv)
67 int argc;
68 char **argv;
69 {
70 char *cp,
71 **ap,
72 **argp,
73 buffer[80],
74 *arguments[MAXARGS];
75 struct passwd *pw;
76
77 #ifdef LOCALE
78 setlocale(LC_ALL, "");
79 #endif
80 invo_name = r1bindex (argv[0], '/');
81 if ((cp = m_find (invo_name)) != NULL) {
82 ap = brkstring (cp = getcpy (cp), " ", "\n");
83 ap = copyip (ap, arguments);
84 }
85 else
86 ap = arguments;
87 (void) copyip (argv + 1, ap);
88 argp = arguments;
89
90 if ((shell = getenv ("SHELL")) == NULL)
91 if ((pw = getpwuid (getuid ())) != NULL
92 && pw -> pw_shell
93 && *pw -> pw_shell)
94 shell = getcpy (pw -> pw_shell);
95
96 if ((pw = getpwnam (bboards)) == NULL)
97 adios (NULLCP, "no entry for ~%s", bboards);
98 if (pw -> pw_uid != geteuid ())
99 adios (NULLCP, "not running setuid to %s", bboards);
100
101 current_folder = ((cp = m_find (pfolder)) || (cp = m_find (inbox)))
102 ? getcpy (cp) : defalt;
103
104 /* \f */
105
106 while (cp = *argp++) {
107 if (*cp == '-')
108 switch (smatch (++cp, switches)) {
109 case AMBIGSW:
110 ambigsw (cp, switches);
111 done (1);
112 case UNKWNSW:
113 adios (NULLCP, "-%s unknown", cp);
114 case HELPSW:
115 (void) sprintf (buffer, "%s [+folder] [switches] bboard",
116 invo_name);
117 help (buffer, switches);
118 done (1);
119
120 case SHELLSW:
121 if (!(shell = *argp++) || *shell == '-')
122 adios (NULLCP, "missing argument to %s", argp[-2]);
123 continue;
124
125 case VERBSW:
126 verbosw++;
127 continue;
128 case NVERBSW:
129 verbosw = 0;
130 continue;
131 }
132 if (*cp == '+')
133 if (bbfolder)
134 adios (NULLCP, "only one folder at a time!");
135 else
136 bbfolder = cp;
137 else
138 if (bb != NULL)
139 adios (NULLCP, "only one BBoard a time!");
140 else
141 if ((bb = getbbnam (cp)) == NULL
142 && (bb = getbbaka (cp)) == NULL)
143 adios (NULLCP, "no such BBoard as '%s'", cp);
144 }
145
146 /* \f */
147
148 if (!bb)
149 adios (NULLCP, "no BBoard specified");
150 if (!bbfolder)
151 bbfolder = "+bbl";
152 (void) sprintf (subfolder, "%s/arc", bbfolder);
153
154 if (!m_find ("path"))
155 free (path ("./", TFOLDER));
156 cwd = getcpy (pwd ());
157
158 process ();
159
160 m_replace (pfolder, current_folder);
161 m_update ();
162
163 done (0);
164 }
165
166 /* \f */
167
168 process () {
169 int child_id;
170 char buffer[BUFSIZ];
171
172 if (!ldrbb (bb) && !ldrchk (bb))
173 return;
174
175 if (stat (bb -> bb_file, &bbstat) == NOTOK)
176 adios (NULLCP, "no such file as %s", bb -> bb_file);
177
178 if (stat (bb -> bb_archive, &substat) != NOTOK
179 && substat.st_size > 0)
180 sub_ok++;
181 /* else */
182 substat.st_mode = bbstat.st_mode;/* archive should always match */
183 substat.st_gid = bbstat.st_gid;/* actual bboard mode & gid */
184
185 /* do subfolder first, since you will lose otherwise... */
186 (void) sprintf (buffer, "Remove messages currently in %s? ", subfolder);
187 if (check_folder (subfolder) && getanswer (buffer))
188 rmf (subfolder);
189
190 (void) sprintf (buffer, "Remove messages currently in %s? ", bbfolder);
191 if (check_folder (bbfolder) && getanswer (buffer))
192 rmf (bbfolder);
193
194 switch (child_id = fork ()) {
195 case NOTOK:
196 adios ("fork", "unable to");
197
198 case OK:
199 do_child (); /* NOTREACHED */
200
201 default:
202 do_parent (child_id);
203 break;
204 }
205 }
206
207 /* \f */
208
209 int check_folder (folder)
210 char *folder;
211 {
212 char *maildir;
213 struct stat st;
214 struct msgs *mp;
215
216 maildir = m_maildir (folder + 1);
217
218 if (stat (maildir, &st) == NOTOK)
219 return 0;
220
221 if ((st.st_mode & S_IFMT) != S_IFDIR)
222 adios (NULLCP, "not a directory '%s'", maildir);
223 check_mode (maildir, (st.st_mode | 0555) & 0777);
224
225 if (chdir (maildir) == NOTOK)
226 adios (maildir, "unable to change to");
227 if (!(mp = m_gmsg (folder + 1)))
228 adios (NULLCP, "unable to read %s", folder);
229
230 if (chdir (cwd) == NOTOK)
231 admonish (cwd, "could not change back to");
232 return (mp -> hghmsg != 0);
233 }
234
235 /* \f */
236
237 do_parent (child_id)
238 int child_id;
239 {
240 int zap = 0;
241 char buffer[BUFSIZ];
242
243 if (pidwait (child_id, NOTOK) == NOTOK)
244 done (1);
245
246 (void) putchar ('\n');
247
248 (void) check_folder (bbfolder);
249 if (getanswer ("Incorporate changes? "))
250 update (&bbstat, bb -> bb_file, bbfolder, bb -> bb_info, bb -> bb_map);
251 (void) sprintf (buffer, "Remove %s? ", bbfolder);
252 if (getanswer (buffer))
253 zap++;
254
255 if (check_folder (subfolder)) {
256 if (getanswer ("Update archives? "))
257 update (&substat, bb -> bb_archive, subfolder, NULLCP, NULLCP);
258 (void) sprintf (buffer, "Remove %s? ", subfolder);
259 if (getanswer (buffer))
260 rmf (subfolder);
261 }
262 else
263 if (sub_ok
264 && getanswer ("Remove archives? ")
265 && getanswer ("Are you sure? "))
266 if (unlink (bb -> bb_archive) == NOTOK)
267 admonish (bb -> bb_archive, "unable to remove %s");
268 if (zap)
269 rmf (bbfolder);
270 }
271
272 /* \f */
273
274 check_mode (dir, mode)
275 char *dir;
276 unsigned int mode;
277 {
278 int child_id;
279 struct stat st;
280 #ifdef SYS5DIR
281 struct dirent *dp;
282 #else SYS5DIR
283 struct direct *dp;
284 #endif SYS5DIR
285 DIR * dd;
286
287 if (verbosw)
288 fprintf (stderr, "chmod %o %s\n", mode, dir);
289
290 switch (child_id = fork ()) {
291 case NOTOK:
292 adios ("fork", "unable to");
293
294 case OK:
295 (void) setgid (getgid ());
296 (void) setuid (getuid ());
297
298 if (chmod (dir, (int) mode) == NOTOK)
299 adios (dir, "unable to change mode of");
300 if (chdir (dir) == NOTOK)
301 adios (dir, "unable to change to");
302 if ((dd = opendir (dir)) == NULL)
303 adios (dir, "unable to read");
304 while (dp = readdir (dd))
305 if (dp -> d_name[0] != '.') {
306 if (stat (dp -> d_name, &st) == NOTOK) {
307 admonish (dp -> d_name, "unable to stat");
308 continue;
309 }
310 if (chmod (dp -> d_name, (int) ((st.st_mode | 0444) & 0777))
311 == NOTOK)
312 admonish (dp -> d_name, "unable to change mode of");
313 }
314 closedir (dd);
315 done (0);
316
317 default:
318 if (pidwait (child_id, OK))
319 done (1);
320 break;
321 }
322 }
323
324 /* \f */
325
326 /* ARGSUSED */
327
328 update (stp, file, folder, info, map)
329 struct stat *stp;
330 char *file,
331 *folder,
332 *info,
333 *map;
334 {
335 int fd;
336 struct stat st;
337
338 if (stat (file, &st) != NOTOK
339 && st.st_mtime != stp -> st_mtime) {
340 printf ("File '%s' has changed...\n", file);
341 if (getanswer ("Append to it instead? "))
342 goto work;
343 else
344 if (!getanswer ("Still update it? "))
345 return;
346 }
347 if ((fd = creat (file, BBMODE)) == NOTOK)
348 adios (file, "unable to re-create");
349 else {
350 (void) close (fd);
351 if (map)
352 (void) unlink (map);
353 }
354 #ifdef notdef
355 if (info)
356 check_info (folder, info);
357 #endif notdef
358
359 work: ;
360 pack (folder, file);
361 if (chmod (file, (int) (stp -> st_mode & 0777)) == NOTOK)
362 admonish (file, "unable to change mode of");
363 if (stat (file, &st) != NOTOK && st.st_gid != stp -> st_gid)
364 chgrp (file, stp -> st_gid);
365 }
366
367 /* \f */
368
369 #ifdef notdef
370 check_info (folder, info)
371 char *folder,
372 *info;
373 {
374 int id,
375 state;
376 char *hdrptr,
377 *maildir,
378 *msgnam,
379 posted[BUFSIZ],
380 name[NAMESZ],
381 buf[BUFSIZ];
382 struct msgs *mp;
383 FILE * fp;
384
385 if (chdir (maildir = m_maildir (folder + 1)) == NOTOK)
386 adios (maildir, "unable to change to");
387
388 if (!(mp = m_gmsg (folder + 1)))
389 adios (NULL, "unable to read %s", folder);
390 if (mp -> hghmsg) {
391 if ((fp = fopen (msgnam = m_name (mp -> hghmsg), "r")) == NULL)
392 adios (NULL, "unable to read message %s in %s",
393 msgnam, folder);
394 id = 0;
395 posted[0] = NULL;
396 for (state = FLD;;) {
397 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
398 case FLD:
399 case FLDEOF:
400 case FLDPLUS:
401 hdrptr = add (buf, NULL);
402 while (state == FLDPLUS) {
403 state = m_getfld (state, name, buf, sizeof buf, fp);
404 hdrptr = add (buf, hdrptr);
405 }
406 if (uleq (name, "BBoard-ID")) {
407 id = atoi (buf);
408 if (id > 0 && posted[0])
409 break;
410 }
411 if (uleq (name, "BB-Posted")) {
412 strncpy (posted, buf, sizeof posted - 2);
413 if (posted[strlen (posted) - 1] == '\n')
414 posted[strlen (posted) - 1] = NULL;
415 if (id > 0 && posted[0])
416 break;
417 }
418 continue;
419
420 default:
421 admonish (NULL, "unable to find BBoard-info in message %s",
422 msgnam);
423 (void) fclose (fp);
424 goto no_risk;
425 }
426 break;
427 }
428 (void) fclose (fp);
429
430 if (verbosw)
431 fprintf (stderr,
432 "[ Highest message has %s%d and\n\t\t %s%s ]\n",
433 "BBoard-ID: ", id, "BB-Posted: ", posted);
434
435 if ((fp = lkfopen (info, "w")) == NULL)
436 adios (info, "unable to lock and fopen");
437 fprintf (fp, "%d\n%s\n", id, posted);
438 (void) lkfclose (fp, info);
439 }
440
441 no_risk: ;
442 if (chdir (cwd) == NOTOK)
443 admonish (cwd, "could not change back to");
444 }
445 #endif notdef
446
447 /* \f */
448
449 pack (folder, file)
450 char *folder,
451 *file;
452 {
453 int child_id;
454
455 switch (child_id = fork ()) {
456 case NOTOK:
457 admonish ("fork", "unable to");
458 return;
459
460 case OK:
461 if (verbosw)
462 fprintf (stderr, "pack %s -file %s\n", folder, file);
463
464 execlp (packproc, r1bindex (packproc, '/'),
465 folder, "-file", file, NULLCP);
466 fprintf (stderr, "unable to exec ");
467 perror (packproc);
468 _exit (-1);
469
470 default:
471 (void) pidXwait (child_id, packproc);
472 break;
473 }
474 }
475
476 /* \f */
477
478 chgrp (file, gid)
479 char *file;
480 short gid;
481 {
482 int child_id;
483 char group[BUFSIZ];
484
485 switch (child_id = fork ()) {
486 case NOTOK:
487 admonish ("fork", "unable to");
488 return;
489
490 case OK:
491 (void) setuid (geteuid ());/* make sure chgrp works */
492 (void) sprintf (group, "%d", gid);
493 if (verbosw)
494 fprintf (stderr, "chgrp %s %s\n", group, file);
495
496 execlp ("/bin/chgrp", "chgrp", group, file, NULLCP);
497 fprintf (stderr, "unable to exec ");
498 perror ("/bin/chgrp");
499 _exit (-1);
500
501 default:
502 (void) pidXwait (child_id, "chgrp");
503 break;
504 }
505 }
506
507 /* \f */
508
509 rmf (folder)
510 char *folder;
511 {
512 int child_id;
513
514 switch (child_id = fork ()) {
515 case NOTOK:
516 admonish ("fork", "unable to");
517 return;
518
519 case OK:
520 (void) setgid (getgid ());
521 (void) setuid (getuid ());
522 if (verbosw)
523 fprintf (stderr, "rmf %s\n", folder);
524
525 execlp (rmfproc, r1bindex (rmfproc, '/'), folder, NULLCP);
526 fprintf (stderr, "unable to exec ");
527 perror (rmfproc);
528 _exit (-1);
529
530 default:
531 (void) pidXwait (child_id, rmfproc);
532 break;
533 }
534 }
535
536 /* \f */
537
538 do_child () {
539 char buffer[BUFSIZ];
540
541 (void) setgid (getgid ()); /* become the user, not bboards */
542 (void) setuid (getuid ());
543
544 inc (bb -> bb_file, bbfolder);
545 if (sub_ok)
546 inc (bb -> bb_archive, subfolder);
547 /* else
548 create the folder */
549
550 if (verbosw)
551 (void) putchar ('\n');
552 printf ("[ Working folder is %s, Archive folder is %s ]\n",
553 bbfolder, subfolder);
554 printf ("[ Type CTRL-D to finish ]\n");
555
556 m_replace (pfolder, bbfolder + 1);
557 m_update ();
558
559 (void) sprintf (buffer, "=> %s: %s", invo_name, bb -> bb_name);
560 execlp (shell, buffer, NULLCP);
561 fprintf (stderr, "unable to exec ");
562 perror (shell);
563 _exit (-1);
564 }
565
566 /* \f */
567
568 inc (file, folder)
569 char *file,
570 *folder;
571 {
572 int child_id;
573
574 switch (child_id = fork ()) {
575 case NOTOK:
576 adios ("fork", "unable to");
577
578 case OK:
579 if (verbosw)
580 fprintf (stderr, "inc %s -file %s -silent\n", folder, file);
581 execlp (incproc, r1bindex (incproc, '/'),
582 folder, "-file", file, "-silent", NULLCP);
583 fprintf (stderr, "unable to exec ");
584 perror (incproc);
585 _exit (-1);
586
587 default:
588 if (pidXwait (child_id, incproc))
589 done (1);
590 break;
591 }
592 }