/*
* remote_cmd.cc
*
* Copyright (C) 1995, 1996, 1997, 1997, 1998, 1999, 2000, 2001, 2002 Kenichi Kourai
* Copyright (C) 1999, 2000, 2001, 2002 Luiz Blanes
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with blwm; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef ALLOW_RMTCMD
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "main.h"
#include "remote_cmd.h"
#include "function.h"
#include "hash.h"
#include "blwmrc.h"
#define TMP_DIR "/tmp/"
#define FIFO_PREFIX "blwm-"
RemoteCommand::RemoteCommand()
{
char *dispName = DisplayString(display);
int dispLen = strlen(dispName);
int dirLen = strlen(TMP_DIR);
int prefixLen = strlen(FIFO_PREFIX);
m_fifoName = (char *)malloc(dirLen + prefixLen + dispLen + 1);
sprintf(m_fifoName, "%s%s%s", TMP_DIR, FIFO_PREFIX, dispName);
if (mknod(m_fifoName, S_IFIFO | 0600, 0) == -1) {
if (errno != EEXIST) {
BlwmError("RemoteCommand: mknod: %s", strerror(errno));
m_fd = -1;
return;
}
if (unlink(m_fifoName) == -1) {
BlwmError("'%s' exists but cannot be removed: %s",
m_fifoName, strerror(errno));
m_fd = -1;
return;
}
BlwmError("removed '%s'", m_fifoName);
if (mknod(m_fifoName, S_IFIFO | 0600, 0) == -1) {
BlwmError("mknod '%s': %s", m_fifoName, strerror(errno));
m_fd = -1;
return;
}
}
if ((m_fd = open(m_fifoName, O_RDWR | O_NONBLOCK)) == -1) {
BlwmError("open '%s': %s", m_fifoName, strerror(errno));
return;
}
}
RemoteCommand::~RemoteCommand()
{
if (m_fd != -1) {
close(m_fd);
if (unlink(m_fifoName) == -1)
BlwmError("RemoteCommand: unlink '%s': %s", m_fifoName, strerror(errno));
free(m_fifoName);
}
}
#define BUF_SIZE 256
void RemoteCommand::process()
{
char buf[BUF_SIZE];
char *cmd, *ptr;
int len;
if ((len = read(m_fd, buf, BUF_SIZE)) < 0) {
if (errno != EAGAIN)
BlwmError("RemoteCommand: read: %s", strerror(errno));
return;
}
cmd = ptr = buf;
while (len > 0) {
if (*ptr == '\n') {
*ptr = '\0';
interpret(cmd);
cmd = ptr + 1; // point to the next command
}
ptr++;
len--;
}
if (cmd != ptr) {
if (cmd == buf)
BlwmError("too long remote command; command must be terminated by '\n'");
else
BlwmError("incomplete remote command is discarded");
}
}
void RemoteCommand::interpret(char* cmd)
{
FuncNumber *fn;
char *ptr = cmd, *args;
while (*ptr != '\0') {
if (*ptr == ' ')
break;
ptr++;
}
*ptr = '\0';
args = ptr + 1;
if ((fn = BlFunction::funcHashTable->GetHashItem(cmd)) == NULL) {
BlwmError("invalid function name: '%s'", cmd);
return;
}
switch (*fn) {
case Q_NONE:
return;
case Q_EXIT:
{
Bool bakUseExitDialog = UseExitDialog;
Bool bakUseConfirmDialog = UseConfirmDialog;
// change to non-interructive mode
UseExitDialog = False;
UseConfirmDialog = False;
BlFunction::execFunction(Q_EXIT);
UseExitDialog = bakUseExitDialog;
UseConfirmDialog = bakUseConfirmDialog;
}
break;
case Q_RESTART:
// window focus
case Q_CHANGE_WINDOW:
case Q_CHANGE_WINDOW_BACK:
case Q_CHANGE_WINDOW_INSCR:
case Q_CHANGE_WINDOW_BACK_INSCR:
case Q_DESKTOP_FOCUS:
// window rearrangement
case Q_OVERLAP:
case Q_OVERLAP_INSCR:
case Q_TILE_HORZ:
case Q_TILE_HORZ_INSCR:
case Q_TILE_VERT:
case Q_TILE_VERT_INSCR:
case Q_MINIMIZE_ALL:
case Q_MINIMIZE_ALL_INSCR:
case Q_RESTORE_ALL:
case Q_RESTORE_ALL_INSCR:
case Q_CLOSE_ALL:
case Q_CLOSE_ALL_INSCR:
// menu
case Q_POPUP_START_MENU:
case Q_POPUP_DESKTOP_MENU:
case Q_POPDOWN_ALL_MENU:
// paging
case Q_LEFT_PAGING:
case Q_RIGHT_PAGING:
case Q_UP_PAGING:
case Q_DOWN_PAGING:
// taskbar
case Q_BOTTOM:
case Q_TOP:
case Q_LEFT:
case Q_RIGHT:
case Q_TOGGLE_AUTOHIDE:
case Q_ENABLE_AUTOHIDE:
case Q_DISABLE_AUTOHIDE:
case Q_TOGGLE_TASKBAR:
case Q_ENABLE_TASKBAR:
case Q_DISABLE_TASKBAR:
case Q_SHOW_TASKBAR:
case Q_HIDE_TASKBAR:
// pager
case Q_TOGGLE_PAGER:
case Q_ENABLE_PAGER:
case Q_DISABLE_PAGER:
// icon
case Q_LINEUP_ICON:
BlFunction::execFunction(*fn);
break;
case Q_MINIMIZE:
case Q_MAXIMIZE:
case Q_RESTORE:
case Q_EXPAND:
case Q_EXPAND_LEFT:
case Q_EXPAND_RIGHT:
case Q_EXPAND_UP:
case Q_EXPAND_DOWN:
case Q_RAISE:
case Q_LOWER:
case Q_CLOSE:
case Q_KILL:
case Q_TOGGLE_ONTOP:
case Q_ENABLE_ONTOP:
case Q_DISABLE_ONTOP:
case Q_TOGGLE_STICKY:
case Q_ENABLE_STICKY:
case Q_DISABLE_STICKY:
{
List<Blwm>* blwmList = &desktop.GetBlwmList();
List<Blwm>::Iterator i(blwmList);
Blwm* blWm;
int idx=0;
XClassHint wm_class; // STRING
for (blWm = i.GetHead(); blWm; blWm = i.GetNext()) {
XGetClassHint(display, blWm->GetWin(), &wm_class);
if ((!strncmp(args, wm_class.res_name, strlen(args))) ||
(!strncmp(args, wm_class.res_class, strlen(args)))) {
BlFunction::execFunction(*fn, blWm);
}
}
break;
}
default:
BlwmError("not supported command '%s' as a remote command", cmd);
break;
}
}
#endif // ALLOW_RMTCMD
syntax highlighted by Code2HTML, v. 0.9.1