1438 lines
24 KiB
Plaintext
1438 lines
24 KiB
Plaintext
makefile
|
||
OBJ=access.o bdos.o begin.o blkio.o ceof.o close.o croot.o csread.o exec.o\
|
||
execl.o fcbinit.o find.o ioctl.o isatty.o lseek.o open.o read.o rename.o\
|
||
sbrk.o stkover.o unlink.o user.o write.o
|
||
|
||
CC=cc
|
||
AS=as
|
||
MODEL=
|
||
AMODEL=0
|
||
|
||
.c.o:
|
||
$(CC) +$(MODEL) -n $*.c -o $@
|
||
sqz $@
|
||
|
||
.asm.o:
|
||
$(AS) -dMODEL=$(AMODEL) $*.asm -o $@
|
||
sqz $@
|
||
|
||
bld: $(OBJ)
|
||
@echo cpm86 done
|
||
access.c
|
||
/* Copyright (C) 1982 by Manx Software Systems */
|
||
#include "errno.h"
|
||
#include "fcntl.h"
|
||
#include "io.h"
|
||
|
||
access(path, amode)
|
||
char *path;
|
||
{
|
||
register int fd;
|
||
|
||
if ((fd = open(path, amode&2 ? 1 : 0)) != -1) {
|
||
close(fd);
|
||
fd = 0;
|
||
}
|
||
return fd;
|
||
}
|
||
|
||
bdos.asm
|
||
; :ts=8
|
||
; Copyright (C) 1983 by Manx Software Systems
|
||
codeseg segment para public 'code'
|
||
assume cs:codeseg
|
||
;
|
||
public bdos_
|
||
bdos_ proc near
|
||
push bp
|
||
mov bp,sp
|
||
push di
|
||
push si
|
||
mov cx,word ptr 4[bp]
|
||
mov dx,word ptr 6[bp]
|
||
int 224
|
||
pop si
|
||
pop di
|
||
pop bp
|
||
and ax,255
|
||
ret
|
||
;
|
||
bdos_ endp
|
||
codeseg ends
|
||
end
|
||
begin.asm
|
||
; Copyright (C) 1983, 1984 by Manx Software Systems
|
||
; :ts=8
|
||
codeseg segment word public 'code'
|
||
public $MEMRY
|
||
public _mbot_, _sbot_
|
||
dataseg segment word public 'data'
|
||
$MEMRY dw -1
|
||
public errno_
|
||
errno_ dw 0
|
||
public _dsval_,_csval_
|
||
_dsval_ dw 0
|
||
_csval_ dw 0
|
||
_mbot_ dw 0
|
||
_sbot_ dw 0
|
||
exitad dw 0
|
||
exitcs dw 0
|
||
bad8087 db "8087/80287 is required!",13,10,'$'
|
||
extrn _Uorg_:byte,_Uend_:byte
|
||
dataseg ends
|
||
|
||
assume cs:codeseg,ds:dataseg,es:dataseg,ss:dataseg
|
||
extrn Croot_:near
|
||
extrn $fltinit:near
|
||
public $begin
|
||
public _exit_
|
||
$begin proc far
|
||
pop exitad
|
||
pop exitcs
|
||
cli
|
||
mov ax,ds
|
||
mov es,ax
|
||
mov ss,ax
|
||
mov sp,word ptr ds:[6]
|
||
and sp,-2
|
||
sti
|
||
cld
|
||
; clear uninitialized data
|
||
mov di,offset _Uorg_
|
||
mov cx,offset _Uend_
|
||
sub cx,di
|
||
inc cx
|
||
shr cx,1
|
||
jcxz noclear
|
||
sub ax,ax
|
||
rep stosw
|
||
noclear:
|
||
mov ax,$MEMRY ;save memory allocation info for sbrk()
|
||
mov _mbot_,ax
|
||
add ax,512
|
||
mov _sbot_,ax
|
||
mov _dsval_,ds
|
||
mov _csval_,cs
|
||
call $fltinit
|
||
jc no_8087
|
||
call Croot_
|
||
_exit_:
|
||
sub cx,cx
|
||
sub dx,dx
|
||
jmp dword ptr exitad
|
||
;
|
||
no_8087:
|
||
mov cx,9 ;cp/m print message
|
||
mov dx,offset bad8087
|
||
int 254 ;tell the user about it
|
||
jmp short _exit_
|
||
|
||
$begin endp
|
||
|
||
public _sig_setup_
|
||
_sig_setup_ proc near
|
||
ret
|
||
_sig_setup_ endp
|
||
|
||
|
||
codeseg ends
|
||
end $begin
|
||
blkio.asm
|
||
; :ts=8
|
||
; Copyright (C) 1983 by Manx Software Systems
|
||
codeseg segment para public 'code'
|
||
dataseg segment para public 'data'
|
||
extrn errno_:word
|
||
dataseg ends
|
||
|
||
assume cs:codeseg,ds:dataseg,es:dataseg,ss:dataseg
|
||
public blkrd_
|
||
blkrd_ proc near
|
||
mov cl,33 ;set function to read sequential
|
||
jmp short rdwrt
|
||
;
|
||
public blkwr_
|
||
blkwr_:
|
||
mov cl,34 ;set function to write sequential
|
||
rdwrt:
|
||
push bp
|
||
mov bp,sp
|
||
push di
|
||
push si
|
||
push cx ;save function code on stack
|
||
ioloop:
|
||
mov dx,6[bp]
|
||
add word ptr 6[bp],128 ;bump to next 128 byte position
|
||
push bp
|
||
mov cl,26 ;set DMA address
|
||
int 224
|
||
pop bp
|
||
pop cx
|
||
push cx
|
||
push bp
|
||
mov dx,4[bp]
|
||
int 224 ;read or write sector
|
||
pop bp
|
||
and ax,0ffH
|
||
jnz ioerr
|
||
mov bx,4[bp] ;get fcb address
|
||
add word ptr 33[bx],1 ;increment random record #
|
||
adc byte ptr 35[bx],0
|
||
dec word ptr 8[bp]
|
||
jnz ioloop
|
||
blkexit:
|
||
pop cx ;pull function code from stack
|
||
mov ax,word ptr 8[bp] ;get number of sectors remaining
|
||
pop si
|
||
pop di
|
||
pop bp
|
||
test ax,ax
|
||
ret ;all done, return number remaining
|
||
;
|
||
ioerr:
|
||
cmp al,1
|
||
je blkexit
|
||
cmp al,4
|
||
je blkexit
|
||
mov errno_,ax
|
||
jmp blkexit
|
||
blkrd_ endp
|
||
codeseg ends
|
||
end
|
||
c86.bld
|
||
stdio/tmpfile.o
|
||
stdio/perror.o
|
||
stdio/fdopen.o
|
||
stdio/fgets.o
|
||
stdio/fopen.o
|
||
stdio/assert.o
|
||
stdio/fprintf.o
|
||
stdio/fputs.o
|
||
stdio/fread.o
|
||
stdio/fscanf.o
|
||
stdio/fseek.o
|
||
stdio/fwrite.o
|
||
stdio/gets.o
|
||
stdio/getchar.o
|
||
stdio/getw.o
|
||
stdio/printf.o
|
||
stdio/puterr.o
|
||
stdio/puts.o
|
||
stdio/putchar.o
|
||
stdio/aputc.o
|
||
stdio/putw.o
|
||
stdio/putc.o
|
||
stdio/scanf.o
|
||
stdio/agetc.o
|
||
stdio/getc.o
|
||
stdio/getbuff.o
|
||
stdio/setbuf.o
|
||
stdio/ungetc.o
|
||
stdio/tmpnam.o
|
||
stdio/mktemp.o
|
||
misc/atoi.o
|
||
misc/atol.o
|
||
misc/calloc.o
|
||
misc/qsort.o
|
||
misc/sscanf.o
|
||
misc/scan.o
|
||
misc/rand.o
|
||
misc/abort.o
|
||
misc/raise.o
|
||
misc/signal.o
|
||
misc/malloc.o
|
||
misc/sprintf.o
|
||
misc/format.o
|
||
misc/ctype.o
|
||
mch86/cswt.o
|
||
mch86/cswit.o
|
||
mch86/clswit.o
|
||
mch86/farcall.o
|
||
mch86/fcall.o
|
||
mch86/index.o
|
||
mch86/lsubs.o
|
||
mch86/olsubs.o
|
||
mch86/peek.o
|
||
mch86/port.o
|
||
mch86/rindex.o
|
||
mch86/segread.o
|
||
mch86/setjmp.o
|
||
mch86/strlen.o
|
||
mch86/strncpy.o
|
||
mch86/swapmem.o
|
||
mch86/sysint.o
|
||
mch86/toupper.o
|
||
cpm86/sbrk.o
|
||
mch86/memccpy.o
|
||
mch86/memchr.o
|
||
mch86/memcmp.o
|
||
mch86/memcpy.o
|
||
mch86/memset.o
|
||
cpm86/access.o
|
||
cpm86/csread.o
|
||
mch86/movblock.o
|
||
cpm86/execl.o
|
||
cpm86/exec.o
|
||
cpm86/ioctl.o
|
||
cpm86/isatty.o
|
||
cpm86/lseek.o
|
||
cpm86/read.o
|
||
cpm86/rename.o
|
||
cpm86/write.o
|
||
cpm86/blkio.o
|
||
mch86/csav.o
|
||
mch86/pointers.o
|
||
mch86/fptrs.o
|
||
mch86/ptrdiff.o
|
||
mch86/ptradd.o
|
||
mch86/strchr.o
|
||
mch86/strrchr.o
|
||
cpm86/stkover.o
|
||
cpm86/begin.o
|
||
cpm86/croot.o
|
||
cpm86/close.o
|
||
cpm86/open.o
|
||
mch86/strcmp.o
|
||
cpm86/ceof.o
|
||
cpm86/find.o
|
||
mch86/setmem.o
|
||
mch86/strcat.o
|
||
mch86/strcpy.o
|
||
mch86/movmem.o
|
||
cpm86/unlink.o
|
||
mch86/fltstub.o
|
||
cpm86/bdos.o
|
||
cpm86/fcbinit.o
|
||
cpm86/user.o
|
||
ceof.c
|
||
/* Copyright (C) 1984 by Manx Software Systems */
|
||
#include "io.h"
|
||
#include "errno.h"
|
||
|
||
_Ceof(fp)
|
||
register struct fcbtab *fp;
|
||
{
|
||
register char *cp;
|
||
|
||
bdos(FILSIZ, &fp->fcb);
|
||
if (fp->fcb.f_record == 0) {
|
||
fp->offset = 0;
|
||
return 0;
|
||
}
|
||
--fp->fcb.f_record; /* backup to last record */
|
||
if (_find(fp))
|
||
return -1;
|
||
|
||
for (cp = Wrkbuf+128 ; cp > Wrkbuf ; )
|
||
if (*--cp != 0x1a) {
|
||
++cp;
|
||
break;
|
||
}
|
||
if ((fp->offset = (char)((int)(cp-Wrkbuf))) == 128) {
|
||
++fp->fcb.f_record;
|
||
fp->offset = 0;
|
||
}
|
||
return 0;
|
||
}
|
||
close.c
|
||
/* Copyright (C) 1982 by Manx Software Systems */
|
||
#include "errno.h"
|
||
#include "io.h"
|
||
|
||
close(fd)
|
||
{
|
||
register struct channel *chp;
|
||
extern int bdf_();
|
||
|
||
if (fd < 0 || fd > MAXCHAN) {
|
||
errno = EBADF;
|
||
return -1;
|
||
}
|
||
chp = &chantab[fd];
|
||
fd = (*chp->c_close)(chp->c_arg);
|
||
chp->c_read = chp->c_write = chp->c_ioctl = chp->c_seek = 0;
|
||
chp->c_close = bdf_;
|
||
return fd;
|
||
}
|
||
croot.c
|
||
/* Copyright (C) 1981,1982,1984 by Manx Software Systems */
|
||
#include "errno.h"
|
||
#include "fcntl.h"
|
||
#include "io.h"
|
||
|
||
int bdf_(), ret_();
|
||
|
||
/*
|
||
* channel table: relates fd's to devices
|
||
*/
|
||
struct channel chantab[] = {
|
||
{ 2, 0, 1, 0, ret_, (_arg)2 },
|
||
{ 0, 2, 1, 0, ret_, (_arg)2 },
|
||
{ 0, 2, 1, 0, ret_, (_arg)2 },
|
||
{ 0, 0, 0, 0, bdf_, (_arg)0 },
|
||
{ 0, 0, 0, 0, bdf_, (_arg)0 },
|
||
{ 0, 0, 0, 0, bdf_, (_arg)0 },
|
||
{ 0, 0, 0, 0, bdf_, (_arg)0 },
|
||
{ 0, 0, 0, 0, bdf_, (_arg)0 },
|
||
{ 0, 0, 0, 0, bdf_, (_arg)0 },
|
||
{ 0, 0, 0, 0, bdf_, (_arg)0 },
|
||
{ 0, 0, 0, 0, bdf_, (_arg)0 },
|
||
};
|
||
|
||
#define MAXARGS 30
|
||
static char *Argv[MAXARGS];
|
||
static char Argbuf[128];
|
||
static int Argc;
|
||
int (*cls_)() = ret_;
|
||
|
||
Croot()
|
||
{
|
||
register char *cp, *fname;
|
||
register int k;
|
||
|
||
movmem((char *)0x81, Argbuf, 127);
|
||
Argbuf[*(char *)0x80 & 0x7f] = 0;
|
||
Argv[0] = "";
|
||
cp = Argbuf;
|
||
Argc = 1;
|
||
while (Argc < MAXARGS) {
|
||
while (*cp == ' ' || *cp == '\t')
|
||
++cp;
|
||
if (*cp == 0)
|
||
break;
|
||
#ifndef NOREDIR
|
||
if (*cp == '>') { /* redirect output */
|
||
k = 1;
|
||
goto redirect;
|
||
} else if (*cp == '<') { /* redirect input */
|
||
k = 0;
|
||
redirect:
|
||
while (*++cp == ' ' || *cp == '\t')
|
||
;
|
||
fname = cp;
|
||
while (*++cp)
|
||
if (*cp == ' ' || *cp == '\t') {
|
||
*cp++ = 0;
|
||
break;
|
||
}
|
||
close(k);
|
||
if (k)
|
||
k = creat(fname, 0666);
|
||
else
|
||
k = open(fname, O_RDONLY);
|
||
if (k == -1) {
|
||
strcpy(0x80, "Can't open file for redirection: ");
|
||
strcat(0x80, fname);
|
||
strcat(0x80, "$");
|
||
bdos(9,0x80);
|
||
exit(10);
|
||
}
|
||
} else
|
||
#endif
|
||
{
|
||
Argv[Argc++] = cp;
|
||
while (*++cp)
|
||
if (*cp == ' ' || *cp == '\t') {
|
||
*cp++ = 0;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
main(Argc,Argv);
|
||
exit(0);
|
||
}
|
||
|
||
exit(code)
|
||
{
|
||
register int fd;
|
||
|
||
(*cls_)();
|
||
for (fd = 0 ; fd < MAXCHAN ; )
|
||
close(fd++);
|
||
if (code && (bdos(24)&1) != 0)
|
||
unlink("A:$$$.SUB");
|
||
_exit();
|
||
}
|
||
|
||
bdf_()
|
||
{
|
||
errno = EBADF;
|
||
return -1;
|
||
}
|
||
|
||
ret_()
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
csread.c
|
||
/* Copyright (C) 1983, 1984 by Manx Software Systems */
|
||
#include "io.h"
|
||
#include "errno.h"
|
||
|
||
extern int errno;
|
||
extern unsigned _dsval, _csval;
|
||
|
||
_csread(fd, buffer, len)
|
||
char *buffer;
|
||
{
|
||
register unsigned l = 0;
|
||
register struct fcbtab *fp;
|
||
register struct channel *chp;
|
||
unsigned k,j;
|
||
|
||
chp = &chantab[fd];
|
||
if (chp->c_read != 1) { /* only valid for disk files */
|
||
errno = EINVAL;
|
||
return -1;
|
||
}
|
||
|
||
fp = (struct fcbtab *)chp->c_arg;
|
||
setusr(fp->user);
|
||
|
||
if (fp->offset) {
|
||
if ((l = 128 - fp->offset) > len)
|
||
l = len;
|
||
if (getsect(fp, buffer, l)) {
|
||
l = 0;
|
||
goto done;
|
||
}
|
||
}
|
||
if (k = (len-l)/128) {
|
||
bdos(51, _csval); /* set dma segment to CS */
|
||
j = blkrd(&fp->fcb, buffer+l, k);
|
||
bdos(51, _dsval); /* set dma segment back to DS */
|
||
if (j != 0) {
|
||
l += (k-j)*128;
|
||
goto done;
|
||
}
|
||
}
|
||
l += k*128;
|
||
if (l < len)
|
||
if (getsect(fp, buffer+l, len-l))
|
||
goto done;
|
||
l = len;
|
||
|
||
done:
|
||
rstusr();
|
||
return l;
|
||
}
|
||
|
||
static
|
||
getsect(fp, buf, len)
|
||
register struct fcbtab *fp; char *buf; unsigned len;
|
||
{
|
||
if (_find(fp))
|
||
return -1;
|
||
movblock(Wrkbuf+fp->offset,_dsval, buf,_csval, len);
|
||
if ((fp->offset = (fp->offset + len) & 127) == 0)
|
||
++fp->fcb.f_record;
|
||
return 0;
|
||
}
|
||
|
||
exec.c
|
||
/* Copyright (C) 1983, 1984 by Manx Software Systems */
|
||
|
||
execlp(path, args)
|
||
char *path, *args;
|
||
{
|
||
return execvp(path, &args);
|
||
}
|
||
|
||
execvp(path, argv)
|
||
char *path, **argv;
|
||
{
|
||
char buffer[130];
|
||
register char *cp, *xp;
|
||
|
||
cp = buffer;
|
||
for (xp = path ; *xp && cp < buffer+128 ; )
|
||
*cp++ = *xp++;
|
||
if (*argv) {
|
||
++argv; /* skip arg0, used for unix (tm) compatibility */
|
||
while (*argv) {
|
||
*cp++ = ' ';
|
||
for (xp = *argv++ ; *xp && cp < buffer+128 ; )
|
||
*cp++ = *xp++;
|
||
}
|
||
}
|
||
*cp = 0;
|
||
bdos(26, buffer);
|
||
bdos(47, 0);
|
||
}
|
||
|
||
execl.c
|
||
/* Copyright (C) 1983, 1984 by Manx Software Systems */
|
||
|
||
execl(path, args)
|
||
char *path, *args;
|
||
{
|
||
return execvp(path, &args);
|
||
}
|
||
|
||
execv(path, argv)
|
||
char *path, **argv;
|
||
{
|
||
return execvp(path, argv);
|
||
}
|
||
fcbinit.asm
|
||
; :ts=8
|
||
; Copyright (C) 1983, 1984 by Manx Software Systems
|
||
codeseg segment para public 'code'
|
||
;
|
||
include lmacros.h
|
||
public fcbinit_
|
||
fcbinit_ proc near
|
||
mov bx,sp
|
||
push di
|
||
push si
|
||
cld
|
||
ifndef LONGPTR
|
||
mov di,ds
|
||
mov es,di
|
||
endif
|
||
mov si,word ptr 2[bx] ;si contains name
|
||
mov di,word ptr 4[bx] ;di contains fcb address
|
||
; clear name to blanks
|
||
mov dx,di ;save fcb address in dx
|
||
inc di
|
||
mov cx,11 ;clear name and ext to blanks
|
||
mov al,' '
|
||
rep stosb
|
||
mov cx,4
|
||
sub al,al
|
||
rep stosb
|
||
mov di,dx ;restore fcb address
|
||
;
|
||
sub dx,dx ;init user #
|
||
mov cl,10 ;multiplier inside loop
|
||
userloop: ;loop packing leading digits into DL
|
||
lodsb
|
||
cmp al,'0'
|
||
jb userdone
|
||
cmp al,'9'
|
||
ja userdone
|
||
sub al,'0'
|
||
xchg ax,dx ;get accumlated value into AL for multiply
|
||
mul cl ;value *= 10
|
||
add al,dl ;add in new digit
|
||
xchg ax,dx ;put result back into DL
|
||
jmp userloop
|
||
;
|
||
userdone:
|
||
cmp al,'/' ;check if user # prefix
|
||
je haveuser
|
||
mov dl,255 ;set user # to default indicator
|
||
mov si,word ptr 2[bx] ;reset filename pointer
|
||
haveuser:
|
||
;
|
||
sub al,al ;default drive #
|
||
cmp byte ptr 1[si],':'
|
||
jnz setdrive
|
||
;
|
||
lodsb
|
||
inc si ;skip over colon
|
||
and al,127
|
||
cmp al,'A'
|
||
jl badname
|
||
cmp al,'Z'
|
||
jg lowerc
|
||
sub al,'A'-1
|
||
jmp short setdrive
|
||
;
|
||
lowerc:
|
||
cmp al,'a'
|
||
jl badname
|
||
cmp al,'z'
|
||
jg badname
|
||
sub al,'a'-1
|
||
setdrive:
|
||
stosb
|
||
; move name in mapping to upper case
|
||
mov cx,8
|
||
nameskp:
|
||
inc cx
|
||
namelp:
|
||
lodsb
|
||
cmp al,'.'
|
||
jz namedn
|
||
test al,al
|
||
jz alldone
|
||
loop store
|
||
jmp short nameskp
|
||
store:
|
||
call toupper
|
||
stosb
|
||
jmp short namelp
|
||
;
|
||
namedn:
|
||
dec cx
|
||
add di,cx
|
||
; move extension mapping to upper case
|
||
mov cx,3
|
||
extlp:
|
||
lodsb
|
||
test al,al
|
||
jz alldone
|
||
call toupper
|
||
stosb
|
||
loop extlp
|
||
;
|
||
alldone:
|
||
xchg ax,dx
|
||
and ax,255
|
||
retn:
|
||
pop si
|
||
pop di
|
||
ret
|
||
;
|
||
badname:
|
||
sub ax,ax
|
||
dec ax
|
||
jmp short retn
|
||
;
|
||
toupper:
|
||
cmp al,'*'
|
||
jne nostar
|
||
dec si ;backup so we see star again
|
||
mov al,'?' ;and map into question mark
|
||
ret
|
||
nostar:
|
||
cmp al,'a'
|
||
jl notrans
|
||
cmp al,'z'
|
||
jg notrans
|
||
sub al,'a'-'A'
|
||
notrans:
|
||
ret
|
||
fcbinit_ endp
|
||
codeseg ends
|
||
end
|
||
find.c
|
||
/* Copyright (C) 1984 by Manx Software Systems */
|
||
#include "io.h"
|
||
|
||
static struct fcbtab *Wfp;
|
||
static unsigned Wsct;
|
||
|
||
_zap() /* invalidate work buffer */
|
||
{
|
||
Wfp = 0;
|
||
}
|
||
|
||
_find(fp)
|
||
register struct fcbtab *fp;
|
||
{
|
||
extern int errno;
|
||
|
||
bdos(SETDMA, Wrkbuf);
|
||
if (Wfp != fp || fp->fcb.f_record != Wsct) {
|
||
if ((errno = bdos(READRN, &fp->fcb)) == 1 || errno == 4) {
|
||
errno = 0;
|
||
setmem(Wrkbuf, 128, 0x1a);
|
||
Wfp = 0;
|
||
return 1;
|
||
} else if (errno)
|
||
return -1;
|
||
Wfp = fp;
|
||
Wsct = fp->fcb.f_record;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
ioctl.c
|
||
/* Copyright (C) 1984 by Manx Software Systems */
|
||
#include "io.h"
|
||
#include "errno.h"
|
||
#include "sgtty.h"
|
||
|
||
#define TIME 10 /* number of iterations of raw_rd loop */
|
||
#define MIN 1 /* minimum number of chars returned from read */
|
||
|
||
extern int (*Rd_tab[])();
|
||
extern int (*Wrt_tab[])();
|
||
|
||
struct sgttyb Tty_ctl;
|
||
extern char _Eol;
|
||
extern int tty_rd();
|
||
static int raw_rd(), raw_wr();
|
||
static int rd_func, wrt_func;
|
||
|
||
ioctl(fd, cmd, arg)
|
||
struct sgttyb *arg;
|
||
{
|
||
register struct channel *chp;
|
||
|
||
chp = &chantab[fd];
|
||
if (chp->c_ioctl == 0) {
|
||
errno = ENOTTY;
|
||
return -1;
|
||
}
|
||
switch (cmd) {
|
||
case TIOCGETP:
|
||
*arg = Tty_ctl;
|
||
break;
|
||
case TIOCSETP:
|
||
Tty_ctl = *arg;
|
||
Wrt_tab[2] = raw_wr;
|
||
Rd_tab[2] = raw_rd;
|
||
if (Tty_ctl.sg_flags&RAW) {
|
||
rd_func =
|
||
wrt_func = 6;
|
||
_Eol = '\r';
|
||
break;
|
||
} else if (Tty_ctl.sg_flags&CBREAK) {
|
||
rd_func = (Tty_ctl.sg_flags&ECHO) ? 1 : 6;
|
||
wrt_func = 2;
|
||
} else {
|
||
Rd_tab[2] = tty_rd;
|
||
wrt_func = 2;
|
||
}
|
||
if (Tty_ctl.sg_flags&CRMOD)
|
||
_Eol = '\n';
|
||
else
|
||
_Eol = '\r';
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
raw_rd(x, buff, len)
|
||
register char *buff;
|
||
{
|
||
int c, i;
|
||
register int count;
|
||
|
||
for (count = 0 ; count < len ; ) {
|
||
for (i = TIME ; i-- ; )
|
||
if ((c = bdos(rd_func,0xff)) != 0)
|
||
goto have_char;
|
||
if (count < MIN)
|
||
continue;
|
||
break;
|
||
have_char:
|
||
if (c == '\r')
|
||
c = _Eol;
|
||
*buff++ = c;
|
||
++count;
|
||
}
|
||
return count;
|
||
}
|
||
|
||
raw_wr(kind, buff, len)
|
||
register char *buff;
|
||
{
|
||
register int count;
|
||
|
||
for (count = len ; count-- ; ) {
|
||
if (*buff == '\n' && (Tty_ctl.sg_flags&CRMOD))
|
||
bdos(wrt_func,'\r');
|
||
bdos(wrt_func,*buff++);
|
||
}
|
||
return len;
|
||
}
|
||
isatty.c
|
||
/* Copyright (C) 1983 by Manx Software Systems */
|
||
#include "io.h"
|
||
#include "errno.h"
|
||
|
||
isatty(fd)
|
||
{
|
||
return chantab[fd].c_ioctl;
|
||
}
|
||
|
||
lseek.c
|
||
/* Copyright (C) 1982, 1984 by Manx Software Systems */
|
||
#include "io.h"
|
||
#include "errno.h"
|
||
|
||
long lseek(fd, pos, how)
|
||
long pos;
|
||
{
|
||
register struct fcbtab *fp;
|
||
|
||
if (chantab[fd].c_seek == 0) {
|
||
Badf:
|
||
errno = EBADF;
|
||
return -1L;
|
||
}
|
||
fp = (struct fcbtab *)chantab[fd].c_arg;
|
||
|
||
switch (how) {
|
||
case 2:
|
||
/*
|
||
* Close the file because CP/M doesn't know how big an open file is.
|
||
* However, the fcb is still valid.
|
||
*/
|
||
setusr(fp->user);
|
||
fp->fcb.f_name[4] |= 0x80; /* set parital close flag for MP/M */
|
||
bdos(CLSFIL, &fp->fcb);
|
||
fp->fcb.f_name[4] &= 0x7f; /* clear parital close flag */
|
||
_Ceof(fp);
|
||
rstusr();
|
||
case 1:
|
||
pos += fp->offset + ((long)fp->fcb.f_record << 7);
|
||
case 0:
|
||
break;
|
||
|
||
default:
|
||
errno = EINVAL;
|
||
return -1L;
|
||
}
|
||
|
||
fp->fcb.f_overfl = 0;
|
||
if (pos < 0) {
|
||
fp->offset = fp->fcb.f_record = 0;
|
||
errno = EINVAL;
|
||
return -1L;
|
||
}
|
||
fp->offset = (unsigned)pos & 127;
|
||
fp->fcb.f_record = pos >> 7;
|
||
return pos;
|
||
}
|
||
|
||
open.c
|
||
/* Copyright (C) 1982 by Manx Software Systems */
|
||
#include "errno.h"
|
||
#include "fcntl.h"
|
||
#include "io.h"
|
||
|
||
#define MAXFILE 8 /* maximum number of open DISK files */
|
||
int bdf_(), ret_(), fileop();
|
||
/*
|
||
* note: The ioctl function knows that the condev read/write numbers are
|
||
* 2. It uses this information to patch the read/write tables.
|
||
*/
|
||
static struct device condev = { 2, 2, 1, 0, ret_ };
|
||
static struct device bdosout= { 0, 3, 0, 0, ret_ };
|
||
static struct device bdosin = { 3, 0, 0, 0, ret_ };
|
||
static struct device filedev= { 1, 1, 0, 1, fileop };
|
||
|
||
/*
|
||
* device table, contains names and pointers to device entries
|
||
*/
|
||
static struct devtabl devtabl[] = {
|
||
{ "con:", &condev, (_arg)2 },
|
||
{ "CON:", &condev, (_arg)2 },
|
||
{ "lst:", &bdosout,(_arg)5 },
|
||
{ "LST:", &bdosout,(_arg)5 },
|
||
{ "prn:", &bdosout,(_arg)5 },
|
||
{ "PRN:", &bdosout,(_arg)5 },
|
||
{ "pun:", &bdosout,(_arg)4 },
|
||
{ "PUN:", &bdosout,(_arg)4 },
|
||
{ "rdr:", &bdosin, (_arg)3 },
|
||
{ "RDR:", &bdosin, (_arg)3 },
|
||
{ 0, &filedev, (_arg)0 } /* this must be the last slot in the table! */
|
||
};
|
||
|
||
|
||
creat(name, mode)
|
||
char *name;
|
||
{
|
||
return open(name, O_WRONLY|O_TRUNC|O_CREAT, mode);
|
||
}
|
||
|
||
open(name, flag, mode)
|
||
char *name;
|
||
{
|
||
register struct devtabl *dp;
|
||
register struct channel *chp;
|
||
register struct device *dev;
|
||
int fd, mdmask;
|
||
|
||
for (chp = chantab, fd = 0 ; fd < MAXCHAN ; ++chp, ++fd)
|
||
if (chp->c_close == bdf_)
|
||
goto fndchan;
|
||
errno = EMFILE;
|
||
return -1;
|
||
|
||
fndchan:
|
||
for (dp = devtabl ; dp->d_name ; ++dp)
|
||
if (strcmp(dp->d_name, name) == 0)
|
||
break;
|
||
dev = dp->d_dev;
|
||
mdmask = (flag&3) + 1;
|
||
if (mdmask&1) {
|
||
if ((chp->c_read = dev->d_read) == 0) {
|
||
errno = EACCES;
|
||
return -1;
|
||
}
|
||
}
|
||
if (mdmask&2) {
|
||
if ((chp->c_write = dev->d_write) == 0) {
|
||
errno = EACCES;
|
||
return -1;
|
||
}
|
||
}
|
||
chp->c_arg = dp->d_arg;
|
||
chp->c_ioctl = dev->d_ioctl;
|
||
chp->c_seek = dev->d_seek;
|
||
chp->c_close = ret_;
|
||
if ((*dev->d_open)(name, flag, mode, chp, dp) < 0) {
|
||
chp->c_close = bdf_;
|
||
return -1;
|
||
}
|
||
return fd;
|
||
}
|
||
|
||
static struct fcbtab fcbtab[MAXFILE];
|
||
|
||
static
|
||
fileop(name,flag,mode,chp,dp)
|
||
char *name; struct channel *chp; struct devtabl *dp;
|
||
{
|
||
register struct fcbtab *fp;
|
||
int filecl();
|
||
int user;
|
||
|
||
for ( fp = fcbtab ; fp < fcbtab+MAXFILE ; ++fp )
|
||
if ( fp->flags == 0 )
|
||
goto havefcb;
|
||
errno = EMFILE;
|
||
return -1;
|
||
|
||
havefcb:
|
||
if ((user = fcbinit(name,&fp->fcb)) == -1) {
|
||
errno = EINVAL;
|
||
return -1;
|
||
}
|
||
if (user == 255)
|
||
user = getusr();
|
||
setusr(user);
|
||
if (flag & O_TRUNC)
|
||
bdos(DELFIL, &fp->fcb);
|
||
if (bdos(OPNFIL,&fp->fcb) == 0xff) {
|
||
if ((flag&(O_TRUNC|O_CREAT)) == 0 || bdos(MAKFIL,&fp->fcb) == 0xff) {
|
||
errno = ENOENT;
|
||
rstusr();
|
||
return -1;
|
||
}
|
||
} else if ((flag&(O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) {
|
||
errno = EEXIST;
|
||
goto punt;
|
||
} else if ((flag&3) > 0 && fp->fcb.f_type[0]&0x80) {
|
||
errno = EACCES;
|
||
punt:
|
||
bdos(CLSFIL, &fp->fcb);
|
||
rstusr();
|
||
return -1;
|
||
}
|
||
|
||
fp->offset = fp->fcb.f_overfl = fp->fcb.f_record = 0;
|
||
fp->user = user;
|
||
chp->c_arg = (_arg)fp;
|
||
fp->flags = (flag&3)+1;
|
||
chp->c_close = filecl;
|
||
if (flag&O_APPEND)
|
||
_Ceof(fp);
|
||
rstusr();
|
||
return 0;
|
||
}
|
||
|
||
static
|
||
filecl(fp)
|
||
register struct fcbtab *fp;
|
||
{
|
||
_zap(); /* zap work buffer, so data is not reused */
|
||
setusr(fp->user);
|
||
bdos(CLSFIL,&fp->fcb);
|
||
rstusr();
|
||
fp->flags = 0;
|
||
return 0;
|
||
}
|
||
|
||
read.c
|
||
/* Copyright (C) 1983, 1984 by Manx Software Systems */
|
||
#include "io.h"
|
||
#include "errno.h"
|
||
#include "fcntl.h"
|
||
|
||
int bdf_(), filerd(), tty_rd(), bdosrd();
|
||
|
||
int (*Rd_tab[])() = {
|
||
bdf_, filerd, tty_rd, bdosrd,
|
||
};
|
||
extern int errno;
|
||
|
||
read(fd, buff, len)
|
||
char *buff;
|
||
{
|
||
register struct channel *chp;
|
||
|
||
chp = &chantab[fd];
|
||
return (*Rd_tab[chp->c_read])((struct fcbtab *)chp->c_arg, buff, len);
|
||
}
|
||
|
||
static
|
||
filerd(afp,buffer,len)
|
||
struct fcbtab *afp;
|
||
char *buffer; unsigned len;
|
||
{
|
||
register unsigned l = 0;
|
||
register struct fcbtab *fp;
|
||
unsigned k,j;
|
||
|
||
fp = afp;
|
||
setusr(fp->user);
|
||
if (fp->offset) {
|
||
if ((l = 128 - fp->offset) > len)
|
||
l = len;
|
||
if (getsect(fp, buffer, l)) {
|
||
rstusr();
|
||
return 0;
|
||
}
|
||
}
|
||
if (k = (len-l)/128)
|
||
if ((j = blkrd(&fp->fcb, buffer+l, k)) != 0) {
|
||
rstusr();
|
||
return (k-j)*128 + l;
|
||
}
|
||
l += k*128;
|
||
if (l < len)
|
||
if (getsect(fp, buffer+l, len-l)) {
|
||
rstusr();
|
||
return l;
|
||
}
|
||
rstusr();
|
||
return len;
|
||
}
|
||
|
||
static
|
||
getsect(fp, buf, len)
|
||
register struct fcbtab *fp; char *buf; unsigned len;
|
||
{
|
||
if (_find(fp))
|
||
return -1;
|
||
movmem(Wrkbuf+fp->offset, buf, len);
|
||
if ((fp->offset = (fp->offset + len) & 127) == 0)
|
||
++fp->fcb.f_record;
|
||
return 0;
|
||
}
|
||
|
||
char _Eol = '\n';
|
||
|
||
tty_rd(x,buff,len)
|
||
char *buff;
|
||
{
|
||
static char buffer[258];
|
||
static int used;
|
||
register int l;
|
||
|
||
if (buffer[1] == 0) {
|
||
buffer[0] = 255;
|
||
buffer[1] = buffer[2] = 0;
|
||
bdos(10,buffer);
|
||
bdos(2,'\n');
|
||
if (buffer[2] == 0x1a) {
|
||
buffer[1] = 0;
|
||
return 0;
|
||
}
|
||
buffer[++buffer[1] + 1] = _Eol;
|
||
used = 2;
|
||
}
|
||
if ((l = buffer[1]) > len)
|
||
l = len;
|
||
movmem(buffer+used, buff, l);
|
||
used += l;
|
||
buffer[1] -= l;
|
||
return l;
|
||
}
|
||
|
||
static
|
||
bdosrd(kind, buff, len)
|
||
register char *buff;
|
||
{
|
||
register int count;
|
||
|
||
for (count = 0 ; count < len ; ++count) {
|
||
if ((*buff++ = bdos(kind)) == 0x1a)
|
||
break;
|
||
}
|
||
return count;
|
||
}
|
||
rename.c
|
||
/* Copyright (C) 1983, 1984 by Manx Software Systems */
|
||
#include "errno.h"
|
||
|
||
rename(old, new)
|
||
char *old, *new;
|
||
{
|
||
auto char buff[60];
|
||
register int user;
|
||
|
||
user = fcbinit(old,buff);
|
||
fcbinit(new,buff+16);
|
||
setusr(user);
|
||
user = 0;
|
||
if (bdos(15,buff+16) != 0xff) {
|
||
bdos(16,buff+16);
|
||
errno = EEXIST;
|
||
user = -1;
|
||
} else if (bdos(23,buff) == 0xff) {
|
||
errno = ENOENT;
|
||
user = -1;
|
||
}
|
||
rstusr();
|
||
return user;
|
||
}
|
||
sbrk.asm
|
||
; :ts=8
|
||
;Copyright (C) 1983 by Manx Software Systems
|
||
include lmacros.h
|
||
dataseg segment word public 'data'
|
||
extrn $MEMRY:word
|
||
extrn _mbot_:word, _sbot_:word
|
||
extrn errno_:word
|
||
stkred dw 512
|
||
dataseg ends
|
||
assume ds:dataseg
|
||
;
|
||
; sbrk(size): return address of current top & bump by size bytes
|
||
;
|
||
procdef sbrk,<<siz,word>>
|
||
push di
|
||
mov ax,siz
|
||
mov di,$MEMRY
|
||
add ax,di
|
||
push ax
|
||
call brk_
|
||
pop cx
|
||
jnz brk_error
|
||
mov ax,di ;return original value of the break
|
||
ifdef LONGPTR
|
||
mov dx,ds
|
||
pop di
|
||
pret
|
||
endif
|
||
brk_error:
|
||
pop di
|
||
ifdef LONGPTR
|
||
mov dx,ax
|
||
endif
|
||
test ax,ax ;set flags for C
|
||
pret
|
||
pend sbrk
|
||
;
|
||
; brk(addr): set current top address to addr
|
||
; returns 0 if ok, -1 if error
|
||
;
|
||
procdef brk,<<addr,word>>
|
||
mov ax,addr
|
||
inc ax
|
||
and al,-2
|
||
mov bx,sp
|
||
sub bx,stkred
|
||
cmp ax,bx ;double check with sp for saftey
|
||
jae brk_ov
|
||
cmp ax,_mbot_
|
||
jb brk_ov
|
||
mov $MEMRY,ax ;new value is good so save it away
|
||
add ax,stkred
|
||
mov _sbot_,ax
|
||
sub ax,ax
|
||
pret
|
||
; invalid request
|
||
brk_ov:
|
||
mov errno_,-4
|
||
mov ax,-1
|
||
test ax,ax
|
||
pret
|
||
pend brk
|
||
;
|
||
; rsvstk(size): set saftey margin for stack
|
||
; this will make sure that at least size
|
||
; bytes of stack below the current level remain.
|
||
;
|
||
procdef rsvstk,<<stksize,word>>
|
||
mov ax,stksize
|
||
mov stkred,ax
|
||
add ax,$MEMRY
|
||
mov _sbot_,ax
|
||
pret
|
||
pend rsvstk
|
||
finish
|
||
end
|
||
stkover.c
|
||
_stkover()
|
||
{
|
||
bdos(9, "STACK OVERFLOW, INCREASE STACK SIZE\r\n$");
|
||
_exit(200);
|
||
}
|
||
unlink.c
|
||
/* Copyright (C) 1983, 1984 by Manx Software Systems */
|
||
#include "errno.h"
|
||
|
||
unlink(name)
|
||
char *name;
|
||
{
|
||
auto char delfcb[40];
|
||
register int user;
|
||
|
||
user = fcbinit(name,delfcb);
|
||
setusr(user);
|
||
user = bdos(19,delfcb);
|
||
rstusr();
|
||
if (user == 0xff) {
|
||
errno = ENOENT;
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
user.asm
|
||
; Copyright (C) 1984 by Manx Software Systems
|
||
; :ts=8
|
||
|
||
codeseg segment para public 'code'
|
||
dataseg segment para public 'data'
|
||
olduser db 0
|
||
dataseg ends
|
||
assume cs:codeseg,ds:dataseg
|
||
public getusr_
|
||
getusr_ proc near
|
||
push bp
|
||
push si
|
||
push di
|
||
mov cl,32
|
||
mov dl,255
|
||
int 224
|
||
and ax,255
|
||
pop di
|
||
pop si
|
||
pop bp
|
||
ret
|
||
getusr_ endp
|
||
;
|
||
public setusr_
|
||
setusr_ proc near
|
||
push bp
|
||
mov bp,sp
|
||
push si
|
||
push di
|
||
mov cl,32
|
||
mov dl,255
|
||
int 224
|
||
mov olduser,al
|
||
;
|
||
mov dl,4[bp]
|
||
cmp dl,255
|
||
je skipset
|
||
mov cl,32
|
||
int 224
|
||
skipset:
|
||
pop di
|
||
pop si
|
||
pop bp
|
||
ret
|
||
setusr_ endp
|
||
;
|
||
public rstusr_
|
||
rstusr_ proc near
|
||
push bp
|
||
push si
|
||
push di
|
||
mov cl,32
|
||
mov dl,olduser
|
||
int 224
|
||
pop di
|
||
pop si
|
||
pop bp
|
||
ret
|
||
rstusr_ endp
|
||
codeseg ends
|
||
end
|
||
write.c
|
||
/* Copyright (C) 1983, 1984 by Manx Software Systems */
|
||
#include "io.h"
|
||
#include "errno.h"
|
||
|
||
int tty_wr(), bdoswr(), filewr(), bdf_();
|
||
|
||
int (*Wrt_tab[])() = {
|
||
bdf_, filewr, bdoswr, bdoswr
|
||
};
|
||
|
||
write(fd, buff, len)
|
||
char *buff;
|
||
{
|
||
register struct channel *chp;
|
||
|
||
chp = &chantab[fd];
|
||
return (*Wrt_tab[chp->c_write])((struct fcbtab *)chp->c_arg, buff, len);
|
||
}
|
||
|
||
static
|
||
filewr(afp,buffer,len)
|
||
struct fcbtab *afp;
|
||
char *buffer; unsigned len;
|
||
{
|
||
register unsigned l = 0;
|
||
register struct fcbtab *fp;
|
||
unsigned k,j;
|
||
|
||
fp = afp;
|
||
setusr(fp->user);
|
||
if (fp->offset) {
|
||
if ((l = 128 - fp->offset) > len)
|
||
l = len;
|
||
if (putsect(fp, buffer, l)) {
|
||
rstusr();
|
||
return -1;
|
||
}
|
||
}
|
||
if (k = (len-l)/128)
|
||
if ((j = blkwr(&fp->fcb, buffer+l, k)) != 0) {
|
||
rstusr();
|
||
if ((l += (k-j)*128) == 0)
|
||
return -1;
|
||
else
|
||
return l;
|
||
}
|
||
l += k*128;
|
||
if (l < len)
|
||
if (putsect(fp, buffer+l, len-l)) {
|
||
rstusr();
|
||
return l;
|
||
}
|
||
rstusr();
|
||
return len;
|
||
}
|
||
|
||
static
|
||
putsect(fp, buf, len)
|
||
register struct fcbtab *fp; char *buf; unsigned len;
|
||
{
|
||
if (_find(fp) < 0)
|
||
return -1;
|
||
movmem(buf, Wrkbuf+fp->offset, len);
|
||
if ((errno = bdos(WRITRN, &fp->fcb)) != 0)
|
||
return -1;
|
||
if ((fp->offset = (fp->offset + len) & 127) == 0)
|
||
++fp->fcb.f_record;
|
||
return 0;
|
||
}
|
||
|
||
tty_wr(kind, buff, len)
|
||
register char *buff;
|
||
{
|
||
register int count;
|
||
|
||
for (count = len ; count-- ; ) {
|
||
if (*buff == '\n')
|
||
bdos(2,'\r');
|
||
bdos(2,*buff++);
|
||
}
|
||
return len;
|
||
}
|
||
|
||
static
|
||
bdoswr(kind, buff, len)
|
||
register char *buff;
|
||
{
|
||
register int count;
|
||
|
||
for (count = len ; count-- ; )
|
||
bdos(kind,*buff++);
|
||
return len;
|
||
}
|
||
|
||
|