File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / usr / src / usr.bin / bsc / cmd / batch / bscbatch.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:26:12 2019 UTC (7 years ago) by root
Branches: bsd, MAIN
CVS tags: v121, HEAD
Power 6/32 Unix version 1.21

/*	D.L.Buck and Associates, Inc. - 8/27/84
 *
 *	COPYRIGHT NOTICE:
 *		Copyright c 8/27/84 - An unpublished work by 
 *		D.L.Buck and Associates, Inc.
 *
 *	PROPRIETARY RIGHTS NOTICE:
 *		All rights reserved. This document and program contains
 *		proprietary information of D.L.Buck and Associates,Inc.
 *		of San Jose, California, U.S.A., embodying confidential
 *		information,  ideas, and expressions,  no part of which
 *		may be reproduced, or transmitted in any form or by any
 *		means,  electronic,  mechanical,  or otherwise, without
 *		the written permission of D.L.Buck and Associates, Inc.
 *
 * NAME
 *	bscbatch - BISYNC batch job submission and query
 *
 * SYNOPSIS
 *	bscbatch [-to=hostname] [-copy] [-mail] [-transp] [file ... ]
 *	bscbatch -q[=hostname] [-t=hh[mm]] [-l=lines]
 *
 * DESCRIPTION
 *	bscbatch submits files to the BISYNC daemon (bscd) for transmission to
 *	a host, and searches among files received from a specific host for a
 *	particular user.
 *
 * ALGORITHM
 *	I.Initialize:
 *		A. set default values
 *		B. get user id from /etc/passwd
 *		C. get current directory's path name
 *		D. get command line options
 *		E. if queuing operation
 *			1. get host parameters
 *			2. check command line options against host parameters
 *     II. If queuing operation:
 *		A. open AUDIT file (if audit trail is being kept)
 *		B. if command line is exhausted:
 *			1. get file to queue from stdin
 *			2. make "C" (queue control) file name
 *			3. make "D" (file copy) file name
 *			4. make a copy of stdin file in "D" file name
 *			5. make the queue control file
 *		C. if command line isn't exhausted:
 *			1. while not at end of command line:
 *				a. make sure file's name is full path name
 *				b. check that it exists
 *				c. make "C" (queue control) file name
 *				d. if -copy option set:
 *					i. make "D" (file copy) file name
 *				       ii. make a copy of file in "D" file name
 *				e. make the queue control file
 *		D. if an audit trail is being kept:
 *			1. close the audit file
 *    III. If query operation:
 *		A. change to host spool directory
 *		B. open host spool directory
 *		C. while not finished reading directory and file read has
 *		   an inode > 0:
 *			1. if file's name has PR or PU in it (print or punch
 *			   file):
 *				a. if -age parameter was set:
 *					i. get file's age
 *				       ii. if file's age < age wanted:
 *						continue
 *				b. open file
 *				c. display file's name, when it was received,
 *				   and its size
 *				d. while lines displayed <= -lines parameter:
 *					i. display a line from the file,
 *					   one character at a time; if
 *					   character isn't printable, display
 *					   it in hex, enclosed in angular
 *					   brackets (<%x>).
 *				e. close the file
 *				f. display "Rename? (Y/N): " message
 *				g. get reply
 *				h. if Y, get user's input for renamimg
 *					i. try to open new name
 *				       ii. if new name is an existing file,
 *					   let user choose whether or not to
 *					   overwrite it
 *				      iii. if not an existing file, or okay to
 *					   overwrite, use system call ("mv")
 *					   to rename the file
 *				i. display "Press Return to Continue" message
 *		D. close directory
 */

#include <stdio.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>
#include <ctype.h>
#include "local.h"
#if defined BSD42
#include <sys/time.h>
#else
#include <time.h>
#endif

#define YES 1
#define NO 0
#define PATH "/usr/spool/bscbatch/"
#define LIB "/usr/lib/bscbatch/"

#ifndef lint
static char sccsid[] = "@(#)bscbatch.c	1.14 REL";
#endif

int mail = NO;		/* send mail only if problems occur */
int copy = NO;		/* copy file to send before sending? */
int transp = NO;	/* can host receive transparent data? */
int delete = NO;	/* delete file after sending? */
int queue = YES;	/* queuing or query mode? */
int lines;		/* number of lines to display in query mode */
int pid;		/* contains process id for this process; used to
			   give unique names to control and copy files */
int alpha_ctr;		/* alpha array index; unique letter is part of control
			   and copy file names */
int age;		/* hhmm ; minimum age of received files to display */
int host_transp = YES;	/* can host receive transp data? */

