home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / commercial-software / programming / AZTEC302.ZIP / CPM86.ARC < prev    next >
Text File  |  1998-09-16  |  22KB  |  1,272 lines

  1. bdos.asm
  2. ; :ts=8
  3. ; Copyright (C) 1983 by Manx Software Systems
  4. codeseg    segment    para public 'code'
  5.     assume    cs:codeseg
  6. ;
  7.     public    bdos_
  8. bdos_    proc    near
  9.     push    bp
  10.     mov    bp,sp
  11.     push    di
  12.     push    si
  13.     mov    cx,word ptr 4[bp]
  14.     mov    dx,word ptr 6[bp]
  15.     int    224
  16.     pop    si
  17.     pop    di
  18.     pop    bp
  19.     and    ax,255
  20.     ret
  21. ;
  22. bdos_    endp
  23. codeseg    ends
  24.     end
  25. begin.asm
  26. ; Copyright (C) 1983, 1984 by Manx Software Systems
  27. ; :ts=8
  28. codeseg    segment    para public 'code'
  29.     public    $MEMRY
  30.     public    _mbot_, sbot
  31. dataseg    segment    para public 'data'
  32. $MEMRY    dw    -1
  33.     public    errno_
  34. errno_    dw    0
  35.     public    _dsval_,_csval_
  36. _dsval_    dw    0
  37. _csval_    dw    0
  38. _mbot_    dw    0
  39. sbot    dw    0
  40. exitad    dw    0
  41. exitcs    dw    0
  42.     extrn    _Uorg_:byte,_Uend_:byte
  43. dataseg    ends
  44.  
  45.     assume    cs:codeseg,ds:dataseg,es:dataseg,ss:dataseg
  46.     extrn Croot_:near
  47.     public    $begin
  48.     public    _exit_
  49. $begin    proc    far
  50.     pop    exitad
  51.     pop    exitcs
  52.     cli
  53.     mov    ax,ds
  54.     mov    es,ax
  55.     mov    ss,ax
  56.     mov    sp,word ptr ds:[6]
  57.     and    sp,-2
  58.     sti
  59.     cld
  60. ;        clear uninitialized data
  61.     mov    di,offset _Uorg_
  62.     mov    cx,offset _Uend_
  63.     sub    cx,di
  64.     inc    cx
  65.     shr    cx,1
  66.     jcxz    noclear
  67.     sub    ax,ax
  68. rep    stosw
  69. noclear:
  70.     mov    ax,$MEMRY    ;save memory allocation info for sbrk()
  71.     mov    _mbot_,ax
  72.     mov    ax,sp
  73.     sub    ax,2048        ;allow 2Kb of stack space
  74.     mov    sbot,ax
  75.     mov    _dsval_,ds
  76.     mov    _csval_,cs
  77.     call    Croot_
  78. _exit_:
  79.     sub    cx,cx
  80.     sub    dx,dx
  81.     jmp    dword ptr exitad
  82. $begin    endp
  83. codeseg    ends
  84.     end    $begin
  85. blkio.asm
  86. ; :ts=8
  87. ; Copyright (C) 1983 by Manx Software Systems
  88. codeseg    segment    para public 'code'
  89. dataseg    segment para public 'data'
  90.     extrn    errno_:word
  91. dataseg    ends
  92.  
  93.     assume    cs:codeseg,ds:dataseg,es:dataseg,ss:dataseg
  94.     public blkrd_
  95. blkrd_    proc    near
  96.     mov    cl,33        ;set function to read sequential
  97.     jmp    short rdwrt
  98. ;
  99.     public    blkwr_
  100. blkwr_:
  101.     mov    cl,34        ;set function to write sequential
  102. rdwrt:
  103.     push    bp
  104.     mov    bp,sp
  105.     push    di
  106.     push    si
  107.     push    cx        ;save function code on stack
  108. ioloop:
  109.     mov    dx,6[bp]
  110.     add    word ptr 6[bp],128    ;bump to next 128 byte position
  111.     push    bp
  112.     mov    cl,26        ;set DMA address
  113.     int    224
  114.     pop    bp
  115.     pop    cx
  116.     push    cx
  117.     push    bp
  118.     mov    dx,4[bp]
  119.     int    224    ;read or write sector
  120.     pop    bp
  121.     and    ax,0ffH
  122.     jnz    ioerr
  123.     mov    bx,4[bp]    ;get fcb address
  124.     add    word ptr 33[bx],1    ;increment random record #
  125.     adc    byte ptr 35[bx],0
  126.     dec    word ptr 8[bp]
  127.     jnz    ioloop
  128. blkexit:
  129.     pop    cx        ;pull function code from stack
  130.     mov    ax,word ptr 8[bp]    ;get number of sectors remaining
  131.     pop    si
  132.     pop    di
  133.     pop    bp
  134.     test    ax,ax
  135.     ret            ;all done, return number remaining
  136. ;
  137. ioerr:
  138.     cmp    al,1
  139.     je    blkexit
  140.     cmp    al,4
  141.     je    blkexit
  142.     mov    errno_,ax
  143.     jmp    blkexit
  144. blkrd_    endp
  145. codeseg    ends
  146.     end
  147. ceof.c
  148. /* Copyright (C) 1984 by Manx Software Systems */
  149. #include "io.h"
  150. #include "errno.h"
  151.  
  152. _Ceof(fp)
  153. register struct fcbtab *fp;
  154. {
  155.     register char *cp;
  156.  
  157.     bdos(FILSIZ, &fp->fcb);
  158.     if (fp->fcb.f_record == 0) {
  159.         fp->offset = 0;
  160.         return 0;
  161.     }
  162.     --fp->fcb.f_record;            /* backup to last record */
  163.     if (_find(fp))
  164.         return -1;
  165.  
  166.     for (cp = Wrkbuf+128 ; cp > Wrkbuf ; )
  167.         if (*--cp != 0x1a) {
  168.             ++cp;
  169.             break;
  170.         }
  171.     if ((fp->offset = (char)((int)(cp-Wrkbuf))) == 128) {
  172.         ++fp->fcb.f_record;
  173.         fp->offset = 0;
  174.     }
  175.     return 0;
  176. }
  177. close.c
  178. /* Copyright (C) 1982 by Manx Software Systems */
  179. #include "errno.h"
  180. #include "io.h"
  181.  
  182. close(fd)
  183. {
  184.     register struct channel *chp;
  185.     extern int bdf_();
  186.  
  187.     if (fd < 0 || fd > MAXCHAN) {
  188.         errno = EBADF;
  189.         return -1;
  190.     }
  191.     chp = &chantab[fd];
  192.     fd = (*chp->c_close)(chp->c_arg);
  193.     chp->c_read = chp->c_write = chp->c_ioctl = chp->c_seek = 0;
  194.     chp->c_close = bdf_;
  195.     return fd;
  196. }
  197. croot.c
  198. /* Copyright (C) 1981,1982,1984 by Manx Software Systems */
  199. #include "errno.h"
  200. #include "fcntl.h"
  201. #include "io.h"
  202.  
  203. int bdf_(), ret_();
  204.  
  205. /*
  206.  * channel table: relates fd's to devices
  207.  */
  208. struct channel chantab[] = {
  209.     { 2, 0, 1, 0, ret_, 2 },
  210.     { 0, 2, 1, 0, ret_, 2 },
  211.     { 0, 2, 1, 0, ret_, 2 },
  212.     { 0, 0, 0, 0, bdf_, 0 },
  213.     { 0, 0, 0, 0, bdf_, 0 },
  214.     { 0, 0, 0, 0, bdf_, 0 },
  215.     { 0, 0, 0, 0, bdf_, 0 },
  216.     { 0, 0, 0, 0, bdf_, 0 },
  217.     { 0, 0, 0, 0, bdf_, 0 },
  218.     { 0, 0, 0, 0, bdf_, 0 },
  219.     { 0, 0, 0, 0, bdf_, 0 },
  220. };
  221.  
  222. #define MAXARGS 30
  223. static char *Argv[MAXARGS];
  224. static char Argbuf[128];
  225. static int Argc;
  226. int (*cls_)() = ret_;
  227.  
  228. Croot()
  229. {
  230.     register char *cp, *fname;
  231.     register int k;
  232.  
  233.     movmem((char *)0x81, Argbuf, 127);
  234.     Argbuf[*(char *)0x80 & 0x7f] = 0;
  235.     Argv[0] = "";
  236.     cp = Argbuf;
  237.     Argc = 1;
  238.     while (Argc < MAXARGS) {
  239.         while (*cp == ' ' || *cp == '\t')
  240.             ++cp;
  241.         if (*cp == 0)
  242.             break;
  243. #ifndef NOREDIR
  244.         if (*cp == '>') {        /* redirect output */
  245.             k = 1;
  246.             goto redirect;
  247.         } else if (*cp == '<') {    /* redirect input */
  248.             k = 0;
  249. redirect:
  250.             while (*++cp == ' ' || *cp == '\t')
  251.                 ;
  252.             fname = cp;
  253.             while (*++cp)
  254.                 if (*cp == ' ' || *cp == '\t') {
  255.                     *cp++ = 0;
  256.                     break;
  257.                 }
  258.             close(k);
  259.             if (k)
  260.                 k = creat(fname, 0666);
  261.             else
  262.                 k = open(fname, O_RDONLY);
  263.             if (k == -1) {
  264.                 strcpy(0x80, "Can't open file for redirection: ");
  265.                 strcat(0x80, fname);
  266.                 strcat(0x80, "$");
  267.                 bdos(9,0x80);
  268.                 exit(10);
  269.             }
  270.         } else
  271. #endif
  272.         {
  273.             Argv[Argc++] = cp;
  274.             while (*++cp)
  275.                 if (*cp == ' ' || *cp == '\t') {
  276.                     *cp++ = 0;
  277.                     break;
  278.                 }
  279.         }
  280.     }
  281.     main(Argc,Argv);
  282.     exit(0);
  283. }
  284.  
  285. exit(code)
  286. {
  287.     register int fd;
  288.  
  289.     (*cls_)();
  290.     for (fd = 0 ; fd < MAXCHAN ; )
  291.         close(fd++);
  292.     if (code && (bdos(24)&1) != 0)
  293.         unlink("A:$$$.SUB");
  294.     _exit();
  295. }
  296.  
  297. bdf_()
  298. {
  299.     errno = EBADF;
  300.     return -1;
  301. }
  302.  
  303. ret_()
  304. {
  305.     return 0;
  306. }
  307.  
  308. csread.c
  309. /* Copyright (C) 1983, 1984 by Manx Software Systems */
  310. #include "io.h"
  311. #include "errno.h"
  312.  
  313. extern int errno;
  314. extern unsigned _dsval, _csval;
  315.  
  316. _csread(fd, buffer, len)
  317. char *buffer;
  318. {
  319.     register unsigned l = 0;
  320.     register struct fcbtab *fp;
  321.     register struct channel *chp;
  322.     unsigned k,j;
  323.  
  324.     chp = &chantab[fd];
  325.     if (chp->c_read != 1) {        /* only valid for disk files */
  326.         errno = EINVAL;
  327.         return -1;
  328.     }
  329.  
  330.     fp = chp->c_arg;
  331.     setusr(fp->user);
  332.  
  333.     if (fp->offset) {
  334.         if ((l = 128 - fp->offset) > len)
  335.             l = len;
  336.         if (getsect(fp, buffer, l)) {
  337.             l = 0;
  338.             goto done;
  339.         }
  340.     }
  341.     if (k = (len-l)/128) {
  342.         bdos(51, _csval);    /* set dma segment to CS */
  343.         j = blkrd(&fp->fcb, buffer+l, k);
  344.         bdos(51, _dsval);    /* set dma segment back to DS */
  345.         if (j != 0) {
  346.             l += (k-j)*128;
  347.             goto done;
  348.         }
  349.     }
  350.     l += k*128;
  351.     if (l < len)
  352.         if (getsect(fp, buffer+l, len-l))
  353.             goto done;
  354.     l = len;
  355.  
  356. done:
  357.     rstusr();
  358.     return l;
  359. }
  360.  
  361. static
  362. getsect(fp, buf, len)
  363. register struct fcbtab *fp; char *buf; unsigned len;
  364. {
  365.     if (_find(fp))
  366.         return -1;
  367.     movblock(Wrkbuf+fp->offset,_dsval, buf,_csval, len);
  368.     if ((fp->offset = (fp->offset + len) & 127) == 0)
  369.         ++fp->fcb.f_record;
  370.     return 0;
  371. }
  372.  
  373. exec.c
  374. /* Copyright (C) 1983, 1984 by Manx Software Systems */
  375.  
  376. execlp(path, args)
  377. char *path, *args;
  378. {
  379.     return execvp(path, &args);
  380. }
  381.  
  382. execvp(path, argv)
  383. char *path, **argv;
  384. {
  385.     char buffer[130];
  386.     register char *cp, *xp;
  387.  
  388.     cp = buffer;
  389.     for (xp = path ; *xp && cp < buffer+128 ; )
  390.         *cp++ = *xp++;
  391.     if (*argv) {
  392.         ++argv;            /* skip arg0, used for unix (tm) compatibility */
  393.         while (*argv) {
  394.             *cp++ = ' ';
  395.             for (xp = *argv++ ; *xp && cp < buffer+128 ; )
  396.                 *cp++ = *xp++;
  397.         }
  398.     }
  399.     *cp = 0;
  400.     bdos(26, buffer);
  401.     bdos(47, 0);
  402. }
  403.  
  404. execl.c
  405. /* Copyright (C) 1983, 1984 by Manx Software Systems */
  406.  
  407. execl(path, args)
  408. char *path, *args;
  409. {
  410.     return execvp(path, &args);
  411. }
  412.  
  413. execv(path, argv)
  414. char *path, **argv;
  415. {
  416.     return execvp(path, argv);
  417. }
  418. fcbinit.asm
  419. ; :ts=8
  420. ; Copyright (C) 1983, 1984 by Manx Software Systems
  421. codeseg    segment    para public 'code'
  422. ;
  423.     include lmacros.h
  424.     public fcbinit_
  425. fcbinit_ proc    near
  426.     mov    bx,sp
  427.     push    di
  428.     push    si
  429.     cld
  430. ifndef LONGPTR
  431.     mov    di,ds
  432.     mov    es,di
  433. endif
  434.     mov    si,word ptr 2[bx]    ;si contains name
  435.     mov    di,word ptr 4[bx]    ;di contains fcb address
  436. ;            clear name to blanks
  437.     mov    dx,di        ;save fcb address in dx
  438.     inc    di
  439.     mov    cx,11        ;clear name and ext to blanks
  440.     mov    al,' '
  441. rep    stosb
  442.     mov    cx,4
  443.     sub    al,al
  444. rep    stosb
  445.     mov    di,dx        ;restore fcb address
  446. ;
  447.     sub    dx,dx        ;init user #
  448.     mov    cl,10        ;multiplier inside loop
  449. userloop:            ;loop packing leading digits into DL
  450.     lodsb
  451.     cmp    al,'0'
  452.     jb    userdone
  453.     cmp    al,'9'
  454.     ja    userdone
  455.     sub    al,'0'
  456.     xchg    ax,dx        ;get accumlated value into AL for multiply
  457.     mul    cl        ;value *= 10
  458.     add    al,dl        ;add in new digit
  459.     xchg    ax,dx        ;put result back into DL
  460.     jmp    userloop
  461. ;
  462. userdone:
  463.     cmp    al,'/'        ;check if user # prefix
  464.     je    haveuser
  465.     mov    dl,255        ;set user # to default indicator
  466.     mov    si,word ptr 2[bx]    ;reset filename pointer
  467. haveuser:
  468. ;
  469.     sub    al,al        ;default drive #
  470.     cmp    byte ptr 1[si],':'
  471.     jnz    setdrive
  472. ;
  473.     lodsb
  474.     inc    si        ;skip over colon
  475.     and    al,127
  476.     cmp    al,'A'
  477.     jl    badname
  478.     cmp    al,'Z'
  479.     jg    lowerc
  480.     sub    al,'A'-1
  481.     jmp    short setdrive
  482. ;
  483. lowerc:
  484.     cmp    al,'a'
  485.     jl    badname
  486.     cmp    al,'z'
  487.     jg    badname
  488.     sub    al,'a'-1
  489. setdrive:
  490.     stosb
  491. ;                move name in mapping to upper case
  492.     mov    cx,8
  493. nameskp:
  494.     inc    cx
  495. namelp:
  496.     lodsb
  497.     cmp    al,'.'
  498.     jz    namedn
  499.     test    al,al
  500.     jz    alldone
  501.     loop    store
  502.     jmp    short nameskp
  503. store:
  504.     call    toupper
  505.     stosb
  506.     jmp    short namelp
  507. ;
  508. namedn:
  509.     dec    cx
  510.     add    di,cx
  511. ;                    move extension mapping to upper case
  512.     mov    cx,3
  513. extlp:
  514.     lodsb
  515.     test    al,al
  516.     jz    alldone
  517.     call    toupper
  518.     stosb
  519.     loop    extlp
  520. ;
  521. alldone:
  522.     xchg    ax,dx
  523.     and    ax,255
  524. retn:
  525.     pop    si
  526.     pop    di
  527.     ret
  528. ;
  529. badname:
  530.     sub    ax,ax
  531.     dec    ax
  532.     jmp    short retn
  533. ;
  534. toupper:
  535.     cmp    al,'*'
  536.     jne    nostar
  537.     dec    si        ;backup so we see star again
  538.     mov    al,'?'        ;and map into question mark
  539.     ret
  540. nostar:
  541.     cmp    al,'a'
  542.     jl    notrans
  543.     cmp    al,'z'
  544.     jg    notrans
  545.     sub    al,'a'-'A'
  546. notrans:
  547.     ret
  548. fcbinit_ endp
  549. codeseg    ends
  550.     end
  551. find.c
  552. /* Copyright (C) 1984 by Manx Software Systems */
  553. #include "io.h"
  554.  
  555. static struct fcbtab *Wfp;
  556. static unsigned Wsct;
  557.  
  558. _zap()            /* invalidate work buffer */
  559. {
  560.     Wfp = 0;
  561. }
  562.  
  563. _find(fp)
  564. register struct fcbtab *fp;
  565. {
  566.     extern int errno;
  567.  
  568.     bdos(SETDMA, Wrkbuf);
  569.     if (Wfp != fp || fp->fcb.f_record != Wsct) {
  570.         if ((errno = bdos(READRN, &fp->fcb)) == 1 || errno == 4) {
  571.             errno = 0;
  572.             setmem(Wrkbuf, 128, 0x1a);
  573.             Wfp = 0;
  574.             return 1;
  575.         } else if (errno)
  576.             return -1;
  577.         Wfp = fp;
  578.         Wsct = fp->fcb.f_record;
  579.     }
  580.     return 0;
  581. }
  582.  
  583. ioctl.c
  584. /* Copyright (C) 1984 by Manx Software Systems */
  585. #include "io.h"
  586. #include "errno.h"
  587. #include "sgtty.h"
  588.  
  589. #define TIME    10        /* number of iterations of raw_rd loop */
  590. #define MIN        1        /* minimum number of chars returned from read */
  591.  
  592. extern int (*Rd_tab[])();
  593. extern int (*Wrt_tab[])();
  594.  
  595. struct sgttyb Tty_ctl;
  596. extern char _Eol;
  597. extern int tty_rd();
  598. static int raw_rd(), raw_wr();
  599. static int rd_func, wrt_func;
  600.  
  601. ioctl(fd, cmd, arg)
  602. struct sgttyb *arg;
  603. {
  604.     register struct channel *chp;
  605.  
  606.     chp = &chantab[fd];
  607.     if (chp->c_ioctl == 0) {
  608.         errno = ENOTTY;
  609.         return -1;
  610.     }
  611.     switch (cmd) {
  612.     case TIOCGETP:
  613.         *arg = Tty_ctl;
  614.         break;
  615.     case TIOCSETP:
  616.         Tty_ctl = *arg;
  617.         Wrt_tab[2] = raw_wr;
  618.         Rd_tab[2] = raw_rd;
  619.         if (Tty_ctl.sg_flags&RAW) {
  620.             rd_func =
  621.             wrt_func = 6;
  622.             _Eol = '\r';
  623.             break;
  624.         } else if (Tty_ctl.sg_flags&CBREAK) {
  625.             rd_func = (Tty_ctl.sg_flags&ECHO) ? 1 : 6;
  626.             wrt_func = 2;
  627.         } else {
  628.             Rd_tab[2] = tty_rd;
  629.             wrt_func = 2;
  630.         }
  631.         if (Tty_ctl.sg_flags&CRMOD)
  632.             _Eol = '\n';
  633.         else
  634.             _Eol = '\r';
  635.     }
  636.     return 0;
  637. }
  638.  
  639. raw_rd(x, buff, len)
  640. register char *buff;
  641. {
  642.     int c, i;
  643.     register int count;
  644.  
  645.     for (count = 0 ; count < len ; ) {
  646.         for (i = TIME ; i-- ; )
  647.             if ((c = bdos(rd_func,0xff)) != 0)
  648.                 goto have_char;
  649.         if (count < MIN)
  650.             continue;
  651.         break;
  652. have_char:
  653.         if (c == '\r')
  654.             c = _Eol;
  655.         *buff++ = c;
  656.         ++count;
  657.     }
  658.     return count;
  659. }
  660.  
  661. raw_wr(kind, buff, len)
  662. register char *buff;
  663. {
  664.     register int count;
  665.  
  666.     for (count = len ; count-- ; ) {
  667.         if (*buff == '\n' && (Tty_ctl.sg_flags&CRMOD))
  668.             bdos(wrt_func,'\r');
  669.         bdos(wrt_func,*buff++);
  670.     }
  671.     return len;
  672. }
  673. isatty.c
  674. /* Copyright (C) 1983 by Manx Software Systems */
  675. #include "io.h"
  676. #include "errno.h"
  677.  
  678. isatty(fd)
  679. {
  680.     return chantab[fd].c_ioctl;
  681. }
  682.  
  683. lseek.c
  684. /* Copyright (C) 1982, 1984 by Manx Software Systems */
  685. #include "io.h"
  686. #include "errno.h"
  687.  
  688. long lseek(fd, pos, how)
  689. long pos;
  690. {
  691.     register struct fcbtab *fp;
  692.  
  693.     if (chantab[fd].c_seek == 0) {
  694. Badf:
  695.         errno = EBADF;
  696.         return -1L;
  697.     }
  698.     fp = chantab[fd].c_arg;
  699.  
  700.     switch (how) {
  701.     case 2:
  702.         /*
  703.          * Close the file because CP/M doesn't know how big an open file is.
  704.          * However, the fcb is still valid.
  705.          */
  706.         setusr(fp->user);
  707.         fp->fcb.f_name[4] |= 0x80;    /* set parital close flag for MP/M */
  708.         bdos(CLSFIL, &fp->fcb);
  709.         fp->fcb.f_name[4] &= 0x7f;    /* clear parital close flag */
  710.         _Ceof(fp);
  711.         rstusr();
  712.     case 1:
  713.         pos += fp->offset + ((long)fp->fcb.f_record << 7);
  714.     case 0:
  715.         break;
  716.  
  717.     default:
  718.         errno = EINVAL;
  719.         return -1L;
  720.     }
  721.  
  722.     fp->fcb.f_overfl = 0;
  723.     if (pos < 0) {
  724.         fp->offset = fp->fcb.f_record = 0;
  725.         errno = EINVAL;
  726.         return -1L;
  727.     }
  728.     fp->offset = (unsigned)pos & 127;
  729.     fp->fcb.f_record = pos >> 7;
  730.     return pos;
  731. }
  732.  
  733. open.c
  734. /* Copyright (C) 1982 by Manx Software Systems */
  735. #include "errno.h"
  736. #include "fcntl.h"
  737. #include "io.h"
  738.  
  739. #define MAXFILE    8    /* maximum number of open DISK files */
  740. int bdf_(), ret_(), fileop();
  741. /*
  742.  * note: The ioctl function knows that the condev read/write numbers are
  743.  * 2.  It uses this information to patch the read/write tables.
  744.  */
  745. static struct device condev = { 2, 2, 1, 0, ret_ };
  746. static struct device bdosout= { 0, 3, 0, 0, ret_ };
  747. static struct device bdosin = { 3, 0, 0, 0, ret_ };
  748. static struct device filedev= { 1, 1, 0, 1, fileop };
  749.  
  750. /*
  751.  * device table, contains names and pointers to device entries
  752.  */
  753. static struct devtabl devtabl[] = {
  754.     { "con:", &condev, 2 },
  755.     { "CON:", &condev, 2 },
  756.     { "lst:", &bdosout, 5 },
  757.     { "LST:", &bdosout, 5 },
  758.     { "prn:", &bdosout, 5 },
  759.     { "PRN:", &bdosout, 5 },
  760.     { "pun:", &bdosout, 4 },
  761.     { "PUN:", &bdosout, 4 },
  762.     { "rdr:", &bdosin, 3 },
  763.     { "RDR:", &bdosin, 3 },
  764.     { 0, &filedev, 0 }        /* this must be the last slot in the table! */
  765. };
  766.  
  767.  
  768. creat(name, mode)
  769. char *name;
  770. {
  771.     return open(name, O_WRONLY|O_TRUNC|O_CREAT, mode);
  772. }
  773.  
  774. open(name, flag, mode)
  775. char *name;
  776. {
  777.     register struct devtabl *dp;
  778.     register struct channel *chp;
  779.     register struct device *dev;
  780.     int fd, mdmask;
  781.  
  782.     for (chp = chantab, fd = 0 ; fd < MAXCHAN ; ++chp, ++fd)
  783.         if (chp->c_close == bdf_)
  784.             goto fndchan;
  785.     errno = EMFILE;
  786.     return -1;
  787.  
  788. fndchan:
  789.     for (dp = devtabl ; dp->d_name ; ++dp)
  790.         if (strcmp(dp->d_name, name) == 0)
  791.             break;
  792.     dev = dp->d_dev;
  793.     mdmask = (flag&3) + 1;
  794.     if (mdmask&1) {
  795.         if ((chp->c_read = dev->d_read) == 0) {
  796.             errno = EACCES;
  797.             return -1;
  798.         }
  799.     }
  800.     if (mdmask&2) {
  801.         if ((chp->c_write = dev->d_write) == 0) {
  802.             errno = EACCES;
  803.             return -1;
  804.         }
  805.     }
  806.     chp->c_arg = dp->d_arg;
  807.     chp->c_ioctl = dev->d_ioctl;
  808.     chp->c_seek = dev->d_seek;
  809.     chp->c_close = ret_;
  810.     if ((*dev->d_open)(name, flag, mode, chp, dp) < 0) {
  811.         chp->c_close = bdf_;
  812.         return -1;
  813.     }
  814.     return fd;
  815. }
  816.  
  817. static struct fcbtab fcbtab[MAXFILE];
  818.  
  819. static
  820. fileop(name,flag,mode,chp,dp)
  821. char *name; struct channel *chp; struct devtabl *dp;
  822. {
  823.     register struct fcbtab *fp;
  824.     int filecl();
  825.     int user;
  826.  
  827.     for ( fp = fcbtab ; fp < fcbtab+MAXFILE ; ++fp )
  828.         if ( fp->flags == 0 )
  829.             goto havefcb;
  830.     errno = EMFILE;
  831.     return -1;
  832.  
  833. havefcb:
  834.     if ((user = fcbinit(name,&fp->fcb)) == -1) {
  835.         errno = EINVAL;
  836.         return -1;
  837.     }
  838.     if (user == 255)
  839.         user = getusr();
  840.     setusr(user);
  841.     if (flag & O_TRUNC)
  842.         bdos(DELFIL, &fp->fcb);
  843.     if (bdos(OPNFIL,&fp->fcb) == 0xff) {
  844.         if ((flag&(O_TRUNC|O_CREAT)) == 0 || bdos(MAKFIL,&fp->fcb) == 0xff) {
  845.             errno = ENOENT;
  846.             rstusr();
  847.             return -1;
  848.         }
  849.     } else if ((flag&(O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) {
  850.         errno = EEXIST;
  851.         goto punt;
  852.     } else if ((flag&3) > 0 && fp->fcb.f_type[0]&0x80) {
  853.         errno = EACCES;
  854. punt:
  855.         bdos(CLSFIL, &fp->fcb);
  856.         rstusr();
  857.         return -1;
  858.     }
  859.     
  860.     fp->offset = fp->fcb.f_overfl = fp->fcb.f_record = 0;
  861.     fp->user = user;
  862.     chp->c_arg = (_arg)fp;
  863.     fp->flags = (flag&3)+1;
  864.     chp->c_close = filecl;
  865.     if (flag&O_APPEND)
  866.         _Ceof(fp);
  867.     rstusr();
  868.     return 0;
  869. }
  870.  
  871. static
  872. filecl(fp)
  873. register struct fcbtab *fp;
  874. {
  875.     _zap();        /* zap work buffer, so data is not reused */
  876.     setusr(fp->user);
  877.     bdos(CLSFIL,&fp->fcb);
  878.     rstusr();
  879.     fp->flags = 0;
  880.     return 0;
  881. }
  882.  
  883. read.c
  884. /* Copyright (C) 1983, 1984 by Manx Software Systems */
  885. #include "io.h"
  886. #include "errno.h"
  887. #include "fcntl.h"
  888.  
  889. int bdf_(), filerd(), tty_rd(), bdosrd();
  890.  
  891. int (*Rd_tab[])() = {
  892.     bdf_, filerd, tty_rd, bdosrd,
  893. };
  894. extern int errno;
  895.  
  896. read(fd, buff, len)
  897. char *buff;
  898. {
  899.     register struct channel *chp;
  900.  
  901.     chp = &chantab[fd];
  902.     return (*Rd_tab[chp->c_read])(chp->c_arg, buff, len);
  903. }
  904.  
  905. static
  906. filerd(afp,buffer,len)
  907. struct fcbtab *afp;
  908. char *buffer; unsigned len;
  909. {
  910.     register unsigned l = 0;
  911.     register struct fcbtab *fp;
  912.     unsigned k,j;
  913.  
  914.     fp = afp;
  915.     setusr(fp->user);
  916.     if (fp->offset) {
  917.         if ((l = 128 - fp->offset) > len)
  918.             l = len;
  919.         if (getsect(fp, buffer, l)) {
  920.             rstusr();
  921.             return 0;
  922.         }
  923.     }
  924.     if (k = (len-l)/128)
  925.         if ((j = blkrd(&fp->fcb, buffer+l, k)) != 0) {
  926.             rstusr();
  927.             return (k-j)*128 + l;
  928.         }
  929.     l += k*128;
  930.     if (l < len)
  931.         if (getsect(fp, buffer+l, len-l)) {
  932.             rstusr();
  933.             return l;
  934.         }
  935.     rstusr();
  936.     return len;
  937. }
  938.  
  939. static
  940. getsect(fp, buf, len)
  941. register struct fcbtab *fp; char *buf; unsigned len;
  942. {
  943.     if (_find(fp))
  944.         return -1;
  945.     movmem(Wrkbuf+fp->offset, buf, len);
  946.     if ((fp->offset = (fp->offset + len) & 127) == 0)
  947.         ++fp->fcb.f_record;
  948.     return 0;
  949. }
  950.  
  951. char _Eol = '\n';
  952.  
  953. tty_rd(x,buff,len)
  954. char *buff;
  955. {
  956.     static char buffer[258];
  957.     static int used;
  958.     register int l;
  959.  
  960.     if (buffer[1] == 0) {
  961.         buffer[0] = 255;
  962.         buffer[1] = buffer[2] = 0;
  963.         bdos(10,buffer);
  964.         bdos(2,'\n');
  965.         if (buffer[2] == 0x1a) {
  966.             buffer[1] = 0;
  967.             return 0;
  968.         }
  969.         buffer[++buffer[1] + 1] = _Eol;
  970.         used = 2;
  971.     }
  972.     if ((l = buffer[1]) > len)
  973.         l = len;
  974.     movmem(buffer+used, buff, l);
  975.     used += l;
  976.     buffer[1] -= l;
  977.     return l;
  978. }
  979.  
  980. static
  981. bdosrd(kind, buff, len)
  982. register char *buff;
  983. {
  984.     register int count;
  985.  
  986.     for (count = 0 ; count < len ; ++count) {
  987.         if ((*buff++ = bdos(kind)) == 0x1a)
  988.             break;
  989.     }
  990.     return count;
  991. }
  992. rename.c
  993. /* Copyright (C) 1983, 1984 by Manx Software Systems */
  994. #include "errno.h"
  995.  
  996. rename(old, new)
  997. char *old, *new;
  998. {
  999.     auto char buff[60];
  1000.     register int user;
  1001.  
  1002.     user = fcbinit(old,buff);
  1003.     fcbinit(new,buff+16);
  1004.     setusr(user);
  1005.     user = 0;
  1006.     if (bdos(15,buff+16) != 0xff) {
  1007.         bdos(16,buff+16);
  1008.         errno = EEXIST;
  1009.         user = -1;
  1010.     } else if (bdos(23,buff) == 0xff) {
  1011.         errno = ENOENT;
  1012.         user = -1;
  1013.     }
  1014.     rstusr();
  1015.     return user;
  1016. }
  1017. unlink.c
  1018. /* Copyright (C) 1983, 1984 by Manx Software Systems */
  1019. #include "errno.h"
  1020.  
  1021. unlink(name)
  1022. char *name;
  1023. {
  1024.     auto char delfcb[40];
  1025.     register int user;
  1026.  
  1027.     user = fcbinit(name,delfcb);
  1028.     setusr(user);
  1029.     user = bdos(19,delfcb);
  1030.     rstusr();
  1031.     if (user == 0xff) {
  1032.         errno = ENOENT;
  1033.         return -1;
  1034.     }
  1035.     return 0;
  1036. }
  1037.  
  1038. user.asm
  1039. ; Copyright (C) 1984 by Manx Software Systems
  1040. ; :ts=8
  1041.  
  1042. codeseg    segment para public 'code'
  1043. dataseg segment para public 'data'
  1044. olduser    db    0
  1045. dataseg    ends
  1046.     assume    cs:codeseg,ds:dataseg
  1047.     public    getusr_
  1048. getusr_    proc    near
  1049.     push    bp
  1050.     push    si
  1051.     push    di
  1052.     mov    cl,32
  1053.     mov    dl,255
  1054.     int    224
  1055.     and    ax,255
  1056.     pop    di
  1057.     pop    si
  1058.     pop    bp
  1059.     ret
  1060. getusr_    endp
  1061. ;
  1062.     public    setusr_
  1063. setusr_    proc    near
  1064.     push    bp
  1065.     mov    bp,sp
  1066.     push    si
  1067.     push    di
  1068.     mov    cl,32
  1069.     mov    dl,255
  1070.     int    224
  1071.     mov    olduser,al
  1072. ;
  1073.     mov    dl,4[bp]
  1074.     cmp    dl,255
  1075.     je    skipset
  1076.     mov    cl,32
  1077.     int    224
  1078. skipset:
  1079.     pop    di
  1080.     pop    si
  1081.     pop    bp
  1082.     ret
  1083. setusr_    endp
  1084. ;
  1085.     public    rstusr_
  1086. rstusr_    proc    near
  1087.     push    bp
  1088.     push    si
  1089.     push    di
  1090.     mov    cl,32
  1091.     mov    dl,olduser
  1092.     int    224
  1093.     pop    di
  1094.     pop    si
  1095.     pop    bp
  1096.     ret
  1097. rstusr_    endp
  1098. codeseg    ends
  1099.     end
  1100. write.c
  1101. /* Copyright (C) 1983, 1984 by Manx Software Systems */
  1102. #include "io.h"
  1103. #include "errno.h"
  1104.  
  1105. int tty_wr(), bdoswr(), filewr(), bdf_();
  1106.  
  1107. int (*Wrt_tab[])() = {
  1108.     bdf_, filewr, bdoswr, bdoswr
  1109. };
  1110.  
  1111. write(fd, buff, len)
  1112. char *buff;
  1113. {
  1114.     register struct channel *chp;
  1115.  
  1116.     chp = &chantab[fd];
  1117.     return (*Wrt_tab[chp->c_write])(chp->c_arg, buff, len);
  1118. }
  1119.  
  1120. static
  1121. filewr(afp,buffer,len)
  1122. struct fcbtab *afp;
  1123. char *buffer; unsigned len;
  1124. {
  1125.     register unsigned l = 0;
  1126.     register struct fcbtab *fp;
  1127.     unsigned k,j;
  1128.  
  1129.     fp = afp;
  1130.     setusr(fp->user);
  1131.     if (fp->offset) {
  1132.         if ((l = 128 - fp->offset) > len)
  1133.             l = len;
  1134.         if (putsect(fp, buffer, l)) {
  1135.             rstusr();
  1136.             return -1;
  1137.         }
  1138.     }
  1139.     if (k = (len-l)/128)
  1140.         if ((j = blkwr(&fp->fcb, buffer+l, k)) != 0) {
  1141.             rstusr();
  1142.             if ((l += (k-j)*128) == 0)
  1143.                 return -1;
  1144.             else
  1145.                 return l;
  1146.         }
  1147.     l += k*128;
  1148.     if (l < len)
  1149.         if (putsect(fp, buffer+l, len-l)) {
  1150.             rstusr();
  1151.             return l;
  1152.         }
  1153.     rstusr();
  1154.     return len;
  1155. }
  1156.  
  1157. static
  1158. putsect(fp, buf, len)
  1159. register struct fcbtab *fp; char *buf; unsigned len;
  1160. {
  1161.     if (_find(fp) < 0)
  1162.         return -1;
  1163.     movmem(buf, Wrkbuf+fp->offset, len);
  1164.     if ((errno = bdos(WRITRN, &fp->fcb)) != 0)
  1165.         return -1;
  1166.     if ((fp->offset = (fp->offset + len) & 127) == 0)
  1167.         ++fp->fcb.f_record;
  1168.     return 0;
  1169. }
  1170.  
  1171. tty_wr(kind, buff, len)
  1172. register char *buff;
  1173. {
  1174.     register int count;
  1175.  
  1176.     for (count = len ; count-- ; ) {
  1177.         if (*buff == '\n')
  1178.             bdos(2,'\r');
  1179.         bdos(2,*buff++);
  1180.     }
  1181.     return len;
  1182. }
  1183.  
  1184. static
  1185. bdoswr(kind, buff, len)
  1186. register char *buff;
  1187. {
  1188.     register int count;
  1189.  
  1190.     for (count = len ; count-- ; )
  1191.         bdos(kind,*buff++);
  1192.     return len;
  1193. }
  1194.  
  1195. sbrk.asm
  1196. ; :ts=8
  1197. ;Copyright (C) 1983 by Manx Software Systems
  1198.     include lmacros.h
  1199. dataseg    segment    word public 'data'
  1200.     extrn    $MEMRY:word
  1201.     extrn    _mbot_:word, sbot:word
  1202.     extrn    errno_:word
  1203. dataseg    ends
  1204.     assume    ds:dataseg
  1205. ;
  1206. ; sbrk(size): return address of current top & bump by size bytes
  1207. ;
  1208.     procdef    sbrk,<<siz,word>>
  1209.     push    di
  1210.     mov    ax,siz
  1211.     mov    di,$MEMRY
  1212.     add    ax,di
  1213.     push    ax
  1214.     call    brk_
  1215.     pop    cx
  1216.     jnz    brk_error
  1217.     mov    ax,di        ;return original value of the break
  1218. ifdef LONGPTR
  1219.     mov    dx,ds
  1220.     pop    di
  1221.     pret
  1222. endif
  1223. brk_error:
  1224.     pop    di
  1225. ifdef LONGPTR
  1226.     mov    dx,ax
  1227. endif
  1228.     test    ax,ax        ;set flags for C
  1229.     pret
  1230.     pend    sbrk
  1231. ;
  1232. ; brk(addr):    set current top address to addr
  1233. ;        returns 0 if ok, -1 if error
  1234. ;
  1235.     procdef brk,<<addr,word>>
  1236.     mov    ax,addr
  1237.     inc    ax
  1238.     and    al,-2
  1239.     cmp    ax,sbot            ;check for stack/heap overflow
  1240.     jae    brk_ov
  1241.     mov    bx,sp
  1242.     cmp    ax,bx            ;double check with sp for saftey
  1243.     jae    brk_ov
  1244.     cmp    ax,_mbot_
  1245.     jb    brk_ov
  1246.     mov    $MEMRY,ax    ;new value is good so save it away
  1247.     sub    ax,ax
  1248.     pret
  1249. ; invalid request
  1250. brk_ov:
  1251.     mov    errno_,-4
  1252.     mov    ax,-1
  1253.     test    ax,ax
  1254.     pret
  1255.     pend    brk
  1256. ;
  1257. ; rsvstk(size):        set saftey margin for stack
  1258. ;            this will make sure that at least size
  1259. ;            bytes of stack below the current level remain.
  1260. ;
  1261.     procdef    rsvstk,<<stksize,word>>
  1262.     mov    ax,sp
  1263.     sub    ax,stksize
  1264.     mov    sbot,ax
  1265.     pret
  1266.     pend    rsvstk
  1267.     finish
  1268.     end
  1269. xponent value
  1270.     test    ax,ax
  1271.     jnz    mf_nzero
  1272.     ldptr    bx,dptr,es    ;get p