Annotation of coherent/b/STREAMS/coh.386/null.c, revision 1.1

1.1     ! root        1: /* $Header: /src386/STREAMS/coh.386/RCS/null.c,v 2.3 93/08/09 13:35:51 bin Exp Locker: bin $ */
        !             2: /* (lgl-
        !             3:  *     The information contained herein is a trade secret of Mark Williams
        !             4:  *     Company, and  is confidential information.  It is provided  under a
        !             5:  *     license agreement,  and may be  copied or disclosed  only under the
        !             6:  *     terms of  that agreement.  Any  reproduction or disclosure  of this
        !             7:  *     material without the express written authorization of Mark Williams
        !             8:  *     Company or persuant to the license agreement is unlawful.
        !             9:  *
        !            10:  *     COHERENT Version 2.3.37
        !            11:  *     Copyright (c) 1982, 1983, 1984.
        !            12:  *     An unpublished work by Mark Williams Company, Chicago.
        !            13:  *     All rights reserved.
        !            14:  -lgl) */
        !            15: /*
        !            16:  * Null and memory driver.
        !            17:  *  Minor device 0 is /dev/null
        !            18:  *  Minor device 1 is /dev/mem, physical memory
        !            19:  *  Minor device 2 is /dev/kmem, kernel data
        !            20:  *  Minor device 3 is /dev/cmos
        !            21:  *  Minor device 4 is /dev/boot_gift
        !            22:  *  Minor device 5 is /dev/clock
        !            23:  *  Minor device 6 is /dev/ps
        !            24:  *  Minor device 7 is /dev/kmemhi, virtual memory 0x8000_0000-0xFFFF_FFFF
        !            25:  *  Minor device 11 is /dev/idle
        !            26:  *
        !            27:  * $Log:       null.c,v $
        !            28:  * Revision 2.3  93/08/09  13:35:51  bin
        !            29:  * Kernel 82 changes
        !            30:  * 
        !            31:  * Revision 2.2  93/07/26  14:28:57  nigel
        !            32:  * Nigel's R80
        !            33:  * 
        !            34:  * Revision 1.7  93/04/14  10:06:37  root
        !            35:  * r75
        !            36:  * 
        !            37:  * Revision 1.10  93/03/02  08:16:25  bin
        !            38:  * kernel 73 update
        !            39:  * 
        !            40:  * Revision 1.6  92/11/09  17:10:54  root
        !            41:  * Just before adding vio segs.
        !            42:  * 
        !            43:  * Revision 1.2  92/01/06  11:59:49  hal
        !            44:  * Compile with cc.mwc.
        !            45:  * 
        !            46:  * Revision 1.1        88/03/24  16:14:04      src
        !            47:  * Initial revision
        !            48:  * 
        !            49:  */
        !            50: 
        !            51: /*
        !            52:  * The symbol "DANGEROUS" should be undefined for a production system.
        !            53:  */
        !            54: #ifdef TRACER
        !            55: #define NULL_IOCTL     /* Allow ioctl()s for /dev/kmem.  */
        !            56: #define DANGEROUS      /* Allow dangerous ioctl()s for /dev/null.  */
        !            57: #endif
        !            58: #define IDLE_DEV
        !            59: 
        !            60: #include <kernel/typed.h>
        !            61: 
        !            62: #include <sys/coherent.h>
        !            63: #include <sys/con.h>
        !            64: #include <sys/errno.h>
        !            65: #include <sys/stat.h>
        !            66: #include <sys/inode.h>
        !            67: #include <sys/seg.h>
        !            68: #include <sys/coh_ps.h>
        !            69: #include <sys/file.h>
        !            70: #if defined NULL_IOCTL || defined IDLE_DEV
        !            71:    #include <sys/null.h>
        !            72: #endif /* NULL_IOCTL || IDLE_DEV */
        !            73: 
        !            74: 
        !            75: #if    TRACER
        !            76: #include <sys/buf.h>
        !            77: #endif
        !            78: 
        !            79: /* These are minor numbers.  */
        !            80: #define DEV_NULL       0       /* /dev/null    */
        !            81: #define DEV_MEM                1       /* /dev/mem     */
        !            82: #define DEV_KMEM       2       /* /dev/kmem    */
        !            83: #define DEV_CMOS       3       /* /dev/cmos    */
        !            84: #define DEV_BOOTGIFT   4       /* /dev/bootgift  */
        !            85: #define DEV_CLOCK      5       /* /dev/clock  */
        !            86: #define DEV_PS         6       /* /dev/ps  */
        !            87: #define DEV_KMEMHI     7       /* /dev/kmemhi  */
        !            88: #define DEV_IDLE       11      /* /dev/idle    */
        !            89: 
        !            90: #define KMEMHI_BASE    0x80000000
        !            91: #define PXCOPY_LIM     4096
        !            92: 
        !            93: /*
        !            94:  * CMOS devices are limited by an 8 bit address.
        !            95:  */
        !            96: #define MAX_CMOS       255
        !            97: #define CMOS_LEN       256
        !            98: 
        !            99: /*
        !           100:  * The first 14 bytes of the CMOS are the clock.
        !           101:  */
        !           102: #define MAX_CLOCK      13
        !           103: #define CLOCK_LEN      14
        !           104: 
        !           105: /*
        !           106:  * These are definitions for mucking with the CMOS clock.
        !           107:  */
        !           108: #define SRA    10      /* Status Register A */
        !           109: #define SRB    11      /* Status Register B */
        !           110: #define SRC    12      /* Status Register C */
        !           111: #define SRD    13      /* Status Register D */
        !           112: 
        !           113: #define UIP    0x80    /* Update In Progress bit of SRA.       */
        !           114: #define NO_UPD 0x80    /* No Update bit of SRB.                */
        !           115: 
        !           116: /*
        !           117:  * Functions for configuration.
        !           118:  */
        !           119: void   nlopen();
        !           120: void   nlclose();
        !           121: void   nlread();
        !           122: void   nlwrite();
        !           123: int    nlioctl();
        !           124: int    nulldev();
        !           125: int    nonedev();
        !           126: 
        !           127: /*
        !           128:  * Configuration table.
        !           129:  */
        !           130: CON nlcon ={
        !           131:        DFCHR,                          /* Flags */
        !           132:        0,                              /* Major index */
        !           133:        nlopen,                         /* Open */
        !           134:        nlclose,                        /* Close */
        !           135:        nulldev,                        /* Block */
        !           136:        nlread,                         /* Read */
        !           137:        nlwrite,                        /* Write */
        !           138: #if defined NULL_IOCTL || defined IDLE_DEV
        !           139:        nlioctl,                        /* Ioctl */
        !           140: #else /* NULL_IOCTL || IDLE_DEV */
        !           141:        nonedev,                        /* Ioctl */
        !           142: #endif /* NULL_IOCTL || IDLE_DEV */
        !           143:        nulldev,                        /* Powerfail */
        !           144:        nulldev,                        /* Timeout */
        !           145:        nulldev,                        /* Load */
        !           146:        nulldev                         /* Unload */
        !           147: };
        !           148: 
        !           149: int lock_clock();
        !           150: void unlock_clock();
        !           151: 
        !           152: /*
        !           153:  * Null/memory open routine.
        !           154:  */
        !           155: void
        !           156: nlopen(dev, mode)
        !           157: dev_t dev;
        !           158: int mode;
        !           159: {
        !           160:        switch (minor(dev)) {
        !           161: #ifdef IDLE_DEV
        !           162:        case DEV_IDLE:
        !           163: #endif
        !           164:        case DEV_PS:
        !           165:                /* /dev/ps is read only */
        !           166:                if (IPR != (IPR & mode)) 
        !           167:                        SET_U_ERROR( EACCES, "/dev/ps is read only" );
        !           168:                break;
        !           169:        default:
        !           170:                /*
        !           171:                 * For minor devices on NULL there is
        !           172:                 * usually no action for open().
        !           173:                 */
        !           174:                break;
        !           175:        }
        !           176:        return;
        !           177: } /* nlopen() */
        !           178: 
        !           179: /*
        !           180:  * Null/memory close routine.
        !           181:  */
        !           182: void
        !           183: nlclose(dev, mode)
        !           184: dev_t dev;
        !           185: int mode;
        !           186: {
        !           187:        /*
        !           188:         * For minor devices on NULL there is
        !           189:         * Usually no action for close().
        !           190:         */
        !           191:        return;
        !           192: } /* nlclose() */
        !           193: 
        !           194: /*
        !           195:  * Null/memory read routine.
        !           196:  */
        !           197: void
        !           198: nlread(dev, iop)
        !           199: dev_t dev;
        !           200: register IO *iop;
        !           201: {
        !           202:        register unsigned       bytesRead;
        !           203:        register PROC           *pp1;           /* */
        !           204:        char                    psBuf[ARGSZ];   /* buffer for command line
        !           205:                                                 * arguments for ps. */
        !           206:        stMonitor               psData;         /* All process data for */
        !           207:        UPROC                   *uprc;          /* pointer to u area */
        !           208:        int                     ndpUseg;        /* System global address 
        !           209:                                                 * of U segment */
        !           210:        unsigned int            seek;
        !           211:        unsigned char           read_cmos();
        !           212:        extern typed_space      boot_gift;
        !           213: 
        !           214:        switch (minor (dev)) {
        !           215:        case DEV_NULL:
        !           216:                /*
        !           217:                 * Read nothing.
        !           218:                 * Do NOT update iop->io_ioc.
        !           219:                 * This way, caller knows 0 bytes were read.
        !           220:                 */
        !           221:                break;
        !           222: 
        !           223:        case DEV_MEM: {
        !           224:                int src = iop->io_seek;
        !           225:                int dest = iop->io.pbase;
        !           226: 
        !           227:                while (iop->io_ioc) {
        !           228:                        int numBytes = PXCOPY_LIM;
        !           229:                        if (numBytes > iop->io_ioc)
        !           230:                                numBytes = iop->io_ioc;
        !           231: 
        !           232:                        bytesRead = pxcopy (src, dest, numBytes,
        !           233:                                            SEG_386_UD | R_USR);
        !           234:                        src += bytesRead;
        !           235:                        dest += bytesRead;
        !           236:                        iop->io_ioc -= bytesRead;
        !           237:                        if (u.u_error == EFAULT) {
        !           238:                                u.u_error = 0;
        !           239:                                break;
        !           240:                        }
        !           241:                }
        !           242:                break;
        !           243:        }
        !           244: 
        !           245:        case DEV_KMEM:
        !           246:                iowrite (iop, iop->io_seek, iop->io_ioc);
        !           247:                if (u.u_error == EFAULT)
        !           248:                        u.u_error = 0;
        !           249:                break;
        !           250: 
        !           251:        case DEV_CLOCK:
        !           252:                /*
        !           253:                 * Don't go past the end of the CLOCK.
        !           254:                 */
        !           255:                if (iop->io_seek >= CLOCK_LEN)
        !           256:                        break;
        !           257: 
        !           258:                /*
        !           259:                 * Lock the clock before any reading.
        !           260:                 */
        !           261: 
        !           262:                if (lock_clock () == 0) {
        !           263:                        SET_U_ERROR (EIO, "RT clock will not settle.");
        !           264:                        break;
        !           265:                }
        !           266: 
        !           267:                /*
        !           268:                 * Read the requested data out of the CMOS.
        !           269:                 */
        !           270:                for (seek = iop->io_seek; seek < CLOCK_LEN; seek++) {
        !           271:                        if(ioputc(read_cmos(seek), iop) == -1)
        !           272:                                break;
        !           273:                }
        !           274: 
        !           275:                /*
        !           276:                 * Now that we are done reading the CMOS, let
        !           277:                 * the clock loose.
        !           278:                 */
        !           279:                unlock_clock();
        !           280:                break;
        !           281: 
        !           282:        case DEV_CMOS:
        !           283:                /*
        !           284:                 * Don't go past the end of the CMOS.
        !           285:                 */
        !           286:                if (iop->io_seek >= CMOS_LEN)
        !           287:                        break;
        !           288: 
        !           289:                /*
        !           290:                 * Read the requested data out of the CMOS.
        !           291:                 */
        !           292:                for (seek = iop->io_seek; seek < CMOS_LEN; seek++) {
        !           293:                        if(ioputc(read_cmos(seek), iop) == -1)
        !           294:                                break;
        !           295:                }
        !           296:                break;
        !           297: 
        !           298:        case DEV_BOOTGIFT:
        !           299:                /*
        !           300:                 * Reads all from the data structure boot_gift.
        !           301:                 */
        !           302:                if (iop->io_seek < BG_LEN) {
        !           303:                        bytesRead = iop->io_ioc;
        !           304: 
        !           305:                        /*
        !           306:                         * Copy no more than to the end of boot_gift.
        !           307:                         */
        !           308:                        if (iop->io_seek + bytesRead > BG_LEN)
        !           309:                                bytesRead = BG_LEN - iop->io_seek;
        !           310: 
        !           311:                        iowrite (iop, (char *) (& boot_gift) + iop->io_seek,
        !           312:                                 bytesRead);
        !           313:                }
        !           314:                break;
        !           315: 
        !           316:        case DEV_PS:
        !           317:                /* Lock the process table. It allows to have an atomic ps. */
        !           318:                lock (pnxgate);
        !           319:                /* Main driver loop. Go through all processes. Fill struct PS
        !           320:                 * and send put to user buffer.
        !           321:                 */
        !           322:                for (pp1 = & procq; (pp1 = pp1->p_nforw) != & procq; ) {
        !           323:                        register int            i;      /* loop index */
        !           324:                        register unsigned       uLen,   /* Process size */
        !           325:                                                uLenR;  /* Real process size */
        !           326:                        register SEG    *sp;    /* u area segment */
        !           327:                        int work;       /* virtual click number */
        !           328: 
        !           329:                        /* Check if driver can send next proc data */ 
        !           330:                        if (iop->io_ioc < sizeof (stMonitor)) 
        !           331:                                break;
        !           332:                                
        !           333:                        /* Calculate the size of process. */
        !           334:                        uLen = uLenR = 0;
        !           335:                        for (i = 0 ; i < NUSEG ; i++) {
        !           336:                                if ((sp = pp1->p_segp [i]) == NULL)
        !           337:                                        continue;
        !           338:                                uLenR += sp->s_size;
        !           339:                                if (i == SIUSERP || i == SIAUXIL)
        !           340:                                        continue;
        !           341:                                uLen += sp->s_size;
        !           342:                
        !           343:                        } 
        !           344: 
        !           345:                        /* Find u area for process pp1 */
        !           346:                        sp = pp1->p_segp [SIUSERP];
        !           347:                        ndpUseg = MAPIO (sp->s_vmem, U_OFFSET);
        !           348:                        work = workAlloc ();
        !           349:                        ptable1_v [work] = 
        !           350:                                   sysmem.u.pbase [btocrd (ndpUseg)] | SEG_RW;
        !           351:                        uprc = (UPROC *) (ctob (work) + U_OFFSET);
        !           352:                        memcpy (psData.u_comm, uprc->u_comm, ARGSZ);
        !           353:                        memcpy (psData.u_sleep, uprc->u_sleep, U_SLEEP_LEN);
        !           354:                        workFree (work);
        !           355: 
        !           356: #ifdef TRACER
        !           357:                        if (strncmp (psData.u_sleep, "lock",
        !           358:                                     U_SLEEP_LEN) == 0) {
        !           359:                                GATE          * g = pp1->p_event;
        !           360:                                printf ("[%d] locked at %x lock %s (%d) = %x\n",
        !           361:                                        pp1->p_pid, g, g->_name, g->_count,
        !           362:                                        g->_lock [0]);
        !           363:                        }
        !           364:                        if (strncmp (psData.u_sleep, "bpwait",
        !           365:                                     U_SLEEP_LEN) == 0) {
        !           366:                                BUF           * bp = pp1->p_event;
        !           367:                                printf ("[%d] blocked on %x flags = %x\n",
        !           368:                                        pp1->p_pid, bp, bp->b_flag);
        !           369:                        }
        !           370: #endif
        !           371: 
        !           372:                        /* fill up stMonitor */
        !           373:                        psData.p_pid = pp1->p_pid;
        !           374:                        psData.p_ppid = pp1->p_ppid;
        !           375:                        psData.p_uid = pp1->p_uid;
        !           376:                        psData.p_ruid = pp1->p_ruid;
        !           377:                        psData.p_rgid = pp1->p_rgid;
        !           378:                        psData.p_state = pp1->p_state;
        !           379:                        psData.p_flags = pp1->p_flags;
        !           380:                        psData.rrun = (char *) pp1 != pp1->p_event;
        !           381:                        psData.p_event = pp1->p_event;
        !           382:                        psData.p_ttdev = pp1->p_ttdev;
        !           383:                        psData.p_nice = pp1->p_nice;
        !           384:                        psData.size = (short) (uLen >> 10);
        !           385:                        psData.rsize = (short) (uLenR >> 10);
        !           386:                        psData.p_schedPri = pp1->p_schedPri;
        !           387:                        psData.p_utime = pp1->p_utime;
        !           388:                        psData.p_stime = pp1->p_stime;
        !           389: 
        !           390:                        memcpy (psData.pr_argv, psBuf, ARGSZ);
        !           391: 
        !           392:                        /* send data to user */
        !           393:                        iowrite (iop, (char *) & psData, sizeof (stMonitor));
        !           394:                }
        !           395:                unlock (pnxgate);
        !           396:                break;
        !           397: 
        !           398:        case DEV_KMEMHI:
        !           399:                iowrite (iop, iop->io_seek - KMEMHI_BASE, iop->io_ioc);
        !           400:                if (u.u_error == EFAULT)
        !           401:                        u.u_error = 0;
        !           402:                break;
        !           403: 
        !           404:        default:
        !           405:                SET_U_ERROR (ENXIO, "nlread(): illegal minor device for null");
        !           406:        }
        !           407:        return;
        !           408: }
        !           409: 
        !           410: /*
        !           411:  * Null/memory write routine.
        !           412:  */
        !           413: void
        !           414: nlwrite(dev, iop)
        !           415: dev_t dev;
        !           416: register IO *iop;
        !           417: {
        !           418:        register unsigned bytesWrit;
        !           419:        unsigned write_cmos();
        !           420:        unsigned seek;
        !           421:        int     ch;
        !           422: 
        !           423:        switch (minor (dev)) {
        !           424:        case DEV_NULL:
        !           425:                /*
        !           426:                 * Tell caller all bytes were written.
        !           427:                 */
        !           428:                iop->io_ioc = 0;
        !           429:                break;
        !           430: 
        !           431:        case DEV_MEM:
        !           432:                while (iop->io_ioc) {
        !           433:                        int src = iop->io.pbase;
        !           434:                        int dest = iop->io_seek;
        !           435:                        int numBytes = PXCOPY_LIM;
        !           436:                        if (numBytes > iop->io_ioc)
        !           437:                                numBytes = iop->io_ioc;
        !           438: 
        !           439:                        bytesWrit = xpcopy (src, dest, numBytes,
        !           440:                                            SEG_386_UD | R_USR);
        !           441:                        src += bytesWrit;
        !           442:                        dest += bytesWrit;
        !           443:                        iop->io_ioc -= bytesWrit;
        !           444:                        if (u.u_error == EFAULT) {
        !           445:                                u.u_error = 0;
        !           446:                                break;
        !           447:                        }
        !           448:                }
        !           449:                break;
        !           450: 
        !           451:        case DEV_KMEM:
        !           452:                ioread (iop, iop->io_seek, iop->io_ioc);
        !           453:                break;
        !           454: 
        !           455:        case DEV_CLOCK:
        !           456:                /*
        !           457:                 * Don't go past the end of the CLOCK.
        !           458:                 */
        !           459:                if (iop->io_seek >= CLOCK_LEN)
        !           460:                        break;
        !           461: 
        !           462:                /*
        !           463:                 * Lock the clock before any writing.
        !           464:                 */
        !           465:                if (lock_clock () == 0) {
        !           466:                        SET_U_ERROR (EIO, "RT clock will not settle.");
        !           467:                        break;
        !           468:                }
        !           469: 
        !           470:                /*
        !           471:                 * Write the requested data into the CMOS.
        !           472:                 */
        !           473: 
        !           474:                for (seek = iop->io_seek ; seek < CLOCK_LEN ; seek ++) {
        !           475:                        if ((ch = iogetc (iop)) == -1)
        !           476:                                break;
        !           477:                        write_cmos (seek, ch);
        !           478:                }
        !           479: 
        !           480:                /*
        !           481:                 * Now that we are done writing the CMOS, let
        !           482:                 * the clock loose.
        !           483:                 */
        !           484:                unlock_clock ();
        !           485:                break;
        !           486: 
        !           487:        case DEV_CMOS:
        !           488:                /*
        !           489:                 * Don't go past the end of the CMOS.
        !           490:                 */
        !           491:                if (iop->io_seek >= CMOS_LEN)
        !           492:                        break;
        !           493: 
        !           494:                /*
        !           495:                 * Write the requested data into the CMOS.
        !           496:                 */
        !           497:                for (seek = iop->io_seek ; seek < CMOS_LEN ; seek ++) {
        !           498:                        if ((ch = iogetc (iop)) == -1)
        !           499:                                break;
        !           500:                        write_cmos (seek, ch);
        !           501:                }
        !           502:                break;
        !           503: 
        !           504:        case DEV_BOOTGIFT:
        !           505:                /*
        !           506:                 * /dev/bootgift is not writable.
        !           507:                 */
        !           508:                break;
        !           509: 
        !           510:        case DEV_PS:
        !           511:                /*
        !           512:                 * We should not be able to open /dev/ps to write.
        !           513:                 * Just paranoya.
        !           514:                 */
        !           515:                break;
        !           516: 
        !           517:        case DEV_KMEMHI:
        !           518:                ioread (iop, iop->io_seek - KMEMHI_BASE, iop->io_ioc);
        !           519:                break;
        !           520: 
        !           521:        default:
        !           522:                SET_U_ERROR (ENXIO,
        !           523:                             "nlwrite(): illegal minor device for null");
        !           524:        }
        !           525:        return;
        !           526: }
        !           527: 
        !           528: #if defined NULL_IOCTL || defined IDLE_DEV /* Includes all of nlioctl().  */
        !           529: 
        !           530: /*
        !           531:  * Do an ioctl call for /dev/null.
        !           532:  */
        !           533: int
        !           534: nlioctl(dev, cmd, vec)
        !           535:        dev_t dev;
        !           536:        int cmd;
        !           537:        char * vec;
        !           538: {
        !           539:        /* Only /dev/kmem and /dev/idle have an ioctl.  */
        !           540:        switch (minor (dev)) {
        !           541: #ifdef NULL_IOCTL
        !           542:        case DEV_KMEM:
        !           543:                switch (cmd) {
        !           544: #ifdef DANGEROUS
        !           545:                case NLCALL:    /* Call a function.  */
        !           546:                return docall (vec);
        !           547: #endif /* DANGEROUS */
        !           548:                default:
        !           549:                        SET_U_ERROR (EINVAL,
        !           550:                                     "nioctl(): illegal command for kmem");
        !           551:                        return -1;
        !           552:                }
        !           553: #endif /* NULL_IOCTL */
        !           554: #ifdef IDLE_DEV
        !           555:        case DEV_IDLE:
        !           556:                if (cmd != NLIDLE) { 
        !           557:                        SET_U_ERROR (EINVAL,
        !           558:                                     "nioctl(): illegal command for idle");
        !           559:                        return -1;
        !           560:                } else {
        !           561:                        register PROC *pp;
        !           562:                        register int *mem = vec;
        !           563: 
        !           564: 
        !           565:                        pp = & procq;   /* point to process queue */
        !           566: 
        !           567:                        if (pp->p_pid != 0) {
        !           568:                                while ((pp = pp->p_nforw) != &procq)
        !           569:                                        if (pp->p_pid == 0)       /* idle process ? */
        !           570:                                                break;
        !           571:                        }
        !           572: 
        !           573:                        /*
        !           574:                         * At this point, pp->p_utime and pp->p_stime contain
        !           575:                         * the idle time of the system process
        !           576:                         */
        !           577: 
        !           578:                        if (pp->p_pid != 0)
        !           579:                                putuwd (mem ++, 0);
        !           580:                        else
        !           581:                                putuwd (mem ++, pp->p_utime + pp->p_stime);
        !           582:                        putuwd (mem, lbolt);
        !           583:                        return 1; 
        !           584:                }
        !           585: 
        !           586: #endif /* IDLE_DEV */
        !           587:        default:
        !           588:                SET_U_ERROR(EINVAL, "illegal minor device for null ioctl");
        !           589:                return -1;
        !           590:        } /* switch on minor device */
        !           591: 
        !           592: } /* nlioctl() */
        !           593: 
        !           594: #endif /* NULL_IOCTL || IDLE_DEV */
        !           595: 
        !           596: #ifdef DANGEROUS /* Includes all of docall().  */
        !           597: /*
        !           598:  * MASSIVE SECURITY HOLE!  This should NOT be included in a distribution
        !           599:  * system.  Among other problems, it becomes possible to do "setuid(0)".
        !           600:  *
        !           601:  * Call a function with arguments.
        !           602:  *
        !           603:  * Takes an array of unsigned ints.  The first element is the length of
        !           604:  * the whole array, the second element is a pointer to the function to
        !           605:  * call, all other elements are arguments.  At most 5 arguments may be
        !           606:  * passed.
        !           607:  *
        !           608:  * Returns the return value of the called fuction in uvec[0].
        !           609:  */
        !           610: int
        !           611: docall(uvec)
        !           612:        unsigned uvec[];
        !           613: {
        !           614:        int (* func)();
        !           615:        unsigned kvec[7];
        !           616:        int retval;
        !           617: 
        !           618:        printf("NLCALL security hole.\n");
        !           619: 
        !           620:        /* Fetch the first element of vec.  */
        !           621:        ukcopy (uvec, kvec, sizeof (unsigned));
        !           622: 
        !           623:        if (kvec [0] < 2 || kvec[0] > 7) {
        !           624:                /* Invalid number of elements in uvec.  */
        !           625:                SET_U_ERROR (EINVAL, "Invalid number of elements in uvec");
        !           626:                return -1;
        !           627:        }
        !           628:        
        !           629:        /* Fetch the whole vector.  */
        !           630:        ukcopy (uvec, kvec, kvec [0] * sizeof (unsigned));
        !           631: 
        !           632:        /* Extract the function.  */
        !           633:        func = (int (*)()) kvec [1];
        !           634: 
        !           635:        /* Call the function with all arguments.  */
        !           636:        retval = (* func) (kvec [2], kvec [3], kvec [4], kvec [5], kvec [6]);
        !           637: 
        !           638:        kucopy (& retval, uvec, sizeof (unsigned));
        !           639: } /* docall() */
        !           640: 
        !           641: #endif /* DANGEROUS */
        !           642: 
        !           643: /*
        !           644:  * int lock_clock() -- Stop the update cycle on the CMOS RT clock and
        !           645:  * wait for it to settle.  Returns 0 if the clock would not settle
        !           646:  * in time.
        !           647:  */
        !           648: int
        !           649: lock_clock()
        !           650: {
        !           651:        register int i;
        !           652: 
        !           653:        /*
        !           654:         * Wait for the clock to settle.  If it does not settle in
        !           655:         * a reasonable amount of time, give up.
        !           656:         */
        !           657: 
        !           658:        i = 65536;      /* Loop for a longish time.  */
        !           659:        while (-- i > 0) {
        !           660:                if (0 == (UIP & read_cmos (SRA))) {
        !           661:                        break;  /* Break if there is no update in progress.  */
        !           662:                }
        !           663:        }
        !           664:        
        !           665:        if (0 == i) {
        !           666:                /* The clock would not settle.  */
        !           667:                return 0;
        !           668:        }
        !           669: 
        !           670:        /*
        !           671:         * There is a tiny race here--an interrupt could conceivably
        !           672:         * come here, thus allowing enough delay for another update to
        !           673:         * begin.  But if we take interrupts that take a full second
        !           674:         * to process, other things are going to break horribly.
        !           675:         */
        !           676:        
        !           677:        /*
        !           678:         * Lock out updates.
        !           679:         * We set the No Updates bit in Clock Status Register B.
        !           680:         */
        !           681:        write_cmos (SRB, read_cmos (SRB) | NO_UPD);
        !           682:        return 1;
        !           683: } /* lock_clock() */
        !           684: 
        !           685: /*
        !           686:  * void unlock_clock() -- Restart the update cycle on the CMOS RT clock.
        !           687:  */ 
        !           688: void
        !           689: unlock_clock()
        !           690: {
        !           691:        /*
        !           692:         * We clear the No Updates bit in Clock Status Register B.
        !           693:         */
        !           694:        write_cmos (SRB, read_cmos(SRB) & ~ NO_UPD);
        !           695: } /* unlock_clock() */

unix.superglobalmegacorp.com

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