|
|
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.