1
0
Files
2022-09-29 17:59:04 +03:00

371 lines
8.5 KiB
C

#define _RPCGEN_CLNT
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/errno.h>
#include <string.h>
#if !SVR4
#include <strings.h>
#endif /* !SVR4 */
#include <stdlib.h>
#include <unistd.h>
#include <sys/fcntl.h>
#include <rpc/rpc.h>
#include <assert.h>
#include <sys/stat.h>
#include <sys/file.h>
#if _IRIX
#include <mntent.h>
#endif /* _IRIX */
#if _SUNOS
#include <sys/mnttab.h>
#endif /* _SUNOS */
#include "nprocess.h"
#include "util.h"
#include "lockprocess.h"
#define OPTSTR "vo:"
#define DEFAULT_PROCS 3
char *Progname = NULL;
int Verbose = 0;
int Quit = 0;
int Alarm = 0;
char *Options[] = {
"procs",
#define OPT_PROCS 0
"time",
#define OPT_TIME 1
NULL
};
extern int errno;
extern char *optarg;
extern int optind;
CLIENT *
server_init( char *hostname, char *dirname )
{
struct servopts sops;
CLIENT *clnt = NULL;
int status;
int *replyp;
assert( valid_addresses( (caddr_t)hostname, 1 ) &&
valid_addresses( (caddr_t)dirname, 1 ) );
if ( clnt = clnt_create( hostname, NPROCESSPROG, NPROCESSVERS_ONE,
"tcp" ) ) {
if (replyp = nprocessproc_reset_1(NULL, clnt)) {
if ( status = *replyp ) {
fprintf( stderr,
"%s: server_init: server reset failed, status = %d\n",
Progname );
clnt_destroy( clnt );
clnt = NULL;
if ( status > 0 ) {
errno = status;
perror( "set_server_opts" );
}
} else {
sops.so_verbose = Verbose;
sops.so_directory = dirname;
if (replyp = nprocessproc_servopts_1(&sops, clnt)) {
if ( status = *replyp ) {
clnt_destroy( clnt );
clnt = NULL;
fprintf( stderr,
"%s: server_init: status = %d\n",
Progname, status );
if ( status > 0 ) {
errno = status;
perror( "set_server_opts" );
}
}
} else {
fprintf(stderr, "%s: unable to set server options\n",
Progname);
status = -1;
}
}
} else {
fprintf(stderr, "%s: unable to reset server\n", Progname);
status = -1;
}
} else {
clnt = NULL;
fprintf( stderr, "%s: server_init: %s\n", Progname,
clnt_spcreateerror( hostname ) );
}
return( clnt );
}
static void
signal_handler(int sig, int code, struct sigcontext *sc)
{
switch (sig) {
case SIGALRM:
Alarm = 1;
break;
default:
printf("signal_handler: stray signal %d code %d\n", sig, code);
case SIGINT:
Quit = 1;
}
}
void
usage(void)
{
(void)fprintf( stderr, "usage: %s [-v] [-o options] [hostname]\n",
Progname );
(void)fprintf( stderr, "available options: hostdir=<pathname>\n");
(void)fprintf( stderr, " dir=<pathname>\n");
(void)fprintf( stderr, " procs=<process count>\n");
}
/*
* starting point
*/
int
main( int argc, char **argv )
{
time_t clock;
proclist_t *plist = NULL;
proclist_t *plp = NULL;
int *resp;
unsigned seconds = 0;
char *token;
int *replyp;
pid_t pid;
int procs = DEFAULT_PROCS;
int status = 0;
char *hostname = NULL;
struct mntent *mnt;
pathstr localpath = NULL;
pathstr remotepath = NULL;
int opt;
CLIENT *clnt;
char *optval;
char *optstr;
Progname = *argv;
while ( (opt = getopt( argc, argv, OPTSTR )) != EOF ) {
switch ( opt ) {
case 'o':
optstr = optarg;
while (*optstr) {
switch (getsubopt(&optstr, Options, &optval)) {
case OPT_PROCS:
procs = atoi(optval);
break;
case OPT_TIME:
if (token = strrchr(optval, ':')) {
*token = '\0';
token++;
seconds = (unsigned)atoi(token);
if (token = strrchr(optval, ':')) {
*token = '\0';
token++;
seconds += ((unsigned)atoi(token) * 60) +
((unsigned)atoi(optval) * 3600);
} else {
seconds += (unsigned)atoi(optval) * 60;
}
} else {
seconds = (unsigned)atoi(optval);
}
break;
default:
fprintf(stderr, "Illegal option %s\n", optval);
usage();
exit(-1);
}
}
break;
case 'v':
Verbose++;
break;
default:
usage();
exit( -1 );
}
}
/*
* if the directory name was specified, chdir to it
*/
if ( optind < argc ) {
localpath = argv[optind];
optind++;
if (chdir( localpath )) {
status = errno;
(void)fprintf( stderr, "%s: unable to change directory to %s: ",
Progname, localpath );
perror( localpath );
return( status );
}
}
/*
* convert the local path name to an absolue path
*/
localpath = absolute_path(NULL);
assert(localpath);
/*
* locate the mount point for the given absolute path
*/
mnt = find_mount_point(localpath);
assert(mnt);
/*
* given the file system name for the mount point, determine the
* host name
*/
remotepath = localpath;
if (optind < argc) {
get_host_info(argv[optind], &hostname, &remotepath);
} else {
get_host_info(mnt->mnt_fsname, &hostname, &remotepath);
}
assert(hostname);
assert(remotepath);
assert(!isfile(remotepath));
assert(!isfile(localpath));
if ( Verbose ) {
printf( "%s: hostname = %s, localpath = %s, remotepath = %s\n",
Progname, hostname, localpath, remotepath );
printf( "%s: %d test processes\n", Progname, procs );
}
if (seconds) {
printf( "%s: test duration will be %d seconds\n", Progname,
seconds );
} else {
printf( "%s: test duration is indefinate\n", Progname );
}
(void)signal(SIGINT, signal_handler);
(void)signal(SIGALRM, signal_handler);
/*
* connect to the server
*/
if ( clnt = server_init( hostname, remotepath ) ) {
/*
* connection established, start the processes on the server
*/
if (replyp = nprocessproc_runprocs_1(&procs, clnt)) {
if (!(status = *replyp)) {
/*
* processes successfully started on the server, now
* start them here
*/
if (procs == 1) {
status = lockprocess(stdout, seconds);
} else {
while (procs--) {
if ( (pid = newprocess(seconds, &plist)) == -1 ) {
/*
* process startup error, kill any already started
*/
status = errno;
while (plp = plist) {
plist = plp->pl_next;
if (kill(plp->pl_pid, SIGINT) == -1) {
fprintf(stderr, "%s: kill(%d, SIGINT): %s",
Progname, (int)plp->pl_pid,
strerror(errno));
}
free(plp);
}
plist = NULL;
/*
* kill the processes on the server
*/
resp = nprocessproc_killprocs_1(NULL, clnt);
if (!resp) {
fprintf( stderr,
"%s: nprocessproc_killprocs_1 returned "
"NULL\n", Progname );
} else if (*resp) {
fprintf(stderr,
"%s: nprocessproc_killprocs_1: %s\n",
Progname, strerror(*resp));
}
return(status);
}
}
/*
* wait for a signal or a process to terminate
*/
if (seconds) {
(void)alarm(seconds/4);
}
status = 0;
while (!Quit && !status) {
status = reap_processes(plist);
if (Alarm) {
Alarm = 0;
clock = time(NULL);
printf("%s\n", ctime(&clock));
(void)signal(SIGALRM, signal_handler);
(void)alarm(seconds/4);
}
}
/*
* kill the server processes and the local processes
*/
resp = nprocessproc_killprocs_1(NULL, clnt);
if (!resp) {
status = -1;
fprintf( stderr, "%s: nprocessproc_killprocs_1 "
"returned NULL\n", Progname );
} else if (status = *resp) {
fprintf(stderr, "%s: nprocessproc_killprocs_1: %s\n",
Progname, strerror(status));
}
/*
* kill any remaining local processes
*/
for (plp = plist; plp; plp = plp->pl_next) {
if (kill(plp->pl_pid, SIGINT) == -1) {
switch (errno) {
case ESRCH:
if (Verbose) {
printf("kill(%d, SIGINT): %s\n",
plp->pl_pid, strerror(errno));
}
break;
default:
fprintf(stderr, "%s: kill(%d, SIGINT): %s",
Progname, (int)plp->pl_pid,
strerror(errno));
}
} else if (Verbose) {
printf("Process %d signalled (SIGINT)\n",
plp->pl_pid);
}
}
/*
* collect process status and messges
*/
while (reap_processes(plist) == 0) ;
}
} else {
fprintf(stderr, "%s: nprocessproc_runprocs_1: %s\n",
Progname, strerror(status));
}
} else {
fprintf(stderr, "%s: nprocessproc_runprocs_1 returned NULL\n",
Progname);
status = -1;
}
if ( !status ) {
printf( "%s: passed\n", Progname );
} else {
printf( "%s: failed\n", Progname );
}
} else {
status = -1;
}
return( status );
}