summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSadrul Habib Chowdhury <sadrul@users.sourceforge.net>2010-02-16 11:37:14 -0500
committerSadrul Habib Chowdhury <sadrul@users.sourceforge.net>2010-02-16 11:37:14 -0500
commit5275b7c42a4eb590249b1fca47ce184fe2ba69f9 (patch)
tree9caa1b77e863fe2b314ba34fbf4a4befd5b95b3f
parent97059b7ad521cf796daee07397c658d9716dd1e7 (diff)
parent2f39e64a76b2db7ce5ae88b6c087b8e60a47ce06 (diff)
downloadscreen-5275b7c42a4eb590249b1fca47ce184fe2ba69f9.tar.gz
Merge branch 'query-result'
-rw-r--r--src/attacher.c78
-rw-r--r--src/comm.c14
-rw-r--r--src/comm.sh2
-rw-r--r--src/doc/screen.117
-rw-r--r--src/doc/screen.texinfo16
-rw-r--r--src/extern.h2
-rw-r--r--src/process.c45
-rw-r--r--src/screen.c10
-rw-r--r--src/screen.h3
-rw-r--r--src/socket.c54
10 files changed, 218 insertions, 23 deletions
diff --git a/src/attacher.c b/src/attacher.c
index 1bba70f..ef3ce8b 100644
--- a/src/attacher.c
+++ b/src/attacher.c
@@ -83,6 +83,21 @@ AttachSigCont SIGDEFARG
SIGRETURN;
}
+static int QueryResult;
+
+static sigret_t
+QueryResultSuccess SIGDEFARG
+{
+ QueryResult = 1;
+ SIGRETURN;
+}
+
+static sigret_t
+QueryResultFail SIGDEFARG
+{
+ QueryResult = 2;
+ SIGRETURN;
+}
/*
* Send message to a screen backend.
@@ -923,10 +938,11 @@ screen_builtin_lck()
void
-SendCmdMessage(sty, match, av)
+SendCmdMessage(sty, match, av, query)
char *sty;
char *match;
char **av;
+int query;
{
int i, s;
struct msg m;
@@ -954,7 +970,7 @@ char **av;
exit(1);
}
bzero((char *)&m, sizeof(m));
- m.type = MSG_COMMAND;
+ m.type = query ? MSG_QUERY : MSG_COMMAND;
if (attach_tty)
{
strncpy(m.m_tty, attach_tty, sizeof(m.m_tty) - 1);
@@ -979,7 +995,59 @@ char **av;
m.m.command.preselect[sizeof(m.m.command.preselect) - 1] = 0;
m.m.command.apid = getpid();
debug1("SendCommandMsg writing '%s'\n", m.m.command.cmd);
- if (WriteMessage(s, &m))
- Msg(errno, "write");
- close(s);
+ if (query)
+ {
+ /* Create a server socket so we can get back the result */
+ char *sp = SockPath + strlen(SockPath);
+ char query[] = "-queryX";
+ char c;
+ int r = -1;
+ for (c = 'A'; c <= 'Z'; c++)
+ {
+ query[6] = c;
+ strcpy(sp, query); /* XXX: strncpy? */
+ if ((r = MakeServerSocket()) >= 0)
+ break;
+ }
+ if (r < 0)
+ {
+ for (c = '0'; c <= '9'; c++)
+ {
+ query[6] = c;
+ strcpy(sp, query);
+ if ((r = MakeServerSocket()) >= 0)
+ break;
+ }
+ }
+
+ if (r < 0)
+ Panic(0, "Could not create a listening socket to read the results.");
+
+ strncpy(m.m.command.writeback, SockPath, sizeof(m.m.command.writeback) - 1);
+ m.m.command.writeback[sizeof(m.m.command.writeback) - 1] = '\0';
+
+ /* Send the message, then wait for a response */
+ signal(SIGCONT, QueryResultSuccess);
+ signal(SIG_BYE, QueryResultFail);
+ if (WriteMessage(s, &m))
+ Msg(errno, "write");
+ close(s);
+ while (!QueryResult)
+ pause();
+ signal(SIGCONT, SIG_DFL);
+ signal(SIG_BYE, SIG_DFL);
+
+ /* Read the result and spit it out to stdout */
+ ReceiveRaw(r);
+ unlink(SockPath);
+ if (QueryResult == 2) /* An error happened */
+ exit(1);
+ }
+ else
+ {
+ if (WriteMessage(s, &m))
+ Msg(errno, "write");
+ close(s);
+ }
}
+
diff --git a/src/comm.c b/src/comm.c
index 17fbd56..ba9806b 100644
--- a/src/comm.c
+++ b/src/comm.c
@@ -180,7 +180,7 @@ struct comm comms[RC_LAST + 1] =
{ "dinfo", NEED_DISPLAY|ARGS_0 },
{ "displays", NEED_LAYER|ARGS_0 },
{ "dumptermcap", NEED_FORE|ARGS_0 },
- { "echo", ARGS_12 },
+ { "echo", CAN_QUERY|ARGS_12 },
#ifdef ENCODINGS
{ "encoding", ARGS_12 },
#endif
@@ -207,12 +207,12 @@ struct comm comms[RC_LAST + 1] =
{ "hstatus", NEED_FORE|ARGS_1 },
{ "idle", ARGS_0|ARGS_ORMORE },
{ "ignorecase", ARGS_01 },
- { "info", NEED_LAYER|ARGS_0 },
+ { "info", CAN_QUERY|NEED_LAYER|ARGS_0 },
#ifdef ENCODINGS
{ "kanji", NEED_FORE|ARGS_12 },
#endif
{ "kill", NEED_FORE|ARGS_0 },
- { "lastmsg", NEED_DISPLAY|ARGS_0 },
+ { "lastmsg", CAN_QUERY|NEED_DISPLAY|ARGS_0 },
{ "layout", ARGS_1|ARGS_ORMORE},
{ "license", NEED_LAYER|ARGS_0 },
#ifdef LOCK
@@ -286,7 +286,7 @@ struct comm comms[RC_LAST + 1] =
#ifdef COPY_PASTE
{ "scrollback", NEED_FORE|ARGS_1 },
#endif
- { "select", ARGS_01 },
+ { "select", CAN_QUERY|ARGS_01 },
{ "sessionname", ARGS_01 },
{ "setenv", ARGS_012 },
{ "setsid", ARGS_1 },
@@ -311,8 +311,8 @@ struct comm comms[RC_LAST + 1] =
{ "termcap", ARGS_23 },
{ "termcapinfo", ARGS_23 },
{ "terminfo", ARGS_23 },
- { "time", ARGS_01 },
- { "title", NEED_FORE|ARGS_01 },
+ { "time", CAN_QUERY|ARGS_01 },
+ { "title", CAN_QUERY|NEED_FORE|ARGS_01 },
{ "umask", ARGS_1|ARGS_ORMORE },
{ "unbindall", ARGS_0 },
{ "unsetenv", ARGS_1 },
@@ -327,7 +327,7 @@ struct comm comms[RC_LAST + 1] =
{ "wall", NEED_DISPLAY|ARGS_1},
{ "width", ARGS_0123 },
{ "windowlist", ARGS_012 },
- { "windows", NEED_DISPLAY|ARGS_0 },
+ { "windows", CAN_QUERY|ARGS_0 },
{ "wrap", NEED_FORE|ARGS_01 },
#ifdef COPY_PASTE
{ "writebuf", ARGS_0123 },
diff --git a/src/comm.sh b/src/comm.sh
index a4b06e7..4fc8cb2 100644
--- a/src/comm.sh
+++ b/src/comm.sh
@@ -43,6 +43,8 @@ struct comm
#define NEED_FORE (1<<6) /* this command needs a fore window */
#define NEED_DISPLAY (1<<7) /* this command needs a display */
#define NEED_LAYER (1<<8) /* this command needs a layer */
+#define CAN_QUERY (1<<9) /* this command can be queried, i.e. used with -Q to
+ get back a result to stdout */
#define ARGS_01 (ARGS_0 | ARGS_PLUS1)
#define ARGS_02 (ARGS_0 | ARGS_PLUS2)
diff --git a/src/doc/screen.1 b/src/doc/screen.1
index 3ac5571..c26bbc8 100644
--- a/src/doc/screen.1
+++ b/src/doc/screen.1
@@ -305,6 +305,22 @@ there is no session to resume. 12 (or more) indicates that there are 2 (or
more) sessions to resume and you should specify which one to choose.
In all other cases \*Q-q\*U has no effect.
.TP 5
+.B \-Q
+Some commands now can be queried from a remote session using this
+flag, e.g. 'screen -Q windows'. The commands will send the
+response to the stdout of the querying process. If there was an
+error in the command, then the querying process will exit with
+a non-zero status.
+
+The commands that can be queried now are:
+ \fBecho\fP
+ \fBinfo\fP
+ \fBlastmsg\fP
+ \fBselect\fP
+ \fBtime\fP
+ \fBtitle\fP
+ \fBwindows\fP
+.TP 5
.BR \-r " [" \fIpid.tty.host ]
.PD 0
.TP 5
@@ -376,7 +392,6 @@ the \fB-d\fP or \fB-r\fP option to tell screen to look only for
attached or detached screen sessions. Note that this command doesn't
work if the session is password protected.
-
.SH "DEFAULT KEY BINDINGS"
.ta 12n 26n
As mentioned, each
diff --git a/src/doc/screen.texinfo b/src/doc/screen.texinfo
index 44d233e..f7371e1 100644
--- a/src/doc/screen.texinfo
+++ b/src/doc/screen.texinfo
@@ -374,6 +374,22 @@ there is no session to resume. 12 (or more) indicates that there are 2 (or
more) sessions to resume and you should specify which one to choose.
In all other cases @samp{-q} has no effect.
+@item -Q
+Some commands now can be queried from a remote session using this
+flag, e.g. 'screen -Q windows'. The commands will send the
+response to the stdout of the querying process. If there was an
+error in the command, then the querying process will exit with
+a non-zero status.
+
+The commands that can be queried now are:
+ @code{echo}
+ @code{info}
+ @code{lastmsg}
+ @code{select}
+ @code{time}
+ @code{title}
+ @code{windows}
+
@item -r [@var{pid.sessionname}]
@itemx -r @var{sessionowner}/[@var{pid.sessionname}]
Resume a detached @code{screen} session. No other options (except
diff --git a/src/extern.h b/src/extern.h
index 38a8d6e..dc5857e 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -241,7 +241,7 @@ extern void FreeTransTable __P((void));
extern int Attach __P((int));
extern void Attacher __P((void));
extern sigret_t AttacherFinit __P(SIGPROTOARG);
-extern void SendCmdMessage __P((char *, char *, char **));
+extern void SendCmdMessage __P((char *, char *, char **, int));
/* display.c */
extern struct display *MakeDisplay __P((char *, char *, char *, int, int, struct mode *));
diff --git a/src/process.c b/src/process.c
index 128b0e2..34ed63d 100644
--- a/src/process.c
+++ b/src/process.c
@@ -59,6 +59,7 @@ extern char *BellString, *ActivityString, *ShellProg, *ShellArgs[];
extern char *hstatusstring, *captionstring, *timestring;
extern char *wliststr, *wlisttit;
extern int captionalways;
+extern int queryflag;
extern char *hardcopydir, *screenlogfile, *logtstamp_string;
extern int log_flush, logtstamp_on, logtstamp_after;
extern char *VisualBellString;
@@ -1147,19 +1148,35 @@ int key;
return;
}
n = comms[nr].flags;
+ /* Commands will have a CAN_QUERY flag, depending on whether they have
+ * something to return on a query. For example, 'windows' can return a result,
+ * but 'other' cannot.
+ * If some command causes an error, then it should reset queryflag to -1, so that
+ * the process requesting the query can be notified that an error happened.
+ */
+ if (!(n & CAN_QUERY) && queryflag >= 0)
+ {
+ /* Query flag is set, but this command cannot be queried. */
+ Msg(0, "%s command cannot be queried.", comms[nr].name);
+ queryflag = -1;
+ return;
+ }
if ((n & NEED_DISPLAY) && display == 0)
{
Msg(0, "%s: %s: display required", rc_name, comms[nr].name);
+ queryflag = -1;
return;
}
if ((n & NEED_FORE) && fore == 0)
{
Msg(0, "%s: %s: window required", rc_name, comms[nr].name);
+ queryflag = -1;
return;
}
if ((n & NEED_LAYER) && flayer == 0)
{
Msg(0, "%s: %s: display or window required", rc_name, comms[nr].name);
+ queryflag = -1;
return;
}
if ((argc = CheckArgNum(nr, args)) < 0)
@@ -1171,6 +1188,7 @@ int key;
{
Msg(0, "%s: %s: permission denied (user %s)",
rc_name, comms[nr].name, (EffectiveAclUser ? EffectiveAclUser : D_user)->u_name);
+ queryflag = -1;
return;
}
}
@@ -1190,7 +1208,10 @@ int key;
else if (args[0][0] == '.' && !args[0][1])
{
if (!fore)
- Msg(0, "select . needs a window");
+ {
+ Msg(0, "select . needs a window");
+ queryflag = -1;
+ }
else
{
SetForeWindow(fore);
@@ -1199,6 +1220,8 @@ int key;
}
else if (ParseWinNum(act, &n) == 0)
SwitchWindow(n);
+ else if (queryflag >= 0)
+ queryflag = -1; /* ParseWinNum already prints out an appropriate error message. */
break;
#ifdef AUTO_NUKE
case RC_DEFAUTONUKE:
@@ -2026,6 +2049,13 @@ int key;
}
break;
case RC_TITLE:
+ if (queryflag >= 0)
+ {
+ if (fore)
+ Msg(0, "%s", fore->w_title);
+ else
+ queryflag = -1;
+ }
if (*args == 0)
InputAKA();
else
@@ -2635,7 +2665,10 @@ int key;
if (s)
Msg(0, "%s", s);
else
- Msg(0, "%s: 'echo [-n] [-p] \"string\"' expected.", rc_name);
+ {
+ Msg(0, "%s: 'echo [-n] [-p] \"string\"' expected.", rc_name);
+ queryflag = -1;
+ }
break;
case RC_BELL:
case RC_BELL_MSG:
@@ -5318,7 +5351,7 @@ int where;
continue;
if ((flags & 1) && display && p == D_fore)
continue;
- if (D_fore && D_fore->w_group != p->w_group)
+ if (display && D_fore && D_fore->w_group != p->w_group)
continue;
cmd = p->w_title;
@@ -5460,13 +5493,11 @@ int where;
char buf[1024];
char *s, *ss;
- if (!display)
- return;
- if (where == -1 && D_fore)
+ if (display && where == -1 && D_fore)
where = D_fore->w_number;
ss = AddWindows(buf, sizeof(buf), 0, where);
s = buf + strlen(buf);
- if (ss - buf > D_width / 2)
+ if (display && ss - buf > D_width / 2)
{
ss -= D_width / 2;
if (s - ss < D_width)
diff --git a/src/screen.c b/src/screen.c
index 92b2001..67cddbc 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -207,6 +207,7 @@ char *wlisttit;
int auto_detach = 1;
int iflag, rflag, dflag, lsflag, quietflag, wipeflag, xflag;
int cmdflag;
+int queryflag = -1;
int adaptflag;
#ifdef MULTIUSER
@@ -680,6 +681,10 @@ char **av;
case 'q':
quietflag = 1;
break;
+ case 'Q':
+ queryflag = 1;
+ cmdflag = 1;
+ break;
case 'r':
case 'R':
#ifdef MULTI
@@ -1176,7 +1181,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)
@@ -2105,6 +2110,9 @@ VA_DECL
}
else
printf("%s\r\n", buf);
+
+ if (queryflag >= 0)
+ write(queryflag, buf, strlen(buf));
}
/*
diff --git a/src/screen.h b/src/screen.h
index a151e38..fa4cc82 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -173,6 +173,7 @@ struct mode
#define MSG_WINCH 6
#define MSG_HANGUP 7
#define MSG_COMMAND 8
+#define MSG_QUERY 9
/*
* versions of struct msg:
@@ -227,6 +228,8 @@ struct msg
char cmd[MAXPATHLEN]; /* command */
int apid; /* pid of frontend */
char preselect[20];
+ char writeback[MAXPATHLEN]; /* The socket to write the result.
+ Only used for MSG_QUERY */
}
command;
char message[MAXPATHLEN * 2];
diff --git a/src/socket.c b/src/socket.c
index a174b72..70b57db 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -65,6 +65,7 @@ static void AskPassword __P((struct msg *));
extern char *RcFileName, *extra_incap, *extra_outcap;
extern int ServerSocket, real_uid, real_gid, eff_uid, eff_gid;
extern int dflag, iflag, rflag, lsflag, quietflag, wipeflag, xflag;
+extern int queryflag;
extern char *attach_tty, *LoginName, HostName[];
extern struct display *display, *displays;
extern struct win *fore, **wtab, *console_window, *windows;
@@ -1170,6 +1171,26 @@ ReceiveMsg()
FinishDetach(&m);
break;
#endif
+ case MSG_QUERY:
+ {
+ char *oldSockPath = SaveStr(SockPath);
+ strcpy(SockPath, m.m.command.writeback);
+ int s = MakeClientSocket(0);
+ strcpy(SockPath, oldSockPath);
+ Free(oldSockPath);
+ if (s >= 0)
+ {
+ queryflag = s;
+ DoCommandMsg(&m);
+ close(s);
+ }
+ else
+ queryflag = -1;
+
+ Kill(m.m.command.apid, (queryflag >= 0) ? SIGCONT : SIG_BYE); /* Send SIG_BYE if an error happened */
+ queryflag = -1;
+ }
+ break;
case MSG_COMMAND:
DoCommandMsg(&m);
break;
@@ -1178,6 +1199,32 @@ ReceiveMsg()
}
}
+void
+ReceiveRaw(s)
+int s;
+{
+ char rd[256];
+ int len = 0;
+#ifdef NAMEDPIPE
+ if (fcntl(s, F_SETFL, 0) == -1)
+ Panic(errno, "BLOCK fcntl");
+#else
+ struct sockaddr_un a;
+ len = sizeof(a);
+ if ((s = accept(s, (struct sockaddr *) &a, (void *)&len)) < 0)
+ {
+ Msg(errno, "accept");
+ return;
+ }
+#endif
+ while ((len = read(s, rd, 255)) > 0)
+ {
+ rd[len] = 0;
+ printf("%s", rd);
+ }
+ close(s);
+}
+
#if defined(_SEQUENT_) && !defined(NAMEDPIPE)
#undef connect
/*
@@ -1605,12 +1652,16 @@ struct msg *mp;
if (fc != fullcmd)
*--fc = 0;
if (Parse(fullcmd, fc - fullcmd, args, argl) <= 0)
- return;
+ {
+ /* XXX: Return some useful message back if MSG_QUERY */
+ return;
+ }
#ifdef MULTIUSER
user = *FindUserPtr(mp->m.attach.auser);
if (user == 0)
{
Msg(0, "Unknown user %s tried to send a command!", mp->m.attach.auser);
+ /* XXX: Return some useful message back if MSG_QUERY */
return;
}
#else
@@ -1620,6 +1671,7 @@ struct msg *mp;
if (user->u_password && *user->u_password)
{
Msg(0, "User %s has a password, cannot use -X option.", mp->m.attach.auser);
+ /* XXX: Return some useful message back if MSG_QUERY */
return;
}
#endif