summaryrefslogtreecommitdiff
path: root/src/screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/screen.c')
-rw-r--r--src/screen.c234
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)