Fix segfault setting MenuFace pixmap style for menus.
[fvwm.git] / modules / FvwmConsole / FvwmConsole.c
blobedf3e586434298d8d96552d3c7c24358498750c8
1 /* -*-c-*- */
2 /*
3 * Fvwm command input interface.
5 * Copyright 1996, Toshi Isogai. No guarantees or warantees or anything
6 * are provided. Use this program at your own risk. Permission to use
7 * this program for any purpose is given,
8 * as long as the copyright is kept intact.
9 */
11 /* This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /* FIXME: The signal handling of this module is largely broken */
28 #include "config.h"
30 #include "FvwmConsole.h"
31 #include "libs/fio.h"
32 #include "libs/fvwmsignal.h"
34 /* using ParseModuleArgs now */
35 static ModuleArgs* module;
37 int Fd[2]; /* pipe to fvwm */
38 int Ns = -1; /* socket handles */
39 char Name[80]; /* name of this program in executable format */
40 char *S_name = NULL; /* socket name */
42 void server(void);
43 RETSIGTYPE DeadPipe(int);
44 void ErrMsg(char *msg);
45 void SigHandler(int);
47 void clean_up(void)
49 if (Ns != -1)
51 close(Ns);
52 Ns = -1;
54 if (S_name != NULL)
56 unlink(S_name);
57 S_name = NULL;
60 return;
64 * signal handler
66 RETSIGTYPE DeadPipe(int dummy)
68 clean_up();
69 exit(0);
71 SIGNAL_RETURN;
74 RETSIGTYPE SigHandler(int dummy)
76 clean_up();
77 exit(0);
79 SIGNAL_RETURN;
82 RETSIGTYPE ReapChildren(int sig)
84 fvwmReapChildren(sig);
86 SIGNAL_RETURN;
89 int main(int argc, char *argv[])
91 char client[120];
92 char **eargv;
93 int i, j, k;
94 char *xterm_pre[] = { "-title", Name, "-name", Name, NULL };
95 char *xterm_post[] = { "-e", NULL, NULL };
96 int clpid;
98 /* Why is this not just put in the initializer of xterm_a?
99 * Apparently, it is a non-standard extension to use a non-constant
100 * address (of client) in an initializer (of xterm_a).
102 xterm_post[1] = client;
104 module = ParseModuleArgs(argc, argv, 0); /* we don't use an alias */
105 if (module == NULL)
107 fprintf(
108 stderr, "FvwmConsole version "VERSION" should only be"
109 " executed by fvwm!\n");
110 exit(1);
112 strcpy(Name, module->name);
113 /* construct client's name */
114 strcpy(client, argv[0]);
115 strcat(client, "C");
116 eargv =(char **)safemalloc((argc+12)*sizeof(char *));
117 /* copy arguments */
118 eargv[0] = XTERM;
119 j = 1;
120 for (k = 0; xterm_pre[k] != NULL; j++, k++)
122 eargv[j] = xterm_pre[k];
124 for (i = 0; i< module->user_argc; i++)
126 if (!strcmp(module->user_argv[i], "-e"))
128 i++;
129 break;
131 else if (!strcmp(module->user_argv[i], "-terminal"))
133 i++;
134 if (i < module->user_argc)
135 /* use alternative terminal emulator */
136 eargv[0] = module->user_argv[i];
138 else
140 eargv[j++] = module->user_argv[i];
143 for (k = 0; xterm_post[k] != NULL; j++, k++)
145 eargv[j] = xterm_post[k];
148 /* copy rest of -e args */
149 for (; i<module->user_argc; i++, j++)
151 eargv[j-1] = module->user_argv[i];
153 eargv[j] = NULL;
154 signal(SIGCHLD, ReapChildren);
155 /* Dead pipes mean fvwm died */
156 signal(SIGPIPE, DeadPipe);
157 signal(SIGINT, SigHandler);
158 signal(SIGQUIT, SigHandler);
159 signal(SIGALRM, SigHandler);
161 Fd[0] = module->to_fvwm;
162 Fd[1] = module->from_fvwm;
164 /* launch xterm with client */
165 clpid = fork();
166 if (clpid < 0)
168 ErrMsg("client forking");
170 else if (clpid == 0)
172 execvp(*eargv, eargv);
173 ErrMsg("exec");
175 /* tell fvwm we're running */
176 SendFinishedStartupNotification(Fd);
178 server();
180 return 0;
184 * setup server and communicate with fvwm and the client
186 void server(void)
188 struct sockaddr_un sas, csas;
189 int len;
190 socklen_t clen; /* length of sockaddr */
191 char buf[MAX_COMMAND_SIZE]; /* command line buffer */
192 char *tline;
193 char ver[40];
194 fd_set fdset;
195 char *home;
196 int s;
197 int msglen;
198 int rc;
200 /* make a socket */
201 s = socket(AF_UNIX, SOCK_STREAM, 0);
202 if (s < 0 )
204 ErrMsg("socket");
207 /* name the socket */
208 home = getenv("FVWM_USERDIR");
209 S_name = safemalloc(strlen(home) + sizeof(S_NAME) + 1);
210 strcpy(S_name, home);
211 strcat(S_name, S_NAME);
213 sas.sun_family = AF_UNIX;
214 strcpy(sas.sun_path, S_name);
215 /* bind the above name to the socket: first, erase the old socket */
216 unlink(S_name);
217 len = sizeof(sas) - sizeof(sas.sun_path) + strlen(sas.sun_path);
218 umask(0077);
219 rc = bind(s, (struct sockaddr *)&sas, len);
220 if (rc < 0)
222 ErrMsg("bind");
224 else
226 /* don't wait forever for connections */
227 alarm(FVWMCONSOLE_CONNECTION_TO_SECS);
228 /* listen to the socket */
229 rc = listen(s, 5);
230 alarm(0);
231 if (rc < 0)
233 ErrMsg("listen");
235 /* accept connections */
236 clen = sizeof(csas);
237 Ns = accept(s, (struct sockaddr *)&csas, &clen);
238 if (Ns < 0)
240 ErrMsg("accept");
243 /* send config lines to Client */
244 tline = NULL;
245 fvwm_send(Ns, C_BEG, strlen(C_BEG), 0);
246 GetConfigLine(Fd, &tline);
247 while (tline != NULL)
249 if (strlen(tline) > 1)
251 fvwm_send(Ns, tline, strlen(tline), 0);
252 fvwm_send(Ns, "\n", 1, 0);
254 GetConfigLine(Fd, &tline);
256 fvwm_send(Ns, C_END, strlen(C_END), 0);
257 strcpy(ver, "*");
258 strcpy(ver, module->name);
259 strcat(ver, " version ");
260 strcat(ver, VERSION VERSIONINFO);
261 strcat(ver, "\n");
262 fvwm_send(Ns, ver, strlen(ver), 0);
264 while (1)
266 FD_ZERO(&fdset);
267 FD_SET(Ns, &fdset);
268 FD_SET(Fd[1], &fdset);
270 fvwmSelect(FD_SETSIZE, SELECT_FD_SET_CAST &fdset, 0, 0, NULL);
271 if (FD_ISSET(Fd[1], &fdset))
273 FvwmPacket* packet = ReadFvwmPacket(Fd[1]);
275 if (packet == NULL)
277 clean_up();
278 exit(0);
280 else
282 if (packet->type == M_PASS)
284 msglen = strlen(
285 (char *)&(packet->body[3]));
286 if (msglen > MAX_MESSAGE_SIZE-2)
288 msglen = MAX_MESSAGE_SIZE-2;
290 fvwm_send(
291 Ns, (char *)&(packet->body[3]),
292 msglen, 0);
296 if (FD_ISSET(Ns, &fdset))
298 int len;
299 int rc;
301 rc = fvwm_recv(Ns, buf, MAX_COMMAND_SIZE, 0);
302 if (rc == 0)
304 /* client is terminated */
305 clean_up();
306 exit(0);
308 /* process the own unique commands */
309 len = strlen(buf);
310 if (len > 0 && buf[len - 1] == '\n')
312 buf[len - 1] = '\0';
314 /* send command */
315 SendText(Fd, buf, 0);
321 * print error message on stderr and exit
323 void ErrMsg(char *msg)
325 fprintf(
326 stderr, "%s server error in %s, errno %d: %s\n", Name, msg,
327 errno, strerror(errno));
328 clean_up();
329 exit(1);