[sub.sources.os9] v02i004: Ptyman 1.3 Sources - Part 2/2

fkk@stasys.sta.sub.org (Frank Kaefer) (06/22/91)

Posting-number: Volume 2, Issue 4
Submitted-by: ram@ramsys.UUCP (Reimer A. Mellin)
Archive-name: ptyman1.3_src2

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 2)."
# Contents:  funcs.c ptyman.c
# Wrapped by ram@ramsys on Sun Jun 23 11:05:16 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'funcs.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'funcs.c'\"
else
echo shar: Extracting \"'funcs.c'\" \(21278 characters\)
sed "s/^X//" >'funcs.c' <<'END_OF_FILE'
X/*       This software is copyright (C) 1989 by Reimer Mellin        *
X*                                                                    *
X*        Permission is granted to reproduce and distribute           *
X*        this package by any means so long as no fee is charged      *
X*        above a nominal handling fee and so long as this            *
X*        notice is always included in the copies.                    *
X*        Commerical use or incorporation into commercial software    *
X*        is prohibited without the written permission of the         *
X*        author.                                                     *
X*                                                                    *
X*        Other rights are reserved except as explicitly granted      *
X*        by written permission of the author.                        *
X*                Reimer Mellin                                       *
X*                                                                    *
X*                Sulenstr.8                                          *
X*                D-8000 Muenchen 71 (Federal Republic of Germany)    *
X*                                                                    *
X*           EMAIL:                                                   *
X*                mellin@lan.informatik.tu-muenchen.dbp.de            *
X*                ram@altger.UUCP                                     *
X*                ram%ramsys@chiuur.sub.org (home)                    *
X*                                                                    */
X/*  */
X
X/*
X * Funcs.c : Unterfunktionen zum Pty-FileManager.
X *
X * $Header: /h0/USR/REIMER/PTYMAN/RCS/funcs.c_v 1.3 91/06/08 01:20:27 ram Exp $
X *
X * $Log:	funcs.c_v $
X * Revision 1.3  91/06/08  01:20:27  ram
X * Added SS_IOCONT & SS_IOSTOP, various bugfixes, ftp-release on smilodon,
X * please share and distribute !!
X * 
X * Revision 1.2.1.2  89/09/04  13:12:41  ram
X * added some comments
X * 
X * Revision 1.2.1.1  89/08/31  12:24:51  ram
X * negative Read/Write Counts are made positive
X * 
X * Revision 1.2  89/07/16  01:04:51  ram
X * minor changes to Sub-net release
X * 
X * Revision 1.1.1.1  89/07/14  19:48:36  ram
X * Fixed: kbich, kbach. Sub-net Beta-Release
X * 
X * Revision 1.1  89/07/13  23:21:10  ram
X * Initial revision
X * 
X */
X
X#include <types.h>
X#include <MACHINE/reg.h>
X#include "ptyman.h"
X#include <path.h>
X#include <sg_codes.h>
X#include <procid.h>
X#include <signal.h>
X#include <modes.h>
X#include <errno.h>
X
X#include "misc.h"
X
Xextern union pathdesc pd;
X
Xint
Xhangup(procdesc)
Xregister   procid    *procdesc;
X{
X    /* TRUE:
X     *          - pty-typ is a tty
X     *          - and correspondent pty has gone
X     * Action:    send a offsig, if conection was severed by server
X     */
X
X    if(pd.ptypvt.typ == TTY && pd.ptypvt.pty == (union pathdesc *) 0) {
X        errno = E_HANGUP;
X        return TRUE;
X    }
X    return FALSE;
X}
X
Xint inline
Xdosleep( procdesc )
Xregister    procid  *procdesc;
X{
X    /*
X     * 0:   - if wakedup by SIGWAKE
X     * -1:  - if signal is < 32 ( ENOENT ) orseq process has been aborted
X     * 0:   - other
X     */
X
X    if( tsleep(0) == 0 && procdesc->_signal == 0)
X        return 0;
X    if( (errno = procdesc->_signal) < 32
X      || procdesc->_state & (P_DEAD|P_CONDEMNED))
X        return -1;
X    return 0;
X}
X
X/*
X * Falls Echo angeschaltet ist, schreibe einen Charakter in den Echobuffer
X * 1:   - falls echo ausgeschaltet ist oder echo erfolgreich
X * -1:  - Fehler bei Ausgabe (z.b. Prozess aborted)
X */
Xint
Xechochar( ch, buf, procdesc)
Xregister    u_char          ch;
Xregister    struct  ptybuf *buf;
X            procid         *procdesc;
X{   register    int rv;
X
X    /*
X     * if echo is off, return success
X     */
X    if( pd.ptyopt.pd_eko == '\0')
X        return(1);
X
X    /*
X     * wait for other I/O, and register for SIGINT,SIGQUIT (set lpd )
X     */
X    iowait( buf->wpid);
X    buf->wsig = SIGWAKE;
X    buf->lpd = &pd;
X
X    /*
X     * my standard output-loop
X     */
X    while( buf->wptr >= (buf->buf + buf->size)) {
X        /* stopped means STOP, so hang around and do not WakeUp */
X        if( !(buf->flags & STOPPED))
X          WAKE(buf->rpid, buf->rsig);
X        buf->wpid = procdesc->_id;
X        do {
X            if( dosleep(procdesc) < 0) {
X                rv = -1;
X                goto outloop;
X            }
X        } while( buf->wpid);
X    }
X    *(buf->wptr)++ = ch;
X    rv = 1;
Xoutloop:
X    buf->wpid = 0;
X        /* stopped means STOP, so do not WakeUp */
X    if( !(buf->flags & STOPPED))
X      WAKE(buf->rpid, buf->rsig);
X    return( rv );
X}
X
X/*
X * Lese cnt-Bytes im Raw-modus ein. Kein Echo, Lineediting etc....
X * 0:   - cnt-bytes gelesen
X * x:   - (cnt-x) bytes gelesen
X * -x:  - nach (cnt-x) ist Fehler aufgetreten (Interupted, Hangup etc.)
X */
Xint
Xcpinraw(buf, echobuf, ustack, procdesc)
Xregister    struct  ptybuf *buf;
Xregister    struct  ptybuf *echobuf;
X            REGISTERS      *ustack;
X            procid         *procdesc;
X{   register    int     cnt = ustack->d[1] & 0x7fffffff; /* no neg. counts */
X    register    u_char *dest = (u_char *) ustack->a[0];
X    register    u_char ch;
X
X    /*
X     * this can only happen if _ss_sign() was set
X     */
X    if( buf->rpid == procdesc->_id) {
X        errno = E_NOTRDY;
X        return -cnt;
X    }
X
X    /* wait for other processes to finish */
X    iowait( buf->rpid);
X    buf->rsig = SIGWAKE;
X
X    /* copy cnt bytes */
X    for(; cnt > 0; --cnt) {
X        /* if read-ptr reached write-ptr synchronize with partner */
X        while( buf->rptr >= buf->wptr ) {
X            /* reset ptr */
X            buf->wptr = buf->rptr = buf->buf;
X
X            /* stopped means STOP, so hang around and do not WakeUp */
X            if( !(buf->flags & STOPPED))
X              WAKE(buf->wpid, buf->wsig);
X
X            buf->rpid = procdesc->_id;
X            do {
X                if( dosleep(procdesc) < 0) {
X                    cnt = -cnt;
X                    goto outloop;
X                }
X            } while ( buf->rpid);
X        }
X        /*
X         * in read, one has still to check for SIGQUIT etc..
X         * the signal is sent by the writing-process
X         */
X        if( ch = getctrlchar( (*dest++ = *(buf->rptr)++), &pd))
X          switch( ch ) {
X            case INT:
X                errno = SIGINT;
X                cnt = - (--cnt);
X                goto outloop;
X
X            case QUT:
X                errno = SIGQUIT;
X                cnt = - (--cnt);
X                goto outloop;
X
X            case EOR:
X                pd.ptypvt.line = 0;
X                break;
X          }
X    }
Xoutloop:
X    buf->rpid = 0;
X    if(buf->rptr >= buf->wptr ) {
X        buf->wptr = buf->rptr = buf->buf;
X        /* stopped means STOP, so do not WakeUp */
X        if( !(buf->flags & STOPPED))
X          WAKE(buf->wpid, buf->wsig);
X    }
X    return( cnt);
X}
X
X/*
X * Lese cnt-Bytes. Echo, Lineediting, vorzeitiger Abbruch bei Lesen von CR
X * 0:   - cnt-bytes gelesen
X * x:   - (cnt-x) bytes gelesen
X * -x:  - nach (cnt-x) ist Fehler aufgetreten (Interupted, Hangup etc.)
X */
Xint
Xcpin(buf, echobuf, ustack, procdesc)
Xregister    struct  ptybuf *buf;
X            struct  ptybuf *echobuf;
X            REGISTERS      *ustack;
X            procid         *procdesc;
X{   register    int     cnt = ustack->d[1] & 0x7fffffff; /* no neg. counts */
X    register    u_char *dest = (u_char *) ustack->a[0];
X    register    u_char *old  = pd.path.pd_buf;
X    register    u_char  ch;
X
X    /*
X     * this can only happen if _ss_sign() was set
X     */
X    if( buf->rpid == procdesc->_id) {
X        errno = E_NOTRDY;
X        return -cnt;
X    }
X
X    /* wait for other processes to finish */
X    iowait( buf->rpid);
X    buf->rsig = SIGWAKE;
X
X    for(; cnt > 0; --cnt) {
X        /* if read-ptr reached write-ptr synchronize with partner */
X        while( buf->rptr >= buf->wptr ) {
X            /* reset ptr */
X            buf->wptr = buf->rptr = buf->buf;
X
X            /* stopped means STOP, so do not WakeUp */
X            if( !(buf->flags & STOPPED))
X              WAKE(buf->wpid, buf->wsig);
X
X            buf->rpid = procdesc->_id;
X            do {
X                if( dosleep(procdesc) < 0) {
X                    cnt = -cnt;
X                    goto outloop;
X                }
X            } while( buf->rpid);
X        }
X#ifdef UPCHAR
X        ch = ( pd.ptyopt.pd_upc ? upchar(*(buf->rptr)++) : *(buf->rptr)++);
X#else
X        ch = *(buf->rptr)++;
X#endif
X        switch( getctrlchar(ch, &pd) ) {
X
X            case BSP:
X               /*
X                * look in the Tech. manual to see what is meant here
X                */
X               if( ( pd.ptyopt.pd_bso ?
X                   (echochar( pd.ptyopt.pd_bse, echobuf, procdesc) +
X                    echochar( ' ' ,echobuf, procdesc) +
X                    echochar( pd.ptyopt.pd_bse, echobuf, procdesc) < 3) :
X                   (echochar( pd.ptyopt.pd_bse, echobuf, procdesc) < 1))) {
X                        cnt = -cnt;
X                        goto outloop;
X                }
X                dest--; old--;
X                dest = MAX( (dest), ((u_char *) ustack->a[0]));
X                old  = MAX( (old ), pd.path.pd_buf);
X                if( cnt == ustack->d[1] )
X                    cnt = ustack->d[1]+1;
X                else
X                    cnt += 2;
X                break;
X
X            case EOR:
X                /*
X                 * EOR resets pd_line and finishes
X                 */
X                pd.ptypvt.line = 0;
X                *old++ = *dest++ = ch;
X                if( ( echochar( ch, echobuf, procdesc) < 0
X                    || ( pd.ptyopt.pd_alf
X                        && echochar( '\l', echobuf, procdesc) < 0))) {
X                    cnt = -cnt;
X                    goto outloop;
X                }
X                cnt--;
X                goto outloop;
X
X            case INT:
X                *old = *dest = ch;
X                errno = SIGINT;
X                cnt = - (--cnt);
X                goto outloop;
X
X            case QUT:
X                *old = *dest = ch;
X                errno = SIGQUIT;
X                cnt = - (--cnt);
X                goto outloop;
X
X            case EOF:
X                /*
X                 * EOF only as first character !
X                 */
X                if( old == pd.path.pd_buf) {
X                    errno = E_EOF;
X                    cnt = -cnt;
X                    goto outloop;
X                }
X
X            case DEL:
X                if( pd.ptyopt.pd_dlo != '\0' ) {
X                  for(; old > pd.path.pd_buf; --old,cnt++)
X                    if(( pd.ptyopt.pd_bso ?
X                       (echochar( pd.ptyopt.pd_bse, echobuf, procdesc) +
X                        echochar( ' ' ,echobuf, procdesc) +
X                        echochar( pd.ptyopt.pd_bse, echobuf, procdesc) < 3) :
X                       (echochar( pd.ptyopt.pd_bse, echobuf, procdesc) < 1))) {
X                          cnt = -cnt;
X                          goto outloop;
X                    }
X                }
X                else
X                   if( (echochar( pd.ptyopt.pd_eor, echobuf, procdesc)
X                      + echochar( '\l', echobuf, procdesc) < 2)) {
X                            cnt = -cnt;
X                            goto outloop;
X                   }
X                dest = (u_char *) ustack->a[0];
X                old  = pd.path.pd_buf;
X                cnt  = ustack->d[1]+1;
X                break;
X
X            case DUP:
X                for(; cnt > 0 ; --cnt) {
X                  if((ch = *dest++ = *old++) == pd.ptyopt.pd_eor &&
X                      pd.ptyopt.pd_eor) {
X                           dest--; old--;
X                           break;
X                  }
X                  if( echochar( (ch < ' ' ? '.': ch), echobuf, procdesc) < 0) {
X                           cnt = - (--cnt);
X                           goto outloop;
X                  }
X                }
X                break;
X
X            case RPR:
X                *old = *dest = pd.ptyopt.pd_eor;
X                if(( echochar( *old, echobuf, procdesc) < 0 ||
X                    (pd.ptyopt.pd_alf && echochar( '\l', echobuf, procdesc) < 0))) {
X                      cnt = -cnt;
X                      goto outloop;
X                }
X                {
X                    register u_char *tmp = pd.path.pd_buf;
X
X                    for(; tmp < old; tmp++)
X                        if( echochar( *tmp, echobuf, procdesc) < 0) {
X                            cnt = - cnt;
X                            goto outloop;
X                        }
X		}
X                break;
X
X            default:
X                *old++ = *dest++ = ch;
X                if( echochar( (ch < ' ' ? '.': ch), echobuf, procdesc) < 0) {
X                    cnt = - (--cnt);
X                    goto outloop;
X                }
X        }
X    }
Xoutloop:
X    buf->rpid = 0;
X    if( buf->rptr >= buf->wptr ) {
X        buf->wptr = buf->rptr = buf->buf;
X        /* stopped means STOP, so do not WakeUp */
X        if( !(buf->flags & STOPPED))
X          WAKE(buf->wpid, buf->wsig);
X    }
X    return( cnt);
X}
X
X/*
X * Schreibe cnt-Bytes im Raw-modus. Kein Alf etc....
X * 0:   - cnt-bytes geschrieben
X * x:   - (cnt-x) bytes geschrieben
X * -x:  - nach (cnt-x) ist Fehler aufgetreten (Interupted, Hangup etc.)
X */
Xint
Xcpoutraw(buf, echobuf, ustack, procdesc)
Xregister    struct  ptybuf *buf;
Xregister    struct  ptybuf *echobuf;
X            REGISTERS      *ustack;
X            procid         *procdesc;
X{   register    int               cnt = ustack->d[1] & 0x7fffffff;
X    register    u_char            *src = (u_char *) ustack->a[0];
X    register    union   pathdesc  *echopd = echobuf->lpd;
X    register    u_char            ch;
X    register    u_int             bufend = (u_int) buf->buf + buf->size;
X
X    iowait( buf->wpid);
X    buf->wsig = SIGWAKE;
X    buf->lpd = &pd;
X
X    for(; cnt > 0; --cnt) {
X        while( (buf->wptr >= (u_char *) bufend)) {
X            if( !(buf->flags & STOPPED))
X              WAKE(buf->rpid, buf->rsig);
X            buf->wpid = procdesc->_id;
X            do {
X                if( dosleep(procdesc) < 0) {
X                    cnt = -cnt;
X                    goto outloop;
X                }
X	    } while( buf->wpid);
X        }
X        ch = *(buf->wptr)++ = *src++;
X        if( echopd )
X          switch( getctrlchar( ch, echopd )) {
X            /*
X             * Pause-Char: set pause-stop and remove char
X             */
X            case PSC:
X              echobuf->flags |= PSCSTOP;
X              (buf->wptr)--; /* dont send */
X              break;
X
X            /*
X             * XOFF-char .. set xoff-stop and remove char
X             */
X            case XOFF:
X              echobuf->flags |= XOFFSTOP;
X              (buf->wptr)--; /* dont send */
X              break;
X
X            /*
X             * XON-char .. remove xoff-stop and remove char
X             * we have to Wake the stopped process !!
X             */
X            case XON:
X              echobuf->flags &= ~XOFFSTOP;
X              (buf->wptr)--; /* dont send */
X              WAKE(echobuf->wpid, echobuf->wsig);
X              break;
X
X            /*
X             * here the INT and QUIT signals are sent to the
X             * last writing process ( echopd )
X             */
X            case INT:
X            case QUT:
X              if( ch == echopd->ptyopt.pd_int)
X                kill(echopd->path.pd_lproc,SIGINT);
X              else
X                kill(echopd->path.pd_lproc,SIGQUIT);
X              /* fall through ?! */
X
X            default:
X              /*
X               * any char removes the pause-stop !!!
X               * but the char gets clobbered
X               */
X              if( echobuf->flags & PSCSTOP ) {
X                echobuf->flags &= ~PSCSTOP;
X                (buf->wptr)--; /* dont send */
X                WAKE(echobuf->wpid, echobuf->wsig);
X              }
X              break;
X          }
X    }
Xoutloop:
X    buf->wpid = 0;
X    /*
X     * only send WAKEUP if we output any char !! (XON/PSC-stop!
X     * otherwise this may get confused with _ss_sigs !!
X     */
X    if( buf->wptr > buf->rptr && !(buf->flags & STOPPED ))
X      WAKE(buf->rpid, buf->rsig);
X    return( cnt);
X}
X
X/*
X * Schreibe cnt-Bytes. Alf, Tab-expanding, Pause-behandlung, Abbruch bei
X * vorzeitigem CR
X * 0:   - cnt-bytes geschrieben
X * x:   - (cnt-x) bytes geschrieben
X * -x:  - nach (cnt-x) ist Fehler aufgetreten (Interupted, Hangup etc.)
X */
Xint
Xcpout(buf, echobuf, ustack, procdesc)
Xregister    struct  ptybuf *buf;
Xregister    struct  ptybuf *echobuf;
X            REGISTERS      *ustack;
X            procid         *procdesc;
X{   register    int               cnt = ustack->d[1] & 0x7fffffff;
X    register    u_char            *src = (u_char *) ustack->a[0];
X    register    union   pathdesc  *echopd = echobuf->lpd;
X    register    u_char            ch;
X    register    u_int             bufend = (u_int) buf->buf + buf->size;
X
X    iowait( buf->wpid );
X    buf->wsig = SIGWAKE;
X    buf->lpd = &pd;
X
X    for(; cnt > 0; --cnt) {
X        while( (buf->wptr >= (u_char *) bufend)) {
X            if( !(buf->flags & STOPPED))
X              WAKE(buf->rpid, buf->rsig);
X            buf->wpid = procdesc->_id;
X            do {
X                if( dosleep(procdesc) < 0) {
X                    cnt = -cnt;
X                    goto outloop;
X                }
X            } while( buf->wpid);
X        }
X        pd.ptyopt.pd_Col++;
X        ch = *(buf->wptr)++ = *src++;
X        if( ch ) {
X          if( echopd )
X            switch( getctrlchar( ch, echopd )) {
X             /*
X              * Pause-Char: set pause-stop and remove char
X              */
X              case PSC:
X                echobuf->flags |= PSCSTOP;
X                (buf->wptr)--; /* dont send */
X                break;
X
X             /*
X              * XOFF-char .. set xoff-stop and remove char
X              */
X              case XOFF:
X                echobuf->flags |= XOFFSTOP;
X                (buf->wptr)--; /* dont send */
X                break;
X
X             /*
X              * XON-char .. remove xoff-stop and remove char
X              * we have to Wake to stopped process !!
X              */
X              case XON:
X                echobuf->flags &= ~XOFFSTOP;
X                (buf->wptr)--; /* dont send */
X                WAKE(echobuf->wpid, echobuf->wsig);
X                break;
X
X             /*
X              * QUIT and INT signals to last writing device
X              */
X              case INT:
X              case QUT:
X                if( ch == echopd->ptyopt.pd_int)
X                  kill(echopd->path.pd_lproc,SIGINT);
X                else
X                  kill(echopd->path.pd_lproc,SIGQUIT);
X                /* fall through ?? */
X
X              /*
X               * any char removes the pause-stop !!!
X               * but the char gets clobbered
X               */
X              default:
X                if( echobuf->flags & PSCSTOP ) {
X                  echobuf->flags &= ~PSCSTOP;
X                  (buf->wptr)--; /* dont send */
X                  WAKE(echobuf->wpid, echobuf->wsig);
X                }
X                break;
X            }
X          if( ch == pd.ptyopt.pd_eor ) {
X            pd.ptyopt.pd_Col = 0;
X            if( pd.ptyopt.pd_pau && ++pd.ptypvt.line == pd.ptyopt.pd_pag ) {
X                pd.ptypvt.line = 0;
X                iowait( echobuf->rpid);
X                if( !(echobuf->flags & STOPPED))
X                  WAKE(echobuf->wpid, echobuf->wsig);
X                echobuf->rpid = procdesc->_id;
X                do {
X                   if( dosleep(procdesc) < 0) {
X                      cnt = -cnt;
X                      goto outloop;
X                   }
X                } while( echobuf->rpid);
X                echobuf->rptr++;
X            }
X            if( pd.ptyopt.pd_alf ) {
X                if( buf->wptr >= (buf->buf + buf->size)) {
X                    if( !(echobuf->flags & STOPPED))
X                      WAKE(buf->rpid, buf->rsig);
X                    buf->wpid = procdesc->_id;
X                    do {
X                        if( dosleep(procdesc) < 0) {
X                            cnt = -cnt;
X                            goto outloop;
X                        }
X                    } while( buf->wpid);
X		}
X                *(buf->wptr)++ = '\l';
X            }
X            --cnt;
X            break;
X          } else
X            if( pd.ptyopt.pd_Tabs && pd.ptyopt.pd_Tab && ch == pd.ptyopt.pd_Tab) {
X                register short i = (pd.ptyopt.pd_Col-1) % pd.ptyopt.pd_Tabs;
X                (buf->wptr)--;
X                for(; i > 0; i--) {
X                    while( buf->wptr >= (buf->buf + buf->size)) {
X                        if( !(buf->flags & STOPPED))
X                          WAKE(buf->rpid, buf->rsig);
X                        buf->wpid = procdesc->_id;
X                        do {
X                            if( dosleep(procdesc) < 0) {
X                                cnt = -cnt;
X                                goto outloop;
X                            }
X                        } while( buf->wpid);
X                    }
X                    *(buf->wptr)++ = ' ';
X                }
X            }
X        }
X    }
Xoutloop:
X    buf->wpid = 0;
X    /*
X     * only send WAKEUP if we output any char !! (XON/PSC-stop!
X     * otherwise this may get confused with _ss_sigs !!
X     */
X    if( buf->wptr > buf->rptr && !(buf->flags & STOPPED ))
X      WAKE(buf->rpid, buf->rsig);
X    return( cnt);
X}
END_OF_FILE
if test 21278 -ne `wc -c <'funcs.c'`; then
    echo shar: \"'funcs.c'\" unpacked with wrong size!
