mirror of https://github.com/0intro/wmii
removed various unused crap
This commit is contained in:
parent
8ef8918f09
commit
f767ebcca8
|
@ -1,43 +0,0 @@
|
|||
.TH WMIIBAR 1 wmii-3
|
||||
.SH NAME
|
||||
wmiibar \- window manager improved 2 bar
|
||||
.SH SYNOPSIS
|
||||
.B wmiibar
|
||||
.B \-s
|
||||
.I socketfile
|
||||
.SH DESCRIPTION
|
||||
.SS Overview
|
||||
.B wmiibar
|
||||
is a generic and highly customizable bar for the X Window System,
|
||||
originally designed for
|
||||
.BR wmii (1).
|
||||
It supports arbitrary sized labels with arbitrary styles on a per label
|
||||
basis and with button click events.
|
||||
Like wmii,
|
||||
.B wmiibar
|
||||
also implements a socket-based fileserver, which is accessed to configure and
|
||||
interoperate with other components.
|
||||
.SS Options
|
||||
.TP
|
||||
.BI \-s " socketfile"
|
||||
specifies the socketfile that
|
||||
.B wmiibar
|
||||
should create.
|
||||
.TP
|
||||
.B \-v
|
||||
prints version information to stderr, then exits.
|
||||
.SS Customization
|
||||
.B wmiibar
|
||||
is customized through manipulating its filesystem namespace.
|
||||
In the default setup of
|
||||
.BR wmii (1)
|
||||
the namespace of
|
||||
.B wmiibar
|
||||
can be found in /bar.
|
||||
.SH SEE ALSO
|
||||
.BR wmiifs (1),
|
||||
.BR wmii (1),
|
||||
.BR wmiiwm (1),
|
||||
.BR wmiikeys (1),
|
||||
.BR wmiimenu (1),
|
||||
.BR wmiir (1)
|
898
cmd/wmiibar.c
898
cmd/wmiibar.c
|
@ -1,898 +0,0 @@
|
|||
/*
|
||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "wmii.h"
|
||||
|
||||
/*
|
||||
* filesystem specification
|
||||
* / Droot
|
||||
* /font Ffont <xlib font name>
|
||||
* /defcolor Fdefcolor <#RRGGBB> <#RRGGBB> <#RRGGBB>
|
||||
* /event Fevent
|
||||
* /expand Fexpand id of expandable label
|
||||
* /ctl Fctl command interface
|
||||
* /new/ Ditem
|
||||
* /1/ Ditem
|
||||
* /1/data Fdata <arbitrary data which gets displayed>
|
||||
* /1/color Fcolor <#RRGGBB> <#RRGGBB> <#RRGGBB>
|
||||
*/
|
||||
|
||||
/* 8-bit qid.path.type */
|
||||
enum {
|
||||
Droot,
|
||||
Ditem,
|
||||
Fctl,
|
||||
Ffont,
|
||||
Fdefcolor,
|
||||
Fexpand,
|
||||
Fevent,
|
||||
Fdata, /* data to display */
|
||||
Fcolor
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned short id;
|
||||
char data[256];
|
||||
char colstr[24];
|
||||
Color color;
|
||||
XRectangle rect;
|
||||
} Item;
|
||||
|
||||
static size_t nitem = 0;
|
||||
static size_t itemsz = 0;
|
||||
static size_t iexpand = 0;
|
||||
static Item **item = 0;
|
||||
static IXPServer srv = { 0 };
|
||||
static Display *dpy;
|
||||
static int screen;
|
||||
static char *font = nil;
|
||||
static XFontStruct *xfont;
|
||||
static GC gc;
|
||||
static Window win;
|
||||
static XRectangle brect, rect;
|
||||
static Pixmap pmap;
|
||||
static char defcolstr[24];
|
||||
static Color defcolor;
|
||||
Qid root_qid;
|
||||
|
||||
static void do_pend_fcall(char *event);
|
||||
|
||||
static char version[] = "wmiibar - " VERSION ", (C)opyright MMIV-MMVI Anselm R. Garbe\n";
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "%s", "usage: wmiibar -a <address> [-v]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
dummy_error_handler(Display * dpy, XErrorEvent * err)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Item *
|
||||
new_item()
|
||||
{
|
||||
static unsigned int id = 1;
|
||||
Item *it = cext_emallocz(sizeof(Item));
|
||||
it->id = id++;
|
||||
cext_strlcpy(it->colstr, defcolstr, sizeof(it->colstr));
|
||||
it->color = defcolor;
|
||||
item = (Item **)cext_array_attach((void **)item, it, sizeof(Item *), &itemsz);
|
||||
nitem++;
|
||||
return it;
|
||||
}
|
||||
|
||||
static void
|
||||
detach_item(Item *it)
|
||||
{
|
||||
cext_array_detach((void **)item, it, &itemsz);
|
||||
nitem--;
|
||||
}
|
||||
|
||||
static void
|
||||
draw()
|
||||
{
|
||||
size_t i;
|
||||
unsigned int w = 0;
|
||||
Draw d = { 0 };
|
||||
|
||||
d.align = WEST;
|
||||
d.gc = gc;
|
||||
d.drawable = pmap;
|
||||
d.rect = brect;
|
||||
d.rect.y = 0;
|
||||
d.font = xfont;
|
||||
|
||||
if(!nitem) { /* /default only */
|
||||
d.color = defcolor;
|
||||
blitz_drawlabel(dpy, &d);
|
||||
}
|
||||
else {
|
||||
for(i = 0; i < nitem; i++) {
|
||||
Item *it = item[i];
|
||||
it->rect.x = it->rect.y = 0;
|
||||
it->rect.height = brect.height;
|
||||
if(i == iexpand)
|
||||
continue;
|
||||
it->rect.width = brect.height;
|
||||
if(strlen(it->data)) {
|
||||
if(!strncmp(it->data, "%m:", 3))
|
||||
it->rect.width = brect.height / 2;
|
||||
else
|
||||
it->rect.width += XTextWidth(xfont, it->data, strlen(it->data));
|
||||
}
|
||||
w += it->rect.width;
|
||||
}
|
||||
|
||||
if(w >= brect.width) {
|
||||
/* failsafe mode, give all labels same width */
|
||||
w = brect.width / nitem;
|
||||
for(i = 0; i < nitem; i++) {
|
||||
item[i]->rect.x = i * w;
|
||||
item[i]->rect.width = w;
|
||||
}
|
||||
i--;
|
||||
item[i]->rect.width = brect.width - item[i]->rect.x;
|
||||
}
|
||||
else {
|
||||
item[iexpand]->rect.width = brect.width - w;
|
||||
for(i = 1; i < nitem; i++)
|
||||
item[i]->rect.x = item[i - 1]->rect.x + item[i - 1]->rect.width;
|
||||
}
|
||||
|
||||
for(i = 0; i < nitem; i++) {
|
||||
d.color = item[i]->color;
|
||||
d.rect = item[i]->rect;
|
||||
d.data = item[i]->data;
|
||||
if(d.data && !strncmp(d.data, "%m:", 3))
|
||||
blitz_drawmeter(dpy, &d);
|
||||
else
|
||||
blitz_drawlabel(dpy, &d);
|
||||
}
|
||||
}
|
||||
XCopyArea(dpy, pmap, win, gc, 0, 0, brect.width, brect.height, 0, 0);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
|
||||
static void
|
||||
update_geometry()
|
||||
{
|
||||
char buf[64];
|
||||
brect = rect;
|
||||
brect.height = xfont->ascent + xfont->descent + 4;
|
||||
brect.y = rect.height - brect.height;
|
||||
XMoveResizeWindow(dpy, win, brect.x, brect.y, brect.width, brect.height);
|
||||
XSync(dpy, False);
|
||||
XFreePixmap(dpy, pmap);
|
||||
pmap = XCreatePixmap(dpy, win, brect.width, brect.height,
|
||||
DefaultDepth(dpy, screen));
|
||||
XSync(dpy, False);
|
||||
snprintf(buf, sizeof(buf), "NewGeometry %d %d %d %d\n", brect.x, brect.y, brect.width, brect.height);
|
||||
do_pend_fcall(buf);
|
||||
draw();
|
||||
}
|
||||
|
||||
static void
|
||||
handle_buttonpress(XButtonPressedEvent * e)
|
||||
{
|
||||
size_t i;
|
||||
char buf[32];
|
||||
for(i = 0; i < nitem; i++)
|
||||
if(blitz_ispointinrect(e->x, e->y, &item[i]->rect)) {
|
||||
snprintf(buf, sizeof(buf), "Button%dPress %d\n", e->button, i);
|
||||
do_pend_fcall(buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
check_x_event(IXPConn *c)
|
||||
{
|
||||
XEvent e;
|
||||
|
||||
while(XPending(dpy)) {
|
||||
XNextEvent(dpy, &e);
|
||||
switch (e.type) {
|
||||
case ButtonPress:
|
||||
handle_buttonpress(&e.xbutton);
|
||||
break;
|
||||
case Expose:
|
||||
if(e.xexpose.count == 0)
|
||||
draw();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
index_of_id(unsigned short id)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < nitem; i++)
|
||||
if(item[i]->id == id)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* IXP stuff */
|
||||
|
||||
static unsigned long long
|
||||
mkqpath(unsigned char type, unsigned short id)
|
||||
{
|
||||
return ((unsigned long long) id << 8) | (unsigned long long) type;
|
||||
}
|
||||
|
||||
static unsigned char
|
||||
qpath_type(unsigned long long path)
|
||||
{
|
||||
return path & 0xff;
|
||||
}
|
||||
|
||||
static unsigned short
|
||||
qpath_id(unsigned long long path)
|
||||
{
|
||||
return (path >> 8) & 0xffff;
|
||||
}
|
||||
|
||||
static char *
|
||||
qid_to_name(Qid *qid)
|
||||
{
|
||||
unsigned char type = qpath_type(qid->path);
|
||||
unsigned short id = qpath_id(qid->path);
|
||||
int i;
|
||||
static char buf[32];
|
||||
|
||||
if(id && ((i = index_of_id(id)) == -1))
|
||||
return nil;
|
||||
switch(type) {
|
||||
case Droot: return "/"; break;
|
||||
case Ditem:
|
||||
snprintf(buf, sizeof(buf), "%u", i + 1);
|
||||
return buf;
|
||||
break;
|
||||
case Fctl: return "ctl"; break;
|
||||
case Ffont: return "font"; break;
|
||||
case Fdefcolor: return "defcolor"; break;
|
||||
case Fexpand: return "expand"; break;
|
||||
case Fdata: return "data"; break;
|
||||
case Fevent: return "event"; break;
|
||||
case Fcolor: return "color"; break;
|
||||
default: return nil; break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
name_to_type(char *name)
|
||||
{
|
||||
const char *err;
|
||||
unsigned int i;
|
||||
if(!name || !name[0] || !strncmp(name, "/", 2) || !strncmp(name, "..", 3))
|
||||
return Droot;
|
||||
if(!strncmp(name, "new", 4))
|
||||
return Ditem;
|
||||
if(!strncmp(name, "ctl", 4))
|
||||
return Fctl;
|
||||
if(!strncmp(name, "font", 5))
|
||||
return Ffont;
|
||||
if(!strncmp(name, "defcolor", 9))
|
||||
return Fdefcolor;
|
||||
if(!strncmp(name, "expand", 7))
|
||||
return Fexpand;
|
||||
if(!strncmp(name, "data", 5))
|
||||
return Fdata;
|
||||
if(!strncmp(name, "event", 6))
|
||||
return Fevent;
|
||||
if(!strncmp(name, "color", 6))
|
||||
return Fcolor;
|
||||
i = (unsigned short) cext_strtonum(name, 1, 0xffff, &err);
|
||||
if(!err && (i - 1 <= nitem))
|
||||
return Ditem;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
mkqid(Qid *dir, char *wname, Qid *new, Bool iswalk)
|
||||
{
|
||||
const char *err;
|
||||
unsigned short id = qpath_id(dir->path);
|
||||
int i, type = name_to_type(wname);
|
||||
|
||||
if(id && ((i = index_of_id(id)) == -1))
|
||||
return -1;
|
||||
|
||||
if((dir->type != IXP_QTDIR) || (type == -1))
|
||||
return -1;
|
||||
|
||||
new->dtype = qpath_type(dir->path);
|
||||
new->version = 0;
|
||||
switch(type) {
|
||||
case Droot:
|
||||
*new = root_qid;
|
||||
break;
|
||||
case Ditem:
|
||||
new->type = IXP_QTDIR;
|
||||
if(!strncmp(wname, "new", 4)) {
|
||||
/*fprintf(stderr, "mkqid iswalk=%d, wname=%s\n", iswalk, wname);*/
|
||||
if(iswalk)
|
||||
new->path = mkqpath(Ditem, new_item()->id);
|
||||
else
|
||||
new->path = mkqpath(Ditem, 0);
|
||||
}
|
||||
else {
|
||||
i = cext_strtonum(wname, 1, 0xffff, &err);
|
||||
if(err || (i - 1 >= nitem))
|
||||
return -1;
|
||||
new->path = mkqpath(Ditem, item[i - 1]->id);
|
||||
}
|
||||
break;
|
||||
case Fdata:
|
||||
case Fcolor:
|
||||
if(i >= nitem)
|
||||
return -1;
|
||||
default:
|
||||
new->type = IXP_QTFILE;
|
||||
new->path = mkqpath(type, id);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
xwalk(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
unsigned short nwqid = 0;
|
||||
Qid dir = root_qid;
|
||||
IXPMap *m;
|
||||
|
||||
if(!(m = ixp_server_fid2map(c, fcall->fid)))
|
||||
return Enofid;
|
||||
if(fcall->fid != fcall->newfid && (ixp_server_fid2map(c, fcall->newfid)))
|
||||
return Enofid;
|
||||
if(fcall->nwname) {
|
||||
dir = m->qid;
|
||||
for(nwqid = 0; (nwqid < fcall->nwname)
|
||||
&& !mkqid(&dir, fcall->wname[nwqid], &fcall->wqid[nwqid], True); nwqid++) {
|
||||
/*fprintf(stderr, "wname=%s nwqid=%d\n", fcall->wname[nwqid], nwqid);*/
|
||||
dir = fcall->wqid[nwqid];
|
||||
}
|
||||
if(!nwqid)
|
||||
return Enofile;
|
||||
}
|
||||
/* a fid will only be valid, if the walk was complete */
|
||||
if(nwqid == fcall->nwname) {
|
||||
if(fcall->fid != fcall->newfid) {
|
||||
m = cext_emallocz(sizeof(IXPMap));
|
||||
c->map = (IXPMap **)cext_array_attach((void **)c->map,
|
||||
m, sizeof(IXPMap *), &c->mapsz);
|
||||
}
|
||||
m->qid = dir;
|
||||
m->fid = fcall->newfid;
|
||||
}
|
||||
fcall->id = RWALK;
|
||||
fcall->nwqid = nwqid;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static char *
|
||||
xopen(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
if(!(fcall->mode | IXP_OREAD) && !(fcall->mode | IXP_OWRITE))
|
||||
return Enomode;
|
||||
fcall->id = ROPEN;
|
||||
fcall->qid = m->qid;
|
||||
fcall->iounit = 256;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
mkstat(Stat *stat, Qid *dir, char *name, unsigned long long length, unsigned int mode)
|
||||
{
|
||||
stat->mode = mode;
|
||||
stat->atime = stat->mtime = time(0);
|
||||
cext_strlcpy(stat->uid, getenv("USER"), sizeof(stat->uid));
|
||||
cext_strlcpy(stat->gid, getenv("USER"), sizeof(stat->gid));
|
||||
cext_strlcpy(stat->muid, getenv("USER"), sizeof(stat->muid));
|
||||
|
||||
cext_strlcpy(stat->name, name, sizeof(stat->name));
|
||||
stat->length = length;
|
||||
mkqid(dir, name, &stat->qid, False);
|
||||
return ixp_sizeof_stat(stat);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
type_to_stat(Stat *stat, char *name, Qid *dir)
|
||||
{
|
||||
int i, type = name_to_type(name);
|
||||
unsigned short id = qpath_id(dir->path);
|
||||
char buf[16];
|
||||
|
||||
if(id && ((i = index_of_id(id)) == -1))
|
||||
return 0;
|
||||
switch (type) {
|
||||
case Droot:
|
||||
case Ditem:
|
||||
return mkstat(stat, dir, name, 0, DMDIR | DMREAD | DMEXEC);
|
||||
break;
|
||||
case Fctl:
|
||||
return mkstat(stat, dir, name, 0, DMWRITE);
|
||||
break;
|
||||
case Fevent:
|
||||
return mkstat(stat, dir, name, 0, DMREAD);
|
||||
break;
|
||||
case Ffont:
|
||||
return mkstat(stat, dir, name, strlen(font), DMREAD | DMWRITE);
|
||||
break;
|
||||
case Fdefcolor:
|
||||
return mkstat(stat, dir, name, 23, DMREAD | DMWRITE);
|
||||
break;
|
||||
case Fexpand:
|
||||
snprintf(buf, sizeof(buf), "%u", iexpand + 1);
|
||||
return mkstat(stat, dir, name, strlen(buf), DMREAD | DMWRITE);
|
||||
break;
|
||||
case Fdata:
|
||||
return mkstat(stat, dir, name, (i == nitem) ? 0 : strlen(item[i]->data), DMREAD | DMWRITE);
|
||||
break;
|
||||
case Fcolor:
|
||||
return mkstat(stat, dir, name, 23, DMREAD | DMWRITE);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
xremove(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
unsigned short id = qpath_id(m->qid.path);
|
||||
int i;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
if(id && ((i = qpath_id(id)) == -1))
|
||||
return Enofile;
|
||||
if((qpath_type(m->qid.path) == Ditem) && (i < nitem)) {
|
||||
Item *it = item[i];
|
||||
/* clunk */
|
||||
cext_array_detach((void **)c->map, m, &c->mapsz);
|
||||
free(m);
|
||||
/* now detach the item */
|
||||
detach_item(it);
|
||||
free(it);
|
||||
if(iexpand >= nitem)
|
||||
iexpand = 0;
|
||||
draw();
|
||||
fcall->id = RREMOVE;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
return Enoperm;
|
||||
}
|
||||
|
||||
static char *
|
||||
xread(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
Stat stat;
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
unsigned short id;
|
||||
unsigned char *p = fcall->data;
|
||||
unsigned int len;
|
||||
int i;
|
||||
char buf[32];
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
id = qpath_id(m->qid.path);
|
||||
if(id && ((i = index_of_id(id)) == -1))
|
||||
return Enofile;
|
||||
|
||||
fcall->count = 0;
|
||||
if(fcall->offset) {
|
||||
switch (qpath_type(m->qid.path)) {
|
||||
case Droot:
|
||||
/* jump to offset */
|
||||
len = type_to_stat(&stat, "ctl", &m->qid);
|
||||
len += type_to_stat(&stat, "font", &m->qid);
|
||||
len += type_to_stat(&stat, "defcolor", &m->qid);
|
||||
len += type_to_stat(&stat, "expand", &m->qid);
|
||||
len += type_to_stat(&stat, "new", &m->qid);
|
||||
len += type_to_stat(&stat, "event", &m->qid);
|
||||
for(i = 0; i < nitem; i++) {
|
||||
snprintf(buf, sizeof(buf), "%u", i + 1);
|
||||
len += type_to_stat(&stat, buf, &m->qid);
|
||||
if(len <= fcall->offset)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
/* offset found, proceeding */
|
||||
for(; i < nitem; i++) {
|
||||
snprintf(buf, sizeof(buf), "%u", i + 1);
|
||||
len = type_to_stat(&stat, buf, &m->qid);
|
||||
if(fcall->count + len > fcall->iounit)
|
||||
break;
|
||||
fcall->count += len;
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
}
|
||||
break;
|
||||
case Fevent:
|
||||
ixp_server_enqueue_fcall(c, fcall);
|
||||
return nil;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (qpath_type(m->qid.path)) {
|
||||
case Droot:
|
||||
fcall->count = type_to_stat(&stat, "ctl", &m->qid);
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
fcall->count += type_to_stat(&stat, "font", &m->qid);
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
fcall->count += type_to_stat(&stat, "defcolor", &m->qid);
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
fcall->count += type_to_stat(&stat, "expand", &m->qid);
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
fcall->count += type_to_stat(&stat, "new", &m->qid);
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
fcall->count += type_to_stat(&stat, "event", &m->qid);
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
for(i = 0; i < nitem; i++) {
|
||||
snprintf(buf, sizeof(buf), "%u", i + 1);
|
||||
len = type_to_stat(&stat, buf, &m->qid);
|
||||
if(fcall->count + len > fcall->iounit)
|
||||
break;
|
||||
fcall->count += len;
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
}
|
||||
break;
|
||||
case Ditem:
|
||||
if(i >= nitem)
|
||||
return Enofile;
|
||||
fcall->count = type_to_stat(&stat, "color", &m->qid);
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
fcall->count += type_to_stat(&stat, "data", &m->qid);
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
break;
|
||||
case Fctl:
|
||||
return Enoperm;
|
||||
break;
|
||||
case Ffont:
|
||||
if((fcall->count = strlen(font)))
|
||||
memcpy(p, font, fcall->count);
|
||||
break;
|
||||
case Fdefcolor:
|
||||
if((fcall->count = strlen(defcolstr)))
|
||||
memcpy(p, defcolstr, fcall->count);
|
||||
break;
|
||||
case Fexpand:
|
||||
snprintf(buf, sizeof(buf), "%u", iexpand + 1);
|
||||
fcall->count = strlen(buf);
|
||||
memcpy(p, buf, fcall->count);
|
||||
break;
|
||||
case Fdata:
|
||||
if(i >= nitem)
|
||||
return Enofile;
|
||||
if((fcall->count = strlen(item[i]->data)))
|
||||
memcpy(p, item[i]->data, fcall->count);
|
||||
break;
|
||||
case Fcolor:
|
||||
if(i >= nitem)
|
||||
return Enofile;
|
||||
if((fcall->count = strlen(item[i]->colstr)))
|
||||
memcpy(p, item[i]->colstr, fcall->count);
|
||||
break;
|
||||
case Fevent:
|
||||
ixp_server_enqueue_fcall(c, fcall);
|
||||
return nil;
|
||||
break;
|
||||
default:
|
||||
return "invalid read";
|
||||
break;
|
||||
}
|
||||
}
|
||||
fcall->id = RREAD;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static char *
|
||||
xstat(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
char *name;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
name = qid_to_name(&m->qid);
|
||||
/*fprintf(stderr, "xstat: name=%s\n", name);*/
|
||||
if(!type_to_stat(&fcall->stat, name, &m->qid))
|
||||
return Enofile;
|
||||
fcall->id = RSTAT;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static char *
|
||||
xwrite(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
char buf[256];
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
unsigned short id;
|
||||
int i;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
id = qpath_id(m->qid.path);
|
||||
if(id && ((i = index_of_id(id)) == -1))
|
||||
return Enofile;
|
||||
switch (qpath_type(m->qid.path)) {
|
||||
case Fctl:
|
||||
if(fcall->count == 4) {
|
||||
memcpy(buf, fcall->data, 4);
|
||||
buf[4] = 0;
|
||||
if(!strncmp(buf, "quit", 5)) {
|
||||
srv.running = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Enocommand;
|
||||
break;
|
||||
case Ffont:
|
||||
if(font)
|
||||
free(font);
|
||||
font = cext_emallocz(fcall->count + 1);
|
||||
memcpy(font, fcall->data, fcall->count);
|
||||
XFreeFont(dpy, xfont);
|
||||
xfont = blitz_getfont(dpy, font);
|
||||
update_geometry();
|
||||
break;
|
||||
case Fdefcolor:
|
||||
if((fcall->count != 23)
|
||||
|| (fcall->data[0] != '#') || (fcall->data[8] != '#')
|
||||
|| (fcall->data[16] != '#')
|
||||
)
|
||||
return "wrong color format";
|
||||
memcpy(defcolstr, fcall->data, fcall->count);
|
||||
defcolstr[fcall->count] = 0;
|
||||
blitz_loadcolor(dpy, screen, defcolstr, &defcolor);
|
||||
break;
|
||||
case Fexpand:
|
||||
{
|
||||
const char *err;
|
||||
if(fcall->count && fcall->count < 16) {
|
||||
memcpy(buf, fcall->data, fcall->count);
|
||||
buf[fcall->count] = 0;
|
||||
i = (unsigned short) cext_strtonum(buf, 1, 0xffff, &err);
|
||||
if(!err && (i - 1 < nitem)) {
|
||||
iexpand = i - 1;
|
||||
draw();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Enofile;
|
||||
break;
|
||||
case Fdata:
|
||||
{
|
||||
unsigned int len = fcall->count;
|
||||
if(i >= nitem)
|
||||
return Enofile;
|
||||
if(len >= sizeof(item[i]->data))
|
||||
len = sizeof(item[i]->data) - 1;
|
||||
memcpy(item[i]->data, fcall->data, len);
|
||||
item[i]->data[len] = 0;
|
||||
draw();
|
||||
}
|
||||
break;
|
||||
case Fcolor:
|
||||
if((i >= nitem) || (fcall->count != 23)
|
||||
|| (fcall->data[0] != '#') || (fcall->data[8] != '#')
|
||||
|| (fcall->data[16] != '#')
|
||||
)
|
||||
return "wrong color format";
|
||||
memcpy(item[i]->colstr, fcall->data, fcall->count);
|
||||
item[i]->colstr[fcall->count] = 0;
|
||||
blitz_loadcolor(dpy, screen, item[i]->colstr, &item[i]->color);
|
||||
draw();
|
||||
break;
|
||||
default:
|
||||
return "invalid write";
|
||||
break;
|
||||
}
|
||||
fcall->id = RWRITE;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
do_fcall(IXPConn *c)
|
||||
{
|
||||
static Fcall fcall;
|
||||
unsigned int msize;
|
||||
char *errstr;
|
||||
|
||||
if((msize = ixp_server_receive_fcall(c, &fcall))) {
|
||||
/*fprintf(stderr, "fcall=%d\n", fcall.id);*/
|
||||
switch(fcall.id) {
|
||||
case TVERSION: errstr = wmii_ixp_version(c, &fcall); break;
|
||||
case TATTACH: errstr = wmii_ixp_attach(c, &fcall); break;
|
||||
case TWALK: errstr = xwalk(c, &fcall); break;
|
||||
case TREMOVE: errstr = xremove(c, &fcall); break;
|
||||
case TOPEN: errstr = xopen(c, &fcall); break;
|
||||
case TREAD: errstr = xread(c, &fcall); break;
|
||||
case TWRITE: errstr = xwrite(c, &fcall); break;
|
||||
case TCLUNK: errstr = wmii_ixp_clunk(c, &fcall); break;
|
||||
case TSTAT: errstr = xstat(c, &fcall); break;
|
||||
default: errstr = Enofunc; break;
|
||||
}
|
||||
if(errstr)
|
||||
ixp_server_respond_error(c, &fcall, errstr);
|
||||
}
|
||||
check_x_event(nil);
|
||||
}
|
||||
|
||||
static void
|
||||
do_pend_fcall(char *event)
|
||||
{
|
||||
size_t i;
|
||||
Fcall *fcall;
|
||||
for(i = 0; (i < srv.connsz) && srv.conn[i]; i++) {
|
||||
IXPConn *c = srv.conn[i];
|
||||
/* all pending TREADs are on /event, so no qid checking necessary */
|
||||
while((fcall = ixp_server_dequeue_fcall_id(c, TREAD))) {
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
unsigned char *p = fcall->data;
|
||||
|
||||
if(!m) {
|
||||
if(ixp_server_respond_error(c, fcall, Enofid))
|
||||
break;
|
||||
}
|
||||
else if(qpath_type(m->qid.path) == Fevent) {
|
||||
fcall->count = strlen(event);
|
||||
memcpy(p, event, fcall->count);
|
||||
fcall->id = RREAD;
|
||||
if(ixp_server_respond_fcall(c, fcall))
|
||||
break;
|
||||
}
|
||||
free(fcall);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
new_ixp_conn(IXPConn *c)
|
||||
{
|
||||
int fd = ixp_accept_sock(c->fd);
|
||||
|
||||
if(fd >= 0)
|
||||
ixp_server_open_conn(c->srv, fd, do_fcall, ixp_server_close_conn);
|
||||
}
|
||||
|
||||
/* main */
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
char *errstr;
|
||||
char *address = nil;
|
||||
XSetWindowAttributes wa;
|
||||
|
||||
/* command line args */
|
||||
for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
|
||||
switch (argv[i][1]) {
|
||||
case 'v':
|
||||
fprintf(stdout, "%s", version);
|
||||
exit(0);
|
||||
break;
|
||||
case 'a':
|
||||
if(i + 1 < argc)
|
||||
address = argv[++i];
|
||||
else
|
||||
usage();
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!address)
|
||||
usage();
|
||||
|
||||
dpy = XOpenDisplay(0);
|
||||
if(!dpy) {
|
||||
fprintf(stderr, "%s", "wmiibar: cannot open display\n");
|
||||
exit(1);
|
||||
}
|
||||
XSetErrorHandler(dummy_error_handler);
|
||||
screen = DefaultScreen(dpy);
|
||||
|
||||
i = ixp_create_sock(address, &errstr);
|
||||
if(i < 0) {
|
||||
fprintf(stderr, "wmiibar: fatal: %s\n", errstr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* IXP server */
|
||||
ixp_server_open_conn(&srv, i, new_ixp_conn, ixp_server_close_conn);
|
||||
root_qid.type = IXP_QTDIR;
|
||||
root_qid.version = 0;
|
||||
root_qid.path = mkqpath(Droot, 0);
|
||||
|
||||
/* X server */
|
||||
ixp_server_open_conn(&srv, ConnectionNumber(dpy), check_x_event, nil);
|
||||
|
||||
/* default settings */
|
||||
cext_strlcpy(defcolstr, BLITZ_SELCOLORS, sizeof(defcolstr));
|
||||
blitz_loadcolor(dpy, screen, defcolstr, &defcolor);
|
||||
|
||||
/* X stuff */
|
||||
font = strdup(BLITZ_FONT);
|
||||
xfont = blitz_getfont(dpy, font);
|
||||
wa.override_redirect = 1;
|
||||
wa.background_pixmap = ParentRelative;
|
||||
wa.event_mask = ExposureMask | ButtonPressMask
|
||||
| SubstructureRedirectMask | SubstructureNotifyMask;
|
||||
|
||||
rect.x = rect.y = 0;
|
||||
rect.width = DisplayWidth(dpy, screen);
|
||||
rect.height = DisplayHeight(dpy, screen);
|
||||
brect = rect;
|
||||
brect.height = xfont->ascent + xfont->descent + 4;
|
||||
brect.y = rect.height - brect.height;
|
||||
|
||||
win = XCreateWindow(dpy, RootWindow(dpy, screen), brect.x, brect.y,
|
||||
brect.width, brect.height, 0, DefaultDepth(dpy, screen),
|
||||
CopyFromParent, DefaultVisual(dpy, screen),
|
||||
CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
|
||||
XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_left_ptr));
|
||||
XSync(dpy, False);
|
||||
|
||||
gc = XCreateGC(dpy, win, 0, 0);
|
||||
|
||||
pmap = XCreatePixmap(dpy, win, brect.width, brect.height,
|
||||
DefaultDepth(dpy, screen));
|
||||
|
||||
/* main loop */
|
||||
XMapRaised(dpy, win);
|
||||
draw();
|
||||
|
||||
errstr = ixp_server_loop(&srv);
|
||||
if(errstr)
|
||||
fprintf(stderr, "wmiibar: fatal: %s\n", errstr);
|
||||
|
||||
/* cleanup */
|
||||
ixp_server_close(&srv);
|
||||
XCloseDisplay(dpy);
|
||||
|
||||
return errstr ? 1 : 0;
|
||||
}
|
38
cmd/wmiifs.1
38
cmd/wmiifs.1
|
@ -1,38 +0,0 @@
|
|||
.TH WMIIFS 1 wmii-3
|
||||
.SH NAME
|
||||
wmiifs \- window manager improved 2 filesystem
|
||||
.SH SYNOPSIS
|
||||
.B wmiifs
|
||||
.B \-s
|
||||
.I socketfile
|
||||
.SH DESCRIPTION
|
||||
.SS Overview
|
||||
.B wmiifs
|
||||
is a socket-based fileserver which is used for binding other fileserver
|
||||
filesystems to a specific namespace. It routes filesystem accesses to
|
||||
the specific fileserver and behaves to the outside as one master
|
||||
filesystem.
|
||||
.SS Options
|
||||
.TP
|
||||
.BI \-s " socketfile"
|
||||
specifies the socketfile that
|
||||
.B wmiifs
|
||||
should create.
|
||||
.TP
|
||||
.B \-v
|
||||
prints version information to stderr, then exits.
|
||||
.SS Customization
|
||||
.B wmiifs
|
||||
is customized through manipulating its filesystem namespace.
|
||||
In the default setup of
|
||||
.BR wmii (1)
|
||||
the namespace of
|
||||
.B wmiifs
|
||||
can be found in /.
|
||||
.SH SEE ALSO
|
||||
.BR wmiibar (1),
|
||||
.BR wmii (1),
|
||||
.BR wmiiwm (1),
|
||||
.BR wmiikeys (1),
|
||||
.BR wmiimenu (1),
|
||||
.BR wmiir (1)
|
791
cmd/wmiifs.c
791
cmd/wmiifs.c
|
@ -1,791 +0,0 @@
|
|||
/*
|
||||
* (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "wmii.h"
|
||||
|
||||
/*
|
||||
* filesystem specification
|
||||
* / Droot
|
||||
* /ctl Fctl command interface
|
||||
* /foobar Dmount
|
||||
*/
|
||||
|
||||
/* 8-bit qid.path.type */
|
||||
enum {
|
||||
Droot,
|
||||
Dmount,
|
||||
Fctl
|
||||
};
|
||||
|
||||
typedef struct Bind Bind;
|
||||
struct Bind {
|
||||
unsigned int fid;
|
||||
Fcall fcall;
|
||||
IXPClient client;
|
||||
IXPConn *rx;
|
||||
IXPConn *tx;
|
||||
};
|
||||
|
||||
typedef struct Mount Mount;
|
||||
struct Mount {
|
||||
unsigned short id;
|
||||
char wname[IXP_MAX_FLEN];
|
||||
char address[256];
|
||||
};
|
||||
|
||||
Qid root_qid;
|
||||
static Display *dpy;
|
||||
static IXPServer srv;
|
||||
static Mount **mount = nil;
|
||||
static size_t mountsz = 0;
|
||||
static size_t nmount = 0;
|
||||
static unsigned char *msg[IXP_MAX_MSG];
|
||||
static Bind **bind = nil;
|
||||
static size_t bindsz = 0;
|
||||
static size_t nbind = 0;
|
||||
|
||||
static void do_mnt_fcall(IXPConn *c);
|
||||
|
||||
static char version[] = "wmiifs - " VERSION ", (C)opyright MMIV-MMVI Anselm R. Garbe\n";
|
||||
static char Enoserv[] = "server not found";
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "usage: wmiifs -a <address> [-v]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static Mount *
|
||||
name_to_mount(char *name)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < nmount; i++)
|
||||
if(!strncmp(mount[i]->wname, name, sizeof(mount[i]->wname)))
|
||||
return mount[i];
|
||||
return nil;
|
||||
}
|
||||
|
||||
static Bind *
|
||||
fid_to_bind(unsigned int fid)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < nbind; i++)
|
||||
if(bind[i]->fid == fid)
|
||||
return bind[i];
|
||||
return nil;
|
||||
}
|
||||
|
||||
static Bind *
|
||||
rx_to_bind(IXPConn *c)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < nbind; i++)
|
||||
if(bind[i]->rx == c)
|
||||
return bind[i];
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
xunbind(Bind *b) {
|
||||
cext_array_detach((void **)srv.conn, b->rx, &srv.connsz);
|
||||
free(b->rx);
|
||||
cext_array_detach((void **)bind, b, &bindsz);
|
||||
nbind--;
|
||||
ixp_client_deinit(&b->client);
|
||||
if(b->tx && b->tx->close)
|
||||
b->tx->close(b->tx);
|
||||
free(b);
|
||||
}
|
||||
|
||||
static void
|
||||
close_rx_conn(IXPConn *c)
|
||||
{
|
||||
Bind *b = rx_to_bind(c);
|
||||
if(!b)
|
||||
return;
|
||||
xunbind(b);
|
||||
}
|
||||
|
||||
static Bind *
|
||||
xbind(char *address, unsigned int fid)
|
||||
{
|
||||
char addr[256];
|
||||
Bind *b = cext_emallocz(sizeof(Bind));
|
||||
|
||||
cext_strlcpy(addr, address, sizeof(addr));
|
||||
if(ixp_client_init(&b->client, addr, fid) == -1) {
|
||||
free(b);
|
||||
return nil;
|
||||
}
|
||||
b->rx = ixp_server_open_conn(&srv, b->client.fd, do_mnt_fcall, close_rx_conn);
|
||||
bind = (Bind **)cext_array_attach((void **)bind, b, sizeof(Bind *), &bindsz);
|
||||
nbind++;
|
||||
return b;
|
||||
}
|
||||
|
||||
static void
|
||||
xunmount(Mount *mnt) /* called by xremove */
|
||||
{
|
||||
cext_array_detach((void **)mount, mnt, &mountsz);
|
||||
nmount--;
|
||||
free(mnt);
|
||||
}
|
||||
|
||||
static char *
|
||||
xmount(char *arg)
|
||||
{
|
||||
char *address = arg;
|
||||
char *p, *wname = strchr(address, ' ');
|
||||
Mount *mnt;
|
||||
|
||||
if(!wname)
|
||||
return "no mount point supplied";
|
||||
*wname = 0;
|
||||
wname++;
|
||||
if(*wname == '/')
|
||||
wname++;
|
||||
p = strchr(wname, '/');
|
||||
if(p)
|
||||
*p = 0; /* mount name is not allowed to contain slashes */
|
||||
|
||||
if(!address || !wname || !*address || !*wname)
|
||||
return Enoserv;
|
||||
|
||||
if(!(mnt = name_to_mount(wname))) {
|
||||
mnt = cext_emallocz(sizeof(Mount));
|
||||
cext_strlcpy(mnt->address, address, sizeof(mnt->address));
|
||||
mount = (Mount **)cext_array_attach((void **)mount, mnt, sizeof(Mount *), &mountsz);
|
||||
nmount++;
|
||||
}
|
||||
cext_strlcpy(mnt->wname, wname, sizeof(mnt->wname));
|
||||
return nil;
|
||||
}
|
||||
|
||||
static int
|
||||
index_of_id(unsigned short id)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < nmount; i++)
|
||||
if(mount[i]->id == id)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* IXP stuff */
|
||||
|
||||
static unsigned long long
|
||||
mkqpath(unsigned char type, unsigned short id)
|
||||
{
|
||||
return ((unsigned long long) id << 8) | (unsigned long long) type;
|
||||
}
|
||||
|
||||
static unsigned char
|
||||
qpath_type(unsigned long long path)
|
||||
{
|
||||
return path & 0xff;
|
||||
}
|
||||
|
||||
static unsigned short
|
||||
qpath_id(unsigned long long path)
|
||||
{
|
||||
return (path >> 8) & 0xffff;
|
||||
}
|
||||
|
||||
static char *
|
||||
qid_to_name(Qid *qid)
|
||||
{
|
||||
unsigned char type = qpath_type(qid->path);
|
||||
unsigned short id = qpath_id(qid->path);
|
||||
int i;
|
||||
|
||||
if(id && ((i = index_of_id(id)) == -1))
|
||||
return nil;
|
||||
switch(type) {
|
||||
case Droot: return "/"; break;
|
||||
case Dmount: return mount[i]->wname; break;
|
||||
case Fctl: return "ctl"; break;
|
||||
default: return nil; break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
name_to_type(char *name)
|
||||
{
|
||||
if(!name || !name[0] || !strncmp(name, "/", 2) || !strncmp(name, "..", 3))
|
||||
return Droot;
|
||||
if(!strncmp(name, "ctl", 4))
|
||||
return Fctl;
|
||||
if(name_to_mount(name))
|
||||
return Dmount;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
mkqid(Qid *dir, char *wname, Qid *new, Bool iswalk)
|
||||
{
|
||||
Mount *mnt;
|
||||
int type = name_to_type(wname);
|
||||
|
||||
if((dir->type != IXP_QTDIR) || (type == -1))
|
||||
return -1;
|
||||
|
||||
new->dtype = qpath_type(dir->path);
|
||||
new->version = 0;
|
||||
switch(type) {
|
||||
case Droot:
|
||||
*new = root_qid;
|
||||
break;
|
||||
case Dmount:
|
||||
if(!(mnt = name_to_mount(wname)))
|
||||
return -1;
|
||||
new->type = IXP_QTDIR;
|
||||
new->path = mkqpath(type, mnt->id);
|
||||
break;
|
||||
default:
|
||||
new->type = IXP_QTFILE;
|
||||
new->path = mkqpath(type, 0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
mkstat(Stat *stat, Qid *dir, char *name, unsigned long long length, unsigned int mode)
|
||||
{
|
||||
stat->mode = mode;
|
||||
stat->atime = stat->mtime = time(0);
|
||||
cext_strlcpy(stat->uid, getenv("USER"), sizeof(stat->uid));
|
||||
cext_strlcpy(stat->gid, getenv("USER"), sizeof(stat->gid));
|
||||
cext_strlcpy(stat->muid, getenv("USER"), sizeof(stat->muid));
|
||||
|
||||
cext_strlcpy(stat->name, name, sizeof(stat->name));
|
||||
stat->length = length;
|
||||
mkqid(dir, name, &stat->qid, False);
|
||||
return ixp_sizeof_stat(stat);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
type_to_stat(Stat *stat, char *name, Qid *dir)
|
||||
{
|
||||
Mount *mnt;
|
||||
int type = name_to_type(name);
|
||||
|
||||
switch (type) {
|
||||
case Droot:
|
||||
return mkstat(stat, dir, name, 0, DMDIR | DMREAD | DMEXEC);
|
||||
break;
|
||||
case Fctl:
|
||||
return mkstat(stat, dir, name, 0, DMWRITE);
|
||||
break;
|
||||
case Dmount:
|
||||
if(!(mnt = name_to_mount(name)))
|
||||
return -1;
|
||||
return mkstat(stat, dir, name, 0, DMDIR | DMREAD | DMEXEC | DMMOUNT);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mntrespond(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
Bind *b = rx_to_bind(c);
|
||||
/*fprintf(stderr, "mntrespond, welcome: fcall->id=%d\n", fcall->id);*/
|
||||
memcpy(&b->fcall, fcall, sizeof(Fcall));
|
||||
ixp_server_respond_fcall(b->tx, &b->fcall);
|
||||
}
|
||||
|
||||
static void
|
||||
mntwalk(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
Qid dir = root_qid;
|
||||
Bind *b = rx_to_bind(c);
|
||||
unsigned int nwqid;
|
||||
IXPMap *m;
|
||||
|
||||
if(!(m = ixp_server_fid2map(b->tx, b->fcall.fid))) {
|
||||
ixp_server_respond_error(b->tx, &b->fcall, Enofid);
|
||||
xunbind(b);
|
||||
return;
|
||||
}
|
||||
|
||||
if(mkqid(&dir, b->fcall.wname[0], &b->fcall.wqid[0], True) == -1) {
|
||||
/*fprintf(stderr, "%s", "wmiifs: mntwalk cannot make qid\n");*/
|
||||
ixp_server_respond_error(b->tx, &b->fcall, Enofile);
|
||||
xunbind(b);
|
||||
return;
|
||||
}
|
||||
dir = b->fcall.wqid[0]; /* mount point */
|
||||
for(nwqid = 0; nwqid < fcall->nwqid; nwqid++)
|
||||
b->fcall.wqid[nwqid + 1] = fcall->wqid[nwqid];
|
||||
nwqid++;
|
||||
|
||||
if(!nwqid) {
|
||||
/*fprintf(stderr, "%s", "wmiifs: mntwalk nwqid wrong \n");*/
|
||||
ixp_server_respond_error(b->tx, &b->fcall, Enofile);
|
||||
xunbind(b);
|
||||
return;
|
||||
}
|
||||
|
||||
/* a fid will only be valid, if the walk was complete */
|
||||
/*fprintf(stderr, "nwqid=%d b->fcall.nwname=%d", nwqid, b->fcall.nwname);*/
|
||||
if(nwqid == b->fcall.nwname) {
|
||||
if(b->fcall.fid != b->fcall.newfid) {
|
||||
m = cext_emallocz(sizeof(IXPMap));
|
||||
b->tx->map = (IXPMap **)
|
||||
cext_array_attach((void **)b->tx->map, m, sizeof(IXPMap *), &b->tx->mapsz);
|
||||
}
|
||||
m->qid = dir; /* mount point, even if not */
|
||||
m->fid = b->fcall.newfid;
|
||||
/*fprintf(stderr, "%s", "wmiifs: fffaoooo\n");*/
|
||||
}
|
||||
/*fprintf(stderr, "wmiifs: success mntwalk b-tx=%x m->fid = %d (b->fcall.newfid=%d)\n",
|
||||
b->tx, m->fid, b->fcall.newfid);*/
|
||||
b->fid = m->fid;
|
||||
b->fcall.id = RWALK;
|
||||
b->fcall.nwqid = nwqid;
|
||||
ixp_server_respond_fcall(b->tx, &b->fcall);
|
||||
}
|
||||
|
||||
static char *
|
||||
mntrequest(Bind *b, Fcall *tx)
|
||||
{
|
||||
unsigned int msize;
|
||||
/*fprintf(stderr, "mntrequest: welcome, tx=%x tx->id=%d fid=%d\n", b->tx, tx->id, tx->fid);*/
|
||||
memcpy(&b->client.fcall, tx, sizeof(Fcall));
|
||||
memcpy(&b->fcall, tx, sizeof(Fcall));
|
||||
msize = ixp_fcall_to_msg(msg, &b->client.fcall, IXP_MAX_MSG);
|
||||
b->client.errstr = 0;
|
||||
if(ixp_send_message(b->client.fd, msg, msize, &b->client.errstr) != msize) {
|
||||
xunbind(b);
|
||||
return Enofile;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
static char *
|
||||
xwalk(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
unsigned short nwqid = 0;
|
||||
Qid dir = root_qid;
|
||||
IXPMap *m;
|
||||
Mount *mnt;
|
||||
|
||||
/*fprintf(stderr, "xwalk: welcome fcall->wname[0]=%s fcall->fid=%d\n", fcall->wname[0], fcall->fid);*/
|
||||
if(!(m = ixp_server_fid2map(c, fcall->fid)))
|
||||
return Enofid;
|
||||
if(fcall->fid != fcall->newfid && (ixp_server_fid2map(c, fcall->newfid)))
|
||||
return Enofid;
|
||||
/*fprintf(stderr, "xwalk: fcall->nwname=%d\n", fcall->nwname);*/
|
||||
if(fcall->nwname) {
|
||||
dir = m->qid;
|
||||
if((mnt = name_to_mount(fcall->wname[0]))) {
|
||||
unsigned int i;
|
||||
Bind *b;
|
||||
|
||||
if(!(b = xbind(mnt->address, fcall->fid)))
|
||||
return Enoserv;
|
||||
|
||||
memcpy(&b->client.fcall, fcall, sizeof(Fcall));
|
||||
memcpy(&b->fcall, fcall, sizeof(Fcall));
|
||||
/*fprintf(stderr, "xwalk: sending fid=%d (newfid=%d)\n", b->client.fcall.fid, b->client.fcall.newfid);*/
|
||||
|
||||
b->client.fcall.nwname = fcall->nwname - 1;
|
||||
for(i = 1; i < fcall->nwname; i++)
|
||||
cext_strlcpy(b->client.fcall.wname[i - 1], fcall->wname[i],
|
||||
sizeof(b->client.fcall.wname[i - 1]));
|
||||
|
||||
i = ixp_fcall_to_msg(msg, &b->client.fcall, IXP_MAX_MSG);
|
||||
b->client.errstr = 0;
|
||||
if(ixp_send_message(b->client.fd, msg, i, &b->client.errstr) != i) {
|
||||
xunbind(b);
|
||||
return Enofile;
|
||||
}
|
||||
b->tx = c;
|
||||
return nil;
|
||||
}
|
||||
else {
|
||||
for(nwqid = 0; (nwqid < fcall->nwname)
|
||||
&& !mkqid(&dir, fcall->wname[nwqid], &fcall->wqid[nwqid], True); nwqid++) {
|
||||
dir = fcall->wqid[nwqid];
|
||||
}
|
||||
if(!nwqid)
|
||||
return Enofile;
|
||||
}
|
||||
}
|
||||
/* a fid will only be valid, if the walk was complete */
|
||||
if(nwqid == fcall->nwname) {
|
||||
if(fcall->fid != fcall->newfid) {
|
||||
m = cext_emallocz(sizeof(IXPMap));
|
||||
c->map = (IXPMap **)cext_array_attach((void **)c->map,
|
||||
m, sizeof(IXPMap *), &c->mapsz);
|
||||
}
|
||||
m->qid = dir;
|
||||
m->fid = fcall->newfid;
|
||||
}
|
||||
fcall->id = RWALK;
|
||||
fcall->nwqid = nwqid;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static char *
|
||||
xcreate(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
Bind *b;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
if((b = fid_to_bind(m->fid)))
|
||||
return mntrequest(b, fcall);
|
||||
return Enoperm;
|
||||
}
|
||||
|
||||
static char *
|
||||
xopen(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
Bind *b;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
if((b = fid_to_bind(m->fid)))
|
||||
return mntrequest(b, fcall);
|
||||
if(!(fcall->mode | IXP_OREAD) && !(fcall->mode | IXP_OWRITE))
|
||||
return Enomode;
|
||||
fcall->id = ROPEN;
|
||||
fcall->qid = m->qid;
|
||||
fcall->iounit = 2048;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
mntclunkremove(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
Bind *b = rx_to_bind(c);
|
||||
IXPMap *m;
|
||||
|
||||
if(!(m = ixp_server_fid2map(b->tx, b->fcall.fid))) {
|
||||
ixp_server_respond_error(b->tx, &b->fcall, Enofid);
|
||||
xunbind(b);
|
||||
return;
|
||||
}
|
||||
cext_array_detach((void **)b->tx->map, m, &b->tx->mapsz);
|
||||
free(m);
|
||||
ixp_server_respond_fcall(b->tx, &b->fcall);
|
||||
xunbind(b);
|
||||
}
|
||||
|
||||
static char *
|
||||
xremove(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
Bind *b;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
if((b = fid_to_bind(m->fid)))
|
||||
return mntrequest(b, fcall);
|
||||
return Enoperm;
|
||||
}
|
||||
|
||||
static char *
|
||||
xread(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
Stat stat;
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
unsigned short id;
|
||||
unsigned char *p = fcall->data;
|
||||
unsigned int len = 0;
|
||||
Bind *b;
|
||||
int i;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
if((b = fid_to_bind(m->fid)))
|
||||
return mntrequest(b, fcall);
|
||||
id = qpath_id(m->qid.path);
|
||||
if(id && ((i = index_of_id(id)) == -1))
|
||||
return Enofile;
|
||||
|
||||
fcall->count = 0;
|
||||
if(fcall->offset) {
|
||||
switch (qpath_type(m->qid.path)) {
|
||||
case Droot:
|
||||
/* jump to offset */
|
||||
len = type_to_stat(&stat, "ctl", &m->qid);
|
||||
for(i = 0; i < nmount; i++) {
|
||||
len += type_to_stat(&stat, mount[i]->wname, &m->qid);
|
||||
if(len <= fcall->offset)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
/* offset found, proceeding */
|
||||
for(; i < nmount; i++) {
|
||||
len = type_to_stat(&stat, mount[i]->wname, &m->qid);
|
||||
if(fcall->count + len > fcall->iounit)
|
||||
break;
|
||||
fcall->count += len;
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (qpath_type(m->qid.path)) {
|
||||
case Droot:
|
||||
fcall->count = type_to_stat(&stat, "ctl", &m->qid);
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
for(i = 0; i < nmount; i++) {
|
||||
len = type_to_stat(&stat, mount[i]->wname, &m->qid);
|
||||
if(fcall->count + len > fcall->iounit)
|
||||
break;
|
||||
fcall->count += len;
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
}
|
||||
break;
|
||||
case Dmount:
|
||||
/* TODO: */
|
||||
break;
|
||||
case Fctl:
|
||||
return Enoperm;
|
||||
break;
|
||||
default:
|
||||
return "invalid read";
|
||||
break;
|
||||
}
|
||||
}
|
||||
fcall->id = RREAD;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static char *
|
||||
xstat(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
Bind *b;
|
||||
char *name;
|
||||
/*fprintf(stderr, "xstat: welcome, c=%x fcall->fid=%d\n", c, fcall->fid);*/
|
||||
if(!m)
|
||||
return Enofid;
|
||||
/*fprintf(stderr, "xstat: now fetching bind, fcall->fid=%d\n", fcall->fid);*/
|
||||
if((b = fid_to_bind(m->fid)))
|
||||
return mntrequest(b, fcall);
|
||||
name = qid_to_name(&m->qid);
|
||||
if(!type_to_stat(&fcall->stat, name, &m->qid))
|
||||
return Enofile;
|
||||
fcall->id = RSTAT;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static char *
|
||||
xwrite(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
char *p, buf[256];
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
Bind *b;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
if((b = fid_to_bind(m->fid)))
|
||||
return mntrequest(b, fcall);
|
||||
switch (qpath_type(m->qid.path)) {
|
||||
case Fctl:
|
||||
if(fcall->count > sizeof(buf) - 1)
|
||||
return Enocommand;
|
||||
memcpy(buf, fcall->data, fcall->count);
|
||||
buf[fcall->count] = 0;
|
||||
if(!strncmp(buf, "quit", 5)) {
|
||||
srv.running = 0;
|
||||
break;
|
||||
}
|
||||
else if(!strncmp(buf, "mount ", 6)) {
|
||||
p = xmount(&buf[6]);
|
||||
if(p)
|
||||
return p;
|
||||
break;
|
||||
}
|
||||
else if(!strncmp(buf, "unmount ", 8)) {
|
||||
Mount *mnt;
|
||||
char *mstr = &buf[8];
|
||||
if(*mstr == '/')
|
||||
mstr++;
|
||||
p = strchr(mstr, '/');
|
||||
if(p)
|
||||
*p = 0; /* mount name is not allowed to contain slashes */
|
||||
if((mnt = name_to_mount(mstr))) {
|
||||
xunmount(mnt);
|
||||
break;
|
||||
}
|
||||
return "no such mount point";
|
||||
}
|
||||
return Enocommand;
|
||||
break;
|
||||
default:
|
||||
return "invalid write";
|
||||
break;
|
||||
}
|
||||
fcall->id = RWRITE;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
char *
|
||||
xclunk(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
Bind *b;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
if((b = fid_to_bind(m->fid)))
|
||||
return mntrequest(b, fcall);
|
||||
cext_array_detach((void **)c->map, m, &c->mapsz);
|
||||
free(m);
|
||||
fcall->id = RCLUNK;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
do_mnt_fcall(IXPConn *c)
|
||||
{
|
||||
static Fcall fcall;
|
||||
unsigned int msize;
|
||||
|
||||
if((msize = ixp_server_receive_fcall(c, &fcall))) {
|
||||
/*fprintf(stderr, "mntfcall=%d\n", fcall.id);*/
|
||||
switch(fcall.id) {
|
||||
case RWALK: mntwalk(c, &fcall); break;
|
||||
case RREMOVE:
|
||||
case RCLUNK: mntclunkremove(c, &fcall); break;
|
||||
case RCREATE:
|
||||
case ROPEN:
|
||||
case RREAD:
|
||||
case RWRITE:
|
||||
case RSTAT:
|
||||
case RERROR: mntrespond(c, &fcall); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_fcall(IXPConn *c)
|
||||
{
|
||||
static Fcall fcall;
|
||||
unsigned int msize;
|
||||
char *errstr;
|
||||
|
||||
if((msize = ixp_server_receive_fcall(c, &fcall))) {
|
||||
/*fprintf(stderr, "locfcall=%d\n", fcall.id);*/
|
||||
switch(fcall.id) {
|
||||
case TVERSION: errstr = wmii_ixp_version(c, &fcall); break;
|
||||
case TATTACH: errstr = wmii_ixp_attach(c, &fcall); break;
|
||||
case TWALK: errstr = xwalk(c, &fcall); break;
|
||||
case TREMOVE: errstr = xremove(c, &fcall); break;
|
||||
case TCREATE: errstr = xcreate(c, &fcall); break;
|
||||
case TOPEN: errstr = xopen(c, &fcall); break;
|
||||
case TREAD: errstr = xread(c, &fcall); break;
|
||||
case TWRITE: errstr = xwrite(c, &fcall); break;
|
||||
case TCLUNK: errstr = xclunk(c, &fcall); break;
|
||||
case TSTAT: errstr = xstat(c, &fcall); break;
|
||||
default: errstr = Enofunc; break;
|
||||
}
|
||||
if(errstr)
|
||||
ixp_server_respond_error(c, &fcall, errstr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
new_ixp_conn(IXPConn *c)
|
||||
{
|
||||
int fd = ixp_accept_sock(c->fd);
|
||||
|
||||
if(fd >= 0)
|
||||
ixp_server_open_conn(c->srv, fd, do_fcall, ixp_server_close_conn);
|
||||
}
|
||||
|
||||
static void
|
||||
check_x_event(IXPConn *c)
|
||||
{
|
||||
XEvent ev;
|
||||
while(XPending(dpy))
|
||||
XNextEvent(dpy, &ev);
|
||||
/* why check them? because X won't kill wmiifs when X dies */
|
||||
}
|
||||
|
||||
/* main */
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
char *errstr;
|
||||
char *address = nil;
|
||||
|
||||
/* command line args */
|
||||
for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
|
||||
switch (argv[i][1]) {
|
||||
case 'v':
|
||||
fprintf(stdout, "%s", version);
|
||||
exit(0);
|
||||
break;
|
||||
case 'a':
|
||||
if(i + 1 < argc)
|
||||
address = argv[++i];
|
||||
else
|
||||
usage();
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* just for the case X crashes/gets quit */
|
||||
dpy = XOpenDisplay(0);
|
||||
if(!dpy) {
|
||||
fprintf(stderr, "%s", "wmiifs: cannot open display\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
i = ixp_create_sock(address, &errstr);
|
||||
if(i < 0) {
|
||||
fprintf(stderr, "wmiifs: fatal: %s\n", errstr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* IXP server */
|
||||
ixp_server_open_conn(&srv, i, new_ixp_conn, ixp_server_close_conn);
|
||||
root_qid.type = IXP_QTDIR;
|
||||
root_qid.version = 0;
|
||||
root_qid.path = mkqpath(Droot, 0);
|
||||
|
||||
/* X server */
|
||||
ixp_server_open_conn(&srv, ConnectionNumber(dpy), check_x_event, nil);
|
||||
|
||||
/* main loop */
|
||||
errstr = ixp_server_loop(&srv);
|
||||
if(errstr)
|
||||
fprintf(stderr, "wmiibar: fatal: %s\n", errstr);
|
||||
|
||||
/* cleanup */
|
||||
ixp_server_close(&srv);
|
||||
XCloseDisplay(dpy);
|
||||
|
||||
return errstr ? 1 : 0;
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
.TH WMIIKEYS 1 wmii-3
|
||||
.SH NAME
|
||||
wmiikeys \- window manager improved 2 keys
|
||||
.SH SYNOPSIS
|
||||
.B wmiikeys
|
||||
.B \-s
|
||||
.I socketfile
|
||||
.SH DESCRIPTION
|
||||
.SS Overview
|
||||
.B wmiikeys
|
||||
is a generic, highly customizable, and efficient key grabbing utility for the
|
||||
X Window System, originally designed for
|
||||
.BR wmii (1).
|
||||
It is similar to xbindkeys, but provides more flexibility and comes
|
||||
with equivalent features like the ratpoison keyboard control allows.
|
||||
It supports arbitrary, user defined shortcuts which are bound to
|
||||
arbitrary actions.
|
||||
Like wmii,
|
||||
.B wmiikeys
|
||||
also implements a socket-based fileserver, which is accessed to configure and
|
||||
interact with other components.
|
||||
.SS Options
|
||||
.TP
|
||||
.BI \-s " socketfile"
|
||||
specifies the socketfile that
|
||||
.B wmiikeys
|
||||
should create.
|
||||
.TP
|
||||
.B \-v
|
||||
prints version information to stderr, then exits.
|
||||
.SS Customization
|
||||
.B wmiikeys
|
||||
is customized through manipulating its filesystem namespace.
|
||||
In the default setup of
|
||||
.BR wmii (1)
|
||||
the namespace of
|
||||
.B wmiikeys
|
||||
can be found in /keys.
|
||||
.SH SEE ALSO
|
||||
.BR wmiibar (1),
|
||||
.BR wmiifs (1),
|
||||
.BR wmii (1),
|
||||
.BR wmiiwm (1),
|
||||
.BR wmiimenu (1),
|
||||
.BR wmiir (1)
|
814
cmd/wmiikeys.c
814
cmd/wmiikeys.c
|
@ -1,814 +0,0 @@
|
|||
/*
|
||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <time.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#include "wmii.h"
|
||||
|
||||
/*
|
||||
* filesystem specification
|
||||
* / Droot
|
||||
* /ctl Fctl command interface
|
||||
* /grab Fgrab setup interface
|
||||
* /event Fevent read for receiving key presses
|
||||
* /foo Fkey key file
|
||||
*/
|
||||
|
||||
/* 8-bit qid.path.type */
|
||||
enum {
|
||||
Droot,
|
||||
Fctl,
|
||||
Fgrab,
|
||||
Fevent,
|
||||
Fkey
|
||||
};
|
||||
|
||||
typedef struct Key Key;
|
||||
struct Key {
|
||||
unsigned short id;
|
||||
char name[128];
|
||||
unsigned long mod;
|
||||
KeyCode key;
|
||||
Key *next;
|
||||
};
|
||||
|
||||
static IXPServer srv;
|
||||
static Display *dpy;
|
||||
static Window root;
|
||||
static Key **key = nil;
|
||||
static size_t keysz = 0;
|
||||
static size_t nkey = 0;
|
||||
static unsigned int num_lock_mask, valid_mask;
|
||||
Qid root_qid;
|
||||
|
||||
static char version[] = "wmiikeys - " VERSION ", (C)opyright MMIV-MMVI Anselm R. Garbe\n";
|
||||
|
||||
static void do_pend_fcall(char *event);
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "%s", "usage: wmiikeys [-a <address>] [-v]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* X stuff */
|
||||
|
||||
static void
|
||||
grab_key(Key *k)
|
||||
{
|
||||
XGrabKey(dpy, k->key, k->mod, root,
|
||||
True, GrabModeAsync, GrabModeAsync);
|
||||
if(num_lock_mask) {
|
||||
XGrabKey(dpy, k->key, k->mod | num_lock_mask, root,
|
||||
True, GrabModeAsync, GrabModeAsync);
|
||||
XGrabKey(dpy, k->key, k->mod | num_lock_mask | LockMask, root,
|
||||
True, GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
XSync(dpy, False);
|
||||
}
|
||||
|
||||
static void
|
||||
ungrab_key(Key *k)
|
||||
{
|
||||
XUngrabKey(dpy, k->key, k->mod, root);
|
||||
if(num_lock_mask) {
|
||||
XUngrabKey(dpy, k->key, k->mod | num_lock_mask, root);
|
||||
XUngrabKey(dpy, k->key, k->mod | num_lock_mask | LockMask, root);
|
||||
}
|
||||
XSync(dpy, False);
|
||||
}
|
||||
|
||||
static Key *
|
||||
create_key(char *name)
|
||||
{
|
||||
char buf[128];
|
||||
char *seq[8];
|
||||
char *key;
|
||||
size_t i, toks;
|
||||
static unsigned short id = 1;
|
||||
Key *k = 0, *r = 0;
|
||||
|
||||
cext_strlcpy(buf, name, sizeof(buf));
|
||||
toks = cext_tokenize(seq, 8, buf, ',');
|
||||
|
||||
for(i = 0; i < toks; i++) {
|
||||
if(!k)
|
||||
r = k = cext_emallocz(sizeof(Key));
|
||||
else {
|
||||
k->next = cext_emallocz(sizeof(Key));
|
||||
k = k->next;
|
||||
}
|
||||
cext_strlcpy(k->name, name, sizeof(k->name));
|
||||
key = strrchr(seq[i], '-');
|
||||
if(key)
|
||||
key++;
|
||||
else
|
||||
key = seq[i];
|
||||
k->key = XKeysymToKeycode(dpy, XStringToKeysym(key));
|
||||
k->mod = blitz_strtomod(seq[i]);
|
||||
}
|
||||
r->id = id++;
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_key(Key *k)
|
||||
{
|
||||
if(k->next)
|
||||
destroy_key(k->next);
|
||||
free(k);
|
||||
}
|
||||
|
||||
static void
|
||||
next_keystroke(unsigned long *mod, KeyCode *key)
|
||||
{
|
||||
XEvent e;
|
||||
KeySym sym;
|
||||
*mod = 0;
|
||||
do {
|
||||
XMaskEvent(dpy, KeyPressMask, &e);
|
||||
*mod |= e.xkey.state & valid_mask;
|
||||
*key = (KeyCode) e.xkey.keycode;
|
||||
sym = XKeycodeToKeysym(dpy, e.xkey.keycode, 0);
|
||||
} while(IsModifierKey(sym));
|
||||
}
|
||||
|
||||
static void
|
||||
emulate_key_press(unsigned long mod, KeyCode key)
|
||||
{
|
||||
XEvent e;
|
||||
Window client_win;
|
||||
int revert;
|
||||
|
||||
XGetInputFocus(dpy, &client_win, &revert);
|
||||
|
||||
e.xkey.type = KeyPress;
|
||||
e.xkey.time = CurrentTime;
|
||||
e.xkey.window = client_win;
|
||||
e.xkey.display = dpy;
|
||||
e.xkey.state = mod;
|
||||
e.xkey.keycode = key;
|
||||
XSendEvent(dpy, client_win, True, KeyPressMask, &e);
|
||||
e.xkey.type = KeyRelease;
|
||||
XSendEvent(dpy, client_win, True, KeyReleaseMask, &e);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
|
||||
static Key **
|
||||
match_keys(Key **t, size_t n, unsigned long mod, KeyCode keycode, Bool next, size_t *nres)
|
||||
{
|
||||
Key **result = nil;
|
||||
size_t ressz = 0;
|
||||
size_t i = 0;
|
||||
*nres = 0;
|
||||
for(i = 0; i < n; i++) {
|
||||
Key *k = next ? t[i]->next : t[i];
|
||||
if(k && (k->mod == mod) && (k->key == keycode)) {
|
||||
result = (Key **)cext_array_attach((void **)result, k, sizeof(Key *), &ressz);
|
||||
(*nres)++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
handle_key_seq(Window w, Key **done, size_t ndone)
|
||||
{
|
||||
unsigned long mod;
|
||||
KeyCode key;
|
||||
Key **found = nil;
|
||||
size_t nfound = 0;
|
||||
char buf[128];
|
||||
|
||||
next_keystroke(&mod, &key);
|
||||
|
||||
found = match_keys(done, ndone, mod, key, True, &nfound);
|
||||
if((done[0]->mod == mod) && (done[0]->key == key))
|
||||
emulate_key_press(mod, key); /* double key */
|
||||
else {
|
||||
switch(nfound) {
|
||||
case 0:
|
||||
XBell(dpy, 0);
|
||||
return; /* grabbed but not found */
|
||||
case 1:
|
||||
if(!found[0]->next) {
|
||||
snprintf(buf, sizeof(buf), "%s\n", found[0]->name);
|
||||
do_pend_fcall(buf);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
handle_key_seq(w, found, nfound);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(found);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_key(Window w, unsigned long mod, KeyCode keycode)
|
||||
{
|
||||
size_t nfound;
|
||||
char buf[128];
|
||||
Key **found = match_keys(key, nkey, mod, keycode, False, &nfound);
|
||||
switch(nfound) {
|
||||
case 0:
|
||||
XBell(dpy, 0);
|
||||
return; /* grabbed but not found */
|
||||
case 1:
|
||||
if(!found[0]->next) {
|
||||
snprintf(buf, sizeof(buf), "%s\n", found[0]->name);
|
||||
do_pend_fcall(buf);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
handle_key_seq(w, found, nfound);
|
||||
XUngrabKeyboard(dpy, CurrentTime);
|
||||
XSync(dpy, False);
|
||||
break;
|
||||
}
|
||||
free(found);
|
||||
}
|
||||
|
||||
static void
|
||||
check_x_event(IXPConn *c)
|
||||
{
|
||||
XEvent ev;
|
||||
while(XPending(dpy)) {
|
||||
XNextEvent(dpy, &ev);
|
||||
switch (ev.type) {
|
||||
case KeyPress:
|
||||
ev.xkey.state &= valid_mask;
|
||||
handle_key(root, ev.xkey.state, (KeyCode) ev.xkey.keycode);
|
||||
break;
|
||||
case KeymapNotify:
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < nkey; i++) {
|
||||
ungrab_key(key[i]);
|
||||
grab_key(key[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
dummy_error_handler(Display * dpy, XErrorEvent * err)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Key *
|
||||
key_of_name(char *name)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < nkey; i++)
|
||||
if(!strncmp(key[i]->name, name, sizeof(key[i]->name)))
|
||||
return key[i];
|
||||
return nil;
|
||||
}
|
||||
|
||||
static int
|
||||
index_of_id(unsigned short id)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < nkey; i++)
|
||||
if(key[i]->id == id)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* IXP stuff */
|
||||
|
||||
static unsigned long long
|
||||
mkqpath(unsigned char type, unsigned short id)
|
||||
{
|
||||
return ((unsigned long long) id << 8) | (unsigned long long) type;
|
||||
}
|
||||
|
||||
static unsigned char
|
||||
qpath_type(unsigned long long path)
|
||||
{
|
||||
return path & 0xff;
|
||||
}
|
||||
|
||||
static unsigned short
|
||||
qpath_id(unsigned long long path)
|
||||
{
|
||||
return (path >> 8) & 0xffff;
|
||||
}
|
||||
|
||||
static char *
|
||||
qid_to_name(Qid *qid)
|
||||
{
|
||||
unsigned char type = qpath_type(qid->path);
|
||||
unsigned short id = qpath_id(qid->path);
|
||||
int i;
|
||||
|
||||
if(id && ((i = index_of_id(id)) == -1))
|
||||
return nil;
|
||||
switch(type) {
|
||||
case Droot: return "/"; break;
|
||||
case Fctl: return "ctl"; break;
|
||||
case Fgrab: return "grab"; break;
|
||||
case Fevent: return "event"; break;
|
||||
case Fkey: return key[i]->name; break;
|
||||
default: return nil; break;
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
name_to_type(char *name)
|
||||
{
|
||||
if(!name || !name[0] || !strncmp(name, "/", 2) || !strncmp(name, "..", 3))
|
||||
return Droot;
|
||||
if(!strncmp(name, "ctl", 4))
|
||||
return Fctl;
|
||||
if(!strncmp(name, "grab", 5))
|
||||
return Fgrab;
|
||||
if(!strncmp(name, "event", 6))
|
||||
return Fevent;
|
||||
if(key_of_name(name))
|
||||
return Fkey;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
mkqid(Qid *dir, char *wname, Qid *new, Bool iswalk)
|
||||
{
|
||||
Key *k;
|
||||
int type = name_to_type(wname);
|
||||
|
||||
if((dir->type != IXP_QTDIR) || (type == -1))
|
||||
return -1;
|
||||
|
||||
new->dtype = qpath_type(dir->path);
|
||||
new->version = 0;
|
||||
switch(type) {
|
||||
case Droot:
|
||||
*new = root_qid;
|
||||
break;
|
||||
case Fkey:
|
||||
if(!(k = key_of_name(wname)))
|
||||
return -1;
|
||||
new->type = IXP_QTFILE;
|
||||
new->path = mkqpath(type, k->id);
|
||||
break;
|
||||
default:
|
||||
new->type = IXP_QTFILE;
|
||||
new->path = mkqpath(type, 0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
xwalk(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
unsigned short nwqid = 0;
|
||||
Qid dir = root_qid;
|
||||
IXPMap *m;
|
||||
|
||||
if(!(m = ixp_server_fid2map(c, fcall->fid)))
|
||||
return Enofid;
|
||||
if(fcall->fid != fcall->newfid && (ixp_server_fid2map(c, fcall->newfid)))
|
||||
return Enofid;
|
||||
if(fcall->nwname) {
|
||||
dir = m->qid;
|
||||
for(nwqid = 0; (nwqid < fcall->nwname)
|
||||
&& !mkqid(&dir, fcall->wname[nwqid], &fcall->wqid[nwqid], True); nwqid++) {
|
||||
/*fprintf(stderr, "wname=%s nwqid=%d\n", fcall->wname[nwqid], nwqid);*/
|
||||
dir = fcall->wqid[nwqid];
|
||||
}
|
||||
if(!nwqid)
|
||||
return Enofile;
|
||||
}
|
||||
/* a fid will only be valid, if the walk was complete */
|
||||
if(nwqid == fcall->nwname) {
|
||||
if(fcall->fid != fcall->newfid) {
|
||||
m = cext_emallocz(sizeof(IXPMap));
|
||||
c->map = (IXPMap **)cext_array_attach((void **)c->map,
|
||||
m, sizeof(IXPMap *), &c->mapsz);
|
||||
}
|
||||
m->qid = dir;
|
||||
m->fid = fcall->newfid;
|
||||
}
|
||||
fcall->id = RWALK;
|
||||
fcall->nwqid = nwqid;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static char *
|
||||
xopen(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
if(!(fcall->mode | IXP_OREAD) && !(fcall->mode | IXP_OWRITE))
|
||||
return Enomode;
|
||||
fcall->id = ROPEN;
|
||||
fcall->qid = m->qid;
|
||||
fcall->iounit = 2048;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
mkstat(Stat *stat, Qid *dir, char *name, unsigned long long length, unsigned int mode)
|
||||
{
|
||||
stat->mode = mode;
|
||||
stat->atime = stat->mtime = time(0);
|
||||
cext_strlcpy(stat->uid, getenv("USER"), sizeof(stat->uid));
|
||||
cext_strlcpy(stat->gid, getenv("USER"), sizeof(stat->gid));
|
||||
cext_strlcpy(stat->muid, getenv("USER"), sizeof(stat->muid));
|
||||
|
||||
cext_strlcpy(stat->name, name, sizeof(stat->name));
|
||||
stat->length = length;
|
||||
mkqid(dir, name, &stat->qid, False);
|
||||
return ixp_sizeof_stat(stat);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
type_to_stat(Stat *stat, char *name, Qid *dir)
|
||||
{
|
||||
int type = name_to_type(name);
|
||||
|
||||
switch (type) {
|
||||
case Droot:
|
||||
case Fctl:
|
||||
case Fgrab:
|
||||
return mkstat(stat, dir, name, 0, DMWRITE);
|
||||
break;
|
||||
case Fevent:
|
||||
return mkstat(stat, dir, name, 0, DMREAD);
|
||||
break;
|
||||
case Fkey:
|
||||
return mkstat(stat, dir, name, 0, 0);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
xremove(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
unsigned short id = qpath_id(m->qid.path);
|
||||
int i;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
if(id && ((i = qpath_id(id)) == -1))
|
||||
return Enofile;
|
||||
if((qpath_type(m->qid.path) == Fkey) && (i < nkey)) {
|
||||
Key *k = key[i];
|
||||
/* clunk */
|
||||
cext_array_detach((void **)c->map, m, &c->mapsz);
|
||||
free(m);
|
||||
/* now detach the item */
|
||||
cext_array_detach((void **)key, k, &keysz);
|
||||
nkey--;
|
||||
destroy_key(k);
|
||||
fcall->id = RREMOVE;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
return Enoperm;
|
||||
}
|
||||
|
||||
static char *
|
||||
xread(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
Stat stat;
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
unsigned short id;
|
||||
unsigned char *p = fcall->data;
|
||||
unsigned int len = 0;
|
||||
int i;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
id = qpath_id(m->qid.path);
|
||||
if(id && ((i = index_of_id(id)) == -1))
|
||||
return Enofile;
|
||||
|
||||
fcall->count = 0;
|
||||
if(fcall->offset) {
|
||||
switch (qpath_type(m->qid.path)) {
|
||||
case Droot:
|
||||
/* jump to offset */
|
||||
len = type_to_stat(&stat, "ctl", &m->qid);
|
||||
len += type_to_stat(&stat, "grab", &m->qid);
|
||||
len += type_to_stat(&stat, "event", &m->qid);
|
||||
for(i = 0; i < nkey; i++) {
|
||||
len += type_to_stat(&stat, key[i]->name, &m->qid);
|
||||
fprintf(stderr, "len=%d <= fcall->offset=%lld\n", len, fcall->offset);
|
||||
if(len <= fcall->offset)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
/* offset found, proceeding */
|
||||
for(; i < nkey; i++) {
|
||||
fprintf(stderr, "offset xread %s\n", key[i]->name);
|
||||
len = type_to_stat(&stat, key[i]->name, &m->qid);
|
||||
if(fcall->count + len > fcall->iounit)
|
||||
break;
|
||||
fcall->count += len;
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
}
|
||||
break;
|
||||
case Fevent:
|
||||
ixp_server_enqueue_fcall(c, fcall);
|
||||
return nil;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (qpath_type(m->qid.path)) {
|
||||
case Droot:
|
||||
fcall->count = type_to_stat(&stat, "ctl", &m->qid);
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
fcall->count += type_to_stat(&stat, "grab", &m->qid);
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
fcall->count += type_to_stat(&stat, "event", &m->qid);
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
for(i = 0; i < nkey; i++) {
|
||||
fprintf(stderr, "normal xread %s\n", key[i]->name);
|
||||
len = type_to_stat(&stat, key[i]->name, &m->qid);
|
||||
if(fcall->count + len > fcall->iounit)
|
||||
break;
|
||||
fcall->count += len;
|
||||
p = ixp_enc_stat(p, &stat);
|
||||
}
|
||||
break;
|
||||
case Fctl:
|
||||
case Fevent:
|
||||
ixp_server_enqueue_fcall(c, fcall);
|
||||
return nil;
|
||||
default:
|
||||
return Enoperm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fcall->id = RREAD;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static char *
|
||||
xstat(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
char *name;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
name = qid_to_name(&m->qid);
|
||||
/*fprintf(stderr, "xstat: name=%s\n", name);*/
|
||||
if(!type_to_stat(&fcall->stat, name, &m->qid))
|
||||
return Enofile;
|
||||
fcall->id = RSTAT;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static char *
|
||||
xwrite(IXPConn *c, Fcall *fcall)
|
||||
{
|
||||
char buf[128];
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
unsigned short id;
|
||||
int i;
|
||||
|
||||
if(!m)
|
||||
return Enofid;
|
||||
id = qpath_id(m->qid.path);
|
||||
if(id && ((i = index_of_id(id)) == -1))
|
||||
return Enofile;
|
||||
switch (qpath_type(m->qid.path)) {
|
||||
case Fctl:
|
||||
if(fcall->count == 4) {
|
||||
memcpy(buf, fcall->data, 4);
|
||||
buf[4] = 0;
|
||||
if(!strncmp(buf, "quit", 5)) {
|
||||
srv.running = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Enocommand;
|
||||
break;
|
||||
case Fgrab:
|
||||
if(fcall->count > 2048)
|
||||
return Enoperm;
|
||||
{
|
||||
static size_t lastcount;
|
||||
static char last[2048]; /* iounit */
|
||||
char fcallbuf[2048], tmp[2048]; /* iounit */
|
||||
char *p1, *p2;
|
||||
Key *k;
|
||||
if(!fcall->offset) {
|
||||
while(nkey) {
|
||||
Key *k = key[0];
|
||||
ungrab_key(k);
|
||||
cext_array_detach((void **)key, k, &keysz);
|
||||
nkey--;
|
||||
destroy_key(k);
|
||||
}
|
||||
}
|
||||
if(!fcall->count)
|
||||
break;
|
||||
memcpy(fcallbuf, fcall->data, fcall->count);
|
||||
fcallbuf[fcall->count] = 0;
|
||||
if(fcall->offset) {
|
||||
p1 = strrchr(last, '\n');
|
||||
p2 = strchr(fcallbuf, '\n');
|
||||
memcpy(tmp, p1, lastcount - (p1 - last));
|
||||
memcpy(tmp + (lastcount - (p1 - last)), p2, p2 - fcallbuf);
|
||||
tmp[(lastcount - (p1 - last)) + (p2 - fcallbuf)] = 0;
|
||||
k = create_key(tmp);
|
||||
key = (Key **)cext_array_attach((void **)key, k, sizeof(Key *), &keysz);
|
||||
nkey++;
|
||||
grab_key(k);
|
||||
|
||||
}
|
||||
else p2 = fcallbuf;
|
||||
lastcount = fcall->count;
|
||||
memcpy(last, fcall->data, fcall->count);
|
||||
while(p2 - fcallbuf < fcall->count) {
|
||||
p1 = strchr(p2, '\n');
|
||||
if(!p1)
|
||||
return "cannot grab, no \n supplied";
|
||||
*p1 = 0;
|
||||
k = create_key(p2);
|
||||
key = (Key **)cext_array_attach((void **)key, k, sizeof(Key *), &keysz);
|
||||
nkey++;
|
||||
grab_key(k);
|
||||
*p1 = '\n';
|
||||
p2 = ++p1;
|
||||
}
|
||||
lastcount = fcall->count;
|
||||
memcpy(last, fcall->data, fcall->count);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return Enoperm;
|
||||
break;
|
||||
}
|
||||
fcall->id = RWRITE;
|
||||
ixp_server_respond_fcall(c, fcall);
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
do_fcall(IXPConn *c)
|
||||
{
|
||||
static Fcall fcall;
|
||||
unsigned int msize;
|
||||
char *errstr;
|
||||
|
||||
if((msize = ixp_server_receive_fcall(c, &fcall))) {
|
||||
/*fprintf(stderr, "fcall=%d\n", fcall.id);*/
|
||||
switch(fcall.id) {
|
||||
case TVERSION: errstr = wmii_ixp_version(c, &fcall); break;
|
||||
case TATTACH: errstr = wmii_ixp_attach(c, &fcall); break;
|
||||
case TWALK: errstr = xwalk(c, &fcall); break;
|
||||
case TREMOVE: errstr = xremove(c, &fcall); break;
|
||||
case TOPEN: errstr = xopen(c, &fcall); break;
|
||||
case TREAD: errstr = xread(c, &fcall); break;
|
||||
case TWRITE: errstr = xwrite(c, &fcall); break;
|
||||
case TCLUNK: errstr = wmii_ixp_clunk(c, &fcall); break;
|
||||
case TSTAT: errstr = xstat(c, &fcall); break;
|
||||
default: errstr = Enofunc; break;
|
||||
}
|
||||
if(errstr)
|
||||
ixp_server_respond_error(c, &fcall, errstr);
|
||||
}
|
||||
check_x_event(nil);
|
||||
}
|
||||
|
||||
static void
|
||||
do_pend_fcall(char *event)
|
||||
{
|
||||
size_t i;
|
||||
Fcall *fcall;
|
||||
for(i = 0; (i < srv.connsz) && srv.conn[i]; i++) {
|
||||
IXPConn *c = srv.conn[i];
|
||||
/* all pending TREADs are on /event, so no qid checking necessary */
|
||||
while((fcall = ixp_server_dequeue_fcall_id(c, TREAD))) {
|
||||
IXPMap *m = ixp_server_fid2map(c, fcall->fid);
|
||||
unsigned char *p = fcall->data;
|
||||
|
||||
if(!m) {
|
||||
if(ixp_server_respond_error(c, fcall, Enofid))
|
||||
break;
|
||||
}
|
||||
else if(qpath_type(m->qid.path) == Fevent) {
|
||||
fcall->count = strlen(event);
|
||||
memcpy(p, event, fcall->count);
|
||||
fcall->id = RREAD;
|
||||
if(ixp_server_respond_fcall(c, fcall))
|
||||
break;
|
||||
}
|
||||
free(fcall);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
new_ixp_conn(IXPConn *c)
|
||||
{
|
||||
int fd = ixp_accept_sock(c->fd);
|
||||
|
||||
if(fd >= 0)
|
||||
ixp_server_open_conn(c->srv, fd, do_fcall, ixp_server_close_conn);
|
||||
}
|
||||
|
||||
/* main */
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
char *errstr;
|
||||
char *address = nil;
|
||||
|
||||
/* command line args */
|
||||
for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) {
|
||||
switch (argv[i][1]) {
|
||||
case 'v':
|
||||
fprintf(stdout, "%s", version);
|
||||
exit(0);
|
||||
break;
|
||||
case 'a':
|
||||
if(i + 1 < argc)
|
||||
address = argv[++i];
|
||||
else
|
||||
usage();
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!address)
|
||||
usage();
|
||||
|
||||
dpy = XOpenDisplay(0);
|
||||
if(!dpy) {
|
||||
fprintf(stderr, "%s", "wmiikeys: cannot open display\n");
|
||||
exit(1);
|
||||
}
|
||||
XSetErrorHandler(dummy_error_handler);
|
||||
|
||||
i = ixp_create_sock(address, &errstr);
|
||||
if(i < 0) {
|
||||
fprintf(stderr, "wmiibar: fatal: %s\n", errstr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* IXP server */
|
||||
ixp_server_open_conn(&srv, i, new_ixp_conn, ixp_server_close_conn);
|
||||
root_qid.type = IXP_QTDIR;
|
||||
root_qid.version = 0;
|
||||
root_qid.path = mkqpath(Droot, 0);
|
||||
|
||||
/* X server */
|
||||
ixp_server_open_conn(&srv, ConnectionNumber(dpy), check_x_event, nil);
|
||||
|
||||
root = RootWindow(dpy, DefaultScreen(dpy));
|
||||
wmii_init_lock_modifiers(dpy, &valid_mask, &num_lock_mask);
|
||||
|
||||
/* main loop */
|
||||
errstr = ixp_server_loop(&srv);
|
||||
if(errstr)
|
||||
fprintf(stderr, "wmiibar: fatal: %s\n", errstr);
|
||||
|
||||
/* cleanup */
|
||||
ixp_server_close(&srv);
|
||||
XCloseDisplay(dpy);
|
||||
|
||||
return errstr ? 1 : 0;
|
||||
}
|
28
liblitz/kb.c
28
liblitz/kb.c
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "blitz.h"
|
||||
|
||||
unsigned long blitz_strtomod(char *val)
|
||||
{
|
||||
unsigned long mod = 0;
|
||||
if (strstr(val, "Shift"))
|
||||
mod |= ShiftMask;
|
||||
if (strstr(val, "Control"))
|
||||
mod |= ControlMask;
|
||||
if (strstr(val, "Mod1") || strstr(val, "Alt"))
|
||||
mod |= Mod1Mask;
|
||||
if (strstr(val, "Mod2"))
|
||||
mod |= Mod2Mask;
|
||||
if (strstr(val, "Mod3"))
|
||||
mod |= Mod3Mask;
|
||||
if (strstr(val, "Mod4"))
|
||||
mod |= Mod4Mask;
|
||||
if (strstr(val, "Mod5"))
|
||||
mod |= Mod5Mask;
|
||||
return mod;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "blitz.h"
|
||||
|
||||
/* free the result manually! */
|
||||
char *blitz_buttontostr(unsigned int button)
|
||||
{
|
||||
char result[8];
|
||||
result[0] = 0;
|
||||
snprintf(result, 8, "Button%ud", button - Button1);
|
||||
return cext_estrdup(result);
|
||||
}
|
||||
|
||||
unsigned int blitz_strtobutton(char *val)
|
||||
{
|
||||
unsigned int res = 0;
|
||||
if (val && strlen(val) > 6 && !strncmp(val, "Button", 6))
|
||||
res = blitz_strtonum(&val[6], 1, 5) + Button1;
|
||||
return res;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "blitz.h"
|
||||
|
||||
long long blitz_strtonum(const char *numstr, long long minval, long long maxval)
|
||||
{
|
||||
const char *errstr;
|
||||
long long ret = cext_strtonum(numstr, minval, maxval, &errstr);
|
||||
if (errstr)
|
||||
fprintf(stderr, "liblitz: cannot convert '%s' into integer: %s [%lld..%lld]\n", numstr, errstr, minval, maxval);
|
||||
return ret;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
# libwmii - mediator lib for wmii
|
||||
# (C)opyright MMIV-MMVI Anselm R. Garbe
|
||||
|
||||
include ../config.mk
|
||||
|
||||
CFLAGS += -I../liblitz -I../libixp -I../libcext
|
||||
LDFLAGS += -L../liblitz -llitz -L../libixp -lixp -L../libcext -lcext
|
||||
|
||||
SRC = ixp.c spawn.c wm.c
|
||||
|
||||
OBJ = ${SRC:.c=.o}
|
||||
|
||||
all: libwmii
|
||||
@echo built libwmii
|
||||
|
||||
.c.o:
|
||||
@echo CC $<
|
||||
@${CC} -c ${CFLAGS} $<
|
||||
|
||||
libwmii: ${OBJ}
|
||||
@echo AR $@.a
|
||||
@${AR} $@.a ${OBJ}
|
||||
@${RANLIB} $@.a
|
||||
|
||||
clean:
|
||||
rm -f libwmii.a *.o
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "wmii.h"
|
||||
|
||||
static void (*sigchld)() = 0;
|
||||
|
||||
static void
|
||||
sig_handler(int signal)
|
||||
{
|
||||
switch (signal)
|
||||
{
|
||||
case SIGINT:
|
||||
case SIGTERM:
|
||||
case SIGHUP:
|
||||
if(sigchld)
|
||||
sigchld();
|
||||
break;
|
||||
case SIGCHLD:
|
||||
wait(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wmii_signal(void (*sigchld_handler)())
|
||||
{
|
||||
sigchld = sigchld_handler;
|
||||
signal(SIGTERM, sig_handler);
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGHUP, sig_handler);
|
||||
signal(SIGCHLD, sig_handler);
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "wmii.h"
|
||||
|
||||
void
|
||||
wmii_spawn(void *dpy, char *cmd)
|
||||
{
|
||||
if(fork() == 0) {
|
||||
if(fork() == 0) {
|
||||
setsid();
|
||||
close(ConnectionNumber(dpy));
|
||||
execlp("rc", "rc", "-c", cmd, (char *) 0);
|
||||
perror("failed");
|
||||
exit(1);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
wait(0);
|
||||
}
|
81
libwmii/wm.c
81
libwmii/wm.c
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
|
||||
#include "blitz.h"
|
||||
|
||||
int
|
||||
wmii_property(Display * dpy, Window w, Atom a, Atom t, long l,
|
||||
unsigned char **prop)
|
||||
{
|
||||
Atom real;
|
||||
int format;
|
||||
unsigned long res, extra;
|
||||
int status;
|
||||
|
||||
status =
|
||||
XGetWindowProperty(dpy, w, a, 0L, l, False, t, &real, &format,
|
||||
&res, &extra, prop);
|
||||
|
||||
if(status != Success || *prop == 0) {
|
||||
return 0;
|
||||
}
|
||||
if(res == 0) {
|
||||
free((void *) *prop);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
wmii_send_message(Display * dpy, Window w, Atom a, long value)
|
||||
{
|
||||
XEvent e;
|
||||
e.type = ClientMessage;
|
||||
e.xclient.window = w;
|
||||
e.xclient.message_type = a;
|
||||
e.xclient.format = 32;
|
||||
e.xclient.data.l[0] = value;
|
||||
e.xclient.data.l[1] = CurrentTime;
|
||||
|
||||
XSendEvent(dpy, w, False, NoEventMask, &e);
|
||||
XSync(dpy, False);
|
||||
}
|
||||
|
||||
#define NUM_MASKS 8
|
||||
void
|
||||
wmii_init_lock_modifiers(Display * dpy, unsigned int *valid_mask,
|
||||
unsigned int *num_lock_mask)
|
||||
{
|
||||
XModifierKeymap *modmap;
|
||||
KeyCode num_lock;
|
||||
static int masks[NUM_MASKS] = {
|
||||
ShiftMask, LockMask, ControlMask, Mod1Mask,
|
||||
Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
|
||||
};
|
||||
int i;
|
||||
|
||||
*num_lock_mask = 0;
|
||||
modmap = XGetModifierMapping(dpy);
|
||||
num_lock = XKeysymToKeycode(dpy, XStringToKeysym("Num_Lock"));
|
||||
|
||||
if(modmap && modmap->max_keypermod > 0) {
|
||||
int max = NUM_MASKS * modmap->max_keypermod;
|
||||
for(i = 0; i < max; i++) {
|
||||
if(num_lock && (modmap->modifiermap[i] == num_lock)) {
|
||||
*num_lock_mask = masks[i / modmap->max_keypermod];
|
||||
}
|
||||
}
|
||||
}
|
||||
XFreeModifiermap(modmap);
|
||||
|
||||
*valid_mask = 255 & ~(*num_lock_mask | LockMask);
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/*
|
||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
|
||||
#include "ixp.h"
|
||||
#include "blitz.h"
|
||||
|
||||
/* ixp.c */
|
||||
#define E9pversion "9P version not supported"
|
||||
#define Enoperm "permission denied"
|
||||
#define Enofid "fid not found"
|
||||
#define Enofile "file not found"
|
||||
#define Enomode "mode not supported"
|
||||
#define Enofunc "function not supported"
|
||||
#define Enocommand "command not supported"
|
||||
|
||||
char *wmii_ixp_version(IXPConn *c, Fcall *fcall);
|
||||
char *wmii_ixp_attach(IXPConn *c, Fcall *fcall);
|
||||
char *wmii_ixp_clunk(IXPConn *c, Fcall *fcall);
|
||||
|
||||
/* spawn.c */
|
||||
void wmii_spawn(void *dpy, char *cmd);
|
||||
|
||||
/* wm.c */
|
||||
int wmii_property(Display * dpy, Window w, Atom a, Atom t, long l, unsigned char **prop);
|
||||
void wmii_send_message(Display * dpy, Window w, Atom a, long value);
|
||||
void wmii_init_lock_modifiers(Display * dpy, unsigned int *valid_mask,
|
||||
unsigned int *num_lock_mask);
|
||||
|
||||
extern Qid root_qid;
|
88
rc/keys
88
rc/keys
|
@ -1,88 +0,0 @@
|
|||
#!9PREFIX/bin/rc
|
||||
# configure wmiikeys
|
||||
|
||||
fn xwrite { echo -n $2 | wmiir write $1 }
|
||||
|
||||
xwrite /keys/ctl quit >/dev/null >[2=1]
|
||||
xwrite /ctl 'mount unix!/tmp/.ixp-'^$USER^'/wmiikeys-'^$WMII_IDENT^' /keys'
|
||||
wmiikeys -a unix!/tmp/.ixp-$USER/wmiikeys-$WMII_IDENT &
|
||||
sleep 1
|
||||
|
||||
wmiir -a unix!/tmp/.ixp-$USER/wmiikeys-$WMII_IDENT write /grab <<END
|
||||
Control-Alt-k
|
||||
Control-Alt-c
|
||||
Control-Alt-q,y
|
||||
Control-Alt-w,y
|
||||
Alt-t
|
||||
Alt-d
|
||||
Alt-a
|
||||
Shift-Alt-a
|
||||
Alt-n
|
||||
Alt-m
|
||||
Alt-Return
|
||||
Shift-Alt-Return
|
||||
Control-Alt-y
|
||||
Alt-h
|
||||
Alt-l
|
||||
Alt-Tab
|
||||
Alt-j
|
||||
Alt-k
|
||||
Shift-Alt-h
|
||||
Shift-Alt-l
|
||||
Shift-Alt-p
|
||||
Shift-Alt-1
|
||||
Shift-Alt-2
|
||||
Shift-Alt-3
|
||||
Shift-Alt-4
|
||||
END
|
||||
|
||||
wmiir -a unix!/tmp/.ixp-$USER/wmiikeys-$WMII_IDENT read /event | \
|
||||
while(key=`{read}) {
|
||||
xwrite /bar/2/data $key
|
||||
switch($key) {
|
||||
case Control-Alt-k
|
||||
keys
|
||||
case Control-Alt-c
|
||||
xwrite /wm/sel/sel/sel/ctl kill
|
||||
case Control-Alt-q,y
|
||||
quit
|
||||
case Control-Alt-w,y
|
||||
wmiirc
|
||||
case Alt-t
|
||||
extern xterm -rv &
|
||||
case Alt-d
|
||||
xwrite /wm/sel/sel/sel/ctl detach
|
||||
case Alt-a
|
||||
xwrite /wm/ctl attach
|
||||
case Shift-Alt-a
|
||||
xwrite /wm/ctl detached
|
||||
case Alt-n
|
||||
wmiir read /wm/sel/new >/dev/null >[2=1]
|
||||
case Alt-m
|
||||
xwrite /wm/sel/sel/sel/ctl max
|
||||
case Alt-Return
|
||||
xwrite /wm/sel/sel/ctl 'swap east'
|
||||
case Shift-Alt-Return
|
||||
xwrite /wm/sel/sel/ctl 'swap west'
|
||||
case Control-Alt-y
|
||||
wmiir read /wm/new >/dev/null >[2=1]
|
||||
case Alt-h
|
||||
xwrite /wm/sel/ctl 'select next'
|
||||
case Alt-l
|
||||
xwrite /wm/sel/ctl 'select prev'
|
||||
case Alt-Tab
|
||||
xwrite /wm/sel/sel/ctl 'select next'
|
||||
case Alt-j
|
||||
xwrite /wm/sel/sel/ctl 'select next'
|
||||
case Alt-k
|
||||
xwrite /wm/sel/sel/ctl 'select prev'
|
||||
case Shift-Alt-h
|
||||
xwrite /wm/ctl 'select prev'
|
||||
case Shift-Alt-l
|
||||
xwrite /wm/ctl 'select next'
|
||||
case Shift-Alt-p
|
||||
xwrite /wm/ctl pager
|
||||
case Shift-Alt-[1-9]
|
||||
xwrite /wm/ctl 'select '^`{echo $k|sed 's/.*-//g'}
|
||||
}
|
||||
}
|
7
rc/kmode
7
rc/kmode
|
@ -1,7 +0,0 @@
|
|||
#!9PREFIX/bin/rc
|
||||
# activate shortcuts of the given mode
|
||||
|
||||
wmiir write /keys/grabkeyb 0
|
||||
wmiir write /keys/lookup /mode/$1
|
||||
|
||||
eval `{wmiir read /wm/event/pageupdate}
|
Loading…
Reference in New Issue