Annotation of 43BSD/contrib/news/src/funcs.c, revision 1.1.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.