xenocara/app/fvwm/extras/FvwmConsole/FvwmConsole.c

247 lines
5.5 KiB
C

/*
Fvwm command input interface.
Copyright 1996, 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 "FvwmConsole.h"
#define MYVERSION "1.3"
char *MyName;
int Fd[2]; /* pipe to fvwm */
int Ns; /* socket handles */
char Name[80]; /* name of this program in executable format */
char *S_name; /* socket name */
void server( void );
void DeadPipe( int );
void CloseSocket();
void ErrMsg( char *msg );
void SigHandler( int );
int main(int argc, char *argv[]){
char *tmp, *s;
char client[120];
char **eargv;
int i,j,k;
char *xterm_a[] = { "-title", Name, "-name", Name, "-e", NULL, NULL };
int clpid;
/* Why is this not just put in the initializer of xterm_a?
Apparently, it is a non-standard extension to use a non-constant address (of client)
in an initializer (of xterm_a). */
xterm_a[5] = client;
/* Save the program name - its used for error messages and option parsing */
tmp = argv[0];
s=strrchr(argv[0], '/');
if (s != NULL)
tmp = s + 1;
strcpy( Name, tmp );
MyName = safemalloc(strlen(tmp)+2);
strcpy(MyName,"*");
strcat(MyName, tmp);
/* construct client's name */
strcpy( client, argv[0] );
strcat( client, "C" );
if(argc < FARGS) {
fprintf(stderr,"%s Version %s should only be executed by fvwm!\n",MyName,
MYVERSION);
exit(1);
}
if( ( eargv =(char **)safemalloc((argc+12)*sizeof(char *)) ) == NULL ) {
ErrMsg( "allocation" );
}
/* copy arguments */
eargv[0] = XTERM;
j = 1;
for ( i=FARGS ; i<argc; i++ ) {
if( !strcmp ( argv[i], "-e" ) ) {
i++;
break;
} else {
eargv[j++] = argv[i];
}
}
for ( k=0 ; xterm_a[k] != NULL ; j++, k++ ) {
eargv[j] = xterm_a[k];
}
/* copy rest of -e args */
for( ; i<argc; i++, j++ ) {
eargv[j-1] = argv[i];
}
eargv[j] = NULL;
/* Dead pipes mean fvwm died */
signal (SIGPIPE, DeadPipe);
signal (SIGINT, SigHandler);
signal (SIGQUIT, SigHandler);
Fd[0] = atoi(argv[1]);
Fd[1] = atoi(argv[2]);
/* launch xterm with client */
clpid = fork();
if( clpid < 0) {
ErrMsg("client forking");
}else if(clpid == 0 ) {
execvp( *eargv, eargv );
ErrMsg("exec");
}
server();
return (0);
}
/***********************************************************************
* signal handler
***********************************************************************/
void DeadPipe( int dummy ) {
fprintf(stderr,"%s: dead pipe\n", Name);
CloseSocket();
exit(0);
}
void SigHandler(int dummy) {
CloseSocket();
exit(1);
}
/*********************************************************/
/* close sockets and spawned process */
/*********************************************************/
void CloseSocket() {
send(Ns, C_CLOSE, strlen(C_CLOSE), 0);
close(Ns); /* remove the socket */
unlink( S_name );
}
/*********************************************************/
/* setup server and communicate with fvwm and the client */
/*********************************************************/
void server ( void ) {
struct sockaddr_un sas, csas;
int len, clen; /* length of sockaddr */
char buf[MAX_COMMAND_SIZE]; /* command line buffer */
char *tline;
char ver[40];
fd_set fdset;
unsigned long *body;
unsigned long header[HEADER_SIZE];
char *home;
int s;
int msglen;
/* make a socket */
if( (s = socket(AF_UNIX, SOCK_STREAM, 0 )) < 0 ) {
ErrMsg( "socket");
exit(1);
}
/* name the socket */
home = getenv("HOME");
S_name = safemalloc( strlen(home)+ 16);
strcpy(S_name,home);
strcat(S_name,S_NAME);
sas.sun_family = AF_UNIX;
strcpy( sas.sun_path, S_name );
/* bind the above name to the socket */
/* first, erase the old socket */
unlink( S_name );
len = sizeof(sas) - sizeof( sas.sun_path) + strlen( sas.sun_path );
if( bind(s, (struct sockaddr *)&sas,len) < 0 ) {
ErrMsg( "bind" );
exit(1);
}
/* listen to the socket */
/* set backlog to 5 */
if ( listen(s,5) < 0 ) {
ErrMsg( "listen" );
exit(1);
}
/* accept connections */
clen = sizeof(csas);
if(( Ns = accept(s, (struct sockaddr *)&csas, &clen)) < 0 ) {
ErrMsg( "accept");
exit(1);
}
/* send config lines to Client */
tline = NULL;
send(Ns, C_BEG, strlen(C_BEG), 0);
GetConfigLine(Fd,&tline);
while(tline != NULL) {
if(strlen(tline)>1) {
send(Ns, tline, strlen(tline),0);
}
GetConfigLine(Fd,&tline);
}
send(Ns, C_END, strlen(C_END), 0);
strcpy( ver, MyName);
strcat( ver, " Ver. " );
strcat( ver, MYVERSION);
strcat( ver, "\n" );
send(Ns, ver, strlen(ver), 0 );
while (1){
FD_ZERO(&fdset);
FD_SET(Ns, &fdset);
FD_SET(Fd[1], &fdset);
select(FD_SETSIZE,SELECT_TYPE_ARG234 &fdset, 0, 0, NULL);
if (FD_ISSET(Fd[1], &fdset)){
if( ReadFvwmPacket(Fd[1],header,&body) > 0) {
if(header[1] == M_PASS) {
msglen = strlen((char *)&body[3]);
if( msglen > MAX_MESSAGE_SIZE-2 ) {
msglen = MAX_MESSAGE_SIZE-2;
}
send( Ns, (char *)&body[3], msglen, 0 );
}
free(body);
}
}
if (FD_ISSET(Ns, &fdset)){
if( recv( Ns, buf, MAX_COMMAND_SIZE,0 ) == 0 ) {
/* client is terminated */
break;
}
/* process the own unique commands */
SendText(Fd,buf,0); /* send command */
}
}
CloseSocket();
exit(0);
}
/******************************************/
/* print error message on stderr and exit */
/******************************************/
void ErrMsg( char *msg ) {
fprintf( stderr, "%s server error in %s, errno %d\n", Name, msg, errno );
CloseSocket();
exit(1);
}