3 * Fvwm command input interface.
5 * Copyright 1998, Toshi Isogai.
6 * Use this program at your own risk.
7 * Permission to use this program for any purpose is given,
8 * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include "FvwmCommand.h"
30 #include "libs/fvwmsignal.h"
31 #include "libs/fvwmlib.h"
33 #define MYNAME "FvwmCommand"
35 static int Fdr
, Fdw
; /* file discriptor for fifo */
36 static int Fdrun
; /* file discriptor for run file */
37 static char *Fr_name
= NULL
;
40 static struct timeval Tv
;
41 static int Opt_reply
; /* wait for replay */
42 static int Opt_monitor
;
48 volatile sig_atomic_t Bg
; /* FvwmCommand in background */
51 void err_msg( const char *msg
);
52 void err_quit( const char *msg
);
53 void sendit( char *cmd
);
55 static RETSIGTYPE
sig_ttin(int);
56 static RETSIGTYPE
sig_quit(int);
58 int read_f(int fd
, char *p
, int len
);
59 void close_fifos(void);
61 void process_message( void ) ;
62 void list( unsigned long *body
, char *) ;
63 void list_configure(unsigned long *body
);
64 void list_focus_change(unsigned long *body
) ;
65 void list_header(unsigned long *body
, char *) ;
66 void list_icon_loc(unsigned long *body
) ;
67 void list_iconify(unsigned long *body
);
68 void list_mini_icon(unsigned long *body
) ;
69 void list_new_desk(unsigned long *body
) ;
70 void list_new_page(unsigned long *body
) ;
71 void list_string (char *str
);
72 void spawn_child( void );
77 * send command to and receive message from the server
80 int main ( int argc
, char *argv
[])
82 char cmd
[MAX_MODULE_INPUT_TEXT_LEN
+ 1];
83 char *f_stem
, *fc_name
, *fm_name
;
97 struct sigaction sigact
;
99 sigemptyset(&sigact
.sa_mask
);
101 sigact
.sa_flags
= SA_RESTART
;
105 sigact
.sa_handler
= sig_ttin
;
106 sigaction(SIGTTIN
, &sigact
, NULL
);
107 sigaction(SIGTTOU
, &sigact
, NULL
);
109 sigaddset(&sigact
.sa_mask
, SIGINT
);
110 sigaddset(&sigact
.sa_mask
, SIGHUP
);
111 sigaddset(&sigact
.sa_mask
, SIGQUIT
);
112 sigaddset(&sigact
.sa_mask
, SIGTERM
);
115 sigact
.sa_flags
= SA_INTERRUPT
;
119 sigact
.sa_handler
= sig_quit
;
120 sigaction(SIGINT
, &sigact
, NULL
);
121 sigaction(SIGHUP
, &sigact
, NULL
);
122 sigaction(SIGQUIT
, &sigact
, NULL
);
123 sigaction(SIGTERM
, &sigact
, NULL
);
124 sigaction(SIGPIPE
, &sigact
, NULL
);
127 #ifdef USE_BSD_SIGNALS
129 sigmask(SIGINT
) | sigmask(SIGHUP
) | sigmask(SIGQUIT
) |
130 sigmask(SIGTERM
) | sigmask(SIGPIPE
));
132 signal(SIGINT
, sig_quit
);
133 signal(SIGHUP
, sig_quit
);
134 signal(SIGQUIT
, sig_quit
);
135 signal(SIGTERM
, sig_quit
);
136 signal(SIGPIPE
, sig_quit
);
137 signal(SIGTTIN
, sig_ttin
);
138 signal(SIGTTOU
, sig_ttin
);
139 #ifdef HAVE_SIGINTERRUPT
140 siginterrupt(SIGINT
, 1);
141 siginterrupt(SIGHUP
, 1);
142 siginterrupt(SIGQUIT
, 1);
143 siginterrupt(SIGTERM
, 1);
144 siginterrupt(SIGPIPE
, 1);
145 siginterrupt(SIGTTIN
, 0);
146 siginterrupt(SIGTTOU
, 0);
164 while( (opt
= getopt( argc
, argv
, "S:hvF:f:w:i:rmc" )) != EOF
)
176 Opt_flags
= atoi (optarg
);
183 Opt_info
= atoi( optarg
);
186 printf("%s %s\n", MYNAME
, VERSION
);
189 Tv
.tv_usec
= atoi( optarg
) % 1000000;
190 Tv
.tv_sec
= atoi( optarg
) / 1000000;
208 if ((f_stem
= fifos_get_default_name()) == NULL
)
210 fprintf (stderr
, "\n%s can't decide on fifo-name. "
211 "Make sure that $FVWM_USERDIR is set.\n",
218 fm_name
= safemalloc( strlen(f_stem
) + 2 );
219 strcpy(fm_name
,f_stem
);
220 strcat(fm_name
, "M");
221 fc_name
= safemalloc( strlen(f_stem
) + 2 );
222 strcpy(fc_name
,f_stem
);
223 strcat(fc_name
, "C");
224 s
= safemalloc( strlen(f_stem
) + 2 );
228 Fdrun
= open(s
, O_WRONLY
| O_CREAT
| O_EXCL
| O_NOFOLLOW
, 0600);
233 if ((f
= fopen (s
,"r" )) != NULL
)
238 fprintf (stderr
, "\nFvwmCommand lock file %sR is detected. "
239 "This may indicate another FvwmCommand is running. "
240 "It appears to be running under process ID:\n%s\n",
241 f_stem
, (*cmd
) ? cmd
: "(unknown)" );
242 fprintf (stderr
, "You may either kill the process or run FvwmCommand "
243 "with another FIFO set using option -S and -f. "
244 "If the process doesn't exist, simply remove file:\n%sR\n\n",
250 err_quit ("writing lock file");
257 sprintf (cmd
,"%s '%sS %s'", argv
[0], MYNAME
, sf_stem
);
264 sprintf(buf
, "%d\n", (int)getpid());
265 write(Fdrun
, buf
, strlen(buf
));
271 while ((Fdr
=open (fm_name
, O_RDONLY
| O_NOFOLLOW
)) < 0)
275 err_quit ("opening message fifo");
280 while ((Fdw
=open (fc_name
, O_WRONLY
| O_NOFOLLOW
)) < 0)
284 err_quit ("opening command fifo");
293 while (fgets(cmd
, MAX_MODULE_INPUT_TEXT_LEN
- 1, stdin
))
299 else if( Opt_monitor
)
302 /* test if its stdin is closed for coprocess */
306 FD_SET(STDIN_FILENO
, &fdset
);
307 ncnt
= fvwmSelect(FD_SETSIZE
, &fdset
, 0, 0, &tv2
);
308 if( ncnt
&& (fgets( cmd
, 1, stdin
)==0 || cmd
[0] == 0))
313 /* line buffer stdout for coprocess */
314 setvbuf( stdout
, NULL
, _IOLBF
, 0);
316 /* send arguments first */
317 for( ;i
< argc
; i
++ )
319 strncpy( cmd
, argv
[i
], MAX_MODULE_INPUT_TEXT_LEN
- 1 );
324 while( !isTerminated
)
330 FD_SET(STDIN_FILENO
, &fdset
);
332 ncnt
= fvwmSelect(FD_SETSIZE
, &fdset
, 0, 0, NULL
);
334 /* message from fvwm */
335 if (FD_ISSET(Fdr
, &fdset
))
343 if( FD_ISSET(STDIN_FILENO
, &fdset
) )
345 if( fgets( cmd
, MAX_MODULE_INPUT_TEXT_LEN
- 1, stdin
) == 0 )
349 /* other than SIGTTIN */
361 for( ;i
< argc
; i
++ )
363 strncpy( cmd
, argv
[i
], MAX_MODULE_INPUT_TEXT_LEN
- 1 );
374 * send exit notice and close fifos
376 void close_fifos (void)
390 fvwmSetTerminate(sig
);
400 signal(SIGTTIN
, SIG_IGN
);
401 signal(SIGTTOU
, SIG_IGN
);
406 * print error message on stderr
408 void err_quit( const char *msg
)
410 fprintf (stderr
, "%s ", strerror(errno
));
416 void err_msg( const char *msg
)
418 fprintf( stderr
, "%s error in %s\n", MYNAME
, msg
);
422 * add cr to the command and send it
424 void sendit( char *cmd
)
433 if( cmd
[clen
-1] != '\n' )
440 write( Fdw
, cmd
, clen
);
452 /* wait indefinitely */
454 FD_SET( Fdr
, &fdset
);
455 ncnt
= select(FD_SETSIZE
, SELECT_FD_SET_CAST
&fdset
, 0, 0, NULL
);
460 tv
.tv_sec
= Tv
.tv_sec
;
461 tv
.tv_usec
= Tv
.tv_usec
;
465 ncnt
= select(FD_SETSIZE
, SELECT_FD_SET_CAST
&fdset
, 0, 0, &tv
);
477 if (FD_ISSET(Fdr
, &fdset
))
490 fprintf (stderr
, "Usage: %s [OPTION] [COMMAND]...\n", MYNAME
);
491 fprintf (stderr
, "Send commands to fvwm via %sS\n\n", MYNAME
);
493 " -c read and send commands from stdin\n"
494 " The COMMAND if any is ignored.\n");
497 "invoke another %s server with fifo <file name>\n",
500 " -f <file name> use fifo <file name> to connect to %sS\n",
503 " -i <info level> 0 - error only\n" );
505 " 1 - above and config info (default)\n" );
507 " 2 - above and static info\n" );
509 " 3 - above and dynamic info\n" );
511 " -1 - none (default, much faster)\n" );
513 " -F <flag info> 0 - no flag info\n");
515 " 2 - full flag info (default)\n");
517 " -m monitor fvwm message transaction\n");
520 "wait for a reply (overrides waiting time)\n");
522 " -v print version number\n");
524 " -w <micro sec> waiting time for the reponse from fvwm\n");
525 fprintf (stderr
, "\nDefault fifo names are ~/.%sC and ~/.%sM\n",
527 fprintf (stderr
, "Default waiting time is 500,000 us\n");
533 int read_f(int fd
, char *p
, int len
)
538 n
= read(fd
, &p
[i
], len
-i
);
539 if (n
<0 && errno
!=EAGAIN
)
541 err_quit("reading message");
557 void process_message( void )
559 unsigned long type
, length
, body
[sizeof(struct ConfigWinPacket
)];
561 read_f( Fdr
, (char*)&type
, SOL
);
562 read_f( Fdr
, (char*)&length
, SOL
);
563 read_f( Fdr
, (char*)body
, length
);
567 fprintf( stderr
,"%s", (char *)&body
[3] );
569 else if( Opt_info
>= 1 )
575 list( body
, "window");
581 list(body
, "class" );
584 list(body
, "resource");
587 case M_END_WINDOWLIST
:
588 list_string("end windowlist");
592 list(body
, "icon file");
594 case M_ICON_LOCATION
:
598 case M_END_CONFIG_INFO
:
599 list_string("end configinfo");
603 list(body
, "default icon");
607 list_mini_icon( body
);
611 printf( "%s\n", (char *)&body
[3] );
624 case M_CONFIGURE_WINDOW
:
625 list_configure( body
);
628 list(body
, "string");
643 list_header(body
, "add");
644 list_configure( body
);
647 list_header(body
, "raise");
650 list_header(body
, "lower");
653 list_focus_change( body
);
655 case M_DESTROY_WINDOW
:
656 list_header(body
, "destroy");
659 list_iconify( body
);
662 list_header(body
, "deiconify");
665 list_header(body
, "map");
668 list_header(body
, "windowshade");
670 case M_DEWINDOWSHADE
:
671 list_header(body
, "dewindowshade");
674 printf("0x%lx type 0x%lx\n", body
[0], type
);
686 * print configuration info
690 void list_configure(unsigned long *body
)
692 struct ConfigWinPacket
*cfgpacket
= (void *)body
;
695 printf( "0x%08lx %-20s x %ld, y %ld, width %ld, height %ld\n",
696 cfgpacket
->w
, "frame", cfgpacket
->frame_x
, cfgpacket
->frame_y
,
697 cfgpacket
->frame_width
, cfgpacket
->frame_height
);
698 printf( "0x%08lx %-20s %ld\n" ,cfgpacket
->w
, "desktop", cfgpacket
->desk
);
700 /* Oooh, you asked for it... */
703 printf( "Packet flags\n" );
704 printf( "is_sticky_across_pages: %d\n",
705 IS_STICKY_ACROSS_PAGES( cfgpacket
) );
706 printf( "is_sticky_across_desks: %d\n",
707 IS_STICKY_ACROSS_DESKS( cfgpacket
) );
708 printf( "has_icon_font: %d\n",
709 HAS_ICON_FONT( cfgpacket
) );
710 printf( "has_window_font: %d\n",
711 HAS_WINDOW_FONT( cfgpacket
) );
712 printf( "do_circulate_skip: %d\n",
713 DO_SKIP_CIRCULATE( cfgpacket
) );
714 printf( "do_circulate_skip_icon: %d\n",
715 DO_SKIP_ICON_CIRCULATE( cfgpacket
) );
716 printf( "do_circulate_skip_shaded: %d\n",
717 DO_SKIP_SHADED_CIRCULATE( cfgpacket
) );
718 printf( "do_grab_focus_when_created: %d\n",
719 FP_DO_GRAB_FOCUS( FW_FOCUS_POLICY(cfgpacket
) ) );
720 printf( "do_grab_focus_when_transient_created: %d\n",
721 FP_DO_GRAB_FOCUS_TRANSIENT( FW_FOCUS_POLICY(cfgpacket
) ) );
722 printf( "do_ignore_restack: %d\n",
723 DO_IGNORE_RESTACK( cfgpacket
) );
724 printf( "do_lower_transient: %d\n",
725 DO_LOWER_TRANSIENT( cfgpacket
) );
726 printf( "do_not_show_on_map: %d\n",
727 DO_NOT_SHOW_ON_MAP( cfgpacket
) );
728 printf( "do_not_pass_click_focus_click: %d\n",
729 FP_DO_PASS_FOCUS_CLICK( FW_FOCUS_POLICY(cfgpacket
) ) );
730 printf( "do_raise_transient: %d\n",
731 DO_RAISE_TRANSIENT( cfgpacket
) );
732 printf( "do_resize_opaque: %d\n",
733 DO_RESIZE_OPAQUE( cfgpacket
) );
734 printf( "do_shrink_windowshade: %d\n",
735 DO_SHRINK_WINDOWSHADE( cfgpacket
) );
736 printf( "do_stack_transient_parent: %d\n",
737 DO_STACK_TRANSIENT_PARENT( cfgpacket
) );
738 printf( "do_window_list_skip: %d\n",
739 DO_SKIP_WINDOW_LIST( cfgpacket
) );
740 printf( "has_depressable_border: %d\n",
741 HAS_DEPRESSABLE_BORDER( cfgpacket
) );
742 printf( "has_mwm_border: %d\n",
743 HAS_MWM_BORDER( cfgpacket
) );
744 printf( "has_mwm_buttons: %d\n",
745 HAS_MWM_BUTTONS( cfgpacket
) );
746 printf( "has_mwm_override: %d\n",
747 HAS_MWM_OVERRIDE_HINTS( cfgpacket
) );
748 printf( "has_no_icon_title: %d\n",
749 HAS_NO_ICON_TITLE( cfgpacket
) );
750 printf( "has_override_size: %d\n",
751 HAS_OVERRIDE_SIZE_HINTS( cfgpacket
) );
752 printf( "has_stippled_title: %d\n",
753 HAS_STIPPLED_TITLE( cfgpacket
) );
754 printf( "is_fixed: %d\n",
755 IS_FIXED( cfgpacket
) );
756 printf( "is_icon_sticky_across_pages: %d\n",
757 IS_ICON_STICKY_ACROSS_PAGES( cfgpacket
) );
758 printf( "is_icon_sticky_across_desks: %d\n",
759 IS_ICON_STICKY_ACROSS_DESKS( cfgpacket
) );
760 printf( "is_icon_suppressed: %d\n",
761 IS_ICON_SUPPRESSED( cfgpacket
) );
762 printf( "is_lenient: %d\n",
763 FP_IS_LENIENT( FW_FOCUS_POLICY(cfgpacket
) ) );
764 printf( "does_wm_delete_window: %d\n",
765 WM_DELETES_WINDOW( cfgpacket
) );
766 printf( "does_wm_take_focus: %d\n",
767 WM_TAKES_FOCUS( cfgpacket
) );
768 printf( "do_iconify_after_map: %d\n",
769 DO_ICONIFY_AFTER_MAP( cfgpacket
) );
770 printf( "do_reuse_destroyed: %d\n",
771 DO_REUSE_DESTROYED( cfgpacket
) );
772 printf( "has_border: %d\n",
773 !HAS_NO_BORDER( cfgpacket
) );
774 printf( "has_title: %d\n",
775 HAS_TITLE( cfgpacket
) );
776 printf( "is_iconify_pending: %d\n",
777 IS_ICONIFY_PENDING( cfgpacket
) );
778 printf( "is_fully_visible: %d\n",
779 IS_FULLY_VISIBLE( cfgpacket
) );
780 printf( "is_iconified: %d\n",
781 IS_ICONIFIED( cfgpacket
) );
782 printf( "is_iconfied_by_parent: %d\n",
783 IS_ICONIFIED_BY_PARENT( cfgpacket
) );
784 printf( "is_icon_entered: %d\n",
785 IS_ICON_ENTERED( cfgpacket
) );
786 printf( "is_icon_font_loaded: %d\n",
787 IS_ICON_FONT_LOADED( cfgpacket
) );
788 printf( "is_icon_moved: %d\n",
789 IS_ICON_MOVED( cfgpacket
) );
790 printf( "is_icon_ours: %d\n",
791 IS_ICON_OURS( cfgpacket
) );
792 printf( "is_icon_shaped: %d\n",
793 IS_ICON_SHAPED( cfgpacket
) );
794 printf( "is_icon_unmapped: %d\n",
795 IS_ICON_UNMAPPED( cfgpacket
) );
796 printf( "is_mapped: %d\n",
797 IS_MAPPED( cfgpacket
) );
798 printf( "is_map_pending: %d\n",
799 IS_MAP_PENDING( cfgpacket
) );
800 printf( "is_maximized: %d\n",
801 IS_MAXIMIZED( cfgpacket
) );
802 printf( "is_name_changed: %d\n",
803 IS_NAME_CHANGED( cfgpacket
) );
804 printf( "is_partially_visible: %d\n",
805 IS_PARTIALLY_VISIBLE( cfgpacket
) );
806 printf( "is_pixmap_ours: %d\n",
807 IS_PIXMAP_OURS( cfgpacket
) );
808 printf( "is_size_inc_set: %d\n",
809 IS_SIZE_INC_SET( cfgpacket
) );
810 printf( "is_transient: %d\n",
811 IS_TRANSIENT( cfgpacket
) );
812 printf( "is_window_drawn_once: %d\n",
813 cfgpacket
->flags
.is_window_drawn_once
);
814 printf( "is_viewport_moved: %d\n",
815 IS_VIEWPORT_MOVED( cfgpacket
) );
816 printf( "is_window_being_moved_opaque: %d\n",
817 IS_WINDOW_BEING_MOVED_OPAQUE( cfgpacket
) );
818 printf( "is_window_font_loaded: %d\n",
819 IS_WINDOW_FONT_LOADED( cfgpacket
) );
820 printf( "is_window_shaded %d\n",
821 IS_SHADED( cfgpacket
) );
822 printf( "title_dir: %d\n",
823 GET_TITLE_DIR( cfgpacket
) );
826 printf( "0x%08lx %-20s %hd\n",
827 cfgpacket
->w
, "title height", cfgpacket
->title_height
);
828 printf( "0x%08lx %-20s %hd\n",
829 cfgpacket
->w
, "border width", cfgpacket
->border_width
);
830 printf( "0x%08lx %-20s width %ld, height %ld\n", cfgpacket
->w
, "base size",
831 cfgpacket
->hints_base_width
, cfgpacket
->hints_base_height
);
832 printf( "0x%08lx %-20s width %ld, height %ld\n", cfgpacket
->w
,
833 "size increment", cfgpacket
->hints_width_inc
,
834 cfgpacket
->hints_height_inc
);
835 printf( "0x%08lx %-20s width %ld, height %ld\n", cfgpacket
->w
, "min size",
836 cfgpacket
->hints_min_width
, cfgpacket
->hints_min_height
);
837 printf( "0x%08lx %-20s width %ld, height %ld\n", cfgpacket
->w
, "max size",
838 cfgpacket
->hints_max_width
, cfgpacket
->hints_max_height
);
840 switch(cfgpacket
->hints_win_gravity
)
845 case NorthWestGravity
:
851 case NorthEastGravity
:
863 case SouthWestGravity
:
869 case SouthEastGravity
:
879 printf( "0x%08lx %-20s %s\n", cfgpacket
->w
, "gravity", grav
);
880 printf( "0x%08lx %-20s text 0x%lx, back 0x%lx\n", cfgpacket
->w
, "pixel",
881 cfgpacket
->TextPixel
, cfgpacket
->BackPixel
);
886 * print info icon location
889 void list_icon_loc(unsigned long *body
)
891 printf( "0x%08lx %-20s x %ld, y %ld, width %ld, height%ld\n",
892 body
[0], "icon location", body
[3], body
[4], body
[5], body
[6] );
897 * print info mini icon
900 void list_mini_icon(unsigned long *body
)
902 printf( "0x%08lx %-20s width %ld, height %ld, depth %ld\n",
903 body
[0], "mini icon",body
[5], body
[6], body
[7] );
908 * print info message body[3]
911 void list( unsigned long *body
, char *text
)
913 printf( "0x%08lx %-20s %s\n", body
[0], text
, (char *)&body
[3] );
919 * print info new page
922 void list_new_page(unsigned long *body
)
924 printf( " %-20s x %ld, y %ld, desk %ld, max x %ld, max y %ld\n",
926 body
[0], body
[1], body
[2], body
[3], body
[4]);
931 * print info new desk
934 void list_new_desk(unsigned long *body
)
936 printf( " %-20s %ld\n", "new desk", body
[0] );
944 void list_string (char *str
)
946 printf( "%-20s\n", str
);
954 void list_header(unsigned long *body
, char *text
)
956 printf("0x%08lx %s\n", body
[0], text
);
961 * print info focus change
964 void list_focus_change(unsigned long *body
)
966 printf( "0x%08lx %-20s highlight 0x%lx, foreground 0x%lx, background 0x%lx\n",
967 body
[0], "focus change", body
[3], body
[4], body
[5] );
975 void list_iconify(unsigned long *body
)
977 printf( "0x%08lx %-20s x %ld, y %ld, width %ld, hight %ld\n",
978 body
[0], "iconify", body
[3], body
[4], body
[5], body
[6] );