diff options
Diffstat (limited to 'src/screen.c')
-rw-r--r-- | src/screen.c | 181 |
1 files changed, 137 insertions, 44 deletions
diff --git a/src/screen.c b/src/screen.c index 7239560..5c15a39 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1,4 +1,7 @@ -/* Copyright (c) 2008 +/* Copyright (c) 2010 + * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) + * Sadrul Habib Chowdhury (sadrul@users.sourceforge.net) + * Copyright (c) 2008, 2009 * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de) * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de) * Micah Cowan (micah@cowan.name) @@ -118,6 +121,8 @@ int VBellWait, MsgWait, MsgMinWait, SilenceWait; extern struct acluser *users; extern struct display *displays, *display; +extern struct LayFuncs MarkLf; + extern int visual_bell; #ifdef COPY_PASTE @@ -205,6 +210,7 @@ char *wlisttit; int auto_detach = 1; int iflag, rflag, dflag, lsflag, quietflag, wipeflag, xflag; int cmdflag; +int queryflag = -1; int adaptflag; #ifdef MULTIUSER @@ -235,7 +241,7 @@ int cjkwidth; #ifdef NETHACK int nethackflag = 0; #endif -int maxwin = MAXWIN; +int maxwin; struct layer *flayer; @@ -463,10 +469,10 @@ char **av; screenlogfile = SaveStr("screenlog.%n"); logtstamp_string = SaveStr("-- %n:%t -- time-stamp -- %M/%d/%y %c:%s --\n"); hstatusstring = SaveStr("%h"); - captionstring = SaveStr("%3n %t"); + captionstring = SaveStr("%4n %t"); timestring = SaveStr("%c:%s %M %d %H%? %l%?"); - wlisttit = SaveStr("Num Name%=Flags"); - wliststr = SaveStr("%3n %t%=%f"); + wlisttit = SaveStr(" Num Name%=Flags"); + wliststr = SaveStr("%4n %t%=%f"); #ifdef COPY_PASTE BufferFile = SaveStr(DEFAULT_BUFFERFILE); #endif @@ -678,6 +684,10 @@ char **av; case 'q': quietflag = 1; break; + case 'Q': + queryflag = 1; + cmdflag = 1; + break; case 'r': case 'R': #ifdef MULTI @@ -757,17 +767,12 @@ char **av; real_gid = getgid(); eff_uid = geteuid(); eff_gid = getegid(); - if (eff_uid != real_uid) - { - /* if running with s-bit, we must install a special signal - * handler routine that resets the s-bit, so that we get a - * core file anyway. - */ + #ifdef SIGBUS /* OOPS, linux has no bus errors! */ - signal(SIGBUS, CoreDump); + signal(SIGBUS, CoreDump); #endif /* SIGBUS */ - signal(SIGSEGV, CoreDump); - } + signal(SIGSEGV, CoreDump); + #ifdef USE_LOCALE setlocale(LC_ALL, ""); @@ -813,7 +818,7 @@ char **av; size_t newsz; char *newbuf = malloc(3 * len); if (!newbuf) - Panic(0, strnomem); + Panic(0, "%s", strnomem); newsz = RecodeBuf(nwin_options.aka, len, nwin_options.encoding, 0, newbuf); newbuf[newsz] = '\0'; @@ -1076,7 +1081,7 @@ char **av; else { SockDir = SOCKDIR; - if (lstat(SockDir, &st)) + if (stat(SockDir, &st)) { n = (eff_uid == 0 && (real_uid || eff_gid == real_gid)) ? 0755 : (eff_gid != real_gid) ? 0775 : @@ -1174,7 +1179,7 @@ char **av; if (!*av) Panic(0, "Please specify a command."); SET_GUID(); - SendCmdMessage(sty, SockMatch, av); + SendCmdMessage(sty, SockMatch, av, queryflag >= 0); exit(0); } else if (rflag || xflag) @@ -1414,8 +1419,13 @@ char **av; debug("We open one default window, as screenrc did not specify one.\n"); if (MakeWindow(&nwin) == -1) { - Msg(0, "Sorry, could not find a PTY."); - sleep(5); + fd_set rfd; + struct timeval tv = { MsgWait/1000, 1000*(MsgWait%1000) }; + FD_SET(0, &rfd); + + Msg(0, "Sorry, could not find a PTY or TTY."); + // allow user to exit early by pressing any key. + select(1, &rfd, NULL, NULL, &tv); Finit(0); /* NOTREACHED */ } @@ -1468,6 +1478,26 @@ int wstat_valid; { int killit = 0; + if (p->w_destroyev.data == (char *)p) + { + wstat = p->w_exitstatus; + wstat_valid = 1; + evdeq(&p->w_destroyev); + p->w_destroyev.data = 0; + } + +#if defined(BSDJOBS) && !defined(BSDWAIT) + if (!wstat_valid && p->w_pid > 0) + { + /* EOF on file descriptor. The process is probably also dead. + * try a waitpid */ + if (waitpid(p->w_pid, &wstat, WNOHANG | WUNTRACED) == p->w_pid) + { + p->w_pid = 0; + wstat_valid = 1; + } + } +#endif if (ZombieKey_destroy && ZombieKey_onerror && wstat_valid && WIFEXITED(wstat) && WEXITSTATUS(wstat) == 0) killit = 1; @@ -1604,39 +1634,55 @@ SigInt SIGDEFARG static sigret_t CoreDump SIGDEFARG { + /* if running with s-bit, we must reset the s-bit, so that we get a + * core file anyway. + */ + struct display *disp; char buf[80]; + char *dump_msg = " (core dumped)"; + + int running_w_s_bit = getuid() != geteuid(); +#if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW) + if (running_w_s_bit) + dump_msg = ""; +#endif + #if defined(SYSVSIGS) && defined(SIGHASARG) signal(sigsig, SIG_IGN); #endif setgid(getgid()); setuid(getuid()); unlink("core"); + #ifdef SIGHASARG - sprintf(buf, "\r\n[screen caught signal %d.%s]\r\n", sigsig, + sprintf(buf, "\r\n[screen caught signal %d.%s]\r\n", sigsig, dump_msg); #else - sprintf(buf, "\r\n[screen caught a fatal signal.%s]\r\n", + sprintf(buf, "\r\n[screen caught a fatal signal.%s]\r\n", dump_msg); #endif -#if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW) - "" -#else /* SHADOWPW && !DEBUG */ - " (core dumped)" -#endif /* SHADOWPW && !DEBUG */ - ); + for (disp = displays; disp; disp = disp->d_next) { + if (disp->d_nonblock < -1 || disp->d_nonblock > 1000000) + continue; fcntl(disp->d_userfd, F_SETFL, 0); SetTTY(disp->d_userfd, &D_OldMode); write(disp->d_userfd, buf, strlen(buf)); Kill(disp->d_userpid, SIG_BYE); } + + if (running_w_s_bit) + { #if defined(SHADOWPW) && !defined(DEBUG) && !defined(DUMPSHADOW) - Kill(getpid(), SIGKILL); - eexit(11); + Kill(getpid(), SIGKILL); + eexit(11); #else /* SHADOWPW && !DEBUG */ - abort(); + abort(); #endif /* SHADOWPW && !DEBUG */ + } + else + abort(); SIGRETURN; } @@ -1708,7 +1754,16 @@ DoWait() else #endif { - WindowDied(p, wstat, 1); + /* Screen will detect the window has died when the window's + * file descriptor signals EOF (which it will do when the process in + * the window terminates). So do this in a timeout of 10 seconds. + * (not doing this at all might also work) + * See #27061 for more details. + */ + p->w_destroyev.data = (char *)p; + p->w_exitstatus = wstat; + SetTimeout(&p->w_destroyev, 10 * 1000); + evenq(&p->w_destroyev); } break; } @@ -1776,7 +1831,7 @@ int i; RestoreLoginSlot(); #endif AddStr("[screen is terminating]\r\n"); - Flush(); + Flush(3); SetTTY(D_userfd, &D_OldMode); fcntl(D_userfd, F_SETFL, 0); freetty(); @@ -1997,7 +2052,7 @@ MakeNewEnv() free((char *)NewEnv); NewEnv = np = (char **) malloc((unsigned) (op - environ + 7 + 1) * sizeof(char **)); if (!NewEnv) - Panic(0, strnomem); + Panic(0, "%s", strnomem); sprintf(stybuf, "STY=%s", strlen(SockName) <= MAXSTR - 5 ? SockName : "?"); *np++ = stybuf; /* NewEnv[0] */ *np++ = Term; /* NewEnv[1] */ @@ -2023,11 +2078,11 @@ MakeNewEnv() void /*VARARGS2*/ #if defined(USEVARARGS) && defined(__STDC__) -Msg(int err, char *fmt, VA_DOTS) +Msg(int err, const char *fmt, VA_DOTS) #else Msg(err, fmt, VA_DOTS) int err; -char *fmt; +const char *fmt; VA_DECL #endif { @@ -2069,6 +2124,9 @@ VA_DECL } else printf("%s\r\n", buf); + + if (queryflag >= 0) + write(queryflag, buf, strlen(buf)); } /* @@ -2077,11 +2135,11 @@ VA_DECL void /*VARARGS2*/ #if defined(USEVARARGS) && defined(__STDC__) -Panic(int err, char *fmt, VA_DOTS) +Panic(int err, const char *fmt, VA_DOTS) #else Panic(err, fmt, VA_DOTS) int err; -char *fmt; +const char *fmt; VA_DECL #endif { @@ -2125,7 +2183,7 @@ VA_DECL if (D_status) RemoveStatus(); FinitTerm(); - Flush(); + Flush(3); #ifdef UTMPOK RestoreLoginSlot(); #endif @@ -2168,7 +2226,7 @@ static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; #endif static char winmsg_buf[MAXSTR]; -#define MAX_WINMSG_REND 16 /* rendition changes */ +#define MAX_WINMSG_REND 256 /* rendition changes */ static int winmsg_rend[MAX_WINMSG_REND]; static int winmsg_rendpos[MAX_WINMSG_REND]; static int winmsg_numrend; @@ -2331,7 +2389,7 @@ char **cmdv; bt = (struct backtick *)malloc(sizeof *bt); if (!bt) { - Msg(0, strnomem); + Msg(0, "%s", strnomem); return; } bzero(bt, sizeof(*bt)); @@ -2353,7 +2411,7 @@ char **cmdv; bt->buf = (char *)malloc(MAXSTR); if (bt->buf == 0) { - Msg(0, strnomem); + Msg(0, "%s", strnomem); setbacktick(num, 0, 0, (char **)0); return; } @@ -2417,6 +2475,22 @@ time_t now; return bt->result; } +int +AddWinMsgRend(str, r) +const char *str; +int r; +{ + if (winmsg_numrend >= MAX_WINMSG_REND || str < winmsg_buf || + str >= winmsg_buf + MAXSTR) + return -1; + + winmsg_rend[winmsg_numrend] = r; + winmsg_rendpos[winmsg_numrend] = str - winmsg_buf; + winmsg_numrend++; + + return 0; +} + char * MakeWinMsgEv(str, win, esc, padlen, ev, rec) char *str; @@ -2672,9 +2746,7 @@ int rec; oldfore = D_fore; D_fore = win; } - ss = AddWindows(p, l - 1, (*s == 'w' ? 0 : 1) | (longflg ? 0 : 2) | (plusflg ? 4 : 0), win ? win->w_number : -1); - if (minusflg) - *ss = 0; + ss = AddWindows(p, l - 1, (*s == 'w' ? 0 : 1) | (longflg ? 0 : 2) | (plusflg ? 4 : 0) | (minusflg ? 8 : 0), win ? win->w_number : -1); if (display) D_fore = oldfore; } @@ -2773,6 +2845,18 @@ int rec; if (minusflg) qmflag = 1; break; + case 'P': + p--; +#ifdef COPY_PASTE + if (display && ev && ev != &D_hstatusev) /* Hack */ + { + /* Is the layer in the current canvas in copy mode? */ + struct canvas *cv = (struct canvas *)ev->data; + if (ev == &cv->c_captev && cv->c_layer->l_layfn == &MarkLf) + qmflag = 1; + } +#endif + break; case '>': truncpos = p - winmsg_buf; truncper = num > 100 ? 100 : num; @@ -3157,6 +3241,15 @@ char *data; } WindowChanged(p, 'f'); } + if (p->w_silence == SILENCE_FOUND) + { + /* Unset the flag if the user switched to this window. */ + if (p->w_layer.l_cvlist) + { + p->w_silence = SILENCE_ON; + WindowChanged(p, 'f'); + } + } } for (display = displays; display; display = display->d_next) |