/* ** File name: GETSYI_CLNT_SUBS.C ** ** Copyright (c) 1991, by ** Process Software Corporation ** Framingham, Massachusetts ** ** This file contains functions that are common to all implementations of the ** getsyi client. */ /* ** Include files */ #include #include #include "TCPWARE_INCLUDE:RPC.H" #include "GETSYI.H" #include "GETSYI_DEF.H" /* ** Declare Functions */ longw parse_command_line(); void write_output(); /* ** These macros define the strings "UDP" and "TCP" as integers. */ #define UDP ('U' + ('D' << 8) + ('P' << 16) + 0) #define TCP ('T' + ('C' << 8) + ('P' << 16) + 0) /* ** This macro sets the character pointer x to the address of the string ** containing the parameter's argument. The argument may be specified as ** either: -xargument or -x argument. */ #define get_arg_string( x) \ {if( (*argv)[2]) (x) = *argv+2; \ else if( argc > 1) { argc--; (x) = *++argv;}} /* ** Variables ** ** This is the transport that this RPC call will use. If this value is ** non-zero, then the user cannot specify a transport. We treat this as an ** integer since both of the strings "UDP" and "TCP" are 4 bytes. */ globalref longw transport; globalref char *host; /* host where the server is */ static readonly char INV_PARAM[] = "Invalid parameter: %s\n"; /* **************************************** ** ** Function: parse_command_line() ** ** Abstract: ** This function parses the command line. It is called by all three ** clients. The command line is of the following form: ** ** getsyi [-u|-t] [-d#] [-hhost] [-nnode] code [code...] ** -d# is the optional RPC debugging value to use. ** -hhost is the name of the host on which the server resides. The ** default is the same as the cluster node. If this is not given, then ** the server is assumed to be on this node. ** -nnode is the name of the cluster node about which the information ** is to be obtained. The default is a NULL string. ** ** Specifying the server host or the cluster node more than once is ** invalid. If mulitple debugging values are given, all except the last ** one are ignored. ** ** These two flags apply only to the clnt_call client: ** -u indicates that the client is to use the UDP transport. This is the ** default. ** -t indicates that the client is to use the TCP transport. ** ** code is a string that will be converted to upper case and sent to the ** server. At least one code must be specified, and at most MAX_ITEM_CODES ** may be specified. ** ** Return value: ** A VMS status code. If the status code SS$_BADPARAM is returned, the ** main program displays the correct command format. */ longw parse_command_line( argc, argv, argsp) int argc; char *argv[]; getsyi_args *argsp; { longw debug = 0; /* initial debugging value is 0 */ char *cp; /* temporary pointer */ item *itemp; argsp->gsa_node_name = 0; /* no node name yet */ /* ** This loop is executed until a command line element that does not begin with ** a '-' is found. This is assumed to be the first code (Unless get_arg_string ** handles it.) The first command line element is the filename of the program, ** so it is ignored. */ while( --argc > 0 && **++argv == '-') { switch( (*argv)[1]) { case 'u': /* using UDP transport */ case 'U': if( transport != 0) /* already have a transport */ goto invalid_parameter; transport = UDP; break; case 't': /* using TCP transport */ case 'T': if( transport != 0) /* already have a transport */ goto invalid_parameter; transport = TCP; break; case 'd': /* specifying a debugging value */ case 'D': get_arg_string( cp); if( cp) /* catch the case when -d is entered w/o a # */ sscanf( cp, "%x", &debug); break; case 'h': /* the server's host */ case 'H': if( host != 0) /* already have a host name */ goto invalid_parameter; get_arg_string( host); break; case 'n': /* optional node for info */ case 'N': if( argsp->gsa_node_name != 0) /* already have a node name */ goto invalid_parameter; get_arg_string( argsp->gsa_node_name); break; default: goto invalid_parameter; } } /* ** Assume that everything left on the line is an item code. There must be at ** least 1 item code, but no more than MAX_ITEM_CODES. */ if( argc == 0) return( SS$_BADPARAM); if( argc > MAX_ITEM_CODES) return( SS$_OVRMAXARG); /* ** If the user gave a cluster node name, but no host name, set the host name ** to be the node name. */ if( argsp->gsa_node_name) { if( host == 0) host = argsp->gsa_node_name; } /* ** The user did not give a node name, so set it to a null string (not a NULL ** pointer). If a host name was not given, use the local host name. */ else { if( (argsp->gsa_node_name = get_vm( 1)) == 0) return( SS$_INSFMEM); *argsp->gsa_node_name = '\0'; if( host == 0) { if( (host = get_vm( 256)) == 0) return( SS$_INSFMEM); if( gethostname( host, 256) == 0) { printf( "Local node name is unavailable\n"); return( SS$_NOSUCHNODE); } } } /* ** If the user did not specify a transport, use UDP. */ if( transport == 0) transport = UDP; /* ** If the debugging value is non-zero, set it. */ if( debug) oncrpc_set_char( RPCCHAR__DEBUG, &debug); /* ** The client will use non-privileged ports. */ oncrpc_set_char( RPCCHAR__DEFPORTS, &RPCPORTS__NORMAL); itemp = get_vm( argc * sizeof( item)); if( itemp == 0) return( SS$_INSFMEM); argsp->gsa_item_codes.gsa_item_codes_len = argc; argsp->gsa_item_codes.gsa_item_codes_val = itemp; /* ** Convert the code strings to upper case. Use the same memory that DCL ** assigned for them. */ for( ; argc > 0; --argc, argv++, itemp++) { for( cp = *argv; *cp; cp++) *cp = _toupper( *cp); *itemp = *argv; } return( SS$_NORMAL); invalid_parameter: printf( INV_PARAM, *argv); return( SS$_BADPARAM); } /* end function parse_command_line() */ /* **************************************** ** ** Function: write_output() ** ** Abstract: ** This function displays the output that the server sent to the client. ** The getsyi_res union has two arms, as determined by gsr_status: ** SS$_NORMAL (1): the call completed successfully and the results ** consist of several strings. ** any other value (all even): The call encountered a VMS error. The ** server returned the appropriate status code and the VMS message ** description. A status code of zero indicates that the user ** specified an invalid code. The message indicates which code ** was invalid. */ void write_output( argsp, resultsp) getsyi_args *argsp; getsyi_res *resultsp; { int i; longw no_strings; item *itemp; result *rsltp; itemp = argsp->gsa_item_codes.gsa_item_codes_val; _error( resultsp->gsr_status) { printf( "The server returned error status %u\nThe message is: \"%s\"\n", resultsp->gsr_status, resultsp->getsyi_res_u.gsr_msg); return; } no_strings = resultsp->getsyi_res_u.gsr_info.gsi_results.gsi_results_len; rsltp = resultsp->getsyi_res_u.gsr_info.gsi_results.gsi_results_val; for( i = no_strings; i > 0; --i, itemp++, rsltp++) printf( "%s returned: \"%s\"\n", *itemp, *rsltp); } /* end function write_output() */ /* end file GETSYI_CLNT_SUBS.C */