1 /* An ircII-like split-screen front end
2 Copyright (C) 1995 Roger Espel Llima
4 Started: 17 Feb 95 by orabidoo <roger.espel.llima@ens.fr>
5 Latest modification: 7 June 97
7 To compile: gcc ssfe.c -o ssfe -ltermcap
9 If it doesn't work, try gcc ssfe.c -o ssfe -lcurses
10 or try cc, acc or c89 instead of gcc, or -lncurses.
12 Use: ssfe [options] program arguments
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation. See the file LICENSE for details.
20 #include <sys/types.h>
34 #include <sys/ioctl.h>
37 #include <sys/select.h>
43 unsigned char *statusline;
44 int ystatus, yinput; /* line number of the status line, input line */
52 struct sgttyb term, term0;
53 struct tchars tch, tch0;
54 struct ltchars lch, lch0;
56 struct termios term, term0;
62 int readfd, writefd, errfd;
65 unsigned char tmpstr[BUF_SIZE], extrainput[BUF_SIZE+20], readbuf[2*BUF_SIZE],
66 *input, *writebuf, o_buffer[BUF_SIZE];
67 int bold=0, inv=0, under=0, wherex=0, wherey=0, donl=0;
68 int hold_mode=0, hold_lines=0, ctrlx=0, beep=0, flow=0;
70 unsigned char defprompt[]="> ",
73 int plen=0, specialprompt=0, modified=1, no_echo=0;
75 #define MAX_TAB_LINES 20
77 unsigned char string[BUF_SIZE];
78 struct tabinfo *prev, *next;
81 struct tabinfo *curtabt=NULL, *curtabr=NULL, *oldest=NULL;
83 #define MAX_HIST_LINES 50
85 unsigned char string[BUF_SIZE+20];
87 struct histinfo *prev, *next;
90 struct histinfo *histcurrent=NULL, *histoldest=NULL;
92 char ctrl_t[128] = "/next\n";
94 unsigned char id[]="`#ssfe#", *inid=id, protcmd[BUF_SIZE], *wpc=protcmd;
95 int idstatus=0; /* 0 looking for/in the word, 1 in the arguments */
96 #define ID_BACK "@ssfe@"
98 int rc, rrc, inputcursor, inputlast, inputofs, inarrow=0, quote=0;
99 int cursorwhere; /* 0 = up, 1 = down, 2 = undef */
100 int dispmode=1; /* 0=raw, 1=wordwrap, 2=process ^b^v^_ */
104 char *termtype, termcap[1024], *tc, capabilities[2048];
105 char *t_cm, *t_cl, *t_mr, *t_md, *t_me, *t_cs, *t_ce, *t_us;
108 fd_set ready, result;
112 extern unsigned char *tgoto(unsigned char *cm, int col, int line);
114 extern unsigned char *tgoto();
118 int myputchar(int c) {
122 unsigned char cc=(unsigned char)c;
123 return(write(1, &cc, 1));
131 (*w++)=(unsigned char)c;
135 void putcap(unsigned char *s) {
140 tputs(s, 0, myputchar);
144 int do_cs(int y1, int y2) {
148 static char temp[16];
150 sprintf(temp, "\e[%d;%dr", y1, y2);
151 write(1, temp, strlen(temp));
152 } else putcap((char *)tgoto(t_cs, y2-1, y1-1));
156 void writecap(unsigned char *s) {
161 tputs(s, 0, addchar);
165 void gotoxy(int x, int y) {
169 /* left upper = 0, 0 */
170 putcap(tgoto(t_cm, x, y));
173 #define clearscreen() (putcap(t_cl))
174 #define cleareol() (putcap(t_ce))
175 #define fullscroll() (do_cs(0, 0))
176 #define winscroll() (do_cs(1, lines-2))
177 #define setbold() (putcap(t_md))
178 #define setunder() (putcap(t_us))
179 #define setinv() (putcap(t_mr))
180 #define normal() (putcap(t_me))
183 void ofsredisplay(int x);
184 void inschar(unsigned char t);
185 void dokbdchar(unsigned char t);
191 void displaystatus();
194 void cleanupexit(int n, unsigned char *error) {
196 void cleanupexit(n, error)
198 unsigned char *error; {
205 ioctl(ttyfd, TIOCSETP, &term0);
206 ioctl(ttyfd, TIOCSETC, &tch0);
207 ioctl(ttyfd, TIOCSLTC, &lch0);
209 tcsetattr(ttyfd, TCSADRAIN, &term0);
213 fprintf(stderr, "%s\n", error);
220 cleanupexit(1, "interrupted");
224 cleanupexit(1, "program died");
230 ioctl(ttyfd, TIOCSETP, &term);
231 ioctl(ttyfd, TIOCSETC, &tch);
232 ioctl(ttyfd, TIOCSLTC, &lch);
234 tcsetattr(ttyfd, TCSANOW, &term);
248 ioctl(ttyfd, TIOCSETP, &term0);
249 ioctl(ttyfd, TIOCSETC, &tch0);
250 ioctl(ttyfd, TIOCSLTC, &lch0);
252 tcsetattr(ttyfd, TCSANOW, &term0);
255 signal(SIGTSTP, SIG_DFL);
256 signal(SIGCONT, sigcont);
257 kill(mypid, SIGTSTP);
262 signal(SIGWINCH, sigwinch);
263 if (ioctl(ttyfd, TIOCGWINSZ, &wsz)>=0 && wsz.ws_row>0 && wsz.ws_col>0) {
272 if (inputlast>cols-8) {
274 inputofs=inputlast-cols+9;
277 inputcursor=inputlast;
285 signal(SIGHUP, interrupted);
286 signal(SIGINT, interrupted);
287 signal(SIGQUIT, SIG_IGN);
288 signal(SIGPIPE, sigpipe);
289 signal(SIGTSTP, suspend);
290 signal(SIGCONT, sigcont);
292 signal(SIGWINCH, sigwinch);
297 void setstatus(unsigned char *title) {
299 void setstatus(title)
300 unsigned char *title; {
302 unsigned char *t=title;
303 for (;*t;t++) if (*t<' ') (*t)+='@';
304 memset(statusline, ' ', MAX_COLS-1);
305 memcpy(statusline, title, strlen(title)<MAX_COLS ? strlen(title) : MAX_COLS);
308 void displaystatus() {
313 write(1, statusline, cols-1);
315 gotoxy(cols-4, ystatus);
324 int casecmp(unsigned char *s, unsigned char *t) {
327 unsigned char *s, *t; {
329 while (((*s>='a' && *s<='z')?(*s)-32:*s)==
330 ((*t>='a' && *t<='z')?(*t)-32:*t)) {
331 if (*s=='\0') return 1;
338 void addtab(unsigned char *line) {
341 unsigned char *line; {
347 if (casecmp(nt->string, line)) {
348 strcpy(nt->string, line);
349 if (nt==oldest) oldest=nt->prev;
351 nt->prev->next=nt->next;
352 nt->next->prev=nt->prev;
354 nt->next=oldest->next;
358 curtabt=oldest->next;
363 } while (nt!=oldest);
366 nt=(struct tabinfo *)malloc(sizeof (struct tabinfo));
367 nt->prev=nt->next=curtabt=curtabr=oldest=nt;
369 } else if (tablines<MAX_TAB_LINES) {
370 nt=(struct tabinfo *)malloc(sizeof (struct tabinfo));
372 nt->next=oldest->next;
380 strcpy(nt->string, line);
382 curtabt=oldest->next;
386 void doprotcommand() {
389 switch (protcmd[0]) {
390 case 'i' : dispmode=2; /* set irc mode, ack */
392 write(writefd, "@ssfe@i\n", 8);
394 case 'c' : dispmode=1; /* set cooked mode, ack */
395 write(writefd, "@ssfe@c\n", 8);
397 case 's' : setstatus(protcmd+1); /* set status */
400 case 'T' : strncpy(ctrl_t, protcmd+1, 127); /* set ^t's text */
402 strcat(ctrl_t, "\n");
404 case 't' : addtab(protcmd+1); /* add tabkey entry */
406 case 'l' : fullscroll(); /* clear screen */
409 bold=inv=under=wherex=wherey=donl=0;
414 case 'P' : no_echo = 1; /* password prompt */
415 case 'p' : if (strlen(protcmd+1)<=8) { /* prompt something */
417 if (!specialprompt) {
418 histcurrent->len=inputlast;
419 histcurrent->plen=plen;
422 strcpy(input, protcmd+1);
425 modified=specialprompt=1;
426 inputlast=inputcursor=plen;
430 case 'n' : if (cursorwhere!=1) { /* type text */
433 gotoxy(inputcursor, yinput);
436 for (tmp=protcmd+1; *tmp; tmp++) {
440 case 'o' : strcpy(o_buffer, protcmd+1);
448 if (hold_mode && hold_lines>lines-4) {
451 gotoxy(cols-4, ystatus);
461 gotoxy(cols-4, ystatus);
467 gotoxy(cols-1, wherey);
469 if (under) setunder();
475 void formatter(unsigned char *readbuf, int rc) {
477 void formatter(readbuf, rc)
478 unsigned char *readbuf;
482 unsigned char t, *r, *lwr, *lww;
483 int lwrc, lwbold, lwunder, lwinv, lwx;
485 if (cursorwhere!=0) {
487 gotoxy(wherex, wherey);
495 bold=inv=under=lwbold=lwinv=lwunder=0;
496 if (wherey<ystatus-1) wherey++;
497 } else if (dispmode>1) {
499 if (under) setunder();
505 if (rc && readbuf[rc-1]=='\n') {
510 if (dispmode==0) cutline=1;
513 if (rc) write(1, readbuf, rc);
523 if (t=='\r') continue;
524 if (wherex>cols-2 || (t==9 && wherex>(cols-2)&0xfff8)) {
525 if (t==' ' || t==9) ;
526 else if (lww>writebuf+cols/2) {
527 wherex=lwx; r=lwr; w=lww; rc=lwrc;
528 bold=lwbold; inv=lwinv; under=lwunder; wherex=lwx;
532 write(1, writebuf, w-writebuf);
534 write(1, "\r\n ", 13);
536 lwr=r; lww=w; lwrc=rc;
537 lwbold=bold; lwinv=inv; lwunder=under;
539 if (wherey<ystatus-1) wherey++;
543 if (w!=writebuf) write(1, writebuf, w-writebuf);
548 lwr=r; lww=w; lwrc=rc;
549 lwbold=bold=lwinv=inv=lwunder=under=lwx=wherex=0;
550 if (wherey<ystatus-1) wherey++;
551 } else if (dispmode>1 &&
552 ((t==2 && bold) || (t==22 && inv) || (t==31 && under))) {
555 } else if (dispmode>1 && t==2) {
558 } else if (dispmode>1 && t==22) {
561 } else if (dispmode>1 && t==31) {
564 } else if (dispmode>1 && t==15) {
565 if (bold || inv || under) writecap(t_me);
569 wherex=(wherex & 0xfff8)+8;
570 } else if (t<' ' && (t!=7 || !beep)) {
580 if (bold) writecap(t_md);
581 if (inv) writecap(t_mr);
582 if (under) writecap(t_us);
587 if (t==' ' || t==9) {
588 lwr=r; lww=w; lwrc=rc;
589 lwbold=bold; lwinv=inv; lwunder=under;
593 if (w!=writebuf) write(1, writebuf, w-writebuf);
597 void doprogramline(unsigned char *readbuf, int rc) {
599 void doprogramline(readbuf, rc)
600 unsigned char *readbuf;
604 unsigned char *w, *r, *r2, t;
606 formatter(readbuf, rc);
617 } else if (*inid==t && (inid!=id || r==(readbuf+1) || *(r-2)=='\n')) {
622 while (r2!=wpc) (*w++)=(*r2++);
636 if (w!=readbuf) formatter(readbuf, w-readbuf);
640 void write1(unsigned char t, int pos) {
646 if (no_echo && pos>=plen) {
659 void ofsredisplay(int x) {
661 void ofsredisplay(x) {
663 /* redisplays starting at x */
667 if (inputlast-inputofs>=x) {
668 i=((inputlast-inputofs>cols-1 ? cols-1-x : inputlast-inputofs-x));
669 for (w=input+inputofs+x; i--; w++) write1(*w, w-input);
672 gotoxy(inputcursor, yinput);
677 void delempty(struct histinfo *leavealone) {
679 void delempty(leavealone)
680 struct histinfo *leavealone; {
682 struct histinfo *h, *h2;
687 if ((h->len<=h->plen) && (h!=leavealone)) {
689 h->next->prev=h->prev;
690 h->prev->next=h->next;
699 } while ((h!=histoldest || cont) && histlines>0);
706 struct histinfo *makenew() {
709 nh=(struct histinfo *)malloc(sizeof (struct histinfo));
710 nh->prev=nh->next=histoldest=nh;
712 } else if (histlines<MAX_HIST_LINES) {
713 nh=(struct histinfo *)malloc(sizeof (struct histinfo));
715 nh->next=histoldest->next;
727 void sendline(int yank) {
729 void sendline(yank) {
731 if (!specialprompt) {
732 histcurrent->len=inputlast;
733 histcurrent->plen=plen;
736 input[inputlast]='\n';
737 if (printmode) formatter(input, inputlast+1);
738 if (write(writefd, input+plen, inputlast+1-plen)<inputlast+1-plen)
739 cleanupexit(1, "write error");
741 input[inputlast]='\0';
743 histcurrent=makenew();
744 input=histcurrent->string;
745 strcpy(input, prompt);
747 inputofs=specialprompt=0;
749 inputcursor=inputlast=plen;
757 if (inputlast>plen) {
760 histcurrent=makenew();
761 strcpy(histcurrent->string, h->string);
762 input=histcurrent->string;
769 if (inputcursor<8 && inputofs>0) {
771 inputcursor+=cols-16;
773 inputcursor+=inputofs;
777 } else if (inputcursor>cols-8) {
779 inputcursor-=cols-16;
785 if (inputlast>cols-8) {
787 inputofs=inputlast-cols+9;
790 inputcursor=inputlast;
796 void inschar(unsigned char t) {
804 if (inputlast<BUF_SIZE-4) {
806 if (inputofs+inputcursor==inputlast) {
807 write1(t, inputlast);
808 input[inputlast++]=t;
809 input[inputlast]='\0';
813 while (tmp>=input+inputofs+inputcursor)
815 input[inputofs+(inputcursor++)]=t;
817 ofsredisplay(inputcursor-1);
824 void dokbdchar(unsigned char t) {
833 if (t=='[' || t=='O') {
838 } else if (inarrow==2) {
841 else if (t=='C') t=6;
842 else if (t=='A') t=16;
843 else if (t=='B') t=14;
846 if (ctrlx && !quote) {
849 if (dispmode>0 && ((t=='h' && !hold_mode) || t=='y')) {
852 if (cursorwhere!=1) fullscroll();
855 gotoxy(cols-4, ystatus);
859 } else if (dispmode>0 && ((t=='h' && hold_mode) || t=='n')) {
861 if (cursorwhere!=1) fullscroll();
864 gotoxy(cols-4, ystatus);
868 } else if (dispmode>0 && t=='i') {
871 } else if (dispmode>0 && t=='b') {
873 } else if (t=='c') cleanupexit(1, "exiting");
877 if (cursorwhere!=1) {
880 gotoxy(inputcursor, yinput);
883 if (t==24 && !quote) {
887 if (t==27 && !quote) {
889 } else if ((t==10 || t==13) && !quote) { /* return, newline */
893 curtabt=oldest->next;
895 } else if (t==25 && !quote) { /* ^y */
896 if (!specialprompt) {
900 curtabt=oldest->next;
903 } else if (t==21 && !quote) { /* ^u */
906 inputcursor=inputlast=plen;
909 } else if ((t==8 || t==0x7f) && !quote) { /* ^h, ^? */
910 if (inputcursor>plen) {
912 tmp=input+inputcursor+inputofs;
913 while (tmp<input+inputlast)
915 input[--inputlast]='\0';
916 gotoxy(--inputcursor, yinput);
917 ofsredisplay(inputcursor);
920 } else if (t==4 && !quote) { /* ^d */
921 if (inputcursor+inputofs<inputlast) {
923 tmp=input+inputcursor+inputofs+1;
924 while (tmp<input+inputlast)
926 input[--inputlast]='\0';
927 gotoxy(inputcursor, yinput);
928 ofsredisplay(inputcursor);
930 } else if (t==11 && !quote) { /* ^k */
931 if (inputcursor+inputofs<inputlast) {
933 input[inputlast=inputofs+inputcursor]='\0';
934 ofsredisplay(inputcursor);
936 } else if (t==2 && !quote) { /* ^b */
937 if (inputcursor>0 && (inputcursor>plen || inputofs>0)) {
938 gotoxy(--inputcursor, yinput);
941 } else if (t==6 && !quote) { /* ^f */
942 if (inputcursor+inputofs<inputlast) {
943 gotoxy(++inputcursor, yinput);
946 } else if (t==1 && !quote) { /* ^a */
947 if (inputcursor+inputofs>plen) {
949 gotoxy((inputcursor=plen), yinput);
956 } else if (t==5 && !quote) { /* ^e */
957 if (inputcursor+inputofs<inputlast) {
958 if (inputlast-inputofs<cols-3) {
959 gotoxy((inputcursor=inputlast-inputofs), yinput);
960 } else if (inputlast>cols-8) {
962 inputofs=inputlast-cols+9;
966 inputcursor=inputlast;
970 } else if (t==12 && !quote) { /* ^l */
973 } else if (t==9 && !quote) { /* TAB */
976 strcpy(input+plen, curtabt->string);
977 curtabr=curtabt->prev;
978 curtabt=curtabt->next;
979 inputlast=strlen(input);
982 } else if (t==18 && !quote) { /* ^r */
985 strcpy(input+plen, curtabr->string);
986 curtabt=curtabr->next;
987 curtabr=curtabr->prev;
988 inputlast=strlen(input);
991 } else if (t==16 && !quote) { /* ^p */
992 if (histlines>1 && !specialprompt) {
993 histcurrent->plen=plen;
994 histcurrent->len=inputlast;
995 histcurrent=histcurrent->next;
996 plen=histcurrent->plen;
997 inputlast=histcurrent->len;
998 input=histcurrent->string;
1002 } else if (t==14 && !quote) { /* ^n */
1003 if (histlines>1 && !specialprompt) {
1004 histcurrent->plen=plen;
1005 histcurrent->len=inputlast;
1006 histcurrent=histcurrent->prev;
1007 plen=histcurrent->plen;
1008 inputlast=histcurrent->len;
1009 input=histcurrent->string;
1013 } else if (t==15 &&!quote) { /* ^o */
1014 if (strlen(o_buffer)) modify();
1015 for (tmp=o_buffer; *tmp; tmp++) inschar(*tmp);
1016 } else if (t==20 && !quote) { /* ^t */
1017 write(writefd, ctrl_t, strlen(ctrl_t));
1018 } else if (t==22 && !quote) { /* ^v */
1022 } else if (t==23 && !quote) { /* ^w */
1026 bold=inv=under=wherex=wherey=donl=0;
1035 void barf(unsigned char *m) {
1040 fprintf(stderr, "%s\n", m);
1047 fprintf(stderr, "Use: %s [options] program [program's options]\n", myname);
1048 fprintf(stderr, "Options are:\n");
1049 fprintf(stderr, " -raw, -cooked, -irc : set display mode\n");
1050 fprintf(stderr, " -print : print your input lines\n");
1051 fprintf(stderr, " -prompt <prompt> : specify a command-line prompt\n");
1052 fprintf(stderr, " -hold : pause after each full screen (for cooked/irc mode)\n");
1053 fprintf(stderr, " -beep : let beeps through (for cooked/irc mode)\n");
1054 fprintf(stderr, " -flow : leave ^S/^Q alone for flow control\n");
1059 int main(int argc, char *argv[]) {
1061 int main(argc, argv)
1067 int pfds0[2], pfds1[2], pfds2[2];
1072 if (strcmp(argv[1], "-raw")==0) {
1075 } else if (strcmp(argv[1], "-cooked")==0) {
1078 } else if (strcmp(argv[1], "-irc")==0) {
1081 } else if (strcmp(argv[1], "-hold")==0) {
1084 } else if (strcmp(argv[1], "-print")==0) {
1086 if (prompt==nullstring) prompt=defprompt;
1088 } else if (strcmp(argv[1], "-beep")==0) {
1091 } else if (strcmp(argv[1], "-flow")==0) {
1094 } else if (strcmp(argv[1], "-prompt")==0) {
1095 if (argc>2) prompt=(unsigned char *)argv[2];
1096 if (strlen(prompt)>8) barf("Prompt too long");
1101 if (!isatty(0)) barf("I can only run on a tty, sorry");
1102 if ((termtype=getenv("TERM"))==NULL) barf("No terminal type set");
1103 if (tgetent(termcap, termtype)<1) barf("No termcap info for your terminal");
1105 if ((t_cm=(char *)tgetstr("cm", &tc))==NULL)
1106 barf("Can't find a way to move the cursor around with your terminal");
1107 if ((t_cl=(char *)tgetstr("cl", &tc))==NULL)
1108 barf("Can't find a way to clear the screen with your terminal");
1109 if ((t_ce=(char *)tgetstr("ce", &tc))==NULL)
1110 barf("Can't find a way to clear to end of line with your terminal");
1111 if ((t_cs=(char *)tgetstr("cs", &tc))==NULL) {
1112 if (strncmp(termtype, "xterm", 5)==0 || strncmp(termtype, "vt100", 5)==0)
1115 barf("Can't find a way to set the scrolling region with your terminal");
1117 if ((t_me=(char *)tgetstr("me", &tc))!=NULL) {
1118 if ((t_mr=(char *)tgetstr("mr", &tc))==NULL) t_mr=t_me;
1119 if ((t_md=(char *)tgetstr("md", &tc))==NULL) t_md=t_me;
1120 if ((t_us=(char *)tgetstr("us", &tc))==NULL) t_us=t_me;
1121 } else if ((t_me=(char *)tgetstr("se", &tc))!=NULL &&
1122 (t_mr=(char *)tgetstr("so", &tc))!=NULL) {
1127 t_me=t_md=t_mr=t_us=tc;
1132 if ((ttyfd=open("/dev/tty", O_RDWR))<0 &&
1133 (ttyfd=open("/dev/tty", O_RDONLY))<0) barf("Can't open terminal!");
1138 if (ioctl(ttyfd, TIOCGWINSZ, &wsz)<0 || wsz.ws_row<1 || wsz.ws_col<1) {
1140 lines=((vr=getenv("LINES"))?atoi(vr):0);
1141 cols=((vr=getenv("COLUMNS"))?atoi(vr):0);
1142 if (lines<1 || cols<1) {
1143 if ((lines=tgetnum("li"))<1 || (cols=tgetnum("co"))<1) {
1154 if (pipe(pfds0)<0 || pipe(pfds1)<0 || pipe(pfds2)<0) {
1159 switch (pid=fork()) {
1164 if (pfds0[0]!=0) dup2(pfds0[0], 0);
1165 if (pfds1[1]!=1) dup2(pfds1[1], 1);
1166 if (pfds2[1]!=2) dup2(pfds2[1], 2);
1167 if (pfds0[0]>2) close(pfds0[0]);
1168 if (pfds0[1]>2) close(pfds0[1]);
1169 if (pfds1[0]>2) close(pfds1[0]);
1170 if (pfds1[1]>2) close(pfds1[1]);
1171 if (pfds2[0]>2) close(pfds2[0]);
1172 if (pfds2[1]>2) close(pfds2[1]);
1173 /* okay we can read from 0 and write to 1 and 2, now.. it seems */
1174 execvp(argv[1], argv+1);
1189 if (ioctl(ttyfd, TIOCGETP, &term)<0 || ioctl(ttyfd, TIOCGETC, &tch)<0 ||
1190 ioctl(ttyfd, TIOCGLTC, &lch)<0) {
1191 perror("sgtty get ioctl");
1197 term.sg_flags|=CBREAK;
1198 term.sg_flags&= ~ECHO & ~CRMOD;
1200 memset(&tch, -1, sizeof(tch));
1201 memset(&lch, -1, sizeof(lch));
1202 tch.t_intrc=(char)28;
1203 tch.t_quitc=(char)3;
1205 tch.t_startc=(char)17;
1206 tch.t_stopc=(char)19;
1208 lch.t_suspc=(char)26;
1210 if (ioctl(ttyfd, TIOCSETP, &term)<0 || ioctl(ttyfd, TIOCSETC, &tch)<0 ||
1211 ioctl(ttyfd, TIOCSLTC, &lch)<0) {
1212 perror("sgtty set ioctl");
1217 if (tcgetattr(ttyfd, &term)<0) {
1218 perror("tcgetattr");
1223 term.c_lflag &= ~ECHO & ~ICANON;
1224 term.c_cc[VTIME]=(char)0;
1225 term.c_cc[VMIN]=(char)1;
1227 term.c_cc[VSTOP]=(char)0;
1228 term.c_cc[VSTART]=(char)0;
1230 term.c_cc[VQUIT]=(char)3;
1231 term.c_cc[VINTR]=(char)28; /* reverse ^c and ^\ */
1232 term.c_cc[VSUSP]=(char)26;
1234 term.c_cc[VREPRINT]=(char)0;
1237 term.c_cc[VDISCARD]=(char)0;
1240 term.c_cc[VLNEXT]=(char)0;
1243 term.c_cc[VDSUSP]=(char)0;
1246 if (tcsetattr(ttyfd, TCSANOW, &term)<0) {
1247 perror("tcsetattr");
1257 if (lines>255) barf("Screen too big");
1258 if (ystatus<=2 || cols<20) barf("Screen too small");
1260 statusline=(unsigned char *)malloc(MAX_COLS);
1261 writebuf=(unsigned char *)malloc(20*BUF_SIZE);
1262 strcpy(tmpstr, " ");
1263 for (i=1; i<argc; i++)
1264 if (strlen(tmpstr)+strlen(argv[i])<cols-1) {
1265 strcat(tmpstr, argv[i]);
1266 strcat(tmpstr, " ");
1270 if (dispmode==0) wherey=ystatus-1;
1274 histoldest=histcurrent=(struct histinfo *)malloc(sizeof (struct histinfo));
1275 input=histcurrent->string;
1276 histcurrent->prev=histcurrent->next=histcurrent;
1278 plen=strlen(prompt);
1279 inputlast=inputcursor=plen;
1280 strcpy(input, prompt);
1287 FD_SET(ttyfd, &ready);
1288 FD_SET(readfd, &ready);
1289 FD_SET(errfd, &ready);
1293 if (select(64, &result, NULL, NULL, NULL)<=0)
1294 if (errno==EINTR) continue;
1295 else cleanupexit(1, "select error");
1297 if (FD_ISSET(readfd, &result))
1298 if ((rc=read(readfd, readbuf, BUF_SIZE))>0)
1299 doprogramline(readbuf, rc);
1301 cleanupexit(1, "program terminated");
1302 if (FD_ISSET(errfd, &result))
1303 if ((rc=read(errfd, readbuf, BUF_SIZE))>0)
1304 doprogramline(readbuf, rc);
1306 cleanupexit(1, "program terminated");
1307 if (FD_ISSET(ttyfd, &result))
1308 if ((rrc=read(0, readbuf, BUF_SIZE))>0)
1309 for (t=readbuf; rrc>0; rrc--) dokbdchar(*(t++));
1311 cleanupexit(1, "read error from keyboard");