2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 ** Module.c: code for modules to communicate with fvwm
23 #include "libs/defaults.h"
28 * Loop until count bytes are read, unless an error or end-of-file
32 static int positive_read(int fd
, char *buf
, int count
)
36 int n_read
= read(fd
, buf
, count
);
49 * Reads a single packet of info from fvwm.
50 * The packet is stored in static memory that is reused during
54 FvwmPacket
*ReadFvwmPacket(int fd
)
56 static unsigned long buffer
[FvwmPacketMaxSize
];
57 FvwmPacket
*packet
= (FvwmPacket
*)buffer
;
60 /* The `start flag' value supposedly exists to synchronize the
61 * fvwm -> module communication. However, the communication goes
62 * through a pipe. I don't see how any data could ever get lost,
63 * so how would fvwm & the module become unsynchronized?
67 if (positive_read(fd
, (char *)buffer
, sizeof(unsigned long))
72 } while (packet
->start_pattern
!= START_FLAG
);
74 /* Now read the rest of the header */
75 if (positive_read(fd
, (char *)(&buffer
[1]), 3 * sizeof(unsigned long))
80 length
= FvwmPacketBodySize_byte(*packet
);
81 if (length
> FvwmPacketMaxSize_byte
- FvwmPacketHeaderSize_byte
)
86 /* Finally, read the body, and we're done */
87 if (positive_read(fd
, (char *)(&buffer
[4]), length
) < 0)
98 * SendFinishedStartupNotification - informs fvwm that the module has
99 * finished its startup procedures and is fully operational now.
102 void SendFinishedStartupNotification(int *fd
)
104 SendText(fd
, ModuleFinishedStartupResponse
, 0);
109 * SendUnlockNotification - informs fvwm that the module has
110 * finished it's procedures and fvwm may proceed.
113 void SendUnlockNotification(int *fd
)
115 SendText(fd
, ModuleUnlockResponse
, 0);
120 * SendQuitNotification - informs fvwm that the module has
121 * finished and may be killed.
124 static unsigned long ModuleContinue
= 1;
125 void SendQuitNotification(int *fd
)
128 SendText(fd
, ModuleUnlockResponse
, 0); /* unlock just in case */
133 * SendText - Sends arbitrary text/command back to fvwm
136 void SendText(int *fd
, const char *message
, unsigned long window
)
146 /* Get enough memory to store the entire message. */
147 len
= strlen(message
);
148 p
= buf
= alloca(sizeof(long) * (3 + 1 + (len
/ sizeof(long))));
150 /* Put the message in the buffer, and... */
151 *((unsigned long *)p
) = window
;
152 p
+= sizeof(unsigned long);
154 *((unsigned long *)p
) = len
;
155 p
+= sizeof(unsigned long);
160 memcpy(p
, &ModuleContinue
, sizeof(unsigned long));
161 p
+= sizeof(unsigned long);
164 write(fd
[0], buf
, p
- buf
);
169 * SendFvwmPipe - Sends message to fvwm: The message is a comma-delimited
170 * string separated into its component sections and sent one by one to fvwm.
171 * It is discouraged to use this function with a "synchronous" module.
175 void SendFvwmPipe(int *fd
, const char *message
, unsigned long window
)
177 const char *hold
= message
;
180 while ((temp
= strchr(hold
, ',')) != NULL
)
182 char *temp_msg
= (char*)alloca(temp
- hold
+ 1);
184 strncpy(temp_msg
, hold
, (temp
- hold
));
185 temp_msg
[(temp
- hold
)] = '\0';
188 SendText(fd
, temp_msg
, window
);
192 * Send the last part of the string :
193 * we don't need to copy this into separate
194 * storage because we don't need to modify it ...
196 * NOTE: this makes this second call to SendText()
197 * distinct from the first call. Two calls is
198 * cleaner than hacking the loop to make only
201 SendText(fd
, hold
, window
);
204 void SetMessageMask(int *fd
, unsigned long mask
)
206 char set_mask_mesg
[50];
208 sprintf(set_mask_mesg
, "SET_MASK %lu", mask
);
209 SendText(fd
, set_mask_mesg
, 0);
212 void SetSyncMask(int *fd
, unsigned long mask
)
214 char set_syncmask_mesg
[50];
216 sprintf(set_syncmask_mesg
, "SET_SYNC_MASK %lu", mask
);
217 SendText(fd
, set_syncmask_mesg
, 0);
220 void SetNoGrabMask(int *fd
, unsigned long mask
)
222 char set_nograbmask_mesg
[50];
224 sprintf(set_nograbmask_mesg
, "SET_NOGRAB_MASK %lu", mask
);
225 SendText(fd
, set_nograbmask_mesg
, 0);
229 * Optional routine that sets the matching criteria for config lines
230 * that should be sent to a module by way of the GetConfigLine function.
232 * If this routine is not called, all module config lines are sent.
234 static int first_pass
= 1;
236 void InitGetConfigLine(int *fd
, char *match
)
238 char *buffer
= (char *)alloca(strlen(match
) + 32);
239 first_pass
= 0; /* make sure get wont do this */
240 sprintf(buffer
, "Send_ConfigInfo %s", match
);
241 SendText(fd
, buffer
, 0);
246 * Gets a module configuration line from fvwm. Returns NULL if there are
247 * no more lines to be had. "line" is a pointer to a char *.
249 * Changed 10/19/98 by Dan Espen:
251 * - The "isspace" call was referring to memory beyond the end of the
252 * input area. This could have led to the creation of a core file. Added
253 * "body_size" to keep it in bounds.
255 void GetConfigLine(int *fd
, char **tline
)
262 SendText(fd
, "Send_ConfigInfo", 0);
268 packet
= ReadFvwmPacket(fd
[1]);
269 if (packet
== NULL
|| packet
->type
== M_END_CONFIG_INFO
)
274 } while (packet
->type
!= M_CONFIG_INFO
);
276 /* For whatever reason CONFIG_INFO packets start with three
277 * (unsigned long) zeros. Skip the zeros and any whitespace that
279 *tline
= (char *)&(packet
->body
[3]);
280 body_count
= FvwmPacketBodySize(*packet
) * sizeof(unsigned long);
282 while (body_count
> 0 && isspace((unsigned char)**tline
))
290 ModuleArgs
*ParseModuleArgs(int argc
, char *argv
[], int use_arg6_as_alias
)
292 static ModuleArgs ma
;
294 /* Need at least six arguments:
295 [0] name of executable
296 [1] file descriptor of module->fvwm pipe (write end)
297 [2] file descriptor of fvwm->module pipe (read end)
298 [3] pathname of last config file read (ignored, use Send_ConfigInfo)
299 [4] application window context
300 [5] window decoration context
302 Optionally (left column used if use_arg6_as_alias is true):
303 [6] alias or user argument 0
304 [7] user arg 0 or user arg 1
312 /* Module name is (last component of) argv[0] or possibly an alias
313 passed on the command line. */
314 if (use_arg6_as_alias
&& argc
>= 7)
317 ma
.user_argc
= argc
- 7;
318 ma
.user_argv
= &(argv
[7]);
322 char *p
= strrchr(argv
[0], '/');
331 ma
.user_argc
= argc
- 6;
332 ma
.user_argv
= &(argv
[6]);
335 ma
.namelen
=strlen(ma
.name
);
337 if (ma
.user_argc
== 0)
342 /* File descriptors for the pipes */
343 ma
.to_fvwm
= atoi(argv
[1]);
344 ma
.from_fvwm
= atoi(argv
[2]);
348 /* These two are generated as long hex strings */
349 ma
.window
= strtoul(argv
[4], NULL
, 16);
350 ma
.decoration
= strtoul(argv
[5], NULL
, 16);
355 /* expands certain variables in a command to be sent by a module */
356 char *module_expand_action(
357 Display
*dpy
, int screen
, char *in_action
, rectangle
*r
,
358 char *forecolor
, char *backcolor
)
391 rectangle tmpr
= { 0, 0, 0, 0 };
393 has_geom
= (r
== NULL
) ? False
: True
;
394 has_fg
= (forecolor
== NULL
) ? False
: True
;
395 has_bg
= (backcolor
== NULL
) ? False
: True
;
400 /* create a temporary storage for expanding */
401 action
= (char *)safemalloc(MAX_MODULE_INPUT_TEXT_LEN
);
402 for (src
= in_action
, dest
= action
; *src
!= 0; src
++)
409 /* it's a variable */
413 *(dest
++) = *(src
++);
414 i
= GetTokenIndex(src
, variables
, -1, &rest
);
429 if (backcolor
== NULL
)
441 val
= DisplayWidth(dpy
, screen
) - r
->x
- 1;
445 val
= r
->x
+ r
->width
;
449 val
= DisplayWidth(dpy
, screen
) - r
->x
- r
->width
- 1;
457 val
= DisplayHeight(dpy
, screen
) - r
->y
- 1;
461 val
= r
->y
+ r
->height
;
464 case 10: /* -bottom */
465 val
= DisplayHeight(dpy
, screen
) - r
->y
- r
->height
- 1;
472 case 12: /* height */
476 default: /* unknown */
480 if (is_value
== False
&& is_string
== False
)
489 if (MAX_MODULE_INPUT_TEXT_LEN
- (dest
- action
) <= 16)
495 /* print the number into the string */
496 sprintf(dest
, "%d%n", val
, &offset
);
501 if (MAX_MODULE_INPUT_TEXT_LEN
- (dest
- action
) <=
508 /* print the colour name into the string */
511 sprintf(dest
, "%s%n", string
, &offset
);