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