long atol();		/* function converts ascii to long */
long minspace;		/* minimum free blocks required to receive host
			   files or copy files to be sent */
long freespace;		/* # of free blocks left on file system /u */
long time();		/* function returns current time */

FILE *fopen();		/* function opens files */
FILE *fptr;		/* fopen's all-purpose file pointer */
FILE *popen();		/* function creates a pipe between bscbatch and a
			   command to be submitted to the shell for execution.
			   It returns a stream pointer which can be used to
			   read from the command's standard output or write to
			   its standard input. In bscbatch, it'll be used to
			   read in the # of free blocks available, returned by
			   the df command. */
FILE *pptr;		/* the pointer returned by popen */
FILE *aud;		/* the AUDIT file pointer */

char *strcpy();		/* copies strings into specified vars */
char *index();		/* returns a pointer to positions of specified string
			   in specified variable */
char *pos;		/* pointer that index returns */
char *devptr;		/* use to get device for doing minspace check on */
char *strcat();		/* concatenate function */
char *gets();		/* get a string from stdin */
void exit();

char line[300];		/* all-purpose string recepticle */
char dname[15];		/* contains name of device for minspace check */
char sys_string[50];	/* construct commands to submit to the shell via the
			   system command in here */
char pwd[50];		/* contains pathname to this directory */
char path[50];		/* contains host spool directory pathname */

char alpha[27] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";	/* index string for unique
						   spool file names */
char *user;		/* contains user name */
char hostname[20];	/* contains host name */
char libpath[50];	/* path to host's configuration file */

struct stat s;		/* returns pointer to stat structure */

main(argc,argv)
int argc;
char *argv[];
{
	int i = 0;			/* convenient index */

	struct passwd *getpwuid();	/* function returns a pointer to a
					   structure containing /etc/passwd 
					   data */
	struct passwd *uid;		/* pointer that getpwuid() returns */
	char *getlogin();		/* returns pointer to the login name */
/* set default values */
	strcpy(hostname,"default");		/* host default */

/* get user id number from /etc/passwd file. getlogin() returns
   a pointer to the login name in user; getpwuid returns a pointer to the
   structure containing the broken-out field of the login name's entry in
   /etc/passwd */
	user = getlogin();
	if (user == NULL) {
		if ((uid = getpwuid(getuid())) == NULL)	{
			fprintf(stderr,"bscbatch: don't know who you are!\n");
			exit(1);
		}
		user = uid->pw_name;
	}

/* get this directory's pathname */
	fptr = popen("pwd","r");
	fgets(pwd,sizeof pwd-1,fptr);
	pwd[strlen(pwd)-1] = '\0';

/* get options from command line */
	while (++i < argc && argv[i][0] == '-')	{
	/* copy option -- if this is YES, a copy of the file to be transmitted
	   is to be made. That copy will be transmitted to the host, rather
	   than the original. */
		if (strcmp(argv[i],"-copy") == 0)	{
			copy = YES;
			continue;
		}

	/* mail option -- if this is YES, user is to receive mail whether
	   transmission was successful or not */
		if (strcmp(argv[i],"-mail") == 0)	{
			mail = YES;
			continue;
		}

	/* transparent mode option */
		if (strcmp(argv[i],"-transp") == 0)	{
			transp = YES;
			continue;
		}

	/* time option */
		if(strncmp(argv[i],"-t=",3) == 0)	{
			if (argv[i][3] >= '0' && argv[i][3] <= '9')
				age = atoi(&argv[i][3]);
			else	{
				fprintf(stderr,
				"bscbatch: not a number <%s>\n",argv[i]);
				exit(1);
			}
			if (age < 100)
				age *= 100;
			continue;
		}

	/* number of lines to display while searching (lines option) */
		if (strncmp(argv[i],"-l=",3) == 0)	{
			if (argv[i][3] >= '0' && argv[i][3] <= '9')
				lines = atoi(&argv[i][3]);
			else	{
				fprintf(stderr,
				"bscbatch: not a number <%s>\n",argv[i]);
				exit(1);
			}
			continue;
		}
	
	/* host to queue files for, or query spool directory of */
		if (strncmp(argv[i],"-to",3) == 0 ||
		    strncmp(argv[i],"-q",2) == 0)	{
			if ((pos=index(argv[i],'=')) != NULL)	{
				++pos;
				strcpy(hostname,pos);
			}
			queue = (strncmp(argv[i],"-q",2)==0)?NO:YES;
			continue;
		}

	/* if this is a flag, it's gotta be an unrecognized one */
		if (argv[i][0] == '-')	{
			fprintf(stderr,
			"bscbatch: unrecognized option <%s>\n",argv[i]);
			exit(1);
		}
	}

/* check that all flags are valid with the option chosen */
	if (!queue && (copy || mail || transp))	{
		fprintf(stderr,
	"bscbatch: options -copy, -mail, and -transp can't be used with -q\n");
		exit(1);
	}

	if (queue && (lines || age))	{
		fprintf(stderr,
			"bscbatch: options -l and -t can't be used with -to\n");
		exit(1);
	}
/* set-up host options/parameters */
	set_host();

/* do queuing or query */
	queue?do_queue(argc,i,argv):do_query();
}

