pdp11v/usr/src/cmd/gcos/spool.c
/* @(#)spool.c 1.3 */
/* 3.0 SID # 1.3 */
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#define ONL 0
#define TOSS 1
/*GCOSA = GCOS job with ASCII data.*/
/*GCOSB = GCOS job with BCD data.*/
#define GCOSA 1
#define GCOSB 2
#define FGET 3
#define LPR 4
#define GCAT 1 /*flag for gcat command*/
#define MAIL 2 /*flag for GCOS mail command.*/
#if SPTYPE == LPR
#ifndef SPDIR
#define SPDIR "/usr/spool/lpd"
#endif
#ifndef DAEMON
#define DAEMON "/usr/lib/lpd"
#endif
#ifndef DAEMON2
#define DAEMON2 "/etc/lpd"
#endif
#else
#ifndef SPDIR
#define SPDIR "/usr/spool/dpd"
#endif
#ifndef DAEMON
#define DAEMON "/usr/lib/dpd"
#endif
#ifndef DAEMON2
#define DAEMON2 "/etc/dpd"
#endif
#endif
int INCHAR = 0; /*index of incremented character in
temporary file names. */
#ifndef MAXJOB
#define MAXJOB 750000L
#endif
char version[] = "Version 2/1/82";
char grade;
char remote[]= "$ remote **,onl";
char toss[] = "$ sysout toss";
int remotsw; /*toss-output flag*/
char *mailfile = 0;
char wantmail = 0;
char *pp = 0; /*recipient of mail*/
char *identf = 0; /*ident card info*/
int uidf = 0;
char gcosid[13]; /*gcos userid*/
char cpflag = 'l'; /*copy/link flag*/
int rmflag = 0; /*remove flag*/
int debug = 0;
int gcdebug = 0; /*GCOS debug switch*/
int archsw = 0; /*archive switch*/
int argc;
char **argv;
char *arg;
int nact = 0; /*number of non-null files to process.*/
int gsize = 20; /*size of current file in GCOS blocks.*/
long usize = 20*1200; /*size of current file in bytes.*/
long jobsize = 0; /*size of current job in bytes.*/
#define CARDSIZE 83
char idcard[CARDSIZE]; /*$ IDENT card image.*/
int iacct, iname; /*index of account number, user name in idcard.*/
char cardbuf[BUFSIZ]; /*for use by callers of card() and copy().*/
FILE *tff; /*temporary control card file*/
FILE *nfile();
char *getarg();
char *strchr(), *strrchr();
comopt(o) /*routine to test for common options.*/
char o;
{
switch (o){
case 'c':
cpflag = 'c';
break;
case 'f': /*option to set filename for mail. MRW*/
mailfile = getarg('f');
break;
case 'i':
identf = getarg('i');
break;
case 'm':
wantmail++;
if(arg[2])
pp = &arg[2];
break;
case 'n': /*new option to suppress mail. MRW*/
wantmail = 0;
break;
case 'o':
remotsw = ONL;
break;
case 'r':
rmflag++;
break;
case 's':
if(arg[2] < '1' || arg[2] > '4')
goto unknown;
grade = arg[2];
break;
case 't':
if(arg[2])
goto unknown;
remotsw = TOSS;
break;
case '#':
debug = 1;
break;
case 'Z': /*GCOS debugging switch*/
gcdebug = 1;
break;
unknown:
default:
return(0);
}
return(1);
}
char *
getarg(c) /*get modifier for complex options --
from either same or next argument. MRW
e.g. either "-ffile" or "-f file"*/
char c;
{
if(arg[2])
return(&arg[2]);
else if(--argc>1)
return(arg = (++argv)[1]);
errout("Incomplete -%c option",c);
}
#if SPTYPE != LPR
gcos1() /*set up common initial GCOS control cards.*/
{
if(debug)
tff = stdout;
else
if((tff = nfile(tfname)) == NULL)
errout("Can't create %s.", tfname);
card('S', "");
card('L', "$ sgrade %c %s", grade, version );
if(ident())
out();
card('L', remote);
if(remotsw == TOSS)
card('L', toss);
}
gcos2() /*add final control cards, and spool job.*/
{
if(jobsize > MAXJOB)
errout("Job too large for GCOS: %ld bytes.", jobsize);
if(wantmail)
card('N', mailfile);
card('L', "$ endjob");
if(debug)
out();
fclose(tff);
if(nact) {
dfname[INCHAR]++;
if(link(tfname, dfname) < 0)
errout("Cannot rename %s", tfname);
unlink(tfname);
execl(DAEMON, DAEMON, 0);
execl(DAEMON2, DAEMON2, 0);
err("Can't find %s.\nFiles left in spooling dir.", DAEMON);
exit(1);
}
errout("No data; job deleted.");
}
#endif
FILE *nfile(name) /*generate a new file name, and open file.*/
char *name;
{
FILE *f;
if(name[INCHAR] >= 'z')
return(NULL);
name[INCHAR]++;
if(!access(name, 0) || (f = fopen(name, "w")) == NULL)
return(NULL);
return(f);
}
#if SPTYPE == GCOSA || SPTYPE == LPR
filargs() /*process file arguments for dpr, gcat, fsend, lpr.*/
{
int i;
FILE *f;
if(argc == 1){
if(mailfile == 0)
mailfile = "pipe.end";
if(copy(stdin, mailfile, GCATSW) == -1)
out();
if(archsw)
archive();
}
while(--argc) {
arg = *++argv;
if(size(arg,arg) <= 0)
continue;
switch(cpflag){
case 'l':
if(lfname[INCHAR]++ >= 'z')
cpflag = rmflag ? 'c' : 'n';
else if(link(arg, lfname) == 0){
nuact(arg, arg);
card(BF, lfname);
card('U', lfname);
break;
}
case 'n':
if(*arg == '/' && !rmflag){
nuact(arg, arg);
card(BF, arg);
break;
}
case 'c':
jobsize -= usize; /*let copy() add the size.*/
f = fopen(arg, "r");
if(f == NULL){
err("Cannot open %s", arg);
continue;
}
i = copy(f, arg, GCATSW);
fclose(f);
if(i == -1)
continue;
break;
}
if(archsw)
archive();
if(rmflag){
if(unlink(arg) < 0)
err("Cannot remove %s", arg);
}
if(mailfile == 0)
mailfile = arg;
}
}
copy(f, gname, spsw)
FILE *f;
char *gname;
int spsw;
{
int c, oc;
FILE *ff;
/* try removing limit on copy file .. see if anyone objects.
long cnt;
cnt = 0;
* remove limit on copy file.*/
oc = EOF;
if((ff = nfile(cfname)) == NULL){
err("Too many copy files; %s not copied", gname);
return(-1);
}
if(spsw == MAIL){
fprintf(ff, cardbuf);
}
while((c = getc(f)) != EOF){
if(spsw == MAIL && (oc == '\n' || oc == EOF) && c == '.'){
if((c = getc(f)) == '\n') /*allow . as mail EOF*/
if(oc == '\n')
break;
else
errout("No mail to send");
else if(putc('.', ff) == EOF){
err("Write error on copy of %s.", gname);
break;
}
}
if((oc = putc(c, ff)) == EOF && ferror(ff)){
err("Write error on copy of %s.", gname);
break;
}
/* try removing limit on copy file .. see if anyone objects.
cnt++;
if(cnt > MAXCOPY){
err("Copy file %s is too large", gname);
break;
}
* remove limit on copy file.*/
}
fclose(ff);
if(size(gname, cfname) <= 0){
unlink(cfname);
return(-1);
}
nuact(gname, cfname);
card(BF, cfname);
card('U', cfname);
return(0);
}
#endif
#if SPTYPE != FGET
size(name, temp)
char *temp, *name;
{
struct stat stbuf;
if(stat(temp,&stbuf) < 0){
err("Cannot open %s", temp);
return(-1);
}
if(!stbuf.st_size){
err("File %s is empty.", name);
return(0);
}
usize = stbuf.st_size;
jobsize += usize;
gsize = usize / 1200;
gsize++;
nact++;
return(gsize);
}
#endif
#if SPTYPE == GCOSB
copyfile(fin, p) /* precede every line with a letter L */
FILE *fin;
char *p;
{
char *cp;
while( fgets(cardbuf,CARDSIZE, fin) ){
if((cp = strchr(cardbuf, '\n')) == NULL)
errout("Line too long in file %s.", p);
*cp = '\0';
card('L', cardbuf);
jobsize += strlen(cardbuf);
}
nact++;
if(mailfile == 0)
mailfile = p;
}
#endif
/*VARARGS*/
card(c, s, a1, a2, a3, a4)
int c;
char *s;
{
putc( c, tff );
if(fprintf(tff, s, a1, a2, a3, a4) > CARDSIZE){
#if SPTYPE != LPR
err("Overflow of GCOS card size:");
errout(s, a1, a2, a3, a4);
#endif
}
c = putc( '\n', tff );
if(c == EOF && ferror(tff))
errout("Error writing control file.");
}
#include <pwd.h>
struct passwd *getpwuid();
ident()
{
int c, i, j, n, test;
char *p;
struct passwd *b1;
if((b1 = getpwuid(getuid())) == NULL) {
err("Invalid user id");
return(1);
}
j = 0;
#if SPTYPE != LPR
while(c = "$ ident "[j])
idcard[j++] = c;
iacct = j;
#endif
i = 0;
n = CARDSIZE - strlen(b1->pw_name) - 2;
if(identf) {
while((c = identf[i++]) && j < n)
idcard[j++] = c;
idcard[j++] = ',';
}
#if SPTYPE != LPR
else{ /*there are now 3 possible passwd formats*/
#if RES
p = b1->pw_gecos; /*research style*/
#else
p = strrchr(b1->pw_gecos,')'); /*UNIX/TS style*/
#if ISCC
if(p != NULL)
*p = ','; /*new ISCC standard style*/
p = strrchr(b1->pw_gecos, '(');
#endif
p = (p==NULL) ? b1->pw_gecos : p+1 ;
#endif
strncpy(&idcard[j], p, n-j);
j = strlen(idcard);
idcard[j++] = ',';
}
#endif
iname = j;
i = 0;
if(!pp)
pp = &idcard[j];
while(c = b1->pw_name[i++])
idcard[j++] = c;
idcard[j] = '\0';
#if SPTYPE != LPR
i = 0;
n = 2;
while(n--) {
test = 0;
while((c=idcard[i++]) && c != ',') {
if('0' <= c && c <= '9') test += c - '0';
else test = 1;
}
if(c == 0 || test <= n){ /*acct must be non-zero number;
/*box may be anything non-zero*/
idcard[j] = '\0';
err("Invalid IDENT information - %s", idcard);
return (1);
}
}
if(!uidf) {
n = 0;
while((c = idcard[i++]) && c != ',') {
if(n >= 12) break;
gcosid[n++] = c;
}
gcosid[n++] = '\0';
}
#endif
card('L', idcard);
if(wantmail){
card('M',pp);
if(identf)
card('Q', idcard); /*mail back $IDENT card.*/
}
return (0);
}
setup()
{
register i;
int out();
NAME = argv[0];
INCHAR = sizeof(SPDIR) + 2;
if(NTEMP < 2 || sizeof(Xfname[0]) < INCHAR+8){
err("Program bug; overflow in Xfname.");
exit(1);
}
strcpy(Xfname[0], SPDIR);
strcat(Xfname[0], "/dfAXXXXXX");
Xfname[0][INCHAR] = FIRSTCHAR;
Xfname[0][INCHAR-2] = Xchar[0];
mktemp(Xfname[0]);
for(i=1; i<NTEMP; i++){
strcpy(Xfname[i], Xfname[0]);
Xfname[i][INCHAR-2] = Xchar[i];
}
if(signal(SIGHUP, SIG_IGN) != SIG_IGN)
signal(SIGHUP, out);
if(signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, out);
if(signal(SIGQUIT, SIG_IGN) != SIG_IGN)
signal(SIGQUIT, out);
if(signal(SIGTERM, SIG_IGN) != SIG_IGN)
signal(SIGTERM, out);
jobsize = 0;
}
/*VARARGS*/
err(s, a1, a2, a3, a4)
char *s;
{
fprintf(stderr, "%s: ", NAME);
fprintf(stderr, s, a1, a2, a3, a4);
putc('\n', stderr);
}
/*VARARGS*/
errout(s, a1, a2, a3, a4)
char *s;
{
err(s, a1, a2, a3, a4);
out();
}
out()
{
register i, j;
signal(SIGHUP, SIG_IGN);
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
signal(SIGTERM, SIG_IGN);
i = INCHAR;
for(j = 0; j < NTEMP; j++)
for(; Xfname[j][i] != FIRSTCHAR; Xfname[j][i]--)
unlink(Xfname[j]);
exit(1);
}