home *** CD-ROM | disk | FTP | other *** search
- /* havefun.c - This module contains the code to do the main i/o handling.
-
- Copyright 1989 by Jeffrey F. Lawhorn (jeffl@berick.uucp)
-
- This file is part of vuser.
-
- vuser is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your
- option) any later version.
-
- vuser is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to the
- Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #if !defined(lint)
- static char SCCSid[] = "$Id: havefun.c,v 1.1 89/12/15 21:28:52 jeffl Exp $";
- #endif
-
- #include <stdio.h>
- #include <ctype.h>
- #include <signal.h>
-
- #if defined(__STDC__)
- extern void KillSlave();
- extern int DeadSlave();
- void Send2MasterPty(char *, int);
- void Send2stdout(char *, int);
- #else
- extern void KillSlave();
- extern int DeadSlave();
- void Send2MasterPty();
- void Send2stdout();
- #endif
-
- extern FILE *ScriptFile;
- extern FILE *RecordFile;
- extern int MasterPty;
- extern int Interactive;
-
- char PromptBuf[4096];
- char InComingPrompt[8192];
- char PromptLookedFor[4096];
- int PromptSize = 10;
- int PromptCount = 0;
- int ICPCount = 0;
- int ICPLength = 0;
- char *CurrPromptPos = PromptBuf - 1;
- char EscapeChar = '@';
- #if defined(TIMEOUT_IS_LONG)
- long TimeOut = 30;
- #else
- #include <sys/time.h>
- struct timeval TimeOut = {30, 0};
- #endif
-
- void Send2ScriptFile(curr, start, stop, size)
- char *curr, *start, *stop;
- int size;
- {
- if(curr > stop)
- curr = start + 1;
- while(size--) {
- if(isprint(*curr) && *curr != '\\')
- putc(*curr, ScriptFile);
- else
- switch(*curr) {
- case '\n': fputs("\\n", ScriptFile); break;
- case '\r': fputs("\\r", ScriptFile); break;
- case '\t': fputs("\\t", ScriptFile); break;
- case '\f': fputs("\\f", ScriptFile); break;
- case '\\': fputs("\\\\", ScriptFile); break;
- default: fprintf(ScriptFile, "\\0%03o", *curr); break;
- }
- if(++curr > stop)
- curr = start;
- }
- putc('\n', ScriptFile);
- return;
- }
-
- int GetOneChar()
- {
- char chr = 0;
-
- if(Interactive) {
- write(1, "@", 1);
- read(0, &chr, 1);
- if(chr != EscapeChar)
- write(1, &chr, 1);
- return((int)chr);
- }
- return(getchar());
- }
-
- int DoEscape(inBuf, cnt)
- char *inBuf;
- int cnt;
- {
- int gotChar = -1;
- char buf[4096];
-
- if(!cnt)
- gotChar = GetOneChar();
- else {
- gotChar = *inBuf++;
- --cnt;
- }
- if(gotChar == EscapeChar) {
- if(ScriptFile) {
- fseek(ScriptFile, -1, 1);
- putc(EscapeChar, ScriptFile);
- putc('\n', ScriptFile);
- }
- if(!Interactive)
- write(1, &gotChar, 1);
- return(0);
- }
- if(Interactive)
- Tty2ShellMode();
- if(gotChar == '!') {
- if(cnt)
- strcpy(buf, inBuf);
- else
- gets(buf);
- if(ScriptFile) {
- fseek(ScriptFile, -1, 1);
- putc('!', ScriptFile);
- fputs(buf, ScriptFile);
- }
- if(!Interactive) {
- write(1, "@!", 2);
- write(1, buf, strlen(buf));
- write(1, "\n", 1);
- }
- signal(SIGCLD, SIG_DFL);
- system(buf);
- signal(SIGCLD, DeadSlave);
- } else if(gotChar == 't' || gotChar == 'T') {
- gets(buf);
- if(ScriptFile) {
- fseek(ScriptFile, -1, 1);
- putc('t', ScriptFile);
- fputs(buf, ScriptFile);
- }
- if(!Interactive) {
- write(1, "@t", 2);
- write(1, buf, strlen(buf));
- write(1, "\n", 1);
- }
- #if defined(TIMEOUT_IS_LONG)
- TimeOut = atol(buf);
- #else
- TimeOut.tv_sec = atol(buf);
- #endif
- } else if(gotChar == 'q' || gotChar == 'Q') {
- gets(buf);
- if(ScriptFile) {
- fseek(ScriptFile, -1, 1);
- putc('q', ScriptFile);
- fputs(buf, ScriptFile);
- }
- if(!Interactive) {
- write(1, "@q", 2);
- write(1, buf, strlen(buf));
- write(1, "\n", 1);
- }
- PromptSize = atoi(buf);
- }
- Tty2ProgramMode();
- return(1);
- }
-
- void SendResponse();
-
- void GetNextPrompt()
- {
- int chr = EOF;
-
- ICPLength = 0;
- while((chr = getchar()) != EOF) {
- switch(chr) {
- case '\n': {
- if(!ICPLength)
- SendResponse();
- return;
- }
- case '\\': {
- switch(chr = getchar()) {
- case '0': {
- chr = ((getchar() - '0') * 64);
- chr += ((getchar() - '0') * 8);
- chr += (getchar() - '0');
- break;
- }
- case 'n': chr = '\n'; break;
- case 'r': chr = '\r'; break;
- case 't': chr = '\t'; break;
- case 'f': chr = '\f'; break;
- case '\\': break;
- }
- break;
- }
- }
- PromptLookedFor[ICPLength++] = chr;
- }
- return;
- }
-
- void SendResponse()
- {
- int chr = EOF;
- int sendBufCount = 0;
- char sendBuf[4096];
-
- while((chr = getchar()) != EOF) {
- switch(chr) {
- case '\n': {
- Send2MasterPty(sendBuf, sendBufCount);
- GetNextPrompt();
- return;
- }
- case '\\': {
- switch(chr = getchar()) {
- case '0': {
- chr = ((getchar() - '0') * 64);
- chr += ((getchar() - '0') * 8);
- chr += (getchar() - '0');
- break;
- }
- case 'n': chr = '\n'; break;
- case 'r': chr = '\r'; break;
- case 't': chr = '\t'; break;
- case 'f': chr = '\f'; break;
- case '\\': break;
- }
- break;
- }
- }
- if(chr == EscapeChar)
- if(DoEscape(NULL, 0))
- continue;
- sendBuf[sendBufCount++] = chr;
- }
- return;
- }
-
- int PromptCompare(ptr1, ptr2, cnt)
- char *ptr1, *ptr2;
- int cnt;
- {
- while(cnt-- && *ptr1++ == *ptr2++);
- if(!cnt)
- return(0);
- return(*--ptr1 - *--ptr2);
- }
-
- void DoPromptStuff(buf, cnt)
- char *buf;
- int cnt;
- {
- while(cnt--) {
- InComingPrompt[ICPCount++] = *buf++;
- if(ICPCount >= ICPLength) {
- if(ICPCount > 8192) {
- memcpy(InComingPrompt, InComingPrompt + ICPCount - ICPLength,
- ICPLength);
- ICPCount = ICPLength;
- }
- if(!PromptCompare(InComingPrompt + ICPCount - ICPLength,
- PromptLookedFor, ICPLength)) {
- SendResponse();
- ICPCount = 0;
- continue;
- }
- }
- }
- return;
- }
-
- void Send2stdout(buf, cnt)
- char *buf;
- int cnt;
- {
- int savedCnt = 0;
-
- if(ScriptFile)
- for(; savedCnt < cnt; ++savedCnt) {
- if(++CurrPromptPos > PromptBuf + PromptSize)
- CurrPromptPos = PromptBuf;
- *CurrPromptPos = *(buf + savedCnt);
- if(PromptCount++ >= PromptSize)
- PromptCount = PromptSize;
- }
- write(1, buf, cnt);
- if(!Interactive)
- DoPromptStuff(buf, cnt);
- if(RecordFile)
- fwrite(buf, 1, cnt, RecordFile);
- return;
- }
-
- void Send2MasterPty(buf, cnt)
- char *buf;
- int cnt;
- {
- static int lastCharSent = -1;
-
- if(ScriptFile) {
- if(cnt == 1 && *buf != EscapeChar && PromptCount > 0
- && PromptBuf[PromptCount - 1] == lastCharSent) {
- fseek(ScriptFile, -1, 1);
- Send2ScriptFile(buf, buf, buf + 1, 1);
- } else {
- Send2ScriptFile(PromptCount >= PromptSize ?
- CurrPromptPos+1:PromptBuf,
- PromptBuf, PromptBuf + PromptSize, PromptCount);
- CurrPromptPos = PromptBuf - 1;
- PromptCount = 0;
- Send2ScriptFile(buf, buf, buf + cnt, cnt);
- }
- lastCharSent = buf[cnt - 1];
- }
- if(Interactive) {
- int pos = 0;
- for(; pos < cnt; ++pos)
- if(buf[pos] == EscapeChar) {
- write(MasterPty, buf, pos);
- if(DoEscape(buf + pos + 1, cnt - pos - 1))
- return;
- }
- }
- write(MasterPty, buf, cnt);
- return;
- }
-
- void HaveFun()
- {
- int readMask = 0, cnt = -1;
- char buf[4096];
-
- if(!Interactive)
- GetNextPrompt();
- while(1) {
- readMask = (1 << MasterPty) | Interactive;
- if(select(32, &readMask, (int *)NULL, (int *)NULL, &TimeOut) < 0) {
- perror("on select: ");
- KillSlave();
- }
- if(readMask & (1 << MasterPty)) {
- if((cnt = read(MasterPty, buf, sizeof(buf))) < 0) {
- perror("read of master pty: ");
- KillSlave();
- }
- Send2stdout(buf, cnt);
- } else if(readMask & 1) {
- if((cnt = read(0, buf, sizeof(buf))) < 0) {
- perror("read of stdin: ");
- KillSlave();
- }
- Send2MasterPty(buf, cnt);
- } else if(!Interactive)
- SendResponse();
- }
- }
-