]>
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 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Implementation of SVID messages
28 * Author: Daniel Boulet
30 * Copyright 1993 Daniel Boulet and RTMX Inc.
32 * This system call was implemented by Daniel Boulet under contract from RTMX.
34 * Redistribution and use in source forms, with and without modification,
35 * are permitted provided that this entire comment appears intact.
37 * Redistribution in binary form may occur without any restrictions.
38 * Obviously, it would be nice if you gave credit where credit is due
39 * but requiring it would be too onerous.
41 * This software is provided ``AS IS'' without any warranties of any kind.
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/sysproto.h>
47 #include <sys/kernel.h>
50 #include <sys/sysent.h>
52 static void msginit
__P((void *));
53 SYSINIT(sysv_msg
, SI_SUB_SYSV_MSG
, SI_ORDER_FIRST
, msginit
, NULL
)
58 #ifndef _SYS_SYSPROTO_H_
60 int msgctl
__P((struct proc
*p
, struct msgctl_args
*uap
));
62 int msgget
__P((struct proc
*p
, struct msgget_args
*uap
));
64 int msgsnd
__P((struct proc
*p
, struct msgsnd_args
*uap
));
66 int msgrcv
__P((struct proc
*p
, struct msgrcv_args
*uap
));
68 static void msg_freehdr
__P((struct msg
*msghdr
));
70 /* XXX casting to (sy_call_t *) is bogus, as usual. */
71 static sy_call_t
*msgcalls
[] = {
72 (sy_call_t
*)msgctl
, (sy_call_t
*)msgget
,
73 (sy_call_t
*)msgsnd
, (sy_call_t
*)msgrcv
76 static int nfree_msgmaps
; /* # of free map entries */
77 static short free_msgmaps
; /* head of linked list of free map entries */
78 static struct msg
*free_msghdrs
; /* list of free msg headers */
79 char *msgpool
; /* MSGMAX byte long msg buffer pool */
80 struct msgmap
*msgmaps
; /* MSGSEG msgmap structures */
81 struct msg
*msghdrs
; /* MSGTQL msg headers */
82 struct msqid_ds
*msqids
; /* MSGMNI msqid_ds struct's */
91 * msginfo.msgssz should be a power of two for efficiency reasons.
92 * It is also pretty silly if msginfo.msgssz is less than 8
93 * or greater than about 256 so ...
97 while (i
< 1024 && i
!= msginfo
.msgssz
)
99 if (i
!= msginfo
.msgssz
) {
100 printf("msginfo.msgssz=%d (0x%x)\n", msginfo
.msgssz
,
102 panic("msginfo.msgssz not a small power of 2");
105 if (msginfo
.msgseg
> 32767) {
106 printf("msginfo.msgseg=%d\n", msginfo
.msgseg
);
107 panic("msginfo.msgseg > 32767");
111 panic("msgmaps is NULL");
113 for (i
= 0; i
< msginfo
.msgseg
; i
++) {
115 msgmaps
[i
-1].next
= i
;
116 msgmaps
[i
].next
= -1; /* implies entry is available */
119 nfree_msgmaps
= msginfo
.msgseg
;
122 panic("msghdrs is NULL");
124 for (i
= 0; i
< msginfo
.msgtql
; i
++) {
125 msghdrs
[i
].msg_type
= 0;
127 msghdrs
[i
-1].msg_next
= &msghdrs
[i
];
128 msghdrs
[i
].msg_next
= NULL
;
130 free_msghdrs
= &msghdrs
[0];
133 panic("msqids is NULL");
135 for (i
= 0; i
< msginfo
.msgmni
; i
++) {
136 msqids
[i
].msg_qbytes
= 0; /* implies entry is available */
137 msqids
[i
].msg_perm
.seq
= 0; /* reset to a known value */
142 * Entry point for all MSG calls
147 /* XXX actually varargs. */
148 struct msgsys_args
/* {
158 if (uap
->which
>= sizeof(msgcalls
)/sizeof(msgcalls
[0]))
160 return ((*msgcalls
[uap
->which
])(p
, &uap
->a2
));
167 while (msghdr
->msg_ts
> 0) {
169 if (msghdr
->msg_spot
< 0 || msghdr
->msg_spot
>= msginfo
.msgseg
)
170 panic("msghdr->msg_spot out of range");
171 next
= msgmaps
[msghdr
->msg_spot
].next
;
172 msgmaps
[msghdr
->msg_spot
].next
= free_msgmaps
;
173 free_msgmaps
= msghdr
->msg_spot
;
175 msghdr
->msg_spot
= next
;
176 if (msghdr
->msg_ts
>= msginfo
.msgssz
)
177 msghdr
->msg_ts
-= msginfo
.msgssz
;
181 if (msghdr
->msg_spot
!= -1)
182 panic("msghdr->msg_spot != -1");
183 msghdr
->msg_next
= free_msghdrs
;
184 free_msghdrs
= msghdr
;
187 #ifndef _SYS_SYSPROTO_H_
191 struct msqid_ds
*buf
;
198 register struct msgctl_args
*uap
;
200 int msqid
= uap
->msqid
;
202 struct msqid_ds
*user_msqptr
= uap
->buf
;
203 struct ucred
*cred
= p
->p_ucred
;
205 struct msqid_ds msqbuf
;
206 register struct msqid_ds
*msqptr
;
209 printf("call to msgctl(%d, %d, 0x%x)\n", msqid
, cmd
, user_msqptr
);
212 msqid
= IPCID_TO_IX(msqid
);
214 if (msqid
< 0 || msqid
>= msginfo
.msgmni
) {
216 printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid
,
222 msqptr
= &msqids
[msqid
];
224 if (msqptr
->msg_qbytes
== 0) {
226 printf("no such msqid\n");
230 if (msqptr
->msg_perm
.seq
!= IPCID_TO_SEQ(uap
->msqid
)) {
232 printf("wrong sequence number\n");
245 if ((eval
= ipcperm(cred
, &msqptr
->msg_perm
, IPC_M
)))
247 /* Free the message headers */
248 msghdr
= msqptr
->msg_first
;
249 while (msghdr
!= NULL
) {
250 struct msg
*msghdr_tmp
;
252 /* Free the segments of each message */
253 msqptr
->msg_cbytes
-= msghdr
->msg_ts
;
256 msghdr
= msghdr
->msg_next
;
257 msg_freehdr(msghdr_tmp
);
260 if (msqptr
->msg_cbytes
!= 0)
261 panic("msg_cbytes is messed up");
262 if (msqptr
->msg_qnum
!= 0)
263 panic("msg_qnum is messed up");
265 msqptr
->msg_qbytes
= 0; /* Mark it as free */
267 wakeup((caddr_t
)msqptr
);
273 if ((eval
= ipcperm(cred
, &msqptr
->msg_perm
, IPC_M
)))
275 if ((eval
= copyin(user_msqptr
, &msqbuf
, sizeof(msqbuf
))) != 0)
277 if (msqbuf
.msg_qbytes
> msqptr
->msg_qbytes
) {
278 eval
= suser(cred
, &p
->p_acflag
);
282 if (msqbuf
.msg_qbytes
> msginfo
.msgmnb
) {
284 printf("can't increase msg_qbytes beyond %d (truncating)\n",
287 msqbuf
.msg_qbytes
= msginfo
.msgmnb
; /* silently restrict qbytes to system limit */
289 if (msqbuf
.msg_qbytes
== 0) {
291 printf("can't reduce msg_qbytes to 0\n");
293 return(EINVAL
); /* non-standard errno! */
295 msqptr
->msg_perm
.uid
= msqbuf
.msg_perm
.uid
; /* change the owner */
296 msqptr
->msg_perm
.gid
= msqbuf
.msg_perm
.gid
; /* change the owner */
297 msqptr
->msg_perm
.mode
= (msqptr
->msg_perm
.mode
& ~0777) |
298 (msqbuf
.msg_perm
.mode
& 0777);
299 msqptr
->msg_qbytes
= msqbuf
.msg_qbytes
;
300 msqptr
->msg_ctime
= time_second
;
304 if ((eval
= ipcperm(cred
, &msqptr
->msg_perm
, IPC_R
))) {
306 printf("requester doesn't have read access\n");
310 eval
= copyout((caddr_t
)msqptr
, user_msqptr
,
311 sizeof(struct msqid_ds
));
316 printf("invalid command %d\n", cmd
);
322 p
->p_retval
[0] = rval
;
326 #ifndef _SYS_SYSPROTO_H_
336 register struct msgget_args
*uap
;
340 int msgflg
= uap
->msgflg
;
341 struct ucred
*cred
= p
->p_ucred
;
342 register struct msqid_ds
*msqptr
= NULL
;
345 printf("msgget(0x%x, 0%o)\n", key
, msgflg
);
348 if (key
!= IPC_PRIVATE
) {
349 for (msqid
= 0; msqid
< msginfo
.msgmni
; msqid
++) {
350 msqptr
= &msqids
[msqid
];
351 if (msqptr
->msg_qbytes
!= 0 &&
352 msqptr
->msg_perm
.key
== key
)
355 if (msqid
< msginfo
.msgmni
) {
357 printf("found public key\n");
359 if ((msgflg
& IPC_CREAT
) && (msgflg
& IPC_EXCL
)) {
361 printf("not exclusive\n");
365 if ((eval
= ipcperm(cred
, &msqptr
->msg_perm
, msgflg
& 0700 ))) {
367 printf("requester doesn't have 0%o access\n",
377 printf("need to allocate the msqid_ds\n");
379 if (key
== IPC_PRIVATE
|| (msgflg
& IPC_CREAT
)) {
380 for (msqid
= 0; msqid
< msginfo
.msgmni
; msqid
++) {
382 * Look for an unallocated and unlocked msqid_ds.
383 * msqid_ds's can be locked by msgsnd or msgrcv while
384 * they are copying the message in/out. We can't
385 * re-use the entry until they release it.
387 msqptr
= &msqids
[msqid
];
388 if (msqptr
->msg_qbytes
== 0 &&
389 (msqptr
->msg_perm
.mode
& MSG_LOCKED
) == 0)
392 if (msqid
== msginfo
.msgmni
) {
394 printf("no more msqid_ds's available\n");
399 printf("msqid %d is available\n", msqid
);
401 msqptr
->msg_perm
.key
= key
;
402 msqptr
->msg_perm
.cuid
= cred
->cr_uid
;
403 msqptr
->msg_perm
.uid
= cred
->cr_uid
;
404 msqptr
->msg_perm
.cgid
= cred
->cr_gid
;
405 msqptr
->msg_perm
.gid
= cred
->cr_gid
;
406 msqptr
->msg_perm
.mode
= (msgflg
& 0777);
407 /* Make sure that the returned msqid is unique */
408 msqptr
->msg_perm
.seq
++;
409 msqptr
->msg_first
= NULL
;
410 msqptr
->msg_last
= NULL
;
411 msqptr
->msg_cbytes
= 0;
412 msqptr
->msg_qnum
= 0;
413 msqptr
->msg_qbytes
= msginfo
.msgmnb
;
414 msqptr
->msg_lspid
= 0;
415 msqptr
->msg_lrpid
= 0;
416 msqptr
->msg_stime
= 0;
417 msqptr
->msg_rtime
= 0;
418 msqptr
->msg_ctime
= time_second
;
421 printf("didn't find it and wasn't asked to create it\n");
427 /* Construct the unique msqid */
428 p
->p_retval
[0] = IXSEQ_TO_IPCID(msqid
, msqptr
->msg_perm
);
432 #ifndef _SYS_SYSPROTO_H_
444 register struct msgsnd_args
*uap
;
446 int msqid
= uap
->msqid
;
447 void *user_msgp
= uap
->msgp
;
448 size_t msgsz
= uap
->msgsz
;
449 int msgflg
= uap
->msgflg
;
450 int segs_needed
, eval
;
451 struct ucred
*cred
= p
->p_ucred
;
452 register struct msqid_ds
*msqptr
;
453 register struct msg
*msghdr
;
457 printf("call to msgsnd(%d, 0x%x, %d, %d)\n", msqid
, user_msgp
, msgsz
,
461 msqid
= IPCID_TO_IX(msqid
);
463 if (msqid
< 0 || msqid
>= msginfo
.msgmni
) {
465 printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid
,
471 msqptr
= &msqids
[msqid
];
472 if (msqptr
->msg_qbytes
== 0) {
474 printf("no such message queue id\n");
478 if (msqptr
->msg_perm
.seq
!= IPCID_TO_SEQ(uap
->msqid
)) {
480 printf("wrong sequence number\n");
485 if ((eval
= ipcperm(cred
, &msqptr
->msg_perm
, IPC_W
))) {
487 printf("requester doesn't have write access\n");
492 segs_needed
= (msgsz
+ msginfo
.msgssz
- 1) / msginfo
.msgssz
;
494 printf("msgsz=%d, msgssz=%d, segs_needed=%d\n", msgsz
, msginfo
.msgssz
,
498 int need_more_resources
= 0;
502 * (inside this loop in case msg_qbytes changes while we sleep)
505 if (msgsz
> msqptr
->msg_qbytes
) {
507 printf("msgsz > msqptr->msg_qbytes\n");
512 if (msqptr
->msg_perm
.mode
& MSG_LOCKED
) {
514 printf("msqid is locked\n");
516 need_more_resources
= 1;
518 if (msgsz
+ msqptr
->msg_cbytes
> msqptr
->msg_qbytes
) {
520 printf("msgsz + msg_cbytes > msg_qbytes\n");
522 need_more_resources
= 1;
524 if (segs_needed
> nfree_msgmaps
) {
526 printf("segs_needed > nfree_msgmaps\n");
528 need_more_resources
= 1;
530 if (free_msghdrs
== NULL
) {
532 printf("no more msghdrs\n");
534 need_more_resources
= 1;
537 if (need_more_resources
) {
540 if ((msgflg
& IPC_NOWAIT
) != 0) {
542 printf("need more resources but caller doesn't want to wait\n");
547 if ((msqptr
->msg_perm
.mode
& MSG_LOCKED
) != 0) {
549 printf("we don't own the msqid_ds\n");
553 /* Force later arrivals to wait for our
556 printf("we own the msqid_ds\n");
558 msqptr
->msg_perm
.mode
|= MSG_LOCKED
;
562 printf("goodnight\n");
564 eval
= tsleep((caddr_t
)msqptr
, (PZERO
- 4) | PCATCH
,
567 printf("good morning, eval=%d\n", eval
);
570 msqptr
->msg_perm
.mode
&= ~MSG_LOCKED
;
573 printf("msgsnd: interrupted system call\n");
579 * Make sure that the msq queue still exists
582 if (msqptr
->msg_qbytes
== 0) {
584 printf("msqid deleted\n");
586 /* The SVID says to return EIDRM. */
590 /* Unfortunately, BSD doesn't define that code
598 printf("got all the resources that we need\n");
605 * We have the resources that we need.
609 if (msqptr
->msg_perm
.mode
& MSG_LOCKED
)
610 panic("msg_perm.mode & MSG_LOCKED");
611 if (segs_needed
> nfree_msgmaps
)
612 panic("segs_needed > nfree_msgmaps");
613 if (msgsz
+ msqptr
->msg_cbytes
> msqptr
->msg_qbytes
)
614 panic("msgsz + msg_cbytes > msg_qbytes");
615 if (free_msghdrs
== NULL
)
616 panic("no more msghdrs");
619 * Re-lock the msqid_ds in case we page-fault when copying in the
623 if ((msqptr
->msg_perm
.mode
& MSG_LOCKED
) != 0)
624 panic("msqid_ds is already locked");
625 msqptr
->msg_perm
.mode
|= MSG_LOCKED
;
628 * Allocate a message header
631 msghdr
= free_msghdrs
;
632 free_msghdrs
= msghdr
->msg_next
;
633 msghdr
->msg_spot
= -1;
634 msghdr
->msg_ts
= msgsz
;
637 * Allocate space for the message
640 while (segs_needed
> 0) {
641 if (nfree_msgmaps
<= 0)
642 panic("not enough msgmaps");
643 if (free_msgmaps
== -1)
644 panic("nil free_msgmaps");
647 panic("next too low #1");
648 if (next
>= msginfo
.msgseg
)
649 panic("next out of range #1");
651 printf("allocating segment %d to message\n", next
);
653 free_msgmaps
= msgmaps
[next
].next
;
655 msgmaps
[next
].next
= msghdr
->msg_spot
;
656 msghdr
->msg_spot
= next
;
661 * Copy in the message type
664 if ((eval
= copyin(user_msgp
, &msghdr
->msg_type
,
665 sizeof(msghdr
->msg_type
))) != 0) {
667 printf("error %d copying the message type\n", eval
);
670 msqptr
->msg_perm
.mode
&= ~MSG_LOCKED
;
671 wakeup((caddr_t
)msqptr
);
674 user_msgp
= (char *)user_msgp
+ sizeof(msghdr
->msg_type
);
677 * Validate the message type
680 if (msghdr
->msg_type
< 1) {
682 msqptr
->msg_perm
.mode
&= ~MSG_LOCKED
;
683 wakeup((caddr_t
)msqptr
);
685 printf("mtype (%d) < 1\n", msghdr
->msg_type
);
691 * Copy in the message body
694 next
= msghdr
->msg_spot
;
697 if (msgsz
> msginfo
.msgssz
)
698 tlen
= msginfo
.msgssz
;
702 panic("next too low #2");
703 if (next
>= msginfo
.msgseg
)
704 panic("next out of range #2");
705 if ((eval
= copyin(user_msgp
, &msgpool
[next
* msginfo
.msgssz
],
708 printf("error %d copying in message segment\n", eval
);
711 msqptr
->msg_perm
.mode
&= ~MSG_LOCKED
;
712 wakeup((caddr_t
)msqptr
);
716 user_msgp
= (char *)user_msgp
+ tlen
;
717 next
= msgmaps
[next
].next
;
720 panic("didn't use all the msg segments");
723 * We've got the message. Unlock the msqid_ds.
726 msqptr
->msg_perm
.mode
&= ~MSG_LOCKED
;
729 * Make sure that the msqid_ds is still allocated.
732 if (msqptr
->msg_qbytes
== 0) {
734 wakeup((caddr_t
)msqptr
);
735 /* The SVID says to return EIDRM. */
739 /* Unfortunately, BSD doesn't define that code yet! */
745 * Put the message into the queue
748 if (msqptr
->msg_first
== NULL
) {
749 msqptr
->msg_first
= msghdr
;
750 msqptr
->msg_last
= msghdr
;
752 msqptr
->msg_last
->msg_next
= msghdr
;
753 msqptr
->msg_last
= msghdr
;
755 msqptr
->msg_last
->msg_next
= NULL
;
757 msqptr
->msg_cbytes
+= msghdr
->msg_ts
;
759 msqptr
->msg_lspid
= p
->p_pid
;
760 msqptr
->msg_stime
= time_second
;
762 wakeup((caddr_t
)msqptr
);
767 #ifndef _SYS_SYSPROTO_H_
780 register struct msgrcv_args
*uap
;
782 int msqid
= uap
->msqid
;
783 void *user_msgp
= uap
->msgp
;
784 size_t msgsz
= uap
->msgsz
;
785 long msgtyp
= uap
->msgtyp
;
786 int msgflg
= uap
->msgflg
;
788 struct ucred
*cred
= p
->p_ucred
;
789 register struct msqid_ds
*msqptr
;
790 register struct msg
*msghdr
;
795 printf("call to msgrcv(%d, 0x%x, %d, %ld, %d)\n", msqid
, user_msgp
,
796 msgsz
, msgtyp
, msgflg
);
799 msqid
= IPCID_TO_IX(msqid
);
801 if (msqid
< 0 || msqid
>= msginfo
.msgmni
) {
803 printf("msqid (%d) out of range (0<=msqid<%d)\n", msqid
,
809 msqptr
= &msqids
[msqid
];
810 if (msqptr
->msg_qbytes
== 0) {
812 printf("no such message queue id\n");
816 if (msqptr
->msg_perm
.seq
!= IPCID_TO_SEQ(uap
->msqid
)) {
818 printf("wrong sequence number\n");
823 if ((eval
= ipcperm(cred
, &msqptr
->msg_perm
, IPC_R
))) {
825 printf("requester doesn't have read access\n");
831 while (msghdr
== NULL
) {
833 msghdr
= msqptr
->msg_first
;
834 if (msghdr
!= NULL
) {
835 if (msgsz
< msghdr
->msg_ts
&&
836 (msgflg
& MSG_NOERROR
) == 0) {
838 printf("first message on the queue is too big (want %d, got %d)\n",
839 msgsz
, msghdr
->msg_ts
);
843 if (msqptr
->msg_first
== msqptr
->msg_last
) {
844 msqptr
->msg_first
= NULL
;
845 msqptr
->msg_last
= NULL
;
847 msqptr
->msg_first
= msghdr
->msg_next
;
848 if (msqptr
->msg_first
== NULL
)
849 panic("msg_first/last messed up #1");
853 struct msg
*previous
;
857 prev
= &(msqptr
->msg_first
);
858 while ((msghdr
= *prev
) != NULL
) {
860 * Is this message's type an exact match or is
861 * this message's type less than or equal to
862 * the absolute value of a negative msgtyp?
863 * Note that the second half of this test can
864 * NEVER be true if msgtyp is positive since
865 * msg_type is always positive!
868 if (msgtyp
== msghdr
->msg_type
||
869 msghdr
->msg_type
<= -msgtyp
) {
871 printf("found message type %d, requested %d\n",
872 msghdr
->msg_type
, msgtyp
);
874 if (msgsz
< msghdr
->msg_ts
&&
875 (msgflg
& MSG_NOERROR
) == 0) {
877 printf("requested message on the queue is too big (want %d, got %d)\n",
878 msgsz
, msghdr
->msg_ts
);
882 *prev
= msghdr
->msg_next
;
883 if (msghdr
== msqptr
->msg_last
) {
884 if (previous
== NULL
) {
887 panic("msg_first/last messed up #2");
895 panic("msg_first/last messed up #3");
903 prev
= &(msghdr
->msg_next
);
908 * We've either extracted the msghdr for the appropriate
909 * message or there isn't one.
910 * If there is one then bail out of this loop.
917 * Hmph! No message found. Does the user want to wait?
920 if ((msgflg
& IPC_NOWAIT
) != 0) {
922 printf("no appropriate message found (msgtyp=%d)\n",
925 /* The SVID says to return ENOMSG. */
929 /* Unfortunately, BSD doesn't define that code yet! */
935 * Wait for something to happen
939 printf("msgrcv: goodnight\n");
941 eval
= tsleep((caddr_t
)msqptr
, (PZERO
- 4) | PCATCH
, "msgwait",
944 printf("msgrcv: good morning (eval=%d)\n", eval
);
949 printf("msgsnd: interrupted system call\n");
955 * Make sure that the msq queue still exists
958 if (msqptr
->msg_qbytes
== 0 ||
959 msqptr
->msg_perm
.seq
!= IPCID_TO_SEQ(uap
->msqid
)) {
961 printf("msqid deleted\n");
963 /* The SVID says to return EIDRM. */
967 /* Unfortunately, BSD doesn't define that code yet! */
974 * Return the message to the user.
976 * First, do the bookkeeping (before we risk being interrupted).
979 msqptr
->msg_cbytes
-= msghdr
->msg_ts
;
981 msqptr
->msg_lrpid
= p
->p_pid
;
982 msqptr
->msg_rtime
= time_second
;
985 * Make msgsz the actual amount that we'll be returning.
986 * Note that this effectively truncates the message if it is too long
987 * (since msgsz is never increased).
991 printf("found a message, msgsz=%d, msg_ts=%d\n", msgsz
,
994 if (msgsz
> msghdr
->msg_ts
)
995 msgsz
= msghdr
->msg_ts
;
998 * Return the type to the user.
1001 eval
= copyout((caddr_t
)&(msghdr
->msg_type
), user_msgp
,
1002 sizeof(msghdr
->msg_type
));
1005 printf("error (%d) copying out message type\n", eval
);
1007 msg_freehdr(msghdr
);
1008 wakeup((caddr_t
)msqptr
);
1011 user_msgp
= (char *)user_msgp
+ sizeof(msghdr
->msg_type
);
1014 * Return the segments to the user
1017 next
= msghdr
->msg_spot
;
1018 for (len
= 0; len
< msgsz
; len
+= msginfo
.msgssz
) {
1021 if (msgsz
> msginfo
.msgssz
)
1022 tlen
= msginfo
.msgssz
;
1026 panic("next too low #3");
1027 if (next
>= msginfo
.msgseg
)
1028 panic("next out of range #3");
1029 eval
= copyout((caddr_t
)&msgpool
[next
* msginfo
.msgssz
],
1033 printf("error (%d) copying out message segment\n",
1036 msg_freehdr(msghdr
);
1037 wakeup((caddr_t
)msqptr
);
1040 user_msgp
= (char *)user_msgp
+ tlen
;
1041 next
= msgmaps
[next
].next
;
1045 * Done, return the actual number of bytes copied out.
1048 msg_freehdr(msghdr
);
1049 wakeup((caddr_t
)msqptr
);
1050 p
->p_retval
[0] = msgsz
;