|
|
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: * funcs - functions used by many programs
16: */
17:
18: #ifdef SCCSID
19: static char *SccsId = "@(#)funcs.c 2.31 1/17/86";
20: #endif /* SCCSID */
21:
22: /*LINTLIBRARY*/
23:
24: #include "params.h"
25: #include <errno.h>
26: #if defined(USG) || defined(BSD4_2) || defined(BSD4_1C)
27: #include <fcntl.h>
28: #endif /* !v7 */
29:
30: extern char *Progname;
31:
32: /*
33: * News group matching.
34: *
35: * nglist is a list of newsgroups.
36: * sublist is a list of subscriptions.
37: * sublist may have "meta newsgroups" in it.
38: * All fields are NGDELIM separated,
39: * and there is an NGDELIM at the end of each argument.
40: *
41: * Currently implemented glitches:
42: * sublist uses 'all' like shell uses '*', and '.' like shell '/'.
43: * If subscription X matches Y, it also matches Y.anything.
44: */
45: ngmatch(nglist, sublist)
46: register char *nglist, *sublist;
47: {
48: register char *n, *s;
49: register int rc;
50:
51: rc = FALSE;
52: for (n = nglist; *n != '\0' && rc == FALSE;) {
53: for (s = sublist; *s != '\0';) {
54: if (*s != NEGCHAR)
55: rc = rc || ptrncmp(s, n);
56: else
57: rc = rc && !ptrncmp(s+1, n);
58: while (*s++ != NGDELIM && *s != '\0')
59: ;
60: }
61: while (*n++ != NGDELIM && *n != '\0')
62: ;
63: }
64: return rc;
65: }
66:
67: /*
68: * Compare two newsgroups for equality.
69: * The first one may be a "meta" newsgroup.
70: */
71: ptrncmp(ng1, ng2)
72: register char *ng1, *ng2;
73: {
74: while (*ng1 != NGDELIM && *ng1 != '\0') {
75: if (ng1[0]=='a' && ng1[1]=='l' && ng1[2]=='l') {
76: ng1 += 3;
77: while (*ng2 != NGDELIM && *ng2 != '.' && *ng2 != '\0')
78: if (ptrncmp(ng1, ng2++))
79: return(TRUE);
80: return ptrncmp(ng1, ng2);
81: } else if (*ng1++ != *ng2++)
82: return FALSE;
83: }
84: return *ng2 == '.' || *ng2 == NGDELIM || *ng2 == '\0';
85: }
86:
87: /*
88: * Exec the shell.
89: * This version resets uid, gid, and umask.
90: * Called with fsubr(ushell, s, NULL)
91: */
92: /* ARGSUSED */
93: ushell(s, dummy)
94: char *s, *dummy;
95: {
96: (void) umask(savmask);
97: (void) setgid(gid);
98: (void) setuid(uid);
99: xshell(s);
100: }
101:
102: /*
103: * Exec the shell.
104: */
105:
106: #ifdef lint
107: char **environ;
108: #else /* !lint */
109: extern char **environ;
110: #endif /* !lint */
111:
112: xshell(s)
113: char *s;
114: {
115: char *env[100], **envp;
116: char a[BUFLEN + 2];
117: extern char filename[];
118: /* set $A */
119: (void) sprintf(a, "A=%s", filename);
120: env[0] = a;
121: for (envp = env + 1 ; *environ != NULL && envp < env + 98 ; environ++)
122: if ((*environ)[0] != 'A' || (*environ)[1] != '=')
123: *envp++ = *environ;
124: *envp = NULL;
125:
126: execle(SHELL, SHELL, "-c", s, (char *)0, env);
127: xerror("No shell!");
128: }
129:
130: /*
131: * Fork and call a subroutine with two args.
132: * Return pid without waiting.
133: */
134: fsubr(f, s1, s2)
135: int (*f)();
136: char *s1, *s2;
137: {
138: register int pid;
139:
140: while ((pid = fork()) == -1)
141: sleep((unsigned)1);
142: if (pid == 0) {
143: (*f)(s1, s2);
144: exit(0);
145: }
146: return pid;
147: }
148:
149: /*
150: * Wait on a child process.
151: */
152: fwait(pid)
153: register int pid;
154: {
155: register int w;
156: int status;
157: int (*onhup)(), (*onint)();
158:
159: onint = signal(SIGINT, SIG_IGN);
160: onhup = signal(SIGHUP, SIG_IGN);
161: while ((w = wait(&status)) != pid && w != -1)
162: ;
163: if (w == -1)
164: status = -1;
165: (void) signal(SIGINT, onint);
166: (void) signal(SIGHUP, onhup);
167: return status;
168: }
169:
170: /*
171: * Strip trailing newlines, blanks, and tabs from 's'.
172: * Return TRUE if newline was found, else FALSE.
173: */
174: nstrip(s)
175: register char *s;
176: {
177: register char *p;
178: register int rc;
179:
180: rc = FALSE;
181: p = s;
182: while (*p)
183: if (*p++ == '\n')
184: rc = TRUE;
185: while (--p >= s && (*p == '\n' || *p == ' ' || *p == '\t'));
186: *++p = '\0';
187: return rc;
188: }
189:
190: /*
191: * Local open routine.
192: */
193: FILE *
194: xfopen(name, fmode)
195: register char *name, *fmode;
196: {
197: register FILE *fp;
198: char *fname;
199: extern int errno;
200:
201: if ((fp = fopen(name, fmode)) == NULL) {
202: #ifdef IHCC
203: /*
204: * IHCC users only see the "filename" that was in trouble,
205: * not the whole path. (for security!)
206: */
207: fname = rindex(name, '/') + 1;
208: #else
209: fname = name;
210: #endif
211: xerror("Cannot open %s (%s): %s", fname, fmode, errmsg(errno));
212: }
213: /* kludge for setuid not being honored for root */
214: if ((uid == 0) && (duid != 0) && ((*fmode == 'a') || (*fmode == 'w')))
215: (void) chown(name, duid, dgid);
216: return fp;
217: }
218:
219: char *
220: errmsg(code)
221: int code;
222: {
223: extern int sys_nerr;
224: extern char *sys_errlist[];
225: static char ebuf[6+5+1];
226:
227: if (code > sys_nerr) {
228: (void) sprintf(ebuf, "Error %d", code);
229: return ebuf;
230: } else
231: return sys_errlist[code];
232: }
233:
234: prefix(full, pref)
235: register char *full, *pref;
236: {
237: register char fc, pc;
238:
239: while ((pc = *pref++) != '\0') {
240: fc = *full++;
241: if (isupper(fc))
242: fc = tolower(fc);
243: if (isupper(pc))
244: pc = tolower(pc);
245: if (fc != pc)
246: return FALSE;
247: }
248: return TRUE;
249: }
250:
251: char *
252: dirname(ngname)
253: char *ngname;
254: {
255: static char rbuf[BUFLEN];
256: register char *p;
257:
258: (void) sprintf(rbuf, "%s/%s", SPOOL, ngname);
259:
260: for (p=rbuf+strlen(SPOOL); *p; p++)
261: if (*p == '.')
262: *p = '/';
263: return rbuf;
264: }
265:
266: /*
267: * Return TRUE iff ngname is a valid newsgroup name
268: */
269: validng(ngname)
270: char *ngname;
271: {
272: register FILE *fp;
273: register char *p, *q;
274: char abuf[BUFLEN];
275:
276: fp = xfopen(ACTIVE, "r");
277: while(fgets(abuf, BUFLEN, fp) != NULL) {
278: p = abuf;
279: q = ngname;
280: while (*p++ == *q++)
281: ;
282: if (*--q == '\0' && *--p == ' ') {
283: (void) fclose(fp);
284: return TRUE;
285: }
286: }
287: (void) fclose(fp);
288: return FALSE;
289: }
290:
291: /* VARARGS1 */
292: xerror(message, arg1, arg2, arg3)
293: char *message;
294: int arg1, arg2, arg3;
295: {
296: char buffer[128];
297:
298: fflush(stdout);
299: (void) sprintf(buffer, message, arg1, arg2, arg3);
300: logerr(buffer);
301: xxit(1);
302: }
303:
304: /* VARARGS1 */
305: log(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
306: char *fmt;
307: {
308: _dolog(0, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
309: }
310:
311: /* VARARGS1 */
312: logerr(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
313: char *fmt;
314: {
315: _dolog(1, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
316: }
317:
318: char *lfsuffix[] = {
319: "log",
320: "errlog",
321: 0
322: };
323:
324: /*
325: * Log the given message, with printf strings and parameters allowed,
326: * on the log file, if it can be written. The date and an attempt at
327: * figuring out the remote system name are also logged.
328: */
329: /* VARARGS1 */
330: _dolog(which, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
331: char *fmt;
332: {
333: FILE *logfile;
334: register char *p, *logtime;
335: int i;
336: char logfname[BUFLEN]; /* the log file */
337: char rmtsys[BUFLEN];
338: char msg[BUFLEN];
339: time_t t;
340:
341: (void) strcpy(rmtsys, header.path);
342: p = index(rmtsys, '!');
343: if (p == NULL)
344: p = index(rmtsys, ':');
345: if (p)
346: *p = 0;
347: else {
348: p = rindex(rmtsys, '@');
349: if (p)
350: (void) strcpy(rmtsys, p+1);
351: else
352: (void) strcpy(rmtsys, "local");
353: }
354:
355: (void) time(&t);
356: logtime = ctime(&t);
357: logtime[16] = 0;
358: logtime += 4;
359:
360:
361: (void) sprintf(msg, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
362:
363: if (which)
364: fprintf(stderr,"%s: %s\n", Progname, msg);
365:
366: for (i=0; i<=which;i++) {
367: (void) sprintf(logfname, "%s/%s", LIB, lfsuffix[i]);
368:
369: if (access(logfname, 0) == 0 && (logfile = fopen(logfname, "a")) != NULL) {
370: #if defined(USG) || defined(BSD4_2) || defined(BSD4_1C)
371: int flags;
372: flags = fcntl(fileno(logfile), F_GETFL, 0);
373: (void) fcntl(fileno(logfile), F_SETFL, flags|O_APPEND);
374: #else /* v7 */
375: (void) lseek(fileno(logfile), 0L, 2);
376: #endif /* v7 */
377: if (i)
378: fprintf(logfile, "%s\t%s\t%s: %s\n", logtime,
379: header.ident[0] ? header.ident : username, Progname, msg);
380: else
381: fprintf(logfile, "%s\t%s\t%s\n", logtime,
382: rmtsys, msg);
383: (void) fclose(logfile);
384: }
385: }
386: }
387: #ifdef VMS
388:
389: /*
390: * vmslink allows simulation of file linking under VMS.
391: */
392: vmslink(infile,outfile)
393: char *infile, *outfile;
394: {
395: FILE *fp;
396:
397: if (access(outfile,0) == 0) {
398: errno = EEXIST;
399: return -1;
400: }
401:
402: fp = fopen(outfile, "w");
403: if (fp == NULL) {
404: errno = EACCES;
405: return -1;
406: }
407:
408: (void) fprintf(fp, "%s", infile);
409: (void) fclose(fp);
410:
411: return 0;
412: }
413:
414: /*
415: * vmsdelete deletes all revisions of a file. It attempts to
416: * appear as unlink(2) under conventional Unix in other respects.
417: */
418: vmsdelete(file)
419: char *file;
420: {
421: int i;
422:
423: i = unlink(file);
424: if (i != 0)
425: return i;
426:
427: i = errno;
428: while (unlink(file) == 0)
429: ;
430: errno = i;
431:
432: return 0;
433: }
434:
435: /*
436: * Convert a Unix file to a VMS fixed record format file by
437: * executing the 'unixtovms' command.
438: */
439: unixtovms(file)
440: char *file;
441: {
442: char buf[BUFLEN];
443: sprintf(buf, "exec /etc/unixtovms %s", file);
444: return system(buf);
445: }
446:
447: /*
448: * Convert a VMS fixed record format file to a Unix file by
449: * executing the 'vmstounix' command.
450: */
451: vmstounix(file)
452: char *file;
453: {
454: char buf[BUFLEN];
455: sprintf(buf,"exec /etc/vmstounix %s", file);
456: return system(buf);
457: }
458: #endif /* VMS */
459:
460: #if !defined(BSD4_2) && !defined(BSD4_1C)
461: /*
462: * make a directory. Also make sure that the directory is owned
463: * by the right userid
464: */
465: mkdir(path, perm)
466: char *path;
467: int perm;
468: {
469: int pid, status;
470:
471: if (pid=fork()) {
472: status = fwait(pid);
473: #if defined(USG) && !defined(CHEAP)
474: if (pid=fork())
475: (void) fwait(pid);
476: else {
477: setgid(gid);
478: setuid(uid);
479: if (chown(path, duid, dgid) == 0)
480: (void) chmod(path, perm&(~N_UMASK));
481: _exit(0);
482: }
483: #endif /* USG && !CHEAP */
484: } else {
485: (void) setgid(dgid);
486: if (setuid(duid) < 0)
487: (void) umask(0);
488: else
489: (void) umask(perm&N_UMASK);
490: (void) execlp("mkdir", "mkdir", path, (char *)NULL);
491: perror(path);
492: _exit(1);
493: }
494: return status;
495: }
496: #endif /* !BSD4_2 && ! BSD4_1C */
497: #ifndef USG
498: char *
499: strpbrk(str, chars)
500: register char *str, *chars;
501: {
502: register char *cp;
503:
504: do {
505: cp = chars - 1;
506: while (*++cp) {
507: if (*str == *cp)
508: return str;
509: }
510: } while (*str++);
511: return NULL;
512: }
513: #endif /* !USG */
514:
515: #ifdef FASCIST
516: /*
517: * This routine checks to see if the posting user is allowed to
518: * post to the given newsgroup. If the username is not in the file
519: * $LIBDIR/authorized then the default in the symbol FASCIST is used.
520: *
521: * Format of the call:
522: * fascist(user, newgroups)
523: *
524: * Returns:
525: * FALSE, if authorized
526: * TRUE, if not
527: *
528: * Format of the file "authorized" is:
529: * user:allowed groups
530: *
531: * Example:
532: * root:net.all,mod.all
533: * naughty_person:junk,net.politics
534: * operator:!net.all,general,test,mod.unix
535: *
536: * An open environment could have FASCIST set to "all"
537: * and then individual entries could be made in the authorized file
538: * to prevent certain individuals from posting to such a wide
539: * area.
540: *
541: * Note that a distribution of "all" does NOT mean to allow postings
542: * only to local groups -- "all" includes "all.all".
543: * Use "all,!all.all" to get this behavior
544: *
545: * Eugene Spafford spaf@gatech May 22, 1985
546: */
547:
548: fascist(user, newsgroups)
549: register char *user, *newsgroups;
550: {
551: FILE *facfd;
552: char facuser[BUFLEN], facgroups[BUFLEN], factemp[BUFLEN];
553: register char *facptr;
554:
555: /* First, open the necessary file...$LIBDIR/authorized and see if there
556: * is an entry for this user
557: */
558:
559: (void) strncpy(facgroups, FASCIST, BUFLEN);
560: sprintf(factemp, "%s/%s", LIBDIR, "authorized");
561: facfd = fopen(factemp, "r");
562:
563: if (facfd != NULL) { /* If no such file, we go with the global default */
564: while (fscanf(facfd, "%[^:]:%s\n", facuser, factemp) != EOF)
565: if (strncmp(facuser, user, BUFLEN) == 0) {
566: (void) strcat(facgroups, ",");
567: (void) strcat(facgroups, factemp);
568: break;
569: }
570: fclose (facfd);
571: }
572: #ifdef DEBUG
573: fprintf(stderr, "facgroups = %s\n", facgroups);
574: fprintf(stderr, "newsgroups = %s\n", newsgroups);
575: #endif DEBUG
576:
577: /* We step through the newsgroups being posted to and check each against
578: * the restriction list. *ALL* posted groups must match the restriction
579: * list or we don't allow the posting.
580: */
581:
582: while (*newsgroups != '\0') {
583: facptr = factemp;
584: while (*newsgroups != '\0' && *newsgroups != NGDELIM)
585: *facptr++ = *newsgroups++;
586: *facptr = '\0';
587: if (*newsgroups == NGDELIM)
588: newsgroups++;
589:
590: #ifdef DEBUG
591: fprintf(stderr, "Checking newsgroup '%s'\n", factemp);
592: #endif
593:
594: if (ngmatch(factemp, facgroups) == FALSE)
595: return TRUE;
596: }
597:
598: /* must be okay -- return */
599: #ifdef DEBUG
600: fprintf (stderr, "Newsgroups approved for this poster.\n");
601: #endif DEBUG
602: return FALSE;
603: }
604: #endif FASCIST
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.