|
|
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);
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.