home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_100
/
110_01
/
yam7.c
< prev
next >
Wrap
Text File
|
1984-03-03
|
12KB
|
571 lines
/*
>>:yam7.c 9-8-81
* File open and close stuff
* This file assumes operation on a CP/M system
*/
#include "yam.h"
struct fcb { /* CP/M Version 2 fcb AS SEEN BY THE USER */
char dr; /* drive number */
char fname[8]; /* fname[1] used by TAG2 */
char ftype[3]; /* corresponds to extension in rt-11 */
char ex; /* file extent normally 0 */
char s1; /* reserved for bdos's benefit */
char s2; /* likewise, =0 on call to open,make,search */
char rc; /* record count for extent[ex] 0...128 */
char dmap[16];
char cr; /* current record, initialized to 0 by usr */
unsigned recn; /* highest record number */
char recovf; /* overflow of above */
};
#define CONST 2 /* bios console char ready */
#define CONIN 3 /* bios cons char input */
#define CONOUT 4 /* bios cons char output */
#define SRCH 17 /*bdos search for file pattern*/
#define SRCHNXT 18 /* search for next occurrence */
#define SETDMA 26 /* set address for read, write, etc. */
#define SETATTRIB 30 /* update file attributes */
#define SETGETUSER 32 /* set or get user number */
#define COMPFILSIZ 35 /* compute file size into recn and recovf */
#define UFNSIZE 15 /* a:foobar12.urk\0 is 15 chars */
openrx(name)
char *name;
{
#ifdef RESTRICTED
char *s;
if(s=cisubstr(name, ".com")) /* upload .com files as .obj */
strcpy(s, ".OBJ");
if(cisubstr(name, "$$$"))
return ERROR; /* don't allow upload of $$$.sub */
#endif
#ifdef LOGFILE
logfile(name, 'r'); /* record file xmsn */
#endif
unspace(name);
lprintf("'%s' ", name); /* show the name right away */
if(!Creamfile && fopen(name, fout) != ERROR) {
fclose(fout);
printf("Exists ", name);
#ifdef XMODEM
return ERROR;
#else
printf("Replace it (y/n)??");
if(tolower(getchar())!= 'y')
return ERROR;
#endif
}
if(fcreat(name, fout)==ERROR){
printf("Can't create %s\n", name);
return ERROR;
}
Rfile= TRUE;
strcpy(Rname, name);
Dumping= !Squelch;
lprintf("Created%s\n", Dumping? "" : " recording OFF");
return OK;
}
closerx(pad)
{
if(Rfile) {
if(!Quiet)
lpstat("Closing %s", Rname);
#ifdef BDSC
if(pad)
do
putc(CPMEOF, fout);
while(fout._nleft % SECSIZ);
#endif
fflush(fout);
fclose(fout);
Rfile=FALSE;
}
}
opentx(name)
char *name;
{
struct fcb *fp, *fcbaddr();
lprintf("'%s' ", name);
#ifdef LOGFILE
logfile(name, 's'); /* record file xmsn */
#endif
unspace(name);
if(fopen(name, fin)==ERROR){
printf("Can't open %s\n", name);
return ERROR;
}
#ifdef RESTRICTED
if(cisubstr(name, ".bad")
|| (fp=fcbaddr(fin._fd))==ERROR
|| (fp->fname[1] & 0200)
) {
fclose(fin); printf("\n'%s' Not for Distribution\n", name);
return ERROR;
}
#endif
Tfile= TRUE;
strcpy(Tname, name);
lprintf("Open\n");
return OK;
}
closetx()
{
if(Tfile) {
fclose(fin);
if(!Quiet)
lpstat("%s closed", Tname);
Tfile=FALSE;
}
}
/* search the phone file for name */
getphone(name, buffer)
char *name, *buffer;
{
closetx();
if(fopen(PHONES, fin)==ERROR) {
printf("Cannot open %s\n", PHONES);
return ERROR;
} else {
while(fgets(buffer, fin))
if(cmdeq(buffer, name)) {
fclose(fin);
return OK;
}
}
printf("Can't find data for %s\n", name);
fclose(fin);
return ERROR;
}
/* channge default disk and optionally, user number */
chdir(p)
char *p;
{
unsigned newuser;
newuser=user; *p=toupper(*p);
if(index(*p, DISKS)) {
defdisk= *p - 'A';
bdos(14, defdisk);
#ifdef CDOS
return;
#else
if(!isdigit(p[1]))
return;
if((newuser=atoi(p+1)) <= MAXUSER) {
bdos(SETGETUSER, newuser);
user=newuser;
return;
}
#endif
}
printf("Disk %c and/or User %d Illegal\n", *p, newuser);
}
/* fetch default disk and user number */
initdd()
{
Secpblk=SECPBLK;
defdisk= bdos(25,0);
#ifdef CDOS
user=0;
#else
user=bdos(SETGETUSER, 0377);
#endif
}
/*
* Z19 gets to use it's 25th line. pstat starts at 48th char
* note that a call to lpstat will erase what pstat displays
*/
/*VARARGS*/
pstat(a,b,c)
char *a, *b, *c;
{
#ifdef Z19
lprintf("\033x1\033j\033Y8P");
#endif
lprintf(a,b,c);
#ifdef Z19
lprintf("\033K\033k");
#else
lprintf("\n");
#endif
}
/*
* Z19 gets to use it's 25th line. lpstat starts at col 1
* Rest of line is erased
*/
/*VARARGS*/
lpstat(a,b,c)
char *a, *b, *c;
{
#ifdef Z19
lprintf("\033x1\033j\033Y8 ");
#endif
lprintf(a,b,c);
#ifdef Z19
lprintf("\033K\033k");
#else
lprintf("\n");
#endif
}
char getcty()
{
return bios(CONIN,0);
}
char putcty(c)
char c;
{
bios(CONOUT, c);
if(bios(CONST,0)) {
if((c=bios(CONIN,0))==XOFF)
bios(CONIN,0);
else
return c;
}
return FALSE;
}
dolist(argc, argp)
char **argp;
{
int listfile();
#ifdef XMODEM
printf("^S pauses, ^K skips to next file, ^X terminates\n");
#endif
expand(listfile, argc, argp);
}
listfile(name)
char *name;
{
int c;
#ifdef XMODEM
printf("\nListing '%s'\n\022", name);
#endif
closetx();
if(opentx(name)==ERROR)
return ERROR;
else {
while((c=getc(fin))!=EOF && c != CPMEOF) {
if( !(c=putcty(c)))
continue;
if(c==003 || c==CAN || c==013)
break;
}
closetx();
#ifdef XMODEM
sendline(024); /* squelch in case user downloading */
#endif
}
/* cancel rest of files if ^C ^X */
if(c==003 || c==CAN)
return ERROR;
else
return OK;
}
/* fill buf with count chars padding with ^Z for CPM */
filbuf(buf, count)
char *buf;
{
register c, m;
m=count;
while((c=getc(fin))!=EOF) {
*buf++ =c;
if(--m == 0)
break;
}
if(m==count)
return 0;
else
while(--m>=0)
*buf++ = 032;
return count;
}
dodir(argc, argp)
char **argp;
{
/* printf("Directory\n");*/
int pdirent();
cfast=0; /* counter for 4 across format */
expand(pdirent, argc, argp);
}
pdirent(name)
{
printf("%-14s%c", name, (++cfast&03)?' ':'\n');
}
#ifndef CDOS
/* docomp does a directory listing showing sectors for each matched file
* and computes total transmission time of matched files in batch mode
* time is sum of:
* number of files * open/close time (assumed 5 seconds)
* time to xmit and ACK each sector assuming no path delay or error
* disk i/o time at each end, not dependent on baud rate
*/
docomp(argc,argp)
char **argp;
{
unsigned compsecs();
unsigned spm; /* sectors per minute-baud */
unsigned dminutes; /* tenths of minutes */
cfast=Numsecs=Numblks=0;
/* printf("Directory\n");*/
expand(compsecs, argc, argp);
spm= Baudrate/23; /* (Baudrate*60)/(10 bits each char * 136 chars) */
dminutes= (Numfiles/2)+((10*(Numfiles+Numsecs))/spm)+(Numsecs/25);
printf("\n%u Files %u Blocks %u K\n",
Numfiles, Numblks, (Numblks*(Secpblk/8)));
printf("%u Sectors %u.%u Minutes Xmsn Time at %u Baud\n",
Numsecs, dminutes/10, dminutes%10, Baudrate);
}
/* add file length (in CP/M 128 byte records) to Numsecs */
unsigned compsecs(ufn)
char *ufn;
{
struct fcb fstat;
printf("%-14s", ufn);
unspace(ufn);
setfcb( &fstat, ufn);
bdos(COMPFILSIZ, &fstat);
Numsecs += fstat.recn;
Numblks += (fstat.recn+Secpblk)/Secpblk;
printf("%4u%c",fstat.recn, (++cfast&03)?' ':'\n');
}
#endif
expand(fnx, argc, argp)
int (*fnx)();
char **argp;
{
char name[PATHLEN], *s;
Numfiles=0;
if(argc<=0)
return e1xpand(fnx, "*.*");
else
while(--argc>=0) {
/* change b: to b:*.* */
strcpy(name, *argp++);
if((s=index(':', name)) && *++s == 0)
strcpy(s, "*.*");
if(e1xpand(fnx, name)==ERROR)
return ERROR;
}
}
/*
* e1xpand expands ambiguous pathname afnp
* calling fnx for each.
* Modified from: Parameter list builder by Richard Greenlaw
* 251 Colony Ct. Gahanna, Ohio 43230
*/
e1xpand(fnx, afnp)
int (*fnx)();
char *afnp; /* possible ambiguous file name*/
{
struct fcb sfcb, *pfcb;
char *p, *q, i, byteaddr;
int filecount, m;
char tbuf[SECSIZ];
struct {
char xYxx[UFNSIZE]; /* unambiguous file name */
} *fp;
int strcmp();
/* build CPM fcb */
unspace(afnp);
if(setfcb(&sfcb, afnp) == ERROR) {
printf("%s is bad pattern\n", afnp);
return ERROR;
}
if(Wrapped || (bufend-bufcq)<2048) {
dumprxbuff(); /* I need the space for building the pathlist */
clearbuff(); /* so the printer won't try to list dir's */
bufmark=bufst;
} else
bufmark=bufcq;
/* Search disk directory for all ufns which match afn*/
for(fp=bufmark,filecount=0;; fp++,filecount++) {
tryanother:
bdos(SETDMA, tbuf);
if((byteaddr=bdos(filecount? SRCHNXT:SRCH, &sfcb))==255)
break;
/* calculate pointer to filename fcb returned by bdos */
pfcb = (tbuf + 32 * (byteaddr % 4));
#ifdef RESTRICTED
/* check for tag bit on 2nd byte of filename (TAG2) */
if(pfcb->fname[1]&0200)
goto tryanother;
#endif
Numfiles++;
p = fp;
if(fp>bufend) { /* Note: assumes some slop after bufend! */
printf("Out of Memory for pathname expansion\n");
return ERROR;
}
if(*(afnp+1) == ':') {
/* Drive spec.*/
*p++ = *afnp;
*p++ = ':';
}
/*Copy filename from directory*/
q = pfcb;
for(i =8; i; --i)
*p++ = (0177& *++q);
*p++ = '.' ;
/*Copy file extent*/
for(i = 3; i; --i)
*p++ = (0177& *++q);
*p = '\0' ;
}
qsort(bufmark, filecount, UFNSIZE, strcmp);
for(fp=bufmark; --filecount>=0;) {
p=fp++;
/* execute desired function with real pathname */
if((*fnx)(p)==ERROR)
return ERROR;
}
}
/*
* cisubstr(string, token) searches for lower case token in string s
* returns pointer to token within string if found, NULL otherwise
*/
char *cisubstr(s, t)
char *s,*t;
{
char *ss,*tt;
/* search for first char of token */
for(ss=s; *s; s++)
if(tolower(*s)==*t)
/* compare token with substring */
for(ss=s,tt=t; ;) {
if(*tt==0)
return s;
if(tolower(*ss++) != *tt++)
break;
}
return NULL;
}
#ifdef XMODEM
/*
* lprintf is like regular printf but uses direct output to console
* This prevents status printouts from disrupting file transfers, etc.
*/
lprintf(a,b,c,d,e,f)
char *a, *b, *c, *d, *e, *f;
{
char lbuf[CMDLEN], *s;
/* format data into lbuf */
sprintf(lbuf, a,b,c,d,e,f);
/* now send lbuf to console directly */
for(s=lbuf; *s; ) {
if(*s=='\n') {
while(!COREADY) /* expand \n to \r\n */
;
outp(CDATA, '\r');
}
while(!COREADY)
;
outp(CDATA, *s++);
}
}
#endif
/* copy string s onto itself deleting spaces "hello there" > "hellothere" */
unspace(s)
char *s;
{
char *p;
for(p=s; *s; s++)
if(*s != ' ')
*p++ = *s;
*p++ =0;
}
#ifdef LOGFILE
/*
* logfile keeps a record of files transmitted.
* Mode is 's' for send file, 'r' for receive file, 't' for type file
* Lifted from xcmodem by J. Wierda,R. Hart, and W. Earnest
*/
#define RPB 4 /* log records per buffer */
#define LRL 32 /* logical rec length LRL*RPB == SECSIZ */
logfile(name, mode)
char *name;
char mode;
{
struct fcb *fcbaddr(),*fp;
int fd,rnum,bnum;
char *i, *lrec, lbuf[SECSIZ+2];
if(i=index(':', name))
name= ++i; /* discard possible drive spec */
bdos(SETGETUSER, 0); /* get it from user 0 */
fd=open(LOGFILE,2);
if(fd == ERROR) { /* if file absent, create and initialize it */
fd = creat(LOGFILE);
if(fd == ERROR)
return;
else {
rnum=1;
fp=fcbaddr(fd);
fp->fname[1] |= 0200; /* set TAG2 bit */
bdos(SETATTRIB, fp); /* and update attributes */
}
}
else {
read(fd, lbuf, 1);
rnum=atoi(lbuf)+1;
}
setmem(lbuf, SECSIZ, 0);
sprintf(lbuf, "%d\r\n", rnum);
seek(fd,0,0);
write(fd, lbuf, 1); /* update last record number */
bnum=rnum/RPB;
rnum=(rnum%RPB)*LRL;
seek(fd, bnum, 0);
if(rnum==0)
setmem(lbuf, SECSIZ, 0);
else
read(fd, lbuf, 1);
sprintf(&lbuf[rnum], "%s %c %u\r\n", name, mode, Baudrate);
seek(fd, bnum, 0);
write(fd,lbuf,1);
close(fd);
bdos(SETGETUSER, user);
}
#endif
/
logfile(name, mode)
char *name;
char mode;
{
struct fc