mirror of
https://github.com/0intro/wmii
synced 2024-11-22 05:42:05 +03:00
reorganized, still liblitz there
This commit is contained in:
parent
b71f8a147e
commit
4a7273b827
2
Makefile
2
Makefile
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
include config.mk
|
include config.mk
|
||||||
|
|
||||||
SUBDIRS = libcext liblitz libixp cmd
|
SUBDIRS = liblitz
|
||||||
|
|
||||||
BIN = cmd/wm/wmii cmd/wm/wmiiwm cmd/wmiir
|
BIN = cmd/wm/wmii cmd/wm/wmiiwm cmd/wmiir
|
||||||
|
|
||||||
|
28
cmd/Makefile
28
cmd/Makefile
@ -1,28 +0,0 @@
|
|||||||
# window manager improved 2 utilities
|
|
||||||
# (C)opyright MMIV-MMVI Anselm R. Garbe
|
|
||||||
|
|
||||||
include ../config.mk
|
|
||||||
|
|
||||||
CFLAGS += -I../liblitz -I../libixp -I../libcext
|
|
||||||
LDFLAGS += -L../libixp -lixp -L../libcext -lcext
|
|
||||||
X11LDFLAGS += -L../liblitz -llitz -L../libcext -lcext
|
|
||||||
|
|
||||||
SRC = wmiir.c
|
|
||||||
ALLSRC = ${SRC}
|
|
||||||
|
|
||||||
all: ${ALLSRC:.c=}
|
|
||||||
@echo built wmii commands
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
@echo CC $<
|
|
||||||
@${CC} -c ${CFLAGS} $<
|
|
||||||
|
|
||||||
${SRC:.c=}: ${SRC:.c=.o}
|
|
||||||
@echo LD $@
|
|
||||||
@${CC} -o $@ $@.o ${LDFLAGS}
|
|
||||||
|
|
||||||
# Solaris
|
|
||||||
# @${CC} -o $* $*.o ${LDFLAGS} -lsocket
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f ${ALLSRC:.c=} *.o
|
|
@ -1,84 +0,0 @@
|
|||||||
.TH WMIIMENU 1 wmii-4
|
|
||||||
.SH NAME
|
|
||||||
wmiimenu \- window manager improved 2 menu
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B wmiimenu
|
|
||||||
.RB [ \-v ]
|
|
||||||
.RB [ \-t
|
|
||||||
.IR title ]
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.SS Overview
|
|
||||||
.B wmiimenu
|
|
||||||
is a generic, highly customizable, and efficient menu for the X Window System,
|
|
||||||
originally designed for
|
|
||||||
.BR wmii (1).
|
|
||||||
It supports arbitrary, user defined menu contents.
|
|
||||||
.SS Options
|
|
||||||
.TP
|
|
||||||
.B \-v
|
|
||||||
prints version information to stdout, then exits.
|
|
||||||
.TP
|
|
||||||
.BI \-t " title"
|
|
||||||
displays
|
|
||||||
.I title
|
|
||||||
above the menu.
|
|
||||||
.SS Usage
|
|
||||||
.B wmiimenu
|
|
||||||
reads a list of newline-separated items from stdin and creates a menu.
|
|
||||||
When the user selects an item or enters any text and presses Enter, his choice
|
|
||||||
is printed to stdout and
|
|
||||||
.B wmiimenu
|
|
||||||
terminates.
|
|
||||||
.SS Keyboard Control
|
|
||||||
.B wmiimenu
|
|
||||||
is completely controlled by the keyboard. The following keys are recognized:
|
|
||||||
.TP 2
|
|
||||||
Any printable character
|
|
||||||
appends the character to the text in the input field. This works as a filter:
|
|
||||||
only items containing this text will be displayed.
|
|
||||||
.TP 2
|
|
||||||
Left/Right (Control-p/Control-n)
|
|
||||||
select the previous/next item.
|
|
||||||
.TP 2
|
|
||||||
Tab (Control-i)
|
|
||||||
copy the selected item to the input field.
|
|
||||||
.TP 2
|
|
||||||
Enter (Control-j)
|
|
||||||
confirm selection and quit (print the selected item to stdout).
|
|
||||||
.TP 2
|
|
||||||
Shift-Enter (Shift-Control-j)
|
|
||||||
confirm selection and quit (print the text in the input field to stdout).
|
|
||||||
.TP 2
|
|
||||||
Escape (Control-[)
|
|
||||||
quit without selecting an item.
|
|
||||||
.TP 2
|
|
||||||
Backspace (Control-h)
|
|
||||||
remove enough characters from the input field to change its filtering effect.
|
|
||||||
.TP 2
|
|
||||||
Control-u
|
|
||||||
remove all characters from the input field.
|
|
||||||
.SS Exit codes
|
|
||||||
.B wmiimenu
|
|
||||||
returns
|
|
||||||
.B 0
|
|
||||||
if Enter is pressed on termination,
|
|
||||||
.B 1
|
|
||||||
if Escape is pressed.
|
|
||||||
.SH ENVIRONMENT
|
|
||||||
.TP
|
|
||||||
WMII_FONT
|
|
||||||
The X11 font used to display each item in the menu.
|
|
||||||
.br
|
|
||||||
Default: fixed
|
|
||||||
.TP
|
|
||||||
WMII_NORMCOLORS
|
|
||||||
The foreground, background, and border colors of a label. Syntactically, three blank-separated color values of the form #RRGGBB are expected.
|
|
||||||
.br
|
|
||||||
Default: #222222 #eeeeee #666666
|
|
||||||
.TP
|
|
||||||
WMII_SELCOLORS
|
|
||||||
Like WMII_NORMCOLORS, but for the selected label.
|
|
||||||
.br
|
|
||||||
Default: #ffffff #335577 #447799
|
|
||||||
.SH SEE ALSO
|
|
||||||
.BR wmii (1)
|
|
86
cmd/wmiir.1
86
cmd/wmiir.1
@ -1,86 +0,0 @@
|
|||||||
.TH WMIIR 1 wmii-4
|
|
||||||
.SH NAME
|
|
||||||
wmiir \- window manager improved 2 remote
|
|
||||||
.SH SYNOPSIS
|
|
||||||
.B wmiir
|
|
||||||
.RB [ \-a
|
|
||||||
.IR address ]
|
|
||||||
.I action
|
|
||||||
.I file
|
|
||||||
.br
|
|
||||||
.B wmiir
|
|
||||||
.B \-v
|
|
||||||
.SH DESCRIPTION
|
|
||||||
.SS Overview
|
|
||||||
.B wmiir
|
|
||||||
is a client to access the filesystem of
|
|
||||||
.BR wmiiwm (1)
|
|
||||||
from the command line or from shell
|
|
||||||
scripts. It can be used to configure
|
|
||||||
.BR wmii (1).
|
|
||||||
.SS Options
|
|
||||||
.TP
|
|
||||||
.BI \-a " address"
|
|
||||||
Lets you specify the address to which
|
|
||||||
.B wmiir
|
|
||||||
will establish a connection. If this option is not supplied, and the
|
|
||||||
environment variable WMII_ADDRESS is set,
|
|
||||||
.B wmiir
|
|
||||||
will use this value as its address. Currently, the address can only be a
|
|
||||||
unix socket file or a tcp socket. The syntax for
|
|
||||||
.I address
|
|
||||||
is taken (along with many other profound ideas) from the Plan 9 operating
|
|
||||||
system and has the form
|
|
||||||
.BR unix!/path/to/socket
|
|
||||||
for unix socket files, and
|
|
||||||
.BR tcp!hostname!port
|
|
||||||
for tcp sockets.
|
|
||||||
.TP
|
|
||||||
.B \-v
|
|
||||||
Prints version information to stdout, then exits.
|
|
||||||
.TP
|
|
||||||
The syntax of the actions is as follows:
|
|
||||||
.TP
|
|
||||||
.B write
|
|
||||||
Writes the supplied data from stdin to
|
|
||||||
.IR file,
|
|
||||||
overwriting any previous data. The data to be written is arbitrary
|
|
||||||
and only gains meaning (and restrictions) when it is interpreted by
|
|
||||||
.BR wmiiwm (1).
|
|
||||||
See
|
|
||||||
.B EXAMPLES
|
|
||||||
below.
|
|
||||||
.TP
|
|
||||||
.B create
|
|
||||||
Creates file or directory but does not write any data. If the file exists,
|
|
||||||
nothing is done.
|
|
||||||
.TP
|
|
||||||
.B read
|
|
||||||
Reads file or directory contents
|
|
||||||
.TP
|
|
||||||
.B remove
|
|
||||||
Removes file or directory tree
|
|
||||||
.SH ENVIRONMENT
|
|
||||||
.TP
|
|
||||||
WMII_ADDRESS
|
|
||||||
See above.
|
|
||||||
.SH EXAMPLES
|
|
||||||
.TP
|
|
||||||
.B wmiir read /
|
|
||||||
This prints the root directory of the wmii filesystem. For more information
|
|
||||||
about the contents of this filesystem, see
|
|
||||||
.BR wmiiwm (1).
|
|
||||||
.TP
|
|
||||||
.B echo -n quit | wmiir write /ctl
|
|
||||||
Write 'quit' to the main control file of the wmii filesystem, effectively
|
|
||||||
leaving wmii.
|
|
||||||
.TP
|
|
||||||
.B echo -n view 2 | wmiir write /ctl
|
|
||||||
Bring into view all clients tagged '2'. To learn about clients and
|
|
||||||
tags, see
|
|
||||||
.BR wmiiwm (1).
|
|
||||||
.SH SEE ALSO
|
|
||||||
.BR wmii (1),
|
|
||||||
.BR wmiiwm (1)
|
|
||||||
|
|
||||||
http://www.cs.bell-labs.com/sys/man/5/INDEX.html
|
|
324
cmd/wmiir.c
324
cmd/wmiir.c
@ -1,324 +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 <dirent.h>
|
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include <ixp.h>
|
|
||||||
|
|
||||||
static IXPClient c = { 0 };
|
|
||||||
|
|
||||||
static char version[] = "wmiir - " VERSION ", (C)opyright MMIV-MMVI Anselm R. Garbe\n";
|
|
||||||
|
|
||||||
static void
|
|
||||||
usage()
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s",
|
|
||||||
"usage: wmiir [-a <address>] [-v] create | read | ls [-l] | remove | write <file>\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_data(unsigned int fid)
|
|
||||||
{
|
|
||||||
void *data = cext_emallocz(c.ofcall.iounit);
|
|
||||||
unsigned long long offset = 0;
|
|
||||||
unsigned int len = 0;
|
|
||||||
|
|
||||||
while((len = read(0, data, c.ofcall.iounit)) > 0) {
|
|
||||||
if(ixp_client_write(&c, fid, offset, len, data) != len) {
|
|
||||||
fprintf(stderr, "wmiir: cannot write file: %s\n", c.errstr);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
offset += len;
|
|
||||||
}
|
|
||||||
if(offset == 0) /* do an explicit empty write when no writing has been done yet */
|
|
||||||
if(ixp_client_write(&c, fid, offset, 0, 0) != 0)
|
|
||||||
fprintf(stderr, "wmiir: cannot write file: %s\n", c.errstr);
|
|
||||||
free(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
xcreate(char *file)
|
|
||||||
{
|
|
||||||
unsigned int fid;
|
|
||||||
char *p = strrchr(file, '/');
|
|
||||||
|
|
||||||
if(!p)
|
|
||||||
p = file;
|
|
||||||
|
|
||||||
fid = c.root_fid << 2;
|
|
||||||
/* walk to bottom-most directory */
|
|
||||||
*p = 0;
|
|
||||||
if(ixp_client_walk(&c, fid, file) == -1) {
|
|
||||||
fprintf(stderr, "wmiir: cannot walk to '%s': %s\n", file, c.errstr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
if(ixp_client_create(&c, fid, p, IXP_DMWRITE, IXP_OWRITE) == -1) {
|
|
||||||
fprintf(stderr, "wmiir: cannot create file '%s': %s\n", p, c.errstr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(!(c.ofcall.qid.type&P9DMDIR))
|
|
||||||
write_data(fid);
|
|
||||||
return ixp_client_close(&c, fid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
xwrite(char *file, unsigned char mode)
|
|
||||||
{
|
|
||||||
/* open */
|
|
||||||
unsigned int fid = c.root_fid << 2;
|
|
||||||
if(ixp_client_walkopen(&c, fid, file, mode) == -1) {
|
|
||||||
fprintf(stderr, "wmiir: cannot open file '%s': %s\n", file, c.errstr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
write_data(fid);
|
|
||||||
return ixp_client_close(&c, fid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
comp_stat(const void *s1, const void *s2)
|
|
||||||
{
|
|
||||||
Stat *st1 = (Stat *)s1;
|
|
||||||
Stat *st2 = (Stat *)s2;
|
|
||||||
return strcmp(st1->name, st2->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
setrwx(long m, char *s)
|
|
||||||
{
|
|
||||||
static char *modes[] =
|
|
||||||
{
|
|
||||||
"---",
|
|
||||||
"--x",
|
|
||||||
"-w-",
|
|
||||||
"-wx",
|
|
||||||
"r--",
|
|
||||||
"r-x",
|
|
||||||
"rw-",
|
|
||||||
"rwx",
|
|
||||||
};
|
|
||||||
strncpy(s, modes[m], 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
str_of_mode(unsigned int mode)
|
|
||||||
{
|
|
||||||
static char buf[16];
|
|
||||||
|
|
||||||
if(mode & IXP_DMDIR)
|
|
||||||
buf[0]='d';
|
|
||||||
else
|
|
||||||
buf[0]='-';
|
|
||||||
|
|
||||||
buf[1]='-';
|
|
||||||
setrwx((mode >> 6) & 7, &buf[2]);
|
|
||||||
setrwx((mode >> 3) & 7, &buf[5]);
|
|
||||||
setrwx((mode >> 0) & 7, &buf[8]);
|
|
||||||
buf[11] = 0;
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
|
||||||
str_of_time(unsigned int val)
|
|
||||||
{
|
|
||||||
static char buf[32];
|
|
||||||
time_t t = (time_t)(int)val;
|
|
||||||
char *tstr = ctime(&t);
|
|
||||||
cext_strlcpy(buf, tstr ? tstr : "in v a l id ", sizeof(buf));
|
|
||||||
buf[strlen(buf) - 1] = 0;
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
print_stat(Stat *s, int details)
|
|
||||||
{
|
|
||||||
if(details)
|
|
||||||
fprintf(stdout, "%s %s %s %5llu %s %s\n", str_of_mode(s->mode),
|
|
||||||
s->uid, s->gid, s->length, str_of_time(s->mtime), s->name);
|
|
||||||
else {
|
|
||||||
if(s->mode & IXP_DMDIR)
|
|
||||||
fprintf(stdout, "%s/\n", s->name);
|
|
||||||
else
|
|
||||||
fprintf(stdout, "%s\n", s->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
xls(void *result, unsigned int msize, int details)
|
|
||||||
{
|
|
||||||
unsigned int n = 0, i = 0;
|
|
||||||
unsigned char *p = result;
|
|
||||||
Stat *dir;
|
|
||||||
static Stat stat;
|
|
||||||
|
|
||||||
do {
|
|
||||||
ixp_unpack_stat(&p, nil, &stat);
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
while(p - (unsigned char*)result < msize);
|
|
||||||
dir = (Stat *)cext_emallocz(sizeof(Stat) * n);
|
|
||||||
p = result;
|
|
||||||
do {
|
|
||||||
ixp_unpack_stat(&p, nil, &dir[i++]);
|
|
||||||
}
|
|
||||||
while(p - (unsigned char*)result < msize);
|
|
||||||
qsort(dir, n, sizeof(Stat), comp_stat);
|
|
||||||
for(i = 0; i < n; i++)
|
|
||||||
print_stat(&dir[i], details);
|
|
||||||
free(dir);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
unsigned long long offset = 0;
|
|
||||||
|
|
||||||
if(ixp_client_stat(&c, fid, file) == -1) {
|
|
||||||
fprintf(stderr, "wmiir: cannot stat file '%s': %s\n", file, c.errstr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
buf = c.ofcall.stat;
|
|
||||||
ixp_unpack_stat(&buf, nil, s);
|
|
||||||
if(!(s->mode & IXP_DMDIR)) {
|
|
||||||
print_stat(s, details);
|
|
||||||
fflush(stdout);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* directory */
|
|
||||||
if(ixp_client_open(&c, fid, IXP_OREAD) == -1) {
|
|
||||||
fprintf(stderr, "wmiir: cannot open directory '%s': %s\n", file, c.errstr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
while((count = ixp_client_read(&c, fid, offset, result, IXP_MAX_MSG)) > 0) {
|
|
||||||
data = cext_erealloc(data, offset + count);
|
|
||||||
memcpy(data + offset, result, count);
|
|
||||||
offset += count;
|
|
||||||
}
|
|
||||||
if(count == -1) {
|
|
||||||
fprintf(stderr, "wmiir: cannot read directory '%s': %s\n", file, c.errstr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(data)
|
|
||||||
xls(data, offset + count, details);
|
|
||||||
return ixp_client_close(&c, fid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
xread(char *file)
|
|
||||||
{
|
|
||||||
unsigned int fid = c.root_fid << 2;
|
|
||||||
int count;
|
|
||||||
static unsigned char result[IXP_MAX_MSG];
|
|
||||||
unsigned long long offset = 0;
|
|
||||||
|
|
||||||
if(ixp_client_walkopen(&c, fid, file, IXP_OREAD) == -1) {
|
|
||||||
fprintf(stderr, "wmiir: cannot open file '%s': %s\n", file, c.errstr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while((count = ixp_client_read(&c, fid, offset, result, IXP_MAX_MSG)) > 0) {
|
|
||||||
write(1, result, count);
|
|
||||||
offset += count;
|
|
||||||
}
|
|
||||||
if(count == -1) {
|
|
||||||
fprintf(stderr, "wmiir: cannot read file/directory '%s': %s\n", file, c.errstr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return ixp_client_close(&c, fid);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
xremove(char *file)
|
|
||||||
{
|
|
||||||
unsigned int fid;
|
|
||||||
|
|
||||||
fid = c.root_fid << 2;
|
|
||||||
if(ixp_client_remove(&c, fid, file) == -1) {
|
|
||||||
fprintf(stderr, "wmiir: cannot remove file '%s': %s\n", file, c.errstr);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int ret = 0, i = 0, details = 0;
|
|
||||||
char *cmd, *file, *address = getenv("WMII_ADDRESS");
|
|
||||||
|
|
||||||
/* command line args */
|
|
||||||
if(argc < 2)
|
|
||||||
usage();
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cmd = argv[argc - 2];
|
|
||||||
file = argv[argc - 1];
|
|
||||||
if((details = !strncmp(cmd, "-l", 3))) {
|
|
||||||
if(argc < 3)
|
|
||||||
usage();
|
|
||||||
if(strncmp(argv[argc - 3], "ls", 3))
|
|
||||||
usage();
|
|
||||||
cmd = argv[argc - 3];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!address) {
|
|
||||||
fprintf(stderr, "%s", "wmiir: error: $WMII_ADDRESS not set\n");
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ixp_client_dial(&c, address, getpid()) == -1) {
|
|
||||||
fprintf(stderr, "wmiir: %s\n", c.errstr);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!strncmp(cmd, "create", 7))
|
|
||||||
ret = xcreate(file);
|
|
||||||
else if(!strncmp(cmd, "ls", 3))
|
|
||||||
ret = xdir(file, details);
|
|
||||||
else if(!strncmp(cmd, "read", 5))
|
|
||||||
ret = xread(file);
|
|
||||||
else if(!strncmp(cmd, "remove", 7))
|
|
||||||
ret = xremove(file);
|
|
||||||
else if(!strncmp(cmd, "write", 6))
|
|
||||||
ret = xwrite(file, IXP_OWRITE);
|
|
||||||
else
|
|
||||||
usage();
|
|
||||||
|
|
||||||
/* close socket */
|
|
||||||
ixp_client_hangup(&c);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
25
doc/Makefile
25
doc/Makefile
@ -1,25 +0,0 @@
|
|||||||
# window manager improved 2 user guide
|
|
||||||
l2h_opts=-local_icons -scalable_fonts -split +1 -subdir -show_section_numbers -address "<br>Last update: $(shell date) by $$USER@$$HOSTNAME"
|
|
||||||
|
|
||||||
SRC = guide_en.tex wmii.tex
|
|
||||||
DVI = ${SRC:.tex=.dvi}
|
|
||||||
PDF = ${SRC:.tex=.pdf}
|
|
||||||
PS = ${SRC:.tex=.ps}
|
|
||||||
HTML = ${SRC:.tex=.html}
|
|
||||||
|
|
||||||
.SUFFIXES: .tex .dvi .pdf .ps .html
|
|
||||||
|
|
||||||
all: ${DVI} ${PDF} #${PS} ${HTML}
|
|
||||||
.tex.dvi:
|
|
||||||
latex -interaction=batchmode $<
|
|
||||||
latex -interaction=batchmode $<
|
|
||||||
.tex.pdf:
|
|
||||||
pdflatex $<
|
|
||||||
pdflatex $<
|
|
||||||
.dvi.ps:
|
|
||||||
dvips -o $@ $<
|
|
||||||
.tex.html:
|
|
||||||
latex2html ${l2h_opts} $<
|
|
||||||
clean:
|
|
||||||
rm -f *.pdf *.ps *.dvi *.log *.aux *.out *.toc
|
|
||||||
rm -rf guide_en
|
|
1005
doc/guide_en.tex
1005
doc/guide_en.tex
File diff suppressed because it is too large
Load Diff
83
doc/wmii.tex
83
doc/wmii.tex
@ -1,83 +0,0 @@
|
|||||||
% (C)opyright 2005 by Anselm R. Garbe
|
|
||||||
\documentclass{article} \usepackage{times} \begin{document}
|
|
||||||
|
|
||||||
\title{Improved GUI concepts for experienced users}
|
|
||||||
|
|
||||||
\author{Anselm R. Garbe\\ \small garbeam at gmail dot com}
|
|
||||||
|
|
||||||
\maketitle \thispagestyle{empty}
|
|
||||||
|
|
||||||
\begin{abstract}
|
|
||||||
This article presents the motivation and concepts of the dynamic
|
|
||||||
window manager wmii and the graphical toolkit liblitz for the
|
|
||||||
\it{X Window System}.
|
|
||||||
\end{abstract}
|
|
||||||
|
|
||||||
|
|
||||||
%-------------------------------------------------------------------------
|
|
||||||
\section{Motivation}
|
|
||||||
|
|
||||||
Most common graphical user interfaces are designed after the WIMP\cite{wimp}
|
|
||||||
paradigm, which has dominated the desktop environment
|
|
||||||
landscape since late 1980s. While research has been done on alternative
|
|
||||||
user interfaces, often the focus targeted more in ease of use and low
|
|
||||||
learning curves for new computer users rather than in efficiency and
|
|
||||||
power of abstraction.
|
|
||||||
|
|
||||||
The main reason has been the economical success of computers
|
|
||||||
in the normal consumer market, which consists of unexperienced users mainly.
|
|
||||||
Our motivation is to change this situation and to provide a graphical
|
|
||||||
user interface for experienced users, though we know that this market is
|
|
||||||
a niche.
|
|
||||||
|
|
||||||
There has been done rarly research in the non-wimp GUI landscape for years.
|
|
||||||
Back in 80s and early 90s there has been some research in
|
|
||||||
this area for the Plan 9\cite{plan9} operating system at Bell Labs.
|
|
||||||
Most recent research has been done by individuals only, like Tuomo Valkonen with
|
|
||||||
his Ion\cite{ion} project and Lars Bernhardsson with his
|
|
||||||
LarsWM\cite{larswm} project.
|
|
||||||
|
|
||||||
The approaches found in the Plan 9 operating system are interesting, because
|
|
||||||
on the one hand they cancelled the Unix tradition to work in Teletype emulators
|
|
||||||
and on the other hand, they didn't followed the WIMP paradigm propagated by Apple,
|
|
||||||
IBM or Microsoft. This makes Plan 9 the most unique approach compared to the
|
|
||||||
classical WIMP world.
|
|
||||||
|
|
||||||
The main aspects of an improved GUI consists of two things, a powerful
|
|
||||||
window management approach and a sane and simple widget set which fits well
|
|
||||||
into this window management approach.
|
|
||||||
|
|
||||||
In the area of improved window management concepts there has been done more
|
|
||||||
research, thus there appeared several different approaches. But the area
|
|
||||||
of improved widget sets which form powerful applications with a simple widget
|
|
||||||
set has been ignored for long time. Instead, the WIMP world introduced many
|
|
||||||
widgets which seem to focus on eye-candy, like progress bars, but don't
|
|
||||||
fix the essential problems with WIMP toolkits.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\section{Future}
|
|
||||||
|
|
||||||
|
|
||||||
\section*{Acknowlegdements} Following people provided useful feedback or several
|
|
||||||
grammar fixes to this article:
|
|
||||||
\begin{itemize}
|
|
||||||
\item Frank Boehme (1st version of this article)
|
|
||||||
\item Tuncer M zayamut Ayaz (1st version of this article)
|
|
||||||
\end{itemize}
|
|
||||||
|
|
||||||
\begin{thebibliography}{99}
|
|
||||||
\bibitem{wimp} Ashley George Taylor, WIMP Interfaces, CS6751 Topic Report: Winter '97
|
|
||||||
\bibitem{x} X Window System - http://www.freedesktop.org
|
|
||||||
\bibitem{plan9} plan9 operating system - http://cm.bell-labs.com/plan9dist/
|
|
||||||
\bibitem{acme} Rob Pike, Acme: A User Interface for Programmers -
|
|
||||||
http://www.cs.bell-labs.com/sys/doc/acme/acme.html
|
|
||||||
\bibitem{rat} Ratpoison window manager - http://www.nongnu.org/ratpoison/
|
|
||||||
\bibitem{evil} evilwm window manager - http://evilwm.sf.net
|
|
||||||
\bibitem{ion} Ion window manager - http://modeemi.cs.tut.fi/~tuomov/ion/
|
|
||||||
\bibitem{larswm} LarsWM window manager - http://www.fnurt.net/larswm/
|
|
||||||
\bibitem{vi} Vi Improved (VIM) - http://www.vim.org
|
|
||||||
\bibitem{9p} 9P protocol - http://www.cs.bell-labs.com/sys/man/5/INDEX.html
|
|
||||||
\end{thebibliography}
|
|
||||||
|
|
||||||
\end{document}
|
|
@ -1,28 +0,0 @@
|
|||||||
# libcext - c extensions for wmii project
|
|
||||||
# (C)opyright MMIV-MMVI Anselm R. Garbe
|
|
||||||
|
|
||||||
include ../config.mk
|
|
||||||
|
|
||||||
SRC = assert.c malloc.c strlcat.c strlcpy.c tokenize.c \
|
|
||||||
trim.c
|
|
||||||
|
|
||||||
OBJ = ${SRC:.c=.o}
|
|
||||||
|
|
||||||
.PREFIXES = .c .o
|
|
||||||
|
|
||||||
all: libcext.a
|
|
||||||
@echo built libcext
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
@echo CC $<
|
|
||||||
@${CC} -c ${CFLAGS} $<
|
|
||||||
|
|
||||||
$(OBJ): cext.h
|
|
||||||
|
|
||||||
libcext.a: ${OBJ}
|
|
||||||
@echo AR $@
|
|
||||||
@${AR} $@ ${OBJ}
|
|
||||||
@${RANLIB} $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f libcext.a *.o
|
|
@ -1,10 +0,0 @@
|
|||||||
/* Public Domain */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
void
|
|
||||||
cext_failed_assert(char *a, char *file, int line)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Assertion \"%s\" failed at %s:%d\n", a, file, line);
|
|
||||||
abort();
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
|
||||||
* See LICENSE file for license details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#ifndef nil
|
|
||||||
#define nil (void *)0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* asprintf.c */
|
|
||||||
extern int cext_asprintf(char **str, char const *fmt, ...);
|
|
||||||
|
|
||||||
/* malloc.c */
|
|
||||||
extern void *cext_emallocz(unsigned int size);
|
|
||||||
extern void *cext_emalloc(unsigned int size);
|
|
||||||
extern void *cext_erealloc(void *ptr, unsigned int size);
|
|
||||||
extern char *cext_estrdup(const char *str);
|
|
||||||
|
|
||||||
/* strlcat.c */
|
|
||||||
extern unsigned int cext_strlcat(char *dst, const char *src, unsigned int siz);
|
|
||||||
|
|
||||||
/* strlcpy.c */
|
|
||||||
extern unsigned int cext_strlcpy(char *dst, const char *src, unsigned int siz);
|
|
||||||
|
|
||||||
/* tokenize.c */
|
|
||||||
extern unsigned int cext_tokenize(char **result, unsigned int reslen, char *str, char delim);
|
|
||||||
|
|
||||||
/* trim.c */
|
|
||||||
extern void cext_trim(char *str, const char *chars);
|
|
||||||
|
|
||||||
/* assert.c */
|
|
||||||
#define cext_assert(a) do { \
|
|
||||||
if(!(a)) \
|
|
||||||
cext_failed_assert(#a, __FILE__, __LINE__); \
|
|
||||||
} while (0)
|
|
||||||
extern void cext_failed_assert(char *a, char *file, int line);
|
|
@ -1,54 +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 "cext.h"
|
|
||||||
|
|
||||||
static void
|
|
||||||
bad_malloc(unsigned int size)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "fatal: could not malloc() %d bytes\n",
|
|
||||||
(int) size);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
cext_emallocz(unsigned int size)
|
|
||||||
{
|
|
||||||
void *res = calloc(1, size);
|
|
||||||
if(!res)
|
|
||||||
bad_malloc(size);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
cext_emalloc(unsigned int size)
|
|
||||||
{
|
|
||||||
void *res = malloc(size);
|
|
||||||
if(!res)
|
|
||||||
bad_malloc(size);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
cext_erealloc(void *ptr, unsigned int size)
|
|
||||||
{
|
|
||||||
void *res = realloc(ptr, size);
|
|
||||||
if(!res)
|
|
||||||
bad_malloc(size);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
cext_estrdup(const char *str)
|
|
||||||
{
|
|
||||||
void *res = strdup(str);
|
|
||||||
if(!res)
|
|
||||||
bad_malloc(strlen(str));
|
|
||||||
return res;
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "cext.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Appends src to string dst of size siz (unlike strncat, siz is the
|
|
||||||
* full size of dst, not space left). At most siz-1 characters
|
|
||||||
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
|
|
||||||
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
|
|
||||||
* If retval >= siz, truncation occurred.
|
|
||||||
*/
|
|
||||||
unsigned int
|
|
||||||
cext_strlcat(char *dst, const char *src, unsigned int siz)
|
|
||||||
{
|
|
||||||
register char *d = dst;
|
|
||||||
register const char *s = src;
|
|
||||||
register unsigned int n = siz;
|
|
||||||
unsigned int dlen;
|
|
||||||
|
|
||||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
|
||||||
while(n-- != 0 && *d != 0)
|
|
||||||
d++;
|
|
||||||
dlen = d - dst;
|
|
||||||
n = siz - dlen;
|
|
||||||
|
|
||||||
if(n == 0)
|
|
||||||
return (dlen + strlen(s));
|
|
||||||
while(*s != 0) {
|
|
||||||
if(n != 1) {
|
|
||||||
*d++ = *s;
|
|
||||||
n--;
|
|
||||||
}
|
|
||||||
s++;
|
|
||||||
}
|
|
||||||
*d = 0;
|
|
||||||
|
|
||||||
return (dlen + (s - src)); /* count does not include NUL */
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include "cext.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy src to string dst of size siz. At most siz-1 characters
|
|
||||||
* will be copied. Always NUL terminates (unless siz == 0).
|
|
||||||
* Returns strlen(src); if retval >= siz, truncation occurred.
|
|
||||||
*/
|
|
||||||
unsigned int
|
|
||||||
cext_strlcpy(char *dst, const char *src, unsigned int siz)
|
|
||||||
{
|
|
||||||
register char *d = dst;
|
|
||||||
register const char *s = src;
|
|
||||||
register unsigned int n = siz;
|
|
||||||
|
|
||||||
/* Copy as many bytes as will fit */
|
|
||||||
if(n != 0 && --n != 0) {
|
|
||||||
do {
|
|
||||||
if((*d++ = *s++) == 0)
|
|
||||||
break;
|
|
||||||
} while(--n != 0);
|
|
||||||
}
|
|
||||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
|
||||||
if(n == 0) {
|
|
||||||
if(siz != 0)
|
|
||||||
*d = '\0'; /* NUL-terminate dst */
|
|
||||||
while(*s++);
|
|
||||||
}
|
|
||||||
return (s - src - 1); /* count does not include NUL */
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
|
||||||
* See LICENSE file for license details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "cext.h"
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
cext_tokenize(char **result, unsigned int reslen, char *str, char delim)
|
|
||||||
{
|
|
||||||
char *p, *n;
|
|
||||||
unsigned int i = 0;
|
|
||||||
|
|
||||||
if(!str)
|
|
||||||
return 0;
|
|
||||||
for(n = str; *n == delim; n++);
|
|
||||||
p = n;
|
|
||||||
for(i = 0; *n != 0;) {
|
|
||||||
if(i == reslen)
|
|
||||||
return i;
|
|
||||||
if(*n == delim) {
|
|
||||||
*n = 0;
|
|
||||||
if(strlen(p))
|
|
||||||
result[i++] = p;
|
|
||||||
p = ++n;
|
|
||||||
} else
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
if((i < reslen) && (p < n) && strlen(p))
|
|
||||||
result[i++] = p;
|
|
||||||
return i; /* number of tokens */
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) MMVI Anselm R. Garbe <arg@suckless.org>
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice appear in all copies.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "cext.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Removes all characters in chars from str.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
cext_trim(char *str, const char *chars)
|
|
||||||
{
|
|
||||||
const char *cp;
|
|
||||||
char *sp, *sn;
|
|
||||||
|
|
||||||
for(cp = chars; *cp; cp++) {
|
|
||||||
for(sp = sn = str; *sn; sn++) {
|
|
||||||
if(*sn != *cp)
|
|
||||||
*(sp++) = *sn;
|
|
||||||
}
|
|
||||||
*sp = 0;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
# libixp - lib ixp protocol
|
|
||||||
# (C)opyright MMIV-MMVI Anselm R. Garbe
|
|
||||||
|
|
||||||
include ../config.mk
|
|
||||||
|
|
||||||
CFLAGS += -I ../libcext
|
|
||||||
|
|
||||||
SRC = client.c convert.c message.c server.c socket.c transport.c intmap.c request.c
|
|
||||||
|
|
||||||
OBJ = ${SRC:.c=.o}
|
|
||||||
|
|
||||||
all: libixp.a
|
|
||||||
@echo built libixp
|
|
||||||
|
|
||||||
.c.o:
|
|
||||||
@echo CC $<
|
|
||||||
@${CC} -c ${CFLAGS} $<
|
|
||||||
|
|
||||||
libixp.a: ${OBJ}
|
|
||||||
@echo AR $@
|
|
||||||
@${AR} $@ ${OBJ}
|
|
||||||
@${RANLIB} $@
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f libixp.a *.o
|
|
220
libixp/client.c
220
libixp/client.c
@ -1,220 +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 <sys/socket.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "ixp.h"
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_client_do_fcall(IXPClient *c)
|
|
||||||
{
|
|
||||||
static unsigned char msg[IXP_MAX_MSG];
|
|
||||||
unsigned int msize = ixp_fcall2msg(msg, &c->ifcall, IXP_MAX_MSG);
|
|
||||||
|
|
||||||
c->errstr = 0;
|
|
||||||
if(ixp_send_message(c->fd, msg, msize, &c->errstr) != msize)
|
|
||||||
return -1;
|
|
||||||
if(!ixp_recv_message(c->fd, msg, IXP_MAX_MSG, &c->errstr))
|
|
||||||
return -1;
|
|
||||||
if(!(msize = ixp_msg2fcall(&c->ofcall, msg, IXP_MAX_MSG))) {
|
|
||||||
c->errstr = "received bad message";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(c->ofcall.type == RERROR) {
|
|
||||||
c->errstr = c->ofcall.ename;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_client_dial(IXPClient *c, char *sockfile, unsigned int rootfid)
|
|
||||||
{
|
|
||||||
|
|
||||||
if((c->fd = ixp_connect_sock(sockfile)) < 0) {
|
|
||||||
c->errstr = "cannot connect server";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
c->ifcall.type = TVERSION;
|
|
||||||
c->ifcall.tag = IXP_NOTAG;
|
|
||||||
c->ifcall.msize = IXP_MAX_MSG;
|
|
||||||
c->ifcall.version = IXP_VERSION;
|
|
||||||
if(ixp_client_do_fcall(c) == -1) {
|
|
||||||
fprintf(stderr, "error: %s\n", c->errstr);
|
|
||||||
ixp_client_hangup(c);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(strncmp(c->ofcall.version, IXP_VERSION, strlen(IXP_VERSION))) {
|
|
||||||
fprintf(stderr, "error: %s\n", c->errstr);
|
|
||||||
c->errstr = "9P versions differ";
|
|
||||||
ixp_client_hangup(c);
|
|
||||||
return -1; /* we cannot handle this version */
|
|
||||||
}
|
|
||||||
free(c->ofcall.version);
|
|
||||||
c->root_fid = rootfid;
|
|
||||||
|
|
||||||
c->ifcall.type = TATTACH;
|
|
||||||
c->ifcall.tag = IXP_NOTAG;
|
|
||||||
c->ifcall.fid = c->root_fid;
|
|
||||||
c->ifcall.afid = IXP_NOFID;
|
|
||||||
c->ifcall.uname = getenv("USER");
|
|
||||||
c->ifcall.aname = "";
|
|
||||||
if(ixp_client_do_fcall(c) == -1) {
|
|
||||||
fprintf(stderr, "error: %s\n", c->errstr);
|
|
||||||
ixp_client_hangup(c);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
c->root_qid = c->ofcall.qid;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_client_remove(IXPClient *c, unsigned int newfid, char *filepath)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(ixp_client_walk(c, newfid, filepath) == -1)
|
|
||||||
return -1;
|
|
||||||
c->ifcall.type = TREMOVE;
|
|
||||||
c->ifcall.tag = IXP_NOTAG;
|
|
||||||
c->ifcall.fid = newfid;
|
|
||||||
|
|
||||||
return ixp_client_do_fcall(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_client_create(IXPClient *c, unsigned int dirfid, char *name,
|
|
||||||
unsigned int perm, unsigned char mode)
|
|
||||||
{
|
|
||||||
c->ifcall.type = TCREATE;
|
|
||||||
c->ifcall.tag = IXP_NOTAG;
|
|
||||||
c->ifcall.fid = dirfid;
|
|
||||||
c->ifcall.name = name;
|
|
||||||
c->ifcall.perm = perm;
|
|
||||||
c->ifcall.mode = mode;
|
|
||||||
return ixp_client_do_fcall(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_client_walk(IXPClient *c, unsigned int newfid, char *filepath)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
char *wname[IXP_MAX_WELEM];
|
|
||||||
|
|
||||||
c->ifcall.type = TWALK;
|
|
||||||
c->ifcall.fid = c->root_fid;
|
|
||||||
c->ifcall.newfid = newfid;
|
|
||||||
if(filepath) {
|
|
||||||
c->ifcall.name = filepath;
|
|
||||||
c->ifcall.nwname =
|
|
||||||
cext_tokenize(wname, IXP_MAX_WELEM, c->ifcall.name, '/');
|
|
||||||
for(i = 0; i < c->ifcall.nwname; i++)
|
|
||||||
c->ifcall.wname[i] = wname[i];
|
|
||||||
}
|
|
||||||
return ixp_client_do_fcall(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_client_stat(IXPClient *c, unsigned int newfid, char *filepath)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(ixp_client_walk(c, newfid, filepath) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
c->ifcall.type = TSTAT;
|
|
||||||
c->ifcall.tag = IXP_NOTAG;
|
|
||||||
c->ifcall.fid = newfid;
|
|
||||||
return ixp_client_do_fcall(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_client_open(IXPClient *c, unsigned int newfid, unsigned char mode)
|
|
||||||
{
|
|
||||||
|
|
||||||
c->ifcall.type = TOPEN;
|
|
||||||
c->ifcall.tag = IXP_NOTAG;
|
|
||||||
c->ifcall.fid = newfid;
|
|
||||||
c->ifcall.mode = mode;
|
|
||||||
return ixp_client_do_fcall(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_client_walkopen(IXPClient *c, unsigned int newfid, char *filepath,
|
|
||||||
unsigned char mode)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(ixp_client_walk(c, newfid, filepath) == -1)
|
|
||||||
return -1;
|
|
||||||
return ixp_client_open(c, newfid, mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_client_read(IXPClient *c, unsigned int fid, unsigned long long offset,
|
|
||||||
void *result, unsigned int res_len)
|
|
||||||
{
|
|
||||||
unsigned int bytes = c->ofcall.iounit;
|
|
||||||
|
|
||||||
c->ifcall.type = TREAD;
|
|
||||||
c->ifcall.tag = IXP_NOTAG;
|
|
||||||
c->ifcall.fid = fid;
|
|
||||||
c->ifcall.offset = offset;
|
|
||||||
c->ifcall.count = res_len < bytes ? res_len : bytes;
|
|
||||||
if(ixp_client_do_fcall(c) == -1)
|
|
||||||
return -1;
|
|
||||||
memcpy(result, c->ofcall.data, c->ofcall.count);
|
|
||||||
free(c->ofcall.data);
|
|
||||||
|
|
||||||
return c->ofcall.count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_client_write(IXPClient *c, unsigned int fid,
|
|
||||||
unsigned long long offset, unsigned int count,
|
|
||||||
unsigned char *data)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(count > c->ofcall.iounit) {
|
|
||||||
c->errstr = "iounit exceeded";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
c->ifcall.type = TWRITE;
|
|
||||||
c->ifcall.tag = IXP_NOTAG;
|
|
||||||
c->ifcall.fid = fid;
|
|
||||||
c->ifcall.offset = offset;
|
|
||||||
c->ifcall.count = count;
|
|
||||||
c->ifcall.data = (void *)data;
|
|
||||||
if(ixp_client_do_fcall(c) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return c->ofcall.count;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_client_close(IXPClient *c, unsigned int fid)
|
|
||||||
{
|
|
||||||
|
|
||||||
c->ifcall.type = TCLUNK;
|
|
||||||
c->ifcall.tag = IXP_NOTAG;
|
|
||||||
c->ifcall.fid = fid;
|
|
||||||
return ixp_client_do_fcall(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_client_hangup(IXPClient *c)
|
|
||||||
{
|
|
||||||
/* session finished, now shutdown */
|
|
||||||
if(c->fd) {
|
|
||||||
shutdown(c->fd, SHUT_RDWR);
|
|
||||||
close(c->fd);
|
|
||||||
}
|
|
||||||
}
|
|
236
libixp/convert.c
236
libixp/convert.c
@ -1,236 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
|
||||||
* See LICENSE file for license details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include "ixp.h"
|
|
||||||
|
|
||||||
/* packode/unpackode stuff */
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_pack_u8(unsigned char **msg, int *msize, unsigned char val)
|
|
||||||
{
|
|
||||||
if(!msize || (*msize -= 1) >= 0)
|
|
||||||
*(*msg)++ = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_unpack_u8(unsigned char **msg, int *msize, unsigned char *val)
|
|
||||||
{
|
|
||||||
if(!msize || (*msize -= 1) >= 0)
|
|
||||||
*val = *(*msg)++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_pack_u16(unsigned char **msg, int *msize, unsigned short val)
|
|
||||||
{
|
|
||||||
if(!msize || (*msize -= 2) >= 0) {
|
|
||||||
*(*msg)++ = val;
|
|
||||||
*(*msg)++ = val >> 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_unpack_u16(unsigned char **msg, int *msize, unsigned short *val)
|
|
||||||
{
|
|
||||||
if(!msize || (*msize -= 2) >= 0) {
|
|
||||||
*val = *(*msg)++;
|
|
||||||
*val |= *(*msg)++ << 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_pack_u32(unsigned char **msg, int *msize, unsigned int val)
|
|
||||||
{
|
|
||||||
if(!msize || (*msize -= 4) >= 0) {
|
|
||||||
*(*msg)++ = val;
|
|
||||||
*(*msg)++ = val >> 8;
|
|
||||||
*(*msg)++ = val >> 16;
|
|
||||||
*(*msg)++ = val >> 24;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_unpack_u32(unsigned char **msg, int *msize, unsigned int *val)
|
|
||||||
{
|
|
||||||
if(!msize || (*msize -= 4) >= 0) {
|
|
||||||
*val = *(*msg)++;
|
|
||||||
*val |= *(*msg)++ << 8;
|
|
||||||
*val |= *(*msg)++ << 16;
|
|
||||||
*val |= *(*msg)++ << 24;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_pack_u64(unsigned char **msg, int *msize, unsigned long long val)
|
|
||||||
{
|
|
||||||
if(!msize || (*msize -= 8) >= 0) {
|
|
||||||
*(*msg)++ = val;
|
|
||||||
*(*msg)++ = val >> 8;
|
|
||||||
*(*msg)++ = val >> 16;
|
|
||||||
*(*msg)++ = val >> 24;
|
|
||||||
*(*msg)++ = val >> 32;
|
|
||||||
*(*msg)++ = val >> 40;
|
|
||||||
*(*msg)++ = val >> 48;
|
|
||||||
*(*msg)++ = val >> 56;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_unpack_u64(unsigned char **msg, int *msize, unsigned long long *val)
|
|
||||||
{
|
|
||||||
if(!msize || (*msize -= 8) >= 0) {
|
|
||||||
*val |= *(*msg)++;
|
|
||||||
*val |= *(*msg)++ << 8;
|
|
||||||
*val |= *(*msg)++ << 16;
|
|
||||||
*val |= *(*msg)++ << 24;
|
|
||||||
*val |= (unsigned long long)*(*msg)++ << 32;
|
|
||||||
*val |= (unsigned long long)*(*msg)++ << 40;
|
|
||||||
*val |= (unsigned long long)*(*msg)++ << 48;
|
|
||||||
*val |= (unsigned long long)*(*msg)++ << 56;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_pack_string(unsigned char **msg, int *msize, const char *s)
|
|
||||||
{
|
|
||||||
unsigned short len = s ? strlen(s) : 0;
|
|
||||||
ixp_pack_u16(msg, msize, len);
|
|
||||||
if(s)
|
|
||||||
ixp_pack_data(msg, msize, (void *)s, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_unpack_strings(unsigned char **msg, int *msize, unsigned short n, char **strings) {
|
|
||||||
unsigned char *s = *msg;
|
|
||||||
unsigned int i, size = 0;
|
|
||||||
unsigned short len;
|
|
||||||
for(i=0; i<n; i++) {
|
|
||||||
ixp_unpack_u16(&s, msize, &len);
|
|
||||||
s += len;
|
|
||||||
size += len + 1; /* for '\0' */
|
|
||||||
}
|
|
||||||
if(!size) {
|
|
||||||
/* So we don't try to free some random value */
|
|
||||||
*strings = nil;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
s = cext_emalloc(size);
|
|
||||||
for(i=0; i < n; i++) {
|
|
||||||
ixp_unpack_u16(msg, msize, &len);
|
|
||||||
if(!msize || (*msize -= len) < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
memcpy(s, *msg, len);
|
|
||||||
s[len] = '\0';
|
|
||||||
strings[i] = (char *)s;
|
|
||||||
*msg += len;
|
|
||||||
s += len + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_unpack_string(unsigned char **msg, int *msize, char **string, unsigned short *len)
|
|
||||||
{
|
|
||||||
ixp_unpack_u16(msg, msize, len);
|
|
||||||
*string = nil;
|
|
||||||
if (!msize || (*msize -= *len) >= 0) {
|
|
||||||
*string = cext_emalloc(*len+1);
|
|
||||||
if(*len)
|
|
||||||
memcpy(*string, *msg, *len);
|
|
||||||
(*string)[*len] = 0;
|
|
||||||
*msg += *len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_pack_data(unsigned char **msg, int *msize, unsigned char *data, unsigned int datalen)
|
|
||||||
{
|
|
||||||
if(!msize || (*msize -= datalen) >= 0) {
|
|
||||||
memcpy(*msg, data, datalen);
|
|
||||||
*msg += datalen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_unpack_data(unsigned char **msg, int *msize, unsigned char **data, unsigned int datalen)
|
|
||||||
{
|
|
||||||
if(!msize || (*msize -= datalen) >= 0) {
|
|
||||||
*data = cext_emallocz(datalen);
|
|
||||||
memcpy(*data, *msg, datalen);
|
|
||||||
*msg += datalen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_pack_prefix(unsigned char *msg, unsigned int size, unsigned char id,
|
|
||||||
unsigned short tag)
|
|
||||||
{
|
|
||||||
ixp_pack_u32(&msg, 0, size);
|
|
||||||
ixp_pack_u8(&msg, 0, id);
|
|
||||||
ixp_pack_u16(&msg, 0, tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_unpack_prefix(unsigned char **msg, unsigned int *size, unsigned char *id,
|
|
||||||
unsigned short *tag)
|
|
||||||
{
|
|
||||||
int msize;
|
|
||||||
ixp_unpack_u32(msg, nil, size);
|
|
||||||
msize = *size;
|
|
||||||
ixp_unpack_u8(msg, &msize, id);
|
|
||||||
ixp_unpack_u16(msg, &msize, tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_pack_qid(unsigned char **msg, int *msize, Qid * qid)
|
|
||||||
{
|
|
||||||
ixp_pack_u8(msg, msize, qid->type);
|
|
||||||
ixp_pack_u32(msg, msize, qid->version);
|
|
||||||
ixp_pack_u64(msg, msize, qid->path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_unpack_qid(unsigned char **msg, int *msize, Qid * qid)
|
|
||||||
{
|
|
||||||
ixp_unpack_u8(msg, msize, &qid->type);
|
|
||||||
ixp_unpack_u32(msg, msize, &qid->version);
|
|
||||||
ixp_unpack_u64(msg, msize, &qid->path);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_pack_stat(unsigned char **msg, int *msize, Stat * stat)
|
|
||||||
{
|
|
||||||
ixp_pack_u16(msg, msize, ixp_sizeof_stat(stat) - sizeof(unsigned short));
|
|
||||||
ixp_pack_u16(msg, msize, stat->type);
|
|
||||||
ixp_pack_u32(msg, msize, stat->dev);
|
|
||||||
ixp_pack_qid(msg, msize, &stat->qid);
|
|
||||||
ixp_pack_u32(msg, msize, stat->mode);
|
|
||||||
ixp_pack_u32(msg, msize, stat->atime);
|
|
||||||
ixp_pack_u32(msg, msize, stat->mtime);
|
|
||||||
ixp_pack_u64(msg, msize, stat->length);
|
|
||||||
ixp_pack_string(msg, msize, stat->name);
|
|
||||||
ixp_pack_string(msg, msize, stat->uid);
|
|
||||||
ixp_pack_string(msg, msize, stat->gid);
|
|
||||||
ixp_pack_string(msg, msize, stat->muid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_unpack_stat(unsigned char **msg, int *msize, Stat * stat)
|
|
||||||
{
|
|
||||||
unsigned short dummy;
|
|
||||||
*msg += sizeof(unsigned short);
|
|
||||||
ixp_unpack_u16(msg, msize, &stat->type);
|
|
||||||
ixp_unpack_u32(msg, msize, &stat->dev);
|
|
||||||
ixp_unpack_qid(msg, msize, &stat->qid);
|
|
||||||
ixp_unpack_u32(msg, msize, &stat->mode);
|
|
||||||
ixp_unpack_u32(msg, msize, &stat->atime);
|
|
||||||
ixp_unpack_u32(msg, msize, &stat->mtime);
|
|
||||||
ixp_unpack_u64(msg, msize, &stat->length);
|
|
||||||
ixp_unpack_string(msg, msize, &stat->name, &dummy);
|
|
||||||
ixp_unpack_string(msg, msize, &stat->uid, &dummy);
|
|
||||||
ixp_unpack_string(msg, msize, &stat->gid, &dummy);
|
|
||||||
ixp_unpack_string(msg, msize, &stat->muid, &dummy);
|
|
||||||
}
|
|
144
libixp/intmap.c
144
libixp/intmap.c
@ -1,144 +0,0 @@
|
|||||||
/* 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) if(v){}else{}
|
|
||||||
|
|
||||||
struct Intlist {
|
|
||||||
unsigned long id;
|
|
||||||
void* aux;
|
|
||||||
Intlist* link;
|
|
||||||
unsigned int ref;
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned long
|
|
||||||
hashid(Intmap *map, unsigned long id)
|
|
||||||
{
|
|
||||||
return id%map->nhash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
nop(void *v)
|
|
||||||
{
|
|
||||||
USED(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
initmap(Intmap *m, unsigned long nhash, void *hash)
|
|
||||||
{
|
|
||||||
m->nhash = nhash;
|
|
||||||
m->hash = hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Intlist**
|
|
||||||
llookup(Intmap *map, unsigned long id)
|
|
||||||
{
|
|
||||||
Intlist **lf;
|
|
||||||
|
|
||||||
for(lf=&map->hash[hashid(map, id)]; *lf; lf=&(*lf)->link)
|
|
||||||
if((*lf)->id == id)
|
|
||||||
break;
|
|
||||||
return lf;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
freemap(Intmap *map, void (*destroy)(void*))
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
Intlist *p, *nlink;
|
|
||||||
|
|
||||||
if(destroy == nil)
|
|
||||||
destroy = nop;
|
|
||||||
for(i=0; i<map->nhash; i++){
|
|
||||||
for(p=map->hash[i]; p; p=nlink){
|
|
||||||
nlink = p->link;
|
|
||||||
destroy(p->aux);
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
Intlist *f;
|
|
||||||
void *v;
|
|
||||||
|
|
||||||
if((f = *llookup(map, id)))
|
|
||||||
v = f->aux;
|
|
||||||
else
|
|
||||||
v = nil;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
|
||||||
insertkey(Intmap *map, unsigned long id, void *v)
|
|
||||||
{
|
|
||||||
Intlist *f;
|
|
||||||
void *ov;
|
|
||||||
unsigned long h;
|
|
||||||
|
|
||||||
if((f = *llookup(map, id))){
|
|
||||||
/* no decrement for ov because we're returning it */
|
|
||||||
ov = f->aux;
|
|
||||||
f->aux = v;
|
|
||||||
}else{
|
|
||||||
f = cext_emallocz(sizeof(*f));
|
|
||||||
f->id = id;
|
|
||||||
f->aux = v;
|
|
||||||
h = hashid(map, id);
|
|
||||||
f->link = map->hash[h];
|
|
||||||
map->hash[h] = f;
|
|
||||||
ov = nil;
|
|
||||||
}
|
|
||||||
return ov;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
caninsertkey(Intmap *map, unsigned long id, void *v)
|
|
||||||
{
|
|
||||||
Intlist *f;
|
|
||||||
int rv;
|
|
||||||
unsigned long h;
|
|
||||||
|
|
||||||
if(*llookup(map, id))
|
|
||||||
rv = 0;
|
|
||||||
else{
|
|
||||||
f = cext_emallocz(sizeof *f);
|
|
||||||
f->id = id;
|
|
||||||
f->aux = v;
|
|
||||||
h = hashid(map, id);
|
|
||||||
f->link = map->hash[h];
|
|
||||||
map->hash[h] = f;
|
|
||||||
rv = 1;
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
void*
|
|
||||||
deletekey(Intmap *map, unsigned long id)
|
|
||||||
{
|
|
||||||
Intlist **lf, *f;
|
|
||||||
void *ov;
|
|
||||||
|
|
||||||
if((f = *(lf = llookup(map, id)))){
|
|
||||||
ov = f->aux;
|
|
||||||
*lf = f->link;
|
|
||||||
free(f);
|
|
||||||
}else
|
|
||||||
ov = nil;
|
|
||||||
return ov;
|
|
||||||
}
|
|
369
libixp/ixp.h
369
libixp/ixp.h
@ -1,369 +0,0 @@
|
|||||||
/*
|
|
||||||
*(C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
|
||||||
*See LICENSE file for license details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <cext.h>
|
|
||||||
|
|
||||||
#define IXP_VERSION "9P2000"
|
|
||||||
#define IXP_NOTAG (unsigned short)~0U /*Dummy tag */
|
|
||||||
#define IXP_NOFID (unsigned int)~0 /*No auth */
|
|
||||||
|
|
||||||
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,
|
|
||||||
RVERSION,
|
|
||||||
TAUTH = 102,
|
|
||||||
RAUTH,
|
|
||||||
TATTACH = 104,
|
|
||||||
RATTACH,
|
|
||||||
TERROR = 106, /* illegal */
|
|
||||||
RERROR,
|
|
||||||
TFLUSH = 108,
|
|
||||||
RFLUSH,
|
|
||||||
TWALK = 110,
|
|
||||||
RWALK,
|
|
||||||
TOPEN = 112,
|
|
||||||
ROPEN,
|
|
||||||
TCREATE = 114,
|
|
||||||
RCREATE,
|
|
||||||
TREAD = 116,
|
|
||||||
RREAD,
|
|
||||||
TWRITE = 118,
|
|
||||||
RWRITE,
|
|
||||||
TCLUNK = 120,
|
|
||||||
RCLUNK,
|
|
||||||
TREMOVE = 122,
|
|
||||||
RREMOVE,
|
|
||||||
TSTAT = 124,
|
|
||||||
RSTAT,
|
|
||||||
TWSTAT = 126,
|
|
||||||
RWSTAT,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* borrowed from libc.h of Plan 9 */
|
|
||||||
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 */
|
|
||||||
IXP_DMAUTH = 0x08000000, /* mode bit for authentication file */
|
|
||||||
IXP_DMTMP = 0x04000000, /* mode bit for non-backed-up file */
|
|
||||||
IXP_DMREAD = 0x4<<6, /* mode bit for read permission */
|
|
||||||
IXP_DMWRITE = 0x2<<6, /* mode bit for write permission */
|
|
||||||
IXP_DMEXEC = 0x1<<6 /* mode bit for execute permission */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* modes */
|
|
||||||
enum { IXP_OREAD = 0x00,
|
|
||||||
IXP_OWRITE = 0x01,
|
|
||||||
IXP_ORDWR = 0x02,
|
|
||||||
IXP_OEXEC = 0x03,
|
|
||||||
IXP_OEXCL = 0x04,
|
|
||||||
IXP_OTRUNC = 0x10,
|
|
||||||
IXP_OREXEC = 0x20,
|
|
||||||
IXP_ORCLOSE = 0x40,
|
|
||||||
IXP_OAPPEND = 0x80,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* qid.types */
|
|
||||||
enum { IXP_QTDIR = 0x80,
|
|
||||||
IXP_QTAPPEND = 0x40,
|
|
||||||
IXP_QTEXCL = 0x20,
|
|
||||||
IXP_QTMOUNT = 0x10,
|
|
||||||
IXP_QTAUTH = 0x08,
|
|
||||||
IXP_QTTMP = 0x04,
|
|
||||||
IXP_QTSYMLINK = 0x02,
|
|
||||||
IXP_QTLINK = 0x01,
|
|
||||||
IXP_QTFILE = 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* from libc.h in p9p */
|
|
||||||
enum { P9OREAD = 0, /* open for read */
|
|
||||||
P9OWRITE = 1, /* write */
|
|
||||||
P9ORDWR = 2, /* read and write */
|
|
||||||
P9OEXEC = 3, /* execute, == read but check execute permission */
|
|
||||||
P9OTRUNC = 16, /* or'ed in (except for exec), truncate file first */
|
|
||||||
P9OCEXEC = 32, /* or'ed in, close on exec */
|
|
||||||
P9ORCLOSE = 64, /* or'ed in, remove on close */
|
|
||||||
P9ODIRECT = 128, /* or'ed in, direct access */
|
|
||||||
P9ONONBLOCK = 256, /* or'ed in, non-blocking call */
|
|
||||||
P9OEXCL = 0x1000, /* or'ed in, exclusive use (create only) */
|
|
||||||
P9OLOCK = 0x2000, /* or'ed in, lock after opening */
|
|
||||||
P9OAPPEND = 0x4000 /* or'ed in, append only */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* bits in Qid.type */
|
|
||||||
enum { P9QTDIR = 0x80, /* type bit for directories */
|
|
||||||
P9QTAPPEND = 0x40, /* type bit for append only files */
|
|
||||||
P9QTEXCL = 0x20, /* type bit for exclusive use files */
|
|
||||||
P9QTMOUNT = 0x10, /* type bit for mounted channel */
|
|
||||||
P9QTAUTH = 0x08, /* type bit for authentication file */
|
|
||||||
P9QTTMP = 0x04, /* type bit for non-backed-up file */
|
|
||||||
P9QTSYMLINK = 0x02, /* type bit for symbolic link */
|
|
||||||
P9QTFILE = 0x00 /* type bits for plain file */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* bits in Dir.mode */
|
|
||||||
#define P9DMDIR 0x80000000 /* mode bit for directories */
|
|
||||||
#define P9DMAPPEND 0x40000000 /* mode bit for append only files */
|
|
||||||
#define P9DMEXCL 0x20000000 /* mode bit for exclusive use files */
|
|
||||||
#define P9DMMOUNT 0x10000000 /* mode bit for mounted channel */
|
|
||||||
#define P9DMAUTH 0x08000000 /* mode bit for authentication file */
|
|
||||||
#define P9DMTMP 0x04000000 /* mode bit for non-backed-up file */
|
|
||||||
#define P9DMSYMLINK 0x02000000 /* mode bit for symbolic link (Unix, 9P2000.u) */
|
|
||||||
#define P9DMDEVICE 0x00800000 /* mode bit for device file (Unix, 9P2000.u) */
|
|
||||||
#define P9DMNAMEDPIPE 0x00200000 /* mode bit for named pipe (Unix, 9P2000.u) */
|
|
||||||
#define P9DMSOCKET 0x00100000 /* mode bit for socket (Unix, 9P2000.u) */
|
|
||||||
#define P9DMSETUID 0x00080000 /* mode bit for setuid (Unix, 9P2000.u) */
|
|
||||||
#define P9DMSETGID 0x00040000 /* mode bit for setgid (Unix, 9P2000.u) */
|
|
||||||
|
|
||||||
enum { P9DMREAD = 0x4, /* mode bit for read permission */
|
|
||||||
P9DMWRITE = 0x2, /* mode bit for write permission */
|
|
||||||
P9DMEXEC = 0x1 /* mode bit for execute permission */
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct Qid Qid;
|
|
||||||
struct Qid {
|
|
||||||
unsigned char type;
|
|
||||||
unsigned int version;
|
|
||||||
unsigned long long path;
|
|
||||||
/* internal use only */
|
|
||||||
unsigned char dir_type;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* stat structure */
|
|
||||||
typedef struct Stat {
|
|
||||||
unsigned short type;
|
|
||||||
unsigned int dev;
|
|
||||||
Qid qid;
|
|
||||||
unsigned int mode;
|
|
||||||
unsigned int atime;
|
|
||||||
unsigned int mtime;
|
|
||||||
unsigned long long length;
|
|
||||||
char *name;
|
|
||||||
char *uid;
|
|
||||||
char *gid;
|
|
||||||
char *muid;
|
|
||||||
} Stat;
|
|
||||||
|
|
||||||
/* from fcall(3) in plan9port */
|
|
||||||
typedef struct Fcall {
|
|
||||||
unsigned char type;
|
|
||||||
unsigned short tag;
|
|
||||||
unsigned int fid;
|
|
||||||
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 */
|
|
||||||
unsigned long long offset; /* +Tread */
|
|
||||||
/* +Rread */
|
|
||||||
unsigned int count; /* +Tread */
|
|
||||||
char *data;
|
|
||||||
};
|
|
||||||
struct { /* Twstat, Rstat */
|
|
||||||
unsigned short nstat;
|
|
||||||
unsigned char *stat;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
} Fcall;
|
|
||||||
|
|
||||||
typedef struct IXPServer IXPServer;
|
|
||||||
typedef struct IXPConn IXPConn;
|
|
||||||
typedef struct Intmap Intmap;
|
|
||||||
|
|
||||||
typedef struct Intlist Intlist;
|
|
||||||
struct Intmap {
|
|
||||||
unsigned long nhash;
|
|
||||||
Intlist **hash;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IXPConn {
|
|
||||||
IXPServer *srv;
|
|
||||||
void *aux;
|
|
||||||
int fd;
|
|
||||||
void (*read) (IXPConn *);
|
|
||||||
void (*close) (IXPConn *);
|
|
||||||
char closed;
|
|
||||||
|
|
||||||
/* Implementation details */
|
|
||||||
/* do not use */
|
|
||||||
IXPConn *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IXPServer {
|
|
||||||
int running;
|
|
||||||
IXPConn *conn;
|
|
||||||
int maxfd;
|
|
||||||
fd_set rd;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct IXPClient {
|
|
||||||
int fd;
|
|
||||||
unsigned int root_fid;
|
|
||||||
Qid root_qid;
|
|
||||||
Fcall ifcall;
|
|
||||||
Fcall ofcall;
|
|
||||||
char *errstr;
|
|
||||||
} IXPClient;
|
|
||||||
|
|
||||||
typedef struct P9Conn P9Conn;
|
|
||||||
typedef struct Fid {
|
|
||||||
P9Conn *conn;
|
|
||||||
Intmap *map;
|
|
||||||
char *uid;
|
|
||||||
void *aux;
|
|
||||||
unsigned long fid;
|
|
||||||
Qid qid;
|
|
||||||
signed char omode;
|
|
||||||
} Fid;
|
|
||||||
|
|
||||||
typedef struct P9Req P9Req;
|
|
||||||
struct P9Req {
|
|
||||||
P9Conn *conn;
|
|
||||||
Fid *fid;
|
|
||||||
Fid *newfid;
|
|
||||||
P9Req *oldreq;
|
|
||||||
Fcall ifcall;
|
|
||||||
Fcall ofcall;
|
|
||||||
void *aux;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct P9Srv {
|
|
||||||
void (*attach)(P9Req *r);
|
|
||||||
void (*clunk)(P9Req *r);
|
|
||||||
void (*create)(P9Req *r);
|
|
||||||
void (*flush)(P9Req *r);
|
|
||||||
void (*open)(P9Req *r);
|
|
||||||
void (*read)(P9Req *r);
|
|
||||||
void (*remove)(P9Req *r);
|
|
||||||
void (*stat)(P9Req *r);
|
|
||||||
void (*walk)(P9Req *r);
|
|
||||||
void (*write)(P9Req *r);
|
|
||||||
void (*freefid)(Fid *f);
|
|
||||||
} P9Srv;
|
|
||||||
|
|
||||||
/* client.c */
|
|
||||||
extern int ixp_client_dial(IXPClient *c, char *address, unsigned int rootfid);
|
|
||||||
extern void ixp_client_hangup(IXPClient *c);
|
|
||||||
extern int ixp_client_remove(IXPClient *c, unsigned int newfid, char *filepath);
|
|
||||||
extern int ixp_client_create(IXPClient *c, unsigned int dirfid, char *name,
|
|
||||||
unsigned int perm, unsigned char mode);
|
|
||||||
extern int ixp_client_walk(IXPClient *c, unsigned int newfid, char *filepath);
|
|
||||||
extern int ixp_client_stat(IXPClient *c, unsigned int newfid, char *filepath);
|
|
||||||
extern int ixp_client_walkopen(IXPClient *c, unsigned int newfid, char *filepath,
|
|
||||||
unsigned char mode);
|
|
||||||
extern int ixp_client_open(IXPClient *c, unsigned int newfid, unsigned char mode);
|
|
||||||
extern int ixp_client_read(IXPClient *c, unsigned int fid,
|
|
||||||
unsigned long long offset, void *result,
|
|
||||||
unsigned int res_len);
|
|
||||||
extern int ixp_client_write(IXPClient *c, unsigned int fid,
|
|
||||||
unsigned long long offset,
|
|
||||||
unsigned int count, unsigned char *data);
|
|
||||||
extern int ixp_client_close(IXPClient *c, unsigned int fid);
|
|
||||||
extern int ixp_client_do_fcall(IXPClient * c);
|
|
||||||
|
|
||||||
/* convert.c */
|
|
||||||
extern void ixp_pack_u8(unsigned char **msg, int *msize, unsigned char val);
|
|
||||||
extern void ixp_unpack_u8(unsigned char **msg, int *msize, unsigned char *val);
|
|
||||||
extern void ixp_pack_u16(unsigned char **msg, int *msize, unsigned short val);
|
|
||||||
extern void ixp_unpack_u16(unsigned char **msg, int *msize, unsigned short *val);
|
|
||||||
extern void ixp_pack_u32(unsigned char **msg, int *msize, unsigned int val);
|
|
||||||
extern void ixp_unpack_u32(unsigned char **msg, int *msize, unsigned int *val);
|
|
||||||
extern void ixp_pack_u64(unsigned char **msg, int *msize, unsigned long long val);
|
|
||||||
extern void ixp_unpack_u64(unsigned char **msg, int *msize, unsigned long long *val);
|
|
||||||
extern void ixp_pack_string(unsigned char **msg, int *msize, const char *s);
|
|
||||||
extern void ixp_unpack_strings(unsigned char **msg, int *msize, unsigned short n, char **strings);
|
|
||||||
extern void ixp_unpack_string(unsigned char **msg, int *msize, char **string, unsigned short *len);
|
|
||||||
extern void ixp_pack_data(unsigned char **msg, int *msize, unsigned char *data,
|
|
||||||
unsigned int datalen);
|
|
||||||
extern void ixp_unpack_data(unsigned char **msg, int *msize, unsigned char **data,
|
|
||||||
unsigned int datalen);
|
|
||||||
extern void ixp_pack_prefix(unsigned char *msg, unsigned int size,
|
|
||||||
unsigned char id, unsigned short tag);
|
|
||||||
extern void ixp_unpack_prefix(unsigned char **msg, unsigned int *size,
|
|
||||||
unsigned char *id, unsigned short *tag);
|
|
||||||
extern void ixp_pack_qid(unsigned char **msg, int *msize, Qid *qid);
|
|
||||||
extern void ixp_unpack_qid(unsigned char **msg, int *msize, Qid *qid);
|
|
||||||
extern void ixp_pack_stat(unsigned char **msg, int *msize, Stat *stat);
|
|
||||||
extern void ixp_unpack_stat(unsigned char **msg, int *msize, Stat *stat);
|
|
||||||
|
|
||||||
/* request.c */
|
|
||||||
extern void respond(P9Req *r, char *error);
|
|
||||||
extern void serve_9pcon(IXPConn *c);
|
|
||||||
|
|
||||||
/* intmap.c */
|
|
||||||
extern void initmap(Intmap *m, unsigned long nhash, void *hash);
|
|
||||||
extern void incref_map(Intmap *m);
|
|
||||||
extern void decref_map(Intmap *m);
|
|
||||||
extern void freemap(Intmap *map, void (*destroy)(void*));
|
|
||||||
extern void execmap(Intmap *map, void (*destroy)(void*));
|
|
||||||
extern void* lookupkey(Intmap *map, unsigned long id);
|
|
||||||
extern void* insertkey(Intmap *map, unsigned long id, void *v);
|
|
||||||
extern int caninsertkey(Intmap *map, unsigned long id, void *v);
|
|
||||||
extern void* deletekey(Intmap *map, unsigned long id);
|
|
||||||
|
|
||||||
/* message.c */
|
|
||||||
extern unsigned short ixp_sizeof_stat(Stat *stat);
|
|
||||||
extern unsigned int ixp_fcall2msg(void *msg, Fcall *fcall, unsigned int msglen);
|
|
||||||
extern unsigned int ixp_msg2fcall(Fcall *call, void *msg, unsigned int msglen);
|
|
||||||
|
|
||||||
/* server.c */
|
|
||||||
extern IXPConn *ixp_server_open_conn(IXPServer *s, int fd, void *aux,
|
|
||||||
void (*read)(IXPConn *c), void (*close)(IXPConn *c));
|
|
||||||
extern void ixp_server_close_conn(IXPConn *c);
|
|
||||||
extern char *ixp_server_loop(IXPServer *s);
|
|
||||||
extern unsigned int ixp_server_receive_fcall(IXPConn *c, Fcall *fcall);
|
|
||||||
extern int ixp_server_respond_fcall(IXPConn *c, Fcall *fcall);
|
|
||||||
extern int ixp_server_respond_error(IXPConn *c, Fcall *fcall, char *errstr);
|
|
||||||
extern void ixp_server_close(IXPServer *s);
|
|
||||||
|
|
||||||
/* socket.c */
|
|
||||||
extern int ixp_connect_sock(char *address);
|
|
||||||
extern int ixp_create_sock(char *address, char **errstr);
|
|
||||||
|
|
||||||
/* transport.c */
|
|
||||||
extern unsigned int ixp_send_message(int fd, void *msg, unsigned int msize, char **errstr);
|
|
||||||
extern unsigned int ixp_recv_message(int fd, void *msg, unsigned int msglen, char **errstr);
|
|
243
libixp/message.c
243
libixp/message.c
@ -1,243 +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 "ixp.h"
|
|
||||||
|
|
||||||
#define IXP_QIDSZ (sizeof(unsigned char) + sizeof(unsigned int)\
|
|
||||||
+ sizeof(unsigned long long))
|
|
||||||
|
|
||||||
static unsigned short
|
|
||||||
sizeof_string(const char *s)
|
|
||||||
{
|
|
||||||
return sizeof(unsigned short) + strlen(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned short
|
|
||||||
ixp_sizeof_stat(Stat * stat)
|
|
||||||
{
|
|
||||||
return IXP_QIDSZ
|
|
||||||
+ 2 * sizeof(unsigned short)
|
|
||||||
+ 4 * sizeof(unsigned int)
|
|
||||||
+ sizeof(unsigned long long)
|
|
||||||
+ sizeof_string(stat->name)
|
|
||||||
+ sizeof_string(stat->uid)
|
|
||||||
+ sizeof_string(stat->gid)
|
|
||||||
+ sizeof_string(stat->muid);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
ixp_fcall2msg(void *msg, Fcall *fcall, unsigned int msglen)
|
|
||||||
{
|
|
||||||
unsigned int i = sizeof(unsigned char) +
|
|
||||||
sizeof(unsigned short) + sizeof(unsigned int);
|
|
||||||
int msize = msglen - i;
|
|
||||||
unsigned char *p = msg + i;
|
|
||||||
|
|
||||||
switch (fcall->type) {
|
|
||||||
case TVERSION:
|
|
||||||
case RVERSION:
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->msize);
|
|
||||||
ixp_pack_string(&p, &msize, fcall->version);
|
|
||||||
break;
|
|
||||||
case TAUTH:
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->afid);
|
|
||||||
ixp_pack_string(&p, &msize, fcall->uname);
|
|
||||||
ixp_pack_string(&p, &msize, fcall->aname);
|
|
||||||
break;
|
|
||||||
case RAUTH:
|
|
||||||
ixp_pack_qid(&p, &msize, &fcall->aqid);
|
|
||||||
break;
|
|
||||||
case RATTACH:
|
|
||||||
ixp_pack_qid(&p, &msize, &fcall->qid);
|
|
||||||
break;
|
|
||||||
case TATTACH:
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->fid);
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->afid);
|
|
||||||
ixp_pack_string(&p, &msize, fcall->uname);
|
|
||||||
ixp_pack_string(&p, &msize, fcall->aname);
|
|
||||||
break;
|
|
||||||
case RERROR:
|
|
||||||
ixp_pack_string(&p, &msize, fcall->ename);
|
|
||||||
break;
|
|
||||||
case TFLUSH:
|
|
||||||
ixp_pack_u16(&p, &msize, fcall->oldtag);
|
|
||||||
break;
|
|
||||||
case TWALK:
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->fid);
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->newfid);
|
|
||||||
ixp_pack_u16(&p, &msize, fcall->nwname);
|
|
||||||
for(i = 0; i < fcall->nwname; i++)
|
|
||||||
ixp_pack_string(&p, &msize, fcall->wname[i]);
|
|
||||||
break;
|
|
||||||
case RWALK:
|
|
||||||
ixp_pack_u16(&p, &msize, fcall->nwqid);
|
|
||||||
for(i = 0; i < fcall->nwqid; i++)
|
|
||||||
ixp_pack_qid(&p, &msize, &fcall->wqid[i]);
|
|
||||||
break;
|
|
||||||
case TOPEN:
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->fid);
|
|
||||||
ixp_pack_u8(&p, &msize, fcall->mode);
|
|
||||||
break;
|
|
||||||
case ROPEN:
|
|
||||||
case RCREATE:
|
|
||||||
ixp_pack_qid(&p, &msize, &fcall->qid);
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->iounit);
|
|
||||||
break;
|
|
||||||
case TCREATE:
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->fid);
|
|
||||||
ixp_pack_string(&p, &msize, fcall->name);
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->perm);
|
|
||||||
ixp_pack_u8(&p, &msize, fcall->mode);
|
|
||||||
break;
|
|
||||||
case TREAD:
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->fid);
|
|
||||||
ixp_pack_u64(&p, &msize, fcall->offset);
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->count);
|
|
||||||
break;
|
|
||||||
case RREAD:
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->count);
|
|
||||||
ixp_pack_data(&p, &msize, (unsigned char *)fcall->data, fcall->count);
|
|
||||||
break;
|
|
||||||
case TWRITE:
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->fid);
|
|
||||||
ixp_pack_u64(&p, &msize, fcall->offset);
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->count);
|
|
||||||
ixp_pack_data(&p, &msize, (unsigned char *)fcall->data, fcall->count);
|
|
||||||
break;
|
|
||||||
case RWRITE:
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->count);
|
|
||||||
break;
|
|
||||||
case TCLUNK:
|
|
||||||
case TREMOVE:
|
|
||||||
case TSTAT:
|
|
||||||
ixp_pack_u32(&p, &msize, fcall->fid);
|
|
||||||
break;
|
|
||||||
case RSTAT:
|
|
||||||
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, fcall->nstat);
|
|
||||||
ixp_pack_data(&p, &msize, fcall->stat, fcall->nstat);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(msize < 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
msize = msglen - msize;
|
|
||||||
ixp_pack_prefix(msg, msize, fcall->type, fcall->tag);
|
|
||||||
return msize;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
ixp_msg2fcall(Fcall *fcall, void *msg, unsigned int msglen)
|
|
||||||
{
|
|
||||||
int msize;
|
|
||||||
unsigned int i, tsize;
|
|
||||||
unsigned short len;
|
|
||||||
unsigned char *p = msg;
|
|
||||||
ixp_unpack_prefix(&p, (unsigned int *)&msize, &fcall->type, &fcall->tag);
|
|
||||||
tsize = msize;
|
|
||||||
|
|
||||||
if(msize > msglen) /* bad message */
|
|
||||||
return 0;
|
|
||||||
switch (fcall->type) {
|
|
||||||
case TVERSION:
|
|
||||||
case RVERSION:
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->msize);
|
|
||||||
ixp_unpack_string(&p, &msize, &fcall->version, &len);
|
|
||||||
break;
|
|
||||||
case TAUTH:
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->afid);
|
|
||||||
ixp_unpack_string(&p, &msize, &fcall->uname, &len);
|
|
||||||
ixp_unpack_string(&p, &msize, &fcall->aname, &len);
|
|
||||||
break;
|
|
||||||
case RAUTH:
|
|
||||||
ixp_unpack_qid(&p, &msize, &fcall->aqid);
|
|
||||||
break;
|
|
||||||
case RATTACH:
|
|
||||||
ixp_unpack_qid(&p, &msize, &fcall->qid);
|
|
||||||
break;
|
|
||||||
case TATTACH:
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->fid);
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->afid);
|
|
||||||
ixp_unpack_string(&p, &msize, &fcall->uname, &len);
|
|
||||||
ixp_unpack_string(&p, &msize, &fcall->aname, &len);
|
|
||||||
break;
|
|
||||||
case RERROR:
|
|
||||||
ixp_unpack_string(&p, &msize, &fcall->ename, &len);
|
|
||||||
break;
|
|
||||||
case TFLUSH:
|
|
||||||
ixp_unpack_u16(&p, &msize, &fcall->oldtag);
|
|
||||||
break;
|
|
||||||
case TWALK:
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->fid);
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->newfid);
|
|
||||||
ixp_unpack_u16(&p, &msize, &fcall->nwname);
|
|
||||||
ixp_unpack_strings(&p, &msize, fcall->nwname, fcall->wname);
|
|
||||||
break;
|
|
||||||
case RWALK:
|
|
||||||
ixp_unpack_u16(&p, &msize, &fcall->nwqid);
|
|
||||||
for(i = 0; i < fcall->nwqid; i++)
|
|
||||||
ixp_unpack_qid(&p, &msize, &fcall->wqid[i]);
|
|
||||||
break;
|
|
||||||
case TOPEN:
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->fid);
|
|
||||||
ixp_unpack_u8(&p, &msize, &fcall->mode);
|
|
||||||
break;
|
|
||||||
case ROPEN:
|
|
||||||
case RCREATE:
|
|
||||||
ixp_unpack_qid(&p, &msize, &fcall->qid);
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->iounit);
|
|
||||||
break;
|
|
||||||
case TCREATE:
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->fid);
|
|
||||||
ixp_unpack_string(&p, &msize, &fcall->name, &len);
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->perm);
|
|
||||||
ixp_unpack_u8(&p, &msize, &fcall->mode);
|
|
||||||
break;
|
|
||||||
case TREAD:
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->fid);
|
|
||||||
ixp_unpack_u64(&p, &msize, &fcall->offset);
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->count);
|
|
||||||
break;
|
|
||||||
case RREAD:
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->count);
|
|
||||||
ixp_unpack_data(&p, &msize, (void *)&fcall->data, fcall->count);
|
|
||||||
break;
|
|
||||||
case TWRITE:
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->fid);
|
|
||||||
ixp_unpack_u64(&p, &msize, &fcall->offset);
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->count);
|
|
||||||
ixp_unpack_data(&p, &msize, (void *)&fcall->data, fcall->count);
|
|
||||||
break;
|
|
||||||
case RWRITE:
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->count);
|
|
||||||
break;
|
|
||||||
case TCLUNK:
|
|
||||||
case TREMOVE:
|
|
||||||
case TSTAT:
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->fid);
|
|
||||||
break;
|
|
||||||
case RSTAT:
|
|
||||||
ixp_unpack_u16(&p, &msize, &len);
|
|
||||||
ixp_unpack_data(&p, &msize, &fcall->stat, len);
|
|
||||||
break;
|
|
||||||
case TWSTAT:
|
|
||||||
ixp_unpack_u32(&p, &msize, &fcall->fid);
|
|
||||||
ixp_unpack_u16(&p, &msize, &len);
|
|
||||||
ixp_unpack_data(&p, &msize, &fcall->stat, len);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(msize > 0)
|
|
||||||
return tsize;
|
|
||||||
return 0;
|
|
||||||
}
|
|
394
libixp/request.c
394
libixp/request.c
@ -1,394 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C)opyright MMVI Kris Maglione <fbsdaemon at gmail dot com>
|
|
||||||
* See LICENSE file for license details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include "ixp.h"
|
|
||||||
|
|
||||||
static void ixp_handle_req(P9Req *r);
|
|
||||||
|
|
||||||
/* We use string literals rather than arrays here because
|
|
||||||
* they're allocated in a readonly section */
|
|
||||||
static char
|
|
||||||
*Eduptag = "tag in use",
|
|
||||||
*Edupfid = "fid in use",
|
|
||||||
*Enofunc = "function not implemented",
|
|
||||||
*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 };
|
|
||||||
|
|
||||||
struct P9Conn {
|
|
||||||
Intmap tagmap;
|
|
||||||
void *taghash[TAG_BUCKETS];
|
|
||||||
Intmap fidmap;
|
|
||||||
void *fidhash[FID_BUCKETS];
|
|
||||||
P9Srv *srv;
|
|
||||||
IXPConn *conn;
|
|
||||||
unsigned int msize;
|
|
||||||
unsigned char *buf;
|
|
||||||
unsigned int ref;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_p9conn(P9Conn *pc) {
|
|
||||||
free(pc->buf);
|
|
||||||
free(pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *
|
|
||||||
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);
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
destroyfid(P9Conn *pc, unsigned long fid) {
|
|
||||||
Fid *f;
|
|
||||||
if(!(f = deletekey(&pc->fidmap, fid)))
|
|
||||||
return 0;
|
|
||||||
if(pc->srv->freefid)
|
|
||||||
pc->srv->freefid(f);
|
|
||||||
free(f);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_server_handle_fcall(IXPConn *c)
|
|
||||||
{
|
|
||||||
Fcall fcall = {0};
|
|
||||||
P9Conn *pc = c->aux;
|
|
||||||
P9Req *req;
|
|
||||||
unsigned int msize;
|
|
||||||
char *errstr = nil;
|
|
||||||
|
|
||||||
if(!(msize = ixp_recv_message(c->fd, pc->buf, pc->msize, &errstr)))
|
|
||||||
goto Fail;
|
|
||||||
if(!(msize = ixp_msg2fcall(&fcall, pc->buf, IXP_MAX_MSG)))
|
|
||||||
goto Fail;
|
|
||||||
|
|
||||||
req = cext_emallocz(sizeof(P9Req));
|
|
||||||
req->conn = pc;
|
|
||||||
req->ifcall = fcall;
|
|
||||||
pc->conn = c;
|
|
||||||
|
|
||||||
if(lookupkey(&pc->tagmap, fcall.tag))
|
|
||||||
return respond(req, Eduptag);
|
|
||||||
|
|
||||||
insertkey(&pc->tagmap, fcall.tag, req);
|
|
||||||
return ixp_handle_req(req);
|
|
||||||
|
|
||||||
Fail:
|
|
||||||
ixp_server_close_conn(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ixp_handle_req(P9Req *r)
|
|
||||||
{
|
|
||||||
P9Conn *pc = r->conn;
|
|
||||||
P9Srv *srv = pc->srv;
|
|
||||||
|
|
||||||
switch(r->ifcall.type) {
|
|
||||||
default:
|
|
||||||
respond(r, Enofunc);
|
|
||||||
break;
|
|
||||||
case TVERSION:
|
|
||||||
if(!strncmp(r->ifcall.version, "9P", 3)) {
|
|
||||||
r->ofcall.version = "9P";
|
|
||||||
}else
|
|
||||||
if(!strncmp(r->ifcall.version, "9P2000", 7)) {
|
|
||||||
r->ofcall.version = "9P2000";
|
|
||||||
}else{
|
|
||||||
r->ofcall.version = "unknown";
|
|
||||||
}
|
|
||||||
r->ofcall.msize = r->ifcall.msize;
|
|
||||||
respond(r, nil);
|
|
||||||
break;
|
|
||||||
case TATTACH:
|
|
||||||
if(!(r->fid = createfid(&pc->fidmap, r->ifcall.fid, pc)))
|
|
||||||
return respond(r, Edupfid);
|
|
||||||
/* attach is a required function */
|
|
||||||
srv->attach(r);
|
|
||||||
break;
|
|
||||||
case TCLUNK:
|
|
||||||
if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
|
|
||||||
return respond(r, Enofid);
|
|
||||||
if(!srv->clunk)
|
|
||||||
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);
|
|
||||||
if(r->fid->omode != -1)
|
|
||||||
return respond(r, Ebotch);
|
|
||||||
if(!(r->fid->qid.type&P9QTDIR))
|
|
||||||
return respond(r, Enotdir);
|
|
||||||
if(!pc->srv->create)
|
|
||||||
return respond(r, Enofunc);
|
|
||||||
pc->srv->create(r);
|
|
||||||
break;
|
|
||||||
case TOPEN:
|
|
||||||
if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
|
|
||||||
return respond(r, Enofid);
|
|
||||||
if((r->fid->qid.type&P9QTDIR) && (r->ifcall.mode|P9ORCLOSE) != (P9OREAD|P9ORCLOSE))
|
|
||||||
return respond(r, Eisdir);
|
|
||||||
r->ofcall.qid = r->fid->qid;
|
|
||||||
if(!pc->srv->open)
|
|
||||||
return respond(r, Enofunc);
|
|
||||||
pc->srv->open(r);
|
|
||||||
break;
|
|
||||||
case TREAD:
|
|
||||||
if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
|
|
||||||
return respond(r, Enofid);
|
|
||||||
if(r->fid->omode == -1 || r->fid->omode == P9OWRITE)
|
|
||||||
return respond(r, Ebotch);
|
|
||||||
if(!pc->srv->read)
|
|
||||||
return respond(r, Enofunc);
|
|
||||||
pc->srv->read(r);
|
|
||||||
break;
|
|
||||||
case TREMOVE:
|
|
||||||
if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
|
|
||||||
return respond(r, Enofid);
|
|
||||||
if(!pc->srv->remove)
|
|
||||||
return respond(r, Enofunc);
|
|
||||||
pc->srv->remove(r);
|
|
||||||
break;
|
|
||||||
case TSTAT:
|
|
||||||
if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
|
|
||||||
return respond(r, Enofid);
|
|
||||||
if(!pc->srv->stat)
|
|
||||||
return respond(r, Enofunc);
|
|
||||||
pc->srv->stat(r);
|
|
||||||
break;
|
|
||||||
case TWALK:
|
|
||||||
if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
|
|
||||||
return respond(r, Enofid);
|
|
||||||
if(r->fid->omode != -1)
|
|
||||||
return respond(r, "cannot walk from an open fid");
|
|
||||||
if(r->ifcall.nwname && !(r->fid->qid.type&P9QTDIR))
|
|
||||||
return respond(r, Enotdir);
|
|
||||||
if((r->ifcall.fid != r->ifcall.newfid)) {
|
|
||||||
if(!(r->newfid = createfid(&pc->fidmap, r->ifcall.newfid, pc)))
|
|
||||||
return respond(r, Edupfid);
|
|
||||||
}else
|
|
||||||
r->newfid = r->fid;
|
|
||||||
if(!pc->srv->walk)
|
|
||||||
return respond(r, Enofunc);
|
|
||||||
pc->srv->walk(r);
|
|
||||||
break;
|
|
||||||
case TWRITE:
|
|
||||||
if(!(r->fid = lookupkey(&pc->fidmap, r->ifcall.fid)))
|
|
||||||
return respond(r, Enofid);
|
|
||||||
if((r->fid->omode&3) != P9OWRITE && (r->fid->omode&3) != P9ORDWR)
|
|
||||||
return respond(r, "write on fid not opened for writing");
|
|
||||||
if(!pc->srv->write)
|
|
||||||
return respond(r, Enofunc);
|
|
||||||
pc->srv->write(r);
|
|
||||||
break;
|
|
||||||
/* Still to be implemented: flush, wstat, auth */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
respond(P9Req *r, char *error) {
|
|
||||||
P9Conn *pc = r->conn;
|
|
||||||
switch(r->ifcall.type) {
|
|
||||||
default:
|
|
||||||
if(!error)
|
|
||||||
cext_assert(!"Respond called on unsupported fcall type");
|
|
||||||
break;
|
|
||||||
case TVERSION:
|
|
||||||
cext_assert(!error);
|
|
||||||
free(r->ifcall.version);
|
|
||||||
pc->msize = (r->ofcall.msize < IXP_MAX_MSG) ? r->ofcall.msize : IXP_MAX_MSG;
|
|
||||||
free(pc->buf);
|
|
||||||
pc->buf = cext_emallocz(r->ofcall.msize);
|
|
||||||
break;
|
|
||||||
case TATTACH:
|
|
||||||
if(error)
|
|
||||||
destroyfid(pc, r->fid->fid);
|
|
||||||
free(r->ifcall.uname);
|
|
||||||
free(r->ifcall.aname);
|
|
||||||
break;
|
|
||||||
case TOPEN:
|
|
||||||
case TCREATE:
|
|
||||||
if(!error) {
|
|
||||||
r->fid->omode = r->ifcall.mode;
|
|
||||||
r->fid->qid = r->ofcall.qid;
|
|
||||||
}
|
|
||||||
free(r->ifcall.name);
|
|
||||||
r->ofcall.iounit = pc->msize - sizeof(unsigned long);
|
|
||||||
break;
|
|
||||||
case TWALK:
|
|
||||||
if(error || r->ofcall.nwqid < r->ifcall.nwname) {
|
|
||||||
if(r->ifcall.fid != r->ifcall.newfid && r->newfid)
|
|
||||||
destroyfid(pc, r->newfid->fid);
|
|
||||||
if(!error && r->ofcall.nwqid == 0)
|
|
||||||
error = Enofile;
|
|
||||||
}else{
|
|
||||||
if(r->ofcall.nwqid == 0)
|
|
||||||
r->newfid->qid = r->fid->qid;
|
|
||||||
else
|
|
||||||
r->newfid->qid = r->ofcall.wqid[r->ofcall.nwqid-1];
|
|
||||||
}
|
|
||||||
free(*r->ifcall.wname);
|
|
||||||
break;
|
|
||||||
case TWRITE:
|
|
||||||
free(r->ifcall.data);
|
|
||||||
break;
|
|
||||||
case TREMOVE:
|
|
||||||
if(r->fid)
|
|
||||||
destroyfid(pc, r->fid->fid);
|
|
||||||
break;
|
|
||||||
case TCLUNK:
|
|
||||||
if(r->fid)
|
|
||||||
destroyfid(pc, r->fid->fid);
|
|
||||||
if(!pc->conn && r->ifcall.tag == IXP_NOTAG)
|
|
||||||
pc->ref--;
|
|
||||||
break;
|
|
||||||
case TFLUSH:
|
|
||||||
if((r->oldreq = lookupkey(&pc->tagmap, r->ifcall.oldtag)))
|
|
||||||
respond(r->oldreq, Einterrupted);
|
|
||||||
if(!pc->conn && r->ifcall.tag == IXP_NOTAG)
|
|
||||||
pc->ref--;
|
|
||||||
break;
|
|
||||||
case TREAD:
|
|
||||||
case TSTAT:
|
|
||||||
break;
|
|
||||||
/* Still to be implemented: flush, wstat, auth */
|
|
||||||
}
|
|
||||||
|
|
||||||
r->ofcall.tag = r->ifcall.tag;
|
|
||||||
if(!error)
|
|
||||||
r->ofcall.type = r->ifcall.type + 1;
|
|
||||||
else {
|
|
||||||
r->ofcall.type = RERROR;
|
|
||||||
r->ofcall.ename = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pc->conn)
|
|
||||||
ixp_server_respond_fcall(pc->conn, &r->ofcall);
|
|
||||||
|
|
||||||
switch(r->ofcall.type) {
|
|
||||||
case RSTAT:
|
|
||||||
free(r->ofcall.stat);
|
|
||||||
break;
|
|
||||||
case RREAD:
|
|
||||||
free(r->ofcall.data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
deletekey(&pc->tagmap, r->ifcall.tag);;
|
|
||||||
free(r);
|
|
||||||
|
|
||||||
if(!pc->conn && pc->ref == 0)
|
|
||||||
free_p9conn(pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pending request cleanup */
|
|
||||||
static void
|
|
||||||
ixp_void_request(void *t) {
|
|
||||||
P9Req *r, *tr;
|
|
||||||
P9Conn *pc;
|
|
||||||
|
|
||||||
r = t;
|
|
||||||
pc = r->conn;
|
|
||||||
|
|
||||||
tr = cext_emallocz(sizeof(P9Req));
|
|
||||||
tr->conn = pc;
|
|
||||||
tr->ifcall.type = TFLUSH;
|
|
||||||
tr->ifcall.tag = IXP_NOTAG;
|
|
||||||
tr->ifcall.oldtag = r->ifcall.tag;
|
|
||||||
ixp_handle_req(tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open FID cleanup */
|
|
||||||
static void
|
|
||||||
ixp_void_fid(void *t) {
|
|
||||||
P9Conn *pc;
|
|
||||||
P9Req *tr;
|
|
||||||
Fid *f;
|
|
||||||
|
|
||||||
f = t;
|
|
||||||
pc = f->conn;
|
|
||||||
|
|
||||||
tr = cext_emallocz(sizeof(P9Req));
|
|
||||||
tr->fid = f;
|
|
||||||
tr->conn = pc;
|
|
||||||
tr->ifcall.type = TCLUNK;
|
|
||||||
tr->ifcall.tag = IXP_NOTAG;
|
|
||||||
tr->ifcall.fid = f->fid;
|
|
||||||
ixp_handle_req(tr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ixp_p9conn_incref(void *r) {
|
|
||||||
P9Conn *pc = *(P9Conn **)r;
|
|
||||||
pc->ref++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* To cleanup a connction, we increase the ref count for
|
|
||||||
* each open FID and pending request and generate clunk and
|
|
||||||
* flush requests. As each request is responded to and each
|
|
||||||
* FID is clunked, we decrease the ref count. When the ref
|
|
||||||
* count is 0, we free the P9Conn and its buf. The IXPConn
|
|
||||||
* is taken care of in server.c */
|
|
||||||
static void
|
|
||||||
ixp_cleanup_conn(IXPConn *c) {
|
|
||||||
P9Conn *pc = c->aux;
|
|
||||||
pc->conn = nil;
|
|
||||||
pc->ref = 1;
|
|
||||||
execmap(&pc->tagmap, ixp_p9conn_incref);
|
|
||||||
execmap(&pc->fidmap, ixp_p9conn_incref);
|
|
||||||
if(pc->ref > 1) {
|
|
||||||
execmap(&pc->tagmap, ixp_void_request);
|
|
||||||
execmap(&pc->fidmap, ixp_void_fid);
|
|
||||||
}
|
|
||||||
if(--pc->ref == 0)
|
|
||||||
free_p9conn(pc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Handle incoming 9P connections */
|
|
||||||
void
|
|
||||||
serve_9pcon(IXPConn *c) {
|
|
||||||
int fd = accept(c->fd, nil, nil);
|
|
||||||
if(fd < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
P9Conn *pc = cext_emallocz(sizeof(P9Conn));
|
|
||||||
pc->srv = c->aux;
|
|
||||||
|
|
||||||
/* XXX */
|
|
||||||
pc->msize = 1024;
|
|
||||||
pc->buf = cext_emallocz(pc->msize);
|
|
||||||
|
|
||||||
initmap(&pc->tagmap, TAG_BUCKETS, &pc->taghash);
|
|
||||||
initmap(&pc->fidmap, FID_BUCKETS, &pc->fidhash);
|
|
||||||
|
|
||||||
ixp_server_open_conn(c->srv, fd, pc, ixp_server_handle_fcall, ixp_cleanup_conn);
|
|
||||||
}
|
|
130
libixp/server.c
130
libixp/server.c
@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
|
||||||
* See LICENSE file for license details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "ixp.h"
|
|
||||||
|
|
||||||
static unsigned char *msg[IXP_MAX_MSG];
|
|
||||||
|
|
||||||
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;
|
|
||||||
c->next = s->conn;
|
|
||||||
s->conn = c;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_server_close_conn(IXPConn *c)
|
|
||||||
{
|
|
||||||
IXPServer *s = c->srv;
|
|
||||||
IXPConn **tc;
|
|
||||||
for(tc=&s->conn; *tc && *tc != c; tc=&(*tc)->next);
|
|
||||||
cext_assert(*tc == c);
|
|
||||||
*tc = c->next;
|
|
||||||
c->closed = 1;
|
|
||||||
if(c->close)
|
|
||||||
c->close(c);
|
|
||||||
else
|
|
||||||
shutdown(c->fd, SHUT_RDWR);
|
|
||||||
close(c->fd);
|
|
||||||
free(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
prepare_select(IXPServer *s)
|
|
||||||
{
|
|
||||||
IXPConn **c;
|
|
||||||
FD_ZERO(&s->rd);
|
|
||||||
for(c=&s->conn; *c; *c && (c=&(*c)->next)) {
|
|
||||||
if(s->maxfd < (*c)->fd)
|
|
||||||
s->maxfd = (*c)->fd;
|
|
||||||
if((*c)->read)
|
|
||||||
FD_SET((*c)->fd, &s->rd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
handle_conns(IXPServer *s)
|
|
||||||
{
|
|
||||||
IXPConn *c, *n;
|
|
||||||
for((c=s->conn) && (n=c->next); c; (c=n) && (n=c->next))
|
|
||||||
if(FD_ISSET(c->fd, &s->rd) && c->read)
|
|
||||||
c->read(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
ixp_server_loop(IXPServer *s)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
s->running = 1;
|
|
||||||
|
|
||||||
/* main loop */
|
|
||||||
while(s->running) {
|
|
||||||
prepare_select(s);
|
|
||||||
|
|
||||||
r = select(s->maxfd + 1, &s->rd, 0, 0, 0);
|
|
||||||
if(r == -1 && errno == EINTR)
|
|
||||||
continue;
|
|
||||||
if(r < 0)
|
|
||||||
return "fatal select error";
|
|
||||||
else if(r > 0)
|
|
||||||
handle_conns(s);
|
|
||||||
}
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
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))) {
|
|
||||||
ixp_server_close_conn(c);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return ixp_msg2fcall(fcall, msg, IXP_MAX_MSG);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
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) {
|
|
||||||
ixp_server_close_conn(c);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ixp_server_close(IXPServer *s)
|
|
||||||
{
|
|
||||||
IXPConn *c, *next;
|
|
||||||
for(c=s->conn; c; c=next) {
|
|
||||||
next=c->next;
|
|
||||||
ixp_server_close_conn(c);
|
|
||||||
}
|
|
||||||
}
|
|
200
libixp/socket.c
200
libixp/socket.c
@ -1,200 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
|
||||||
* See LICENSE file for license details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "ixp.h"
|
|
||||||
|
|
||||||
static int
|
|
||||||
connect_unix_sock(char *address)
|
|
||||||
{
|
|
||||||
int fd = 0;
|
|
||||||
struct sockaddr_un addr = { 0 };
|
|
||||||
socklen_t su_len;
|
|
||||||
|
|
||||||
/* init */
|
|
||||||
addr.sun_family = AF_UNIX;
|
|
||||||
strncpy(addr.sun_path, address, sizeof(addr.sun_path));
|
|
||||||
su_len = sizeof(struct sockaddr) + strlen(addr.sun_path);
|
|
||||||
|
|
||||||
if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
|
|
||||||
return -1;
|
|
||||||
if(connect(fd, (struct sockaddr *) &addr, su_len)) {
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
connect_inet_sock(char *host)
|
|
||||||
{
|
|
||||||
int fd = 0;
|
|
||||||
struct sockaddr_in addr = { 0 };
|
|
||||||
struct hostent *hp;
|
|
||||||
char *port = strrchr(host, '!');
|
|
||||||
unsigned int prt;
|
|
||||||
|
|
||||||
if(!port)
|
|
||||||
return -1;
|
|
||||||
*port = 0;
|
|
||||||
port++;
|
|
||||||
if(sscanf(port, "%d", &prt) != 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* init */
|
|
||||||
if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
|
|
||||||
return -1;
|
|
||||||
hp = gethostbyname(host);
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(prt);
|
|
||||||
bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
|
|
||||||
|
|
||||||
if(connect(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in))) {
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_connect_sock(char *address)
|
|
||||||
{
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if((p = strchr(address, '!'))) {
|
|
||||||
*p = 0;
|
|
||||||
p++;
|
|
||||||
|
|
||||||
if(!strncmp(address, "unix", 5))
|
|
||||||
return connect_unix_sock(p);
|
|
||||||
else if(!strncmp(address, "tcp", 4))
|
|
||||||
return connect_inet_sock(p);
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
create_inet_sock(char *host, char **errstr)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
struct sockaddr_in addr = { 0 };
|
|
||||||
struct hostent *hp;
|
|
||||||
char *port = strrchr(host, '!');
|
|
||||||
unsigned int prt;
|
|
||||||
|
|
||||||
if(!port) {
|
|
||||||
*errstr = "no port provided in address";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*port = 0;
|
|
||||||
port++;
|
|
||||||
if(sscanf(port, "%d", &prt) != 1) {
|
|
||||||
*errstr = "invalid port number";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
|
||||||
if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
|
||||||
*errstr = "cannot open socket";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
addr.sin_family = AF_INET;
|
|
||||||
addr.sin_port = htons(prt);
|
|
||||||
|
|
||||||
if(!strncmp(host, "*", 2))
|
|
||||||
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
||||||
else if((hp = gethostbyname(host)))
|
|
||||||
bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
|
|
||||||
else {
|
|
||||||
*errstr = "cannot translate hostname to an address";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bind(fd, (struct sockaddr *) &addr, sizeof(struct sockaddr_in)) < 0) {
|
|
||||||
*errstr = "cannot bind socket";
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(listen(fd, IXP_MAX_CACHE) < 0) {
|
|
||||||
*errstr = "cannot listen on socket";
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
create_unix_sock(char *file, char **errstr)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
int yes = 1;
|
|
||||||
struct sockaddr_un addr = { 0 };
|
|
||||||
socklen_t su_len;
|
|
||||||
|
|
||||||
signal(SIGPIPE, SIG_IGN);
|
|
||||||
if((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
|
|
||||||
*errstr = "cannot open socket";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
|
|
||||||
(char *) &yes, sizeof(yes)) < 0) {
|
|
||||||
*errstr = "cannot set socket options";
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
addr.sun_family = AF_UNIX;
|
|
||||||
strncpy(addr.sun_path, file, sizeof(addr.sun_path));
|
|
||||||
su_len = sizeof(struct sockaddr) + strlen(addr.sun_path);
|
|
||||||
|
|
||||||
unlink(file); /* remove old socket, if any */
|
|
||||||
if(bind(fd, (struct sockaddr *) &addr, su_len) < 0) {
|
|
||||||
*errstr = "cannot bind socket";
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
chmod(file, S_IRWXU);
|
|
||||||
|
|
||||||
if(listen(fd, IXP_MAX_CACHE) < 0) {
|
|
||||||
*errstr = "cannot listen on socket";
|
|
||||||
close(fd);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
ixp_create_sock(char *address, char **errstr)
|
|
||||||
{
|
|
||||||
char *p = strchr(address, '!');
|
|
||||||
char *addr, *type;
|
|
||||||
|
|
||||||
if(!p) {
|
|
||||||
*errstr = "no socket type defined";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*p = 0;
|
|
||||||
|
|
||||||
addr = &p[1];
|
|
||||||
type = address; /* unix, inet */
|
|
||||||
|
|
||||||
if(!strncmp(type, "unix", 5))
|
|
||||||
return create_unix_sock(addr, errstr);
|
|
||||||
else if(!strncmp(type, "tcp", 4))
|
|
||||||
return create_inet_sock(addr, errstr);
|
|
||||||
else
|
|
||||||
*errstr = "unkown socket type";
|
|
||||||
return -1;
|
|
||||||
}
|
|
@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>
|
|
||||||
* See LICENSE file for license details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/un.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "ixp.h"
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
ixp_send_message(int fd, void *msg, unsigned int msize, char **errstr)
|
|
||||||
{
|
|
||||||
unsigned int num = 0;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
/* send message */
|
|
||||||
while(num < msize) {
|
|
||||||
r = write(fd, msg + num, msize - num);
|
|
||||||
if(r == -1 && errno == EINTR)
|
|
||||||
continue;
|
|
||||||
if(r < 1) {
|
|
||||||
*errstr = "broken pipe";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
num += r;
|
|
||||||
}
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int
|
|
||||||
ixp_recv_data(int fd, void *msg, unsigned int msize, char **errstr)
|
|
||||||
{
|
|
||||||
unsigned int num = 0;
|
|
||||||
int r = 0;
|
|
||||||
|
|
||||||
/* receive data */
|
|
||||||
while(num < msize) {
|
|
||||||
r = read(fd, msg + num, msize - num);
|
|
||||||
if(r == -1 && errno == EINTR)
|
|
||||||
continue;
|
|
||||||
if(r < 1) {
|
|
||||||
*errstr = "broken pipe";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
num += r;
|
|
||||||
}
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int
|
|
||||||
ixp_recv_message(int fd, void *msg, unsigned int msglen, char **errstr)
|
|
||||||
{
|
|
||||||
unsigned int msize;
|
|
||||||
|
|
||||||
/* receive header */
|
|
||||||
if(ixp_recv_data(fd, msg, sizeof(unsigned int), errstr) !=
|
|
||||||
sizeof(unsigned int))
|
|
||||||
return 0;
|
|
||||||
ixp_unpack_u32((void *)&msg, nil, &msize);
|
|
||||||
if(msize > msglen) {
|
|
||||||
*errstr = "invalid message header";
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* receive message */
|
|
||||||
if(ixp_recv_data(fd, msg, msize - sizeof(unsigned int), errstr)
|
|
||||||
!= msize - sizeof(unsigned int))
|
|
||||||
return 0;
|
|
||||||
return msize;
|
|
||||||
}
|
|
@ -6,7 +6,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <cext.h>
|
|
||||||
#include "blitz.h"
|
#include "blitz.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -30,7 +29,7 @@ blitz_draw_label(BlitzBrush *b, char *text)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
shortened = 0;
|
shortened = 0;
|
||||||
cext_strlcpy(buf, text, sizeof(buf));
|
strncpy(buf, text, sizeof(buf));
|
||||||
len = strlen(buf);
|
len = strlen(buf);
|
||||||
gcv.foreground = b->color.fg;
|
gcv.foreground = b->color.fg;
|
||||||
gcv.background = b->color.bg;
|
gcv.background = b->color.bg;
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <cext.h>
|
|
||||||
|
|
||||||
#include "blitz.h"
|
#include "blitz.h"
|
||||||
|
|
||||||
@ -14,7 +13,7 @@ xloadcolor(Blitz *blitz, char *colstr)
|
|||||||
XColor color;
|
XColor color;
|
||||||
char col[8];
|
char col[8];
|
||||||
|
|
||||||
cext_strlcpy(col, colstr, sizeof(col));
|
strncpy(col, colstr, sizeof(col));
|
||||||
col[7] = 0;
|
col[7] = 0;
|
||||||
XAllocNamedColor(blitz->dpy,
|
XAllocNamedColor(blitz->dpy,
|
||||||
DefaultColormap(blitz->dpy, blitz->screen), col, &color, &color);
|
DefaultColormap(blitz->dpy, blitz->screen), col, &color, &color);
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <cext.h>
|
|
||||||
|
|
||||||
#include "blitz.h"
|
#include "blitz.h"
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
@ -16,7 +14,7 @@ blitz_textwidth_l(BlitzFont *font, char *text, unsigned int len)
|
|||||||
{
|
{
|
||||||
if(font->set) {
|
if(font->set) {
|
||||||
XRectangle r;
|
XRectangle r;
|
||||||
XmbTextExtents(font->set, text, len, nil, &r);
|
XmbTextExtents(font->set, text, len, NULL, &r);
|
||||||
return r.width;
|
return r.width;
|
||||||
}
|
}
|
||||||
return XTextWidth(font->xfont, text, len);
|
return XTextWidth(font->xfont, text, len);
|
||||||
@ -32,7 +30,7 @@ void
|
|||||||
blitz_loadfont(Blitz *blitz, BlitzFont *font)
|
blitz_loadfont(Blitz *blitz, BlitzFont *font)
|
||||||
{
|
{
|
||||||
char *fontname = font->fontstr;
|
char *fontname = font->fontstr;
|
||||||
char **missing = nil, *def = "?";
|
char **missing = NULL, *def = "?";
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
@ -45,7 +43,7 @@ blitz_loadfont(Blitz *blitz, BlitzFont *font)
|
|||||||
XFreeStringList(missing);
|
XFreeStringList(missing);
|
||||||
if(font->set) {
|
if(font->set) {
|
||||||
XFreeFontSet(blitz->dpy, font->set);
|
XFreeFontSet(blitz->dpy, font->set);
|
||||||
font->set = nil;
|
font->set = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(font->set) {
|
if(font->set) {
|
||||||
@ -68,7 +66,7 @@ blitz_loadfont(Blitz *blitz, BlitzFont *font)
|
|||||||
else {
|
else {
|
||||||
if(font->xfont)
|
if(font->xfont)
|
||||||
XFreeFont(blitz->dpy, font->xfont);
|
XFreeFont(blitz->dpy, font->xfont);
|
||||||
font->xfont = nil;
|
font->xfont = NULL;
|
||||||
font->xfont = XLoadQueryFont(blitz->dpy, fontname);
|
font->xfont = XLoadQueryFont(blitz->dpy, fontname);
|
||||||
if (!font->xfont) {
|
if (!font->xfont) {
|
||||||
fontname = "fixed";
|
fontname = "fixed";
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
# Heavy access test of wmiiwm's fs
|
|
||||||
|
|
||||||
dump_fs() {
|
|
||||||
echo $1
|
|
||||||
wmiir read $1|wmiir write $1;
|
|
||||||
for i in `wmiir read $1|awk '{print $10}'`
|
|
||||||
do
|
|
||||||
if test $i != "event"
|
|
||||||
then
|
|
||||||
dump_fs $1/$i
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
while true
|
|
||||||
do
|
|
||||||
dump_fs /
|
|
||||||
done
|
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Loading…
Reference in New Issue
Block a user