xref: /illumos-gate/usr/src/cmd/mdb/common/mdb/mdb_strio.c (revision 0c1b95be)
1 /*
2  * CDDL HEADER START
3  *
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
7  * with the License.
8  *
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.
13  *
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]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1997-2001 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 /*
28  * String I/O Backend
29  *
30  * Simple backend to provide the ability to perform i/o reads from an in-memory
31  * string.  This allows us to mdb_eval() a string -- by creating an i/o object
32  * out of it, we can then pass it to the parser as stdin.
33  */
34 
35 #include <mdb/mdb_modapi.h>
36 #include <mdb/mdb_io_impl.h>
37 #include <mdb/mdb_string.h>
38 #include <mdb/mdb_err.h>
39 
40 typedef struct str_data {
41 	char *str_base;		/* Pointer to private copy of string */
42 	char *str_ptr;		/* Current seek pointer */
43 	size_t str_len;		/* Length of string */
44 } str_data_t;
45 
46 static ssize_t
strio_read(mdb_io_t * io,void * buf,size_t nbytes)47 strio_read(mdb_io_t *io, void *buf, size_t nbytes)
48 {
49 	str_data_t *sd = io->io_data;
50 	size_t left = sd->str_base + sd->str_len - sd->str_ptr;
51 
52 	if (left != 0) {
53 		size_t obytes = nbytes < left ? nbytes : left;
54 		(void) strncpy(buf, sd->str_ptr, obytes);
55 		sd->str_ptr += obytes;
56 		return (obytes);
57 	}
58 
59 	return (0); /* At end of string: return EOF */
60 }
61 
62 static off64_t
strio_seek(mdb_io_t * io,off64_t offset,int whence)63 strio_seek(mdb_io_t *io, off64_t offset, int whence)
64 {
65 	str_data_t *sd = io->io_data;
66 	char *nptr;
67 
68 	if (io->io_next != NULL)
69 		return (IOP_SEEK(io->io_next, offset, whence));
70 
71 	switch (whence) {
72 	case SEEK_SET:
73 		nptr = sd->str_base + offset;
74 		break;
75 	case SEEK_CUR:
76 		nptr = sd->str_ptr + offset;
77 		break;
78 	case SEEK_END:
79 		nptr = sd->str_base + sd->str_len + offset;
80 		break;
81 	default:
82 		return (set_errno(EINVAL));
83 	}
84 
85 	if (nptr < sd->str_base || nptr > sd->str_ptr + sd->str_len)
86 		return (set_errno(EINVAL));
87 
88 	sd->str_ptr = nptr;
89 	return ((off64_t)(nptr - sd->str_base));
90 }
91 
92 static void
strio_close(mdb_io_t * io)93 strio_close(mdb_io_t *io)
94 {
95 	str_data_t *sd = io->io_data;
96 
97 	strfree(sd->str_base);
98 	mdb_free(sd, sizeof (str_data_t));
99 }
100 
101 static const char *
strio_name(mdb_io_t * io)102 strio_name(mdb_io_t *io)
103 {
104 	if (io->io_next != NULL)
105 		return (IOP_NAME(io->io_next));
106 
107 	return ("(string)");
108 }
109 
110 static const mdb_io_ops_t strio_ops = {
111 	.io_read = strio_read,
112 	.io_write = no_io_write,
113 	.io_seek = strio_seek,
114 	.io_ctl = no_io_ctl,
115 	.io_close = strio_close,
116 	.io_name = strio_name,
117 	.io_link = no_io_link,
118 	.io_unlink = no_io_unlink,
119 	.io_setattr = no_io_setattr,
120 	.io_suspend = no_io_suspend,
121 	.io_resume = no_io_resume,
122 };
123 
124 mdb_io_t *
mdb_strio_create(const char * s)125 mdb_strio_create(const char *s)
126 {
127 	mdb_io_t *io = mdb_alloc(sizeof (mdb_io_t), UM_SLEEP);
128 	str_data_t *sd = mdb_alloc(sizeof (str_data_t), UM_SLEEP);
129 
130 	/*
131 	 * Our parser expects each command to end with '\n' or ';'.  To
132 	 * simplify things for the caller, we append a trailing newline
133 	 * so the argvec string can be passed directly sans modifications.
134 	 */
135 	sd->str_len = strlen(s) + 1;
136 	sd->str_base = strndup(s, sd->str_len);
137 	(void) strcat(sd->str_base, "\n");
138 	sd->str_ptr = sd->str_base;
139 
140 	io->io_ops = &strio_ops;
141 	io->io_data = sd;
142 	io->io_next = NULL;
143 	io->io_refcnt = 0;
144 
145 	return (io);
146 }
147 
148 int
mdb_iob_isastr(mdb_iob_t * iob)149 mdb_iob_isastr(mdb_iob_t *iob)
150 {
151 	mdb_io_t *io;
152 
153 	for (io = iob->iob_iop; io != NULL; io = io->io_next) {
154 		if (io->io_ops == &strio_ops)
155 			return (1);
156 	}
157 
158 	return (0);
159 }
160