diff options
author | Sadrul Habib Chowdhury <sadrul@users.sourceforge.net> | 2009-09-30 15:54:19 -0400 |
---|---|---|
committer | Sadrul Habib Chowdhury <sadrul@users.sourceforge.net> | 2009-09-30 15:54:19 -0400 |
commit | 8147d08647d59aba7accb748c42db2aba3f31bc4 (patch) | |
tree | 2decb5cf015d3b1899116d79cd2c11628fd2ce60 | |
parent | 7cb17d54cc8fca88e17d6d1e7be2fd49daef1b9d (diff) | |
download | screen-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.c | 67 | ||||
-rw-r--r-- | src/comm.c | 4 | ||||
-rw-r--r-- | src/comm.sh | 2 | ||||
-rw-r--r-- | src/extern.h | 2 | ||||
-rw-r--r-- | src/process.c | 12 | ||||
-rw-r--r-- | src/screen.c | 7 | ||||
-rw-r--r-- | src/screen.h | 3 | ||||
-rw-r--r-- | src/socket.c | 51 |
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); + } } @@ -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 |