fi
# end of 'funcs.c'
fi
if test -f 'ptyman.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ptyman.c'\"
else
echo shar: Extracting \"'ptyman.c'\" \(19781 characters\)
sed "s/^X//" >'ptyman.c' <<'END_OF_FILE'
X/*       This software is copyright (C) 1989 by Reimer Mellin        *
X*                                                                    *
X*        Permission is granted to reproduce and distribute           *
X*        this package by any means so long as no fee is charged      *
X*        above a nominal handling fee and so long as this            *
X*        notice is always included in the copies.                    *
X*        Commerical use or incorporation into commercial software    *
X*        is prohibited without the written permission of the         *
X*        author.                                                     *
X*                                                                    *
X*        Other rights are reserved except as explicitly granted      *
X*        by written permission of the author.                        *
X*                Reimer Mellin                                       *
X*                                                                    *
X*                Sulenstr.8                                          *
X*                D-8000 Muenchen 71 (Federal Republic of Germany)    *
X*                                                                    *
X*           EMAIL:                                                   *
X*                mellin@lan.informatik.tu-muenchen.dbp.de            *
X*                ram@altger.UUCP                                     *
X*                ram%ramsys@chiuur.sub.org (home)                    *
X*                                                                    */
X
X/*  */
X
X/*
X * HauptModul des PtyManagers -- Einsprung-Routinen vom Assembler-Interface
X *
X * $Header: /h0/USR/REIMER/PTYMAN/RCS/ptyman.c_v 1.3 91/06/08 01:19:40 ram Exp $
X *
X * $Log:	ptyman.c_v $
X * Revision 1.3  91/06/08  01:19:40  ram
X * Added SS_IOCONT & SS_IOSTOP, various bugfixes, ftp-release on smilodon,
X * please share and distribute !!
X * 
X * Revision 1.2.1.2  89/09/04  13:14:23  ram
X * added some comments
X * 
X * Revision 1.2.1.1  89/08/31  12:26:06  ram
X * Copyright-message added
X * 
X * Revision 1.2  89/07/16  01:06:12  ram
X * minor changes to Sub-net Release
X * 
X * Revision 1.1.1.1  89/07/14  19:49:56  ram
X * Fixed: SS_SSig Bug. Sub-Net Beta-Release
X * 
X * Revision 1.1  89/07/13  23:22:15  ram
X * Initial revision
X * 
X */
X
X#include <types.h>
X#include <MACHINE/reg.h>
X#include "Ptyman.h"
X#include <path.h>
X#include <sg_codes.h>
X#include <procid.h>
X#include <modes.h>
X#include <sgstat.h>
X#include <setsys.h>
X#include <signal.h>
X#include <errno.h>
X
X#ifdef ST
X#include <stconfuncs.h>
X#endif
X
X#include "misc.h"
X
Xunion pathdesc pd;      /* a6 points to the Path-Descriptor !!! */
X
X/*
X * O P E N
X */
XOpen(procdesc, ustack)
X  procid    *procdesc;
X  REGISTERS *ustack;
X{
X    register    u_char  *name = (u_char *) ustack->a[0];
X    register    int      namcnt,i;
X    register    Pathdesc ptr;
X
X    if( ( namcnt = _prsnam(name)) < 0)
X        return -1;
X
X    pd.ptypvt.typ = (name[1] == 'P' || name[1] == 'p') ? PTY : TTY;
X
X    if( (pd.path.pd_mod & (u_char) ustack->d[0]) != (u_char) ustack->d[0]) {
X        errno = E_BMODE;
X        return -1;
X    }
X
X    pd.path.pd_mod = (u_char) ustack->d[0];
X    if( pd.ptypvt.typ == TTY || !(pd.path.pd_mod & S_IFDIR)) {
X      if( name[namcnt] != '/') {
X        errno = E_BPNAM;
X        return -1;
X      }
X
X      name += namcnt+1;
X
X      if( ( namcnt = _prsnam(name)) < 0 || namcnt > 28
X         || name[namcnt] != '\0') {
X        errno = E_BPNAM;
X        return -1;
X      }
X    }
X
X    for(i=0; i < namcnt;i++)
X        pd.ptyopt.pd_name[i] = upchar(name[i]);
X
X    pd.ptyopt.pd_name[namcnt-1] |= 0x80;
X    
X    pd.ptyopt.pd_namlen = namcnt;
X
X    /* normal ptys have buffers and so on, dir-ptys don't ! */
X    if( !(pd.path.pd_mod & S_IFDIR)) {
X      if( pd.ptypvt.typ != PTY) {
X          /* tty */
X          /* look for correspondent pty in path-list and then look its
X           * tty-list for already openend NON-SHAREABLE ttys ...
X           */
X
X          /*
X           * The start of all open paths on this device
X           * maintained by the kernel (IOMan)
X           */
X          ptr = ((Ptystatic) pd.path.pd_dev->V_stat)->v_sysio.v_paths;
X          for(; ptr ; ptr = ptr->path.pd_paths)
X              if( ptr->ptypvt.typ == PTY
X               && strcmp( ptr->ptyopt.pd_name, pd.ptyopt.pd_name) == 0 ) {
X                  pd.ptypvt.pty = ptr;
X
X                  /*
X                   * look through the connected tty-list of the pty
X                   */
X                  for( ptr = ptr->ptypvt.tty; ptr ; ptr = ptr->ptypvt.tty)
X                    if( S_ISHARE & (pd.path.pd_mod | ptr->path.pd_mod) ) {
X                      errno = E_SHARE;
X                      return -1;
X                    }
X                  /*
X                   * Ok: we found a pty with no NON-SHAREABLES ttys
X                   */
X                  pd.ptypvt.tty = pd.ptypvt.pty->ptypvt.tty;
X                  pd.ptypvt.pty->ptypvt.tty = &pd;
X                  /*
X                   * send the pty on onsig, if requested
X                   */
X                  if( pd.ptypvt.pty->ptypvt.onsig != 0 )
X                      kill((ptr->path.pd_cpr ?
X                              ptr->path.pd_cpr : ptr->path.pd_lproc)
X                           ,pd.ptypvt.pty->ptypvt.onsig);
X                  return 0;
X              }
X          /*
X           * not found ... linger around and wait until connected by the pty
X           * any real i/o will isuue an error
X           */
X          return 0;
X      } else {
X          /* pty */
X          /* if same name exists, exists with error */
X
X          /*
X           * The start of all open paths on this device
X           * maintained by the kernel (IOMan)
X           */
X          ptr = ((Ptystatic) pd.path.pd_dev->V_stat)->v_sysio.v_paths;
X          for(; ptr ; ptr = ptr->path.pd_paths)
X              if( ptr->ptypvt.typ == PTY && ptr != &pd
X               && strcmp( ptr->ptyopt.pd_name, pd.ptyopt.pd_name) == 0 ) {
X                  errno = E_SHARE;
X                  return -1;
X              }
X          /*
X           * Ok: we are the only pty with our name
X           * set buffersize and allocate them; if NOMEM exit with error
X           */
X          pd.ptypvt.rbuf.size = pd.ptypvt.wbuf.size = DEFBUFSIZE;
X          if((pd.ptypvt.rbuf.buf =
X                    (u_char *)_srqmem( (pd.ptypvt.rbuf.size))) == (u_char *)0 ||
X             (pd.ptypvt.wbuf.buf =
X                    (u_char *)_srqmem( (pd.ptypvt.wbuf.size))) == (u_char *)0) {
X              if( pd.ptypvt.wbuf.buf )
X                  (void) _srtmem(pd.ptypvt.wbuf.buf,pd.ptypvt.wbuf.size);
X              if( pd.ptypvt.rbuf.buf )
X                  (void) _srtmem(pd.ptypvt.rbuf.buf,pd.ptypvt.rbuf.size);
X              return -1;
X          }
X
X          pd.ptypvt.rbuf.rptr = pd.ptypvt.rbuf.wptr = pd.ptypvt.rbuf.buf;
X          pd.ptypvt.wbuf.rptr = pd.ptypvt.wbuf.wptr = pd.ptypvt.wbuf.buf;
X
X          /*
X           * The start of all open paths on this device
X           * maintained by the kernel (IOMan)
X           */
X          ptr = ((Ptystatic) pd.path.pd_dev->V_stat)->v_sysio.v_paths;
X          /* look for all lingering ttys and connect them */
X          for(; ptr ; ptr = ptr->path.pd_paths)
X              if( ptr->ptypvt.typ == TTY
X               && strcmp( ptr->ptyopt.pd_name, pd.ptyopt.pd_name) == 0 ) {
X                  ptr->ptypvt.pty = &pd;
X                  ptr->ptypvt.tty = pd.ptypvt.tty;
X                  pd.ptypvt.tty = ptr;
X                  /*
X                   * if they had wished on DCON-sig, give them what they want
X                   */
X                  if( ptr->ptypvt.onsig != 0 )
X                      kill( (ptr->path.pd_cpr ?
X                             ptr->path.pd_cpr : ptr->path.pd_lproc)
X                           , ptr->ptypvt.onsig);
X              }
X      }
X    } else {
X      /*
X       * dir-ptys have a list of ptys to output :-)
X       * misuse the tty-list for that
X       */
X      pd.ptypvt.tty = ((Ptystatic) pd.path.pd_dev->V_stat)->v_sysio.v_paths;
X    }
X    return 0;
X}
X
X/*
X * C l o s e
X */
XClose(procdesc, ustack)
X  procid    *procdesc;
X  REGISTERS *ustack;
X{
X    register    struct ptybuf *bptr;
X
X    if( !(pd.path.pd_mod & S_IFDIR)) {
X      /*
X       * non-dir-ptys have some cleanup to do
X       */
X
X      /* clear _ss_sign() */
X      bptr = ( pd.ptypvt.typ == PTY || pd.ptypvt.pty == 0) ?
X          &pd.ptypvt.rbuf :
X          &((pd.ptypvt.pty)->ptypvt.wbuf);
X      if( bptr->rpid == procdesc->_id )
X          bptr->rpid = 0;
X
X      /* deallocate buffer if we are the last incarnation on this pd */
X      if( pd.path.pd_count == 0 )
X          if( pd.ptypvt.typ == PTY ) {
X              register Pathdesc ptr;
X      /*
X       * and send all listening ttys a HUP and mark that the connection
X       * is severed
X       */
X              for(ptr = pd.ptypvt.tty; ptr ; ptr = ptr->ptypvt.tty) {
X                      ptr->ptypvt.pty = (union pathdesc *) 0;
X                      kill( (ptr->path.pd_cpr ?
X                             ptr->path.pd_cpr : ptr->path.pd_lproc)
X                           ,(ptr->ptypvt.offsig ? ptr->ptypvt.offsig : SIGHUP));
X              }
X              (void) _srtmem( pd.ptypvt.rbuf.buf, pd.ptypvt.rbuf.size);
X              (void) _srtmem( pd.ptypvt.wbuf.buf, pd.ptypvt.wbuf.size);
X          } else {
X              if( pd.ptypvt.pty != 0 ) {
X                register Pathdesc ptr;
X
X              /*
X               * tty: ok remove us from the connected-tty-list in the pty
X               * data-structure
X               */
X                for(ptr = pd.ptypvt.pty; ptr ; ptr = ptr->ptypvt.tty)
X                  if( ptr->ptypvt.tty == &pd )
X                    ptr->ptypvt.tty = pd.ptypvt.tty;
X
X              /*
X               * cancel all references to us ... (for echo or whatever)
X               * and send the pty an sighup if requested
X               */
X                if( (pd.ptypvt.pty)->ptypvt.rbuf.lpd == &pd)
X                  (pd.ptypvt.pty)->ptypvt.rbuf.lpd = NULL;
X                if( (pd.ptypvt.pty)->ptypvt.tty == NULL
X                  && (pd.ptypvt.pty)->ptypvt.offsig != 0)
X                  kill( ((pd.ptypvt.pty)->path.pd_cpr ?
X                         (pd.ptypvt.pty)->path.pd_cpr :
X                         (pd.ptypvt.pty)->path.pd_lproc)
X                       ,(pd.ptypvt.pty)->ptypvt.offsig);
X              }
X              /*
X               * if we had a line-editing-buffer .. free it
X               */
X              if( pd.path.pd_buf )
X                  (void) _srtmem( pd.path.pd_buf, LINEBUFSIZ);
X          }
X    } else {
X      pd.ptypvt.tty = 0;
X    }
X    return(0);
X}
X
XIoRet ( bytes , ustack )
Xint         bytes;
XREGISTERS   *ustack;
X{
X    if( bytes < 0) {
X        ustack->d[1] += bytes;
X        return -1;
X    }
X    ustack->d[1] -= bytes;
X    return(0);
X}
X
XReadDir( ustack )
X  REGISTERS *ustack;
X{
X  register int      i;
X  
X  while( pd.ptypvt.tty && ( pd.ptypvt.tty == &pd
X                        || (pd.ptypvt.tty)->ptypvt.typ != pd.ptypvt.typ))
X    pd.ptypvt.tty = (pd.ptypvt.tty)->path.pd_paths;
X  if( pd.ptypvt.tty ) {
X    i = MIN( 32, ustack->d[1] );
X    memcpy( ustack->a[0], (pd.ptypvt.tty)->ptyopt.pd_name, i);
X    ustack->d[1] = i;
X  } else {
X    errno = E_EOF;
X    return -1;
X  }
X  pd.ptypvt.tty = (pd.ptypvt.tty)->path.pd_paths;
X  return 0;
X}
X
XRead(procdesc, ustack)
X  procid    *procdesc;
X  REGISTERS *ustack;
X{
X
X    if( (pd.path.pd_mod & S_IFDIR)) {
X      return(ReadDir( ustack ));
X    }
X
X    /*
X     * return error if no connection established
X     */
X    if( hangup(procdesc) )
X        return -1;
X
X    /*
X     * select buffer ...
X     */
X    if( pd.ptypvt.typ == PTY ) {
X        return( IoRet( (cpinraw( &pd.ptypvt.rbuf, &pd.ptypvt.wbuf,
X            ustack, procdesc)), ustack ));
X    } else {
X        return( IoRet( (cpinraw( &((pd.ptypvt.pty)->ptypvt.wbuf),
X            &((pd.ptypvt.pty)->ptypvt.rbuf), ustack, procdesc)), ustack));
X    }
X}
X
XReadLn(procdesc, ustack)
X  procid    *procdesc;
X  REGISTERS *ustack;
X{
X    if( (pd.path.pd_mod & S_IFDIR)) {
X      return(ReadDir( ustack ));
X    }
X
X    if( hangup(procdesc) )
X        return -1;
X    /*
X     * the line-editing buffer
X     */
X    if( pd.path.pd_buf == NULL) {
X        if((pd.path.pd_buf = (u_char *) _srqmem(LINEBUFSIZ)) == NULL)
X            return(-1);
X        else
X            initbuf(pd.path.pd_buf, LINEBUFSIZ-1);  /* dont change !! */
X    }
X
X    if( ustack->d[1] > LINEBUFSIZ )
X        ustack->d[1] = LINEBUFSIZ;
X
X    /*
X     * select buffer ...
X     */
X    if( pd.ptypvt.typ == PTY ) {
X        return( IoRet( (cpin( &pd.ptypvt.rbuf, &pd.ptypvt.wbuf,
X                              ustack, procdesc))
X                       , ustack ));
X    } else {
X        return( IoRet( (cpin( &((pd.ptypvt.pty)->ptypvt.wbuf),
X                              &((pd.ptypvt.pty)->ptypvt.rbuf),
X                              ustack, procdesc))
X                       , ustack ));
X    }
X}
X
XWrite(procdesc, ustack)
X  procid    *procdesc;
X  REGISTERS *ustack;
X{
X    if( (pd.path.pd_mod & S_IFDIR)) {
X      errno = E_BMODE;
X      return -1;
X    }
X
X    if( hangup(procdesc) )
X        return -1;
X
X    if( pd.ptypvt.typ == PTY ) {
X        return( IoRet( (cpoutraw( &pd.ptypvt.wbuf, &pd.ptypvt.rbuf,
X                                  ustack, procdesc))
X                       , ustack ));
X    } else {
X        return( IoRet( (cpoutraw( &((pd.ptypvt.pty)->ptypvt.rbuf),
X                                  &((pd.ptypvt.pty)->ptypvt.wbuf),
X                                  ustack, procdesc))
X                       , ustack ));
X    }
X}
X
XWriteLn(procdesc, ustack)
X  procid    *procdesc;
X  REGISTERS *ustack;
X{
X    if( (pd.path.pd_mod & S_IFDIR)) {
X      errno = E_BMODE;
X      return -1;
X    }
X
X    if( hangup(procdesc) )
X        return -1;
X
X    if( pd.ptypvt.typ == PTY ) {
X        return( IoRet( (cpout( &pd.ptypvt.wbuf, &pd.ptypvt.rbuf, 
X                               ustack, procdesc))
X                       , ustack ));
X    } else {
X        return( IoRet( (cpout( &((pd.ptypvt.pty)->ptypvt.rbuf), 
X                               &((pd.ptypvt.pty)->ptypvt.wbuf),
X                               ustack, procdesc))
X                       , ustack));
X    }
X}
X
X
X/*
X * G e t S t a t
X */
XGetStat(procdesc, ustack)
X  procid    *procdesc;
X  REGISTERS *ustack;
X{
X    register struct ptybuf  *ptr;
X
X    switch (ustack->d[1] & 0x0ffff) {
X
X        case SS_DevNm:
X            /*
X             * returns name of the [pt]ty ...
X             */
X            memcpy( ustack->a[0], "tty/", 4);
X            if( pd.ptypvt.typ == PTY)
X                    *((u_char *)ustack->a[0]) = 'p';
X            memcpy( ((u_char *)ustack->a[0]) + 4, pd.ptyopt.pd_name,
X                    pd.ptyopt.pd_namlen);
X            *((u_char *) ustack->a[0] + pd.ptyopt.pd_namlen + 4) = '\0';
X            break;
X
X        case SS_Opt:
X            /*
X             * copy the option-field
X             */
X            memcpy( ustack->a[0], &(pd.ptyopt.pd_dtp), OPTMAX);
X            break;
X
X        case SS_Size:
X            /*
X             * buffer size lesen ?!
X             */
X            ustack->d[2] = pd.path.pd_mod & S_IFDIR ? 32 : DEFBUFSIZE ;
X            break;
X
X        default:
X            if( hangup(procdesc) )
X                return -1;
X            switch (ustack->d[1] & 0x0ffff) {
X
X                case SS_Ready:
X                    /*
X                     * return TRUE if number of chars in buffer > 0 ...
X                     */
X                    ptr = ( pd.ptypvt.typ == PTY) ? &pd.ptypvt.rbuf :
X                         &((pd.ptypvt.pty)->ptypvt.wbuf);
X                    if( (ptr->flags & STOPPED)
X                      || (ustack->d[1] = (ptr->wptr - ptr->rptr)) <= 0 ) {
X                        errno = E_NOTRDY;
X                        return -1;
X                    }
X                    break;
X
X                case SS_EOF:
X                    /*
X                     * always return 0
X                     */
X                    ustack->d[1] = 0;
X                    break;
X
X                case SS_BlkRd:
X                    /*
X                     * like a Read
X                     */
X                    ustack->d[1] = ustack->d[2];
X                    return( Read( procdesc, ustack));
X
X                default:        
X                    pd.path.pd_errno = E_UNKSVC;
X                    return(-1);
X            }
X    }
X    return (0);
X}
X
X
X/*
X * S e t S t a t
X */
XSetStat(procdesc, ustack)
X  procid    *procdesc;
X  REGISTERS *ustack;
X{
X    register struct ptybuf  *ptr;
X
X    switch (ustack->d[1] & 0x0ffff) {
X
X        case SS_EnRTS:
X        case SS_DCOn:
X            /*
X             * set the pd_onsig -- thats all
X             */
X            pd.ptypvt.onsig = (u_short) ustack->d[2];
X            break;
X            
X        case SS_DsRTS:
X        case SS_DCOff:
X            /*
X             * set the pd_offsig -- thats all
X             */
X            pd.ptypvt.offsig = (u_short) ustack->d[2];
X            break;
X
X        case SS_Opt:
X            /*
X             * copy the option-field
X             */
X            memcpy( &(pd.ptyopt.pd_dtp), ustack->a[0], OPTMAX);
X            break;
X
X        default:
X            if( hangup(procdesc) )
X                return -1;
X            switch (ustack->d[1] & 0x0ffff) {
X                register    union pathdesc *sp;
X
X                case SS_IOSTOP:
X                    sp = ( pd.ptypvt.typ == PTY) ?
X                              &pd :
X                               pd.ptypvt.pty;
X                    sp->ptypvt.rbuf.flags |= IOSTOP;
X                    sp->ptypvt.wbuf.flags |= IOSTOP;
X                    break;
X
X                case SS_IOCONT:
X                    sp = ( pd.ptypvt.typ == PTY) ?
X                              &pd :
X                               pd.ptypvt.pty;
X                    sp->ptypvt.rbuf.flags &= ~IOSTOP;
X                    WAKE( sp->ptypvt.rbuf.rpid, sp->ptypvt.rbuf.rsig );
X                    sp->ptypvt.wbuf.flags &= ~IOSTOP;
X                    WAKE( sp->ptypvt.wbuf.rpid, sp->ptypvt.wbuf.rsig );
X                    break;
X
X                case SS_SSig:
X                    /*
X                     * set ssig, if someother is already waiting --> error
X                     * if data is already available --> send sig immediatly
X                     */
X                    ptr = ( pd.ptypvt.typ == PTY) ?
X                              &pd.ptypvt.rbuf :
X                              &((pd.ptypvt.pty)->ptypvt.wbuf);
X                    if( ptr->rpid || (ptr->flags & STOPPED)) {
X                        errno = E_NOTRDY;
X                        return -1;
X                    }
X                    if( ((ptr->wptr - ptr->rptr)) <= 0 ) {
X                        ptr->rpid = procdesc->_id;
X                        ptr->rsig = ustack->d[2];
X                    } else kill(procdesc->_id,ustack->d[2]);
X                    break;
X
X                case SS_Relea:
X                    /*
X                     * clear _ss_sign()
X                     */
X                    ptr = ( pd.ptypvt.typ == PTY) ?
X                              &pd.ptypvt.rbuf :
X                              &((pd.ptypvt.pty)->ptypvt.wbuf);
X                    if( ptr->rpid == procdesc->_id)
X                        ptr->rpid = 0;
X                    break;
X#ifdef ST
X                /*
X                 * like Blkwr
X                 */
X                case SS_Screen:
X                    if( (u_short) ustack->d[2] != ScrOut)
X                        break;
X                    ustack->d[2] = ustack->d[3];
X#endif
X                case SS_BlkWr:
X                /*
X                 * like a Write
X                 */
X                    ustack->d[1] = ustack->d[2];
X                    return( Write( procdesc, ustack));
X
X                default:
X                    pd.path.pd_errno = E_UNKSVC;
X                    return(-1);
X            }
X    }
X    return (0);
X}
END_OF_FILE
if test 19781 -ne `wc -c <'ptyman.c'`; then
    echo shar: \"'ptyman.c'\" unpacked with wrong size!
fi
# end of 'ptyman.c'
fi
echo shar: End of archive 2 \(of 2\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
| Frank Kaefer | fkk@stasys.sta.sub.org | Starnberg, Germany |
| Compuserve: 72427,2101   | Internet: fkk@Germany.Sun.COM   |
| unido!sunde!fkaefer      |    postmaster@Germany.Sun.COM   |