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 |