xenocara/app/fvwm/extras/FvwmCommand/FvwmCommandS.c

407 lines
7.9 KiB
C

/* $Id: FvwmCommandS.c,v 1.1.1.1 2006/11/26 10:53:10 matthieu Exp $
* $Source: /home/cvs/xenocara/app/fvwm/extras/FvwmCommand/Attic/FvwmCommandS.c,v $
*
* Fvwm command input interface.
*
* Copyright 1997, Toshi Isogai. No guarantees or warantees or anything
* are provided. Use this program at your own risk. Permission to use
* this program for any purpose is given,
* as long as the copyright is kept intact.
*
*/
#include "FvwmCommand.h"
#define MYNAME "FvwmCommandS"
int Fd[2]; /* pipe to fvwm */
int Ffdr; /* command fifo file discriptors */
int Ffdw; /* message fifo file discriptors */
char *F_name, *Fc_name, *Fm_name; /* fifo name */
char Nounlink; /* don't delete fifo when true */
char Connect; /* client is connected */
int open_fifos (char *f_stem);
void close_fifos();
void close_pipes();
void DeadPipe( int );
void err_msg( char *msg );
void err_quit( char *msg );
void process_message(unsigned long type,unsigned long *body);
void relay_packet( unsigned long, unsigned long, unsigned long *);
void server( char * );
void sig_handler( int );
int write_f (int fd, char *p, int len);
int main(int argc, char *argv[]) {
char *fifoname;
if(argc < FARGS) {
fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",
MYNAME, MYVERSION);
exit(1);
}
if( argc == FARGS+1 ) {
fifoname = argv[FARGS];
}else{
fifoname = NULL;
}
signal (SIGPIPE, DeadPipe);
signal (SIGINT, sig_handler);
signal (SIGQUIT, sig_handler);
signal (SIGHUP, sig_handler);
signal (SIGTERM, sig_handler);
Fd[0] = atoi(argv[1]);
Fd[1] = atoi(argv[2]);
Nounlink = 0;
server( fifoname );
exit(1);
}
/*
* signal handler
*/
void DeadPipe( int dummy ) {
fprintf(stderr,"%s: dead pipe\n", MYNAME);
close_pipes();
exit(0);
}
void sig_handler(int signo) {
close_pipes();
exit(1);
}
/*
* setup server and communicate with fvwm and the client
*/
void server ( char *name ) {
char *home;
char *f_stem;
int len;
fd_set fdset;
unsigned long *body;
unsigned long header[HEADER_SIZE];
char buf[MAX_COMMAND_SIZE]; /* command receiving buffer */
char cmd[MAX_COMMAND_SIZE];
int ix,cix;
if( name == NULL ) {
/* default name */
home = getenv("HOME");
f_stem = safemalloc( strlen(home)+ strlen(F_NAME) + 3);
strcpy (f_stem, home);
if (f_stem[strlen(f_stem)-1] != '/') {
strcat (f_stem, "/");
}
strcat (f_stem, F_NAME);
}else{
f_stem = name;
}
if (open_fifos (f_stem) < 0) {
exit (-1);
}
SendText(Fd," ",0); /* tell fvwm that we are here */
cix = 0;
while (1){
FD_ZERO(&fdset);
FD_SET(Ffdr, &fdset);
FD_SET(Fd[1], &fdset);
if (select(FD_SETSIZE, SELECT_TYPE_ARG234 &fdset, 0, 0, NULL) < 0) {
if (errno == EINTR) {
continue;
}
}
if (FD_ISSET(Fd[1], &fdset)){
if( ReadFvwmPacket(Fd[1],header,&body) > 0) {
if (Connect) {
process_message(header[1], body);
}
free(body);
}
}
if (FD_ISSET(Ffdr, &fdset)){
len = read( Ffdr, buf, MAX_COMMAND_SIZE-1 );
if (len == 0) {
continue;
}
if (len < 0) {
if (errno != EAGAIN && errno != EINTR) {
err_quit("reading fifo");
}
}
Connect = 1;
/* in case of multiple long lines */
for (ix=0; ix<len; ix++) {
cmd[cix] = buf[ix];
if (cmd[cix] == '\n') {
cmd[cix+1] = '\0';
cix = 0;
if (!strncmp (cmd, CMD_CONNECT, strlen(CMD_CONNECT))) {
/* do nothing */
} else if (!strcmp (cmd, CMD_EXIT)) {
Connect = 0;
break;
} else {
if (!strcmp (cmd, CMD_KILL_NOUNLINK)) {
Nounlink = 1;
strcpy (cmd, "killme" );
}
SendText (Fd,cmd,0);
}
}else{
if (cix >= MAX_COMMAND_SIZE-1) {
err_msg ("command too long");
cix = 0;
} else {
cix++;
}
}
}
}
}
}
/*
* close fifos and pipes
*/
void close_pipes() {
close (Fd[0]);
close (Fd[1]);
close_fifos();
}
void close_fifos () {
close (Ffdw);
close (Ffdr);
if (!Nounlink) {
strcat (F_name,"C");
unlink (F_name);
F_name[strlen(F_name)-1] = 'M';
unlink (F_name);
F_name[strlen(F_name)-1] = 'R';
unlink (F_name);
}
free (F_name);
Ffdr = -1;
Ffdw = -1;
}
/*
* open fifos
*/
int open_fifos (char *f_stem) {
char *fc_name, *fm_name;
/* create 2 fifos */
fc_name = malloc( strlen(f_stem) + 2 );
if (fc_name == NULL) {
err_msg( "allocating command" );
return -1;
}
fm_name = malloc( strlen(f_stem) + 2 );
if (fm_name == NULL) {
err_msg( "allocating message" );
return -1;
}
strcpy(fc_name,f_stem);
strcpy(fm_name,f_stem);
strcat(fc_name, "C");
strcat(fm_name, "M");
if( (Ffdw = open(fc_name, O_RDWR | O_NONBLOCK ) ) > 0) {
write_f( Ffdw, CMD_KILL_NOUNLINK, strlen(CMD_KILL_NOUNLINK) );
close( Ffdw );
}
unlink( fm_name );
unlink( fc_name );
if( mkfifo( fm_name, S_IRUSR | S_IWUSR ) < 0 ) {
err_msg( fm_name );
return -1;
}
if( mkfifo( fc_name, S_IRUSR | S_IWUSR ) < 0 ) {
err_msg( fc_name );
return -1;
}
Ffdr = open(fc_name, O_RDWR | O_NONBLOCK | O_TRUNC);
if (Ffdr < 0) {
err_msg( "opening command fifo" );
return -1;
}
free(fc_name);
Ffdw = open(fm_name, O_RDWR | O_NONBLOCK | O_TRUNC);
if (Ffdw < 0) {
err_msg( "opening message fifo" );
return -1;
}
free(fm_name);
F_name = malloc (strlen (f_stem) + 2);
if (F_name == NULL) {
err_msg( "allocating name string" );
return -1;
}
strcpy (F_name, f_stem);
return 0;
}
/*
* Process window list messages
*/
void process_message(unsigned long type,unsigned long *body){
int msglen;
switch(type) {
case M_CONFIGURE_WINDOW:
relay_packet( type, 24*SOL, body );
break;
case M_WINDOW_NAME:
case M_ICON_NAME:
case M_RES_CLASS:
case M_RES_NAME:
case M_ICON_FILE:
case M_DEFAULTICON:
msglen = strlen( (char *)&body[3] );
relay_packet( type, msglen+1+3*SOL, body );
break;
case M_END_WINDOWLIST:
case M_END_CONFIG_INFO:
relay_packet( type, 0*SOL, body );
break;
case M_ICON_LOCATION:
relay_packet( type, 7*SOL, body );
break;
case M_ERROR:
case M_STRING:
case M_CONFIG_INFO:
msglen = strlen( (char *)&body[3] );
relay_packet( type, msglen+1+3*SOL, body );
break;
case M_MINI_ICON:
relay_packet( type, 6*SOL, body );
break;
case M_NEW_PAGE:
relay_packet( type, 5*SOL, body );
break;
case M_NEW_DESK:
relay_packet( type, 1*SOL, body );
break;
case M_ADD_WINDOW:
relay_packet( type, 24*SOL, body );
break;
case M_RAISE_WINDOW:
case M_LOWER_WINDOW:
case M_FOCUS_CHANGE:
case M_DESTROY_WINDOW:
case M_DEICONIFY:
case M_MAP:
case M_WINDOWSHADE:
case M_DEWINDOWSHADE:
relay_packet( type, 4*SOL, body );
break;
case M_ICONIFY:
relay_packet( type, 7*SOL, body );
break;
default:
relay_packet( type, 4*SOL, body );
}
}
/*
* print error message on stderr and exit
*/
void err_msg( char *msg ) {
fprintf( stderr, "%s server error in %s, %s\n",
MYNAME, msg, strerror(errno) );
}
void err_quit( char *msg ) {
err_msg (msg);
close_pipes();
exit(1);
}
/*
* relay packet to front-end
*/
void relay_packet( unsigned long type,
unsigned long length, unsigned long *body) {
write_f( Ffdw, (char*)&type, SOL );
write_f( Ffdw, (char*)&length, SOL );
write_f( Ffdw, (char*)body, length );
}
/*
* write to fifo
*/
int write_f (int fd, char *p, int len) {
int i, n;
struct timeval tv;
int again;
static int giveup=0;
again = 0;
tv.tv_sec = 0;
tv.tv_usec = 50000;
for (i=0; i<len; ) {
n = write (fd, &p[i], len-i);
if (n<0) {
if( errno==EINTR) {
continue;
} else if (errno==EAGAIN ) {
if (again++ < 5) {
select(0, 0, 0, 0, &tv);
continue;
}else{
if (giveup++ > 20) {
Connect = 0;
}
return -1; /* give up this message */
}
}
err_quit ("writing fifo");
}
i += n;
}
giveup = 0;
return 0;
}