|
|
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
* rcvf
*
* SYNOPSIS
* rcvf()
*
* DESCRIPTION
* receive a file -- called from bscd
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <bsc/bscio.h>
#include "local.h"
#define YES 1
#define NO 0
#define DC1 0x11
#define DC2 0x12
#define DC3 0x13
#define ESC 0x1b
#define GS 0x1d
#define RCDSEP 0x1e
#define EM 0x19
#define US 0x1f
#define EBESC 0x27
#define EB4 0xf4 /* ebcdic 4; used to check for ESC 4 sequences */
#ifndef lint
static char sccsid[] = "%W% %Q%";
#endif
extern struct bscio c_params;
extern char hostname[];
extern char auditlock[];
extern char lockfile[];
extern char spool[];
extern char emsg[];
extern char user[];
extern int devfd;
extern int ascii;
extern int trnsp;
extern int total_bl;
extern int ctr;
extern int ius;
extern long maxfsize;
extern long minspace;
void exit();
char *strcpy();
rcvf()
{
int len; /* length of read-in rbuff */
int rfd = 0; /* receive file descriptor */
int pid; /* process id goes in here; used to make
unique receive file name */
int sw;
int blocks = 0; /* number of blocks received */
int nblnks; /* number of blanks in compressed string */
int c_writes = 0; /* number of chars written to received file */
int write_ok = YES; /* whether or not it's ok to write to receive
file (used with maxfsize) */
int write_amt; /* number of chars to write to receive file */
long c_count = 0; /* count of total characters written to receive
file (used with maxfsize) */
char fname[80]; /* receive file name */
char rbuff[512]; /* stuff gets received in here */
char type[6]; /* print or punch file */
char rtype[3]; /* PRint or PUnch */
char expandarea[1024]; /* place to de-compress blocks */
char blank;
char a_msg[150]; /* audit file message */
register char *r; /* receive buffer pointer */
register char *exptr; /* expand area pointer */
register char *pos; /* pointer returned by bstrchr */
char *bstrchr(); /* fn rtns ptr to given char in string */
struct stat s; /* points to file status structure */
FILE *popen();
blank = ascii?' ':0x40;
pid = getpid(); /* get process id for this process */
sw = 0;
while ((len = read(devfd,rbuff,sizeof rbuff)) > 0) {
if (write_ok)
++blocks;
ioctl(devfd,BSCGET,&c_params);
if (!sw)
{ /* do first-time stuff */
/* if first character in receive buffer is DC2, DC3, or ESC
followed by 4, this is a punch file. If first character
is DC1, this is a print file. */
r = rbuff;
/* if it isn't ascii, translate it before testing it */
if (!ascii) ebcasc(rbuff, 2);
if (*r == DC2 || *r == DC3 ||
(*r == ESC && *(r+1) == '4')) {
strcpy(rtype,"PU");
strcpy(type,"punch");
} else {
strcpy(rtype,"PR");
strcpy(type,"print");
}
/* translate it back to ebcdic so it won't be confused later */
if (!ascii) ascebc(rbuff, 2);
sprintf(fname,"%s/%s%04d%d",spool,rtype,ctr,pid);
/* create the file in the host's spool directory
with read/write permission for everyone */
if ((rfd = creat(fname,0666)) == -1)
{ fprintf(stderr,
"bscd <%s>: file <%s> can't be created\n",
hostname,fname);
unlink(auditlock);
unlink(lockfile);
exit(1); }
++sw;
/* update AUDIT file */
if (c_params.b_flags == BSCTXP)
sprintf(a_msg,
"Receiving <%s> file, transparent mode",
type);
else
sprintf(a_msg,
"Receiving <%s> file",type);
write_aud("R",a_msg);
}
if (c_params.b_flags == BSCTXP)
{ write(rfd,rbuff,(unsigned)len); /* take as is */
continue; }
/* de-block */
exptr = expandarea;
r = rbuff;
r[len] = '\0';
while(pos = bstrchr(r,GS,len - ((int)(r-rbuff))))
{ if (pos-r)
bcopy(exptr,r,(int)(pos-r));
exptr += pos - r;
++pos;
nblnks = *pos++ - 0x40;
while(--nblnks >= 0)
*exptr++ = blank;
r = pos;
}
bcopy(exptr,r,len - ((int)(r-rbuff)));
exptr += len - (r - rbuff);
len = exptr - expandarea;
/* translate is necessary */
if (!ascii)
ebcasc(expandarea,len);
/* check that there's a US or EM at the end of the buffer */
if (*(exptr-1) != RCDSEP && *(exptr-1) != EM &&
*(exptr-1) != US) {
*exptr++ = '\n';
++len;
}
/* Accept either RS (1E), EM (19), or US (1F) as record terminators.
The latter two are used in 2780 mode, and the EM occurs if the
record is shorter (or longer) than would normally be expected
(usually 80 characters). Thus, if an EM character is found, ignore
a US character if it immediately follows. If only a US terminator is
found for a record, it is replaced by a newline.
Sound confusing? That's comm for you. */
pos = expandarea;
while ( (r = bstrchr(pos,EM,len - (int)(pos-expandarea)))||
(r = bstrchr(pos,RCDSEP,len - (int)(pos-expandarea))) ){
*r++ = '\n';
pos = r;
}
pos = expandarea;
while ( pos = bstrchr(pos,US,len - (int)(pos - expandarea))) {
if (pos > expandarea && pos[-1] == '\n'){
bcopy(pos,pos+1,len-(int)(pos+1 - expandarea));
--len;
--exptr;
}
else
*pos++ = '\n';
}
if (write_ok && (!maxfsize || c_count < maxfsize)) {
write_amt = (maxfsize && (c_count+(exptr-expandarea) > maxfsize))?
maxfsize - c_count: exptr - expandarea;
c_writes = write(rfd,expandarea,(unsigned)write_amt);
if (c_writes == -1) {
fprintf(stderr,
"bscd <%s>: can't write to file <%s>\n",
hostname,fname);
unlink(auditlock);
unlink(lockfile);
exit(1);
}
c_count += c_writes;
if (maxfsize && c_count >= maxfsize) {
strcpy(a_msg,
"Receive file truncated, <maximum file size encountered>");
write_aud("R",a_msg);
/* send msg to user about it */
notefile(user," ",a_msg);
write_ok = NO;
}
}
}
/* check for errors on receive */
if (len < 0) {
ioctl(devfd, BSCGET, &c_params);
get_errors();
sprintf(a_msg,"Receiving aborted, <%s>",emsg);
write_aud("R",a_msg);
return(1); }
if (rfd > 0)
close(rfd);
if (!sw) /* nothing received -- just return */
return(0);
/* call asgnfile - give a more meaningful name to received file */
asgnfile(hostname,fname);
/* receive done - update AUDIT */
stat(fname,&s);
sprintf(a_msg,
"Receiving complete (%ld bytes, %d blocks), assigned to file <%s>",
s.st_size,blocks,fname);
write_aud("R",a_msg);
total_bl += blocks;
++ctr;
return(2);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.