4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <mdb/mdb_modapi.h>
30 #include <mdb/mdb_ks.h>
32 #include <sys/types.h>
33 #include <sys/strsubr.h>
36 typedef struct pt_flags
{
41 static const struct pt_flags pf
[] = {
42 { "PTLOCK", "Master/slave pair is locked" },
43 { "PTMOPEN", "Master side is open" },
44 { "PTSOPEN", "Slave side is open" },
45 { "PTSTTY", "Slave side is tty" },
50 pt_parse_flag(const ptflags_t ftable
[], const char *arg
, uint32_t *flag
)
54 for (i
= 0; ftable
[i
].pt_name
!= NULL
; i
++) {
55 if (strcasecmp(arg
, ftable
[i
].pt_name
) == 0) {
65 pt_flag_usage(const ptflags_t ftable
[])
69 for (i
= 0; ftable
[i
].pt_name
!= NULL
; i
++)
70 mdb_printf("%12s %s\n",
71 ftable
[i
].pt_name
, ftable
[i
].pt_descr
);
77 ptms_pr_qinfo(char *buf
, size_t nbytes
, struct pt_ttys
*pt
, char *peername
,
78 queue_t
*peerq
, char *procname
)
80 (void) mdb_snprintf(buf
, nbytes
,
81 "pts/%d:%s: %p\nprocess: %d(%s)",
82 pt
->pt_minor
, peername
, peerq
, pt
->pt_pid
, procname
);
86 ptms(uintptr_t addr
, uint_t flags
, int argc
, const mdb_arg_t
*argv
)
88 const int PT_FLGDELT
= (int)(sizeof (uintptr_t) * 2 + 5);
91 char c
[MAXCOMLEN
+ 1];
92 const char *flag
= NULL
, *not_flag
= NULL
;
94 uint_t verbose
= FALSE
;
95 uint32_t mask
= 0, not_mask
= 0;
97 if (!(flags
& DCMD_ADDRSPEC
))
98 return (mdb_walk_dcmd("ptms", "ptms", argc
, argv
));
100 if (mdb_getopts(argc
, argv
,
101 'v', MDB_OPT_SETBITS
, TRUE
, &verbose
,
102 'f', MDB_OPT_STR
, &flag
,
103 'F', MDB_OPT_STR
, ¬_flag
, NULL
) != argc
)
106 if (DCMD_HDRSPEC(flags
) && flag
== NULL
&& not_flag
== NULL
) {
107 (void) mdb_printf("%?-s %s %s %?-s %?-s %3s %-6s %s\n",
108 "ADDR", "PTY", "FL", "MASTERQ", "SLAVEQ",
109 "ZID", "PID", "PROC");
112 if (flag
!= NULL
&& pt_parse_flag(pf
, flag
, &mask
) == -1) {
113 mdb_warn("unrecognized pty flag '%s'\n", flag
);
118 if (not_flag
!= NULL
&& pt_parse_flag(pf
, not_flag
, ¬_mask
) == -1) {
119 mdb_warn("unrecognized queue flag '%s'\n", flag
);
124 if (mdb_vread(&pt
, sizeof (pt
), addr
) == -1) {
125 mdb_warn("failed to read pty structure");
129 if (mask
!= 0 && !(pt
.pt_state
& mask
))
132 if (not_mask
!= 0 && (pt
.pt_state
& not_mask
))
136 * Options are specified for filtering, so If any option is specified on
137 * the command line, just print address and exit.
139 if (flag
!= NULL
|| not_flag
!= NULL
) {
140 mdb_printf("%0?p\n", addr
);
144 if (pt
.pt_pid
!= 0) {
145 if (mdb_pid2proc(pt
.pt_pid
, &p
) == NULL
)
146 (void) strcpy(c
, "<defunct>");
148 (void) strcpy(c
, p
.p_user
.u_comm
);
150 (void) strcpy(c
, "<unknown>");
152 (void) mdb_printf("%0?p %3d %2x %0?p %0?p %3d %6d %s\n",
153 addr
, pt
.pt_minor
, pt
.pt_state
, pt
.ptm_rdq
, pt
.pts_rdq
,
154 pt
.pt_zoneid
, pt
.pt_pid
, c
);
159 for (i
= 0; pf
[i
].pt_name
!= NULL
; i
++) {
160 if (!(pt
.pt_state
& (1 << i
)))
163 mdb_printf("%*s|\n%*s+--> ",
164 PT_FLGDELT
, "", PT_FLGDELT
, "");
167 mdb_printf("%*s ", PT_FLGDELT
, "");
169 mdb_printf("%-12s %s\n",
170 pf
[i
].pt_name
, pf
[i
].pt_descr
);
178 ptms_qinfo(const queue_t
*q
, char *buf
, size_t nbytes
, int ismaster
)
180 char c
[MAXCOMLEN
+ 1];
184 (void) mdb_vread(&pt
, sizeof (pt
), (uintptr_t)q
->q_ptr
);
186 if (pt
.pt_pid
!= 0) {
187 if (mdb_pid2proc(pt
.pt_pid
, &p
) == NULL
)
188 (void) strcpy(c
, "<defunct>");
190 (void) strcpy(c
, p
.p_user
.u_comm
);
192 (void) strcpy(c
, "<unknown>");
195 ptms_pr_qinfo(buf
, nbytes
, &pt
, "slave", pt
.pts_rdq
, c
);
197 ptms_pr_qinfo(buf
, nbytes
, &pt
, "master", pt
.ptm_rdq
, c
);
201 ptm_qinfo(const queue_t
*q
, char *buf
, size_t nbytes
)
203 ptms_qinfo(q
, buf
, nbytes
, 1);
207 pts_qinfo(const queue_t
*q
, char *buf
, size_t nbytes
)
209 ptms_qinfo(q
, buf
, nbytes
, 0);
213 ptms_walk_init(mdb_walk_state_t
*wsp
)
217 if (wsp
->walk_addr
!= NULL
) {
218 mdb_warn("ptms supports only global walks");
222 if (mdb_readvar(&wsp
->walk_addr
, "ptms_slots") == -1) {
223 mdb_warn("failed to read 'ptms_slots'");
227 if (mdb_readvar(&nslots
, "ptms_nslots") == -1) {
228 mdb_warn("failed to read 'ptms_nslots'");
233 * We remember the pointer value at the end of the array. When
234 * the walk gets there, we're done.
236 wsp
->walk_arg
= (((struct pt_ttys
**)wsp
->walk_addr
) + (nslots
- 1));
237 wsp
->walk_data
= mdb_alloc(sizeof (struct pt_ttys
), UM_SLEEP
);
243 ptms_walk_step(mdb_walk_state_t
*wsp
)
248 if (wsp
->walk_addr
> (uintptr_t)wsp
->walk_arg
)
251 if (mdb_vread(&ptr
, sizeof (struct pt_ttys
*), wsp
->walk_addr
) !=
252 (sizeof (struct pt_ttys
*))) {
253 mdb_warn("failed to read pt_ttys* at %p", wsp
->walk_addr
);
258 wsp
->walk_addr
+= sizeof (uintptr_t);
262 if (mdb_vread(wsp
->walk_data
, sizeof (struct pt_ttys
), ptr
) !=
263 sizeof (struct pt_ttys
)) {
264 mdb_warn("failed to read pt_ttys at %p", ptr
);
268 status
= wsp
->walk_callback(ptr
, wsp
->walk_data
, wsp
->walk_cbdata
);
269 wsp
->walk_addr
+= sizeof (uintptr_t);
275 ptms_walk_fini(mdb_walk_state_t
*wsp
)
277 mdb_free(wsp
->walk_data
, sizeof (struct pt_ttys
));
280 static const mdb_dcmd_t dcmds
[] = {
281 { "ptms", "?[-v] [-f flag] [-F flag]",
282 "print pseudo-terminal information", ptms
},
283 { "pty", "?[-v] [-f flag] [-F flag]",
284 "print pseudo-terminal information (alias of ::ptms", ptms
},
288 static const mdb_walker_t walkers
[] = {
289 { "ptms", "walk list of pseudo-tty's",
290 ptms_walk_init
, ptms_walk_step
, ptms_walk_fini
},
291 { "pty", "walk list of pseudo-tty's (alias of ::walk ptms)",
292 ptms_walk_init
, ptms_walk_step
, ptms_walk_fini
},
296 static const mdb_qops_t ptm_qops
= {
297 ptm_qinfo
, mdb_qrnext_default
, mdb_qwnext_default
300 static const mdb_qops_t pts_qops
= {
301 pts_qinfo
, mdb_qrnext_default
, mdb_qwnext_default
304 static const mdb_modinfo_t modinfo
= {
305 MDB_API_VERSION
, dcmds
, walkers
308 const mdb_modinfo_t
*
313 if (mdb_lookup_by_obj("ptm", "ptmwint", &sym
) == 0)
314 mdb_qops_install(&ptm_qops
, (uintptr_t)sym
.st_value
);
315 if (mdb_lookup_by_obj("pts", "ptswint", &sym
) == 0)
316 mdb_qops_install(&pts_qops
, (uintptr_t)sym
.st_value
);
326 if (mdb_lookup_by_obj("ptm", "ptmwint", &sym
) == 0)
327 mdb_qops_remove(&ptm_qops
, (uintptr_t)sym
.st_value
);
328 if (mdb_lookup_by_obj("pts", "ptswint", &sym
) == 0)
329 mdb_qops_remove(&pts_qops
, (uintptr_t)sym
.st_value
);