diff options
Diffstat (limited to 'src/screen.c')
-rw-r--r-- | src/screen.c | 234 |
1 files changed, 153 insertions, 81 deletions
diff --git a/src/screen.c b/src/screen.c index 0506b6e..ba5c259 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1,4 +1,7 @@ -/* Copyright (c) 2008, 2009 +/* 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; @@ -468,10 +474,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 @@ -683,6 +689,10 @@ char **av; case 'q': quietflag = 1; break; + case 'Q': + queryflag = 1; + cmdflag = 1; + break; case 'r': case 'R': #ifdef MULTI @@ -769,17 +779,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, ""); @@ -825,7 +830,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'; @@ -1088,7 +1093,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 : @@ -1186,7 +1191,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) @@ -1496,6 +1501,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; @@ -1632,39 +1657,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; } @@ -1736,7 +1777,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; } @@ -1809,7 +1859,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(); @@ -2034,7 +2084,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] */ @@ -2057,33 +2107,37 @@ MakeNewEnv() *np = 0; } -void -/*VARARGS2*/ #if defined(USEVARARGS) && defined(__STDC__) -Msg(int err, char *fmt, VA_DOTS) + #define DEFINE_VARARGS_FN(fnname) void fnname (int err, const char *fmt, VA_DOTS) #else -Msg(err, fmt, VA_DOTS) -int err; -char *fmt; -VA_DECL -#endif + #define DEFINE_VARARGS_FN(fnname) void fnname(err, fmt, VA_DOTS) \ + int err; \ + const char *fmt; \ + VA_DECL +#endif + +#define PROCESS_MESSAGE(B) do { \ + char *p = B; \ + VA_LIST(ap) \ + VA_START(ap, fmt); \ + fmt = DoNLS(fmt); \ + (void)vsnprintf(p, sizeof(B) - 100, fmt, VA_ARGS(ap)); \ + VA_END(ap); \ + if (err) \ + { \ + p += strlen(p); \ + *p++ = ':'; \ + *p++ = ' '; \ + strncpy(p, strerror(err), B + sizeof(B) - p - 1); \ + B[sizeof(B) - 1] = 0; \ + } \ + } while (0) + +DEFINE_VARARGS_FN(Msg) { - VA_LIST(ap) char buf[MAXPATHLEN*2]; - char *p = buf; + PROCESS_MESSAGE(buf); - VA_START(ap, fmt); - fmt = DoNLS(fmt); - (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap)); - VA_END(ap); - if (err) - { - p += strlen(p); - *p++ = ':'; - *p++ = ' '; - strncpy(p, strerror(err), buf + sizeof(buf) - p - 1); - buf[sizeof(buf) - 1] = 0; - } debug2("Msg('%s') (%#x);\n", buf, (unsigned int)display); if (display && displays) @@ -2106,38 +2160,19 @@ VA_DECL } else printf("%s\r\n", buf); + + if (queryflag >= 0) + write(queryflag, buf, strlen(buf)); } /* * Call FinitTerm for all displays, write a message to each and call eexit(); */ -void -/*VARARGS2*/ -#if defined(USEVARARGS) && defined(__STDC__) -Panic(int err, char *fmt, VA_DOTS) -#else -Panic(err, fmt, VA_DOTS) -int err; -char *fmt; -VA_DECL -#endif +DEFINE_VARARGS_FN(Panic) { - VA_LIST(ap) char buf[MAXPATHLEN*2]; - char *p = buf; + PROCESS_MESSAGE(buf); - VA_START(ap, fmt); - fmt = DoNLS(fmt); - (void)vsnprintf(p, sizeof(buf) - 100, fmt, VA_ARGS(ap)); - VA_END(ap); - if (err) - { - p += strlen(p); - *p++ = ':'; - *p++ = ' '; - strncpy(p, strerror(err), buf + sizeof(buf) - p - 1); - buf[sizeof(buf) - 1] = 0; - } debug3("Panic('%s'); display=%x displays=%x\n", buf, display, displays); if (displays == 0 && display == 0) { @@ -2162,7 +2197,7 @@ VA_DECL if (D_status) RemoveStatus(); FinitTerm(); - Flush(); + Flush(3); #ifdef UTMPOK RestoreLoginSlot(); #endif @@ -2190,6 +2225,22 @@ VA_DECL eexit(1); } +DEFINE_VARARGS_FN(QueryMsg) +{ + char buf[MAXPATHLEN*2]; + + if (queryflag < 0) + return; + + PROCESS_MESSAGE(buf); + write(queryflag, buf, strlen(buf)); +} + +DEFINE_VARARGS_FN(Dummy) +{} + +#undef PROCESS_MESSAGE +#undef DEFINE_VARARGS_FN /* * '^' is allowed as an escape mechanism for control characters. jw. @@ -2205,7 +2256,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; @@ -2368,7 +2419,7 @@ char **cmdv; bt = (struct backtick *)malloc(sizeof *bt); if (!bt) { - Msg(0, strnomem); + Msg(0, "%s", strnomem); return; } bzero(bt, sizeof(*bt)); @@ -2390,7 +2441,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; } @@ -2856,6 +2907,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; @@ -3240,6 +3303,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) |