2 /* This module, and the entire FvwmM4 program, and the concept for
3 * interfacing this module to the Window Manager, are all original work
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
33 #include "libs/ftime.h"
37 #include <sys/param.h>
38 #include <sys/types.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/Strings.h"
49 #include "libs/System.h"
50 #include "libs/fvwm_sys_stat.h"
53 #include "libs/fvwmlib.h"
54 #include "libs/FShape.h"
55 #include "libs/PictureBase.h"
56 #include "libs/FSMlib.h"
57 #include <X11/StringDefs.h>
58 #include <X11/Shell.h>
59 #define Resolution(pixels, mm) ((((pixels) * 2000 / (mm)) + 1) / 2)
65 static char *MkDef(char *name
, char *def
);
66 static char *MkNum(char *name
,int def
);
67 static char *m4_defs(Display
*display
, const char *host
, char *m4_options
, char *config_file
);
68 #define MAXHOSTNAME 255
71 int m4_enable
; /* use m4? */
72 int m4_prefix
; /* Do GNU m4 prefixing (-P) */
73 int m4_prefix_defines
; /* Add "m4_" to the names of the defines */
74 char m4_options
[BUFSIZ
]; /* Command line options to m4 */
75 char m4_outfile
[BUFSIZ
] = ""; /* The output filename for m4 */
76 char *m4_prog
= "m4"; /* Name of the m4 program */
77 int m4_default_quotes
; /* Use default m4 quotes */
78 char *m4_startquote
= "`"; /* Left quote characters for m4 */
79 char *m4_endquote
= "'"; /* Right quote characters for m4 */
85 * main - start of module
88 int main(int argc
, char **argv
)
90 Display
*dpy
; /* which display are we talking to */
92 char *display_name
= NULL
;
93 char *filename
= NULL
;
102 /* Figure out the working directory and go to it */
103 user_dir
= getenv("FVWM_USERDIR");
104 if (user_dir
!= NULL
)
106 if (chdir(user_dir
) < 0)
107 fprintf(stderr
, "%s: <<Warning>> chdir to %s failed in m4_defs",
113 m4_prefix_defines
= False
;
114 sprintf(m4_options
, " ");
115 m4_default_quotes
= 1;
116 /* add FVWM_DATADIR to the include path. Can't use the -I option here because
117 * it is incompatible with the System V version of m4. Instead, append it to
118 * the front of the M4PATH environment variable. */
119 m4path
= getenv("M4PATH");
122 m4path
= safemalloc(sizeof("M4PATH=") + strlen(FVWM_DATADIR
) + 1);
123 sprintf(m4path
, "M4PATH=%s", FVWM_DATADIR
);
130 sizeof("M4PATH=") + strlen(FVWM_DATADIR
) + strlen(m4path
) + 2);
131 sprintf(s
, "M4PATH=%s:%s", FVWM_DATADIR
, m4path
);
136 /* Record the program name for error messages */
139 s
=strrchr(argv
[0], '/');
143 MyName
= safemalloc(strlen(temp
)+2);
145 strcat(MyName
, temp
);
149 fprintf(stderr
,"%s Version %s should only be executed by fvwm!\n",MyName
,
154 /* We should exit if our fvwm pipes die */
155 signal (SIGPIPE
, DeadPipe
);
157 fd
[0] = atoi(argv
[1]);
158 fd
[1] = atoi(argv
[2]);
162 if(strcasecmp(argv
[i
],"-m4-prefix") == 0)
166 else if(strcasecmp(argv
[i
],"-m4-prefix-defines") == 0)
168 m4_prefix_defines
= True
;
170 else if(strcasecmp(argv
[i
],"-m4opt") == 0)
172 /* leaving this in just in case-- any option starting with '-'
173 will get passed on to m4 anyway */
174 strcat(m4_options
, argv
[++i
]);
175 strcat(m4_options
, " ");
177 else if(strcasecmp(argv
[i
],"-m4-squote") == 0)
179 m4_startquote
= argv
[++i
];
180 m4_default_quotes
= 0;
182 else if(strcasecmp(argv
[i
],"-m4-equote") == 0)
184 m4_endquote
= argv
[++i
];
185 m4_default_quotes
= 0;
187 else if (strcasecmp(argv
[i
], "-m4prog") == 0)
191 else if(strcasecmp(argv
[i
], "-outfile") == 0)
193 strcpy(m4_outfile
,argv
[++i
]);
195 else if(strcasecmp(argv
[i
], "-debug") == 0)
199 else if(strcasecmp(argv
[i
], "-lock") == 0)
203 else if(strcasecmp(argv
[i
], "-noread") == 0)
207 else if (strncasecmp(argv
[i
],"-",1) == 0)
209 /* pass on any other arguments starting with '-' to m4 */
210 strcat(m4_options
, argv
[i
]);
211 strcat(m4_options
, " ");
219 fprintf(stderr
, "%s: no file specified.\n", MyName
);
222 for(i
=0;i
<strlen(filename
);i
++)
223 if((filename
[i
] == '\n')||(filename
[i
] == '\r'))
228 if (!(dpy
= XOpenDisplay(display_name
)))
230 fprintf(stderr
,"FvwmM4: can't open display %s",
231 XDisplayName(display_name
));
236 PictureInitCMap(dpy
);
238 /* tell fvwm we're running if -lock is not used */
240 SendFinishedStartupNotification(fd
);
242 tmp_file
= m4_defs(dpy
, display_name
,m4_options
, filename
);
246 char *read_string
= CatString3("Read '", tmp_file
, "'");
247 SendText(fd
, read_string
, 0);
250 /* tell fvwm to continue if -lock is used */
252 SendFinishedStartupNotification(fd
);
254 /* For a debugging version, we may wish to omit this part. */
255 /* I'll let some m4 advocates clean this up */
259 char *delete_file
= tmp_file
;
260 if (tmp_file
[0] != '/' && user_dir
!= NULL
)
262 delete_file
= safestrdup(CatString3(user_dir
, "/", tmp_file
));
264 delete_string
= CatString3("Exec exec /bin/rm '", delete_file
, "'");
265 SendText(fd
, delete_string
, 0);
273 static char *m4_defs(
274 Display
*display
, const char *host
, char *m4_options
, char *config_file
)
278 char client
[MAXHOSTNAME
], server
[MAXHOSTNAME
], *colon
;
280 char options
[BUFSIZ
];
281 static char tmp_name
[BUFSIZ
];
282 struct hostent
*hostname
;
283 char *vc
; /* Visual Class */
285 struct passwd
*pwent
;
287 int ScreenWidth
, ScreenHeight
;
290 /* Generate a temporary filename. Honor the TMPDIR environment variable,
291 if set. Hope nobody deletes this file! */
293 if (strlen(m4_outfile
) == 0)
295 if ((vc
= getenv("TMPDIR")))
297 strcpy(tmp_name
, vc
);
301 strcpy(tmp_name
, "/tmp");
303 strcat(tmp_name
, "/fvwmrcXXXXXX");
304 fd
= fvwm_mkstemp(tmp_name
);
309 "[FvwmM4][m4_def] fvwm_mkstemp failed %s\n",
316 strcpy(tmp_name
, m4_outfile
);
318 * check to make sure it doesn't exist already, to prevent
321 /* first try to unlink it */
324 tmp_name
, O_WRONLY
|O_EXCL
|O_CREAT
,
325 FVWM_S_IRUSR
| FVWM_S_IWUSR
);
330 "[FvwmM4][m4_defs] error opening file %s\n",
339 * Create the appropriate command line to run m4, and
340 * open a pipe to the command.
346 options
, "%s --prefix-builtins %s > %s\n",
348 m4_options
, tmp_name
);
352 sprintf(options
, "%s %s > %s\n",
354 m4_options
, tmp_name
);
356 tmpf
= popen(options
, "w");
361 "[FvwmM4][m4_defs] Cannot open pipe to m4\n");
365 gethostname(client
,MAXHOSTNAME
);
366 getostype (ostype
, sizeof ostype
);
368 /* Change the quoting characters, if specified */
370 if (!m4_default_quotes
)
373 tmpf
, "%schangequote(%s, %s)%sdnl\n",
374 (m4_prefix
) ? "m4_" : "",
375 m4_startquote
, m4_endquote
,
376 (m4_prefix
) ? "m4_" : "");
379 hostname
= gethostbyname(client
);
380 strcpy(server
, XDisplayName(host
));
381 colon
= strchr(server
, ':');
382 if (colon
!= NULL
) *colon
= '\0';
383 if ((server
[0] == '\0') || (!strcmp(server
, "unix")))
384 strcpy(server
, client
); /* must be connected to :0 or unix:0 */
386 /* TWM_TYPE is fvwm, for completeness */
388 fputs(MkDef("TWM_TYPE", "fvwm"), tmpf
);
390 /* The machine running the X server */
391 fputs(MkDef("SERVERHOST", server
), tmpf
);
392 /* The machine running the window manager process */
393 fputs(MkDef("CLIENTHOST", client
), tmpf
);
395 fputs(MkDef("HOSTNAME", (char *)hostname
->h_name
), tmpf
);
397 fputs(MkDef("HOSTNAME", (char *)client
), tmpf
);
399 fputs(MkDef("OSTYPE", ostype
), tmpf
);
401 pwent
=getpwuid(geteuid());
402 fputs(MkDef("USER", pwent
->pw_name
), tmpf
);
404 fputs(MkDef("HOME", getenv("HOME")), tmpf
);
405 fputs(MkNum("VERSION", ProtocolVersion(display
)), tmpf
);
406 fputs(MkNum("REVISION", ProtocolRevision(display
)), tmpf
);
407 fputs(MkDef("VENDOR", ServerVendor(display
)), tmpf
);
408 fputs(MkNum("RELEASE", VendorRelease(display
)), tmpf
);
410 Mscreen
= DefaultScreen(display
);
411 fputs(MkNum("SCREEN", Mscreen
), tmpf
);
413 ScreenWidth
= DisplayWidth(display
,Mscreen
);
414 ScreenHeight
= DisplayHeight(display
,Mscreen
);
415 fputs(MkNum("WIDTH", DisplayWidth(display
,Mscreen
)), tmpf
);
416 fputs(MkNum("HEIGHT", DisplayHeight(display
,Mscreen
)), tmpf
);
418 screen
= ScreenOfDisplay(display
, Mscreen
);
420 "X_RESOLUTION",Resolution(screen
->width
,screen
->mwidth
)),
423 "Y_RESOLUTION",Resolution(screen
->height
,screen
->mheight
)),
425 fputs(MkNum("PLANES",DisplayPlanes(display
, Mscreen
)), tmpf
);
427 visual
= DefaultVisualOfScreen(screen
);
428 fputs(MkNum("BITS_PER_RGB", visual
->bits_per_rgb
), tmpf
);
430 switch(visual
->class)
454 fputs(MkDef("CLASS", vc
), tmpf
);
456 switch(Pvisual
->class)
480 fputs(MkDef("FVWM_CLASS", vc
), tmpf
);
482 if (visual
->class != StaticGray
&& visual
->class != GrayScale
)
483 fputs(MkDef("COLOR", "Yes"), tmpf
);
485 fputs(MkDef("COLOR", "No"), tmpf
);
487 if (Pvisual
->class != StaticGray
&& Pvisual
->class != GrayScale
)
488 fputs(MkDef("FVWM_COLOR", "Yes"), tmpf
);
490 fputs(MkDef("FVWM_COLOR", "No"), tmpf
);
492 fputs(MkDef("FVWM_VERSION", VERSION
), tmpf
);
494 /* Add options together */
496 if (FHaveShapeExtension
)
497 strcat(options
, "SHAPE ");
500 strcat(options
, "XPM ");
502 strcat(options
, "M4 ");
504 fputs(MkDef("OPTIONS", options
), tmpf
);
506 fputs(MkDef("FVWM_MODULEDIR", FVWM_MODULEDIR
), tmpf
);
507 fputs(MkDef("FVWM_DATADIR", FVWM_DATADIR
), tmpf
);
509 if ((vc
= getenv("FVWM_USERDIR")))
510 fputs(MkDef("FVWM_USERDIR", vc
), tmpf
);
512 if (SessionSupport
&& (vc
= getenv("SESSION_MANAGER")))
513 fputs(MkDef("SESSION_MANAGER", vc
), tmpf
);
516 * At this point, we've sent the definitions to m4. Just include
517 * the fvwmrc file now.
520 fprintf(tmpf
, "%sinclude(%s%s%s)\n",
521 (m4_prefix
) ? "m4_": "",
534 * SIGPIPE handler - SIGPIPE means fvwm is dying
537 RETSIGTYPE
DeadPipe(int nonsense
)
543 static char *MkDef(char *name
, char *def
)
548 /* Get space to hold everything, if needed */
550 n
= EXTRA
+ strlen(name
) + strlen(def
);
554 strcpy(cp
, "m4_define(");
556 strcpy(cp
, "define(");
558 if (m4_prefix_defines
)
562 /* Tack on "," and 2 sets of starting quotes */
564 strcat(cp
, m4_startquote
);
565 strcat(cp
, m4_startquote
);
567 /* The definition itself */
570 /* Add 2 sets of closing quotes */
571 strcat(cp
, m4_endquote
);
572 strcat(cp
, m4_endquote
);
574 /* End the definition, appropriately */
584 static char *MkNum(char *name
,int def
)
588 sprintf(num
, "%d", def
);
590 return(MkDef(name
, num
));