1999-10-04 14:52:39 -07:00
|
|
|
/*
|
2007-01-13 11:14:29 -08:00
|
|
|
* Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
|
2023-06-14 08:36:50 -07:00
|
|
|
* Copyright (C) 2004-2023 Kim Woelders
|
2005-03-19 08:40:18 -08:00
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
* of this software and associated documentation files (the "Software"), to
|
|
|
|
* deal in the Software without restriction, including without limitation the
|
|
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
|
|
* sell copies of the Software, and to permit persons to whom the Software is
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies of the Software, its documentation and marketing & publicity
|
|
|
|
* materials, and acknowledgment shall be given in the documentation, materials
|
|
|
|
* and software packages that this Software was used.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
|
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1999-10-04 14:52:39 -07:00
|
|
|
*/
|
2023-12-16 07:57:01 -08:00
|
|
|
#include "config.h"
|
2023-12-18 04:18:10 -08:00
|
|
|
#include <stdbool.h>
|
2023-12-16 07:57:01 -08:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2023-12-17 08:53:27 -08:00
|
|
|
#include <poll.h>
|
2023-12-16 07:57:01 -08:00
|
|
|
#include <X11/Xlib.h>
|
1999-08-17 15:56:46 -07:00
|
|
|
#include "E.h"
|
|
|
|
|
2023-12-17 10:31:56 -08:00
|
|
|
#if USE_LINEEDIT_EDITLINE
|
|
|
|
#define USE_LINEEDIT 1
|
|
|
|
#include <editline.h>
|
|
|
|
#elif USE_LINEEDIT_READLINE
|
|
|
|
#define USE_LINEEDIT 1
|
|
|
|
#include <readline/readline.h>
|
|
|
|
#include <readline/history.h>
|
|
|
|
#endif
|
|
|
|
|
2023-12-18 04:18:10 -08:00
|
|
|
#define PROMPT "eesh> "
|
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
Display *disp;
|
1999-08-17 15:56:46 -07:00
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
static Client *e;
|
2023-12-18 04:18:10 -08:00
|
|
|
static bool use_prompt;
|
|
|
|
static bool input_pending;
|
|
|
|
static bool reply_pending;
|
2004-07-01 02:27:30 -07:00
|
|
|
|
|
|
|
static void
|
|
|
|
process_line(char *line)
|
|
|
|
{
|
2023-12-18 04:18:10 -08:00
|
|
|
input_pending = false;
|
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
if (!line)
|
|
|
|
exit(0);
|
2004-07-01 02:27:30 -07:00
|
|
|
|
2023-12-17 10:31:56 -08:00
|
|
|
if (*line)
|
|
|
|
{
|
|
|
|
CommsSend(e, line);
|
|
|
|
XSync(disp, False);
|
|
|
|
reply_pending = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if USE_LINEEDIT
|
|
|
|
if (!use_prompt)
|
|
|
|
return;
|
|
|
|
rl_set_prompt("");
|
|
|
|
add_history(line);
|
|
|
|
#endif
|
2004-07-01 02:27:30 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
stdin_read(void)
|
|
|
|
{
|
2023-12-22 09:53:04 -08:00
|
|
|
static char buf[10240];
|
|
|
|
static int nin; // Bytes in buffer
|
2023-12-17 09:59:21 -08:00
|
|
|
int nr;
|
|
|
|
char *p;
|
2004-07-01 02:27:30 -07:00
|
|
|
|
2023-12-17 09:59:21 -08:00
|
|
|
nr = read(STDIN_FILENO, buf + nin, sizeof(buf) - 1 - nin);
|
|
|
|
if (nr <= 0)
|
|
|
|
exit(0);
|
|
|
|
nin += nr;
|
|
|
|
buf[nin] = '\0';
|
|
|
|
|
|
|
|
for (;;)
|
2023-10-21 02:04:12 -07:00
|
|
|
{
|
2023-12-17 09:59:21 -08:00
|
|
|
p = strchr(buf, '\n');
|
|
|
|
if (!p)
|
|
|
|
break;
|
|
|
|
|
|
|
|
*p++ = '\0'; // Terminate line at \n
|
|
|
|
|
|
|
|
process_line(buf);
|
|
|
|
if (*p == '\0')
|
2023-10-21 02:04:12 -07:00
|
|
|
{
|
2023-12-17 09:59:21 -08:00
|
|
|
nin = 0; // No more input
|
|
|
|
break;
|
2023-10-21 02:04:12 -07:00
|
|
|
}
|
2023-12-17 09:59:21 -08:00
|
|
|
|
|
|
|
// Move remaining data to start of buffer
|
|
|
|
nr = p - buf;
|
|
|
|
nin -= nr;
|
|
|
|
memmove(buf, buf + nr, nin);
|
2023-10-21 02:04:12 -07:00
|
|
|
}
|
2004-07-01 02:27:30 -07:00
|
|
|
}
|
|
|
|
|
2023-12-17 10:31:56 -08:00
|
|
|
#if USE_LINEEDIT
|
2023-12-22 09:53:04 -08:00
|
|
|
static void
|
|
|
|
stdin_state_setup(void)
|
|
|
|
{
|
2023-12-17 10:31:56 -08:00
|
|
|
rl_callback_handler_install("", process_line);
|
2023-12-22 09:53:04 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
stdin_state_restore(void)
|
|
|
|
{
|
2023-12-17 10:31:56 -08:00
|
|
|
rl_callback_handler_remove();
|
2023-12-22 09:53:04 -08:00
|
|
|
}
|
2023-12-17 10:31:56 -08:00
|
|
|
#endif
|
2023-12-22 09:53:04 -08:00
|
|
|
|
1999-08-17 15:56:46 -07:00
|
|
|
int
|
|
|
|
main(int argc, char **argv)
|
|
|
|
{
|
2023-10-21 02:04:12 -07:00
|
|
|
XEvent ev;
|
2023-12-16 07:57:01 -08:00
|
|
|
Window my_win, comms_win;
|
2023-10-21 02:04:12 -07:00
|
|
|
Client *me;
|
2023-12-23 04:20:50 -08:00
|
|
|
int rc, i;
|
2023-12-17 08:53:27 -08:00
|
|
|
struct pollfd pfd[2];
|
|
|
|
int nfd, timeout;
|
2023-10-21 02:04:12 -07:00
|
|
|
char *command, *s;
|
|
|
|
int len, l;
|
|
|
|
const char *space;
|
2023-12-18 04:18:10 -08:00
|
|
|
bool interactive;
|
1999-08-17 15:56:46 -07:00
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
for (i = 1; i < argc; i++)
|
|
|
|
{
|
|
|
|
s = argv[i];
|
|
|
|
if (*s != '-')
|
|
|
|
break;
|
2004-11-21 14:11:09 -08:00
|
|
|
|
2023-12-16 07:57:01 -08:00
|
|
|
if (!strcmp(argv[i], "-h") ||
|
|
|
|
!strcmp(argv[i], "-help") || !strcmp(argv[i], "--help"))
|
2023-10-21 02:04:12 -07:00
|
|
|
{
|
|
|
|
printf
|
|
|
|
("eesh sends commands to E\n\n"
|
|
|
|
"Examples:\n"
|
2023-12-16 07:57:01 -08:00
|
|
|
" eesh window_list all : Show window list\n"
|
|
|
|
" eesh win_op Pager-0 move 10 20 : Move Pager-0 to position 10,20\n\n");
|
2023-10-21 02:04:12 -07:00
|
|
|
printf("Use eesh by itself to enter the \"interactive mode\"\n"
|
|
|
|
" Ctrl-D will exit interactive mode\n"
|
|
|
|
" Use \"help\" from inside interactive mode for further assistance\n");
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
}
|
1999-08-17 15:56:46 -07:00
|
|
|
|
2023-12-16 07:57:01 -08:00
|
|
|
disp = XOpenDisplay(NULL);
|
2023-10-21 02:04:12 -07:00
|
|
|
if (!disp)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Failed to connect to X server\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
2004-07-01 02:27:30 -07:00
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
CommsInit();
|
|
|
|
comms_win = CommsFindCommsWindow();
|
|
|
|
my_win = CommsSetup(comms_win);
|
2004-07-01 02:27:30 -07:00
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
e = ClientCreate(comms_win);
|
|
|
|
me = ClientCreate(my_win);
|
2004-07-01 02:27:30 -07:00
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
CommsSend(e, "set clientname eesh");
|
|
|
|
CommsSend(e, "set version 0.2");
|
2004-11-21 14:11:09 -08:00
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
command = NULL;
|
|
|
|
space = "";
|
|
|
|
if (i < argc)
|
|
|
|
{
|
|
|
|
len = 0;
|
|
|
|
for (; i < argc; i++)
|
|
|
|
{
|
|
|
|
s = argv[i];
|
|
|
|
l = strlen(s);
|
|
|
|
command = EREALLOC(char, command, len + l + 4);
|
2007-01-16 17:10:44 -08:00
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
if (strchr(s, ' '))
|
|
|
|
l = snprintf(command + len, l + 4, "%s'%s'", space, s);
|
|
|
|
else
|
|
|
|
l = snprintf(command + len, l + 4, "%s%s", space, s);
|
|
|
|
len += l;
|
|
|
|
space = " ";
|
|
|
|
}
|
|
|
|
}
|
1999-09-21 19:16:37 -07:00
|
|
|
|
2023-12-18 04:18:10 -08:00
|
|
|
input_pending = false;
|
|
|
|
reply_pending = false;
|
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
if (command)
|
|
|
|
{
|
|
|
|
/* Non-interactive */
|
2023-12-18 04:18:10 -08:00
|
|
|
interactive = use_prompt = false;
|
2023-10-21 02:04:12 -07:00
|
|
|
CommsSend(e, command);
|
|
|
|
XSync(disp, False);
|
2023-12-18 04:18:10 -08:00
|
|
|
reply_pending = true;
|
2023-10-21 02:04:12 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Interactive */
|
2023-12-18 04:18:10 -08:00
|
|
|
interactive = true;
|
|
|
|
use_prompt = isatty(STDIN_FILENO);
|
2023-12-17 10:31:56 -08:00
|
|
|
#if USE_LINEEDIT
|
|
|
|
if (use_prompt)
|
|
|
|
{
|
|
|
|
stdin_state_setup();
|
|
|
|
atexit(stdin_state_restore);
|
|
|
|
}
|
|
|
|
#endif
|
2023-10-21 02:04:12 -07:00
|
|
|
}
|
1999-09-21 19:16:37 -07:00
|
|
|
|
2023-12-17 08:53:27 -08:00
|
|
|
memset(pfd, 0, sizeof(pfd));
|
|
|
|
pfd[0].fd = ConnectionNumber(disp);
|
|
|
|
pfd[0].events = POLLIN;
|
|
|
|
pfd[1].fd = STDIN_FILENO;
|
|
|
|
pfd[1].events = POLLIN;
|
|
|
|
nfd = command ? 1 : 2;
|
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
XSync(disp, False);
|
|
|
|
while (XPending(disp))
|
|
|
|
{
|
|
|
|
XNextEvent(disp, &ev);
|
|
|
|
switch (ev.type)
|
|
|
|
{
|
|
|
|
case ClientMessage:
|
|
|
|
s = CommsGet(me, &ev);
|
|
|
|
if (!s)
|
|
|
|
break;
|
2023-12-18 04:18:10 -08:00
|
|
|
reply_pending = false;
|
2023-10-21 02:04:12 -07:00
|
|
|
if (*s)
|
2023-12-18 04:18:10 -08:00
|
|
|
{
|
2023-10-21 02:04:12 -07:00
|
|
|
printf("%s", s);
|
2023-12-18 04:18:10 -08:00
|
|
|
fflush(stdout);
|
|
|
|
}
|
2023-10-21 02:04:12 -07:00
|
|
|
Efree(s);
|
2023-12-18 04:18:10 -08:00
|
|
|
if (!interactive)
|
2023-10-21 02:04:12 -07:00
|
|
|
goto done;
|
|
|
|
break;
|
|
|
|
case DestroyNotify:
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
2007-09-29 09:39:33 -07:00
|
|
|
|
2023-12-18 04:18:10 -08:00
|
|
|
if (use_prompt && !input_pending && !reply_pending)
|
|
|
|
{
|
2023-12-17 10:31:56 -08:00
|
|
|
#if USE_LINEEDIT
|
|
|
|
rl_set_prompt(PROMPT);
|
|
|
|
rl_forced_update_display();
|
|
|
|
#else
|
2023-12-18 04:18:10 -08:00
|
|
|
printf(PROMPT);
|
|
|
|
fflush(stdout);
|
2023-12-17 10:31:56 -08:00
|
|
|
#endif
|
2023-12-18 04:18:10 -08:00
|
|
|
}
|
|
|
|
|
2023-12-23 04:20:50 -08:00
|
|
|
timeout = reply_pending ? 10 : -1;
|
|
|
|
|
|
|
|
rc = poll(pfd, nfd, timeout);
|
|
|
|
if (rc < 0)
|
2023-10-21 02:04:12 -07:00
|
|
|
break;
|
2004-07-01 02:27:30 -07:00
|
|
|
|
2023-12-23 04:20:50 -08:00
|
|
|
if (rc == 0)
|
|
|
|
{
|
|
|
|
reply_pending = false;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2023-12-17 08:53:27 -08:00
|
|
|
if (pfd[1].revents)
|
2023-10-21 02:04:12 -07:00
|
|
|
{
|
2023-12-17 08:53:27 -08:00
|
|
|
if (pfd[1].revents & POLLIN)
|
|
|
|
{
|
2023-12-17 10:31:56 -08:00
|
|
|
input_pending = true;
|
|
|
|
#if USE_LINEEDIT
|
|
|
|
if (use_prompt)
|
|
|
|
rl_callback_read_char();
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
stdin_read();
|
2023-12-17 08:53:27 -08:00
|
|
|
}
|
|
|
|
if (pfd[1].revents & POLLHUP)
|
|
|
|
break;
|
2023-10-21 02:04:12 -07:00
|
|
|
}
|
|
|
|
}
|
2004-07-01 02:27:30 -07:00
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
done:
|
|
|
|
ClientDestroy(e);
|
|
|
|
ClientDestroy(me);
|
|
|
|
free(command);
|
2004-11-21 14:11:09 -08:00
|
|
|
|
2023-10-21 02:04:12 -07:00
|
|
|
return 0;
|
1999-08-17 15:56:46 -07:00
|
|
|
}
|