reorganized, still liblitz there

This commit is contained in:
Anselm R. Garbe 2006-10-12 15:11:25 +02:00
parent b71f8a147e
commit 4a7273b827
48 changed files with 7 additions and 4004 deletions

View File

@ -3,7 +3,7 @@
include config.mk
SUBDIRS = libcext liblitz libixp cmd
SUBDIRS = liblitz
BIN = cmd/wm/wmii cmd/wm/wmiiwm cmd/wmiir

View File

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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;
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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}

View File

View File

View File

@ -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

View File

@ -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();
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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 */
}

View File

@ -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 */
}

View File

@ -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 */
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -6,7 +6,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cext.h>
#include "blitz.h"
void
@ -30,7 +29,7 @@ blitz_draw_label(BlitzBrush *b, char *text)
return;
shortened = 0;
cext_strlcpy(buf, text, sizeof(buf));
strncpy(buf, text, sizeof(buf));
len = strlen(buf);
gcv.foreground = b->color.fg;
gcv.background = b->color.bg;

View File

@ -4,7 +4,6 @@
*/
#include <string.h>
#include <cext.h>
#include "blitz.h"
@ -14,7 +13,7 @@ xloadcolor(Blitz *blitz, char *colstr)
XColor color;
char col[8];
cext_strlcpy(col, colstr, sizeof(col));
strncpy(col, colstr, sizeof(col));
col[7] = 0;
XAllocNamedColor(blitz->dpy,
DefaultColormap(blitz->dpy, blitz->screen), col, &color, &color);

View File

@ -7,8 +7,6 @@
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <cext.h>
#include "blitz.h"
unsigned int
@ -16,7 +14,7 @@ blitz_textwidth_l(BlitzFont *font, char *text, unsigned int len)
{
if(font->set) {
XRectangle r;
XmbTextExtents(font->set, text, len, nil, &r);
XmbTextExtents(font->set, text, len, NULL, &r);
return r.width;
}
return XTextWidth(font->xfont, text, len);
@ -32,7 +30,7 @@ void
blitz_loadfont(Blitz *blitz, BlitzFont *font)
{
char *fontname = font->fontstr;
char **missing = nil, *def = "?";
char **missing = NULL, *def = "?";
int n;
setlocale(LC_ALL, "");
@ -45,7 +43,7 @@ blitz_loadfont(Blitz *blitz, BlitzFont *font)
XFreeStringList(missing);
if(font->set) {
XFreeFontSet(blitz->dpy, font->set);
font->set = nil;
font->set = NULL;
}
}
if(font->set) {
@ -68,7 +66,7 @@ blitz_loadfont(Blitz *blitz, BlitzFont *font)
else {
if(font->xfont)
XFreeFont(blitz->dpy, font->xfont);
font->xfont = nil;
font->xfont = NULL;
font->xfont = XLoadQueryFont(blitz->dpy, fontname);
if (!font->xfont) {
fontname = "fixed";

View File

@ -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

View File

View File

View File

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB