File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / usr / src / usr.bin / bsc / cmd / batch / bscd.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. - %H%
 *
 *	COPYRIGHT NOTICE:
 *		Copyright c %H% - 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
 *	bscd - BISYNC communications daemon
 *
 * SYNOPSIS
 *	bscd
 *
 * DESCRIPTION
 *	bscd submits files queued by bscbatch to the BISYNC driver (bsc),
 *	which sends them to a specified remote host via 3780 or 2780
 *	protocol over telephone lines. It is started by an entry in
 *	/usr/lib/crontab.
 *
 * ALGORITHM
 *	0. try to create the bsclock file
 *		a. if already there, another bscd is running; exit
 *	1. search all host queues for work
 *	2. for each host having file(s) queued to send:
 *		a. call installation exit "connect"
 *		b. open bsc device
 *		c. set bsc device parameters via ioctl call
 *		d. while there's another queue control file:
 *			  i. open control file
 *			 ii. get control parameters
 *			iii. set bsc device parameters as directed by
 *			     control file via ioctl call
 *			 iv. close control file
 *			  v. open actual file to be sent
 *			 vi. while not eof:
 *				format a block
 *				submit it to the bsc driver via write
 *				if an error is encountered:
 *					close file (host is probably trying
 *						    to send to you)
 *					goto 'e.'
 *
 *			vii. close file
 *		       viii. call installation exit "notefile" if requested by
 *			     control file mail flag
 *			 ix. remove control file if send successful
 *		e. try to receive files:
 *			  i. while not eof:
 *				read a block from bsc device
 *				unformat the block
 *				write it either to a PR or PU file somehow
 *			 ii. call installation exit "asgnfile"
 *			iii. repeat from 'i.' until read times out
 *		f. if another queue control file appeared, go back to step 'd'
 *		g. close device
 *		h. call installation exit "disconnect"
 *		i. unlink bsc lock file
 *	
 *	make note in the AUDIT file of host spool directory of each action
 *	as processing occurs
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/dir.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#include "local.h"
#include <bsc/bscio.h>
#if defined BSD42
#include <sys/time.h>
#else
#include <time.h>
#endif

#define libpath "/usr/lib/bscbatch/"
#define spoolpath "/usr/spool/bscbatch/"
#define YES 1
#define NO 0
#define OK 2
#define GS 0x1d			/* group separator */

#ifndef lint
static char sccsid[] = "%W% %Q%";
#endif
extern int errno;		/* system error numbers get put in here */
extern char *sys_errlist[];	/* Explanatory strings for error numbers */

char hostname[20];		/* contains host name */
char audname[80];		/* temp audit pathname goes here */
char auditlock[80];		/* audit lockfile pathname goes here */
char new_audnm[80];		/* real audit name goes here */
char spool[50];			/* contains host spool directory path */
char hostid[20];		/* host id to check for */
char signon[50];		/* host signon file */
char signoff[50];		/* host signoff file */
char lockfile[50];		/* bsc lock file name */
char emsg[40];			/* contains error message for AUDIT */
char delfile[50];		/* file to delete when through transmitting */
char user[20];			/* user name */
char sys_admin[20] = "/dev/console";		/* system administrator name  
						   for problem mail */
char df_string[40];		/* minspace check command */
char sendfile[50];		/* full name of file to send */
char note[100];			/* mail to system administrator goes in here */
char dname[15];			/* contains name of device to check if
				   MINSPACE parameter set */

char *strcpy();			/* function copies one string to another */
char *strcat();			/* function appends one string to another */
char *index();			/* function looks for one string in another */

int chk_hostid;
int chk_termid;
int blksize;
int primary = BSCPRIM;
int recsize;
int recblk;
int recsep;
int rviab;
int ius;		/* unit separator for 2780 used? */
int pt_to_pt;
int son_file;		/* is there a signon file to send? */
int soff_file;		/* is there a signoff file to send? */
int mail = NO;		/* send mail no matter what? */
int trnsp = NO;		/* force a file to be sent transparent? */
int transp_ok = YES;	/* transparent transmission ok for this host? */
int blocks;		/* tracks number of blocks written to bsc device */
int ascii;		/* ascii or ebcdic data? */
int compress = YES;	/* compress data ? */
int devfd;		/* bsc device file descriptor */
int total_bl = 0;	/* total blocks sent or received */
int ctr = 0;		/* used to supply unique names to received files */
int set_trnsp = NO;	/* have any of sendfile's blocks been sent in
			   transparent mode, if this is a normal file? */

int sigint();		/* signal interrupt routine */
long maxfsize = 0;	/* max size a receive file can be before it must
			   be truncated */
long minspace = 0;	/* minimum space required to receive files from a
			   host */
long atol();		/* converts ascii to long */
char devname[20];
char ctlfile[50];	/* queue control file name */

FILE *fopen();		/* function opens files */
FILE *popen();		/* initiate I/O to form a process */
FILE *aud;		/* host AUDIT file pointer */

struct tm *localtime();	/* function returns current time */
struct tm *t;		/* localtime returns time into here */

struct bscio c_params;	/* current bsc driver parameters */
struct bscio s_params;	/* parameters bsc driver was set with */
long time();
long currtime;
void exit();
#if defined BSD42
DIR *libfd;		/* Host Configuration directory fd	*/
DIR *spoolfd;		/* Spool directory fd			*/
#else
int libfd;		/* host config directory file descriptor */
int spoolfd;		/* spool directory file descriptor */
#endif

main()
{
	int more = YES;
	int contention = NO;	/*contention error encountered? */
	int err;		/* get_err or connect error code */
	int almost_done;	/* are we almost done communicating with
				   this host? */

	long lseek();
#if defined BSD42
	struct direct *dir;	/* points to libpath directory entry	*/
	struct direct *hdir;	/* points to spoolpath directory entry	*/
#else
	struct direct dir;	/* libpath directory entry		*/
	struct direct hdir;	/* spoolpath directory entry		*/
#endif
	struct stat s;		/* points to file status structure */

	char cfg_name[50];	/* contains host configuration file name */
	char line[100];		/* line of file to be sent read in here */
	int lockfd;		/* bsc lock file file descriptor	*/

	FILE *pptr;		/* stream ptr to be used with popen */

	/* catch signals -- if bscd spawned as background process,
	   allow kill -15 (SIGTERM) to nicely make it go away. */
	if (isatty(0))
		signal(SIGINT,sigint);
	else
		signal(SIGTERM,sigint);

	/* 1. search all host queues for work */
#if defined BSD42
	if ((libfd = opendir(libpath)) == NULL) {
#else
	if ((libfd = open(libpath,0)) == -1) {
#endif
		fprintf(stderr,
			"bscd: can't open <%s> configuration directory\n",
			libpath);
		exit(1);
	}

#if defined BSD42
	while ((dir = readdir(libfd)) != NULL)	{
		if (dir->d_name[0] == '.')
			continue;
		strcpy(hostname,dir->d_name);
#else
	while (read(libfd,&dir,sizeof dir) == sizeof dir)	{
		if (dir.d_name[0] == '.' || dir.d_ino == 0)
			continue;
		strcpy(hostname,dir.d_name);
#endif
		sprintf(spool,"%s%s",spoolpath,hostname);

	/* try to access spool directory; if not there, continue */
#if defined BSD42
		if ((spoolfd = opendir(spool)) == NULL) {
#else
		if ((spoolfd = open(spool,0)) == -1) {
#endif
			sprintf(note,
			"bscd <%s>: directory <%s> not readable",
			hostname,spool);
			fputs(note,stderr);
			/* send mail about the problem */
			post();
			continue;
		}

	/* try to access the lock file -- if okay, another bscd is running;
	   abort. */
	sprintf(lockfile,"%s/%s",spool,"bsclock");
		if (access(lockfile,0) == 0) {
			fprintf(stderr,
			"bscd <%s>: another bscd process is currently running\n",
			hostname);
			lockfile[0] = '\0';
			continue;
		}
		/* Create the lock file					*/
		if ( (lockfd = creat(lockfile,0)) < 0) {
			fprintf(stderr,
			"bscd <%s>: can't create %s\n",hostname,lockfile);
			exit(1);
		} else
			close(lockfd);
		/* open the host directory and search for work */
		if (searchq(spoolfd) == NO) {
			quithost();
			continue;
		}

	/* get host configuration parameters */
		sprintf(cfg_name,"%s%s",libpath,hostname);
		get_cnfg(cfg_name);
		
	/* construct AUDIT pathname, open AUDIT file */
		open_audit();

	/* write "ready for connect" msg to AUDIT */
		sprintf (note,"Ready for connect via <%s>",
			 devname);
		write_aud("C",note);

	/* call connect installation exit */
		if (err = connect (hostname, devname)) {
		/* skip this host if there were problems */
			sprintf(note, "Connection failed, <%s>",emsg);
			write_aud("C",note);

		/* send mail about it */
			post();
			quithost();
			continue;
		}

	/* open bsc device */
		if ((devfd = open(devname,2)) == -1)	{
			if (errno == EBUSY) {
				fprintf(stderr,
				"bscd <%s>: <%s> being used.\n",
				hostname, devname);
				sprintf(note,
				"Open failed, device <%s> busy.", devname);
				write_aud("C", note);

			/* send mail about problem */
				post();
				quithost();
				goto Disconnect;
			}

			sprintf(note,
				"Connection failed, %s cannot be opened: %s",
				devname,sys_errlist[errno]);

			fprintf(stderr, "bscd <%s>: %s\n", hostname, note);
		
			/* update AUDIT file with the news */
			write_aud("C",note);

		/* send mail about problem */
			post();
			quithost();
			goto Disconnect;
		}

	/* write "connected" message to AUDIT file */
		strcpy(note,"Connected");
		if (chk_hostid)
			sprintf(note,"%s - host id is %s",note,hostid);

		write_aud("C",note);

	/* set device parameters */
		ioctl(devfd,BSCSET,&s_params);

	/* if a signon file was specified, send it via send_son
	   (send_son.c) */
		if (son_file)	{
			if ((more = send_son(signon)) == NO)	{
				sprintf(note,"Disconnected, <%s>",
				emsg);
				write_aud("D",note);
				goto Disconnect;
			}
		/* if there's a contention problem, abort sending */
			if (c_params.b_flags == BSCONTND) {
				contention = YES;
				goto Receive_Files;
			}
			
			sprintf(note,
			"Transmission of SIGNON file <%s> completed (%d blocks)",
			signon,blocks);
			write_aud("T",note);
			total_bl += blocks;
			blocks = 0;
		}

		almost_done = NO;
Send_Files:	/* get another queue control file while there is one */
#if defined BSD42
		rewinddir(spoolfd);
		while ((hdir = readdir(spoolfd)) != NULL) {
			if (hdir->d_name[0] != 'C')
				continue;
			sprintf(ctlfile,"%s/%s",spool,hdir->d_name);
#else
		lseek(spoolfd,0L,0);
		while (read(spoolfd,&hdir,sizeof hdir) == sizeof hdir)	{
			if (hdir.d_ino == 0 || hdir.d_name[0] != 'C')
				continue;
			sprintf(ctlfile,"%s/%s",spool,hdir.d_name);
#endif

		/* get queue control parameters */
			if (get_params())	/* error		*/
				continue;
		
		/* if no sendfile, look for control file w/sendfile */
			if (!sendfile[0])
				continue;

		/* found something to send; just in case we were sent back
		   here after getting a receive timeout from the host and
		   almost_done is YES, we shall set almost_done back to NO. */
			almost_done = NO;

		/* set secondary ioctl parameters */
			if (trnsp)
				ioctl(devfd,BSCTRNSP,0);

			/* send file */
			if (sendf(sendfile) == -1) {
			/* get_errors determines error msg */
				more = get_errors();

				if (!transp_ok && trnsp)	{
					sprintf(emsg,
		"Attempt to send transparent to non-transparent host <%s>",
					hostname);
					more = NO;
				}

				sprintf(note,
				"bscd <%s> :Transmission of <%s> aborted, <%s>",
				hostname,sendfile,emsg);
				write_aud("S",note);

			/* if we got an rvi abort, remove queue control file
			   (and delfile, if any), and go down to receive */
				if (c_params.b_flags == BSCRVI)	{
					unlink(ctlfile);
					if (delfile)
						unlink(delfile);
					contention = YES;
					goto Receive_Files;
				}

			/* if there's a contention problem, abort sending */
				if (c_params.b_flags == BSCONTND)	{
					contention = YES;
					goto Receive_Files;
				}

			/* send mail about problem */
				post();

				if (more == NO)	{
					sprintf(note,"Disconnected, <%s>",
					emsg);
					write_aud("D",note);
					goto Disconnect;
				} else
					continue;
			}

		/* if send successful and q_ctl mail flag set,
			call installation exit notefile */
		sprintf(note,"bscd: File <%s> sent successfully",sendfile);
		notefile(user,sendfile,note);

		/* unlink q_ctl and delfile */
		unlink(ctlfile);
		if (delfile)
			unlink(delfile);

		/* tell the AUDIT file this file's all done */
			sprintf(note,set_trnsp?
			"Transmission of <%s> completed (transparent,%d blocks)":
			"Transmission of <%s> completed (%d blocks)",
			sendfile,blocks);

			write_aud("S",note);

			total_bl += blocks;
			blocks = 0;
			set_trnsp = NO;
		}	/* End of while read hdir (host spool directory) */

	/* if this isn't the first time we've been to Send_Files,
   we got a receive timeout the last time we were in Receive_Files,
   and there was nothing else to send, then almost_done will
   be set. That means it's time to disconnect; write disconnect message
   and goto Disconnect. */
	if (almost_done == 1) 	{
		sprintf(note,"Disconnected, <Receive idle timeout>");
		write_aud("D",note);
		goto Send_Signoff;
	}

	/* get transmit status and write to AUDIT */
	ioctl(devfd,BSCGET,&c_params);
	sprintf(note,
	"EOT, sent %d blocks, did %d TTDs, had %d NAKs, %d timeouts, %d WACKs",
	total_bl,c_params.b_nttd,c_params.b_nnak,c_params.b_nor,
	c_params.b_nwack);

	write_aud("T",note);

Receive_Files:
	/* try to receive something  (rcvf is receive function) */
	/* first check minimum space in user area if minspace set */
	if (minspace) 	{
		pptr = popen(df_string,"r");
		fgets(line,sizeof line,pptr);
		if (atol(&line[25]) < minspace)	{
			sprintf(note,
			"bscd <%s>: file system <%s> has less than minimum blocks available. Processing aborted.",
			hostname,dname);

			write_aud("D",note);
		/* send mail about it all */
			post();
		
		/* and now, do the disconnect stuff */
			goto Send_Signoff;
		}
	}

	total_bl = 0;
	/* rcvf returns OK (2) if a file was received successfully; 
	   NO (0) if nothing was received;
	   YES (1) if an error was encountered */
	while ((err = rcvf()) == OK || err == NO) {
		if (minspace) 	{
			pptr = popen(df_string,"r");
			fgets(line,sizeof line,pptr);
			if (atol(&line[25]) < minspace)	{
				strcpy(note,
				"Receiving aborted - minimum space unavailable");
				write_aud("D",note);

			/* send mail about it all */
				post();

			}
		}
		if (contention)	
			break;
	}

/* if contention on the line, go back and try to send file again */
	if (contention)	{
		contention = NO;
		goto Send_Files;
	}

	if (err == YES)	{	/* rcvf reported problem */
		get_errors();

	/* if receive timeout, go back to send to check if there's
	   anything else to transmit */
		if (c_params.b_flags == BSCRXTO) {
			almost_done = 1;
		/* update AUDIT with status of receive */
			ioctl(devfd,BSCGET,&c_params);
			sprintf(note,
"EOT, received %d blocks, did %d WACKs and %d NAKs, had %d TTDs, %d overruns",
			total_bl,c_params.b_nwack,c_params.b_nnak,
			c_params.b_nttd,c_params.b_nor);
			write_aud("T",note);

			goto Send_Files;
		}

		sprintf(note,"Receiving aborted, <%s>",emsg);
		write_aud("R",note);
		sprintf(note,"Disconnected, <%s>",emsg);
		write_aud("D",note);
		goto Disconnect;
	}

/* update AUDIT with status of receive */
	ioctl(devfd,BSCGET,&c_params);
	sprintf(note,
"EOT, received %d blocks, did %d WACKs and %d NAKs, had %d TTDs, %d overruns",
	total_bl,c_params.b_nwack,c_params.b_nnak,c_params.b_nttd,
	c_params.b_nor);
	write_aud("T",note);

/* if a new queue control file appeared, go back and send it */
#if defined BSD42
	rewinddir(spoolfd);
#else
	lseek(spoolfd,0L,0);	/* rewind host directory */
#endif
	if (searchq(spoolfd) == YES)
	{	stat(ctlfile,&s);
		if (s.st_size > 0)
			goto Send_Files;
	}

Send_Signoff:
	/* if there's a signoff file, send it (soff_send.c) */
		if (soff_file)	{
			total_bl = 0;
			if ((more = soff_send(signoff)) == NO)	{
				sprintf(note,"Disconnected, <%s>",
				emsg);
				write_aud("D",note);
				goto Disconnect;
			}
			sprintf(note,
			"Transmission of SIGNOFF file <%s> completed (%d blocks)",
			signoff,blocks);
			write_aud("D",note);
			total_bl += blocks;

			ioctl(devfd,BSCGET,&c_params);
			sprintf(note,
			"EOT, sent %d blocks, did %d TTDs, had %d NAKs, %d timeouts, %d WACKs",
			total_bl,c_params.b_nttd,c_params.b_nnak,
			c_params.b_nor,c_params.b_nwack);

			write_aud("T",note);
			blocks = 0;
		}
Disconnect:
	quithost();
	}
}

/* search the host directory for files queued to send */
searchq(wfd)
#if defined BSD42
DIR *wfd;
#else
int wfd;
#endif
{
	int work = NO;
#if defined BSD42
	struct direct *d;

	while ((d = readdir(wfd)) != NULL)
		if (d->d_name[0] == 'C')
		{	work = YES;
			sprintf(ctlfile,"%s/%s",spool,d->d_name);
			break;	}
#else
	struct direct d;

	while (read(wfd,&d,sizeof d) == sizeof d)
		if (d.d_ino != 0 && d.d_name[0] == 'C')
		{	work = YES;
			sprintf(ctlfile,"%s/%s",spool,d.d_name);
			break;	}
#endif

	return (work);
}

/* quithost -- cleanup at end of host processing */
quithost()
{
	if (devfd > 0) {
		close(devfd);
		devfd = -1;
		/* do any necessary disconnect cleanup */
		disconnect(hostname,devname);
	}

	if (lockfile[0]) {
		unlink(lockfile);
		lockfile[0] = '\0';
	}
	if (auditlock[0]) {
		unlink(auditlock);
		auditlock[0] = '\0';
	}
	if (aud)	{
		fclose(aud);
		aud = (FILE *)0;
		if (link(audname,new_audnm) >= 0) {
			unlink(audname);
		}
	}
#if defined BSD42
	if (spoolfd) {
		closedir(spoolfd);
		spoolfd = (DIR *)0;
	}
#else
	if (spoolfd > 0) {
		close(spoolfd);
		spoolfd = -1;
	}
#endif
}

/* sigint -- do signal interrupt processing */
sigint(sig)
int sig;
{
	char msg[80];
	sprintf(msg,"Signal %d received",sig);
	/* update the audit file */
	write_aud("D",msg);

	quithost();
	exit(0);
}

/* param_err - invalid keyword parameter error */
param_err(kword,fname)
char *kword;
char *fname;
{
/* send mail about problem */
	sprintf(note,"Invalid parameter for keyword <%s>\n in <%s>\n",
	kword,fname);
	post();

	fputs(note,stderr);
	quithost();
	exit(1);
}

/* post - post mail to the system administrator about problems encountered */
post()
{
	FILE *popen(),*pptr;
	char address[50];

	sprintf(address,"mail %s",sys_admin);
	if (sys_admin[0] == '/')	{
		pptr = fopen(sys_admin,"a");
		fputs(note,pptr);
		fclose(pptr);
	} else	{
		pptr = popen(address,"w");
		fputs(note,pptr);
		pclose(pptr);
	}
}

/* get_cnfg - get host configuration parameters 
   The function bcopy used herein does the same thing as strncpy, only
   it actually does copy n characters, and doesn't stop at NULL. Very
   convenient for binary or transparent data which contains NULLs... 
	bcopy(to,from,nbytes) */

get_cnfg(config_file)
char config_file[];
{
	FILE *fptr;		/* file pointer returned by fopen */

	int counter = 0;	/* tracks line of config file being read */
	int i = 0;		/* convenient index */

	/* default b_flags parameter values */
	int halfdup = 0;
	int irs = 0;
	
	char *index();
	char *pos;		/* general buffer position pointer */
	char *dptr;		/* dname position pointer */
	char cline[50];		/* contains one configuration line */

	s_params.b_blks = 508;	/* default block size */
	blksize = 508;		/* as above */
	recsize = 503;
	recblk = 503;
	recsep = 0x1e;
	rviab = BSCRVIABT;	/* abort on receiving rvi */
	maxfsize = 0L;
	minspace = 0L;
	s_params.b_nbid = 0;		/* default number of bids limit */
	s_params.b_nnak = 16;		/* default number of naks allowed */
	s_params.b_nretry = 15;		/* default number of retrys allowed */
	s_params.b_nttd = 120;		/* default number of temp. txt delays */
	s_params.b_nwack = 120;		/* default number of wacks allowed */
	s_params.b_nor = 60;		/* default timeout */
	pt_to_pt = 0;
	chk_hostid = NO;
	son_file = NO;
	soff_file = NO;
	chk_termid = NO;

	strcpy(devname,"/dev/bsc");		/* default device name */
	strcpy(sys_admin,"/dev/console");	/* default system administrator
						   name for problem mail */
	ascii = NO;
	compress = YES;

/* read host configuration file for actual parameters */
	if ((fptr = fopen(config_file,"r")) == NULL) {
		fprintf(stderr,
		"bscd: can't open <%s> configuration file \n",hostname);
		quithost();
		exit(1);
	}

	while ((fgets(cline,sizeof cline,fptr)) != NULL) {
		++counter;
		
		if (strncmp(cline,"BLKSIZE=",8) == 0) {
			pos = &cline[8];
			s_params.b_blks = atoi(pos);
			blksize = s_params.b_blks;
			if (s_params.b_blks < 32 || s_params.b_blks > 512)
				param_err("BLKSIZE",config_file);
			continue;
		}

		if (strncmp(cline,"CODE=",5) == 0) {
			pos = &cline[5];
			if(strncmp(pos,"ASCII",5) != 0 && 
			   strncmp(pos,"EBCDIC",6) != 0)
				param_err("CODE",config_file);
			ascii = strncmp(pos,"ASCII",5) == 0?BSCASCII:NO;
			continue;
		}

		if (strncmp(cline,"COMPRESS=",9) == 0) {
			pos = &cline[9];
			if (strncmp(pos,"YES",3) != 0 && 
			    strncmp(pos,"NO",2) != 0)
				param_err("COMPRESS",config_file);
			compress =strncmp(pos,"YES",3)==0?YES:NO;
			continue;
		}

		if (strncmp(cline,"DEVICE=",7) == 0) {
			pos = &cline[7];
			strcpy(devname,pos);
			devname[strlen(devname)-1] = '\0';
			continue;
		}

		if(strncmp(cline,"DUPLEX=",7) == 0) {
			pos = &cline[7];
			if (strncmp(pos,"HALF",4) != 0 && 
			    strncmp(pos,"FULL",4) != 0)
				param_err("DUPLEX",config_file);
			halfdup =strncmp(pos,"HALF",4)==0?0:BSCFDX;
			continue;
		}

		if (strncmp(cline,"IDCHECK=",8) ==0) {
			pos = &cline[8];
			strcpy(s_params.b_hostid,pos);
			chk_hostid = BSCCKHOST; 
			continue;
		}

		if (strncmp(cline,"MAIL=",5) == 0) {
			pos = &cline[5];
			strcpy(sys_admin,pos);
			continue;
		}

		if (strncmp(cline,"MAXFSIZE=",9) == 0) {
			pos = &cline[9];
			maxfsize = atol(pos);
			if (maxfsize > 1000000000L)
				param_err("MAXFSIZE",config_file);
			continue;
			}

		if (strncmp(cline,"MINSPACE=",9) == 0) {
			if ((pos = index(cline,',')) == NULL)
				param_err("MINSPACE",config_file);
			++pos;
			minspace = atol(pos);
			if (minspace > 1000000000L)
				param_err("MINSPACE",config_file);
			pos = &cline[9];
			dptr = &dname[0];
			while(*pos != ',')
				*dptr++ = *pos++;
			*dptr = '\0';
			sprintf(df_string,"df -f %s\n",dname);
			continue;
		}
	
		if (strncmp(cline,"MPTADDR=",8) == 0) {
			pos = &cline[8];
			strcpy(s_params.b_termid,pos);
			pt_to_pt = BSCMPT;
			continue;
		}

		if (strncmp(cline,"NBID=",5) == 0) {
			pos = &cline[5];
			s_params.b_nbid = atoi(pos);
			if (s_params.b_nbid > 127 || s_params.b_nbid < 0)
				param_err("NBID",config_file);
			continue;
		}

		if (strncmp(cline,"NNAK=",5) == 0) {
			pos = &cline[5];
			s_params.b_nnak = atoi(pos);
			if (s_params.b_nnak > 127 || s_params.b_nnak < 0)
				param_err("NNAK",config_file);
			continue;
		}

		if (strncmp(cline,"NRETRY=",7) == 0) {
			pos = &cline[7];
			s_params.b_nretry = atoi(pos);
			if (s_params.b_nretry > 127 || s_params.b_nretry < 0)
				param_err("NRETRY",config_file);
			continue;
		}

		if (strncmp(cline,"NTTD=",5) == 0) {
			pos = &cline[5];
			s_params.b_nttd = atoi(pos);
			if (s_params.b_nttd > 127 || s_params.b_nttd < 0)
				param_err("NTTD",config_file);
			continue;
		}

		if (strncmp(cline,"NWACK=",6) == 0) {
			pos = &cline[6];
			s_params.b_nwack = atoi(pos);
			if (s_params.b_nwack > 127 || s_params.b_nwack < 0)
				param_err("NWACK",config_file);
			continue;
		}

		if (strncmp(cline,"RECBLK=",7) == 0) {
			pos = &cline[7];
			recblk = atoi(pos);
			if (recblk > 507)
				param_err("RECBLK",config_file);
			continue;
		}

		if (strncmp(cline,"RECSEP=",7) == 0) {
			pos = &cline[7];
			irs =strncmp(pos,"IRS",3)==0?0:BSCIUS;
			recsep = (irs == 0)?0x1e:0x19;
			continue;
		}

		if (strncmp(cline,"RECSIZE=",8) == 0) {
			pos = &cline[8];
			recsize = atoi(pos);
			if (recsize > 507)
				recsize = 507;
			continue;
		}

		if (strncmp(cline,"RVIMODE=",8) == 0) {
			pos = &cline[8];
			if (strncmp(pos,"ABORT",5) != 0 && 
			    strncmp(pos,"IGNORE",6) != 0)
				param_err("RVIMODE",config_file);
			rviab =strncmp(pos,"ABORT",5)==0?BSCRVIABT:NO;
			continue;
		}

		if (strncmp(cline,"SIGNON=",7) == 0) {
			strcpy(signon,&cline[7]);
			signon[strlen(signon)-1] = '\0';
			son_file = YES;
			continue;
		}

		if (strncmp(cline,"SIGNOFF=",8) == 0) {
			strcpy(signoff,&cline[8]);
			signoff[strlen(signoff)-1] = '\0';
			soff_file = YES;
			continue;
		}

		if (strncmp(cline,"STATION=",8) == 0) {
			pos = &cline[8];
			if (strncmp(pos,"PRIMARY",7) != 0 &&
			    strncmp(pos,"SECONDARY",9) != 0)
				param_err("STATION",config_file);
			primary =strncmp(pos,"PRIMARY",7)==0?BSCPRIM:NO;
			continue;
		}

		if (strncmp(cline,"TERMID=",7) == 0) {
			pos = &cline[7];
			bcopy(s_params.b_termid,pos,strlen(pos)-1);
			chk_termid = YES;
			continue;
		}

		if (strncmp(cline,"TIMEOUT=",8) == 0) {
			pos = &cline[8];
			i = atoi(pos);
			if (i > 0 && i <= 3000)
				s_params.b_nor = atoi(pos);
			else
				param_err("TIMEOUT",config_file);
			continue;
		}

		
		if (strncmp(cline,"TRANSPARENT=",12) == 0) {
			pos = &cline[12];
			if (strncmp(pos,"YES",3) != 0 && 
			    strncmp(pos,"NO",2) != 0)
				param_err("TRANSPARENT",config_file);
			transp_ok =strncmp(pos,"YES",3)==0?YES:NO;
			continue;
		}

		if (strncmp(cline,"UNITSEP=",8) == 0) {
			pos = &cline[8];
			ius = (strncmp(pos,"YES",3) == 0)? BSCIUS:NO;
			continue;
		}

		/* invalid keyword parameter error */
		sprintf(note,
			"bscd <%s>: Unrecognized keyword, line %d in <%s>\n",
			hostname,counter,config_file);

		fputs(note,stderr);
		post();
		quithost();
		exit(1);
	}

/* insure that the record size is smaller than the block size */
	if (recsize > blksize - 5)
		recsize = blksize - 5;

	s_params.b_flags = ascii | halfdup | ius | rviab |
			   primary | chk_hostid | pt_to_pt;
/* translate termid if one given and ebcdic */
	if (!ascii && chk_termid)
		ascebc(s_params.b_termid,strlen(s_params.b_termid));
/* close configuration file */
	fclose(fptr);
}

/* open_audit - open the host's AUDIT file */
open_audit()
{
	int audfd;

	/* construct AUDIT file pathname */
	sprintf(audname,"%s/%s",spool,"AUDIT");
	sprintf(new_audnm,"%s/%s",spool,"AUDIT");

	if (access(audname,0) == 0)	{
		sprintf(auditlock,"%s/%s",spool,"auditlock");
		if ((audfd = creat(auditlock,0)) < 0) {
			auditlock[0] = '\0';
			bsc_audnm();
		} else	{
			close(audfd);
			aud = fopen(audname,"a");
		}
	}
}

char *usr_name;			/* ptr returned by getlogin */
/* write_aud - write message to audit file */
write_aud(type,msg)
char *type;
char *msg;
{
	char *getlogin();		/* returns ptr to login name for this
					   process */

	if (aud == NULL)
		return;

	/* if first time, get login name */
	if (usr_name == NULL)
		if ((usr_name=getlogin()) == NULL)
			usr_name="unknown";

	/* get current time */
	currtime = time((long*)0);
	t = localtime(&currtime);

	fprintf (aud, "%s %s %02d%02d%02d%02d%02d %s\n",
		usr_name, type, t->tm_year, (t->tm_mon) + 1,
		t->tm_mday, t->tm_hour, t->tm_min, msg);
	fflush(aud);
}

/* do_compress - replace blanks with group separator and count of blanks */
do_compress(string,llen)
char *string;
register int llen;	/* line length */
{
	register int blanks;	/* count of blanks */

	register char *s, *r;
	char blank;

	blank = ascii?' ':0x40;

	r = s = string;
	
	while (1)	{
	/* "copy" characters into string as long as they aren't blank */
		while (llen > 0 && *s != blank) { 
			--llen;
			*r++ = *s++;
		}

		if (llen == 0)	/* no blanks were found */
			break;

	/* skip over blanks in string, keep count to encode as group separator
	   (GS) followed by number of blanks -- encode only if more than
	   two blanks are found */
		blanks = 0;
		while (llen > 0 && *s == blank){
			++blanks;
			--llen;
			++s;
		}

		if (blanks > 2)
		{	*r++ = GS;
			if (blanks <= 63)
				*r++ = 0x40 + blanks;
			else {
				*r++ = 0x40 + 63;
				*r++ = GS;
				*r++ = 0x40 + (blanks - 63);
			}
			continue;
		}
		else if (blanks == 2)
			*r++ = blank;

		*r++ = blank;
	}
	*r = '\0';
	return(r-string);
}

unix.superglobalmegacorp.com

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