Annotation of 43BSD/contrib/news/src/funcs.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.