rdprot.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <search.h>
#include <stdlib.h>
#include "rdprot.h"
#include "rdutil.h"
/*
* This file works out the protocol layer of the bidirectional data interface
* between the rds and the client. In the server mode rds writes greetings and
* a protocol header to the output stream.
* pheader == { "@RDS-MAG@" PROTV }
* PROTV == { protocol version }
* Then it sends a prompt and waits for command from client.
* PROMPT == { "@RDS@>" }
* COMMAND == { "command" cmd }
* cmd == { "-pUuJjS" | "-p" | "-u" | "-U" |
* "-j" | "-J" | "-S" | "-i100" | "alive"| "exit" }
* The answer from rds is always a lists of data. The header of the answer data
* contains the number of lists in the package. Each list has a header and
* some elements, which have again a header and some fields of data:
* answer == { lshead, n * list }
* lshead == { number of lists }
* list == { lheader, n * element }
* lheader == { LISTT, ELEMN }
* LISTT == { type of the list }
* ELEMN == { number of elements in the list }
* element == { eheader, field }
* eheader == { ELMID, FILDN }
* ELMID == { element id, like pid, uid, project name }
* field == { KEY, VALUE }
* All protocol elements have a key and a value separated by one space.
* The value begins after the first space and ends with the new line character.
* Protocol keys are: "@RDS-MAG@", PROTV, LISTN, LISTT, ELEMN ELMID, FILDN,
* RDERR. The special key RDERR can occur in any line and indicates that an
* error condition occurred, where the VALUE is the error message.
*/
static char *nullstr = "";
static int format_int64(int, char *, char *, int);
static int format_int32(int, char *, char *, int);
static int format_ulong(int, char *, char *, int);
static int format_float(int, char *, char *, int);
static int format_double(int, char *, char *, int);
static int format_string(int, char *, char *, int);
static int format_timestruc(int, char *, char *, int);
/*
* The kv_pair_t represents an field in a c-sturcture. An filed
* is defined by a key 'field name', format function and an offset
* in this structure
*/
/*
*/
{
};
{
};
static kv_pair_t lwpinfo_stub[] =
{
};
static kv_pair_t prusage_stub[] =
{
};
/*
* in an active user list.
*/
{
};
/*
* in an active project list.
*/
{
};
/*
* in a system list.
*/
{
};
/*
* in command.
*/
{
};
/*
* Each list type has its own fields description, the list type is
* the index into this table:
* L_PRC_SI - processes statistical information
* L_USR_SI - useres statistical information
* L_PRJ_SI - projects statistical information
* L_AC_USR - active users
* L_AC_PRJ - active projects
* L_SYSTEM - system
*/
#define NOF_STUBS 10
{ 0, NULL},
};
/*
* read a protocol line, do some checks and extract its key
* and value part.
*/
static int
r_line() {
format_err("can't read line");
return (-1);
}
return (-1);
}
/* carriage return */
if (len == 1) {
return (0);
}
/* see P_MAXKEY and P_MAXVAL for string sizes */
return (-1);
}
return (-1);
}
return (0);
}
#define STRUCT_TO_STR 1
#define STR_TO_STRUCT 2
/*
* if STR_TO_STRUCT read a 64 bit value from string buffer, format it and
* write it into the structure.
* if STRUCT_TO_STR read a 64 bit value from structure and write it as
* a string into buffer.
*/
static int
{
int64_t v;
if (set == STR_TO_STRUCT) {
return (-1);
}
} else {
}
return (0);
}
/*
* if STR_TO_STRUCT read a 32 bit value from string buffer, format it and
* write it into the structure.
* if STRUCT_TO_STR read a 32 bit value from structure and write it as
* a string into buffer.
*/
static int
{
int32_t v;
if (set == STR_TO_STRUCT) {
return (-1);
}
} else {
}
return (0);
}
/*
*/
static int
{
ulong_t v;
if (set == STR_TO_STRUCT) {
return (-1);
}
} else {
}
return (0);
}
/*
* if STR_TO_STRUCT read a float value from string buffer, format it and
* write it into the structure.
* if STRUCT_TO_STR read a float value from structure and write it as
* a string into buffer.
*/
static int
{
float v;
if (set == STR_TO_STRUCT) {
return (-1);
}
} else {
}
return (0);
}
/*
* if STR_TO_STRUCT read a double value from string buffer, format it and
* write it into the structure.
* if STRUCT_TO_STR read a double value from structure and write it as
* a string into buffer.
*/
static int
{
double v;
if (set == STR_TO_STRUCT) {
return (-1);
}
} else {
}
return (0);
}
/*
* if STR_TO_STRUCT read a string from string buffer, format it and
* write it into the structure.
* if STRUCT_TO_STR read a string from structure and write it as
* a string into buffer.
*/
static int
{
char *v;
if (set == STR_TO_STRUCT) {
} else {
v = nullstr;
return (-1);
}
} else {
}
}
return (0);
}
static int
{
if (set == STR_TO_STRUCT) {
return (-1);
}
} else {
/*
* Since the times in prusage start with millisecond
* precision after the micro state accounting was enabled
* values otherwise we will get negative values in next run.
*/
}
return (0);
}
/*
* A hash table of keys == names and data == { formats and offsets }.
*/
static int
init_hashtab() {
int i, j, size = 0;
for (i = 0; i < NOF_STUBS + 1; i++) {
}
format_err("can't create hash table");
return (-1);
}
for (i = 0; i < NOF_STUBS + 1; i++) {
format_err("can't insert into hash table");
return (-1);
}
}
}
return (0);
}
int
{
format_err("can't open read stream");
return (-1);
}
if (init_hashtab() != 0) {
format_err("can't initialize hashtab");
return (-1);
}
format_err("can't open write stream");
return (-1);
}
} else {
return (-1);
}
return (0);
}
void
{
hdestroy();
}
/*
* @RDS-MAG@
* PROTV 100
*/
int
wr_phead()
{
return (0);
}
/*
* @RDS@> [code]
*/
int
return (0);
}
int
wr_lshead(int n)
{
return (0);
}
/*
* LISTT [type]
* ELEMN [n]
*/
int
{
return (0);
}
/*
* ELMID [elemid]
* FILDN [number of elements]
* e.g.
* id_usr 11050000000
* id_sys 7850000000
* id_ttime 0
* id_tpftime 0
*
* Write all fields defined by stub[stubidx]. The src is the source pointer.
* For each element read the key, grab the format function and the offset.
* Read and format the element from the source and write it out as a string.
*/
int
{
int i;
}
return (0);
}
int
{
return (0);
}
int
{
return (0);
}
/*
* RDERR [err]
*/
void
{
}
while (len-- > 0) {
}
}
/*
* read a protocol line, check the key and return the value associated
* with it.
*/
int64_t v = -1;
if ((r_line() == -1) ||
return (-1);
}
return (v);
}
char *
r_cmd()
{
if (r_line() == -1) {
format_err("can't read command");
return (NULL);
}
return (value);
}
int
r_phead()
{
int protv;
int i = 0;
while (i++ < MAX_RETRIES) {
format_err("can't read prot. head");
return (-1);
}
continue;
break;
return (-1);
}
}
format_err("can't read prot. version");
return (-1);
}
if (protv != PROT_VERSION) {
format_err("unsupported prot. version");
return (-1);
}
return (0);
}
int
r_lshead()
{
int ret;
format_err("can't read number of lists");
return (-1);
}
return (ret);
}
int
{
format_err("can't read list type");
return (-1);
}
}
int
{
int fn, i;
if (r_line() == -1) {
format_err("can't read element id");
return (-1);
} else {
}
format_err("can't read number of fields");
return (-1);
}
for (i = 0; i < fn; i++) {
if (r_line() == -1) {
return (-1);
} else {
format_err("%s: \"%s\" ",
"unknown key ", line);
return (-1);
}
}
}
return (0);
}
int
{
if (r_line() == -1) {
format_err("can't read element id");
return (-1);
} else {
return (0);
}
}