1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  * Copyright (C) 2004-2020 Kim Woelders
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to
7  * deal in the Software without restriction, including without limitation the
8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9  * sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies of the Software, its documentation and marketing & publicity
14  * materials, and acknowledgment shall be given in the documentation, materials
15  * and software packages that this Software was used.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include <sys/select.h>
25 #include "E.h"
26 #include <sys/select.h>
27 
28 /* Global vars */
29 Display            *disp;
30 
31 static char         buf[10240];
32 static int          stdin_state;
33 static char        *display_name;
34 static Client      *e;
35 static Window       my_win, comms_win;
36 
37 static void
process_line(char * line)38 process_line(char *line)
39 {
40    if (!line)
41       exit(0);
42    if (*line == '\0')
43       return;
44 
45    CommsSend(e, line);
46    XSync(disp, False);
47 }
48 
49 static void
stdin_state_setup(void)50 stdin_state_setup(void)
51 {
52    stdin_state = fcntl(0, F_GETFL, 0);
53    fcntl(0, F_SETFL, O_NONBLOCK);
54 }
55 
56 static void
stdin_state_restore(void)57 stdin_state_restore(void)
58 {
59    fcntl(0, F_SETFL, stdin_state);
60 }
61 
62 static void
stdin_read(void)63 stdin_read(void)
64 {
65    static int          j = 0;
66    int                 k, ret;
67 
68    k = 0;
69    while ((ret = read(0, &(buf[j]), 1) > 0))
70      {
71 	k = 1;
72 	if (buf[j] == '\n')
73 	  {
74 	     buf[j] = 0;
75 	     if (strlen(buf) > 0)
76 		process_line(buf);
77 	     j = -1;
78 	  }
79 	j++;
80      }
81    if ((ret < 0) || ((k == 0) && (ret == 0)))
82       exit(0);
83 }
84 
85 int
main(int argc,char ** argv)86 main(int argc, char **argv)
87 {
88    XEvent              ev;
89    Client             *me;
90    int                 i;
91    fd_set              fd;
92    char               *command, *s;
93    char                mode;
94    int                 len, l;
95 
96    mode = 0;
97    display_name = NULL;
98    command = NULL;
99 #ifdef __clang_analyzer__
100    /* Seems not to understand asm FD_ZERO() */
101    memset(&fd, 0, sizeof(fd));
102 #endif
103 
104    for (i = 1; i < argc; i++)
105      {
106 	s = argv[i];
107 	if (*s != '-')
108 	   break;
109 
110 	if (!strcmp(argv[i], "-e"))
111 	  {
112 	     mode = -1;
113 	  }
114 	else if (!strcmp(argv[i], "-ewait"))
115 	  {
116 	     mode = 1;
117 	  }
118 	else if (!strcmp(argv[i], "-display"))
119 	  {
120 	     if (i != (argc - 1))
121 	       {
122 		  display_name = argv[++i];
123 		  display_name = Estrdup(display_name);
124 	       }
125 	  }
126 	else if ((!strcmp(argv[i], "-h")) ||
127 		 (!strcmp(argv[i], "-help")) || (!strcmp(argv[i], "--help")))
128 	  {
129 	     printf
130 		("eesh sends commands to E\n\n"
131 		 "Examples:\n"
132 		 "  eesh Command to Send to E then wait for a reply then exit\n"
133 		 "  eesh -ewait \"Command to Send to E then wait for a reply then exit\"\n"
134 		 "  eesh -e \"Command to Send to Enlightenment then exit\"\n\n");
135 	     printf("Use eesh by itself to enter the \"interactive mode\"\n"
136 		    "  Ctrl-D will exit interactive mode\n"
137 		    "  Use \"help\" from inside interactive mode for further assistance\n");
138 	     exit(0);
139 	  }
140      }
141 
142    /* Open a connection to the diplay nominated by the DISPLAY variable */
143    /* Or set with the -display option */
144    disp = XOpenDisplay(display_name);
145    if (!disp)
146      {
147 	fprintf(stderr, "Failed to connect to X server\n");
148 	exit(1);
149      }
150 
151    CommsInit();
152    comms_win = CommsFindCommsWindow();
153    my_win = CommsSetup(comms_win);
154 
155    e = ClientCreate(comms_win);
156    me = ClientCreate(my_win);
157 
158    CommsSend(e, "set clientname eesh");
159    CommsSend(e, "set version 0.2");
160 #if 0				/* Speed it up */
161    CommsSend(e, "set author The Rasterman");
162    CommsSend(e, "set email raster@rasterman.com");
163    CommsSend(e, "set web http://www.enlightenment.org");
164 /* CommsSend(e, "set address NONE"); */
165    CommsSend(e, "set info Enlightenment IPC Shell - talk to E direct");
166 /* CommsSend(e, "set pixmap 0"); */
167 #endif
168 
169    if (!command && i < argc)
170      {
171 	mode = 1;
172 	len = 0;
173 	for (; i < argc; i++)
174 	  {
175 	     l = strlen(argv[i]);
176 	     command = EREALLOC(char, command, len + l + 2);
177 
178 	     if (len)
179 		command[len++] = ' ';
180 	     strcpy(command + len, argv[i]);
181 	     len += l;
182 	  }
183      }
184 
185    if (command)
186      {
187 	/* Non-interactive */
188 	CommsSend(e, command);
189 	XSync(disp, False);
190 #if 0				/* No - Wait for ack */
191 	if (mode <= 0)
192 	   goto done;
193 #endif
194      }
195    else
196      {
197 	/* Interactive */
198 	stdin_state_setup();
199 	atexit(stdin_state_restore);
200      }
201 
202    for (;;)
203      {
204 	XSync(disp, False);
205 	while (XPending(disp))
206 	  {
207 	     XNextEvent(disp, &ev);
208 	     switch (ev.type)
209 	       {
210 	       case ClientMessage:
211 		  s = CommsGet(me, &ev);
212 		  if (!s)
213 		     break;
214 		  if (*s)
215 		     printf("%s", s);
216 		  fflush(stdout);
217 		  Efree(s);
218 		  if (mode)
219 		     goto done;
220 		  break;
221 	       case DestroyNotify:
222 		  goto done;
223 	       }
224 	  }
225 
226 	FD_ZERO(&fd);
227 	if (!command)
228 	   FD_SET(0, &fd);
229 	FD_SET(ConnectionNumber(disp), &fd);
230 
231 	if (select(ConnectionNumber(disp) + 1, &fd, NULL, NULL, NULL) < 0)
232 	   break;
233 
234 	if (FD_ISSET(0, &fd))
235 	  {
236 	     stdin_read();
237 	  }
238      }
239 
240  done:
241    ClientDestroy(e);
242    ClientDestroy(me);
243    free(command);
244 
245    return 0;
246 }
247 
248 #if !USE_LIBC_STRDUP
249 char               *
Estrdup(const char * s)250 Estrdup(const char *s)
251 {
252    char               *ss;
253    int                 sz;
254 
255    if (!s)
256       return NULL;
257    sz = strlen(s);
258    ss = EMALLOC(char, sz + 1);
259    memcpy(ss, s, sz + 1);
260 
261    return ss;
262 }
263 #endif
264