File:  [MW Coherent from dump] / coherent / a / usr / bob / uusrc / src / uuxqt.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:34 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 *  uuxqt.c
 *
 *  Execute local commands spooled by remote sites.
 *
 *  copyright (x) richard h. lamb 1985, 1986, 1987
 *  changes (massive) copyright (c) 1989-1991 by Mark Williams Company
 */

#include <stdio.h>
#include <signal.h>
#include <access.h>
#include <sys/param.h>
#include <sys/stat.h>
#include "dirent.h"
#include "dcp.h"
#include "perm.h"

/*
 *  Global Variables Definitions
 */

char	directory[CTLFLEN];		/* directory for control files	*/
char	xfile[CTLFLEN];			/* "X.*" control file name	*/
FILE	*xfp = NULL;			/* Opened "X.*" FILE pointer	*/
int	processid;			/* process id of this uuxqt	*/
char	line[BUFSIZ];			/* Reading a text line		*/

static	char	command[BUFSIZ], input[60], output[60];
static	char	orig_user[128];
static	char	orig_system[SITELEN+1];
static	char	notifywho[BUFSIZ];
static	char	*allowed;

static	int	failstatus_req;
static	int	succstatus_req;
static	char	errbuf1[BUFSIZ];
static	char	errbuf2[BUFSIZ];
static	char	errbuf3[BUFSIZ];
static	char	reason[80];

static	char	*sep = " \t\n";

char	*rmtname = NULL;
char	**zenvp;			/* Globally Available envp	*/

extern	int optind;
extern	int optopt;
extern	char *optarg;

/*
 *  Extern Function Declarations
 */

extern	char	*strtok();
extern	char	*index();

catchsegv()
{
	fatal("Segmentation violation -- uuxqt aborted");
}

catchterm()
{
	fatal("Local signal -- uuxqt aborted");
}

