|
|
1.1 root 1: /*
2: * This software is Copyright (c) 1986 by Rick Adams.
3: *
4: * Permission is hereby granted to copy, reproduce, redistribute or
5: * otherwise use this software as long as: there is no monetary
6: * profit gained specifically from the use or reproduction or this
7: * software, it is not sold, rented, traded or otherwise marketed, and
8: * this copyright notice is included prominently in any copy
9: * made.
10: *
11: * The author make no claims as to the fitness or correctness of
12: * this software for any use whatsoever, and it is provided as is.
13: * Any use of this software is at the user's own risk.
14: *
15: * ifuncs - functions used by inews.
16: */
17:
18: #ifdef SCCSID
19: static char *SccsId = "@(#)ifuncs.c 2.51 3/19/86";
20: #endif /* SCCSID */
21:
22: #include "iparams.h"
23: #include <errno.h>
24: #include <ctype.h>
25:
26: /*LINTLIBRARY*/
27:
28: #define AFSIZ 4000 /* size of text in the active file for initial malloc */
29:
30: /*
31: * Transmit this article to all interested systems.
32: */
33:
34: #ifdef u370
35: static struct srec srec;
36: #endif /* u370 */
37:
38: static struct hbuf h, hh;
39:
40: #ifdef MULTICAST
41: #define MAXMCAST 20
42: #define MAXMCS 10
43:
44: struct multicast {
45: char mc_name[SBUFLEN]; /* "multi-cast" name */
46: short mc_syscnt;
47: char mc_tosys[MAXMCAST][SBUFLEN];
48: } mcast[MAXMCS];
49:
50: static int mccount;
51: #endif /* MULTICAST */
52:
53: #ifndef DBM
54: char *histfile();
55: #endif /* !DBM */
56:
57: broadcast()
58: {
59: register char *hptr;
60: register char *sptr;
61: register FILE *fp;
62: #ifndef u370
63: struct srec srec;
64: #endif
65: char sentbuf[LBUFLEN];
66: int nsent = 0;
67: char *sentsys;
68:
69: /* h is a local copy of the header we can scribble on */
70: fp = xfopen(ARTICLE, "r");
71: if (hread(&h, fp, TRUE) == NULL)
72: xerror("Cannot reread article");
73: (void) fclose(fp);
74:
75: (void) strcpy(sentbuf, h.ident);
76: (void) strcat(sentbuf, " sent to ");
77: sentsys = index(sentbuf, 0);
78: nsent = 0;
79: /* break path into list of systems. */
80: sptr = hptr = h.path;
81: while ((hptr=strpbrk(hptr, NETCHRS)) != NULL) {
82: *hptr++ = '\0';
83: sptr = hptr;
84: }
85: *sptr = '\0';
86:
87: #ifdef MULTICAST
88: mccount = 0;
89: #endif /* MULTICAST */
90:
91: /* loop once per system. */
92: s_openr();
93: while (s_read(&srec)) {
94: #ifdef HIDDENNET
95: if (strncmp(srec.s_name, LOCALSYSNAME, SNLN) == 0)
96: continue;
97: #endif /* HIDDENNET */
98: if (strncmp(srec.s_name, FULLSYSNAME, SNLN) == 0)
99: continue;
100: if (sptr = srec.s_nosend) {
101: while (*sptr) {
102: while (*sptr && *sptr != ',')
103: sptr++;
104: if (*sptr == ',')
105: *sptr++ = '\0';
106: }
107: *++sptr = '\0';
108: }
109: hptr = h.path;
110: while (*hptr != '\0') {
111: if (strncmp(srec.s_name, hptr, SNLN) == 0)
112: goto contin;
113: if (sptr = srec.s_nosend) {
114: while (*sptr != '\0') {
115: if (strncmp(sptr, hptr, SNLN) == 0)
116: goto contin;
117: while (*sptr++)
118: ;
119: }
120: }
121: while (*hptr++ != '\0')
122: ;
123: }
124: if (!ngmatch(h.nbuf, srec.s_nbuf))
125: continue;
126: if (h.distribution[0] != '\0' &&
127: !ngmatch(h.distribution, srec.s_nbuf) &&
128: !ngmatch(srec.s_nbuf, h.distribution))
129: continue;
130: if (nsent) {
131: hptr = sentsys;
132: while ((sptr = index(hptr, ',')) != NULL) {
133: *sptr = '\0';
134: if (strcmp(hptr, srec.s_name) == 0) {
135: *sptr = ',';
136: goto contin;
137: }
138: *sptr++ = ',';
139: for (hptr = sptr; isspace(*hptr); hptr++)
140: ;
141: }
142: if (strcmp(hptr, srec.s_name) == 0)
143: continue;
144: }
145: /* now we've found a system to send this article to */
146: #ifdef MULTICAST
147: if (index(srec.s_flags, 'M')) {
148: /* do a "multi-cast" transmit */
149: register struct multicast *m;
150:
151: if (strlen(srec.s_name) >= SBUFLEN ||
152: strlen(srec.s_xmit) >= SBUFLEN)
153: xerror("system name too long for multicast");
154: for (m = mcast; m < &mcast[mccount]; m++)
155: if (strcmp(srec.s_xmit, m->mc_name) == 0)
156: break;
157: if (m >= &mcast[MAXMCS])
158: xerror("Too many multicasts");
159: if (m == &mcast[mccount]) {
160: mccount++;
161: m->mc_syscnt = 0;
162: strcpy(m->mc_name, srec.s_xmit);
163: }
164: if (m->mc_syscnt >= MAXMCAST)
165: xerror("Too many systems for multicast");
166: strcpy(m->mc_tosys[m->mc_syscnt++], srec.s_name);
167: } else {
168: register struct multicast *m;
169: register char **yptr;
170: char *sysptrs[MAXMCAST];
171: int mc;
172:
173: mc = 0;
174: for (m = mcast; m < &mcast[mccount]; m++)
175: if (strcmp(m->mc_name, srec.s_name) == 0) {
176: yptr = sysptrs;
177: while (mc < m->mc_syscnt)
178: *yptr++ = m->mc_tosys[mc++];
179: break;
180: }
181: if (!transmit(&srec,xfopen(ARTICLE,"r"),1,sysptrs,mc))
182: continue;
183: }
184: #else /* !MULTICAST */
185: if (!transmit(&srec, xfopen(ARTICLE, "r"), 1, (char **)0, 0))
186: continue;
187: #endif /* !MULTICAST */
188: if (nsent)
189: (void) strcat(sentbuf, ", ");
190: (void) strcat(sentbuf, srec.s_name);
191: nsent++;
192: contin:;
193: }
194: if (nsent)
195: log(sentbuf);
196: s_close();
197: }
198:
199: /*
200: * Transmit file to system.
201: */
202: #define PROC 0004
203: #ifndef MULTICAST
204: /* ARGSUSED */
205: #endif /* !MULTICAST */
206: transmit(sp, ifp, maynotify, sysnames, mc)
207: register struct srec *sp;
208: register FILE *ifp;
209: int maynotify;
210: char **sysnames;
211: int mc;
212: {
213: register FILE *ofp;
214: register int c;
215: register char *ptr;
216: char TRANS[BUFLEN];
217: char *argv[20];
218: register int pid;
219: extern char firstbufname[];
220:
221: /* A: afmt: the other machine runs an A news, so we xmit in A format */
222: int afmt = (index(sp->s_flags, 'A') != NULL);
223: /* B: use B format (this is the default - don't use this letter elsewise). */
224: /* F: append name to file */
225: int appfile = (index(sp->s_flags, 'F') != NULL);
226: /* L: local: don't send the article unless it was generated locally */
227: int local = ((ptr = index(sp->s_flags, 'L')) != NULL);
228: /* H: interpolate history line into command, use existing file */
229: int history = (index(sp->s_flags, 'H') != NULL);
230: /* M: multi-cast: this is taken care of above, but don't reuse flag */
231: #ifdef MULTICAST
232: /* O: multi-cast only, don't send article if not multicast hosts */
233: int multisend = (index(sp->s_flags, 'O') != NULL);
234: #endif /* MULTICAST */
235: /* N: notify: don't send the article, just tell him we have it */
236: int notify = maynotify && (index(sp->s_flags, 'N') != NULL);
237: /* S: noshell: don't fork a shell to execute the xmit command */
238: int noshell = (index(sp->s_flags, 'S') != NULL);
239: /* U: useexist: use the -c option to uux to use the existing copy */
240: int useexist = (index(sp->s_flags, 'U') != NULL);
241:
242: if (local && mode == PROC) {
243: local = 0;
244: while (isdigit(*++ptr))
245: local = local * 10 + *ptr - '0';
246: for (ptr = h.path; *ptr != '\0' && local >= 0; local--)
247: while (*ptr++ != '\0')
248: ;
249: if (local < 0) {
250: (void) fclose(ifp);
251: return FALSE;
252: }
253: }
254:
255: #ifdef DEBUG
256: printf("Transmitting to '%s'\n", sp->s_name);
257: #endif /* DEBUG */
258:
259: #ifdef MULTICAST
260: if (multisend && mc == 0) {
261: (void) fclose(ifp);
262: return FALSE;
263: }
264: #endif /* MULTICAST */
265:
266: if (!appfile && !useexist && !history) {
267: if (!hread(&hh, ifp, TRUE)) {
268: logerr("Bad header, not transmitting %s re %s to %s",
269: hh.ident, hh.title, sp->s_name);
270: (void) fclose(ifp);
271: return FALSE;
272: }
273: if (hh.nbuf[0] == '\0') {
274: fprintf(stderr, "Article not subscribed to by %s\n", sp->s_name);
275: (void) fclose(ifp);
276: return FALSE;
277: }
278: (void) sprintf(TRANS, "%s/trXXXXXX", SPOOL);
279: }
280:
281: if (notify) {
282: char oldid[50];
283: (void) sprintf(hh.title, "ihave %s %s", hh.ident, FULLSYSNAME);
284: (void) sprintf(hh.nbuf, "to.%s.ctl", sp->s_name);
285: (void) strcpy(oldid, hh.ident);
286: getident(&hh);
287: log("tell %s about %s, notif. id %s",
288: sp->s_name, oldid, hh.ident);
289: }
290:
291: if (appfile) {
292: if (firstbufname[0] == '\0') {
293: extern char histline[];
294: localize("junk");
295: savehist(histline);
296: xerror("No file name to xmit from");
297: }
298: if (sp->s_xmit[0] == '\0')
299: sprintf(sp->s_xmit, "%s/%s", BATCHDIR, sp->s_name);
300: #ifdef IHCC
301: (void) sprintf(TRANS, "%s/%s/%s", logdir(HOME), BATCHDIR, sp->s_xmit);
302: ofp = fopen(TRANS, "a");
303: #else /* !IHCC */
304: ofp = fopen(sp->s_xmit, "a");
305: #endif /* !IHCC */
306: if (ofp == NULL)
307: xerror("Cannot append to %s", sp->s_xmit);
308: #ifdef MULTICAST
309: fprintf(ofp, "%s", firstbufname);
310: while (--mc >= 0)
311: fprintf(ofp, " %s", *sysnames++);
312: fprintf(ofp, "\n");
313: #else /* !MULTICAST */
314: fprintf(ofp, "%s\n", firstbufname);
315: #endif /* !MULTICAST */
316: (void) fclose(ofp);
317: (void) fclose(ifp);
318: return TRUE;
319: }
320: else if (useexist) {
321: if (firstbufname[0] == '\0')
322: xerror("No file name to xmit from");
323: if (*sp->s_xmit == '\0')
324: #ifdef UXMIT
325: (void) sprintf(bfr, UXMIT, sp->s_name, firstbufname);
326: #else
327: xerror("UXMIT not defined for U flag");
328: #endif
329: else
330: #ifdef MULTICAST
331: makeargs(bfr, sp->s_xmit, firstbufname, sysnames, mc);
332: #else
333: (void) sprintf(bfr, sp->s_xmit, firstbufname);
334: #endif
335: (void) fclose(ifp);
336: } else if (history) {
337: extern char histline[];
338:
339: if (*sp->s_xmit == '\0')
340: xerror("no xmit command with H flag");
341: #ifdef MULTICAST
342: makeargs(bfr, sp->s_xmit, histline, sysnames, mc);
343: #else
344: (void) sprintf(bfr, sp->s_xmit, histline);
345: #endif
346: } else {
347: ofp = xfopen(mktemp(TRANS), "w");
348: if (afmt) {
349: #ifdef OLD
350: fprintf(ofp, "A%s\n%s\n%s!%s\n%s\n%s\n", oident(hh.ident), hh.nbuf, FULLSYSNAME,
351: hh.path, hh.subdate, hh.title);
352: #else /* !OLD */
353: logerr("Must have OLD defined to use A flag for xmit");
354: return FALSE;
355: #endif /* !OLD */
356: } else
357: hwrite(&hh, ofp);
358: if (!notify)
359: while ((c = getc(ifp)) != EOF)
360: putc(c, ofp);
361: if (ferror(ofp))
362: xerror("write failed on transmit");
363: (void) fclose(ifp);
364: (void) fclose(ofp);
365: if (*sp->s_xmit == '\0')
366: (void) sprintf(bfr, DFTXMIT, sp->s_name, TRANS);
367: else
368: #ifdef MULTICAST
369: makeargs(bfr, sp->s_xmit, TRANS, sysnames, mc);
370: #else /* !MULTICAST */
371: (void) sprintf(bfr, sp->s_xmit, TRANS);
372: #endif /* !MULTICAST */
373: }
374:
375: /* At this point, the command to be executed is in bfr. */
376: if (noshell) {
377: if (pid = fork())
378: fwait(pid);
379: else {
380: (void) close(0);
381: (void) open(TRANS, 0);
382: ptr = bfr;
383: for (pid = 0; pid < 19; pid++) {
384: while (isspace(*ptr))
385: *ptr++ = 0;
386: argv[pid] = ptr;
387: while (!isspace(*++ptr) && *ptr)
388: ;
389: if (!*ptr)
390: break;
391: }
392: argv[++pid] = 0;
393: (void) setgid(gid);
394: (void) setuid(uid);
395: execv(argv[0], argv);
396: xerror("Can't execv %s", argv[0]);
397: }
398: } else {
399: if (!history && sp->s_xmit[0] && !index(bfr, '<')) {
400: char newcmd[LBUFLEN];
401:
402: (void) sprintf(newcmd, "(%s) <%s", bfr,
403: useexist ? firstbufname : TRANS);
404: system(newcmd);
405: } else
406: system(bfr);
407: }
408: if (!appfile && !useexist && !history)
409: (void) unlink(TRANS);
410: (void) fclose(ifp);
411: return TRUE;
412: }
413:
414: #ifdef MULTICAST
415: makeargs(buf, cmd, arg2, sysargs, sac)
416: char *buf;
417: char *cmd;
418: char *arg2;
419: register char **sysargs;
420: int sac;
421: {
422: register char *p = cmd;
423: register char *q;
424: register ac = 0;
425: register char *b = buf;
426:
427: q = p;
428: do {
429: if (q = index(q, ' '))
430: *q = '\0';
431: if (index(p, '%')) {
432: switch (++ac) {
433: case 1:
434: while (--sac >= 0) {
435: sprintf(b, p, *sysargs++);
436: b = index(b, '\0');
437: }
438: break;
439: case 2:
440: sprintf(b, p, arg2);
441: b = index(b, '\0');
442: break;
443: default:
444: if (q)
445: *q = ' ';
446: xerror("badly formed command: %s", cmd);
447: }
448: } else {
449: strcpy(b, p);
450: b = index(b, '\0');
451: }
452: if (q) {
453: *q = ' ';
454: p = q;
455: while (isspace(*q))
456: q++;
457: }
458: } while (q != NULL);
459: }
460: #endif /* MULTICAST */
461:
462: typedef struct {
463: char *dptr;
464: int dsize;
465: } datum;
466:
467: /*
468: * Return TRUE if we have seen this file before, else FALSE.
469: */
470: history(hp)
471: struct hbuf *hp;
472: {
473: #ifdef DBM
474: datum lhs, rhs;
475: datum fetch();
476: #else /* !DBM */
477: register FILE *hfp;
478: register char *p;
479: #endif /* !DBM */
480: char lcident[BUFLEN];
481: extern char histline[];
482:
483: #ifdef DEBUG
484: fprintf(stderr,"history(%s)\n", hp->ident);
485: #endif /* DEBUG */
486: /*
487: * Make the article ID case insensitive.
488: */
489: (void) strcpy(lcident, hp->ident);
490: lcase(lcident);
491:
492: idlock(lcident);
493: #ifdef DBM
494: initdbm(ARTFILE);
495: lhs.dptr = lcident;
496: lhs.dsize = strlen(lhs.dptr) + 1;
497: rhs = fetch(lhs);
498: if (rhs.dptr)
499: return(TRUE);
500: #else /* !DBM */
501: hfp = xfopen(histfile(lcident), "r");
502: while (fgets(bfr, BUFLEN, hfp) != NULL) {
503: p = index(bfr, '\t');
504: if (p == NULL)
505: p = index(bfr, '\n');
506: if (p != NULL) /* can happen if nulls in file */
507: *p = 0;
508: lcase(bfr);
509:
510: if (strcmp(bfr, lcident) == 0) {
511: (void) fclose(hfp);
512: idunlock();
513: #ifdef DEBUG
514: fprintf(stderr,"history returns true\n");
515: #endif /* DEBUG */
516: return TRUE;
517: }
518: }
519: (void) fclose(hfp);
520: #endif /* !DBM */
521: histline[0] = '\0';
522: addhist(hp->ident);
523: addhist("\t");
524: #ifdef DEBUG
525: fprintf(stderr,"history returns false\n");
526: #endif
527: return FALSE;
528: }
529:
530: char histline[PATHLEN];
531:
532: addhist(msg)
533: char *msg;
534: {
535: (void) strcat(histline, msg);
536: }
537:
538: savehist(hline)
539: char *hline;
540: {
541: register FILE *hfp;
542: datum lhs, rhs;
543: long fpos;
544: register char *p;
545:
546: hfp = xfopen(ARTFILE, "a");
547: fpos = ftell(hfp);
548: fprintf(hfp, "%s\n", hline);
549: (void) fclose(hfp);
550: #ifdef DBM
551: /* We assume that history has already been called, calling dbminit. */
552: p = index(hline, '\t');
553: if (p)
554: *p = 0;
555: lcase(hline);
556: lhs.dptr = hline;
557: lhs.dsize = strlen(lhs.dptr) + 1;
558: rhs.dptr = (char *)&fpos;
559: rhs.dsize = sizeof fpos;
560: store(lhs, rhs);
561: #else /* !DBM */
562: /* also append to proper history subfile */
563: hfp = xfopen(histfile(hline), "a");
564: fprintf(hfp, "%s\n", hline);
565: (void) fclose(hfp);
566: #endif /* !DBM */
567: idunlock();
568: }
569:
570: /*
571: * Save partial news.
572: */
573: /* ARGSUSED */
574: newssave(fd, dummy)
575: FILE *fd;
576: char *dummy;
577: {
578: register FILE *tofd, *fromfd;
579: char sfname[BUFLEN];
580: register int c;
581: time_t tim;
582:
583: if (fd == NULL)
584: fromfd = xfopen(INFILE, "r");
585: else
586: fromfd = fd;
587: (void) umask(savmask);
588: (void) setgid(gid);
589: (void) setuid(uid);
590:
591: (void) sprintf(sfname, "%s/%s", userhome, PARTIAL);
592: if ((tofd = fopen(sfname, "a")) == NULL)
593: xerror("Cannot save partial news in %s", sfname);
594: (void) time(&tim);
595: fprintf(tofd, "----- News saved at %s\n", arpadate(&tim));
596: while ((c = getc(fromfd)) != EOF)
597: putc(c, tofd);
598: (void) fclose(fromfd);
599: (void) fclose(tofd);
600: printf("News saved in %s\n", sfname);
601: xxit(1);
602: }
603:
604: /*
605: * Handle dates in header.
606: */
607:
608: dates(hp)
609: struct hbuf *hp;
610: {
611: time_t edt;
612:
613: if (*hp->subdate) {
614: if (cgtdate(hp->subdate) < 0) {
615: xerror("Cannot parse submittal date '%s'", hp->subdate);
616: }
617: } else {
618: (void) time(&edt);
619: (void) strcpy(hp->subdate, arpadate(&edt));
620: }
621: }
622:
623: char lockname[80];
624: idlock(str)
625: char *str;
626: {
627: register int i;
628: char tempname[80];
629: time_t now;
630: struct stat sbuf;
631: extern int errno;
632: #ifdef VMS
633: int fd;
634:
635: (void) sprintf(lockname, "/tmp/%s.l.1", str);
636: if ((fd = creat(lockname, 0444)) < 0) {
637: #else /* !VMS */
638: (void) strcpy(tempname, "/tmp/LTMP.XXXXXX");
639: (void) mktemp(tempname);
640: (void) sprintf(lockname, "/tmp/L%s", str);
641: #ifdef FOURTEENMAX
642: lockname[5 /* /tmp/ */ + 14] = '\0';
643: #endif
644: i = creat(tempname, 0666);
645: if (i < 0)
646: xerror("Cannot creat %s: errno %d", tempname, errno);
647: (void) close(i);
648: while (link(tempname, lockname)) {
649: #endif /* !VMS */
650: (void) time(&now);
651: i = stat(lockname, &sbuf);
652: if (i < 0) {
653: xerror("Directory permission problem in /tmp");
654: }
655: if (sbuf.st_mtime + 10*60 < now) {
656: (void) unlink(lockname);
657: logerr("Article %s locked up", str);
658: break;
659: }
660: log("waiting on lock for %s", lockname);
661: sleep((unsigned)60);
662: }
663: #ifdef VMS
664: (void) close(fd);
665: #endif
666: (void) unlink(tempname);
667: }
668:
669: idunlock()
670: {
671: (void) unlink(lockname);
672: }
673:
674: /*
675: * Put a unique name into header.ident.
676: */
677: getident(hp)
678: struct hbuf *hp;
679: {
680: long seqn;
681: register FILE *fp;
682:
683: lock();
684: fp = xfopen(SEQFILE, "r");
685: (void) fgets(bfr, BUFLEN, fp);
686: (void) fclose(fp);
687: seqn = atol(bfr) + 1;
688: #ifdef VMS
689: (void) unlink(SEQFILE);
690: #endif /* VMS */
691: fp = xfopen(SEQFILE, "r+w");
692: fprintf(fp, "%ld\n", seqn);
693: (void) fclose(fp);
694: unlock();
695: #ifdef HIDDENNET
696: if (strcmp(LOCALSYSNAME, FULLSYSNAME))
697: (void) sprintf(hp->ident, "<%ld@%s.%s%s>", seqn, LOCALSYSNAME, FULLSYSNAME,
698: MYDOMAIN);
699: else
700: #endif /* !HIDDENNET */
701: (void) sprintf(hp->ident, "<%ld@%s%s>", seqn, FULLSYSNAME, MYDOMAIN);
702: }
703:
704: /*
705: * Check that header.nbuf contains only valid newsgroup names;
706: * exit with error if not valid.
707: *
708: */
709: ngfcheck(isproc)
710: int isproc;
711: {
712: register char *s1, *s2;
713: register FILE *f;
714: register char *os1;
715: int ngroups = 1;
716: unsigned int ngsize = AFSIZ;
717: char tbuf[BUFLEN], *ngcheck;
718:
719: f = xfopen(ACTIVE, "r");
720: ngcheck = malloc(ngsize);
721: if (ngcheck == NULL)
722: xerror("Can't malloc the active file");
723: s1 = ngcheck;
724: while (fgets(bfr, BUFLEN, f) != NULL) {
725: os1 = s1;
726: for(s2 = bfr; *s2 != '\0' && *s2 != ' ';) {
727: if (s1 >= &ngcheck[ngsize-2]) {
728: unsigned int offs = s1 - ngcheck;
729: ngsize += LBUFLEN;
730: ngcheck = realloc(ngcheck, ngsize);
731: if (ngcheck == NULL)
732: xerror("Can't realloc active file");
733: s1 = ngcheck + offs;
734: }
735: *s1++ = *s2++;
736: }
737: *s1++ = '\0';
738: if (isproc) /* don't check to see if can post to this group */
739: continue;
740: while (*s2++ != '\0' && *s2 != ' ')
741: ; /* skip max article number */
742: while (*s2++ != '\0' && *s2 != ' ')
743: ; /* skip min article number */
744: if (*s2++ != '\0' && *s2 == 'n')
745: s1 = os1; /* can't post to this group */
746: }
747: *s1++ = '\0';
748: *s1 = '\0';
749: (void) fclose(f);
750:
751: s1 = header.nbuf;
752: s2 = nbuf;
753: while (*s1 == NGDELIM || *s1 == ' ')
754: s1++; /* skip leading junk */
755: do {
756: /* there shouldn't be blanks, but give the jerk a break */
757: if (*s1 == NGDELIM || *s1 == ' ') {
758: *s2++ = '\0';
759: while (*++s1 == NGDELIM || *s1 == ' ')
760: ; /* remove extra commas */
761: if (*s1 != '\0')
762: ngroups++;
763: } else
764: *s2++ = *s1++;
765: } while (*s1 != '\0');
766: if (s2[-1] == NGDELIM) /* strip trailing commas */
767: s2--;
768: *s2 = '\0';
769:
770: s1 = nbuf;
771: while (*s1 != '\0') { /* for each newsgroup in header */
772: s2 = ngcheck;
773: while (*s2 != '\0') { /* for each newsgroup in active file */
774: if (strcmp(s1, s2) == 0)
775: break;
776: while (*s2++ != '\0')
777: ;
778: }
779: if (*s2 == '\0') { /* not found. remove it */
780: if (!isproc) {
781: logerr("Invalid news group '%s'", s1);
782: newssave(stdin, (char *)NULL);
783: }
784: /* See if it's in our alias list */
785: f = xfopen(ALIASES,"r");
786: while (fscanf(f,"%s %s", tbuf, bfr) == 2
787: && strcmp(s1, tbuf))
788: ;
789: (void) fclose(f);
790: if (strcmp(s1, tbuf) == 0) {
791: logerr("Aliased newsgroup '%s' to '%s'", s1, bfr);
792: os1 = s1;
793: s1 = nbuf;
794: s2 = tbuf;
795: while (s1 < os1) /* copy left part */
796: *s2++ = *s1++;
797: s1 = bfr;
798: while (*s1 != '\0') /* copy alias */
799: *s2++ = *s1++;
800: *s2++ = '\0';
801: s1 = os1;
802: os1 = nbuf + (s2 - tbuf);
803: while (*s1++ != '\0') /* skip old group */
804: ;
805: /* copy right part */
806: tbufcpy(s2, s1);
807: /* copy back to original buffer */
808: tbufcpy(nbuf, tbuf);
809: s1 = os1;
810: } else {
811: logerr("Unknown newsgroup '%s' removed", s1);
812: s2 = s1;
813: while (*s2++ != '\0') /* skip the bad one */
814: ;
815: tbufcpy(s1, s2);
816: }
817: } else { /* It's in our active file */
818: os1 = s1;
819: while (*s1++ != '\0')
820: ;
821: /* check for local only distribution on incoming
822: newsgroups. This might occur if someone posted to
823: general,net.unix */
824: if(isproc && ngroups > 1 && index(os1, '.') == NULL
825: && index(header.nbuf, '.') != NULL) {
826: logerr("Local group '%s' removed", os1);
827: tbufcpy(os1, s1);
828: s1 = os1;
829: }
830: }
831: }
832: /* remove any duplicates */
833: os1 = s1 = nbuf;
834: for(;;) {
835: if (*s1++ == '\0') {
836: if (*s1 == '\0')
837: break;
838: s2 = s1;
839: while (*s2 != '\0') {
840: if (strcmp(os1, s2) == 0) {
841: logerr("Duplicate '%s' removed",os1);
842: os1 = s2;
843: while (*s2++ != '\0') /* skip it */
844: ;
845: tbufcpy(os1, s2);
846: } else
847: while (*s2++ != '\0')
848: ;
849: }
850: os1 = s1;
851: s1[-1] = '\0';
852: }
853: }
854: if (nbuf[0] != '\0') {
855: s1 = header.nbuf;
856: s2 = nbuf;
857: do {
858: while (*s2 != '\0')
859: *s1++ = *s2++;
860: *s1++ = NGDELIM;
861: } while (*++s2 != '\0');
862: *--s1 = '\0';
863: (void) free(ngcheck);
864: return FALSE;
865: }
866: (void) free(ngcheck);
867: return TRUE;
868: }
869:
870: tbufcpy(s1, s2)
871: register char *s1, *s2;
872: {
873: do {
874: while (*s2 != '\0')
875: *s1++ = *s2++;
876: *s1++ = '\0';
877: } while (*++s2 != '\0');
878: *s1 = '\0';
879: }
880:
881:
882: /*
883: * Figure out who posted the article (which is locally entered).
884: * The results are placed in the header structure hp.
885: */
886: gensender(hp, logname)
887: struct hbuf *hp;
888: char *logname;
889: {
890: register char *fn, *p;
891: char buf[BUFLEN];
892: char *fullname(), *getenv();
893: int fd, n;
894:
895: fn = getenv("NAME");
896:
897: if (fn == NULL) {
898: (void) sprintf(buf, "%s/%s", userhome, ".name");
899: fd = open(buf, 0);
900: if (fd >= 0) {
901: n = read(fd, buf, sizeof buf);
902: (void) close(fd);
903: if (n > 0 && buf[0] >= 'A') {
904: fn = buf;
905: for (p=fn; *p; p++)
906: if (*p < ' ')
907: *p = '\0';
908: }
909: }
910: }
911:
912: if (fn == NULL)
913: fn = fullname(logname);
914:
915: (void) sprintf(hp->path, "%s", logname);
916: (void) sprintf(hp->from, "%s@%s%s (%s)", logname, FULLSYSNAME, MYDOMAIN, fn);
917: }
918:
919: /*
920: * Trap interrupts.
921: */
922: onsig(n)
923: int n;
924: {
925: static int numsigs = 0;
926: /*
927: * Most UNIX systems reset caught signals to SIG_DFL.
928: * This bad design requires that the trap be set again here.
929: * Unfortunately, if the signal recurs before the trap is set,
930: * the program will die, possibly leaving the lock in place.
931: */
932: if (++numsigs > 100) {
933: logerr("inews ran away looping on signal %d", n);
934: xxit(1);
935: }
936: (void) signal(n, onsig);
937: SigTrap = n;
938: }
939:
940: #ifdef BATCH
941: /*
942: * If the stdin begins with "#", we assume we have been fed a batched
943: * shell script which looks like this:
944: * #! rnews 1234
945: * article with 1234 chars
946: * #! rnews 4321
947: * article with 4321 chars
948: *
949: * In this case we just exec the unbatcher and let it unpack and call us back.
950: *
951: * Note that there is a potential security hole here. If the batcher is
952: * /bin/sh, someone could ship you arbitrary stuff to run as shell commands.
953: * The main protection you have is that the effective uid will be news, not
954: * uucp and not the super user. (That, plus the fact that BATCH is set to
955: * "unbatch" as the system is distributed.) If you want to run a batched link
956: * and you are security conscious, do not use /bin/sh as the unbatcher.
957: * the thing to do is to change BATCH in your localize.sh file from /bin/sh
958: * to some restricted shell which can only run rnews.
959: */
960: checkbatch()
961: {
962: int c;
963:
964: c = getc(stdin);
965: if (c != EOF)
966: (void) ungetc(c, stdin);
967: clearerr(stdin);
968: if (c == '#') {
969: char unbatcher[BUFLEN];
970:
971: (void) sprintf(unbatcher, "%s/%s", LIB, BATCH);
972: reset_stdin();
973: execl(unbatcher, "news-unpack", (char *)0);
974: xerror("Unable to exec shell to unpack news.");
975: }
976: }
977:
978: /*
979: * We've already done a read on stdin, and we want to seek back to the
980: * beginning. We want the real file descriptor (beyond buffers) to
981: * reflect the true beginning. Do whatever is necessary.
982: */
983: reset_stdin()
984: {
985: register FILE *ofd;
986: register int c;
987: char *ofdname;
988: long lseek();
989:
990: /* First try to seek back - if so, it's a cheap way back. */
991: if (lseek(0, 0L, 0) == 0L)
992: return;
993:
994: /* Can't seek, so have to copy input to a file and use that. */
995: ofdname = "/tmp/inewsXXXXXX";
996: (void) mktemp(ofdname);
997: ofd = fopen(ofdname, "w");
998: while ((c=getc(stdin)) != EOF)
999: putc(c, ofd);
1000: if (ferror(ofd))
1001: xerror("write failed on temp file %s", ofdname);
1002: (void) fclose(stdin);
1003: (void) fclose(ofd);
1004:
1005: /* Now for a few lower level hacks to reopen stdin and make
1006: * absolutely sure that the right fd's are done for the exec.
1007: */
1008: (void) close(0); /* make sure stdin is really closed. */
1009: (void) open(ofdname, 0); /* should return zero */
1010: (void) unlink(ofdname); /* to avoid cleaning it up later. */
1011: }
1012: #endif /* BATCH */
1013:
1014: /*
1015: * Exit and cleanup.
1016: */
1017: xxit(status)
1018: int status;
1019: {
1020: (void) unlink(INFILE);
1021: (void) unlink(ARTICLE);
1022: while (lockcount > 0)
1023: unlock();
1024: idunlock();
1025: exit(status);
1026: }
1027:
1028: rwaccess(fname)
1029: char *fname;
1030: {
1031: int fd;
1032:
1033: fd = open(fname, 2);
1034: if (fd < 0)
1035: return 0;
1036: (void) close(fd);
1037: return 1;
1038: }
1039:
1040: exists(fname)
1041: char *fname;
1042: {
1043: int fd;
1044:
1045: fd = open(fname, 0);
1046: if (fd < 0)
1047: return 0;
1048: (void) close(fd);
1049: return 1;
1050: }
1051:
1052: int lockcount = 0; /* no. of times we've called lock */
1053:
1054: #ifdef VMS
1055:
1056: #define SUBLOCK "/tmp/netnews.lck.1"
1057:
1058: /*
1059: * Newsystem locking.
1060: * These routines are different for VMS because we can not
1061: * effectively simulate links, and VMS supports multiple
1062: * version numbers of files
1063: */
1064: lock()
1065: {
1066: register int i;
1067: register int fd;
1068:
1069: if (lockcount++ == 0) {
1070: i = DEADTIME;
1071: while ((fd = creat(SUBLOCK, 0444)) < 0) {
1072: if (--i < 0) {
1073: (void) unlink(SUBLOCK);
1074: logerr("News system locked up");
1075: }
1076: if (i < -3)
1077: xerror("Unable to unlock news system");
1078: sleep((unsigned)1);
1079: }
1080: (void) close(fd);
1081: }
1082: }
1083:
1084: unlock()
1085: {
1086: if (--lockcount == 0)
1087: (void) unlink(SUBLOCK);
1088: }
1089:
1090: #else /* !VMS */
1091:
1092: /*
1093: * Newsystem locking.
1094: */
1095:
1096: #ifdef BSD4_2
1097: #include <sys/file.h>
1098: static int LockFd = -1;
1099: lock()
1100: {
1101: LockFd = open(SUBFILE,0);
1102: /* This will sleep until the other program releases the lock */
1103: /* We may need to alarm out of this, but I don't think so */
1104: (void) flock(LockFd, LOCK_EX);
1105: }
1106:
1107: unlock()
1108: {
1109: (void) flock(LockFd, LOCK_UN);
1110: (void) close(LockFd);
1111: }
1112: #else /* !BSD4_2 */
1113: /* Why doesn't USG unix have file locking????? */
1114: lock()
1115: {
1116: register int i;
1117: extern int errno;
1118:
1119: if (lockcount++ == 0) {
1120: i = DEADTIME;
1121: while (link(SUBFILE, LOCKFILE)) {
1122: if (errno != EEXIST)
1123: break;
1124: if (--i < 0)
1125: xerror("News system locked up");
1126: sleep((unsigned)1);
1127: }
1128: }
1129: }
1130:
1131: unlock()
1132: {
1133: if (--lockcount == 0)
1134: (void) unlink(LOCKFILE);
1135: }
1136: #endif /* !BSD4_2 */
1137: #endif /* !VMS */
1138:
1139: /*
1140: * Generate the name of the person responsible for posting this article,
1141: * in order to check that two articles were posted by the same person.
1142: */
1143: char *
1144: senderof(hp)
1145: struct hbuf *hp;
1146: {
1147: char *q, *tp;
1148: char *tailpath();
1149:
1150: if (hp->sender[0])
1151: tp = hp->sender;
1152: else if (hp->from[0])
1153: tp = hp->from;
1154: else
1155: tp = tailpath(hp);
1156:
1157: /* Remove full name */
1158: q = index(tp, ' ');
1159: if (q)
1160: *q = '\0';
1161:
1162: q = malloc((unsigned)(strlen(tp) + 1));
1163: (void) strcpy(q, tp);
1164: return q;
1165: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.