summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSadrul Habib Chowdhury <sadrul@users.sourceforge.net>2009-09-30 15:54:19 -0400
committerSadrul Habib Chowdhury <sadrul@users.sourceforge.net>2009-09-30 15:54:19 -0400
commit8147d08647d59aba7accb748c42db2aba3f31bc4 (patch)
tree2decb5cf015d3b1899116d79cd2c11628fd2ce60
parent7cb17d54cc8fca88e17d6d1e7be2fd49daef1b9d (diff)
downloadscreen-8147d08647d59aba7accb748c42db2aba3f31bc4.tar.gz
'screen -Q <command>' to get back results.
This is the just the start of querying an existing session. The goal is to allow something like "windows=`screen -Q windows`" in a bash script to get back the results from the 'windows' command. Most of the framework is done. Now the commands need to be updated to specially deal with the queries.
-rw-r--r--src/attacher.c67
-rw-r--r--src/comm.c4
-rw-r--r--src/comm.sh2
-rw-r--r--src/extern.h2
-rw-r--r--src/process.c12
-rw-r--r--src/screen.c7
-rw-r--r--src/screen.h3
-rw-r--r--src/socket.c51
8 files changed, 138 insertions, 10 deletions
diff --git a/src/attacher.c b/src/attacher.c
index a416ec1..46c14ec 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,48 @@ 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)
+ 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 aedfe49..934ad23 100644
--- a/src/comm.c
+++ b/src/comm.c
@@ -206,12 +206,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
diff --git a/src/comm.sh b/src/comm.sh
index 44c83dd..190de58 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/extern.h b/src/extern.h
index e3e0a59..9e26883 100644
--- a/src/extern.h
+++ b/src/extern.h
@@ -239,7 +239,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 fa3d06c..1737dcf 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1144,6 +1144,18 @@ int key;
return;
}
n = comms[nr].flags;
+ /* XXX: 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 0
+ if (!(n & CAN_QUERY) && queryflag)
+ {
+ /* Query flag is set, but this command cannot be queried. */
+ Msg(0, "%s command cannot be queried.", comms[nr].name);
+ return;
+ }
+#endif
if ((n & NEED_DISPLAY) && display == 0)
{
Msg(0, "%s: %s: display required", rc_name, comms[nr].name);
diff --git a/src/screen.c b/src/screen.c
index e8f4cac..d09359a 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -205,6 +205,7 @@ char *wlisttit;
int auto_detach = 1;
int iflag, rflag, dflag, lsflag, quietflag, wipeflag, xflag;
int cmdflag;
+int queryflag;
int adaptflag;
#ifdef MULTIUSER
@@ -678,6 +679,10 @@ char **av;
case 'q':
quietflag = 1;
break;
+ case 'Q':
+ queryflag = 1;
+ cmdflag = 1;
+ break;
case 'r':
case 'R':
#ifdef MULTI
@@ -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);
exit(0);
}
else if (rflag || xflag)
diff --git a/src/screen.h b/src/screen.h
index d80f0d5..a5145e7 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -172,6 +172,7 @@ struct mode
#define MSG_WINCH 6
#define MSG_HANGUP 7
#define MSG_COMMAND 8
+#define MSG_QUERY 9
/*
* versions of struct msg:
@@ -226,6 +227,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 7832832..965a7d0 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -1156,14 +1156,58 @@ ReceiveMsg()
FinishDetach(&m);
break;
#endif
+ case MSG_QUERY:
+ /* Reset error buffer */
+ /* Reset output buffer */
+ /* FALLTHROUGH */
case MSG_COMMAND:
DoCommandMsg(&m);
+ if (m.type == MSG_QUERY)
+ {
+ char *oldSockPath = SaveStr(SockPath);
+ strcpy(SockPath, m.m.command.writeback);
+ int s = MakeClientSocket(0);
+ strcpy(SockPath, oldSockPath);
+ Free(oldSockPath);
+ if (s >= 0)
+ {
+ write(s, "So ...", 7);
+ close(s);
+ }
+ Kill(m.m.command.apid, SIGCONT); /* Send SIG_BYE if an error happened, instead */
+ }
break;
default:
Msg(0, "Invalid message (type %d).", m.type);
}
}
+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
/*
@@ -1590,12 +1634,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
@@ -1605,6 +1653,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