main(argc, argv, envp)
int argc;
char *argv[], *envp[];
{
	char xqtdir[LOGFLEN];
	char ch;

	while ( (ch=getopt(argc, argv, "x:vV")) != EOF ) {
		switch (ch) {
		case 'x':
			debuglevel = atoi(optarg);
			break;
		case 'v':
		case 'V':
			fatal("uuxqt: Version %s", VERSION);
		case '?':
		default:
			fatal("Improper option usage: %c", optopt);
		}
	}

	bedaemon();	/* detach from controlling terminal */

	zenvp = envp;
	processid = getpid();
	signal(SIGINT,  SIG_IGN);
	signal(SIGHUP,  SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
	signal(SIGTERM, catchterm);
	signal(SIGSEGV, catchsegv);
	open_debug("uuxqt", 0);
	sprintf(xqtdir, "%s/.Xqtdir", SPOOLDIR);
	if (chdir(xqtdir) != 0)
		fatal("can't chdir to: %s", xqtdir);
	dcxqt();
	close_debug();
	exit(0);
}

dcxqt()
{
	if ( lockexist("uuxqt") )
		return;

	if ( lockit("uuxqt") < 0 )
		fatal("Can't lock uuxqt");

	if ( dscan_start() ) {
		while ( dscan() ) {
			if ( xscan_start() ) {
				while ( xscan() )
					dcxqt_work();
				xscan_done();
			}
		}
		dscan_done();
	}
	if ( lockrm("uuxqt") < 0 )
		printmsg(M_LOG, "error unlocking uuxqt");
}

/*
 * Perform the work specified in the "X.*" control file: "xfile"
 */

dcxqt_work()
{
	static	char lastsite[SITELEN] = "\0";
	int	filewait = 0;
	int	removethis = 0;
	int	did_work = 0;
	int	fnd;
	int	execval;
	char	*sp, *osp;

	if ( (xfp=fopen(xfile, "r")) == NULL )
		return;

	reason[0] = input[0] = output[0] = command[0] =
	notifywho[0] = orig_user[0] = orig_system[0] =
	errbuf1[0] = errbuf2[0] = errbuf3[0] = '\0';
	failstatus_req = succstatus_req = fnd = 0;

	while ( fgets(line, BUFSIZ, xfp) != NULL ) {
		sp = strtok(line, sep);
		switch(line[0]) {
		case 'C':
			sp = strtok(NULL, "#\n");
			strcpy(command, sp);
			break;
		case 'F':
			sp = strtok(NULL, sep);
			osp = strtok(NULL, sep);
			sprintf(input,"%s/%s", directory, sp);
			filewait |= isfileabsent(input);
			
			if (filewait == 0 && osp != NULL) {
				if (link(input, osp) == -1) {
					sprintf(errbuf1,
						"Cannot link %s to %s.\n",
						input, osp);
					removethis = 1;
				}
				ul(input);
				input[0] = '\0';
			}
			break;
		case 'I':
			sp = strtok(NULL, sep);
			sprintf(input, "%s/%s", directory, sp);
			break;
		case 'M':
			strcpy(errbuf2,
				"Execute M record not supported");
			break;
		case 'O':
			sp = strtok(NULL, sep);
			sprintf(output, "%s/%s", directory, sp);
			break;
		case 'R':
			strcpy (notifywho, sp = strtok(NULL, sep));
			break;
		case 'U':
			strcpy(orig_user, sp = strtok(NULL, sep));
			strncpy(orig_system,sp=strtok(NULL, sep), SITELEN);
			if ( strncmp(orig_system, lastsite, SITELEN) != 0) {
				strncpy(lastsite, orig_system, SITELEN);
				rmtname = &lastsite[0];
				open_the_logfile("uuxqt");
				plog(M_INFO, "Starting Xqt {%d} (V%s)",
							 processid, VERSION);
				perm_get(orig_system, NULL);
				allowed = perm_value(commands_e);
			}
			break;
		case 'Z':
			failstatus_req = 1;
			break;
		case 'n':
			succstatus_req = 1;
			break;
		case '#':
			break;
		default:
			sprintf(errbuf3, "Unknown command %s", sp);
			break;
		}
	}

	if (strlen(notifywho) < 1)
		strcpy (notifywho, orig_user);
	if (strlen(errbuf1) > 0)
		plog(M_INFO, errbuf1);
	if (strlen(errbuf2) > 0)
		plog(M_INFO, errbuf2);
	if (strlen(errbuf3) > 0)
		plog(M_INFO, errbuf3);

	plog(M_INFO, "%s (<%s >%s)", command, input, output);
	if (removethis) {
		unlinkfiles();
	} else if (filewait)
		plog(M_INFO, "Waiting for files");
	else {
		did_work ++;
		if ( (execval=shell2(command, input, output)) != 0 ) {
			plog(M_INFO, "Command failed, status %d (0x%04x)",
						execval, execval);
			strcpy(reason, "Exit status not zero");
		}
		if (succstatus_req || (failstatus_req && (execval != 0))) 
			remote_status(execval);
		unlinkfiles();
	}
	if (did_work > 0) {
		plog(M_INFO, "Finished {%d}", processid);
	}
	fclose(xfp);
}

unlinkfiles()
{
	char	*osp, *sp;

	rewind(xfp);
	while(fgets(line, BUFSIZ, xfp) != NULL) {
		sp = strtok(line, sep);
		switch(line[0]) {
		case 'C':
			break;
		case 'F':
			sp = strtok(NULL, sep);
			osp = strtok(NULL, sep);
			ul(sp);
			if (osp != NULL) 
				ul(osp);
			break;
		case 'I':case 'M':case 'O':
		case 'U':case 'Z':case 'n':
		default:
			break;
		
		}
	}
	ul(xfile);
	ul(input);
	ul(output);
}

static
ul(fn)
char	*fn;
{
	int	status;
	if (strlen(fn) < 1)
		return;
	status = unlink(fn);	
}

remote_status(val)
int val;
{
	static char pbuf[BUFSIZ];

	FILE	*fmp;
	(void) signal(SIGPIPE, SIG_IGN);
	sprintf(pbuf, "mail -auucp %s!%s ", orig_system, notifywho);
	if ((fmp = popen(pbuf, "w")) == NULL)
		plog(M_INFO, "Cannot send remote status mail");
	else {
		fprintf(fmp, "From: UUXQT V%s\n", VERSION);
		fprintf(fmp, "Subject: UUXQT remote execution status\n\n");
		fprintf(fmp,
			"Command \"%s\" %s.\n\tStatus %d (0x%04x)",
			command, val ? "failed" : "succeeded", val, val);
		if (strlen(reason) > 0)
			fprintf(fmp, "\nReason: %s", reason);
		fprintf(fmp, "\n");
		if (pclose(fmp) != 0)
			plog(M_INFO, "Remote status mail failed");
		plog(M_INFO, "Remote status mail posted to %s!%s",
			orig_system, notifywho);
	}
}

isfileabsent(fn)
char	*fn;
{
	return access(fn, AREAD);
}

#define	MAXENVS	200
static	char *uuenvp[MAXENVS];
static	char uu_user[BUFSIZ];
static	char uu_mach[BUFSIZ];

shell2(command, inname, outname)
char *command;
char *inname;
char *outname;
{
	int	waitstat;
	int	fd, i;
	int	waitpid, cpid;

	if ( !permission(command) ) {
		strcpy(reason, "No permission to execute command");
		plog(M_INFO, "No permission to execute: %s", command);
		if (failstatus_req)
			remote_status(-1);
		return 0;
	}

	sprintf(uu_user, "UU_USER=%s", notifywho);
	sprintf(uu_mach, "UU_MACHINE=%s", orig_system);
	uuenvp[0] = uu_user;
	uuenvp[1] = uu_mach;
	for (i=2; (zenvp[i]!=NULL) && (i<MAXENVS); i++)
		uuenvp[i] = zenvp[i-2];
		if ((cpid = fork()) < 0) {
		plog(M_INFO, "couldn't fork");
		return -1;
	}
	if (cpid == 0) {
		if (strlen(inname) != 0) {
			fd = open(inname, 0);
			dup2(fd, 0);
			if (fd > 0)
				close(fd);
		}
		if (strlen(outname) != 0) {
			fd = creat(outname, 0644);
			dup2(fd, 1);
			if (fd > 1)
				close(fd);
		}
		execle("/bin/sh", "sh", "-c", command, (char *)0, uuenvp);
		plog(M_INFO, "Could not exec /bin/sh");
		exit(0177);
	}
	while (((waitpid = wait(&waitstat)) != cpid) && (waitpid > 0))
		;
	return waitstat;
}

permission(command)
char *command;
{
	char *sp, *cp, *spcp;
	int ok;

	if ( (spcp=index(command, ' ')) != NULL ) 
		*spcp = '\0';

	sp = allowed;
	ok = 0;
	do {
		if ( (cp=index(sp, ':')) != NULL )
			*cp = '\0';
		if ( strcmp(command, sp) == 0 )
			ok = 1;
		if ( cp != NULL )
			*cp++ = ':';
	} while ( !ok && ((sp=cp) != NULL) );

	if ( spcp != NULL )
		*spcp = ' ';
	return(ok);
}

/*
 * Directory Scan Functions:
 *
 * dscan_start()  :  Opens SPOOLDIR to scan for sitename subdirectories
 *		  :  Returns: (1) opened ok, (0) error
 * dscan()	  :  Sets variable "directory" to next directory
 *		  :  Returns: (1) found directory, (0) no directory
 * dscan_done()	  :  Done scanning SPOOLDIR for directories
 *
 * xscan_start()  :  Opens "directory" to scan for "X.*" control files
 *		  :  Returns: (1) opened ok, (0) error
 * xscan()	  :  Sets variable "xfile" to next such "X.*" control file
 *		  :  Returns: (1) found file, (0) no file
 * xscan_done()	  :  Done scanning "directory" for "X.*" control files
 */

static	DIR *sdirp, *xdirp;
extern	DIR *opendir();
extern	struct direct *readdir();

dscan_start()
{
	if ( (sdirp=opendir(SPOOLDIR)) == NULL ) {
		printmsg(M_LOG, "Cannot open spool directory: %s", SPOOLDIR);
		return(0);
	}
	return(1);
}

dscan()
{
	struct stat statbuf;
	struct dirent *mdp;

	while( (mdp=readdir(sdirp)) != NULL ) {
		if ( mdp->d_name[0] == '.' )
			continue;
		sprintf(directory, "%s/%s", SPOOLDIR, mdp->d_name);
		stat(directory, &statbuf);
		if ( statbuf.st_mode & S_IFDIR )
			return(1);
	}
	return(0);
}

dscan_done()
{
	closedir(sdirp);
}

xscan_start()
{
	if ( (xdirp=opendir(directory)) == NULL ) {
		printmsg(M_LOG, "Cannot open spool directory: %s", directory);
		return(0);
	}
	return(1);
}

xscan()
{
	struct stat statbuf;
	struct dirent *xdp;

	while( (xdp=readdir(xdirp)) != NULL ) {
		if ( strncmp(xdp->d_name, "X.", 2) == 0 ) {
			sprintf(xfile, "%s/%s", directory, xdp->d_name);
			stat(xfile, &statbuf);
			if ( statbuf.st_mode & S_IFDIR )
				continue;
			return(1);
		}
	}
	return(0);
}

xscan_done()
{
	closedir(xdirp);
}

fatal(x)
{
	printmsg(M_FATAL, "%r", &x);
	if ( lockexist("uuxqt") )
		lockrm("uuxqt");
	close_logfile();
	close_debug();
	exit(1);
}	

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.