/************************************************************************/ /* */ /* RZMP Source File #3 */ /* */ /************************************************************************/ #define RZMP #include "zmp.h" #include char *alloc(); fstat(fname,status) char *fname; struct stat *status; { unsigned filelength(); fcbinit(fname,&Thefcb); status->records = filelength(&Thefcb); getfirst(fname); fcbinit("????????.???",&Thefcb); } unsigned filelength(fcbp) struct fcb *fcbp; { int olduser; bdos(SETDMA,CPMBUF); /* set dma address */ olduser = getuid(); /* save this user number */ setuid(fcbp->freserved & 0x0f); /* go to file's user no. */ bdos(35,fcbp); setuid(olduser); /* restore original */ return fcbp->ranrec; } roundup(dividend,divisor) int dividend, divisor; { return (dividend/divisor + ((dividend%divisor) ? 1 : 0)); } getfirst(aname) /* ambiguous file name */ char *aname; { bdos(SETDMA,CPMBUF); /* set dma address */ fcbinit(aname,&Thefcb); return bdos(SFF,&Thefcb) & 0xff; } getnext() { bdos(SETDMA,CPMBUF); /* set dma address */ return bdos(SFN,NULL) & 0xff; } memcpy(dest,source,count) char *dest, *source; int count; { while (count--) *dest++ = *source++; } memset(dest,byte,count) char *dest, byte; int count; { while (count--) *dest++ = byte; } /* command: expand wild cards in the command line. (7/25/83) * usage: command(&argc, &argv) modifies argc and argv as necessary * uses sbrk to create the new arg list * NOTE: requires fcbinit() and bdos() from file stdlib.c. When used * with a linker and stdlib.rel, remove the #include stdlib.c. * * Written by Dr. Jim Gillogly; Modified for CP/M by Walt Bilofsky. * Modified by HM to just get ambiguous fn for zmodem, ymodem. */ int COMnf,*COMfn,COMc,*COMv; char *COMarg,*COMs; static expand(); command(argcp,argvp) int *argcp,*argvp; { char *p, c, *index(); int drive, user; int f_alloc[MAXFILES]; COMfn = f_alloc; COMc = *argcp; COMv = *argvp; COMnf = 0; for (COMarg = *COMv; COMc--; COMarg = *++COMv) { #ifdef DEBUG printf("\nDoing %s",COMarg); #endif if (!(*Wheel) && (index(COMarg,':'))) { /* ensure du: in range */ drive = (int) *COMarg; user = atoi(COMarg+1); if ((drive > MAdrive) || (user > MAuser)) continue; /* out of range */ } for (COMs = COMarg; *COMs; COMs++) if (*COMs == '?' || *COMs == '*') { if (Private) goto contn; /* no wildcards on private */ if (!expand()) { /* Too many names */ *argcp = 0; return; } goto contn; /* expand each name at most once */ } COMfn[COMnf] = alloc(FNSIZE); p = COMarg; while (c = *p) /* convert to lower case */ *p++ = isupper(c) ? tolower(c) : c; strcpy(COMfn[COMnf++],COMarg); /* no expansion */ contn: ; } *argcp = COMnf; COMfn[COMnf++] = -1; COMv = *argvp = alloc(2 * COMnf); while (COMnf--) COMv[COMnf] = COMfn[COMnf]; } static expand() /* Returns FALSE if error */ { char fcb[36]; static char *p,*q,*r,c; static int i,flg,olduser; #ifdef DEBUG printf("\nExpanding %s",COMarg); #endif olduser = getuid(); /* save original user area */ fcbinit(COMarg,fcb); if (fcb[0] == -1) fcb[0] = '?'; /* Check for all users */ if (!(*Wheel) && (fcb[0] == '?')) /* but only for wheels */ fcb[0] = olduser; for (i = flg = 1; i <= 11; ++i) { /* Expand *'s */ if (i == 9) flg = 1; if (fcb[i] == '*') flg = 0; if (flg == 0) fcb[i] = '?'; } setuid(fcb[13]); /* go to specified user area */ flg = 17; bdos(26,0x80); /* Make sure DMA address OK */ while (((i = bdos(flg,fcb)) & 0xff) != 0xff) { COMfn[COMnf++] = q = alloc(FNSIZE); if (COMnf >= MAXFILES-1) { for (p = "Too many file names.\n"; putchar(*p++); ); { setuid(olduser); return FALSE; } } p = 0x81 + i * 32; /* Where to find dir. record */ /* Transfer du: first */ if ((index(COMarg,':')) && COMarg[0] != '?') { r = COMarg; do *q++ = c = *r++; while (c != ':'); } /* Now transfer filename */ r = q; /* save pointer for test */ for (i = 12; --i; ) { if (i == 3) *q++ = '.'; if ((*q = isupper(c = *p++ & 0177) ? tolower(c) : c) != ' ') ++q; } *q = 0; flg = 18; } setuid(olduser); return TRUE; } ctr(p) char *p; { return max((80 - strlen(p))/2,0); } opabort() { char lastkey; if (bdos(66)) { /* local console input status */ if ((lastkey = bdos(67) & 0xff) == ESC) { flush(); report(MESSAGE,"Operator abort"); QuitFlag = TRUE; } } return QuitFlag; } /* * readock(timeout, count) reads character(s) from modem * (1 <= count <= 3) * it attempts to read count characters. If it gets more than one, * it is an error unless all are CAN * (otherwise, only normal response is ACK, CAN, or C) * * timeout is in tenths of seconds */ readock(timeout, count) int timeout, count; { static int c; static char byt[5]; c = mread(byt,count,timeout); if (c < 1) return TIMEOUT; if (c == 1) return (byt[0] & 0xff); else while (c) if (byt[--c] != CAN) return NERROR; return CAN; } readline(n) int n; { return (readock(n,1)); } putlabel(string) char string[]; { cls(); locate(0,ctr(string) - 1); /* Centre on top line */ stndout(); /* Inverse video */ lprint(string); /* Print the string */ stndend(); /* Inverse off */ } killlabel() /*disable 25th line*/ { cls(); /* just clear screen */ } box() /* put box on screen for file transfer */ { register int i; static char *headings[] = { "","Protocol:","File Name:","File Size:", "Block Check:","Transfer Time:", "Bytes Transferred:","Blocks Transferred:", "Sectors in File:","Error Count:", "Last Message: NONE" }; static int start[] = { 0,13+LC,12+LC,12+LC,10+LC,8+LC,4+LC,3+LC,6+LC, 10+LC,9+LC }; LOCATE(TR,LC); lputch(UL); for (i = 1; i < WD-1; i++) lputch(HORIZ); lputch(UR); LOCATE(BR,LC); lputch(LL); for (i = 1; i < WD-1; i++) lputch(HORIZ); lputch(LR); for (i = 1; i < HT-1; i++) { LOCATE(TR+i,LC); lputch(VERT); LOCATE(TR+i,RC); lputch(VERT); } clrbox(); for (i=1; i<11; i++) { locate(TR+i,start[i]); lprint(headings[i]); } } clrbox() { register int i; for (i=TR+1; i < BR; i++) { locate(i,LC+1); lprint(" "); } } mread(buffer, count, timeout) /* time in tenths of secs */ char *buffer; int count, timeout; { int i, c; i = 0; while (!(c = mrd()) && (timeout--) && !opabort()); if (c) buffer[i++] = mcharinp(); return i; } mcharinp() { static unsigned c; c = mchin(); if (Stopped) { mchout(CTRLQ); Stopped = FALSE; } return c; } mcharout(c) char c; { while (!moutrdy()) opabort(); /* Test for operator abort while we wait */ mchout(c); /* Then send it */ } minprdy() { return mirdy() || Stopped; } /* Check transmission time of a batch of files and return error if too long */ checktime(count,list) short count; char *list[]; { short result = NERROR, i, mins, ksize, lcount = 0; unsigned short baudrate, curtime, maxtime; long total_size = 0L; struct stat fs; char filename[20]; if (!Shutup) printf("Calculating...."); for (i = 0; i < count; i++) { strcpy(filename,list[i]); if (Private) { deldrive(filename); addu(filename,Dprivdrive,Dprivuser); } if (!checkname(filename)) { /* only if it's ok to send */ fstat(filename,&fs); /* add file length */ total_size += (long)fs.records * 128L; lcount++; /* bump local count */ } if (!Shutup) printf("."); /* reassure user we're still awake */ } if (lcount) { /* if there's any to send, */ /* calculate transmission time */ baudrate = Baudtable[Current.cbaudindex]; mins = ((int) (total_size / (baudrate * 9 / 100)) / 60) + 1; curtime = bdos(79); /* current time on system */ maxtime = bdos(81,255); /* max time allowed on system (0 = no limit) */ if (!maxtime || (mins < (maxtime - curtime))) { result = OK; ksize = (short)(total_size / 1024L) + 1; if (!Shutup) printf("\n%dk in %d files, transmission time around %d minutes.\n", ksize,lcount,mins); } else printf("\nInsufficient time remaining."); } if (result == NERROR) printf("\nNo files sent.\n"); return result; } /* Try to open temporary .LOG file */ /* File is only opened if a non-zero value is set for the .LOG file drive, */ /* and if either the user isn't a wheel or if Logwheel is set true */ openlog() { char filename[20], *malloc(); Outopen = FALSE; if (Logdrive && (!(*Wheel) || Logwheel)) { strcpy(filename,Outfile); addu(filename,Logdrive,Loguser); unlink(filename); /* erase any already there */ Outbuf = malloc(SECSIZ); if (!allocerror(Outbuf)) { /* get a 128-byte buffer */ Outfd = creat(filename,0); /* Then try to open it */ Outopen = (Outfd != UBIOT); /* set the flag */ memset( Outbuf, 0x1a, SECSIZ); /* fill the buffer */ } } } /* Close temporary .log file */ closelog() { if (Outopen) { /* only if it's open */ putlog(CPMEOF, TRUE); /* store a 1a hex and flush */ close(Outfd); /* then close the file */ } } /* Store a filename and other data in the temporary file */ savelog(filename, nrbytes) char *filename; long nrbytes; { char c, *p, *itoa(), *ttime(); if (Outopen) { /* only if open */ p = ttime(nrbytes); /* store transmission time */ while (*p) putlog(*p++,FALSE); putlog(' ',FALSE); while (c = *filename++) putlog(c,FALSE); /* store the name */ putlog(' ',FALSE); p = itoa(((short) (nrbytes / 1024L)) + 1); /* calculate length in k */ while (*p) putlog(*p++,FALSE); /* store */ putlog('k',FALSE); putlog(CR,FALSE); /* then cr/lf */ putlog(LF,FALSE); } } /* Put a character in the temporary file and write the sector if full */ /* Flush the buffer to disk if flag is true */ /* Assumes the file has been checked and found open */ putlog(c, flag) char c; short flag; { static short i = 0; /* pointer to place in buffer */ short bytes; Outbuf[i++] = c; /* store the character */ if ((i == SECSIZ) || flag){ /* if buffer full or flag set, */ bytes = write(Outfd, Outbuf, SECSIZ); /* write it */ if (bytes != SECSIZ) { /* error */ Outopen = FALSE; /* say it's closed */ perror("Can\'t write output file."); } memset( Outbuf, 0x1a, SECSIZ); /* fill the buffer */ i = 0; /* reset the pointer */ } } /* End of RZMP module 3 */