xref: /onnv-gate/usr/src/cmd/wbem/provider/tools/rds/rdprot.c (revision 6152:60a422e88ea9)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*6152Sak198940  * Common Development and Distribution License (the "License").
6*6152Sak198940  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
21*6152Sak198940 
220Sstevel@tonic-gate /*
23*6152Sak198940  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <search.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate 
320Sstevel@tonic-gate #include <sys/utsname.h>
330Sstevel@tonic-gate #include "rdprot.h"
340Sstevel@tonic-gate #include "rdutil.h"
350Sstevel@tonic-gate /*
360Sstevel@tonic-gate  * This file works out the protocol layer of the bidirectional data interface
370Sstevel@tonic-gate  * between the rds and the client. In the server mode rds writes greetings and
380Sstevel@tonic-gate  * a protocol header to the output stream.
390Sstevel@tonic-gate  * pheader  == { "@RDS-MAG@"  PROTV }
400Sstevel@tonic-gate  * PROTV    == { protocol version }
410Sstevel@tonic-gate  * Then it sends a prompt and waits for command from client.
420Sstevel@tonic-gate  * PROMPT   == { "@RDS@>" }
430Sstevel@tonic-gate  * COMMAND  == { "command"  cmd }
440Sstevel@tonic-gate  * cmd	    == { "-pUuJjS" | "-p" | "-u" | "-U" |
450Sstevel@tonic-gate  *		 "-j" | "-J" | "-S" | "-i100" | "alive"| "exit" }
460Sstevel@tonic-gate  * The answer from rds is always a lists of data. The header of the answer data
470Sstevel@tonic-gate  * contains the number of lists in the package. Each list has a header and
480Sstevel@tonic-gate  * some elements, which have again a header and some fields of data:
490Sstevel@tonic-gate  * answer   == { lshead,  n * list }
500Sstevel@tonic-gate  * lshead   == { number of lists }
510Sstevel@tonic-gate  * list     == { lheader, n * element }
520Sstevel@tonic-gate  * lheader  == { LISTT, ELEMN }
530Sstevel@tonic-gate  * LISTT    == { type of the list }
540Sstevel@tonic-gate  * ELEMN    == { number of elements in the list }
550Sstevel@tonic-gate  * element  == { eheader, field }
560Sstevel@tonic-gate  * eheader  == { ELMID, FILDN }
570Sstevel@tonic-gate  * ELMID    == { element id, like pid, uid, project name }
580Sstevel@tonic-gate  * field    == { KEY, VALUE }
590Sstevel@tonic-gate  * All protocol elements have a key and a value separated by one space.
600Sstevel@tonic-gate  * The value begins after the first space and ends with the new line character.
610Sstevel@tonic-gate  * Protocol keys are: "@RDS-MAG@", PROTV, LISTN,  LISTT, ELEMN ELMID, FILDN,
620Sstevel@tonic-gate  * RDERR. The special key RDERR can occur in any line and indicates that an
630Sstevel@tonic-gate  * error condition occurred, where the VALUE is the error message.
640Sstevel@tonic-gate  */
650Sstevel@tonic-gate 
660Sstevel@tonic-gate static char line[P_MAXLEN];
670Sstevel@tonic-gate static char error[P_MAXLEN];
680Sstevel@tonic-gate static char value[P_MAXVAL];
690Sstevel@tonic-gate static char key[P_MAXKEY];
700Sstevel@tonic-gate 
710Sstevel@tonic-gate static char *nullstr = "";
720Sstevel@tonic-gate static FILE *wstream, *rstream;
730Sstevel@tonic-gate 
740Sstevel@tonic-gate static int format_int64(int, char *, char *, int);
750Sstevel@tonic-gate static int format_int32(int, char *, char *, int);
760Sstevel@tonic-gate static int format_ulong(int, char *, char *, int);
770Sstevel@tonic-gate static int format_float(int, char *, char *, int);
780Sstevel@tonic-gate static int format_double(int, char *, char *, int);
790Sstevel@tonic-gate static int format_string(int, char *, char *, int);
800Sstevel@tonic-gate static int format_timestruc(int, char *, char *, int);
810Sstevel@tonic-gate 
820Sstevel@tonic-gate /*
830Sstevel@tonic-gate  * The kv_pair_t represents an field in a  c-sturcture. An filed
840Sstevel@tonic-gate  * is defined by a key 'field name', format function and an offset
850Sstevel@tonic-gate  * in this structure
860Sstevel@tonic-gate  */
870Sstevel@tonic-gate 
880Sstevel@tonic-gate /*
890Sstevel@tonic-gate  * Array of fields from id_info_t structure, that are sent/received
900Sstevel@tonic-gate  * in a process/user/project utilization list.
910Sstevel@tonic-gate  */
920Sstevel@tonic-gate static kv_pair_t id_stub[] =
930Sstevel@tonic-gate {
940Sstevel@tonic-gate { "id_pid",	{ format_int32, offsetof(id_info_t, id_pid) }},
950Sstevel@tonic-gate { "id_uid",	{ format_int32, offsetof(id_info_t, id_uid) }},
960Sstevel@tonic-gate { "id_projid",	{ format_int32, offsetof(id_info_t, id_projid) }},
970Sstevel@tonic-gate { "id_usr", 	{ format_double, offsetof(id_info_t, id_usr) }},
980Sstevel@tonic-gate { "id_sys", 	{ format_double, offsetof(id_info_t, id_sys) }},
990Sstevel@tonic-gate { "id_ttime", 	{ format_double, offsetof(id_info_t, id_ttime) }},
1000Sstevel@tonic-gate { "id_tpftime", { format_double, offsetof(id_info_t, id_tpftime) }},
1010Sstevel@tonic-gate { "id_dpftime", { format_double, offsetof(id_info_t, id_dpftime) }},
1020Sstevel@tonic-gate { "id_kpftime", { format_double, offsetof(id_info_t, id_kpftime) }},
1030Sstevel@tonic-gate { "id_lck", 	{ format_double, offsetof(id_info_t, id_lck) }},
1040Sstevel@tonic-gate { "id_slp", 	{ format_double, offsetof(id_info_t, id_slp) }},
1050Sstevel@tonic-gate { "id_lat", 	{ format_double, offsetof(id_info_t, id_lat) }},
1060Sstevel@tonic-gate { "id_stime", 	{ format_double, offsetof(id_info_t, id_stime) }},
1070Sstevel@tonic-gate { "id_minf", 	{ format_int64, offsetof(id_info_t, id_minf) }},
1080Sstevel@tonic-gate { "id_majf", 	{ format_int64, offsetof(id_info_t, id_majf) }},
1090Sstevel@tonic-gate { "id_nswap", 	{ format_int64, offsetof(id_info_t, id_nswap) }},
1100Sstevel@tonic-gate { "id_inblk", 	{ format_int64, offsetof(id_info_t, id_inblk) }},
1110Sstevel@tonic-gate { "id_oublk", 	{ format_int64, offsetof(id_info_t, id_oublk) }},
1120Sstevel@tonic-gate { "id_msnd", 	{ format_int64, offsetof(id_info_t, id_msnd) }},
1130Sstevel@tonic-gate { "id_mrcv", 	{ format_int64, offsetof(id_info_t, id_mrcv) }},
1140Sstevel@tonic-gate { "id_sigs", 	{ format_int64, offsetof(id_info_t, id_sigs) }},
1150Sstevel@tonic-gate { "id_vctx", 	{ format_int64, offsetof(id_info_t, id_vctx) }},
1160Sstevel@tonic-gate { "id_ictx", 	{ format_int64, offsetof(id_info_t, id_ictx) }},
1170Sstevel@tonic-gate { "id_scl", 	{ format_int64, offsetof(id_info_t, id_scl) }},
1180Sstevel@tonic-gate { "id_ioch", 	{ format_int64, offsetof(id_info_t, id_ioch) }},
1190Sstevel@tonic-gate { "id_hpsize", 	{ format_int64, offsetof(id_info_t, id_hpsize) }},
1200Sstevel@tonic-gate { "id_size", 	{ format_int64, offsetof(id_info_t, id_size) }},
1210Sstevel@tonic-gate { "id_rssize", 	{ format_int64, offsetof(id_info_t, id_rssize) }},
1220Sstevel@tonic-gate { "id_pctcpu", 	{ format_float, offsetof(id_info_t, id_pctcpu) }},
1230Sstevel@tonic-gate { "id_pctmem", 	{ format_float, offsetof(id_info_t, id_pctmem) }},
1240Sstevel@tonic-gate { "id_time", 	{ format_int64, offsetof(id_info_t, id_time) }},
1250Sstevel@tonic-gate { "id_nlwps", 	{ format_int32, offsetof(id_info_t, id_nlwps) }},
1260Sstevel@tonic-gate { "id_timestamp", { format_int64, offsetof(id_info_t, id_timestamp) }},
1270Sstevel@tonic-gate { "id_nproc", 	{ format_int32, offsetof(id_info_t, id_nproc) }},
1280Sstevel@tonic-gate { "id_inpkg", 	{ format_int64, offsetof(id_info_t, id_inpkg) }},
1290Sstevel@tonic-gate { "id_oupkg", 	{ format_int64, offsetof(id_info_t, id_oupkg) }},
1300Sstevel@tonic-gate { "id_name", 	{ format_string, offsetof(id_info_t, id_name) }}
1310Sstevel@tonic-gate };
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate static kv_pair_t lwp_stub[] =
1340Sstevel@tonic-gate {
1350Sstevel@tonic-gate {"li_usage",	{ format_ulong, offsetof(lwp_info_t, li_usr) }},
1360Sstevel@tonic-gate {"li_usr",	{ format_ulong, offsetof(lwp_info_t, li_usr) }},
1370Sstevel@tonic-gate {"li_sys",	{ format_ulong, offsetof(lwp_info_t, li_sys) }},
1380Sstevel@tonic-gate {"li_ttime",	{ format_ulong, offsetof(lwp_info_t, li_ttime) }},
1390Sstevel@tonic-gate {"li_tpftime",	{ format_ulong, offsetof(lwp_info_t, li_tpftime) }},
1400Sstevel@tonic-gate {"li_dpftime",	{ format_ulong, offsetof(lwp_info_t, li_dpftime) }},
1410Sstevel@tonic-gate {"li_kpftime",	{ format_ulong, offsetof(lwp_info_t, li_kpftime) }},
1420Sstevel@tonic-gate {"li_lck",	{ format_ulong, offsetof(lwp_info_t, li_lck) }},
1430Sstevel@tonic-gate {"li_slp",	{ format_ulong, offsetof(lwp_info_t, li_slp) }},
1440Sstevel@tonic-gate {"li_lat",	{ format_ulong, offsetof(lwp_info_t, li_lat) }},
1450Sstevel@tonic-gate {"li_stime",	{ format_ulong, offsetof(lwp_info_t, li_stime) }},
1460Sstevel@tonic-gate {"li_minf",	{ format_ulong, offsetof(lwp_info_t, li_minf) }},
1470Sstevel@tonic-gate {"li_majf",	{ format_ulong, offsetof(lwp_info_t, li_majf) }},
1480Sstevel@tonic-gate {"li_nswap",	{ format_ulong, offsetof(lwp_info_t, li_nswap) }},
1490Sstevel@tonic-gate {"li_inblk",	{ format_ulong, offsetof(lwp_info_t, li_inblk) }},
1500Sstevel@tonic-gate {"li_oublk",	{ format_ulong, offsetof(lwp_info_t, li_oublk) }},
1510Sstevel@tonic-gate {"li_msnd",	{ format_ulong, offsetof(lwp_info_t, li_msnd) }},
1520Sstevel@tonic-gate {"li_mrcv",	{ format_ulong, offsetof(lwp_info_t, li_mrcv) }},
1530Sstevel@tonic-gate {"li_sigs",	{ format_ulong, offsetof(lwp_info_t, li_sigs) }},
1540Sstevel@tonic-gate {"li_vctx",	{ format_ulong, offsetof(lwp_info_t, li_vctx) }},
1550Sstevel@tonic-gate {"li_ictx",	{ format_ulong, offsetof(lwp_info_t, li_ictx) }},
1560Sstevel@tonic-gate {"li_scl",	{ format_ulong, offsetof(lwp_info_t, li_scl) }},
1570Sstevel@tonic-gate {"li_ioch",	{ format_ulong, offsetof(lwp_info_t, li_ioch) }},
1580Sstevel@tonic-gate {"li_hpsize",	{ format_ulong, offsetof(lwp_info_t, li_hpsize) }},
1590Sstevel@tonic-gate {"li_timestamp", { format_ulong, offsetof(lwp_info_t, li_timestamp) }},
1600Sstevel@tonic-gate };
1610Sstevel@tonic-gate 
1620Sstevel@tonic-gate static kv_pair_t lwpinfo_stub[] =
1630Sstevel@tonic-gate {
1640Sstevel@tonic-gate {"lwpr_pid",	{ format_int32, offsetof(lwpinfo_t, pr_pid) }},
1650Sstevel@tonic-gate {"lwpr_lwpid",	{ format_int32, offsetof(lwpinfo_t, pr_lwpid) }},
1660Sstevel@tonic-gate };
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate static kv_pair_t prusage_stub[] =
1690Sstevel@tonic-gate {
1700Sstevel@tonic-gate {"pr_tstamp",	{ format_timestruc, offsetof(prusage_t, pr_tstamp) }},
1710Sstevel@tonic-gate {"pr_create",	{ format_timestruc, offsetof(prusage_t, pr_create) }},
1720Sstevel@tonic-gate {"pr_term",	{ format_timestruc, offsetof(prusage_t, pr_term) }},
1730Sstevel@tonic-gate {"pr_rtime",	{ format_timestruc, offsetof(prusage_t, pr_rtime) }},
1740Sstevel@tonic-gate {"pr_utime",	{ format_timestruc, offsetof(prusage_t, pr_utime) }},
1750Sstevel@tonic-gate {"pr_stime",	{ format_timestruc, offsetof(prusage_t, pr_stime) }},
1760Sstevel@tonic-gate {"pr_ttime",	{ format_timestruc, offsetof(prusage_t, pr_ttime) }},
1770Sstevel@tonic-gate {"pr_tftime",	{ format_timestruc, offsetof(prusage_t, pr_tftime) }},
1780Sstevel@tonic-gate {"pr_dftime",	{ format_timestruc, offsetof(prusage_t, pr_dftime) }},
1790Sstevel@tonic-gate {"pr_kftime",	{ format_timestruc, offsetof(prusage_t, pr_kftime) }},
1800Sstevel@tonic-gate {"pr_ltime",	{ format_timestruc, offsetof(prusage_t, pr_ltime) }},
1810Sstevel@tonic-gate {"pr_slptime",	{ format_timestruc, offsetof(prusage_t, pr_slptime) }},
1820Sstevel@tonic-gate {"pr_wtime",	{ format_timestruc, offsetof(prusage_t, pr_wtime) }},
1830Sstevel@tonic-gate {"pr_stoptime", { format_timestruc, offsetof(prusage_t, pr_stoptime) }},
1840Sstevel@tonic-gate {"pr_minf",	{ format_ulong, offsetof(prusage_t, pr_minf) }},
1850Sstevel@tonic-gate {"pr_majf",	{ format_ulong, offsetof(prusage_t, pr_majf) }},
1860Sstevel@tonic-gate {"pr_nswap",	{ format_ulong, offsetof(prusage_t, pr_nswap) }},
1870Sstevel@tonic-gate {"pr_inblk",	{ format_ulong, offsetof(prusage_t, pr_inblk) }},
1880Sstevel@tonic-gate {"pr_oublk",	{ format_ulong, offsetof(prusage_t, pr_oublk) }},
1890Sstevel@tonic-gate {"pr_msnd",	{ format_ulong, offsetof(prusage_t, pr_msnd) }},
1900Sstevel@tonic-gate {"pr_mrcv",	{ format_ulong, offsetof(prusage_t, pr_mrcv) }},
1910Sstevel@tonic-gate {"pr_sigs",	{ format_ulong, offsetof(prusage_t, pr_sigs) }},
1920Sstevel@tonic-gate {"pr_vctx",	{ format_ulong, offsetof(prusage_t, pr_vctx) }},
1930Sstevel@tonic-gate {"pr_ictx",	{ format_ulong, offsetof(prusage_t, pr_ictx) }},
1940Sstevel@tonic-gate {"pr_sysc",	{ format_ulong, offsetof(prusage_t, pr_sysc) }},
1950Sstevel@tonic-gate {"pr_ioch",	{ format_ulong, offsetof(prusage_t, pr_ioch) }},
1960Sstevel@tonic-gate };
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate /*
1990Sstevel@tonic-gate  * Array of fields in id_info_t structure, that are sent/received
2000Sstevel@tonic-gate  * in an active user list.
2010Sstevel@tonic-gate  */
2020Sstevel@tonic-gate static kv_pair_t usr_stub[] =
2030Sstevel@tonic-gate {
2040Sstevel@tonic-gate { "usr_id", 	{ format_int32, offsetof(id_info_t, id_uid) }},
2050Sstevel@tonic-gate { "usr_name", 	{ format_string, offsetof(id_info_t, id_name) }}
2060Sstevel@tonic-gate };
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate /*
2090Sstevel@tonic-gate  * Array of fields in id_info_t structure, that are sent/received
2100Sstevel@tonic-gate  * in an active project list.
2110Sstevel@tonic-gate  */
2120Sstevel@tonic-gate static kv_pair_t prj_stub[] =
2130Sstevel@tonic-gate {
2140Sstevel@tonic-gate { "prj_id", 	{ format_int32, offsetof(id_info_t, id_projid) }},
2150Sstevel@tonic-gate { "prj_name", 	{ format_string, offsetof(id_info_t, id_name)   }}
2160Sstevel@tonic-gate };
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate /*
2190Sstevel@tonic-gate  * Array of fields in id_info_t structure, that are sent/received
2200Sstevel@tonic-gate  * in a system list.
2210Sstevel@tonic-gate  */
2220Sstevel@tonic-gate static kv_pair_t sys_stub[] =
2230Sstevel@tonic-gate {
2240Sstevel@tonic-gate { "sys_nodename", { format_string, offsetof(sys_info_t, nodename) }},
2250Sstevel@tonic-gate { "sys_name",	{ format_string, offsetof(sys_info_t, name) }}
2260Sstevel@tonic-gate };
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate /*
2290Sstevel@tonic-gate  * Array of fields in id_info_t structure, that are sent/received
2300Sstevel@tonic-gate  * in command.
2310Sstevel@tonic-gate  */
2320Sstevel@tonic-gate static kv_pair_t cmd_stub[] =
2330Sstevel@tonic-gate {
2340Sstevel@tonic-gate { "command",	{ format_int32, offsetof(cmd_t, command) }}
2350Sstevel@tonic-gate };
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate #define	stubsize(stub) ((sizeof (stub))/(sizeof (kv_pair_t)))
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate /*
2400Sstevel@tonic-gate  * Each list type has its own fields description, the list type is
2410Sstevel@tonic-gate  * the index into this table:
2420Sstevel@tonic-gate  * L_PRC_SI - processes statistical information
2430Sstevel@tonic-gate  * L_USR_SI - useres statistical information
2440Sstevel@tonic-gate  * L_PRJ_SI - projects statistical information
2450Sstevel@tonic-gate  * L_AC_USR - active users
2460Sstevel@tonic-gate  * L_AC_PRJ - active projects
2470Sstevel@tonic-gate  * L_SYSTEM - system
2480Sstevel@tonic-gate  */
2490Sstevel@tonic-gate #define	NOF_STUBS   10
2500Sstevel@tonic-gate static stub_t stubs[NOF_STUBS + 1] = {
2510Sstevel@tonic-gate { 0, NULL},
2520Sstevel@tonic-gate { stubsize(id_stub), id_stub},
2530Sstevel@tonic-gate { stubsize(id_stub), id_stub},
2540Sstevel@tonic-gate { stubsize(id_stub), id_stub},
2550Sstevel@tonic-gate { stubsize(usr_stub), usr_stub},
2560Sstevel@tonic-gate { stubsize(prj_stub), prj_stub},
2570Sstevel@tonic-gate { stubsize(sys_stub), sys_stub},
2580Sstevel@tonic-gate { stubsize(cmd_stub), cmd_stub},
2590Sstevel@tonic-gate { stubsize(lwp_stub), lwp_stub},
2600Sstevel@tonic-gate { stubsize(lwpinfo_stub), lwpinfo_stub},
2610Sstevel@tonic-gate { stubsize(prusage_stub), prusage_stub},
2620Sstevel@tonic-gate };
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate /*
2650Sstevel@tonic-gate  * read a protocol line, do some checks and extract its key
2660Sstevel@tonic-gate  * and value part.
2670Sstevel@tonic-gate  */
2680Sstevel@tonic-gate static int
r_line()2690Sstevel@tonic-gate r_line() {
2700Sstevel@tonic-gate 	size_t len;
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	if (fgets(line, P_MAXLEN, rstream) == NULL) {
2730Sstevel@tonic-gate 		format_err("can't read line");
2740Sstevel@tonic-gate 		return (-1);
2750Sstevel@tonic-gate 	}
2760Sstevel@tonic-gate 	len = strlen(line);
2770Sstevel@tonic-gate 	if (len > P_MAXLEN) {
2780Sstevel@tonic-gate 		format_err("%s: \"%s\"", "wrong line length", line);
2790Sstevel@tonic-gate 		return (-1);
2800Sstevel@tonic-gate 	}
2810Sstevel@tonic-gate 	/* carriage return */
2820Sstevel@tonic-gate 	if (len == 1) {
2830Sstevel@tonic-gate 		value[0] = line[0];
2840Sstevel@tonic-gate 		return (0);
2850Sstevel@tonic-gate 	}
2860Sstevel@tonic-gate 	/* see P_MAXKEY and P_MAXVAL for string sizes */
2870Sstevel@tonic-gate 	if (sscanf(line, "%19s %58s", key, value) != 2) {
2880Sstevel@tonic-gate 		format_err("%s: \"%s\"", "wrong line format", line);
2890Sstevel@tonic-gate 		return (-1);
2900Sstevel@tonic-gate 	}
2910Sstevel@tonic-gate 	if (strcmp(key, RDERR) == 0) {
2920Sstevel@tonic-gate 		(void) strcpy(error, line + strlen(RDERR) + 1);
2930Sstevel@tonic-gate 		return (-1);
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 	return (0);
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate #define	STRUCT_TO_STR	1
2990Sstevel@tonic-gate #define	STR_TO_STRUCT	2
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate /*
3020Sstevel@tonic-gate  * if STR_TO_STRUCT read a 64 bit value from string buffer, format it and
3030Sstevel@tonic-gate  * write it into the structure.
3040Sstevel@tonic-gate  * if STRUCT_TO_STR read a 64 bit value from structure and write it as
3050Sstevel@tonic-gate  * a string into buffer.
3060Sstevel@tonic-gate  */
3070Sstevel@tonic-gate static int
format_int64(int set,char * buf,char * strct,int off)3080Sstevel@tonic-gate format_int64(int set, char *buf, char *strct, int off)
3090Sstevel@tonic-gate {
3100Sstevel@tonic-gate 	int64_t v;
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
3130Sstevel@tonic-gate 		if (sscanf(buf, "%" SCNd64, &v) != 1) {
3140Sstevel@tonic-gate 			format_err("%s: \"%s\"", "wrong line format", line);
3150Sstevel@tonic-gate 			return (-1);
3160Sstevel@tonic-gate 		}
3170Sstevel@tonic-gate 		*(int64_t *)(void *)(strct + off) = v;
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	} else {
3200Sstevel@tonic-gate 		v = *((int64_t *)(void *)(strct + off));
3210Sstevel@tonic-gate 		(void) sprintf(buf, "%" PRId64, v);
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 	}
3240Sstevel@tonic-gate 	return (0);
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate /*
3280Sstevel@tonic-gate  * if STR_TO_STRUCT read a 32 bit value from string buffer, format it and
3290Sstevel@tonic-gate  * write it into the structure.
3300Sstevel@tonic-gate  * if STRUCT_TO_STR read a 32 bit value from structure and write it as
3310Sstevel@tonic-gate  * a string into buffer.
3320Sstevel@tonic-gate  */
3330Sstevel@tonic-gate static int
format_int32(int set,char * buf,char * id,int off)3340Sstevel@tonic-gate format_int32(int set, char *buf, char *id, int off)
3350Sstevel@tonic-gate {
3360Sstevel@tonic-gate 	int32_t v;
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
3390Sstevel@tonic-gate 		if (sscanf(buf, "%d", &v) != 1) {
3400Sstevel@tonic-gate 			format_err("%s: \"%s\"", "wrong line format", line);
3410Sstevel@tonic-gate 			return (-1);
3420Sstevel@tonic-gate 		}
3430Sstevel@tonic-gate 		*(int32_t *)(void *)(id + off) = v;
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	} else {
3460Sstevel@tonic-gate 		v = *((int32_t *)(void *)(id + off));
3470Sstevel@tonic-gate 		(void) sprintf(buf, "%d", v);
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	}
3500Sstevel@tonic-gate 	return (0);
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate /*
3540Sstevel@tonic-gate  */
3550Sstevel@tonic-gate static int
format_ulong(int set,char * buf,char * id,int off)3560Sstevel@tonic-gate format_ulong(int set, char *buf, char *id, int off)
3570Sstevel@tonic-gate {
3580Sstevel@tonic-gate 	ulong_t v;
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
3610Sstevel@tonic-gate 		if (sscanf(buf, "%lu", &v) != 1) {
3620Sstevel@tonic-gate 			format_err("%s: \"%s\"", "wrong line format", line);
3630Sstevel@tonic-gate 			return (-1);
3640Sstevel@tonic-gate 		}
3650Sstevel@tonic-gate 		*(ulong_t *)(void *)(id + off) = v;
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 	} else {
3680Sstevel@tonic-gate 		v = *((ulong_t *)(void *)(id + off));
3690Sstevel@tonic-gate 		(void) sprintf(buf, "%ld", v);
3700Sstevel@tonic-gate 
3710Sstevel@tonic-gate 	}
3720Sstevel@tonic-gate 	return (0);
3730Sstevel@tonic-gate }
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate /*
3760Sstevel@tonic-gate  * if STR_TO_STRUCT read a float value from string buffer, format it and
3770Sstevel@tonic-gate  * write it into the structure.
3780Sstevel@tonic-gate  * if STRUCT_TO_STR read a float value from structure and write it as
3790Sstevel@tonic-gate  * a string into buffer.
3800Sstevel@tonic-gate  */
3810Sstevel@tonic-gate static int
format_float(int set,char * buf,char * id,int off)3820Sstevel@tonic-gate format_float(int set, char *buf, char *id, int off)
3830Sstevel@tonic-gate {
3840Sstevel@tonic-gate 	float v;
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
3870Sstevel@tonic-gate 		if (sscanf(buf, "%f", &v) != 1) {
3880Sstevel@tonic-gate 			format_err("%s: \"%s\"", "wrong line format", line);
3890Sstevel@tonic-gate 			return (-1);
3900Sstevel@tonic-gate 		}
3910Sstevel@tonic-gate 		*(float *)(void *)(id + off) = v;
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 	} else {
3940Sstevel@tonic-gate 		v = *((float *)(void *)(id + off));
3950Sstevel@tonic-gate 		(void) sprintf(buf, "%f", v);
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	}
3980Sstevel@tonic-gate 	return (0);
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate /*
4020Sstevel@tonic-gate  * if STR_TO_STRUCT read a double value from string buffer, format it and
4030Sstevel@tonic-gate  * write it into the structure.
4040Sstevel@tonic-gate  * if STRUCT_TO_STR read a double value from structure and write it as
4050Sstevel@tonic-gate  * a string into buffer.
4060Sstevel@tonic-gate  */
4070Sstevel@tonic-gate static int
format_double(int set,char * buf,char * id,int off)4080Sstevel@tonic-gate format_double(int set, char *buf, char *id, int off)
4090Sstevel@tonic-gate {
4100Sstevel@tonic-gate 	double v;
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
4130Sstevel@tonic-gate 		if (sscanf(buf, "%lf", &v) != 1) {
4140Sstevel@tonic-gate 			format_err("wrong line format: \"%s\"", line);
4150Sstevel@tonic-gate 			return (-1);
4160Sstevel@tonic-gate 		}
4170Sstevel@tonic-gate 		*(double *)(void *)(id + off) = v;
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 	} else {
4200Sstevel@tonic-gate 		v = *((double *)(void *)(id + off));
4210Sstevel@tonic-gate 		(void) sprintf(buf, "%f", v);
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	}
4240Sstevel@tonic-gate 	return (0);
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate /*
4280Sstevel@tonic-gate  * if STR_TO_STRUCT read a string from string buffer, format it and
4290Sstevel@tonic-gate  * write it into the structure.
4300Sstevel@tonic-gate  * if STRUCT_TO_STR read a string from structure and write it as
4310Sstevel@tonic-gate  * a string into buffer.
4320Sstevel@tonic-gate  */
4330Sstevel@tonic-gate static int
format_string(int set,char * buf,char * id,int off)4340Sstevel@tonic-gate format_string(int set, char *buf, char *id, int off)
4350Sstevel@tonic-gate {
4360Sstevel@tonic-gate 	char *v;
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
4390Sstevel@tonic-gate 		if ((v = (char *)malloc(strlen(buf) + 1))  != 0) {
4400Sstevel@tonic-gate 			(void) strcpy(v, buf);
4410Sstevel@tonic-gate 		} else {
4420Sstevel@tonic-gate 			v = nullstr;
4430Sstevel@tonic-gate 			return (-1);
4440Sstevel@tonic-gate 		}
4450Sstevel@tonic-gate 		*(char **)(void *)(id + off) = v;
4460Sstevel@tonic-gate 	} else {
4470Sstevel@tonic-gate 		if ((*((char **)(void *)(id + off))) != NULL) {
4480Sstevel@tonic-gate 			(void) snprintf(buf, P_MAXVAL, "%s",
449*6152Sak198940 			    *((char **)(void *)(id + off)));
4500Sstevel@tonic-gate 		}
4510Sstevel@tonic-gate 	}
4520Sstevel@tonic-gate 	return (0);
4530Sstevel@tonic-gate }
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate static int
format_timestruc(int set,char * buf,char * strct,int off)4560Sstevel@tonic-gate format_timestruc(int set, char *buf, char *strct, int off)
4570Sstevel@tonic-gate {
4580Sstevel@tonic-gate 	int64_t v1;
4590Sstevel@tonic-gate 	int64_t v2;
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 	if (set == STR_TO_STRUCT) {
4620Sstevel@tonic-gate 		if (sscanf(buf, "%" SCNd64 ",%" SCNd64, &v1, &v2) != 2) {
4630Sstevel@tonic-gate 			format_err("%s: \"%s\"", "wrong line format", line);
4640Sstevel@tonic-gate 			return (-1);
4650Sstevel@tonic-gate 		}
4660Sstevel@tonic-gate 		((timestruc_t *)(void *)(strct + off))->tv_sec = v1;
4670Sstevel@tonic-gate 		((timestruc_t *)(void *)(strct + off))->tv_nsec = v2;
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate 	} else {
4700Sstevel@tonic-gate 		v1 = ((timestruc_t *)(void *)(strct + off))->tv_sec;
4710Sstevel@tonic-gate 		/*
4720Sstevel@tonic-gate 		 * Since the times in prusage start with millisecond
4730Sstevel@tonic-gate 		 * precision after the micro state accounting was enabled
4740Sstevel@tonic-gate 		 * discard the nano/micro second fraction in the saved
4750Sstevel@tonic-gate 		 * values otherwise we will get negative values in next run.
4760Sstevel@tonic-gate 		 */
4770Sstevel@tonic-gate 		v2 = ((((timestruc_t *)(void *)(strct + off))->tv_nsec) /
4780Sstevel@tonic-gate 			MICROSEC) * MICROSEC;
4790Sstevel@tonic-gate 		(void) sprintf(buf, "%" PRId64 ",%" PRId64, v1, v2);
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	}
4820Sstevel@tonic-gate 	return (0);
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate /*
4860Sstevel@tonic-gate  * A hash table of keys == names and data == { formats and offsets }.
4870Sstevel@tonic-gate  */
4880Sstevel@tonic-gate static int
init_hashtab()4890Sstevel@tonic-gate init_hashtab() {
4900Sstevel@tonic-gate 	ENTRY item;
4910Sstevel@tonic-gate 	int   i, j, size = 0;
4920Sstevel@tonic-gate 
4930Sstevel@tonic-gate 	for (i = 0; i < NOF_STUBS + 1; i++) {
4940Sstevel@tonic-gate 		size += stubs[i].size;
4950Sstevel@tonic-gate 	}
4960Sstevel@tonic-gate 	if (hcreate(size) == 0) {
4970Sstevel@tonic-gate 		format_err("can't create hash table");
4980Sstevel@tonic-gate 		return (-1);
4990Sstevel@tonic-gate 	}
5000Sstevel@tonic-gate 	for (i = 0; i < NOF_STUBS + 1; i++) {
5010Sstevel@tonic-gate 		for (j = 0; j < stubs[i].size; j++) {
5020Sstevel@tonic-gate 			item.key = stubs[i].stub[j].key;
5030Sstevel@tonic-gate 			item.data = (void *) &(stubs[i].stub[j].info);
5040Sstevel@tonic-gate 			if (hsearch(item, ENTER) == NULL) {
5050Sstevel@tonic-gate 				format_err("can't insert into hash table");
5060Sstevel@tonic-gate 				return (-1);
5070Sstevel@tonic-gate 			}
5080Sstevel@tonic-gate 		}
5090Sstevel@tonic-gate 	}
5100Sstevel@tonic-gate 	return (0);
5110Sstevel@tonic-gate }
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate int
open_prot(int fd,char * rw)5140Sstevel@tonic-gate open_prot(int fd, char *rw)
5150Sstevel@tonic-gate {
5160Sstevel@tonic-gate 	if (strcmp(rw, "r") == 0) {
5170Sstevel@tonic-gate 		if ((rstream = fdopen(fd, rw)) == NULL) {
5180Sstevel@tonic-gate 			format_err("can't open read stream");
5190Sstevel@tonic-gate 			return (-1);
5200Sstevel@tonic-gate 		}
5210Sstevel@tonic-gate 		if (init_hashtab() != 0) {
5220Sstevel@tonic-gate 			format_err("can't initialize hashtab");
5230Sstevel@tonic-gate 			return (-1);
5240Sstevel@tonic-gate 		}
5250Sstevel@tonic-gate 	} else if (strcmp(rw, "w") == 0) {
5260Sstevel@tonic-gate 		if ((wstream = fdopen(fd, rw)) == NULL) {
5270Sstevel@tonic-gate 			format_err("can't open write stream");
5280Sstevel@tonic-gate 			return (-1);
5290Sstevel@tonic-gate 		}
5300Sstevel@tonic-gate 	} else {
5310Sstevel@tonic-gate 		format_err("open_prot(), wrong argument  %s", rw);
5320Sstevel@tonic-gate 			return (-1);
5330Sstevel@tonic-gate 	}
5340Sstevel@tonic-gate 	return (0);
5350Sstevel@tonic-gate }
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate void
close_prot()5380Sstevel@tonic-gate close_prot()
5390Sstevel@tonic-gate {
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	(void) fclose(rstream);
5420Sstevel@tonic-gate 	(void) fclose(wstream);
5430Sstevel@tonic-gate 	hdestroy();
5440Sstevel@tonic-gate }
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate /*
5470Sstevel@tonic-gate  * @RDS-MAG@
5480Sstevel@tonic-gate  * PROTV 100
5490Sstevel@tonic-gate  */
5500Sstevel@tonic-gate int
wr_phead()5510Sstevel@tonic-gate wr_phead()
5520Sstevel@tonic-gate {
5530Sstevel@tonic-gate 	(void) fprintf(wstream, "%s\n%s %d\n",
554*6152Sak198940 	    PROTM, PROTV, PROT_VERSION);
5550Sstevel@tonic-gate 	(void) fflush(wstream);
5560Sstevel@tonic-gate 	return (0);
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate /*
5590Sstevel@tonic-gate  * @RDS@> [code]
5600Sstevel@tonic-gate  */
5610Sstevel@tonic-gate int
wr_prompt(char * code)5620Sstevel@tonic-gate wr_prompt(char *code) {
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 	(void) fprintf(wstream, "%s%s\n", PROMPT, code);
5650Sstevel@tonic-gate 	(void) fflush(wstream);
5660Sstevel@tonic-gate 	return (0);
5670Sstevel@tonic-gate }
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate int
wr_lshead(int n)5700Sstevel@tonic-gate wr_lshead(int n)
5710Sstevel@tonic-gate {
5720Sstevel@tonic-gate 	(void) fprintf(wstream, "%s %d\n", LISTN, n);
5730Sstevel@tonic-gate 	(void) fflush(wstream);
5740Sstevel@tonic-gate 	return (0);
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate /*
5780Sstevel@tonic-gate  * LISTT [type]
5790Sstevel@tonic-gate  * ELEMN [n]
5800Sstevel@tonic-gate  */
5810Sstevel@tonic-gate int
wr_lhead(int type,int n)5820Sstevel@tonic-gate wr_lhead(int type, int n)
5830Sstevel@tonic-gate {
5840Sstevel@tonic-gate 	(void) fprintf(wstream, "%s %d\n%s %d\n", LISTT, type, ELEMN, n);
5850Sstevel@tonic-gate 	(void) fflush(wstream);
5860Sstevel@tonic-gate 	return (0);
5870Sstevel@tonic-gate }
5880Sstevel@tonic-gate /*
5890Sstevel@tonic-gate  * ELMID [elemid]
5900Sstevel@tonic-gate  * FILDN [number of elements]
5910Sstevel@tonic-gate  * e.g.
5920Sstevel@tonic-gate  * id_usr 11050000000
5930Sstevel@tonic-gate  * id_sys 7850000000
5940Sstevel@tonic-gate  * id_ttime 0
5950Sstevel@tonic-gate  * id_tpftime 0
5960Sstevel@tonic-gate  *
5970Sstevel@tonic-gate  * Write all fields defined by stub[stubidx]. The src is the source pointer.
5980Sstevel@tonic-gate  * For each element read the key, grab the format function and the offset.
5990Sstevel@tonic-gate  * Read and format the element from the source and write it out as a string.
6000Sstevel@tonic-gate  */
6010Sstevel@tonic-gate int
wr_element(int stubidx,char * src,char * elemid)6020Sstevel@tonic-gate wr_element(int stubidx, char *src, char *elemid)
6030Sstevel@tonic-gate {
6040Sstevel@tonic-gate 	int i;
6050Sstevel@tonic-gate 
6060Sstevel@tonic-gate 	(void) fprintf(wstream, "%s %s\n%s %d\n",
607*6152Sak198940 	    ELMID, elemid, FILDN, stubs[stubidx].size);
6080Sstevel@tonic-gate 	for (i = 0; i < stubs[stubidx].size; i++) {
6090Sstevel@tonic-gate 		stubs[stubidx].stub[i].info.format(STRUCT_TO_STR,
610*6152Sak198940 		    value, src, stubs[stubidx].stub[i].info.off);
6110Sstevel@tonic-gate 		(void) fprintf(wstream, "%s %s\n",
612*6152Sak198940 		    stubs[stubidx].stub[i].key, value);
6130Sstevel@tonic-gate 	}
6140Sstevel@tonic-gate 	(void) fflush(wstream);
6150Sstevel@tonic-gate 	return (0);
6160Sstevel@tonic-gate }
6170Sstevel@tonic-gate 
6180Sstevel@tonic-gate int
wr_string(char * str)6190Sstevel@tonic-gate wr_string(char *str)
6200Sstevel@tonic-gate {
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	(void) fprintf(wstream, "%s", str);
6230Sstevel@tonic-gate 	(void) fflush(wstream);
6240Sstevel@tonic-gate 	return (0);
6250Sstevel@tonic-gate }
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate int
wr_value(char * key,int64_t v)6280Sstevel@tonic-gate wr_value(char *key, int64_t v)
6290Sstevel@tonic-gate {
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	(void) fprintf(wstream, "%s %" PRId64 "\n", key, v);
6320Sstevel@tonic-gate 	(void) fflush(wstream);
6330Sstevel@tonic-gate 	return (0);
6340Sstevel@tonic-gate }
6350Sstevel@tonic-gate /*
6360Sstevel@tonic-gate  * RDERR [err]
6370Sstevel@tonic-gate  */
6380Sstevel@tonic-gate void
wr_error(char * err)6390Sstevel@tonic-gate wr_error(char *err)
6400Sstevel@tonic-gate {
6410Sstevel@tonic-gate 	size_t len = strlen(RDERR + 1);
6420Sstevel@tonic-gate 	if (strlen(err) > P_MAXLEN - len) {
6430Sstevel@tonic-gate 		*(err + P_MAXLEN - len - 4) = '.';
6440Sstevel@tonic-gate 		*(err + P_MAXLEN - len - 3) = '.';
6450Sstevel@tonic-gate 		*(err + P_MAXLEN - len - 2) = '.';
6460Sstevel@tonic-gate 		*(err + P_MAXLEN - len - 1) = 0;
6470Sstevel@tonic-gate 	}
6480Sstevel@tonic-gate 	len = strlen(err) - 1;
649*6152Sak198940 	if (strlen(err) == 0) {
650*6152Sak198940 		return;
651*6152Sak198940 	}
6520Sstevel@tonic-gate 	while (len-- > 0) {
6530Sstevel@tonic-gate 		if (*(err + len) == '\n')
6540Sstevel@tonic-gate 			*(err + len) = ' ';
6550Sstevel@tonic-gate 	}
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 	(void) fprintf(wstream, "%s %s\n", RDERR, err);
6580Sstevel@tonic-gate 	(void) fflush(wstream);
6590Sstevel@tonic-gate }
6600Sstevel@tonic-gate 
6610Sstevel@tonic-gate /*
6620Sstevel@tonic-gate  * read a protocol line, check the key and return the value associated
6630Sstevel@tonic-gate  * with it.
6640Sstevel@tonic-gate  */
6650Sstevel@tonic-gate int64_t
r_value(char * check_key)6660Sstevel@tonic-gate r_value(char *check_key) {
6670Sstevel@tonic-gate 	int64_t v = -1;
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate 	if ((r_line() == -1) ||
6700Sstevel@tonic-gate 			(strcmp(check_key, key) != 0) ||
6710Sstevel@tonic-gate 			(sscanf(value, "%" SCNd64, &v) != 1)) {
6720Sstevel@tonic-gate 		return (-1);
6730Sstevel@tonic-gate 	}
6740Sstevel@tonic-gate 	return (v);
6750Sstevel@tonic-gate }
6760Sstevel@tonic-gate 
6770Sstevel@tonic-gate char *
r_cmd()6780Sstevel@tonic-gate r_cmd()
6790Sstevel@tonic-gate {
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate 	if (r_line() == -1) {
6820Sstevel@tonic-gate 		format_err("can't read command");
6830Sstevel@tonic-gate 		return (NULL);
6840Sstevel@tonic-gate 	}
6850Sstevel@tonic-gate 	return (value);
6860Sstevel@tonic-gate }
6870Sstevel@tonic-gate 
6880Sstevel@tonic-gate int
r_phead()6890Sstevel@tonic-gate r_phead()
6900Sstevel@tonic-gate {
6910Sstevel@tonic-gate 	int protv;
6920Sstevel@tonic-gate 	size_t len = strlen(PROTM);
6930Sstevel@tonic-gate 	size_t errorlen = strlen(RDERR);
6940Sstevel@tonic-gate 	int i = 0;
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 	while (i++ < MAX_RETRIES) {
6970Sstevel@tonic-gate 		if (fgets(line, P_MAXLEN, rstream) == NULL) {
6980Sstevel@tonic-gate 			format_err("can't read prot. head");
6990Sstevel@tonic-gate 			return (-1);
7000Sstevel@tonic-gate 		}
7010Sstevel@tonic-gate 		len = strlen(line);
7020Sstevel@tonic-gate 		if (len > P_MAXLEN)
7030Sstevel@tonic-gate 			continue;
7040Sstevel@tonic-gate 		if (strcmp(line, PROTM) == 0)
7050Sstevel@tonic-gate 			break;
7060Sstevel@tonic-gate 		if (strncmp(line, RDERR, errorlen) == 0) {
7070Sstevel@tonic-gate 			(void) strcpy(error, line + strlen(RDERR) + 1);
7080Sstevel@tonic-gate 			return (-1);
7090Sstevel@tonic-gate 		}
7100Sstevel@tonic-gate 	}
7110Sstevel@tonic-gate 	if ((protv = r_value(PROTV)) == -1) {
7120Sstevel@tonic-gate 		format_err("can't read prot. version");
7130Sstevel@tonic-gate 		return (-1);
7140Sstevel@tonic-gate 	}
7150Sstevel@tonic-gate 	if (protv != PROT_VERSION) {
7160Sstevel@tonic-gate 		format_err("unsupported prot. version");
7170Sstevel@tonic-gate 		return (-1);
7180Sstevel@tonic-gate 	}
7190Sstevel@tonic-gate 	return (0);
7200Sstevel@tonic-gate }
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate int
r_lshead()7230Sstevel@tonic-gate r_lshead()
7240Sstevel@tonic-gate {
7250Sstevel@tonic-gate 	int  ret;
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 	if ((ret = r_value(LISTN)) == -1) {
7280Sstevel@tonic-gate 		format_err("can't read number of lists");
7290Sstevel@tonic-gate 		return (-1);
7300Sstevel@tonic-gate 	}
7310Sstevel@tonic-gate 	return (ret);
7320Sstevel@tonic-gate }
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate int
r_lhead(int * type)7350Sstevel@tonic-gate r_lhead(int *type)
7360Sstevel@tonic-gate {
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate 	if ((*type = r_value(LISTT)) == -1) {
7390Sstevel@tonic-gate 		format_err("can't read list type");
7400Sstevel@tonic-gate 		return (-1);
7410Sstevel@tonic-gate 	}
7420Sstevel@tonic-gate 	return (r_value(ELEMN));
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate int
r_element(char * src,char * elemid)7460Sstevel@tonic-gate r_element(char *src, char *elemid)
7470Sstevel@tonic-gate {
7480Sstevel@tonic-gate 	int fn, i;
7490Sstevel@tonic-gate 	ENTRY item, *fitem;
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 	if (r_line() == -1) {
7520Sstevel@tonic-gate 		format_err("can't read element id");
7530Sstevel@tonic-gate 		return (-1);
7540Sstevel@tonic-gate 	} else {
7550Sstevel@tonic-gate 		(void) strcpy(elemid, value);
7560Sstevel@tonic-gate 	}
7570Sstevel@tonic-gate 	if ((fn = r_value(FILDN)) == -1) {
7580Sstevel@tonic-gate 		format_err("can't read number of fields");
7590Sstevel@tonic-gate 		return (-1);
7600Sstevel@tonic-gate 	}
7610Sstevel@tonic-gate 	for (i = 0; i < fn; i++) {
7620Sstevel@tonic-gate 		if (r_line() == -1) {
7630Sstevel@tonic-gate 			return (-1);
7640Sstevel@tonic-gate 		} else {
7650Sstevel@tonic-gate 			item.key = key;
7660Sstevel@tonic-gate 			if ((fitem = hsearch(item, FIND)) == NULL) {
7670Sstevel@tonic-gate 				format_err("%s: \"%s\" ",
7680Sstevel@tonic-gate 						"unknown key ", line);
7690Sstevel@tonic-gate 				return (-1);
7700Sstevel@tonic-gate 			}
7710Sstevel@tonic-gate 			((info_t *)(void *)fitem->data)->
7720Sstevel@tonic-gate 				format(STR_TO_STRUCT, value, src,
7730Sstevel@tonic-gate 					((info_t *)(void *)fitem->data)->off);
7740Sstevel@tonic-gate 			}
7750Sstevel@tonic-gate 	}
7760Sstevel@tonic-gate 	return (0);
7770Sstevel@tonic-gate }
7780Sstevel@tonic-gate 
7790Sstevel@tonic-gate int
skip_line()7800Sstevel@tonic-gate skip_line()
7810Sstevel@tonic-gate {
7820Sstevel@tonic-gate 	if (r_line() == -1) {
7830Sstevel@tonic-gate 		format_err("can't read element id");
7840Sstevel@tonic-gate 		return (-1);
7850Sstevel@tonic-gate 	} else {
7860Sstevel@tonic-gate 		return (0);
7870Sstevel@tonic-gate 	}
7880Sstevel@tonic-gate }
789