]>
git.saurik.com Git - apple/xnu.git/blob - bsd/kern/sysv_msg.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Implementation of SVID messages
25 * Author: Daniel Boulet
27 * Copyright 1993 Daniel Boulet and RTMX Inc.
29 * This system call was implemented by Daniel Boulet under contract from RTMX.
31 * Redistribution and use in source forms, with and without modification,
32 * are permitted provided that this entire comment appears intact.
34 * Redistribution in binary form may occur without any restrictions.
35 * Obviously, it would be nice if you gave credit where credit is due
36 * but requiring it would be too onerous.
38 * This software is provided ``AS IS'' without any warranties of any kind.
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/sysproto.h>
44 #include <sys/kernel.h>
47 #include <sys/sysent.h>
49 static void msginit
__P((void *));
50 SYSINIT(sysv_msg
, SI_SUB_SYSV_MSG
, SI_ORDER_FIRST
, msginit
, NULL
)
55 #ifndef _SYS_SYSPROTO_H_
57 int msgctl
__P((struct proc
*p
, struct msgctl_args
*uap
));
59 int msgget
__P((struct proc
*p
, struct msgget_args
*uap
));
61 int msgsnd
__P((struct proc
*p
, struct msgsnd_args
*uap
));
63 int msgrcv
__P((struct proc
*p
, struct msgrcv_args
*uap
));
65 static void msg_freehdr
__P((struct msg
*msghdr
));
67 /* XXX casting to (sy_call_t *) is bogus, as usual. */
68 static sy_call_t
*msgcalls
[] = {
69 (sy_call_t
*)msgctl
, (sy_call_t
*)msgget
,
70 (sy_call_t
*)msgsnd
, (sy_call_t
*)msgrcv
73 static int nfree_msgmaps
; /* # of free map entries */
74 static short free_msgmaps
; /* head of linked list of free map entries */
75 static struct msg
*free_msghdrs
; /* list of free msg headers */
76 char *msgpool
; /* MSGMAX byte long msg buffer pool */
77 struct msgmap
*msgmaps
; /* MSGSEG msgmap structures */
78 struct msg
*msghdrs
; /* MSGTQL msg headers */
79 struct msqid_ds
*msqids
; /* MSGMNI msqid_ds struct's */
88 * msginfo.msgssz should be a power of two for efficiency reasons.
89 * It is also pretty silly if msginfo.msgssz is less than 8
90 * or greater than about 256 so ...
94 while (i
< 1024 && i
!= msginfo
.msgssz
)
96 if (i
!= msginfo
.msgssz
) {
97 printf("msginfo.msgssz=%d (0x%x)\n", msginfo
.msgssz
,
99 panic("msginfo.msgssz not a small power of 2");
102 if (msginfo
.msgseg
> 32767) {
103 printf("msginfo.msgseg=%d\n", msginfo
.msgseg
);
104 panic("msginfo.msgseg > 32767");
108 panic("msgmaps is NULL");
110 for (i
= 0; i
< msginfo
.msgseg
; i
++) {
112 msgmaps
[i
-1].next
= i
;
113 msgmaps
[i
].next
= -1; /* implies entry is available */
116 nfree_msgmaps
= msginfo
.msgseg
;
119 panic("msghdrs is NULL");
121 for (i
= 0; i
< msginfo
.msgtql
; i
++) {
122 msghdrs
[i
].msg_type
= 0;
124 msghdrs
[i
-1].msg_next
= &msghdrs
[i
];
125 msghdrs
[i
].msg_next
= NULL
;
127 free_msghdrs
= &msghdrs
[0];
130 panic("msqids is NULL");
132 for (i
= 0; i
< msginfo
.msgmni
; i
++) {
133 msqids
[i
].msg_qbytes
= 0; /* implies entry is available */
134 msqids
[i
].msg_perm
.seq
= 0; /* reset to a known value */
139 * Entry point for all MSG calls
144 /* XXX actually varargs. */
145 struct msgsys_args
/* {
155 if (uap
->which
>= sizeof(msgcalls
)/sizeof(msgcalls
[0]))
157 return ((*msgcalls
[uap
->which
])(p
, &uap
->a2
));
164 while (msghdr
->msg_ts
> 0) {
166 if (msghdr
->msg_spot
< 0 || msghdr
->msg_spot
>= msginfo
.msgseg
)
167 panic("msghdr->msg_spot out of range");
168 next
= msgmaps
[msghdr
->msg_spot
].next
;
169 msgmaps
[msghdr
->msg_spot
].next
= free_msgmaps
;
170 free_msgmaps
= msghdr
->msg_spot
;
172 msghdr
->msg_spot
= next
;
173 if (msghdr
->msg_ts
>= msginfo
.msgssz
)
174 msghdr
->msg_ts
-= msginfo
.msgssz
;
178 if (msghdr
->msg_spot
!= -1)
179 panic("msghdr->msg_spot != -1");
180 msghdr
->msg_next
= free_msghdrs
;
181 free_msghdrs
= msghdr
;
184 #ifndef _SYS_SYSPROTO_H_
188 struct msqid_ds
*buf
;
195 register struct msgctl_args
*uap
;
197 int msqid
= uap
->msqid
;
199 struct msqid_ds
*user_msqptr
= uap
->buf
;
200 struct ucred
*cred
= p
->p_ucred
;
202 struct msqid_ds msqbuf
;
203 register struct msqid_ds
*msqptr
;
206 printf("call to msgctl(%d, %d, 0x%x)\n", msqid
, cmd
, user_msqptr
);
209 msqid
= IPCID_TO_IX(msqid
);
211 if (msqid
< 0 || msqid
>= msginfo
.msgmni
) {
213 printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid
,
219 msqptr
= &msqids
[msqid
];
221 if (msqptr
->msg_qbytes
== 0) {
223 printf("no such msqid\n");
227 if (msqptr
->msg_perm
.seq
!= IPCID_TO_SEQ(uap
->msqid
)) {
229 printf("wrong sequence number\n");
242 if ((eval
= ipcperm(cred
, &msqptr
->msg_perm
, IPC_M
)))
244 /* Free the message headers */
245 msghdr
= msqptr
->msg_first
;
246 while (msghdr
!= NULL
) {
247 struct msg
*msghdr_tmp
;
249 /* Free the segments of each message */
250 msqptr
->msg_cbytes
-= msghdr
->msg_ts
;
253 msghdr
= msghdr
->msg_next
;
254 msg_freehdr(msghdr_tmp
);
257 if (msqptr
->msg_cbytes
!= 0)
258 panic("msg_cbytes is messed up");
259 if (msqptr
->msg_qnum
!= 0)
260 panic("msg_qnum is messed up");
262 msqptr
->msg_qbytes
= 0; /* Mark it as free */
264 wakeup((caddr_t
)msqptr
);
270 if ((eval
= ipcperm(cred
, &msqptr
->msg_perm
, IPC_M
)))
272 if ((eval
= copyin(user_msqptr
, &msqbuf
, sizeof(msqbuf
))) != 0)
274 if (msqbuf
.msg_qbytes
> msqptr
->msg_qbytes
) {
275 eval
= suser(cred
, &p
->p_acflag
);
279 if (msqbuf
.msg_qbytes
> msginfo
.msgmnb
) {
281 printf("can't increase msg_qbytes beyond %d (truncating)\n",
284 msqbuf
.msg_qbytes
= msginfo
.msgmnb
; /* silently restrict qbytes to system limit */
286 if (msqbuf
.msg_qbytes
== 0) {
288 printf("can't reduce msg_qbytes to 0\n");
290 return(EINVAL
); /* non-standard errno! */
292 msqptr
->msg_perm
.uid
= msqbuf
.msg_perm
.uid
; /* change the owner */
293 msqptr
->msg_perm
.gid
= msqbuf
.msg_perm
.gid
; /* change the owner */
294 msqptr
->msg_perm
.mode
= (msqptr
->msg_perm
.mode
& ~0777) |
295 (msqbuf
.msg_perm
.mode
& 0777);
296 msqptr
->msg_qbytes
= msqbuf
.msg_qbytes
;
297 msqptr
->msg_ctime
= time_second
;
301 if ((eval
= ipcperm(cred
, &msqptr
->msg_perm
, IPC_R
))) {
303 printf("requester doesn't have read access\n");
307 eval
= copyout((caddr_t
)msqptr
, user_msqptr
,
308 sizeof(struct msqid_ds
));
313 printf("invalid command %d\n", cmd
);
319 p
->p_retval
[0] = rval
;
323 #ifndef _SYS_SYSPROTO_H_
333 register struct msgget_args
*uap
;
337 int msgflg
= uap
->msgflg
;
338 struct ucred
*cred
= p
->p_ucred
;
339 register struct msqid_ds
*msqptr
= NULL
;
342 printf("msgget(0x%x, 0%o)\n", key
, msgflg
);
345 if (key
!= IPC_PRIVATE
) {
346 for (msqid
= 0; msqid
< msginfo
.msgmni
; msqid
++) {
347 msqptr
= &msqids
[msqid
];
348 if (msqptr
->msg_qbytes
!= 0 &&
349 msqptr
->msg_perm
.key
== key
)
352 if (msqid
< msginfo
.msgmni
) {
354 printf("found public key\n");
356 if ((msgflg
& IPC_CREAT
) && (msgflg
& IPC_EXCL
)) {
358 printf("not exclusive\n");
362 if ((eval
= ipcperm(cred
, &msqptr
->msg_perm
, msgflg
& 0700 ))) {
364 printf("requester doesn't have 0%o access\n",
374 printf("need to allocate the msqid_ds\n");
376 if (key
== IPC_PRIVATE
|| (msgflg
& IPC_CREAT
)) {
377 for (msqid
= 0; msqid
< msginfo
.msgmni
; msqid
++) {
379 * Look for an unallocated and unlocked msqid_ds.
380 * msqid_ds's can be locked by msgsnd or msgrcv while
381 * they are copying the message in/out. We can't
382 * re-use the entry until they release it.
384 msqptr
= &msqids
[msqid
];
385 if (msqptr
->msg_qbytes
== 0 &&
386 (msqptr
->msg_perm
.mode
& MSG_LOCKED
) == 0)
389 if (msqid
== msginfo
.msgmni
) {
391 printf("no more msqid_ds's available\n");
396 printf("msqid %d is available\n", msqid
);
398 msqptr
->msg_perm
.key
= key
;
399 msqptr
->msg_perm
.cuid
= cred
->cr_uid
;
400 msqptr
->msg_perm
.uid
= cred
->cr_uid
;
401 msqptr
->msg_perm
.cgid
= cred
->cr_gid
;
402 msqptr
->msg_perm
.gid
= cred
->cr_gid
;
403 msqptr
->msg_perm
.mode
= (msgflg
& 0777);
404 /* Make sure that the returned msqid is unique */
405 msqptr
->msg_perm
.seq
++;
406 msqptr
->msg_first
= NULL
;
407 msqptr
->msg_last
= NULL
;
408 msqptr
->msg_cbytes
= 0;
409 msqptr
->msg_qnum
= 0;
410 msqptr
->msg_qbytes
= msginfo
.msgmnb
;
411 msqptr
->msg_lspid
= 0;
412 msqptr
->msg_lrpid
= 0;
413 msqptr
->msg_stime
= 0;
414 msqptr
->msg_rtime
= 0;
415 msqptr
->msg_ctime
= time_second
;
418 printf("didn't find it and wasn't asked to create it\n");
424 /* Construct the unique msqid */
425 p
->p_retval
[0] = IXSEQ_TO_IPCID(msqid
, msqptr
->msg_perm
);
429 #ifndef _SYS_SYSPROTO_H_
441 register struct msgsnd_args
*uap
;
443 int msqid
= uap
->msqid
;
444 void *user_msgp
= uap
->msgp
;
445 size_t msgsz
= uap
->msgsz
;
446 int msgflg
= uap
->msgflg
;
447 int segs_needed
, eval
;
448 struct ucred
*cred
= p
->p_ucred
;
449 register struct msqid_ds
*msqptr
;
450 register struct msg
*msghdr
;
454 printf("call to msgsnd(%d, 0x%x, %d, %d)\n", msqid
, user_msgp
, msgsz
,
458 msqid
= IPCID_TO_IX(msqid
);
460 if (msqid
< 0 || msqid
>= msginfo
.msgmni
) {
462 printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid
,
468 msqptr
= &msqids
[msqid
];
469 if (msqptr
->msg_qbytes
== 0) {
471 printf("no such message queue id\n");
475 if (msqptr
->msg_perm
.seq
!= IPCID_TO_SEQ(uap
->msqid
)) {
477 printf("wrong sequence number\n");
482 if ((eval
= ipcperm(cred
, &msqptr
->msg_perm
, IPC_W
))) {
484 printf("requester doesn't have write access\n");
489 segs_needed
= (msgsz
+ msginfo
.msgssz
- 1) / msginfo
.msgssz
;
491 printf("msgsz=%d, msgssz=%d, segs_needed=%d\n", msgsz
, msginfo
.msgssz
,
495 int need_more_resources
= 0;
499 * (inside this loop in case msg_qbytes changes while we sleep)
502 if (msgsz
> msqptr
->msg_qbytes
) {
504 printf("msgsz > msqptr->msg_qbytes\n");
509 if (msqptr
->msg_perm
.mode
& MSG_LOCKED
) {
511 printf("msqid is locked\n");
513 need_more_resources
= 1;
515 if (msgsz
+ msqptr
->msg_cbytes
> msqptr
->msg_qbytes
) {
517 printf("msgsz + msg_cbytes > msg_qbytes\n");
519 need_more_resources
= 1;
521 if (segs_needed
> nfree_msgmaps
) {
523 printf("segs_needed > nfree_msgmaps\n");
525 need_more_resources
= 1;
527 if (free_msghdrs
== NULL
) {
529 printf("no more msghdrs\n");
531 need_more_resources
= 1;
534 if (need_more_resources
) {
537 if ((msgflg
& IPC_NOWAIT
) != 0) {
539 printf("need more resources but caller doesn't want to wait\n");
544 if ((msqptr
->msg_perm
.mode
& MSG_LOCKED
) != 0) {
546 printf("we don't own the msqid_ds\n");
550 /* Force later arrivals to wait for our
553 printf("we own the msqid_ds\n");
555 msqptr
->msg_perm
.mode
|= MSG_LOCKED
;
559 printf("goodnight\n");
561 eval
= tsleep((caddr_t
)msqptr
, (PZERO
- 4) | PCATCH
,
564 printf("good morning, eval=%d\n", eval
);
567 msqptr
->msg_perm
.mode
&= ~MSG_LOCKED
;
570 printf("msgsnd: interrupted system call\n");
576 * Make sure that the msq queue still exists
579 if (msqptr
->msg_qbytes
== 0) {
581 printf("msqid deleted\n");
583 /* The SVID says to return EIDRM. */
587 /* Unfortunately, BSD doesn't define that code
595 printf("got all the resources that we need\n");
602 * We have the resources that we need.
606 if (msqptr
->msg_perm
.mode
& MSG_LOCKED
)
607 panic("msg_perm.mode & MSG_LOCKED");
608 if (segs_needed
> nfree_msgmaps
)
609 panic("segs_needed > nfree_msgmaps");
610 if (msgsz
+ msqptr
->msg_cbytes
> msqptr
->msg_qbytes
)
611 panic("msgsz + msg_cbytes > msg_qbytes");
612 if (free_msghdrs
== NULL
)
613 panic("no more msghdrs");
616 * Re-lock the msqid_ds in case we page-fault when copying in the
620 if ((msqptr
->msg_perm
.mode
& MSG_LOCKED
) != 0)
621 panic("msqid_ds is already locked");
622 msqptr
->msg_perm
.mode
|= MSG_LOCKED
;
625 * Allocate a message header
628 msghdr
= free_msghdrs
;
629 free_msghdrs
= msghdr
->msg_next
;
630 msghdr
->msg_spot
= -1;
631 msghdr
->msg_ts
= msgsz
;
634 * Allocate space for the message
637 while (segs_needed
> 0) {
638 if (nfree_msgmaps
<= 0)
639 panic("not enough msgmaps");
640 if (free_msgmaps
== -1)
641 panic("nil free_msgmaps");
644 panic("next too low #1");
645 if (next
>= msginfo
.msgseg
)
646 panic("next out of range #1");
648 printf("allocating segment %d to message\n", next
);
650 free_msgmaps
= msgmaps
[next
].next
;
652 msgmaps
[next
].next
= msghdr
->msg_spot
;
653 msghdr
->msg_spot
= next
;
658 * Copy in the message type
661 if ((eval
= copyin(user_msgp
, &msghdr
->msg_type
,
662 sizeof(msghdr
->msg_type
))) != 0) {
664 printf("error %d copying the message type\n", eval
);
667 msqptr
->msg_perm
.mode
&= ~MSG_LOCKED
;
668 wakeup((caddr_t
)msqptr
);
671 user_msgp
= (char *)user_msgp
+ sizeof(msghdr
->msg_type
);
674 * Validate the message type
677 if (msghdr
->msg_type
< 1) {
679 msqptr
->msg_perm
.mode
&= ~MSG_LOCKED
;
680 wakeup((caddr_t
)msqptr
);
682 printf("mtype (%d) < 1\n", msghdr
->msg_type
);
688 * Copy in the message body
691 next
= msghdr
->msg_spot
;
694 if (msgsz
> msginfo
.msgssz
)
695 tlen
= msginfo
.msgssz
;
699 panic("next too low #2");
700 if (next
>= msginfo
.msgseg
)
701 panic("next out of range #2");
702 if ((eval
= copyin(user_msgp
, &msgpool
[next
* msginfo
.msgssz
],
705 printf("error %d copying in message segment\n", eval
);
708 msqptr
->msg_perm
.mode
&= ~MSG_LOCKED
;
709 wakeup((caddr_t
)msqptr
);
713 user_msgp
= (char *)user_msgp
+ tlen
;
714 next
= msgmaps
[next
].next
;
717 panic("didn't use all the msg segments");
720 * We've got the message. Unlock the msqid_ds.
723 msqptr
->msg_perm
.mode
&= ~MSG_LOCKED
;
726 * Make sure that the msqid_ds is still allocated.
729 if (msqptr
->msg_qbytes
== 0) {
731 wakeup((caddr_t
)msqptr
);
732 /* The SVID says to return EIDRM. */
736 /* Unfortunately, BSD doesn't define that code yet! */
742 * Put the message into the queue
745 if (msqptr
->msg_first
== NULL
) {
746 msqptr
->msg_first
= msghdr
;
747 msqptr
->msg_last
= msghdr
;
749 msqptr
->msg_last
->msg_next
= msghdr
;
750 msqptr
->msg_last
= msghdr
;
752 msqptr
->msg_last
->msg_next
= NULL
;
754 msqptr
->msg_cbytes
+= msghdr
->msg_ts
;
756 msqptr
->msg_lspid
= p
->p_pid
;
757 msqptr
->msg_stime
= time_second
;
759 wakeup((caddr_t
)msqptr
);
764 #ifndef _SYS_SYSPROTO_H_
777 register struct msgrcv_args
*uap
;
779 int msqid
= uap
->msqid
;
780 void *user_msgp
= uap
->msgp
;
781 size_t msgsz
= uap
->msgsz
;
782 long msgtyp
= uap
->msgtyp
;
783 int msgflg
= uap
->msgflg
;
785 struct ucred
*cred
= p
->p_ucred
;
786 register struct msqid_ds
*msqptr
;
787 register struct msg
*msghdr
;
792 printf("call to msgrcv(%d, 0x%x, %d, %ld, %d)\n", msqid
, user_msgp
,
793 msgsz
, msgtyp
, msgflg
);
796 msqid
= IPCID_TO_IX(msqid
);
798 if (msqid
< 0 || msqid
>= msginfo
.msgmni
) {
800 printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid
,
806 msqptr
= &msqids
[msqid
];
807 if (msqptr
->msg_qbytes
== 0) {
809 printf("no such message queue id\n");
813 if (msqptr
->msg_perm
.seq
!= IPCID_TO_SEQ(uap
->msqid
)) {
815 printf("wrong sequence number\n");
820 if ((eval
= ipcperm(cred
, &msqptr
->msg_perm
, IPC_R
))) {
822 printf("requester doesn't have read access\n");
828 while (msghdr
== NULL
) {
830 msghdr
= msqptr
->msg_first
;
831 if (msghdr
!= NULL
) {
832 if (msgsz
< msghdr
->msg_ts
&&
833 (msgflg
& MSG_NOERROR
) == 0) {
835 printf("first message on the queue is too big (want %d, got %d)\n",
836 msgsz
, msghdr
->msg_ts
);
840 if (msqptr
->msg_first
== msqptr
->msg_last
) {
841 msqptr
->msg_first
= NULL
;
842 msqptr
->msg_last
= NULL
;
844 msqptr
->msg_first
= msghdr
->msg_next
;
845 if (msqptr
->msg_first
== NULL
)
846 panic("msg_first/last messed up #1");
850 struct msg
*previous
;
854 prev
= &(msqptr
->msg_first
);
855 while ((msghdr
= *prev
) != NULL
) {
857 * Is this message's type an exact match or is
858 * this message's type less than or equal to
859 * the absolute value of a negative msgtyp?
860 * Note that the second half of this test can
861 * NEVER be true if msgtyp is positive since
862 * msg_type is always positive!
865 if (msgtyp
== msghdr
->msg_type
||
866 msghdr
->msg_type
<= -msgtyp
) {
868 printf("found message type %d, requested %d\n",
869 msghdr
->msg_type
, msgtyp
);
871 if (msgsz
< msghdr
->msg_ts
&&
872 (msgflg
& MSG_NOERROR
) == 0) {
874 printf("requested message on the queue is too big (want %d, got %d)\n",
875 msgsz
, msghdr
->msg_ts
);
879 *prev
= msghdr
->msg_next
;
880 if (msghdr
== msqptr
->msg_last
) {
881 if (previous
== NULL
) {
884 panic("msg_first/last messed up #2");
892 panic("msg_first/last messed up #3");
900 prev
= &(msghdr
->msg_next
);
905 * We've either extracted the msghdr for the appropriate
906 * message or there isn't one.
907 * If there is one then bail out of this loop.
914 * Hmph! No message found. Does the user want to wait?
917 if ((msgflg
& IPC_NOWAIT
) != 0) {
919 printf("no appropriate message found (msgtyp=%d)\n",
922 /* The SVID says to return ENOMSG. */
926 /* Unfortunately, BSD doesn't define that code yet! */
932 * Wait for something to happen
936 printf("msgrcv: goodnight\n");
938 eval
= tsleep((caddr_t
)msqptr
, (PZERO
- 4) | PCATCH
, "msgwait",
941 printf("msgrcv: good morning (eval=%d)\n", eval
);
946 printf("msgsnd: interrupted system call\n");
952 * Make sure that the msq queue still exists
955 if (msqptr
->msg_qbytes
== 0 ||
956 msqptr
->msg_perm
.seq
!= IPCID_TO_SEQ(uap
->msqid
)) {
958 printf("msqid deleted\n");
960 /* The SVID says to return EIDRM. */
964 /* Unfortunately, BSD doesn't define that code yet! */
971 * Return the message to the user.
973 * First, do the bookkeeping (before we risk being interrupted).
976 msqptr
->msg_cbytes
-= msghdr
->msg_ts
;
978 msqptr
->msg_lrpid
= p
->p_pid
;
979 msqptr
->msg_rtime
= time_second
;
982 * Make msgsz the actual amount that we'll be returning.
983 * Note that this effectively truncates the message if it is too long
984 * (since msgsz is never increased).
988 printf("found a message, msgsz=%d, msg_ts=%d\n", msgsz
,
991 if (msgsz
> msghdr
->msg_ts
)
992 msgsz
= msghdr
->msg_ts
;
995 * Return the type to the user.
998 eval
= copyout((caddr_t
)&(msghdr
->msg_type
), user_msgp
,
999 sizeof(msghdr
->msg_type
));
1002 printf("error (%d) copying out message type\n", eval
);
1004 msg_freehdr(msghdr
);
1005 wakeup((caddr_t
)msqptr
);
1008 user_msgp
= (char *)user_msgp
+ sizeof(msghdr
->msg_type
);
1011 * Return the segments to the user
1014 next
= msghdr
->msg_spot
;
1015 for (len
= 0; len
< msgsz
; len
+= msginfo
.msgssz
) {
1018 if (msgsz
> msginfo
.msgssz
)
1019 tlen
= msginfo
.msgssz
;
1023 panic("next too low #3");
1024 if (next
>= msginfo
.msgseg
)
1025 panic("next out of range #3");
1026 eval
= copyout((caddr_t
)&msgpool
[next
* msginfo
.msgssz
],
1030 printf("error (%d) copying out message segment\n",
1033 msg_freehdr(msghdr
);
1034 wakeup((caddr_t
)msqptr
);
1037 user_msgp
= (char *)user_msgp
+ tlen
;
1038 next
= msgmaps
[next
].next
;
1042 * Done, return the actual number of bytes copied out.
1045 msg_freehdr(msghdr
);
1046 wakeup((caddr_t
)msqptr
);
1047 p
->p_retval
[0] = msgsz
;