Files
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

718 lines
19 KiB
C

static char sccs_id[] = " @(#)14 1.20 src/bos/usr/lib/nim/methods/m_alloc_ns.c, cmdnim, bos41J, 9511A_all 3/6/95 09:16:32";
/*
* COMPONENT_NAME: CMDNIM
*
* FUNCTIONS: ./usr/lib/nim/methods/m_alloc_ns.c
*
*
* ORIGINS: 27
*
*
* (C) COPYRIGHT International Business Machines Corp. 1993, 1995
* All Rights Reserved
* Licensed Materials - Property of IBM
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
#include "cmdnim_mstr.h"
extern int ch_pdattr_ass();
/*---------------------------- module globals -----------------------------*/
ATTR_ASS_LIST attr_ass;
VALID_ATTR valid_attrs[] =
{
{0, NULL, FALSE, ch_pdattr_ass}
};
char *name=NULL; /* target object name */
char *server=NULL; /* server of nim_script */
char *pathname=NULL; /* pathname of nim_script */
/*---------------------------- parse_args ------------------------------
*
* NAME: parse_args
*
* FUNCTION:
* parses command line arguments
*
* EXECUTION ENVIRONMENT:
*
* NOTES:
* calls nim_error
*
* RECOVERY OPERATION:
*
* DATA STRUCTURES:
* parameters:
* argc = argc from main
* argv = argv from main
* global:
*
* RETURNS: (int)
* SUCCESS = no syntax errors on command line
*
* OUTPUT:
*-----------------------------------------------------------------------------*/
int
parse_args( int argc,
char *argv[] )
{ extern char *optarg;
extern int optind, optopt;
int c;
/* loop through all args */
while ( (c = getopt(argc, argv, "a:q")) != -1 )
{ switch (c)
{
case 'a': /* attribute assignment */
if (! parse_attr_ass( &attr_ass, valid_attrs, optarg, FALSE ) )
nim_error( 0, NULL, NULL, NULL );
break;
case 'q': /* display valid_attrs */
cmd_what( valid_attrs );
exit( 0 );
break;
case ':': /* option is missing a required argument */
nim_error( ERR_MISSING_OPT_ARG, optopt, NULL, NULL );
break;
case '?': /* unknown option */
nim_error( ERR_BAD_OPT, optopt,
MSG_msg(MSG_GENERIC_ALSYNTAX), NULL );
break;
}
}
/* check for errors */
if ( optind == argc )
nim_error( ERR_MISSING_OPERAND, MSG_msg(MSG_OBJ_NAME), NULL, NULL );
else if ( optind < (argc-1) )
nim_error( ERR_SYNTAX, MSG_msg(MSG_GENERIC_ALSYNTAX), NULL, NULL );
name = argv[optind];
/* return */
return( SUCCESS );
} /* end of parse_args */
/*---------------------------- mk_nim_script ------------------------------
*
* NAME: mk_nim_script
*
* FUNCTION:
* constructs a NIM customization script at the specified location
*
* EXECUTION ENVIRONMENT:
*
* NOTES:
* sets errstr on failure
* this function ASSUMES that <client> was retrieved using lag_object
*
* RECOVERY OPERATION:
*
* DATA STRUCTURES:
* parameters:
* client = ptr to nim_object for client
* alloc_list = LIST of res_access structs
* server = name of machine where script is to reside
* location = pathname of the script file
* global:
* attr_ass
*
* RETURNS: (int)
* SUCCESS = script file created
* FAILURE = nothing to do or odm error or rcat error
*
* OUTPUT:
*-----------------------------------------------------------------------------*/
int
mk_nim_script( struct nim_object *client,
LIST *alloc_list,
char *server,
char *location )
{ int installp_flags;
int mk_nimclient;
int instfix = FALSE;
int fixes = FALSE;
int fix_bundle = FALSE;
int installp_bundle = FALSE;
int filesets = FALSE;
int async;
struct res_access *raccess;
struct res_access *simages=NULL;
int cust_present=FALSE;
ODMQUERY
struct nim_pdattr pdattr;
FILE *fp;
int i,j;
int local;
char tmp[MAX_TMP];
char *chmod[] = { CHMOD, "755", location, NULL };
int rc;
FILE *c_stdout = NULL;
struct nim_if nimif;
int pif = -1;
int snm = -1;
int ring_speed = -1;
int cable_type = -1;
NIM_OBJECT( net, ninfo )
char cmd_offset[MAX_TMP];
int debug = FALSE;
char *bundle = NULL;
LIST buns;
int boot_env;
int net_type;
VERBOSE(" building the nim_script\n",NULL,NULL,NULL,NULL)
/* initialize installp_bundle LIST */
if ( get_list_space( &buns, DEFAULT_CHUNK_SIZE, TRUE ) == FAILURE )
return( FAILURE );
/* look for attr flags */
mk_nimclient = (find_attr_ass( &attr_ass, ATTR_NO_NIM_CLIENT ) < 0);
async = (find_attr_ass( &attr_ass, ATTR_ASYNC ) >= 0);
installp_flags = find_attr_ass( &attr_ass, ATTR_INSTALLP_FLAGS );
filesets = (find_attr_ass( &attr_ass, ATTR_INSTALLP_OPTIONS ) >= 0);
fixes = (find_attr_ass( &attr_ass, ATTR_FIXES ) >= 0);
boot_env = ( find_attr_ass( &attr_ass, ATTR_BOOT_ENV ) >= 0 );
if ( boot_env )
strcpy( cmd_offset, SPOT_OFFSET );
else
cmd_offset[0] = NULL_BYTE;
debug = ( find_attr_ass( &attr_ass, ATTR_DEBUG ) >= 0 );
/* reserve the first entry in <buns> for installp_options or fixes */
if (fixes)
{
if ( add_to_LIST( &buns,
attr_value(&attr_ass,ATTR_FIXES) ) == FAILURE )
return( FAILURE );
}
else
{
if ( add_to_LIST( &buns,
attr_value(&attr_ass,ATTR_INSTALLP_OPTIONS) ) == FAILURE )
return( FAILURE );
}
/* look for lpp_source and other cust type resources */
VERBOSE(" looking for cust type resources\n",NULL,NULL,NULL,NULL)
for (i=0; i < alloc_list->num; i++)
{
raccess = (struct res_access *) alloc_list->list[i];
VERBOSE2(" Checking \"%s\"\n",raccess->name,NULL,NULL,NULL)
/* what kind of resource? */
switch (raccess->type)
{
case ATTR_LPP_SOURCE:
VERBOSE2(" found \"%s\"\n",raccess->name,NULL,NULL,NULL)
simages = raccess;
break;
case ATTR_INSTALLP_BUNDLE:
case ATTR_FIX_BUNDLE:
VERBOSE2(" found \"%s\"\n",raccess->name,NULL,NULL,NULL)
if (raccess->type == ATTR_INSTALLP_BUNDLE)
installp_bundle = TRUE;
else if (raccess->type == ATTR_FIX_BUNDLE)
fix_bundle = TRUE;
/* is resource local or remote to the client? */
if ( strcmp( client->name, raccess->server ) == 0 )
{
/* bundle is local to client */
bundle = raccess->location;
}
else
{
/* bundle is remote to client */
bundle = nim_malloc( strlen(raccess->nimif.hostname) +
strlen(raccess->location) + 2 );
sprintf( bundle, "%s:%s", raccess->nimif.hostname,
raccess->location );
}
/* add it to the installp_bundle LIST */
if ( add_to_LIST( &buns, bundle ) == FAILURE )
return( FAILURE );
break;
default:
if ( attr_in_subclass( raccess->type, ATTR_SUBCLASS_CUST ) ) {
VERBOSE2(" found \"%s\"\n",raccess->name,NULL,NULL,NULL)
cust_present = TRUE;
}
break;
} /* switch */
} /* for */
/* check for conflicts (can't mix-n-match fix attributes and */
/* resources with installp attributes and resources). */
if (fixes && filesets)
nim_error( ERR_ATTR_CONFLICT, ATTR_FIXES_T,
ATTR_INSTALLP_OPTIONS_T, NULL);
if (fixes && installp_bundle)
nim_error( ERR_ATTR_RES_CONFLICT, ATTR_FIXES_T,
ATTR_INSTALLP_BUNDLE_T, NULL);
if (fix_bundle && filesets)
nim_error( ERR_ATTR_RES_CONFLICT, ATTR_INSTALLP_OPTIONS_T,
ATTR_FIX_BUNDLE_T, NULL);
if (fix_bundle && installp_bundle)
nim_error( ERR_RES_CONFLICT, ATTR_FIX_BUNDLE_T,
ATTR_INSTALLP_BUNDLE_T, NULL);
instfix = (fixes || fix_bundle);
/* check to see if lpp_source is required */
if ( (mk_nimclient) || (*buns.list[0] != NULL_BYTE) || (buns.num > 1) )
{
if ( simages == NULL )
{
nene( ERR_MISSING_RES, client->name, NULL, NULL );
fprintf( stderr, "\t%s\n", ATTR_LPP_SOURCE_T );
return( FAILURE );
}
else
cust_present = TRUE;
}
/* must have at least one customization resource to continue */
if (mk_nimclient) {
if ( ! cust_present ) {
VERBOSE(" No cust type resources found\n",NULL,NULL,NULL,NULL)
if ( simages != NULL )
ERROR( ERR_NO_FILESETS, NULL, NULL, NULL )
else
ERROR( ERR_NO_CUST, client->name, NULL, NULL )
}
}
/* if we get here, we've got something we need to build a cust script for */
/* where should we build the script? */
if ( strcmp( niminfo.nim_name, server ) == 0 )
{
/* script will be local to current machine */
/* open the FILE now */
if ( (fp = fopen( location, "w" )) == NULL )
ERROR( ERR_ERRNO, NULL, NULL, NULL )
}
else
{
/* script will reside on another machine */
/* open a remote file pointer */
if ( rcat( server, location, &fp ) == FAILURE )
return( FAILURE );
}
/* if going to be NIM client, then need the primary interface info */
if ( mk_nimclient )
{
/* get client's primary IF and convert it */
if ( (pif = find_attr( client, NULL, NULL, 1, ATTR_IF )) < 0 )
ERROR( ERR_OBJ_MISSING_ATTR, PIF, client->name, NULL )
else if ( s2nim_if( client->attrs[pif].value, &nimif ) == FAILURE )
ERROR( ERR_NET_INFO, PIF, client->name, NULL )
else if ( (net_type = a2net_type( nimif.adapter )) == -1 )
ERROR( 0, NULL, NULL, NULL )
/* get object corresponding to the client's primary net */
if ( lag_object( 0, nimif.network, &net, &ninfo ) == FAILURE )
return( FAILURE );
/* find the ATTR_SNM */
if ( (snm = find_attr( net, NULL, NULL, 0, ATTR_SNM )) < 0 )
ERROR( ERR_OBJ_MISSING_ATTR, ATTR_SNM_T, net->name, NULL )
/* ATTR_RING_SPEED required? */
if ( (net_type == ATTR_TOK) &&
((ring_speed =
find_attr( client, NULL, NULL, 1, ATTR_RING_SPEED )) < 0) )
ERROR( ERR_OBJ_MISSING_ATTR, ATTR_RING_SPEED_T, client->name, NULL )
/* ATTR_CABLE_TYPE required? */
if ( (net_type == ATTR_ENT) &&
((cable_type =
find_attr( client, NULL, NULL, 1, ATTR_CABLE_TYPE )) < 0) )
ERROR( ERR_OBJ_MISSING_ATTR, ATTR_CABLE_TYPE_T, client->name, NULL )
}
/* ready to generate the script */
/* header info */
fprintf( fp, "#!/bin/ksh\n\n" );
fprintf( fp, "# %s for %s\n", ATTR_NIM_SCRIPT_T, client->name );
fprintf( fp, "result=%s\n\n", RESULT_SUCCESS_T );
/* include NIM client initialization? */
if ( mk_nimclient )
{
fprintf( fp, MSG_msg (MSG_NIMC_INIT));
if ( debug )
fprintf( fp, "%s%s -v \\\n", SPOT_OFFSET, C_MK_NIMCLIENT );
else
fprintf( fp, "%s%s \\\n", SPOT_OFFSET, C_MK_NIMCLIENT );
fprintf( fp, "\t-a%s=%s \\\n", ATTR_HOSTNAME_T, nimif.hostname );
fprintf( fp, "\t-a%s=%s \\\n", ATTR_IP_T, nimif.ip );
if ( ring_speed >= 0 )
fprintf( fp, "\t-a%s=%s \\\n", ATTR_RING_SPEED_T,
client->attrs[ring_speed].value );
if ( cable_type >= 0 )
fprintf( fp, "\t-a%s=%s \\\n", ATTR_CABLE_TYPE_T,
client->attrs[cable_type].value );
fprintf( fp, "\t-a%s=%s\n", ATTR_SNM_T, net->attrs[snm].value );
/* check the return code */
fprintf( fp, "[[ $? != 0 ]] && result=%s\n\n", RESULT_FAILURE_T );
}
/* NOTE that we want to construct this script such that installp */
/* operations are performed first, then scripts are executed */
/* this is VERY important so that customers can count on the order in */
/* which customization is performed */
/* look for installp resources */
for (i=0; i < alloc_list->num; i++)
{
raccess = (struct res_access *) alloc_list->list[i];
/* is resource local or remote to the client? */
if ( strcmp( client->name, raccess->server ) == 0 )
local = TRUE;
else
local = FALSE;
/* what kind of resource? */
switch (raccess->type)
{
case ATTR_LPP_SOURCE:
if ( (raccess == simages) &&
(mk_nimclient) &&
(*buns.list[0] == NULL_BYTE) &&
(buns.num <= 1) )
/* skip the next part - SIMAGES already being used for */
/* some other purpose */
continue;
/* install using options and/or bundles */
for (j=0; j < buns.num; j++)
{
if ( (j==0) && (*buns.list[0] == NULL_BYTE) )
/* no ATTR_INSTALLP_OPTIONS or IATTR_FIXES were passed */
continue;
fprintf( fp, "# %s=%s\n", ATTR_LPP_SOURCE_T, raccess->name );
if ( debug )
fprintf( fp,"%s%s -v \\\n", cmd_offset, C_INSTALLP );
else
fprintf( fp,"%s%s \\\n", cmd_offset, C_INSTALLP );
/* ATTR_BOOT_ENV specified by caller? */
if ( boot_env )
fprintf( fp, "\t-a%s=yes \\\n", ATTR_BOOT_ENV_T );
if ( j == 0 )
{
/* ATTR_INSTALLP_OPTIONS occupy the first entry in <buns> */
if (instfix)
fprintf( fp, "\t-a%s=\"%s\" \\\n", ATTR_FIXES_T,
buns.list[j] );
else
fprintf( fp, "\t-a%s=\"%s\" \\\n", ATTR_INSTALLP_OPTIONS_T,
buns.list[j] );
}
else
{
if (instfix)
fprintf( fp, "\t-a%s=%s \\\n", ATTR_FIX_BUNDLE_T,
buns.list[j] );
else
fprintf( fp, "\t-a%s=%s \\\n", ATTR_INSTALLP_BUNDLE_T,
buns.list[j] );
}
/* use flags? */
if ( installp_flags >= 0 )
fprintf( fp,"\t-a%s=\"%s\" \\\n", ATTR_INSTALLP_FLAGS_T,
attr_ass.list[ installp_flags ]->value );
if ( local )
fprintf( fp, "\t-a%s=%s\n", ATTR_LPP_SOURCE_T,
raccess->location );
else
fprintf( fp, "\t-a%s=%s:%s\n", ATTR_LPP_SOURCE_T,
raccess->nimif.hostname, raccess->location );
/* check the return code */
fprintf( fp, "[[ $? != 0 ]] && result=%s\n\n", RESULT_FAILURE_T);
}
break;
}
}
/* NOW look for scripts */
for (i=0; i < alloc_list->num; i++)
{
raccess = (struct res_access *) alloc_list->list[i];
/* is resource local or remote to the client? */
if ( strcmp( client->name, raccess->server ) == 0 )
local = TRUE;
else
local = FALSE;
/* what kind of resource? */
switch (raccess->type)
{
case ATTR_SCRIPT:
fprintf( fp, "# %s=%s\n", ATTR_SCRIPT_T, raccess->name );
if ( debug )
fprintf( fp, "%s%s -v \\\n", cmd_offset, C_SCRIPT );
else
fprintf( fp, "%s%s \\\n", cmd_offset, C_SCRIPT );
if ( local )
fprintf( fp, "\t-a%s=\"%s\"\n", ATTR_LOCATION_T,
raccess->location );
else
fprintf( fp, "\t-a%s=\"%s:%s\"\n", ATTR_LOCATION_T,
raccess->nimif.hostname, raccess->location );
/* check the return code */
fprintf( fp, "[[ $? != 0 ]] && result=%s\n\n", RESULT_FAILURE_T );
break;
}
}
if ( async )
{
/* add a call to nimclient so that we know when the script finishes */
fprintf( fp, MSG_msg(MSG_CHG_CONTROL_STATE) );
fprintf( fp, "%s%s -R ${result}\n\n", cmd_offset, NIMCLIENT );
}
/*
* if we dont want to be a nim client after the install
* and this is the boot environment then put a rm /etc/niminfo
* into the /etc/firstboot
*/
if ( !mk_nimclient && boot_env ) {
fprintf( fp, "%s \"%s -f %s\" >> %s\n", ECHO, RM, NIM_ENV_FILE, FIRSTBOOT);
}
/* if any failure occurs within the script, exit non-zero */
fprintf( fp, "[[ ${result} = %s ]] && exit 0 || exit 1\n\n",
RESULT_SUCCESS_T );
/* all done with the FILE */
fclose( fp );
/* set execute perms for the script */
if ( (master_exec( server, &rc, &c_stdout, chmod ) == FAILURE) ||
(rc > 0) )
return( FAILURE );
return( SUCCESS );
} /* end of mk_nim_script */
/*---------------------------- undo ------------------------------
*
* NAME: undo
*
* FUNCTION:
* backs out changes made by alloc_nimscript
*
* EXECUTION ENVIRONMENT:
*
* NOTES:
* calls nim_error
*
* RECOVERY OPERATION:
*
* DATA STRUCTURES:
* parameters:
* errno = err_code
* str1 = err str1
* str2 = err str2
* str3 = err str3
* global:
* server
* pathname
*
* RETURNS: (void)
*
* OUTPUT:
*-----------------------------------------------------------------------------*/
void
undo( int errno,
char *str1,
char *str2,
char *str3 )
{ int rc;
FILE *c_stdout=NULL;
char *args[] = { RM, "-f", pathname, NULL };
disable_err_sig();
/* initialize the errstr */
if ( errno > 0 )
errstr( errno, str1, str2, str3 );
protect_errstr = TRUE;
/* remove nim_script if it was created */
if ( (server != NULL) && (pathname != NULL) )
master_exec( server, &rc, &c_stdout, args );
/* exit with error */
nim_error( 0, NULL, NULL, NULL );
} /* end of undo */
/*------------------------- alloc_nimscript -------------------------
*
* NAME: alloc_nimscript
*
* FUNCTION:
* creates a nim_script for the specified client
*
* EXECUTION ENVIRONMENT:
*
* NOTES:
* calls nim_error
*
* RECOVERY OPERATION:
*
* DATA STRUCTURES:
* parameters:
* global:
* name
*
* RETURNS: (int)
* SUCCESS = boot resource allocated
* FAILURE = error encountered
*
* OUTPUT:
* writes nim_script location to stdout
*-----------------------------------------------------------------------------*/
int
alloc_nimscript()
{ NIM_OBJECT( client, cinfo )
NIM_OBJECT( res, rinfo )
LIST list;
int i,j;
char *server;
char *location;
struct nim_if nimif;
struct nim_if server_nimif;
int Cstate;
/* get the client's object */
if ( lag_object( 0, name, &client, &cinfo ) == FAILURE )
nim_error( 0, NULL, NULL, NULL );
/* cache the current Cstate (this operation which called us) */
if ( (i = find_attr( client, NULL, NULL, 0, ATTR_CSTATE )) < 0 )
nim_error( ERR_OBJ_MISSING_ATTR, ATTR_CSTATE_T, client->name, NULL );
Cstate = (int) strtol( client->attrs[i].value, NULL, 0 );
/* find the client's PIF */
if ( (i = find_attr( client, NULL, NULL, 1, ATTR_IF )) < 0 )
nim_error( ERR_OBJ_MISSING_ATTR, PIF, client->name, NULL );
/* convert to nim_if */
if ( s2nim_if( client->attrs[i].value, &nimif ) == FAILURE )
nim_error( ERR_NET_INFO, PIF, client->name, NULL );
/* generate a LIST of res_access structs */
if ( LIST_res_access( client, &list ) == FAILURE )
nim_error( 0, NULL, NULL, NULL );
/* get the nim_script object */
if ( lag_object( 0, ATTR_NIM_SCRIPT_T, &res, &rinfo ) == FAILURE )
nim_error( 0, NULL, NULL, NULL );
/* get the server & location of the nim_script (right now, it's the master */
if ( (i = find_attr( res, NULL, NULL, 0, ATTR_SERVER )) < 0 )
nim_error( ERR_OBJ_MISSING_ATTR, ATTR_SERVER_T, res->name, NULL );
else if ( (j = find_attr( res, NULL, NULL, 0, ATTR_LOCATION )) < 0 )
nim_error( ERR_OBJ_MISSING_ATTR, ATTR_LOCATION_T, res->name, NULL );
server = res->attrs[i].value;
location = res->attrs[j].value;
/* construct the pathname of the client's nim_script */
pathname = nim_malloc( strlen(location) + strlen(client->name) + 9 );
sprintf( pathname, "%s/%s.script", location, client->name );
VERBOSE(" nim_script pathname is %s:%s\n",server,pathname,NULL,NULL)
/* allocation checks */
if ( ok_to_allocate( client, nimif.network, res, &server_nimif ) == FAILURE )
nim_error( 0, NULL, NULL, NULL );
/* construct the client's nim_script */
if ( mk_nim_script( client, &list, server, pathname ) == FAILURE )
{
/* if the calling operation is bos_inst... */
if ( Cstate == STATE_BOS_INST )
{
/* ignore certain errors */
if ( (niminfo.errno == ERR_NO_FILESETS) ||
(niminfo.errno == ERR_NO_CUST) )
return( SUCCESS );
}
nim_error( 0, NULL, NULL, NULL );
}
undo_on_interrupt = undo;
/* finish allocation (administrative stuff) */
if ( do_allocation( client, res, pathname, &server_nimif, NULL ) == FAILURE )
undo( 0, NULL, NULL, NULL );
/* success! */
uaf_object( res, &rinfo, FALSE );
undo_on_interrupt = NULL;
return( SUCCESS );
} /* end of alloc_nimscript */
/************************** main ********************************/
main( int argc, char *argv[] )
{
/* initialize NIM environment */
mstr_init( argv[0], ERR_POLICY_METHOD, NULL );
if ( ! get_list_space( &attr_ass, DEFAULT_CHUNK_SIZE, TRUE ) )
nim_error( 0, NULL, NULL, NULL );
/* parse command line */
parse_args( argc, argv );
VERBOSE("m_alloc_ns: allocate a nim_script to %s\n",name,NULL,NULL,NULL)
/* create a nim_script for the specified client */
alloc_nimscript();
exit( 0 );
}