/* process a file */
char audname[80];	/* temp audit pathname goes here */
char new_audnm[80];	/* real audit pathname goes here */
char auditlock[80];	/* audit lockfile name goes here */

do_queue(args,i,argv)
int args,i;
char *argv[];
{
	FILE *cptr;		/* fopen's general purpose file pointer */

	char fname[100];	/* contains the full data file name */
	char cpyname[100];	/* contains the "D" file name for copy */
	char ctlname[100];	/* queue control file name */


	pid = getpid();		/* get process id and put in pid */

/* open the audit file; if unable to, audit trail not being kept */
	sprintf(audname,"%s/%s",path,"AUDIT");
	if (access(audname,0) >= 0)	{
		sprintf(auditlock,"%s/%s",path,"auditlock");
		if (creat(auditlock,0) < 0)
			bsc_audnm();
		else
			aud = fopen(audname,"a");
	}

	if (i>=args)	/* command line used up; get files from stdin */
	{
		cptr = stdin;
		sprintf(ctlname,"%s/C%c%d",path,alpha[alpha_ctr],pid);

		/* make a copy of stdin in D<alpha><process_id> */
		sprintf(cpyname,"%s/D%c%d",path,alpha[alpha_ctr],pid);
		delete = YES;
		do_copy(cptr,cpyname);
		mkctl(mail,transp,delete,cpyname,ctlname);
	}
	else
	{
		for (;i<args;++i)
		{
			if(argv[i][0] != '/')
				sprintf(fname,"%s/%s",pwd,argv[i]);
			else
				strcpy(fname,argv[i]);

			if ((cptr = fopen(fname,"r")) == NULL)
			{	fprintf(stderr,
				"bscbatch: file <%s> not found\n",fname);
				continue;
			}

			sprintf(ctlname,"%s/C%c%d",path,alpha[alpha_ctr],pid);
			if (copy)
			{	sprintf(cpyname,"%s/D%c%d",path,alpha[alpha_ctr],pid);
				delete = YES;
				do_copy(cptr,cpyname);
				strcpy(fname,cpyname);
			}
			mkctl(mail,transp,delete,fname,ctlname);
			fclose(cptr);
			delete = NO;
			++alpha_ctr;
		}
	}

	go_away();
}

/* do clean-up type stuff and go away */
go_away()
{
	if (aud != NULL)	{
		fclose(aud);
		if (link(audname,new_audnm) >= 0)
			unlink(audname);
		else
			unlink(auditlock);
	}
	exit(1);
}

