xref: /onnv-gate/usr/src/cmd/wbem/provider/tools/rds/rdprot.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <search.h>
30*0Sstevel@tonic-gate #include <stdlib.h>
31*0Sstevel@tonic-gate 
32*0Sstevel@tonic-gate #include <sys/utsname.h>
33*0Sstevel@tonic-gate #include "rdprot.h"
34*0Sstevel@tonic-gate #include "rdutil.h"
35*0Sstevel@tonic-gate /*
36*0Sstevel@tonic-gate  * This file works out the protocol layer of the bidirectional data interface
37*0Sstevel@tonic-gate  * between the rds and the client. In the server mode rds writes greetings and
38*0Sstevel@tonic-gate  * a protocol header to the output stream.
39*0Sstevel@tonic-gate  * pheader  == { "@RDS-MAG@"  PROTV }
40*0Sstevel@tonic-gate  * PROTV    == { protocol version }
41*0Sstevel@tonic-gate  * Then it sends a prompt and waits for command from client.
42*0Sstevel@tonic-gate  * PROMPT   == { "@RDS@>" }
43*0Sstevel@tonic-gate  * COMMAND  == { "command"  cmd }
44*0Sstevel@tonic-gate  * cmd	    == { "-pUuJjS" | "-p" | "-u" | "-U" |
45*0Sstevel@tonic-gate  *		 "-j" | "-J" | "-S" | "-i100" | "alive"| "exit" }
46*0Sstevel@tonic-gate  * The answer from rds is always a lists of data. The header of the answer data
47*0Sstevel@tonic-gate  * contains the number of lists in the package. Each list has a header and
48*0Sstevel@tonic-gate  * some elements, which have again a header and some fields of data:
49*0Sstevel@tonic-gate  * answer   == { lshead,  n * list }
50*0Sstevel@tonic-gate  * lshead   == { number of lists }
51*0Sstevel@tonic-gate  * list     == { lheader, n * element }
52*0Sstevel@tonic-gate  * lheader  == { LISTT, ELEMN }
53*0Sstevel@tonic-gate  * LISTT    == { type of the list }
54*0Sstevel@tonic-gate  * ELEMN    == { number of elements in the list }
55*0Sstevel@tonic-gate  * element  == { eheader, field }
56*0Sstevel@tonic-gate  * eheader  == { ELMID, FILDN }
57*0Sstevel@tonic-gate  * ELMID    == { element id, like pid, uid, project name }
58*0Sstevel@tonic-gate  * field    == { KEY, VALUE }
59*0Sstevel@tonic-gate  * All protocol elements have a key and a value separated by one space.
60*0Sstevel@tonic-gate  * The value begins after the first space and ends with the new line character.
61*0Sstevel@tonic-gate  * Protocol keys are: "@RDS-MAG@", PROTV, LISTN,  LISTT, ELEMN ELMID, FILDN,
62*0Sstevel@tonic-gate  * RDERR. The special key RDERR can occur in any line and indicates that an
63*0Sstevel@tonic-gate  * error condition occurred, where the VALUE is the error message.
64*0Sstevel@tonic-gate  */
65*0Sstevel@tonic-gate 
66*0Sstevel@tonic-gate static char line[P_MAXLEN];
67*0Sstevel@tonic-gate static char error[P_MAXLEN];
68*0Sstevel@tonic-gate static char value[P_MAXVAL];
69*0Sstevel@tonic-gate static char key[P_MAXKEY];
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate static char *nullstr = "";
72*0Sstevel@tonic-gate static FILE *wstream, *rstream;
73*0Sstevel@tonic-gate 
74*0Sstevel@tonic-gate static int format_int64(int, char *, char *, int);
75*0Sstevel@tonic-gate static int format_int32(int, char *, char *, int);
76*0Sstevel@tonic-gate static int format_ulong(int, char *, char *, int);
77*0Sstevel@tonic-gate static int format_float(int, char *, char *, int);
78*0Sstevel@tonic-gate static int format_double(int, char *, char *, int);
79*0Sstevel@tonic-gate static int format_string(int, char *, char *, int);
80*0Sstevel@tonic-gate static int format_timestruc(int, char *, char *, int);
81*0Sstevel@tonic-gate 
82*0Sstevel@tonic-gate /*
83*0Sstevel@tonic-gate  * The kv_pair_t represents an field in a  c-sturcture. An filed
84*0Sstevel@tonic-gate  * is defined by a key 'field name', format function and an offset
85*0Sstevel@tonic-gate  * in this structure
86*0Sstevel@tonic-gate  */
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate /*
89*0Sstevel@tonic-gate  * Array of fields from id_info_t structure, that are sent/received
90*0Sstevel@tonic-gate  * in a process/user/project utilization list.
91*0Sstevel@tonic-gate  */
92*0Sstevel@tonic-gate static kv_pair_t id_stub[] =
93*0Sstevel@tonic-gate {
94*0Sstevel@tonic-gate { "id_pid",	{ format_int32, offsetof(id_info_t, id_pid) }},
95*0Sstevel@tonic-gate { "id_uid",	{ format_int32, offsetof(id_info_t, id_uid) }},
96*0Sstevel@tonic-gate { "id_projid",	{ format_int32, offsetof(id_info_t, id_projid) }},
97*0Sstevel@tonic-gate { "id_usr", 	{ format_double, offsetof(id_info_t, id_usr) }},
98*0Sstevel@tonic-gate { "id_sys", 	{ format_double, offsetof(id_info_t, id_sys) }},
99*0Sstevel@tonic-gate { "id_ttime", 	{ format_double, offsetof(id_info_t, id_ttime) }},
100*0Sstevel@tonic-gate { "id_tpftime", { format_double, offsetof(id_info_t, id_tpftime) }},
101*0Sstevel@tonic-gate { "id_dpftime", { format_double, offsetof(id_info_t, id_dpftime) }},
102*0Sstevel@tonic-gate { "id_kpftime", { format_double, offsetof(id_info_t, id_kpftime) }},
103*0Sstevel@tonic-gate { "id_lck", 	{ format_double, offsetof(id_info_t, id_lck) }},
104*0Sstevel@tonic-gate { "id_slp", 	{ format_double, offsetof(id_info_t, id_slp) }},
105*0Sstevel@tonic-gate { "id_lat", 	{ format_double, offsetof(id_info_t, id_lat) }},
106*0Sstevel@tonic-gate { "id_stime", 	{ format_double, offsetof(id_info_t, id_stime) }},
107*0Sstevel@tonic-gate { "id_minf", 	{ format_int64, offsetof(id_info_t, id_minf) }},
108*0Sstevel@tonic-gate { "id_majf", 	{ format_int64, offsetof(id_info_t, id_majf) }},
109*0Sstevel@tonic-gate { "id_nswap", 	{ format_int64, offsetof(id_info_t, id_nswap) }},
110*0Sstevel@tonic-gate { "id_inblk", 	{ format_int64, offsetof(id_info_t, id_inblk) }},
111*0Sstevel@tonic-gate { "id_oublk", 	{ format_int64, offsetof(id_info_t, id_oublk) }},
112*0Sstevel@tonic-gate { "id_msnd", 	{ format_int64, offsetof(id_info_t, id_msnd) }},
113*0Sstevel@tonic-gate { "id_mrcv", 	{ format_int64, offsetof(id_info_t, id_mrcv) }},
114*0Sstevel@tonic-gate { "id_sigs", 	{ format_int64, offsetof(id_info_t, id_sigs) }},
115*0Sstevel@tonic-gate { "id_vctx", 	{ format_int64, offsetof(id_info_t, id_vctx) }},
116*0Sstevel@tonic-gate { "id_ictx", 	{ format_int64, offsetof(id_info_t, id_ictx) }},
117*0Sstevel@tonic-gate { "id_scl", 	{ format_int64, offsetof(id_info_t, id_scl) }},
118*0Sstevel@tonic-gate { "id_ioch", 	{ format_int64, offsetof(id_info_t, id_ioch) }},
119*0Sstevel@tonic-gate { "id_hpsize", 	{ format_int64, offsetof(id_info_t, id_hpsize) }},
120*0Sstevel@tonic-gate { "id_size", 	{ format_int64, offsetof(id_info_t, id_size) }},
121*0Sstevel@tonic-gate { "id_rssize", 	{ format_int64, offsetof(id_info_t, id_rssize) }},
122*0Sstevel@tonic-gate { "id_pctcpu", 	{ format_float, offsetof(id_info_t, id_pctcpu) }},
123*0Sstevel@tonic-gate { "id_pctmem", 	{ format_float, offsetof(id_info_t, id_pctmem) }},
124*0Sstevel@tonic-gate { "id_time", 	{ format_int64, offsetof(id_info_t, id_time) }},
125*0Sstevel@tonic-gate { "id_nlwps", 	{ format_int32, offsetof(id_info_t, id_nlwps) }},
126*0Sstevel@tonic-gate { "id_timestamp", { format_int64, offsetof(id_info_t, id_timestamp) }},
127*0Sstevel@tonic-gate { "id_nproc", 	{ format_int32, offsetof(id_info_t, id_nproc) }},
128*0Sstevel@tonic-gate { "id_inpkg", 	{ format_int64, offsetof(id_info_t, id_inpkg) }},
129*0Sstevel@tonic-gate { "id_oupkg", 	{ format_int64, offsetof(id_info_t, id_oupkg) }},
130*0Sstevel@tonic-gate { "id_name", 	{ format_string, offsetof(id_info_t, id_name) }}
131*0Sstevel@tonic-gate };
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate static kv_pair_t lwp_stub[] =
134*0Sstevel@tonic-gate {
135*0Sstevel@tonic-gate {"li_usage",	{ format_ulong, offsetof(lwp_info_t, li_usr) }},
136*0Sstevel@tonic-gate {"li_usr",	{ format_ulong, offsetof(lwp_info_t, li_usr) }},
137*0Sstevel@tonic-gate {"li_sys",	{ format_ulong, offsetof(lwp_info_t, li_sys) }},
138*0Sstevel@tonic-gate {"li_ttime",	{ format_ulong, offsetof(lwp_info_t, li_ttime) }},
139*0Sstevel@tonic-gate {"li_tpftime",	{ format_ulong, offsetof(lwp_info_t, li_tpftime) }},
140*0Sstevel@tonic-gate {"li_dpftime",	{ format_ulong, offsetof(lwp_info_t, li_dpftime) }},
141*0Sstevel@tonic-gate {"li_kpftime",	{ format_ulong, offsetof(lwp_info_t, li_kpftime) }},
142*0Sstevel@tonic-gate {"li_lck",	{ format_ulong, offsetof(lwp_info_t, li_lck) }},
143*0Sstevel@tonic-gate {"li_slp",	{ format_ulong, offsetof(lwp_info_t, li_slp) }},
144*0Sstevel@tonic-gate {"li_lat",	{ format_ulong, offsetof(lwp_info_t, li_lat) }},
145*0Sstevel@tonic-gate {"li_stime",	{ format_ulong, offsetof(lwp_info_t, li_stime) }},
146*0Sstevel@tonic-gate {"li_minf",	{ format_ulong, offsetof(lwp_info_t, li_minf) }},
147*0Sstevel@tonic-gate {"li_majf",	{ format_ulong, offsetof(lwp_info_t, li_majf) }},
148*0Sstevel@tonic-gate {"li_nswap",	{ format_ulong, offsetof(lwp_info_t, li_nswap) }},
149*0Sstevel@tonic-gate {"li_inblk",	{ format_ulong, offsetof(lwp_info_t, li_inblk) }},
150*0Sstevel@tonic-gate {"li_oublk",	{ format_ulong, offsetof(lwp_info_t, li_oublk) }},
151*0Sstevel@tonic-gate {"li_msnd",	{ format_ulong, offsetof(lwp_info_t, li_msnd) }},
152*0Sstevel@tonic-gate {"li_mrcv",	{ format_ulong, offsetof(lwp_info_t, li_mrcv) }},
153*0Sstevel@tonic-gate {"li_sigs",	{ format_ulong, offsetof(lwp_info_t, li_sigs) }},
154*0Sstevel@tonic-gate {"li_vctx",	{ format_ulong, offsetof(lwp_info_t, li_vctx) }},
155*0Sstevel@tonic-gate {"li_ictx",	{ format_ulong, offsetof(lwp_info_t, li_ictx) }},
156*0Sstevel@tonic-gate {"li_scl",	{ format_ulong, offsetof(lwp_info_t, li_scl) }},
157*0Sstevel@tonic-gate {"li_ioch",	{ format_ulong, offsetof(lwp_info_t, li_ioch) }},
158*0Sstevel@tonic-gate {"li_hpsize",	{ format_ulong, offsetof(lwp_info_t, li_hpsize) }},
159*0Sstevel@tonic-gate {"li_timestamp", { format_ulong, offsetof(lwp_info_t, li_timestamp) }},
160*0Sstevel@tonic-gate };
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate static kv_pair_t lwpinfo_stub[] =
163*0Sstevel@tonic-gate {
164*0Sstevel@tonic-gate {"lwpr_pid",	{ format_int32, offsetof(lwpinfo_t, pr_pid) }},
165*0Sstevel@tonic-gate {"lwpr_lwpid",	{ format_int32, offsetof(lwpinfo_t, pr_lwpid) }},
166*0Sstevel@tonic-gate };
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate static kv_pair_t prusage_stub[] =
169*0Sstevel@tonic-gate {
170*0Sstevel@tonic-gate {"pr_tstamp",	{ format_timestruc, offsetof(prusage_t, pr_tstamp) }},
171*0Sstevel@tonic-gate {"pr_create",	{ format_timestruc, offsetof(prusage_t, pr_create) }},
172*0Sstevel@tonic-gate {"pr_term",	{ format_timestruc, offsetof(prusage_t, pr_term) }},
173*0Sstevel@tonic-gate {"pr_rtime",	{ format_timestruc, offsetof(prusage_t, pr_rtime) }},
174*0Sstevel@tonic-gate {"pr_utime",	{ format_timestruc, offsetof(prusage_t, pr_utime) }},
175*0Sstevel@tonic-gate {"pr_stime",	{ format_timestruc, offsetof(prusage_t, pr_stime) }},
176*0Sstevel@tonic-gate {"pr_ttime",	{ format_timestruc, offsetof(prusage_t, pr_ttime) }},
177*0Sstevel@tonic-gate {"pr_tftime",	{ format_timestruc, offsetof(prusage_t, pr_tftime) }},
178*0Sstevel@tonic-gate {"pr_dftime",	{ format_timestruc, offsetof(prusage_t, pr_dftime) }},
179*0Sstevel@tonic-gate {"pr_kftime",	{ format_timestruc, offsetof(prusage_t, pr_kftime) }},
180*0Sstevel@tonic-gate {"pr_ltime",	{ format_timestruc, offsetof(prusage_t, pr_ltime) }},
181*0Sstevel@tonic-gate {"pr_slptime",	{ format_timestruc, offsetof(prusage_t, pr_slptime) }},
182*0Sstevel@tonic-gate {"pr_wtime",	{ format_timestruc, offsetof(prusage_t, pr_wtime) }},
183*0Sstevel@tonic-gate {"pr_stoptime", { format_timestruc, offsetof(prusage_t, pr_stoptime) }},
184*0Sstevel@tonic-gate {"pr_minf",	{ format_ulong, offsetof(prusage_t, pr_minf) }},
185*0Sstevel@tonic-gate {"pr_majf",	{ format_ulong, offsetof(prusage_t, pr_majf) }},
186*0Sstevel@tonic-gate {"pr_nswap",	{ format_ulong, offsetof(prusage_t, pr_nswap) }},
187*0Sstevel@tonic-gate {"pr_inblk",	{ format_ulong, offsetof(prusage_t, pr_inblk) }},
188*0Sstevel@tonic-gate {"pr_oublk",	{ format_ulong, offsetof(prusage_t, pr_oublk) }},
189*0Sstevel@tonic-gate {"pr_msnd",	{ format_ulong, offsetof(prusage_t, pr_msnd) }},
190*0Sstevel@tonic-gate {"pr_mrcv",	{ format_ulong, offsetof(prusage_t, pr_mrcv) }},
191*0Sstevel@tonic-gate {"pr_sigs",	{ format_ulong, offsetof(prusage_t, pr_sigs) }},
192*0Sstevel@tonic-gate {"pr_vctx",	{ format_ulong, offsetof(prusage_t, pr_vctx) }},
193*0Sstevel@tonic-gate {"pr_ictx",	{ format_ulong, offsetof(prusage_t, pr_ictx) }},
194*0Sstevel@tonic-gate {"pr_sysc",	{ format_ulong, offsetof(prusage_t, pr_sysc) }},
195*0Sstevel@tonic-gate {"pr_ioch",	{ format_ulong, offsetof(prusage_t, pr_ioch) }},
196*0Sstevel@tonic-gate };
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate /*
199*0Sstevel@tonic-gate  * Array of fields in id_info_t structure, that are sent/received
200*0Sstevel@tonic-gate  * in an active user list.
201*0Sstevel@tonic-gate  */
202*0Sstevel@tonic-gate static kv_pair_t usr_stub[] =
203*0Sstevel@tonic-gate {
204*0Sstevel@tonic-gate { "usr_id", 	{ format_int32, offsetof(id_info_t, id_uid) }},
205*0Sstevel@tonic-gate { "usr_name", 	{ format_string, offsetof(id_info_t, id_name) }}
206*0Sstevel@tonic-gate };
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate /*
209*0Sstevel@tonic-gate  * Array of fields in id_info_t structure, that are sent/received
210*0Sstevel@tonic-gate  * in an active project list.
211*0Sstevel@tonic-gate  */
212*0Sstevel@tonic-gate static kv_pair_t prj_stub[] =
213*0Sstevel@tonic-gate {
214*0Sstevel@tonic-gate { "prj_id", 	{ format_int32, offsetof(id_info_t, id_projid) }},
215*0Sstevel@tonic-gate { "prj_name", 	{ format_string, offsetof(id_info_t, id_name)   }}
216*0Sstevel@tonic-gate };
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate /*
219*0Sstevel@tonic-gate  * Array of fields in id_info_t structure, that are sent/received
220*0Sstevel@tonic-gate  * in a system list.
221*0Sstevel@tonic-gate  */
222*0Sstevel@tonic-gate static kv_pair_t sys_stub[] =
223*0Sstevel@tonic-gate {
224*0Sstevel@tonic-gate { "sys_nodename", { format_string, offsetof(sys_info_t, nodename) }},
225*0Sstevel@tonic-gate { "sys_name",	{ format_string, offsetof(sys_info_t, name) }}
226*0Sstevel@tonic-gate };
227*0Sstevel@tonic-gate 
228*0Sstevel@tonic-gate /*
229*0Sstevel@tonic-gate  * Array of fields in id_info_t structure, that are sent/received
230*0Sstevel@tonic-gate  * in command.
231*0Sstevel@tonic-gate  */
232*0Sstevel@tonic-gate static kv_pair_t cmd_stub[] =
233*0Sstevel@tonic-gate {
234*0Sstevel@tonic-gate { "command",	{ format_int32, offsetof(cmd_t, command) }}
235*0Sstevel@tonic-gate };
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate #define	stubsize(stub) ((sizeof (stub))/(sizeof (kv_pair_t)))
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate /*
240*0Sstevel@tonic-gate  * Each list type has its own fields description, the list type is
241*0Sstevel@tonic-gate  * the index into this table:
242*0Sstevel@tonic-gate  * L_PRC_SI - processes statistical information
243*0Sstevel@tonic-gate  * L_USR_SI - useres statistical information
244*0Sstevel@tonic-gate  * L_PRJ_SI - projects statistical information
245*0Sstevel@tonic-gate  * L_AC_USR - active users
246*0Sstevel@tonic-gate  * L_AC_PRJ - active projects
247*0Sstevel@tonic-gate  * L_SYSTEM - system
248*0Sstevel@tonic-gate  */
249*0Sstevel@tonic-gate #define	NOF_STUBS   10
250*0Sstevel@tonic-gate static stub_t stubs[NOF_STUBS + 1] = {
251*0Sstevel@tonic-gate { 0, NULL},
252*0Sstevel@tonic-gate { stubsize(id_stub), id_stub},
253*0Sstevel@tonic-gate { stubsize(id_stub), id_stub},
254*0Sstevel@tonic-gate { stubsize(id_stub), id_stub},
255*0Sstevel@tonic-gate { stubsize(usr_stub), usr_stub},
256*0Sstevel@tonic-gate { stubsize(prj_stub), prj_stub},
257*0Sstevel@tonic-gate { stubsize(sys_stub), sys_stub},
258*0Sstevel@tonic-gate { stubsize(cmd_stub), cmd_stub},
259*0Sstevel@tonic-gate { stubsize(lwp_stub), lwp_stub},
260*0Sstevel@tonic-gate { stubsize(lwpinfo_stub), lwpinfo_stub},
261*0Sstevel@tonic-gate { stubsize(prusage_stub), prusage_stub},
262*0Sstevel@tonic-gate };
263*0Sstevel@tonic-gate 
264*0Sstevel@tonic-gate /*
265*0Sstevel@tonic-gate  * read a protocol line, do some checks and extract its key
266*0Sstevel@tonic-gate  * and value part.
267*0Sstevel@tonic-gate  */
268*0Sstevel@tonic-gate static int
269*0Sstevel@tonic-gate r_line() {
270*0Sstevel@tonic-gate 	size_t len;
271*0Sstevel@tonic-gate 
272*0Sstevel@tonic-gate 	if (fgets(line, P_MAXLEN, rstream) == NULL) {
273*0Sstevel@tonic-gate 		format_err("can't read line");
274*0Sstevel@tonic-gate 		return (-1);
275*0Sstevel@tonic-gate 	}
276*0Sstevel@tonic-gate 	len = strlen(line);
277*0Sstevel@tonic-gate 	if (len > P_MAXLEN) {
278*0Sstevel@tonic-gate 		format_err("%s: \"%s\"", "wrong line length", line);
279*0Sstevel@tonic-gate 		return (-1);
280*0Sstevel@tonic-gate 	}
281*0Sstevel@tonic-gate 	/* carriage return */
282*0Sstevel@tonic-gate 	if (len == 1) {
283*0Sstevel@tonic-gate 		value[0] = line[0];
284*0Sstevel@tonic-gate 		return (0);
285*0Sstevel@tonic-gate 	}
286*0Sstevel@tonic-gate 	/* see P_MAXKEY and P_MAXVAL for string sizes */
287*0Sstevel@tonic-gate 	if (sscanf(line, "%19s %58s", key, value) != 2) {
288*0Sstevel@tonic-gate 		format_err("%s: \"%s\"", "wrong line format", line);
289*0Sstevel@tonic-gate 		return (-1);
290*0Sstevel@tonic-gate 	}
291*0Sstevel@tonic-gate 	if (strcmp(key, RDERR) == 0) {
292*0Sstevel@tonic-gate 		(void) strcpy(error, line + strlen(RDERR) + 1);
293*0Sstevel@tonic-gate 		return (-1);
294*0Sstevel@tonic-gate 	}
295*0Sstevel@tonic-gate 	return (0);
296*0Sstevel@tonic-gate }
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate #define	STRUCT_TO_STR	1
299*0Sstevel@tonic-gate #define	STR_TO_STRUCT	2
300*0Sstevel@tonic-gate 
301*0Sstevel@tonic-gate /*
302*0Sstevel@tonic-gate  * if STR_TO_STRUCT read a 64 bit value from string buffer, format it and
303*0Sstevel@tonic-gate  * write it into the structure.
304*0Sstevel@tonic-gate  * if STRUCT_TO_STR read a 64 bit value from structure and write it as
305*0Sstevel@tonic-gate  * a string into buffer.
306*0Sstevel@tonic-gate  */
307*0Sstevel@tonic-gate static int
308*0Sstevel@tonic-gate format_int64(int set, char *buf, char *strct, int off)
309*0Sstevel@tonic-gate {
310*0Sstevel@tonic-gate 	int64_t v;
311*0Sstevel@tonic-gate 
312*0Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
313*0Sstevel@tonic-gate 		if (sscanf(buf, "%" SCNd64, &v) != 1) {
314*0Sstevel@tonic-gate 			format_err("%s: \"%s\"", "wrong line format", line);
315*0Sstevel@tonic-gate 			return (-1);
316*0Sstevel@tonic-gate 		}
317*0Sstevel@tonic-gate 		*(int64_t *)(void *)(strct + off) = v;
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 	} else {
320*0Sstevel@tonic-gate 		v = *((int64_t *)(void *)(strct + off));
321*0Sstevel@tonic-gate 		(void) sprintf(buf, "%" PRId64, v);
322*0Sstevel@tonic-gate 
323*0Sstevel@tonic-gate 	}
324*0Sstevel@tonic-gate 	return (0);
325*0Sstevel@tonic-gate }
326*0Sstevel@tonic-gate 
327*0Sstevel@tonic-gate /*
328*0Sstevel@tonic-gate  * if STR_TO_STRUCT read a 32 bit value from string buffer, format it and
329*0Sstevel@tonic-gate  * write it into the structure.
330*0Sstevel@tonic-gate  * if STRUCT_TO_STR read a 32 bit value from structure and write it as
331*0Sstevel@tonic-gate  * a string into buffer.
332*0Sstevel@tonic-gate  */
333*0Sstevel@tonic-gate static int
334*0Sstevel@tonic-gate format_int32(int set, char *buf, char *id, int off)
335*0Sstevel@tonic-gate {
336*0Sstevel@tonic-gate 	int32_t v;
337*0Sstevel@tonic-gate 
338*0Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
339*0Sstevel@tonic-gate 		if (sscanf(buf, "%d", &v) != 1) {
340*0Sstevel@tonic-gate 			format_err("%s: \"%s\"", "wrong line format", line);
341*0Sstevel@tonic-gate 			return (-1);
342*0Sstevel@tonic-gate 		}
343*0Sstevel@tonic-gate 		*(int32_t *)(void *)(id + off) = v;
344*0Sstevel@tonic-gate 
345*0Sstevel@tonic-gate 	} else {
346*0Sstevel@tonic-gate 		v = *((int32_t *)(void *)(id + off));
347*0Sstevel@tonic-gate 		(void) sprintf(buf, "%d", v);
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate 	}
350*0Sstevel@tonic-gate 	return (0);
351*0Sstevel@tonic-gate }
352*0Sstevel@tonic-gate 
353*0Sstevel@tonic-gate /*
354*0Sstevel@tonic-gate  */
355*0Sstevel@tonic-gate static int
356*0Sstevel@tonic-gate format_ulong(int set, char *buf, char *id, int off)
357*0Sstevel@tonic-gate {
358*0Sstevel@tonic-gate 	ulong_t v;
359*0Sstevel@tonic-gate 
360*0Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
361*0Sstevel@tonic-gate 		if (sscanf(buf, "%lu", &v) != 1) {
362*0Sstevel@tonic-gate 			format_err("%s: \"%s\"", "wrong line format", line);
363*0Sstevel@tonic-gate 			return (-1);
364*0Sstevel@tonic-gate 		}
365*0Sstevel@tonic-gate 		*(ulong_t *)(void *)(id + off) = v;
366*0Sstevel@tonic-gate 
367*0Sstevel@tonic-gate 	} else {
368*0Sstevel@tonic-gate 		v = *((ulong_t *)(void *)(id + off));
369*0Sstevel@tonic-gate 		(void) sprintf(buf, "%ld", v);
370*0Sstevel@tonic-gate 
371*0Sstevel@tonic-gate 	}
372*0Sstevel@tonic-gate 	return (0);
373*0Sstevel@tonic-gate }
374*0Sstevel@tonic-gate 
375*0Sstevel@tonic-gate /*
376*0Sstevel@tonic-gate  * if STR_TO_STRUCT read a float value from string buffer, format it and
377*0Sstevel@tonic-gate  * write it into the structure.
378*0Sstevel@tonic-gate  * if STRUCT_TO_STR read a float value from structure and write it as
379*0Sstevel@tonic-gate  * a string into buffer.
380*0Sstevel@tonic-gate  */
381*0Sstevel@tonic-gate static int
382*0Sstevel@tonic-gate format_float(int set, char *buf, char *id, int off)
383*0Sstevel@tonic-gate {
384*0Sstevel@tonic-gate 	float v;
385*0Sstevel@tonic-gate 
386*0Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
387*0Sstevel@tonic-gate 		if (sscanf(buf, "%f", &v) != 1) {
388*0Sstevel@tonic-gate 			format_err("%s: \"%s\"", "wrong line format", line);
389*0Sstevel@tonic-gate 			return (-1);
390*0Sstevel@tonic-gate 		}
391*0Sstevel@tonic-gate 		*(float *)(void *)(id + off) = v;
392*0Sstevel@tonic-gate 
393*0Sstevel@tonic-gate 	} else {
394*0Sstevel@tonic-gate 		v = *((float *)(void *)(id + off));
395*0Sstevel@tonic-gate 		(void) sprintf(buf, "%f", v);
396*0Sstevel@tonic-gate 
397*0Sstevel@tonic-gate 	}
398*0Sstevel@tonic-gate 	return (0);
399*0Sstevel@tonic-gate }
400*0Sstevel@tonic-gate 
401*0Sstevel@tonic-gate /*
402*0Sstevel@tonic-gate  * if STR_TO_STRUCT read a double value from string buffer, format it and
403*0Sstevel@tonic-gate  * write it into the structure.
404*0Sstevel@tonic-gate  * if STRUCT_TO_STR read a double value from structure and write it as
405*0Sstevel@tonic-gate  * a string into buffer.
406*0Sstevel@tonic-gate  */
407*0Sstevel@tonic-gate static int
408*0Sstevel@tonic-gate format_double(int set, char *buf, char *id, int off)
409*0Sstevel@tonic-gate {
410*0Sstevel@tonic-gate 	double v;
411*0Sstevel@tonic-gate 
412*0Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
413*0Sstevel@tonic-gate 		if (sscanf(buf, "%lf", &v) != 1) {
414*0Sstevel@tonic-gate 			format_err("wrong line format: \"%s\"", line);
415*0Sstevel@tonic-gate 			return (-1);
416*0Sstevel@tonic-gate 		}
417*0Sstevel@tonic-gate 		*(double *)(void *)(id + off) = v;
418*0Sstevel@tonic-gate 
419*0Sstevel@tonic-gate 	} else {
420*0Sstevel@tonic-gate 		v = *((double *)(void *)(id + off));
421*0Sstevel@tonic-gate 		(void) sprintf(buf, "%f", v);
422*0Sstevel@tonic-gate 
423*0Sstevel@tonic-gate 	}
424*0Sstevel@tonic-gate 	return (0);
425*0Sstevel@tonic-gate }
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate /*
428*0Sstevel@tonic-gate  * if STR_TO_STRUCT read a string from string buffer, format it and
429*0Sstevel@tonic-gate  * write it into the structure.
430*0Sstevel@tonic-gate  * if STRUCT_TO_STR read a string from structure and write it as
431*0Sstevel@tonic-gate  * a string into buffer.
432*0Sstevel@tonic-gate  */
433*0Sstevel@tonic-gate static int
434*0Sstevel@tonic-gate format_string(int set, char *buf, char *id, int off)
435*0Sstevel@tonic-gate {
436*0Sstevel@tonic-gate 	char *v;
437*0Sstevel@tonic-gate 
438*0Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
439*0Sstevel@tonic-gate 		if ((v = (char *)malloc(strlen(buf) + 1))  != 0) {
440*0Sstevel@tonic-gate 			(void) strcpy(v, buf);
441*0Sstevel@tonic-gate 		} else {
442*0Sstevel@tonic-gate 			v = nullstr;
443*0Sstevel@tonic-gate 			return (-1);
444*0Sstevel@tonic-gate 		}
445*0Sstevel@tonic-gate 		*(char **)(void *)(id + off) = v;
446*0Sstevel@tonic-gate 	} else {
447*0Sstevel@tonic-gate 		if ((*((char **)(void *)(id + off))) != NULL) {
448*0Sstevel@tonic-gate 			(void) snprintf(buf, P_MAXVAL, "%s",
449*0Sstevel@tonic-gate 					*((char **)(void *)(id + off)));
450*0Sstevel@tonic-gate 		}
451*0Sstevel@tonic-gate 	}
452*0Sstevel@tonic-gate 	return (0);
453*0Sstevel@tonic-gate }
454*0Sstevel@tonic-gate 
455*0Sstevel@tonic-gate static int
456*0Sstevel@tonic-gate format_timestruc(int set, char *buf, char *strct, int off)
457*0Sstevel@tonic-gate {
458*0Sstevel@tonic-gate 	int64_t v1;
459*0Sstevel@tonic-gate 	int64_t v2;
460*0Sstevel@tonic-gate 
461*0Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
462*0Sstevel@tonic-gate 		if (sscanf(buf, "%" SCNd64 ",%" SCNd64, &v1, &v2) != 2) {
463*0Sstevel@tonic-gate 			format_err("%s: \"%s\"", "wrong line format", line);
464*0Sstevel@tonic-gate 			return (-1);
465*0Sstevel@tonic-gate 		}
466*0Sstevel@tonic-gate 		((timestruc_t *)(void *)(strct + off))->tv_sec = v1;
467*0Sstevel@tonic-gate 		((timestruc_t *)(void *)(strct + off))->tv_nsec = v2;
468*0Sstevel@tonic-gate 
469*0Sstevel@tonic-gate 	} else {
470*0Sstevel@tonic-gate 		v1 = ((timestruc_t *)(void *)(strct + off))->tv_sec;
471*0Sstevel@tonic-gate 		/*
472*0Sstevel@tonic-gate 		 * Since the times in prusage start with millisecond
473*0Sstevel@tonic-gate 		 * precision after the micro state accounting was enabled
474*0Sstevel@tonic-gate 		 * discard the nano/micro second fraction in the saved
475*0Sstevel@tonic-gate 		 * values otherwise we will get negative values in next run.
476*0Sstevel@tonic-gate 		 */
477*0Sstevel@tonic-gate 		v2 = ((((timestruc_t *)(void *)(strct + off))->tv_nsec) /
478*0Sstevel@tonic-gate 			MICROSEC) * MICROSEC;
479*0Sstevel@tonic-gate 		(void) sprintf(buf, "%" PRId64 ",%" PRId64, v1, v2);
480*0Sstevel@tonic-gate 
481*0Sstevel@tonic-gate 	}
482*0Sstevel@tonic-gate 	return (0);
483*0Sstevel@tonic-gate }
484*0Sstevel@tonic-gate 
485*0Sstevel@tonic-gate /*
486*0Sstevel@tonic-gate  * A hash table of keys == names and data == { formats and offsets }.
487*0Sstevel@tonic-gate  */
488*0Sstevel@tonic-gate static int
489*0Sstevel@tonic-gate init_hashtab() {
490*0Sstevel@tonic-gate 	ENTRY item;
491*0Sstevel@tonic-gate 	int   i, j, size = 0;
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate 	for (i = 0; i < NOF_STUBS + 1; i++) {
494*0Sstevel@tonic-gate 		size += stubs[i].size;
495*0Sstevel@tonic-gate 	}
496*0Sstevel@tonic-gate 	if (hcreate(size) == 0) {
497*0Sstevel@tonic-gate 		format_err("can't create hash table");
498*0Sstevel@tonic-gate 		return (-1);
499*0Sstevel@tonic-gate 	}
500*0Sstevel@tonic-gate 	for (i = 0; i < NOF_STUBS + 1; i++) {
501*0Sstevel@tonic-gate 		for (j = 0; j < stubs[i].size; j++) {
502*0Sstevel@tonic-gate 			item.key = stubs[i].stub[j].key;
503*0Sstevel@tonic-gate 			item.data = (void *) &(stubs[i].stub[j].info);
504*0Sstevel@tonic-gate 			if (hsearch(item, ENTER) == NULL) {
505*0Sstevel@tonic-gate 				format_err("can't insert into hash table");
506*0Sstevel@tonic-gate 				return (-1);
507*0Sstevel@tonic-gate 			}
508*0Sstevel@tonic-gate 		}
509*0Sstevel@tonic-gate 	}
510*0Sstevel@tonic-gate 	return (0);
511*0Sstevel@tonic-gate }
512*0Sstevel@tonic-gate 
513*0Sstevel@tonic-gate int
514*0Sstevel@tonic-gate open_prot(int fd, char *rw)
515*0Sstevel@tonic-gate {
516*0Sstevel@tonic-gate 	if (strcmp(rw, "r") == 0) {
517*0Sstevel@tonic-gate 		if ((rstream = fdopen(fd, rw)) == NULL) {
518*0Sstevel@tonic-gate 			format_err("can't open read stream");
519*0Sstevel@tonic-gate 			return (-1);
520*0Sstevel@tonic-gate 		}
521*0Sstevel@tonic-gate 		if (init_hashtab() != 0) {
522*0Sstevel@tonic-gate 			format_err("can't initialize hashtab");
523*0Sstevel@tonic-gate 			return (-1);
524*0Sstevel@tonic-gate 		}
525*0Sstevel@tonic-gate 	} else if (strcmp(rw, "w") == 0) {
526*0Sstevel@tonic-gate 		if ((wstream = fdopen(fd, rw)) == NULL) {
527*0Sstevel@tonic-gate 			format_err("can't open write stream");
528*0Sstevel@tonic-gate 			return (-1);
529*0Sstevel@tonic-gate 		}
530*0Sstevel@tonic-gate 	} else {
531*0Sstevel@tonic-gate 		format_err("open_prot(), wrong argument  %s", rw);
532*0Sstevel@tonic-gate 			return (-1);
533*0Sstevel@tonic-gate 	}
534*0Sstevel@tonic-gate 	return (0);
535*0Sstevel@tonic-gate }
536*0Sstevel@tonic-gate 
537*0Sstevel@tonic-gate void
538*0Sstevel@tonic-gate close_prot()
539*0Sstevel@tonic-gate {
540*0Sstevel@tonic-gate 
541*0Sstevel@tonic-gate 	(void) fclose(rstream);
542*0Sstevel@tonic-gate 	(void) fclose(wstream);
543*0Sstevel@tonic-gate 	hdestroy();
544*0Sstevel@tonic-gate }
545*0Sstevel@tonic-gate 
546*0Sstevel@tonic-gate /*
547*0Sstevel@tonic-gate  * @RDS-MAG@
548*0Sstevel@tonic-gate  * PROTV 100
549*0Sstevel@tonic-gate  */
550*0Sstevel@tonic-gate int
551*0Sstevel@tonic-gate wr_phead()
552*0Sstevel@tonic-gate {
553*0Sstevel@tonic-gate 	(void) fprintf(wstream, "%s\n%s %d\n",
554*0Sstevel@tonic-gate 			PROTM, PROTV, PROT_VERSION);
555*0Sstevel@tonic-gate 	(void) fflush(wstream);
556*0Sstevel@tonic-gate 	return (0);
557*0Sstevel@tonic-gate }
558*0Sstevel@tonic-gate /*
559*0Sstevel@tonic-gate  * @RDS@> [code]
560*0Sstevel@tonic-gate  */
561*0Sstevel@tonic-gate int
562*0Sstevel@tonic-gate wr_prompt(char *code) {
563*0Sstevel@tonic-gate 
564*0Sstevel@tonic-gate 	(void) fprintf(wstream, "%s%s\n", PROMPT, code);
565*0Sstevel@tonic-gate 	(void) fflush(wstream);
566*0Sstevel@tonic-gate 	return (0);
567*0Sstevel@tonic-gate }
568*0Sstevel@tonic-gate 
569*0Sstevel@tonic-gate int
570*0Sstevel@tonic-gate wr_lshead(int n)
571*0Sstevel@tonic-gate {
572*0Sstevel@tonic-gate 	(void) fprintf(wstream, "%s %d\n", LISTN, n);
573*0Sstevel@tonic-gate 	(void) fflush(wstream);
574*0Sstevel@tonic-gate 	return (0);
575*0Sstevel@tonic-gate }
576*0Sstevel@tonic-gate 
577*0Sstevel@tonic-gate /*
578*0Sstevel@tonic-gate  * LISTT [type]
579*0Sstevel@tonic-gate  * ELEMN [n]
580*0Sstevel@tonic-gate  */
581*0Sstevel@tonic-gate int
582*0Sstevel@tonic-gate wr_lhead(int type, int n)
583*0Sstevel@tonic-gate {
584*0Sstevel@tonic-gate 	(void) fprintf(wstream, "%s %d\n%s %d\n", LISTT, type, ELEMN, n);
585*0Sstevel@tonic-gate 	(void) fflush(wstream);
586*0Sstevel@tonic-gate 	return (0);
587*0Sstevel@tonic-gate }
588*0Sstevel@tonic-gate /*
589*0Sstevel@tonic-gate  * ELMID [elemid]
590*0Sstevel@tonic-gate  * FILDN [number of elements]
591*0Sstevel@tonic-gate  * e.g.
592*0Sstevel@tonic-gate  * id_usr 11050000000
593*0Sstevel@tonic-gate  * id_sys 7850000000
594*0Sstevel@tonic-gate  * id_ttime 0
595*0Sstevel@tonic-gate  * id_tpftime 0
596*0Sstevel@tonic-gate  *
597*0Sstevel@tonic-gate  * Write all fields defined by stub[stubidx]. The src is the source pointer.
598*0Sstevel@tonic-gate  * For each element read the key, grab the format function and the offset.
599*0Sstevel@tonic-gate  * Read and format the element from the source and write it out as a string.
600*0Sstevel@tonic-gate  */
601*0Sstevel@tonic-gate int
602*0Sstevel@tonic-gate wr_element(int stubidx, char *src, char *elemid)
603*0Sstevel@tonic-gate {
604*0Sstevel@tonic-gate 	int i;
605*0Sstevel@tonic-gate 
606*0Sstevel@tonic-gate 	(void) fprintf(wstream, "%s %s\n%s %d\n",
607*0Sstevel@tonic-gate 			ELMID, elemid, FILDN, stubs[stubidx].size);
608*0Sstevel@tonic-gate 	for (i = 0; i < stubs[stubidx].size; i++) {
609*0Sstevel@tonic-gate 		stubs[stubidx].stub[i].info.format(STRUCT_TO_STR,
610*0Sstevel@tonic-gate 				value, src, stubs[stubidx].stub[i].info.off);
611*0Sstevel@tonic-gate 		(void) fprintf(wstream, "%s %s\n",
612*0Sstevel@tonic-gate 				stubs[stubidx].stub[i].key, value);
613*0Sstevel@tonic-gate 	}
614*0Sstevel@tonic-gate 	(void) fflush(wstream);
615*0Sstevel@tonic-gate 	return (0);
616*0Sstevel@tonic-gate }
617*0Sstevel@tonic-gate 
618*0Sstevel@tonic-gate int
619*0Sstevel@tonic-gate wr_string(char *str)
620*0Sstevel@tonic-gate {
621*0Sstevel@tonic-gate 
622*0Sstevel@tonic-gate 	(void) fprintf(wstream, "%s", str);
623*0Sstevel@tonic-gate 	(void) fflush(wstream);
624*0Sstevel@tonic-gate 	return (0);
625*0Sstevel@tonic-gate }
626*0Sstevel@tonic-gate 
627*0Sstevel@tonic-gate int
628*0Sstevel@tonic-gate wr_value(char *key, int64_t v)
629*0Sstevel@tonic-gate {
630*0Sstevel@tonic-gate 
631*0Sstevel@tonic-gate 	(void) fprintf(wstream, "%s %" PRId64 "\n", key, v);
632*0Sstevel@tonic-gate 	(void) fflush(wstream);
633*0Sstevel@tonic-gate 	return (0);
634*0Sstevel@tonic-gate }
635*0Sstevel@tonic-gate /*
636*0Sstevel@tonic-gate  * RDERR [err]
637*0Sstevel@tonic-gate  */
638*0Sstevel@tonic-gate void
639*0Sstevel@tonic-gate wr_error(char *err)
640*0Sstevel@tonic-gate {
641*0Sstevel@tonic-gate 	size_t len = strlen(RDERR + 1);
642*0Sstevel@tonic-gate 	if (strlen(err) > P_MAXLEN - len) {
643*0Sstevel@tonic-gate 		*(err + P_MAXLEN - len - 4) = '.';
644*0Sstevel@tonic-gate 		*(err + P_MAXLEN - len - 3) = '.';
645*0Sstevel@tonic-gate 		*(err + P_MAXLEN - len - 2) = '.';
646*0Sstevel@tonic-gate 		*(err + P_MAXLEN - len - 1) = 0;
647*0Sstevel@tonic-gate 	}
648*0Sstevel@tonic-gate 	len = strlen(err) - 1;
649*0Sstevel@tonic-gate 	while (len-- > 0) {
650*0Sstevel@tonic-gate 		if (*(err + len) == '\n')
651*0Sstevel@tonic-gate 			*(err + len) = ' ';
652*0Sstevel@tonic-gate 	}
653*0Sstevel@tonic-gate 
654*0Sstevel@tonic-gate 	(void) fprintf(wstream, "%s %s\n", RDERR, err);
655*0Sstevel@tonic-gate 	(void) fflush(wstream);
656*0Sstevel@tonic-gate }
657*0Sstevel@tonic-gate 
658*0Sstevel@tonic-gate /*
659*0Sstevel@tonic-gate  * read a protocol line, check the key and return the value associated
660*0Sstevel@tonic-gate  * with it.
661*0Sstevel@tonic-gate  */
662*0Sstevel@tonic-gate int64_t
663*0Sstevel@tonic-gate r_value(char *check_key) {
664*0Sstevel@tonic-gate 	int64_t v = -1;
665*0Sstevel@tonic-gate 
666*0Sstevel@tonic-gate 	if ((r_line() == -1) ||
667*0Sstevel@tonic-gate 			(strcmp(check_key, key) != 0) ||
668*0Sstevel@tonic-gate 			(sscanf(value, "%" SCNd64, &v) != 1)) {
669*0Sstevel@tonic-gate 		return (-1);
670*0Sstevel@tonic-gate 	}
671*0Sstevel@tonic-gate 	return (v);
672*0Sstevel@tonic-gate }
673*0Sstevel@tonic-gate 
674*0Sstevel@tonic-gate char *
675*0Sstevel@tonic-gate r_cmd()
676*0Sstevel@tonic-gate {
677*0Sstevel@tonic-gate 
678*0Sstevel@tonic-gate 	if (r_line() == -1) {
679*0Sstevel@tonic-gate 		format_err("can't read command");
680*0Sstevel@tonic-gate 		return (NULL);
681*0Sstevel@tonic-gate 	}
682*0Sstevel@tonic-gate 	return (value);
683*0Sstevel@tonic-gate }
684*0Sstevel@tonic-gate 
685*0Sstevel@tonic-gate int
686*0Sstevel@tonic-gate r_phead()
687*0Sstevel@tonic-gate {
688*0Sstevel@tonic-gate 	int protv;
689*0Sstevel@tonic-gate 	size_t len = strlen(PROTM);
690*0Sstevel@tonic-gate 	size_t errorlen = strlen(RDERR);
691*0Sstevel@tonic-gate 	int i = 0;
692*0Sstevel@tonic-gate 
693*0Sstevel@tonic-gate 	while (i++ < MAX_RETRIES) {
694*0Sstevel@tonic-gate 		if (fgets(line, P_MAXLEN, rstream) == NULL) {
695*0Sstevel@tonic-gate 			format_err("can't read prot. head");
696*0Sstevel@tonic-gate 			return (-1);
697*0Sstevel@tonic-gate 		}
698*0Sstevel@tonic-gate 		len = strlen(line);
699*0Sstevel@tonic-gate 		if (len > P_MAXLEN)
700*0Sstevel@tonic-gate 			continue;
701*0Sstevel@tonic-gate 		if (strcmp(line, PROTM) == 0)
702*0Sstevel@tonic-gate 			break;
703*0Sstevel@tonic-gate 		if (strncmp(line, RDERR, errorlen) == 0) {
704*0Sstevel@tonic-gate 			(void) strcpy(error, line + strlen(RDERR) + 1);
705*0Sstevel@tonic-gate 			return (-1);
706*0Sstevel@tonic-gate 		}
707*0Sstevel@tonic-gate 	}
708*0Sstevel@tonic-gate 	if ((protv = r_value(PROTV)) == -1) {
709*0Sstevel@tonic-gate 		format_err("can't read prot. version");
710*0Sstevel@tonic-gate 		return (-1);
711*0Sstevel@tonic-gate 	}
712*0Sstevel@tonic-gate 	if (protv != PROT_VERSION) {
713*0Sstevel@tonic-gate 		format_err("unsupported prot. version");
714*0Sstevel@tonic-gate 		return (-1);
715*0Sstevel@tonic-gate 	}
716*0Sstevel@tonic-gate 	return (0);
717*0Sstevel@tonic-gate }
718*0Sstevel@tonic-gate 
719*0Sstevel@tonic-gate int
720*0Sstevel@tonic-gate r_lshead()
721*0Sstevel@tonic-gate {
722*0Sstevel@tonic-gate 	int  ret;
723*0Sstevel@tonic-gate 
724*0Sstevel@tonic-gate 	if ((ret = r_value(LISTN)) == -1) {
725*0Sstevel@tonic-gate 		format_err("can't read number of lists");
726*0Sstevel@tonic-gate 		return (-1);
727*0Sstevel@tonic-gate 	}
728*0Sstevel@tonic-gate 	return (ret);
729*0Sstevel@tonic-gate }
730*0Sstevel@tonic-gate 
731*0Sstevel@tonic-gate int
732*0Sstevel@tonic-gate r_lhead(int *type)
733*0Sstevel@tonic-gate {
734*0Sstevel@tonic-gate 
735*0Sstevel@tonic-gate 	if ((*type = r_value(LISTT)) == -1) {
736*0Sstevel@tonic-gate 		format_err("can't read list type");
737*0Sstevel@tonic-gate 		return (-1);
738*0Sstevel@tonic-gate 	}
739*0Sstevel@tonic-gate 	return (r_value(ELEMN));
740*0Sstevel@tonic-gate }
741*0Sstevel@tonic-gate 
742*0Sstevel@tonic-gate int
743*0Sstevel@tonic-gate r_element(char *src, char *elemid)
744*0Sstevel@tonic-gate {
745*0Sstevel@tonic-gate 	int fn, i;
746*0Sstevel@tonic-gate 	ENTRY item, *fitem;
747*0Sstevel@tonic-gate 
748*0Sstevel@tonic-gate 	if (r_line() == -1) {
749*0Sstevel@tonic-gate 		format_err("can't read element id");
750*0Sstevel@tonic-gate 		return (-1);
751*0Sstevel@tonic-gate 	} else {
752*0Sstevel@tonic-gate 		(void) strcpy(elemid, value);
753*0Sstevel@tonic-gate 	}
754*0Sstevel@tonic-gate 	if ((fn = r_value(FILDN)) == -1) {
755*0Sstevel@tonic-gate 		format_err("can't read number of fields");
756*0Sstevel@tonic-gate 		return (-1);
757*0Sstevel@tonic-gate 	}
758*0Sstevel@tonic-gate 	for (i = 0; i < fn; i++) {
759*0Sstevel@tonic-gate 		if (r_line() == -1) {
760*0Sstevel@tonic-gate 			return (-1);
761*0Sstevel@tonic-gate 		} else {
762*0Sstevel@tonic-gate 			item.key = key;
763*0Sstevel@tonic-gate 			if ((fitem = hsearch(item, FIND)) == NULL) {
764*0Sstevel@tonic-gate 				format_err("%s: \"%s\" ",
765*0Sstevel@tonic-gate 						"unknown key ", line);
766*0Sstevel@tonic-gate 				return (-1);
767*0Sstevel@tonic-gate 			}
768*0Sstevel@tonic-gate 			((info_t *)(void *)fitem->data)->
769*0Sstevel@tonic-gate 				format(STR_TO_STRUCT, value, src,
770*0Sstevel@tonic-gate 					((info_t *)(void *)fitem->data)->off);
771*0Sstevel@tonic-gate 			}
772*0Sstevel@tonic-gate 	}
773*0Sstevel@tonic-gate 	return (0);
774*0Sstevel@tonic-gate }
775*0Sstevel@tonic-gate 
776*0Sstevel@tonic-gate int
777*0Sstevel@tonic-gate skip_line()
778*0Sstevel@tonic-gate {
779*0Sstevel@tonic-gate 	if (r_line() == -1) {
780*0Sstevel@tonic-gate 		format_err("can't read element id");
781*0Sstevel@tonic-gate 		return (-1);
782*0Sstevel@tonic-gate 	} else {
783*0Sstevel@tonic-gate 		return (0);
784*0Sstevel@tonic-gate 	}
785*0Sstevel@tonic-gate }
786