2 * Copyright (c) 1993 Jan-Simon Pendry
4 * The Regents of the University of California. All rights reserved.
6 * This code is derived from software contributed to Berkeley by
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94
36 * $FreeBSD: src/sys/miscfs/procfs/procfs_status.c,v 1.20.2.4 2002/01/22 17:22:59 nectar Exp $
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/malloc.h>
45 #include <sys/vnode.h>
47 #include <sys/resourcevar.h>
48 #include <vfs/procfs/procfs.h>
52 #include <vm/vm_param.h>
55 #define DOCHECK() do { \
56 if (ps >= psbuf+sizeof(psbuf)) { \
63 procfs_dostatus(struct proc
*curp
, struct lwp
*lp
, struct pfsnode
*pfs
,
66 struct proc
*p
= lp
->lwp_proc
;
72 int pid
, ppid
, pgid
, sid
;
76 char psbuf
[256]; /* XXX - conservative */
78 if (uio
->uio_rw
!= UIO_READ
)
82 ppid
= p
->p_pptr
? p
->p_pptr
->p_pid
: 0;
83 pgid
= p
->p_pgrp
->pg_id
;
84 sess
= p
->p_pgrp
->pg_session
;
85 sid
= sess
->s_leader
? sess
->s_leader
->p_pid
: 0;
87 /* comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg
88 euid ruid rgid,egid,groups[1 .. NGROUPS]
90 KASSERT(sizeof(psbuf
) > MAXCOMLEN
,
91 ("Too short buffer for new MAXCOMLEN"));
94 bcopy(p
->p_comm
, ps
, MAXCOMLEN
);
98 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
,
99 " %d %d %d %d ", pid
, ppid
, pgid
, sid
);
101 if ((p
->p_flags
& P_CONTROLT
) && (tp
= sess
->s_ttyp
))
102 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
,
103 "%d,%d ", major(tp
->t_dev
), minor(tp
->t_dev
));
105 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
,
111 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
, "%sctty", sep
);
115 if (SESS_LEADER(p
)) {
116 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
, "%ssldr", sep
);
121 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
, "noflags");
125 if (p
->p_flags
& P_SWAPPEDOUT
) {
126 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
,
127 " -1,-1 -1,-1 -1,-1");
132 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
,
133 " %ld,%ld %ld,%ld %ld,%ld",
136 ru
.ru_utime
.tv_sec
, ru
.ru_utime
.tv_usec
,
137 ru
.ru_stime
.tv_sec
, ru
.ru_stime
.tv_usec
);
141 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
, " %s",
142 (lp
->lwp_wchan
&& lp
->lwp_wmesg
) ? lp
->lwp_wmesg
: "nochan");
147 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
, " %lu %lu %lu",
149 (u_long
)p
->p_ucred
->cr_ruid
,
150 (u_long
)p
->p_ucred
->cr_rgid
);
153 /* egid (p->p_ucred->cr_svgid) is equal to cr_ngroups[0]
154 see also getegid(2) in /sys/kern/kern_prot.c */
156 for (i
= 0; i
< cr
->cr_ngroups
; i
++) {
157 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
,
158 ",%lu", (u_long
)cr
->cr_groups
[i
]);
162 if (p
->p_ucred
->cr_prison
)
163 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
,
164 " %s", p
->p_ucred
->cr_prison
->pr_host
);
166 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
, " -");
168 ps
+= ksnprintf(ps
, psbuf
+ sizeof(psbuf
) - ps
, "\n");
172 error
= uiomove_frombuf(psbuf
, xlen
, uio
);
179 procfs_docmdline(struct proc
*curp
, struct lwp
*lp
, struct pfsnode
*pfs
,
182 struct proc
*p
= lp
->lwp_proc
;
186 struct ps_strings pstr
;
189 size_t bytes_left
, done
;
192 if (uio
->uio_rw
!= UIO_READ
)
196 * If we are using the ps/cmdline caching, use that. Otherwise
197 * revert back to the old way which only implements full cmdline
198 * for the currept process and just p->p_comm for all other
200 * Note that if the argv is no longer available, we deliberately
201 * don't fall back on p->p_comm or return an error: the authentic
202 * Linux behaviour is to return zero-length in this case.
204 if (p
->p_upmap
!= NULL
&& p
->p_upmap
->proc_title
[0] &&
205 (ps_argsopen
|| (CHECKIO(curp
, p
) &&
206 (p
->p_flags
& P_INEXEC
) == 0 &&
207 !p_trespass(curp
->p_ucred
, p
->p_ucred
))
210 * Args set via writable user process mmap.
211 * We must calculate the string length manually
212 * because the user data can change at any time.
214 bp
= p
->p_upmap
->proc_title
;
215 for (buflen
= 0; buflen
< UPMAP_MAXPROCTITLE
- 1; ++buflen
) {
220 } else if (p
->p_args
&&
221 (ps_argsopen
|| (CHECKIO(curp
, p
) &&
222 (p
->p_flags
& P_INEXEC
) == 0 &&
223 !p_trespass(curp
->p_ucred
, p
->p_ucred
))
225 bp
= p
->p_args
->ar_args
;
226 buflen
= p
->p_args
->ar_length
;
228 } else if (p
!= curp
) {
234 buf
= kmalloc(buflen
+ 1, M_TEMP
, M_WAITOK
);
237 error
= copyin((void*)PS_STRINGS
, &pstr
, sizeof(pstr
));
243 if (pstr
.ps_nargvstr
< 0) {
247 if (pstr
.ps_nargvstr
> ARG_MAX
) {
251 ps_argvstr
= kmalloc(pstr
.ps_nargvstr
* sizeof(char *),
253 error
= copyin((void *)pstr
.ps_argvstr
, ps_argvstr
,
254 pstr
.ps_nargvstr
* sizeof(char *));
256 kfree(ps_argvstr
, M_TEMP
);
261 for (i
= 0; bytes_left
&& (i
< pstr
.ps_nargvstr
); i
++) {
262 error
= copyinstr(ps_argvstr
[i
], ps
,
264 /* If too long or malformed, just truncate */
273 kfree(ps_argvstr
, M_TEMP
);
276 error
= uiomove_frombuf(bp
, buflen
, uio
);