cvsimport
[fvwm.git] / modules / FvwmCpp / FvwmCpp.c
blob2b8e0d4eccf20d5c2ae85b163458b352183c41a8
1 /* -*-c-*- */
2 /* This module, and the entire FvwmCpp program, and the concept for
3 * interfacing this module to the Window Manager, are all original work
4 * by Robert Nation
6 * Copyright 1994, Robert Nation
7 * No guarantees or warantees or anything
8 * are provided or implied in any way whatsoever. Use this program at your
9 * own risk. Permission to use this program for any purpose is given,
10 * as long as the copyright is kept intact. */
12 /* This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "config.h"
29 #include <stdio.h>
30 #include <signal.h>
31 #include <fcntl.h>
32 #include <sys/wait.h>
33 #include "libs/ftime.h"
34 #include <unistd.h>
35 #include <ctype.h>
36 #include <pwd.h>
37 #include <sys/param.h>
38 #include <sys/types.h>
39 #include <netdb.h>
41 #include <X11/Xlib.h>
42 #include <X11/Xutil.h>
43 #include <X11/Xproto.h>
44 #include <X11/Xatom.h>
45 #include <X11/Intrinsic.h>
47 #include "libs/Module.h"
48 #include "libs/fvwm_sys_stat.h"
50 #include "FvwmCpp.h"
51 #include "libs/fvwmlib.h"
52 #include "libs/FShape.h"
53 #include "libs/PictureBase.h"
54 #include "libs/FSMlib.h"
55 #include "libs/Strings.h"
56 #include "libs/System.h"
57 #include <X11/StringDefs.h>
58 #include <X11/Shell.h>
59 #define Resolution(pixels, mm) ((((pixels) * 2000 / (mm)) + 1) / 2)
61 char *MyName;
62 int fd[2];
64 long Vx, Vy;
65 static char *MkDef(char *name, char *def);
66 static char *MkNum(char *name,int def);
67 static char *cpp_defs(Display *display, const char *host, char *m4_options, char *config_file);
68 #define MAXHOSTNAME 255
69 #define EXTRA 20
71 char *cpp_prog = FVWM_CPP; /* Name of the cpp program */
73 char cpp_options[BUFSIZ];
74 char cpp_outfile[BUFSIZ]="";
79 * Procedure:
80 * main - start of module
83 int main(int argc, char **argv)
85 Display *dpy; /* which display are we talking to */
86 char *temp, *s;
87 char *display_name = NULL;
88 char *filename = NULL;
89 char *tmp_file;
90 int i;
91 int debug = 0;
92 int lock = 0;
93 int noread = 0;
94 char *user_dir;
96 /* Figure out the working directory and go to it */
97 user_dir = getenv("FVWM_USERDIR");
98 if (user_dir != NULL)
100 if (chdir(user_dir) < 0)
101 fprintf(stderr, "%s: <<Warning>> chdir to %s failed in cpp_defs",
102 MyName, user_dir);
105 sprintf(cpp_options, "-I'%s' ", FVWM_DATADIR);
107 /* Record the program name for error messages */
108 temp = argv[0];
110 s=strrchr(argv[0], '/');
111 if (s != NULL)
112 temp = s + 1;
114 MyName = safemalloc(strlen(temp)+2);
115 strcpy(MyName,"*");
116 strcat(MyName, temp);
118 if(argc < 6)
120 fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName,
121 VERSION);
122 exit(1);
125 /* We should exit if our fvwm pipes die */
126 signal (SIGPIPE, DeadPipe);
128 fd[0] = atoi(argv[1]);
129 fd[1] = atoi(argv[2]);
131 for(i=6;i<argc;i++)
133 /* leaving this in just in case-- any option starting with '-'
134 will get passed on to cpp anyway */
135 if(strcasecmp(argv[i],"-cppopt") == 0)
137 strcat(cpp_options, argv[++i]);
138 strcat(cpp_options, " ");
140 else if (strcasecmp(argv[i], "-cppprog") == 0)
142 cpp_prog = argv[++i];
144 else if(strcasecmp(argv[i], "-outfile") == 0)
146 strcpy(cpp_outfile,argv[++i]);
148 else if(strcasecmp(argv[i], "-debug") == 0)
150 debug = 1;
152 else if(strcasecmp(argv[i], "-lock") == 0)
154 lock = 1;
156 else if(strcasecmp(argv[i], "-noread") == 0)
158 noread = 1;
160 else if (strncasecmp(argv[i],"-",1) == 0)
162 /* pass on any other arguments starting with '-' to cpp */
163 strcat(cpp_options, argv[i]);
164 strcat(cpp_options, " ");
166 else
167 filename = argv[i];
170 /* If we don't have a cpp, stop right now. */
171 if (!cpp_prog || cpp_prog[0] == '\0') {
172 fprintf(stderr, "%s: no C preprocessor program specified\n", MyName);
173 exit(1);
176 if (!filename)
178 fprintf(stderr, "%s: no file specified.\n", MyName);
179 exit(1);
181 for(i=0;i<strlen(filename);i++)
182 if((filename[i] == '\n')||(filename[i] == '\r'))
184 filename[i] = 0;
187 if (!(dpy = XOpenDisplay(display_name)))
189 fprintf(stderr,"%s: can't open display %s",
190 MyName, XDisplayName(display_name));
191 exit (1);
194 /* set up G */
195 PictureInitCMap(dpy);
197 /* tell fvwm we're running if -lock is not used */
198 if (!lock)
199 SendFinishedStartupNotification(fd);
201 tmp_file = cpp_defs(dpy, display_name,cpp_options, filename);
203 if (!noread)
205 char *read_string = CatString3("Read '", tmp_file, "'");
206 SendText(fd, read_string, 0);
209 /* tell fvwm to continue if -lock is used */
210 if (lock)
211 SendFinishedStartupNotification(fd);
213 /* For a debugging version, we may wish to omit this part. */
214 /* I'll let some cpp advocates clean this up */
215 if (!debug)
217 char *delete_string;
218 char *delete_file = tmp_file;
219 if (tmp_file[0] != '/' && user_dir != NULL)
221 delete_file = safestrdup(CatString3(user_dir, "/", tmp_file));
223 delete_string = CatString3("Exec exec /bin/rm '", delete_file, "'");
224 SendText(fd, delete_string, 0);
227 return 0;
232 static char *cpp_defs(Display *display, const char *host, char *cpp_options, char *config_file)
234 Screen *screen;
235 Visual *visual;
236 char client[MAXHOSTNAME], server[MAXHOSTNAME], *colon;
237 char ostype[BUFSIZ];
238 char options[BUFSIZ];
239 static char tmp_name[BUFSIZ];
240 struct hostent *hostname;
241 char *vc; /* Visual Class */
242 FILE *tmpf;
243 struct passwd *pwent;
244 int fd;
245 int ScreenWidth, ScreenHeight;
246 int Mscreen;
248 /* Generate a temporary filename. Honor the TMPDIR environment variable,
249 if set. Hope nobody deletes this file! */
251 if (strlen(cpp_outfile) == 0)
253 if ((vc=getenv("TMPDIR")))
255 strcpy(tmp_name, vc);
257 else
259 strcpy(tmp_name, "/tmp");
261 strcat(tmp_name, "/fvwmrcXXXXXX");
262 fd = fvwm_mkstemp(tmp_name);
263 if (fd == -1)
265 fprintf(
266 stderr,
267 "[FvwmCpp][cpp_def] fvwm_mkstemp failed %s\n",
268 tmp_name);
269 exit(0377);
272 else
274 strcpy(tmp_name,cpp_outfile);
276 * check to make sure it doesn't exist already, to prevent
277 * security hole
279 /* first try to unlink it */
280 unlink(tmp_name);
281 fd = open(
282 tmp_name, O_WRONLY|O_EXCL|O_CREAT,
283 FVWM_S_IRUSR | FVWM_S_IWUSR);
284 if (fd < 0)
286 fprintf(
287 stderr,
288 "[FvwmCpp][cpp_defs] error opening file %s\n",
289 tmp_name);
290 exit(0377);
293 close(fd);
296 * Create the appropriate command line to run cpp, and
297 * open a pipe to the command.
300 sprintf(options, "%s %s >%s\n", cpp_prog, cpp_options, tmp_name);
301 tmpf = popen(options, "w");
302 if (tmpf == NULL)
304 fprintf(
305 stderr,
306 "[FvwmCpp][cpp_defs] Cannot open pipe to cpp\n");
307 exit(0377);
310 gethostname(client,MAXHOSTNAME);
312 getostype (ostype, sizeof ostype);
314 hostname = gethostbyname(client);
315 strcpy(server, XDisplayName(host));
316 colon = strchr(server, ':');
317 if (colon != NULL) *colon = '\0';
318 if ((server[0] == '\0') || (!strcmp(server, "unix")))
319 strcpy(server, client); /* must be connected to :0 or unix:0 */
321 /* TWM_TYPE is fvwm, for completeness */
323 fputs(MkDef("TWM_TYPE", "fvwm"), tmpf);
325 /* The machine running the X server */
326 fputs(MkDef("SERVERHOST", server), tmpf);
327 /* The machine running the window manager process */
328 fputs(MkDef("CLIENTHOST", client), tmpf);
329 if (hostname)
330 fputs(MkDef("HOSTNAME", (char *)hostname->h_name), tmpf);
331 else
332 fputs(MkDef("HOSTNAME", (char *)client), tmpf);
334 fputs(MkDef("OSTYPE", ostype), tmpf);
336 pwent=getpwuid(geteuid());
337 fputs(MkDef("USER", pwent->pw_name), tmpf);
339 fputs(MkDef("HOME", getenv("HOME")), tmpf);
340 fputs(MkNum("VERSION", ProtocolVersion(display)), tmpf);
341 fputs(MkNum("REVISION", ProtocolRevision(display)), tmpf);
342 fputs(MkDef("VENDOR", ServerVendor(display)), tmpf);
343 fputs(MkNum("RELEASE", VendorRelease(display)), tmpf);
345 Mscreen= DefaultScreen(display);
346 fputs(MkNum("SCREEN", Mscreen), tmpf);
348 ScreenWidth = DisplayWidth(display,Mscreen);
349 ScreenHeight = DisplayHeight(display,Mscreen);
350 fputs(MkNum("WIDTH", DisplayWidth(display,Mscreen)), tmpf);
351 fputs(MkNum("HEIGHT", DisplayHeight(display,Mscreen)), tmpf);
353 screen = ScreenOfDisplay(display, Mscreen);
354 fputs(MkNum("X_RESOLUTION",Resolution(screen->width,screen->mwidth)),
355 tmpf);
356 fputs(MkNum("Y_RESOLUTION",Resolution(screen->height,screen->mheight)),
357 tmpf);
358 fputs(MkNum("PLANES",DisplayPlanes(display, Mscreen)), tmpf);
360 visual = DefaultVisualOfScreen(screen);
361 fputs(MkNum("BITS_PER_RGB", visual->bits_per_rgb), tmpf);
363 switch(visual->class)
365 case(StaticGray):
366 vc = "StaticGray";
367 break;
368 case(GrayScale):
369 vc = "GrayScale";
370 break;
371 case(StaticColor):
372 vc = "StaticColor";
373 break;
374 case(PseudoColor):
375 vc = "PseudoColor";
376 break;
377 case(TrueColor):
378 vc = "TrueColor";
379 break;
380 case(DirectColor):
381 vc = "DirectColor";
382 break;
383 default:
384 vc = "NonStandard";
385 break;
387 fputs(MkDef("CLASS", vc), tmpf);
389 switch(Pvisual->class)
391 case(StaticGray):
392 vc = "StaticGray";
393 break;
394 case(GrayScale):
395 vc = "GrayScale";
396 break;
397 case(StaticColor):
398 vc = "StaticColor";
399 break;
400 case(PseudoColor):
401 vc = "PseudoColor";
402 break;
403 case(TrueColor):
404 vc = "TrueColor";
405 break;
406 case(DirectColor):
407 vc = "DirectColor";
408 break;
409 default:
410 vc = "NonStandard";
411 break;
413 fputs(MkDef("FVWM_CLASS", vc), tmpf);
415 if (visual->class != StaticGray && visual->class != GrayScale)
416 fputs(MkDef("COLOR", "Yes"), tmpf);
417 else
418 fputs(MkDef("COLOR", "No"), tmpf);
420 if (Pvisual->class != StaticGray && Pvisual->class != GrayScale)
421 fputs(MkDef("FVWM_COLOR", "Yes"), tmpf);
422 else
423 fputs(MkDef("FVWM_COLOR", "No"), tmpf);
425 fputs(MkDef("FVWM_VERSION", VERSION), tmpf);
427 /* Add options together */
428 *options = '\0';
429 if (FHaveShapeExtension)
430 strcat(options, "SHAPE ");
432 if (XpmSupport)
433 strcat(options, "XPM ");
435 strcat(options, "Cpp ");
437 fputs(MkDef("OPTIONS", options), tmpf);
439 fputs(MkDef("FVWM_MODULEDIR", FVWM_MODULEDIR), tmpf);
440 fputs(MkDef("FVWM_DATADIR", FVWM_DATADIR), tmpf);
442 if ((vc = getenv("FVWM_USERDIR")))
443 fputs(MkDef("FVWM_USERDIR", vc), tmpf);
445 if (SessionSupport && (vc = getenv("SESSION_MANAGER")))
446 fputs(MkDef("SESSION_MANAGER", vc), tmpf);
450 * At this point, we've sent the definitions to cpp. Just include
451 * the fvwmrc file now.
454 fprintf(tmpf, "#include \"%s\"\n", config_file);
456 pclose(tmpf);
457 return(tmp_name);
466 * Procedure:
467 * SIGPIPE handler - SIGPIPE means fvwm is dying
470 RETSIGTYPE DeadPipe(int nonsense)
472 exit(0);
473 SIGNAL_RETURN;
476 static char *MkDef(char *name, char *def)
478 char *cp = NULL;
479 int n;
481 /* Get space to hold everything, if needed */
483 n = EXTRA + strlen(name) + strlen(def);
484 cp = safemalloc(n);
486 sprintf(cp, "#define %s %s\n",name,def);
488 return(cp);
491 static char *MkNum(char *name,int def)
493 char num[20];
495 sprintf(num, "%d", def);
497 return(MkDef(name, num));