/* query: display all PR and PU files which are in this directory */
do_query()
{
#if defined BSD42
	DIR *fd;		/* Spool Directory			*/
	struct direct *d;	/* Ptr to Spool directory entry		*/
#else
	int fd;			/* Spool Directory			*/
	struct direct d;	/* Spool Directory Entry		*/
#endif
	int cctr = 0;		/* count # of chars on this line so far */
	int c;			/* temp place in which to test *lptr for
				   isprint and isspace */
	int counter = 0;	/* tracks lines already displayed */
	int fage;		/* age of file to display */
	long fday,currday;
	register char *lptr;	/* for displaying one char at a time */

	struct stat t;		/* function returns a structure which
				   contains the inode data for the specified
				   file. */
	struct tm *lt,*localtime();

	char tstring[21];	/* results of ctime go in here */
	char ans[20];		/* all-purpose answer place */
	char *ctime();

	/* change to directory */
	chdir(path);

	/* open it */
#if defined BSD42
#define	DNAME	d->d_name
	fd = opendir(".");
	while ((d = readdir(fd)) != NULL) {
#else
#define	DNAME	d.d_name
	fd = open(".",0);
	while (read(fd,&d,sizeof d) == sizeof d) {
		if (d.d_ino == 0)
			continue;
#endif

		if (strncmp(DNAME,"PR",2) == 0 ||
		    strncmp(DNAME,"PU",2) == 0)
		{
			stat(DNAME,&t);
			if (age) {
				lt = localtime(&t.st_ctime);
				fage = ((lt->tm_hour) * 100) + (lt->tm_min);

				fday = ((lt->tm_mon) *100L) + (lt->tm_mday);
				lt = localtime((long*)0);
				currday = ((lt->tm_mon) * 100L) + (lt->tm_mday);
				if (fage < age)
					continue;
			}
		/* set default number of lines to display if none specified */
			if (!lines) lines = 20;
			
			if ((fptr = fopen(DNAME,"r")) == NULL)
			{	fprintf(stderr,
				"bscbatch: can't open <%s/%s>\n",
				path,DNAME);
				exit(1);	}

			strcpy(tstring,ctime(&t.st_ctime));
			tstring[19] = '\0';

			/* display file name */
			fprintf(stdout,
			">>>>> File: %s/%s <<<<<\n",path,DNAME);
			fprintf(stdout,
			">>>>> Received: %s ..... Size: %ld bytes <<<<<\n",
			  tstring,t.st_size);
			while(fgets(line,sizeof line-1,fptr) != NULL && 
				counter < lines)	{
			/* display lines from file, one character at a time;
			   skip line[0] and line[1] if line[0] is ESC; means
			   a special print instruction is at line[1]. Print
			   no more than 80 characters on a line. If character 
			   isn't printable, display it in hex enclosed in 
			   angular brackets. */
				lptr = &line[0];
				if (line[0] == '\033' )	/* 033 is ESC */
					lptr = &line[2];
				while (*lptr != '\n' && cctr < 80)	{
					c = *lptr;
					if (!isprint(c) && !isspace(c)) {
						c &= 0xff;
						printf("<%x>",c);
					}
					else
						putc(*lptr,stdout);
					++lptr;
					++cctr;
				}
				putc('\n',stdout);
				cctr = 0;
				++counter;
			}
			
			fclose(fptr);

			/* get response from user before continuing */
			fputs("\n>>>> Rename? (Y/N) :",stdout);
			gets(ans);
			if (ans[0] == 'Y' || ans[0] == 'y')
				rename(DNAME);
			fputs("\n>>>> Press RETURN to continue <<<<",stdout);
			getc(stdin);

			counter = 0;
		}
	}
#if defined BSD42
	closedir(fd);
#else
	close(fd);		/* close directory */
#endif
}

/* rename -- rename a received file */
rename(oldname)
char *oldname;
{
	FILE *nptr;		/* new file's file pointer */
	char testnm[80];	/* get new file name here */
	char newname[80];	/* new name for received file built here */
	char systr[100];	/* string to submit to shell for execution */
	char ans[20];		/* all-purpose reply variable */

	fputs("\n>>>> Enter New File Name: ",stdout);
	gets(testnm);

	if (testnm[0] != '/')	/* put file into user's original directory */
		sprintf(newname,"%s/%s",pwd,testnm);
	else
		strcpy(newname, testnm);

/* try to open newname; if you can, warn the user */
	if ((nptr = fopen(newname,"r")) != NULL)	{
		fclose(nptr);
		fprintf(stderr,"bscbatch: file <%s> exists\n",newname);
		fputs("Overwrite? (Y/N): ",stdout);
		gets(ans);
		if (ans[0] == 'N' || ans[0] == 'n')
			return;
	}

	sprintf(systr,"mv %s %s\n",oldname,newname);
	fprintf(stdout, "\n>>>> Verify move %s to %s (y/n): ", oldname,newname);
	gets(ans);
	if (ans[0] == 'y' || ans[0] == 'Y')
		system(systr);
	
	return;
}

/* create queue control files */
mkctl(ml,trnsp,del,fname,ctlname)
int ml,trnsp,del;
char fname[],ctlname[];
{
	FILE *ctlptr;
	char cline[50];
	char msg[100];		/* message going into audit file */

	long time();
	long currtime;

	struct tm *t;
	struct tm *localtime();

/* all files queued during this session will have the same process id number
   attached to their q-ctl names; use letters of the alphabet to make each
   name unique if open for write not allowed because file name already exists */
	do
		sprintf(ctlname,"%s/C%c%d",path,alpha[alpha_ctr],pid);
	while ((ctlptr = fopen(ctlname,"w")) == NULL && alpha_ctr < 26);

	if (ctlptr == NULL)
	{	fprintf(stderr,
			"bscbatch: can't create <%s>\n",ctlname);	
			go_away();
	}
	
	sprintf(msg,"Queued <%s>, option(s):   ",fname);

/* mail option set -- force mail to be sent to user when file successfully
   transmitted */
	if (ml)
	{	sprintf(cline,"M=%s\n",user);
		fputs(cline,ctlptr);
		strcat(msg,"<mail> ");
	}
	
/* transp option set -- force file to be sent in transparent mode */
	if (trnsp)
	{	sprintf(cline,"T %s\n",fname);
		fputs(cline,ctlptr);
		strcat(msg,"<transparent> ");
	}
	
	else
	{	sprintf(cline,"S %s\n",fname);
		fputs(cline,ctlptr);
	}
	
	if (del)
	{	sprintf(cline,"D %s\n",fname);
		fputs(cline,ctlptr);
		strcat(msg,"<copy> ");
	}

/* update the audit file if audit trail being kept */
	if (aud)	{
		if (!transp && !mail && !copy && !del)
			strcat(msg," <none>");
		
		currtime = time((long *)0);
		t = localtime(&currtime);

		fprintf(aud,
		"%s %s %02d%02d%02d%02d%02d %s\n",
		user,"Q",t->tm_year,(t->tm_mon)+1,
		t->tm_mday,t->tm_hour,t->tm_min,msg);
	}
	
	fclose(ctlptr);
}

/* create a copy of the file to send */
do_copy(fileptr,cpyname)
FILE *fileptr;
char cpyname[];
{
	FILE *dptr;

	char cline[100];

	if ((dptr = fopen(cpyname,"w")) == NULL)
	{	fprintf(stderr,
			"bscbatch: can't create <%s>\n",cpyname);
		go_away();
	}

	while (fgets(cline,100,fileptr) != NULL)
		fputs(cline,dptr);

	fclose(dptr);
}

/* set_host() - do host set-up and option/parameter checking */
set_host()
{
	int linect = 0;			/* keeps track of line being read
					   from host config file */

/* get transparent and minimum space parameters from host config file */
	strcpy(libpath,LIB);
	strcat(libpath,hostname);

	if ((fptr = fopen(libpath,"r")) == NULL)	{
		fprintf(stderr,"bscbatch: host <%s> not known\n",hostname);
		exit(1);
	}

	while (fgets(line,sizeof line,fptr) != NULL)	{
		/* loop to get transparent and minspace parameters */
		++linect;
		if (strncmp(line,"TRANSPARENT=",12) == 0)	{
			pos = &line[12];
			host_transp = strncmp(pos,"YES",3)?NO:YES;
			continue;
		}
		if (strncmp(line,"MINSPACE=",9) == 0)	{
			if ((pos = index(line,',')) == NULL)	{
				fprintf(stderr,
		       "bscbatch: Incorrect parameter usage, line %d in <%s>\n",
				linect,libpath);
				exit(1);
			}
			++pos;
			minspace = atol(pos);
			pos = &line[9];
			devptr = &dname[0];
			while (*pos != ',')
				*devptr++ = *pos++;
			*devptr = '\0';
			continue;
		}
	}

/* check that, if host cannot receive transparent date, the transparent
   option hasn't been set */
	if (transp && (host_transp == NO))	{
		fprintf(stderr,
		"bscbatch: host <%s> cannot receive transparent files\n",
		hostname);
		exit(1);
	}
	
/* check space left in file system / (user area):
   the df command prints the # of free blocks and inodes available on the
   entire system. Since all that's needed here is the # of free blocks in 
   /, the flag -f is used and / is specified. popen creates a pipe between
   bscbatch and the df command, returning a file pointer (pptr) to df's output.
   fgets can then be used to read the string df returns into line and
   the number of free blocks is then extracted. */
	if (queue && minspace)
	{	sprintf(sys_string,"df -f %s\n",dname);
		pptr = popen(sys_string,"r");
		fgets(line,100,pptr);
		freespace = atol(&line[25]);
	}

/* check that, if copy option specified and minspace is set, freespace is
   at least 150% of minspace */
	if (copy && minspace && (freespace < (minspace * 1.5)))	{
		fprintf(stderr,
		"bscbatch: can't copy your files -- file system too full\n");
		exit(1);
	}

/* construct spool pathname, change to it to check validity */
	strcpy(path,PATH);
	strcat(path,hostname);
	stat(path,&s);
	if ((s.st_mode & S_IFMT)!= S_IFDIR)	{
		fprintf(stderr,"bscbatch: <%s> has no spool directory\n",
			hostname);
		exit(1);
	}
}

unix.superglobalmegacorp.com

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