Annotation of coherent/b/STREAMS/io.386/msg386.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * System V Compatible Messaging
        !             3:  *
        !             4:  * This module provides System V compatible messaging operations.
        !             5:  */
        !             6: #include <sys/coherent.h>
        !             7: #include <sys/sched.h>
        !             8: #include <sys/types.h>
        !             9: #include <sys/uproc.h>
        !            10: #include <sys/errno.h>
        !            11: #include <sys/stat.h>
        !            12: #include <sys/con.h>
        !            13: #include <sys/seg.h>
        !            14: #include <sys/msg.h>
        !            15: 
        !            16: /*
        !            17:  * Global Message Parameters. We want them to be patchable.
        !            18:  */
        !            19: unsigned NMSQID = 50;  /* maximum number of message queues */
        !            20: unsigned NMSQB  = 4096;        /* default maximum queue size in bytes */
        !            21: unsigned NMSG = 40;    /* maximum number of messages per queue */
        !            22: unsigned NMSC = 2048;  /* message text size */
        !            23: 
        !            24: #ifdef TRACER
        !            25: int    dballoc = 0;    /* For debug only */
        !            26: int    dbfree = 0;
        !            27: #endif
        !            28: 
        !            29: /* Message Information */
        !            30: struct msqid_ds *msqs = NULL;  /* Array of message queues */
        !            31: GATE           *msg_gate;      /* Message gates */
        !            32: char           **msg_map;      /* Memory map */
        !            33: 
        !            34: /* 
        !            35:  * Msgctl - Message Control Operations.
        !            36:  */
        !            37: umsgctl(qid, cmd, buf)
        !            38: int qid;
        !            39: int cmd;
        !            40: struct msqid_ds *buf;
        !            41: {
        !            42:        register struct msqid_ds        *qp;    /* message queues */
        !            43:        register struct msg             *mp;    /* single message queue */
        !            44:        unsigned short                  n;      /* temporary variable */
        !            45: 
        !            46:        /* Validate qid */
        !            47:        if (qid < 0)  {
        !            48:                u.u_error = EINVAL;
        !            49:                return -1;
        !            50:        }
        !            51:        qp = &msqs[qid % NMSQID];
        !            52: 
        !            53:        /* Validate queue existence.*/
        !            54:        if (qp->msg_perm.seq != qid || (qp->msg_perm.mode & IPC_ALLOC) == 0) {
        !            55:                u.u_error = EINVAL;
        !            56:                return -1;
        !            57:        }
        !            58: 
        !            59:        switch (cmd) {
        !            60:        case IPC_STAT:
        !            61:                /* Validate access authority. */
        !            62:                if ((ipcaccess(&qp->msg_perm) & MSG_R) == 0) {
        !            63:                        u.u_error = EACCES;
        !            64:                        break;
        !            65:                }
        !            66: 
        !            67:                 /* Copy queue info to user buffer */
        !            68:                kucopy(qp, buf, sizeof(struct msqid_ds));
        !            69:                break;
        !            70:        case IPC_SET:
        !            71:                 /* Validate modify authority. */
        !            72:                if ((u.u_uid != 0) && (u.u_uid != qp->msg_perm.uid)) {
        !            73:                        u.u_error = EPERM;
        !            74:                        break;
        !            75:                }
        !            76: 
        !            77:                /*
        !            78:                 * Get desired queue size.
        !            79:                 */
        !            80:                n = getusd(&(buf->msg_qbytes));
        !            81:                if (u.u_error)
        !            82:                        break;
        !            83: 
        !            84:                /*
        !            85:                 * Only super-user can increase queue size.
        !            86:                 */
        !            87:                if ((u.u_uid != 0) && (n > qp->msg_qbytes)) {
        !            88:                        u.u_error = EPERM;
        !            89:                        break;
        !            90:                }
        !            91: 
        !            92:                /*
        !            93:                 * Set queue parameters.
        !            94:                 */
        !            95:                qp->msg_perm.uid = getusd(&(buf->msg_perm.uid));
        !            96:                qp->msg_perm.gid = getusd(&(buf->msg_perm.gid));
        !            97:                qp->msg_perm.mode &= ~0777;
        !            98:                qp->msg_perm.mode |= getusd(&(buf->msg_perm.mode)) & 0777;
        !            99:                /* We may want to change the max size of a single message too.
        !           100:                 * It is not obvious how to do it. There is no
        !           101:                 * description in SVID. So it is possible that at some point
        !           102:                 * the size of the single message happens to be greater than
        !           103:                 * the size of message queue ;-(
        !           104:                 */
        !           105:                qp->msg_qbytes = NMSQB = n;
        !           106:                break;
        !           107: 
        !           108:        case IPC_RMID:
        !           109:                 /* Validate removal authority. */
        !           110:                if ((u.u_uid != 0) && (u.u_uid != qp->msg_perm.uid)) {
        !           111:                        u.u_error = EPERM;
        !           112:                        break;
        !           113:                }
        !           114:                /* Free all messages on the queue being removed. */
        !           115:                while (mp = qp->msg_first) {
        !           116:                        qp->msg_first = mp->msg_next;
        !           117:                        T_MSGQ(0x01, dballoc -= sizeof(struct msg));
        !           118:                        msgfree(mp);
        !           119:                }
        !           120:                T_MSGQ(0x01, printf("F%d", dballoc));
        !           121: 
        !           122:                /* Reset queue parameters. */
        !           123:                qp->msg_last = NULL;
        !           124:                qp->msg_qnum = 0;
        !           125:                qp->msg_cbytes = 0;
        !           126:                qp->msg_perm.mode = 0;
        !           127:                /* Set last change time */
        !           128:                qp->msg_ctime  = timer.t_time; 
        !           129:                /* We have to pick up a new unique sequence number.
        !           130:                 * There is a "wrap around bug". But, it is BCS.
        !           131:                 */
        !           132:                qp->msg_perm.seq += (unsigned short) 50;
        !           133:                break;
        !           134:        default:
        !           135:                u.u_error = EINVAL;
        !           136:        }
        !           137: 
        !           138:        if (u.u_error)
        !           139:                return -1;
        !           140: 
        !           141:        return 0;
        !           142: }
        !           143: 
        !           144: /*
        !           145:  * Msgget - Get set of messages
        !           146:  */
        !           147: umsgget(mykey, msgflg)
        !           148: key_t mykey;
        !           149: int msgflg;
        !           150: {
        !           151:        register struct msqid_ds *qp;           
        !           152:        register struct msqid_ds *freeidp = NULL;       
        !           153:        int rwmode;
        !           154:        
        !           155:        /* Init message queues on the first msgget */
        !           156:        if (msqs == NULL)
        !           157:                if (msginit()) {
        !           158:                        u.u_error = ENOSPC;
        !           159:                        return -1;
        !           160:                }
        !           161:        /* Extract desired access mode from flags. */
        !           162:        rwmode = msgflg & 0777; /* 0666 ??? */
        !           163:        T_MSGQ(0x02, printf("U%o", rwmode));
        !           164:        /* Search for desired message queue [also for first free queue]. */
        !           165:        for (qp = msqs; qp < msqs + NMSQID; qp++) {
        !           166:                /* Look for an older free queue */
        !           167:                if (!(qp->msg_perm.mode & IPC_ALLOC)) {
        !           168:                        if (freeidp == NULL 
        !           169:                                        || freeidp->msg_ctime > qp->msg_ctime)
        !           170:                                freeidp = qp;
        !           171:                        continue;
        !           172:                }
        !           173:                if (mykey == IPC_PRIVATE) {     /* creat a new queue */
        !           174:                        if (msgflg & IPC_EXCL)  /* unique new queue */
        !           175:                                if (mykey == qp->msg_perm.key) {
        !           176:                                        u.u_error = EEXIST;/* We cannot creat */
        !           177:                                        return -1;         /* exclusive queue */
        !           178:                                }
        !           179:                        continue;
        !           180:                }
        !           181:                if (qp->msg_perm.key != mykey)  
        !           182:                        continue;
        !           183: 
        !           184:                if (mykey == qp->msg_perm.key) {        /* found! */
        !           185:                        if ((msgflg & IPC_CREAT) && (msgflg & IPC_EXCL)) {
        !           186:                                u.u_error = EEXIST;     /* We cannot creat */
        !           187:                                return -1;              /* exclusive queue */
        !           188:                        }
        !           189: 
        !           190:                        /* PERMISSIONS */
        !           191:                        /* For super-user or if mode is 0 */
        !           192:                        if (u.u_uid == 0 || !rwmode) 
        !           193:                                return qp->msg_perm.seq;
        !           194: 
        !           195:                        /* For owner or creator */
        !           196:                        T_MSGQ(0x02, printf("Q%o", qp->msg_perm.mode));
        !           197:                        if (u.u_uid == qp->msg_perm.uid 
        !           198:                          || u.u_uid == qp->msg_perm.cuid) {
        !           199:                                if ((rwmode & 0600) & (qp->msg_perm.mode & 0600))
        !           200:                                        return qp->msg_perm.seq;
        !           201:                                else {
        !           202:                                        u.u_error = EACCES;
        !           203:                                        return -1;
        !           204:                                }
        !           205:                        }
        !           206: 
        !           207:                        /* For group */         
        !           208:                        if (u.u_gid == qp->msg_perm.gid 
        !           209:                          || u.u_gid == qp->msg_perm.cgid) {
        !           210:                                if ((rwmode & 060) & (qp->msg_perm.mode & 060))
        !           211:                                        return qp->msg_perm.seq;
        !           212:                                else {
        !           213:                                        u.u_error = EACCES;
        !           214:                                        return -1;
        !           215:                                }
        !           216:                        }
        !           217: 
        !           218:                        /* For the rest of the world */
        !           219:                        if ((rwmode & 06) & (qp->msg_perm.mode & 06)) 
        !           220:                                return qp->msg_perm.seq;
        !           221:                        else {
        !           222:                                u.u_error = EACCES;
        !           223:                                return -1;
        !           224:                        }
        !           225:                }
        !           226:        }
        !           227: 
        !           228:        /* Creat a new queue */
        !           229:        if (!(msgflg & IPC_CREAT)) {
        !           230:                u.u_error = ENOENT;
        !           231:                return -1;
        !           232:        }
        !           233:        if ((qp = freeidp) == NULL) {
        !           234:                u.u_error = ENOSPC;
        !           235:                return -1;
        !           236:        }
        !           237:        /* Set new queue */
        !           238:        qp->msg_ctime  = timer.t_time; 
        !           239:        qp->msg_perm.cuid = qp->msg_perm.uid = u.u_uid;
        !           240:        qp->msg_perm.cgid = qp->msg_perm.gid = u.u_gid;
        !           241:        qp->msg_perm.mode = rwmode | IPC_ALLOC;
        !           242:        qp->msg_qnum = qp->msg_lspid = qp->msg_lrpid = qp->msg_stime 
        !           243:                = qp->msg_rtime = 0;
        !           244:        qp->msg_perm.key  = mykey;
        !           245: 
        !           246:        return qp->msg_perm.seq;
        !           247: }
        !           248: 
        !           249: /*
        !           250:  * Allocate space for the message queues and gates.
        !           251:  * Initialize message queue headers
        !           252:  * Return -1 on error.
        !           253:  */
        !           254: msginit()
        !           255: {
        !           256:        struct msqid_ds *qp;
        !           257:        
        !           258:        T_MSGQ(0x01, printf("A%d",dballoc += sizeof(struct msqid_ds) * NMSQID));
        !           259: 
        !           260:        /* Allocate space for message headers */
        !           261:        if ((msqs = 
        !           262:          (struct msqid_ds *) kalloc(sizeof(struct msqid_ds) * NMSQID)) == NULL)
        !           263:                return -1;
        !           264: 
        !           265:        T_MSGQ(0x01, printf("A%d", dballoc += sizeof(GATE) * NMSQID));
        !           266: 
        !           267:        /* Allocate space for message gates */
        !           268:        if ((msg_gate = (GATE *) kalloc(sizeof(GATE) * NMSQID)) == NULL) {
        !           269:                kfree(msqs);
        !           270:                msqs = NULL;
        !           271:                return -1;
        !           272:        }
        !           273: 
        !           274:        T_MSGQ(0x01, printf("A%d", dballoc += sizeof(char *) * NMSQID * NMSG));
        !           275: 
        !           276:        /* Allocate space for the message map */
        !           277:        if ((msg_map = kalloc(sizeof(char *) * NMSQID * NMSG)) == NULL) {
        !           278:                kfree(msqs);
        !           279:                msqs = NULL;
        !           280:                kfree(msg_gate);
        !           281:                return -1;
        !           282:        }
        !           283:        /* Clear gate and map areas */
        !           284:        kclear(msg_gate, sizeof(GATE) * NMSQID);
        !           285:        kclear(msg_map, sizeof(char *) * NMSQID * NMSG);
        !           286:        /* Set initial queue values */
        !           287:        for (qp = msqs; qp < msqs + NMSQID; qp++) {
        !           288:                qp->msg_first  = NULL;  /* First and last pointers to   */
        !           289:                qp->msg_last   = NULL;  /* message queue                */
        !           290:                qp->msg_cbytes = 0;     /* Number of bytes in queue     */
        !           291:                qp->msg_qnum   = 0;     /* Number of messages in queue  */
        !           292:                qp->msg_qbytes = NMSQB; /* Max size of a queue          */
        !           293:                qp->msg_lspid  = 0;     /* Pid of last msgsnd           */
        !           294:                qp->msg_lrpid  = 0;     /* Pid of last msgrcv           */
        !           295:                qp->msg_stime  = 0;     /* Last msgsnd time             */
        !           296:                qp->msg_rtime  = 0;     /* Last msgrcv time             */
        !           297:                qp->msg_ctime  = timer.t_time; /* Last change time      */
        !           298:                qp->msg_perm.seq = qp - msqs;
        !           299:                qp->msg_perm.mode = 0;
        !           300:        }
        !           301:        return 0;
        !           302: }
        !           303: 
        !           304: /* 
        !           305:  * Remove the message. Clear message text and header. Reset values in 
        !           306:  * message map.
        !           307:  */
        !           308: msgfree(mp)
        !           309: struct msg     *mp;    /* Message header to be remove */
        !           310: {
        !           311: 
        !           312:        kfree(msg_map[mp->msg_spot]);
        !           313:        msg_map[mp->msg_spot] = NULL;
        !           314:        kfree(mp);
        !           315:        T_MSGQ(0x01, printf("F%d", dballoc-=(mp->msg_ts + sizeof(struct msg))));
        !           316: }
        !           317: 
        !           318: /*
        !           319:  * Send a Message
        !           320:  */
        !           321: umsgsnd(qid, bufp, msgsz, msgflg)
        !           322: int    qid;            /* queue id */
        !           323: struct         msgbuf *bufp;   /* message buffer */
        !           324: int    msgsz,          /* message size */
        !           325:        msgflg;         /* flags */
        !           326: {
        !           327:        register struct msqid_ds        *qp;    /* message queue */
        !           328:        register struct msg             *mp,    /* message struct */ 
        !           329:                                        *tmp;
        !           330:        int                             q_num;  /* number of a queue */
        !           331:        int                             i_spot; /* # of empty entry in map */
        !           332: 
        !           333:        /* Validate queue identifier. */
        !           334:        for (qp = msqs; qp < msqs + NMSQID; qp++) 
        !           335:                if (qp->msg_perm.seq == qid)    /* found */
        !           336:                        break;
        !           337: 
        !           338:        q_num = qp - msqs;              
        !           339:        /* qid is not a valid qid identifier */
        !           340:        if (q_num >= NMSQID) {
        !           341:                u.u_error = EINVAL;
        !           342:                return -1;
        !           343:        }
        !           344: 
        !           345:        if (!(ipcaccess(&qp->msg_perm) & MSG_W)) { /* can't send mesg */
        !           346:                u.u_error = EACCES;
        !           347:                return -1;
        !           348:        }
        !           349: 
        !           350:        /* Check if message has a valid message type and size.
        !           351:         * The comparisson with NMSQB was done because user could
        !           352:         * reduce this value.
        !           353:         */
        !           354:        if (bufp->mtype < 1 || msgsz < 0 || msgsz > NMSC || msgsz > NMSQB) {
        !           355:                u.u_error = EACCES;
        !           356:                return -1;
        !           357:        }
        !           358:        
        !           359:        /* Now we have a valid message. Check if we can send it. */
        !           360:        lock(msg_gate[q_num]);  /* Lock it to avoid race condition */
        !           361:        while (qp->msg_qnum >= NMSG || 
        !           362:                        qp->msg_qbytes < (qp->msg_cbytes + msgsz)) {
        !           363:                if (msgflg & IPC_NOWAIT) {
        !           364:                        u.u_error = EAGAIN;
        !           365:                        unlock(msg_gate[q_num]);
        !           366:                        return -1;
        !           367:                }
        !           368:                /* We have to wait here */
        !           369:                qp->msg_perm.mode |= MSG_WWAIT;
        !           370:                unlock(msg_gate[q_num]);
        !           371: 
        !           372:                if (x_sleep (qp, pritty, slpriSigCatch, "umsgsnd")
        !           373:                    == PROCESS_SIGNALLED) {
        !           374:                        /* Abort if a signal was received */
        !           375:                        u.u_error = EINTR;
        !           376:                        return -1;
        !           377:                }
        !           378: 
        !           379:                /* Abort if the message queue was removed. */
        !           380:                if (qid != qp->msg_perm.seq) {
        !           381:                        u.u_error = EINVAL;
        !           382:                        return -1;
        !           383:                }
        !           384:                lock(msg_gate[q_num]);
        !           385:        }
        !           386: 
        !           387:        /* Find empty entry in message map */
        !           388:        for (i_spot = 0; i_spot < NMSQID * NMSG; i_spot++)
        !           389:                if (msg_map[i_spot] == NULL)
        !           390:                        break;
        !           391:        /* It cannot happen when we do not have empty entry in map,
        !           392:         * but let check it.
        !           393:         */
        !           394:        if (i_spot >= NMSQID * NMSG) {
        !           395:                u.u_error = ENOSPC;
        !           396:                return -1;
        !           397:        }
        !           398: 
        !           399:        T_MSGQ(0x01, printf("A%d", dballoc += sizeof(struct msg)));
        !           400: 
        !           401:        /* Get space for the message header */
        !           402:        if ((mp = kalloc(sizeof(struct msg))) == NULL) {
        !           403:                unlock(msg_gate[q_num]);
        !           404:                u.u_error = ENOSPC;
        !           405:                return -1;
        !           406:        }
        !           407: 
        !           408:        T_MSGQ(0x01, printf("A%d", dballoc += msgsz));
        !           409: 
        !           410:        /* Alloc space for the message text */
        !           411:        if ((msg_map[i_spot] = kalloc(msgsz)) == NULL) {
        !           412:                kfree(mp);
        !           413:                unlock(msg_gate[q_num]);
        !           414:                u.u_error = ENOSPC;
        !           415:                return -1;
        !           416:        }
        !           417: 
        !           418:        mp->msg_next = NULL;
        !           419:        mp->msg_ts = msgsz;
        !           420:        /* The map address is a number of msg_map array element */
        !           421:        mp->msg_spot = i_spot;
        !           422: 
        !           423:        /* Transfer the message type and text.*/
        !           424:        if (ukcopy(&(bufp->mtype), &(mp->msg_type), sizeof(mp->msg_type)) !=
        !           425:                                                sizeof(mp->msg_type))
        !           426:                u.u_error = EFAULT;
        !           427:        if (ukcopy(&bufp->mtext[0], msg_map[i_spot], msgsz) != msgsz)
        !           428:                u.u_error = EFAULT;
        !           429:        if (u.u_error) {
        !           430:                msgfree(mp);
        !           431:                unlock(msg_gate[q_num]);
        !           432:                return -1;
        !           433:        }
        !           434: 
        !           435:        /* Move the message to the desired queue. */
        !           436:        if (qp->msg_first == NULL) /* This is the first message per queue */
        !           437:                qp->msg_first = qp->msg_last = mp;
        !           438:        else {  /* There are messages */
        !           439:                /* Find last message in gueue */
        !           440:                for (tmp = qp->msg_first; ; tmp = tmp->msg_next)
        !           441:                        if (tmp->msg_next == NULL)
        !           442:                                break;
        !           443:                qp->msg_last = tmp->msg_next = mp;
        !           444:        }
        !           445:        mp->msg_next = NULL;
        !           446: 
        !           447:        /* Update queue statistics. */
        !           448:        qp->msg_cbytes += msgsz;
        !           449:        qp->msg_qnum++;
        !           450:        qp->msg_lspid = SELF->p_pid;
        !           451:        qp->msg_stime = timer.t_time;
        !           452: 
        !           453:        /* Unlock queue and wake processes waiting to receive. */
        !           454:        unlock(msg_gate[q_num]);
        !           455:        if (qp->msg_perm.mode & MSG_RWAIT) {
        !           456:                qp->msg_perm.mode &= ~MSG_RWAIT;
        !           457:                wakeup(qp);
        !           458:        }
        !           459:        return 0;
        !           460: }
        !           461: 
        !           462: /*
        !           463:  * Receive a Message
        !           464:  */
        !           465: umsgrcv(qid, bufp, msgsz, msgtyp, msgflg)
        !           466: int            qid;    /* Message queue id     */
        !           467: struct msgbuf  *bufp;  /* Message buffer       */
        !           468: int            msgsz;  /* Message text size    */
        !           469: long           msgtyp; /* Message type         */
        !           470: int            msgflg; /* Message flag         */
        !           471: {
        !           472:        register struct msqid_ds        *qp;    /* queue headers        */
        !           473:        register struct msg             *mp,    /* message headers      */
        !           474:                                        *prev;
        !           475:        int                             q_num;  /* queue number         */
        !           476:        int                             i_spot;
        !           477: 
        !           478:        /* Validate queue identifier. */
        !           479:        if (qid < 0 || msqs == NULL) {
        !           480:                u.u_error = EINVAL;
        !           481:                return -1;
        !           482:        }
        !           483:        q_num = qid % NMSQID;
        !           484:        qp = &msqs[q_num];
        !           485: 
        !           486:        /* Validate queue existence.*/
        !           487:        if (qp->msg_perm.seq != qid || (qp->msg_perm.mode & IPC_ALLOC) == 0) {
        !           488:                u.u_error = EINVAL;
        !           489:                return -1;
        !           490:        }
        !           491: 
        !           492:        /* Permission denied */
        !           493:        if ((ipcaccess(&qp->msg_perm) & MSG_R) == 0) {
        !           494:                u.u_error = EACCES;
        !           495:                return -1;
        !           496:        }
        !           497: 
        !           498:        /* Wait for message */
        !           499:        lock(msg_gate[q_num]);
        !           500:        for (;;) {
        !           501:                prev = NULL;
        !           502:                mp = qp->msg_first;
        !           503:                /* Find mesg of type <= abs(msgtyp) */
        !           504:                if (msgtyp < 0) {
        !           505:                        struct msg *qmin;       /* Message with lowest mtype */
        !           506:                        struct msg *xprev;      /* Previous message */
        !           507:                        
        !           508:                        qmin = NULL;
        !           509:                        xprev = prev;
        !           510:                        msgtyp = -msgtyp;
        !           511: 
        !           512:                        for (; mp != NULL; prev = mp, mp = mp->msg_next) {
        !           513:                                if (mp->msg_type > msgtyp)
        !           514:                                        continue;
        !           515:                                if (qmin == NULL 
        !           516:                                           || mp->msg_type < qmin->msg_type) {
        !           517:                                        xprev = prev;
        !           518:                                        qmin = mp;
        !           519:                                }
        !           520:                        }
        !           521:                        prev = xprev;
        !           522:                        mp  = qmin;
        !           523:                        msgtyp = -msgtyp;
        !           524:                } else if (msgtyp > 0) { /* Find message of type == msgtyp */
        !           525:                        while (mp != NULL && mp->msg_type != msgtyp) {
        !           526:                                prev = mp;
        !           527:                                mp = mp->msg_next;
        !           528:                        }
        !           529:                } else  /* Else take first message */
        !           530:                        mp = qp->msg_first;
        !           531: 
        !           532:                if (mp != NULL) /* Found */
        !           533:                        break;
        !           534:        
        !           535:                /* Can't wait to receive mesg */
        !           536:                if (msgflg & IPC_NOWAIT) {
        !           537:                        u.u_error = ENOMSG;
        !           538:                        unlock(msg_gate[q_num]);
        !           539:                        return -1;
        !           540:                }
        !           541: 
        !           542:                /* We can go sleep now */
        !           543:                qp->msg_perm.mode |= MSG_RWAIT;
        !           544:                unlock(msg_gate[q_num]);
        !           545:                if (x_sleep (qp, pritty, slpriSigCatch, "umsgrcv")
        !           546:                    == PROCESS_SIGNALLED) {
        !           547:                        u.u_error = EINTR;
        !           548:                        return -1;
        !           549:                }
        !           550: 
        !           551:                /* Not same q anymore */
        !           552:                if (qid != qp->msg_perm.seq) {
        !           553:                        u.u_error = EINVAL;
        !           554:                        return -1;
        !           555:                }
        !           556:                lock(msg_gate[q_num]);
        !           557:        }
        !           558: 
        !           559:        /* Ensure entire message can be transferred, or MSG_NOERROR asserted.*/
        !           560:        if (msgsz < mp->msg_ts && (msgflg & MSG_NOERROR) == 0) {
        !           561:                unlock(msg_gate[q_num]);
        !           562:                u.u_error = E2BIG;
        !           563:                return -1;
        !           564:        }
        !           565: 
        !           566:        /* Transfer message data */
        !           567:        if (msgsz > mp->msg_ts)
        !           568:                msgsz = mp->msg_ts;
        !           569: 
        !           570:        kucopy(&(mp->msg_type), &(bufp->mtype), sizeof(mp->msg_type));
        !           571: 
        !           572:        i_spot = mp->msg_spot;
        !           573:        if (kucopy(msg_map[i_spot], bufp->mtext, msgsz) != msgsz)
        !           574:                u.u_error = EFAULT;
        !           575: 
        !           576:        /* Abort if address fault occurred during transfer. */
        !           577:        if (u.u_error) {
        !           578:                unlock(msg_gate[q_num]);
        !           579:                return -1;
        !           580:        }
        !           581:        /* Remove message from queue */
        !           582:        if (prev != NULL)
        !           583:                prev->msg_next = mp->msg_next;
        !           584:        else
        !           585:                qp->msg_first = mp->msg_next;
        !           586: 
        !           587:        if (qp->msg_last == mp)
        !           588:                qp->msg_last = prev;
        !           589: 
        !           590: 
        !           591:        /* Update queue statistics */
        !           592:        qp->msg_cbytes -= mp->msg_ts;
        !           593:        qp->msg_qnum--;
        !           594:        qp->msg_lrpid = SELF->p_pid;
        !           595:        qp->msg_rtime = timer.t_time;
        !           596: 
        !           597:        /* free message */
        !           598:        msgfree(mp);
        !           599: 
        !           600:        unlock(msg_gate[q_num]);
        !           601:        /* Wakeup processes waiting to send. */
        !           602:        if (qp->msg_perm.mode & MSG_WWAIT) {
        !           603:                qp->msg_perm.mode &= ~MSG_WWAIT;
        !           604:                wakeup(qp);
        !           605:        }
        !           606:        return msgsz;
        !           607: }
        !           608: 

unix.superglobalmegacorp.com

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