Merge in diffs for fs2.c and libixp

This commit is contained in:
Kris Maglione 2006-06-17 07:32:49 -04:00
parent 72c7d317e2
commit a4e2ab7b59
18 changed files with 759 additions and 400 deletions

View File

@ -9,7 +9,7 @@ LDFLAGS += -L../../liblitz -llitz -L../../libixp -lixp -L../../libcext -lcext -
# Solaris
# LDFLAGS += -lsocket
SRC = area.c bar.c client.c column.c event.c frame.c fs.c geom.c \
SRC = area.c bar.c client.c column.c event.c frame.c fs2.c geom.c \
key.c mouse.c rule.c view.c wm.c
OBJ = ${SRC:.c=.o}

View File

@ -27,10 +27,12 @@ create_bar(char *name)
b->id = id++;
cext_strlcpy(b->name, name, sizeof(b->name));
cext_strlcpy(b->colstr, def.normcolor, sizeof(b->colstr));
b->color = def.norm;
cext_strlcpy(b->color.string, def.normcolor.string, sizeof(b->color.string));
b->color.col = def.normcolor.col;
for(i=&bar; *i && (strcmp((*i)->name, name) < 0); i=&(*i)->next);
for(i=&lbar; *i; i=&(*i)->next)
if(strcmp((*i)->name, name) < 0)
break;
b->next = *i;
*i = b;
@ -41,7 +43,7 @@ void
destroy_bar(Bar *b)
{
Bar **i;
for(i=&bar; *i && *i != b; i=&(*i)->next);
for(i=&lbar; *i && *i != b; i=&(*i)->next);
*i = b->next;
b->next = free_bars;
@ -98,14 +100,14 @@ draw_bar()
d.rect.x = d.rect.y = 0;
d.font = blitzfont;
d.color = def.norm;
d.color = def.normcolor.col;
blitz_drawlabel(&d);
blitz_drawborder(&d);
if(!bar)
if(!lbar)
goto MapBar;
for(b=bar; b && (w < brect.width); b=b->next, size++) {
for(b=lbar; b && (w < brect.width); b=b->next, size++) {
b->rect.x = 0;
b->rect.y = 0;
b->rect.width = brect.height;
@ -118,21 +120,21 @@ draw_bar()
if(b) { /* give all bars same width */
for(; b; b=b->next, size++);
w = brect.width / size;
for(b=bar; b; b=b->next) {
for(b=lbar; b; b=b->next) {
b->rect.x = i * w;
b->rect.width = w;
}
}
else { /* expand bar properly */
for(exp = bar; exp && exp->next; exp=exp->next);
else { /* expand lbar properly */
for(exp = lbar; exp && exp->next; exp=exp->next);
if(exp)
exp->rect.width += (brect.width - w);
for(b=bar; b->next; b=b->next)
for(b=lbar; b->next; b=b->next)
b->next->rect.x = b->rect.x + b->rect.width;
}
for(b=bar; b; b=b->next) {
d.color = b->color;
for(b=lbar; b; b=b->next) {
d.color = b->color.col;
d.rect = b->rect;
d.data = b->data;
if(b == exp)
@ -154,7 +156,7 @@ bar_of_name(const char *name)
Bar *b;
cext_strlcpy(buf, name, sizeof(buf));
for(b=bar; b && strncmp(b->name, name, sizeof(b->name)); b=b->next);
for(b=lbar; b && strncmp(b->name, name, sizeof(b->name)); b=b->next);
return b;
}
@ -162,6 +164,6 @@ Bar *
bar_of_id(unsigned short id)
{
Bar *b;
for(b=bar; b && b->id != id; b=b->next);
for(b=lbar; b && b->id != id; b=b->next);
return b;
}

View File

@ -293,10 +293,10 @@ draw_client(Client *c)
d.font = blitzfont;
d.gc = c->gc;
if(sel_screen && (c == sel_client()))
d.color = def.sel;
if(sel_screen && (c == sel_client()))
d.color = def.selcolor.col;
else
d.color = def.norm;
d.color = def.normcolor.col;
/* draw border */
if(def.border) {
@ -323,17 +323,17 @@ draw_client(Client *c)
d.data = buf;
if(f->area->sel == f)
d.color = def.sel;
d.color = def.selcolor.col;
else
d.color = def.norm;
d.color = def.normcolor.col;
blitz_drawlabel(&d);
blitz_drawborder(&d);
d.rect.x = 0;
if(sel_screen && (c == sel_client()))
d.color = def.sel;
if(sel_screen && (c == sel_client()))
d.color = def.selcolor.col;
else
d.color = def.norm;
d.color = def.normcolor.col;
/* tag bar */
d.rect.width = d.rect.height + blitz_textwidth(&blitzfont, c->tags);
@ -874,7 +874,7 @@ match_tags(Client *c, const char *prop)
Rule *r;
regmatch_t tmpregm;
for(r=trule; r; r=r->next)
for(r=def.tagrules.rule; r; r=r->next)
if(!regexec(&r->regex, prop, 1, &tmpregm, 0))
if(!strlen(c->tags) || !strncmp(c->tags, "nil", 4))
apply_tags(c, r->value);
@ -883,7 +883,7 @@ match_tags(Client *c, const char *prop)
void
apply_rules(Client *c)
{
if(def.tagrules)
if(def.tagrules.string)
match_tags(c, c->props);
if(!strlen(c->tags))

View File

@ -73,7 +73,7 @@ handle_buttonrelease(XEvent *e)
XButtonPressedEvent *ev = &e->xbutton;
static char buf[32];
if(ev->window == barwin) {
for(b=bar; b; b=b->next)
for(b=lbar; b; b=b->next)
if(ispointinrect(ev->x, ev->y, &b->rect)) {
snprintf(buf, sizeof(buf), "BarClick %s %d\n",
b->name, ev->button);

View File

@ -1186,11 +1186,11 @@ xread(IXPConn *c, Fcall *fcall)
break;
case FsFselcolors:
if((fcall->count = strlen(def.selcolor)))
memcpy(p, def.selcolor, fcall->count);
memcpy(p, def.selcolor.string, fcall->count);
break;
case FsFnormcolors:
if((fcall->count = strlen(def.normcolor)))
memcpy(p, def.normcolor, fcall->count);
memcpy(p, def.normcolor.string, fcall->count);
break;
case FsFkeys:
fcall->count = def.keys ? strlen(def.keys) : 0;
@ -1382,18 +1382,18 @@ xwrite(IXPConn *c, Fcall *fcall)
if((fcall->count != 23) || (fcall->data[0] != '#')
|| (fcall->data[8] != '#') || (fcall->data[16] != '#'))
return Ebadvalue;
memcpy(def.selcolor, fcall->data, fcall->count);
def.selcolor[fcall->count] = 0;
blitz_loadcolor(&def.sel, def.selcolor);
memcpy(def.selcolor.string, fcall->data, fcall->count);
def.selcolor.string[fcall->count] = 0;
blitz_loadcolor(&def.selcolor.col, def.selcolor.string);
draw_clients();
break;
case FsFnormcolors:
if((fcall->count != 23) || (fcall->data[0] != '#')
|| (fcall->data[8] != '#') || (fcall->data[16] != '#'))
return Ebadvalue;
memcpy(def.normcolor, fcall->data, fcall->count);
def.normcolor[fcall->count] = 0;
blitz_loadcolor(&def.norm, def.normcolor);
memcpy(def.normcolor.string, fcall->data, fcall->count);
def.normcolor.string[fcall->count] = 0;
blitz_loadcolor(&def.normcolor.col, def.normcolor.string);
draw_clients();
break;
case FsFkeys:
@ -1411,9 +1411,9 @@ xwrite(IXPConn *c, Fcall *fcall)
def.keys[fcall->offset + fcall->count] = 0;
break;
case FsFtagrules:
if(def.tagrulessz < fcall->offset + fcall->count + 1) {
def.tagrulessz = fcall->offset + fcall->count + 1;
tmp = cext_emallocz(def.tagrulessz);
if(def.tagrules.size < fcall->offset + fcall->count + 1) {
def.tagrules.size = fcall->offset + fcall->count + 1;
tmp = cext_emallocz(def.tagrules.size);
len = def.tagrules ? strlen(def.tagrules) : 0;
if(len) {
memcpy(tmp, def.tagrules, len);
@ -1425,9 +1425,9 @@ xwrite(IXPConn *c, Fcall *fcall)
def.tagrules[fcall->offset + fcall->count] = 0;
break;
case FsFcolrules:
if(def.colrulessz < fcall->offset + fcall->count + 1) {
def.colrulessz = fcall->offset + fcall->count + 1;
tmp = cext_emallocz(def.colrulessz);
if(def.colrules.size < fcall->offset + fcall->count + 1) {
def.colrules.size = fcall->offset + fcall->count + 1;
tmp = cext_emallocz(def.colrules.size);
len = def.colrules ? strlen(def.colrules) : 0;
if(len) {
memcpy(tmp, def.colrules, len);
@ -1528,13 +1528,13 @@ xclunk(IXPConn *c, Fcall *fcall)
if(type == FsFkeys)
update_keys();
else if(type == FsFtagrules) {
update_rules(&trule, def.tagrules);
update_rules(&def.tagrules.rule, def.tagrules.string);
for(cl=client; cl; cl=cl->next)
apply_rules(cl);
update_views();
}
else if(type == FsFcolrules) {
update_rules(&vrule, def.colrules);
update_rules(&def.colrules.rule, def.colrules.string);
}
if(c->map == m)
c->map = m->next;
@ -1607,5 +1607,5 @@ new_ixp_conn(IXPConn *c)
int fd = accept(c->fd, nil, nil);
if(fd >= 0)
ixp_server_open_conn(c->srv, fd, do_fcall, ixp_server_close_conn);
ixp_server_open_conn(c->srv, fd, do_fcall, nil);
}

View File

@ -4,44 +4,8 @@
#include <time.h>
#include "wm.h"
P9Srv p9srv = {
.open= fs_open,
.walk= fs_walk,
.read= fs_read,
.stat= fs_stat,
.write= fs_write,
.clunk= fs_clunk,
.attach=fs_attach,
.create=fs_create,
.remove=fs_remove,
.freefid=fs_freefid
};
#define QID(t, i) (((long long)((t)&0xFF)<<32)|((i)&0xFFFFFFFF))
/* Will I ever need these macros?
* I don't think so. */
#define TYPE(q) ((q)>>32&0xFF)
#define ID(q) ((q)&0xFFFFFFFF)
static char
Enoperm[] = "permission denied",
Enofile[] = "file not found",
Eisdir[] = "file is a directory",
Ebadvalue[] = "bad value",
Enocommand[] = "command not supported";
//static char Efidinuse[] = "fid in use";
//static char Enomode[] = "mode not supported";
//static char Enofunc[] = "function not supported";
enum { FsRoot, FsDClient, FsDClients, FsDLBar,
FsDRBar, FsDSClient, FsDTag, FsDTags,
FsFBar, FsFBorder, FsFCNorm, FsFCSel,
FsFCctl, FsFCindex, FsFColRules, FsFEvent,
FsFFont, FsFKeys, FsFRctl, FsFTagRules,
FsFTctl, FsFTindex, FsFprops, RsFFont
};
/* Datatypes: */
typedef struct Dirtab Dirtab;
struct Dirtab {
char *name;
@ -56,6 +20,7 @@ struct FileId {
union {
void *ref;
Bar *bar;
Bar **bar_p;
View *view;
Client *client;
Rules *rule;
@ -67,15 +32,65 @@ struct FileId {
unsigned short nref;
};
/* Function prototypes */
static void dostat(Stat *s, unsigned int len, FileId *f);
/* Error messages */
static char
Enoperm[] = "permission denied",
Enofile[] = "file not found",
Ebadvalue[] = "bad value",
Einterrupted[] = "interrupted",
Enocommand[] = "command not supported";
/* Old error messages:
Eisdir[] = "file is a directory",
Efidinuse[] = "fid in use",
Enomode[] = "mode not supported",
Enofunc[] = "function not supported",
*/
/* Constants */
enum { /* Dirs */
FsRoot, FsDClient, FsDClients, FsDBar,
FsDSClient, FsDTag, FsDTags,
/* Files */
FsFBar, FsFBorder, FsFCNorm, FsFCSel,
FsFCctl, FsFCindex, FsFColRules, FsFCtags,
FsFEvent, FsFFont, FsFKeys, FsFRctl,
FsFTagRules, FsFTctl, FsFTindex, FsFprops,
RsFFont
};
/* QID Macros */
#define QID(t, i) (((long long)((t)&0xFF)<<32)|((i)&0xFFFFFFFF))
/* Will I ever need these macros?
* I don't think so. */
#define TYPE(q) ((q)>>32&0xFF)
#define ID(q) ((q)&0xFFFFFFFF)
/* Global vars */
FileId *free_fileid = nil;
Req *pending_event_reads = nil;
P9Srv p9srv = {
.open= fs_open,
.walk= fs_walk,
.read= fs_read,
.stat= fs_stat,
.write= fs_write,
.clunk= fs_clunk,
.flush= fs_flush,
.attach=fs_attach,
.create=fs_create,
.remove=fs_remove,
.freefid=fs_freefid
};
/* ad-hoc file tree. Empty names ("") indicate a dynamic entry to be filled
* in by lookup_file */
static Dirtab
dirtabroot[]= {{".", QTDIR, FsRoot, 0500|DMDIR },
{"rbar", QTDIR, FsDRBar, 0700|DMDIR },
{"lbar", QTDIR, FsDLBar, 0700|DMDIR },
{"rbar", QTDIR, FsDBar, 0700|DMDIR },
{"lbar", QTDIR, FsDBar, 0700|DMDIR },
{"client", QTDIR, FsDClients, 0500|DMDIR },
{"tag", QTDIR, FsDTags, 0500|DMDIR },
{"ctl", QTAPPEND, FsFRctl, 0600|DMAPPEND },
@ -93,14 +108,16 @@ dirtabclients[]={{".", QTDIR, FsDClients, 0500|DMDIR },
{nil}},
dirtabclient[]= {{".", QTDIR, FsDClient, 0500|DMDIR },
{"ctl", QTAPPEND, FsFCctl, 0200|DMAPPEND },
{"tags", QTFILE, FsFCtags, 0600 },
{"props", QTFILE, FsFprops, 0400 },
{nil}},
dirtabsclient[]={{".", QTDIR, FsDSClient, 0500|DMDIR },
{"ctl", QTAPPEND, FsFCctl, 0200|DMAPPEND },
{"index", QTFILE, FsFCindex, 0400 },
{"tags", QTFILE, FsFCtags, 0600 },
{"props", QTFILE, FsFprops, 0400 },
{nil}},
dirtabbar[]= {{".", QTDIR, FsDRBar, 0700|DMDIR },
dirtabbar[]= {{".", QTDIR, FsDBar, 0700|DMDIR },
{"", QTFILE, FsFBar, 0600 },
{nil}},
dirtabtags[]= {{".", QTDIR, FsDTags, 0500|DMDIR },
@ -115,8 +132,7 @@ dirtabtag[]= {{".", QTDIR, FsDTag, 0500|DMDIR },
* since otherwise we would need to use compound literals */
static Dirtab *dirtab[] = {
[FsRoot] dirtabroot,
[FsDRBar] dirtabbar,
[FsDLBar] dirtabbar,
[FsDBar] dirtabbar,
[FsDClients] dirtabclients,
[FsDClient] dirtabclient,
[FsDSClient] dirtabsclient,
@ -198,7 +214,9 @@ lookup_file(FileId *parent, char *name)
case FsDClients:
if(!name || !strncmp(name, "sel", 4)) {
if((c = sel_client())) {
file = push_file(&last);
file = get_file();
*last = file;
last = &file->next;
file->ref = c;
file->id = c->id;
file->index = idx_of_client(c);
@ -214,7 +232,9 @@ lookup_file(FileId *parent, char *name)
i=0;
for(c=client; c; c=c->next, i++) {
if(!name || i == id) {
file = push_file(&last);
file = get_file();
*last = file;
last = &file->next;
file->ref = c;
file->id = c->id;
file->tab = *dir;
@ -226,7 +246,9 @@ lookup_file(FileId *parent, char *name)
case FsDTags:
if(!name || !strncmp(name, "sel", 4)) {
if(sel) {
file = push_file(&last);
file = get_file();
*last = file;
last = &file->next;
file->ref = sel;
file->id = sel->id;
file->tab = *dir;
@ -235,7 +257,9 @@ lookup_file(FileId *parent, char *name)
}
for(v=view; v; v=v->next) {
if(!name || !strcmp(name, v->name)) {
file = push_file(&last);
file = get_file();
*last = file;
last = &file->next;
file->ref = v;
file->id = v->id;
file->tab = *dir;
@ -244,11 +268,12 @@ lookup_file(FileId *parent, char *name)
}
}
break;
case FsDRBar:
case FsDLBar:
for(b=parent->ref; b; b=b->next) {
case FsDBar:
for(b=*parent->bar_p; b; b=b->next) {
if(!name || !strcmp(name, b->name)) {
file = push_file(&last);
file = get_file();
*last = file;
last = &file->next;
file->ref = b;
file->id = b->id;
file->tab = *dir;
@ -260,18 +285,21 @@ lookup_file(FileId *parent, char *name)
}
}else /* Static dirs */
if(!name || !strcmp(name, dir->name)) {
file = push_file(&last);
file = get_file();
*last = file;
last = &file->next;
file->id = 0;
file->ref = parent->ref;
file->tab = *dir;
file->tab.name = strdup(file->tab.name);
/* Special considerations: */
switch(file->tab.type) {
case FsDLBar:
file->ref = lbar;
break;
case FsDRBar:
file->ref = rbar;
case FsDBar:
if(!strncmp(file->tab.name, "lbar", 5))
file->ref = &lbar;
else
file->ref = &rbar;
break;
case FsFColRules:
file->ref = &def.colrules;
@ -315,6 +343,7 @@ fs_walk(Req *r) {
nf = lookup_file(f, r->ifcall.wname[i]);
if(!nf)
break;
cext_assert(!nf->next);
nf->next = f;
f = nf;
}
@ -336,8 +365,8 @@ fs_walk(Req *r) {
if(r->ifcall.fid == r->ifcall.newfid) {
nf=r->fid->aux;
r->fid->aux = f;
for(; nf; nf=f) {
f = nf->next;
while((nf = f)) {
f=f->next;
free_file(nf);
}
}
@ -347,7 +376,6 @@ fs_walk(Req *r) {
respond(r, nil);
}
/* All of this stat stuf is ugly. */
void
fs_stat(Req *r) {
Stat s;
@ -363,6 +391,7 @@ fs_stat(Req *r) {
respond(r, nil);
}
/* This should be moved to libixp */
static void
write_buf(Req *r, void *buf, unsigned int len) {
if(r->ifcall.offset >= len)
@ -385,7 +414,7 @@ void
fs_read(Req *r) {
unsigned char *buf;
FileId *f, *tf;
unsigned int n, offset;
int n, offset;
int size;
offset = 0;
@ -411,8 +440,8 @@ fs_read(Req *r) {
offset += n;
}
for(; f; f = tf) {
tf = f->next;
while((f = tf)) {
tf=tf->next;
free_file(f);
}
@ -437,11 +466,32 @@ fs_read(Req *r) {
case FsFFont:
write_buf(r, (void *)def.font, strlen(def.font));
return respond(r, nil);
case FsFBorder:
asprintf((void *)&r->ofcall.data, "%d", def.border);
if(!r->ifcall.offset)
r->ofcall.count = strlen(r->ofcall.data);
case FsFCtags:
write_buf(r, (void *)f->client->tags, strlen(f->client->tags));
return respond(r, nil);
case FsFCindex:
if(r->ifcall.offset)
return respond(r, nil);
n = asprintf((char **)&r->ofcall.data, "%d", f->index);
cext_assert(n >= 0);
r->ofcall.count = n;
return respond(r, nil);
case FsFBorder:
if(r->ifcall.offset)
return respond(r, nil);
n = asprintf((char **)&r->ofcall.data, "%d", def.border);
cext_assert(n >= 0);
r->ofcall.count = n;
return respond(r, nil);
case FsFTindex:
buf = view_index(f->view);
n = strlen(buf);
write_buf(r, (void *)buf, n);
return respond(r, nil);
case FsFEvent:
r->aux = pending_event_reads;
pending_event_reads = r;
return;
}
/* XXX: This should be taken care of by open */
/* should probably be an assertion in the future */
@ -461,8 +511,6 @@ fs_attach(Req *r) {
respond(r, nil);
}
/* XXX: fs_* functions below here are yet to be properly implemented */
void
fs_open(Req *r) {
/* XXX */
@ -480,17 +528,12 @@ fs_freefid(Fid *f) {
}
}
void
fs_remove(Req *r) {
respond(r, "not implemented");
}
void
fs_clunk(Req *r) {
Client *c;
FileId *f = r->fid->aux;
switch(r->ifcall.type) {
switch(f->tab.type) {
case FsFTagRules:
update_rules(&f->rule->rule, f->rule->string);
/* no break */
@ -499,10 +542,19 @@ fs_clunk(Req *r) {
apply_rules(c);
update_views();
break;
case FsFKeys:
update_keys();
break;
case FsFCtags:
apply_tags(f->client, f->client->tags);
update_views();
draw_client(f->client);
break;
}
respond(r, nil);
}
/* This should be moved to libixp */
void
write_to_buf(Req *r, void *buf, unsigned int *len, unsigned int max) {
unsigned int offset, count;
@ -517,8 +569,7 @@ write_to_buf(Req *r, void *buf, unsigned int *len, unsigned int max) {
if(max && (count > max - offset))
count = max - offset;
if(r->fid->omode&OTRUNC || (offset + count > *len))
*len = offset + count;
*len = offset + count;
if(max == 0) {
*(void **)buf = realloc(*(void **)buf, *len);
@ -529,6 +580,34 @@ write_to_buf(Req *r, void *buf, unsigned int *len, unsigned int max) {
memcpy(buf + offset, r->ifcall.data, count);
}
/* This should be moved to libixp */
void
data_to_cstring(Req *r) {
unsigned int i;
if(r->ifcall.count) {
for(i=0; i < r->ifcall.count; i++)
if(r->ifcall.data[i] == '\n')
break;
if(i == r->ifcall.count)
r->ifcall.data = realloc(r->ifcall.data, ++i);
cext_assert(r->ifcall.data);
r->ifcall.data[i] = '\0';
}
}
/* This should be moved to liblitz */
int
parse_colors(char **buf, int *buflen, Color *col) {
unsigned int i;
if(*buflen < 23 || 3 != sscanf(*buf, "#%06x #%06x #%06x", &i,&i,&i))
return 0;
(*buflen) -= 23;
bcopy(*buf, col->string, 23);
blitz_loadcolor(&col->col, col->string);
return 1;
}
/* This function needs to be seriously cleaned up */
void
fs_write(Req *r) {
FileId *f;
@ -536,64 +615,129 @@ fs_write(Req *r) {
unsigned int i;
f = r->fid->aux;
if(f->tab.perm & DMDIR) {
respond(r, Eisdir);
}else{
switch(f->tab.type) {
case FsFColRules:
case FsFTagRules:
write_to_buf(r, &f->rule->string, &f->rule->size, 0);
return respond(r, nil);
case FsFKeys:
write_to_buf(r, &def.keys, &def.keyssz, 0);
return respond(r, nil);
case FsFFont:
i=strlen(def.font);
write_to_buf(r, &def.font, &i, 0);
return respond(r, nil);
case FsFBorder:
/* fix me! */
buf = realloc(r->ifcall.data, r->ifcall.count + 1);
cext_assert(buf);
buf[r->ifcall.count] = '\0';
i = (unsigned int)strtol(r->ifcall.data, &buf, 10);
if(*buf)
return respond(r, Ebadvalue);
def.border = i;
return respond(r, nil);
case FsFCSel:
case FsFCNorm:
if((r->ifcall.count != 23) ||
(3 != sscanf(r->ifcall.data, "#%06x #%06x #%06x", &i,&i,&i)))
return respond(r, Ebadvalue);
r->ofcall.count = 23;
bcopy(r->ifcall.data, f->col->string, 23);
blitz_loadcolor(&f->col->col, f->col->string);
draw_clients();
return respond(r, nil);
case FsFRctl:
if(!strncmp(r->ifcall.data, "quit", 5))
srv.running = 0;
else if(!strncmp(buf, "view ", 5))
select_view(&r->ifcall.data[5]);
else
return respond(r, Enocommand);
r->ofcall.msize = r->ifcall.msize;
return respond(r, nil);
}
respond(r, Enoperm);
switch(f->tab.type) {
case FsFColRules:
case FsFTagRules:
write_to_buf(r, &f->rule->string, &f->rule->size, 0);
return respond(r, nil);
case FsFKeys:
write_to_buf(r, &def.keys, &def.keyssz, 0);
return respond(r, nil);
case FsFFont:
data_to_cstring(r);
i=strlen(def.font);
write_to_buf(r, &def.font, &i, 0);
def.font[i] = '\0';
r->ofcall.count = i- r->ifcall.offset;
return respond(r, nil);
case FsFCtags:
data_to_cstring(r);
i=strlen(f->client->tags);
write_to_buf(r, &f->client->tags, &i, 255);
f->client->tags[i] = '\0';
r->ofcall.count = i- r->ifcall.offset;
return respond(r, nil);
case FsFBorder:
data_to_cstring(r);
i = (unsigned int)strtol(r->ifcall.data, &buf, 10);
if(*buf)
return respond(r, Ebadvalue);
def.border = i;
return respond(r, nil);
case FsFBar:
/* XXX: This should validate after each write */
i = strlen(f->bar->buf);
write_to_buf(r, &f->bar->buf, &i, 279);
f->bar->buf[i] = '\0';
r->ofcall.count = i- r->ifcall.offset;
return respond(r, nil);
case FsFCSel:
case FsFCNorm:
/* XXX: This allows for junk after the color string */
data_to_cstring(r);
buf = r->ifcall.data;
i = r->ifcall.count;
if(!parse_colors((char **)&buf, &i, f->col))
return respond(r, Ebadvalue);
draw_clients();
r->ofcall.count = r->ifcall.count - i;
return respond(r, nil);
case FsFRctl:
data_to_cstring(r);
/* XXX: This needs to be moved to client_message(char *) */
if(!strncmp(r->ifcall.data, "quit", 5))
srv.running = 0;
else if(!strncmp(r->ifcall.data, "view ", 5))
select_view(&r->ifcall.data[5]);
else
return respond(r, Enocommand);
r->ofcall.count = r->ifcall.count;
return respond(r, nil);
case FsFEvent:
/* XXX: r->ifcall.count could be very large */
buf = cext_emallocz(r->ifcall.count + 1);
bcopy(r->ifcall.data, buf, r->ifcall.count);
write_event(buf);
free(buf);
r->ofcall.count = r->ifcall.count;
return respond(r, nil);
}
respond(r, Enoperm);
}
void
fs_flush(Req *r) {
Req **t;
for(t=&pending_event_reads; *t; t=(Req **)&(*t)->aux) {
if(*t == r->oldreq) {
*t = (*t)->aux;
respond(r->oldreq, Einterrupted);
break;
}
}
respond(r, nil);
}
void
fs_create(Req *r) {
FileId *f = r->fid->aux;
switch(f->tab.type) {
default:
/* XXX: This should be taken care of by the library */
return respond(r, Enoperm);
case FsDBar:
if(!strlen(r->ifcall.name))
return respond(r, Ebadvalue);
create_bar(r->ifcall.name);
f = lookup_file(f, r->ifcall.name);
if(!f)
return respond(r, Enofile);
r->ofcall.qid.type = f->tab.qtype;
r->ofcall.qid.path = QID(f->tab.type, f->id);
free_file(f);
respond(r, nil);
break;
}
}
void
fs_remove(Req *r) {
respond(r, "not implemented");
}
/* XXX: Shuts up the linker, but is yet to be written */
void
write_event(char *buf) {
return;
Req **r;
unsigned int len = strlen(buf);
if(!len)
return;
for(r=&pending_event_reads; *r; *r=(*r)->aux) {
/* XXX: It would be nice if strdup wasn't necessary here */
(*r)->ofcall.data = strdup(buf);
(*r)->ofcall.count = len;
respond(*r, nil);
}
}
static void

View File

@ -337,6 +337,43 @@ is_view_of(Client *c, View *v)
return False;
}
/* XXX: This will need cleanup */
unsigned char *
view_index(View *v) {
enum { BUF_MAX = 8092 };
static unsigned char buf[BUF_MAX];
unsigned int a_i, buf_i, n;
int len;
Frame *f;
Area *a;
len = BUF_MAX;
buf_i = 0;
for((a = v->area), (a_i = 0); a; (a=a->next), (a_i++)) {
for(f=a->frame; f && len > 0; f=f->anext) {
XRectangle *r = &f->rect;
if(a_i == 0)
n = snprintf(&buf[buf_i], len, "~ %d %d %d %d %d %s\n",
idx_of_client(f->client),
r->x, r->y, r->width, r->height,
f->client->props);
else
n = snprintf(&buf[buf_i], len, "%d %d %d %s\n",
a_i, idx_of_client(f->client),
r->width, f->client->props);
buf_i += n;
len -= n;
}
}
return buf;
}
/* XXX: This will need cleanup too */
int
view_message(View *v, char *message) {
return 0;
}
static Bool
is_empty(View *v)
{
@ -391,7 +428,7 @@ newcolw_of_view(View *v)
unsigned int i, n;
regmatch_t tmpregm;
for(r=vrule; r; r=r->next) {
for(r=def.colrules.rule; r; r=r->next) {
if(!regexec(&r->regex, v->name, 1, &tmpregm, 0)) {
char buf[256];
char *toks[16];

View File

@ -148,7 +148,7 @@ init_screen()
gcv.subwindow_mode = IncludeInferiors;
gcv.function = GXxor;
gcv.foreground = def.sel.bg;
gcv.foreground = def.selcolor.col.bg;
gcv.plane_mask = AllPlanes;
gcv.graphics_exposures = False;
xorgc = XCreateGC(dpy, root, GCForeground | GCGraphicsExposures |
@ -245,7 +245,7 @@ main(int argc, char *argv[])
dpy = XOpenDisplay(0);
if(!dpy) {
fprintf(stderr, "%s", "wmiiwm: cannot open display\n");
fputs("wmiiwm: cannot open display\n", stderr);
exit(1);
}
screen = DefaultScreen(dpy);
@ -259,8 +259,7 @@ main(int argc, char *argv[])
XSync(dpy, False);
if(other_wm_running) {
fprintf(stderr,
"wmiiwm: another window manager is already running\n");
fputs("wmiiwm: another window manager is already running\n", stderr);
exit(1);
}
if(checkwm) {
@ -281,36 +280,32 @@ main(int argc, char *argv[])
}
/* IXP server */
ixp_server_open_conn(&srv, i, new_ixp_conn, ixp_server_close_conn);
root_qid.qid.dir_type = FsDroot;
root_qid.type = IXP_QTDIR;
root_qid.version = 0;
root_qid.ptype = FsDroot;
ixp_server_open_conn(&srv, i, &p9srv, serve_9pcon, nil);
/* X server */
ixp_server_open_conn(&srv, ConnectionNumber(dpy), check_x_event, nil);
ixp_server_open_conn(&srv, ConnectionNumber(dpy), nil, check_x_event, nil);
init_x_event_handler();
blitz_x11_init(dpy);
view = nil;
client = nil;
sel = nil;
bar = nil;
lbar = nil;
key = nil;
def.colrules = nil;
def.colrulessz = 0;
def.tagrules = nil;
def.tagrulessz = 0;
def.colrules.string = nil;
def.colrules.size = 0;
def.tagrules.string = nil;
def.tagrules.size = 0;
def.keys = nil;
def.keyssz = 0;
def.font = strdup(BLITZ_FONT);
def.border = 2;
def.colmode = Coldefault;
cext_strlcpy(def.selcolor, BLITZ_SELCOLORS, sizeof(def.selcolor));
blitz_loadcolor(&def.sel, def.selcolor);
cext_strlcpy(def.normcolor, BLITZ_NORMCOLORS, sizeof(def.normcolor));
blitz_loadcolor(&def.norm, def.normcolor);
cext_strlcpy(def.selcolor.string, BLITZ_SELCOLORS, sizeof(def.selcolor.string));
blitz_loadcolor(&def.selcolor.col, def.selcolor.string);
cext_strlcpy(def.normcolor.string, BLITZ_NORMCOLORS, sizeof(def.normcolor.string));
blitz_loadcolor(&def.normcolor.col, def.normcolor.string);
cext_strlcpy(def.grabmod, "Mod1", sizeof(def.grabmod));
def.mod = Mod1Mask;

View File

@ -42,6 +42,7 @@ enum {
};
/* 8-bit qid.path.type */
/*
enum {
FsDroot,
FsDdef,
@ -74,18 +75,15 @@ enum {
FsFindex,
FsLast
};
*/
enum { MIN_COLWIDTH = 64 };
enum { WM_PROTOCOL_DELWIN = 1 };
typedef struct View View;
#define VIEW(p) ((View *)(p))
typedef struct Area Area;
#define AREA(p) ((Area *)(p))
typedef struct Frame Frame;
#define FRAME(p) ((Frame *)(p))
typedef struct Client Client;
#define CLIENT(p) ((Client *)(p))
struct View {
View *next;
@ -156,33 +154,46 @@ struct Key {
KeyCode key;
};
#define BAR(p) ((Bar *)(p))
typedef struct Color {
char string[24];
BlitzColor col;
} Color;
typedef struct Bar Bar;
struct Bar {
Bar *next;
char buf[280];
char name[256];
char data[256];
char colstr[24];
Color color;
unsigned short id;
BlitzColor color;
XRectangle rect;
};
typedef struct Rule Rule;
struct Rule {
Rule *next;
regex_t regex;
char value[256];
};
typedef struct Rules {
Rule *rule;
char *string;
unsigned int size;
} Rules;
/* default values */
typedef struct {
char selcolor[24];
char normcolor[24];
Color selcolor;
Color normcolor;
char *font;
BlitzColor sel;
BlitzColor norm;
unsigned int border;
unsigned int snap;
char *keys;
unsigned int keyssz;
char *tagrules;
unsigned int tagrulessz;
char *colrules;
unsigned int colrulessz;
Rules tagrules;
Rules colrules;
char grabmod[5];
unsigned long mod;
int colmode;
@ -203,22 +214,16 @@ typedef struct {
} PackedQid;
/* global variables */
typedef struct Rule Rule;
struct Rule {
Rule *next;
regex_t regex;
char value[256];
};
/* global variables */
View *view;
Client *client;
Key *key;
Bar *bar;
Rule *trule;
Rule *vrule;
Bar *lbar;
Bar *rbar;
View *sel;
P9Srv p9srv;
Display *dpy;
int screen;
Window root;
@ -317,6 +322,19 @@ int idx_of_frame(Frame *f);
Frame *frame_of_id(Area *a, unsigned short id);
Client *frame_of_win(Window w);
/* fs2.c */
void fs_attach(Req *r);
void fs_clunk(Req *r);
void fs_create(Req *r);
void fs_flush(Req *r);
void fs_freefid(Fid *f);
void fs_open(Req *r);
void fs_read(Req *r);
void fs_remove(Req *r);
void fs_stat(Req *r);
void fs_walk(Req *r);
void fs_write(Req *r);
/* fs.c */
unsigned long long pack_qpath(unsigned char type, unsigned short i1,
unsigned short i2, unsigned short i3);
@ -357,6 +375,7 @@ void attach_to_view(View *v, Client *c);
Client *sel_client_of_view(View *v);
void restack_view(View *v);
View *view_of_name(const char *name);
unsigned char * view_index(View *v);
void destroy_view(View *v);
void update_views();
unsigned int newcolw_of_view(View *v);

View File

@ -176,6 +176,9 @@ static int
xdir(char *file, int details)
{
unsigned int fid = c.root_fid << 2;
/* XXX: buffer overflow */
Stat *s = cext_emallocz(sizeof(Stat));
unsigned char *buf;
int count;
static unsigned char result[IXP_MAX_MSG];
void *data = nil;
@ -185,8 +188,10 @@ xdir(char *file, int details)
fprintf(stderr, "wmiir: cannot stat file '%s': %s\n", file, c.errstr);
return -1;
}
if(!(c.fcall.stat.mode & IXP_DMDIR)) {
print_stat(&c.fcall.stat, details);
buf = c.fcall.stat;
ixp_unpack_stat(&buf, s);
if(!(s->mode & IXP_DMDIR)) {
print_stat(s, details);
fflush(stdout);
return 0;
}

View File

@ -26,8 +26,8 @@ ixp_client_do_fcall(IXPClient *c)
c->errstr = "received bad message";
return -1;
}
if(c->fcall.id == RERROR) {
c->errstr = c->fcall.errstr;
if(c->fcall.type == RERROR) {
c->errstr = c->fcall.ename;
return -1;
}
return 0;
@ -40,31 +40,31 @@ ixp_client_dial(IXPClient *c, char *sockfile, unsigned int rootfid)
c->errstr = "cannot connect server";
return -1;
}
c->fcall.id = TVERSION;
c->fcall.type = TVERSION;
c->fcall.tag = IXP_NOTAG;
c->fcall.maxmsg = IXP_MAX_MSG;
cext_strlcpy(c->fcall.version, IXP_VERSION, sizeof(c->fcall.version));
c->fcall.msize = IXP_MAX_MSG;
c->fcall.version = strdup(IXP_VERSION);
if(ixp_client_do_fcall(c) == -1) {
fprintf(stderr, "error: %s\n", c->fcall.errstr);
fprintf(stderr, "error: %s\n", c->fcall.ename);
ixp_client_hangup(c);
return -1;
}
if(strncmp(c->fcall.version, IXP_VERSION, strlen(IXP_VERSION))) {
fprintf(stderr, "error: %s\n", c->fcall.errstr);
fprintf(stderr, "error: %s\n", c->fcall.ename);
c->errstr = "9P versions differ";
ixp_client_hangup(c);
return -1; /* we cannot handle this version */
}
c->root_fid = rootfid;
c->fcall.id = TATTACH;
c->fcall.type = TATTACH;
c->fcall.tag = IXP_NOTAG;
c->fcall.fid = c->root_fid;
c->fcall.afid = IXP_NOFID;
cext_strlcpy(c->fcall.uname, getenv("USER"), sizeof(c->fcall.uname));
c->fcall.aname[0] = 0;
c->fcall.uname = strdup(getenv("USER"));
c->fcall.aname = strdup("");
if(ixp_client_do_fcall(c) == -1) {
fprintf(stderr, "error: %s\n", c->fcall.errstr);
fprintf(stderr, "error: %s\n", c->fcall.ename);
ixp_client_hangup(c);
return -1;
}
@ -77,7 +77,7 @@ ixp_client_remove(IXPClient *c, unsigned int newfid, char *filepath)
{
if(ixp_client_walk(c, newfid, filepath) == -1)
return -1;
c->fcall.id = TREMOVE;
c->fcall.type = TREMOVE;
c->fcall.tag = IXP_NOTAG;
c->fcall.fid = newfid;
return ixp_client_do_fcall(c);
@ -87,10 +87,10 @@ int
ixp_client_create(IXPClient *c, unsigned int dirfid, char *name,
unsigned int perm, unsigned char mode)
{
c->fcall.id = TCREATE;
c->fcall.type = TCREATE;
c->fcall.tag = IXP_NOTAG;
c->fcall.fid = dirfid;
cext_strlcpy(c->fcall.name, name, sizeof(c->fcall.name));
c->fcall.name = strdup(name);
c->fcall.perm = perm;
c->fcall.mode = mode;
return ixp_client_do_fcall(c);
@ -101,15 +101,15 @@ ixp_client_walk(IXPClient *c, unsigned int newfid, char *filepath)
{
unsigned int i;
char *wname[IXP_MAX_WELEM];
c->fcall.id = TWALK;
c->fcall.type = TWALK;
c->fcall.fid = c->root_fid;
c->fcall.newfid = newfid;
if(filepath) {
cext_strlcpy(c->fcall.name, filepath, sizeof(c->fcall.name));
c->fcall.name = strdup(filepath);
c->fcall.nwname =
cext_tokenize(wname, IXP_MAX_WELEM, c->fcall.name, '/');
for(i = 0; i < c->fcall.nwname; i++)
cext_strlcpy(c->fcall.wname[i], wname[i], sizeof(c->fcall.wname[i]));
c->fcall.wname[i] = strdup(wname[i]);
}
return ixp_client_do_fcall(c);
}
@ -120,7 +120,7 @@ ixp_client_stat(IXPClient *c, unsigned int newfid, char *filepath)
if(ixp_client_walk(c, newfid, filepath) == -1)
return -1;
c->fcall.id = TSTAT;
c->fcall.type = TSTAT;
c->fcall.tag = IXP_NOTAG;
c->fcall.fid = newfid;
return ixp_client_do_fcall(c);
@ -129,7 +129,7 @@ ixp_client_stat(IXPClient *c, unsigned int newfid, char *filepath)
int
ixp_client_open(IXPClient *c, unsigned int newfid, unsigned char mode)
{
c->fcall.id = TOPEN;
c->fcall.type = TOPEN;
c->fcall.tag = IXP_NOTAG;
c->fcall.fid = newfid;
c->fcall.mode = mode;
@ -151,7 +151,7 @@ ixp_client_read(IXPClient *c, unsigned int fid, unsigned long long offset,
{
unsigned int bytes = c->fcall.iounit;
c->fcall.id = TREAD;
c->fcall.type = TREAD;
c->fcall.tag = IXP_NOTAG;
c->fcall.fid = fid;
c->fcall.offset = offset;
@ -171,7 +171,7 @@ ixp_client_write(IXPClient *c, unsigned int fid,
c->errstr = "iounit exceeded";
return -1;
}
c->fcall.id = TWRITE;
c->fcall.type = TWRITE;
c->fcall.tag = IXP_NOTAG;
c->fcall.fid = fid;
c->fcall.offset = offset;
@ -185,7 +185,7 @@ ixp_client_write(IXPClient *c, unsigned int fid,
int
ixp_client_close(IXPClient *c, unsigned int fid)
{
c->fcall.id = TCLUNK;
c->fcall.type = TCLUNK;
c->fcall.tag = IXP_NOTAG;
c->fcall.fid = fid;
return ixp_client_do_fcall(c);

View File

@ -102,6 +102,11 @@ ixp_unpack_strings(unsigned char **msg, unsigned short n, char **strings) {
s += len;
size += len + 1; /* for '\0' */
}
if(!size) {
/* So we don't try to free some random value */
*strings = nil;
return;
}
/* XXX: we don't really need mallocz here */
s = cext_emallocz(size);
for(i=0; i < n; i++) {
@ -115,20 +120,17 @@ ixp_unpack_strings(unsigned char **msg, unsigned short n, char **strings) {
}
void
ixp_unpack_string(unsigned char **msg, char *string, unsigned short stringlen,
unsigned short *len)
ixp_unpack_string(unsigned char **msg, char **string, unsigned short *len)
{
ixp_unpack_u16(msg, len);
*string = nil;
if (!*len)
return;
if (*len > stringlen - 1) {
/* might never happen if stringlen == IXP_MAX_MSG */
string[0] = 0;
} else {
memcpy(string, *msg, *len);
string[*len] = 0;
*msg += *len;
}
/* XXX we don't really need emallocz here */
*string = cext_emallocz(*len+1);
memcpy(*string, *msg, *len);
string[*len] = 0;
*msg += *len;
}
void
@ -141,9 +143,11 @@ ixp_pack_data(unsigned char **msg, int *msize, unsigned char *data, unsigned int
}
void
ixp_unpack_data(unsigned char **msg, unsigned char *data, unsigned int datalen)
ixp_unpack_data(unsigned char **msg, unsigned char **data, unsigned int datalen)
{
memcpy(data, *msg, datalen);
/* XXX: this could be too large a number */
*data = cext_emallocz(datalen);
memcpy(*data, *msg, datalen);
*msg += datalen;
}
@ -212,8 +216,8 @@ ixp_unpack_stat(unsigned char **msg, Stat * stat)
ixp_unpack_u32(msg, &stat->atime);
ixp_unpack_u32(msg, &stat->mtime);
ixp_unpack_u64(msg, &stat->length);
ixp_unpack_string(msg, stat->name, sizeof(stat->name), &dummy);
ixp_unpack_string(msg, stat->uid, sizeof(stat->uid), &dummy);
ixp_unpack_string(msg, stat->gid, sizeof(stat->gid), &dummy);
ixp_unpack_string(msg, stat->muid, sizeof(stat->muid), &dummy);
ixp_unpack_string(msg, &stat->name, &dummy);
ixp_unpack_string(msg, &stat->uid, &dummy);
ixp_unpack_string(msg, &stat->gid, &dummy);
ixp_unpack_string(msg, &stat->muid, &dummy);
}

View File

@ -1,8 +1,14 @@
/* This file is derived from src/lib9p/intmap.c from plan9port */
/* See LICENCE.p9p for terms of use */
#include <stdlib.h>
#include <ixp.h>
#define USED(v)
#include "ixp.h"
#define USED(v) if(v){}else{}
struct Intlist {
unsigned long id;
void* aux;
Intlist* link;
};
static unsigned long
hashid(Intmap *map, unsigned long id)
@ -50,6 +56,19 @@ freemap(Intmap *map, void (*destroy)(void*))
}
}
}
void
execmap(Intmap *map, void (*run)(void*))
{
int i;
Intlist *p, *nlink;
for(i=0; i<map->nhash; i++){
for(p=map->hash[i]; p; p=nlink){
nlink = p->link;
run(p->aux);
}
}
}
void*
lookupkey(Intmap *map, unsigned long id)

View File

@ -10,17 +10,16 @@
#define IXP_NOTAG (unsigned short)~0U /*Dummy tag */
#define IXP_NOFID (unsigned int)~0 /*No auth */
enum { IXP_MAX_VERSION = 32 };
enum { IXP_MAX_ERROR = 128 };
enum { IXP_MAX_CACHE = 32 };
enum { IXP_MAX_MSG = 8192 };
enum { IXP_MAX_FLEN = 128 };
enum { IXP_MAX_ULEN = 32 };
enum { IXP_MAX_WELEM = 16 };
enum { IXP_MAX_VERSION = 32,
IXP_MAX_ERROR = 128,
IXP_MAX_CACHE = 32,
IXP_MAX_MSG = 8192,
IXP_MAX_FLEN = 128,
IXP_MAX_ULEN = 32,
IXP_MAX_WELEM = 16 };
/* 9P message types */
enum {
TVERSION = 100,
enum { TVERSION = 100,
RVERSION,
TAUTH = 102,
RAUTH,
@ -51,8 +50,7 @@ enum {
};
/* borrowed from libc.h of Plan 9 */
enum {
IXP_DMDIR = 0x80000000, /* mode bit for directories */
enum { IXP_DMDIR = 0x80000000, /* mode bit for directories */
IXP_DMAPPEND = 0x40000000, /* mode bit for append only files */
IXP_DMEXCL = 0x20000000, /* mode bit for exclusive use files */
IXP_DMMOUNT = 0x10000000, /* mode bit for mounted channel */
@ -64,8 +62,7 @@ enum {
};
/* modes */
enum {
IXP_OREAD = 0x00,
enum { IXP_OREAD = 0x00,
IXP_OWRITE = 0x01,
IXP_ORDWR = 0x02,
IXP_OEXEC = 0x03,
@ -77,8 +74,7 @@ enum {
};
/* qid.types */
enum {
IXP_QTDIR = 0x80,
enum { IXP_QTDIR = 0x80,
IXP_QTAPPEND = 0x40,
IXP_QTEXCL = 0x20,
IXP_QTMOUNT = 0x10,
@ -89,6 +85,52 @@ enum {
IXP_QTFILE = 0x00,
};
/* from libc.h in p9p */
enum { OREAD = 0, /* open for read */
OWRITE = 1, /* write */
ORDWR = 2, /* read and write */
OEXEC = 3, /* execute, == read but check execute permission */
OTRUNC = 16, /* or'ed in (except for exec), truncate file first */
OCEXEC = 32, /* or'ed in, close on exec */
ORCLOSE = 64, /* or'ed in, remove on close */
ODIRECT = 128, /* or'ed in, direct access */
ONONBLOCK = 256, /* or'ed in, non-blocking call */
OEXCL = 0x1000, /* or'ed in, exclusive use (create only) */
OLOCK = 0x2000, /* or'ed in, lock after opening */
OAPPEND = 0x4000 /* or'ed in, append only */
};
/* bits in Qid.type */
enum { QTDIR = 0x80, /* type bit for directories */
QTAPPEND = 0x40, /* type bit for append only files */
QTEXCL = 0x20, /* type bit for exclusive use files */
QTMOUNT = 0x10, /* type bit for mounted channel */
QTAUTH = 0x08, /* type bit for authentication file */
QTTMP = 0x04, /* type bit for non-backed-up file */
QTSYMLINK = 0x02, /* type bit for symbolic link */
QTFILE = 0x00 /* type bits for plain file */
};
/* bits in Dir.mode */
enum { DMDIR = 0x80000000, /* mode bit for directories */
DMAPPEND = 0x40000000, /* mode bit for append only files */
DMEXCL = 0x20000000, /* mode bit for exclusive use files */
DMMOUNT = 0x10000000, /* mode bit for mounted channel */
DMAUTH = 0x08000000, /* mode bit for authentication file */
DMTMP = 0x04000000, /* mode bit for non-backed-up file */
DMSYMLINK = 0x02000000, /* mode bit for symbolic link (Unix, 9P2000.u) */
DMDEVICE = 0x00800000, /* mode bit for device file (Unix, 9P2000.u) */
DMNAMEDPIPE = 0x00200000, /* mode bit for named pipe (Unix, 9P2000.u) */
DMSOCKET = 0x00100000, /* mode bit for socket (Unix, 9P2000.u) */
DMSETUID = 0x00080000, /* mode bit for setuid (Unix, 9P2000.u) */
DMSETGID = 0x00040000, /* mode bit for setgid (Unix, 9P2000.u) */
DMREAD = 0x4, /* mode bit for read permission */
DMWRITE = 0x2, /* mode bit for write permission */
DMEXEC = 0x1 /* mode bit for execute permission */
};
typedef struct Qid Qid;
struct Qid {
unsigned char type;
@ -99,7 +141,7 @@ struct Qid {
};
/* stat structure */
typedef struct {
typedef struct Stat {
unsigned short type;
unsigned int dev;
Qid qid;
@ -107,39 +149,65 @@ typedef struct {
unsigned int atime;
unsigned int mtime;
unsigned long long length;
char name[IXP_MAX_FLEN];
char uid[IXP_MAX_ULEN];
char gid[IXP_MAX_ULEN];
char muid[IXP_MAX_ULEN];
char *name;
char *uid;
char *gid;
char *muid;
} Stat;
typedef struct {
unsigned char id;
/* from fcall(3) in plan9port */
typedef struct Fcall {
unsigned char type;
unsigned short tag;
unsigned int fid;
unsigned int maxmsg; /* Tversion, Rversion */
char version[IXP_MAX_VERSION]; /* Tversion, Rversion */
unsigned short oldtag; /* Tflush */
char errstr[IXP_MAX_ERROR]; /* Rerror */
Qid qid; /* Rattach, Ropen, Rcreate */
unsigned int iounit; /* Ropen, Rcreate */
Qid aqid; /* Rauth */
unsigned int afid; /* Tauth, Tattach */
char uname[IXP_MAX_ULEN]; /* Tauth, Tattach */
char aname[IXP_MAX_FLEN]; /* Tauth, Tattach */
unsigned int perm; /* Tcreate */
char name[IXP_MAX_FLEN]; /* Tcreate */
unsigned char mode; /* Tcreate, Topen */
unsigned int newfid; /* Twalk */
unsigned short nwname; /* Twalk */
char *wname[IXP_MAX_WELEM];/* Twalk */
unsigned short nwqid; /* Rwalk */
Qid wqid[IXP_MAX_WELEM]; /* Rwalk */
unsigned long long offset; /* Tread, Twrite */
unsigned int count; /* Tread, Twrite, Rread */
Stat stat; /* Rstat */
unsigned short nstat; /* Twstat, Rstat */
unsigned char data[IXP_MAX_MSG]; /* Twrite, Rread, Twstat, Rstat */
union {
struct { /* Tversion, Rversion */
unsigned int msize;
char *version;
};
struct { /* Tflush */
unsigned short oldtag;
};
struct { /* Rerror */
char *ename;
};
struct { /* Ropen, Rcreate */
Qid qid; /* +Rattach */
unsigned int iounit;
};
struct { /* Rauth */
Qid aqid;
};
struct { /* Tauth, Tattach */
unsigned int afid;
char *uname;
char *aname;
};
struct { /* Tcreate */
unsigned int perm;
char *name;
unsigned char mode; /* +Topen */
};
struct { /* Twalk */
unsigned int newfid;
unsigned short nwname;
char *wname[IXP_MAX_WELEM];
};
struct { /* Rwalk */
unsigned short nwqid;
Qid wqid[IXP_MAX_WELEM];
};
struct { /* Twrite */
long long offset; /* +Tread */
/* +Rread */
unsigned int count; /* +Tread */
unsigned char *data;
};
struct { /* Twstat, Rstat */
unsigned short nstat;
unsigned char *stat;
};
};
} Fcall;
typedef struct IXPServer IXPServer;
@ -155,29 +223,23 @@ struct IXPMap {
Qid wqid[IXP_MAX_WELEM];
};
typedef struct Intlist Intlist;
struct Intlist
{
unsigned long id;
void* aux;
Intlist* link;
};
struct Intmap
{
typedef struct Intlist Intlist;
struct Intmap {
unsigned long nhash;
Intlist **hash;
};
struct IXPConn {
IXPConn *next;
int fd;
IXPServer *srv;
void (*read) (IXPConn *);
void (*close) (IXPConn *);
IXPMap *map;
Fcall pending;
int is_pending;
IXPServer *srv;
void *aux;
int fd;
void (*read) (IXPConn *);
void (*close) (IXPConn *);
char closed;
/* Implementation details */
/* do not use */
IXPConn *next;
};
struct IXPServer {
@ -187,7 +249,7 @@ struct IXPServer {
fd_set rd;
};
typedef struct {
typedef struct IXPClient {
int fd;
unsigned int root_fid;
Qid root_qid;
@ -195,6 +257,48 @@ typedef struct {
char *errstr;
} IXPClient;
typedef struct P9Conn P9Conn;
typedef struct Fid {
unsigned long fid;
char omode;
char *uid;
Qid qid;
void *aux;
/* Implementation details */
/* do not use */
P9Conn *conn;
Intmap *map;
} Fid;
typedef struct Req Req;
struct Req {
Fid *fid;
Fid *newfid;
Req *oldreq;
Fcall ifcall;
Fcall ofcall;
void *aux;
/* Implementation detail */
/* do not use */
P9Conn *conn;
};
typedef struct P9Srv {
void (*attach)(Req *r);
void (*clunk)(Req *r);
void (*create)(Req *r);
void (*flush)(Req *r);
void (*open)(Req *r);
void (*read)(Req *r);
void (*remove)(Req *r);
void (*stat)(Req *r);
void (*walk)(Req *r);
void (*write)(Req *r);
void (*freefid)(Fid *f);
} P9Srv;
/* client.c */
int ixp_client_dial(IXPClient *c, char *address, unsigned int rootfid);
void ixp_client_hangup(IXPClient *c);
@ -226,11 +330,10 @@ void ixp_pack_u64(unsigned char **msg, int *msize, unsigned long long val);
void ixp_unpack_u64(unsigned char **msg, unsigned long long *val);
void ixp_pack_string(unsigned char **msg, int *msize, const char *s);
void ixp_unpack_strings(unsigned char **msg, unsigned short n, char **strings);
void ixp_unpack_string(unsigned char **msg, char *string,
unsigned short stringlen, unsigned short *len);
void ixp_unpack_string(unsigned char **msg, char **string, unsigned short *len);
void ixp_pack_data(unsigned char **msg, int *msize, unsigned char *data,
unsigned int datalen);
void ixp_unpack_data(unsigned char **msg, unsigned char *data,
void ixp_unpack_data(unsigned char **msg, unsigned char **data,
unsigned int datalen);
void ixp_pack_prefix(unsigned char *msg, unsigned int size,
unsigned char id, unsigned short tag);
@ -241,9 +344,14 @@ void ixp_unpack_qid(unsigned char **msg, Qid *qid);
void ixp_pack_stat(unsigned char **msg, int *msize, Stat *stat);
void ixp_unpack_stat(unsigned char **msg, Stat *stat);
/* request.c */
void respond(Req *r, char *error);
void serve_9pcon(IXPConn *c);
/* intmap.c */
void initmap(Intmap *m, unsigned long nhash, void *hash);
void freemap(Intmap *map, void (*destroy)(void*));
void execmap(Intmap *map, void (*destroy)(void*));
void* lookupkey(Intmap *map, unsigned long id);
void* insertkey(Intmap *map, unsigned long id, void *v);
int caninsertkey(Intmap *map, unsigned long id, void *v);
@ -255,7 +363,7 @@ unsigned int ixp_fcall2msg(void *msg, Fcall *fcall, unsigned int msglen);
unsigned int ixp_msg2fcall(Fcall *call, void *msg, unsigned int msglen);
/* server.c */
IXPConn *ixp_server_open_conn(IXPServer *s, int fd,
IXPConn *ixp_server_open_conn(IXPServer *s, int fd, void *aux,
void (*read)(IXPConn *c), void (*close)(IXPConn *c));
void ixp_server_close_conn(IXPConn *c);
char *ixp_server_loop(IXPServer *s);

View File

@ -38,10 +38,10 @@ ixp_fcall2msg(void *msg, Fcall *fcall, unsigned int msglen)
int msize = msglen - i;
unsigned char *p = msg + i;
switch (fcall->id) {
switch (fcall->type) {
case TVERSION:
case RVERSION:
ixp_pack_u32(&p, &msize, fcall->maxmsg);
ixp_pack_u32(&p, &msize, fcall->msize);
ixp_pack_string(&p, &msize, fcall->version);
break;
case TAUTH:
@ -62,7 +62,7 @@ ixp_fcall2msg(void *msg, Fcall *fcall, unsigned int msglen)
ixp_pack_string(&p, &msize, fcall->aname);
break;
case RERROR:
ixp_pack_string(&p, &msize, fcall->errstr);
ixp_pack_string(&p, &msize, fcall->ename);
break;
case TFLUSH:
ixp_pack_u16(&p, &msize, fcall->oldtag);
@ -118,13 +118,13 @@ ixp_fcall2msg(void *msg, Fcall *fcall, unsigned int msglen)
ixp_pack_u32(&p, &msize, fcall->fid);
break;
case RSTAT:
ixp_pack_u16(&p, &msize, ixp_sizeof_stat(&fcall->stat));
ixp_pack_stat(&p, &msize, &fcall->stat);
ixp_pack_u16(&p, &msize, fcall->nstat);
ixp_pack_data(&p, &msize, fcall->stat, fcall->nstat);
break;
case TWSTAT:
ixp_pack_u32(&p, &msize, fcall->fid);
ixp_pack_u16(&p, &msize, ixp_sizeof_stat(&fcall->stat));
ixp_pack_stat(&p, &msize, &fcall->stat);
ixp_pack_u16(&p, &msize, fcall->nstat);
ixp_pack_data(&p, &msize, fcall->stat, fcall->nstat);
break;
}
@ -132,7 +132,7 @@ ixp_fcall2msg(void *msg, Fcall *fcall, unsigned int msglen)
return 0;
msize = msglen - msize;
ixp_pack_prefix(msg, msize, fcall->id, fcall->tag);
ixp_pack_prefix(msg, msize, fcall->type, fcall->tag);
return msize;
}
@ -142,20 +142,20 @@ ixp_msg2fcall(Fcall *fcall, void *msg, unsigned int msglen)
unsigned int i, msize;
unsigned short len;
unsigned char *p = msg;
ixp_unpack_prefix(&p, &msize, &fcall->id, &fcall->tag);
ixp_unpack_prefix(&p, &msize, &fcall->type, &fcall->tag);
if(msize > msglen) /* bad message */
return 0;
switch (fcall->id) {
switch (fcall->type) {
case TVERSION:
case RVERSION:
ixp_unpack_u32(&p, &fcall->maxmsg);
ixp_unpack_string(&p, fcall->version, sizeof(fcall->version), &len);
ixp_unpack_u32(&p, &fcall->msize);
ixp_unpack_string(&p, &fcall->version, &len);
break;
case TAUTH:
ixp_unpack_u32(&p, &fcall->afid);
ixp_unpack_string(&p, fcall->uname, sizeof(fcall->uname), &len);
ixp_unpack_string(&p, fcall->aname, sizeof(fcall->aname), &len);
ixp_unpack_string(&p, &fcall->uname, &len);
ixp_unpack_string(&p, &fcall->aname, &len);
break;
case RAUTH:
ixp_unpack_qid(&p, &fcall->aqid);
@ -166,11 +166,11 @@ ixp_msg2fcall(Fcall *fcall, void *msg, unsigned int msglen)
case TATTACH:
ixp_unpack_u32(&p, &fcall->fid);
ixp_unpack_u32(&p, &fcall->afid);
ixp_unpack_string(&p, fcall->uname, sizeof(fcall->uname), &len);
ixp_unpack_string(&p, fcall->aname, sizeof(fcall->aname), &len);
ixp_unpack_string(&p, &fcall->uname, &len);
ixp_unpack_string(&p, &fcall->aname, &len);
break;
case RERROR:
ixp_unpack_string(&p, fcall->errstr, sizeof(fcall->errstr), &len);
ixp_unpack_string(&p, &fcall->ename, &len);
break;
case TFLUSH:
ixp_unpack_u16(&p, &fcall->oldtag);
@ -179,7 +179,7 @@ ixp_msg2fcall(Fcall *fcall, void *msg, unsigned int msglen)
ixp_unpack_u32(&p, &fcall->fid);
ixp_unpack_u32(&p, &fcall->newfid);
ixp_unpack_u16(&p, &fcall->nwname);
ixp_unpack_strings(&p, fcall->nwname, &fcall->wname);
ixp_unpack_strings(&p, fcall->nwname, fcall->wname);
break;
case RWALK:
ixp_unpack_u16(&p, &fcall->nwqid);
@ -197,7 +197,7 @@ ixp_msg2fcall(Fcall *fcall, void *msg, unsigned int msglen)
break;
case TCREATE:
ixp_unpack_u32(&p, &fcall->fid);
ixp_unpack_string(&p, fcall->name, sizeof(fcall->name), &len);
ixp_unpack_string(&p, &fcall->name, &len);
ixp_unpack_u32(&p, &fcall->perm);
ixp_unpack_u8(&p, &fcall->mode);
break;
@ -208,13 +208,13 @@ ixp_msg2fcall(Fcall *fcall, void *msg, unsigned int msglen)
break;
case RREAD:
ixp_unpack_u32(&p, &fcall->count);
ixp_unpack_data(&p, fcall->data, fcall->count);
ixp_unpack_data(&p, &fcall->data, fcall->count);
break;
case TWRITE:
ixp_unpack_u32(&p, &fcall->fid);
ixp_unpack_u64(&p, &fcall->offset);
ixp_unpack_u32(&p, &fcall->count);
ixp_unpack_data(&p, fcall->data, fcall->count);
ixp_unpack_data(&p, &fcall->data, fcall->count);
break;
case RWRITE:
ixp_unpack_u32(&p, &fcall->count);
@ -226,12 +226,12 @@ ixp_msg2fcall(Fcall *fcall, void *msg, unsigned int msglen)
break;
case RSTAT:
ixp_unpack_u16(&p, &len);
ixp_unpack_stat(&p, &fcall->stat);
ixp_unpack_data(&p, &fcall->stat, len);
break;
case TWSTAT:
ixp_unpack_u32(&p, &fcall->fid);
ixp_unpack_u16(&p, &len);
ixp_unpack_stat(&p, &fcall->stat);
ixp_unpack_data(&p, &fcall->stat, len);
break;
}

View File

@ -13,28 +13,32 @@ static char
Ebotch[] = "9P protocol botch",
Enofile[] = "file does not exist",
Enofid[] = "fid does not exist",
Enotag[] = "tag does not exist",
Enotdir[] = "not a directory",
Einterrupted[] = "interrupted",
Eisdir[] = "cannot perform operation on a directory";
enum { TAG_BUCKETS = 64,
FID_BUCKETS = 64 };
typedef struct P9Conn {
struct P9Conn {
Intmap tagmap;
void *taghash[TAG_BUCKETS];
Intmap fidmap;
void *fidhash[FID_BUCKETS];
P9Srv *srv;
IXPConn *conn;
unsigned int msize;
unsigned char *buf;
} P9Conn;
};
void *
createfid(Intmap *map, int fid) {
createfid(Intmap *map, int fid, P9Conn *pc) {
Fid *f = cext_emallocz(sizeof(Fid));
f->fid = fid;
f->omode = -1;
f->map = map;
f->conn = pc;
if(caninsertkey(map, fid, f))
return f;
free(f);
@ -67,8 +71,9 @@ ixp_server_handle_fcall(IXPConn *c)
goto Fail;
req = cext_emallocz(sizeof(Req));
req->conn = c;
req->conn = pc;
req->ifcall = fcall;
pc->conn = c;
if(lookupkey(&pc->tagmap, fcall.tag))
return respond(req, Eduptag);
@ -83,7 +88,7 @@ Fail:
static void
ixp_handle_req(Req *r)
{
P9Conn *pc = r->conn->aux;
P9Conn *pc = r->conn;
P9Srv *srv = pc->srv;
switch(r->ifcall.type) {
@ -103,7 +108,7 @@ ixp_handle_req(Req *r)
respond(r, nil);
break;
case TATTACH:
if(!(r->fid = createfid(&pc->fidmap, r->ifcall.fid)))
if(!(r->fid = createfid(&pc->fidmap, r->ifcall.fid, pc)))
return respond(r, Edupfid);
/* attach is a required function */
srv->attach(r);
@ -115,6 +120,13 @@ ixp_handle_req(Req *r)
return respond(r, nil);
srv->clunk(r);
break;
case TFLUSH:
if(!(r->oldreq = lookupkey(&pc->tagmap, r->ifcall.oldtag)))
return respond(r, Enotag);
if(!srv->flush)
return respond(r, Enofunc);
srv->flush(r);
break;
case TCREATE:
if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
return respond(r, Enofid);
@ -167,7 +179,7 @@ ixp_handle_req(Req *r)
if(r->ifcall.nwname && !(r->fid->qid.type&QTDIR))
return respond(r, Enotdir);
if((r->ifcall.fid != r->ifcall.newfid)) {
if(!(r->newfid = createfid(&pc->fidmap, r->ifcall.newfid)))
if(!(r->newfid = createfid(&pc->fidmap, r->ifcall.newfid, pc)))
return respond(r, Edupfid);
}else
r->newfid = r->fid;
@ -190,7 +202,7 @@ ixp_handle_req(Req *r)
void
respond(Req *r, char *error) {
P9Conn *pc = r->conn->aux;
P9Conn *pc = r->conn;
switch(r->ifcall.type) {
default:
if(!error)
@ -238,6 +250,10 @@ respond(Req *r, char *error) {
case TCLUNK:
destroyfid(pc, r->fid->fid);
break;
case TFLUSH:
if((r->oldreq = lookupkey(&pc->tagmap, r->ifcall.oldtag)))
respond(r->oldreq, Einterrupted);
break;
case TREAD:
case TREMOVE:
case TSTAT:
@ -253,8 +269,8 @@ respond(Req *r, char *error) {
r->ofcall.ename = error;
}
/* XXX Check if conn is still open */
ixp_server_respond_fcall(r->conn, &r->ofcall);
if(pc->conn)
ixp_server_respond_fcall(pc->conn, &r->ofcall);
switch(r->ofcall.type) {
case RSTAT:
@ -269,21 +285,55 @@ respond(Req *r, char *error) {
free(r);
}
/* XXX: This cleanup code *needs* to be cleaned up */
static void
ixp_void_request(void *r) {
/* generate flush request */
ixp_void_request(void *t) {
unsigned int tag;
Req *r, *tr;
P9Conn *pc;
r = t;
pc = r->conn;
/* XXX: need a better way of doing this */
for(tag=0; lookupkey(&pc->tagmap, tag); tag++);
tr = cext_emallocz(sizeof(Req));
tr->conn = pc;
tr->ifcall.type = TFLUSH;
tr->ifcall.tag = tag;
tr->ifcall.oldtag = r->ifcall.tag;
ixp_handle_req(tr);
}
static void
ixp_void_fid(void *f) {
/* generate clunk request */
ixp_void_fid(void *t) {
unsigned int tag;
P9Conn *pc;
Req *tr;
Fid *f;
f = t;
pc = f->conn;
/* XXX: need a better way of doing this */
for(tag=0; lookupkey(&pc->tagmap, tag); tag++);
tr = cext_emallocz(sizeof(Req));
tr->fid = f;
tr->conn = pc;
tr->ifcall.type = TCLUNK;
tr->ifcall.tag = tag;
tr->ifcall.fid = f->fid;
ixp_handle_req(tr);
}
static void
ixp_cleanup_conn(IXPConn *c) {
P9Conn *pc = c->aux;
freemap(&pc->tagmap, ixp_void_request);
freemap(&pc->fidmap, ixp_void_fid);
pc->conn = nil;
execmap(&pc->tagmap, ixp_void_request);
freemap(&pc->tagmap, nil);
execmap(&pc->fidmap, ixp_void_fid);
freemap(&pc->fidmap, nil);
free(pc->buf);
free(pc);
}

View File

@ -18,11 +18,13 @@
static unsigned char *msg[IXP_MAX_MSG];
IXPConn *ixp_server_open_conn(IXPServer *s, int fd, void (*read)(IXPConn *c),
void (*close)(IXPConn *c))
IXPConn *
ixp_server_open_conn(IXPServer *s, int fd, void *aux,
void (*read)(IXPConn *c), void (*close)(IXPConn *c))
{
IXPConn *c = cext_emallocz(sizeof(IXPConn));
c->fd = fd;
c->aux = aux;
c->srv = s;
c->read = read;
c->close = close;
@ -36,15 +38,14 @@ ixp_server_close_conn(IXPConn *c)
{
IXPServer *s = c->srv;
IXPConn **tc;
IXPMap *m;
for(tc=&s->conn; *tc && *tc != c; tc=&(*tc)->next);
cext_assert(*tc == c);
*tc = c->next;
while((m = c->map)) {
c->map = m->next;
free(m);
}
shutdown(c->fd, SHUT_RDWR);
c->closed = 1;
if(c->close)
c->close(c);
else
shutdown(c->fd, SHUT_RDWR);
close(c->fd);
free(c);
}
@ -68,7 +69,6 @@ handle_conns(IXPServer *s)
IXPConn **c;
for(c=&s->conn; *c; *c && (c=&(*c)->next))
if(FD_ISSET((*c)->fd, &s->rd) && (*c)->read)
/* call read handler */
(*c)->read(*c);
}
@ -93,22 +93,13 @@ ixp_server_loop(IXPServer *s)
return nil;
}
IXPMap *
ixp_server_fid2map(IXPConn *c, unsigned int fid)
{
IXPMap *m;
for(m=c->map; m && m->fid != fid; m=m->next);
return m;
}
unsigned int
ixp_server_receive_fcall(IXPConn *c, Fcall *fcall)
{
unsigned int msize;
char *errstr = 0;
if(!(msize = ixp_recv_message(c->fd, msg, IXP_MAX_MSG, &errstr))) {
if(c->close)
c->close(c);
ixp_server_close_conn(c);
return 0;
}
return ixp_msg2fcall(fcall, msg, IXP_MAX_MSG);
@ -119,24 +110,10 @@ ixp_server_respond_fcall(IXPConn *c, Fcall *fcall)
{
char *errstr;
unsigned int msize = ixp_fcall2msg(msg, fcall, IXP_MAX_MSG);
if(c->closed)
return 0;
if(ixp_send_message(c->fd, msg, msize, &errstr) != msize) {
if(c->close)
c->close(c);
return -1;
}
return 0;
}
int
ixp_server_respond_error(IXPConn *c, Fcall *fcall, char *errstr)
{
unsigned int msize;
fcall->id = RERROR;
cext_strlcpy(fcall->errstr, errstr, sizeof(fcall->errstr));
msize = ixp_fcall2msg(msg, fcall, IXP_MAX_MSG);
if(ixp_send_message(c->fd, msg, msize, &errstr) != msize) {
if(c->close)
c->close(c);
ixp_server_close_conn(c);
return -1;
}
return 0;
@ -148,7 +125,6 @@ ixp_server_close(IXPServer *s)
IXPConn *c, *next;
for(c=s->conn; c; c=next) {
next=c->next;
if(c->close)
c->close(c);
ixp_server_close_conn(c);
}
}

View File

@ -64,7 +64,7 @@ ixp_recv_message(int fd, void *msg, unsigned int msglen, char **errstr)
if(ixp_recv_data(fd, msg, sizeof(unsigned int), errstr) !=
sizeof(unsigned int))
return 0;
ixp_unpack_u32((unsigned char**)&msg, &msize);
ixp_unpack_u32((void *)&msg, &msize);
if(msize > msglen) {
*errstr = "invalid message header";
return 0;