Newsgroups: comp.sources.unix From: screen@uni-erlangen.de (Juergen & Michael) Subject: v27i017: screen-3.5.1 - full-screen window manager/multiplexor, Part04/10 References: <1.744844979.5722@gw.home.vix.com> Sender: unix-sources-moderator@gw.home.vix.com Approved: vixie@gw.home.vix.com Submitted-By: screen@uni-erlangen.de (Juergen & Michael) Posting-Number: Volume 27, Issue 17 Archive-Name: screen-3.5.1/part04 #! /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 'display.c' <<'END_OF_FILE' X/* Copyright (c) 1993 X * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) X * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) X * Copyright (c) 1987 Oliver Laumann X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 2, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program (see the file COPYING); if not, write to the X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X * X **************************************************************** X */ X X#include "rcs.h" XRCS_ID("$Id: display.c,v 1.11 1993/08/04 00:42:31 mlschroe Exp $ FAU") X X X#include X#include X X#include "config.h" X#include "screen.h" X#include "extern.h" X Xstatic void CountChars __P((int)); Xstatic void PutChar __P((int)); Xstatic int BlankResize __P((int, int)); X X Xextern struct win *windows; X Xextern int use_hardstatus; Xextern int MsgMinWait; Xextern int Z0width, Z1width; Xextern char *blank, *null; X X/* X * tputs needs this to calculate the padding X */ X#ifndef NEED_OSPEED Xextern X#endif /* NEED_OSPEED */ Xshort ospeed; X X Xstruct display *display, *displays; X X#ifndef MULTI Xstruct display TheDisplay; X#endif X X X/* X * The default values X */ Xint defobuflimit = OBUF_MAX; X#ifdef AUTO_NUKE Xint defautonuke = 0; X#endif X X/* X * Default layer management X */ X Xvoid XDefProcess(bufp, lenp) Xchar **bufp; Xint *lenp; X{ X *bufp += *lenp; X *lenp = 0; X} X Xvoid XDefRedisplayLine(y, xs, xe, isblank) Xint y, xs, xe, isblank; X{ X if (isblank == 0 && y >= 0) X DefClearLine(y, xs, xe); X} X Xvoid XDefClearLine(y, xs, xe) Xint y, xs, xe; X{ X DisplayLine(null, null, null, blank, null, null, y, xs, xe); X} X X/*ARGSUSED*/ Xint XDefRewrite(y, xs, xe, doit) Xint y, xs, xe, doit; X{ X return EXPENSIVE; X} X Xvoid XDefSetCursor() X{ X GotoPos(0, 0); X} X X/*ARGSUSED*/ Xint XDefResize(wi, he) Xint wi, he; X{ X return -1; X} X Xvoid XDefRestore() X{ X InsertMode(0); X ChangeScrollRegion(0, d_height - 1); X KeypadMode(0); X CursorkeysMode(0); X SetAttrFont(0, ASCII); X SetFlow(FLOW_NOW); X} X X/* X * Blank layer management X */ X Xstruct LayFuncs BlankLf = X{ X DefProcess, X 0, X DefRedisplayLine, X DefClearLine, X DefRewrite, X DefSetCursor, X BlankResize, X DefRestore X}; X Xstruct layer BlankLayer = X{ X 0, X 0, X &BlankLf, X 0 X}; X X/*ARGSUSED*/ Xstatic int XBlankResize(wi, he) Xint wi, he; X{ X return 0; X} X X X/* X * Generate new display X */ X Xstruct display * XMakeDisplay(uname, utty, term, fd, pid, Mode) Xchar *uname, *utty, *term; Xint fd, pid; Xstruct mode *Mode; X{ X struct user **u; X X#ifdef MULTI X if ((display = (struct display *)malloc(sizeof(*display))) == 0) X return 0; X bzero((char *) display, sizeof(*display)); X#else X if (displays) X return 0; X display = &TheDisplay; X#endif X display->_d_next = displays; X displays = display; X d_flow = 1; X d_userfd = fd; X d_OldMode = *Mode; X Resize_obuf(); /* Allocate memory for buffer */ X d_obufmax = defobuflimit; X#ifdef AUTO_NUKE X d_auto_nuke = defautonuke; X#endif X d_obufp = d_obuf; X d_userpid = pid; X#ifdef POSIX X d_dospeed = (short) cfgetospeed(&d_OldMode.tio); X#else X# ifndef TERMIO X d_dospeed = (short) d_OldMode.m_ttyb.sg_ospeed; X# endif X#endif X debug1("New displays ospeed = %d\n", d_dospeed); X strcpy(d_usertty, utty); X strcpy(d_termname, term); X X if (!*(u = FindUserPtr(uname)) && UserAdd(uname, NULL, u)) X { X FreeDisplay(); X return NULL; /* could not find or add user */ X } X d_user = *u; X d_lay = &BlankLayer; X d_layfn = BlankLayer.l_layfn; X return display; X} X Xvoid XFreeDisplay() X{ X#ifdef MULTI X struct display *d, **dp; X X for (dp = &displays; (d = *dp) ; dp = &d->_d_next) X if (d == display) X break; X ASSERT(d); X if (d_status_lastmsg) X free(d_status_lastmsg); X if (d_obuf) X free(d_obuf); X *dp = display->_d_next; X free(display); X#else /* MULTI */ X ASSERT(display == displays); X ASSERT(display == &TheDisplay); X displays = 0; X#endif /* MULTI */ X display = 0; X} X X/* X * if the adaptflag is on, we keep the size of this display, else X * we may try to restore our old window sizes. X */ Xvoid XInitTerm(adapt) Xint adapt; X{ X ASSERT(display); X d_top = d_bot = -1; X PutStr(TI); X PutStr(IS); X /* Check for toggle */ X if (IM && strcmp(IM, EI)) X PutStr(EI); X d_insert = 0; X /* Check for toggle */ X if (KS && strcmp(KS, KE)) X PutStr(KE); X d_keypad = 0; X if (CCS && strcmp(CCS, CCE)) X PutStr(CCE); X d_cursorkeys = 0; X PutStr(CE0); X d_font = ASCII; X if (adapt == 0) X ResizeDisplay(d_defwidth, d_defheight); X ChangeScrollRegion(0, d_height - 1); X d_x = d_y = 0; X Flush(); X ClearDisplay(); X debug1("we %swant to adapt all our windows to the display\n", X (adapt) ? "" : "don't "); X /* In case the size was changed by a init sequence */ X CheckScreenSize((adapt) ? 2 : 0); X} X Xvoid XFinitTerm() X{ X ASSERT(display); X ResizeDisplay(d_defwidth, d_defheight); X DefRestore(); X SetAttrFont(0, ASCII); X d_x = d_y = -1; X GotoPos(0, d_height - 1); X AddChar('\n'); X PutStr(TE); X Flush(); X} X X Xvoid XINSERTCHAR(c) Xint c; X{ X ASSERT(display); X if (!d_insert && d_x < d_width - 1) X { X if (IC || CIC) X { X if (IC) X PutStr(IC); X else X CPutStr(CIC, 1); X RAW_PUTCHAR(c); X return; X } X InsertMode(1); X if (!d_insert) X { X RefreshLine(d_y, d_x, d_width-1, 0); X return; X } X } X RAW_PUTCHAR(c); X} X Xvoid XPUTCHAR(c) Xint c; X{ X ASSERT(display); X if (d_insert && d_x < d_width - 1) X InsertMode(0); X RAW_PUTCHAR(c); X} X Xvoid XPUTCHARLP(c) Xint c; X{ X if (d_x < d_width - 1) X { X if (d_insert) X InsertMode(0); X RAW_PUTCHAR(c); X return; X } X if (CLP || d_y != d_bot) X { X RAW_PUTCHAR(c); X return; X } X d_lp_missing = 1; X d_lp_image = c; X d_lp_attr = d_attr; X d_lp_font = d_font; X} X X/* X * RAW_PUTCHAR() is for all text that will be displayed. X * NOTE: charset Nr. 0 has a conversion table, but c1, c2, ... don't. X */ X Xvoid XRAW_PUTCHAR(c) Xint c; X{ X ASSERT(display); X if (d_font == '0') X { X AddChar(d_c0_tab[c]); X } X else X AddChar(c); X if (++d_x >= d_width) X { X if ((AM && !CLP) || d_x > d_width) X { X d_x -= d_width; X if (d_y < d_height-1 && d_y != d_bot) X d_y++; X } X } X} X Xstatic void XPutChar(c) Xint c; X{ X /* this PutChar for ESC-sequences only (AddChar is a macro) */ X AddChar(c); X} X Xvoid XPutStr(s) Xchar *s; X{ X if (display && s) X { X ospeed = d_dospeed; X tputs(s, 1, PutChar); X } X} X Xvoid XCPutStr(s, c) Xchar *s; Xint c; X{ X if (display && s) X { X ospeed = d_dospeed; X tputs(tgoto(s, 0, c), 1, PutChar); X } X} X X X/* Insert mode is a toggle on some terminals, so we need this hack: X */ Xvoid XInsertMode(on) Xint on; X{ X if (display && on != d_insert && IM) X { X d_insert = on; X if (d_insert) X PutStr(IM); X else X PutStr(EI); X } X} X X/* ...and maybe d_keypad application mode is a toggle, too: X */ Xvoid XKeypadMode(on) Xint on; X{ X if (display && d_keypad != on && KS) X { X d_keypad = on; X if (d_keypad) X PutStr(KS); X else X PutStr(KE); X } X} X Xvoid XCursorkeysMode(on) Xint on; X{ X if (display && d_cursorkeys != on && CCS) X { X d_cursorkeys = on; X if (d_cursorkeys) X PutStr(CCS); X else X PutStr(CCE); X } X} X Xstatic int StrCost; X X/* ARGSUSED */ Xstatic void XCountChars(c) Xint c; X{ X StrCost++; X} X Xint XCalcCost(s) Xregister char *s; X{ X ASSERT(display); X if (s) X { X StrCost = 0; X ospeed = d_dospeed; X tputs(s, 1, CountChars); X return StrCost; X } X else X return EXPENSIVE; X} X Xvoid XGotoPos(x2, y2) Xint x2, y2; X{ X register int dy, dx, x1, y1; X register int costx, costy; X register int m; X register char *s; X int CMcost; X enum move_t xm = M_NONE, ym = M_NONE; X X if (!display) X return; X X x1 = d_x; X y1 = d_y; X X if (x1 == d_width) X if (CLP && AM) X x1 = -1; /* don't know how the terminal treats this */ X else X x1--; X if (x2 == d_width) X x2--; X dx = x2 - x1; X dy = y2 - y1; X if (dy == 0 && dx == 0) X { X return; X } X if (!MS && (d_attr || d_font != ASCII)) /* Safe to move ? */ X SetAttrFont(0, ASCII); X if (y1 < 0 /* don't know the y position */ X || (y2 > d_bot && y1 <= d_bot) /* have to cross border */ X || (y2 < d_top && y1 >= d_top)) /* of scrollregion ? */ X { X DoCM: X if (HO && !x2 && !y2) X PutStr(HO); X else X PutStr(tgoto(CM, x2, y2)); X d_x = x2; X d_y = y2; X return; X } X /* Calculate CMcost */ X if (HO && !x2 && !y2) X s = HO; X else X s = tgoto(CM, x2, y2); X CMcost = CalcCost(s); X X /* Calculate the cost to move the cursor to the right x position */ X costx = EXPENSIVE; X if (x1 >= 0) /* relativ x positioning only if we know where we are */ X { X if (dx > 0) X { X if (CRI && (dx > 1 || !ND)) X { X costx = CalcCost(tgoto(CRI, 0, dx)); X xm = M_CRI; X } X if ((m = d_NDcost * dx) < costx) X { X costx = m; X xm = M_RI; X } X /* Speedup: dx <= Rewrite() */ X if (dx < costx && (m = Rewrite(y1, x1, x2, 0)) < costx) X { X costx = m; X xm = M_RW; X } X } X else if (dx < 0) X { X if (CLE && (dx < -1 || !BC)) X { X costx = CalcCost(tgoto(CLE, 0, -dx)); X xm = M_CLE; X } X if ((m = -dx * d_LEcost) < costx) X { X costx = m; X xm = M_LE; X } X } X else X costx = 0; X } X /* Speedup: Rewrite() >= x2 */ X if (x2 + d_CRcost < costx && (m = (x2 ? Rewrite(y1, 0, x2, 0) : 0) + d_CRcost) < costx) X { X costx = m; X xm = M_CR; X } X X /* Check if it is already cheaper to do CM */ X if (costx >= CMcost) X goto DoCM; X X /* Calculate the cost to move the cursor to the right y position */ X costy = EXPENSIVE; X if (dy > 0) X { X if (CDO && dy > 1) /* DO & NL are always != 0 */ X { X costy = CalcCost(tgoto(CDO, 0, dy)); X ym = M_CDO; X } X if ((m = dy * ((x2 == 0) ? d_NLcost : d_DOcost)) < costy) X { X costy = m; X ym = M_DO; X } X } X else if (dy < 0) X { X if (CUP && (dy < -1 || !UP)) X { X costy = CalcCost(tgoto(CUP, 0, -dy)); X ym = M_CUP; X } X if ((m = -dy * d_UPcost) < costy) X { X costy = m; X ym = M_UP; X } X } X else X costy = 0; X X /* Finally check if it is cheaper to do CM */ X if (costx + costy >= CMcost) X goto DoCM; X X switch (xm) X { X case M_LE: X while (dx++ < 0) X PutStr(BC); X break; X case M_CLE: X CPutStr(CLE, -dx); X break; X case M_RI: X while (dx-- > 0) X PutStr(ND); X break; X case M_CRI: X CPutStr(CRI, dx); X break; X case M_CR: X PutStr(CR); X d_x = 0; X x1 = 0; X /* FALLTHROUGH */ X case M_RW: X if (x1 < x2) X (void) Rewrite(y1, x1, x2, 1); X break; X default: X break; X } X X switch (ym) X { X case M_UP: X while (dy++ < 0) X PutStr(UP); X break; X case M_CUP: X CPutStr(CUP, -dy); X break; X case M_DO: X s = (x2 == 0) ? NL : DO; X while (dy-- > 0) X PutStr(s); X break; X case M_CDO: X CPutStr(CDO, dy); X break; X default: X break; X } X d_x = x2; X d_y = y2; X} X Xvoid XClearDisplay() X{ X ASSERT(display); X Clear(0, 0, d_width - 1, d_height - 1); X} X Xvoid XClear(xs, ys, xe, ye) Xint xs, ys, xe, ye; X{ X int y, xxe; X X ASSERT(display); X if (xs == d_width) X xs--; X if (xe == d_width) X xe--; X if (d_lp_missing && ys <= d_bot) X { X if (ye > d_bot || (ye == d_bot && xe == d_width - 1)) X d_lp_missing = 0; X } X if (xe == d_width - 1 && ye == d_height - 1) X { X#ifdef AUTO_NUKE X if (xs == 0 && ys == 0 && d_auto_nuke) X NukePending(); X#endif X if (xs == 0 && ys == 0 && CL) X { X PutStr(CL); X d_y = d_x = 0; X return; X } X /* X * Workaround a hp700/22 terminal bug. Do not use CD where CE X * is also appropriate. X */ X if (CD && (ys < ye || !CE)) X { X GotoPos(xs, ys); X PutStr(CD); X return; X } X } X xxe = d_width - 1; X for (y = ys; y <= ye; y++, xs = 0) X { X if (y == ye) X xxe = xe; X if (xs == 0 && CB && (xxe != d_width - 1 || (d_x == xxe && d_y == y))) X { X GotoPos(xxe, y); X PutStr(CB); X continue; X } X if (xxe == d_width - 1 && CE) X { X GotoPos(xs, y); X PutStr(CE); X continue; X } X ClearLine(y, xs, xxe); X } X} X X X/* X * if cur_only > 0, we only redisplay current line, as a full refresh is X * too expensive over a low baud line. X */ Xvoid XRedisplay(cur_only) Xint cur_only; X{ X register int i, stop; X X ASSERT(display); X DefRestore(); X ClearDisplay(); X stop = d_height; X i = 0; X if (cur_only > 0 && d_fore) X { X i = stop = d_fore->w_y; X stop++; X } X else RedisplayLine(-1, 0, d_width - 1, 1); X for (; i < stop; i++) X RedisplayLine(i, 0, d_width - 1, 1); X Restore(); X SetCursor(); X} X X Xvoid XScrollRegion(ys, ye, n) Xint ys, ye, n; X{ X int i; X int up; X int oldtop, oldbot; X int alok, dlok, aldlfaster; X int missy = 0; X X ASSERT(display); X if (n == 0) X return; X if (ys == 0 && ye == d_height - 1 && X (n >= d_height || -n >= d_height)) X { X ClearDisplay(); X return; X } X X if (d_lp_missing) X { X if (d_bot > ye || d_bot < ys) X missy = d_bot; X else X { X missy = d_bot - n; X if (missy>ye || missy= ye-ys+1) X n = ye-ys+1; X X oldtop = d_top; X oldbot = d_bot; X if (d_bot != ye) X ChangeScrollRegion(ys, ye); X alok = (AL || CAL || (ye == d_bot && up)); X dlok = (DL || CDL || (ye == d_bot && !up)); X if (d_top != ys && !(alok && dlok)) X ChangeScrollRegion(ys, ye); X X if (d_lp_missing && X (oldbot != d_bot || X (oldbot == d_bot && up && d_top == ys && d_bot == ye))) X { X FixLP(d_width - 1, oldbot); X if (oldbot == d_bot) /* have scrolled */ X { X if (--n == 0) X { X ChangeScrollRegion(oldtop, oldbot); X return; X } X } X } X X aldlfaster = (n > 1 && ye == d_bot && ((up && CDL) || (!up && CAL))); X X if ((up || SR) && d_top == ys && d_bot == ye && !aldlfaster) X { X if (up) X { X GotoPos(0, ye); X while (n-- > 0) X PutStr(NL); /* was SF, I think NL is faster */ X } X else X { X GotoPos(0, ys); X while (n-- > 0) X PutStr(SR); X } X } X else if (alok && dlok) X { X if (up || ye != d_bot) X { X GotoPos(0, up ? ys : ye+1-n); X if (CDL && !(n == 1 && DL)) X CPutStr(CDL, n); X else X for(i = n; i--; ) X PutStr(DL); X } X if (!up || ye != d_bot) X { X GotoPos(0, up ? ye+1-n : ys); X if (CAL && !(n == 1 && AL)) X CPutStr(CAL, n); X else X for(i = n; i--; ) X PutStr(AL); X } X } X else X { X Redisplay(0); X return; X } X if (d_lp_missing && missy != d_bot) X FixLP(d_width - 1, missy); X ChangeScrollRegion(oldtop, oldbot); X if (d_lp_missing && missy != d_bot) X FixLP(d_width - 1, missy); X} X Xvoid XSetAttr(new) Xregister int new; X{ X register int i, old; X X if (!display || (old = d_attr) == new) X return; X d_attr = new; X for (i = 1; i <= A_MAX; i <<= 1) X { X if ((old & i) && !(new & i)) X { X PutStr(UE); X PutStr(SE); X PutStr(ME); X if (new & A_DI) X PutStr(d_attrtab[ATTR_DI]); X if (new & A_US) X PutStr(d_attrtab[ATTR_US]); X if (new & A_BD) X PutStr(d_attrtab[ATTR_BD]); X if (new & A_RV) X PutStr(d_attrtab[ATTR_RV]); X if (new & A_SO) X PutStr(d_attrtab[ATTR_SO]); X if (new & A_BL) X PutStr(d_attrtab[ATTR_BL]); X return; X } X } X if ((new & A_DI) && !(old & A_DI)) X PutStr(d_attrtab[ATTR_DI]); X if ((new & A_US) && !(old & A_US)) X PutStr(d_attrtab[ATTR_US]); X if ((new & A_BD) && !(old & A_BD)) X PutStr(d_attrtab[ATTR_BD]); X if ((new & A_RV) && !(old & A_RV)) X PutStr(d_attrtab[ATTR_RV]); X if ((new & A_SO) && !(old & A_SO)) X PutStr(d_attrtab[ATTR_SO]); X if ((new & A_BL) && !(old & A_BL)) X PutStr(d_attrtab[ATTR_BL]); X} X Xvoid XSetFont(new) Xint new; X{ X if (!display || d_font == new) X return; X d_font = new; X if (new == ASCII) X PutStr(CE0); X else X CPutStr(CS0, new); X} X Xvoid XSetAttrFont(newattr, newcharset) Xint newattr, newcharset; X{ X SetAttr(newattr); X SetFont(newcharset); X} X Xvoid XMakeStatus(msg) Xchar *msg; X{ X register char *s, *t; X register int max, ti; X X if (!display) X return; X X if (!d_tcinited) X { X debug("tc not inited, just writing msg\n"); X AddStr(msg); X AddStr("\r\n"); X Flush(); X return; X } X if (!use_hardstatus || !HS) X { X max = d_width; X if (CLP == 0) X max--; X } X else X max = WS; X if (d_status) X { X if (!d_status_bell) X { X ti = time((time_t *) 0) - d_status_time; X if (ti < MsgMinWait) X sleep(MsgMinWait - ti); X } X RemoveStatus(); X } X for (s = t = msg; *s && t - msg < max; ++s) X if (*s == BELL) X PutStr(BL); X else if ((unsigned char)*s >= ' ' && *s != 0177) X *t++ = *s; X *t = '\0'; X if (t > msg) X { X if (t - msg >= d_status_buflen) X { X char *buf; X if (d_status_lastmsg) X buf = realloc(d_status_lastmsg, t - msg + 1); X else X buf = malloc(t - msg + 1); X if (buf) X { X d_status_lastmsg = buf; X d_status_buflen = t - msg + 1; X } X } X if (t - msg < d_status_buflen) X strcpy(d_status_lastmsg, msg); X d_status = 1; X d_status_len = t - msg; X d_status_lastx = d_x; X d_status_lasty = d_y; X if (!use_hardstatus || !HS) X { X debug1("using STATLINE %d\n", STATLINE); X GotoPos(0, STATLINE); X SetAttrFont(A_SO, ASCII); X InsertMode(0); X AddStr(msg); X d_x = -1; X } X else X { X debug("using HS\n"); X SetAttrFont(0, ASCII); X InsertMode(0); X CPutStr(TS, 0); X AddStr(msg); X PutStr(FS); X } X Flush(); X (void) time(&d_status_time); X } X} X Xvoid XRemoveStatus() X{ X struct win *p; X X if (!display) X return; X if (!d_status) X return; X X /* X * UGLY HACK ALERT - this should NOT be in display.c X * We need to find the window that caused an activity or bell X * message, to reenable this function there. X */ X for (p = windows; p; p = p->w_next) X { X if (p->w_display != display) X continue; X if (p->w_monitor == MON_MSG) X { X debug1("RemoveStatus clearing monitor win %d\n", p->w_number); X p->w_monitor = MON_DONE; X } X if (p->w_bell == BELL_MSG) X { X debug1("RemoveStatus clearing bell win %d\n", p->w_number); X p->w_bell = BELL_DONE; X } X } X d_status = 0; X d_status_bell = 0; X if (!use_hardstatus || !HS) X { X GotoPos(0, STATLINE); X RefreshLine(STATLINE, 0, d_status_len - 1, 0); X GotoPos(d_status_lastx, d_status_lasty); X } X else X { X SetAttrFont(0, ASCII); X PutStr(DS); X } X SetCursor(); X} X Xvoid XRefreshLine(y, from, to, isblank) Xint y, from, to, isblank; X{ X ASSERT(display); X debug2("RefreshLine %d %d", y, from); X debug2(" %d %d\n", to, isblank); X if (isblank == 0 && CE && to == d_width - 1) X { X GotoPos(from, y); X PutStr(CE); X isblank = 1; X } X RedisplayLine(y, from, to, isblank); X} X Xvoid XFixLP(x2, y2) Xregister int x2, y2; X{ X int oldattr = d_attr, oldfont = d_font; X X ASSERT(display); X GotoPos(x2, y2); X SetAttrFont(d_lp_attr, d_lp_font); X PUTCHAR(d_lp_image); X d_lp_missing = 0; X SetAttrFont(oldattr, oldfont); X} X Xvoid XDisplayLine(os, oa, of, s, as, fs, y, from, to) Xint from, to, y; Xregister char *os, *oa, *of, *s, *as, *fs; X{ X register int x; X int last2flag = 0, delete_lp = 0; X X ASSERT(display); X ASSERT(y >= 0 && y < d_height); X ASSERT(from >= 0 && from < d_width); X ASSERT(to >= 0 && to < d_width); X if (!CLP && y == d_bot && to == d_width - 1) X if (d_lp_missing X || s[to] != os[to] || as[to] != oa[to] || of[to] != fs[to]) X { X if ((IC || IM) && from < to) X { X to -= 2; X last2flag = 1; X d_lp_missing = 0; X } X else X { X to--; X delete_lp = (CE || DC || CDC); X d_lp_missing = (s[to] != ' ' || as[to] || fs[to]); X d_lp_image = s[to]; X d_lp_attr = as[to]; X d_lp_font = fs[to]; X } X } X else X to--; X for (x = from; x <= to; ++x) X { X if (x || d_x != d_width || d_y != y - 1) X { X if (x < to || x != d_width - 1 || s[x + 1] == ' ') X if (s[x] == os[x] && as[x] == oa[x] && of[x] == fs[x]) X continue; X GotoPos(x, y); X } X SetAttr(as[x]); X SetFont(fs[x]); X PUTCHAR(s[x]); X } X if (to == d_width - 1 && y < d_height - 1 && s[to + 1] == ' ') X GotoPos(0, y + 1); X if (last2flag) X { X GotoPos(x, y); X SetAttr(as[x + 1]); X SetFont(fs[x + 1]); X PUTCHAR(s[x + 1]); X GotoPos(x, y); X SetAttr(as[x]); X SetFont(fs[x]); X INSERTCHAR(s[x]); X } X else if (delete_lp) X { X if (DC) X PutStr(DC); X else if (CDC) X CPutStr(CDC, 1); X else if (CE) X PutStr(CE); X } X} X Xvoid XSetLastPos(x,y) Xint x,y; X{ X ASSERT(display); X d_x = x; X d_y = y; X} X Xint XResizeDisplay(wi, he) Xint wi, he; X{ X ASSERT(display); X debug2("ResizeDisplay: to (%d,%d).\n", wi, he); X if (d_width == wi && d_height == he) X { X debug("ResizeDisplay: No change\n"); X return 0; X } X if (CWS) X { X debug("ResizeDisplay: using WS\n"); X PutStr(tgoto(CWS, wi, he)); X ChangeScreenSize(wi, he, 0); X return 0; X } X else if (CZ0 && (wi == Z0width || wi == Z1width)) X { X debug("ResizeDisplay: using Z0/Z1\n"); X PutStr(wi == Z0width ? CZ0 : CZ1); X ChangeScreenSize(wi, d_height, 0); X return (he == d_height) ? 0 : -1; X } X return -1; X} X Xvoid XChangeScrollRegion(newtop, newbot) Xint newtop, newbot; X{ X if (display == 0) X return; X if (CS == 0) X { X d_top = 0; X d_bot = d_height - 1; X return; X } X if (d_top == newtop && d_bot == newbot) X return; X debug2("ChangeScrollRegion: (%d - %d)\n", newtop, newbot); X PutStr(tgoto(CS, newbot, newtop)); X d_top = newtop; X d_bot = newbot; X d_y = d_x = -1; /* Just in case... */ X} X X X/* X * Layer creation / removal X */ X Xint XInitOverlayPage(datasize, lf, block) Xint datasize; Xstruct LayFuncs *lf; Xint block; X{ X char *data; X struct layer *newlay; X X RemoveStatus(); X debug3("Entering new layer display %#x d_fore %#x oldlay %#x\n", X (unsigned int)display, (unsigned int)d_fore, (unsigned int)d_lay); X if ((newlay = (struct layer *)malloc(sizeof(struct layer))) == 0) X { X Msg(0, "No memory for layer struct"); X return(-1); X } X data = 0; X if (datasize) X { X if ((data = malloc(datasize)) == 0) X { X free(newlay); X Msg(0, "No memory for layer data"); X return(-1); X } X bzero(data, datasize); X } X newlay->l_layfn = lf; X newlay->l_block = block | d_lay->l_block; X newlay->l_data = data; X newlay->l_next = d_lay; X if (d_fore) X { X d_fore->w_lay = newlay; /* XXX: CHECK */ X d_fore->w_active = 0; /* XXX: CHECK */ X } X d_lay = newlay; X d_layfn = newlay->l_layfn; X Restore(); X return(0); X} X Xvoid XExitOverlayPage() X{ X struct layer *oldlay; X X debug3("Exiting layer display %#x fore %#x d_lay %#x\n", X (unsigned int)display, (unsigned int)d_fore, (unsigned int)d_lay); X oldlay = d_lay; X if (oldlay->l_data) X free(oldlay->l_data); X d_lay = oldlay->l_next; X d_layfn = d_lay->l_layfn; X free(oldlay); X if (d_fore) X d_fore->w_lay = d_lay; /* XXX: Is this necessary ? */ X Restore(); X SetCursor(); X} X X X/* X * Output buffering routines X */ X Xvoid XAddStr(str) Xchar *str; X{ X register char c; X X ASSERT(display); X while ((c = *str++)) X AddChar(c); X} X Xvoid XAddStrn(str, n) Xchar *str; Xint n; X{ X register char c; X X ASSERT(display); X while ((c = *str++) && n-- > 0) X AddChar(c); X while (n-- > 0) X AddChar(' '); X} X Xvoid XFlush() X{ X register int l; X register char *p; X X ASSERT(display); X l = d_obufp - d_obuf; X debug1("Flush(): %d\n", l); X ASSERT(l + d_obuffree == d_obuflen); X if (l == 0) X return; X if (d_userfd < 0) X { X d_obuffree += l; X d_obufp = d_obuf; X return; X } X p = d_obuf; X if (fcntl(d_userfd, F_SETFL, 0)) X debug1("Warning: DELAY fcntl failed: %d\n", errno); X while (l) X { X register int wr; X wr = write(d_userfd, p, l); X if (wr <= 0) X { X if (errno == EINTR) X continue; X debug1("Writing to display: %d\n", errno); X wr = l; X } X d_obuffree += wr; X p += wr; X l -= wr; X } X d_obuffree += l; X d_obufp = d_obuf; X if (fcntl(d_userfd, F_SETFL, FNDELAY)) X debug1("Warning: NDELAY fcntl failed: %d\n", errno); X} X Xvoid Xfreetty() X{ X if (d_userfd >= 0) X close(d_userfd); X debug1("did freetty %d\n", d_userfd); X d_userfd = -1; X d_obufp = 0; X d_obuffree = 0; X if (d_obuf) X free(d_obuf); X d_obuf = 0; X d_obuflen = 0; X} X X/* X * Asynchronous output routines by X * Tim MacKenzie (tym@dibbler.cs.monash.edu.au) X */ X Xvoid XResize_obuf() X{ X register int ind; X X ASSERT(display); X if (d_obuflen && d_obuf) X { X ind = d_obufp - d_obuf; X d_obuflen += GRAIN; X d_obuffree += GRAIN; X d_obuf = realloc(d_obuf, d_obuflen); X } X else X { X ind = 0; X d_obuflen = GRAIN; X d_obuffree = GRAIN; X d_obuf = malloc(d_obuflen); X } X if (!d_obuf) X Panic(0, "Out of memory"); X d_obufp = d_obuf + ind; X debug1("ResizeObuf: resized to %d\n", d_obuflen); X} X X#ifdef AUTO_NUKE Xvoid XNukePending() X{/* Nuke pending output in current display, clear screen */ X register int len; X int oldfont = d_font, oldattr = d_attr, oldtop = d_top, oldbot = d_bot; X int oldkeypad = d_keypad, oldcursorkeys = d_cursorkeys; X X len = d_obufp - d_obuf; X debug1("NukePending: nuking %d chars\n", len); X X /* Throw away any output that we can... */ X# ifdef POSIX X tcflush(d_userfd, TCOFLUSH); X# else X# ifdef TCFLSH X (void) ioctl(d_userfd, TCFLSH, (char *) 1); X# endif X# endif X X d_obufp = d_obuf; X d_obuffree += len; X d_top = d_bot = -1; X PutStr(TI); X PutStr(IS); X /* Turn off all attributes. (Tim MacKenzie) */ X if (ME) X PutStr(ME); X else X { X PutStr(SE); X PutStr(UE); X } X /* Check for toggle */ X if (IM && strcmp(IM, EI)) X PutStr(EI); X d_insert = 0; X /* Check for toggle */ X if (KS && strcmp(KS, KE)) X PutStr(KE); X d_keypad = 0; X if (CCS && strcmp(CCS, CCE)) X PutStr(CCE); X d_cursorkeys = 0; X PutStr(CE0); X d_font = ASCII; X d_attr = 0; X ChangeScrollRegion(oldtop, oldbot); X SetAttrFont(oldattr, oldfont); X KeypadMode(oldkeypad); X CursorkeysMode(oldcursorkeys); X if (CWS) X { X debug("ResizeDisplay: using WS\n"); X PutStr(tgoto(CWS, d_width, d_height)); X } X else if (CZ0 && (d_width == Z0width || d_width == Z1width)) X { X debug("ResizeDisplay: using Z0/Z1\n"); X PutStr(d_width == Z0width ? CZ0 : CZ1); X } X} X#endif /* AUTO_NUKE */ END_OF_FILE if test 26908 -ne `wc -c <'display.c'`; then echo shar: \"'display.c'\" unpacked with wrong size! fi # end of 'display.c' fi if test -f 'mark.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'mark.c'\" else echo shar: Extracting \"'mark.c'\" \(25787 characters\) sed "s/^X//" >'mark.c' <<'END_OF_FILE' X/* Copyright (c) 1993 X * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) X * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) X * Copyright (c) 1987 Oliver Laumann X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 2, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program (see the file COPYING); if not, write to the X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X * X **************************************************************** X */ X X#include "rcs.h" XRCS_ID("$Id: mark.c,v 1.4 1993/07/30 01:24:47 jnweiger Exp $ FAU") X X#include X X#include "config.h" X#include "screen.h" X#include "mark.h" X#include "extern.h" X X#ifdef COPY_PASTE X Xstatic int is_letter __P((int)); Xstatic void nextword __P((int *, int *, int, int)); Xstatic int linestart __P((int)); Xstatic int lineend __P((int)); Xstatic int rem __P((int, int , int , int , int , char *, int)); Xstatic int eq __P((int, int )); Xstatic int MarkScrollDownDisplay __P((int)); Xstatic int MarkScrollUpDisplay __P((int)); X Xstatic void MarkProcess __P((char **, int *)); Xstatic void MarkAbort __P((void)); Xstatic void MarkRedisplayLine __P((int, int, int, int)); Xstatic int MarkRewrite __P((int, int, int, int)); Xstatic void MarkSetCursor __P((void)); X Xextern struct win *fore; Xextern struct display *display; Xextern char *null, *blank; X X#ifdef NETHACK Xextern nethackflag; X#endif X Xstatic struct LayFuncs MarkLf = X{ X MarkProcess, X MarkAbort, X MarkRedisplayLine, X DefClearLine, X MarkRewrite, X MarkSetCursor, X DefResize, X DefRestore X}; X Xint join_with_cr = 0; Xchar mark_key_tab[256]; /* this array must be initialised first! */ X Xstatic struct markdata *markdata; X X X/* X * VI like is_letter: 0 - whitespace X * 1 - letter X * 2 - other X */ Xstatic int is_letter(c) Xchar c; X{ X if ((c >= 'a' && c <= 'z') || X (c >= 'A' && c <= 'Z') || X (c >= '0' && c <= '9') || X c == '_' || c == '.' || X c == '@' || c == ':' || X c == '%' || c == '!' || X c == '-' || c == '+') X /* thus we can catch email-addresses as a word :-) */ X return 1; X else if (c != ' ') X return 2; X return 0; X} X Xstatic int Xlinestart(y) Xint y; X{ X register int x; X register char *i; X X for (x = markdata->left_mar, i = iWIN(y) + x; x < d_width - 1; x++) X if (*i++ != ' ') X break; X if (x == d_width - 1) X x = markdata->left_mar; X return(x); X} X Xstatic int Xlineend(y) Xint y; X{ X register int x; X register char *i; X X for (x = markdata->right_mar, i = iWIN(y) + x; x >= 0; x--) X if (*i-- != ' ') X break; X if (x < 0) X x = markdata->left_mar; X return(x); X} X X X/* X * nextword calculates the cursor position of the num'th word. X * If the cursor is on a word, it counts as the first. X * NW_BACK: search backward X * NW_ENDOFWORD: find the end of the word X * NW_MUSTMOVE: move at least one char X */ X X#define NW_BACK (1<<0) X#define NW_ENDOFWORD (1<<1) X#define NW_MUSTMOVE (1<<2) X Xstatic void Xnextword(xp, yp, flags, num) Xint *xp, *yp, flags, num; X{ X int xx = d_width, yy = fore->w_histheight + d_height; X register int sx, oq, q, x, y; X X x = *xp; X y = *yp; X sx = (flags & NW_BACK) ? -1 : 1; X if ((flags & NW_ENDOFWORD) && (flags & NW_MUSTMOVE)) X x += sx; X for (oq = -1; ; x += sx, oq = q) X { X if (x >= xx || x < 0) X q = 0; X else X q = is_letter(iWIN(y)[x]); X if (oq >= 0 && oq != q) X { X if (oq == 0 || !(flags & NW_ENDOFWORD)) X *xp = x; X else X *xp = x-sx; X *yp = y; X if ((!(flags & NW_ENDOFWORD) && q) || X ((flags & NW_ENDOFWORD) && oq)) X { X if (--num <= 0) X return; X } X } X if (x == xx) X { X x = -1; X if (++y >= yy) X return; X } X else if (x < 0) X { X x = xx; X if (--y < 0) X return; X } X } X} X X X/* X * y1, y2 are WIN coordinates X * X * redisplay: 0 - just copy X * 1 - redisplay + copy X * 2 - count + copy, don't redisplay X */ X Xstatic int Xrem(x1, y1, x2, y2, redisplay, pt, yend) Xint x1, y1, x2, y2, redisplay, yend; Xchar *pt; X{ X int i, j, from, to, ry; X int l = 0; X char *im; X X markdata->second = 0; X if (y2 < y1 || ((y2 == y1) && (x2 < x1))) X { X i = y2; X y2 = y1; X y1 = i; X i = x2; X x2 = x1; X x1 = i; X } X ry = y1 - markdata->hist_offset; X X i = y1; X if (redisplay != 2 && pt == 0 && ry <0) X { X i -= ry; X ry = 0; X } X for (; i <= y2; i++, ry++) X { X if (redisplay != 2 && pt == 0 && ry > yend) X break; X from = (i == y1) ? x1 : 0; X if (from < markdata->left_mar) X from = markdata->left_mar; X for (to = d_width, im = iWIN(i) + to; to >= 0; to--) X if (*im-- != ' ') X break; X if (i == y2 && x2 < to) X to = x2; X if (to > markdata->right_mar) X to = markdata->right_mar; X if (redisplay == 1 && from <= to && ry >=0 && ry <= yend) X MarkRedisplayLine(ry, from, to, 0); X if (redisplay != 2 && pt == 0) /* don't count/copy */ X continue; X for (j = from, im = iWIN(i)+from; j <= to; j++) X { X if (pt) X *pt++ = *im++; X l++; X } X if (i != y2 && (to != d_width - 1 || iWIN(i)[to + 1] == ' ')) X { X /* X * this code defines, what glues lines together X */ X switch (markdata->nonl) X { X case 0: /* lines separated by newlines */ X if (join_with_cr) X { X if (pt) X *pt++ = '\r'; X l++; X } X if (pt) X *pt++ = '\n'; X l++; X break; X case 1: /* nothing to separate lines */ X break; X case 2: /* lines separated by blanks */ X if (pt) X *pt++ = ' '; X l++; X break; X } X } X } X return(l); X} X X/* Check if two chars are identical. All digits are treatened X * as same. Used for GetHistory() X */ X Xstatic int Xeq(a, b) Xint a, b; X{ X if (a == b) X return 1; X if (a == 0 || b == 0) X return 1; X if (a <= '9' && a >= '0' && b <= '9' && b >= '0') X return 1; X return 0; X} X X Xint XGetHistory() /* return value 1 if u_copybuffer changed */ X{ X int i = 0, q = 0, xx, yy, x, y; X char *linep; X X x = fore->w_x; X if (x >= d_width) X x = d_width - 1; X y = fore->w_y + fore->w_histheight; X debug2("cursor is at x=%d, y=%d\n", x, y); X for (xx = x - 1, linep = iWIN(y) + xx; xx >= 0; xx--) X if ((q = *linep--) != ' ' ) X break; X debug3("%c at (%d,%d)\n", q, xx, y); X for (yy = y - 1; yy >= 0; yy--) X { X linep = iWIN(yy); X if (xx < 0 || eq(linep[xx], q)) X { /* line is matching... */ X for (i = d_width - 1, linep += i; i >= x; i--) X if (*linep-- != ' ') X break; X if (i >= x) X break; X } X } X if (yy < 0) X return 0; X if (d_user->u_copybuffer != NULL) X UserFreeCopyBuffer(d_user); X if ((d_user->u_copybuffer = malloc((unsigned) (i - x + 2))) == NULL) X { X Msg(0, "Not enough memory... Sorry."); X return 0; X } X bcopy(linep - i + x + 1, d_user->u_copybuffer, i - x + 1); X d_user->u_copylen = i - x + 1; X return 1; X} X Xvoid XMarkRoutine() X{ X int x, y; X X ASSERT(fore->w_active); X if (InitOverlayPage(sizeof(*markdata), &MarkLf, 1)) X return; X markdata = (struct markdata *)d_lay->l_data; X markdata->second = 0; X markdata->rep_cnt = 0; X markdata->append_mode = 0; X markdata->write_buffer = 0; X markdata->nonl = 0; X markdata->left_mar = 0; X markdata->right_mar = d_width - 1; X markdata->hist_offset = fore->w_histheight; X x = fore->w_x; X y = D2W(fore->w_y); X if (x >= d_width) X x = d_width - 1; X X GotoPos(x, W2D(y)); X#ifdef NETHACK X if (nethackflag) X Msg(0, "Welcome to hacker's treasure zoo - Column %d Line %d(+%d) (%d,%d)", X x + 1, W2D(y + 1), fore->w_histheight, d_width, d_height); X else X#endif X Msg(0, "Copy mode - Column %d Line %d(+%d) (%d,%d)", X x + 1, W2D(y + 1), fore->w_histheight, d_width, d_height); X markdata->cx = markdata->x1 = x; X markdata->cy = markdata->y1 = y; X} X Xstatic void XMarkSetCursor() X{ X markdata = (struct markdata *)d_lay->l_data; X fore = d_fore; X GotoPos(markdata->cx, W2D(markdata->cy)); X} X Xstatic void XMarkProcess(inbufp,inlenp) Xchar **inbufp; Xint *inlenp; X{ X char *inbuf, *pt; X int inlen; X int cx, cy, x2, y2, j, yend; X int newcopylen = 0, od; X int in_mark; X int rep_cnt; X X/* X char *extrap = 0, extrabuf[100]; X*/ X X markdata = (struct markdata *)d_lay->l_data; X fore = d_fore; X if (inbufp == 0) X { X MarkAbort(); X return; X } X X GotoPos(markdata->cx, W2D(markdata->cy)); X inbuf= *inbufp; X inlen= *inlenp; X pt = inbuf; X in_mark = 1; X while (in_mark && (inlen /* || extrap */)) X { X/* X if (extrap) X { X od = *extrap++; X if (*extrap == 0) X extrap = 0; X } X else X*/ X { X od = mark_key_tab[(unsigned int)*pt++]; X inlen--; X } X rep_cnt = markdata->rep_cnt; X if (od >= '0' && od <= '9') X { X if (rep_cnt < 1001 && (od != '0' || rep_cnt != 0)) X { X markdata->rep_cnt = 10 * rep_cnt + od - '0'; X continue; X /* X * Now what is that 1001 here? Well, we have a screen with X * 25 * 80 = 2000 characters. Movement is at most across the full X * screen. This we do with word by word movement, as character by X * character movement never steps over line boundaries. The most words X * we can place on the screen are 1000 single letter words. Thus 1001 X * is sufficient. Users with bigger screens never write in single letter X * words, as they should be more advanced. jw. X * Oh, wrong. We still give even the experienced user a factor of ten. X */ X } X } X cx = markdata->cx; X cy = markdata->cy; X switch (od) X { X case '\014': /* CTRL-L Redisplay */ X Redisplay(0); X GotoPos(cx, W2D(cy)); X break; X case '\010': /* CTRL-H Backspace */ X case 'h': X if (rep_cnt == 0) X rep_cnt = 1; X revto(cx - rep_cnt, cy); X break; X case '\016': /* CTRL-N */ X case 'j': X if (rep_cnt == 0) X rep_cnt = 1; X revto(cx, cy + rep_cnt); X break; X case '+': X if (rep_cnt == 0) X rep_cnt = 1; X j = cy + rep_cnt; X if (j > fore->w_histheight + d_height - 1) X j = fore->w_histheight + d_height - 1; X revto(linestart(j), j); X break; X case '-': X if (rep_cnt == 0) X rep_cnt = 1; X cy -= rep_cnt; X if (cy < 0) X cy = 0; X revto(linestart(cy), cy); X break; X case '^': X revto(linestart(cy), cy); X break; X case '\n': X revto(markdata->left_mar, cy + 1); X break; X case 'k': X case '\020': /* CTRL-P */ X if (rep_cnt == 0) X rep_cnt = 1; X revto(cx, cy - rep_cnt); X break; X case 'l': X if (rep_cnt == 0) X rep_cnt = 1; X revto(cx + rep_cnt, cy); X break; X case '\001': /* CTRL-A from tcsh/emacs */ X case '0': X revto(markdata->left_mar, cy); X break; X case '\004': /* CTRL-D down half screen */ X if (rep_cnt == 0) X rep_cnt = (d_height + 1) >> 1; X revto_line(cx, cy + rep_cnt, W2D(cy)); X break; X case '$': X revto(lineend(cy), cy); X break; X case '\022': /* CTRL-R emacs style backwards search */ X ISearch(-1); X in_mark = 0; X break; X case '\023': /* CTRL-S emacs style search */ X ISearch(1); X in_mark = 0; X break; X case '\025': /* CTRL-U up half screen */ X if (rep_cnt == 0) X rep_cnt = (d_height + 1) >> 1; X revto_line(cx, cy - rep_cnt, W2D(cy)); X break; X case '\007': /* CTRL-G show cursorpos */ X if (markdata->left_mar == 0 && markdata->right_mar == d_width - 1) X Msg(0, "Column %d Line %d(+%d)", cx+1, W2D(cy)+1, X markdata->hist_offset); X else X Msg(0, "Column %d(%d..%d) Line %d(+%d)", cx+1, X markdata->left_mar+1, markdata->right_mar+1, W2D(cy)+1, markdata->hist_offset); X break; X case '\002': /* CTRL-B back one page */ X if (rep_cnt == 0) X rep_cnt = 1; X rep_cnt *= d_height; X revto(cx, cy - rep_cnt); X break; X case '\006': /* CTRL-F forward one page */ X if (rep_cnt == 0) X rep_cnt = 1; X rep_cnt *= d_height; X revto(cx, cy + rep_cnt); X break; X case '\005': /* CTRL-E scroll up */ X if (rep_cnt == 0) X rep_cnt = 1; X rep_cnt = MarkScrollUpDisplay(rep_cnt); X if (cy < D2W(0)) X revto(cx, D2W(0)); X else X GotoPos(cx, W2D(cy)); X break; X case '\031': /* CTRL-Y scroll down */ X if (rep_cnt == 0) X rep_cnt = 1; X rep_cnt = MarkScrollDownDisplay(rep_cnt); X if (cy > D2W(d_height-1)) X revto(cx, D2W(d_height-1)); X else X GotoPos(cx, W2D(cy)); X break; X case '@': X /* it may be usefull to have a key that does nothing */ X break; X case '%': X rep_cnt--; X /* rep_cnt is a percentage for the history buffer */ X if (rep_cnt < 0) X rep_cnt = 0; X if (rep_cnt > 100) X rep_cnt = 100; X revto_line(markdata->left_mar, (rep_cnt * (fore->w_histheight + d_height)) / 100, (d_height - 1) / 2); X break; X case 'g': X rep_cnt = 1; X /* FALLTHROUGH */ X case 'G': X /* rep_cnt is here the WIN line number */ X if (rep_cnt == 0) X rep_cnt = fore->w_histheight + d_height; X revto_line(markdata->left_mar, --rep_cnt, (d_height - 1) / 2); X break; X case 'H': X revto(markdata->left_mar, D2W(0)); X break; X case 'M': X revto(markdata->left_mar, D2W((d_height - 1) / 2)); X break; X case 'L': X revto(markdata->left_mar, D2W(d_height - 1)); X break; X case '|': X revto(--rep_cnt, cy); X break; X case 'w': X if (rep_cnt == 0) X rep_cnt = 1; X nextword(&cx, &cy, NW_MUSTMOVE, rep_cnt); X revto(cx, cy); X break; X case 'e': X if (rep_cnt == 0) X rep_cnt = 1; X nextword(&cx, &cy, NW_ENDOFWORD|NW_MUSTMOVE, rep_cnt); X revto(cx, cy); X break; X case 'b': X if (rep_cnt == 0) X rep_cnt = 1; X nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD|NW_MUSTMOVE, rep_cnt); X revto(cx, cy); X break; X case 'a': X markdata->append_mode = 1 - markdata->append_mode; X debug1("append mode %d--\n", markdata->append_mode); X Msg(0, (markdata->append_mode) ? ":set append" : ":set noappend"); X break; X case 'v': X case 'V': X /* this sets start column to column 9 for VI :set nu users */ X if (markdata->left_mar == 8) X rep_cnt = 1; X else X rep_cnt = 9; X /* FALLTHROUGH */ X case 'c': X case 'C': X /* set start column (c) and end column (C) */ X if (markdata->second) X { X rem(markdata->x1, markdata->y1, cx, cy, 1, (char *)0, d_height-1); /* Hack */ X markdata->second = 1; /* rem turns off second */ X } X rep_cnt--; X if (rep_cnt < 0) X rep_cnt = cx; X if (od != 'C') X { X markdata->left_mar = rep_cnt; X if (markdata->left_mar > markdata->right_mar) X markdata->left_mar = markdata->right_mar; X } X else X { X markdata->right_mar = rep_cnt; X if (markdata->left_mar > markdata->right_mar) X markdata->right_mar = markdata->left_mar; X } X if (markdata->second) X { X markdata->cx = markdata->x1; markdata->cy = markdata->y1; X revto(cx, cy); X } X if (od == 'v' || od == 'V') X Msg(0, (markdata->left_mar != 8) ? ":set nonu" : ":set nu"); X break; X case 'J': X /* how do you join lines in VI ? */ X markdata->nonl = (markdata->nonl + 1) % 3; X switch (markdata->nonl) X { X case 0: X if (join_with_cr) X Msg(0, "Multiple lines (CR/LF)"); X else X Msg(0, "Multiple lines (LF)"); X break; X case 1: X Msg(0, "Lines joined"); X break; X case 2: X Msg(0, "Lines joined with blanks"); X break; X } X break; X case '/': X Search(1); X in_mark = 0; X break; X case '?': X Search(-1); X in_mark = 0; X break; X case 'n': X Search(0); X break; X case 'y': X case 'Y': X if (markdata->second == 0) X { X revto(linestart(cy), cy); X markdata->second++; X cx = markdata->x1 = markdata->cx; X cy = markdata->y1 = markdata->cy; X } X if (--rep_cnt > 0) X revto(cx, cy + rep_cnt); X revto(lineend(markdata->cy), markdata->cy); X if (od == 'y') X break; X /* FALLTHROUGH */ X case 'W': X if (od == 'W') X { X if (rep_cnt == 0) X rep_cnt = 1; X if (!markdata->second) X { X nextword(&cx, &cy, NW_BACK|NW_ENDOFWORD, 1); X revto(cx, cy); X markdata->second++; X cx = markdata->x1 = markdata->cx; X cy = markdata->y1 = markdata->cy; X } X nextword(&cx, &cy, NW_ENDOFWORD, rep_cnt); X revto(cx, cy); X } X cx = markdata->cx; X cy = markdata->cy; X /* FALLTHROUGH */ X case 'A': X if (od == 'A') X markdata->append_mode = 1; X /* FALLTHROUGH */ X case '>': X if (od == '>') X markdata->write_buffer = 1; X /* FALLTHROUGH */ X case ' ': X case '\r': X if (!markdata->second) X { X markdata->second++; X markdata->x1 = cx; X markdata->y1 = cy; X revto(cx, cy); X#ifdef NETHACK X if (nethackflag) X Msg(0, "You drop a magic marker - Column %d Line %d", X cx+1, W2D(cy)+1); X else X#endif X Msg(0, "First mark set - Column %d Line %d", cx+1, W2D(cy)+1); X break; X } X else X { X int append_mode = markdata->append_mode; X int write_buffer = markdata->write_buffer; X X x2 = cx; X y2 = cy; X newcopylen = rem(markdata->x1, markdata->y1, x2, y2, 2, (char *)0, 0); /* count */ X if (d_user->u_copybuffer != NULL && !append_mode) X { X UserFreeCopyBuffer(d_user); X } X if (newcopylen > 0) X { X /* the +3 below is for : cr + lf + \0 */ X if (d_user->u_copybuffer != NULL) X d_user->u_copybuffer = realloc(d_user->u_copybuffer, X (unsigned) (d_user->u_copylen + newcopylen + 3)); X else X { X d_user->u_copylen = 0; X d_user->u_copybuffer = malloc((unsigned) (newcopylen + 3)); X } X if (d_user->u_copybuffer == NULL) X { X MarkAbort(); X in_mark = 0; X Msg(0, "Not enough memory... Sorry."); X d_user->u_copylen = 0; X d_user->u_copybuffer = NULL; X break; X } X if (append_mode) X { X switch (markdata->nonl) X { X /* X * this code defines, what glues lines together X */ X case 0: X if (join_with_cr) X { X d_user->u_copybuffer[d_user->u_copylen] = '\r'; X d_user->u_copylen++; X } X d_user->u_copybuffer[d_user->u_copylen] = '\n'; X d_user->u_copylen++; X break; X case 1: X break; X case 2: X d_user->u_copybuffer[d_user->u_copylen] = ' '; X d_user->u_copylen++; X break; X } X } X yend = d_height - 1; X if (fore->w_histheight - markdata->hist_offset < d_height) X { X markdata->second = 0; X yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset); X } X d_user->u_copylen += rem(markdata->x1, markdata->y1, x2, y2, X markdata->hist_offset == fore->w_histheight, X d_user->u_copybuffer + d_user->u_copylen, yend); X } X if (markdata->hist_offset != fore->w_histheight) X LAY_CALL_UP(Activate(0)); X ExitOverlayPage(); X if (append_mode) X Msg(0, "Appended %d characters to buffer", X newcopylen); X else X Msg(0, "Copied %d characters into buffer", d_user->u_copylen); X if (write_buffer) X WriteFile(DUMP_EXCHANGE); X in_mark = 0; X break; X } X default: X MarkAbort(); X#ifdef NETHACK X if (nethackflag) X Msg(0, "You escaped the dungeon."); X else X#endif X Msg(0, "Copy mode aborted"); X in_mark = 0; X break; X } X if (in_mark) /* markdata may be freed */ X markdata->rep_cnt = 0; X } X *inbufp = pt; X *inlenp = inlen; X} X Xvoid revto(tx, ty) Xint tx, ty; X{ X revto_line(tx, ty, -1); X} X X/* tx, ty: WINDOW, line: DISPLAY */ Xvoid revto_line(tx, ty, line) Xint tx, ty, line; X{ X int fx, fy; X int x, y, t, revst, reven, qq, ff, tt, st, en, ce = 0; X int ystart = 0, yend = d_height-1; X int i, ry; X X if (tx < 0) X tx = 0; X else if (tx > d_width - 1) X tx = d_width -1; X if (ty < 0) X ty = 0; X else if (ty > fore->w_histheight + d_height - 1) X ty = fore->w_histheight + d_height - 1; X X fx = markdata->cx; fy = markdata->cy; X markdata->cx = tx; markdata->cy = ty; X X /* X * if we go to a position that is currently offscreen X * then scroll the screen X */ X i = 0; X if (line >= 0 && line < d_height) X i = W2D(ty) - line; X else if (ty < markdata->hist_offset) X i = ty - markdata->hist_offset; X else if (ty > markdata->hist_offset + (d_height-1)) X i = ty-markdata->hist_offset-(d_height-1); X if (i > 0) X yend -= MarkScrollUpDisplay(i); X else if (i < 0) X ystart += MarkScrollDownDisplay(-i); X X if (markdata->second == 0) X { X GotoPos(tx, W2D(ty)); X return; X } X X qq = markdata->x1 + markdata->y1 * d_width; X ff = fx + fy * d_width; /* "from" offset in WIN coords */ X tt = tx + ty * d_width; /* "to" offset in WIN coords*/ X X if (ff > tt) X { X st = tt; en = ff; X x = tx; y = ty; X } X else X { X st = ff; en = tt; X x = fx; y = fy; X } X if (st > qq) X { X st++; X x++; X } X if (en < qq) X en--; X if (tt > qq) X { X revst = qq; reven = tt; X } X else X { X revst = tt; reven = qq; X } X ry = y - markdata->hist_offset; X if (ry < ystart) X { X y += (ystart - ry); X x = 0; X st = y * d_width; X ry = ystart; X } X for (t = st; t <= en; t++, x++) X { X if (x >= d_width) X { X x = 0; X y++, ry++; X } X if (ry > yend) X break; X if (t == st || x == 0) X { X for (ce = d_width; ce >= 0; ce--) X if (iWIN(y)[ce] != ' ') X break; X } X if (x <= ce && x >= markdata->left_mar && x <= markdata->right_mar X && (CLP || x < d_width-1 || ry < d_bot)) X { X GotoPos(x, W2D(y)); X if (t >= revst && t <= reven) X SetAttrFont(A_SO, ASCII); X else X SetAttrFont(aWIN(y)[x], fWIN(y)[x]); X PUTCHARLP(iWIN(y)[x]); X } X } X GotoPos(tx, W2D(ty)); X} X Xstatic void XMarkAbort() X{ X int yend, redisp; X X debug("MarkAbort\n"); X markdata = (struct markdata *)d_lay->l_data; X fore = d_fore; X yend = d_height - 1; X redisp = markdata->second; X if (fore->w_histheight - markdata->hist_offset < d_height) X { X markdata->second = 0; X yend -= MarkScrollUpDisplay(fore->w_histheight - markdata->hist_offset); X } X if (markdata->hist_offset != fore->w_histheight) X { X LAY_CALL_UP(Activate(0)); X } X else X { X rem(markdata->x1, markdata->y1, markdata->cx, markdata->cy, redisp, (char *)0, yend); X } X ExitOverlayPage(); X} X X Xstatic void XMarkRedisplayLine(y, xs, xe, isblank) Xint y; /* NOTE: y is in DISPLAY coords system! */ Xint xs, xe; Xint isblank; X{ X int x, i, rm; X int sta, sto, cp; /* NOTE: these 3 are in WINDOW coords system */ X char *wi, *wa, *wf, *oldi; X X if (y < 0) /* No special full page handling */ X return; X X markdata = (struct markdata *)d_lay->l_data; X fore = d_fore; X X wi = iWIN(D2W(y)); X wa = aWIN(D2W(y)); X wf = fWIN(D2W(y)); X oldi = isblank ? blank : null; X X if (markdata->second == 0) X { X DisplayLine(oldi, null, null, wi, wa, wf, y, xs, xe); X return; X } X X sta = markdata->y1 * d_width + markdata->x1; X sto = markdata->cy * d_width + markdata->cx; X if (sta > sto) X { X i=sta; sta=sto; sto=i; X } X cp = D2W(y) * d_width + xs; X X rm = markdata->right_mar; X for (x = d_width; x >= 0; x--) X if (wi[x] != ' ') X break; X if (x < rm) X rm = x; X X for (x = xs; x <= xe; x++, cp++) X if (cp >= sta && x >= markdata->left_mar) X break; X if (x > xs) X DisplayLine(oldi, null, null, wi, wa, wf, y, xs, x-1); X for (; x <= xe; x++, cp++) X { X if (cp > sto || x > rm || (!CLP && x >= d_width-1 && y == d_bot)) X break; X GotoPos(x, y); X SetAttrFont(A_SO, ASCII); X PUTCHARLP(wi[x]); X } X if (x <= xe) X DisplayLine(oldi, null, null, wi, wa, wf, y, x, xe); X} X X X/* X * This ugly routine is to speed up GotoPos() X */ Xstatic int XMarkRewrite(ry, xs, xe, doit) Xint ry, xs, xe, doit; X{ X int dx, x, y, st, en, t, rm; X char *a, *f, *i; X X markdata = (struct markdata *)d_lay->l_data; X fore = d_fore; X y = D2W(ry); X dx = xe - xs; X if (doit) X { X i = iWIN(y) + xs; X while (dx--) X PUTCHARLP(*i++); X return(0); X } X X a = aWIN(y) + xs, X f = fWIN(y) + xs; X if (markdata->second == 0) X st = en = -1; X else X { X st = markdata->y1 * d_width + markdata->x1; X en = markdata->cy * d_width + markdata->cx; X if (st > en) X { X t = st; st = en; en = t; X } X } X t = y * d_width + xs; X for (rm=d_width, i=iWIN(y) + d_width; rm>=0; rm--) X if (*i-- != ' ') X break; X if (rm > markdata->right_mar) X rm = markdata->right_mar; X x = xs; X while (dx--) X { X if (t >= st && t <= en && x >= markdata->left_mar && x <= rm) X { X if (d_attr != A_SO || d_font != ASCII) X return(EXPENSIVE); X } X else X { X if (d_attr != *a || d_font != *f) X return(EXPENSIVE); X } X a++, f++, t++, x++; X } X return(xe - xs); X} X X X/* X * scroll the screen contents up/down. X */ Xstatic int MarkScrollUpDisplay(n) Xint n; X{ X int i; X X debug1("MarkScrollUpDisplay(%d)\n", n); X if (n <= 0) X return 0; X if (n > fore->w_histheight - markdata->hist_offset) X n = fore->w_histheight - markdata->hist_offset; X i = (n < d_height) ? n : (d_height); X ScrollRegion(0, d_height - 1, i); X markdata->hist_offset += n; X while (i-- > 0) X MarkRedisplayLine(d_height - i - 1, 0, d_width - 1, 1); X return n; X} X Xstatic int MarkScrollDownDisplay(n) Xint n; X{ X int i; X X debug1("MarkScrollDownDisplay(%d)\n", n); X if (n <= 0) X return 0; X if (n > markdata->hist_offset) X n = markdata->hist_offset; X i = (n < d_height) ? n : (d_height); X ScrollRegion(0, d_height - 1, -i); X markdata->hist_offset -= n; X while (i-- > 0) X MarkRedisplayLine(i, 0, d_width - 1, 1); X return n; X} X X#endif /* COPY_PASTE */ END_OF_FILE if test 25787 -ne `wc -c <'mark.c'`; then echo shar: \"'mark.c'\" unpacked with wrong size! fi # end of 'mark.c' fi if test -f 'socket.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'socket.c'\" else echo shar: Extracting \"'socket.c'\" \(29765 characters\) sed "s/^X//" >'socket.c' <<'END_OF_FILE' X/* Copyright (c) 1993 X * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) X * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) X * Copyright (c) 1987 Oliver Laumann X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 2, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program (see the file COPYING); if not, write to the X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X * X **************************************************************** X */ X X#include "rcs.h" XRCS_ID("$Id: socket.c,v 1.11 1993/08/04 00:43:00 mlschroe Exp $ FAU") X X#include "config.h" X#include X#include X#ifndef sgi X# include X#endif X#ifndef NAMEDPIPE X#include X#endif X#include X#ifndef NAMEDPIPE X#include X#endif X#include X#ifndef M_XENIX X#include X#endif /* M_XENIX */ X#ifdef DIRENT X# include X#else X# include X# define dirent direct X#endif X X#include "screen.h" X X#ifdef USEVARARGS X# if defined(__STDC__) X# include X# else X# include X# endif X#endif X X#include "extern.h" X X#if defined(_SEQUENT_) && !defined(NAMEDPIPE) X# define connect sconnect /* _SEQUENT_ has braindamaged connect */ Xstatic int sconnect __P((int, struct sockaddr *, int)); X#endif X Xextern char *RcFileName, *extra_incap, *extra_outcap; Xextern int ServerSocket, real_uid, real_gid, eff_uid, eff_gid; Xextern int dflag, iflag, rflag, lsflag, quietflag, wipeflag, xflag; Xextern char *attach_tty, *LoginName, HostName[]; Xextern struct display *display, *displays; Xextern struct win *fore, *wtab[], *console_window, *windows; Xextern struct NewWindow nwin_undef; X#ifdef NETHACK Xextern nethackflag; X#endif X#ifdef MULTIUSER Xextern char *multi; X#endif X X#ifdef PASSWORD Xextern int CheckPassword; Xextern char Password[]; X#endif Xextern char *getenv(); X Xchar SockPath[MAXPATHLEN]; Xchar *SockNamePtr, *SockName; X X#ifdef MULTIUSER X# define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0) | (multi ? 1 : 0)) X#else X# define SOCKMODE (S_IWRITE | S_IREAD | (displays ? S_IEXEC : 0)) X#endif X Xint XRecoverSocket() X{ X#ifndef NOREUID X setreuid(eff_uid, real_uid); X setregid(eff_gid, real_gid); X#endif X (void) unlink(SockPath); X#ifndef NOREUID X setreuid(real_uid, eff_uid); X setregid(real_gid, eff_gid); X#endif X close(ServerSocket); X if ((ServerSocket = MakeServerSocket()) < 0) X return 0; X return 1; X} X X/* X * Socket mode 700 means we are Attached. 600 is detached. X * We return how many sockets we found. If it was exactly one, we come X * back with a SockPath set to it and open it in a fd pointed to by fdp. X * If fdp == 0 we simply produce a list if all sockets. X */ X/* ARGSUSED */ Xint XFindSocket(how, fdp) Xint how; Xint *fdp; X{ X register int s, lasts = 0, found = 0, deadcount = 0, wipecount = 0; X register int l = 0; X register DIR *dirp; X register struct dirent *dp; X register char *Name; X struct stat st; X struct foundsock X { X char *name; X int mode; X } foundsock[100]; /* 100 is hopefully enough. */ X int foundsockcount = 0; X X /* User may or may not give us a (prefix) SockName. We want to search. */ X debug("FindSocket:\n"); X if (SockName) X { X debug1("We want to match '%s'\n", SockName); X l = strlen(SockName); X#ifdef NAME_MAX X if (l > NAME_MAX) X l = NAME_MAX; X#endif X } X X#ifndef NOREUID X setreuid(eff_uid, real_uid); X setregid(eff_gid, real_gid); X#endif X debug1("FindSock searching... '%s'\n", SockPath); X /* X * this is a hack: SockName may point to Filename(Sockpath)... X */ X found = *SockNamePtr; X *SockNamePtr = '\0'; X if ((dirp = opendir(SockPath)) == NULL) X { X Panic(0, "Cannot opendir %s", SockPath); X /* NOTREACHED */ X } X *SockNamePtr = found; X found = 0; X while ((dp = readdir(dirp)) != NULL) X { X Name = dp->d_name; X /* X * there may be a file ".termcap" here. X * Ignore it just like "." and "..". X */ X debug1("- %s\n", Name); X if (Name[0] == '.') X continue; X if (SockName && l) X { X register char *n = Name; X X debug2("Attach found: '%s', needed '%s'\n", Name, SockName); X /* X * The SockNames "hf", "ttyhf", "1", "12345.tty", "12345.ttyhf.medusa" X * all match the Name "12345.ttyhf.medusa". X */ X X if ((*SockName <= '0' || *SockName > '9') && (*n > '0' && *n <= '9')) X { X while (*++n) X if (*n == '.') X { X n++; X break; X } X if (strncmp("tty", SockName, 3) && !strncmp("tty", n, 3)) X n += 3; X } X if (strncmp(n, SockName, l)) X { X debug3("strncmp('%s', '%s', %d)\n", n, SockName, l); X continue; X } X } X /* X * ATTENTION! MakeClientSocket adds SockName to SockPath! X * Anyway, we need it earlier. X */ X strcpy(SockNamePtr, Name); X if (stat(SockPath, &st)) X { X debug1("could not stat! (%d)\n", errno); X continue; X } X#ifndef SOCK_NOT_IN_FS X# ifdef NAMEDPIPE X if (!S_ISFIFO(st.st_mode)) X { X debug1("'%s' is not a pipe, ignored\n", SockPath); X continue; X } X# else /* NAMEDPIPE */ X# ifdef S_ISSOCK X if (!S_ISSOCK(st.st_mode)) X { X debug1("'%s' is not a socket, ignored\n", SockPath); X continue; X } X# endif X# endif /* NAMEDPIPE */ X#endif X if (st.st_uid != real_uid) X { X debug2("uid mismatch (%d - %d) - ignored\n", st.st_uid, real_uid); X continue; X } X s = st.st_mode & 0777; X debug2("FindSocket: %s has mode %04o...\n", Name, s); X#ifdef MULTIUSER X if (multi && ((s & 0677) == 0600)) X continue; X#endif X foundsock[foundsockcount].name = SaveStr(Name); X#ifdef MULTIUSER X foundsock[foundsockcount].mode = s ^ (multi ? 1 : 0); X#else X foundsock[foundsockcount].mode = s; X#endif X { X /* X * marc parses the socketname again X */ X int sockmpid = 0; X char *nam = Name; X X while (*nam) X { X if (*nam > '9' || *nam < '0') X break; X sockmpid = 10 * sockmpid + *nam - '0'; X nam++; X } X /* X * A socket is counted as dead, when there is no X * process belongin to it. If there is one, and the X * socket mode indicates "single user detached", then X * we should be able to connect. X * If successfull, thats o.k. Otherwise we record that mode as -1. X * MakeClientSocket() must be careful not to block forever. X */ X if (((sockmpid > 2) && kill(sockmpid, 0) == -1 && errno == ESRCH) || X (((s & 0677) == 0600) && (s = MakeClientSocket(0, Name)) == -1)) X { X foundsock[foundsockcount].mode = -1; X deadcount++; X } X else X close(s); X } X if (++foundsockcount >= 100) X break; X } X closedir(dirp); X X if (wipeflag) X { X for (s = 0; s < foundsockcount; s++) X { X if (foundsock[s].mode == -1) X { X strcpy(SockNamePtr, foundsock[s].name); X debug1("wiping '%s'\n", SockPath); X if (unlink(SockPath) == 0) X { X foundsock[s].mode = -2; X wipecount++; X } X } X } X } Xdebug3("found=%d, dflag = %d, xflag = %d\n", found, dflag, xflag); X for (s = 0; s < foundsockcount; s++) X if ((foundsock[s].mode) == (dflag ? 0700 : 0600) X || (xflag && foundsock[s].mode == 0700)) X { X found++; Xdebug2("mode = %d --> found = %d\n", foundsock[s].mode, found); X lasts = s; X } X if (quietflag && (lsflag || (found != 1 && rflag != 2))) X eexit(10 + found); X debug2("attach: found=%d, foundsockcount=%d\n", found, foundsockcount); X if (found == 1 && lsflag == 0) X { X if ((lasts = MakeClientSocket(0, SockName = foundsock[lasts].name)) == -1) X found = 0; X } X else if (!quietflag && foundsockcount > 0) X { X switch (found) X { X case 0: X if (lsflag) X { X#ifdef NETHACK X if (nethackflag) X printf("Your inventory:\n"); X else X#endif X printf((foundsockcount > 1) ? X "There are screens on:\n" : "There is a screen on:\n"); X } X else X { X#ifdef NETHACK X if (nethackflag) X printf("Nothing fitting exists in the game:\n"); X else X#endif X printf((foundsockcount > 1) ? X "There are screens on:\n" : "There is a screen on:\n"); X } X break; X case 1: X#ifdef NETHACK X if (nethackflag) X printf((foundsockcount > 1) ? X "Prove thyself worthy or perish:\n" : X "You see here a good looking screen:\n"); X else X#endif X printf((foundsockcount > 1) ? X "There are several screens on:\n" : X "There is a possible screen on:\n"); X break; X default: X#ifdef NETHACK X if (nethackflag) X printf((foundsockcount > 1) ? X "You may whish for a screen, what do you want?\n" : X "You see here a screen:\n"); X else X#endif X printf((foundsockcount > 1) ? X "There are several screens on:\n" : "There is a screen on:\n"); X break; X } X for (s = 0; s < foundsockcount; s++) X { X switch (foundsock[s].mode) X { X case 0700: X printf("\t%s\t(Attached)\n", foundsock[s].name); X break; X case 0600: X printf("\t%s\t(Detached)\n", foundsock[s].name); X break; X#ifdef MULTIUSER X case 0701: X printf("\t%s\t(Multi, attached)\n", foundsock[s].name); X break; X case 0601: X printf("\t%s\t(Multi, detached)\n", foundsock[s].name); X break; X#endif X case -1: X#if defined(__STDC__) || defined(_AIX) || defined(SVR4) X printf("\t%s\t(Dead ??\?)\n", foundsock[s].name); X#else X printf("\t%s\t(Dead ???)\n", foundsock[s].name); X#endif X break; X case -2: X printf("\t%s\t(Removed)\n", foundsock[s].name); X break; X default: X printf("\t%s\t(Wrong mode)\n", foundsock[s].name); X break; X } X } X } X if (deadcount && !quietflag) X { X if (wipeflag) X { X#ifdef NETHACK X if (nethackflag) X printf("You hear%s distant explosion%s.\n", X (deadcount > 1) ? "" : " a", (deadcount > 1) ? "s" : ""); X else X#endif X printf("%d Socket%s wiped out.\n", deadcount, (deadcount > 1)?"s":""); X } X else X { X#ifdef NETHACK X if (nethackflag) X printf("The dead screen%s touch%s you. Try 'screen -wipe'.\n", X (deadcount > 1) ? "s" : "", (deadcount > 1) ? "" : "es"); X else X#endif X printf("Remove dead Sockets with 'screen -wipe'.\n"); X } X } X X for (s = 0; s < foundsockcount; s++) X Free(foundsock[s].name); X if (found == 1 && fdp) X *fdp = lasts; X#ifndef NOREUID X setreuid(real_uid, eff_uid); X setregid(real_gid, eff_gid); X#endif X if (fdp) X return found; X return foundsockcount - wipecount; X} X X#ifdef NAMEDPIPE X Xint XMakeServerSocket() X{ X register int s; X struct stat st; X X strcpy(SockNamePtr, SockName); X# ifdef NAME_MAX X if (strlen(SockNamePtr) > NAME_MAX) X { X debug2("MakeClientSocket: '%s' truncated to %d chars\n", X SockNamePtr, NAME_MAX); X SockNamePtr[NAME_MAX] = '\0'; X } X# endif /* NAME_MAX */ X X# ifndef NOREUID X setreuid(eff_uid, real_uid); X setregid(eff_gid, real_gid); X# endif /* NOREUID */ X if ((s = open(SockPath, O_WRONLY | O_NDELAY)) >= 0) X { X debug("huii, my fifo already exists??\n"); X if (quietflag) X { X Kill(d_userpid, SIG_BYE); X eexit(11); X } X printf("There is already a screen running on %s.\n", X Filename(SockPath)); X if (stat(SockPath, &st) == -1) X Panic(errno, "stat"); X if (st.st_uid != real_uid) X Panic(0, "Unfortunatelly you are not its owner."); X if ((st.st_mode & 0700) == 0600) X Panic(0, "To resume it, use \"screen -r\""); X else X Panic(0, "It is not detached."); X /* NOTREACHED */ X } X# ifndef NOREUID X (void) unlink(SockPath); X if (mknod(SockPath, S_IFIFO | SOCKMODE, 0)) X Panic(0, "mknod fifo %s failed", SockPath); X# ifdef BROKEN_PIPE X if ((s = open(SockPath, O_RDWR | O_NDELAY, 0)) < 0) X# else X if ((s = open(SockPath, O_RDONLY | O_NDELAY, 0)) < 0) X# endif X Panic(errno, "open fifo %s", SockPath); X setreuid(real_uid, eff_uid); X setregid(real_gid, eff_gid); X return s; X# else /* NOREUID */ X if (UserContext() > 0) X { X (void) unlink(SockPath); X if (mknod(SockPath, S_IFIFO | SOCKMODE, 0)) X UserReturn(0); X UserReturn(1); X } X if (UserStatus() <= 0) X Panic(0, "mknod fifo %s failed", SockPath); X# ifdef BROKEN_PIPE X if ((s = secopen(SockPath, O_RDWR | O_NDELAY, 0)) < 0) X# else X if ((s = secopen(SockPath, O_RDONLY | O_NDELAY, 0)) < 0) X# endif X Panic(errno, "open fifo %s", SockPath); X return s; X# endif /* NOREUID */ X} X X Xint XMakeClientSocket(err, name) Xint err; Xchar *name; X{ X register int s = 0; X X strcpy(SockNamePtr, name); X# ifdef NAME_MAX X if (strlen(SockNamePtr) > NAME_MAX) X { X debug2("MakeClientSocket: '%s' truncated to %d chars\n", X SockNamePtr, NAME_MAX); X SockNamePtr[NAME_MAX] = '\0'; X } X# endif /* NAME_MAX */ X X if ((s = secopen(SockPath, O_WRONLY | O_NDELAY, 0)) >= 0) X { X (void) fcntl(s, F_SETFL, 0); X return s; X } X if (err) X Msg(errno, "open: %s (but continuing...)", SockPath); X debug1("MakeClientSocket() open %s failed\n", SockPath); X return -1; X} X X#else /* NAMEDPIPE */ X Xint XMakeServerSocket() X{ X register int s; X struct sockaddr_un a; X struct stat st; X X if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) X Panic(errno, "socket"); X a.sun_family = AF_UNIX; X strcpy(SockNamePtr, SockName); X# ifdef NAME_MAX X if (strlen(SockNamePtr) > NAME_MAX) X { X debug2("MakeServerSocket: '%s' truncated to %d chars\n", X SockNamePtr, NAME_MAX); X SockNamePtr[NAME_MAX] = '\0'; X } X# endif /* NAME_MAX */ X X strcpy(a.sun_path, SockPath); X# ifndef NOREUID X setreuid(eff_uid, real_uid); X setregid(eff_gid, real_gid); X# endif /* NOREUID */ X if (connect(s, (struct sockaddr *) &a, strlen(SockPath) + 2) != -1) X { X debug("oooooh! socket already is alive!\n"); X if (quietflag) X { X Kill(d_userpid, SIG_BYE); X /* X * oh, well. nobody receives that return code. papa X * dies by signal. X */ X eexit(11); X } X printf("There is already a screen running on %s.\n", X Filename(SockPath)); X if (stat(SockPath, &st) == -1) X Panic(errno, "stat"); X if (st.st_uid != real_uid) X Panic(0, "Unfortunatelly you are not its owner."); X if ((st.st_mode & 0700) == 0600) X Panic(0, "To resume it, use \"screen -r\""); X else X Panic(0, "It is not detached."); X /* NOTREACHED */ X } X#if defined(m88k) || defined(sysV68) X close(s); /* we get bind: Invalid argument if this is not done */ X if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) X Panic(errno, "reopen socket"); X#endif X (void) unlink(SockPath); X if (bind(s, (struct sockaddr *) & a, strlen(SockPath) + 2) == -1) X Panic(errno, "bind (%s)", SockPath); X#ifdef SOCK_NOT_IN_FS X { X int f; X if ((f = secopen(SockPath, O_RDWR | O_CREAT, SOCKMODE)) < 0) X Panic(errno, "shadow socket open"); X close(f); X } X#else X chmod(SockPath, SOCKMODE); X# ifdef NOREUID X chown(SockPath, real_uid, real_gid); X# endif /* NOREUID */ X#endif /* SOCK_NOT_IN_FS */ X if (listen(s, 5) == -1) X Panic(errno, "listen"); X# ifdef F_SETOWN X fcntl(s, F_SETOWN, getpid()); X debug1("Serversocket owned by %d\n", fcntl(s, F_GETOWN, 0)); X# endif /* F_SETOWN */ X# ifndef NOREUID X setreuid(real_uid, eff_uid); X setregid(real_gid, eff_gid); X# endif /* NOREUID */ X return s; X} X Xint XMakeClientSocket(err, name) Xint err; Xchar *name; X{ X register int s; X struct sockaddr_un a; X X if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) X Panic(errno, "socket"); X a.sun_family = AF_UNIX; X strcpy(SockNamePtr, name); X# ifdef NAME_MAX X if (strlen(SockNamePtr) > NAME_MAX) X { X debug2("MakeClientSocket: '%s' truncated to %d chars\n", X SockNamePtr, NAME_MAX); X SockNamePtr[NAME_MAX] = '\0'; X } X# endif /* NAME_MAX */ X X strcpy(a.sun_path, SockPath); X# ifndef NOREUID X setreuid(eff_uid, real_uid); X setregid(eff_gid, real_gid); X# else /* NOREUID */ X if (access(SockPath, W_OK)) X { X if (err) X Msg(errno, "%s", SockPath); X debug2("MakeClientSocket: access(%s): %d.\n", SockPath, errno); X close(s); X return -1; X } X# endif /* NOREUID */ X if (connect(s, (struct sockaddr *) &a, strlen(SockPath) + 2) == -1) X { X if (err) X Msg(errno, "%s: connect", SockPath); X debug("MakeClientSocket: connect failed.\n"); X close(s); X s = -1; X } X# ifndef NOREUID X setreuid(real_uid, eff_uid); X setregid(real_gid, eff_gid); X# endif /* NOREUID */ X return s; X} X#endif /* NAMEDPIPE */ X X Xvoid XSendCreateMsg(s, nwin) Xint s; Xstruct NewWindow *nwin; X{ X struct msg m; X register char *p; X register int len, n; X char **av = nwin->args; X X debug1("SendCreateMsg() to '%s'\n", SockPath); X bzero((char *)&m, sizeof(m)); X m.type = MSG_CREATE; X strcpy(m.m_tty, attach_tty); X p = m.m.create.line; X n = 0; X if (nwin->args != nwin_undef.args) X for (av = nwin->args; *av && n < MAXARGS - 1; ++av, ++n) X { X len = strlen(*av) + 1; X if (p + len >= m.m.create.line + MAXPATHLEN - 1) X break; X strcpy(p, *av); X p += len; X } X if (nwin->aka != nwin_undef.aka && p + strlen(nwin->aka) + 1 < m.m.create.line + MAXPATHLEN) X strcpy(p, nwin->aka); X else X *p = '\0'; X m.m.create.nargs = n; X m.m.create.aflag = nwin->aflag; X m.m.create.flowflag = nwin->flowflag; X m.m.create.lflag = nwin->lflag; X m.m.create.hheight = nwin->histheight; X#ifdef SYSV X if (getcwd(m.m.create.dir, sizeof(m.m.create.dir)) == 0) X#else X if (getwd(m.m.create.dir) == 0) X#endif X { X Msg(errno, "%s", m.m.create.dir); X return; X } X if (nwin->term != nwin_undef.term) X strncpy(m.m.create.screenterm, nwin->term, 19); X m.m.create.screenterm[19] = '\0'; X debug1("SendCreateMsg writing '%s'\n", m.m.create.line); X if (write(s, (char *) &m, sizeof m) != sizeof m) X Msg(errno, "write"); X} X Xvoid X#ifdef USEVARARGS X/*VARARGS1*/ X# if defined(__STDC__) XSendErrorMsg(char *fmt, ...) X# else /* __STDC__ */ XSendErrorMsg(fmt, va_alist) Xchar *fmt; Xva_dcl X# endif /* __STDC__ */ X{ /* } */ X static va_list ap; X#else /* USEVARARGS */ X/*VARARGS1*/ XSendErrorMsg(fmt, p1, p2, p3, p4, p5, p6) Xchar *fmt; Xunsigned long p1, p2, p3, p4, p5, p6; X{ X#endif /* USEVARARGS */ X register int s; X struct msg m; X X#ifdef USEVARARGS X# if defined(__STDC__) X va_start(ap, fmt); X# else /* __STDC__ */ X va_start(ap); X# endif /* __STDC__ */ X (void) vsprintf(m.m.message, fmt, ap); X va_end(ap); X#else /* USEVARARGS */ X sprintf(m.m.message, fmt, p1, p2, p3, p4, p5, p6); X#endif /* USEVARARGS */ X debug1("SendErrorMsg: '%s'\n", m.m.message); X if (display == 0) X return; X s = MakeClientSocket(1, SockName); X m.type = MSG_ERROR; X strcpy(m.m_tty, d_usertty); X debug1("SendErrorMsg(): writing to '%s'\n", SockPath); X (void) write(s, (char *) &m, sizeof m); X close(s); X sleep(2); X} X X#ifdef PASSWORD Xstatic int XCheckPasswd(pwd, pid, utty) Xint pid; Xchar *pwd, *utty; X{ X if (CheckPassword && X strcmp(crypt(pwd, (strlen(Password) > 1) ? Password : "JW"), X Password)) X { X if (*pwd) X { X# ifdef NETHACK X if (nethackflag) X Msg(0, "'%s' tries to explode in the sky, but fails. (%s)", utty, pwd); X else X# endif /* NETHACK */ X Msg(0, "Illegal reattach attempt from terminal %s, \"%s\"", utty, pwd); X } X debug1("CheckPass() wrong password kill(%d, SIG_PW_FAIL)\n", pid); X Kill(pid, SIG_PW_FAIL); X return 0; X } X debug1("CheckPass() from %d happy\n", pid); X Kill(pid, SIG_PW_OK); X return 1; X} X#endif /* PASSWORD */ X Xstatic void XExecCreate(mp) Xstruct msg *mp; X{ X struct NewWindow nwin; X char *args[MAXARGS]; X register int n; X register char **pp = args, *p = mp->m.create.line; X X nwin = nwin_undef; X for (n = mp->m.create.nargs; n > 0; --n) X { X *pp++ = p; X p += strlen(p) + 1; X } X *pp = 0; X if (*p) X nwin.aka = p; X if (*args) X nwin.args = args; X nwin.aflag = mp->m.create.aflag; X nwin.flowflag = mp->m.create.flowflag; X if (*mp->m.create.dir) X nwin.dir = mp->m.create.dir; X nwin.lflag = mp->m.create.lflag; X nwin.histheight = mp->m.create.hheight; X if (*mp->m.create.screenterm) X nwin.term = mp->m.create.screenterm; X MakeWindow(&nwin); X} X Xstatic int XCheckPid(pid) Xint pid; X{ X debug1("Checking pid %d\n", pid); X if (pid < 2) X return(-1); X if (eff_uid == real_uid) X return kill(pid, 0); X if (UserContext() == 1) X { X UserReturn(kill(pid, 0)); X } X return UserStatus(); X} X Xvoid XReceiveMsg() X{ X int left, len, i; X static struct msg m; X char *p; X int ns = ServerSocket; X struct mode Mode; X#ifdef UTMPOK X struct win *wi; X#endif X#ifdef REMOTE_DETACH X struct display *next; X#endif X X#ifdef NAMEDPIPE X debug("Ha, there was someone knocking on my fifo??\n"); X if (fcntl(ServerSocket, F_SETFL, 0) == -1) X Panic(errno, "DELAY fcntl"); X#else X struct sockaddr_un a; X X len = sizeof(a); X debug("Ha, there was someone knocking on my socket??\n"); X if ((ns = accept(ns, (struct sockaddr *) &a, &len)) < 0) X { X Msg(errno, "accept"); X return; X } X#endif /* NAMEDPIPE */ X X p = (char *) &m; X left = sizeof(m); X while (left > 0) X { X len = read(ns, p, left); X if (len < 0 && errno == EINTR) X continue; X if (len <= 0) X break; X p += len; X left -= len; X } X X#ifdef NAMEDPIPE X# ifndef BROKEN_PIPE X /* Reopen pipe to prevent EOFs at the select() call */ X close(ServerSocket); X if ((ServerSocket = secopen(SockPath, O_RDONLY | O_NDELAY, 0)) < 0) X Panic(errno, "reopen fifo %s", SockPath); X# endif X#else X close(ns); X#endif X X if (len < 0) X { X Msg(errno, "read"); X return; X } X if (left > 0) X { X if (left != sizeof(m)) X Msg(0, "Message %d of %d bytes too small", left, sizeof(m)); X else X debug("No data on socket.\n"); X return; X } X debug2("*** RecMsg: type %d tty %s\n", m.type, m.m_tty); X for (display = displays; display; display = display->_d_next) X if (strcmp(d_usertty, m.m_tty) == 0) X break; X debug2("display: %s display %sfound\n", m.m_tty, display ? "" : "not "); X if (!display) X { X struct win *w; X X for (w = windows; w; w = w->w_next) X if (!strcmp(m.m_tty, w->w_tty)) X { X display = w->w_display; X debug2("but window %s %sfound.\n", m.m_tty, display ? "" : "deatached (ignoring) "); X break; X } X } X X /* Remove the status to prevent garbage on the screen */ X if (display && d_status) X RemoveStatus(); X X switch (m.type) X { X case MSG_WINCH: X if (display) X CheckScreenSize(1); /* Change fore */ X break; X case MSG_CREATE: X if (display) X ExecCreate(&m); X break; X case MSG_CONT: X if (display && d_userpid != 0 && kill(d_userpid, 0) == 0) X break; /* Intruder Alert */ X debug2("RecMsg: apid=%d,was %d\n", m.m.attach.apid, display ? d_userpid : 0); X /* FALLTHROUGH */ X case MSG_ATTACH: X if (CheckPid(m.m.attach.apid)) X { X debug1("Attach attempt with bad pid(%d)\n", m.m.attach.apid); X Msg(0, "Attach attempt with bad pid(%d) !", m.m.attach.apid); X break; X } X if ((i = secopen(m.m_tty, O_RDWR | O_NDELAY, 0)) < 0) X { X debug1("ALERT: Cannot open %s!\n", m.m_tty); X#ifdef NETHACK X if (nethackflag) X Msg(errno, X "You can't open (%s). Perhaps there's a Monster behind it", X m.m_tty); X else X#endif X Msg(errno, "Attach: Could not open %s", m.m_tty); X Kill(m.m.attach.apid, SIG_BYE); X break; X } X#ifdef PASSWORD X if (!CheckPasswd(m.m.attach.password, m.m.attach.apid, m.m_tty)) X { X debug3("RcvMsg:Checkpass(%s,%d,%s) failed\n", X m.m.attach.password, m.m.attach.apid, m.m_tty); X close(i); X break; X } X#else X# ifdef MULTIUSER X Kill(m.m.attach.apid, SIGCONT); X# endif X#endif /* PASSWORD */ X if (display) X { X debug("RecMsg: hey, why you disturb, we are not detached. hangup!\n"); X close(i); X Kill(m.m.attach.apid, SIG_BYE); X Msg(0, "Attach msg ignored: We are not detached."); X break; X } X X#ifdef MULTIUSER X if (strcmp(m.m.attach.auser, LoginName)) X if (*FindUserPtr(m.m.attach.auser) == 0) X { X write(i, "Access to session denied.\n", 26); X close(i); X Kill(m.m.attach.apid, SIG_BYE); X Msg(0, "Attach: access denied for user %s", m.m.attach.auser); X break; X } X#endif X X errno = 0; X debug2("RecMsg: apid %d is o.k. and we just opened '%s'\n", m.m.attach.apid, m.m_tty); X /* turn off iflag on a multi-attach... */ X if (iflag && displays) X { X iflag = 0; X display = displays; X#if defined(TERMIO) || defined(POSIX) X d_NewMode.tio.c_cc[VINTR] = VDISABLE; X d_NewMode.tio.c_lflag &= ~ISIG; X#else /* TERMIO || POSIX */ X d_NewMode.m_tchars.t_intrc = -1; X#endif /* TERMIO || POSIX */ X SetTTY(d_userfd, &d_NewMode); X } X X /* create new display */ X GetTTY(i, &Mode); X if (MakeDisplay(m.m.attach.auser, m.m_tty, m.m.attach.envterm, i, m.m.attach.apid, &Mode) == 0) X { X write(i, "Could not make display.\n", 24); X close(i); X Msg(errno, "Attach: could not make display for user %s", m.m.attach.auser); X Kill(m.m.attach.apid, SIG_BYE); X break; X } X#ifdef ultrix X brktty(d_userfd); /* for some strange reason this must be done */ X#endif X#if defined(pyr) || defined(xelos) || defined(sequent) X /* X * Kludge for systems with braindamaged termcap routines, X * which evaluate $TERMCAP, regardless weather it describes X * the correct terminal type or not. X */ X debug("unsetenv(TERMCAP) in case of a different terminal"); X unsetenv("TERMCAP"); X#endif X X /* X * We reboot our Terminal Emulator. Forget all we knew about X * the old terminal, reread the termcap entries in .screenrc X * (and nothing more from .screenrc is read. Mainly because X * I did not check, weather a full reinit is save. jw) X * and /etc/screenrc, and initialise anew. X */ X if (extra_outcap) X free(extra_outcap); X if (extra_incap) X free(extra_incap); X extra_incap = extra_outcap = 0; X debug2("Message says size (%dx%d)\n", m.m.attach.columns, m.m.attach.lines); X#ifdef ETCSCREENRC X# ifdef ALLOW_SYSSCREENRC X if ((p = getenv("SYSSCREENRC"))) X StartRc(p); X else X# endif X StartRc(ETCSCREENRC); X#endif X StartRc(RcFileName); X if (InitTermcap(m.m.attach.columns, m.m.attach.lines)) X { X FreeDisplay(); X Kill(m.m.attach.apid, SIG_BYE); X break; X } X InitTerm(m.m.attach.adaptflag); X if (displays->_d_next == 0) X (void) chsock(); X signal(SIGHUP, SigHup); X#ifdef UTMPOK X /* X * we set the Utmp slots again, if we were detached normally X * and if we were detached by ^Z. X */ X RemoveLoginSlot(); X if (displays->_d_next == 0) X for (wi = windows; wi; wi = wi->w_next) X if (wi->w_slot != (slot_t) -1) X SetUtmp(wi); X#endif X SetMode(&d_OldMode, &d_NewMode); X SetTTY(d_userfd, &d_NewMode); X X d_fore = NULL; X if (d_user->u_detachwin >= 0) X fore = wtab[d_user->u_detachwin]; X if (!fore || fore->w_display X#ifdef MULTIUSER X || AclCheckPermWin(d_user, ACL_WRITE, fore) X#endif X ) X { X /* try to get another window */ X#ifdef MULTIUSER X for (wi = windows; wi; wi = wi->w_next) X if (!wi->w_display && !AclCheckPermWin(d_user, ACL_WRITE, fore)) X break; X if (!wi) X for (wi = windows; wi; wi = wi->w_next) X if (!wi->w_display && !AclCheckPermWin(d_user, ACL_READ, fore)) X break; X if (!wi) X#endif X for (wi = windows; wi; wi = wi->w_next) X if (!wi->w_display) X break; X fore = wi; X } X if (fore) X SetForeWindow(fore); X Activate(0); X if (!d_fore) X ShowWindows(); X if (displays->_d_next == 0 && console_window) X { X if (TtyGrabConsole(console_window->w_ptyfd, 1, "reattach") == 0) X Msg(0, "console %s is on window %d", HostName, console_window->w_number); X } X debug("activated...\n"); X break; X case MSG_ERROR: X Msg(0, "%s", m.m.message); X break; X case MSG_HANGUP: X SigHup(SIGARG); X break; X#ifdef REMOTE_DETACH X case MSG_DETACH: X# ifdef POW_DETACH X case MSG_POW_DETACH: X# endif /* POW_DETACH */ X for (display = displays; display; display = next) X { X next = display->_d_next; X# ifdef POW_DETACH X if (m.type == MSG_POW_DETACH) X Detach(D_REMOTE_POWER); X else X# endif /* POW_DETACH */ X if (m.type == MSG_DETACH) X Detach(D_REMOTE); X } X break; X#endif X default: X Msg(0, "Invalid message (type %d).", m.type); X } X} X X#if defined(_SEQUENT_) && !defined(NAMEDPIPE) X#undef connect X X/* X * sequent_ptx socket emulation must have mode 000 on the socket! X */ Xstatic int Xsconnect(s, sapp, len) Xint s, len; Xstruct sockaddr *sapp; X{ X register struct sockaddr_un *sap; X struct stat st; X int x; X X sap = (struct sockaddr_un *)sapp; X if (stat(sap->sun_path, &st)) X return -1; X chmod(sap->sun_path, 0); X x = connect(s, (struct sockaddr *) sap, len); X chmod(sap->sun_path, st.st_mode); X return x; X} X#endif X Xint Xchsock() X{ X int r, euid = geteuid(); X if (euid != real_uid) X { X if (UserContext() <= 0) X return UserStatus(); X } X r = chmod(SockPath, SOCKMODE); X if (euid != real_uid) X UserReturn(r); X return r; X} X END_OF_FILE if test 29765 -ne `wc -c <'socket.c'`; then echo shar: \"'socket.c'\" unpacked with wrong size! fi # end of 'socket.c' fi if test -f 'tty.c.dist' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tty.c.dist'\" else echo shar: Extracting \"'tty.c.dist'\" \(22169 characters\) sed "s/^X//" >'tty.c.dist' <<'END_OF_FILE' X/* Copyright (c) 1993 X * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) X * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) X * Copyright (c) 1987 Oliver Laumann X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 2, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program (see the file COPYING); if not, write to the X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X * X **************************************************************** X */ X X/* X * NOTICE: tty.c is automatically generated from tty.sh X * Do not change anything here. If you then change tty.sh. X */ X X#include "rcs.h" XRCS_ID("$Id: tty.sh,v 1.7 1993/08/05 14:24:09 mlschroe Exp $ FAU") X X#include X#include X#include X#include X#if !defined(sun) || defined(SUNOS3) X# include /* collosions with termios.h */ X#else X# ifndef TIOCEXCL X# include /* needed for TIOCEXCL */ X# endif X#endif X X#ifdef ISC X# include X# include X# include X#endif X X#include "config.h" X#include "screen.h" X#include "extern.h" X Xextern struct display *display, *displays; Xextern int iflag; X X Xstatic sig_t XSigAlrmDummy(SIGDEFARG) X{ X debug("SigAlrmDummy()\n"); X#ifndef SIGVOID X return (sig_t)0; X#endif X} X X/* X * Carefully open a charcter device. Not used to open ttys. X */ X Xint XOpenTTY(line) Xchar *line; X{ X int f; X sig_t (*sigalrm)__P(SIGPROTOARG); X X sigalrm = signal(SIGALRM, SigAlrmDummy); X alarm(2); X /* this open only succeeds, if real uid is allowed */ X if ((f = secopen(line, O_RDWR | O_NDELAY, 0)) == -1) X { X Msg(errno, "Cannot open line '%s' for R/W", line); X alarm(0); X signal(SIGALRM, sigalrm); X return -1; X } X#ifdef I_POP X debug("OpenTTY I_POP\n"); X while (ioctl(f, I_POP, (char *)0) >= 0) X ; X#endif X /* X * We come here exclusively. This is to stop all kermit and cu type things X * accessing the same tty line. X * Perhaps we should better create a lock in some /usr/spool/locks directory? X */ X#ifdef TIOCEXCL X errno = 0; X ioctl(f, TIOCEXCL, (char *) 0); X debug3("%d %d %d\n", getuid(), geteuid(), getpid()); X debug2("%s TIOCEXCL errno %d\n", line, errno); X#endif /* TIOCEXCL */ X /* X * We create a sane tty mode. We do not copy things from the display tty X */ X#if WE_REALLY_WANT_TO_COPY_THE_TTY_MODE X if (display) X { X debug1("OpenTTY: using mode of display for %s\n", line); X SetTTY(f, &d_NewMode); X#ifdef DEBUG X DebugTTY(&d_NewMode); X#endif X } X else X#endif X { X struct mode Mode; X X InitTTY(&Mode, TTY_FLAG_PLAIN); X#ifdef DEBUG X DebugTTY(&Mode); X#endif X SetTTY(f, &Mode); X } X brktty(f); X alarm(0); X signal(SIGALRM, sigalrm); X debug2("'%s' CONNECT fd=%d.\n", line, f); X return f; X} X X X/* X * Tty mode handling X */ X X#if defined(TERMIO) || defined(POSIX) Xint intrc, origintrc = VDISABLE; /* display? */ X#else Xint intrc, origintrc = -1; /* display? */ X#endif Xstatic startc, stopc; /* display? */ X X Xvoid XInitTTY(m, ttyflag) Xstruct mode *m; Xint ttyflag; X{ X bzero((char *)m, sizeof(*m)); X#ifdef POSIX X /* struct termios tio X * defaults, as seen on SunOS 4.1.3 X */ X debug1("InitTTY: POSIX: termios defaults a la SunOS 4.1.3 (%d)\n", ttyflag); X#if defined(BRKINT) X m->tio.c_iflag |= BRKINT; X#endif /* BRKINT */ X#if defined(IGNPAR) X m->tio.c_iflag |= IGNPAR; X#endif /* IGNPAR */ X#if defined(ISTRIP) X m->tio.c_iflag |= ISTRIP; X#endif /* ISTRIP */ X#if defined(IXON) X m->tio.c_iflag |= IXON; X#endif /* IXON */ X#if defined(IMAXBEL) X m->tio.c_iflag |= IMAXBEL; X#endif /* IMAXBEL */ X X if (!ttyflag) /* may not even be good for ptys.. */ X { X#if defined(ICRNL) X m->tio.c_iflag |= ICRNL; X#endif /* ICRNL */ X#if defined(ONLCR) X m->tio.c_oflag |= ONLCR; X#endif /* ONLCR */ X#if defined(TAB3) X m->tio.c_oflag |= TAB3; X#endif /* TAB3 */ X#if defined(PARENB) X m->tio.c_cflag |= PARENB; X#endif /* PARENB */ X } X X#if defined(OPOST) X m->tio.c_oflag |= OPOST; X#endif /* OPOST */ X X#if defined(B9600) X m->tio.c_cflag |= B9600; X#endif /* B9600 */ X#if defined(CS8) X m->tio.c_cflag |= CS8; X#endif /* CS8 */ X#if defined(CREAD) X m->tio.c_cflag |= CREAD; X#endif /* CREAD */ X#if defined(IBSHIFT) && defined(B9600) X m->tio.c_cflag |= B9600 << IBSHIFT; X#endif /* IBSHIFT) && defined(B9600 */ X/* IF{CLOCAL} m->tio.c_cflag |= CLOCAL; */ X X#if defined(ECHOCTL) X m->tio.c_lflag |= ECHOCTL; X#endif /* ECHOCTL */ X#if defined(ECHOKE) X m->tio.c_lflag |= ECHOKE; X#endif /* ECHOKE */ X X if (!ttyflag) X { X#if defined(ISIG) X m->tio.c_lflag |= ISIG; X#endif /* ISIG */ X#if defined(ICANON) X m->tio.c_lflag |= ICANON; X#endif /* ICANON */ X#if defined(ECHO) X m->tio.c_lflag |= ECHO; X#endif /* ECHO */ X } X#if defined(ECHOE) X m->tio.c_lflag |= ECHOE; X#endif /* ECHOE */ X#if defined(ECHOK) X m->tio.c_lflag |= ECHOK; X#endif /* ECHOK */ X#if defined(IEXTEN) X m->tio.c_lflag |= IEXTEN; X#endif /* IEXTEN */ X X#if defined(VINTR) && VINTR < MAXCC X m->tio.c_cc[VINTR] = Ctrl('C'); X#endif /* VINTR */ X#if defined(VQUIT) && VQUIT < MAXCC X m->tio.c_cc[VQUIT] = Ctrl('\\'); X#endif /* VQUIT */ X#if defined(VERASE) && VERASE < MAXCC X m->tio.c_cc[VERASE] = 0x7f; /* DEL */ X#endif /* VERASE */ X#if defined(VKILL) && VKILL < MAXCC X m->tio.c_cc[VKILL] = Ctrl('H'); X#endif /* VKILL */ X#if defined(VEOF) && VEOF < MAXCC X m->tio.c_cc[VEOF] = Ctrl('D'); X#endif /* VEOF */ X#if defined(VEOL) && VEOL < MAXCC X m->tio.c_cc[VEOL] = 0000; X#endif /* VEOL */ X#if defined(VEOL2) && VEOL2 < MAXCC X m->tio.c_cc[VEOL2] = 0000; X#endif /* VEOL2 */ X#if defined(VSWTCH) && VSWTCH < MAXCC X m->tio.c_cc[VSWTCH] = 0000; X#endif /* VSWTCH */ X#if defined(VSTART) && VSTART < MAXCC X m->tio.c_cc[VSTART] = Ctrl('Q'); X#endif /* VSTART */ X#if defined(VSTOP) && VSTOP < MAXCC X m->tio.c_cc[VSTOP] = Ctrl('S'); X#endif /* VSTOP */ X#if defined(VSUSP) && VSUSP < MAXCC X m->tio.c_cc[VSUSP] = Ctrl('Z'); X#endif /* VSUSP */ X#if defined(VDSUSP) && VDSUSP < MAXCC X m->tio.c_cc[VDSUSP] = Ctrl('Y'); X#endif /* VDSUSP */ X#if defined(VREPRINT) && VREPRINT < MAXCC X m->tio.c_cc[VREPRINT] = Ctrl('R'); X#endif /* VREPRINT */ X#if defined(VDISCARD) && VDISCARD < MAXCC X m->tio.c_cc[VDISCARD] = Ctrl('O'); X#endif /* VDISCARD */ X#if defined(VWERASE) && VWERASE < MAXCC X m->tio.c_cc[VWERASE] = Ctrl('W'); X#endif /* VWERASE */ X#if defined(VLNEXT) && VLNEXT < MAXCC X m->tio.c_cc[VLNEXT] = Ctrl('V'); X#endif /* VLNEXT */ X#if defined(VSTATUS) && VSTATUS < MAXCC X m->tio.c_cc[VSTATUS] = Ctrl('T'); X#endif /* VSTATUS */ X X# ifdef hpux X m->m_ltchars.t_suspc = Ctrl('Z'); X m->m_ltchars.t_dsuspc = Ctrl('Y'); X m->m_ltchars.t_rprntc = Ctrl('R'); X m->m_ltchars.t_flushc = Ctrl('O'); X m->m_ltchars.t_werasc = Ctrl('W'); X m->m_ltchars.t_lnextc = Ctrl('V'); X# endif /* hpux */ X X#else /* POSIX */ X X# ifdef TERMIO X debug1("InitTTY: nonPOSIX, struct termio a la Motorola SYSV68 (%d)\n", ttyflag); X /* struct termio tio X * defaults, as seen on Mototola SYSV68: X * input: 7bit, CR->NL, ^S/^Q flow control X * output: POSTprocessing: NL->NL-CR, Tabs to spaces X * control: 9600baud, 8bit CSIZE, enable input X * local: enable signals, erase/kill processing, echo on. X */ X#if defined(ISTRIP) X m->tio.c_iflag |= ISTRIP; X#endif /* ISTRIP */ X#if defined(IXON) X m->tio.c_iflag |= IXON; X#endif /* IXON */ X X#if defined(OPOST) X m->tio.c_oflag |= OPOST; X#endif /* OPOST */ X X if (!ttyflag) /* may not even be good for ptys.. */ X { X#if defined(ICRNL) X m->tio.c_iflag |= ICRNL; X#endif /* ICRNL */ X#if defined(ONLCR) X m->tio.c_oflag |= ONLCR; X#endif /* ONLCR */ X#if defined(TAB3) X m->tio.c_oflag |= TAB3; X#endif /* TAB3 */ X } X X#if defined(B9600) X m->tio.c_cflag = B9600; X#endif /* B9600 */ X#if defined(CS8) X m->tio.c_cflag |= CS8; X#endif /* CS8 */ X#if defined(CREAD) X m->tio.c_cflag |= CREAD; X#endif /* CREAD */ X X if (!ttyflag) X { X#if defined(ISIG) X m->tio.c_lflag |= ISIG; X#endif /* ISIG */ X#if defined(ICANON) X m->tio.c_lflag |= ICANON; X#endif /* ICANON */ X#if defined(ECHO) X m->tio.c_lflag |= ECHO; X#endif /* ECHO */ X } X#if defined(ECHOE) X m->tio.c_lflag |= ECHOE; X#endif /* ECHOE */ X#if defined(ECHOK) X m->tio.c_lflag |= ECHOK; X#endif /* ECHOK */ X X#if defined(VINTR) && VINTR < MAXCC X m->tio.c_cc[VINTR] = Ctrl('C'); X#endif /* VINTR */ X#if defined(VQUIT) && VQUIT < MAXCC X m->tio.c_cc[VQUIT] = Ctrl('\\'); X#endif /* VQUIT */ X#if defined(VERASE) && VERASE < MAXCC X m->tio.c_cc[VERASE] = 0177; /* DEL */ X#endif /* VERASE */ X#if defined(VKILL) && VKILL < MAXCC X m->tio.c_cc[VKILL] = Ctrl('H'); X#endif /* VKILL */ X#if defined(VEOF) && VEOF < MAXCC X m->tio.c_cc[VEOF] = Ctrl('D'); X#endif /* VEOF */ X#if defined(VEOL) && VEOL < MAXCC X m->tio.c_cc[VEOL] = 0377; X#endif /* VEOL */ X#if defined(VEOL2) && VEOL2 < MAXCC X m->tio.c_cc[VEOL2] = 0377; X#endif /* VEOL2 */ X#if defined(VSWTCH) && VSWTCH < MAXCC X m->tio.c_cc[VSWTCH] = 0000; X#endif /* VSWTCH */ X# else /* TERMIO */ X debug1("InitTTY: BSD: defaults a la SunOS 4.1.3 (%d)\n", ttyflag); X m->m_ttyb.sg_ispeed = B9600; X m->m_ttyb.sg_ospeed = B9600; X m->m_ttyb.sg_erase = 0177; /*DEL */ X m->m_ttyb.sg_kill = Ctrl('H'); X if (!ttyflag) X m->m_ttyb.sg_flags = CRMOD | ECHO X#if defined(ANYP) X | ANYP X#endif /* ANYP */ X ; X else X m->m_ttyb.sg_flags = CBREAK X#if defined(ANYP) X | ANYP X#endif /* ANYP */ X ; X X m->m_tchars.t_intrc = Ctrl('C'); X m->m_tchars.t_quitc = Ctrl('\\'); X m->m_tchars.t_startc = Ctrl('Q'); X m->m_tchars.t_stopc = Ctrl('S'); X m->m_tchars.t_eofc = Ctrl('D'); X m->m_tchars.t_brkc = -1; X X m->m_ltchars.t_suspc = Ctrl('Z'); X m->m_ltchars.t_dsuspc = Ctrl('Y'); X m->m_ltchars.t_rprntc = Ctrl('R'); X m->m_ltchars.t_flushc = Ctrl('O'); X m->m_ltchars.t_werasc = Ctrl('W'); X m->m_ltchars.t_lnextc = Ctrl('V'); X X#if defined(NTTYDISC) X m->m_ldisc = NTTYDISC; X#endif /* NTTYDISC */ X X m->m_lmode = 0 X#if defined(LDECCTQ) X | LDECCTQ X#endif /* LDECCTQ */ X#if defined(LCTLECH) X | LCTLECH X#endif /* LCTLECH */ X#if defined(LPASS8) X | LPASS8 X#endif /* LPASS8 */ X#if defined(LCRTKIL) X | LCRTKIL X#endif /* LCRTKIL */ X#if defined(LCRTERA) X | LCRTERA X#endif /* LCRTERA */ X#if defined(LCRTBS) X | LCRTBS X#endif /* LCRTBS */ X; X# endif /* TERMIO */ X#endif /* POSIX */ X} X Xvoid XSetTTY(fd, mp) Xint fd; Xstruct mode *mp; X{ X errno = 0; X#ifdef POSIX X tcsetattr(fd, TCSADRAIN, &mp->tio); X# ifdef hpux X ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); X# endif X#else X# ifdef TERMIO X ioctl(fd, TCSETAW, (char *)&mp->tio); X# else X /* ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); */ X ioctl(fd, TIOCSETC, (char *)&mp->m_tchars); X ioctl(fd, TIOCLSET, (char *)&mp->m_lmode); X ioctl(fd, TIOCSETD, (char *)&mp->m_ldisc); X ioctl(fd, TIOCSETP, (char *)&mp->m_ttyb); X ioctl(fd, TIOCSLTC, (char *)&mp->m_ltchars); /* moved here for apollo. jw */ X# endif X#endif X if (errno) X Msg(errno, "SetTTY (fd %d): ioctl failed", fd); X} X Xvoid XGetTTY(fd, mp) Xint fd; Xstruct mode *mp; X{ X errno = 0; X#ifdef POSIX X tcgetattr(fd, &mp->tio); X# ifdef hpux X ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); X# endif X#else X# ifdef TERMIO X ioctl(fd, TCGETA, (char *)&mp->tio); X# else X ioctl(fd, TIOCGETP, (char *)&mp->m_ttyb); X ioctl(fd, TIOCGETC, (char *)&mp->m_tchars); X ioctl(fd, TIOCGLTC, (char *)&mp->m_ltchars); X ioctl(fd, TIOCLGET, (char *)&mp->m_lmode); X ioctl(fd, TIOCGETD, (char *)&mp->m_ldisc); X# endif X#endif X if (errno) X Msg(errno, "GetTTY (fd %d): ioctl failed", fd); X} X Xvoid XSetMode(op, np) Xstruct mode *op, *np; X{ X *np = *op; X X#if defined(TERMIO) || defined(POSIX) X np->tio.c_iflag &= ~ICRNL; X# ifdef ONLCR X np->tio.c_oflag &= ~ONLCR; X# endif X np->tio.c_lflag &= ~(ICANON | ECHO); X#ifdef OSF1 X /* X * From Andrew Myers (andru@tonic.lcs.mit.edu) X */ X np->tio.c_lflag &= ~IEXTEN; X#endif X X /* X * Unfortunately, the master process never will get SIGINT if the real X * terminal is different from the one on which it was originaly started X * (process group membership has not been restored or the new tty could not X * be made controlling again). In my solution, it is the attacher who X * receives SIGINT (because it is always correctly associated with the real X * tty) and forwards it to the master [kill(MasterPid, SIGINT)]. X * Marc Boucher (marc@CAM.ORG) X */ X if (iflag) X np->tio.c_lflag |= ISIG; X else X np->tio.c_lflag &= ~ISIG; X /* X * careful, careful catche monkey.. X * never set VMIN and VTIME to zero, if you want blocking io. X */ X np->tio.c_cc[VMIN] = 1; X np->tio.c_cc[VTIME] = 0; X startc = op->tio.c_cc[VSTART]; X stopc = op->tio.c_cc[VSTOP]; X if (iflag) X origintrc = intrc = op->tio.c_cc[VINTR]; X else X { X origintrc = op->tio.c_cc[VINTR]; X intrc = np->tio.c_cc[VINTR] = VDISABLE; X } X np->tio.c_cc[VQUIT] = VDISABLE; X if (d_flow == 0) X { X np->tio.c_cc[VINTR] = VDISABLE; X np->tio.c_cc[VSTART] = VDISABLE; X np->tio.c_cc[VSTOP] = VDISABLE; X np->tio.c_iflag &= ~IXON; X } X#if defined(VDISCARD) && VDISCARD < MAXCC X np->tio.c_cc[VDISCARD] = VDISABLE; X#endif /* VDISCARD */ X#if defined(VSUSP) && VSUSP < MAXCC X np->tio.c_cc[VSUSP] = VDISABLE; X#endif /* VSUSP */ X# ifdef hpux X np->m_ltchars.t_suspc = VDISABLE; X np->m_ltchars.t_dsuspc = VDISABLE; X np->m_ltchars.t_rprntc = VDISABLE; X np->m_ltchars.t_flushc = VDISABLE; X np->m_ltchars.t_werasc = VDISABLE; X np->m_ltchars.t_lnextc = VDISABLE; X# else /* hpux */ X#if defined(VDSUSP) && VDSUSP < MAXCC X np->tio.c_cc[VDSUSP] = VDISABLE; X#endif /* VDSUSP */ X# endif /* hpux */ X#else /* TERMIO || POSIX */ X startc = op->m_tchars.t_startc; X stopc = op->m_tchars.t_stopc; X if (iflag) X origintrc = intrc = op->m_tchars.t_intrc; X else X { X origintrc = op->m_tchars.t_intrc; X intrc = np->m_tchars.t_intrc = -1; X } X np->m_ttyb.sg_flags &= ~(CRMOD | ECHO); X np->m_ttyb.sg_flags |= CBREAK; X np->m_tchars.t_quitc = -1; X if (d_flow == 0) X { X np->m_tchars.t_intrc = -1; X np->m_tchars.t_startc = -1; X np->m_tchars.t_stopc = -1; X } X np->m_ltchars.t_suspc = -1; X np->m_ltchars.t_dsuspc = -1; X np->m_ltchars.t_flushc = -1; X np->m_ltchars.t_lnextc = -1; X#endif /* defined(TERMIO) || defined(POSIX) */ X} X Xvoid XSetFlow(on) Xint on; X{ X ASSERT(display); X if (d_flow == on) X return; X#if defined(TERMIO) || defined(POSIX) X if (on) X { X d_NewMode.tio.c_cc[VINTR] = intrc; X d_NewMode.tio.c_cc[VSTART] = startc; X d_NewMode.tio.c_cc[VSTOP] = stopc; X d_NewMode.tio.c_iflag |= IXON; X } X else X { X d_NewMode.tio.c_cc[VINTR] = VDISABLE; X d_NewMode.tio.c_cc[VSTART] = VDISABLE; X d_NewMode.tio.c_cc[VSTOP] = VDISABLE; X d_NewMode.tio.c_iflag &= ~IXON; X } X# ifdef POSIX X if (tcsetattr(d_userfd, TCSANOW, &d_NewMode.tio)) X# else X if (ioctl(d_userfd, TCSETAW, (char *)&d_NewMode.tio) != 0) X# endif X debug1("SetFlow: ioctl errno %d\n", errno); X#else /* POSIX || TERMIO */ X if (on) X { X d_NewMode.m_tchars.t_intrc = intrc; X d_NewMode.m_tchars.t_startc = startc; X d_NewMode.m_tchars.t_stopc = stopc; X } X else X { X d_NewMode.m_tchars.t_intrc = -1; X d_NewMode.m_tchars.t_startc = -1; X d_NewMode.m_tchars.t_stopc = -1; X } X if (ioctl(d_userfd, TIOCSETC, (char *)&d_NewMode.m_tchars) != 0) X debug1("SetFlow: ioctl errno %d\n", errno); X#endif /* POSIX || TERMIO */ X d_flow = on; X} X X X/* X * Job control handling X */ X X/*ARGSUSED*/ Xvoid Xbrktty(fd) Xint fd; X{ X#ifdef POSIX X setsid(); /* will break terminal affiliation */ X# ifdef BSD X ioctl(fd, TIOCSCTTY, (char *)0); X# endif /* BSD */ X#else /* POSIX */ X# ifdef SYSV X setpgrp(); /* will break terminal affiliation */ X# else /* SYSV */ X# ifdef BSDJOBS X int devtty; X X if ((devtty = open("/dev/tty", O_RDWR | O_NDELAY)) >= 0) X { X if (ioctl(devtty, TIOCNOTTY, (char *)0)) X debug2("brktty: ioctl(devtty=%d, TIOCNOTTY, 0) = %d\n", devtty, errno); X close(devtty); X } X# endif /* BSDJOBS */ X# endif /* SYSV */ X#endif /* POSIX */ X} X Xint Xfgtty(fd) Xint fd; X{ X#ifdef BSDJOBS X int mypid; X X mypid = getpid(); X X# if defined(BSDI) || defined(__386BSD__) || defined(__osf__) X setsid(); /* should be already done */ X ioctl(fd, TIOCSCTTY, (char *)0); X# endif /* BSDI || __386BSD__ */ X X# ifdef POSIX X if (tcsetpgrp(fd, mypid)) X { X debug1("fgtty: tcsetpgrp: %d\n", errno); X return -1; X } X# else /* POSIX */ X if (ioctl(fd, TIOCSPGRP, (char *)&mypid) != 0) X debug1("fgtty: TIOSETPGRP: %d\n", errno); X# ifndef SYSV /* Already done in brktty():setpgrp() */ X if (setpgrp(fd, mypid)) X debug1("fgtty: setpgrp: %d\n", errno); X# endif X# endif /* POSIX */ X#endif /* BSDJOBS */ X return 0; X} X X X/* X * Send a break for n * 0.25 seconds. Tty must be PLAIN. X */ X Xvoid SendBreak(wp, n, closeopen) Xstruct win *wp; Xint n, closeopen; X{ X if ((wp->w_t.flags & TTY_FLAG_PLAIN) == 0) X return; X X debug3("break(%d, %d) fd %d\n", n, closeopen, wp->w_ptyfd); X#ifdef POSIX X (void) tcflush(wp->w_ptyfd, TCIOFLUSH); X#else X# ifdef TIOCFLUSH X (void) ioctl(wp->w_ptyfd, TIOCFLUSH, (char *)0); X# endif /* TIOCFLUSH */ X#endif /* POSIX */ X if (closeopen) X { X close(wp->w_ptyfd); X sleep((n + 3) / 4); X if ((wp->w_ptyfd = OpenTTY(wp->w_tty)) < 1) X { X Msg(0, "Ouch, cannot reopen line %s, please try harder", wp->w_tty); X return; X } X (void) fcntl(wp->w_ptyfd, F_SETFL, FNDELAY); X } X else X { X#ifdef POSIX X debug("tcsendbreak\n"); X if (tcsendbreak(wp->w_ptyfd, n) < 0) X { X Msg(errno, "cannot send BREAK"); X return; X } X#else X if (!n) X n++; X# ifdef TCSBRK X debug("TCSBRK\n"); X { X int i; X for (i = 0; i < n; i++) X if (ioctl(wp->w_ptyfd, TCSBRK, (char *)0) < 0) X { X Msg(errno, "Cannot send BREAK"); X return; X } X } X# else /* TCSBRK */ X# if defined(TIOCSBRK) && defined(TIOCCBRK) X debug("TIOCSBRK TIOCCBRK\n"); X if (ioctl(wp->w_ptyfd, TIOCSBRK, (char *)0) < 0) X { X Msg(errno, "Can't send BREAK"); X return; X } X sleep((n + 3) / 4); X if (ioctl(wp->w_ptyfd, TIOCCBRK, (char *)0) < 0) X { X Msg(errno, "BREAK stuck!!! -- HELP!"); X return; X } X# else /* TIOCSBRK && TIOCCBRK */ X Msg(0, "Break not simulated yet"); X return; X# endif /* TIOCSBRK && TIOCCBRK */ X# endif /* TCSBRK */ X#endif /* POSIX */ X debug(" broken\n"); X } X} X X X/* X * Console grabbing X */ X X/*ARGSUSED*/ Xint XTtyGrabConsole(fd, on, rc_name) Xint fd, on; Xchar *rc_name; X{ X#ifdef TIOCCONS X char *slave; X int sfd = -1, ret = 0; X struct display *d; X X if (!on) X { X if ((fd = OpenPTY(&slave)) < 0) X { X Msg(errno, "%s: could not open detach pty master", rc_name); X return -1; X } X if ((sfd = open(slave, O_RDWR)) < 0) X { X Msg(errno, "%s: could not open detach pty slave", rc_name); X close(fd); X return -1; X } X } X else X { X if (displays == 0) X { X Msg(0, "I need a display"); X return -1; X } X for (d = displays; d; d = d->_d_next) X if (strcmp(d->_d_usertty, "/dev/console") == 0) X break; X if (d) X { X Msg(0, "too dangerous - screen is running on /dev/console"); X return -1; X } X } X if (UserContext() == 1) X UserReturn(ioctl(fd, TIOCCONS, (char *)&on)); X ret = UserStatus(); X if (ret) X Msg(errno, "%s: ioctl TIOCCONS failed", rc_name); X if (!on) X { X close(sfd); X close(fd); X } X return ret; X#else /* TIOCCONS */ X Msg(0, "%s: no TIOCCONS on this machine", rc_name); X return -1; X#endif /* TIOCCONS */ X} X X X/* X * Write out the mode struct in a readable form X */ X X#ifdef DEBUG Xvoid XDebugTTY(m) Xstruct mode *m; X{ X int i; X X#ifdef POSIX X debug("struct termios tio:\n"); X debug1("c_iflag = %#x\n", m->tio.c_iflag); X debug1("c_oflag = %#x\n", m->tio.c_oflag); X debug1("c_cflag = %#x\n", m->tio.c_cflag); X debug1("c_lflag = %#x\n", m->tio.c_lflag); X for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++) X { X debug2("c_cc[%d] = %#x\n", i, m->tio.c_cc[i]); X } X# ifdef hpux X debug1("suspc = %#02x\n", m->m_ltchars.t_suspc); X debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc); X debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc); X debug1("flushc = %#02x\n", m->m_ltchars.t_flushc); X debug1("werasc = %#02x\n", m->m_ltchars.t_werasc); X debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc); X# endif /* hpux */ X#else /* POSIX */ X# ifdef TERMIO X debug("struct termio tio:\n"); X debug1("c_iflag = %04o\n", m->tio.c_iflag); X debug1("c_oflag = %04o\n", m->tio.c_oflag); X debug1("c_cflag = %04o\n", m->tio.c_cflag); X debug1("c_lflag = %04o\n", m->tio.c_lflag); X for (i = 0; i < sizeof(m->tio.c_cc)/sizeof(*m->tio.c_cc); i++) X { X debug2("c_cc[%d] = %04o\n", i, m->tio.c_cc[i]); X } X# else /* TERMIO */ X debug1("sg_ispeed = %d\n", m->m_ttyb.sg_ispeed); X debug1("sg_ospeed = %d\n", m->m_ttyb.sg_ospeed); X debug1("sg_erase = %#02x\n", m->m_ttyb.sg_erase); X debug1("sg_kill = %#02x\n", m->m_ttyb.sg_kill); X debug1("sg_flags = %#04x\n", (unsigned short)m->m_ttyb.sg_flags); X debug1("intrc = %#02x\n", m->m_tchars.t_intrc); X debug1("quitc = %#02x\n", m->m_tchars.t_quitc); X debug1("startc = %#02x\n", m->m_tchars.t_startc); X debug1("stopc = %#02x\n", m->m_tchars.t_stopc); X debug1("eofc = %#02x\n", m->m_tchars.t_eofc); X debug1("brkc = %#02x\n", m->m_tchars.t_brkc); X debug1("suspc = %#02x\n", m->m_ltchars.t_suspc); X debug1("dsuspc = %#02x\n", m->m_ltchars.t_dsuspc); X debug1("rprntc = %#02x\n", m->m_ltchars.t_rprntc); X debug1("flushc = %#02x\n", m->m_ltchars.t_flushc); X debug1("werasc = %#02x\n", m->m_ltchars.t_werasc); X debug1("lnextc = %#02x\n", m->m_ltchars.t_lnextc); X debug1("ldisc = %d\n", m->m_ldisc); X debug1("lmode = %#x\n", m->m_lmode); X# endif /* TERMIO */ X#endif /* POSIX */ X} X#endif /* DEBUG */ END_OF_FILE if test 22169 -ne `wc -c <'tty.c.dist'`; then echo shar: \"'tty.c.dist'\" unpacked with wrong size! fi # end of 'tty.c.dist' fi if test -f 'window.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'window.c'\" else echo shar: Extracting \"'window.c'\" \(20847 characters\) sed "s/^X//" >'window.c' <<'END_OF_FILE' X/* Copyright (c) 1993 X * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) X * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) X * Copyright (c) 1987 Oliver Laumann X * X * This program is free software; you can redistribute it and/or modify X * it under the terms of the GNU General Public License as published by X * the Free Software Foundation; either version 2, or (at your option) X * any later version. X * X * This program is distributed in the hope that it will be useful, X * but WITHOUT ANY WARRANTY; without even the implied warranty of X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the X * GNU General Public License for more details. X * X * You should have received a copy of the GNU General Public License X * along with this program (see the file COPYING); if not, write to the X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. X * X **************************************************************** X */ X X#include "rcs.h" XRCS_ID("$Id: window.c,v 1.14 1993/08/05 14:24:15 mlschroe Exp $ FAU") X X#include X#include X#include X#include X#ifndef sun X#include X#endif X X#include "config.h" X#include "screen.h" X#include "extern.h" X X#ifdef SVR4 /* for solaris 2.1 */ X# include X#endif X Xextern struct display *displays, *display; Xextern struct win *windows, *fore, *wtab[], *console_window; Xextern char *ShellArgs[]; Xextern char *ShellProg; Xextern char screenterm[]; Xextern char HostName[]; Xextern int default_monitor, TtyMode; Xextern struct LayFuncs WinLf; Xextern int real_uid, real_gid; Xextern char Termcap[]; Xextern char **NewEnv; X X#if defined(TIOCSWINSZ) || defined(TIOCGWINSZ) Xextern struct winsize glwz; X#endif X X Xstatic int OpenDevice __P((char *, int, int *, char **)); Xstatic int ForkWindow __P((char **, char *, char *, char *, struct win *)); Xstatic void execvpe __P((char *, char **, char **)); X X Xchar DefaultShell[] = "/bin/sh"; Xstatic char DefaultPath[] = ":/usr/ucb:/bin:/usr/bin"; X X Xstruct NewWindow nwin_undef = X{ X -1, (char *)0, (char **)0, (char *)0, (char *)0, -1, -1, X -1, -1, -1 X}; X Xstruct NewWindow nwin_default = X{ X 0, 0, ShellArgs, 0, screenterm, 0, 1*FLOW_NOW, X LOGINDEFAULT, DEFAULTHISTHEIGHT, -1 X}; X Xstruct NewWindow nwin_options; X Xvoid Xnwin_compose(def, new, res) Xstruct NewWindow *def, *new, *res; X{ X res->StartAt = new->StartAt != nwin_undef.StartAt ? new->StartAt : def->StartAt; X res->aka = new->aka != nwin_undef.aka ? new->aka : def->aka; X res->args = new->args != nwin_undef.args ? new->args : def->args; X res->dir = new->dir != nwin_undef.dir ? new->dir : def->dir; X res->term = new->term != nwin_undef.term ? new->term : def->term; X res->aflag = new->aflag != nwin_undef.aflag ? new->aflag : def->aflag; X res->flowflag = new->flowflag != nwin_undef.flowflag ? new->flowflag : def->flowflag; X res->lflag = new->lflag != nwin_undef.lflag ? new->lflag : def->lflag; X res->histheight = new->histheight != nwin_undef.histheight ? new->histheight : def->histheight; X res->monitor = new->monitor != nwin_undef.monitor ? new->monitor : def->monitor; X} X Xint XMakeWindow(newwin) Xstruct NewWindow *newwin; X{ X register struct win **pp, *p; X register int n; X int f = -1; X struct NewWindow nwin; X int ttyflag; X char *TtyName; X X debug1("NewWindow: StartAt %d\n", newwin->StartAt); X debug1("NewWindow: aka %s\n", newwin->aka?newwin->aka:"NULL"); X debug1("NewWindow: dir %s\n", newwin->dir?newwin->dir:"NULL"); X debug1("NewWindow: term %s\n", newwin->term?newwin->term:"NULL"); X nwin_compose(&nwin_default, newwin, &nwin); X debug1("NWin: aka %s\n", nwin.aka ? nwin.aka : "NULL"); X pp = wtab + nwin.StartAt; X X do X { X if (*pp == 0) X break; X if (++pp == wtab + MAXWIN) X pp = wtab; X } X while (pp != wtab + nwin.StartAt); X if (*pp) X { X Msg(0, "No more windows."); X return -1; X } X X#if defined(USRLIMIT) && defined(UTMPOK) X /* X * Count current number of users, if logging windows in. X */ X if (nwin.lflag && CountUsers() >= USRLIMIT) X { X Msg(0, "User limit reached. Window will not be logged in."); X nwin.lflag = 0; X } X#endif X n = pp - wtab; X debug1("Makewin creating %d\n", n); X X if ((f = OpenDevice(nwin.args[0], nwin.lflag, &ttyflag, &TtyName)) < 0) X return -1; X X if ((p = (struct win *) malloc(sizeof(struct win))) == 0) X { X close(f); X Msg(0, strnomem); X return -1; X } X bzero((char *) p, (int) sizeof(struct win)); /* looks like a calloc above */ X#ifdef MULTIUSER X if (NewWindowAcl(p)) X { X free(p); X close(f); X Msg(0, strnomem); X return -1; X } X#endif X p->w_wlock = WLOCK_AUTO; X p->w_dupto = -1; X p->w_winlay.l_next = 0; X p->w_winlay.l_layfn = &WinLf; X p->w_winlay.l_data = (char *)p; X p->w_lay = &p->w_winlay; X p->w_display = display; X if (display) X p->w_wlockuser = d_user; X p->w_number = n; X p->w_ptyfd = f; X p->w_aflag = nwin.aflag; X p->w_flow = nwin.flowflag | ((nwin.flowflag & FLOW_AUTOFLAG) ? (FLOW_AUTO|FLOW_NOW) : FLOW_AUTO); X if (!nwin.aka) X nwin.aka = Filename(nwin.args[0]); X strncpy(p->w_akabuf, nwin.aka, MAXSTR - 1); X if ((nwin.aka = rindex(p->w_akabuf, '|')) != NULL) X { X p->w_autoaka = 0; X *nwin.aka++ = 0; X p->w_title = nwin.aka; X p->w_akachange = nwin.aka + strlen(nwin.aka); X } X else X p->w_title = p->w_akachange = p->w_akabuf; X if ((p->w_monitor = nwin.monitor) == -1) X p->w_monitor = default_monitor; X p->w_norefresh = 0; X strncpy(p->w_tty, TtyName, MAXSTR - 1); X X if (ChangeWindowSize(p, display ? d_defwidth : 80, display ? d_defheight : 24)) X { X FreeWindow(p); X return -1; X } X#ifdef COPY_PASTE X ChangeScrollback(p, nwin.histheight, p->w_width); X#endif X ResetWindow(p); /* sets p->w_wrap */ X X if (ttyflag == TTY_FLAG_PLAIN) X { X p->w_t.flags |= TTY_FLAG_PLAIN; X p->w_pid = 0; X } X else X { X debug("forking...\n"); X#ifdef PSEUDOS X p->w_pwin = NULL; X#endif X p->w_pid = ForkWindow(nwin.args, nwin.dir, nwin.term, TtyName, p); X if (p->w_pid < 0) X { X FreeWindow(p); X return -1; X } X } X /* X * Place the newly created window at the head of the most-recently-used list. X */ X if (display && d_fore) X d_other = d_fore; X *pp = p; X p->w_next = windows; X windows = p; X#ifdef UTMPOK X debug1("MakeWindow will %slog in.\n", nwin.lflag?"":"not "); X if (nwin.lflag == 1) X { X if (display) X SetUtmp(p); X else X p->w_slot = (slot_t) 0; X } X else X p->w_slot = (slot_t) -1; X#endif X SetForeWindow(p); X Activate(p->w_norefresh); X return n; X} X Xvoid XFreeWindow(wp) Xstruct win *wp; X{ X struct display *d; X X#ifdef PSEUDOS X if (wp->w_pwin) X FreePseudowin(wp); X#endif X#ifdef UTMPOK X RemoveUtmp(wp); X#endif X (void) chmod(wp->w_tty, 0666); X (void) chown(wp->w_tty, 0, 0); X close(wp->w_ptyfd); X if (wp == console_window) X console_window = 0; X if (wp->w_logfp != NULL) X fclose(wp->w_logfp); X ChangeWindowSize(wp, 0, 0); X for (d = displays; d; d = d->_d_next) X if (d->_d_other == wp) X d->_d_other = 0; X free(wp); X} X Xstatic int XOpenDevice(arg, lflag, typep, namep) Xchar *arg; Xint lflag; Xint *typep; Xchar **namep; X{ X struct stat st; X int f; X X if ((stat(arg, &st)) == 0 && (st.st_mode & S_IFCHR)) X { X if (access(arg, R_OK | W_OK) == -1) X { X Msg(errno, "Cannot access line '%s' for R/W", arg); X return -1; X } X debug("OpenDevice: OpenTTY\n"); X if ((f = OpenTTY(arg)) < 0) X return -1; X *typep = TTY_FLAG_PLAIN; X *namep = arg; X } X else X { X *typep = 0; /* for now we hope it is a program */ X f = OpenPTY(namep); X if (f == -1) X { X Msg(0, "No more PTYs."); X return -1; X } X#ifdef TIOCPKT X { X int flag = 1; X X if (ioctl(f, TIOCPKT, (char *)&flag)) X { X Msg(errno, "TIOCPKT ioctl"); X close(f); X return -1; X } X } X#endif /* TIOCPKT */ X } X (void) fcntl(f, F_SETFL, FNDELAY); X#ifdef PTYGROUP X (void) chown(*namep, real_uid, PTYGROUP); X#else X (void) chown(*namep, real_uid, real_gid); X#endif X#ifdef UTMPOK X (void) chmod(*namep, lflag ? TtyMode : (TtyMode & ~022)); X#else X (void) chmod(*namep, TtyMode); X#endif X return f; X} X X/* X * Fields w_width, w_height, aflag, number (and w_tty) X * are read from struct win *win. No fields written. X * If pwin is nonzero, filedescriptors are distributed X * between win->w_tty and open(ttyn) X * X */ Xstatic int XForkWindow(args, dir, term, ttyn, win) Xchar **args, *dir, *term, *ttyn; Xstruct win *win; X{ X int pid; X char tebuf[25]; X char ebuf[10]; X char shellbuf[7 + MAXPATHLEN]; X char *proc; X#ifndef TIOCSWINSZ X char libuf[20], cobuf[20]; X#endif X int newfd; X int w = win->w_width; X int h = win->w_height; X#ifdef PSEUDOS X int i, pat, wfdused; X struct pseudowin *pwin = win->w_pwin; X#endif X X proc = *args; X if (proc == 0) X { X args = ShellArgs; X proc = *args; X } X switch (pid = fork()) X { X case -1: X Msg(errno, "fork"); X return -1; X case 0: X signal(SIGHUP, SIG_DFL); X signal(SIGINT, SIG_DFL); X signal(SIGQUIT, SIG_DFL); X signal(SIGTERM, SIG_DFL); X#ifdef BSDJOBS X signal(SIGTTIN, SIG_DFL); X signal(SIGTTOU, SIG_DFL); X#endif X if (setuid(real_uid) || setgid(real_gid)) X { X SendErrorMsg("Setuid/gid: %s", sys_errlist[errno]); X eexit(1); X } X if (dir && *dir && chdir(dir) == -1) X { X SendErrorMsg("Cannot chdir to %s: %s", dir, sys_errlist[errno]); X eexit(1); X } X X if (display) X { X brktty(d_userfd); X freetty(); X } X else X brktty(-1); X#ifdef DEBUG X if (dfp && dfp != stderr) X fclose(dfp); X#endif X closeallfiles(win->w_ptyfd); X#ifdef DEBUG X { X char buf[256]; X X sprintf(buf, "%s/screen.child", DEBUGDIR); X if ((dfp = fopen(buf, "a")) == 0) X dfp = stderr; X else X (void) chmod(buf, 0666); X } X debug1("=== ForkWindow: pid %d\n", getpid()); X#endif X /* Close the three /dev/null descriptors */ X close(0); X close(1); X close(2); X newfd = -1; X /* X * distribute filedescriptors between the ttys X */ X#ifdef PSEUDOS X pat = pwin ? pwin->fdpat : X ((F_PFRONT<<(F_PSHIFT*2)) | (F_PFRONT<w_ptyfd); X wfdused = 1; X } X } X if (wfdused) X { X /* X * the pseudo window process should not be surprised with a X * nonblocking filedescriptor. Poor Backend! X */ X debug1("Clearing NDELAY on window-fd(%d)\n", win->w_ptyfd); X if (fcntl(win->w_ptyfd, F_SETFL, 0)) X SendErrorMsg("Warning: ForkWindow clear NDELAY fcntl failed, %d", errno); X } X#else /* PSEUDOS */ X if ((newfd = open(ttyn, O_RDWR)) != 0) X { X SendErrorMsg("Cannot open %s: %s", ttyn, sys_errlist[errno]); X eexit(1); X } X dup(0); X dup(0); X#endif /* PSEUDOS */ X close(win->w_ptyfd); X X if (newfd >= 0) X { X struct mode fakemode, *modep; X#if defined(SVR4) && !defined(sgi) X if (ioctl(newfd, I_PUSH, "ptem")) X { X SendErrorMsg("Cannot I_PUSH ptem %s %s", ttyn, sys_errlist[errno]); X eexit(1); X } X if (ioctl(newfd, I_PUSH, "ldterm")) X { X SendErrorMsg("Cannot I_PUSH ldterm %s %s", ttyn, sys_errlist[errno]); X eexit(1); X } X if (ioctl(newfd, I_PUSH, "ttcompat")) X { X SendErrorMsg("Cannot I_PUSH ttcompat %s %s", ttyn, sys_errlist[errno]); X eexit(1); X } X#endif X if (fgtty(newfd)) X SendErrorMsg("fgtty: %s (%d)", sys_errlist[errno], errno); X if (display) X { X debug("ForkWindow: using display tty mode for new child.\n"); X modep = &d_OldMode; X } X else X { X debug("No display - creating tty setting\n"); X modep = &fakemode; X InitTTY(modep, 0); X#ifdef DEBUG X DebugTTY(modep); X#endif X } X /* We only want echo if the users input goes to the pseudo X * and the pseudo's stdout is not send to the window. X */ X#ifdef PSEUDOS X if (pwin && (!(pat & F_UWP) || (pat & F_PBACK << F_PSHIFT))) X { X debug1("clearing echo on pseudywin fd (pat %x)\n", pat); X# if defined(POSIX) || defined(TERMIO) X modep->tio.c_lflag &= ~ECHO; X modep->tio.c_iflag &= ~ICRNL; X# else X modep->m_ttyb.sg_flags &= ~ECHO; X# endif X } X#endif X SetTTY(newfd, modep); X#ifdef TIOCSWINSZ X glwz.ws_col = w; X glwz.ws_row = h; X (void) ioctl(newfd, TIOCSWINSZ, (char *)&glwz); X#endif X } X#ifndef TIOCSWINSZ X sprintf(libuf, "LINES=%d", h); X sprintf(cobuf, "COLUMNS=%d", w); X NewEnv[5] = libuf; X NewEnv[6] = cobuf; X#endif X if (win->w_aflag) X NewEnv[2] = MakeTermcap(1); X else X NewEnv[2] = Termcap; X strcpy(shellbuf, "SHELL="); X strncpy(shellbuf + 6, ShellProg, MAXPATHLEN); X shellbuf[MAXPATHLEN + 6] = 0; X NewEnv[4] = shellbuf; X debug1("ForkWindow: NewEnv[4] = '%s'\n", shellbuf); X if (term && *term && strcmp(screenterm, term) && X (strlen(term) < 20)) X { X char *s1, *s2, tl; X X sprintf(tebuf, "TERM=%s", term); X debug2("Makewindow %d with %s\n", win->w_number, tebuf); X tl = strlen(term); X NewEnv[1] = tebuf; X if ((s1 = index(Termcap, '|'))) X { X if ((s2 = index(++s1, '|'))) X { X if (strlen(Termcap) - (s2 - s1) + tl < 1024) X { X bcopy(s2, s1 + tl, strlen(s2) + 1); X bcopy(term, s1, tl); X } X } X } X } X sprintf(ebuf, "WINDOW=%d", win->w_number); X NewEnv[3] = ebuf; X X if (*proc == '-') X proc++; X debug1("calling execvpe %s\n", proc); X execvpe(proc, args, NewEnv); X debug1("exec error: %d\n", errno); X SendErrorMsg("Cannot exec %s: %s", proc, sys_errlist[errno]); X exit(1); X default: X return pid; X } /* end fork switch */ X /* NOTREACHED */ X} X Xstatic void Xexecvpe(prog, args, env) Xchar *prog, **args, **env; X{ X register char *path = NULL, *p; X char buf[1024]; X char *shargs[MAXARGS + 1]; X register int i, eaccess = 0; X X for (i = 0; i < 3; i++) X if (!strncmp("../" + i, prog, 3 - i)) X path = ""; X if (!path && !(path = getenv("PATH"))) X path = DefaultPath; X do X { X p = buf; X while (*path && *path != ':') X *p++ = *path++; X if (p > buf) X *p++ = '/'; X strcpy(p, prog); X execve(buf, args, env); X switch (errno) X { X case ENOEXEC: X shargs[0] = DefaultShell; X shargs[1] = buf; X for (i = 1; (shargs[i + 1] = args[i]) != NULL; ++i) X ; X execve(DefaultShell, shargs, env); X return; X case EACCES: X eaccess = 1; X break; X case ENOMEM: X case E2BIG: X case ETXTBSY: X return; X } X } while (*path++); X if (eaccess) X errno = EACCES; X} X X#ifdef PSEUDOS X Xint Xwinexec(av) Xchar **av; X{ X char **pp; X char *p, *s, *t; X int i, r = 0, l = 0; X struct win *w; X extern struct display *display; X extern struct win *windows; X struct pseudowin *pwin; X X if ((w = display ? fore : windows) == NULL) X return -1; X if (!*av || w->w_pwin) X { X Msg(0, "Filter running: %s", w->w_pwin ? w->w_pwin->p_cmd : "(none)"); X return -1; X } X if (w->w_ptyfd < 0) X { X Msg(0, "You feel dead inside."); X return -1; X } X if (!(pwin = (struct pseudowin *)malloc(sizeof(struct pseudowin)))) X { X Msg(0, strnomem); X return -1; X } X bzero((char *)pwin, (int)sizeof(*pwin)); X X /* allow ^a:!!./ttytest as a short form for ^a:exec !.. ./ttytest */ X for (s = *av; *s == ' '; s++) X ; X for (p = s; *p == ':' || *p == '.' || *p == '!'; p++) X ; X if (*p != '|') X while (*p && p > s && p[-1] == '.') X p--; X if (*p == '|') X { X l = F_UWP; X p++; X } X if (*p) X av[0] = p; X else X av++; X X t = pwin->p_cmd; X for (i = 0; i < 3; i++) X { X *t = (s < p) ? *s++ : '.'; X switch (*t++) X { X case '.': X case '|': X l |= F_PFRONT << (i * F_PSHIFT); X break; X case '!': X l |= F_PBACK << (i * F_PSHIFT); X break; X case ':': X l |= F_PBOTH << (i * F_PSHIFT); X break; X } X } X X if (l & F_UWP) X { X *t++ = '|'; X if ((l & F_PMASK) == F_PFRONT) X { X *pwin->p_cmd = '!'; X l ^= F_PFRONT | F_PBACK; X } X } X if (!(l & F_PBACK)) X l |= F_UWP; X *t++ = ' '; X pwin->fdpat = l; X debug1("winexec: '%#x'\n", pwin->fdpat); X X l = MAXSTR - 4; X for (pp = av; *pp; pp++) X { X p = *pp; X while (*p && l-- > 0) X *t++ = *p++; X if (l <= 0) X break; X *t++ = ' '; X } X *--t = '\0'; X debug1("%s\n", pwin->p_cmd); X X if ((pwin->p_ptyfd = OpenDevice(av[0], 0, &l, &t)) < 0) X { X free(pwin); X return -1; X } X strncpy(pwin->p_tty, t, MAXSTR - 1); X w->w_pwin = pwin; X if (l == TTY_FLAG_PLAIN) X { X FreePseudowin(w); X Msg(0, "Cannot handle a TTY as a pseudo win."); X return -1; X } X#ifdef TIOCPKT X { X int flag = 0; X X if (ioctl(pwin->p_ptyfd, TIOCPKT, (char *)&flag)) X { X Msg(errno, "TIOCPKT ioctl"); X FreePseudowin(w); X return -1; X } X } X#endif /* TIOCPKT */ X pwin->p_pid = ForkWindow(av, NULL, NULL, t, w); X if ((r = pwin->p_pid) < 0) X FreePseudowin(w); X return r; X} X Xvoid XFreePseudowin(w) Xstruct win *w; X{ X struct pseudowin *pwin = w->w_pwin; X X ASSERT(pwin); X if (fcntl(w->w_ptyfd, F_SETFL, FNDELAY)) X Msg(errno, "Warning: FreePseudowin: NDELAY fcntl failed"); X (void) chmod(pwin->p_tty, 0666); X (void) chown(pwin->p_tty, 0, 0); X if (pwin->p_ptyfd >= 0) X close(pwin->p_ptyfd); X free(pwin); X w->w_pwin = NULL; X} X X#endif /* PSEUDOS */ X X X#ifdef MULTI X Xstatic void CloneTermcap __P((struct display *)); Xextern char **environ; X Xint Xexecclone(av) Xchar **av; X{ X int f, sf; X char specialbuf[6]; X struct display *old = display; X char **avp, *namep; X X sf = OpenPTY(&namep); X if (sf == -1) X { X Msg(0, "No more PTYs."); X return -1; X } X f = open(namep, O_RDWR); X if (f == -1) X { X close(sf); X Msg(errno, "Cannot open slave"); X return -1; X } X brktty(f); X signal(SIGHUP, SIG_IGN); /* No hangups, please */ X if (MakeDisplay(d_username, namep, d_termname, f, -1, &d_OldMode) == 0) X { X display = old; X Msg(0, "Could not make display."); X close(f); X return -1; X } X SetMode(&d_OldMode, &d_NewMode); X SetTTY(f, &d_NewMode); X switch (fork()) X { X case -1: X FreeDisplay(); X display = old; X Msg(errno, "fork"); X return -1; X case 0: X d_usertty[0] = 0; /* for SendErrorMsg */ X if (setuid(real_uid) || setgid(real_gid)) X { X SendErrorMsg("Setuid/gid: %s", sys_errlist[errno]); X eexit(1); X } X closeallfiles(sf); X close(1); X dup(sf); X close(sf); X#ifdef DEBUG X { X char buf[256]; X X sprintf(buf, "%s/screen.child", DEBUGDIR); X if ((dfp = fopen(buf, "a")) == 0) X dfp = stderr; X else X (void) chmod(buf, 0666); X } X debug1("=== Clone: pid %d\n", getpid()); X#endif X for (avp = av; *avp; avp++) X { X if (strcmp(*avp, "%p") == 0) X *avp = namep; X if (strcmp(*avp, "%X") == 0) X *avp = specialbuf; X } X sprintf(specialbuf, "-SXX1"); X namep += strlen(namep); X specialbuf[3] = *--namep; X specialbuf[2] = *--namep; X#ifdef DEBUG X debug("Calling:"); X for (avp = av; *avp; avp++) X debug1(" %s", *avp); X debug("\n"); X#endif X execvpe(*av, av, environ); X SendErrorMsg("Cannot exec %s: %s", *av, sys_errlist[errno]); X exit(1); X default: X break; X } X close(sf); X CloneTermcap(old); X InitTerm(0); X Activate(0); X if (d_fore == 0) X ShowWindows(); X return 0; X} X Xextern struct term term[]; /* terminal capabilities */ X Xstatic void XCloneTermcap(old) Xstruct display *old; X{ X char *tp; X int i; X X tp = d_tentry; X for (i = 0; i < T_N; i++) X { X switch(term[i].type) X { X case T_FLG: X d_tcs[i].flg = old->_d_tcs[i].flg; X break; X case T_NUM: X d_tcs[i].num = old->_d_tcs[i].num; X break; X case T_STR: X d_tcs[i].str = old->_d_tcs[i].str; X if (d_tcs[i].str) X { X strcpy(tp, d_tcs[i].str); X d_tcs[i].str = tp; X tp += strlen(tp) + 1; X } X break; X default: X Panic(0, "Illegal tc type in entry #%d", i); X } X } X CheckScreenSize(0); X for (i = 0; i < NATTR; i++) X d_attrtab[i] = old->_d_attrtab[i]; X for (i = 0; i < 256; i++) X d_c0_tab[i] = old->_d_c0_tab[i]; X d_UPcost = old->_d_UPcost; X d_DOcost = old->_d_DOcost; X d_NLcost = old->_d_NLcost; X d_LEcost = old->_d_LEcost; X d_NDcost = old->_d_NDcost; X d_CRcost = old->_d_CRcost; X d_IMcost = old->_d_IMcost; X d_EIcost = old->_d_EIcost; X#ifdef AUTO_NUKE X d_auto_nuke = old->_d_auto_nuke; X#endif X d_tcinited = 1; X} X X#endif X END_OF_FILE if test 20847 -ne `wc -c <'window.c'`; then echo shar: \"'window.c'\" unpacked with wrong size! fi # end of 'window.c' fi echo shar: End of archive 4 \(of 10\). cp /dev/null ark4isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 10 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0