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 |