a
This commit is contained in:
parent
0189e66e88
commit
934846f35c
82
Makefile
Normal file
82
Makefile
Normal file
@ -0,0 +1,82 @@
|
||||
TARG=drawterm
|
||||
CC=gcc
|
||||
CFLAGS=-Iinclude -c -ggdb -D_THREAD_SAFE -pthread # not ready for this yet: -Wall
|
||||
O=o
|
||||
#CC=cl
|
||||
#CFLAGS=-c -nologo -W3 -YX -Zi -MT -Zl -Iinclude -DWINDOWS
|
||||
#O=obj
|
||||
|
||||
OFILES=\
|
||||
main.$O\
|
||||
cpu.$O\
|
||||
readcons.$O\
|
||||
secstore.$O\
|
||||
latin1.$O\
|
||||
|
||||
LIBS=\
|
||||
kern/libkern.a\
|
||||
exportfs/libexportfs.a\
|
||||
libauthsrv/libauthsrv.a\
|
||||
libsec/libsec.a\
|
||||
libmp/libmp.a\
|
||||
libmemdraw/libmemdraw.a\
|
||||
libmemlayer/libmemlayer.a\
|
||||
libdraw/libdraw.a\
|
||||
libc/libc.a\
|
||||
kern/libkern.a\
|
||||
gui-x11/libx11.a\
|
||||
libmemdraw/libmemdraw.a\
|
||||
libdraw/libdraw.a\
|
||||
kern/libkern.a\
|
||||
libc/libc.a\
|
||||
libmemdraw/libmemdraw.a\
|
||||
libmemlayer/libmemlayer.a\
|
||||
libdraw/libdraw.a\
|
||||
libmachdep.a
|
||||
|
||||
$(TARG): $(OFILES) $(LIBS)
|
||||
$(CC) -pthread -o $(TARG) $(OFILES) $(LIBS) -L/usr/X11R6/lib -lX11 -ggdb
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $(CFLAGS) $*.c
|
||||
|
||||
clean:
|
||||
rm -f *.o */*.o */*.a drawterm *.a
|
||||
|
||||
kern/libkern.a:
|
||||
(cd kern; make)
|
||||
|
||||
exportfs/libexportfs.a:
|
||||
(cd exportfs; make)
|
||||
|
||||
libauthsrv/libauthsrv.a:
|
||||
(cd libauthsrv; make)
|
||||
|
||||
libmp/libmp.a:
|
||||
(cd libmp; make)
|
||||
|
||||
libsec/libsec.a:
|
||||
(cd libsec; make)
|
||||
|
||||
libmemdraw/libmemdraw.a:
|
||||
(cd libmemdraw; make)
|
||||
|
||||
libmemlayer/libmemlayer.a:
|
||||
(cd libmemlayer; make)
|
||||
|
||||
libdraw/libdraw.a:
|
||||
(cd libdraw; make)
|
||||
|
||||
libc/libc.a:
|
||||
(cd libc; make)
|
||||
|
||||
gui-x11/libx11.a:
|
||||
(cd gui-x11; make)
|
||||
|
||||
#libmachdep.a:
|
||||
# arch=`uname -m|sed 's/i.86/386/;s/Power Macintosh/power/'`; \
|
||||
# (cd gcc$$arch && make)
|
||||
|
||||
libmachdep.a:
|
||||
(cd posix-386; make)
|
||||
|
16
Notes
Normal file
16
Notes
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
Win32 port Notes:
|
||||
|
||||
* Issues:
|
||||
|
||||
** ownership questions on files are completely deferred by
|
||||
marking them as unknown. It works for now, but probably
|
||||
should be handled correctly.
|
||||
|
||||
** No performance measurements have been done. The interactive
|
||||
response seems faster than old drawterm, but the i/o seems
|
||||
slower.
|
||||
|
||||
** fs functions in devntfs.c need to handle conversions to/from
|
||||
widechar and utf-8.
|
||||
|
20
args.h
Normal file
20
args.h
Normal file
@ -0,0 +1,20 @@
|
||||
extern char *argv0;
|
||||
#define ARGBEGIN for((argv0? 0: (argv0=*argv)),argv++,argc--;\
|
||||
argv[0] && argv[0][0]=='-' && argv[0][1];\
|
||||
argc--, argv++) {\
|
||||
char *_args, *_argt;\
|
||||
Rune _argc;\
|
||||
_args = &argv[0][1];\
|
||||
if(_args[0]=='-' && _args[1]==0){\
|
||||
argc--; argv++; break;\
|
||||
}\
|
||||
_argc = 0;\
|
||||
while(*_args && (_args += chartorune(&_argc, _args)))\
|
||||
switch(_argc)
|
||||
#define ARGEND SET(_argt);USED(_argt); USED(_argc); USED(_args);}USED(argv); USED(argc);
|
||||
#define ARGF() (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
|
||||
#define ARGC() _argc
|
||||
|
||||
#define EARGF(x) (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): (x, (char*)0)))
|
606
cpu.c
Normal file
606
cpu.c
Normal file
@ -0,0 +1,606 @@
|
||||
/*
|
||||
* cpu.c - Make a connection to a cpu server
|
||||
*
|
||||
* Invoked by listen as 'cpu -R | -N service net netdir'
|
||||
* by users as 'cpu [-h system] [-c cmd args ...]'
|
||||
*/
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <auth.h>
|
||||
#include <fcall.h>
|
||||
#include <authsrv.h>
|
||||
#include <libsec.h>
|
||||
#include "args.h"
|
||||
#include "drawterm.h"
|
||||
|
||||
#define Maxfdata 8192
|
||||
#define MaxStr 128
|
||||
|
||||
static char* getuser(void);
|
||||
static void fatal(int, char*, ...);
|
||||
static void catcher(void*, char*);
|
||||
static void usage(void);
|
||||
static void writestr(int, char*, char*, int);
|
||||
static int readstr(int, char*, int);
|
||||
static char *rexcall(int*, char*, char*);
|
||||
static int setamalg(char*);
|
||||
static char *keyspec = "";
|
||||
static AuthInfo *p9any(int);
|
||||
|
||||
static int notechan;
|
||||
#define system csystem
|
||||
static char *system;
|
||||
static int cflag;
|
||||
int dbg;
|
||||
|
||||
static char *srvname = "ncpu";
|
||||
static char *ealgs = "rc4_256 sha1";
|
||||
|
||||
/* message size for exportfs; may be larger so we can do big graphics in CPU window */
|
||||
static int msgsize = Maxfdata+IOHDRSZ;
|
||||
|
||||
/* authentication mechanisms */
|
||||
static int netkeyauth(int);
|
||||
static int netkeysrvauth(int, char*);
|
||||
static int p9auth(int);
|
||||
static int srvp9auth(int, char*);
|
||||
static int noauth(int);
|
||||
static int srvnoauth(int, char*);
|
||||
|
||||
char *authserver;
|
||||
|
||||
typedef struct AuthMethod AuthMethod;
|
||||
struct AuthMethod {
|
||||
char *name; /* name of method */
|
||||
int (*cf)(int); /* client side authentication */
|
||||
int (*sf)(int, char*); /* server side authentication */
|
||||
} authmethod[] =
|
||||
{
|
||||
{ "p9", p9auth, srvp9auth,},
|
||||
{ "netkey", netkeyauth, netkeysrvauth,},
|
||||
// { "none", noauth, srvnoauth,},
|
||||
{ nil, nil}
|
||||
};
|
||||
AuthMethod *am = authmethod; /* default is p9 */
|
||||
|
||||
char *p9authproto = "p9any";
|
||||
|
||||
int setam(char*);
|
||||
|
||||
void
|
||||
exits(char *s)
|
||||
{
|
||||
print("\ngoodbye\n");
|
||||
for(;;) osyield();
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
fprint(2, "usage: drawterm [-a authserver] [-c cpuserver] [-s secstore] [-u user]\n");
|
||||
exits("usage");
|
||||
}
|
||||
int fdd;
|
||||
|
||||
void
|
||||
cpumain(int argc, char **argv)
|
||||
{
|
||||
char dat[MaxStr], buf[MaxStr], cmd[MaxStr], *p, *err, *secstoreserver, *s;
|
||||
int fd, ms, data;
|
||||
|
||||
/* see if we should use a larger message size */
|
||||
fd = open("/dev/draw", OREAD);
|
||||
if(fd > 0){
|
||||
ms = iounit(fd);
|
||||
if(msgsize < ms+IOHDRSZ)
|
||||
msgsize = ms+IOHDRSZ;
|
||||
close(fd);
|
||||
}
|
||||
|
||||
user = readcons("user", getenv("USER"), 0);
|
||||
secstoreserver = nil;
|
||||
ARGBEGIN{
|
||||
case 'a':
|
||||
authserver = EARGF(usage());
|
||||
break;
|
||||
case 'e':
|
||||
ealgs = EARGF(usage());
|
||||
if(*ealgs == 0 || strcmp(ealgs, "clear") == 0)
|
||||
ealgs = nil;
|
||||
break;
|
||||
case 'd':
|
||||
dbg++;
|
||||
break;
|
||||
case 'c':
|
||||
system = EARGF(usage());
|
||||
break;
|
||||
/*
|
||||
case 'c':
|
||||
cflag++;
|
||||
cmd[0] = '!';
|
||||
cmd[1] = '\0';
|
||||
while(p = ARGF()) {
|
||||
strcat(cmd, " ");
|
||||
strcat(cmd, p);
|
||||
}
|
||||
break;
|
||||
*/
|
||||
case 'u':
|
||||
user = EARGF(usage());
|
||||
break;
|
||||
case 's':
|
||||
secstoreserver = EARGF(usage());
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}ARGEND;
|
||||
|
||||
if(secstoreserver == nil)
|
||||
secstoreserver = authserver;
|
||||
|
||||
if(secstoreserver && havesecstore(secstoreserver, user)){
|
||||
s = secstorefetch(secstoreserver, user, nil);
|
||||
if(s){
|
||||
if(strlen(s) >= sizeof secstorebuf)
|
||||
panic("secstore data too big");
|
||||
strcpy(secstorebuf, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(argc != 0)
|
||||
usage();
|
||||
|
||||
if(system == nil) {
|
||||
p = getenv("cpu");
|
||||
if(p == 0)
|
||||
fatal(0, "set $cpu");
|
||||
system = p;
|
||||
}
|
||||
|
||||
if(err = rexcall(&data, system, srvname))
|
||||
fatal(1, "%s: %s", err, system);
|
||||
|
||||
/* Tell the remote side the command to execute and where our working directory is */
|
||||
if(cflag)
|
||||
writestr(data, cmd, "command", 0);
|
||||
if(getcwd(dat, sizeof(dat)) == 0)
|
||||
writestr(data, "NO", "dir", 0);
|
||||
else
|
||||
writestr(data, dat, "dir", 0);
|
||||
|
||||
/*
|
||||
* Wait for the other end to execute and start our file service
|
||||
* of /mnt/term
|
||||
*/
|
||||
if(readstr(data, buf, sizeof(buf)) < 0)
|
||||
fatal(1, "waiting for FS: %r");
|
||||
if(strncmp("FS", buf, 2) != 0) {
|
||||
print("remote cpu: %s", buf);
|
||||
exits(buf);
|
||||
}
|
||||
|
||||
if(readstr(data, buf, sizeof buf) < 0)
|
||||
fatal(1, "waiting for remote export: %r");
|
||||
if(strcmp(buf, "/") != 0){
|
||||
print("remote cpu: %s" , buf);
|
||||
exits(buf);
|
||||
}
|
||||
write(data, "OK", 2);
|
||||
|
||||
/* Begin serving the gnot namespace */
|
||||
exportfs(data, msgsize);
|
||||
fatal(1, "starting exportfs");
|
||||
}
|
||||
|
||||
void
|
||||
fatal(int syserr, char *fmt, ...)
|
||||
{
|
||||
Fmt f;
|
||||
char *str;
|
||||
va_list arg;
|
||||
|
||||
fmtstrinit(&f);
|
||||
fmtprint(&f, "cpu: ");
|
||||
va_start(arg, fmt);
|
||||
fmtvprint(&f, fmt, arg);
|
||||
va_end(arg);
|
||||
if(syserr)
|
||||
fmtprint(&f, ": %r");
|
||||
fmtprint(&f, "\n");
|
||||
str = fmtstrflush(&f);
|
||||
write(2, str, strlen(str));
|
||||
exits(str);
|
||||
}
|
||||
|
||||
char *negstr = "negotiating authentication method";
|
||||
|
||||
char bug[256];
|
||||
|
||||
char*
|
||||
rexcall(int *fd, char *host, char *service)
|
||||
{
|
||||
char *na;
|
||||
char dir[MaxStr];
|
||||
char err[ERRMAX];
|
||||
char msg[MaxStr];
|
||||
int n;
|
||||
|
||||
na = netmkaddr(host, "tcp", "17010");
|
||||
if((*fd = dial(na, 0, dir, 0)) < 0)
|
||||
return "can't dial";
|
||||
|
||||
/* negotiate authentication mechanism */
|
||||
if(ealgs != nil)
|
||||
snprint(msg, sizeof(msg), "%s %s", am->name, ealgs);
|
||||
else
|
||||
snprint(msg, sizeof(msg), "%s", am->name);
|
||||
writestr(*fd, msg, negstr, 0);
|
||||
n = readstr(*fd, err, sizeof err);
|
||||
if(n < 0)
|
||||
return negstr;
|
||||
if(*err){
|
||||
werrstr(err);
|
||||
return negstr;
|
||||
}
|
||||
|
||||
/* authenticate */
|
||||
*fd = (*am->cf)(*fd);
|
||||
if(*fd < 0)
|
||||
return "can't authenticate";
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
writestr(int fd, char *str, char *thing, int ignore)
|
||||
{
|
||||
int l, n;
|
||||
|
||||
l = strlen(str);
|
||||
n = write(fd, str, l+1);
|
||||
if(!ignore && n < 0)
|
||||
fatal(1, "writing network: %s", thing);
|
||||
}
|
||||
|
||||
int
|
||||
readstr(int fd, char *str, int len)
|
||||
{
|
||||
int n;
|
||||
|
||||
while(len) {
|
||||
n = read(fd, str, 1);
|
||||
if(n < 0)
|
||||
return -1;
|
||||
if(*str == '\0')
|
||||
return 0;
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
readln(char *buf, int n)
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
n--; /* room for \0 */
|
||||
p = buf;
|
||||
for(i=0; i<n; i++){
|
||||
if(read(0, p, 1) != 1)
|
||||
break;
|
||||
if(*p == '\n' || *p == '\r')
|
||||
break;
|
||||
p++;
|
||||
}
|
||||
*p = '\0';
|
||||
return p-buf;
|
||||
}
|
||||
|
||||
/*
|
||||
* user level challenge/response
|
||||
*/
|
||||
static int
|
||||
netkeyauth(int fd)
|
||||
{
|
||||
char chall[32];
|
||||
char resp[32];
|
||||
|
||||
strecpy(chall, chall+sizeof chall, getuser());
|
||||
print("user[%s]: ", chall);
|
||||
if(readln(resp, sizeof(resp)) < 0)
|
||||
return -1;
|
||||
if(*resp != 0)
|
||||
strcpy(chall, resp);
|
||||
writestr(fd, chall, "challenge/response", 1);
|
||||
|
||||
for(;;){
|
||||
if(readstr(fd, chall, sizeof chall) < 0)
|
||||
break;
|
||||
if(*chall == 0)
|
||||
return fd;
|
||||
print("challenge: %s\nresponse: ", chall);
|
||||
if(readln(resp, sizeof(resp)) < 0)
|
||||
break;
|
||||
writestr(fd, resp, "challenge/response", 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
netkeysrvauth(int fd, char *user)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
mksecret(char *t, uchar *f)
|
||||
{
|
||||
sprint(t, "%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux",
|
||||
f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);
|
||||
}
|
||||
|
||||
/*
|
||||
* plan9 authentication followed by rc4 encryption
|
||||
*/
|
||||
static int
|
||||
p9auth(int fd)
|
||||
{
|
||||
uchar key[16];
|
||||
uchar digest[SHA1dlen];
|
||||
char fromclientsecret[21];
|
||||
char fromserversecret[21];
|
||||
int i;
|
||||
AuthInfo *ai;
|
||||
|
||||
ai = p9any(fd);
|
||||
if(ai == nil)
|
||||
return -1;
|
||||
memmove(key+4, ai->secret, ai->nsecret);
|
||||
if(ealgs == nil)
|
||||
return fd;
|
||||
|
||||
/* exchange random numbers */
|
||||
srand(truerand());
|
||||
for(i = 0; i < 4; i++)
|
||||
key[i] = rand();
|
||||
if(write(fd, key, 4) != 4)
|
||||
return -1;
|
||||
if(readn(fd, key+12, 4) != 4)
|
||||
return -1;
|
||||
|
||||
/* scramble into two secrets */
|
||||
sha1(key, sizeof(key), digest, nil);
|
||||
mksecret(fromclientsecret, digest);
|
||||
mksecret(fromserversecret, digest+10);
|
||||
|
||||
/* set up encryption */
|
||||
i = pushssl(fd, ealgs, fromclientsecret, fromserversecret, nil);
|
||||
if(i < 0)
|
||||
werrstr("can't establish ssl connection: %r");
|
||||
return i;
|
||||
}
|
||||
|
||||
int
|
||||
authdial(char *net, char *dom)
|
||||
{
|
||||
int fd;
|
||||
fd = dial(netmkaddr(authserver, "tcp", "567"), 0, 0, 0);
|
||||
//print("authdial %d\n", fd);
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int
|
||||
getastickets(Ticketreq *tr, char *trbuf, char *tbuf)
|
||||
{
|
||||
int asfd, rv;
|
||||
char *dom;
|
||||
|
||||
dom = tr->authdom;
|
||||
asfd = authdial(nil, dom);
|
||||
if(asfd < 0)
|
||||
return -1;
|
||||
rv = _asgetticket(asfd, trbuf, tbuf);
|
||||
close(asfd);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
mkserverticket(Ticketreq *tr, char *authkey, char *tbuf)
|
||||
{
|
||||
int i;
|
||||
Ticket t;
|
||||
|
||||
if(strcmp(tr->authid, tr->hostid) != 0)
|
||||
return -1;
|
||||
memset(&t, 0, sizeof(t));
|
||||
memmove(t.chal, tr->chal, CHALLEN);
|
||||
strcpy(t.cuid, tr->uid);
|
||||
strcpy(t.suid, tr->uid);
|
||||
for(i=0; i<DESKEYLEN; i++)
|
||||
t.key[i] = fastrand();
|
||||
t.num = AuthTc;
|
||||
convT2M(&t, tbuf, authkey);
|
||||
t.num = AuthTs;
|
||||
convT2M(&t, tbuf+TICKETLEN, authkey);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gettickets(Ticketreq *tr, char *key, char *trbuf, char *tbuf)
|
||||
{
|
||||
if(getastickets(tr, trbuf, tbuf) >= 0)
|
||||
return 0;
|
||||
return mkserverticket(tr, key, tbuf);
|
||||
}
|
||||
|
||||
AuthInfo*
|
||||
p9any(int fd)
|
||||
{
|
||||
char buf[1024], buf2[1024], cchal[CHALLEN], *bbuf, *p, *dom, *u;
|
||||
char *pass;
|
||||
char tbuf[TICKETLEN+TICKETLEN+AUTHENTLEN], trbuf[TICKREQLEN];
|
||||
char authkey[DESKEYLEN];
|
||||
Authenticator auth;
|
||||
int i, v2, n;
|
||||
Ticketreq tr;
|
||||
Ticket t;
|
||||
AuthInfo *ai;
|
||||
|
||||
if((n = readstr(fd, buf, sizeof buf)) < 0)
|
||||
fatal(1, "cannot read p9any negotiation");
|
||||
bbuf = buf;
|
||||
v2 = 0;
|
||||
if(strncmp(buf, "v.2 ", 4) == 0){
|
||||
v2 = 1;
|
||||
bbuf += 4;
|
||||
}
|
||||
if(p = strchr(bbuf, ' '))
|
||||
*p = 0;
|
||||
p = bbuf;
|
||||
if((dom = strchr(p, '@')) == nil)
|
||||
fatal(1, "bad p9any domain");
|
||||
*dom++ = 0;
|
||||
if(strcmp(p, "p9sk1") != 0)
|
||||
fatal(1, "server did not offer p9sk1");
|
||||
|
||||
sprint(buf2, "%s %s", p, dom);
|
||||
if(write(fd, buf2, strlen(buf2)+1) != strlen(buf2)+1)
|
||||
fatal(1, "cannot write user/domain choice in p9any");
|
||||
if(v2){
|
||||
if((n = readstr(fd, buf, sizeof buf)) != 3)
|
||||
fatal(1, "cannot read OK in p9any");
|
||||
if(memcmp(buf, "OK\0", 3) != 0)
|
||||
fatal(1, "did not get OK in p9any");
|
||||
}
|
||||
for(i=0; i<CHALLEN; i++)
|
||||
cchal[i] = fastrand();
|
||||
if(write(fd, cchal, 8) != 8)
|
||||
fatal(1, "cannot write p9sk1 challenge");
|
||||
|
||||
if(readn(fd, trbuf, TICKREQLEN) != TICKREQLEN)
|
||||
fatal(1, "cannot read ticket request in p9sk1");
|
||||
|
||||
|
||||
convM2TR(trbuf, &tr);
|
||||
u = user;
|
||||
pass = findkey(&u, tr.authdom);
|
||||
if(pass == nil)
|
||||
again:
|
||||
pass = getkey(u, tr.authdom);
|
||||
if(pass == nil)
|
||||
fatal(1, "no password");
|
||||
|
||||
passtokey(authkey, pass);
|
||||
memset(pass, 0, strlen(pass));
|
||||
|
||||
tr.type = AuthTreq;
|
||||
strecpy(tr.hostid, tr.hostid+sizeof tr.hostid, u);
|
||||
strecpy(tr.uid, tr.uid+sizeof tr.uid, u);
|
||||
convTR2M(&tr, trbuf);
|
||||
|
||||
if(gettickets(&tr, authkey, trbuf, tbuf) < 0)
|
||||
fatal(1, "cannot get auth tickets in p9sk1");
|
||||
|
||||
convM2T(tbuf, &t, authkey);
|
||||
if(t.num != AuthTc){
|
||||
print("?password mismatch with auth server\n");
|
||||
goto again;
|
||||
}
|
||||
memmove(tbuf, tbuf+TICKETLEN, TICKETLEN);
|
||||
|
||||
auth.num = AuthAc;
|
||||
memmove(auth.chal, tr.chal, CHALLEN);
|
||||
auth.id = 0;
|
||||
convA2M(&auth, tbuf+TICKETLEN, t.key);
|
||||
|
||||
if(write(fd, tbuf, TICKETLEN+AUTHENTLEN) != TICKETLEN+AUTHENTLEN)
|
||||
fatal(1, "cannot send ticket and authenticator back in p9sk1");
|
||||
|
||||
if(readn(fd, tbuf, AUTHENTLEN) != AUTHENTLEN)
|
||||
fatal(1, "cannot read authenticator in p9sk1");
|
||||
|
||||
convM2A(tbuf, &auth, t.key);
|
||||
if(auth.num != AuthAs
|
||||
|| memcmp(auth.chal, cchal, CHALLEN) != 0
|
||||
|| auth.id != 0){
|
||||
print("?you and auth server agree about password.\n");
|
||||
print("?server is confused.\n");
|
||||
fatal(1, "server lies got %llux.%d want %llux.%d", *(vlong*)auth.chal, auth.id, *(vlong*)cchal, 0);
|
||||
}
|
||||
//print("i am %s there.\n", t.suid);
|
||||
ai = mallocz(sizeof(AuthInfo), 1);
|
||||
ai->secret = mallocz(8, 1);
|
||||
des56to64((uchar*)t.key, ai->secret);
|
||||
ai->nsecret = 8;
|
||||
ai->suid = strdup(t.suid);
|
||||
ai->cuid = strdup(t.cuid);
|
||||
memset(authkey, 0, sizeof authkey);
|
||||
return ai;
|
||||
}
|
||||
|
||||
static int
|
||||
noauth(int fd)
|
||||
{
|
||||
ealgs = nil;
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int
|
||||
srvnoauth(int fd, char *user)
|
||||
{
|
||||
strecpy(user, user+MaxStr, getuser());
|
||||
ealgs = nil;
|
||||
return fd;
|
||||
}
|
||||
|
||||
void
|
||||
loghex(uchar *p, int n)
|
||||
{
|
||||
char buf[100];
|
||||
int i;
|
||||
|
||||
for(i = 0; i < n; i++)
|
||||
sprint(buf+2*i, "%2.2ux", p[i]);
|
||||
// syslog(0, "cpu", buf);
|
||||
}
|
||||
|
||||
static int
|
||||
srvp9auth(int fd, char *user)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* set authentication mechanism
|
||||
*/
|
||||
int
|
||||
setam(char *name)
|
||||
{
|
||||
for(am = authmethod; am->name != nil; am++)
|
||||
if(strcmp(am->name, name) == 0)
|
||||
return 0;
|
||||
am = authmethod;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* set authentication mechanism and encryption/hash algs
|
||||
*/
|
||||
int
|
||||
setamalg(char *s)
|
||||
{
|
||||
ealgs = strchr(s, ' ');
|
||||
if(ealgs != nil)
|
||||
*ealgs++ = 0;
|
||||
return setam(s);
|
||||
}
|
||||
|
||||
char*
|
||||
getuser(void)
|
||||
{
|
||||
return getenv("USER");
|
||||
}
|
||||
|
10
drawterm.h
Normal file
10
drawterm.h
Normal file
@ -0,0 +1,10 @@
|
||||
extern int havesecstore(char *addr, char *owner);
|
||||
extern char *secstore;
|
||||
extern char secstorebuf[65536];
|
||||
extern char *secstorefetch(char *addr, char *owner, char *passwd);
|
||||
extern char *authaddr;
|
||||
extern char *readcons(char *prompt, char *def, int secret);
|
||||
extern int exportfs(int, int);
|
||||
extern char *user;
|
||||
extern char *getkey(char*, char*);
|
||||
extern char *findkey(char**, char*);
|
BIN
drawterm.ico
Normal file
BIN
drawterm.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
72
drawterm.rc
Normal file
72
drawterm.rc
Normal file
@ -0,0 +1,72 @@
|
||||
//Microsoft Developer Studio generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "afxres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
#ifdef _WIN32
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
#endif //_WIN32
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON DISCARDABLE "drawterm.ico"
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE DISCARDABLE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
#endif // English (U.S.) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
BIN
drawterm.res
Normal file
BIN
drawterm.res
Normal file
Binary file not shown.
16
exportfs/Makefile
Normal file
16
exportfs/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
LIB=libexportfs.a
|
||||
CC=gcc
|
||||
CFLAGS=-I../include -I. -I.. -c -ggdb -D_THREAD_SAFE -pthread
|
||||
O=o
|
||||
|
||||
OFILES=\
|
||||
exportfs.$O\
|
||||
exportsrv.$O
|
||||
|
||||
$(LIB): $(OFILES)
|
||||
ar r $(LIB) $(OFILES)
|
||||
ranlib $(LIB)
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $(CFLAGS) $*.c
|
||||
|
503
exportfs/exportfs.c
Normal file
503
exportfs/exportfs.c
Normal file
@ -0,0 +1,503 @@
|
||||
/*
|
||||
* exportfs - Export a plan 9 name space across a network
|
||||
*/
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <fcall.h>
|
||||
#include <libsec.h>
|
||||
#include "drawterm.h"
|
||||
#define Extern
|
||||
#include "exportfs.h"
|
||||
|
||||
/* #define QIDPATH ((1LL<<48)-1) */
|
||||
#define QIDPATH ((((vlong)1)<<48)-1)
|
||||
vlong newqid = 0;
|
||||
|
||||
void (*fcalls[256])(Fsrpc*);
|
||||
|
||||
/* accounting and debugging counters */
|
||||
int filecnt;
|
||||
int freecnt;
|
||||
int qidcnt;
|
||||
int qfreecnt;
|
||||
int ncollision;
|
||||
int netfd;
|
||||
|
||||
int
|
||||
exportfs(int fd, int msgsz)
|
||||
{
|
||||
char buf[ERRMAX], ebuf[ERRMAX];
|
||||
Fsrpc *r;
|
||||
int n;
|
||||
char *dbfile, *srv, *file;
|
||||
ulong initial;
|
||||
|
||||
fcalls[Tversion] = Xversion;
|
||||
fcalls[Tauth] = Xauth;
|
||||
fcalls[Tflush] = Xflush;
|
||||
fcalls[Tattach] = Xattach;
|
||||
fcalls[Twalk] = Xwalk;
|
||||
fcalls[Topen] = slave;
|
||||
fcalls[Tcreate] = Xcreate;
|
||||
fcalls[Tclunk] = Xclunk;
|
||||
fcalls[Tread] = slave;
|
||||
fcalls[Twrite] = slave;
|
||||
fcalls[Tremove] = Xremove;
|
||||
fcalls[Tstat] = Xstat;
|
||||
fcalls[Twstat] = Xwstat;
|
||||
|
||||
srvfd = -1;
|
||||
netfd = fd;
|
||||
//dbg = 1;
|
||||
|
||||
strcpy(buf, "this is buf");
|
||||
strcpy(ebuf, "this is ebuf");
|
||||
DEBUG(DFD, "exportfs: started\n");
|
||||
|
||||
// rfork(RFNOTEG);
|
||||
|
||||
messagesize = msgsz;
|
||||
if(messagesize == 0){
|
||||
messagesize = iounit(netfd);
|
||||
if(messagesize == 0)
|
||||
messagesize = 8192+IOHDRSZ;
|
||||
}
|
||||
|
||||
Workq = emallocz(sizeof(Fsrpc)*Nr_workbufs);
|
||||
// for(i=0; i<Nr_workbufs; i++)
|
||||
// Workq[i].buf = emallocz(messagesize);
|
||||
fhash = emallocz(sizeof(Fid*)*FHASHSIZE);
|
||||
|
||||
fmtinstall('F', fcallfmt);
|
||||
|
||||
initroot();
|
||||
|
||||
DEBUG(DFD, "exportfs: %s\n", buf);
|
||||
|
||||
/*
|
||||
* Start serving file requests from the network
|
||||
*/
|
||||
for(;;) {
|
||||
r = getsbuf();
|
||||
if(r == 0)
|
||||
fatal("Out of service buffers");
|
||||
|
||||
DEBUG(DFD, "read9p...");
|
||||
n = read9pmsg(netfd, r->buf, messagesize);
|
||||
if(n <= 0)
|
||||
fatal(nil);
|
||||
|
||||
if(convM2S(r->buf, n, &r->work) == 0)
|
||||
fatal("convM2S format error");
|
||||
|
||||
DEBUG(DFD, "%F\n", &r->work);
|
||||
(fcalls[r->work.type])(r);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
reply(Fcall *r, Fcall *t, char *err)
|
||||
{
|
||||
uchar *data;
|
||||
int m, n;
|
||||
|
||||
t->tag = r->tag;
|
||||
t->fid = r->fid;
|
||||
if(err) {
|
||||
t->type = Rerror;
|
||||
t->ename = err;
|
||||
}
|
||||
else
|
||||
t->type = r->type + 1;
|
||||
|
||||
DEBUG(DFD, "\t%F\n", t);
|
||||
|
||||
data = malloc(messagesize); /* not mallocz; no need to clear */
|
||||
if(data == nil)
|
||||
fatal(Enomem);
|
||||
n = convS2M(t, data, messagesize);
|
||||
if((m=write(netfd, data, n))!=n){
|
||||
fprint(2, "wrote %d got %d (%r)\n", n, m);
|
||||
fatal("write");
|
||||
}
|
||||
free(data);
|
||||
}
|
||||
|
||||
Fid *
|
||||
getfid(int nr)
|
||||
{
|
||||
Fid *f;
|
||||
|
||||
for(f = fidhash(nr); f; f = f->next)
|
||||
if(f->nr == nr)
|
||||
return f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
freefid(int nr)
|
||||
{
|
||||
Fid *f, **l;
|
||||
char buf[128];
|
||||
|
||||
l = &fidhash(nr);
|
||||
for(f = *l; f; f = f->next) {
|
||||
if(f->nr == nr) {
|
||||
if(f->mid) {
|
||||
sprint(buf, "/mnt/exportfs/%d", f->mid);
|
||||
unmount(0, buf);
|
||||
psmap[f->mid] = 0;
|
||||
}
|
||||
if(f->f) {
|
||||
freefile(f->f);
|
||||
f->f = nil;
|
||||
}
|
||||
*l = f->next;
|
||||
f->next = fidfree;
|
||||
fidfree = f;
|
||||
return 1;
|
||||
}
|
||||
l = &f->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Fid *
|
||||
newfid(int nr)
|
||||
{
|
||||
Fid *new, **l;
|
||||
int i;
|
||||
|
||||
l = &fidhash(nr);
|
||||
for(new = *l; new; new = new->next)
|
||||
if(new->nr == nr)
|
||||
return 0;
|
||||
|
||||
if(fidfree == 0) {
|
||||
fidfree = emallocz(sizeof(Fid) * Fidchunk);
|
||||
|
||||
for(i = 0; i < Fidchunk-1; i++)
|
||||
fidfree[i].next = &fidfree[i+1];
|
||||
|
||||
fidfree[Fidchunk-1].next = 0;
|
||||
}
|
||||
|
||||
new = fidfree;
|
||||
fidfree = new->next;
|
||||
|
||||
memset(new, 0, sizeof(Fid));
|
||||
new->next = *l;
|
||||
*l = new;
|
||||
new->nr = nr;
|
||||
new->fid = -1;
|
||||
new->mid = 0;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
Fsrpc *
|
||||
getsbuf(void)
|
||||
{
|
||||
static int ap;
|
||||
int look, rounds;
|
||||
Fsrpc *wb;
|
||||
int small_instead_of_fast = 1;
|
||||
|
||||
if(small_instead_of_fast)
|
||||
ap = 0; /* so we always start looking at the beginning and reuse buffers */
|
||||
|
||||
for(rounds = 0; rounds < 10; rounds++) {
|
||||
for(look = 0; look < Nr_workbufs; look++) {
|
||||
if(++ap == Nr_workbufs)
|
||||
ap = 0;
|
||||
if(Workq[ap].busy == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if(look == Nr_workbufs){
|
||||
sleep(10 * rounds);
|
||||
continue;
|
||||
}
|
||||
|
||||
wb = &Workq[ap];
|
||||
wb->pid = 0;
|
||||
wb->canint = 0;
|
||||
wb->flushtag = NOTAG;
|
||||
wb->busy = 1;
|
||||
if(wb->buf == nil) /* allocate buffers dynamically to keep size down */
|
||||
wb->buf = emallocz(messagesize);
|
||||
return wb;
|
||||
}
|
||||
fatal("No more work buffers");
|
||||
return nil;
|
||||
}
|
||||
|
||||
void
|
||||
freefile(File *f)
|
||||
{
|
||||
File *parent, *child;
|
||||
|
||||
Loop:
|
||||
f->ref--;
|
||||
if(f->ref > 0)
|
||||
return;
|
||||
freecnt++;
|
||||
if(f->ref < 0) abort();
|
||||
DEBUG(DFD, "free %s\n", f->name);
|
||||
/* delete from parent */
|
||||
parent = f->parent;
|
||||
if(parent->child == f)
|
||||
parent->child = f->childlist;
|
||||
else{
|
||||
for(child=parent->child; child->childlist!=f; child=child->childlist)
|
||||
if(child->childlist == nil)
|
||||
fatal("bad child list");
|
||||
child->childlist = f->childlist;
|
||||
}
|
||||
freeqid(f->qidt);
|
||||
free(f->name);
|
||||
f->name = nil;
|
||||
free(f);
|
||||
f = parent;
|
||||
if(f != nil)
|
||||
goto Loop;
|
||||
}
|
||||
|
||||
File *
|
||||
file(File *parent, char *name)
|
||||
{
|
||||
Dir *dir;
|
||||
char *path;
|
||||
File *f;
|
||||
|
||||
DEBUG(DFD, "\tfile: 0x%p %s name %s\n", parent, parent->name, name);
|
||||
|
||||
path = makepath(parent, name);
|
||||
dir = dirstat(path);
|
||||
free(path);
|
||||
if(dir == nil)
|
||||
return nil;
|
||||
|
||||
for(f = parent->child; f; f = f->childlist)
|
||||
if(strcmp(name, f->name) == 0)
|
||||
break;
|
||||
|
||||
if(f == nil){
|
||||
f = emallocz(sizeof(File));
|
||||
f->name = estrdup(name);
|
||||
|
||||
f->parent = parent;
|
||||
f->childlist = parent->child;
|
||||
parent->child = f;
|
||||
parent->ref++;
|
||||
f->ref = 0;
|
||||
filecnt++;
|
||||
}
|
||||
f->ref++;
|
||||
f->qid.type = dir->qid.type;
|
||||
f->qid.vers = dir->qid.vers;
|
||||
f->qidt = uniqueqid(dir);
|
||||
f->qid.path = f->qidt->uniqpath;
|
||||
|
||||
f->inval = 0;
|
||||
|
||||
free(dir);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
void
|
||||
initroot(void)
|
||||
{
|
||||
Dir *dir;
|
||||
|
||||
root = emallocz(sizeof(File));
|
||||
root->name = estrdup(".");
|
||||
|
||||
dir = dirstat(root->name);
|
||||
if(dir == nil)
|
||||
fatal("root stat");
|
||||
|
||||
root->ref = 1;
|
||||
root->qid.vers = dir->qid.vers;
|
||||
root->qidt = uniqueqid(dir);
|
||||
root->qid.path = root->qidt->uniqpath;
|
||||
root->qid.type = QTDIR;
|
||||
free(dir);
|
||||
|
||||
psmpt = emallocz(sizeof(File));
|
||||
psmpt->name = estrdup("/");
|
||||
|
||||
dir = dirstat(psmpt->name);
|
||||
if(dir == nil)
|
||||
return;
|
||||
|
||||
psmpt->ref = 1;
|
||||
psmpt->qid.vers = dir->qid.vers;
|
||||
psmpt->qidt = uniqueqid(dir);
|
||||
psmpt->qid.path = psmpt->qidt->uniqpath;
|
||||
free(dir);
|
||||
|
||||
psmpt = file(psmpt, "mnt");
|
||||
if(psmpt == 0)
|
||||
return;
|
||||
psmpt = file(psmpt, "exportfs");
|
||||
}
|
||||
|
||||
char*
|
||||
makepath(File *p, char *name)
|
||||
{
|
||||
int i, n;
|
||||
char *c, *s, *path, *seg[256];
|
||||
|
||||
seg[0] = name;
|
||||
n = strlen(name)+2;
|
||||
for(i = 1; i < 256 && p; i++, p = p->parent){
|
||||
seg[i] = p->name;
|
||||
n += strlen(p->name)+1;
|
||||
}
|
||||
path = malloc(n);
|
||||
if(path == nil)
|
||||
fatal("out of memory");
|
||||
s = path;
|
||||
|
||||
while(i--) {
|
||||
for(c = seg[i]; *c; c++)
|
||||
*s++ = *c;
|
||||
*s++ = '/';
|
||||
}
|
||||
while(s[-1] == '/')
|
||||
s--;
|
||||
*s = '\0';
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
int
|
||||
qidhash(vlong path)
|
||||
{
|
||||
int h, n;
|
||||
|
||||
h = 0;
|
||||
for(n=0; n<64; n+=Nqidbits){
|
||||
h ^= path;
|
||||
path >>= Nqidbits;
|
||||
}
|
||||
return h & (Nqidtab-1);
|
||||
}
|
||||
|
||||
void
|
||||
freeqid(Qidtab *q)
|
||||
{
|
||||
ulong h;
|
||||
Qidtab *l;
|
||||
|
||||
q->ref--;
|
||||
if(q->ref > 0)
|
||||
return;
|
||||
qfreecnt++;
|
||||
h = qidhash(q->path);
|
||||
if(qidtab[h] == q)
|
||||
qidtab[h] = q->next;
|
||||
else{
|
||||
for(l=qidtab[h]; l->next!=q; l=l->next)
|
||||
if(l->next == nil)
|
||||
fatal("bad qid list");
|
||||
l->next = q->next;
|
||||
}
|
||||
free(q);
|
||||
}
|
||||
|
||||
Qidtab*
|
||||
qidlookup(Dir *d)
|
||||
{
|
||||
ulong h;
|
||||
Qidtab *q;
|
||||
|
||||
h = qidhash(d->qid.path);
|
||||
for(q=qidtab[h]; q!=nil; q=q->next)
|
||||
if(q->type==d->type && q->dev==d->dev && q->path==d->qid.path)
|
||||
return q;
|
||||
return nil;
|
||||
}
|
||||
|
||||
int
|
||||
qidexists(vlong path)
|
||||
{
|
||||
int h;
|
||||
Qidtab *q;
|
||||
|
||||
for(h=0; h<Nqidtab; h++)
|
||||
for(q=qidtab[h]; q!=nil; q=q->next)
|
||||
if(q->uniqpath == path)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
Qidtab*
|
||||
uniqueqid(Dir *d)
|
||||
{
|
||||
ulong h;
|
||||
vlong path;
|
||||
Qidtab *q;
|
||||
|
||||
q = qidlookup(d);
|
||||
if(q != nil){
|
||||
q->ref++;
|
||||
return q;
|
||||
}
|
||||
path = d->qid.path;
|
||||
while(qidexists(path)){
|
||||
DEBUG(DFD, "collision on %s\n", d->name);
|
||||
/* collision: find a new one */
|
||||
ncollision++;
|
||||
path &= QIDPATH;
|
||||
++newqid;
|
||||
if(newqid >= (1<<16)){
|
||||
DEBUG(DFD, "collision wraparound\n");
|
||||
newqid = 1;
|
||||
}
|
||||
path |= newqid<<48;
|
||||
DEBUG(DFD, "assign qid %.16llux\n", path);
|
||||
}
|
||||
q = mallocz(sizeof(Qidtab), 1);
|
||||
if(q == nil)
|
||||
fatal("no memory for qid table");
|
||||
qidcnt++;
|
||||
q->ref = 1;
|
||||
q->type = d->type;
|
||||
q->dev = d->dev;
|
||||
q->path = d->qid.path;
|
||||
q->uniqpath = path;
|
||||
h = qidhash(d->qid.path);
|
||||
q->next = qidtab[h];
|
||||
qidtab[h] = q;
|
||||
return q;
|
||||
}
|
||||
|
||||
void
|
||||
fatal(char *s, ...)
|
||||
{
|
||||
char buf[ERRMAX];
|
||||
va_list arg;
|
||||
Proc *m;
|
||||
|
||||
if (s) {
|
||||
va_start(arg, s);
|
||||
vsnprint(buf, ERRMAX, s, arg);
|
||||
va_end(arg);
|
||||
}
|
||||
|
||||
/* Clear away the slave children */
|
||||
// for(m = Proclist; m; m = m->next)
|
||||
// postnote(PNPROC, m->pid, "kill");
|
||||
|
||||
DEBUG(DFD, "%s\n", buf);
|
||||
if (s)
|
||||
sysfatal(buf);
|
||||
else
|
||||
exits(nil);
|
||||
}
|
||||
|
148
exportfs/exportfs.h
Normal file
148
exportfs/exportfs.h
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* exportfs.h - definitions for exporting file server
|
||||
*/
|
||||
|
||||
#define DEBUG if(!dbg){}else fprint
|
||||
#define DFD 2
|
||||
#define fidhash(s) fhash[s%FHASHSIZE]
|
||||
|
||||
#define Proc Exproc
|
||||
|
||||
|
||||
typedef struct Fsrpc Fsrpc;
|
||||
typedef struct Fid Fid;
|
||||
typedef struct File File;
|
||||
typedef struct Proc Proc;
|
||||
typedef struct Qidtab Qidtab;
|
||||
|
||||
struct Fsrpc
|
||||
{
|
||||
int busy; /* Work buffer has pending rpc to service */
|
||||
int pid; /* Pid of slave process executing the rpc */
|
||||
int canint; /* Interrupt gate */
|
||||
int flushtag; /* Tag on which to reply to flush */
|
||||
Fcall work; /* Plan 9 incoming Fcall */
|
||||
uchar *buf; /* Data buffer */
|
||||
};
|
||||
|
||||
struct Fid
|
||||
{
|
||||
int fid; /* system fd for i/o */
|
||||
File *f; /* File attached to this fid */
|
||||
int mode;
|
||||
int nr; /* fid number */
|
||||
int mid; /* Mount id */
|
||||
Fid *next; /* hash link */
|
||||
};
|
||||
|
||||
struct File
|
||||
{
|
||||
char *name;
|
||||
int ref;
|
||||
Qid qid;
|
||||
Qidtab *qidt;
|
||||
int inval;
|
||||
File *parent;
|
||||
File *child;
|
||||
File *childlist;
|
||||
};
|
||||
|
||||
struct Proc
|
||||
{
|
||||
int pid;
|
||||
int busy;
|
||||
Proc *next;
|
||||
};
|
||||
|
||||
struct Qidtab
|
||||
{
|
||||
int ref;
|
||||
int type;
|
||||
int dev;
|
||||
vlong path;
|
||||
vlong uniqpath;
|
||||
Qidtab *next;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MAXPROC = 50,
|
||||
FHASHSIZE = 64,
|
||||
Nr_workbufs = 50,
|
||||
Fidchunk = 1000,
|
||||
Npsmpt = 32,
|
||||
Nqidbits = 5,
|
||||
Nqidtab = (1<<Nqidbits),
|
||||
};
|
||||
|
||||
#define Enomem Exenomem
|
||||
#define Ebadfix Exebadfid
|
||||
#define Enotdir Exenotdir
|
||||
#define Edupfid Exedupfid
|
||||
#define Eopen Exeopen
|
||||
#define Exmnt Exexmnt
|
||||
#define Emip Exemip
|
||||
#define Enopsmt Exenopsmt
|
||||
|
||||
extern char Ebadfid[];
|
||||
extern char Enotdir[];
|
||||
extern char Edupfid[];
|
||||
extern char Eopen[];
|
||||
extern char Exmnt[];
|
||||
extern char Enomem[];
|
||||
extern char Emip[];
|
||||
extern char Enopsmt[];
|
||||
|
||||
Extern Fsrpc *Workq;
|
||||
Extern int dbg;
|
||||
Extern File *root;
|
||||
Extern File *psmpt;
|
||||
Extern Fid **fhash;
|
||||
Extern Fid *fidfree;
|
||||
Extern Proc *Proclist;
|
||||
Extern char psmap[Npsmpt];
|
||||
Extern Qidtab *qidtab[Nqidtab];
|
||||
Extern ulong messagesize;
|
||||
Extern int srvfd;
|
||||
|
||||
/* File system protocol service procedures */
|
||||
void Xattach(Fsrpc*);
|
||||
void Xauth(Fsrpc*);
|
||||
void Xclunk(Fsrpc*);
|
||||
void Xcreate(Fsrpc*);
|
||||
void Xflush(Fsrpc*);
|
||||
void Xnop(Fsrpc*);
|
||||
void Xremove(Fsrpc*);
|
||||
void Xstat(Fsrpc*);
|
||||
void Xversion(Fsrpc*);
|
||||
void Xwalk(Fsrpc*);
|
||||
void Xwstat(Fsrpc*);
|
||||
void slave(Fsrpc*);
|
||||
|
||||
void reply(Fcall*, Fcall*, char*);
|
||||
Fid *getfid(int);
|
||||
int freefid(int);
|
||||
Fid *newfid(int);
|
||||
Fsrpc *getsbuf(void);
|
||||
void initroot(void);
|
||||
void fatal(char*, ...);
|
||||
char* makepath(File*, char*);
|
||||
File *file(File*, char*);
|
||||
void freefile(File*);
|
||||
void slaveopen(Fsrpc*);
|
||||
void slaveread(Fsrpc*);
|
||||
void slavewrite(Fsrpc*);
|
||||
void blockingslave(void*);
|
||||
void reopen(Fid *f);
|
||||
void noteproc(int, char*);
|
||||
void flushaction(void*, char*);
|
||||
void pushfcall(char*);
|
||||
Qidtab* uniqueqid(Dir*);
|
||||
void freeqid(Qidtab*);
|
||||
char* estrdup(char*);
|
||||
void* emallocz(uint);
|
||||
int readmessage(int, char*, int);
|
||||
|
||||
#define notify
|
||||
#define noted
|
||||
#define exits
|
679
exportfs/exportsrv.c
Normal file
679
exportfs/exportsrv.c
Normal file
@ -0,0 +1,679 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <fcall.h>
|
||||
#define Extern extern
|
||||
#include "exportfs.h"
|
||||
|
||||
char Ebadfid[] = "Bad fid";
|
||||
char Enotdir[] = "Not a directory";
|
||||
char Edupfid[] = "Fid already in use";
|
||||
char Eopen[] = "Fid already opened";
|
||||
char Exmnt[] = "Cannot .. past mount point";
|
||||
char Emip[] = "Mount in progress";
|
||||
char Enopsmt[] = "Out of pseudo mount points";
|
||||
char Enomem[] = "No memory";
|
||||
char Eversion[] = "Bad 9P2000 version";
|
||||
|
||||
int iounit(int x)
|
||||
{
|
||||
return 8192+IOHDRSZ;
|
||||
}
|
||||
|
||||
void*
|
||||
emallocz(ulong n)
|
||||
{
|
||||
void *v;
|
||||
|
||||
v = mallocz(n, 1);
|
||||
if(v == nil)
|
||||
panic("out of memory");
|
||||
return v;
|
||||
}
|
||||
|
||||
ulong messagesize;
|
||||
|
||||
void
|
||||
Xversion(Fsrpc *t)
|
||||
{
|
||||
Fcall rhdr;
|
||||
|
||||
if(t->work.msize > messagesize)
|
||||
t->work.msize = messagesize;
|
||||
messagesize = t->work.msize;
|
||||
if(strncmp(t->work.version, "9P2000", 6) != 0){
|
||||
reply(&t->work, &rhdr, Eversion);
|
||||
return;
|
||||
}
|
||||
rhdr.version = "9P2000";
|
||||
rhdr.msize = t->work.msize;
|
||||
reply(&t->work, &rhdr, 0);
|
||||
t->busy = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Xauth(Fsrpc *t)
|
||||
{
|
||||
Fcall rhdr;
|
||||
|
||||
reply(&t->work, &rhdr, "exportfs: authentication not required");
|
||||
t->busy = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Xflush(Fsrpc *t)
|
||||
{
|
||||
Fsrpc *w, *e;
|
||||
Fcall rhdr;
|
||||
|
||||
e = &Workq[Nr_workbufs];
|
||||
|
||||
for(w = Workq; w < e; w++) {
|
||||
if(w->work.tag == t->work.oldtag) {
|
||||
DEBUG(DFD, "\tQ busy %d pid %d can %d\n", w->busy, w->pid, w->canint);
|
||||
if(w->busy && w->pid) {
|
||||
w->flushtag = t->work.tag;
|
||||
DEBUG(DFD, "\tset flushtag %d\n", t->work.tag);
|
||||
// if(w->canint)
|
||||
// postnote(PNPROC, w->pid, "flush");
|
||||
t->busy = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reply(&t->work, &rhdr, 0);
|
||||
DEBUG(DFD, "\tflush reply\n");
|
||||
t->busy = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Xattach(Fsrpc *t)
|
||||
{
|
||||
int i, nfd;
|
||||
Fcall rhdr;
|
||||
Fid *f;
|
||||
char buf[128];
|
||||
|
||||
f = newfid(t->work.fid);
|
||||
if(f == 0) {
|
||||
reply(&t->work, &rhdr, Ebadfid);
|
||||
t->busy = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(srvfd >= 0){
|
||||
/*
|
||||
if(psmpt == 0){
|
||||
Nomount:
|
||||
reply(&t->work, &rhdr, Enopsmt);
|
||||
t->busy = 0;
|
||||
freefid(t->work.fid);
|
||||
return;
|
||||
}
|
||||
for(i=0; i<Npsmpt; i++)
|
||||
if(psmap[i] == 0)
|
||||
break;
|
||||
if(i >= Npsmpt)
|
||||
goto Nomount;
|
||||
sprint(buf, "%d", i);
|
||||
f->f = file(psmpt, buf);
|
||||
if(f->f == nil)
|
||||
goto Nomount;
|
||||
sprint(buf, "/mnt/exportfs/%d", i);
|
||||
nfd = dup(srvfd, -1);
|
||||
if(amount(nfd, buf, MREPL|MCREATE, t->work.aname) < 0){
|
||||
errstr(buf, sizeof buf);
|
||||
reply(&t->work, &rhdr, buf);
|
||||
t->busy = 0;
|
||||
freefid(t->work.fid);
|
||||
close(nfd);
|
||||
return;
|
||||
}
|
||||
psmap[i] = 1;
|
||||
f->mid = i;
|
||||
*/
|
||||
}else{
|
||||
f->f = root;
|
||||
f->f->ref++;
|
||||
}
|
||||
|
||||
rhdr.qid = f->f->qid;
|
||||
reply(&t->work, &rhdr, 0);
|
||||
t->busy = 0;
|
||||
}
|
||||
|
||||
Fid*
|
||||
clonefid(Fid *f, int new)
|
||||
{
|
||||
Fid *n;
|
||||
|
||||
n = newfid(new);
|
||||
if(n == 0) {
|
||||
n = getfid(new);
|
||||
if(n == 0)
|
||||
fatal("inconsistent fids");
|
||||
if(n->fid >= 0)
|
||||
close(n->fid);
|
||||
freefid(new);
|
||||
n = newfid(new);
|
||||
if(n == 0)
|
||||
fatal("inconsistent fids2");
|
||||
}
|
||||
n->f = f->f;
|
||||
n->f->ref++;
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
Xwalk(Fsrpc *t)
|
||||
{
|
||||
char err[ERRMAX], *e;
|
||||
Fcall rhdr;
|
||||
Fid *f, *nf;
|
||||
File *wf;
|
||||
int i;
|
||||
|
||||
f = getfid(t->work.fid);
|
||||
if(f == 0) {
|
||||
reply(&t->work, &rhdr, Ebadfid);
|
||||
t->busy = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
nf = nil;
|
||||
if(t->work.newfid != t->work.fid){
|
||||
nf = clonefid(f, t->work.newfid);
|
||||
f = nf;
|
||||
}
|
||||
|
||||
rhdr.nwqid = 0;
|
||||
e = nil;
|
||||
for(i=0; i<t->work.nwname; i++){
|
||||
if(i == MAXWELEM){
|
||||
e = "Too many path elements";
|
||||
break;
|
||||
}
|
||||
|
||||
if(strcmp(t->work.wname[i], "..") == 0) {
|
||||
if(f->f->parent == nil) {
|
||||
e = Exmnt;
|
||||
break;
|
||||
}
|
||||
wf = f->f->parent;
|
||||
wf->ref++;
|
||||
goto Accept;
|
||||
}
|
||||
|
||||
wf = file(f->f, t->work.wname[i]);
|
||||
if(wf == 0){
|
||||
errstr(err, sizeof err);
|
||||
e = err;
|
||||
break;
|
||||
}
|
||||
Accept:
|
||||
freefile(f->f);
|
||||
rhdr.wqid[rhdr.nwqid++] = wf->qid;
|
||||
f->f = wf;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(nf!=nil && (e!=nil || rhdr.nwqid!=t->work.nwname))
|
||||
freefid(t->work.newfid);
|
||||
if(rhdr.nwqid > 0)
|
||||
e = nil;
|
||||
reply(&t->work, &rhdr, e);
|
||||
t->busy = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Xclunk(Fsrpc *t)
|
||||
{
|
||||
Fcall rhdr;
|
||||
Fid *f;
|
||||
|
||||
f = getfid(t->work.fid);
|
||||
if(f == 0) {
|
||||
reply(&t->work, &rhdr, Ebadfid);
|
||||
t->busy = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(f->fid >= 0)
|
||||
close(f->fid);
|
||||
|
||||
freefid(t->work.fid);
|
||||
reply(&t->work, &rhdr, 0);
|
||||
t->busy = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Xstat(Fsrpc *t)
|
||||
{
|
||||
char err[ERRMAX], *path;
|
||||
Fcall rhdr;
|
||||
Fid *f;
|
||||
Dir *d;
|
||||
int s;
|
||||
uchar *statbuf;
|
||||
|
||||
f = getfid(t->work.fid);
|
||||
if(f == 0) {
|
||||
reply(&t->work, &rhdr, Ebadfid);
|
||||
t->busy = 0;
|
||||
return;
|
||||
}
|
||||
if(f->fid >= 0)
|
||||
d = dirfstat(f->fid);
|
||||
else {
|
||||
path = makepath(f->f, "");
|
||||
d = dirstat(path);
|
||||
free(path);
|
||||
}
|
||||
|
||||
if(d == nil) {
|
||||
errstr(err, sizeof err);
|
||||
reply(&t->work, &rhdr, err);
|
||||
t->busy = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
d->qid.path = f->f->qidt->uniqpath;
|
||||
s = sizeD2M(d);
|
||||
statbuf = emallocz(s);
|
||||
s = convD2M(d, statbuf, s);
|
||||
free(d);
|
||||
rhdr.nstat = s;
|
||||
rhdr.stat = statbuf;
|
||||
reply(&t->work, &rhdr, 0);
|
||||
free(statbuf);
|
||||
t->busy = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
getiounit(int fd)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = iounit(fd);
|
||||
if(n > messagesize-IOHDRSZ)
|
||||
n = messagesize-IOHDRSZ;
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
Xcreate(Fsrpc *t)
|
||||
{
|
||||
char err[ERRMAX], *path;
|
||||
Fcall rhdr;
|
||||
Fid *f;
|
||||
File *nf;
|
||||
|
||||
f = getfid(t->work.fid);
|
||||
if(f == 0) {
|
||||
reply(&t->work, &rhdr, Ebadfid);
|
||||
t->busy = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
path = makepath(f->f, t->work.name);
|
||||
f->fid = create(path, t->work.mode, t->work.perm);
|
||||
free(path);
|
||||
if(f->fid < 0) {
|
||||
errstr(err, sizeof err);
|
||||
reply(&t->work, &rhdr, err);
|
||||
t->busy = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
nf = file(f->f, t->work.name);
|
||||
if(nf == 0) {
|
||||
errstr(err, sizeof err);
|
||||
reply(&t->work, &rhdr, err);
|
||||
t->busy = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
f->mode = t->work.mode;
|
||||
freefile(f->f);
|
||||
f->f = nf;
|
||||
rhdr.qid = f->f->qid;
|
||||
rhdr.iounit = getiounit(f->fid);
|
||||
reply(&t->work, &rhdr, 0);
|
||||
t->busy = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Xremove(Fsrpc *t)
|
||||
{
|
||||
char err[ERRMAX], *path;
|
||||
Fcall rhdr;
|
||||
Fid *f;
|
||||
|
||||
f = getfid(t->work.fid);
|
||||
if(f == 0) {
|
||||
reply(&t->work, &rhdr, Ebadfid);
|
||||
t->busy = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
path = makepath(f->f, "");
|
||||
DEBUG(DFD, "\tremove: %s\n", path);
|
||||
if(remove(path) < 0) {
|
||||
free(path);
|
||||
errstr(err, sizeof err);
|
||||
reply(&t->work, &rhdr, err);
|
||||
t->busy = 0;
|
||||
return;
|
||||
}
|
||||
free(path);
|
||||
|
||||
f->f->inval = 1;
|
||||
if(f->fid >= 0)
|
||||
close(f->fid);
|
||||
freefid(t->work.fid);
|
||||
|
||||
reply(&t->work, &rhdr, 0);
|
||||
t->busy = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Xwstat(Fsrpc *t)
|
||||
{
|
||||
char err[ERRMAX], *path;
|
||||
Fcall rhdr;
|
||||
Fid *f;
|
||||
int s;
|
||||
char *strings;
|
||||
Dir d;
|
||||
|
||||
f = getfid(t->work.fid);
|
||||
if(f == 0) {
|
||||
reply(&t->work, &rhdr, Ebadfid);
|
||||
t->busy = 0;
|
||||
return;
|
||||
}
|
||||
strings = emallocz(t->work.nstat); /* ample */
|
||||
if(convM2D(t->work.stat, t->work.nstat, &d, strings) < 0){
|
||||
rerrstr(err, sizeof err);
|
||||
reply(&t->work, &rhdr, err);
|
||||
t->busy = 0;
|
||||
free(strings);
|
||||
return;
|
||||
}
|
||||
|
||||
if(f->fid >= 0)
|
||||
s = dirfwstat(f->fid, &d);
|
||||
else {
|
||||
path = makepath(f->f, "");
|
||||
s = dirwstat(path, &d);
|
||||
free(path);
|
||||
}
|
||||
if(s < 0) {
|
||||
rerrstr(err, sizeof err);
|
||||
reply(&t->work, &rhdr, err);
|
||||
}
|
||||
else {
|
||||
/* wstat may really be rename */
|
||||
if(strcmp(d.name, f->f->name)!=0 && strcmp(d.name, "")!=0){
|
||||
free(f->f->name);
|
||||
f->f->name = estrdup(d.name);
|
||||
}
|
||||
reply(&t->work, &rhdr, 0);
|
||||
}
|
||||
free(strings);
|
||||
t->busy = 0;
|
||||
}
|
||||
|
||||
void
|
||||
slave(Fsrpc *f)
|
||||
{
|
||||
Proc *p;
|
||||
int pid;
|
||||
static int nproc;
|
||||
|
||||
for(;;) {
|
||||
for(p = Proclist; p; p = p->next) {
|
||||
if(p->busy == 0) {
|
||||
f->pid = p->pid;
|
||||
p->busy = 1;
|
||||
pid = rendezvous(p->pid, (ulong)f);
|
||||
if(pid != p->pid)
|
||||
fatal("rendezvous sync fail");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(++nproc > MAXPROC)
|
||||
fatal("too many procs");
|
||||
|
||||
pid = kproc("slave", blockingslave, nil);
|
||||
DEBUG(DFD, "slave pid %d\n", pid);
|
||||
if(pid == -1)
|
||||
fatal("kproc");
|
||||
|
||||
p = malloc(sizeof(Proc));
|
||||
if(p == 0)
|
||||
fatal("out of memory");
|
||||
|
||||
p->busy = 0;
|
||||
p->pid = pid;
|
||||
p->next = Proclist;
|
||||
Proclist = p;
|
||||
|
||||
DEBUG(DFD, "parent %d rendez\n", pid);
|
||||
rendezvous(pid, (ulong)p);
|
||||
DEBUG(DFD, "parent %d went\n", pid);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
blockingslave(void *x)
|
||||
{
|
||||
Fsrpc *p;
|
||||
Fcall rhdr;
|
||||
Proc *m;
|
||||
int pid;
|
||||
|
||||
USED(x);
|
||||
|
||||
notify(flushaction);
|
||||
|
||||
pid = getpid();
|
||||
|
||||
DEBUG(DFD, "blockingslave %d rendez\n", pid);
|
||||
m = (Proc*)rendezvous(pid, 0);
|
||||
DEBUG(DFD, "blockingslave %d rendez got %p\n", pid, m);
|
||||
|
||||
for(;;) {
|
||||
p = (Fsrpc*)rendezvous(pid, pid);
|
||||
if((int)p == ~0) /* Interrupted */
|
||||
continue;
|
||||
|
||||
DEBUG(DFD, "\tslave: %d %F b %d p %d\n", pid, &p->work, p->busy, p->pid);
|
||||
if(p->flushtag != NOTAG)
|
||||
goto flushme;
|
||||
|
||||
switch(p->work.type) {
|
||||
case Tread:
|
||||
slaveread(p);
|
||||
break;
|
||||
|
||||
case Twrite:
|
||||
slavewrite(p);
|
||||
break;
|
||||
|
||||
case Topen:
|
||||
slaveopen(p);
|
||||
break;
|
||||
|
||||
default:
|
||||
reply(&p->work, &rhdr, "exportfs: slave type error");
|
||||
}
|
||||
if(p->flushtag != NOTAG) {
|
||||
flushme:
|
||||
p->work.type = Tflush;
|
||||
p->work.tag = p->flushtag;
|
||||
reply(&p->work, &rhdr, 0);
|
||||
}
|
||||
p->busy = 0;
|
||||
m->busy = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
openmount(int sfd)
|
||||
{
|
||||
werrstr("openmount not implemented");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
slaveopen(Fsrpc *p)
|
||||
{
|
||||
char err[ERRMAX], *path;
|
||||
Fcall *work, rhdr;
|
||||
Fid *f;
|
||||
Dir *d;
|
||||
|
||||
work = &p->work;
|
||||
|
||||
f = getfid(work->fid);
|
||||
if(f == 0) {
|
||||
reply(work, &rhdr, Ebadfid);
|
||||
return;
|
||||
}
|
||||
if(f->fid >= 0) {
|
||||
close(f->fid);
|
||||
f->fid = -1;
|
||||
}
|
||||
|
||||
path = makepath(f->f, "");
|
||||
DEBUG(DFD, "\topen: %s %d\n", path, work->mode);
|
||||
|
||||
p->canint = 1;
|
||||
if(p->flushtag != NOTAG){
|
||||
free(path);
|
||||
return;
|
||||
}
|
||||
/* There is a race here I ignore because there are no locks */
|
||||
f->fid = open(path, work->mode);
|
||||
free(path);
|
||||
p->canint = 0;
|
||||
if(f->fid < 0 || (d = dirfstat(f->fid)) == nil) {
|
||||
Error:
|
||||
errstr(err, sizeof err);
|
||||
reply(work, &rhdr, err);
|
||||
return;
|
||||
}
|
||||
f->f->qid = d->qid;
|
||||
free(d);
|
||||
if(f->f->qid.type & QTMOUNT){ /* fork new exportfs for this */
|
||||
f->fid = openmount(f->fid);
|
||||
if(f->fid < 0)
|
||||
goto Error;
|
||||
}
|
||||
|
||||
DEBUG(DFD, "\topen: fd %d\n", f->fid);
|
||||
f->mode = work->mode;
|
||||
rhdr.iounit = getiounit(f->fid);
|
||||
rhdr.qid = f->f->qid;
|
||||
reply(work, &rhdr, 0);
|
||||
}
|
||||
|
||||
void
|
||||
slaveread(Fsrpc *p)
|
||||
{
|
||||
Fid *f;
|
||||
int n, r;
|
||||
Fcall *work, rhdr;
|
||||
char *data, err[ERRMAX];
|
||||
|
||||
work = &p->work;
|
||||
|
||||
f = getfid(work->fid);
|
||||
if(f == 0) {
|
||||
reply(work, &rhdr, Ebadfid);
|
||||
return;
|
||||
}
|
||||
|
||||
n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
|
||||
p->canint = 1;
|
||||
if(p->flushtag != NOTAG)
|
||||
return;
|
||||
data = malloc(n);
|
||||
if(data == nil)
|
||||
fatal(Enomem);
|
||||
|
||||
/* can't just call pread, since directories must update the offset */
|
||||
r = pread(f->fid, data, n, work->offset);
|
||||
p->canint = 0;
|
||||
if(r < 0) {
|
||||
free(data);
|
||||
errstr(err, sizeof err);
|
||||
reply(work, &rhdr, err);
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG(DFD, "\tread: fd=%d %d bytes\n", f->fid, r);
|
||||
|
||||
rhdr.data = data;
|
||||
rhdr.count = r;
|
||||
reply(work, &rhdr, 0);
|
||||
free(data);
|
||||
}
|
||||
|
||||
void
|
||||
slavewrite(Fsrpc *p)
|
||||
{
|
||||
char err[ERRMAX];
|
||||
Fcall *work, rhdr;
|
||||
Fid *f;
|
||||
int n;
|
||||
|
||||
work = &p->work;
|
||||
|
||||
f = getfid(work->fid);
|
||||
if(f == 0) {
|
||||
reply(work, &rhdr, Ebadfid);
|
||||
return;
|
||||
}
|
||||
|
||||
n = (work->count > messagesize-IOHDRSZ) ? messagesize-IOHDRSZ : work->count;
|
||||
p->canint = 1;
|
||||
if(p->flushtag != NOTAG)
|
||||
return;
|
||||
n = pwrite(f->fid, work->data, n, work->offset);
|
||||
p->canint = 0;
|
||||
if(n < 0) {
|
||||
errstr(err, sizeof err);
|
||||
reply(work, &rhdr, err);
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG(DFD, "\twrite: %d bytes fd=%d\n", n, f->fid);
|
||||
|
||||
rhdr.count = n;
|
||||
reply(work, &rhdr, 0);
|
||||
}
|
||||
|
||||
void
|
||||
reopen(Fid *f)
|
||||
{
|
||||
USED(f);
|
||||
fatal("reopen");
|
||||
}
|
||||
|
||||
void
|
||||
flushaction(void *a, char *cause)
|
||||
{
|
||||
USED(a);
|
||||
if(strncmp(cause, "sys:", 4) == 0 && !strstr(cause, "pipe")) {
|
||||
fprint(2, "exportsrv: note: %s\n", cause);
|
||||
exits("noted");
|
||||
}
|
||||
if(strncmp(cause, "kill", 4) == 0)
|
||||
noted(NDFLT);
|
||||
|
||||
noted(NCONT);
|
||||
}
|
11
exportfs/mkfile
Normal file
11
exportfs/mkfile
Normal file
@ -0,0 +1,11 @@
|
||||
<$DSRC/mkfile-$CONF
|
||||
TARG=libexportfs.$L
|
||||
|
||||
OFILES=\
|
||||
exportfs.$O\
|
||||
exportsrv.$O
|
||||
|
||||
HFILES=\
|
||||
exportfs.h
|
||||
|
||||
<$DSRC/mklib-$CONF
|
23
gui-win32/alloc.c
Normal file
23
gui-win32/alloc.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
|
||||
Memimage*
|
||||
allocmemimage(Rectangle r, ulong chan)
|
||||
{
|
||||
return _allocmemimage(r, chan);
|
||||
}
|
||||
|
||||
void
|
||||
freememimage(Memimage *i)
|
||||
{
|
||||
_freememimage(i);
|
||||
}
|
||||
|
||||
void
|
||||
memfillcolor(Memimage *i, ulong val)
|
||||
{
|
||||
_memfillcolor(i, val);
|
||||
}
|
||||
|
10
gui-win32/cload.c
Normal file
10
gui-win32/cload.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
|
||||
int
|
||||
cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
|
||||
{
|
||||
return _cloadmemimage(i, r, data, ndata);
|
||||
}
|
22
gui-win32/draw.c
Normal file
22
gui-win32/draw.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
|
||||
void
|
||||
memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp, Memimage *mask, Point mp, int op)
|
||||
{
|
||||
_memimagedraw(_memimagedrawsetup(dst, r, src, sp, mask, mp, op));
|
||||
}
|
||||
|
||||
ulong
|
||||
pixelbits(Memimage *m, Point p)
|
||||
{
|
||||
return _pixelbits(m, p);
|
||||
}
|
||||
|
||||
void
|
||||
memimageinit(void)
|
||||
{
|
||||
_memimageinit();
|
||||
}
|
10
gui-win32/load.c
Normal file
10
gui-win32/load.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
|
||||
int
|
||||
loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
|
||||
{
|
||||
return _loadmemimage(i, r, data, ndata);
|
||||
}
|
14
gui-win32/mkfile
Normal file
14
gui-win32/mkfile
Normal file
@ -0,0 +1,14 @@
|
||||
<$DSRC/mkfile-$CONF
|
||||
TARG=libgui.$L
|
||||
|
||||
OFILES=\
|
||||
alloc.$O\
|
||||
cload.$O\
|
||||
draw.$O\
|
||||
load.$O\
|
||||
screen.$O\
|
||||
wstrtoutf.$O
|
||||
|
||||
HFILES=\
|
||||
|
||||
<$DSRC/mklib-$CONF
|
642
gui-win32/screen.c
Normal file
642
gui-win32/screen.c
Normal file
@ -0,0 +1,642 @@
|
||||
#include <windows.h>
|
||||
// #include "winduhz.h"
|
||||
|
||||
#undef Rectangle
|
||||
#define Rectangle _Rectangle
|
||||
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <dat.h>
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
#include "error.h"
|
||||
#include "screen.h"
|
||||
#include "keyboard.h"
|
||||
#include "fns.h"
|
||||
|
||||
Memimage *gscreen;
|
||||
Screeninfo screen;
|
||||
|
||||
extern int mousequeue;
|
||||
static int depth;
|
||||
|
||||
static HINSTANCE inst;
|
||||
static HWND window;
|
||||
static HPALETTE palette;
|
||||
static LOGPALETTE *logpal;
|
||||
static Lock gdilock;
|
||||
static BITMAPINFO *bmi;
|
||||
static HCURSOR hcursor;
|
||||
|
||||
static void winproc(void *);
|
||||
static LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
|
||||
static void paletteinit(void);
|
||||
static void bmiinit(void);
|
||||
static void screenload2(Rectangle r, int ldepth, uchar *p, Point pt, int step);
|
||||
|
||||
static int readybit;
|
||||
static Rendez rend;
|
||||
|
||||
Point ZP;
|
||||
|
||||
static
|
||||
isready(void*a)
|
||||
{
|
||||
return readybit;
|
||||
}
|
||||
|
||||
void
|
||||
screeninit(void)
|
||||
{
|
||||
int fmt;
|
||||
int dx, dy;
|
||||
|
||||
memimageinit();
|
||||
if(depth == 0)
|
||||
depth = GetDeviceCaps(GetDC(NULL), BITSPIXEL);
|
||||
switch(depth){
|
||||
case 32:
|
||||
screen.dibtype = DIB_RGB_COLORS;
|
||||
screen.depth = 32;
|
||||
fmt = XRGB32;
|
||||
break;
|
||||
case 24:
|
||||
screen.dibtype = DIB_RGB_COLORS;
|
||||
screen.depth = 24;
|
||||
fmt = RGB24;
|
||||
break;
|
||||
case 16:
|
||||
screen.dibtype = DIB_RGB_COLORS;
|
||||
screen.depth = 16;
|
||||
fmt = RGB15; /* [sic] */
|
||||
break;
|
||||
case 8:
|
||||
default:
|
||||
screen.dibtype = DIB_PAL_COLORS;
|
||||
screen.depth = 8;
|
||||
depth = 8;
|
||||
fmt = CMAP8;
|
||||
break;
|
||||
}
|
||||
dx = GetDeviceCaps(GetDC(NULL), HORZRES);
|
||||
dy = GetDeviceCaps(GetDC(NULL), VERTRES);
|
||||
|
||||
gscreen = allocmemimage(Rect(0,0,dx,dy), fmt);
|
||||
kproc("winscreen", winproc, 0);
|
||||
sleep(&rend, isready, 0);
|
||||
}
|
||||
|
||||
uchar*
|
||||
attachscreen(Rectangle *r, ulong *chan, int *depth, int *width, int *softscreen, void **X)
|
||||
{
|
||||
*r = gscreen->r;
|
||||
*chan = gscreen->chan;
|
||||
*depth = gscreen->depth;
|
||||
*width = gscreen->width;
|
||||
*softscreen = 1;
|
||||
|
||||
return gscreen->data->bdata;
|
||||
}
|
||||
|
||||
void
|
||||
flushmemscreen(Rectangle r)
|
||||
{
|
||||
screenload(r, gscreen->depth, byteaddr(gscreen, ZP), ZP,
|
||||
gscreen->width*sizeof(ulong));
|
||||
// Sleep(100);
|
||||
}
|
||||
|
||||
void
|
||||
screenload(Rectangle r, int depth, uchar *p, Point pt, int step)
|
||||
{
|
||||
int dx, dy, delx;
|
||||
HDC hdc;
|
||||
RECT winr;
|
||||
|
||||
if(depth != gscreen->depth)
|
||||
panic("screenload: bad ldepth");
|
||||
|
||||
/*
|
||||
* Sometimes we do get rectangles that are off the
|
||||
* screen to the negative axes, for example, when
|
||||
* dragging around a window border in a Move operation.
|
||||
*/
|
||||
if(rectclip(&r, gscreen->r) == 0)
|
||||
return;
|
||||
|
||||
if(step&3 != 0 || ((pt.x*depth)%32) != 0 || (ulong)p&3 != 0)
|
||||
panic("screenload: bad params %d %d %ux", step, pt.x, p);
|
||||
dx = r.max.x - r.min.x;
|
||||
dy = r.max.y - r.min.y;
|
||||
|
||||
if(dx <= 0 || dy <= 0)
|
||||
return;
|
||||
|
||||
if(depth == 24)
|
||||
delx = r.min.x % 4;
|
||||
else
|
||||
delx = r.min.x & (31/depth);
|
||||
|
||||
p += (r.min.y-pt.y)*step;
|
||||
p += ((r.min.x-delx-pt.x)*depth)>>3;
|
||||
|
||||
if(GetWindowRect(window, &winr)==0)
|
||||
return;
|
||||
if(rectclip(&r, Rect(0, 0, winr.right-winr.left, winr.bottom-winr.top))==0)
|
||||
return;
|
||||
|
||||
lock(&gdilock);
|
||||
|
||||
hdc = GetDC(window);
|
||||
SelectPalette(hdc, palette, 0);
|
||||
RealizePalette(hdc);
|
||||
|
||||
//FillRect(hdc,(void*)&r, GetStockObject(BLACK_BRUSH));
|
||||
//GdiFlush();
|
||||
//Sleep(100);
|
||||
|
||||
bmi->bmiHeader.biWidth = (step*8)/depth;
|
||||
bmi->bmiHeader.biHeight = -dy; /* - => origin upper left */
|
||||
|
||||
StretchDIBits(hdc, r.min.x, r.min.y, dx, dy,
|
||||
delx, 0, dx, dy, p, bmi, screen.dibtype, SRCCOPY);
|
||||
|
||||
ReleaseDC(window, hdc);
|
||||
|
||||
GdiFlush();
|
||||
|
||||
unlock(&gdilock);
|
||||
}
|
||||
|
||||
static void
|
||||
winproc(void *a)
|
||||
{
|
||||
WNDCLASS wc;
|
||||
MSG msg;
|
||||
|
||||
inst = GetModuleHandle(NULL);
|
||||
|
||||
paletteinit();
|
||||
bmiinit();
|
||||
terminit();
|
||||
|
||||
wc.style = 0;
|
||||
wc.lpfnWndProc = WindowProc;
|
||||
wc.cbClsExtra = 0;
|
||||
wc.cbWndExtra = 0;
|
||||
wc.hInstance = inst;
|
||||
wc.hIcon = LoadIcon(inst, NULL);
|
||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
||||
wc.hbrBackground = GetStockObject(WHITE_BRUSH);
|
||||
wc.lpszMenuName = 0;
|
||||
wc.lpszClassName = "9pmgraphics";
|
||||
RegisterClass(&wc);
|
||||
|
||||
window = CreateWindowEx(
|
||||
0, /* extended style */
|
||||
"9pmgraphics", /* class */
|
||||
"drawterm screen", /* caption */
|
||||
WS_OVERLAPPEDWINDOW, /* style */
|
||||
CW_USEDEFAULT, /* init. x pos */
|
||||
CW_USEDEFAULT, /* init. y pos */
|
||||
CW_USEDEFAULT, /* init. x size */
|
||||
CW_USEDEFAULT, /* init. y size */
|
||||
NULL, /* parent window (actually owner window for overlapped)*/
|
||||
NULL, /* menu handle */
|
||||
inst, /* program handle */
|
||||
NULL /* create parms */
|
||||
);
|
||||
|
||||
if(window == nil)
|
||||
panic("can't make window\n");
|
||||
|
||||
ShowWindow(window, SW_SHOWDEFAULT);
|
||||
UpdateWindow(window);
|
||||
|
||||
readybit = 1;
|
||||
wakeup(&rend);
|
||||
|
||||
screen.reshaped = 0;
|
||||
|
||||
while(GetMessage(&msg, NULL, 0, 0)) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
// MessageBox(0, "winproc", "exits", MB_OK);
|
||||
ExitProcess(0);
|
||||
}
|
||||
|
||||
int
|
||||
col(int v, int n)
|
||||
{
|
||||
int i, c;
|
||||
|
||||
c = 0;
|
||||
for(i = 0; i < 8; i += n)
|
||||
c |= v << (16-(n+i));
|
||||
return c >> 8;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
paletteinit(void)
|
||||
{
|
||||
PALETTEENTRY *pal;
|
||||
int r, g, b, cr, cg, cb, v;
|
||||
int num, den;
|
||||
int i, j;
|
||||
|
||||
logpal = mallocz(sizeof(LOGPALETTE) + 256*sizeof(PALETTEENTRY), 1);
|
||||
if(logpal == nil)
|
||||
panic("out of memory");
|
||||
logpal->palVersion = 0x300;
|
||||
logpal->palNumEntries = 256;
|
||||
pal = logpal->palPalEntry;
|
||||
|
||||
for(r=0,i=0; r<4; r++) {
|
||||
for(v=0; v<4; v++,i+=16){
|
||||
for(g=0,j=v-r; g<4; g++) {
|
||||
for(b=0; b<4; b++,j++){
|
||||
den=r;
|
||||
if(g>den)
|
||||
den=g;
|
||||
if(b>den)
|
||||
den=b;
|
||||
/* divide check -- pick grey shades */
|
||||
if(den==0)
|
||||
cr=cg=cb=v*17;
|
||||
else{
|
||||
num=17*(4*den+v);
|
||||
cr=r*num/den;
|
||||
cg=g*num/den;
|
||||
cb=b*num/den;
|
||||
}
|
||||
pal[i+(j&15)].peRed = cr;
|
||||
pal[i+(j&15)].peGreen = cg;
|
||||
pal[i+(j&15)].peBlue = cb;
|
||||
pal[i+(j&15)].peFlags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
palette = CreatePalette(logpal);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
getcolor(ulong i, ulong *r, ulong *g, ulong *b)
|
||||
{
|
||||
PALETTEENTRY *pal;
|
||||
|
||||
pal = logpal->palPalEntry;
|
||||
*r = pal[i].peRed;
|
||||
*g = pal[i].peGreen;
|
||||
*b = pal[i].peBlue;
|
||||
}
|
||||
|
||||
void
|
||||
bmiinit(void)
|
||||
{
|
||||
ushort *p;
|
||||
int i;
|
||||
|
||||
bmi = mallocz(sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD), 1);
|
||||
if(bmi == 0)
|
||||
panic("out of memory");
|
||||
bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi->bmiHeader.biWidth = 0;
|
||||
bmi->bmiHeader.biHeight = 0; /* - => origin upper left */
|
||||
bmi->bmiHeader.biPlanes = 1;
|
||||
bmi->bmiHeader.biBitCount = depth;
|
||||
bmi->bmiHeader.biCompression = BI_RGB;
|
||||
bmi->bmiHeader.biSizeImage = 0;
|
||||
bmi->bmiHeader.biXPelsPerMeter = 0;
|
||||
bmi->bmiHeader.biYPelsPerMeter = 0;
|
||||
bmi->bmiHeader.biClrUsed = 0;
|
||||
bmi->bmiHeader.biClrImportant = 0; /* number of important colors: 0 means all */
|
||||
|
||||
p = (ushort*)bmi->bmiColors;
|
||||
for(i = 0; i < 256; i++)
|
||||
p[i] = i;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK
|
||||
WindowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
PAINTSTRUCT paint;
|
||||
HDC hdc;
|
||||
LONG x, y, b;
|
||||
int i;
|
||||
Rectangle r;
|
||||
|
||||
switch(msg) {
|
||||
case WM_CREATE:
|
||||
break;
|
||||
case WM_SETCURSOR:
|
||||
/* User set */
|
||||
if(hcursor != NULL) {
|
||||
SetCursor(hcursor);
|
||||
return 1;
|
||||
}
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_LBUTTONUP:
|
||||
case WM_MBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_LBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_RBUTTONDOWN:
|
||||
x = LOWORD(lparam);
|
||||
y = HIWORD(lparam);
|
||||
b = 0;
|
||||
if(wparam & MK_LBUTTON)
|
||||
b = 1;
|
||||
if(wparam & MK_MBUTTON)
|
||||
b |= 2;
|
||||
if(wparam & MK_RBUTTON) {
|
||||
if(wparam & MK_SHIFT)
|
||||
b |= 2;
|
||||
else
|
||||
b |= 4;
|
||||
}
|
||||
lock(&mouse.lk);
|
||||
i = mouse.wi;
|
||||
if(mousequeue) {
|
||||
if(i == mouse.ri || mouse.lastb != b || mouse.trans) {
|
||||
mouse.wi = (i+1)%Mousequeue;
|
||||
if(mouse.wi == mouse.ri)
|
||||
mouse.ri = (mouse.ri+1)%Mousequeue;
|
||||
mouse.trans = mouse.lastb != b;
|
||||
} else {
|
||||
i = (i-1+Mousequeue)%Mousequeue;
|
||||
}
|
||||
} else {
|
||||
mouse.wi = (i+1)%Mousequeue;
|
||||
mouse.ri = i;
|
||||
}
|
||||
mouse.queue[i].xy.x = x;
|
||||
mouse.queue[i].xy.y = y;
|
||||
mouse.queue[i].buttons = b;
|
||||
mouse.queue[i].msec = ticks();
|
||||
mouse.lastb = b;
|
||||
unlock(&mouse.lk);
|
||||
wakeup(&mouse.r);
|
||||
break;
|
||||
|
||||
case WM_CHAR:
|
||||
/* repeat count is lparam & 0xf */
|
||||
switch(wparam){
|
||||
case '\n':
|
||||
wparam = '\r';
|
||||
break;
|
||||
case '\r':
|
||||
wparam = '\n';
|
||||
break;
|
||||
}
|
||||
kbdputc(kbdq, wparam);
|
||||
break;
|
||||
|
||||
case WM_SYSKEYUP:
|
||||
break;
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_KEYDOWN:
|
||||
switch(wparam) {
|
||||
case VK_MENU:
|
||||
kbdputc(kbdq, Kalt);
|
||||
break;
|
||||
case VK_INSERT:
|
||||
kbdputc(kbdq, Kins);
|
||||
break;
|
||||
case VK_DELETE:
|
||||
// kbdputc(kbdq, Kdel);
|
||||
kbdputc(kbdq, 0x7f); // should have Kdel in keyboard.h
|
||||
break;
|
||||
case VK_UP:
|
||||
kbdputc(kbdq, Kup);
|
||||
break;
|
||||
case VK_DOWN:
|
||||
kbdputc(kbdq, Kdown);
|
||||
break;
|
||||
case VK_LEFT:
|
||||
kbdputc(kbdq, Kleft);
|
||||
break;
|
||||
case VK_RIGHT:
|
||||
kbdputc(kbdq, Kright);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
DestroyWindow(hwnd);
|
||||
break;
|
||||
|
||||
case WM_DESTROY:
|
||||
PostQuitMessage(0);
|
||||
break;
|
||||
|
||||
case WM_PALETTECHANGED:
|
||||
if((HWND)wparam == hwnd)
|
||||
break;
|
||||
/* fall through */
|
||||
case WM_QUERYNEWPALETTE:
|
||||
hdc = GetDC(hwnd);
|
||||
SelectPalette(hdc, palette, 0);
|
||||
if(RealizePalette(hdc) != 0)
|
||||
InvalidateRect(hwnd, nil, 0);
|
||||
ReleaseDC(hwnd, hdc);
|
||||
break;
|
||||
|
||||
case WM_PAINT:
|
||||
hdc = BeginPaint(hwnd, &paint);
|
||||
r.min.x = paint.rcPaint.left;
|
||||
r.min.y = paint.rcPaint.top;
|
||||
r.max.x = paint.rcPaint.right;
|
||||
r.max.y = paint.rcPaint.bottom;
|
||||
flushmemscreen(r);
|
||||
EndPaint(hwnd, &paint);
|
||||
break;
|
||||
case WM_COMMAND:
|
||||
case WM_SETFOCUS:
|
||||
case WM_DEVMODECHANGE:
|
||||
case WM_WININICHANGE:
|
||||
case WM_INITMENU:
|
||||
default:
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
mouseset(Point xy)
|
||||
{
|
||||
POINT pt;
|
||||
|
||||
pt.x = xy.x;
|
||||
pt.y = xy.y;
|
||||
MapWindowPoints(window, 0, &pt, 1);
|
||||
SetCursorPos(pt.x, pt.y);
|
||||
}
|
||||
|
||||
void
|
||||
setcursor(void)
|
||||
{
|
||||
HCURSOR nh;
|
||||
int x, y, h, w;
|
||||
uchar *sp, *cp;
|
||||
uchar *and, *xor;
|
||||
|
||||
h = GetSystemMetrics(SM_CYCURSOR);
|
||||
w = (GetSystemMetrics(SM_CXCURSOR)+7)/8;
|
||||
|
||||
and = mallocz(h*w, 1);
|
||||
memset(and, 0xff, h*w);
|
||||
xor = mallocz(h*w, 1);
|
||||
|
||||
lock(&cursor.lk);
|
||||
for(y=0,sp=cursor.set,cp=cursor.clr; y<16; y++) {
|
||||
for(x=0; x<2; x++) {
|
||||
and[y*w+x] = ~(*sp|*cp);
|
||||
xor[y*w+x] = ~*sp & *cp;
|
||||
cp++;
|
||||
sp++;
|
||||
}
|
||||
}
|
||||
nh = CreateCursor(inst, -cursor.offset.x, -cursor.offset.y,
|
||||
GetSystemMetrics(SM_CXCURSOR), h,
|
||||
and, xor);
|
||||
if(nh != NULL) {
|
||||
SetCursor(nh);
|
||||
if(hcursor != NULL)
|
||||
DestroyCursor(hcursor);
|
||||
hcursor = nh;
|
||||
}
|
||||
unlock(&cursor.lk);
|
||||
|
||||
free(and);
|
||||
free(xor);
|
||||
|
||||
PostMessage(window, WM_SETCURSOR, (int)window, 0);
|
||||
}
|
||||
|
||||
void
|
||||
cursorarrow(void)
|
||||
{
|
||||
if(hcursor != 0) {
|
||||
DestroyCursor(hcursor);
|
||||
hcursor = 0;
|
||||
}
|
||||
SetCursor(LoadCursor(0, IDC_ARROW));
|
||||
PostMessage(window, WM_SETCURSOR, (int)window, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
setcolor(ulong index, ulong red, ulong green, ulong blue)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
uchar*
|
||||
clipreadunicode(HANDLE h)
|
||||
{
|
||||
Rune *p;
|
||||
int n;
|
||||
uchar *q;
|
||||
|
||||
p = GlobalLock(h);
|
||||
n = wstrutflen(p)+1;
|
||||
q = malloc(n);
|
||||
wstrtoutf(q, p, n);
|
||||
GlobalUnlock(h);
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
uchar *
|
||||
clipreadutf(HANDLE h)
|
||||
{
|
||||
uchar *p;
|
||||
|
||||
p = GlobalLock(h);
|
||||
p = strdup(p);
|
||||
GlobalUnlock(h);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
uchar*
|
||||
clipread()
|
||||
{
|
||||
HANDLE h;
|
||||
uchar *p;
|
||||
|
||||
if(!OpenClipboard(window)) {
|
||||
oserror();
|
||||
return strdup("");
|
||||
}
|
||||
|
||||
if(h = GetClipboardData(CF_UNICODETEXT))
|
||||
p = clipreadunicode(h);
|
||||
else if(h = GetClipboardData(CF_TEXT))
|
||||
p = clipreadutf(h);
|
||||
else {
|
||||
oserror();
|
||||
p = strdup("");
|
||||
}
|
||||
|
||||
CloseClipboard();
|
||||
return p;
|
||||
}
|
||||
|
||||
int
|
||||
clipwrite(char *buf)
|
||||
{
|
||||
HANDLE h;
|
||||
char *p, *e;
|
||||
Rune *rp;
|
||||
int n = strlen(buf);
|
||||
|
||||
if(!OpenClipboard(window)) {
|
||||
oserror();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!EmptyClipboard()) {
|
||||
oserror();
|
||||
CloseClipboard();
|
||||
return -1;
|
||||
}
|
||||
|
||||
h = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, (n+1)*sizeof(Rune));
|
||||
if(h == NULL)
|
||||
panic("out of memory");
|
||||
rp = GlobalLock(h);
|
||||
p = buf;
|
||||
e = p+n;
|
||||
while(p<e)
|
||||
p += chartorune(rp++, p);
|
||||
*rp = 0;
|
||||
GlobalUnlock(h);
|
||||
|
||||
SetClipboardData(CF_UNICODETEXT, h);
|
||||
|
||||
h = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, n+1);
|
||||
if(h == NULL)
|
||||
panic("out of memory");
|
||||
p = GlobalLock(h);
|
||||
memcpy(p, buf, n);
|
||||
p[n] = 0;
|
||||
GlobalUnlock(h);
|
||||
|
||||
SetClipboardData(CF_TEXT, h);
|
||||
|
||||
CloseClipboard();
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
atlocalconsole(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
35
gui-win32/wstrtoutf.c
Normal file
35
gui-win32/wstrtoutf.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
|
||||
int
|
||||
wstrutflen(Rune *s)
|
||||
{
|
||||
int n;
|
||||
|
||||
for(n=0; *s; n+=runelen(*s),s++)
|
||||
;
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
wstrtoutf(char *s, Rune *t, int n)
|
||||
{
|
||||
int i;
|
||||
char *s0;
|
||||
|
||||
s0 = s;
|
||||
if(n <= 0)
|
||||
return wstrutflen(t)+1;
|
||||
while(*t) {
|
||||
if(n < UTFmax+1 && n < runelen(*t)+1) {
|
||||
*s = 0;
|
||||
return i+wstrutflen(t)+1;
|
||||
}
|
||||
i = runetochar(s, t);
|
||||
s += i;
|
||||
n -= i;
|
||||
t++;
|
||||
}
|
||||
*s = 0;
|
||||
return s-s0;
|
||||
}
|
20
gui-x11/Makefile
Normal file
20
gui-x11/Makefile
Normal file
@ -0,0 +1,20 @@
|
||||
LIB=libx11.a
|
||||
CC=gcc
|
||||
CFLAGS=-I../include -I. -I/usr/X11R6/include -I../kern -c -ggdb -D_THREAD_SAFE -pthread
|
||||
O=o
|
||||
|
||||
OFILES=\
|
||||
alloc.$O\
|
||||
cload.$O\
|
||||
draw.$O\
|
||||
load.$O\
|
||||
screen.$O\
|
||||
keysym2ucs-x11.$O
|
||||
|
||||
$(LIB): $(OFILES)
|
||||
ar r $(LIB) $(OFILES)
|
||||
ranlib $(LIB)
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $(CFLAGS) $*.c
|
||||
|
209
gui-x11/alloc.c
Normal file
209
gui-x11/alloc.c
Normal file
@ -0,0 +1,209 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
#include "xmem.h"
|
||||
|
||||
/* perfect approximation to NTSC = .299r+.587g+.114b when 0 ≤ r,g,b < 256 */
|
||||
#define RGB2K(r,g,b) ((156763*(r)+307758*(g)+59769*(b))>>19)
|
||||
|
||||
Memimage*
|
||||
xallocmemimage(Rectangle r, ulong chan, int pmid)
|
||||
{
|
||||
Memimage *m;
|
||||
Xmem *xm;
|
||||
XImage *xi;
|
||||
int offset;
|
||||
int d;
|
||||
|
||||
m = _allocmemimage(r, chan);
|
||||
if(chan != GREY1 && chan != xscreenchan)
|
||||
return m;
|
||||
|
||||
d = m->depth;
|
||||
xm = mallocz(sizeof(Xmem), 1);
|
||||
if(pmid != PMundef)
|
||||
xm->pmid = pmid;
|
||||
else
|
||||
xm->pmid = XCreatePixmap(xdisplay, xscreenid, Dx(r), Dy(r), (d==32) ? 24 : d);
|
||||
|
||||
if(m->depth == 24)
|
||||
offset = r.min.x&(4-1);
|
||||
else
|
||||
offset = r.min.x&(31/m->depth);
|
||||
r.min.x -= offset;
|
||||
|
||||
assert(wordsperline(r, m->depth) <= m->width);
|
||||
|
||||
xi = XCreateImage(xdisplay, xvis, m->depth==32?24:m->depth, ZPixmap, 0,
|
||||
(char*)m->data->bdata, Dx(r), Dy(r), 32, m->width*sizeof(ulong));
|
||||
|
||||
if(xi == nil){
|
||||
_freememimage(m);
|
||||
return nil;
|
||||
}
|
||||
|
||||
xm->xi = xi;
|
||||
xm->pc = getcallerpc(&r);
|
||||
xm->r = r;
|
||||
|
||||
/*
|
||||
* Set the parameters of the XImage so its memory looks exactly like a
|
||||
* Memimage, so we can call _memimagedraw on the same data. All frame
|
||||
* buffers we've seen, and Plan 9's graphics code, require big-endian
|
||||
* bits within bytes, but little endian byte order within pixels.
|
||||
*/
|
||||
xi->bitmap_unit = m->depth < 8 || m->depth == 24 ? 8 : m->depth;
|
||||
xi->byte_order = LSBFirst;
|
||||
xi->bitmap_bit_order = MSBFirst;
|
||||
xi->bitmap_pad = 32;
|
||||
xm->r = Rect(0,0,0,0);
|
||||
XInitImage(xi);
|
||||
XFlush(xdisplay);
|
||||
|
||||
m->X = xm;
|
||||
return m;
|
||||
}
|
||||
|
||||
Memimage*
|
||||
allocmemimage(Rectangle r, ulong chan)
|
||||
{
|
||||
return xallocmemimage(r, chan, PMundef);
|
||||
}
|
||||
|
||||
void
|
||||
freememimage(Memimage *m)
|
||||
{
|
||||
Xmem *xm;
|
||||
|
||||
if(m == nil)
|
||||
return;
|
||||
|
||||
if(m->data->ref == 1){
|
||||
if((xm = m->X) != nil){
|
||||
if(xm->xi){
|
||||
xm->xi->data = nil;
|
||||
XFree(xm->xi);
|
||||
}
|
||||
XFreePixmap(xdisplay, xm->pmid);
|
||||
free(xm);
|
||||
m->X = nil;
|
||||
}
|
||||
}
|
||||
_freememimage(m);
|
||||
}
|
||||
|
||||
void
|
||||
memfillcolor(Memimage *m, ulong val)
|
||||
{
|
||||
_memfillcolor(m, val);
|
||||
if(m->X){
|
||||
if((val & 0xFF) == 0xFF)
|
||||
xfillcolor(m, m->r, _rgbatoimg(m, val));
|
||||
else
|
||||
putXdata(m, m->r);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
addrect(Rectangle *rp, Rectangle r)
|
||||
{
|
||||
if(rp->min.x >= rp->max.x)
|
||||
*rp = r;
|
||||
else
|
||||
combinerect(rp, r);
|
||||
}
|
||||
|
||||
XImage*
|
||||
getXdata(Memimage *m, Rectangle r)
|
||||
{
|
||||
uchar *p;
|
||||
int x, y;
|
||||
Xmem *xm;
|
||||
Point xdelta, delta;
|
||||
Point tp;
|
||||
|
||||
xm = m->X;
|
||||
if(xm == nil)
|
||||
return;
|
||||
|
||||
assert(xm != nil && xm->xi != nil);
|
||||
|
||||
if(xm->dirty == 0)
|
||||
return xm->xi;
|
||||
|
||||
r = xm->dirtyr;
|
||||
if(Dx(r)==0 || Dy(r)==0)
|
||||
return xm->xi;
|
||||
|
||||
delta = subpt(r.min, m->r.min);
|
||||
tp = xm->r.min; /* avoid unaligned access on digital unix */
|
||||
xdelta = subpt(r.min, tp);
|
||||
|
||||
XGetSubImage(xdisplay, xm->pmid, delta.x, delta.y, Dx(r), Dy(r),
|
||||
AllPlanes, ZPixmap, xm->xi, xdelta.x, xdelta.y);
|
||||
|
||||
if(xtblbit && m->chan == CMAP8)
|
||||
for(y=r.min.y; y<r.max.y; y++)
|
||||
for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
|
||||
*p = x11toplan9[*p];
|
||||
|
||||
xm->dirty = 0;
|
||||
xm->dirtyr = Rect(0,0,0,0);
|
||||
return xm->xi;
|
||||
}
|
||||
|
||||
void
|
||||
putXdata(Memimage *m, Rectangle r)
|
||||
{
|
||||
Xmem *xm;
|
||||
XImage *xi;
|
||||
GC g;
|
||||
int offset;
|
||||
Point xdelta, delta;
|
||||
Point tp;
|
||||
int x, y;
|
||||
uchar *p;
|
||||
|
||||
xm = m->X;
|
||||
if(xm == nil)
|
||||
return;
|
||||
|
||||
assert(xm != nil);
|
||||
assert(xm->xi != nil);
|
||||
|
||||
xi = xm->xi;
|
||||
|
||||
g = (m->chan == GREY1) ? xgccopy0 : xgccopy;
|
||||
if(m->depth == 24)
|
||||
offset = r.min.x % 4;
|
||||
else
|
||||
offset = m->r.min.x & (31/m->depth);
|
||||
|
||||
delta = subpt(r.min, m->r.min);
|
||||
tp = xm->r.min; /* avoid unaligned access on digital unix */
|
||||
xdelta = subpt(r.min, tp);
|
||||
|
||||
if(xtblbit && m->chan == CMAP8)
|
||||
for(y=r.min.y; y<r.max.y; y++)
|
||||
for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
|
||||
*p = plan9tox11[*p];
|
||||
|
||||
XPutImage(xdisplay, xm->pmid, g, xi, xdelta.x, xdelta.y, delta.x, delta.y, Dx(r), Dy(r));
|
||||
|
||||
if(xtblbit && m->chan == CMAP8)
|
||||
for(y=r.min.y; y<r.max.y; y++)
|
||||
for(x=r.min.x, p=byteaddr(m, Pt(x,y)); x<r.max.x; x++, p++)
|
||||
*p = x11toplan9[*p];
|
||||
}
|
||||
|
||||
void
|
||||
dirtyXdata(Memimage *m, Rectangle r)
|
||||
{
|
||||
Xmem *xm;
|
||||
|
||||
if((xm = m->X) != nil){
|
||||
xm->dirty = 1;
|
||||
addrect(&xm->dirtyr, r);
|
||||
}
|
||||
}
|
16
gui-x11/cload.c
Normal file
16
gui-x11/cload.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
#include "xmem.h"
|
||||
|
||||
int
|
||||
cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = _cloadmemimage(i, r, data, ndata);
|
||||
if(n > 0 && i->X)
|
||||
putXdata(i, r);
|
||||
return n;
|
||||
}
|
189
gui-x11/draw.c
Normal file
189
gui-x11/draw.c
Normal file
@ -0,0 +1,189 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
#include "xmem.h"
|
||||
|
||||
void xfillcolor(Memimage*, Rectangle, ulong);
|
||||
static int xdraw(Memdrawparam*);
|
||||
|
||||
int xgcfillcolor = 0;
|
||||
int xgcfillcolor0 = 0;
|
||||
int xgczeropm = 0;
|
||||
int xgczeropm0 = 0;
|
||||
int xgcsimplecolor = 0;
|
||||
int xgcsimplecolor0 = 0;
|
||||
int xgcsimplepm = 0;
|
||||
int xgcsimplepm0 = 0;
|
||||
int xgcreplsrctile = 0;
|
||||
int xgcreplsrctile0 = 0;
|
||||
|
||||
void
|
||||
memimageinit(void)
|
||||
{
|
||||
static int didinit = 0;
|
||||
|
||||
if(didinit)
|
||||
return;
|
||||
|
||||
didinit = 1;
|
||||
_memimageinit();
|
||||
|
||||
xfillcolor(memblack, memblack->r, 0);
|
||||
xfillcolor(memwhite, memwhite->r, 1);
|
||||
}
|
||||
|
||||
void
|
||||
memimagedraw(Memimage *dst, Rectangle r, Memimage *src, Point sp, Memimage *mask, Point mp, int op)
|
||||
{
|
||||
int didx;
|
||||
Rectangle dr, mr, sr;
|
||||
Memdrawparam *par;
|
||||
|
||||
if((par = _memimagedrawsetup(dst, r, src, sp, mask, mp, op)) == nil)
|
||||
return;
|
||||
_memimagedraw(par);
|
||||
if(!xdraw(par))
|
||||
putXdata(dst, par->r);
|
||||
}
|
||||
|
||||
void
|
||||
xfillcolor(Memimage *m, Rectangle r, ulong v)
|
||||
{
|
||||
GC gc;
|
||||
Xmem *dxm;
|
||||
|
||||
dxm = m->X;
|
||||
assert(dxm != nil);
|
||||
r = rectsubpt(r, m->r.min);
|
||||
|
||||
if(m->chan == GREY1){
|
||||
gc = xgcfill0;
|
||||
if(xgcfillcolor0 != v){
|
||||
XSetForeground(xdisplay, gc, v);
|
||||
xgcfillcolor0 = v;
|
||||
}
|
||||
}else{
|
||||
if(m->chan == CMAP8 && xtblbit)
|
||||
v = plan9tox11[v];
|
||||
|
||||
gc = xgcfill;
|
||||
if(xgcfillcolor != v){
|
||||
XSetForeground(xdisplay, gc, v);
|
||||
xgcfillcolor = v;
|
||||
}
|
||||
}
|
||||
XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, Dx(r), Dy(r));
|
||||
}
|
||||
|
||||
static int
|
||||
xdraw(Memdrawparam *par)
|
||||
{
|
||||
int dy, dx;
|
||||
unsigned m;
|
||||
Memimage *src, *dst, *mask;
|
||||
Xmem *dxm, *sxm, *mxm;
|
||||
GC gc;
|
||||
Rectangle r, sr, mr;
|
||||
ulong sdval;
|
||||
|
||||
dx = Dx(par->r);
|
||||
dy = Dy(par->r);
|
||||
src = par->src;
|
||||
dst = par->dst;
|
||||
mask = par->mask;
|
||||
r = par->r;
|
||||
sr = par->sr;
|
||||
mr = par->mr;
|
||||
sdval = par->sdval;
|
||||
|
||||
return 0;
|
||||
if((dxm = dst->X) == nil)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If we have an opaque mask and source is one opaque pixel we can convert to the
|
||||
* destination format and just XFillRectangle.
|
||||
*/
|
||||
m = Simplesrc|Simplemask|Fullmask;
|
||||
if((par->state&m)==m){
|
||||
xfillcolor(dst, r, sdval);
|
||||
dirtyXdata(dst, par->r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no source alpha, an opaque mask, we can just copy the
|
||||
* source onto the destination. If the channels are the same and
|
||||
* the source is not replicated, XCopyArea suffices.
|
||||
*/
|
||||
m = Simplemask|Fullmask;
|
||||
if((par->state&(m|Replsrc))==m && src->chan == dst->chan && src->X){
|
||||
sxm = src->X;
|
||||
r = rectsubpt(r, dst->r.min);
|
||||
sr = rectsubpt(sr, src->r.min);
|
||||
if(dst->chan == GREY1)
|
||||
gc = xgccopy0;
|
||||
else
|
||||
gc = xgccopy;
|
||||
XCopyArea(xdisplay, sxm->pmid, dxm->pmid, gc,
|
||||
sr.min.x, sr.min.y, dx, dy, r.min.x, r.min.y);
|
||||
dirtyXdata(dst, par->r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* If no source alpha, a 1-bit mask, and a simple source
|
||||
* we can just copy through the mask onto the destination.
|
||||
*/
|
||||
if(dst->X && mask->X && !(mask->flags&Frepl)
|
||||
&& mask->chan == GREY1 && (par->state&Simplesrc)){
|
||||
Point p;
|
||||
|
||||
mxm = mask->X;
|
||||
r = rectsubpt(r, dst->r.min);
|
||||
mr = rectsubpt(mr, mask->r.min);
|
||||
p = subpt(r.min, mr.min);
|
||||
if(dst->chan == GREY1){
|
||||
gc = xgcsimplesrc0;
|
||||
if(xgcsimplecolor0 != sdval){
|
||||
XSetForeground(xdisplay, gc, sdval);
|
||||
xgcsimplecolor0 = sdval;
|
||||
}
|
||||
if(xgcsimplepm0 != mxm->pmid){
|
||||
XSetStipple(xdisplay, gc, mxm->pmid);
|
||||
xgcsimplepm0 = mxm->pmid;
|
||||
}
|
||||
}else{
|
||||
/* somehow this doesn't work on rob's mac
|
||||
gc = xgcsimplesrc;
|
||||
if(dst->chan == CMAP8 && xtblbit)
|
||||
sdval = plan9tox11[sdval];
|
||||
|
||||
if(xgcsimplecolor != sdval){
|
||||
XSetForeground(xdisplay, gc, sdval);
|
||||
xgcsimplecolor = sdval;
|
||||
}
|
||||
if(xgcsimplepm != mxm->pmid){
|
||||
XSetStipple(xdisplay, gc, mxm->pmid);
|
||||
xgcsimplepm = mxm->pmid;
|
||||
}
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
XSetTSOrigin(xdisplay, gc, p.x, p.y);
|
||||
XFillRectangle(xdisplay, dxm->pmid, gc, r.min.x, r.min.y, dx, dy);
|
||||
dirtyXdata(dst, par->r);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ulong
|
||||
pixelbits(Memimage *m, Point p)
|
||||
{
|
||||
Xmem *xm;
|
||||
if(m->X)
|
||||
getXdata(m, Rect(p.x, p.y, p.x+1, p.y+1));
|
||||
return _pixelbits(m, p);
|
||||
}
|
857
gui-x11/keysym2ucs-x11.c
Normal file
857
gui-x11/keysym2ucs-x11.c
Normal file
@ -0,0 +1,857 @@
|
||||
/* $XFree86: xc/programs/xterm/keysym2ucs.c,v 1.5 2001/06/18 19:09:26 dickey Exp $
|
||||
* This module converts keysym values into the corresponding ISO 10646
|
||||
* (UCS, Unicode) values.
|
||||
*
|
||||
* The array keysymtab[] contains pairs of X11 keysym values for graphical
|
||||
* characters and the corresponding Unicode value. The function
|
||||
* keysym2ucs() maps a keysym onto a Unicode value using a binary search,
|
||||
* therefore keysymtab[] must remain SORTED by keysym value.
|
||||
*
|
||||
* The keysym -> UTF-8 conversion will hopefully one day be provided
|
||||
* by Xlib via XmbLookupString() and should ideally not have to be
|
||||
* done in X applications. But we are not there yet.
|
||||
*
|
||||
* We allow to represent any UCS character in the range U-00000000 to
|
||||
* U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
|
||||
* This admittedly does not cover the entire 31-bit space of UCS, but
|
||||
* it does cover all of the characters up to U-10FFFF, which can be
|
||||
* represented by UTF-16, and more, and it is very unlikely that higher
|
||||
* UCS codes will ever be assigned by ISO. So to get Unicode character
|
||||
* U+ABCD you can directly use keysym 0x0100abcd.
|
||||
*
|
||||
* NOTE: The comments in the table below contain the actual character
|
||||
* encoded in UTF-8, so for viewing and editing best use an editor in
|
||||
* UTF-8 mode.
|
||||
*
|
||||
* Author: Markus G. Kuhn <mkuhn@acm.org>, University of Cambridge, April 2001
|
||||
*
|
||||
* Special thanks to Richard Verhoeven <river@win.tue.nl> for preparing
|
||||
* an initial draft of the mapping table.
|
||||
*
|
||||
* This software is in the public domain. Share and enjoy!
|
||||
*
|
||||
* AUTOMATICALLY GENERATED FILE, DO NOT EDIT !!! (unicode/convmap.pl)
|
||||
*/
|
||||
|
||||
#ifndef KEYSYM2UCS_INCLUDED
|
||||
|
||||
#include "keysym2ucs.h"
|
||||
#define VISIBLE /* */
|
||||
|
||||
#else
|
||||
|
||||
#define VISIBLE static
|
||||
|
||||
#endif
|
||||
|
||||
static struct codepair {
|
||||
unsigned short keysym;
|
||||
unsigned short ucs;
|
||||
} keysymtab[] = {
|
||||
{ 0x01a1, 0x0104 }, /* Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK */
|
||||
{ 0x01a2, 0x02d8 }, /* breve ˘ BREVE */
|
||||
{ 0x01a3, 0x0141 }, /* Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE */
|
||||
{ 0x01a5, 0x013d }, /* Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON */
|
||||
{ 0x01a6, 0x015a }, /* Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE */
|
||||
{ 0x01a9, 0x0160 }, /* Scaron Š LATIN CAPITAL LETTER S WITH CARON */
|
||||
{ 0x01aa, 0x015e }, /* Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA */
|
||||
{ 0x01ab, 0x0164 }, /* Tcaron Ť LATIN CAPITAL LETTER T WITH CARON */
|
||||
{ 0x01ac, 0x0179 }, /* Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE */
|
||||
{ 0x01ae, 0x017d }, /* Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON */
|
||||
{ 0x01af, 0x017b }, /* Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE */
|
||||
{ 0x01b1, 0x0105 }, /* aogonek ą LATIN SMALL LETTER A WITH OGONEK */
|
||||
{ 0x01b2, 0x02db }, /* ogonek ˛ OGONEK */
|
||||
{ 0x01b3, 0x0142 }, /* lstroke ł LATIN SMALL LETTER L WITH STROKE */
|
||||
{ 0x01b5, 0x013e }, /* lcaron ľ LATIN SMALL LETTER L WITH CARON */
|
||||
{ 0x01b6, 0x015b }, /* sacute ś LATIN SMALL LETTER S WITH ACUTE */
|
||||
{ 0x01b7, 0x02c7 }, /* caron ˇ CARON */
|
||||
{ 0x01b9, 0x0161 }, /* scaron š LATIN SMALL LETTER S WITH CARON */
|
||||
{ 0x01ba, 0x015f }, /* scedilla ş LATIN SMALL LETTER S WITH CEDILLA */
|
||||
{ 0x01bb, 0x0165 }, /* tcaron ť LATIN SMALL LETTER T WITH CARON */
|
||||
{ 0x01bc, 0x017a }, /* zacute ź LATIN SMALL LETTER Z WITH ACUTE */
|
||||
{ 0x01bd, 0x02dd }, /* doubleacute ˝ DOUBLE ACUTE ACCENT */
|
||||
{ 0x01be, 0x017e }, /* zcaron ž LATIN SMALL LETTER Z WITH CARON */
|
||||
{ 0x01bf, 0x017c }, /* zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE */
|
||||
{ 0x01c0, 0x0154 }, /* Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE */
|
||||
{ 0x01c3, 0x0102 }, /* Abreve Ă LATIN CAPITAL LETTER A WITH BREVE */
|
||||
{ 0x01c5, 0x0139 }, /* Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE */
|
||||
{ 0x01c6, 0x0106 }, /* Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE */
|
||||
{ 0x01c8, 0x010c }, /* Ccaron Č LATIN CAPITAL LETTER C WITH CARON */
|
||||
{ 0x01ca, 0x0118 }, /* Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK */
|
||||
{ 0x01cc, 0x011a }, /* Ecaron Ě LATIN CAPITAL LETTER E WITH CARON */
|
||||
{ 0x01cf, 0x010e }, /* Dcaron Ď LATIN CAPITAL LETTER D WITH CARON */
|
||||
{ 0x01d0, 0x0110 }, /* Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE */
|
||||
{ 0x01d1, 0x0143 }, /* Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE */
|
||||
{ 0x01d2, 0x0147 }, /* Ncaron Ň LATIN CAPITAL LETTER N WITH CARON */
|
||||
{ 0x01d5, 0x0150 }, /* Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */
|
||||
{ 0x01d8, 0x0158 }, /* Rcaron Ř LATIN CAPITAL LETTER R WITH CARON */
|
||||
{ 0x01d9, 0x016e }, /* Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE */
|
||||
{ 0x01db, 0x0170 }, /* Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */
|
||||
{ 0x01de, 0x0162 }, /* Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA */
|
||||
{ 0x01e0, 0x0155 }, /* racute ŕ LATIN SMALL LETTER R WITH ACUTE */
|
||||
{ 0x01e3, 0x0103 }, /* abreve ă LATIN SMALL LETTER A WITH BREVE */
|
||||
{ 0x01e5, 0x013a }, /* lacute ĺ LATIN SMALL LETTER L WITH ACUTE */
|
||||
{ 0x01e6, 0x0107 }, /* cacute ć LATIN SMALL LETTER C WITH ACUTE */
|
||||
{ 0x01e8, 0x010d }, /* ccaron č LATIN SMALL LETTER C WITH CARON */
|
||||
{ 0x01ea, 0x0119 }, /* eogonek ę LATIN SMALL LETTER E WITH OGONEK */
|
||||
{ 0x01ec, 0x011b }, /* ecaron ě LATIN SMALL LETTER E WITH CARON */
|
||||
{ 0x01ef, 0x010f }, /* dcaron ď LATIN SMALL LETTER D WITH CARON */
|
||||
{ 0x01f0, 0x0111 }, /* dstroke đ LATIN SMALL LETTER D WITH STROKE */
|
||||
{ 0x01f1, 0x0144 }, /* nacute ń LATIN SMALL LETTER N WITH ACUTE */
|
||||
{ 0x01f2, 0x0148 }, /* ncaron ň LATIN SMALL LETTER N WITH CARON */
|
||||
{ 0x01f5, 0x0151 }, /* odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE */
|
||||
{ 0x01f8, 0x0159 }, /* rcaron ř LATIN SMALL LETTER R WITH CARON */
|
||||
{ 0x01f9, 0x016f }, /* uring ů LATIN SMALL LETTER U WITH RING ABOVE */
|
||||
{ 0x01fb, 0x0171 }, /* udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE */
|
||||
{ 0x01fe, 0x0163 }, /* tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA */
|
||||
{ 0x01ff, 0x02d9 }, /* abovedot ˙ DOT ABOVE */
|
||||
{ 0x02a1, 0x0126 }, /* Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE */
|
||||
{ 0x02a6, 0x0124 }, /* Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX */
|
||||
{ 0x02a9, 0x0130 }, /* Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE */
|
||||
{ 0x02ab, 0x011e }, /* Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE */
|
||||
{ 0x02ac, 0x0134 }, /* Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX */
|
||||
{ 0x02b1, 0x0127 }, /* hstroke ħ LATIN SMALL LETTER H WITH STROKE */
|
||||
{ 0x02b6, 0x0125 }, /* hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX */
|
||||
{ 0x02b9, 0x0131 }, /* idotless ı LATIN SMALL LETTER DOTLESS I */
|
||||
{ 0x02bb, 0x011f }, /* gbreve ğ LATIN SMALL LETTER G WITH BREVE */
|
||||
{ 0x02bc, 0x0135 }, /* jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX */
|
||||
{ 0x02c5, 0x010a }, /* Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE */
|
||||
{ 0x02c6, 0x0108 }, /* Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX */
|
||||
{ 0x02d5, 0x0120 }, /* Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE */
|
||||
{ 0x02d8, 0x011c }, /* Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX */
|
||||
{ 0x02dd, 0x016c }, /* Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE */
|
||||
{ 0x02de, 0x015c }, /* Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX */
|
||||
{ 0x02e5, 0x010b }, /* cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE */
|
||||
{ 0x02e6, 0x0109 }, /* ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX */
|
||||
{ 0x02f5, 0x0121 }, /* gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE */
|
||||
{ 0x02f8, 0x011d }, /* gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX */
|
||||
{ 0x02fd, 0x016d }, /* ubreve ŭ LATIN SMALL LETTER U WITH BREVE */
|
||||
{ 0x02fe, 0x015d }, /* scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX */
|
||||
{ 0x03a2, 0x0138 }, /* kra ĸ LATIN SMALL LETTER KRA */
|
||||
{ 0x03a3, 0x0156 }, /* Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA */
|
||||
{ 0x03a5, 0x0128 }, /* Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE */
|
||||
{ 0x03a6, 0x013b }, /* Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA */
|
||||
{ 0x03aa, 0x0112 }, /* Emacron Ē LATIN CAPITAL LETTER E WITH MACRON */
|
||||
{ 0x03ab, 0x0122 }, /* Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA */
|
||||
{ 0x03ac, 0x0166 }, /* Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE */
|
||||
{ 0x03b3, 0x0157 }, /* rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA */
|
||||
{ 0x03b5, 0x0129 }, /* itilde ĩ LATIN SMALL LETTER I WITH TILDE */
|
||||
{ 0x03b6, 0x013c }, /* lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA */
|
||||
{ 0x03ba, 0x0113 }, /* emacron ē LATIN SMALL LETTER E WITH MACRON */
|
||||
{ 0x03bb, 0x0123 }, /* gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA */
|
||||
{ 0x03bc, 0x0167 }, /* tslash ŧ LATIN SMALL LETTER T WITH STROKE */
|
||||
{ 0x03bd, 0x014a }, /* ENG Ŋ LATIN CAPITAL LETTER ENG */
|
||||
{ 0x03bf, 0x014b }, /* eng ŋ LATIN SMALL LETTER ENG */
|
||||
{ 0x03c0, 0x0100 }, /* Amacron Ā LATIN CAPITAL LETTER A WITH MACRON */
|
||||
{ 0x03c7, 0x012e }, /* Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK */
|
||||
{ 0x03cc, 0x0116 }, /* Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE */
|
||||
{ 0x03cf, 0x012a }, /* Imacron Ī LATIN CAPITAL LETTER I WITH MACRON */
|
||||
{ 0x03d1, 0x0145 }, /* Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA */
|
||||
{ 0x03d2, 0x014c }, /* Omacron Ō LATIN CAPITAL LETTER O WITH MACRON */
|
||||
{ 0x03d3, 0x0136 }, /* Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA */
|
||||
{ 0x03d9, 0x0172 }, /* Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK */
|
||||
{ 0x03dd, 0x0168 }, /* Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE */
|
||||
{ 0x03de, 0x016a }, /* Umacron Ū LATIN CAPITAL LETTER U WITH MACRON */
|
||||
{ 0x03e0, 0x0101 }, /* amacron ā LATIN SMALL LETTER A WITH MACRON */
|
||||
{ 0x03e7, 0x012f }, /* iogonek į LATIN SMALL LETTER I WITH OGONEK */
|
||||
{ 0x03ec, 0x0117 }, /* eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE */
|
||||
{ 0x03ef, 0x012b }, /* imacron ī LATIN SMALL LETTER I WITH MACRON */
|
||||
{ 0x03f1, 0x0146 }, /* ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA */
|
||||
{ 0x03f2, 0x014d }, /* omacron ō LATIN SMALL LETTER O WITH MACRON */
|
||||
{ 0x03f3, 0x0137 }, /* kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA */
|
||||
{ 0x03f9, 0x0173 }, /* uogonek ų LATIN SMALL LETTER U WITH OGONEK */
|
||||
{ 0x03fd, 0x0169 }, /* utilde ũ LATIN SMALL LETTER U WITH TILDE */
|
||||
{ 0x03fe, 0x016b }, /* umacron ū LATIN SMALL LETTER U WITH MACRON */
|
||||
{ 0x047e, 0x203e }, /* overline ‾ OVERLINE */
|
||||
{ 0x04a1, 0x3002 }, /* kana_fullstop 。 IDEOGRAPHIC FULL STOP */
|
||||
{ 0x04a2, 0x300c }, /* kana_openingbracket 「 LEFT CORNER BRACKET */
|
||||
{ 0x04a3, 0x300d }, /* kana_closingbracket 」 RIGHT CORNER BRACKET */
|
||||
{ 0x04a4, 0x3001 }, /* kana_comma 、 IDEOGRAPHIC COMMA */
|
||||
{ 0x04a5, 0x30fb }, /* kana_conjunctive ・ KATAKANA MIDDLE DOT */
|
||||
{ 0x04a6, 0x30f2 }, /* kana_WO ヲ KATAKANA LETTER WO */
|
||||
{ 0x04a7, 0x30a1 }, /* kana_a ァ KATAKANA LETTER SMALL A */
|
||||
{ 0x04a8, 0x30a3 }, /* kana_i ィ KATAKANA LETTER SMALL I */
|
||||
{ 0x04a9, 0x30a5 }, /* kana_u ゥ KATAKANA LETTER SMALL U */
|
||||
{ 0x04aa, 0x30a7 }, /* kana_e ェ KATAKANA LETTER SMALL E */
|
||||
{ 0x04ab, 0x30a9 }, /* kana_o ォ KATAKANA LETTER SMALL O */
|
||||
{ 0x04ac, 0x30e3 }, /* kana_ya ャ KATAKANA LETTER SMALL YA */
|
||||
{ 0x04ad, 0x30e5 }, /* kana_yu ュ KATAKANA LETTER SMALL YU */
|
||||
{ 0x04ae, 0x30e7 }, /* kana_yo ョ KATAKANA LETTER SMALL YO */
|
||||
{ 0x04af, 0x30c3 }, /* kana_tsu ッ KATAKANA LETTER SMALL TU */
|
||||
{ 0x04b0, 0x30fc }, /* prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK */
|
||||
{ 0x04b1, 0x30a2 }, /* kana_A ア KATAKANA LETTER A */
|
||||
{ 0x04b2, 0x30a4 }, /* kana_I イ KATAKANA LETTER I */
|
||||
{ 0x04b3, 0x30a6 }, /* kana_U ウ KATAKANA LETTER U */
|
||||
{ 0x04b4, 0x30a8 }, /* kana_E エ KATAKANA LETTER E */
|
||||
{ 0x04b5, 0x30aa }, /* kana_O オ KATAKANA LETTER O */
|
||||
{ 0x04b6, 0x30ab }, /* kana_KA カ KATAKANA LETTER KA */
|
||||
{ 0x04b7, 0x30ad }, /* kana_KI キ KATAKANA LETTER KI */
|
||||
{ 0x04b8, 0x30af }, /* kana_KU ク KATAKANA LETTER KU */
|
||||
{ 0x04b9, 0x30b1 }, /* kana_KE ケ KATAKANA LETTER KE */
|
||||
{ 0x04ba, 0x30b3 }, /* kana_KO コ KATAKANA LETTER KO */
|
||||
{ 0x04bb, 0x30b5 }, /* kana_SA サ KATAKANA LETTER SA */
|
||||
{ 0x04bc, 0x30b7 }, /* kana_SHI シ KATAKANA LETTER SI */
|
||||
{ 0x04bd, 0x30b9 }, /* kana_SU ス KATAKANA LETTER SU */
|
||||
{ 0x04be, 0x30bb }, /* kana_SE セ KATAKANA LETTER SE */
|
||||
{ 0x04bf, 0x30bd }, /* kana_SO ソ KATAKANA LETTER SO */
|
||||
{ 0x04c0, 0x30bf }, /* kana_TA タ KATAKANA LETTER TA */
|
||||
{ 0x04c1, 0x30c1 }, /* kana_CHI チ KATAKANA LETTER TI */
|
||||
{ 0x04c2, 0x30c4 }, /* kana_TSU ツ KATAKANA LETTER TU */
|
||||
{ 0x04c3, 0x30c6 }, /* kana_TE テ KATAKANA LETTER TE */
|
||||
{ 0x04c4, 0x30c8 }, /* kana_TO ト KATAKANA LETTER TO */
|
||||
{ 0x04c5, 0x30ca }, /* kana_NA ナ KATAKANA LETTER NA */
|
||||
{ 0x04c6, 0x30cb }, /* kana_NI ニ KATAKANA LETTER NI */
|
||||
{ 0x04c7, 0x30cc }, /* kana_NU ヌ KATAKANA LETTER NU */
|
||||
{ 0x04c8, 0x30cd }, /* kana_NE ネ KATAKANA LETTER NE */
|
||||
{ 0x04c9, 0x30ce }, /* kana_NO ノ KATAKANA LETTER NO */
|
||||
{ 0x04ca, 0x30cf }, /* kana_HA ハ KATAKANA LETTER HA */
|
||||
{ 0x04cb, 0x30d2 }, /* kana_HI ヒ KATAKANA LETTER HI */
|
||||
{ 0x04cc, 0x30d5 }, /* kana_FU フ KATAKANA LETTER HU */
|
||||
{ 0x04cd, 0x30d8 }, /* kana_HE ヘ KATAKANA LETTER HE */
|
||||
{ 0x04ce, 0x30db }, /* kana_HO ホ KATAKANA LETTER HO */
|
||||
{ 0x04cf, 0x30de }, /* kana_MA マ KATAKANA LETTER MA */
|
||||
{ 0x04d0, 0x30df }, /* kana_MI ミ KATAKANA LETTER MI */
|
||||
{ 0x04d1, 0x30e0 }, /* kana_MU ム KATAKANA LETTER MU */
|
||||
{ 0x04d2, 0x30e1 }, /* kana_ME メ KATAKANA LETTER ME */
|
||||
{ 0x04d3, 0x30e2 }, /* kana_MO モ KATAKANA LETTER MO */
|
||||
{ 0x04d4, 0x30e4 }, /* kana_YA ヤ KATAKANA LETTER YA */
|
||||
{ 0x04d5, 0x30e6 }, /* kana_YU ユ KATAKANA LETTER YU */
|
||||
{ 0x04d6, 0x30e8 }, /* kana_YO ヨ KATAKANA LETTER YO */
|
||||
{ 0x04d7, 0x30e9 }, /* kana_RA ラ KATAKANA LETTER RA */
|
||||
{ 0x04d8, 0x30ea }, /* kana_RI リ KATAKANA LETTER RI */
|
||||
{ 0x04d9, 0x30eb }, /* kana_RU ル KATAKANA LETTER RU */
|
||||
{ 0x04da, 0x30ec }, /* kana_RE レ KATAKANA LETTER RE */
|
||||
{ 0x04db, 0x30ed }, /* kana_RO ロ KATAKANA LETTER RO */
|
||||
{ 0x04dc, 0x30ef }, /* kana_WA ワ KATAKANA LETTER WA */
|
||||
{ 0x04dd, 0x30f3 }, /* kana_N ン KATAKANA LETTER N */
|
||||
{ 0x04de, 0x309b }, /* voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK */
|
||||
{ 0x04df, 0x309c }, /* semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK */
|
||||
{ 0x05ac, 0x060c }, /* Arabic_comma ، ARABIC COMMA */
|
||||
{ 0x05bb, 0x061b }, /* Arabic_semicolon ؛ ARABIC SEMICOLON */
|
||||
{ 0x05bf, 0x061f }, /* Arabic_question_mark ؟ ARABIC QUESTION MARK */
|
||||
{ 0x05c1, 0x0621 }, /* Arabic_hamza ء ARABIC LETTER HAMZA */
|
||||
{ 0x05c2, 0x0622 }, /* Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE */
|
||||
{ 0x05c3, 0x0623 }, /* Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE */
|
||||
{ 0x05c4, 0x0624 }, /* Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE */
|
||||
{ 0x05c5, 0x0625 }, /* Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW */
|
||||
{ 0x05c6, 0x0626 }, /* Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE */
|
||||
{ 0x05c7, 0x0627 }, /* Arabic_alef ا ARABIC LETTER ALEF */
|
||||
{ 0x05c8, 0x0628 }, /* Arabic_beh ب ARABIC LETTER BEH */
|
||||
{ 0x05c9, 0x0629 }, /* Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA */
|
||||
{ 0x05ca, 0x062a }, /* Arabic_teh ت ARABIC LETTER TEH */
|
||||
{ 0x05cb, 0x062b }, /* Arabic_theh ث ARABIC LETTER THEH */
|
||||
{ 0x05cc, 0x062c }, /* Arabic_jeem ج ARABIC LETTER JEEM */
|
||||
{ 0x05cd, 0x062d }, /* Arabic_hah ح ARABIC LETTER HAH */
|
||||
{ 0x05ce, 0x062e }, /* Arabic_khah خ ARABIC LETTER KHAH */
|
||||
{ 0x05cf, 0x062f }, /* Arabic_dal د ARABIC LETTER DAL */
|
||||
{ 0x05d0, 0x0630 }, /* Arabic_thal ذ ARABIC LETTER THAL */
|
||||
{ 0x05d1, 0x0631 }, /* Arabic_ra ر ARABIC LETTER REH */
|
||||
{ 0x05d2, 0x0632 }, /* Arabic_zain ز ARABIC LETTER ZAIN */
|
||||
{ 0x05d3, 0x0633 }, /* Arabic_seen س ARABIC LETTER SEEN */
|
||||
{ 0x05d4, 0x0634 }, /* Arabic_sheen ش ARABIC LETTER SHEEN */
|
||||
{ 0x05d5, 0x0635 }, /* Arabic_sad ص ARABIC LETTER SAD */
|
||||
{ 0x05d6, 0x0636 }, /* Arabic_dad ض ARABIC LETTER DAD */
|
||||
{ 0x05d7, 0x0637 }, /* Arabic_tah ط ARABIC LETTER TAH */
|
||||
{ 0x05d8, 0x0638 }, /* Arabic_zah ظ ARABIC LETTER ZAH */
|
||||
{ 0x05d9, 0x0639 }, /* Arabic_ain ع ARABIC LETTER AIN */
|
||||
{ 0x05da, 0x063a }, /* Arabic_ghain غ ARABIC LETTER GHAIN */
|
||||
{ 0x05e0, 0x0640 }, /* Arabic_tatweel ـ ARABIC TATWEEL */
|
||||
{ 0x05e1, 0x0641 }, /* Arabic_feh ف ARABIC LETTER FEH */
|
||||
{ 0x05e2, 0x0642 }, /* Arabic_qaf ق ARABIC LETTER QAF */
|
||||
{ 0x05e3, 0x0643 }, /* Arabic_kaf ك ARABIC LETTER KAF */
|
||||
{ 0x05e4, 0x0644 }, /* Arabic_lam ل ARABIC LETTER LAM */
|
||||
{ 0x05e5, 0x0645 }, /* Arabic_meem م ARABIC LETTER MEEM */
|
||||
{ 0x05e6, 0x0646 }, /* Arabic_noon ن ARABIC LETTER NOON */
|
||||
{ 0x05e7, 0x0647 }, /* Arabic_ha ه ARABIC LETTER HEH */
|
||||
{ 0x05e8, 0x0648 }, /* Arabic_waw و ARABIC LETTER WAW */
|
||||
{ 0x05e9, 0x0649 }, /* Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA */
|
||||
{ 0x05ea, 0x064a }, /* Arabic_yeh ي ARABIC LETTER YEH */
|
||||
{ 0x05eb, 0x064b }, /* Arabic_fathatan ً ARABIC FATHATAN */
|
||||
{ 0x05ec, 0x064c }, /* Arabic_dammatan ٌ ARABIC DAMMATAN */
|
||||
{ 0x05ed, 0x064d }, /* Arabic_kasratan ٍ ARABIC KASRATAN */
|
||||
{ 0x05ee, 0x064e }, /* Arabic_fatha َ ARABIC FATHA */
|
||||
{ 0x05ef, 0x064f }, /* Arabic_damma ُ ARABIC DAMMA */
|
||||
{ 0x05f0, 0x0650 }, /* Arabic_kasra ِ ARABIC KASRA */
|
||||
{ 0x05f1, 0x0651 }, /* Arabic_shadda ّ ARABIC SHADDA */
|
||||
{ 0x05f2, 0x0652 }, /* Arabic_sukun ْ ARABIC SUKUN */
|
||||
{ 0x06a1, 0x0452 }, /* Serbian_dje ђ CYRILLIC SMALL LETTER DJE */
|
||||
{ 0x06a2, 0x0453 }, /* Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE */
|
||||
{ 0x06a3, 0x0451 }, /* Cyrillic_io ё CYRILLIC SMALL LETTER IO */
|
||||
{ 0x06a4, 0x0454 }, /* Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE */
|
||||
{ 0x06a5, 0x0455 }, /* Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE */
|
||||
{ 0x06a6, 0x0456 }, /* Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I */
|
||||
{ 0x06a7, 0x0457 }, /* Ukrainian_yi ї CYRILLIC SMALL LETTER YI */
|
||||
{ 0x06a8, 0x0458 }, /* Cyrillic_je ј CYRILLIC SMALL LETTER JE */
|
||||
{ 0x06a9, 0x0459 }, /* Cyrillic_lje љ CYRILLIC SMALL LETTER LJE */
|
||||
{ 0x06aa, 0x045a }, /* Cyrillic_nje њ CYRILLIC SMALL LETTER NJE */
|
||||
{ 0x06ab, 0x045b }, /* Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE */
|
||||
{ 0x06ac, 0x045c }, /* Macedonia_kje ќ CYRILLIC SMALL LETTER KJE */
|
||||
{ 0x06ae, 0x045e }, /* Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U */
|
||||
{ 0x06af, 0x045f }, /* Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE */
|
||||
{ 0x06b0, 0x2116 }, /* numerosign № NUMERO SIGN */
|
||||
{ 0x06b1, 0x0402 }, /* Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE */
|
||||
{ 0x06b2, 0x0403 }, /* Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE */
|
||||
{ 0x06b3, 0x0401 }, /* Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO */
|
||||
{ 0x06b4, 0x0404 }, /* Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE */
|
||||
{ 0x06b5, 0x0405 }, /* Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE */
|
||||
{ 0x06b6, 0x0406 }, /* Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */
|
||||
{ 0x06b7, 0x0407 }, /* Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI */
|
||||
{ 0x06b8, 0x0408 }, /* Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE */
|
||||
{ 0x06b9, 0x0409 }, /* Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE */
|
||||
{ 0x06ba, 0x040a }, /* Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE */
|
||||
{ 0x06bb, 0x040b }, /* Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE */
|
||||
{ 0x06bc, 0x040c }, /* Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE */
|
||||
{ 0x06be, 0x040e }, /* Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U */
|
||||
{ 0x06bf, 0x040f }, /* Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE */
|
||||
{ 0x06c0, 0x044e }, /* Cyrillic_yu ю CYRILLIC SMALL LETTER YU */
|
||||
{ 0x06c1, 0x0430 }, /* Cyrillic_a а CYRILLIC SMALL LETTER A */
|
||||
{ 0x06c2, 0x0431 }, /* Cyrillic_be б CYRILLIC SMALL LETTER BE */
|
||||
{ 0x06c3, 0x0446 }, /* Cyrillic_tse ц CYRILLIC SMALL LETTER TSE */
|
||||
{ 0x06c4, 0x0434 }, /* Cyrillic_de д CYRILLIC SMALL LETTER DE */
|
||||
{ 0x06c5, 0x0435 }, /* Cyrillic_ie е CYRILLIC SMALL LETTER IE */
|
||||
{ 0x06c6, 0x0444 }, /* Cyrillic_ef ф CYRILLIC SMALL LETTER EF */
|
||||
{ 0x06c7, 0x0433 }, /* Cyrillic_ghe г CYRILLIC SMALL LETTER GHE */
|
||||
{ 0x06c8, 0x0445 }, /* Cyrillic_ha х CYRILLIC SMALL LETTER HA */
|
||||
{ 0x06c9, 0x0438 }, /* Cyrillic_i и CYRILLIC SMALL LETTER I */
|
||||
{ 0x06ca, 0x0439 }, /* Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I */
|
||||
{ 0x06cb, 0x043a }, /* Cyrillic_ka к CYRILLIC SMALL LETTER KA */
|
||||
{ 0x06cc, 0x043b }, /* Cyrillic_el л CYRILLIC SMALL LETTER EL */
|
||||
{ 0x06cd, 0x043c }, /* Cyrillic_em м CYRILLIC SMALL LETTER EM */
|
||||
{ 0x06ce, 0x043d }, /* Cyrillic_en н CYRILLIC SMALL LETTER EN */
|
||||
{ 0x06cf, 0x043e }, /* Cyrillic_o о CYRILLIC SMALL LETTER O */
|
||||
{ 0x06d0, 0x043f }, /* Cyrillic_pe п CYRILLIC SMALL LETTER PE */
|
||||
{ 0x06d1, 0x044f }, /* Cyrillic_ya я CYRILLIC SMALL LETTER YA */
|
||||
{ 0x06d2, 0x0440 }, /* Cyrillic_er р CYRILLIC SMALL LETTER ER */
|
||||
{ 0x06d3, 0x0441 }, /* Cyrillic_es с CYRILLIC SMALL LETTER ES */
|
||||
{ 0x06d4, 0x0442 }, /* Cyrillic_te т CYRILLIC SMALL LETTER TE */
|
||||
{ 0x06d5, 0x0443 }, /* Cyrillic_u у CYRILLIC SMALL LETTER U */
|
||||
{ 0x06d6, 0x0436 }, /* Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE */
|
||||
{ 0x06d7, 0x0432 }, /* Cyrillic_ve в CYRILLIC SMALL LETTER VE */
|
||||
{ 0x06d8, 0x044c }, /* Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN */
|
||||
{ 0x06d9, 0x044b }, /* Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU */
|
||||
{ 0x06da, 0x0437 }, /* Cyrillic_ze з CYRILLIC SMALL LETTER ZE */
|
||||
{ 0x06db, 0x0448 }, /* Cyrillic_sha ш CYRILLIC SMALL LETTER SHA */
|
||||
{ 0x06dc, 0x044d }, /* Cyrillic_e э CYRILLIC SMALL LETTER E */
|
||||
{ 0x06dd, 0x0449 }, /* Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA */
|
||||
{ 0x06de, 0x0447 }, /* Cyrillic_che ч CYRILLIC SMALL LETTER CHE */
|
||||
{ 0x06df, 0x044a }, /* Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN */
|
||||
{ 0x06e0, 0x042e }, /* Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU */
|
||||
{ 0x06e1, 0x0410 }, /* Cyrillic_A А CYRILLIC CAPITAL LETTER A */
|
||||
{ 0x06e2, 0x0411 }, /* Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE */
|
||||
{ 0x06e3, 0x0426 }, /* Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE */
|
||||
{ 0x06e4, 0x0414 }, /* Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE */
|
||||
{ 0x06e5, 0x0415 }, /* Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE */
|
||||
{ 0x06e6, 0x0424 }, /* Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF */
|
||||
{ 0x06e7, 0x0413 }, /* Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE */
|
||||
{ 0x06e8, 0x0425 }, /* Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA */
|
||||
{ 0x06e9, 0x0418 }, /* Cyrillic_I И CYRILLIC CAPITAL LETTER I */
|
||||
{ 0x06ea, 0x0419 }, /* Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I */
|
||||
{ 0x06eb, 0x041a }, /* Cyrillic_KA К CYRILLIC CAPITAL LETTER KA */
|
||||
{ 0x06ec, 0x041b }, /* Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL */
|
||||
{ 0x06ed, 0x041c }, /* Cyrillic_EM М CYRILLIC CAPITAL LETTER EM */
|
||||
{ 0x06ee, 0x041d }, /* Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN */
|
||||
{ 0x06ef, 0x041e }, /* Cyrillic_O О CYRILLIC CAPITAL LETTER O */
|
||||
{ 0x06f0, 0x041f }, /* Cyrillic_PE П CYRILLIC CAPITAL LETTER PE */
|
||||
{ 0x06f1, 0x042f }, /* Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA */
|
||||
{ 0x06f2, 0x0420 }, /* Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER */
|
||||
{ 0x06f3, 0x0421 }, /* Cyrillic_ES С CYRILLIC CAPITAL LETTER ES */
|
||||
{ 0x06f4, 0x0422 }, /* Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE */
|
||||
{ 0x06f5, 0x0423 }, /* Cyrillic_U У CYRILLIC CAPITAL LETTER U */
|
||||
{ 0x06f6, 0x0416 }, /* Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE */
|
||||
{ 0x06f7, 0x0412 }, /* Cyrillic_VE В CYRILLIC CAPITAL LETTER VE */
|
||||
{ 0x06f8, 0x042c }, /* Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN */
|
||||
{ 0x06f9, 0x042b }, /* Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU */
|
||||
{ 0x06fa, 0x0417 }, /* Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE */
|
||||
{ 0x06fb, 0x0428 }, /* Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA */
|
||||
{ 0x06fc, 0x042d }, /* Cyrillic_E Э CYRILLIC CAPITAL LETTER E */
|
||||
{ 0x06fd, 0x0429 }, /* Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA */
|
||||
{ 0x06fe, 0x0427 }, /* Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE */
|
||||
{ 0x06ff, 0x042a }, /* Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN */
|
||||
{ 0x07a1, 0x0386 }, /* Greek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS */
|
||||
{ 0x07a2, 0x0388 }, /* Greek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS */
|
||||
{ 0x07a3, 0x0389 }, /* Greek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS */
|
||||
{ 0x07a4, 0x038a }, /* Greek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS */
|
||||
{ 0x07a5, 0x03aa }, /* Greek_IOTAdiaeresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */
|
||||
{ 0x07a7, 0x038c }, /* Greek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS */
|
||||
{ 0x07a8, 0x038e }, /* Greek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS */
|
||||
{ 0x07a9, 0x03ab }, /* Greek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */
|
||||
{ 0x07ab, 0x038f }, /* Greek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS */
|
||||
{ 0x07ae, 0x0385 }, /* Greek_accentdieresis ΅ GREEK DIALYTIKA TONOS */
|
||||
{ 0x07af, 0x2015 }, /* Greek_horizbar ― HORIZONTAL BAR */
|
||||
{ 0x07b1, 0x03ac }, /* Greek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS */
|
||||
{ 0x07b2, 0x03ad }, /* Greek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS */
|
||||
{ 0x07b3, 0x03ae }, /* Greek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS */
|
||||
{ 0x07b4, 0x03af }, /* Greek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS */
|
||||
{ 0x07b5, 0x03ca }, /* Greek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA */
|
||||
{ 0x07b6, 0x0390 }, /* Greek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */
|
||||
{ 0x07b7, 0x03cc }, /* Greek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS */
|
||||
{ 0x07b8, 0x03cd }, /* Greek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS */
|
||||
{ 0x07b9, 0x03cb }, /* Greek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA */
|
||||
{ 0x07ba, 0x03b0 }, /* Greek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */
|
||||
{ 0x07bb, 0x03ce }, /* Greek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS */
|
||||
{ 0x07c1, 0x0391 }, /* Greek_ALPHA Α GREEK CAPITAL LETTER ALPHA */
|
||||
{ 0x07c2, 0x0392 }, /* Greek_BETA Β GREEK CAPITAL LETTER BETA */
|
||||
{ 0x07c3, 0x0393 }, /* Greek_GAMMA Γ GREEK CAPITAL LETTER GAMMA */
|
||||
{ 0x07c4, 0x0394 }, /* Greek_DELTA Δ GREEK CAPITAL LETTER DELTA */
|
||||
{ 0x07c5, 0x0395 }, /* Greek_EPSILON Ε GREEK CAPITAL LETTER EPSILON */
|
||||
{ 0x07c6, 0x0396 }, /* Greek_ZETA Ζ GREEK CAPITAL LETTER ZETA */
|
||||
{ 0x07c7, 0x0397 }, /* Greek_ETA Η GREEK CAPITAL LETTER ETA */
|
||||
{ 0x07c8, 0x0398 }, /* Greek_THETA Θ GREEK CAPITAL LETTER THETA */
|
||||
{ 0x07c9, 0x0399 }, /* Greek_IOTA Ι GREEK CAPITAL LETTER IOTA */
|
||||
{ 0x07ca, 0x039a }, /* Greek_KAPPA Κ GREEK CAPITAL LETTER KAPPA */
|
||||
{ 0x07cb, 0x039b }, /* Greek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA */
|
||||
{ 0x07cc, 0x039c }, /* Greek_MU Μ GREEK CAPITAL LETTER MU */
|
||||
{ 0x07cd, 0x039d }, /* Greek_NU Ν GREEK CAPITAL LETTER NU */
|
||||
{ 0x07ce, 0x039e }, /* Greek_XI Ξ GREEK CAPITAL LETTER XI */
|
||||
{ 0x07cf, 0x039f }, /* Greek_OMICRON Ο GREEK CAPITAL LETTER OMICRON */
|
||||
{ 0x07d0, 0x03a0 }, /* Greek_PI Π GREEK CAPITAL LETTER PI */
|
||||
{ 0x07d1, 0x03a1 }, /* Greek_RHO Ρ GREEK CAPITAL LETTER RHO */
|
||||
{ 0x07d2, 0x03a3 }, /* Greek_SIGMA Σ GREEK CAPITAL LETTER SIGMA */
|
||||
{ 0x07d4, 0x03a4 }, /* Greek_TAU Τ GREEK CAPITAL LETTER TAU */
|
||||
{ 0x07d5, 0x03a5 }, /* Greek_UPSILON Υ GREEK CAPITAL LETTER UPSILON */
|
||||
{ 0x07d6, 0x03a6 }, /* Greek_PHI Φ GREEK CAPITAL LETTER PHI */
|
||||
{ 0x07d7, 0x03a7 }, /* Greek_CHI Χ GREEK CAPITAL LETTER CHI */
|
||||
{ 0x07d8, 0x03a8 }, /* Greek_PSI Ψ GREEK CAPITAL LETTER PSI */
|
||||
{ 0x07d9, 0x03a9 }, /* Greek_OMEGA Ω GREEK CAPITAL LETTER OMEGA */
|
||||
{ 0x07e1, 0x03b1 }, /* Greek_alpha α GREEK SMALL LETTER ALPHA */
|
||||
{ 0x07e2, 0x03b2 }, /* Greek_beta β GREEK SMALL LETTER BETA */
|
||||
{ 0x07e3, 0x03b3 }, /* Greek_gamma γ GREEK SMALL LETTER GAMMA */
|
||||
{ 0x07e4, 0x03b4 }, /* Greek_delta δ GREEK SMALL LETTER DELTA */
|
||||
{ 0x07e5, 0x03b5 }, /* Greek_epsilon ε GREEK SMALL LETTER EPSILON */
|
||||
{ 0x07e6, 0x03b6 }, /* Greek_zeta ζ GREEK SMALL LETTER ZETA */
|
||||
{ 0x07e7, 0x03b7 }, /* Greek_eta η GREEK SMALL LETTER ETA */
|
||||
{ 0x07e8, 0x03b8 }, /* Greek_theta θ GREEK SMALL LETTER THETA */
|
||||
{ 0x07e9, 0x03b9 }, /* Greek_iota ι GREEK SMALL LETTER IOTA */
|
||||
{ 0x07ea, 0x03ba }, /* Greek_kappa κ GREEK SMALL LETTER KAPPA */
|
||||
{ 0x07eb, 0x03bb }, /* Greek_lambda λ GREEK SMALL LETTER LAMDA */
|
||||
{ 0x07ec, 0x03bc }, /* Greek_mu μ GREEK SMALL LETTER MU */
|
||||
{ 0x07ed, 0x03bd }, /* Greek_nu ν GREEK SMALL LETTER NU */
|
||||
{ 0x07ee, 0x03be }, /* Greek_xi ξ GREEK SMALL LETTER XI */
|
||||
{ 0x07ef, 0x03bf }, /* Greek_omicron ο GREEK SMALL LETTER OMICRON */
|
||||
{ 0x07f0, 0x03c0 }, /* Greek_pi π GREEK SMALL LETTER PI */
|
||||
{ 0x07f1, 0x03c1 }, /* Greek_rho ρ GREEK SMALL LETTER RHO */
|
||||
{ 0x07f2, 0x03c3 }, /* Greek_sigma σ GREEK SMALL LETTER SIGMA */
|
||||
{ 0x07f3, 0x03c2 }, /* Greek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA */
|
||||
{ 0x07f4, 0x03c4 }, /* Greek_tau τ GREEK SMALL LETTER TAU */
|
||||
{ 0x07f5, 0x03c5 }, /* Greek_upsilon υ GREEK SMALL LETTER UPSILON */
|
||||
{ 0x07f6, 0x03c6 }, /* Greek_phi φ GREEK SMALL LETTER PHI */
|
||||
{ 0x07f7, 0x03c7 }, /* Greek_chi χ GREEK SMALL LETTER CHI */
|
||||
{ 0x07f8, 0x03c8 }, /* Greek_psi ψ GREEK SMALL LETTER PSI */
|
||||
{ 0x07f9, 0x03c9 }, /* Greek_omega ω GREEK SMALL LETTER OMEGA */
|
||||
{ 0x08a1, 0x23b7 }, /* leftradical ⎷ ??? */
|
||||
{ 0x08a2, 0x250c }, /* topleftradical ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
|
||||
{ 0x08a3, 0x2500 }, /* horizconnector ─ BOX DRAWINGS LIGHT HORIZONTAL */
|
||||
{ 0x08a4, 0x2320 }, /* topintegral ⌠ TOP HALF INTEGRAL */
|
||||
{ 0x08a5, 0x2321 }, /* botintegral ⌡ BOTTOM HALF INTEGRAL */
|
||||
{ 0x08a6, 0x2502 }, /* vertconnector │ BOX DRAWINGS LIGHT VERTICAL */
|
||||
{ 0x08a7, 0x23a1 }, /* topleftsqbracket ⎡ ??? */
|
||||
{ 0x08a8, 0x23a3 }, /* botleftsqbracket ⎣ ??? */
|
||||
{ 0x08a9, 0x23a4 }, /* toprightsqbracket ⎤ ??? */
|
||||
{ 0x08aa, 0x23a6 }, /* botrightsqbracket ⎦ ??? */
|
||||
{ 0x08ab, 0x239b }, /* topleftparens ⎛ ??? */
|
||||
{ 0x08ac, 0x239d }, /* botleftparens ⎝ ??? */
|
||||
{ 0x08ad, 0x239e }, /* toprightparens ⎞ ??? */
|
||||
{ 0x08ae, 0x23a0 }, /* botrightparens ⎠ ??? */
|
||||
{ 0x08af, 0x23a8 }, /* leftmiddlecurlybrace ⎨ ??? */
|
||||
{ 0x08b0, 0x23ac }, /* rightmiddlecurlybrace ⎬ ??? */
|
||||
/* 0x08b1 topleftsummation ? ??? */
|
||||
/* 0x08b2 botleftsummation ? ??? */
|
||||
/* 0x08b3 topvertsummationconnector ? ??? */
|
||||
/* 0x08b4 botvertsummationconnector ? ??? */
|
||||
/* 0x08b5 toprightsummation ? ??? */
|
||||
/* 0x08b6 botrightsummation ? ??? */
|
||||
/* 0x08b7 rightmiddlesummation ? ??? */
|
||||
{ 0x08bc, 0x2264 }, /* lessthanequal ≤ LESS-THAN OR EQUAL TO */
|
||||
{ 0x08bd, 0x2260 }, /* notequal ≠ NOT EQUAL TO */
|
||||
{ 0x08be, 0x2265 }, /* greaterthanequal ≥ GREATER-THAN OR EQUAL TO */
|
||||
{ 0x08bf, 0x222b }, /* integral ∫ INTEGRAL */
|
||||
{ 0x08c0, 0x2234 }, /* therefore ∴ THEREFORE */
|
||||
{ 0x08c1, 0x221d }, /* variation ∝ PROPORTIONAL TO */
|
||||
{ 0x08c2, 0x221e }, /* infinity ∞ INFINITY */
|
||||
{ 0x08c5, 0x2207 }, /* nabla ∇ NABLA */
|
||||
{ 0x08c8, 0x223c }, /* approximate ∼ TILDE OPERATOR */
|
||||
{ 0x08c9, 0x2243 }, /* similarequal ≃ ASYMPTOTICALLY EQUAL TO */
|
||||
{ 0x08cd, 0x21d4 }, /* ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW */
|
||||
{ 0x08ce, 0x21d2 }, /* implies ⇒ RIGHTWARDS DOUBLE ARROW */
|
||||
{ 0x08cf, 0x2261 }, /* identical ≡ IDENTICAL TO */
|
||||
{ 0x08d6, 0x221a }, /* radical √ SQUARE ROOT */
|
||||
{ 0x08da, 0x2282 }, /* includedin ⊂ SUBSET OF */
|
||||
{ 0x08db, 0x2283 }, /* includes ⊃ SUPERSET OF */
|
||||
{ 0x08dc, 0x2229 }, /* intersection ∩ INTERSECTION */
|
||||
{ 0x08dd, 0x222a }, /* union ∪ UNION */
|
||||
{ 0x08de, 0x2227 }, /* logicaland ∧ LOGICAL AND */
|
||||
{ 0x08df, 0x2228 }, /* logicalor ∨ LOGICAL OR */
|
||||
{ 0x08ef, 0x2202 }, /* partialderivative ∂ PARTIAL DIFFERENTIAL */
|
||||
{ 0x08f6, 0x0192 }, /* function ƒ LATIN SMALL LETTER F WITH HOOK */
|
||||
{ 0x08fb, 0x2190 }, /* leftarrow ← LEFTWARDS ARROW */
|
||||
{ 0x08fc, 0x2191 }, /* uparrow ↑ UPWARDS ARROW */
|
||||
{ 0x08fd, 0x2192 }, /* rightarrow → RIGHTWARDS ARROW */
|
||||
{ 0x08fe, 0x2193 }, /* downarrow ↓ DOWNWARDS ARROW */
|
||||
/* 0x09df blank ? ??? */
|
||||
{ 0x09e0, 0x25c6 }, /* soliddiamond ◆ BLACK DIAMOND */
|
||||
{ 0x09e1, 0x2592 }, /* checkerboard ▒ MEDIUM SHADE */
|
||||
{ 0x09e2, 0x2409 }, /* ht ␉ SYMBOL FOR HORIZONTAL TABULATION */
|
||||
{ 0x09e3, 0x240c }, /* ff ␌ SYMBOL FOR FORM FEED */
|
||||
{ 0x09e4, 0x240d }, /* cr ␍ SYMBOL FOR CARRIAGE RETURN */
|
||||
{ 0x09e5, 0x240a }, /* lf ␊ SYMBOL FOR LINE FEED */
|
||||
{ 0x09e8, 0x2424 }, /* nl  SYMBOL FOR NEWLINE */
|
||||
{ 0x09e9, 0x240b }, /* vt ␋ SYMBOL FOR VERTICAL TABULATION */
|
||||
{ 0x09ea, 0x2518 }, /* lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT */
|
||||
{ 0x09eb, 0x2510 }, /* uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT */
|
||||
{ 0x09ec, 0x250c }, /* upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT */
|
||||
{ 0x09ed, 0x2514 }, /* lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT */
|
||||
{ 0x09ee, 0x253c }, /* crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
|
||||
{ 0x09ef, 0x23ba }, /* horizlinescan1 ⎺ HORIZONTAL SCAN LINE-1 (Unicode 3.2 draft) */
|
||||
{ 0x09f0, 0x23bb }, /* horizlinescan3 ⎻ HORIZONTAL SCAN LINE-3 (Unicode 3.2 draft) */
|
||||
{ 0x09f1, 0x2500 }, /* horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL */
|
||||
{ 0x09f2, 0x23bc }, /* horizlinescan7 ⎼ HORIZONTAL SCAN LINE-7 (Unicode 3.2 draft) */
|
||||
{ 0x09f3, 0x23bd }, /* horizlinescan9 ⎽ HORIZONTAL SCAN LINE-9 (Unicode 3.2 draft) */
|
||||
{ 0x09f4, 0x251c }, /* leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
|
||||
{ 0x09f5, 0x2524 }, /* rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT */
|
||||
{ 0x09f6, 0x2534 }, /* bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL */
|
||||
{ 0x09f7, 0x252c }, /* topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
|
||||
{ 0x09f8, 0x2502 }, /* vertbar │ BOX DRAWINGS LIGHT VERTICAL */
|
||||
{ 0x0aa1, 0x2003 }, /* emspace EM SPACE */
|
||||
{ 0x0aa2, 0x2002 }, /* enspace EN SPACE */
|
||||
{ 0x0aa3, 0x2004 }, /* em3space THREE-PER-EM SPACE */
|
||||
{ 0x0aa4, 0x2005 }, /* em4space FOUR-PER-EM SPACE */
|
||||
{ 0x0aa5, 0x2007 }, /* digitspace FIGURE SPACE */
|
||||
{ 0x0aa6, 0x2008 }, /* punctspace PUNCTUATION SPACE */
|
||||
{ 0x0aa7, 0x2009 }, /* thinspace THIN SPACE */
|
||||
{ 0x0aa8, 0x200a }, /* hairspace HAIR SPACE */
|
||||
{ 0x0aa9, 0x2014 }, /* emdash — EM DASH */
|
||||
{ 0x0aaa, 0x2013 }, /* endash – EN DASH */
|
||||
/* 0x0aac signifblank ? ??? */
|
||||
{ 0x0aae, 0x2026 }, /* ellipsis … HORIZONTAL ELLIPSIS */
|
||||
{ 0x0aaf, 0x2025 }, /* doubbaselinedot ‥ TWO DOT LEADER */
|
||||
{ 0x0ab0, 0x2153 }, /* onethird ⅓ VULGAR FRACTION ONE THIRD */
|
||||
{ 0x0ab1, 0x2154 }, /* twothirds ⅔ VULGAR FRACTION TWO THIRDS */
|
||||
{ 0x0ab2, 0x2155 }, /* onefifth ⅕ VULGAR FRACTION ONE FIFTH */
|
||||
{ 0x0ab3, 0x2156 }, /* twofifths ⅖ VULGAR FRACTION TWO FIFTHS */
|
||||
{ 0x0ab4, 0x2157 }, /* threefifths ⅗ VULGAR FRACTION THREE FIFTHS */
|
||||
{ 0x0ab5, 0x2158 }, /* fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS */
|
||||
{ 0x0ab6, 0x2159 }, /* onesixth ⅙ VULGAR FRACTION ONE SIXTH */
|
||||
{ 0x0ab7, 0x215a }, /* fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS */
|
||||
{ 0x0ab8, 0x2105 }, /* careof ℅ CARE OF */
|
||||
{ 0x0abb, 0x2012 }, /* figdash ‒ FIGURE DASH */
|
||||
{ 0x0abc, 0x2329 }, /* leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET */
|
||||
/* 0x0abd decimalpoint ? ??? */
|
||||
{ 0x0abe, 0x232a }, /* rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET */
|
||||
/* 0x0abf marker ? ??? */
|
||||
{ 0x0ac3, 0x215b }, /* oneeighth ⅛ VULGAR FRACTION ONE EIGHTH */
|
||||
{ 0x0ac4, 0x215c }, /* threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS */
|
||||
{ 0x0ac5, 0x215d }, /* fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS */
|
||||
{ 0x0ac6, 0x215e }, /* seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS */
|
||||
{ 0x0ac9, 0x2122 }, /* trademark ™ TRADE MARK SIGN */
|
||||
{ 0x0aca, 0x2613 }, /* signaturemark ☓ SALTIRE */
|
||||
/* 0x0acb trademarkincircle ? ??? */
|
||||
{ 0x0acc, 0x25c1 }, /* leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE */
|
||||
{ 0x0acd, 0x25b7 }, /* rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE */
|
||||
{ 0x0ace, 0x25cb }, /* emopencircle ○ WHITE CIRCLE */
|
||||
{ 0x0acf, 0x25af }, /* emopenrectangle ▯ WHITE VERTICAL RECTANGLE */
|
||||
{ 0x0ad0, 0x2018 }, /* leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK */
|
||||
{ 0x0ad1, 0x2019 }, /* rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK */
|
||||
{ 0x0ad2, 0x201c }, /* leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK */
|
||||
{ 0x0ad3, 0x201d }, /* rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK */
|
||||
{ 0x0ad4, 0x211e }, /* prescription ℞ PRESCRIPTION TAKE */
|
||||
{ 0x0ad6, 0x2032 }, /* minutes ′ PRIME */
|
||||
{ 0x0ad7, 0x2033 }, /* seconds ″ DOUBLE PRIME */
|
||||
{ 0x0ad9, 0x271d }, /* latincross ✝ LATIN CROSS */
|
||||
/* 0x0ada hexagram ? ??? */
|
||||
{ 0x0adb, 0x25ac }, /* filledrectbullet ▬ BLACK RECTANGLE */
|
||||
{ 0x0adc, 0x25c0 }, /* filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE */
|
||||
{ 0x0add, 0x25b6 }, /* filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE */
|
||||
{ 0x0ade, 0x25cf }, /* emfilledcircle ● BLACK CIRCLE */
|
||||
{ 0x0adf, 0x25ae }, /* emfilledrect ▮ BLACK VERTICAL RECTANGLE */
|
||||
{ 0x0ae0, 0x25e6 }, /* enopencircbullet ◦ WHITE BULLET */
|
||||
{ 0x0ae1, 0x25ab }, /* enopensquarebullet ▫ WHITE SMALL SQUARE */
|
||||
{ 0x0ae2, 0x25ad }, /* openrectbullet ▭ WHITE RECTANGLE */
|
||||
{ 0x0ae3, 0x25b3 }, /* opentribulletup △ WHITE UP-POINTING TRIANGLE */
|
||||
{ 0x0ae4, 0x25bd }, /* opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE */
|
||||
{ 0x0ae5, 0x2606 }, /* openstar ☆ WHITE STAR */
|
||||
{ 0x0ae6, 0x2022 }, /* enfilledcircbullet • BULLET */
|
||||
{ 0x0ae7, 0x25aa }, /* enfilledsqbullet ▪ BLACK SMALL SQUARE */
|
||||
{ 0x0ae8, 0x25b2 }, /* filledtribulletup ▲ BLACK UP-POINTING TRIANGLE */
|
||||
{ 0x0ae9, 0x25bc }, /* filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE */
|
||||
{ 0x0aea, 0x261c }, /* leftpointer ☜ WHITE LEFT POINTING INDEX */
|
||||
{ 0x0aeb, 0x261e }, /* rightpointer ☞ WHITE RIGHT POINTING INDEX */
|
||||
{ 0x0aec, 0x2663 }, /* club ♣ BLACK CLUB SUIT */
|
||||
{ 0x0aed, 0x2666 }, /* diamond ♦ BLACK DIAMOND SUIT */
|
||||
{ 0x0aee, 0x2665 }, /* heart ♥ BLACK HEART SUIT */
|
||||
{ 0x0af0, 0x2720 }, /* maltesecross ✠ MALTESE CROSS */
|
||||
{ 0x0af1, 0x2020 }, /* dagger † DAGGER */
|
||||
{ 0x0af2, 0x2021 }, /* doubledagger ‡ DOUBLE DAGGER */
|
||||
{ 0x0af3, 0x2713 }, /* checkmark ✓ CHECK MARK */
|
||||
{ 0x0af4, 0x2717 }, /* ballotcross ✗ BALLOT X */
|
||||
{ 0x0af5, 0x266f }, /* musicalsharp ♯ MUSIC SHARP SIGN */
|
||||
{ 0x0af6, 0x266d }, /* musicalflat ♭ MUSIC FLAT SIGN */
|
||||
{ 0x0af7, 0x2642 }, /* malesymbol ♂ MALE SIGN */
|
||||
{ 0x0af8, 0x2640 }, /* femalesymbol ♀ FEMALE SIGN */
|
||||
{ 0x0af9, 0x260e }, /* telephone ☎ BLACK TELEPHONE */
|
||||
{ 0x0afa, 0x2315 }, /* telephonerecorder ⌕ TELEPHONE RECORDER */
|
||||
{ 0x0afb, 0x2117 }, /* phonographcopyright ℗ SOUND RECORDING COPYRIGHT */
|
||||
{ 0x0afc, 0x2038 }, /* caret ‸ CARET */
|
||||
{ 0x0afd, 0x201a }, /* singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK */
|
||||
{ 0x0afe, 0x201e }, /* doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK */
|
||||
/* 0x0aff cursor ? ??? */
|
||||
{ 0x0ba3, 0x003c }, /* leftcaret < LESS-THAN SIGN */
|
||||
{ 0x0ba6, 0x003e }, /* rightcaret > GREATER-THAN SIGN */
|
||||
{ 0x0ba8, 0x2228 }, /* downcaret ∨ LOGICAL OR */
|
||||
{ 0x0ba9, 0x2227 }, /* upcaret ∧ LOGICAL AND */
|
||||
{ 0x0bc0, 0x00af }, /* overbar ¯ MACRON */
|
||||
{ 0x0bc2, 0x22a5 }, /* downtack ⊥ UP TACK */
|
||||
{ 0x0bc3, 0x2229 }, /* upshoe ∩ INTERSECTION */
|
||||
{ 0x0bc4, 0x230a }, /* downstile ⌊ LEFT FLOOR */
|
||||
{ 0x0bc6, 0x005f }, /* underbar _ LOW LINE */
|
||||
{ 0x0bca, 0x2218 }, /* jot ∘ RING OPERATOR */
|
||||
{ 0x0bcc, 0x2395 }, /* quad ⎕ APL FUNCTIONAL SYMBOL QUAD */
|
||||
{ 0x0bce, 0x22a4 }, /* uptack ⊤ DOWN TACK */
|
||||
{ 0x0bcf, 0x25cb }, /* circle ○ WHITE CIRCLE */
|
||||
{ 0x0bd3, 0x2308 }, /* upstile ⌈ LEFT CEILING */
|
||||
{ 0x0bd6, 0x222a }, /* downshoe ∪ UNION */
|
||||
{ 0x0bd8, 0x2283 }, /* rightshoe ⊃ SUPERSET OF */
|
||||
{ 0x0bda, 0x2282 }, /* leftshoe ⊂ SUBSET OF */
|
||||
{ 0x0bdc, 0x22a2 }, /* lefttack ⊢ RIGHT TACK */
|
||||
{ 0x0bfc, 0x22a3 }, /* righttack ⊣ LEFT TACK */
|
||||
{ 0x0cdf, 0x2017 }, /* hebrew_doublelowline ‗ DOUBLE LOW LINE */
|
||||
{ 0x0ce0, 0x05d0 }, /* hebrew_aleph א HEBREW LETTER ALEF */
|
||||
{ 0x0ce1, 0x05d1 }, /* hebrew_bet ב HEBREW LETTER BET */
|
||||
{ 0x0ce2, 0x05d2 }, /* hebrew_gimel ג HEBREW LETTER GIMEL */
|
||||
{ 0x0ce3, 0x05d3 }, /* hebrew_dalet ד HEBREW LETTER DALET */
|
||||
{ 0x0ce4, 0x05d4 }, /* hebrew_he ה HEBREW LETTER HE */
|
||||
{ 0x0ce5, 0x05d5 }, /* hebrew_waw ו HEBREW LETTER VAV */
|
||||
{ 0x0ce6, 0x05d6 }, /* hebrew_zain ז HEBREW LETTER ZAYIN */
|
||||
{ 0x0ce7, 0x05d7 }, /* hebrew_chet ח HEBREW LETTER HET */
|
||||
{ 0x0ce8, 0x05d8 }, /* hebrew_tet ט HEBREW LETTER TET */
|
||||
{ 0x0ce9, 0x05d9 }, /* hebrew_yod י HEBREW LETTER YOD */
|
||||
{ 0x0cea, 0x05da }, /* hebrew_finalkaph ך HEBREW LETTER FINAL KAF */
|
||||
{ 0x0ceb, 0x05db }, /* hebrew_kaph כ HEBREW LETTER KAF */
|
||||
{ 0x0cec, 0x05dc }, /* hebrew_lamed ל HEBREW LETTER LAMED */
|
||||
{ 0x0ced, 0x05dd }, /* hebrew_finalmem ם HEBREW LETTER FINAL MEM */
|
||||
{ 0x0cee, 0x05de }, /* hebrew_mem מ HEBREW LETTER MEM */
|
||||
{ 0x0cef, 0x05df }, /* hebrew_finalnun ן HEBREW LETTER FINAL NUN */
|
||||
{ 0x0cf0, 0x05e0 }, /* hebrew_nun נ HEBREW LETTER NUN */
|
||||
{ 0x0cf1, 0x05e1 }, /* hebrew_samech ס HEBREW LETTER SAMEKH */
|
||||
{ 0x0cf2, 0x05e2 }, /* hebrew_ayin ע HEBREW LETTER AYIN */
|
||||
{ 0x0cf3, 0x05e3 }, /* hebrew_finalpe ף HEBREW LETTER FINAL PE */
|
||||
{ 0x0cf4, 0x05e4 }, /* hebrew_pe פ HEBREW LETTER PE */
|
||||
{ 0x0cf5, 0x05e5 }, /* hebrew_finalzade ץ HEBREW LETTER FINAL TSADI */
|
||||
{ 0x0cf6, 0x05e6 }, /* hebrew_zade צ HEBREW LETTER TSADI */
|
||||
{ 0x0cf7, 0x05e7 }, /* hebrew_qoph ק HEBREW LETTER QOF */
|
||||
{ 0x0cf8, 0x05e8 }, /* hebrew_resh ר HEBREW LETTER RESH */
|
||||
{ 0x0cf9, 0x05e9 }, /* hebrew_shin ש HEBREW LETTER SHIN */
|
||||
{ 0x0cfa, 0x05ea }, /* hebrew_taw ת HEBREW LETTER TAV */
|
||||
{ 0x0da1, 0x0e01 }, /* Thai_kokai ก THAI CHARACTER KO KAI */
|
||||
{ 0x0da2, 0x0e02 }, /* Thai_khokhai ข THAI CHARACTER KHO KHAI */
|
||||
{ 0x0da3, 0x0e03 }, /* Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT */
|
||||
{ 0x0da4, 0x0e04 }, /* Thai_khokhwai ค THAI CHARACTER KHO KHWAI */
|
||||
{ 0x0da5, 0x0e05 }, /* Thai_khokhon ฅ THAI CHARACTER KHO KHON */
|
||||
{ 0x0da6, 0x0e06 }, /* Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG */
|
||||
{ 0x0da7, 0x0e07 }, /* Thai_ngongu ง THAI CHARACTER NGO NGU */
|
||||
{ 0x0da8, 0x0e08 }, /* Thai_chochan จ THAI CHARACTER CHO CHAN */
|
||||
{ 0x0da9, 0x0e09 }, /* Thai_choching ฉ THAI CHARACTER CHO CHING */
|
||||
{ 0x0daa, 0x0e0a }, /* Thai_chochang ช THAI CHARACTER CHO CHANG */
|
||||
{ 0x0dab, 0x0e0b }, /* Thai_soso ซ THAI CHARACTER SO SO */
|
||||
{ 0x0dac, 0x0e0c }, /* Thai_chochoe ฌ THAI CHARACTER CHO CHOE */
|
||||
{ 0x0dad, 0x0e0d }, /* Thai_yoying ญ THAI CHARACTER YO YING */
|
||||
{ 0x0dae, 0x0e0e }, /* Thai_dochada ฎ THAI CHARACTER DO CHADA */
|
||||
{ 0x0daf, 0x0e0f }, /* Thai_topatak ฏ THAI CHARACTER TO PATAK */
|
||||
{ 0x0db0, 0x0e10 }, /* Thai_thothan ฐ THAI CHARACTER THO THAN */
|
||||
{ 0x0db1, 0x0e11 }, /* Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO */
|
||||
{ 0x0db2, 0x0e12 }, /* Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO */
|
||||
{ 0x0db3, 0x0e13 }, /* Thai_nonen ณ THAI CHARACTER NO NEN */
|
||||
{ 0x0db4, 0x0e14 }, /* Thai_dodek ด THAI CHARACTER DO DEK */
|
||||
{ 0x0db5, 0x0e15 }, /* Thai_totao ต THAI CHARACTER TO TAO */
|
||||
{ 0x0db6, 0x0e16 }, /* Thai_thothung ถ THAI CHARACTER THO THUNG */
|
||||
{ 0x0db7, 0x0e17 }, /* Thai_thothahan ท THAI CHARACTER THO THAHAN */
|
||||
{ 0x0db8, 0x0e18 }, /* Thai_thothong ธ THAI CHARACTER THO THONG */
|
||||
{ 0x0db9, 0x0e19 }, /* Thai_nonu น THAI CHARACTER NO NU */
|
||||
{ 0x0dba, 0x0e1a }, /* Thai_bobaimai บ THAI CHARACTER BO BAIMAI */
|
||||
{ 0x0dbb, 0x0e1b }, /* Thai_popla ป THAI CHARACTER PO PLA */
|
||||
{ 0x0dbc, 0x0e1c }, /* Thai_phophung ผ THAI CHARACTER PHO PHUNG */
|
||||
{ 0x0dbd, 0x0e1d }, /* Thai_fofa ฝ THAI CHARACTER FO FA */
|
||||
{ 0x0dbe, 0x0e1e }, /* Thai_phophan พ THAI CHARACTER PHO PHAN */
|
||||
{ 0x0dbf, 0x0e1f }, /* Thai_fofan ฟ THAI CHARACTER FO FAN */
|
||||
{ 0x0dc0, 0x0e20 }, /* Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO */
|
||||
{ 0x0dc1, 0x0e21 }, /* Thai_moma ม THAI CHARACTER MO MA */
|
||||
{ 0x0dc2, 0x0e22 }, /* Thai_yoyak ย THAI CHARACTER YO YAK */
|
||||
{ 0x0dc3, 0x0e23 }, /* Thai_rorua ร THAI CHARACTER RO RUA */
|
||||
{ 0x0dc4, 0x0e24 }, /* Thai_ru ฤ THAI CHARACTER RU */
|
||||
{ 0x0dc5, 0x0e25 }, /* Thai_loling ล THAI CHARACTER LO LING */
|
||||
{ 0x0dc6, 0x0e26 }, /* Thai_lu ฦ THAI CHARACTER LU */
|
||||
{ 0x0dc7, 0x0e27 }, /* Thai_wowaen ว THAI CHARACTER WO WAEN */
|
||||
{ 0x0dc8, 0x0e28 }, /* Thai_sosala ศ THAI CHARACTER SO SALA */
|
||||
{ 0x0dc9, 0x0e29 }, /* Thai_sorusi ษ THAI CHARACTER SO RUSI */
|
||||
{ 0x0dca, 0x0e2a }, /* Thai_sosua ส THAI CHARACTER SO SUA */
|
||||
{ 0x0dcb, 0x0e2b }, /* Thai_hohip ห THAI CHARACTER HO HIP */
|
||||
{ 0x0dcc, 0x0e2c }, /* Thai_lochula ฬ THAI CHARACTER LO CHULA */
|
||||
{ 0x0dcd, 0x0e2d }, /* Thai_oang อ THAI CHARACTER O ANG */
|
||||
{ 0x0dce, 0x0e2e }, /* Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK */
|
||||
{ 0x0dcf, 0x0e2f }, /* Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI */
|
||||
{ 0x0dd0, 0x0e30 }, /* Thai_saraa ะ THAI CHARACTER SARA A */
|
||||
{ 0x0dd1, 0x0e31 }, /* Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT */
|
||||
{ 0x0dd2, 0x0e32 }, /* Thai_saraaa า THAI CHARACTER SARA AA */
|
||||
{ 0x0dd3, 0x0e33 }, /* Thai_saraam ำ THAI CHARACTER SARA AM */
|
||||
{ 0x0dd4, 0x0e34 }, /* Thai_sarai ิ THAI CHARACTER SARA I */
|
||||
{ 0x0dd5, 0x0e35 }, /* Thai_saraii ี THAI CHARACTER SARA II */
|
||||
{ 0x0dd6, 0x0e36 }, /* Thai_saraue ึ THAI CHARACTER SARA UE */
|
||||
{ 0x0dd7, 0x0e37 }, /* Thai_sarauee ื THAI CHARACTER SARA UEE */
|
||||
{ 0x0dd8, 0x0e38 }, /* Thai_sarau ุ THAI CHARACTER SARA U */
|
||||
{ 0x0dd9, 0x0e39 }, /* Thai_sarauu ู THAI CHARACTER SARA UU */
|
||||
{ 0x0dda, 0x0e3a }, /* Thai_phinthu ฺ THAI CHARACTER PHINTHU */
|
||||
/* 0x0dde Thai_maihanakat_maitho ? ??? */
|
||||
{ 0x0ddf, 0x0e3f }, /* Thai_baht ฿ THAI CURRENCY SYMBOL BAHT */
|
||||
{ 0x0de0, 0x0e40 }, /* Thai_sarae เ THAI CHARACTER SARA E */
|
||||
{ 0x0de1, 0x0e41 }, /* Thai_saraae แ THAI CHARACTER SARA AE */
|
||||
{ 0x0de2, 0x0e42 }, /* Thai_sarao โ THAI CHARACTER SARA O */
|
||||
{ 0x0de3, 0x0e43 }, /* Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN */
|
||||
{ 0x0de4, 0x0e44 }, /* Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI */
|
||||
{ 0x0de5, 0x0e45 }, /* Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO */
|
||||
{ 0x0de6, 0x0e46 }, /* Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK */
|
||||
{ 0x0de7, 0x0e47 }, /* Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU */
|
||||
{ 0x0de8, 0x0e48 }, /* Thai_maiek ่ THAI CHARACTER MAI EK */
|
||||
{ 0x0de9, 0x0e49 }, /* Thai_maitho ้ THAI CHARACTER MAI THO */
|
||||
{ 0x0dea, 0x0e4a }, /* Thai_maitri ๊ THAI CHARACTER MAI TRI */
|
||||
{ 0x0deb, 0x0e4b }, /* Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA */
|
||||
{ 0x0dec, 0x0e4c }, /* Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT */
|
||||
{ 0x0ded, 0x0e4d }, /* Thai_nikhahit ํ THAI CHARACTER NIKHAHIT */
|
||||
{ 0x0df0, 0x0e50 }, /* Thai_leksun ๐ THAI DIGIT ZERO */
|
||||
{ 0x0df1, 0x0e51 }, /* Thai_leknung ๑ THAI DIGIT ONE */
|
||||
{ 0x0df2, 0x0e52 }, /* Thai_leksong ๒ THAI DIGIT TWO */
|
||||
{ 0x0df3, 0x0e53 }, /* Thai_leksam ๓ THAI DIGIT THREE */
|
||||
{ 0x0df4, 0x0e54 }, /* Thai_leksi ๔ THAI DIGIT FOUR */
|
||||
{ 0x0df5, 0x0e55 }, /* Thai_lekha ๕ THAI DIGIT FIVE */
|
||||
{ 0x0df6, 0x0e56 }, /* Thai_lekhok ๖ THAI DIGIT SIX */
|
||||
{ 0x0df7, 0x0e57 }, /* Thai_lekchet ๗ THAI DIGIT SEVEN */
|
||||
{ 0x0df8, 0x0e58 }, /* Thai_lekpaet ๘ THAI DIGIT EIGHT */
|
||||
{ 0x0df9, 0x0e59 }, /* Thai_lekkao ๙ THAI DIGIT NINE */
|
||||
{ 0x0ea1, 0x3131 }, /* Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK */
|
||||
{ 0x0ea2, 0x3132 }, /* Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK */
|
||||
{ 0x0ea3, 0x3133 }, /* Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS */
|
||||
{ 0x0ea4, 0x3134 }, /* Hangul_Nieun ㄴ HANGUL LETTER NIEUN */
|
||||
{ 0x0ea5, 0x3135 }, /* Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC */
|
||||
{ 0x0ea6, 0x3136 }, /* Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH */
|
||||
{ 0x0ea7, 0x3137 }, /* Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT */
|
||||
{ 0x0ea8, 0x3138 }, /* Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT */
|
||||
{ 0x0ea9, 0x3139 }, /* Hangul_Rieul ㄹ HANGUL LETTER RIEUL */
|
||||
{ 0x0eaa, 0x313a }, /* Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK */
|
||||
{ 0x0eab, 0x313b }, /* Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM */
|
||||
{ 0x0eac, 0x313c }, /* Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP */
|
||||
{ 0x0ead, 0x313d }, /* Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS */
|
||||
{ 0x0eae, 0x313e }, /* Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH */
|
||||
{ 0x0eaf, 0x313f }, /* Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH */
|
||||
{ 0x0eb0, 0x3140 }, /* Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH */
|
||||
{ 0x0eb1, 0x3141 }, /* Hangul_Mieum ㅁ HANGUL LETTER MIEUM */
|
||||
{ 0x0eb2, 0x3142 }, /* Hangul_Pieub ㅂ HANGUL LETTER PIEUP */
|
||||
{ 0x0eb3, 0x3143 }, /* Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP */
|
||||
{ 0x0eb4, 0x3144 }, /* Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS */
|
||||
{ 0x0eb5, 0x3145 }, /* Hangul_Sios ㅅ HANGUL LETTER SIOS */
|
||||
{ 0x0eb6, 0x3146 }, /* Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS */
|
||||
{ 0x0eb7, 0x3147 }, /* Hangul_Ieung ㅇ HANGUL LETTER IEUNG */
|
||||
{ 0x0eb8, 0x3148 }, /* Hangul_Jieuj ㅈ HANGUL LETTER CIEUC */
|
||||
{ 0x0eb9, 0x3149 }, /* Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC */
|
||||
{ 0x0eba, 0x314a }, /* Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH */
|
||||
{ 0x0ebb, 0x314b }, /* Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH */
|
||||
{ 0x0ebc, 0x314c }, /* Hangul_Tieut ㅌ HANGUL LETTER THIEUTH */
|
||||
{ 0x0ebd, 0x314d }, /* Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH */
|
||||
{ 0x0ebe, 0x314e }, /* Hangul_Hieuh ㅎ HANGUL LETTER HIEUH */
|
||||
{ 0x0ebf, 0x314f }, /* Hangul_A ㅏ HANGUL LETTER A */
|
||||
{ 0x0ec0, 0x3150 }, /* Hangul_AE ㅐ HANGUL LETTER AE */
|
||||
{ 0x0ec1, 0x3151 }, /* Hangul_YA ㅑ HANGUL LETTER YA */
|
||||
{ 0x0ec2, 0x3152 }, /* Hangul_YAE ㅒ HANGUL LETTER YAE */
|
||||
{ 0x0ec3, 0x3153 }, /* Hangul_EO ㅓ HANGUL LETTER EO */
|
||||
{ 0x0ec4, 0x3154 }, /* Hangul_E ㅔ HANGUL LETTER E */
|
||||
{ 0x0ec5, 0x3155 }, /* Hangul_YEO ㅕ HANGUL LETTER YEO */
|
||||
{ 0x0ec6, 0x3156 }, /* Hangul_YE ㅖ HANGUL LETTER YE */
|
||||
{ 0x0ec7, 0x3157 }, /* Hangul_O ㅗ HANGUL LETTER O */
|
||||
{ 0x0ec8, 0x3158 }, /* Hangul_WA ㅘ HANGUL LETTER WA */
|
||||
{ 0x0ec9, 0x3159 }, /* Hangul_WAE ㅙ HANGUL LETTER WAE */
|
||||
{ 0x0eca, 0x315a }, /* Hangul_OE ㅚ HANGUL LETTER OE */
|
||||
{ 0x0ecb, 0x315b }, /* Hangul_YO ㅛ HANGUL LETTER YO */
|
||||
{ 0x0ecc, 0x315c }, /* Hangul_U ㅜ HANGUL LETTER U */
|
||||
{ 0x0ecd, 0x315d }, /* Hangul_WEO ㅝ HANGUL LETTER WEO */
|
||||
{ 0x0ece, 0x315e }, /* Hangul_WE ㅞ HANGUL LETTER WE */
|
||||
{ 0x0ecf, 0x315f }, /* Hangul_WI ㅟ HANGUL LETTER WI */
|
||||
{ 0x0ed0, 0x3160 }, /* Hangul_YU ㅠ HANGUL LETTER YU */
|
||||
{ 0x0ed1, 0x3161 }, /* Hangul_EU ㅡ HANGUL LETTER EU */
|
||||
{ 0x0ed2, 0x3162 }, /* Hangul_YI ㅢ HANGUL LETTER YI */
|
||||
{ 0x0ed3, 0x3163 }, /* Hangul_I ㅣ HANGUL LETTER I */
|
||||
{ 0x0ed4, 0x11a8 }, /* Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK */
|
||||
{ 0x0ed5, 0x11a9 }, /* Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK */
|
||||
{ 0x0ed6, 0x11aa }, /* Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS */
|
||||
{ 0x0ed7, 0x11ab }, /* Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN */
|
||||
{ 0x0ed8, 0x11ac }, /* Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC */
|
||||
{ 0x0ed9, 0x11ad }, /* Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH */
|
||||
{ 0x0eda, 0x11ae }, /* Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT */
|
||||
{ 0x0edb, 0x11af }, /* Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL */
|
||||
{ 0x0edc, 0x11b0 }, /* Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK */
|
||||
{ 0x0edd, 0x11b1 }, /* Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM */
|
||||
{ 0x0ede, 0x11b2 }, /* Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP */
|
||||
{ 0x0edf, 0x11b3 }, /* Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS */
|
||||
{ 0x0ee0, 0x11b4 }, /* Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH */
|
||||
{ 0x0ee1, 0x11b5 }, /* Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH */
|
||||
{ 0x0ee2, 0x11b6 }, /* Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH */
|
||||
{ 0x0ee3, 0x11b7 }, /* Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM */
|
||||
{ 0x0ee4, 0x11b8 }, /* Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP */
|
||||
{ 0x0ee5, 0x11b9 }, /* Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS */
|
||||
{ 0x0ee6, 0x11ba }, /* Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS */
|
||||
{ 0x0ee7, 0x11bb }, /* Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS */
|
||||
{ 0x0ee8, 0x11bc }, /* Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG */
|
||||
{ 0x0ee9, 0x11bd }, /* Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC */
|
||||
{ 0x0eea, 0x11be }, /* Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH */
|
||||
{ 0x0eeb, 0x11bf }, /* Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH */
|
||||
{ 0x0eec, 0x11c0 }, /* Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH */
|
||||
{ 0x0eed, 0x11c1 }, /* Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH */
|
||||
{ 0x0eee, 0x11c2 }, /* Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH */
|
||||
{ 0x0eef, 0x316d }, /* Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH */
|
||||
{ 0x0ef0, 0x3171 }, /* Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM */
|
||||
{ 0x0ef1, 0x3178 }, /* Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP */
|
||||
{ 0x0ef2, 0x317f }, /* Hangul_PanSios ㅿ HANGUL LETTER PANSIOS */
|
||||
{ 0x0ef3, 0x3181 }, /* Hangul_KkogjiDalrinIeung ㆁ HANGUL LETTER YESIEUNG */
|
||||
{ 0x0ef4, 0x3184 }, /* Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH */
|
||||
{ 0x0ef5, 0x3186 }, /* Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH */
|
||||
{ 0x0ef6, 0x318d }, /* Hangul_AraeA ㆍ HANGUL LETTER ARAEA */
|
||||
{ 0x0ef7, 0x318e }, /* Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE */
|
||||
{ 0x0ef8, 0x11eb }, /* Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS */
|
||||
{ 0x0ef9, 0x11f0 }, /* Hangul_J_KkogjiDalrinIeung ᇰ HANGUL JONGSEONG YESIEUNG */
|
||||
{ 0x0efa, 0x11f9 }, /* Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH */
|
||||
{ 0x0eff, 0x20a9 }, /* Korean_Won ₩ WON SIGN */
|
||||
{ 0x13a4, 0x20ac }, /* Euro € EURO SIGN */
|
||||
{ 0x13bc, 0x0152 }, /* OE Œ LATIN CAPITAL LIGATURE OE */
|
||||
{ 0x13bd, 0x0153 }, /* oe œ LATIN SMALL LIGATURE OE */
|
||||
{ 0x13be, 0x0178 }, /* Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS */
|
||||
{ 0x20ac, 0x20ac }, /* EuroSign € EURO SIGN */
|
||||
};
|
||||
|
||||
VISIBLE
|
||||
long keysym2ucs(KeySym keysym)
|
||||
{
|
||||
int min = 0;
|
||||
int max = sizeof(keysymtab) / sizeof(struct codepair) - 1;
|
||||
int mid;
|
||||
|
||||
/* first check for Latin-1 characters (1:1 mapping) */
|
||||
if ((keysym >= 0x0020 && keysym <= 0x007e) ||
|
||||
(keysym >= 0x00a0 && keysym <= 0x00ff))
|
||||
return keysym;
|
||||
|
||||
/* also check for directly encoded 24-bit UCS characters */
|
||||
if ((keysym & 0xff000000) == 0x01000000)
|
||||
return keysym & 0x00ffffff;
|
||||
|
||||
/* binary search in table */
|
||||
while (max >= min) {
|
||||
mid = (min + max) / 2;
|
||||
if (keysymtab[mid].keysym < keysym)
|
||||
min = mid + 1;
|
||||
else if (keysymtab[mid].keysym > keysym)
|
||||
max = mid - 1;
|
||||
else {
|
||||
/* found it */
|
||||
return keysymtab[mid].ucs;
|
||||
}
|
||||
}
|
||||
|
||||
/* no matching Unicode value found */
|
||||
return -1;
|
||||
}
|
9
gui-x11/keysym2ucs.h
Normal file
9
gui-x11/keysym2ucs.h
Normal file
@ -0,0 +1,9 @@
|
||||
/* $XFree86: xc/programs/xterm/keysym2ucs.h,v 1.1 1999/06/12 15:37:18 dawes Exp $ */
|
||||
/*
|
||||
* This module converts keysym values into the corresponding ISO 10646-1
|
||||
* (UCS, Unicode) values.
|
||||
*/
|
||||
|
||||
#include <X11/X.h>
|
||||
|
||||
long keysym2ucs(KeySym keysym);
|
754
gui-x11/ksym2utf.h
Normal file
754
gui-x11/ksym2utf.h
Normal file
@ -0,0 +1,754 @@
|
||||
static ulong
|
||||
ksym2utf[] = {
|
||||
[0x01a1] 0x0104,
|
||||
[0x01a2] 0x02d8,
|
||||
[0x01a3] 0x0141,
|
||||
[0x01a5] 0x013d,
|
||||
[0x01a6] 0x015a,
|
||||
[0x01a9] 0x0160,
|
||||
[0x01aa] 0x015e,
|
||||
[0x01ab] 0x0164,
|
||||
[0x01ac] 0x0179,
|
||||
[0x01ae] 0x017d,
|
||||
[0x01af] 0x017b,
|
||||
[0x01b1] 0x0105,
|
||||
[0x01b2] 0x02db,
|
||||
[0x01b3] 0x0142,
|
||||
[0x01b5] 0x013e,
|
||||
[0x01b6] 0x015b,
|
||||
[0x01b7] 0x02c7,
|
||||
[0x01b9] 0x0161,
|
||||
[0x01ba] 0x015f,
|
||||
[0x01bb] 0x0165,
|
||||
[0x01bc] 0x017a,
|
||||
[0x01bd] 0x02dd,
|
||||
[0x01be] 0x017e,
|
||||
[0x01bf] 0x017c,
|
||||
[0x01c0] 0x0154,
|
||||
[0x01c3] 0x0102,
|
||||
[0x01c5] 0x0139,
|
||||
[0x01c6] 0x0106,
|
||||
[0x01c8] 0x010c,
|
||||
[0x01ca] 0x0118,
|
||||
[0x01cc] 0x011a,
|
||||
[0x01cf] 0x010e,
|
||||
[0x01d0] 0x0110,
|
||||
[0x01d1] 0x0143,
|
||||
[0x01d2] 0x0147,
|
||||
[0x01d5] 0x0150,
|
||||
[0x01d8] 0x0158,
|
||||
[0x01d9] 0x016e,
|
||||
[0x01db] 0x0170,
|
||||
[0x01de] 0x0162,
|
||||
[0x01e0] 0x0155,
|
||||
[0x01e3] 0x0103,
|
||||
[0x01e5] 0x013a,
|
||||
[0x01e6] 0x0107,
|
||||
[0x01e8] 0x010d,
|
||||
[0x01ea] 0x0119,
|
||||
[0x01ec] 0x011b,
|
||||
[0x01ef] 0x010f,
|
||||
[0x01f0] 0x0111,
|
||||
[0x01f1] 0x0144,
|
||||
[0x01f2] 0x0148,
|
||||
[0x01f5] 0x0151,
|
||||
[0x01f8] 0x0159,
|
||||
[0x01f9] 0x016f,
|
||||
[0x01fb] 0x0171,
|
||||
[0x01fe] 0x0163,
|
||||
[0x01ff] 0x02d9,
|
||||
[0x02a1] 0x0126,
|
||||
[0x02a6] 0x0124,
|
||||
[0x02a9] 0x0130,
|
||||
[0x02ab] 0x011e,
|
||||
[0x02ac] 0x0134,
|
||||
[0x02b1] 0x0127,
|
||||
[0x02b6] 0x0125,
|
||||
[0x02b9] 0x0131,
|
||||
[0x02bb] 0x011f,
|
||||
[0x02bc] 0x0135,
|
||||
[0x02c5] 0x010a,
|
||||
[0x02c6] 0x0108,
|
||||
[0x02d5] 0x0120,
|
||||
[0x02d8] 0x011c,
|
||||
[0x02dd] 0x016c,
|
||||
[0x02de] 0x015c,
|
||||
[0x02e5] 0x010b,
|
||||
[0x02e6] 0x0109,
|
||||
[0x02f5] 0x0121,
|
||||
[0x02f8] 0x011d,
|
||||
[0x02fd] 0x016d,
|
||||
[0x02fe] 0x015d,
|
||||
[0x03a2] 0x0138,
|
||||
[0x03a3] 0x0156,
|
||||
[0x03a5] 0x0128,
|
||||
[0x03a6] 0x013b,
|
||||
[0x03aa] 0x0112,
|
||||
[0x03ab] 0x0122,
|
||||
[0x03ac] 0x0166,
|
||||
[0x03b3] 0x0157,
|
||||
[0x03b5] 0x0129,
|
||||
[0x03b6] 0x013c,
|
||||
[0x03ba] 0x0113,
|
||||
[0x03bb] 0x0123,
|
||||
[0x03bc] 0x0167,
|
||||
[0x03bd] 0x014a,
|
||||
[0x03bf] 0x014b,
|
||||
[0x03c0] 0x0100,
|
||||
[0x03c7] 0x012e,
|
||||
[0x03cc] 0x0116,
|
||||
[0x03cf] 0x012a,
|
||||
[0x03d1] 0x0145,
|
||||
[0x03d2] 0x014c,
|
||||
[0x03d3] 0x0136,
|
||||
[0x03d9] 0x0172,
|
||||
[0x03dd] 0x0168,
|
||||
[0x03de] 0x016a,
|
||||
[0x03e0] 0x0101,
|
||||
[0x03e7] 0x012f,
|
||||
[0x03ec] 0x0117,
|
||||
[0x03ef] 0x012b,
|
||||
[0x03f1] 0x0146,
|
||||
[0x03f2] 0x014d,
|
||||
[0x03f3] 0x0137,
|
||||
[0x03f9] 0x0173,
|
||||
[0x03fd] 0x0169,
|
||||
[0x03fe] 0x016b,
|
||||
[0x047e] 0x203e,
|
||||
[0x04a1] 0x3002,
|
||||
[0x04a2] 0x300c,
|
||||
[0x04a3] 0x300d,
|
||||
[0x04a4] 0x3001,
|
||||
[0x04a5] 0x30fb,
|
||||
[0x04a6] 0x30f2,
|
||||
[0x04a7] 0x30a1,
|
||||
[0x04a8] 0x30a3,
|
||||
[0x04a9] 0x30a5,
|
||||
[0x04aa] 0x30a7,
|
||||
[0x04ab] 0x30a9,
|
||||
[0x04ac] 0x30e3,
|
||||
[0x04ad] 0x30e5,
|
||||
[0x04ae] 0x30e7,
|
||||
[0x04af] 0x30c3,
|
||||
[0x04b0] 0x30fc,
|
||||
[0x04b1] 0x30a2,
|
||||
[0x04b2] 0x30a4,
|
||||
[0x04b3] 0x30a6,
|
||||
[0x04b4] 0x30a8,
|
||||
[0x04b5] 0x30aa,
|
||||
[0x04b6] 0x30ab,
|
||||
[0x04b7] 0x30ad,
|
||||
[0x04b8] 0x30af,
|
||||
[0x04b9] 0x30b1,
|
||||
[0x04ba] 0x30b3,
|
||||
[0x04bb] 0x30b5,
|
||||
[0x04bc] 0x30b7,
|
||||
[0x04bd] 0x30b9,
|
||||
[0x04be] 0x30bb,
|
||||
[0x04bf] 0x30bd,
|
||||
[0x04c0] 0x30bf,
|
||||
[0x04c1] 0x30c1,
|
||||
[0x04c2] 0x30c4,
|
||||
[0x04c3] 0x30c6,
|
||||
[0x04c4] 0x30c8,
|
||||
[0x04c5] 0x30ca,
|
||||
[0x04c6] 0x30cb,
|
||||
[0x04c7] 0x30cc,
|
||||
[0x04c8] 0x30cd,
|
||||
[0x04c9] 0x30ce,
|
||||
[0x04ca] 0x30cf,
|
||||
[0x04cb] 0x30d2,
|
||||
[0x04cc] 0x30d5,
|
||||
[0x04cd] 0x30d8,
|
||||
[0x04ce] 0x30db,
|
||||
[0x04cf] 0x30de,
|
||||
[0x04d0] 0x30df,
|
||||
[0x04d1] 0x30e0,
|
||||
[0x04d2] 0x30e1,
|
||||
[0x04d3] 0x30e2,
|
||||
[0x04d4] 0x30e4,
|
||||
[0x04d5] 0x30e6,
|
||||
[0x04d6] 0x30e8,
|
||||
[0x04d7] 0x30e9,
|
||||
[0x04d8] 0x30ea,
|
||||
[0x04d9] 0x30eb,
|
||||
[0x04da] 0x30ec,
|
||||
[0x04db] 0x30ed,
|
||||
[0x04dc] 0x30ef,
|
||||
[0x04dd] 0x30f3,
|
||||
[0x04de] 0x309b,
|
||||
[0x04df] 0x309c,
|
||||
[0x05ac] 0x060c,
|
||||
[0x05bb] 0x061b,
|
||||
[0x05bf] 0x061f,
|
||||
[0x05c1] 0x0621,
|
||||
[0x05c2] 0x0622,
|
||||
[0x05c3] 0x0623,
|
||||
[0x05c4] 0x0624,
|
||||
[0x05c5] 0x0625,
|
||||
[0x05c6] 0x0626,
|
||||
[0x05c7] 0x0627,
|
||||
[0x05c8] 0x0628,
|
||||
[0x05c9] 0x0629,
|
||||
[0x05ca] 0x062a,
|
||||
[0x05cb] 0x062b,
|
||||
[0x05cc] 0x062c,
|
||||
[0x05cd] 0x062d,
|
||||
[0x05ce] 0x062e,
|
||||
[0x05cf] 0x062f,
|
||||
[0x05d0] 0x0630,
|
||||
[0x05d1] 0x0631,
|
||||
[0x05d2] 0x0632,
|
||||
[0x05d3] 0x0633,
|
||||
[0x05d4] 0x0634,
|
||||
[0x05d5] 0x0635,
|
||||
[0x05d6] 0x0636,
|
||||
[0x05d7] 0x0637,
|
||||
[0x05d8] 0x0638,
|
||||
[0x05d9] 0x0639,
|
||||
[0x05da] 0x063a,
|
||||
[0x05e0] 0x0640,
|
||||
[0x05e1] 0x0641,
|
||||
[0x05e2] 0x0642,
|
||||
[0x05e3] 0x0643,
|
||||
[0x05e4] 0x0644,
|
||||
[0x05e5] 0x0645,
|
||||
[0x05e6] 0x0646,
|
||||
[0x05e7] 0x0647,
|
||||
[0x05e8] 0x0648,
|
||||
[0x05e9] 0x0649,
|
||||
[0x05ea] 0x064a,
|
||||
[0x05eb] 0x064b,
|
||||
[0x05ec] 0x064c,
|
||||
[0x05ed] 0x064d,
|
||||
[0x05ee] 0x064e,
|
||||
[0x05ef] 0x064f,
|
||||
[0x05f0] 0x0650,
|
||||
[0x05f1] 0x0651,
|
||||
[0x05f2] 0x0652,
|
||||
[0x06a1] 0x0452,
|
||||
[0x06a2] 0x0453,
|
||||
[0x06a3] 0x0451,
|
||||
[0x06a4] 0x0454,
|
||||
[0x06a5] 0x0455,
|
||||
[0x06a6] 0x0456,
|
||||
[0x06a7] 0x0457,
|
||||
[0x06a8] 0x0458,
|
||||
[0x06a9] 0x0459,
|
||||
[0x06aa] 0x045a,
|
||||
[0x06ab] 0x045b,
|
||||
[0x06ac] 0x045c,
|
||||
[0x06ae] 0x045e,
|
||||
[0x06af] 0x045f,
|
||||
[0x06b0] 0x2116,
|
||||
[0x06b1] 0x0402,
|
||||
[0x06b2] 0x0403,
|
||||
[0x06b3] 0x0401,
|
||||
[0x06b4] 0x0404,
|
||||
[0x06b5] 0x0405,
|
||||
[0x06b6] 0x0406,
|
||||
[0x06b7] 0x0407,
|
||||
[0x06b8] 0x0408,
|
||||
[0x06b9] 0x0409,
|
||||
[0x06ba] 0x040a,
|
||||
[0x06bb] 0x040b,
|
||||
[0x06bc] 0x040c,
|
||||
[0x06be] 0x040e,
|
||||
[0x06bf] 0x040f,
|
||||
[0x06c0] 0x044e,
|
||||
[0x06c1] 0x0430,
|
||||
[0x06c2] 0x0431,
|
||||
[0x06c3] 0x0446,
|
||||
[0x06c4] 0x0434,
|
||||
[0x06c5] 0x0435,
|
||||
[0x06c6] 0x0444,
|
||||
[0x06c7] 0x0433,
|
||||
[0x06c8] 0x0445,
|
||||
[0x06c9] 0x0438,
|
||||
[0x06ca] 0x0439,
|
||||
[0x06cb] 0x043a,
|
||||
[0x06cc] 0x043b,
|
||||
[0x06cd] 0x043c,
|
||||
[0x06ce] 0x043d,
|
||||
[0x06cf] 0x043e,
|
||||
[0x06d0] 0x043f,
|
||||
[0x06d1] 0x044f,
|
||||
[0x06d2] 0x0440,
|
||||
[0x06d3] 0x0441,
|
||||
[0x06d4] 0x0442,
|
||||
[0x06d5] 0x0443,
|
||||
[0x06d6] 0x0436,
|
||||
[0x06d7] 0x0432,
|
||||
[0x06d8] 0x044c,
|
||||
[0x06d9] 0x044b,
|
||||
[0x06da] 0x0437,
|
||||
[0x06db] 0x0448,
|
||||
[0x06dc] 0x044d,
|
||||
[0x06dd] 0x0449,
|
||||
[0x06de] 0x0447,
|
||||
[0x06df] 0x044a,
|
||||
[0x06e0] 0x042e,
|
||||
[0x06e1] 0x0410,
|
||||
[0x06e2] 0x0411,
|
||||
[0x06e3] 0x0426,
|
||||
[0x06e4] 0x0414,
|
||||
[0x06e5] 0x0415,
|
||||
[0x06e6] 0x0424,
|
||||
[0x06e7] 0x0413,
|
||||
[0x06e8] 0x0425,
|
||||
[0x06e9] 0x0418,
|
||||
[0x06ea] 0x0419,
|
||||
[0x06eb] 0x041a,
|
||||
[0x06ec] 0x041b,
|
||||
[0x06ed] 0x041c,
|
||||
[0x06ee] 0x041d,
|
||||
[0x06ef] 0x041e,
|
||||
[0x06f0] 0x041f,
|
||||
[0x06f1] 0x042f,
|
||||
[0x06f2] 0x0420,
|
||||
[0x06f3] 0x0421,
|
||||
[0x06f4] 0x0422,
|
||||
[0x06f5] 0x0423,
|
||||
[0x06f6] 0x0416,
|
||||
[0x06f7] 0x0412,
|
||||
[0x06f8] 0x042c,
|
||||
[0x06f9] 0x042b,
|
||||
[0x06fa] 0x0417,
|
||||
[0x06fb] 0x0428,
|
||||
[0x06fc] 0x042d,
|
||||
[0x06fd] 0x0429,
|
||||
[0x06fe] 0x0427,
|
||||
[0x06ff] 0x042a,
|
||||
[0x07a1] 0x0386,
|
||||
[0x07a2] 0x0388,
|
||||
[0x07a3] 0x0389,
|
||||
[0x07a4] 0x038a,
|
||||
[0x07a5] 0x03aa,
|
||||
[0x07a7] 0x038c,
|
||||
[0x07a8] 0x038e,
|
||||
[0x07a9] 0x03ab,
|
||||
[0x07ab] 0x038f,
|
||||
[0x07ae] 0x0385,
|
||||
[0x07af] 0x2015,
|
||||
[0x07b1] 0x03ac,
|
||||
[0x07b2] 0x03ad,
|
||||
[0x07b3] 0x03ae,
|
||||
[0x07b4] 0x03af,
|
||||
[0x07b5] 0x03ca,
|
||||
[0x07b6] 0x0390,
|
||||
[0x07b7] 0x03cc,
|
||||
[0x07b8] 0x03cd,
|
||||
[0x07b9] 0x03cb,
|
||||
[0x07ba] 0x03b0,
|
||||
[0x07bb] 0x03ce,
|
||||
[0x07c1] 0x0391,
|
||||
[0x07c2] 0x0392,
|
||||
[0x07c3] 0x0393,
|
||||
[0x07c4] 0x0394,
|
||||
[0x07c5] 0x0395,
|
||||
[0x07c6] 0x0396,
|
||||
[0x07c7] 0x0397,
|
||||
[0x07c8] 0x0398,
|
||||
[0x07c9] 0x0399,
|
||||
[0x07ca] 0x039a,
|
||||
[0x07cb] 0x039b,
|
||||
[0x07cc] 0x039c,
|
||||
[0x07cd] 0x039d,
|
||||
[0x07ce] 0x039e,
|
||||
[0x07cf] 0x039f,
|
||||
[0x07d0] 0x03a0,
|
||||
[0x07d1] 0x03a1,
|
||||
[0x07d2] 0x03a3,
|
||||
[0x07d4] 0x03a4,
|
||||
[0x07d5] 0x03a5,
|
||||
[0x07d6] 0x03a6,
|
||||
[0x07d7] 0x03a7,
|
||||
[0x07d8] 0x03a8,
|
||||
[0x07d9] 0x03a9,
|
||||
[0x07e1] 0x03b1,
|
||||
[0x07e2] 0x03b2,
|
||||
[0x07e3] 0x03b3,
|
||||
[0x07e4] 0x03b4,
|
||||
[0x07e5] 0x03b5,
|
||||
[0x07e6] 0x03b6,
|
||||
[0x07e7] 0x03b7,
|
||||
[0x07e8] 0x03b8,
|
||||
[0x07e9] 0x03b9,
|
||||
[0x07ea] 0x03ba,
|
||||
[0x07eb] 0x03bb,
|
||||
[0x07ec] 0x03bc,
|
||||
[0x07ed] 0x03bd,
|
||||
[0x07ee] 0x03be,
|
||||
[0x07ef] 0x03bf,
|
||||
[0x07f0] 0x03c0,
|
||||
[0x07f1] 0x03c1,
|
||||
[0x07f2] 0x03c3,
|
||||
[0x07f3] 0x03c2,
|
||||
[0x07f4] 0x03c4,
|
||||
[0x07f5] 0x03c5,
|
||||
[0x07f6] 0x03c6,
|
||||
[0x07f7] 0x03c7,
|
||||
[0x07f8] 0x03c8,
|
||||
[0x07f9] 0x03c9,
|
||||
[0x08a4] 0x2320,
|
||||
[0x08a5] 0x2321,
|
||||
[0x08a6] 0x2502,
|
||||
[0x08bc] 0x2264,
|
||||
[0x08bd] 0x2260,
|
||||
[0x08be] 0x2265,
|
||||
[0x08bf] 0x222b,
|
||||
[0x08c0] 0x2234,
|
||||
[0x08c1] 0x221d,
|
||||
[0x08c2] 0x221e,
|
||||
[0x08c5] 0x2207,
|
||||
[0x08c8] 0x2245,
|
||||
[0x08cd] 0x21d4,
|
||||
[0x08ce] 0x21d2,
|
||||
[0x08cf] 0x2261,
|
||||
[0x08d6] 0x221a,
|
||||
[0x08da] 0x2282,
|
||||
[0x08db] 0x2283,
|
||||
[0x08dc] 0x2229,
|
||||
[0x08dd] 0x222a,
|
||||
[0x08de] 0x2227,
|
||||
[0x08df] 0x2228,
|
||||
[0x08ef] 0x2202,
|
||||
[0x08f6] 0x0192,
|
||||
[0x08fb] 0x2190,
|
||||
[0x08fc] 0x2191,
|
||||
[0x08fd] 0x2192,
|
||||
[0x08fe] 0x2193,
|
||||
[0x09df] 0x2422,
|
||||
[0x09e0] 0x25c6,
|
||||
[0x09e1] 0x2592,
|
||||
[0x09e2] 0x2409,
|
||||
[0x09e3] 0x240c,
|
||||
[0x09e4] 0x240d,
|
||||
[0x09e5] 0x240a,
|
||||
[0x09e8] 0x2424,
|
||||
[0x09e9] 0x240b,
|
||||
[0x09ea] 0x2518,
|
||||
[0x09eb] 0x2510,
|
||||
[0x09ec] 0x250c,
|
||||
[0x09ed] 0x2514,
|
||||
[0x09ee] 0x253c,
|
||||
[0x09f1] 0x2500,
|
||||
[0x09f4] 0x251c,
|
||||
[0x09f5] 0x2524,
|
||||
[0x09f6] 0x2534,
|
||||
[0x09f7] 0x252c,
|
||||
[0x09f8] 0x2502,
|
||||
[0x0aa1] 0x2003,
|
||||
[0x0aa2] 0x2002,
|
||||
[0x0aa3] 0x2004,
|
||||
[0x0aa4] 0x2005,
|
||||
[0x0aa5] 0x2007,
|
||||
[0x0aa6] 0x2008,
|
||||
[0x0aa7] 0x2009,
|
||||
[0x0aa8] 0x200a,
|
||||
[0x0aa9] 0x2014,
|
||||
[0x0aaa] 0x2013,
|
||||
[0x0aae] 0x2026,
|
||||
[0x0ab0] 0x2153,
|
||||
[0x0ab1] 0x2154,
|
||||
[0x0ab2] 0x2155,
|
||||
[0x0ab3] 0x2156,
|
||||
[0x0ab4] 0x2157,
|
||||
[0x0ab5] 0x2158,
|
||||
[0x0ab6] 0x2159,
|
||||
[0x0ab7] 0x215a,
|
||||
[0x0ab8] 0x2105,
|
||||
[0x0abb] 0x2012,
|
||||
[0x0abc] 0x2329,
|
||||
[0x0abd] 0x002e,
|
||||
[0x0abe] 0x232a,
|
||||
[0x0ac3] 0x215b,
|
||||
[0x0ac4] 0x215c,
|
||||
[0x0ac5] 0x215d,
|
||||
[0x0ac6] 0x215e,
|
||||
[0x0ac9] 0x2122,
|
||||
[0x0aca] 0x2613,
|
||||
[0x0acc] 0x25c1,
|
||||
[0x0acd] 0x25b7,
|
||||
[0x0ace] 0x25cb,
|
||||
[0x0acf] 0x25a1,
|
||||
[0x0ad0] 0x2018,
|
||||
[0x0ad1] 0x2019,
|
||||
[0x0ad2] 0x201c,
|
||||
[0x0ad3] 0x201d,
|
||||
[0x0ad4] 0x211e,
|
||||
[0x0ad6] 0x2032,
|
||||
[0x0ad7] 0x2033,
|
||||
[0x0ad9] 0x271d,
|
||||
[0x0adb] 0x25ac,
|
||||
[0x0adc] 0x25c0,
|
||||
[0x0add] 0x25b6,
|
||||
[0x0ade] 0x25cf,
|
||||
[0x0adf] 0x25a0,
|
||||
[0x0ae0] 0x25e6,
|
||||
[0x0ae1] 0x25ab,
|
||||
[0x0ae2] 0x25ad,
|
||||
[0x0ae3] 0x25b3,
|
||||
[0x0ae4] 0x25bd,
|
||||
[0x0ae5] 0x2606,
|
||||
[0x0ae6] 0x2022,
|
||||
[0x0ae7] 0x25aa,
|
||||
[0x0ae8] 0x25b2,
|
||||
[0x0ae9] 0x25bc,
|
||||
[0x0aea] 0x261c,
|
||||
[0x0aeb] 0x261e,
|
||||
[0x0aec] 0x2663,
|
||||
[0x0aed] 0x2666,
|
||||
[0x0aee] 0x2665,
|
||||
[0x0af0] 0x2720,
|
||||
[0x0af1] 0x2020,
|
||||
[0x0af2] 0x2021,
|
||||
[0x0af3] 0x2713,
|
||||
[0x0af4] 0x2717,
|
||||
[0x0af5] 0x266f,
|
||||
[0x0af6] 0x266d,
|
||||
[0x0af7] 0x2642,
|
||||
[0x0af8] 0x2640,
|
||||
[0x0af9] 0x260e,
|
||||
[0x0afa] 0x2315,
|
||||
[0x0afb] 0x2117,
|
||||
[0x0afc] 0x2038,
|
||||
[0x0afd] 0x201a,
|
||||
[0x0afe] 0x201e,
|
||||
[0x0ba3] 0x003c,
|
||||
[0x0ba6] 0x003e,
|
||||
[0x0ba8] 0x2228,
|
||||
[0x0ba9] 0x2227,
|
||||
[0x0bc0] 0x00af,
|
||||
[0x0bc2] 0x22a4,
|
||||
[0x0bc3] 0x2229,
|
||||
[0x0bc4] 0x230a,
|
||||
[0x0bc6] 0x005f,
|
||||
[0x0bca] 0x2218,
|
||||
[0x0bcc] 0x2395,
|
||||
[0x0bce] 0x22a5,
|
||||
[0x0bcf] 0x25cb,
|
||||
[0x0bd3] 0x2308,
|
||||
[0x0bd6] 0x222a,
|
||||
[0x0bd8] 0x2283,
|
||||
[0x0bda] 0x2282,
|
||||
[0x0bdc] 0x22a3,
|
||||
[0x0bfc] 0x22a2,
|
||||
[0x0cdf] 0x2017,
|
||||
[0x0ce0] 0x05d0,
|
||||
[0x0ce1] 0x05d1,
|
||||
[0x0ce2] 0x05d2,
|
||||
[0x0ce3] 0x05d3,
|
||||
[0x0ce4] 0x05d4,
|
||||
[0x0ce5] 0x05d5,
|
||||
[0x0ce6] 0x05d6,
|
||||
[0x0ce7] 0x05d7,
|
||||
[0x0ce8] 0x05d8,
|
||||
[0x0ce9] 0x05d9,
|
||||
[0x0cea] 0x05da,
|
||||
[0x0ceb] 0x05db,
|
||||
[0x0cec] 0x05dc,
|
||||
[0x0ced] 0x05dd,
|
||||
[0x0cee] 0x05de,
|
||||
[0x0cef] 0x05df,
|
||||
[0x0cf0] 0x05e0,
|
||||
[0x0cf1] 0x05e1,
|
||||
[0x0cf2] 0x05e2,
|
||||
[0x0cf3] 0x05e3,
|
||||
[0x0cf4] 0x05e4,
|
||||
[0x0cf5] 0x05e5,
|
||||
[0x0cf6] 0x05e6,
|
||||
[0x0cf7] 0x05e7,
|
||||
[0x0cf8] 0x05e8,
|
||||
[0x0cf9] 0x05e9,
|
||||
[0x0cfa] 0x05ea,
|
||||
[0x0da1] 0x0e01,
|
||||
[0x0da2] 0x0e02,
|
||||
[0x0da3] 0x0e03,
|
||||
[0x0da4] 0x0e04,
|
||||
[0x0da5] 0x0e05,
|
||||
[0x0da6] 0x0e06,
|
||||
[0x0da7] 0x0e07,
|
||||
[0x0da8] 0x0e08,
|
||||
[0x0da9] 0x0e09,
|
||||
[0x0daa] 0x0e0a,
|
||||
[0x0dab] 0x0e0b,
|
||||
[0x0dac] 0x0e0c,
|
||||
[0x0dad] 0x0e0d,
|
||||
[0x0dae] 0x0e0e,
|
||||
[0x0daf] 0x0e0f,
|
||||
[0x0db0] 0x0e10,
|
||||
[0x0db1] 0x0e11,
|
||||
[0x0db2] 0x0e12,
|
||||
[0x0db3] 0x0e13,
|
||||
[0x0db4] 0x0e14,
|
||||
[0x0db5] 0x0e15,
|
||||
[0x0db6] 0x0e16,
|
||||
[0x0db7] 0x0e17,
|
||||
[0x0db8] 0x0e18,
|
||||
[0x0db9] 0x0e19,
|
||||
[0x0dba] 0x0e1a,
|
||||
[0x0dbb] 0x0e1b,
|
||||
[0x0dbc] 0x0e1c,
|
||||
[0x0dbd] 0x0e1d,
|
||||
[0x0dbe] 0x0e1e,
|
||||
[0x0dbf] 0x0e1f,
|
||||
[0x0dc0] 0x0e20,
|
||||
[0x0dc1] 0x0e21,
|
||||
[0x0dc2] 0x0e22,
|
||||
[0x0dc3] 0x0e23,
|
||||
[0x0dc4] 0x0e24,
|
||||
[0x0dc5] 0x0e25,
|
||||
[0x0dc6] 0x0e26,
|
||||
[0x0dc7] 0x0e27,
|
||||
[0x0dc8] 0x0e28,
|
||||
[0x0dc9] 0x0e29,
|
||||
[0x0dca] 0x0e2a,
|
||||
[0x0dcb] 0x0e2b,
|
||||
[0x0dcc] 0x0e2c,
|
||||
[0x0dcd] 0x0e2d,
|
||||
[0x0dce] 0x0e2e,
|
||||
[0x0dcf] 0x0e2f,
|
||||
[0x0dd0] 0x0e30,
|
||||
[0x0dd1] 0x0e31,
|
||||
[0x0dd2] 0x0e32,
|
||||
[0x0dd3] 0x0e33,
|
||||
[0x0dd4] 0x0e34,
|
||||
[0x0dd5] 0x0e35,
|
||||
[0x0dd6] 0x0e36,
|
||||
[0x0dd7] 0x0e37,
|
||||
[0x0dd8] 0x0e38,
|
||||
[0x0dd9] 0x0e39,
|
||||
[0x0dda] 0x0e3a,
|
||||
[0x0dde] 0x0e3e,
|
||||
[0x0ddf] 0x0e3f,
|
||||
[0x0de0] 0x0e40,
|
||||
[0x0de1] 0x0e41,
|
||||
[0x0de2] 0x0e42,
|
||||
[0x0de3] 0x0e43,
|
||||
[0x0de4] 0x0e44,
|
||||
[0x0de5] 0x0e45,
|
||||
[0x0de6] 0x0e46,
|
||||
[0x0de7] 0x0e47,
|
||||
[0x0de8] 0x0e48,
|
||||
[0x0de9] 0x0e49,
|
||||
[0x0dea] 0x0e4a,
|
||||
[0x0deb] 0x0e4b,
|
||||
[0x0dec] 0x0e4c,
|
||||
[0x0ded] 0x0e4d,
|
||||
[0x0df0] 0x0e50,
|
||||
[0x0df1] 0x0e51,
|
||||
[0x0df2] 0x0e52,
|
||||
[0x0df3] 0x0e53,
|
||||
[0x0df4] 0x0e54,
|
||||
[0x0df5] 0x0e55,
|
||||
[0x0df6] 0x0e56,
|
||||
[0x0df7] 0x0e57,
|
||||
[0x0df8] 0x0e58,
|
||||
[0x0df9] 0x0e59,
|
||||
[0x0ea1] 0x3131,
|
||||
[0x0ea2] 0x3132,
|
||||
[0x0ea3] 0x3133,
|
||||
[0x0ea4] 0x3134,
|
||||
[0x0ea5] 0x3135,
|
||||
[0x0ea6] 0x3136,
|
||||
[0x0ea7] 0x3137,
|
||||
[0x0ea8] 0x3138,
|
||||
[0x0ea9] 0x3139,
|
||||
[0x0eaa] 0x313a,
|
||||
[0x0eab] 0x313b,
|
||||
[0x0eac] 0x313c,
|
||||
[0x0ead] 0x313d,
|
||||
[0x0eae] 0x313e,
|
||||
[0x0eaf] 0x313f,
|
||||
[0x0eb0] 0x3140,
|
||||
[0x0eb1] 0x3141,
|
||||
[0x0eb2] 0x3142,
|
||||
[0x0eb3] 0x3143,
|
||||
[0x0eb4] 0x3144,
|
||||
[0x0eb5] 0x3145,
|
||||
[0x0eb6] 0x3146,
|
||||
[0x0eb7] 0x3147,
|
||||
[0x0eb8] 0x3148,
|
||||
[0x0eb9] 0x3149,
|
||||
[0x0eba] 0x314a,
|
||||
[0x0ebb] 0x314b,
|
||||
[0x0ebc] 0x314c,
|
||||
[0x0ebd] 0x314d,
|
||||
[0x0ebe] 0x314e,
|
||||
[0x0ebf] 0x314f,
|
||||
[0x0ec0] 0x3150,
|
||||
[0x0ec1] 0x3151,
|
||||
[0x0ec2] 0x3152,
|
||||
[0x0ec3] 0x3153,
|
||||
[0x0ec4] 0x3154,
|
||||
[0x0ec5] 0x3155,
|
||||
[0x0ec6] 0x3156,
|
||||
[0x0ec7] 0x3157,
|
||||
[0x0ec8] 0x3158,
|
||||
[0x0ec9] 0x3159,
|
||||
[0x0eca] 0x315a,
|
||||
[0x0ecb] 0x315b,
|
||||
[0x0ecc] 0x315c,
|
||||
[0x0ecd] 0x315d,
|
||||
[0x0ece] 0x315e,
|
||||
[0x0ecf] 0x315f,
|
||||
[0x0ed0] 0x3160,
|
||||
[0x0ed1] 0x3161,
|
||||
[0x0ed2] 0x3162,
|
||||
[0x0ed3] 0x3163,
|
||||
[0x0ed4] 0x11a8,
|
||||
[0x0ed5] 0x11a9,
|
||||
[0x0ed6] 0x11aa,
|
||||
[0x0ed7] 0x11ab,
|
||||
[0x0ed8] 0x11ac,
|
||||
[0x0ed9] 0x11ad,
|
||||
[0x0eda] 0x11ae,
|
||||
[0x0edb] 0x11af,
|
||||
[0x0edc] 0x11b0,
|
||||
[0x0edd] 0x11b1,
|
||||
[0x0ede] 0x11b2,
|
||||
[0x0edf] 0x11b3,
|
||||
[0x0ee0] 0x11b4,
|
||||
[0x0ee1] 0x11b5,
|
||||
[0x0ee2] 0x11b6,
|
||||
[0x0ee3] 0x11b7,
|
||||
[0x0ee4] 0x11b8,
|
||||
[0x0ee5] 0x11b9,
|
||||
[0x0ee6] 0x11ba,
|
||||
[0x0ee7] 0x11bb,
|
||||
[0x0ee8] 0x11bc,
|
||||
[0x0ee9] 0x11bd,
|
||||
[0x0eea] 0x11be,
|
||||
[0x0eeb] 0x11bf,
|
||||
[0x0eec] 0x11c0,
|
||||
[0x0eed] 0x11c1,
|
||||
[0x0eee] 0x11c2,
|
||||
[0x0eef] 0x316d,
|
||||
[0x0ef0] 0x3171,
|
||||
[0x0ef1] 0x3178,
|
||||
[0x0ef2] 0x317f,
|
||||
[0x0ef4] 0x3184,
|
||||
[0x0ef5] 0x3186,
|
||||
[0x0ef6] 0x318d,
|
||||
[0x0ef7] 0x318e,
|
||||
[0x0ef8] 0x11eb,
|
||||
[0x0efa] 0x11f9,
|
||||
[0x0eff] 0x20a9,
|
||||
[0x13bc] 0x0152,
|
||||
[0x13bd] 0x0153,
|
||||
[0x13be] 0x0178,
|
||||
[0x20a0] 0x20a0,
|
||||
[0x20a1] 0x20a1,
|
||||
[0x20a2] 0x20a2,
|
||||
[0x20a3] 0x20a3,
|
||||
[0x20a4] 0x20a4,
|
||||
[0x20a5] 0x20a5,
|
||||
[0x20a6] 0x20a6,
|
||||
[0x20a7] 0x20a7,
|
||||
[0x20a8] 0x20a8,
|
||||
[0x20a9] 0x20a9,
|
||||
[0x20aa] 0x20aa,
|
||||
[0x20ab] 0x20ab,
|
||||
[0x20ac] 0x20ac,
|
||||
};
|
16
gui-x11/load.c
Normal file
16
gui-x11/load.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
#include "xmem.h"
|
||||
|
||||
int
|
||||
loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = _loadmemimage(i, r, data, ndata);
|
||||
if(n > 0 && i->X)
|
||||
putXdata(i, r);
|
||||
return n;
|
||||
}
|
1094
gui-x11/screen.c
Normal file
1094
gui-x11/screen.c
Normal file
File diff suppressed because it is too large
Load Diff
60
gui-x11/xmem.h
Normal file
60
gui-x11/xmem.h
Normal file
@ -0,0 +1,60 @@
|
||||
#define Font XXFont
|
||||
#define Screen XXScreen
|
||||
#define Display XXDisplay
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
/* #include <X11/Xlibint.h> */
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/IntrinsicP.h>
|
||||
#include <X11/StringDefs.h>
|
||||
|
||||
#undef Font
|
||||
#undef Screen
|
||||
#undef Display
|
||||
|
||||
/*
|
||||
* Structure pointed to by X field of Memimage
|
||||
*/
|
||||
typedef struct Xmem Xmem;
|
||||
|
||||
enum
|
||||
{
|
||||
PMundef = ~0 /* undefined pixmap id */
|
||||
};
|
||||
|
||||
|
||||
struct Xmem
|
||||
{
|
||||
int pmid; /* pixmap id for screen ldepth instance */
|
||||
XImage *xi; /* local image if we currenty have the data */
|
||||
int dirty;
|
||||
Rectangle dirtyr;
|
||||
Rectangle r;
|
||||
ulong pc; /* who wrote into xi */
|
||||
};
|
||||
|
||||
extern int xtblbit;
|
||||
extern int x24bitswap;
|
||||
extern int plan9tox11[];
|
||||
extern int x11toplan9[];
|
||||
extern int xscreendepth;
|
||||
extern XXDisplay *xdisplay;
|
||||
extern Drawable xscreenid;
|
||||
extern Visual *xvis;
|
||||
extern GC xgcfill, xgcfill0;
|
||||
extern int xgcfillcolor, xgcfillcolor0;
|
||||
extern GC xgccopy, xgccopy0;
|
||||
extern GC xgczero, xgczero0;
|
||||
extern int xgczeropm, xgczeropm0;
|
||||
extern GC xgcsimplesrc, xgcsimplesrc0;
|
||||
extern int xgcsimplecolor, xgcsimplecolor0, xgcsimplepm, xgcsimplepm0;
|
||||
extern GC xgcreplsrc, xgcreplsrc0;
|
||||
extern int xgcreplsrcpm, xgcreplsrcpm0, xgcreplsrctile, xgcreplsrctile0;
|
||||
extern XImage* allocXdata(Memimage*, Rectangle);
|
||||
extern void putXdata(Memimage*, Rectangle);
|
||||
extern XImage* getXdata(Memimage*, Rectangle);
|
||||
extern void freeXdata(Memimage*);
|
||||
extern void dirtyXdata(Memimage*, Rectangle);
|
||||
extern ulong xscreenchan;
|
||||
extern void xfillcolor(Memimage*, Rectangle, ulong);
|
BIN
include/a.out
Normal file
BIN
include/a.out
Normal file
Binary file not shown.
144
include/auth.h
Normal file
144
include/auth.h
Normal file
@ -0,0 +1,144 @@
|
||||
#pragma src "/sys/src/libauth"
|
||||
#pragma lib "libauth.a"
|
||||
|
||||
/*
|
||||
* Interface for typical callers.
|
||||
*/
|
||||
|
||||
typedef struct AuthInfo AuthInfo;
|
||||
typedef struct Chalstate Chalstate;
|
||||
typedef struct Chapreply Chapreply;
|
||||
typedef struct MSchapreply MSchapreply;
|
||||
typedef struct UserPasswd UserPasswd;
|
||||
typedef struct AuthRpc AuthRpc;
|
||||
|
||||
enum
|
||||
{
|
||||
MAXCHLEN= 256, /* max challenge length */
|
||||
MAXNAMELEN= 256, /* maximum name length */
|
||||
MD5LEN= 16,
|
||||
|
||||
ARok = 0, /* rpc return values */
|
||||
ARdone,
|
||||
ARerror,
|
||||
ARneedkey,
|
||||
ARbadkey,
|
||||
ARwritenext,
|
||||
ARtoosmall,
|
||||
ARtoobig,
|
||||
ARrpcfailure,
|
||||
ARphase,
|
||||
|
||||
AuthRpcMax = 4096,
|
||||
};
|
||||
|
||||
struct AuthRpc
|
||||
{
|
||||
int afd;
|
||||
char ibuf[AuthRpcMax];
|
||||
char obuf[AuthRpcMax];
|
||||
char *arg;
|
||||
uint narg;
|
||||
};
|
||||
|
||||
struct AuthInfo
|
||||
{
|
||||
char *cuid; /* caller id */
|
||||
char *suid; /* server id */
|
||||
char *cap; /* capability (only valid on server side) */
|
||||
int nsecret; /* length of secret */
|
||||
uchar *secret; /* secret */
|
||||
};
|
||||
|
||||
struct Chalstate
|
||||
{
|
||||
char *user;
|
||||
char chal[MAXCHLEN];
|
||||
int nchal;
|
||||
void *resp;
|
||||
int nresp;
|
||||
|
||||
/* for implementation only */
|
||||
int afd; /* to factotum */
|
||||
AuthRpc *rpc; /* to factotum */
|
||||
char userbuf[MAXNAMELEN]; /* temp space if needed */
|
||||
int userinchal; /* user was sent to obtain challenge */
|
||||
};
|
||||
|
||||
struct Chapreply /* for protocol "chap" */
|
||||
{
|
||||
uchar id;
|
||||
char resp[MD5LEN];
|
||||
};
|
||||
|
||||
struct MSchapreply /* for protocol "mschap" */
|
||||
{
|
||||
char LMresp[24]; /* Lan Manager response */
|
||||
char NTresp[24]; /* NT response */
|
||||
};
|
||||
|
||||
struct UserPasswd
|
||||
{
|
||||
char *user;
|
||||
char *passwd;
|
||||
};
|
||||
|
||||
extern int newns(char*, char*);
|
||||
extern int addns(char*, char*);
|
||||
|
||||
extern int noworld(char*);
|
||||
extern int amount(int, char*, int, char*);
|
||||
|
||||
/* these two may get generalized away -rsc */
|
||||
extern int login(char*, char*, char*);
|
||||
extern int httpauth(char*, char*);
|
||||
|
||||
typedef struct Attr Attr;
|
||||
typedef struct String String;
|
||||
enum {
|
||||
AttrNameval, /* name=val -- when matching, must have name=val */
|
||||
AttrQuery, /* name? -- when matching, must be present */
|
||||
AttrDefault, /* name:=val -- when matching, if present must match INTERNAL */
|
||||
};
|
||||
struct Attr
|
||||
{
|
||||
int type;
|
||||
Attr *next;
|
||||
char *name;
|
||||
char *val;
|
||||
};
|
||||
|
||||
typedef int AuthGetkey(char*);
|
||||
|
||||
int _attrfmt(Fmt*);
|
||||
Attr *_copyattr(Attr*);
|
||||
Attr *_delattr(Attr*, char*);
|
||||
Attr *_findattr(Attr*, char*);
|
||||
void _freeattr(Attr*);
|
||||
Attr *_mkattr(int, char*, char*, Attr*);
|
||||
Attr *_parseattr(char*);
|
||||
char *_strfindattr(Attr*, char*);
|
||||
#pragma varargck type "A" Attr*
|
||||
|
||||
extern AuthInfo* fauth_proxy(int, AuthRpc *rpc, AuthGetkey *getkey, char *params);
|
||||
extern AuthInfo* auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...);
|
||||
extern int auth_getkey(char*);
|
||||
extern int (*amount_getkey)(char*);
|
||||
extern void auth_freeAI(AuthInfo *ai);
|
||||
extern int auth_chuid(AuthInfo *ai, char *ns);
|
||||
extern Chalstate *auth_challenge(char*, ...);
|
||||
extern AuthInfo* auth_response(Chalstate*);
|
||||
extern int auth_respond(void*, uint, char*, uint, void*, uint, AuthGetkey *getkey, char*, ...);
|
||||
extern void auth_freechal(Chalstate*);
|
||||
extern AuthInfo* auth_userpasswd(char *user, char *passwd);
|
||||
extern UserPasswd* auth_getuserpasswd(AuthGetkey *getkey, char*, ...);
|
||||
extern AuthInfo* auth_getinfo(AuthRpc *rpc);
|
||||
extern AuthRpc* auth_allocrpc(int afd);
|
||||
extern Attr* auth_attr(AuthRpc *rpc);
|
||||
extern void auth_freerpc(AuthRpc *rpc);
|
||||
extern uint auth_rpc(AuthRpc *rpc, char *verb, void *a, int n);
|
||||
extern int auth_wep(char*, char*, ...);
|
||||
#pragma varargck argpos auth_proxy 3
|
||||
#pragma varargck argpos auth_challenge 1
|
||||
#pragma varargck argpos auth_respond 3
|
||||
#pragma varargck argpos auth_getuserpasswd 2
|
166
include/authsrv.h
Normal file
166
include/authsrv.h
Normal file
@ -0,0 +1,166 @@
|
||||
#pragma src "/sys/src/libauthsrv"
|
||||
#pragma lib "libauthsrv.a"
|
||||
|
||||
/*
|
||||
* Interface for talking to authentication server.
|
||||
*/
|
||||
typedef struct Ticket Ticket;
|
||||
typedef struct Ticketreq Ticketreq;
|
||||
typedef struct Authenticator Authenticator;
|
||||
typedef struct Nvrsafe Nvrsafe;
|
||||
typedef struct Passwordreq Passwordreq;
|
||||
typedef struct OChapreply OChapreply;
|
||||
typedef struct OMSchapreply OMSchapreply;
|
||||
|
||||
enum
|
||||
{
|
||||
ANAMELEN= 28, /* maximum size of name in previous proto */
|
||||
AERRLEN= 64, /* maximum size of errstr in previous proto */
|
||||
DOMLEN= 48, /* length of an authentication domain name */
|
||||
DESKEYLEN= 7, /* length of a des key for encrypt/decrypt */
|
||||
CHALLEN= 8, /* length of a plan9 sk1 challenge */
|
||||
NETCHLEN= 16, /* max network challenge length (used in AS protocol) */
|
||||
CONFIGLEN= 14,
|
||||
SECRETLEN= 32, /* max length of a secret */
|
||||
|
||||
KEYDBOFF= 8, /* length of random data at the start of key file */
|
||||
OKEYDBLEN= ANAMELEN+DESKEYLEN+4+2, /* length of an entry in old key file */
|
||||
KEYDBLEN= OKEYDBLEN+SECRETLEN, /* length of an entry in key file */
|
||||
OMD5LEN= 16,
|
||||
};
|
||||
|
||||
/* encryption numberings (anti-replay) */
|
||||
enum
|
||||
{
|
||||
AuthTreq=1, /* ticket request */
|
||||
AuthChal=2, /* challenge box request */
|
||||
AuthPass=3, /* change password */
|
||||
AuthOK=4, /* fixed length reply follows */
|
||||
AuthErr=5, /* error follows */
|
||||
AuthMod=6, /* modify user */
|
||||
AuthApop=7, /* apop authentication for pop3 */
|
||||
AuthOKvar=9, /* variable length reply follows */
|
||||
AuthChap=10, /* chap authentication for ppp */
|
||||
AuthMSchap=11, /* MS chap authentication for ppp */
|
||||
AuthCram=12, /* CRAM verification for IMAP (RFC2195 & rfc2104) */
|
||||
AuthHttp=13, /* http domain login */
|
||||
AuthVNC=14, /* VNC server login (deprecated) */
|
||||
|
||||
|
||||
AuthTs=64, /* ticket encrypted with server's key */
|
||||
AuthTc, /* ticket encrypted with client's key */
|
||||
AuthAs, /* server generated authenticator */
|
||||
AuthAc, /* client generated authenticator */
|
||||
AuthTp, /* ticket encrypted with client's key for password change */
|
||||
AuthHr, /* http reply */
|
||||
};
|
||||
|
||||
struct Ticketreq
|
||||
{
|
||||
char type;
|
||||
char authid[ANAMELEN]; /* server's encryption id */
|
||||
char authdom[DOMLEN]; /* server's authentication domain */
|
||||
char chal[CHALLEN]; /* challenge from server */
|
||||
char hostid[ANAMELEN]; /* host's encryption id */
|
||||
char uid[ANAMELEN]; /* uid of requesting user on host */
|
||||
};
|
||||
#define TICKREQLEN (3*ANAMELEN+CHALLEN+DOMLEN+1)
|
||||
|
||||
struct Ticket
|
||||
{
|
||||
char num; /* replay protection */
|
||||
char chal[CHALLEN]; /* server challenge */
|
||||
char cuid[ANAMELEN]; /* uid on client */
|
||||
char suid[ANAMELEN]; /* uid on server */
|
||||
char key[DESKEYLEN]; /* nonce DES key */
|
||||
};
|
||||
#define TICKETLEN (CHALLEN+2*ANAMELEN+DESKEYLEN+1)
|
||||
|
||||
struct Authenticator
|
||||
{
|
||||
char num; /* replay protection */
|
||||
char chal[CHALLEN];
|
||||
ulong id; /* authenticator id, ++'d with each auth */
|
||||
};
|
||||
#define AUTHENTLEN (CHALLEN+4+1)
|
||||
|
||||
struct Passwordreq
|
||||
{
|
||||
char num;
|
||||
char old[ANAMELEN];
|
||||
char new[ANAMELEN];
|
||||
char changesecret;
|
||||
char secret[SECRETLEN]; /* new secret */
|
||||
};
|
||||
#define PASSREQLEN (2*ANAMELEN+1+1+SECRETLEN)
|
||||
|
||||
struct OChapreply
|
||||
{
|
||||
uchar id;
|
||||
char uid[ANAMELEN];
|
||||
char resp[OMD5LEN];
|
||||
};
|
||||
|
||||
struct OMSchapreply
|
||||
{
|
||||
char uid[ANAMELEN];
|
||||
char LMresp[24]; /* Lan Manager response */
|
||||
char NTresp[24]; /* NT response */
|
||||
};
|
||||
|
||||
/*
|
||||
* convert to/from wire format
|
||||
*/
|
||||
extern int convT2M(Ticket*, char*, char*);
|
||||
extern void convM2T(char*, Ticket*, char*);
|
||||
extern void convM2Tnoenc(char*, Ticket*);
|
||||
extern int convA2M(Authenticator*, char*, char*);
|
||||
extern void convM2A(char*, Authenticator*, char*);
|
||||
extern int convTR2M(Ticketreq*, char*);
|
||||
extern void convM2TR(char*, Ticketreq*);
|
||||
extern int convPR2M(Passwordreq*, char*, char*);
|
||||
extern void convM2PR(char*, Passwordreq*, char*);
|
||||
|
||||
/*
|
||||
* convert ascii password to DES key
|
||||
*/
|
||||
extern int opasstokey(char*, char*);
|
||||
extern int passtokey(char*, char*);
|
||||
|
||||
/*
|
||||
* Nvram interface
|
||||
*/
|
||||
enum {
|
||||
NVwrite = 1<<0, /* always prompt and rewrite nvram */
|
||||
NVwriteonerr = 1<<1, /* prompt and rewrite nvram when corrupt */
|
||||
};
|
||||
|
||||
struct Nvrsafe
|
||||
{
|
||||
char machkey[DESKEYLEN];
|
||||
uchar machsum;
|
||||
char authkey[DESKEYLEN];
|
||||
uchar authsum;
|
||||
char config[CONFIGLEN];
|
||||
uchar configsum;
|
||||
char authid[ANAMELEN];
|
||||
uchar authidsum;
|
||||
char authdom[DOMLEN];
|
||||
uchar authdomsum;
|
||||
};
|
||||
|
||||
extern uchar nvcsum(void*, int);
|
||||
extern int readnvram(Nvrsafe*, int);
|
||||
|
||||
/*
|
||||
* call up auth server
|
||||
*/
|
||||
extern int authdial(char *netroot, char *authdom);
|
||||
|
||||
/*
|
||||
* exchange messages with auth server
|
||||
*/
|
||||
extern int _asgetticket(int, char*, char*);
|
||||
extern int _asrdresp(int, char*, int);
|
||||
extern int sslnegotiate(int, Ticket*, char**, char**);
|
||||
extern int srvsslnegotiate(int, Ticket*, char**, char**);
|
6
include/cursor.h
Normal file
6
include/cursor.h
Normal file
@ -0,0 +1,6 @@
|
||||
struct Cursor
|
||||
{
|
||||
Point offset;
|
||||
uchar clr[2*16];
|
||||
uchar set[2*16];
|
||||
};
|
519
include/draw.h
Normal file
519
include/draw.h
Normal file
@ -0,0 +1,519 @@
|
||||
#pragma src "/sys/src/libdraw"
|
||||
#pragma lib "libdraw.a"
|
||||
|
||||
typedef struct Cachefont Cachefont;
|
||||
typedef struct Cacheinfo Cacheinfo;
|
||||
typedef struct Cachesubf Cachesubf;
|
||||
typedef struct Display Display;
|
||||
typedef struct Font Font;
|
||||
typedef struct Fontchar Fontchar;
|
||||
typedef struct Image Image;
|
||||
typedef struct Mouse Mouse;
|
||||
typedef struct Point Point;
|
||||
typedef struct Rectangle Rectangle;
|
||||
typedef struct RGB RGB;
|
||||
typedef struct Screen Screen;
|
||||
typedef struct Subfont Subfont;
|
||||
|
||||
#pragma varargck type "R" Rectangle
|
||||
#pragma varargck type "P" Point
|
||||
extern int Rfmt(Fmt*);
|
||||
extern int Pfmt(Fmt*);
|
||||
|
||||
enum
|
||||
{
|
||||
DOpaque = 0xFFFFFFFF,
|
||||
DTransparent = 0x00000000, /* only useful for allocimage, memfillcolor */
|
||||
DBlack = 0x000000FF,
|
||||
DWhite = 0xFFFFFFFF,
|
||||
DRed = 0xFF0000FF,
|
||||
DGreen = 0x00FF00FF,
|
||||
DBlue = 0x0000FFFF,
|
||||
DCyan = 0x00FFFFFF,
|
||||
DMagenta = 0xFF00FFFF,
|
||||
DYellow = 0xFFFF00FF,
|
||||
DPaleyellow = 0xFFFFAAFF,
|
||||
DDarkyellow = 0xEEEE9EFF,
|
||||
DDarkgreen = 0x448844FF,
|
||||
DPalegreen = 0xAAFFAAFF,
|
||||
DMedgreen = 0x88CC88FF,
|
||||
DDarkblue = 0x000055FF,
|
||||
DPalebluegreen= 0xAAFFFFFF,
|
||||
DPaleblue = 0x0000BBFF,
|
||||
DBluegreen = 0x008888FF,
|
||||
DGreygreen = 0x55AAAAFF,
|
||||
DPalegreygreen = 0x9EEEEEFF,
|
||||
DYellowgreen = 0x99994CFF,
|
||||
DMedblue = 0x000099FF,
|
||||
DGreyblue = 0x005DBBFF,
|
||||
DPalegreyblue = 0x4993DDFF,
|
||||
DPurpleblue = 0x8888CCFF,
|
||||
|
||||
DNotacolor = 0xFFFFFF00,
|
||||
DNofill = DNotacolor,
|
||||
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Displaybufsize = 8000,
|
||||
ICOSSCALE = 1024,
|
||||
Borderwidth = 4,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* refresh methods */
|
||||
Refbackup = 0,
|
||||
Refnone = 1,
|
||||
Refmesg = 2
|
||||
};
|
||||
#define NOREFRESH ((void*)-1)
|
||||
|
||||
enum
|
||||
{
|
||||
/* line ends */
|
||||
Endsquare = 0,
|
||||
Enddisc = 1,
|
||||
Endarrow = 2,
|
||||
Endmask = 0x1F
|
||||
};
|
||||
|
||||
#define ARROW(a, b, c) (Endarrow|((a)<<5)|((b)<<14)|((c)<<23))
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/* Porter-Duff compositing operators */
|
||||
Clear = 0,
|
||||
|
||||
SinD = 8,
|
||||
DinS = 4,
|
||||
SoutD = 2,
|
||||
DoutS = 1,
|
||||
|
||||
S = SinD|SoutD,
|
||||
SoverD = SinD|SoutD|DoutS,
|
||||
SatopD = SinD|DoutS,
|
||||
SxorD = SoutD|DoutS,
|
||||
|
||||
D = DinS|DoutS,
|
||||
DoverS = DinS|DoutS|SoutD,
|
||||
DatopS = DinS|SoutD,
|
||||
DxorS = DoutS|SoutD, /* == SxorD */
|
||||
|
||||
Ncomp = 12,
|
||||
} Drawop;
|
||||
|
||||
/*
|
||||
* image channel descriptors
|
||||
*/
|
||||
enum {
|
||||
CRed = 0,
|
||||
CGreen,
|
||||
CBlue,
|
||||
CGrey,
|
||||
CAlpha,
|
||||
CMap,
|
||||
CIgnore,
|
||||
NChan,
|
||||
};
|
||||
|
||||
#define __DC(type, nbits) ((((type)&15)<<4)|((nbits)&15))
|
||||
#define CHAN1(a,b) __DC(a,b)
|
||||
#define CHAN2(a,b,c,d) (CHAN1((a),(b))<<8|__DC((c),(d)))
|
||||
#define CHAN3(a,b,c,d,e,f) (CHAN2((a),(b),(c),(d))<<8|__DC((e),(f)))
|
||||
#define CHAN4(a,b,c,d,e,f,g,h) (CHAN3((a),(b),(c),(d),(e),(f))<<8|__DC((g),(h)))
|
||||
|
||||
#define NBITS(c) ((c)&15)
|
||||
#define TYPE(c) (((c)>>4)&15)
|
||||
|
||||
enum {
|
||||
GREY1 = CHAN1(CGrey, 1),
|
||||
GREY2 = CHAN1(CGrey, 2),
|
||||
GREY4 = CHAN1(CGrey, 4),
|
||||
GREY8 = CHAN1(CGrey, 8),
|
||||
CMAP8 = CHAN1(CMap, 8),
|
||||
RGB15 = CHAN4(CIgnore, 1, CRed, 5, CGreen, 5, CBlue, 5),
|
||||
RGB16 = CHAN3(CRed, 5, CGreen, 6, CBlue, 5),
|
||||
RGB24 = CHAN3(CRed, 8, CGreen, 8, CBlue, 8),
|
||||
BGR24 = CHAN3(CBlue, 8, CGreen, 8, CRed, 8),
|
||||
RGBA32 = CHAN4(CRed, 8, CGreen, 8, CBlue, 8, CAlpha, 8),
|
||||
ARGB32 = CHAN4(CAlpha, 8, CRed, 8, CGreen, 8, CBlue, 8), /* stupid VGAs */
|
||||
XRGB32 = CHAN4(CIgnore, 8, CRed, 8, CGreen, 8, CBlue, 8),
|
||||
XBGR32 = CHAN4(CIgnore, 8, CBlue, 8, CGreen, 8, CRed, 8),
|
||||
};
|
||||
|
||||
extern char* chantostr(char*, ulong);
|
||||
extern ulong strtochan(char*);
|
||||
extern int chantodepth(ulong);
|
||||
|
||||
struct Point
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct Rectangle
|
||||
{
|
||||
Point min;
|
||||
Point max;
|
||||
};
|
||||
|
||||
typedef void (*Reffn)(Image*, Rectangle, void*);
|
||||
|
||||
struct Screen
|
||||
{
|
||||
Display *display; /* display holding data */
|
||||
int id; /* id of system-held Screen */
|
||||
Image *image; /* unused; for reference only */
|
||||
Image *fill; /* color to paint behind windows */
|
||||
};
|
||||
|
||||
struct Display
|
||||
{
|
||||
QLock qlock;
|
||||
int locking; /*program is using lockdisplay */
|
||||
int dirno;
|
||||
int fd;
|
||||
int reffd;
|
||||
int ctlfd;
|
||||
int imageid;
|
||||
int local;
|
||||
void (*error)(Display*, char*);
|
||||
char *devdir;
|
||||
char *windir;
|
||||
char oldlabel[64];
|
||||
ulong dataqid;
|
||||
Image *white;
|
||||
Image *black;
|
||||
Image *opaque;
|
||||
Image *transparent;
|
||||
Image *image;
|
||||
uchar *buf;
|
||||
int bufsize;
|
||||
uchar *bufp;
|
||||
Font *defaultfont;
|
||||
Subfont *defaultsubfont;
|
||||
Image *windows;
|
||||
Image *screenimage;
|
||||
int _isnewdisplay;
|
||||
};
|
||||
|
||||
struct Image
|
||||
{
|
||||
Display *display; /* display holding data */
|
||||
int id; /* id of system-held Image */
|
||||
Rectangle r; /* rectangle in data area, local coords */
|
||||
Rectangle clipr; /* clipping region */
|
||||
int depth; /* number of bits per pixel */
|
||||
ulong chan;
|
||||
int repl; /* flag: data replicates to tile clipr */
|
||||
Screen *screen; /* 0 if not a window */
|
||||
Image *next; /* next in list of windows */
|
||||
};
|
||||
|
||||
struct RGB
|
||||
{
|
||||
ulong red;
|
||||
ulong green;
|
||||
ulong blue;
|
||||
};
|
||||
|
||||
/*
|
||||
* Subfonts
|
||||
*
|
||||
* given char c, Subfont *f, Fontchar *i, and Point p, one says
|
||||
* i = f->info+c;
|
||||
* draw(b, Rect(p.x+i->left, p.y+i->top,
|
||||
* p.x+i->left+((i+1)->x-i->x), p.y+i->bottom),
|
||||
* color, f->bits, Pt(i->x, i->top));
|
||||
* p.x += i->width;
|
||||
* to draw characters in the specified color (itself an Image) in Image b.
|
||||
*/
|
||||
|
||||
struct Fontchar
|
||||
{
|
||||
int x; /* left edge of bits */
|
||||
uchar top; /* first non-zero scan-line */
|
||||
uchar bottom; /* last non-zero scan-line + 1 */
|
||||
char left; /* offset of baseline */
|
||||
uchar width; /* width of baseline */
|
||||
};
|
||||
|
||||
struct Subfont
|
||||
{
|
||||
char *name;
|
||||
short n; /* number of chars in font */
|
||||
uchar height; /* height of image */
|
||||
char ascent; /* top of image to baseline */
|
||||
Fontchar *info; /* n+1 character descriptors */
|
||||
Image *bits; /* of font */
|
||||
int ref;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/* starting values */
|
||||
LOG2NFCACHE = 6,
|
||||
NFCACHE = (1<<LOG2NFCACHE), /* #chars cached */
|
||||
NFLOOK = 5, /* #chars to scan in cache */
|
||||
NFSUBF = 2, /* #subfonts to cache */
|
||||
/* max value */
|
||||
MAXFCACHE = 1024+NFLOOK, /* upper limit */
|
||||
MAXSUBF = 50, /* generous upper limit */
|
||||
/* deltas */
|
||||
DSUBF = 4,
|
||||
/* expiry ages */
|
||||
SUBFAGE = 10000,
|
||||
CACHEAGE = 10000
|
||||
};
|
||||
|
||||
struct Cachefont
|
||||
{
|
||||
Rune min; /* lowest rune value to be taken from subfont */
|
||||
Rune max; /* highest rune value+1 to be taken from subfont */
|
||||
int offset; /* position in subfont of character at min */
|
||||
char *name; /* stored in font */
|
||||
char *subfontname; /* to access subfont */
|
||||
};
|
||||
|
||||
struct Cacheinfo
|
||||
{
|
||||
ushort x; /* left edge of bits */
|
||||
uchar width; /* width of baseline */
|
||||
schar left; /* offset of baseline */
|
||||
Rune value; /* value of character at this slot in cache */
|
||||
ushort age;
|
||||
};
|
||||
|
||||
struct Cachesubf
|
||||
{
|
||||
ulong age; /* for replacement */
|
||||
Cachefont *cf; /* font info that owns us */
|
||||
Subfont *f; /* attached subfont */
|
||||
};
|
||||
|
||||
struct Font
|
||||
{
|
||||
char *name;
|
||||
Display *display;
|
||||
short height; /* max height of image, interline spacing */
|
||||
short ascent; /* top of image to baseline */
|
||||
short width; /* widest so far; used in caching only */
|
||||
short nsub; /* number of subfonts */
|
||||
ulong age; /* increasing counter; used for LRU */
|
||||
int maxdepth; /* maximum depth of all loaded subfonts */
|
||||
int ncache; /* size of cache */
|
||||
int nsubf; /* size of subfont list */
|
||||
Cacheinfo *cache;
|
||||
Cachesubf *subf;
|
||||
Cachefont **sub; /* as read from file */
|
||||
Image *cacheimage;
|
||||
};
|
||||
|
||||
#define Dx(r) ((r).max.x-(r).min.x)
|
||||
#define Dy(r) ((r).max.y-(r).min.y)
|
||||
|
||||
/*
|
||||
* Image management
|
||||
*/
|
||||
extern Image* _allocimage(Image*, Display*, Rectangle, ulong, int, ulong, int, int);
|
||||
extern Image* allocimage(Display*, Rectangle, ulong, int, ulong);
|
||||
extern uchar* bufimage(Display*, int);
|
||||
extern int bytesperline(Rectangle, int);
|
||||
extern void closedisplay(Display*);
|
||||
extern void drawerror(Display*, char*);
|
||||
extern int flushimage(Display*, int);
|
||||
extern int freeimage(Image*);
|
||||
extern int _freeimage1(Image*);
|
||||
extern int geninitdraw(char*, void(*)(Display*, char*), char*, char*, char*, int);
|
||||
extern int initdraw(void(*)(Display*, char*), char*, char*);
|
||||
extern int newwindow(char*);
|
||||
extern Display* initdisplay(char*, char*, void(*)(Display*, char*));
|
||||
extern int loadimage(Image*, Rectangle, uchar*, int);
|
||||
extern int cloadimage(Image*, Rectangle, uchar*, int);
|
||||
extern int getwindow(Display*, int);
|
||||
extern int gengetwindow(Display*, char*, Image**, Screen**, int);
|
||||
extern Image* readimage(Display*, int, int);
|
||||
extern Image* creadimage(Display*, int, int);
|
||||
extern int unloadimage(Image*, Rectangle, uchar*, int);
|
||||
extern int wordsperline(Rectangle, int);
|
||||
extern int writeimage(int, Image*, int);
|
||||
extern Image* namedimage(Display*, char*);
|
||||
extern int nameimage(Image*, char*, int);
|
||||
extern Image* allocimagemix(Display*, ulong, ulong);
|
||||
|
||||
/*
|
||||
* Colors
|
||||
*/
|
||||
extern void readcolmap(Display*, RGB*);
|
||||
extern void writecolmap(Display*, RGB*);
|
||||
extern ulong setalpha(ulong, uchar);
|
||||
|
||||
/*
|
||||
* Windows
|
||||
*/
|
||||
extern Screen* allocscreen(Image*, Image*, int);
|
||||
extern Image* _allocwindow(Image*, Screen*, Rectangle, int, ulong);
|
||||
extern Image* allocwindow(Screen*, Rectangle, int, ulong);
|
||||
extern void bottomnwindows(Image**, int);
|
||||
extern void bottomwindow(Image*);
|
||||
extern int freescreen(Screen*);
|
||||
extern Screen* publicscreen(Display*, int, ulong);
|
||||
extern void topnwindows(Image**, int);
|
||||
extern void topwindow(Image*);
|
||||
extern int originwindow(Image*, Point, Point);
|
||||
|
||||
/*
|
||||
* Geometry
|
||||
*/
|
||||
extern Point Pt(int, int);
|
||||
extern Rectangle Rect(int, int, int, int);
|
||||
extern Rectangle Rpt(Point, Point);
|
||||
extern Point addpt(Point, Point);
|
||||
extern Point subpt(Point, Point);
|
||||
extern Point divpt(Point, int);
|
||||
extern Point mulpt(Point, int);
|
||||
extern int eqpt(Point, Point);
|
||||
extern int eqrect(Rectangle, Rectangle);
|
||||
extern Rectangle insetrect(Rectangle, int);
|
||||
extern Rectangle rectaddpt(Rectangle, Point);
|
||||
extern Rectangle rectsubpt(Rectangle, Point);
|
||||
extern Rectangle canonrect(Rectangle);
|
||||
extern int rectXrect(Rectangle, Rectangle);
|
||||
extern int rectinrect(Rectangle, Rectangle);
|
||||
extern void combinerect(Rectangle*, Rectangle);
|
||||
extern int rectclip(Rectangle*, Rectangle);
|
||||
extern int ptinrect(Point, Rectangle);
|
||||
extern void replclipr(Image*, int, Rectangle);
|
||||
extern int drawreplxy(int, int, int); /* used to be drawsetxy */
|
||||
extern Point drawrepl(Rectangle, Point);
|
||||
extern int rgb2cmap(int, int, int);
|
||||
extern int cmap2rgb(int);
|
||||
extern int cmap2rgba(int);
|
||||
extern void icossin(int, int*, int*);
|
||||
extern void icossin2(int, int, int*, int*);
|
||||
|
||||
/*
|
||||
* Graphics
|
||||
*/
|
||||
extern void draw(Image*, Rectangle, Image*, Image*, Point);
|
||||
extern void drawop(Image*, Rectangle, Image*, Image*, Point, Drawop);
|
||||
extern void gendraw(Image*, Rectangle, Image*, Point, Image*, Point);
|
||||
extern void gendrawop(Image*, Rectangle, Image*, Point, Image*, Point, Drawop);
|
||||
extern void line(Image*, Point, Point, int, int, int, Image*, Point);
|
||||
extern void lineop(Image*, Point, Point, int, int, int, Image*, Point, Drawop);
|
||||
extern void poly(Image*, Point*, int, int, int, int, Image*, Point);
|
||||
extern void polyop(Image*, Point*, int, int, int, int, Image*, Point, Drawop);
|
||||
extern void fillpoly(Image*, Point*, int, int, Image*, Point);
|
||||
extern void fillpolyop(Image*, Point*, int, int, Image*, Point, Drawop);
|
||||
extern Point string(Image*, Point, Image*, Point, Font*, char*);
|
||||
extern Point stringop(Image*, Point, Image*, Point, Font*, char*, Drawop);
|
||||
extern Point stringn(Image*, Point, Image*, Point, Font*, char*, int);
|
||||
extern Point stringnop(Image*, Point, Image*, Point, Font*, char*, int, Drawop);
|
||||
extern Point runestring(Image*, Point, Image*, Point, Font*, Rune*);
|
||||
extern Point runestringop(Image*, Point, Image*, Point, Font*, Rune*, Drawop);
|
||||
extern Point runestringn(Image*, Point, Image*, Point, Font*, Rune*, int);
|
||||
extern Point runestringnop(Image*, Point, Image*, Point, Font*, Rune*, int, Drawop);
|
||||
extern Point stringbg(Image*, Point, Image*, Point, Font*, char*, Image*, Point);
|
||||
extern Point stringbgop(Image*, Point, Image*, Point, Font*, char*, Image*, Point, Drawop);
|
||||
extern Point stringnbg(Image*, Point, Image*, Point, Font*, char*, int, Image*, Point);
|
||||
extern Point stringnbgop(Image*, Point, Image*, Point, Font*, char*, int, Image*, Point, Drawop);
|
||||
extern Point runestringbg(Image*, Point, Image*, Point, Font*, Rune*, Image*, Point);
|
||||
extern Point runestringbgop(Image*, Point, Image*, Point, Font*, Rune*, Image*, Point, Drawop);
|
||||
extern Point runestringnbg(Image*, Point, Image*, Point, Font*, Rune*, int, Image*, Point);
|
||||
extern Point runestringnbgop(Image*, Point, Image*, Point, Font*, Rune*, int, Image*, Point, Drawop);
|
||||
extern Point _string(Image*, Point, Image*, Point, Font*, char*, Rune*, int, Rectangle, Image*, Point, Drawop);
|
||||
extern Point stringsubfont(Image*, Point, Image*, Subfont*, char*);
|
||||
extern int bezier(Image*, Point, Point, Point, Point, int, int, int, Image*, Point);
|
||||
extern int bezierop(Image*, Point, Point, Point, Point, int, int, int, Image*, Point, Drawop);
|
||||
extern int bezspline(Image*, Point*, int, int, int, int, Image*, Point);
|
||||
extern int bezsplineop(Image*, Point*, int, int, int, int, Image*, Point, Drawop);
|
||||
extern int bezsplinepts(Point*, int, Point**);
|
||||
extern int fillbezier(Image*, Point, Point, Point, Point, int, Image*, Point);
|
||||
extern int fillbezierop(Image*, Point, Point, Point, Point, int, Image*, Point, Drawop);
|
||||
extern int fillbezspline(Image*, Point*, int, int, Image*, Point);
|
||||
extern int fillbezsplineop(Image*, Point*, int, int, Image*, Point, Drawop);
|
||||
extern void ellipse(Image*, Point, int, int, int, Image*, Point);
|
||||
extern void ellipseop(Image*, Point, int, int, int, Image*, Point, Drawop);
|
||||
extern void fillellipse(Image*, Point, int, int, Image*, Point);
|
||||
extern void fillellipseop(Image*, Point, int, int, Image*, Point, Drawop);
|
||||
extern void arc(Image*, Point, int, int, int, Image*, Point, int, int);
|
||||
extern void arcop(Image*, Point, int, int, int, Image*, Point, int, int, Drawop);
|
||||
extern void fillarc(Image*, Point, int, int, Image*, Point, int, int);
|
||||
extern void fillarcop(Image*, Point, int, int, Image*, Point, int, int, Drawop);
|
||||
extern void border(Image*, Rectangle, int, Image*, Point);
|
||||
extern void borderop(Image*, Rectangle, int, Image*, Point, Drawop);
|
||||
|
||||
/*
|
||||
* Font management
|
||||
*/
|
||||
extern Font* openfont(Display*, char*);
|
||||
extern Font* buildfont(Display*, char*, char*);
|
||||
extern void freefont(Font*);
|
||||
extern Font* mkfont(Subfont*, Rune);
|
||||
extern int cachechars(Font*, char**, Rune**, ushort*, int, int*, char**);
|
||||
extern void agefont(Font*);
|
||||
extern Subfont* allocsubfont(char*, int, int, int, Fontchar*, Image*);
|
||||
extern Subfont* lookupsubfont(Display*, char*);
|
||||
extern void installsubfont(char*, Subfont*);
|
||||
extern void uninstallsubfont(Subfont*);
|
||||
extern void freesubfont(Subfont*);
|
||||
extern Subfont* readsubfont(Display*, char*, int, int);
|
||||
extern Subfont* readsubfonti(Display*, char*, int, Image*, int);
|
||||
extern int writesubfont(int, Subfont*);
|
||||
extern void _unpackinfo(Fontchar*, uchar*, int);
|
||||
extern Point stringsize(Font*, char*);
|
||||
extern int stringwidth(Font*, char*);
|
||||
extern int stringnwidth(Font*, char*, int);
|
||||
extern Point runestringsize(Font*, Rune*);
|
||||
extern int runestringwidth(Font*, Rune*);
|
||||
extern int runestringnwidth(Font*, Rune*, int);
|
||||
extern Point strsubfontwidth(Subfont*, char*);
|
||||
extern int loadchar(Font*, Rune, Cacheinfo*, int, int, char**);
|
||||
extern char* subfontname(char*, char*, int);
|
||||
extern Subfont* _getsubfont(Display*, char*);
|
||||
extern Subfont* getdefont(Display*);
|
||||
extern void lockdisplay(Display*);
|
||||
extern void unlockdisplay(Display*);
|
||||
extern int drawlsetrefresh(ulong, int, void*, void*);
|
||||
|
||||
/*
|
||||
* Predefined
|
||||
*/
|
||||
extern uchar defontdata[];
|
||||
extern int sizeofdefont;
|
||||
extern Point ZP;
|
||||
extern Rectangle ZR;
|
||||
|
||||
/*
|
||||
* Set up by initdraw()
|
||||
*/
|
||||
extern Display *display;
|
||||
extern Font *font;
|
||||
/* extern Image *screen; */
|
||||
extern Screen *_screen;
|
||||
extern int _cursorfd;
|
||||
extern int _drawdebug; /* set to 1 to see errors from flushimage */
|
||||
extern void _setdrawop(Display*, Drawop);
|
||||
|
||||
#define BGSHORT(p) (((p)[0]<<0) | ((p)[1]<<8))
|
||||
#define BGLONG(p) ((BGSHORT(p)<<0) | (BGSHORT(p+2)<<16))
|
||||
#define BPSHORT(p, v) ((p)[0]=(v), (p)[1]=((v)>>8))
|
||||
#define BPLONG(p, v) (BPSHORT(p, (v)), BPSHORT(p+2, (v)>>16))
|
||||
|
||||
/*
|
||||
* Compressed image file parameters and helper routines
|
||||
*/
|
||||
#define NMATCH 3 /* shortest match possible */
|
||||
#define NRUN (NMATCH+31) /* longest match possible */
|
||||
#define NMEM 1024 /* window size */
|
||||
#define NDUMP 128 /* maximum length of dump */
|
||||
#define NCBLOCK 6000 /* size of compressed blocks */
|
||||
extern void _twiddlecompressed(uchar*, int);
|
||||
extern int _compblocksize(Rectangle, int);
|
||||
|
||||
/* XXX backwards helps; should go */
|
||||
extern int log2[];
|
||||
extern ulong drawld2chan[];
|
||||
extern void drawsetdebug(int);
|
10
include/dtos.h
Normal file
10
include/dtos.h
Normal file
@ -0,0 +1,10 @@
|
||||
#if defined(linux) || defined(IRIX) || defined(SOLARIS) || defined(OSF1) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
# include "unix.h"
|
||||
# ifdef __APPLE__
|
||||
# define panic dt_panic
|
||||
# endif
|
||||
#elif defined(WINDOWS)
|
||||
# include "winduhz.h"
|
||||
#else
|
||||
# error "Define an OS"
|
||||
#endif
|
110
include/fcall.h
Normal file
110
include/fcall.h
Normal file
@ -0,0 +1,110 @@
|
||||
#define VERSION9P "9P2000"
|
||||
|
||||
#define MAXWELEM 16
|
||||
|
||||
typedef
|
||||
struct Fcall
|
||||
{
|
||||
uchar type;
|
||||
u32int fid;
|
||||
ushort tag;
|
||||
u32int msize; /* Tversion, Rversion */
|
||||
char *version; /* Tversion, Rversion */
|
||||
ushort oldtag; /* Tflush */
|
||||
char *ename; /* Rerror */
|
||||
Qid qid; /* Rattach, Ropen, Rcreate */
|
||||
u32int iounit; /* Ropen, Rcreate */
|
||||
Qid aqid; /* Rauth */
|
||||
u32int afid; /* Tauth, Tattach */
|
||||
char *uname; /* Tauth, Tattach */
|
||||
char *aname; /* Tauth, Tattach */
|
||||
u32int perm; /* Tcreate */
|
||||
char *name; /* Tcreate */
|
||||
uchar mode; /* Tcreate, Topen */
|
||||
u32int newfid; /* Twalk */
|
||||
ushort nwname; /* Twalk */
|
||||
char *wname[MAXWELEM]; /* Twalk */
|
||||
ushort nwqid; /* Rwalk */
|
||||
Qid wqid[MAXWELEM]; /* Rwalk */
|
||||
vlong offset; /* Tread, Twrite */
|
||||
u32int count; /* Tread, Twrite, Rread */
|
||||
char *data; /* Twrite, Rread */
|
||||
ushort nstat; /* Twstat, Rstat */
|
||||
uchar *stat; /* Twstat, Rstat */
|
||||
} Fcall;
|
||||
|
||||
|
||||
#define GBIT8(p) ((p)[0])
|
||||
#define GBIT16(p) ((p)[0]|((p)[1]<<8))
|
||||
#define GBIT32(p) ((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24))
|
||||
#define GBIT64(p) ((vlong)((p)[0]|((p)[1]<<8)|((p)[2]<<16)|((p)[3]<<24)) |\
|
||||
((vlong)((p)[4]|((p)[5]<<8)|((p)[6]<<16)|((p)[7]<<24)) << 32))
|
||||
|
||||
#define PBIT8(p,v) (p)[0]=(v)
|
||||
#define PBIT16(p,v) (p)[0]=(v);(p)[1]=(v)>>8
|
||||
#define PBIT32(p,v) (p)[0]=(v);(p)[1]=(v)>>8;(p)[2]=(v)>>16;(p)[3]=(v)>>24
|
||||
#define PBIT64(p,v) (p)[0]=(v);(p)[1]=(v)>>8;(p)[2]=(v)>>16;(p)[3]=(v)>>24;\
|
||||
(p)[4]=(v)>>32;(p)[5]=(v)>>40;(p)[6]=(v)>>48;(p)[7]=(v)>>56
|
||||
|
||||
#define BIT8SZ 1
|
||||
#define BIT16SZ 2
|
||||
#define BIT32SZ 4
|
||||
#define BIT64SZ 8
|
||||
#define QIDSZ (BIT8SZ+BIT32SZ+BIT64SZ)
|
||||
|
||||
/* STATFIXLEN includes leading 16-bit count */
|
||||
/* The count, however, excludes itself; total size is BIT16SZ+count */
|
||||
#define STATFIXLEN (BIT16SZ+QIDSZ+5*BIT16SZ+4*BIT32SZ+1*BIT64SZ) /* amount of fixed length data in a stat buffer */
|
||||
|
||||
#define NOTAG (ushort)~0U /* Dummy tag */
|
||||
#define NOFID (u32int)~0U /* Dummy fid */
|
||||
#define IOHDRSZ 24 /* ample room for Twrite/Rread header (iounit) */
|
||||
|
||||
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,
|
||||
Tmax,
|
||||
};
|
||||
|
||||
uint convM2S(uchar*, uint, Fcall*);
|
||||
uint convS2M(Fcall*, uchar*, uint);
|
||||
uint sizeS2M(Fcall*);
|
||||
|
||||
int statcheck(uchar *abuf, uint nbuf);
|
||||
uint convM2D(uchar*, uint, Dir*, char*);
|
||||
uint convD2M(Dir*, uchar*, uint);
|
||||
uint sizeD2M(Dir*);
|
||||
|
||||
int fcallfmt(Fmt*);
|
||||
int dirfmt(Fmt*);
|
||||
int dirmodefmt(Fmt*);
|
||||
|
||||
int read9pmsg(int, void*, uint);
|
||||
|
42
include/keyboard.h
Normal file
42
include/keyboard.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma src "/sys/src/libdraw"
|
||||
#pragma lib "libdraw.a"
|
||||
|
||||
typedef struct Keyboardctl Keyboardctl;
|
||||
typedef struct Channel Channel;
|
||||
|
||||
struct Keyboardctl
|
||||
{
|
||||
Channel *c; /* chan(Rune)[20] */
|
||||
|
||||
char *file;
|
||||
int consfd; /* to cons file */
|
||||
int ctlfd; /* to ctl file */
|
||||
int pid; /* of slave proc */
|
||||
};
|
||||
|
||||
|
||||
extern Keyboardctl* initkeyboard(char*);
|
||||
extern int ctlkeyboard(Keyboardctl*, char*);
|
||||
extern void closekeyboard(Keyboardctl*);
|
||||
|
||||
enum {
|
||||
KF= 0xF000, /* Rune: beginning of private Unicode space */
|
||||
Spec= 0xF800,
|
||||
/* KF|1, KF|2, ..., KF|0xC is F1, F2, ..., F12 */
|
||||
Khome= KF|0x0D,
|
||||
Kup= KF|0x0E,
|
||||
Kpgup= KF|0x0F,
|
||||
Kprint= KF|0x10,
|
||||
Kleft= KF|0x11,
|
||||
Kright= KF|0x12,
|
||||
Kdown= Spec|0x00,
|
||||
Kview= Spec|0x00,
|
||||
Kpgdown= KF|0x13,
|
||||
Kins= KF|0x14,
|
||||
Kend= KF|0x18,
|
||||
|
||||
Kalt= KF|0x15,
|
||||
Kshift= KF|0x16,
|
||||
Kctl= KF|0x17,
|
||||
};
|
||||
|
246
include/lib.h
Normal file
246
include/lib.h
Normal file
@ -0,0 +1,246 @@
|
||||
/* avoid name conflicts */
|
||||
#define accept pm_accept
|
||||
#define listen pm_listen
|
||||
#define sleep ksleep
|
||||
#define wakeup kwakeup
|
||||
#define strtod libstrtod
|
||||
#define pow10 libpow10
|
||||
|
||||
/* conflicts on some os's */
|
||||
#define encrypt libencrypt
|
||||
#define decrypt libdecrypt
|
||||
#define oserror liboserror
|
||||
#define clone libclone
|
||||
#define atexit libatexit
|
||||
#define log2 liblog2
|
||||
#define log liblog
|
||||
#define reboot libreboot
|
||||
#define srand dtsrand
|
||||
#define rand dtrand
|
||||
#define nrand dtnrand
|
||||
#define lrand dtlrand
|
||||
#define lnrand dtlnrand
|
||||
#undef timeradd
|
||||
#define timeradd xtimeradd
|
||||
|
||||
|
||||
#define nil ((void*)0)
|
||||
|
||||
typedef unsigned char p9_uchar;
|
||||
typedef unsigned int p9_uint;
|
||||
typedef unsigned int p9_ulong;
|
||||
typedef int p9_long;
|
||||
typedef signed char p9_schar;
|
||||
typedef unsigned short p9_ushort;
|
||||
typedef unsigned short Rune;
|
||||
typedef unsigned int p9_u32int;
|
||||
typedef p9_u32int mpdigit;
|
||||
|
||||
/* make sure we don't conflict with predefined types */
|
||||
#define schar p9_schar
|
||||
#define uchar p9_uchar
|
||||
#define ushort p9_ushort
|
||||
#define uint p9_uint
|
||||
#define u32int p9_u32int
|
||||
|
||||
/* #define long int rather than p9_long so that "unsigned long" is valid */
|
||||
#define long int
|
||||
#define ulong p9_ulong
|
||||
#define vlong p9_vlong
|
||||
#define uvlong p9_uvlong
|
||||
|
||||
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||
#define USED(x) if(x);else
|
||||
#define SET(x)
|
||||
|
||||
enum
|
||||
{
|
||||
UTFmax = 3, /* maximum bytes per rune */
|
||||
Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */
|
||||
Runeself = 0x80, /* rune and UTF sequences are the same (<) */
|
||||
Runeerror = 0x80 /* decoding error in UTF */
|
||||
};
|
||||
|
||||
/*
|
||||
* new rune routines
|
||||
*/
|
||||
extern int runetochar(char*, Rune*);
|
||||
extern int chartorune(Rune*, char*);
|
||||
extern int runelen(long);
|
||||
extern int fullrune(char*, int);
|
||||
|
||||
extern int wstrtoutf(char*, Rune*, int);
|
||||
extern int wstrutflen(Rune*);
|
||||
|
||||
/*
|
||||
* rune routines from converted str routines
|
||||
*/
|
||||
extern long utflen(char*);
|
||||
extern char* utfrune(char*, long);
|
||||
extern char* utfrrune(char*, long);
|
||||
|
||||
/*
|
||||
* Syscall data structures
|
||||
*/
|
||||
#define MORDER 0x0003 /* mask for bits defining order of mounting */
|
||||
#define MREPL 0x0000 /* mount replaces object */
|
||||
#define MBEFORE 0x0001 /* mount goes before others in union directory */
|
||||
#define MAFTER 0x0002 /* mount goes after others in union directory */
|
||||
#define MCREATE 0x0004 /* permit creation in mounted directory */
|
||||
#define MCACHE 0x0010 /* cache some data */
|
||||
#define MMASK 0x0017 /* all bits on */
|
||||
|
||||
#define OREAD 0 /* open for read */
|
||||
#define OWRITE 1 /* write */
|
||||
#define ORDWR 2 /* read and write */
|
||||
#define OEXEC 3 /* execute, == read but check execute permission */
|
||||
#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
|
||||
#define OCEXEC 32 /* or'ed in, close on exec */
|
||||
#define ORCLOSE 64 /* or'ed in, remove on close */
|
||||
#define OEXCL 0x1000 /* or'ed in, exclusive create */
|
||||
|
||||
#define NCONT 0 /* continue after note */
|
||||
#define NDFLT 1 /* terminate after note */
|
||||
#define NSAVE 2 /* clear note but hold state */
|
||||
#define NRSTR 3 /* restore saved state */
|
||||
|
||||
#define ERRMAX 128 /* max length of error string */
|
||||
#define KNAMELEN 28 /* max length of name held in kernel */
|
||||
|
||||
/* bits in Qid.type */
|
||||
#define QTDIR 0x80 /* type bit for directories */
|
||||
#define QTAPPEND 0x40 /* type bit for append only files */
|
||||
#define QTEXCL 0x20 /* type bit for exclusive use files */
|
||||
#define QTMOUNT 0x10 /* type bit for mounted channel */
|
||||
#define QTAUTH 0x08 /* type bit for authentication file */
|
||||
#define QTFILE 0x00 /* plain file */
|
||||
|
||||
/* bits in Dir.mode */
|
||||
#define DMDIR 0x80000000 /* mode bit for directories */
|
||||
#define DMAPPEND 0x40000000 /* mode bit for append only files */
|
||||
#define DMEXCL 0x20000000 /* mode bit for exclusive use files */
|
||||
#define DMMOUNT 0x10000000 /* mode bit for mounted channel */
|
||||
#define DMAUTH 0x08000000 /* mode bit for authentication files */
|
||||
#define DMREAD 0x4 /* mode bit for read permission */
|
||||
#define DMWRITE 0x2 /* mode bit for write permission */
|
||||
#define DMEXEC 0x1 /* mode bit for execute permission */
|
||||
|
||||
typedef struct Lock
|
||||
{
|
||||
long key;
|
||||
} Lock;
|
||||
|
||||
typedef struct QLock
|
||||
{
|
||||
Lock lk;
|
||||
struct Proc *hold;
|
||||
struct Proc *first;
|
||||
struct Proc *last;
|
||||
} QLock;
|
||||
|
||||
typedef
|
||||
struct Qid
|
||||
{
|
||||
uvlong path;
|
||||
ulong vers;
|
||||
uchar type;
|
||||
} Qid;
|
||||
|
||||
typedef
|
||||
struct Dir {
|
||||
/* system-modified data */
|
||||
ushort type; /* server type */
|
||||
uint dev; /* server subtype */
|
||||
/* file data */
|
||||
Qid qid; /* unique id from server */
|
||||
ulong mode; /* permissions */
|
||||
ulong atime; /* last read time */
|
||||
ulong mtime; /* last write time */
|
||||
vlong length; /* file length */
|
||||
char *name; /* last element of path */
|
||||
char *uid; /* owner name */
|
||||
char *gid; /* group name */
|
||||
char *muid; /* last modifier name */
|
||||
} Dir;
|
||||
|
||||
typedef
|
||||
struct Waitmsg
|
||||
{
|
||||
int pid; /* of loved one */
|
||||
ulong time[3]; /* of loved one & descendants */
|
||||
char *msg;
|
||||
} Waitmsg;
|
||||
|
||||
/*
|
||||
* print routines
|
||||
*/
|
||||
typedef struct Fmt Fmt;
|
||||
struct Fmt{
|
||||
uchar runes; /* output buffer is runes or chars? */
|
||||
void *start; /* of buffer */
|
||||
void *to; /* current place in the buffer */
|
||||
void *stop; /* end of the buffer; overwritten if flush fails */
|
||||
int (*flush)(Fmt *); /* called when to == stop */
|
||||
void *farg; /* to make flush a closure */
|
||||
int nfmt; /* num chars formatted so far */
|
||||
va_list args; /* args passed to dofmt */
|
||||
int r; /* % format Rune */
|
||||
int width;
|
||||
int prec;
|
||||
ulong flags;
|
||||
};
|
||||
|
||||
enum{
|
||||
FmtWidth = 1,
|
||||
FmtLeft = FmtWidth << 1,
|
||||
FmtPrec = FmtLeft << 1,
|
||||
FmtSharp = FmtPrec << 1,
|
||||
FmtSpace = FmtSharp << 1,
|
||||
FmtSign = FmtSpace << 1,
|
||||
FmtZero = FmtSign << 1,
|
||||
FmtUnsigned = FmtZero << 1,
|
||||
FmtShort = FmtUnsigned << 1,
|
||||
FmtLong = FmtShort << 1,
|
||||
FmtVLong = FmtLong << 1,
|
||||
FmtComma = FmtVLong << 1,
|
||||
FmtByte = FmtComma << 1,
|
||||
|
||||
FmtFlag = FmtByte << 1
|
||||
};
|
||||
|
||||
extern int print(char*, ...);
|
||||
extern char* seprint(char*, char*, char*, ...);
|
||||
extern char* vseprint(char*, char*, char*, va_list);
|
||||
extern int snprint(char*, int, char*, ...);
|
||||
extern int vsnprint(char*, int, char*, va_list);
|
||||
extern char* smprint(char*, ...);
|
||||
extern char* vsmprint(char*, va_list);
|
||||
extern int sprint(char*, char*, ...);
|
||||
extern int fprint(int, char*, ...);
|
||||
extern int vfprint(int, char*, va_list);
|
||||
|
||||
extern int (*doquote)(int);
|
||||
extern int runesprint(Rune*, char*, ...);
|
||||
extern int runesnprint(Rune*, int, char*, ...);
|
||||
extern int runevsnprint(Rune*, int, char*, va_list);
|
||||
extern Rune* runeseprint(Rune*, Rune*, char*, ...);
|
||||
extern Rune* runevseprint(Rune*, Rune*, char*, va_list);
|
||||
extern Rune* runesmprint(char*, ...);
|
||||
extern Rune* runevsmprint(char*, va_list);
|
||||
|
||||
extern int fmtfdinit(Fmt*, int, char*, int);
|
||||
extern int fmtfdflush(Fmt*);
|
||||
extern int fmtstrinit(Fmt*);
|
||||
extern int fmtinstall(int, int (*)(Fmt*));
|
||||
extern char* fmtstrflush(Fmt*);
|
||||
extern int runefmtstrinit(Fmt*);
|
||||
extern Rune* runefmtstrflush(Fmt*);
|
||||
|
||||
extern void* mallocz(ulong, int);
|
||||
|
||||
extern void srand(long);
|
||||
extern int rand(void);
|
||||
extern int nrand(int);
|
||||
extern long lrand(void);
|
||||
extern long lnrand(long);
|
||||
extern double frand(void);
|
3
include/libc.h
Normal file
3
include/libc.h
Normal file
@ -0,0 +1,3 @@
|
||||
#include "lib.h"
|
||||
#include "user.h"
|
||||
|
340
include/libsec.h
Normal file
340
include/libsec.h
Normal file
@ -0,0 +1,340 @@
|
||||
|
||||
#ifndef _MPINT
|
||||
typedef struct mpint mpint;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// AES definitions
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
enum
|
||||
{
|
||||
AESbsize= 16,
|
||||
AESmaxkey= 32,
|
||||
AESmaxrounds= 14
|
||||
};
|
||||
|
||||
typedef struct AESstate AESstate;
|
||||
struct AESstate
|
||||
{
|
||||
ulong setup;
|
||||
int rounds;
|
||||
int keybytes;
|
||||
uchar key[AESmaxkey]; /* unexpanded key */
|
||||
u32int ekey[4*(AESmaxrounds + 1)]; /* encryption key */
|
||||
u32int dkey[4*(AESmaxrounds + 1)]; /* decryption key */
|
||||
uchar ivec[AESbsize]; /* initialization vector */
|
||||
};
|
||||
|
||||
void setupAESstate(AESstate *s, uchar key[], int keybytes, uchar *ivec);
|
||||
void aesCBCencrypt(uchar *p, int len, AESstate *s);
|
||||
void aesCBCdecrypt(uchar *p, int len, AESstate *s);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// Blowfish Definitions
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
enum
|
||||
{
|
||||
BFbsize = 8,
|
||||
BFrounds = 16
|
||||
};
|
||||
|
||||
// 16-round Blowfish
|
||||
typedef struct BFstate BFstate;
|
||||
struct BFstate
|
||||
{
|
||||
ulong setup;
|
||||
|
||||
uchar key[56];
|
||||
uchar ivec[8];
|
||||
|
||||
u32int pbox[BFrounds+2];
|
||||
u32int sbox[1024];
|
||||
};
|
||||
|
||||
void setupBFstate(BFstate *s, uchar key[], int keybytes, uchar *ivec);
|
||||
void bfCBCencrypt(uchar*, int, BFstate*);
|
||||
void bfCBCdecrypt(uchar*, int, BFstate*);
|
||||
void bfECBencrypt(uchar*, int, BFstate*);
|
||||
void bfECBdecrypt(uchar*, int, BFstate*);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// DES definitions
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
enum
|
||||
{
|
||||
DESbsize= 8
|
||||
};
|
||||
|
||||
// single des
|
||||
typedef struct DESstate DESstate;
|
||||
struct DESstate
|
||||
{
|
||||
ulong setup;
|
||||
uchar key[8]; /* unexpanded key */
|
||||
ulong expanded[32]; /* expanded key */
|
||||
uchar ivec[8]; /* initialization vector */
|
||||
};
|
||||
|
||||
void setupDESstate(DESstate *s, uchar key[8], uchar *ivec);
|
||||
void des_key_setup(uchar[8], ulong[32]);
|
||||
void block_cipher(ulong*, uchar*, int);
|
||||
void desCBCencrypt(uchar*, int, DESstate*);
|
||||
void desCBCdecrypt(uchar*, int, DESstate*);
|
||||
void desECBencrypt(uchar*, int, DESstate*);
|
||||
void desECBdecrypt(uchar*, int, DESstate*);
|
||||
|
||||
// for backward compatibility with 7 byte DES key format
|
||||
void des56to64(uchar *k56, uchar *k64);
|
||||
void des64to56(uchar *k64, uchar *k56);
|
||||
void key_setup(uchar[7], ulong[32]);
|
||||
|
||||
// triple des encrypt/decrypt orderings
|
||||
enum {
|
||||
DES3E= 0,
|
||||
DES3D= 1,
|
||||
DES3EEE= 0,
|
||||
DES3EDE= 2,
|
||||
DES3DED= 5,
|
||||
DES3DDD= 7
|
||||
};
|
||||
|
||||
typedef struct DES3state DES3state;
|
||||
struct DES3state
|
||||
{
|
||||
ulong setup;
|
||||
uchar key[3][8]; /* unexpanded key */
|
||||
ulong expanded[3][32]; /* expanded key */
|
||||
uchar ivec[8]; /* initialization vector */
|
||||
};
|
||||
|
||||
void setupDES3state(DES3state *s, uchar key[3][8], uchar *ivec);
|
||||
void triple_block_cipher(ulong keys[3][32], uchar*, int);
|
||||
void des3CBCencrypt(uchar*, int, DES3state*);
|
||||
void des3CBCdecrypt(uchar*, int, DES3state*);
|
||||
void des3ECBencrypt(uchar*, int, DES3state*);
|
||||
void des3ECBdecrypt(uchar*, int, DES3state*);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// digests
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
enum
|
||||
{
|
||||
SHA1dlen= 20, /* SHA digest length */
|
||||
MD4dlen= 16, /* MD4 digest length */
|
||||
MD5dlen= 16 /* MD5 digest length */
|
||||
};
|
||||
|
||||
typedef struct DigestState DigestState;
|
||||
struct DigestState
|
||||
{
|
||||
ulong len;
|
||||
u32int state[5];
|
||||
uchar buf[128];
|
||||
int blen;
|
||||
char malloced;
|
||||
char seeded;
|
||||
};
|
||||
typedef struct DigestState SHAstate; /* obsolete name */
|
||||
typedef struct DigestState SHA1state;
|
||||
typedef struct DigestState MD5state;
|
||||
typedef struct DigestState MD4state;
|
||||
|
||||
DigestState* md4(uchar*, ulong, uchar*, DigestState*);
|
||||
DigestState* md5(uchar*, ulong, uchar*, DigestState*);
|
||||
DigestState* sha1(uchar*, ulong, uchar*, DigestState*);
|
||||
DigestState* hmac_md5(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
|
||||
DigestState* hmac_sha1(uchar*, ulong, uchar*, ulong, uchar*, DigestState*);
|
||||
char* sha1pickle(SHA1state*);
|
||||
SHA1state* sha1unpickle(char*);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// random number generation
|
||||
/////////////////////////////////////////////////////////
|
||||
void genrandom(uchar *buf, int nbytes);
|
||||
void prng(uchar *buf, int nbytes);
|
||||
ulong fastrand(void);
|
||||
ulong nfastrand(ulong);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// primes
|
||||
/////////////////////////////////////////////////////////
|
||||
void genprime(mpint *p, int n, int accuracy); // generate an n bit probable prime
|
||||
void gensafeprime(mpint *p, mpint *alpha, int n, int accuracy); // prime and generator
|
||||
void genstrongprime(mpint *p, int n, int accuracy); // generate an n bit strong prime
|
||||
void DSAprimes(mpint *q, mpint *p, uchar seed[SHA1dlen]);
|
||||
int probably_prime(mpint *n, int nrep); // miller-rabin test
|
||||
int smallprimetest(mpint *p); // returns -1 if not prime, 0 otherwise
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// rc4
|
||||
/////////////////////////////////////////////////////////
|
||||
typedef struct RC4state RC4state;
|
||||
struct RC4state
|
||||
{
|
||||
uchar state[256];
|
||||
uchar x;
|
||||
uchar y;
|
||||
};
|
||||
|
||||
void setupRC4state(RC4state*, uchar*, int);
|
||||
void rc4(RC4state*, uchar*, int);
|
||||
void rc4skip(RC4state*, int);
|
||||
void rc4back(RC4state*, int);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// rsa
|
||||
/////////////////////////////////////////////////////////
|
||||
typedef struct RSApub RSApub;
|
||||
typedef struct RSApriv RSApriv;
|
||||
|
||||
// public/encryption key
|
||||
struct RSApub
|
||||
{
|
||||
mpint *n; // modulus
|
||||
mpint *ek; // exp (encryption key)
|
||||
};
|
||||
|
||||
// private/decryption key
|
||||
struct RSApriv
|
||||
{
|
||||
RSApub pub;
|
||||
|
||||
mpint *dk; // exp (decryption key)
|
||||
|
||||
// precomputed values to help with chinese remainder theorem calc
|
||||
mpint *p;
|
||||
mpint *q;
|
||||
mpint *kp; // dk mod p-1
|
||||
mpint *kq; // dk mod q-1
|
||||
mpint *c2; // (inv p) mod q
|
||||
};
|
||||
|
||||
RSApriv* rsagen(int nlen, int elen, int rounds);
|
||||
RSApriv* rsafill(mpint *n, mpint *e, mpint *d, mpint *p, mpint *q);
|
||||
mpint* rsaencrypt(RSApub *k, mpint *in, mpint *out);
|
||||
mpint* rsadecrypt(RSApriv *k, mpint *in, mpint *out);
|
||||
RSApub* rsapuballoc(void);
|
||||
void rsapubfree(RSApub*);
|
||||
RSApriv* rsaprivalloc(void);
|
||||
void rsaprivfree(RSApriv*);
|
||||
RSApub* rsaprivtopub(RSApriv*);
|
||||
RSApub* X509toRSApub(uchar*, int, char*, int);
|
||||
RSApriv* asn1toRSApriv(uchar*, int);
|
||||
void asn1dump(uchar *der, int len);
|
||||
uchar* decodepem(char *s, char *type, int *len);
|
||||
uchar* X509gen(RSApriv *priv, char *subj, ulong valid[2], int *certlen);
|
||||
uchar* X509req(RSApriv *priv, char *subj, int *certlen);
|
||||
char* X509verify(uchar *cert, int ncert, RSApub *pk);
|
||||
void X509dump(uchar *cert, int ncert);
|
||||
/////////////////////////////////////////////////////////
|
||||
// elgamal
|
||||
/////////////////////////////////////////////////////////
|
||||
typedef struct EGpub EGpub;
|
||||
typedef struct EGpriv EGpriv;
|
||||
typedef struct EGsig EGsig;
|
||||
|
||||
// public/encryption key
|
||||
struct EGpub
|
||||
{
|
||||
mpint *p; // modulus
|
||||
mpint *alpha; // generator
|
||||
mpint *key; // (encryption key) alpha**secret mod p
|
||||
};
|
||||
|
||||
// private/decryption key
|
||||
struct EGpriv
|
||||
{
|
||||
EGpub pub;
|
||||
mpint *secret; // (decryption key)
|
||||
};
|
||||
|
||||
// signature
|
||||
struct EGsig
|
||||
{
|
||||
mpint *r, *s;
|
||||
};
|
||||
|
||||
EGpriv* eggen(int nlen, int rounds);
|
||||
mpint* egencrypt(EGpub *k, mpint *in, mpint *out);
|
||||
mpint* egdecrypt(EGpriv *k, mpint *in, mpint *out);
|
||||
EGsig* egsign(EGpriv *k, mpint *m);
|
||||
int egverify(EGpub *k, EGsig *sig, mpint *m);
|
||||
EGpub* egpuballoc(void);
|
||||
void egpubfree(EGpub*);
|
||||
EGpriv* egprivalloc(void);
|
||||
void egprivfree(EGpriv*);
|
||||
EGsig* egsigalloc(void);
|
||||
void egsigfree(EGsig*);
|
||||
EGpub* egprivtopub(EGpriv*);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// dsa
|
||||
/////////////////////////////////////////////////////////
|
||||
typedef struct DSApub DSApub;
|
||||
typedef struct DSApriv DSApriv;
|
||||
typedef struct DSAsig DSAsig;
|
||||
|
||||
// public/encryption key
|
||||
struct DSApub
|
||||
{
|
||||
mpint *p; // modulus
|
||||
mpint *q; // group order, q divides p-1
|
||||
mpint *alpha; // group generator
|
||||
mpint *key; // (encryption key) alpha**secret mod p
|
||||
};
|
||||
|
||||
// private/decryption key
|
||||
struct DSApriv
|
||||
{
|
||||
DSApub pub;
|
||||
mpint *secret; // (decryption key)
|
||||
};
|
||||
|
||||
// signature
|
||||
struct DSAsig
|
||||
{
|
||||
mpint *r, *s;
|
||||
};
|
||||
|
||||
DSApriv* dsagen(DSApub *opub);
|
||||
DSAsig* dsasign(DSApriv *k, mpint *m);
|
||||
int dsaverify(DSApub *k, DSAsig *sig, mpint *m);
|
||||
DSApub* dsapuballoc(void);
|
||||
void dsapubfree(DSApub*);
|
||||
DSApriv* dsaprivalloc(void);
|
||||
void dsaprivfree(DSApriv*);
|
||||
DSAsig* dsasigalloc(void);
|
||||
void dsasigfree(DSAsig*);
|
||||
DSApub* dsaprivtopub(DSApriv*);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
// TLS
|
||||
/////////////////////////////////////////////////////////
|
||||
typedef struct Thumbprint{
|
||||
struct Thumbprint *next;
|
||||
uchar sha1[SHA1dlen];
|
||||
} Thumbprint;
|
||||
|
||||
typedef struct TLSconn{
|
||||
char dir[40]; // connection directory
|
||||
uchar *cert; // certificate (local on input, remote on output)
|
||||
uchar *sessionID;
|
||||
int certlen, sessionIDlen;
|
||||
int (*trace)(char*fmt, ...);
|
||||
} TLSconn;
|
||||
|
||||
// tlshand.c
|
||||
extern int tlsClient(int fd, TLSconn *c);
|
||||
extern int tlsServer(int fd, TLSconn *c);
|
||||
|
||||
// thumb.c
|
||||
extern Thumbprint* initThumbprints(char *ok, char *crl);
|
||||
extern void freeThumbprints(Thumbprint *ok);
|
||||
extern int okThumbprint(uchar *sha1, Thumbprint *ok);
|
||||
|
||||
// readcert.c
|
||||
extern uchar *readcert(char *filename, int *pcertlen);
|
200
include/memdraw.h
Normal file
200
include/memdraw.h
Normal file
@ -0,0 +1,200 @@
|
||||
#pragma src "/sys/src/libmemdraw"
|
||||
#pragma lib "libmemdraw.a"
|
||||
|
||||
typedef struct Memimage Memimage;
|
||||
typedef struct Memdata Memdata;
|
||||
typedef struct Memsubfont Memsubfont;
|
||||
typedef struct Memlayer Memlayer;
|
||||
typedef struct Memcmap Memcmap;
|
||||
typedef struct Memdrawparam Memdrawparam;
|
||||
|
||||
/*
|
||||
* Memdata is allocated from main pool, but .data from the image pool.
|
||||
* Memdata is allocated separately to permit patching its pointer after
|
||||
* compaction when windows share the image data.
|
||||
* The first word of data is a back pointer to the Memdata, to find
|
||||
* The word to patch.
|
||||
*/
|
||||
|
||||
struct Memdata
|
||||
{
|
||||
ulong *base; /* allocated data pointer */
|
||||
uchar *bdata; /* pointer to first byte of actual data; word-aligned */
|
||||
int ref; /* number of Memimages using this data */
|
||||
void* imref;
|
||||
int allocd; /* is this malloc'd? */
|
||||
};
|
||||
|
||||
enum {
|
||||
Frepl = 1<<0, /* is replicated */
|
||||
Fsimple = 1<<1, /* is 1x1 */
|
||||
Fgrey = 1<<2, /* is grey */
|
||||
Falpha = 1<<3, /* has explicit alpha */
|
||||
Fcmap = 1<<4, /* has cmap channel */
|
||||
Fbytes = 1<<5, /* has only 8-bit channels */
|
||||
};
|
||||
|
||||
struct Memimage
|
||||
{
|
||||
Rectangle r; /* rectangle in data area, local coords */
|
||||
Rectangle clipr; /* clipping region */
|
||||
int depth; /* number of bits of storage per pixel */
|
||||
int nchan; /* number of channels */
|
||||
ulong chan; /* channel descriptions */
|
||||
Memcmap *cmap;
|
||||
|
||||
Memdata *data; /* pointer to data; shared by windows in this image */
|
||||
int zero; /* data->bdata+zero==&byte containing (0,0) */
|
||||
ulong width; /* width in words of a single scan line */
|
||||
Memlayer *layer; /* nil if not a layer*/
|
||||
ulong flags;
|
||||
|
||||
int shift[NChan];
|
||||
int mask[NChan];
|
||||
int nbits[NChan];
|
||||
|
||||
void *X;
|
||||
};
|
||||
|
||||
struct Memcmap
|
||||
{
|
||||
uchar cmap2rgb[3*256];
|
||||
uchar rgb2cmap[16*16*16];
|
||||
};
|
||||
|
||||
/*
|
||||
* Subfonts
|
||||
*
|
||||
* given char c, Subfont *f, Fontchar *i, and Point p, one says
|
||||
* i = f->info+c;
|
||||
* draw(b, Rect(p.x+i->left, p.y+i->top,
|
||||
* p.x+i->left+((i+1)->x-i->x), p.y+i->bottom),
|
||||
* color, f->bits, Pt(i->x, i->top));
|
||||
* p.x += i->width;
|
||||
* to draw characters in the specified color (itself a Memimage) in Memimage b.
|
||||
*/
|
||||
|
||||
struct Memsubfont
|
||||
{
|
||||
char *name;
|
||||
short n; /* number of chars in font */
|
||||
uchar height; /* height of bitmap */
|
||||
char ascent; /* top of bitmap to baseline */
|
||||
Fontchar *info; /* n+1 character descriptors */
|
||||
Memimage *bits; /* of font */
|
||||
};
|
||||
|
||||
/*
|
||||
* Encapsulated parameters and information for sub-draw routines.
|
||||
*/
|
||||
enum {
|
||||
Simplesrc=1<<0,
|
||||
Simplemask=1<<1,
|
||||
Replsrc=1<<2,
|
||||
Replmask=1<<3,
|
||||
Fullmask=1<<4,
|
||||
};
|
||||
struct Memdrawparam
|
||||
{
|
||||
Memimage *dst;
|
||||
Rectangle r;
|
||||
Memimage *src;
|
||||
Rectangle sr;
|
||||
Memimage *mask;
|
||||
Rectangle mr;
|
||||
int op;
|
||||
|
||||
ulong state;
|
||||
ulong mval; /* if Simplemask, the mask pixel in mask format */
|
||||
ulong mrgba; /* mval in rgba */
|
||||
ulong sval; /* if Simplesrc, the source pixel in src format */
|
||||
ulong srgba; /* sval in rgba */
|
||||
ulong sdval; /* sval in dst format */
|
||||
};
|
||||
|
||||
/*
|
||||
* Memimage management
|
||||
*/
|
||||
|
||||
extern Memimage* allocmemimage(Rectangle, ulong);
|
||||
extern Memimage* _allocmemimage(Rectangle, ulong);
|
||||
extern Memimage* allocmemimaged(Rectangle, ulong, Memdata*, void*);
|
||||
extern Memimage* readmemimage(int);
|
||||
extern Memimage* creadmemimage(int);
|
||||
extern int writememimage(int, Memimage*);
|
||||
extern void freememimage(Memimage*);
|
||||
extern int _loadmemimage(Memimage*, Rectangle, uchar*, int);
|
||||
extern int _cloadmemimage(Memimage*, Rectangle, uchar*, int);
|
||||
extern int _unloadmemimage(Memimage*, Rectangle, uchar*, int);
|
||||
extern int loadmemimage(Memimage*, Rectangle, uchar*, int);
|
||||
extern int cloadmemimage(Memimage*, Rectangle, uchar*, int);
|
||||
extern int unloadmemimage(Memimage*, Rectangle, uchar*, int);
|
||||
extern ulong* wordaddr(Memimage*, Point);
|
||||
extern uchar* byteaddr(Memimage*, Point);
|
||||
extern int drawclip(Memimage*, Rectangle*, Memimage*, Point*, Memimage*, Point*, Rectangle*, Rectangle*);
|
||||
extern void memfillcolor(Memimage*, ulong);
|
||||
extern int memsetchan(Memimage*, ulong);
|
||||
|
||||
/*
|
||||
* Graphics
|
||||
*/
|
||||
extern void memdraw(Memimage*, Rectangle, Memimage*, Point, Memimage*, Point, int);
|
||||
extern void memline(Memimage*, Point, Point, int, int, int, Memimage*, Point, int);
|
||||
extern void mempoly(Memimage*, Point*, int, int, int, int, Memimage*, Point, int);
|
||||
extern void memfillpoly(Memimage*, Point*, int, int, Memimage*, Point, int);
|
||||
extern void _memfillpolysc(Memimage*, Point*, int, int, Memimage*, Point, int, int, int, int);
|
||||
extern Memdrawparam* _memimagedrawsetup(Memimage*, Rectangle, Memimage*, Point, Memimage*, Point, int);
|
||||
extern void _memimagedraw(Memdrawparam*);
|
||||
extern void memimagedraw(Memimage*, Rectangle, Memimage*, Point, Memimage*, Point, int);
|
||||
extern int hwdraw(Memdrawparam*);
|
||||
extern void memimageline(Memimage*, Point, Point, int, int, int, Memimage*, Point, int);
|
||||
extern void _memimageline(Memimage*, Point, Point, int, int, int, Memimage*, Point, Rectangle, int);
|
||||
extern Point memimagestring(Memimage*, Point, Memimage*, Point, Memsubfont*, char*);
|
||||
extern void memellipse(Memimage*, Point, int, int, int, Memimage*, Point, int);
|
||||
extern void memarc(Memimage*, Point, int, int, int, Memimage*, Point, int, int, int);
|
||||
extern Rectangle memlinebbox(Point, Point, int, int, int);
|
||||
extern int memlineendsize(int);
|
||||
extern void _memmkcmap(void);
|
||||
extern void memimageinit(void);
|
||||
|
||||
/*
|
||||
* Subfont management
|
||||
*/
|
||||
extern Memsubfont* allocmemsubfont(char*, int, int, int, Fontchar*, Memimage*);
|
||||
extern Memsubfont* openmemsubfont(char*);
|
||||
extern void freememsubfont(Memsubfont*);
|
||||
extern Point memsubfontwidth(Memsubfont*, char*);
|
||||
extern Memsubfont* getmemdefont(void);
|
||||
|
||||
/*
|
||||
* Predefined
|
||||
*/
|
||||
extern Memimage* memwhite;
|
||||
extern Memimage* memblack;
|
||||
extern Memimage* memopaque;
|
||||
extern Memimage* memtransparent;
|
||||
extern Memcmap *memdefcmap;
|
||||
|
||||
/*
|
||||
* Kernel interface
|
||||
*/
|
||||
void memimagemove(void*, void*);
|
||||
|
||||
/*
|
||||
* Kernel cruft
|
||||
*/
|
||||
extern void rdb(void);
|
||||
extern int iprint(char*, ...);
|
||||
#pragma varargck argpos iprint 1
|
||||
extern int drawdebug;
|
||||
|
||||
/*
|
||||
* doprint interface: numbconv bit strings
|
||||
*/
|
||||
#pragma varargck type "llb" vlong
|
||||
#pragma varargck type "llb" uvlong
|
||||
#pragma varargck type "lb" long
|
||||
#pragma varargck type "lb" ulong
|
||||
#pragma varargck type "b" int
|
||||
#pragma varargck type "b" uint
|
||||
|
51
include/memlayer.h
Normal file
51
include/memlayer.h
Normal file
@ -0,0 +1,51 @@
|
||||
#pragma src "/sys/src/libmemlayer"
|
||||
#pragma lib "libmemlayer.a"
|
||||
|
||||
typedef struct Memscreen Memscreen;
|
||||
typedef void (*Refreshfn)(Memimage*, Rectangle, void*);
|
||||
|
||||
struct Memscreen
|
||||
{
|
||||
Memimage *frontmost; /* frontmost layer on screen */
|
||||
Memimage *rearmost; /* rearmost layer on screen */
|
||||
Memimage *image; /* upon which all layers are drawn */
|
||||
Memimage *fill; /* if non-zero, picture to use when repainting */
|
||||
};
|
||||
|
||||
struct Memlayer
|
||||
{
|
||||
Rectangle screenr; /* true position of layer on screen */
|
||||
Point delta; /* add delta to go from image coords to screen */
|
||||
Memscreen *screen; /* screen this layer belongs to */
|
||||
Memimage *front; /* window in front of this one */
|
||||
Memimage *rear; /* window behind this one*/
|
||||
int clear; /* layer is fully visible */
|
||||
Memimage *save; /* save area for obscured parts */
|
||||
Refreshfn refreshfn; /* function to call to refresh obscured parts if save==nil */
|
||||
void *refreshptr; /* argument to refreshfn */
|
||||
};
|
||||
|
||||
/*
|
||||
* These functions accept local coordinates
|
||||
*/
|
||||
int memload(Memimage*, Rectangle, uchar*, int, int);
|
||||
int memunload(Memimage*, Rectangle, uchar*, int);
|
||||
|
||||
/*
|
||||
* All these functions accept screen coordinates, not local ones.
|
||||
*/
|
||||
void _memlayerop(void (*fn)(Memimage*, Rectangle, Rectangle, void*, int), Memimage*, Rectangle, Rectangle, void*);
|
||||
Memimage* memlalloc(Memscreen*, Rectangle, Refreshfn, void*, ulong);
|
||||
void memldelete(Memimage*);
|
||||
void memlfree(Memimage*);
|
||||
void memltofront(Memimage*);
|
||||
void memltofrontn(Memimage**, int);
|
||||
void _memltofrontfill(Memimage*, int);
|
||||
void memltorear(Memimage*);
|
||||
void memltorearn(Memimage**, int);
|
||||
int memlsetrefresh(Memimage*, Refreshfn, void*);
|
||||
void memlhide(Memimage*, Rectangle);
|
||||
void memlexpose(Memimage*, Rectangle);
|
||||
void _memlsetclear(Memscreen*);
|
||||
int memlorigin(Memimage*, Point, Point);
|
||||
void memlnorefresh(Memimage*, Rectangle, void*);
|
134
include/mp.h
Normal file
134
include/mp.h
Normal file
@ -0,0 +1,134 @@
|
||||
#define _MPINT 1
|
||||
|
||||
// the code assumes mpdigit to be at least an int
|
||||
// mpdigit must be an atomic type. mpdigit is defined
|
||||
// in the architecture specific u.h
|
||||
|
||||
typedef struct mpint mpint;
|
||||
|
||||
struct mpint
|
||||
{
|
||||
int sign; // +1 or -1
|
||||
int size; // allocated digits
|
||||
int top; // significant digits
|
||||
mpdigit *p;
|
||||
char flags;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MPstatic= 0x01,
|
||||
Dbytes= sizeof(mpdigit), // bytes per digit
|
||||
Dbits= Dbytes*8 // bits per digit
|
||||
};
|
||||
|
||||
// allocation
|
||||
void mpsetminbits(int n); // newly created mpint's get at least n bits
|
||||
mpint* mpnew(int n); // create a new mpint with at least n bits
|
||||
void mpfree(mpint *b);
|
||||
void mpbits(mpint *b, int n); // ensure that b has at least n bits
|
||||
void mpnorm(mpint *b); // dump leading zeros
|
||||
mpint* mpcopy(mpint *b);
|
||||
void mpassign(mpint *old, mpint *new);
|
||||
|
||||
// random bits
|
||||
mpint* mprand(int bits, void (*gen)(uchar*, int), mpint *b);
|
||||
|
||||
// conversion
|
||||
mpint* strtomp(char*, char**, int, mpint*); // ascii
|
||||
int mpfmt(Fmt*);
|
||||
char* mptoa(mpint*, int, char*, int);
|
||||
mpint* letomp(uchar*, uint, mpint*); // byte array, little-endian
|
||||
int mptole(mpint*, uchar*, uint, uchar**);
|
||||
mpint* betomp(uchar*, uint, mpint*); // byte array, little-endian
|
||||
int mptobe(mpint*, uchar*, uint, uchar**);
|
||||
uint mptoui(mpint*); // unsigned int
|
||||
mpint* uitomp(uint, mpint*);
|
||||
int mptoi(mpint*); // int
|
||||
mpint* itomp(int, mpint*);
|
||||
uvlong mptouv(mpint*); // unsigned vlong
|
||||
mpint* uvtomp(uvlong, mpint*);
|
||||
vlong mptov(mpint*); // vlong
|
||||
mpint* vtomp(vlong, mpint*);
|
||||
|
||||
// divide 2 digits by one
|
||||
void mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient);
|
||||
|
||||
// in the following, the result mpint may be
|
||||
// the same as one of the inputs.
|
||||
void mpadd(mpint *b1, mpint *b2, mpint *sum); // sum = b1+b2
|
||||
void mpsub(mpint *b1, mpint *b2, mpint *diff); // diff = b1-b2
|
||||
void mpleft(mpint *b, int shift, mpint *res); // res = b<<shift
|
||||
void mpright(mpint *b, int shift, mpint *res); // res = b>>shift
|
||||
void mpmul(mpint *b1, mpint *b2, mpint *prod); // prod = b1*b2
|
||||
void mpexp(mpint *b, mpint *e, mpint *m, mpint *res); // res = b**e mod m
|
||||
void mpmod(mpint *b, mpint *m, mpint *remainder); // remainder = b mod m
|
||||
|
||||
// quotient = dividend/divisor, remainder = dividend % divisor
|
||||
void mpdiv(mpint *dividend, mpint *divisor, mpint *quotient, mpint *remainder);
|
||||
|
||||
// return neg, 0, pos as b1-b2 is neg, 0, pos
|
||||
int mpcmp(mpint *b1, mpint *b2);
|
||||
|
||||
// extended gcd return d, x, and y, s.t. d = gcd(a,b) and ax+by = d
|
||||
void mpextendedgcd(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y);
|
||||
|
||||
// res = b**-1 mod m
|
||||
void mpinvert(mpint *b, mpint *m, mpint *res);
|
||||
|
||||
// bit counting
|
||||
int mpsignif(mpint*); // number of sigificant bits in mantissa
|
||||
int mplowbits0(mpint*); // k, where n = 2**k * q for odd q
|
||||
|
||||
// well known constants
|
||||
extern mpint *mpzero, *mpone, *mptwo;
|
||||
|
||||
// sum[0:alen] = a[0:alen-1] + b[0:blen-1]
|
||||
// prereq: alen >= blen, sum has room for alen+1 digits
|
||||
void mpvecadd(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *sum);
|
||||
|
||||
// diff[0:alen-1] = a[0:alen-1] - b[0:blen-1]
|
||||
// prereq: alen >= blen, diff has room for alen digits
|
||||
void mpvecsub(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *diff);
|
||||
|
||||
// p[0:n] += m * b[0:n-1]
|
||||
// prereq: p has room for n+1 digits
|
||||
void mpvecdigmuladd(mpdigit *b, int n, mpdigit m, mpdigit *p);
|
||||
|
||||
// p[0:n] -= m * b[0:n-1]
|
||||
// prereq: p has room for n+1 digits
|
||||
int mpvecdigmulsub(mpdigit *b, int n, mpdigit m, mpdigit *p);
|
||||
|
||||
// p[0:alen*blen-1] = a[0:alen-1] * b[0:blen-1]
|
||||
// prereq: alen >= blen, p has room for m*n digits
|
||||
void mpvecmul(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p);
|
||||
|
||||
// sign of a - b or zero if the same
|
||||
int mpveccmp(mpdigit *a, int alen, mpdigit *b, int blen);
|
||||
|
||||
// divide the 2 digit dividend by the one digit divisor and stick in quotient
|
||||
// we assume that the result is one digit - overflow is all 1's
|
||||
void mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient);
|
||||
|
||||
// playing with magnitudes
|
||||
int mpmagcmp(mpint *b1, mpint *b2);
|
||||
void mpmagadd(mpint *b1, mpint *b2, mpint *sum); // sum = b1+b2
|
||||
void mpmagsub(mpint *b1, mpint *b2, mpint *sum); // sum = b1+b2
|
||||
|
||||
// chinese remainder theorem
|
||||
typedef struct CRTpre CRTpre; // precomputed values for converting
|
||||
// twixt residues and mpint
|
||||
typedef struct CRTres CRTres; // residue form of an mpint
|
||||
|
||||
struct CRTres
|
||||
{
|
||||
int n; // number of residues
|
||||
mpint *r[1]; // residues
|
||||
};
|
||||
|
||||
CRTpre* crtpre(int, mpint**); // precompute conversion values
|
||||
CRTres* crtin(CRTpre*, mpint*); // convert mpint to residues
|
||||
void crtout(CRTpre*, CRTres*, mpint*); // convert residues to mpint
|
||||
void crtprefree(CRTpre*);
|
||||
void crtresfree(CRTres*);
|
||||
|
26
include/u.h
Normal file
26
include/u.h
Normal file
@ -0,0 +1,26 @@
|
||||
#include "dtos.h"
|
||||
|
||||
/* avoid name conflicts */
|
||||
#undef accept
|
||||
#undef listen
|
||||
|
||||
/* sys calls */
|
||||
#undef bind
|
||||
#undef chdir
|
||||
#undef close
|
||||
#undef create
|
||||
#undef dup
|
||||
#undef export
|
||||
#undef fstat
|
||||
#undef fwstat
|
||||
#undef mount
|
||||
#undef open
|
||||
#undef start
|
||||
#undef read
|
||||
#undef remove
|
||||
#undef seek
|
||||
#undef stat
|
||||
#undef write
|
||||
#undef wstat
|
||||
#undef unmount
|
||||
#undef pipe
|
14
include/unix.h
Normal file
14
include/unix.h
Normal file
@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <fcntl.h>
|
||||
#include <setjmp.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
typedef long long p9_vlong;
|
||||
typedef unsigned long long p9_uvlong;
|
65
include/user.h
Normal file
65
include/user.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* sys calls */
|
||||
#define bind sysbind
|
||||
#define chdir syschdir
|
||||
#define close sysclose
|
||||
#define create syscreate
|
||||
#define dup sysdup
|
||||
#define export sysexport
|
||||
#define fstat sysfstat
|
||||
#define fwstat sysfwstat
|
||||
#define mount sysmount
|
||||
#define open sysopen
|
||||
#define read sysread
|
||||
#define remove sysremove
|
||||
#define seek sysseek
|
||||
#define stat sysstat
|
||||
#define write syswrite
|
||||
#define wstat syswstat
|
||||
#define unmount sysunmount
|
||||
#define pipe syspipe
|
||||
#define rendezvous sysrendezvous
|
||||
#define getpid sysgetpid
|
||||
#define time systime
|
||||
#define nsec sysnsec
|
||||
#define pread syspread
|
||||
#define pwrite syspwrite
|
||||
|
||||
extern int bind(char*, char*, int);
|
||||
extern int chdir(char*);
|
||||
extern int close(int);
|
||||
extern int create(char*, int, ulong);
|
||||
extern int dup(int, int);
|
||||
extern int export(int);
|
||||
extern int fstat(int, uchar*, int);
|
||||
extern int fwstat(int, uchar*, int);
|
||||
extern int mount(int, int, char*, int, char*);
|
||||
extern int unmount(char*, char*);
|
||||
extern int open(char*, int);
|
||||
extern int pipe(int*);
|
||||
extern long read(int, void*, long);
|
||||
extern long readn(int, void*, long);
|
||||
extern int remove(char*);
|
||||
extern vlong seek(int, vlong, int);
|
||||
extern int stat(char*, uchar*, int);
|
||||
extern long write(int, void*, long);
|
||||
extern int wstat(char*, uchar*, int);
|
||||
|
||||
extern Dir *dirstat(char*);
|
||||
extern Dir *dirfstat(int);
|
||||
extern int dirwstat(char*, Dir*);
|
||||
extern int dirfwstat(int, Dir*);
|
||||
extern long dirread(int, Dir*, long);
|
||||
|
||||
/*
|
||||
* network dialing and authentication
|
||||
*/
|
||||
#define NETPATHLEN 40
|
||||
extern int accept(int, char*);
|
||||
extern int announce(char*, char*);
|
||||
extern int dial(char*, char*, char*, int*);
|
||||
extern int hangup(int);
|
||||
extern int listen(char*, char*);
|
||||
extern char *netmkaddr(char*, char*, char*);
|
||||
extern int reject(int, char*, char*);
|
||||
|
||||
extern char* argv0;
|
6
include/x.c
Normal file
6
include/x.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
main(void)
|
||||
{
|
||||
}
|
50
kern/Makefile
Normal file
50
kern/Makefile
Normal file
@ -0,0 +1,50 @@
|
||||
LIB=libkern.a
|
||||
CC=gcc
|
||||
CFLAGS=-I../include -I. -c -ggdb -D_THREAD_SAFE -pthread
|
||||
O=o
|
||||
#CC=cl
|
||||
#CFLAGS=-c -nologo -W3 -YX -Zi -MT -Zl -I../include -DWINDOWS
|
||||
#O=obj
|
||||
|
||||
OFILES=\
|
||||
allocb.$O\
|
||||
cache.$O\
|
||||
chan.$O\
|
||||
data.$O\
|
||||
dev.$O\
|
||||
devcons.$O\
|
||||
devdraw.$O\
|
||||
devfs.$O\
|
||||
devip.$O\
|
||||
devip-posix.$O\
|
||||
devmnt.$O\
|
||||
devmouse.$O\
|
||||
devpipe.$O\
|
||||
devroot.$O\
|
||||
devssl.$O\
|
||||
devtab.$O\
|
||||
error.$O\
|
||||
parse.$O\
|
||||
pgrp.$O\
|
||||
posix.$O\
|
||||
procinit.$O\
|
||||
rwlock.$O\
|
||||
sleep.$O\
|
||||
smalloc.$O\
|
||||
stub.$O\
|
||||
sysfile.$O\
|
||||
sysproc.$O\
|
||||
qio.$O\
|
||||
qlock.$O\
|
||||
term.$O\
|
||||
todo.$O\
|
||||
uart.$O\
|
||||
waserror.$O
|
||||
|
||||
$(LIB): $(OFILES)
|
||||
ar r $(LIB) $(OFILES)
|
||||
ranlib $(LIB)
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $(CFLAGS) $*.c
|
||||
|
165
kern/allocb.c
Normal file
165
kern/allocb.c
Normal file
@ -0,0 +1,165 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
enum
|
||||
{
|
||||
Hdrspc = 64, /* leave room for high-level headers */
|
||||
Bdead = 0x51494F42, /* "QIOB" */
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
Lock lk;
|
||||
ulong bytes;
|
||||
} ialloc;
|
||||
|
||||
static Block*
|
||||
_allocb(int size)
|
||||
{
|
||||
Block *b;
|
||||
ulong addr;
|
||||
|
||||
if((b = mallocz(sizeof(Block)+size+Hdrspc, 0)) == nil)
|
||||
return nil;
|
||||
|
||||
b->next = nil;
|
||||
b->list = nil;
|
||||
b->free = 0;
|
||||
b->flag = 0;
|
||||
|
||||
/* align start of data portion by rounding up */
|
||||
addr = (ulong)b;
|
||||
addr = ROUND(addr + sizeof(Block), BLOCKALIGN);
|
||||
b->base = (uchar*)addr;
|
||||
|
||||
/* align end of data portion by rounding down */
|
||||
b->lim = ((uchar*)b) + sizeof(Block)+size+Hdrspc;
|
||||
addr = (ulong)(b->lim);
|
||||
addr = addr & ~(BLOCKALIGN-1);
|
||||
b->lim = (uchar*)addr;
|
||||
|
||||
/* leave sluff at beginning for added headers */
|
||||
b->rp = b->lim - ROUND(size, BLOCKALIGN);
|
||||
if(b->rp < b->base)
|
||||
panic("_allocb");
|
||||
b->wp = b->rp;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
Block*
|
||||
allocb(int size)
|
||||
{
|
||||
Block *b;
|
||||
|
||||
/*
|
||||
* Check in a process and wait until successful.
|
||||
* Can still error out of here, though.
|
||||
*/
|
||||
if(up == nil)
|
||||
panic("allocb without up: %luX\n", getcallerpc(&size));
|
||||
if((b = _allocb(size)) == nil){
|
||||
panic("allocb: no memory for %d bytes\n", size);
|
||||
}
|
||||
setmalloctag(b, getcallerpc(&size));
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
Block*
|
||||
iallocb(int size)
|
||||
{
|
||||
Block *b;
|
||||
static int m1, m2;
|
||||
|
||||
if(ialloc.bytes > conf.ialloc){
|
||||
if((m1++%10000)==0)
|
||||
print("iallocb: limited %lud/%lud\n",
|
||||
ialloc.bytes, conf.ialloc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((b = _allocb(size)) == nil){
|
||||
if((m2++%10000)==0)
|
||||
print("iallocb: no memory %lud/%lud\n",
|
||||
ialloc.bytes, conf.ialloc);
|
||||
return nil;
|
||||
}
|
||||
setmalloctag(b, getcallerpc(&size));
|
||||
b->flag = BINTR;
|
||||
|
||||
ilock(&ialloc.lk);
|
||||
ialloc.bytes += b->lim - b->base;
|
||||
iunlock(&ialloc.lk);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
void
|
||||
freeb(Block *b)
|
||||
{
|
||||
void *dead = (void*)Bdead;
|
||||
|
||||
if(b == nil)
|
||||
return;
|
||||
|
||||
/*
|
||||
* drivers which perform non cache coherent DMA manage their own buffer
|
||||
* pool of uncached buffers and provide their own free routine.
|
||||
*/
|
||||
if(b->free) {
|
||||
b->free(b);
|
||||
return;
|
||||
}
|
||||
if(b->flag & BINTR) {
|
||||
ilock(&ialloc.lk);
|
||||
ialloc.bytes -= b->lim - b->base;
|
||||
iunlock(&ialloc.lk);
|
||||
}
|
||||
|
||||
/* poison the block in case someone is still holding onto it */
|
||||
b->next = dead;
|
||||
b->rp = dead;
|
||||
b->wp = dead;
|
||||
b->lim = dead;
|
||||
b->base = dead;
|
||||
|
||||
free(b);
|
||||
}
|
||||
|
||||
void
|
||||
checkb(Block *b, char *msg)
|
||||
{
|
||||
void *dead = (void*)Bdead;
|
||||
|
||||
if(b == dead)
|
||||
panic("checkb b %s %lux", msg, b);
|
||||
if(b->base == dead || b->lim == dead || b->next == dead
|
||||
|| b->rp == dead || b->wp == dead){
|
||||
print("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\n",
|
||||
b->base, b->lim, b->next);
|
||||
print("checkb: rp 0x%8.8luX wp 0x%8.8luX\n", b->rp, b->wp);
|
||||
panic("checkb dead: %s\n", msg);
|
||||
}
|
||||
|
||||
if(b->base > b->lim)
|
||||
panic("checkb 0 %s %lux %lux", msg, b->base, b->lim);
|
||||
if(b->rp < b->base)
|
||||
panic("checkb 1 %s %lux %lux", msg, b->base, b->rp);
|
||||
if(b->wp < b->base)
|
||||
panic("checkb 2 %s %lux %lux", msg, b->base, b->wp);
|
||||
if(b->rp > b->lim)
|
||||
panic("checkb 3 %s %lux %lux", msg, b->rp, b->lim);
|
||||
if(b->wp > b->lim)
|
||||
panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
iallocsummary(void)
|
||||
{
|
||||
print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc);
|
||||
}
|
46
kern/cache.c
Normal file
46
kern/cache.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
void
|
||||
cinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
copen(Chan *c)
|
||||
{
|
||||
USED(c);
|
||||
}
|
||||
|
||||
int
|
||||
cread(Chan *c, uchar *buf, int len, vlong off)
|
||||
{
|
||||
USED(c);
|
||||
USED(buf);
|
||||
USED(len);
|
||||
USED(off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
cupdate(Chan *c, uchar *buf, int len, vlong off)
|
||||
{
|
||||
USED(c);
|
||||
USED(buf);
|
||||
USED(len);
|
||||
USED(off);
|
||||
}
|
||||
|
||||
void
|
||||
cwrite(Chan* c, uchar *buf, int len, vlong off)
|
||||
{
|
||||
USED(c);
|
||||
USED(buf);
|
||||
USED(len);
|
||||
USED(off);
|
||||
}
|
1496
kern/chan.c
Normal file
1496
kern/chan.c
Normal file
File diff suppressed because it is too large
Load Diff
519
kern/dat.h
Normal file
519
kern/dat.h
Normal file
@ -0,0 +1,519 @@
|
||||
#define KNAMELEN 28 /* max length of name held in kernel */
|
||||
#define DOMLEN 64
|
||||
|
||||
#define BLOCKALIGN 8
|
||||
|
||||
typedef struct Alarms Alarms;
|
||||
typedef struct Block Block;
|
||||
typedef struct CSN CSN;
|
||||
typedef struct Chan Chan;
|
||||
typedef struct Cmdbuf Cmdbuf;
|
||||
typedef struct Cmdtab Cmdtab;
|
||||
typedef struct Cname Cname;
|
||||
typedef struct Conf Conf;
|
||||
typedef struct Dev Dev;
|
||||
typedef struct Dirtab Dirtab;
|
||||
typedef struct Edfinterface Edfinterface;
|
||||
typedef struct Egrp Egrp;
|
||||
typedef struct Evalue Evalue;
|
||||
typedef struct Fgrp Fgrp;
|
||||
typedef struct FPsave FPsave;
|
||||
typedef struct DevConf DevConf;
|
||||
typedef struct Label Label;
|
||||
typedef struct List List;
|
||||
typedef struct Log Log;
|
||||
typedef struct Logflag Logflag;
|
||||
typedef struct Mntcache Mntcache;
|
||||
typedef struct Mount Mount;
|
||||
typedef struct Mntrpc Mntrpc;
|
||||
typedef struct Mntwalk Mntwalk;
|
||||
typedef struct Mnt Mnt;
|
||||
typedef struct Mhead Mhead;
|
||||
typedef struct Note Note;
|
||||
typedef struct Page Page;
|
||||
typedef struct Palloc Palloc;
|
||||
typedef struct Perf Perf;
|
||||
typedef struct Pgrps Pgrps;
|
||||
typedef struct PhysUart PhysUart;
|
||||
typedef struct Pgrp Pgrp;
|
||||
typedef struct Physseg Physseg;
|
||||
typedef struct Proc Proc;
|
||||
typedef struct Pte Pte;
|
||||
typedef struct Pthash Pthash;
|
||||
typedef struct Queue Queue;
|
||||
typedef struct Ref Ref;
|
||||
typedef struct Rendez Rendez;
|
||||
typedef struct Rgrp Rgrp;
|
||||
typedef struct RWlock RWlock;
|
||||
typedef struct Schedq Schedq;
|
||||
typedef struct Segment Segment;
|
||||
typedef struct Session Session;
|
||||
typedef struct Task Task;
|
||||
typedef struct Talarm Talarm;
|
||||
typedef struct Timer Timer;
|
||||
typedef struct Uart Uart;
|
||||
typedef struct Ureg Ureg;
|
||||
typedef struct Waitq Waitq;
|
||||
typedef struct Walkqid Walkqid;
|
||||
typedef int Devgen(Chan*, char*, Dirtab*, int, int, Dir*);
|
||||
|
||||
#include "fcall.h"
|
||||
|
||||
enum
|
||||
{
|
||||
SnarfSize = 64*1024,
|
||||
};
|
||||
|
||||
struct Conf
|
||||
{
|
||||
ulong nmach; /* processors */
|
||||
ulong nproc; /* processes */
|
||||
ulong monitor; /* has monitor? */
|
||||
ulong npage0; /* total physical pages of memory */
|
||||
ulong npage1; /* total physical pages of memory */
|
||||
ulong npage; /* total physical pages of memory */
|
||||
ulong upages; /* user page pool */
|
||||
ulong nimage; /* number of page cache image headers */
|
||||
ulong nswap; /* number of swap pages */
|
||||
int nswppo; /* max # of pageouts per segment pass */
|
||||
ulong base0; /* base of bank 0 */
|
||||
ulong base1; /* base of bank 1 */
|
||||
ulong copymode; /* 0 is copy on write, 1 is copy on reference */
|
||||
ulong ialloc; /* max interrupt time allocation in bytes */
|
||||
ulong pipeqsize; /* size in bytes of pipe queues */
|
||||
int nuart; /* number of uart devices */
|
||||
};
|
||||
|
||||
struct Label
|
||||
{
|
||||
jmp_buf buf;
|
||||
};
|
||||
|
||||
struct Ref
|
||||
{
|
||||
Lock lk;
|
||||
long ref;
|
||||
};
|
||||
|
||||
struct Rendez
|
||||
{
|
||||
Lock lk;
|
||||
Proc *p;
|
||||
};
|
||||
|
||||
struct RWlock /* changed from kernel */
|
||||
{
|
||||
int readers;
|
||||
Lock lk;
|
||||
QLock x;
|
||||
QLock k;
|
||||
};
|
||||
|
||||
struct Talarm
|
||||
{
|
||||
Lock lk;
|
||||
Proc *list;
|
||||
};
|
||||
|
||||
struct Alarms
|
||||
{
|
||||
QLock lk;
|
||||
Proc *head;
|
||||
};
|
||||
|
||||
/*
|
||||
* Access types in namec & channel flags
|
||||
*/
|
||||
enum
|
||||
{
|
||||
Aaccess, /* as in stat, wstat */
|
||||
Abind, /* for left-hand-side of bind */
|
||||
Atodir, /* as in chdir */
|
||||
Aopen, /* for i/o */
|
||||
Amount, /* to be mounted or mounted upon */
|
||||
Acreate, /* is to be created */
|
||||
Aremove, /* will be removed by caller */
|
||||
|
||||
COPEN = 0x0001, /* for i/o */
|
||||
CMSG = 0x0002, /* the message channel for a mount */
|
||||
/*rsc CCREATE = 0x0004, /* permits creation if c->mnt */
|
||||
CCEXEC = 0x0008, /* close on exec */
|
||||
CFREE = 0x0010, /* not in use */
|
||||
CRCLOSE = 0x0020, /* remove on close */
|
||||
CCACHE = 0x0080, /* client cache */
|
||||
};
|
||||
|
||||
/* flag values */
|
||||
enum
|
||||
{
|
||||
BINTR = (1<<0),
|
||||
BFREE = (1<<1),
|
||||
Bipck = (1<<2), /* ip checksum */
|
||||
Budpck = (1<<3), /* udp checksum */
|
||||
Btcpck = (1<<4), /* tcp checksum */
|
||||
Bpktck = (1<<5), /* packet checksum */
|
||||
};
|
||||
|
||||
struct Block
|
||||
{
|
||||
Block* next;
|
||||
Block* list;
|
||||
uchar* rp; /* first unconsumed byte */
|
||||
uchar* wp; /* first empty byte */
|
||||
uchar* lim; /* 1 past the end of the buffer */
|
||||
uchar* base; /* start of the buffer */
|
||||
void (*free)(Block*);
|
||||
ushort flag;
|
||||
ushort checksum; /* IP checksum of complete packet (minus media header) */
|
||||
};
|
||||
#define BLEN(s) ((s)->wp - (s)->rp)
|
||||
#define BALLOC(s) ((s)->lim - (s)->base)
|
||||
|
||||
struct Chan
|
||||
{
|
||||
Ref ref;
|
||||
Chan* next; /* allocation */
|
||||
Chan* link;
|
||||
vlong offset; /* in file */
|
||||
ushort type;
|
||||
ulong dev;
|
||||
ushort mode; /* read/write */
|
||||
ushort flag;
|
||||
Qid qid;
|
||||
int fid; /* for devmnt */
|
||||
ulong iounit; /* chunk size for i/o; 0==default */
|
||||
Mhead* umh; /* mount point that derived Chan; used in unionread */
|
||||
Chan* umc; /* channel in union; held for union read */
|
||||
QLock umqlock; /* serialize unionreads */
|
||||
int uri; /* union read index */
|
||||
int dri; /* devdirread index */
|
||||
ulong mountid;
|
||||
Mntcache *mcp; /* Mount cache pointer */
|
||||
Mnt *mux; /* Mnt for clients using me for messages */
|
||||
void* aux;
|
||||
Qid pgrpid; /* for #p/notepg */
|
||||
ulong mid; /* for ns in devproc */
|
||||
Chan* mchan; /* channel to mounted server */
|
||||
Qid mqid; /* qid of root of mount point */
|
||||
Session*session;
|
||||
Cname *name;
|
||||
};
|
||||
|
||||
struct Cname
|
||||
{
|
||||
Ref ref;
|
||||
int alen; /* allocated length */
|
||||
int len; /* strlen(s) */
|
||||
char *s;
|
||||
};
|
||||
|
||||
struct Dev
|
||||
{
|
||||
int dc;
|
||||
char* name;
|
||||
|
||||
void (*reset)(void);
|
||||
void (*init)(void);
|
||||
void (*shutdown)(void);
|
||||
Chan* (*attach)(char*);
|
||||
Walkqid* (*walk)(Chan*, Chan*, char**, int);
|
||||
int (*stat)(Chan*, uchar*, int);
|
||||
Chan* (*open)(Chan*, int);
|
||||
void (*create)(Chan*, char*, int, ulong);
|
||||
void (*close)(Chan*);
|
||||
long (*read)(Chan*, void*, long, vlong);
|
||||
Block* (*bread)(Chan*, long, ulong);
|
||||
long (*write)(Chan*, void*, long, vlong);
|
||||
long (*bwrite)(Chan*, Block*, ulong);
|
||||
void (*remove)(Chan*);
|
||||
int (*wstat)(Chan*, uchar*, int);
|
||||
void (*power)(int); /* power mgt: power(1) => on, power (0) => off */
|
||||
int (*config)(int, char*, DevConf*); // returns nil on error
|
||||
};
|
||||
|
||||
struct Dirtab
|
||||
{
|
||||
char name[KNAMELEN];
|
||||
Qid qid;
|
||||
vlong length;
|
||||
long perm;
|
||||
};
|
||||
|
||||
struct Walkqid
|
||||
{
|
||||
Chan *clone;
|
||||
int nqid;
|
||||
Qid qid[1];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
NSMAX = 1000,
|
||||
NSLOG = 7,
|
||||
NSCACHE = (1<<NSLOG),
|
||||
};
|
||||
|
||||
struct Mntwalk /* state for /proc/#/ns */
|
||||
{
|
||||
int cddone;
|
||||
ulong id;
|
||||
Mhead* mh;
|
||||
Mount* cm;
|
||||
};
|
||||
|
||||
struct Mount
|
||||
{
|
||||
ulong mountid;
|
||||
Mount* next;
|
||||
Mhead* head;
|
||||
Mount* copy;
|
||||
Mount* order;
|
||||
Chan* to; /* channel replacing channel */
|
||||
int mflag;
|
||||
char *spec;
|
||||
};
|
||||
|
||||
struct Mhead
|
||||
{
|
||||
Ref ref;
|
||||
RWlock lock;
|
||||
Chan* from; /* channel mounted upon */
|
||||
Mount* mount; /* what's mounted upon it */
|
||||
Mhead* hash; /* Hash chain */
|
||||
};
|
||||
|
||||
struct Mnt
|
||||
{
|
||||
Lock lk;
|
||||
/* references are counted using c->ref; channels on this mount point incref(c->mchan) == Mnt.c */
|
||||
Chan *c; /* Channel to file service */
|
||||
Proc *rip; /* Reader in progress */
|
||||
Mntrpc *queue; /* Queue of pending requests on this channel */
|
||||
ulong id; /* Multiplexer id for channel check */
|
||||
Mnt *list; /* Free list */
|
||||
int flags; /* cache */
|
||||
int msize; /* data + IOHDRSZ */
|
||||
char *version; /* 9P version */
|
||||
Queue *q; /* input queue */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
NUser, /* note provided externally */
|
||||
NExit, /* deliver note quietly */
|
||||
NDebug, /* print debug message */
|
||||
};
|
||||
|
||||
struct Note
|
||||
{
|
||||
char msg[ERRMAX];
|
||||
int flag; /* whether system posted it */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
RENDLOG = 5,
|
||||
RENDHASH = 1<<RENDLOG, /* Hash to lookup rendezvous tags */
|
||||
MNTLOG = 5,
|
||||
MNTHASH = 1<<MNTLOG, /* Hash to walk mount table */
|
||||
NFD = 100, /* per process file descriptors */
|
||||
PGHLOG = 9,
|
||||
PGHSIZE = 1<<PGHLOG, /* Page hash for image lookup */
|
||||
};
|
||||
#define REND(p,s) ((p)->rendhash[(s)&((1<<RENDLOG)-1)])
|
||||
#define MOUNTH(p,qid) ((p)->mnthash[(qid).path&((1<<MNTLOG)-1)])
|
||||
|
||||
struct Pgrp
|
||||
{
|
||||
Ref ref; /* also used as a lock when mounting */
|
||||
int noattach;
|
||||
ulong pgrpid;
|
||||
QLock debug; /* single access via devproc.c */
|
||||
RWlock ns; /* Namespace n read/one write lock */
|
||||
Mhead *mnthash[MNTHASH];
|
||||
};
|
||||
|
||||
struct Rgrp
|
||||
{
|
||||
Ref ref;
|
||||
Proc *rendhash[RENDHASH]; /* Rendezvous tag hash */
|
||||
};
|
||||
|
||||
struct Egrp
|
||||
{
|
||||
Ref ref;
|
||||
RWlock lk;
|
||||
Evalue **ent;
|
||||
int nent;
|
||||
int ment;
|
||||
ulong path; /* qid.path of next Evalue to be allocated */
|
||||
ulong vers; /* of Egrp */
|
||||
};
|
||||
|
||||
struct Evalue
|
||||
{
|
||||
char *name;
|
||||
char *value;
|
||||
int len;
|
||||
Evalue *link;
|
||||
Qid qid;
|
||||
};
|
||||
|
||||
struct Fgrp
|
||||
{
|
||||
Ref ref;
|
||||
Chan **fd;
|
||||
int nfd; /* number allocated */
|
||||
int maxfd; /* highest fd in use */
|
||||
int exceed; /* debugging */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DELTAFD = 20, /* incremental increase in Fgrp.fd's */
|
||||
NERR = 20
|
||||
};
|
||||
|
||||
typedef uvlong Ticks;
|
||||
|
||||
enum
|
||||
{
|
||||
Running,
|
||||
Rendezvous,
|
||||
Wakeme,
|
||||
};
|
||||
|
||||
struct Proc
|
||||
{
|
||||
uint state;
|
||||
uint mach;
|
||||
|
||||
ulong pid;
|
||||
ulong parentpid;
|
||||
|
||||
Pgrp *pgrp; /* Process group for namespace */
|
||||
Fgrp *fgrp; /* File descriptor group */
|
||||
Rgrp *rgrp;
|
||||
|
||||
Lock rlock; /* sync sleep/wakeup with postnote */
|
||||
Rendez *r; /* rendezvous point slept on */
|
||||
Rendez sleep; /* place for syssleep/debug */
|
||||
int notepending; /* note issued but not acted on */
|
||||
int kp; /* true if a kernel process */
|
||||
|
||||
ulong rendtag; /* Tag for rendezvous */
|
||||
ulong rendval; /* Value for rendezvous */
|
||||
Proc *rendhash; /* Hash list for tag values */
|
||||
|
||||
int nerrlab;
|
||||
Label errlab[NERR];
|
||||
char user[KNAMELEN];
|
||||
char *syserrstr; /* last error from a system call, errbuf0 or 1 */
|
||||
char *errstr; /* reason we're unwinding the error stack, errbuf1 or 0 */
|
||||
char errbuf0[ERRMAX];
|
||||
char errbuf1[ERRMAX];
|
||||
char genbuf[128]; /* buffer used e.g. for last name element from namec */
|
||||
char text[KNAMELEN];
|
||||
|
||||
Chan *slash;
|
||||
Chan *dot;
|
||||
|
||||
Proc *qnext;
|
||||
|
||||
void (*fn)(void*);
|
||||
void *arg;
|
||||
|
||||
char oproc[1024]; /* reserved for os */
|
||||
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PRINTSIZE = 256,
|
||||
MAXCRYPT = 127,
|
||||
NUMSIZE = 12, /* size of formatted number */
|
||||
MB = (1024*1024),
|
||||
READSTR = 1000, /* temporary buffer size for device reads */
|
||||
};
|
||||
|
||||
extern char* conffile;
|
||||
extern int cpuserver;
|
||||
extern Dev* devtab[];
|
||||
extern char *eve;
|
||||
extern char hostdomain[];
|
||||
extern uchar initcode[];
|
||||
extern Queue* kbdq;
|
||||
extern Queue* kprintoq;
|
||||
extern Ref noteidalloc;
|
||||
extern Palloc palloc;
|
||||
extern Queue *serialoq;
|
||||
extern char* statename[];
|
||||
extern int nsyscall;
|
||||
extern char *sysname;
|
||||
extern uint qiomaxatomic;
|
||||
extern Conf conf;
|
||||
enum
|
||||
{
|
||||
LRESPROF = 3,
|
||||
};
|
||||
|
||||
/*
|
||||
* action log
|
||||
*/
|
||||
struct Log {
|
||||
Lock lk;
|
||||
int opens;
|
||||
char* buf;
|
||||
char *end;
|
||||
char *rptr;
|
||||
int len;
|
||||
int nlog;
|
||||
int minread;
|
||||
|
||||
int logmask; /* mask of things to debug */
|
||||
|
||||
QLock readq;
|
||||
Rendez readr;
|
||||
};
|
||||
|
||||
struct Logflag {
|
||||
char* name;
|
||||
int mask;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
NCMDFIELD = 128
|
||||
};
|
||||
|
||||
struct Cmdbuf
|
||||
{
|
||||
char *buf;
|
||||
char **f;
|
||||
int nf;
|
||||
};
|
||||
|
||||
struct Cmdtab
|
||||
{
|
||||
int index; /* used by client to switch on result */
|
||||
char *cmd; /* command name */
|
||||
int narg; /* expected #args; 0 ==> variadic */
|
||||
};
|
||||
|
||||
/* queue state bits, Qmsg, Qcoalesce, and Qkick can be set in qopen */
|
||||
enum
|
||||
{
|
||||
/* Queue.state */
|
||||
Qstarve = (1<<0), /* consumer starved */
|
||||
Qmsg = (1<<1), /* message stream */
|
||||
Qclosed = (1<<2), /* queue has been closed/hungup */
|
||||
Qflow = (1<<3), /* producer flow controlled */
|
||||
Qcoalesce = (1<<4), /* coallesce packets on read */
|
||||
Qkick = (1<<5), /* always call the kick routine after qwrite */
|
||||
};
|
||||
|
||||
#define DEVDOTDOT -1
|
||||
|
||||
extern Proc *_getproc(void);
|
||||
extern void _setproc(Proc*);
|
||||
#define up (_getproc())
|
31
kern/data.c
Normal file
31
kern/data.c
Normal file
@ -0,0 +1,31 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
Proc *up;
|
||||
Conf conf =
|
||||
{
|
||||
1,
|
||||
100,
|
||||
0,
|
||||
1024*1024*1024,
|
||||
1024*1024*1024,
|
||||
1024*1024*1024,
|
||||
1024*1024*1024,
|
||||
1024*1024*1024,
|
||||
1024*1024*1024,
|
||||
1024*1024*1024,
|
||||
1024*1024*1024,
|
||||
1024*1024*1024,
|
||||
1024*1024*1024,
|
||||
1024*1024*1024,
|
||||
1024*1024*1024,
|
||||
0,
|
||||
};
|
||||
|
||||
char *eve = "eve";
|
||||
ulong kerndate;
|
||||
int cpuserver;
|
||||
char hostdomain[] = "drawterm.net";
|
468
kern/dev.c
Normal file
468
kern/dev.c
Normal file
@ -0,0 +1,468 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
extern ulong kerndate;
|
||||
|
||||
void
|
||||
mkqid(Qid *q, vlong path, ulong vers, int type)
|
||||
{
|
||||
q->type = type;
|
||||
q->vers = vers;
|
||||
q->path = path;
|
||||
}
|
||||
|
||||
int
|
||||
devno(int c, int user)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; devtab[i] != nil; i++) {
|
||||
if(devtab[i]->dc == c)
|
||||
return i;
|
||||
}
|
||||
if(user == 0)
|
||||
panic("devno %C 0x%ux", c, c);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
devdir(Chan *c, Qid qid, char *n, vlong length, char *user, long perm, Dir *db)
|
||||
{
|
||||
db->name = n;
|
||||
if(c->flag&CMSG)
|
||||
qid.type |= QTMOUNT;
|
||||
db->qid = qid;
|
||||
db->type = devtab[c->type]->dc;
|
||||
db->dev = c->dev;
|
||||
db->mode = perm;
|
||||
db->mode |= qid.type << 24;
|
||||
db->atime = seconds();
|
||||
db->mtime = kerndate;
|
||||
db->length = length;
|
||||
db->uid = user;
|
||||
db->gid = eve;
|
||||
db->muid = user;
|
||||
}
|
||||
|
||||
/*
|
||||
* (here, Devgen is the prototype; devgen is the function in dev.c.)
|
||||
*
|
||||
* a Devgen is expected to return the directory entry for ".."
|
||||
* if you pass it s==DEVDOTDOT (-1). otherwise...
|
||||
*
|
||||
* there are two contradictory rules.
|
||||
*
|
||||
* (i) if c is a directory, a Devgen is expected to list its children
|
||||
* as you iterate s.
|
||||
*
|
||||
* (ii) whether or not c is a directory, a Devgen is expected to list
|
||||
* its siblings as you iterate s.
|
||||
*
|
||||
* devgen always returns the list of children in the root
|
||||
* directory. thus it follows (i) when c is the root and (ii) otherwise.
|
||||
* many other Devgens follow (i) when c is a directory and (ii) otherwise.
|
||||
*
|
||||
* devwalk assumes (i). it knows that devgen breaks (i)
|
||||
* for children that are themselves directories, and explicitly catches them.
|
||||
*
|
||||
* devstat assumes (ii). if the Devgen in question follows (i)
|
||||
* for this particular c, devstat will not find the necessary info.
|
||||
* with our particular Devgen functions, this happens only for
|
||||
* directories, so devstat makes something up, assuming
|
||||
* c->name, c->qid, eve, DMDIR|0555.
|
||||
*
|
||||
* devdirread assumes (i). the callers have to make sure
|
||||
* that the Devgen satisfies (i) for the chan being read.
|
||||
*/
|
||||
/*
|
||||
* the zeroth element of the table MUST be the directory itself for ..
|
||||
*/
|
||||
int
|
||||
devgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
|
||||
{
|
||||
if(tab == 0)
|
||||
return -1;
|
||||
if(i == DEVDOTDOT){
|
||||
/* nothing */
|
||||
}else if(name){
|
||||
for(i=1; i<ntab; i++)
|
||||
if(strcmp(tab[i].name, name) == 0)
|
||||
break;
|
||||
if(i==ntab)
|
||||
return -1;
|
||||
tab += i;
|
||||
}else{
|
||||
/* skip over the first element, that for . itself */
|
||||
i++;
|
||||
if(i >= ntab)
|
||||
return -1;
|
||||
tab += i;
|
||||
}
|
||||
devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
devreset(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
devinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
devshutdown(void)
|
||||
{
|
||||
}
|
||||
|
||||
Chan*
|
||||
devattach(int tc, char *spec)
|
||||
{
|
||||
Chan *c;
|
||||
char *buf;
|
||||
|
||||
c = newchan();
|
||||
mkqid(&c->qid, 0, 0, QTDIR);
|
||||
c->type = devno(tc, 0);
|
||||
if(spec == nil)
|
||||
spec = "";
|
||||
buf = smalloc(4+strlen(spec)+1);
|
||||
sprint(buf, "#%C%s", tc, spec);
|
||||
c->name = newcname(buf);
|
||||
free(buf);
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
Chan*
|
||||
devclone(Chan *c)
|
||||
{
|
||||
Chan *nc;
|
||||
|
||||
if(c->flag & COPEN)
|
||||
panic("clone of open file type %C\n", devtab[c->type]->dc);
|
||||
|
||||
nc = newchan();
|
||||
|
||||
nc->type = c->type;
|
||||
nc->dev = c->dev;
|
||||
nc->mode = c->mode;
|
||||
nc->qid = c->qid;
|
||||
nc->offset = c->offset;
|
||||
nc->umh = nil;
|
||||
nc->mountid = c->mountid;
|
||||
nc->aux = c->aux;
|
||||
nc->pgrpid = c->pgrpid;
|
||||
nc->mid = c->mid;
|
||||
nc->mqid = c->mqid;
|
||||
nc->mcp = c->mcp;
|
||||
return nc;
|
||||
}
|
||||
|
||||
Walkqid*
|
||||
devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab, Devgen *gen)
|
||||
{
|
||||
int i, j, alloc;
|
||||
Walkqid *wq;
|
||||
char *n;
|
||||
Dir dir;
|
||||
|
||||
if(nname > 0)
|
||||
isdir(c);
|
||||
|
||||
alloc = 0;
|
||||
wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
|
||||
if(waserror()){
|
||||
if(alloc && wq->clone!=nil)
|
||||
cclose(wq->clone);
|
||||
free(wq);
|
||||
return nil;
|
||||
}
|
||||
if(nc == nil){
|
||||
nc = devclone(c);
|
||||
nc->type = 0; /* device doesn't know about this channel yet */
|
||||
alloc = 1;
|
||||
}
|
||||
wq->clone = nc;
|
||||
|
||||
for(j=0; j<nname; j++){
|
||||
if(!(nc->qid.type&QTDIR)){
|
||||
if(j==0)
|
||||
error(Enotdir);
|
||||
goto Done;
|
||||
}
|
||||
n = name[j];
|
||||
if(strcmp(n, ".") == 0){
|
||||
Accept:
|
||||
wq->qid[wq->nqid++] = nc->qid;
|
||||
continue;
|
||||
}
|
||||
if(strcmp(n, "..") == 0){
|
||||
if((*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir) != 1){
|
||||
print("devgen walk .. in dev%s %llux broken\n",
|
||||
devtab[nc->type]->name, nc->qid.path);
|
||||
error("broken devgen");
|
||||
}
|
||||
nc->qid = dir.qid;
|
||||
goto Accept;
|
||||
}
|
||||
/*
|
||||
* Ugly problem: If we're using devgen, make sure we're
|
||||
* walking the directory itself, represented by the first
|
||||
* entry in the table, and not trying to step into a sub-
|
||||
* directory of the table, e.g. /net/net. Devgen itself
|
||||
* should take care of the problem, but it doesn't have
|
||||
* the necessary information (that we're doing a walk).
|
||||
*/
|
||||
if(gen==devgen && nc->qid.path!=tab[0].qid.path)
|
||||
goto Notfound;
|
||||
for(i=0;; i++) {
|
||||
switch((*gen)(nc, n, tab, ntab, i, &dir)){
|
||||
case -1:
|
||||
Notfound:
|
||||
if(j == 0)
|
||||
error(Enonexist);
|
||||
kstrcpy(up->errstr, Enonexist, ERRMAX);
|
||||
goto Done;
|
||||
case 0:
|
||||
continue;
|
||||
case 1:
|
||||
if(strcmp(n, dir.name) == 0){
|
||||
nc->qid = dir.qid;
|
||||
goto Accept;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* We processed at least one name, so will return some data.
|
||||
* If we didn't process all nname entries succesfully, we drop
|
||||
* the cloned channel and return just the Qids of the walks.
|
||||
*/
|
||||
Done:
|
||||
poperror();
|
||||
if(wq->nqid < nname){
|
||||
if(alloc)
|
||||
cclose(wq->clone);
|
||||
wq->clone = nil;
|
||||
}else if(wq->clone){
|
||||
/* attach cloned channel to same device */
|
||||
wq->clone->type = c->type;
|
||||
}
|
||||
return wq;
|
||||
}
|
||||
|
||||
int
|
||||
devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen)
|
||||
{
|
||||
int i;
|
||||
Dir dir;
|
||||
char *p, *elem;
|
||||
|
||||
for(i=0;; i++)
|
||||
switch((*gen)(c, nil, tab, ntab, i, &dir)){
|
||||
case -1:
|
||||
if(c->qid.type & QTDIR){
|
||||
if(c->name == nil)
|
||||
elem = "???";
|
||||
else if(strcmp(c->name->s, "/") == 0)
|
||||
elem = "/";
|
||||
else
|
||||
for(elem=p=c->name->s; *p; p++)
|
||||
if(*p == '/')
|
||||
elem = p+1;
|
||||
devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir);
|
||||
n = convD2M(&dir, db, n);
|
||||
if(n == 0)
|
||||
error(Ebadarg);
|
||||
return n;
|
||||
}
|
||||
print("devstat %C %llux\n", devtab[c->type]->dc, c->qid.path);
|
||||
|
||||
error(Enonexist);
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
if(c->qid.path == dir.qid.path) {
|
||||
if(c->flag&CMSG)
|
||||
dir.mode |= DMMOUNT;
|
||||
n = convD2M(&dir, db, n);
|
||||
if(n == 0)
|
||||
error(Ebadarg);
|
||||
return n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
error(Egreg); /* not reached? */
|
||||
return -1;
|
||||
}
|
||||
|
||||
long
|
||||
devdirread(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen)
|
||||
{
|
||||
long m, dsz;
|
||||
struct{
|
||||
Dir d;
|
||||
char slop[100];
|
||||
}dir;
|
||||
|
||||
for(m=0; m<n; c->dri++) {
|
||||
switch((*gen)(c, nil, tab, ntab, c->dri, &dir.d)){
|
||||
case -1:
|
||||
return m;
|
||||
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
dsz = convD2M(&dir.d, (uchar*)d, n-m);
|
||||
if(dsz <= BIT16SZ){ /* <= not < because this isn't stat; read is stuck */
|
||||
if(m == 0)
|
||||
error(Eshort);
|
||||
return m;
|
||||
}
|
||||
m += dsz;
|
||||
d += dsz;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
/*
|
||||
* error(Eperm) if open permission not granted for up->user.
|
||||
*/
|
||||
void
|
||||
devpermcheck(char *fileuid, ulong perm, int omode)
|
||||
{
|
||||
ulong t;
|
||||
static int access[] = { 0400, 0200, 0600, 0100 };
|
||||
|
||||
if(strcmp(up->user, fileuid) == 0)
|
||||
perm <<= 0;
|
||||
else
|
||||
if(strcmp(up->user, eve) == 0)
|
||||
perm <<= 3;
|
||||
else
|
||||
perm <<= 6;
|
||||
|
||||
t = access[omode&3];
|
||||
if((t&perm) != t)
|
||||
error(Eperm);
|
||||
}
|
||||
|
||||
Chan*
|
||||
devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen)
|
||||
{
|
||||
int i;
|
||||
Dir dir;
|
||||
|
||||
for(i=0;; i++) {
|
||||
switch((*gen)(c, nil, tab, ntab, i, &dir)){
|
||||
case -1:
|
||||
goto Return;
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
if(c->qid.path == dir.qid.path) {
|
||||
devpermcheck(dir.uid, dir.mode, omode);
|
||||
goto Return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
Return:
|
||||
c->offset = 0;
|
||||
if((c->qid.type&QTDIR) && omode!=OREAD)
|
||||
error(Eperm);
|
||||
c->mode = openmode(omode);
|
||||
c->flag |= COPEN;
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
devcreate(Chan *c, char *name, int mode, ulong perm)
|
||||
{
|
||||
USED(c);
|
||||
USED(name);
|
||||
USED(mode);
|
||||
USED(perm);
|
||||
|
||||
error(Eperm);
|
||||
}
|
||||
|
||||
Block*
|
||||
devbread(Chan *c, long n, ulong offset)
|
||||
{
|
||||
Block *bp;
|
||||
|
||||
bp = allocb(n);
|
||||
if(bp == 0)
|
||||
error(Enomem);
|
||||
if(waserror()) {
|
||||
freeb(bp);
|
||||
nexterror();
|
||||
}
|
||||
bp->wp += devtab[c->type]->read(c, bp->wp, n, offset);
|
||||
poperror();
|
||||
return bp;
|
||||
}
|
||||
|
||||
long
|
||||
devbwrite(Chan *c, Block *bp, ulong offset)
|
||||
{
|
||||
long n;
|
||||
|
||||
if(waserror()) {
|
||||
freeb(bp);
|
||||
nexterror();
|
||||
}
|
||||
n = devtab[c->type]->write(c, bp->rp, BLEN(bp), offset);
|
||||
poperror();
|
||||
freeb(bp);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
devremove(Chan *c)
|
||||
{
|
||||
USED(c);
|
||||
error(Eperm);
|
||||
}
|
||||
|
||||
int
|
||||
devwstat(Chan *c, uchar *a, int n)
|
||||
{
|
||||
USED(c);
|
||||
USED(a);
|
||||
USED(n);
|
||||
|
||||
error(Eperm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
devpower(int a)
|
||||
{
|
||||
USED(a);
|
||||
error(Eperm);
|
||||
}
|
||||
|
||||
int
|
||||
devconfig(int a, char *b, DevConf *c)
|
||||
{
|
||||
USED(a);
|
||||
USED(b);
|
||||
USED(c);
|
||||
error(Eperm);
|
||||
return 0;
|
||||
}
|
1238
kern/devcons.c
Normal file
1238
kern/devcons.c
Normal file
File diff suppressed because it is too large
Load Diff
2100
kern/devdraw.c
Normal file
2100
kern/devdraw.c
Normal file
File diff suppressed because it is too large
Load Diff
638
kern/devfs.c
Normal file
638
kern/devfs.c
Normal file
@ -0,0 +1,638 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h> /* for remove, rename */
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef NAME_MAX
|
||||
# define NAME_MAX 256
|
||||
#endif
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
typedef struct Ufsinfo Ufsinfo;
|
||||
|
||||
enum
|
||||
{
|
||||
NUID = 256,
|
||||
NGID = 256,
|
||||
MAXPATH = 1024,
|
||||
MAXCOMP = 128
|
||||
};
|
||||
|
||||
struct Ufsinfo
|
||||
{
|
||||
int mode;
|
||||
int fd;
|
||||
int uid;
|
||||
int gid;
|
||||
DIR* dir;
|
||||
ulong offset;
|
||||
QLock oq;
|
||||
char nextname[NAME_MAX];
|
||||
};
|
||||
|
||||
char *base = "/";
|
||||
|
||||
static Qid fsqid(char*, struct stat *);
|
||||
static void fspath(Chan*, char*, char*);
|
||||
static ulong fsdirread(Chan*, uchar*, int, ulong);
|
||||
static int fsomode(int);
|
||||
|
||||
/* clumsy hack, but not worse than the Path stuff in the last one */
|
||||
static char*
|
||||
uc2name(Chan *c)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if(c->name == nil)
|
||||
return "/";
|
||||
s = c2name(c);
|
||||
if(s[0]=='#' && s[1]=='U')
|
||||
return s+2;
|
||||
return s;
|
||||
}
|
||||
|
||||
static char*
|
||||
lastelem(Chan *c)
|
||||
{
|
||||
char *s, *t;
|
||||
|
||||
s = uc2name(c);
|
||||
if((t = strrchr(s, '/')) == nil)
|
||||
return s;
|
||||
if(t[1] == 0)
|
||||
return t;
|
||||
return t+1;
|
||||
}
|
||||
|
||||
static Chan*
|
||||
fsattach(char *spec)
|
||||
{
|
||||
Chan *c;
|
||||
struct stat stbuf;
|
||||
static int devno;
|
||||
Ufsinfo *uif;
|
||||
|
||||
if(stat(base, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
c = devattach('U', spec);
|
||||
|
||||
uif = mallocz(sizeof(Ufsinfo), 1);
|
||||
uif->mode = stbuf.st_mode;
|
||||
uif->uid = stbuf.st_uid;
|
||||
uif->gid = stbuf.st_gid;
|
||||
|
||||
c->aux = uif;
|
||||
c->dev = devno++;
|
||||
c->qid.type = QTDIR;
|
||||
/*print("fsattach %s\n", c2name(c));*/
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static Chan*
|
||||
fsclone(Chan *c, Chan *nc)
|
||||
{
|
||||
Ufsinfo *uif;
|
||||
|
||||
uif = mallocz(sizeof(Ufsinfo), 1);
|
||||
*uif = *(Ufsinfo*)c->aux;
|
||||
nc->aux = uif;
|
||||
|
||||
return nc;
|
||||
}
|
||||
|
||||
static int
|
||||
fswalk1(Chan *c, char *name)
|
||||
{
|
||||
struct stat stbuf;
|
||||
char path[MAXPATH];
|
||||
Ufsinfo *uif;
|
||||
|
||||
fspath(c, name, path);
|
||||
|
||||
/*print("** fs walk '%s' -> %s\n", path, name); */
|
||||
|
||||
if(stat(path, &stbuf) < 0)
|
||||
return 0;
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
uif->mode = stbuf.st_mode;
|
||||
uif->uid = stbuf.st_uid;
|
||||
uif->gid = stbuf.st_gid;
|
||||
|
||||
c->qid = fsqid(path, &stbuf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern Cname* addelem(Cname*, char*);
|
||||
|
||||
static Walkqid*
|
||||
fswalk(Chan *c, Chan *nc, char **name, int nname)
|
||||
{
|
||||
int i;
|
||||
Cname *cname;
|
||||
Walkqid *wq;
|
||||
|
||||
if(nc != nil)
|
||||
panic("fswalk: nc != nil");
|
||||
wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
|
||||
nc = devclone(c);
|
||||
cname = c->name;
|
||||
incref(&cname->ref);
|
||||
|
||||
fsclone(c, nc);
|
||||
wq->clone = nc;
|
||||
for(i=0; i<nname; i++){
|
||||
nc->name = cname;
|
||||
if(fswalk1(nc, name[i]) == 0)
|
||||
break;
|
||||
cname = addelem(cname, name[i]);
|
||||
wq->qid[i] = nc->qid;
|
||||
}
|
||||
nc->name = nil;
|
||||
cnameclose(cname);
|
||||
if(i != nname){
|
||||
cclose(nc);
|
||||
wq->clone = nil;
|
||||
}
|
||||
wq->nqid = i;
|
||||
return wq;
|
||||
}
|
||||
|
||||
static int
|
||||
fsstat(Chan *c, uchar *buf, int n)
|
||||
{
|
||||
Dir d;
|
||||
struct stat stbuf;
|
||||
char path[MAXPATH];
|
||||
|
||||
if(n < BIT16SZ)
|
||||
error(Eshortstat);
|
||||
|
||||
fspath(c, 0, path);
|
||||
if(stat(path, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
d.name = lastelem(c);
|
||||
d.uid = "unknown";
|
||||
d.gid = "unknown";
|
||||
d.muid = "unknown";
|
||||
d.qid = c->qid;
|
||||
d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777);
|
||||
d.atime = stbuf.st_atime;
|
||||
d.mtime = stbuf.st_mtime;
|
||||
d.length = stbuf.st_size;
|
||||
d.type = 'U';
|
||||
d.dev = c->dev;
|
||||
return convD2M(&d, buf, n);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
fsopen(Chan *c, int mode)
|
||||
{
|
||||
char path[MAXPATH];
|
||||
int m, isdir;
|
||||
Ufsinfo *uif;
|
||||
|
||||
/*print("fsopen %s\n", c2name(c));*/
|
||||
m = mode & (OTRUNC|3);
|
||||
switch(m) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
case 1|16:
|
||||
break;
|
||||
case 2:
|
||||
case 0|16:
|
||||
case 2|16:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
error(Ebadarg);
|
||||
}
|
||||
|
||||
isdir = c->qid.type & QTDIR;
|
||||
|
||||
if(isdir && mode != OREAD)
|
||||
error(Eperm);
|
||||
|
||||
m = fsomode(m & 3);
|
||||
c->mode = openmode(mode);
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
fspath(c, 0, path);
|
||||
if(isdir) {
|
||||
uif->dir = opendir(path);
|
||||
if(uif->dir == 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
else {
|
||||
if(mode & OTRUNC)
|
||||
m |= O_TRUNC;
|
||||
uif->fd = open(path, m, 0666);
|
||||
|
||||
if(uif->fd < 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
uif->offset = 0;
|
||||
|
||||
c->offset = 0;
|
||||
c->flag |= COPEN;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void
|
||||
fscreate(Chan *c, char *name, int mode, ulong perm)
|
||||
{
|
||||
int fd, m;
|
||||
char path[MAXPATH];
|
||||
struct stat stbuf;
|
||||
Ufsinfo *uif;
|
||||
|
||||
m = fsomode(mode&3);
|
||||
|
||||
fspath(c, name, path);
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
if(perm & DMDIR) {
|
||||
if(m)
|
||||
error(Eperm);
|
||||
|
||||
if(mkdir(path, perm & 0777) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
fd = open(path, 0);
|
||||
if(fd >= 0) {
|
||||
chmod(path, perm & 0777);
|
||||
chown(path, uif->uid, uif->uid);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
uif->dir = opendir(path);
|
||||
if(uif->dir == 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
else {
|
||||
fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666);
|
||||
if(fd >= 0) {
|
||||
if(m != 1) {
|
||||
close(fd);
|
||||
fd = open(path, m);
|
||||
}
|
||||
chmod(path, perm & 0777);
|
||||
chown(path, uif->uid, uif->gid);
|
||||
}
|
||||
if(fd < 0)
|
||||
error(strerror(errno));
|
||||
uif->fd = fd;
|
||||
}
|
||||
|
||||
if(stat(path, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
c->qid = fsqid(path, &stbuf);
|
||||
c->offset = 0;
|
||||
c->flag |= COPEN;
|
||||
c->mode = openmode(mode);
|
||||
}
|
||||
|
||||
static void
|
||||
fsclose(Chan *c)
|
||||
{
|
||||
Ufsinfo *uif;
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
if(c->flag & COPEN) {
|
||||
if(c->qid.type & QTDIR)
|
||||
closedir(uif->dir);
|
||||
else
|
||||
close(uif->fd);
|
||||
}
|
||||
|
||||
free(uif);
|
||||
}
|
||||
|
||||
static long
|
||||
fsread(Chan *c, void *va, long n, vlong offset)
|
||||
{
|
||||
int fd, r;
|
||||
Ufsinfo *uif;
|
||||
|
||||
/*print("fsread %s\n", c2name(c));*/
|
||||
if(c->qid.type & QTDIR)
|
||||
return fsdirread(c, va, n, offset);
|
||||
|
||||
uif = c->aux;
|
||||
qlock(&uif->oq);
|
||||
if(waserror()) {
|
||||
qunlock(&uif->oq);
|
||||
nexterror();
|
||||
}
|
||||
fd = uif->fd;
|
||||
if(uif->offset != offset) {
|
||||
r = lseek(fd, offset, 0);
|
||||
if(r < 0)
|
||||
error(strerror(errno));
|
||||
uif->offset = offset;
|
||||
}
|
||||
|
||||
n = read(fd, va, n);
|
||||
if(n < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif->offset += n;
|
||||
qunlock(&uif->oq);
|
||||
poperror();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static long
|
||||
fswrite(Chan *c, void *va, long n, vlong offset)
|
||||
{
|
||||
int fd, r;
|
||||
Ufsinfo *uif;
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
qlock(&uif->oq);
|
||||
if(waserror()) {
|
||||
qunlock(&uif->oq);
|
||||
nexterror();
|
||||
}
|
||||
fd = uif->fd;
|
||||
if(uif->offset != offset) {
|
||||
r = lseek(fd, offset, 0);
|
||||
if(r < 0)
|
||||
error(strerror(errno));
|
||||
uif->offset = offset;
|
||||
}
|
||||
|
||||
n = write(fd, va, n);
|
||||
if(n < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif->offset += n;
|
||||
qunlock(&uif->oq);
|
||||
poperror();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
fsremove(Chan *c)
|
||||
{
|
||||
int n;
|
||||
char path[MAXPATH];
|
||||
|
||||
fspath(c, 0, path);
|
||||
if(c->qid.type & QTDIR)
|
||||
n = rmdir(path);
|
||||
else
|
||||
n = remove(path);
|
||||
if(n < 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
|
||||
int
|
||||
fswstat(Chan *c, uchar *buf, int n)
|
||||
{
|
||||
Dir d;
|
||||
struct stat stbuf;
|
||||
char old[MAXPATH], new[MAXPATH], dir[MAXPATH];
|
||||
char strs[MAXPATH*3], *p;
|
||||
Ufsinfo *uif;
|
||||
|
||||
if(convM2D(buf, n, &d, strs) != n)
|
||||
error(Ebadstat);
|
||||
|
||||
fspath(c, 0, old);
|
||||
if(stat(old, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) {
|
||||
fspath(c, 0, old);
|
||||
strcpy(new, old);
|
||||
p = strrchr(new, '/');
|
||||
strcpy(p+1, d.name);
|
||||
if(rename(old, new) < 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
|
||||
fspath(c, 0, old);
|
||||
if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
|
||||
if(chmod(old, d.mode&0777) < 0)
|
||||
error(strerror(errno));
|
||||
uif->mode &= ~0777;
|
||||
uif->mode |= d.mode&0777;
|
||||
}
|
||||
/*
|
||||
p = name2pass(gid, d.gid);
|
||||
if(p == 0)
|
||||
error(Eunknown);
|
||||
|
||||
if(p->id != stbuf.st_gid) {
|
||||
if(chown(old, stbuf.st_uid, p->id) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif->gid = p->id;
|
||||
}
|
||||
*/
|
||||
return n;
|
||||
}
|
||||
|
||||
static Qid
|
||||
fsqid(char *p, struct stat *st)
|
||||
{
|
||||
Qid q;
|
||||
int dev;
|
||||
ulong h;
|
||||
static int nqdev;
|
||||
static uchar *qdev;
|
||||
|
||||
if(qdev == 0)
|
||||
qdev = mallocz(65536U, 1);
|
||||
|
||||
q.type = 0;
|
||||
if((st->st_mode&S_IFMT) == S_IFDIR)
|
||||
q.type = QTDIR;
|
||||
|
||||
dev = st->st_dev & 0xFFFFUL;
|
||||
if(qdev[dev] == 0)
|
||||
qdev[dev] = ++nqdev;
|
||||
|
||||
h = 0;
|
||||
while(*p != '\0')
|
||||
h += *p++ * 13;
|
||||
|
||||
q.path = (vlong)qdev[dev]<<32;
|
||||
q.path |= h;
|
||||
q.vers = st->st_mtime;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
static void
|
||||
fspath(Chan *c, char *ext, char *path)
|
||||
{
|
||||
int i, n;
|
||||
char *comp[MAXCOMP];
|
||||
|
||||
strcpy(path, base);
|
||||
strcat(path, "/");
|
||||
strcat(path, uc2name(c));
|
||||
if(ext){
|
||||
strcat(path, "/");
|
||||
strcat(path, ext);
|
||||
}
|
||||
cleanname(path);
|
||||
}
|
||||
|
||||
static int
|
||||
isdots(char *name)
|
||||
{
|
||||
if(name[0] != '.')
|
||||
return 0;
|
||||
if(name[1] == '\0')
|
||||
return 1;
|
||||
if(name[1] != '.')
|
||||
return 0;
|
||||
if(name[2] == '\0')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
p9readdir(char *name, Ufsinfo *uif)
|
||||
{
|
||||
struct dirent *de;
|
||||
|
||||
if(uif->nextname[0]){
|
||||
strcpy(name, uif->nextname);
|
||||
uif->nextname[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
de = readdir(uif->dir);
|
||||
if(de == NULL)
|
||||
return 0;
|
||||
|
||||
strcpy(name, de->d_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ulong
|
||||
fsdirread(Chan *c, uchar *va, int count, ulong offset)
|
||||
{
|
||||
int i;
|
||||
Dir d;
|
||||
long n;
|
||||
char de[NAME_MAX];
|
||||
struct stat stbuf;
|
||||
char path[MAXPATH], dirpath[MAXPATH];
|
||||
Ufsinfo *uif;
|
||||
|
||||
/*print("fsdirread %s\n", c2name(c));*/
|
||||
i = 0;
|
||||
uif = c->aux;
|
||||
|
||||
errno = 0;
|
||||
if(uif->offset != offset) {
|
||||
if(offset != 0)
|
||||
error("bad offset in fsdirread");
|
||||
uif->offset = offset; /* sync offset */
|
||||
uif->nextname[0] = 0;
|
||||
rewinddir(uif->dir);
|
||||
}
|
||||
|
||||
fspath(c, 0, dirpath);
|
||||
|
||||
while(i+BIT16SZ < count) {
|
||||
if(!p9readdir(de, uif))
|
||||
break;
|
||||
|
||||
if(de[0]==0 || isdots(de))
|
||||
continue;
|
||||
|
||||
d.name = de;
|
||||
sprint(path, "%s/%s", dirpath, de);
|
||||
memset(&stbuf, 0, sizeof stbuf);
|
||||
|
||||
if(stat(path, &stbuf) < 0) {
|
||||
print("dir: bad path %s\n", path);
|
||||
/* but continue... probably a bad symlink */
|
||||
}
|
||||
|
||||
d.uid = "unknown";
|
||||
d.gid = "unknown";
|
||||
d.qid = fsqid(path, &stbuf);
|
||||
d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777);
|
||||
d.atime = stbuf.st_atime;
|
||||
d.mtime = stbuf.st_mtime;
|
||||
d.length = stbuf.st_size;
|
||||
d.type = 'U';
|
||||
d.dev = c->dev;
|
||||
n = convD2M(&d, (char*)va+i, count-i);
|
||||
if(n == BIT16SZ){
|
||||
strcpy(uif->nextname, de);
|
||||
break;
|
||||
}
|
||||
i += n;
|
||||
}
|
||||
/*print("got %d\n", i);*/
|
||||
uif->offset += i;
|
||||
return i;
|
||||
}
|
||||
|
||||
static int
|
||||
fsomode(int m)
|
||||
{
|
||||
switch(m) {
|
||||
case 0: /* OREAD */
|
||||
case 3: /* OEXEC */
|
||||
return 0;
|
||||
case 1: /* OWRITE */
|
||||
return 1;
|
||||
case 2: /* ORDWR */
|
||||
return 2;
|
||||
}
|
||||
error(Ebadarg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Dev fsdevtab = {
|
||||
'U',
|
||||
"fs",
|
||||
|
||||
devreset,
|
||||
devinit,
|
||||
devshutdown,
|
||||
fsattach,
|
||||
fswalk,
|
||||
fsstat,
|
||||
fsopen,
|
||||
fscreate,
|
||||
fsclose,
|
||||
fsread,
|
||||
devbread,
|
||||
fswrite,
|
||||
devbwrite,
|
||||
fsremove,
|
||||
fswstat,
|
||||
};
|
209
kern/devip-posix.c
Normal file
209
kern/devip-posix.c
Normal file
@ -0,0 +1,209 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "devip.h"
|
||||
|
||||
#undef listen
|
||||
#undef accept
|
||||
#undef bind
|
||||
|
||||
void
|
||||
osipinit(void)
|
||||
{
|
||||
char buf[1024];
|
||||
gethostname(buf, sizeof(buf));
|
||||
kstrdup(&sysname, buf);
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
so_socket(int type)
|
||||
{
|
||||
int fd, one;
|
||||
|
||||
switch(type) {
|
||||
default:
|
||||
error("bad protocol type");
|
||||
case S_TCP:
|
||||
type = SOCK_STREAM;
|
||||
break;
|
||||
case S_UDP:
|
||||
type = SOCK_DGRAM;
|
||||
break;
|
||||
}
|
||||
|
||||
fd = socket(AF_INET, type, 0);
|
||||
if(fd < 0)
|
||||
oserror();
|
||||
|
||||
one = 1;
|
||||
if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0){
|
||||
oserrstr();
|
||||
print("setsockopt: %r");
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
so_connect(int fd, unsigned long raddr, unsigned short rport)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
hnputs(&sin.sin_port, rport);
|
||||
hnputl(&sin.sin_addr.s_addr, raddr);
|
||||
|
||||
if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
|
||||
oserror();
|
||||
}
|
||||
|
||||
void
|
||||
so_getsockname(int fd, unsigned long *laddr, unsigned short *lport)
|
||||
{
|
||||
int len;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
len = sizeof(sin);
|
||||
if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0)
|
||||
oserror();
|
||||
|
||||
if(sin.sin_family != AF_INET || len != sizeof(sin))
|
||||
error("not AF_INET");
|
||||
|
||||
*laddr = nhgetl(&sin.sin_addr.s_addr);
|
||||
*lport = nhgets(&sin.sin_port);
|
||||
}
|
||||
|
||||
void
|
||||
so_listen(int fd)
|
||||
{
|
||||
if(listen(fd, 5) < 0)
|
||||
oserror();
|
||||
}
|
||||
|
||||
int
|
||||
so_accept(int fd, unsigned long *raddr, unsigned short *rport)
|
||||
{
|
||||
int nfd, len;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
len = sizeof(sin);
|
||||
nfd = accept(fd, (struct sockaddr*)&sin, &len);
|
||||
if(nfd < 0)
|
||||
oserror();
|
||||
|
||||
if(sin.sin_family != AF_INET || len != sizeof(sin))
|
||||
error("not AF_INET");
|
||||
|
||||
*raddr = nhgetl(&sin.sin_addr.s_addr);
|
||||
*rport = nhgets(&sin.sin_port);
|
||||
return nfd;
|
||||
}
|
||||
|
||||
void
|
||||
so_bind(int fd, int su, unsigned short port)
|
||||
{
|
||||
int i, one;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
one = 1;
|
||||
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0){
|
||||
oserrstr();
|
||||
print("setsockopt: %r");
|
||||
}
|
||||
|
||||
if(su) {
|
||||
for(i = 600; i < 1024; i++) {
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = i;
|
||||
|
||||
if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0)
|
||||
return;
|
||||
}
|
||||
oserror();
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
hnputs(&sin.sin_port, port);
|
||||
|
||||
if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
|
||||
oserror();
|
||||
}
|
||||
|
||||
int
|
||||
so_gethostbyname(char *host, char**hostv, int n)
|
||||
{
|
||||
int i;
|
||||
char buf[32];
|
||||
unsigned char *p;
|
||||
struct hostent *hp;
|
||||
|
||||
hp = gethostbyname(host);
|
||||
if(hp == 0)
|
||||
return 0;
|
||||
|
||||
for(i = 0; hp->h_addr_list[i] && i < n; i++) {
|
||||
p = (unsigned char*)hp->h_addr_list[i];
|
||||
sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
|
||||
hostv[i] = strdup(buf);
|
||||
if(hostv[i] == 0)
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
char*
|
||||
hostlookup(char *host)
|
||||
{
|
||||
char buf[100];
|
||||
uchar *p;
|
||||
struct hostent *he;
|
||||
|
||||
he = gethostbyname(host);
|
||||
if(he != 0 && he->h_addr_list[0]) {
|
||||
p = (uchar*)he->h_addr_list[0];
|
||||
sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]);
|
||||
} else
|
||||
strcpy(buf, host);
|
||||
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
int
|
||||
so_getservbyname(char *service, char *net, char *port)
|
||||
{
|
||||
struct servent *s;
|
||||
|
||||
s = getservbyname(service, net);
|
||||
if(s == 0)
|
||||
return -1;
|
||||
|
||||
sprint(port, "%d", nhgets(&s->s_port));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
so_send(int fd, void *d, int n, int f)
|
||||
{
|
||||
send(fd, d, n, f);
|
||||
}
|
||||
|
||||
int
|
||||
so_recv(int fd, void *d, int n, int f)
|
||||
{
|
||||
return recv(fd, d, n, f);
|
||||
}
|
208
kern/devip-win.c
Normal file
208
kern/devip-win.c
Normal file
@ -0,0 +1,208 @@
|
||||
#include <windows.h>
|
||||
#include "winduhz.h"
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "devip.h"
|
||||
|
||||
#pragma comment(lib, "wsock32.lib")
|
||||
|
||||
#undef listen
|
||||
#undef accept
|
||||
#undef bind
|
||||
|
||||
void
|
||||
osipinit(void)
|
||||
{
|
||||
WSADATA wasdat;
|
||||
char buf[1024];
|
||||
|
||||
if(WSAStartup(MAKEWORD(1, 1), &wasdat) != 0)
|
||||
panic("no winsock.dll");
|
||||
|
||||
gethostname(buf, sizeof(buf));
|
||||
kstrdup(&sysname, buf);
|
||||
}
|
||||
|
||||
int
|
||||
so_socket(int type)
|
||||
{
|
||||
int fd, one;
|
||||
|
||||
switch(type) {
|
||||
default:
|
||||
error("bad protocol type");
|
||||
case S_TCP:
|
||||
type = SOCK_STREAM;
|
||||
break;
|
||||
case S_UDP:
|
||||
type = SOCK_DGRAM;
|
||||
break;
|
||||
}
|
||||
|
||||
fd = socket(AF_INET, type, 0);
|
||||
if(fd < 0)
|
||||
error(sys_errlist[errno]);
|
||||
|
||||
one = 1;
|
||||
if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0)
|
||||
print("setsockopt: %s", sys_errlist[errno]);
|
||||
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
so_connect(int fd, unsigned long raddr, unsigned short rport)
|
||||
{
|
||||
struct sockaddr_in sin;
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
hnputs(&sin.sin_port, rport);
|
||||
hnputl(&sin.sin_addr.s_addr, raddr);
|
||||
|
||||
if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
|
||||
error(sys_errlist[errno]);
|
||||
}
|
||||
|
||||
void
|
||||
so_getsockname(int fd, unsigned long *laddr, unsigned short *lport)
|
||||
{
|
||||
int len;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
len = sizeof(sin);
|
||||
if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0)
|
||||
error(sys_errlist[errno]);
|
||||
|
||||
if(sin.sin_family != AF_INET || len != sizeof(sin))
|
||||
error("not AF_INET");
|
||||
|
||||
*laddr = nhgetl(&sin.sin_addr.s_addr);
|
||||
*lport = nhgets(&sin.sin_port);
|
||||
}
|
||||
|
||||
void
|
||||
so_listen(int fd)
|
||||
{
|
||||
if(listen(fd, 5) < 0)
|
||||
error(sys_errlist[errno]);
|
||||
}
|
||||
|
||||
int
|
||||
so_accept(int fd, unsigned long *raddr, unsigned short *rport)
|
||||
{
|
||||
int nfd, len;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
len = sizeof(sin);
|
||||
nfd = accept(fd, (struct sockaddr*)&sin, &len);
|
||||
if(nfd < 0)
|
||||
error(sys_errlist[errno]);
|
||||
|
||||
if(sin.sin_family != AF_INET || len != sizeof(sin))
|
||||
error("not AF_INET");
|
||||
|
||||
*raddr = nhgetl(&sin.sin_addr.s_addr);
|
||||
*rport = nhgets(&sin.sin_port);
|
||||
return nfd;
|
||||
}
|
||||
|
||||
void
|
||||
so_bind(int fd, int su, unsigned short port)
|
||||
{
|
||||
int i, one;
|
||||
struct sockaddr_in sin;
|
||||
|
||||
one = 1;
|
||||
if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0)
|
||||
print("setsockopt: %s", sys_errlist[errno]);
|
||||
|
||||
if(su) {
|
||||
for(i = 600; i < 1024; i++) {
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
sin.sin_port = i;
|
||||
|
||||
if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0)
|
||||
return;
|
||||
}
|
||||
error(sys_errlist[errno]);
|
||||
}
|
||||
|
||||
memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
hnputs(&sin.sin_port, port);
|
||||
|
||||
if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
|
||||
error(sys_errlist[errno]);
|
||||
}
|
||||
|
||||
int
|
||||
so_gethostbyname(char *host, char**hostv, int n)
|
||||
{
|
||||
int i;
|
||||
char buf[32];
|
||||
unsigned char *p;
|
||||
struct hostent *hp;
|
||||
|
||||
hp = gethostbyname(host);
|
||||
if(hp == 0)
|
||||
return 0;
|
||||
|
||||
for(i = 0; hp->h_addr_list[i] && i < n; i++) {
|
||||
p = (unsigned char*)hp->h_addr_list[i];
|
||||
sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
|
||||
hostv[i] = strdup(buf);
|
||||
if(hostv[i] == 0)
|
||||
break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
char*
|
||||
hostlookup(char *host)
|
||||
{
|
||||
char buf[100];
|
||||
uchar *p;
|
||||
HOSTENT *he;
|
||||
|
||||
he = gethostbyname(host);
|
||||
if(he != 0 && he->h_addr_list[0]) {
|
||||
p = he->h_addr_list[0];
|
||||
sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]);
|
||||
} else
|
||||
strcpy(buf, host);
|
||||
|
||||
return strdup(buf);
|
||||
}
|
||||
|
||||
int
|
||||
so_getservbyname(char *service, char *net, char *port)
|
||||
{
|
||||
struct servent *s;
|
||||
|
||||
s = getservbyname(service, net);
|
||||
if(s == 0)
|
||||
return -1;
|
||||
|
||||
sprint(port, "%d", nhgets(&s->s_port));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
so_send(int fd, void *d, int n, int f)
|
||||
{
|
||||
return send(fd, d, n, f);
|
||||
}
|
||||
|
||||
int
|
||||
so_recv(int fd, void *d, int n, int f)
|
||||
{
|
||||
return recv(fd, d, n, f);
|
||||
}
|
936
kern/devip.c
Normal file
936
kern/devip.c
Normal file
@ -0,0 +1,936 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "devip.h"
|
||||
|
||||
void hnputl(void *p, unsigned long v);
|
||||
void hnputs(void *p, unsigned short v);
|
||||
unsigned long nhgetl(void *p);
|
||||
unsigned short nhgets(void *p);
|
||||
unsigned long parseip(char *to, char *from);
|
||||
void csclose(Chan*);
|
||||
long csread(Chan*, void*, long, vlong);
|
||||
long cswrite(Chan*, void*, long, vlong);
|
||||
|
||||
void osipinit(void);
|
||||
|
||||
enum
|
||||
{
|
||||
Qtopdir = 1, /* top level directory */
|
||||
Qcs,
|
||||
Qprotodir, /* directory for a protocol */
|
||||
Qclonus,
|
||||
Qconvdir, /* directory for a conversation */
|
||||
Qdata,
|
||||
Qctl,
|
||||
Qstatus,
|
||||
Qremote,
|
||||
Qlocal,
|
||||
Qlisten,
|
||||
|
||||
MAXPROTO = 4
|
||||
};
|
||||
#define TYPE(x) ((int)((x).path & 0xf))
|
||||
#define CONV(x) ((int)(((x).path >> 4)&0xfff))
|
||||
#define PROTO(x) ((int)(((x).path >> 16)&0xff))
|
||||
#define QID(p, c, y) (((p)<<16) | ((c)<<4) | (y))
|
||||
|
||||
typedef struct Proto Proto;
|
||||
typedef struct Conv Conv;
|
||||
struct Conv
|
||||
{
|
||||
int x;
|
||||
Ref r;
|
||||
int sfd;
|
||||
int perm;
|
||||
char owner[KNAMELEN];
|
||||
char* state;
|
||||
ulong laddr;
|
||||
ushort lport;
|
||||
ulong raddr;
|
||||
ushort rport;
|
||||
int restricted;
|
||||
char cerr[KNAMELEN];
|
||||
Proto* p;
|
||||
};
|
||||
|
||||
struct Proto
|
||||
{
|
||||
Lock l;
|
||||
int x;
|
||||
int stype;
|
||||
char name[KNAMELEN];
|
||||
int nc;
|
||||
int maxconv;
|
||||
Conv** conv;
|
||||
Qid qid;
|
||||
};
|
||||
|
||||
static int np;
|
||||
static Proto proto[MAXPROTO];
|
||||
int eipfmt(Fmt*);
|
||||
|
||||
static Conv* protoclone(Proto*, char*, int);
|
||||
static void setladdr(Conv*);
|
||||
|
||||
int
|
||||
ipgen(Chan *c, char *nname, Dirtab *d, int nd, int s, Dir *dp)
|
||||
{
|
||||
Qid q;
|
||||
Conv *cv;
|
||||
char *p;
|
||||
|
||||
USED(nname);
|
||||
q.vers = 0;
|
||||
q.type = 0;
|
||||
switch(TYPE(c->qid)) {
|
||||
case Qtopdir:
|
||||
if(s >= 1+np)
|
||||
return -1;
|
||||
|
||||
if(s == 0){
|
||||
q.path = QID(s, 0, Qcs);
|
||||
devdir(c, q, "cs", 0, "network", 0666, dp);
|
||||
}else{
|
||||
s--;
|
||||
q.path = QID(s, 0, Qprotodir);
|
||||
q.type = QTDIR;
|
||||
devdir(c, q, proto[s].name, 0, "network", DMDIR|0555, dp);
|
||||
}
|
||||
return 1;
|
||||
case Qprotodir:
|
||||
if(s < proto[PROTO(c->qid)].nc) {
|
||||
cv = proto[PROTO(c->qid)].conv[s];
|
||||
sprint(up->genbuf, "%d", s);
|
||||
q.path = QID(PROTO(c->qid), s, Qconvdir);
|
||||
q.type = QTDIR;
|
||||
devdir(c, q, up->genbuf, 0, cv->owner, DMDIR|0555, dp);
|
||||
return 1;
|
||||
}
|
||||
s -= proto[PROTO(c->qid)].nc;
|
||||
switch(s) {
|
||||
default:
|
||||
return -1;
|
||||
case 0:
|
||||
p = "clone";
|
||||
q.path = QID(PROTO(c->qid), 0, Qclonus);
|
||||
break;
|
||||
}
|
||||
devdir(c, q, p, 0, "network", 0555, dp);
|
||||
return 1;
|
||||
case Qconvdir:
|
||||
cv = proto[PROTO(c->qid)].conv[CONV(c->qid)];
|
||||
switch(s) {
|
||||
default:
|
||||
return -1;
|
||||
case 0:
|
||||
q.path = QID(PROTO(c->qid), CONV(c->qid), Qdata);
|
||||
devdir(c, q, "data", 0, cv->owner, cv->perm, dp);
|
||||
return 1;
|
||||
case 1:
|
||||
q.path = QID(PROTO(c->qid), CONV(c->qid), Qctl);
|
||||
devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp);
|
||||
return 1;
|
||||
case 2:
|
||||
p = "status";
|
||||
q.path = QID(PROTO(c->qid), CONV(c->qid), Qstatus);
|
||||
break;
|
||||
case 3:
|
||||
p = "remote";
|
||||
q.path = QID(PROTO(c->qid), CONV(c->qid), Qremote);
|
||||
break;
|
||||
case 4:
|
||||
p = "local";
|
||||
q.path = QID(PROTO(c->qid), CONV(c->qid), Qlocal);
|
||||
break;
|
||||
case 5:
|
||||
p = "listen";
|
||||
q.path = QID(PROTO(c->qid), CONV(c->qid), Qlisten);
|
||||
break;
|
||||
}
|
||||
devdir(c, q, p, 0, cv->owner, 0444, dp);
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
newproto(char *name, int type, int maxconv)
|
||||
{
|
||||
int l;
|
||||
Proto *p;
|
||||
|
||||
if(np >= MAXPROTO) {
|
||||
print("no %s: increase MAXPROTO", name);
|
||||
return;
|
||||
}
|
||||
|
||||
p = &proto[np];
|
||||
strcpy(p->name, name);
|
||||
p->stype = type;
|
||||
p->qid.path = QID(np, 0, Qprotodir);
|
||||
p->qid.type = QTDIR;
|
||||
p->x = np++;
|
||||
p->maxconv = maxconv;
|
||||
l = sizeof(Conv*)*(p->maxconv+1);
|
||||
p->conv = mallocz(l, 1);
|
||||
if(p->conv == 0)
|
||||
panic("no memory");
|
||||
}
|
||||
|
||||
void
|
||||
ipinit(void)
|
||||
{
|
||||
osipinit();
|
||||
|
||||
newproto("udp", S_UDP, 10);
|
||||
newproto("tcp", S_TCP, 30);
|
||||
|
||||
fmtinstall('I', eipfmt);
|
||||
fmtinstall('E', eipfmt);
|
||||
|
||||
}
|
||||
|
||||
Chan *
|
||||
ipattach(char *spec)
|
||||
{
|
||||
Chan *c;
|
||||
|
||||
c = devattach('I', spec);
|
||||
c->qid.path = QID(0, 0, Qtopdir);
|
||||
c->qid.type = QTDIR;
|
||||
c->qid.vers = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
static Walkqid*
|
||||
ipwalk(Chan *c, Chan *nc, char **name, int nname)
|
||||
{
|
||||
return devwalk(c, nc, name, nname, 0, 0, ipgen);
|
||||
}
|
||||
|
||||
int
|
||||
ipstat(Chan *c, uchar *dp, int n)
|
||||
{
|
||||
return devstat(c, dp, n, 0, 0, ipgen);
|
||||
}
|
||||
|
||||
Chan *
|
||||
ipopen(Chan *c, int omode)
|
||||
{
|
||||
Proto *p;
|
||||
ulong raddr;
|
||||
ushort rport;
|
||||
int perm, sfd;
|
||||
Conv *cv, *lcv;
|
||||
|
||||
omode &= 3;
|
||||
switch(omode) {
|
||||
case OREAD:
|
||||
perm = 4;
|
||||
break;
|
||||
case OWRITE:
|
||||
perm = 2;
|
||||
break;
|
||||
case ORDWR:
|
||||
perm = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
switch(TYPE(c->qid)) {
|
||||
default:
|
||||
break;
|
||||
case Qtopdir:
|
||||
case Qprotodir:
|
||||
case Qconvdir:
|
||||
case Qstatus:
|
||||
case Qremote:
|
||||
case Qlocal:
|
||||
if(omode != OREAD)
|
||||
error(Eperm);
|
||||
break;
|
||||
case Qclonus:
|
||||
p = &proto[PROTO(c->qid)];
|
||||
cv = protoclone(p, up->user, -1);
|
||||
if(cv == 0)
|
||||
error(Enodev);
|
||||
c->qid.path = QID(p->x, cv->x, Qctl);
|
||||
c->qid.vers = 0;
|
||||
break;
|
||||
case Qdata:
|
||||
case Qctl:
|
||||
p = &proto[PROTO(c->qid)];
|
||||
lock(&p->l);
|
||||
cv = p->conv[CONV(c->qid)];
|
||||
lock(&cv->r.lk);
|
||||
if((perm & (cv->perm>>6)) != perm) {
|
||||
if(strcmp(up->user, cv->owner) != 0 ||
|
||||
(perm & cv->perm) != perm) {
|
||||
unlock(&cv->r.lk);
|
||||
unlock(&p->l);
|
||||
error(Eperm);
|
||||
}
|
||||
}
|
||||
cv->r.ref++;
|
||||
if(cv->r.ref == 1) {
|
||||
memmove(cv->owner, up->user, KNAMELEN);
|
||||
cv->perm = 0660;
|
||||
}
|
||||
unlock(&cv->r.lk);
|
||||
unlock(&p->l);
|
||||
break;
|
||||
case Qlisten:
|
||||
p = &proto[PROTO(c->qid)];
|
||||
lcv = p->conv[CONV(c->qid)];
|
||||
sfd = so_accept(lcv->sfd, &raddr, &rport);
|
||||
cv = protoclone(p, up->user, sfd);
|
||||
if(cv == 0) {
|
||||
close(sfd);
|
||||
error(Enodev);
|
||||
}
|
||||
cv->raddr = raddr;
|
||||
cv->rport = rport;
|
||||
setladdr(cv);
|
||||
cv->state = "Established";
|
||||
c->qid.path = QID(p->x, cv->x, Qctl);
|
||||
break;
|
||||
}
|
||||
c->mode = openmode(omode);
|
||||
c->flag |= COPEN;
|
||||
c->offset = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
ipclose(Chan *c)
|
||||
{
|
||||
Conv *cc;
|
||||
|
||||
switch(TYPE(c->qid)) {
|
||||
case Qcs:
|
||||
csclose(c);
|
||||
break;
|
||||
case Qdata:
|
||||
case Qctl:
|
||||
if((c->flag & COPEN) == 0)
|
||||
break;
|
||||
cc = proto[PROTO(c->qid)].conv[CONV(c->qid)];
|
||||
if(decref(&cc->r) != 0)
|
||||
break;
|
||||
strcpy(cc->owner, "network");
|
||||
cc->perm = 0666;
|
||||
cc->state = "Closed";
|
||||
cc->laddr = 0;
|
||||
cc->raddr = 0;
|
||||
cc->lport = 0;
|
||||
cc->rport = 0;
|
||||
close(cc->sfd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
long
|
||||
ipread(Chan *ch, void *a, long n, vlong offset)
|
||||
{
|
||||
int r;
|
||||
Conv *c;
|
||||
Proto *x;
|
||||
uchar ip[4];
|
||||
char buf[128], *p;
|
||||
|
||||
/*print("ipread %s %lux\n", c2name(ch), (long)ch->qid.path);*/
|
||||
p = a;
|
||||
switch(TYPE(ch->qid)) {
|
||||
default:
|
||||
error(Eperm);
|
||||
case Qcs:
|
||||
return csread(ch, a, n, offset);
|
||||
case Qprotodir:
|
||||
case Qtopdir:
|
||||
case Qconvdir:
|
||||
return devdirread(ch, a, n, 0, 0, ipgen);
|
||||
case Qctl:
|
||||
sprint(buf, "%d", CONV(ch->qid));
|
||||
return readstr(offset, p, n, buf);
|
||||
case Qremote:
|
||||
c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
|
||||
hnputl(ip, c->raddr);
|
||||
sprint(buf, "%I!%d\n", ip, c->rport);
|
||||
return readstr(offset, p, n, buf);
|
||||
case Qlocal:
|
||||
c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
|
||||
hnputl(ip, c->laddr);
|
||||
sprint(buf, "%I!%d\n", ip, c->lport);
|
||||
return readstr(offset, p, n, buf);
|
||||
case Qstatus:
|
||||
x = &proto[PROTO(ch->qid)];
|
||||
c = x->conv[CONV(ch->qid)];
|
||||
sprint(buf, "%s/%d %d %s \n",
|
||||
c->p->name, c->x, c->r.ref, c->state);
|
||||
return readstr(offset, p, n, buf);
|
||||
case Qdata:
|
||||
c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
|
||||
r = so_recv(c->sfd, a, n, 0);
|
||||
if(r < 0){
|
||||
oserrstr();
|
||||
nexterror();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setladdr(Conv *c)
|
||||
{
|
||||
so_getsockname(c->sfd, &c->laddr, &c->lport);
|
||||
}
|
||||
|
||||
static void
|
||||
setlport(Conv *c)
|
||||
{
|
||||
if(c->restricted == 0 && c->lport == 0)
|
||||
return;
|
||||
|
||||
so_bind(c->sfd, c->restricted, c->lport);
|
||||
}
|
||||
|
||||
static void
|
||||
setladdrport(Conv *c, char *str)
|
||||
{
|
||||
char *p, addr[4];
|
||||
|
||||
p = strchr(str, '!');
|
||||
if(p == 0) {
|
||||
p = str;
|
||||
c->laddr = 0;
|
||||
}
|
||||
else {
|
||||
*p++ = 0;
|
||||
parseip(addr, str);
|
||||
c->laddr = nhgetl((uchar*)addr);
|
||||
}
|
||||
if(*p == '*')
|
||||
c->lport = 0;
|
||||
else
|
||||
c->lport = atoi(p);
|
||||
|
||||
setlport(c);
|
||||
}
|
||||
|
||||
static char*
|
||||
setraddrport(Conv *c, char *str)
|
||||
{
|
||||
char *p, addr[4];
|
||||
|
||||
p = strchr(str, '!');
|
||||
if(p == 0)
|
||||
return "malformed address";
|
||||
*p++ = 0;
|
||||
parseip(addr, str);
|
||||
c->raddr = nhgetl((uchar*)addr);
|
||||
c->rport = atoi(p);
|
||||
p = strchr(p, '!');
|
||||
if(p) {
|
||||
if(strcmp(p, "!r") == 0)
|
||||
c->restricted = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
ipwrite(Chan *ch, void *a, long n, vlong offset)
|
||||
{
|
||||
Conv *c;
|
||||
Proto *x;
|
||||
int r, nf;
|
||||
char *p, *fields[3], buf[128];
|
||||
|
||||
switch(TYPE(ch->qid)) {
|
||||
default:
|
||||
error(Eperm);
|
||||
case Qcs:
|
||||
return cswrite(ch, a, n, offset);
|
||||
case Qctl:
|
||||
x = &proto[PROTO(ch->qid)];
|
||||
c = x->conv[CONV(ch->qid)];
|
||||
if(n > sizeof(buf)-1)
|
||||
n = sizeof(buf)-1;
|
||||
memmove(buf, a, n);
|
||||
buf[n] = '\0';
|
||||
|
||||
nf = tokenize(buf, fields, 3);
|
||||
if(strcmp(fields[0], "connect") == 0){
|
||||
switch(nf) {
|
||||
default:
|
||||
error("bad args to connect");
|
||||
case 2:
|
||||
p = setraddrport(c, fields[1]);
|
||||
if(p != 0)
|
||||
error(p);
|
||||
break;
|
||||
case 3:
|
||||
p = setraddrport(c, fields[1]);
|
||||
if(p != 0)
|
||||
error(p);
|
||||
c->lport = atoi(fields[2]);
|
||||
setlport(c);
|
||||
break;
|
||||
}
|
||||
so_connect(c->sfd, c->raddr, c->rport);
|
||||
setladdr(c);
|
||||
c->state = "Established";
|
||||
return n;
|
||||
}
|
||||
if(strcmp(fields[0], "announce") == 0) {
|
||||
switch(nf){
|
||||
default:
|
||||
error("bad args to announce");
|
||||
case 2:
|
||||
setladdrport(c, fields[1]);
|
||||
break;
|
||||
}
|
||||
so_listen(c->sfd);
|
||||
c->state = "Announced";
|
||||
return n;
|
||||
}
|
||||
if(strcmp(fields[0], "bind") == 0){
|
||||
switch(nf){
|
||||
default:
|
||||
error("bad args to bind");
|
||||
case 2:
|
||||
c->lport = atoi(fields[1]);
|
||||
break;
|
||||
}
|
||||
setlport(c);
|
||||
return n;
|
||||
}
|
||||
error("bad control message");
|
||||
case Qdata:
|
||||
x = &proto[PROTO(ch->qid)];
|
||||
c = x->conv[CONV(ch->qid)];
|
||||
r = so_send(c->sfd, a, n, 0);
|
||||
if(r < 0){
|
||||
oserrstr();
|
||||
nexterror();
|
||||
}
|
||||
return r;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static Conv*
|
||||
protoclone(Proto *p, char *user, int nfd)
|
||||
{
|
||||
Conv *c, **pp, **ep;
|
||||
|
||||
c = 0;
|
||||
lock(&p->l);
|
||||
if(waserror()) {
|
||||
unlock(&p->l);
|
||||
nexterror();
|
||||
}
|
||||
ep = &p->conv[p->maxconv];
|
||||
for(pp = p->conv; pp < ep; pp++) {
|
||||
c = *pp;
|
||||
if(c == 0) {
|
||||
c = mallocz(sizeof(Conv), 1);
|
||||
if(c == 0)
|
||||
error(Enomem);
|
||||
lock(&c->r.lk);
|
||||
c->r.ref = 1;
|
||||
c->p = p;
|
||||
c->x = pp - p->conv;
|
||||
p->nc++;
|
||||
*pp = c;
|
||||
break;
|
||||
}
|
||||
lock(&c->r.lk);
|
||||
if(c->r.ref == 0) {
|
||||
c->r.ref++;
|
||||
break;
|
||||
}
|
||||
unlock(&c->r.lk);
|
||||
}
|
||||
if(pp >= ep) {
|
||||
unlock(&p->l);
|
||||
poperror();
|
||||
return 0;
|
||||
}
|
||||
|
||||
strcpy(c->owner, user);
|
||||
c->perm = 0660;
|
||||
c->state = "Closed";
|
||||
c->restricted = 0;
|
||||
c->laddr = 0;
|
||||
c->raddr = 0;
|
||||
c->lport = 0;
|
||||
c->rport = 0;
|
||||
c->sfd = nfd;
|
||||
if(nfd == -1)
|
||||
c->sfd = so_socket(p->stype);
|
||||
|
||||
unlock(&c->r.lk);
|
||||
unlock(&p->l);
|
||||
poperror();
|
||||
return c;
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
Isprefix= 16,
|
||||
};
|
||||
|
||||
uchar prefixvals[256] =
|
||||
{
|
||||
/*0x00*/ 0 | Isprefix,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x80*/ 1 | Isprefix,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0x90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xA0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xB0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xC0*/ 2 | Isprefix,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xD0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xE0*/ 3 | Isprefix,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xF0*/ 4 | Isprefix,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
/*0xF8*/ 5 | Isprefix,
|
||||
0, 0, 0,
|
||||
/*0xFC*/ 6 | Isprefix,
|
||||
0,
|
||||
/*0xFE*/ 7 | Isprefix,
|
||||
/*0xFF*/ 8 | Isprefix,
|
||||
};
|
||||
|
||||
int
|
||||
eipfmt(Fmt *f)
|
||||
{
|
||||
char buf[5*8];
|
||||
static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
|
||||
static char *ifmt = "%d.%d.%d.%d";
|
||||
uchar *p, ip[16];
|
||||
ulong *lp;
|
||||
ushort s;
|
||||
int i, j, n, eln, eli;
|
||||
ulong ul;
|
||||
|
||||
switch(f->r) {
|
||||
case 'E': /* Ethernet address */
|
||||
p = va_arg(f->args, uchar*);
|
||||
snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
|
||||
return fmtstrcpy(f, buf);
|
||||
|
||||
case 'I':
|
||||
ul = va_arg(f->args, ulong);
|
||||
hnputl(ip, ul);
|
||||
snprint(buf, sizeof buf, ifmt, ip[0], ip[1], ip[2], ip[3]);
|
||||
return fmtstrcpy(f, buf);
|
||||
}
|
||||
return fmtstrcpy(f, "(eipfmt)");
|
||||
}
|
||||
|
||||
void
|
||||
hnputl(void *p, unsigned long v)
|
||||
{
|
||||
unsigned char *a;
|
||||
|
||||
a = p;
|
||||
a[0] = v>>24;
|
||||
a[1] = v>>16;
|
||||
a[2] = v>>8;
|
||||
a[3] = v;
|
||||
}
|
||||
|
||||
void
|
||||
hnputs(void *p, unsigned short v)
|
||||
{
|
||||
unsigned char *a;
|
||||
|
||||
a = p;
|
||||
a[0] = v>>8;
|
||||
a[1] = v;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
nhgetl(void *p)
|
||||
{
|
||||
unsigned char *a;
|
||||
a = p;
|
||||
return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0);
|
||||
}
|
||||
|
||||
unsigned short
|
||||
nhgets(void *p)
|
||||
{
|
||||
unsigned char *a;
|
||||
a = p;
|
||||
return (a[0]<<8)|(a[1]<<0);
|
||||
}
|
||||
|
||||
#define CLASS(p) ((*(unsigned char*)(p))>>6)
|
||||
|
||||
unsigned long
|
||||
parseip(char *to, char *from)
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
p = from;
|
||||
memset(to, 0, 4);
|
||||
for(i = 0; i < 4 && *p; i++){
|
||||
to[i] = strtoul(p, &p, 0);
|
||||
if(*p == '.')
|
||||
p++;
|
||||
}
|
||||
switch(CLASS(to)){
|
||||
case 0: /* class A - 1 byte net */
|
||||
case 1:
|
||||
if(i == 3){
|
||||
to[3] = to[2];
|
||||
to[2] = to[1];
|
||||
to[1] = 0;
|
||||
} else if (i == 2){
|
||||
to[3] = to[1];
|
||||
to[1] = 0;
|
||||
}
|
||||
break;
|
||||
case 2: /* class B - 2 byte net */
|
||||
if(i == 3){
|
||||
to[3] = to[2];
|
||||
to[2] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return nhgetl(to);
|
||||
}
|
||||
|
||||
void
|
||||
csclose(Chan *c)
|
||||
{
|
||||
free(c->aux);
|
||||
}
|
||||
|
||||
long
|
||||
csread(Chan *c, void *a, long n, vlong offset)
|
||||
{
|
||||
if(c->aux == nil)
|
||||
return 0;
|
||||
return readstr(offset, a, n, c->aux);
|
||||
}
|
||||
|
||||
static struct
|
||||
{
|
||||
char *name;
|
||||
uint num;
|
||||
} tab[] = {
|
||||
"cs", 1,
|
||||
"echo", 7,
|
||||
"discard", 9,
|
||||
"systat", 11,
|
||||
"daytime", 13,
|
||||
"netstat", 15,
|
||||
"chargen", 19,
|
||||
"ftp-data", 20,
|
||||
"ftp", 21,
|
||||
"ssh", 22,
|
||||
"telnet", 23,
|
||||
"smtp", 25,
|
||||
"time", 37,
|
||||
"whois", 43,
|
||||
"dns", 53,
|
||||
"domain", 53,
|
||||
"uucp", 64,
|
||||
"gopher", 70,
|
||||
"rje", 77,
|
||||
"finger", 79,
|
||||
"http", 80,
|
||||
"link", 87,
|
||||
"supdup", 95,
|
||||
"hostnames", 101,
|
||||
"iso-tsap", 102,
|
||||
"x400", 103,
|
||||
"x400-snd", 104,
|
||||
"csnet-ns", 105,
|
||||
"pop-2", 109,
|
||||
"pop3", 110,
|
||||
"portmap", 111,
|
||||
"uucp-path", 117,
|
||||
"nntp", 119,
|
||||
"netbios", 139,
|
||||
"imap4", 143,
|
||||
"NeWS", 144,
|
||||
"print-srv", 170,
|
||||
"z39.50", 210,
|
||||
"fsb", 400,
|
||||
"sysmon", 401,
|
||||
"proxy", 402,
|
||||
"proxyd", 404,
|
||||
"https", 443,
|
||||
"cifs", 445,
|
||||
"ssmtp", 465,
|
||||
"rexec", 512,
|
||||
"login", 513,
|
||||
"shell", 514,
|
||||
"printer", 515,
|
||||
"courier", 530,
|
||||
"cscan", 531,
|
||||
"uucp", 540,
|
||||
"snntp", 563,
|
||||
"9fs", 564,
|
||||
"whoami", 565,
|
||||
"guard", 566,
|
||||
"ticket", 567,
|
||||
"dlsftp", 666,
|
||||
"fmclient", 729,
|
||||
"imaps", 993,
|
||||
"pop3s", 995,
|
||||
"ingreslock", 1524,
|
||||
"pptp", 1723,
|
||||
"nfs", 2049,
|
||||
"webster", 2627,
|
||||
"weather", 3000,
|
||||
"secstore", 5356,
|
||||
"Xdisplay", 6000,
|
||||
"styx", 6666,
|
||||
"mpeg", 6667,
|
||||
"rstyx", 6668,
|
||||
"infdb", 6669,
|
||||
"infsigner", 6671,
|
||||
"infcsigner", 6672,
|
||||
"inflogin", 6673,
|
||||
"bandt", 7330,
|
||||
"face", 32000,
|
||||
"dhashgate", 11978,
|
||||
"exportfs", 17007,
|
||||
"rexexec", 17009,
|
||||
"ncpu", 17010,
|
||||
"cpu", 17013,
|
||||
"glenglenda1", 17020,
|
||||
"glenglenda2", 17021,
|
||||
"glenglenda3", 17022,
|
||||
"glenglenda4", 17023,
|
||||
"glenglenda5", 17024,
|
||||
"glenglenda6", 17025,
|
||||
"glenglenda7", 17026,
|
||||
"glenglenda8", 17027,
|
||||
"glenglenda9", 17028,
|
||||
"glenglenda10", 17029,
|
||||
"flyboy", 17032,
|
||||
"dlsftp", 17033,
|
||||
"venti", 17034,
|
||||
"wiki", 17035,
|
||||
"vica", 17036,
|
||||
0
|
||||
};
|
||||
|
||||
static int
|
||||
lookupport(char *s)
|
||||
{
|
||||
int i;
|
||||
char buf[10], *p;
|
||||
|
||||
i = strtol(s, &p, 0);
|
||||
if(*s && *p == 0)
|
||||
return i;
|
||||
|
||||
i = so_getservbyname(s, "tcp", buf);
|
||||
if(i != -1)
|
||||
return atoi(buf);
|
||||
for(i=0; tab[i].name; i++)
|
||||
if(strcmp(s, tab[i].name) == 0)
|
||||
return tab[i].num;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ulong
|
||||
lookuphost(char *s)
|
||||
{
|
||||
char to[4];
|
||||
ulong ip;
|
||||
|
||||
memset(to, 0, sizeof to);
|
||||
parseip(to, s);
|
||||
ip = nhgetl(to);
|
||||
if(ip != 0)
|
||||
return ip;
|
||||
if((s = hostlookup(s)) == nil)
|
||||
return 0;
|
||||
parseip(to, s);
|
||||
ip = nhgetl(to);
|
||||
free(s);
|
||||
return ip;
|
||||
}
|
||||
|
||||
long
|
||||
cswrite(Chan *c, void *a, long n, vlong offset)
|
||||
{
|
||||
char *f[4];
|
||||
char *s, *ns;
|
||||
ulong ip;
|
||||
int nf, port;
|
||||
|
||||
s = malloc(n+1);
|
||||
if(s == nil)
|
||||
error(Enomem);
|
||||
if(waserror()){
|
||||
free(s);
|
||||
nexterror();
|
||||
}
|
||||
memmove(s, a, n);
|
||||
s[n] = 0;
|
||||
nf = getfields(s, f, nelem(f), 0, "!");
|
||||
if(nf != 3)
|
||||
error("can't translate");
|
||||
|
||||
port = lookupport(f[2]);
|
||||
if(port <= 0)
|
||||
error("no translation for port found");
|
||||
|
||||
ip = lookuphost(f[1]);
|
||||
if(ip == 0)
|
||||
error("no translation for host found");
|
||||
|
||||
ns = smprint("/net/%s/clone %I!%d", f[0], ip, port);
|
||||
if(ns == nil)
|
||||
error(Enomem);
|
||||
free(c->aux);
|
||||
c->aux = ns;
|
||||
poperror();
|
||||
free(s);
|
||||
return n;
|
||||
}
|
||||
|
||||
Dev ipdevtab =
|
||||
{
|
||||
'I',
|
||||
"ip",
|
||||
|
||||
devreset,
|
||||
ipinit,
|
||||
devshutdown,
|
||||
ipattach,
|
||||
ipwalk,
|
||||
ipstat,
|
||||
ipopen,
|
||||
devcreate,
|
||||
ipclose,
|
||||
ipread,
|
||||
devbread,
|
||||
ipwrite,
|
||||
devbwrite,
|
||||
devremove,
|
||||
devwstat,
|
||||
};
|
||||
|
17
kern/devip.h
Normal file
17
kern/devip.h
Normal file
@ -0,0 +1,17 @@
|
||||
enum
|
||||
{
|
||||
S_TCP,
|
||||
S_UDP
|
||||
};
|
||||
|
||||
int so_socket(int type);
|
||||
void so_connect(int, unsigned long, unsigned short);
|
||||
void so_getsockname(int, unsigned long*, unsigned short*);
|
||||
void so_bind(int, int, unsigned short);
|
||||
void so_listen(int);
|
||||
int so_accept(int, unsigned long*, unsigned short*);
|
||||
int so_getservbyname(char*, char*, char*);
|
||||
int so_gethostbyname(char*, char**, int);
|
||||
|
||||
char* hostlookup(char*);
|
||||
|
1214
kern/devmnt.c
Normal file
1214
kern/devmnt.c
Normal file
File diff suppressed because it is too large
Load Diff
237
kern/devmouse.c
Normal file
237
kern/devmouse.c
Normal file
@ -0,0 +1,237 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "draw.h"
|
||||
#include "memdraw.h"
|
||||
#include "screen.h"
|
||||
|
||||
int mousequeue;
|
||||
|
||||
Mouseinfo mouse;
|
||||
Cursorinfo cursor;
|
||||
|
||||
static int mousechanged(void*);
|
||||
|
||||
enum{
|
||||
Qdir,
|
||||
Qcursor,
|
||||
Qmouse
|
||||
};
|
||||
|
||||
Dirtab mousedir[]={
|
||||
".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
|
||||
"cursor", {Qcursor}, 0, 0666,
|
||||
"mouse", {Qmouse}, 0, 0666,
|
||||
};
|
||||
|
||||
#define NMOUSE (sizeof(mousedir)/sizeof(Dirtab))
|
||||
|
||||
static Chan*
|
||||
mouseattach(char *spec)
|
||||
{
|
||||
return devattach('m', spec);
|
||||
}
|
||||
|
||||
static Walkqid*
|
||||
mousewalk(Chan *c, Chan *nc, char **name, int nname)
|
||||
{
|
||||
return devwalk(c, nc, name, nname, mousedir, NMOUSE, devgen);
|
||||
}
|
||||
|
||||
static int
|
||||
mousestat(Chan *c, uchar *db, int n)
|
||||
{
|
||||
return devstat(c, db, n, mousedir, NMOUSE, devgen);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
mouseopen(Chan *c, int omode)
|
||||
{
|
||||
switch((long)c->qid.path){
|
||||
case Qdir:
|
||||
if(omode != OREAD)
|
||||
error(Eperm);
|
||||
break;
|
||||
case Qmouse:
|
||||
lock(&mouse.lk);
|
||||
if(mouse.open){
|
||||
unlock(&mouse.lk);
|
||||
error(Einuse);
|
||||
}
|
||||
mouse.open = 1;
|
||||
unlock(&mouse.lk);
|
||||
break;
|
||||
}
|
||||
c->mode = openmode(omode);
|
||||
c->flag |= COPEN;
|
||||
c->offset = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
mouseclose(Chan *c)
|
||||
{
|
||||
if(!(c->flag&COPEN))
|
||||
return;
|
||||
|
||||
switch((long)c->qid.path) {
|
||||
case Qmouse:
|
||||
lock(&mouse.lk);
|
||||
mouse.open = 0;
|
||||
unlock(&mouse.lk);
|
||||
cursorarrow();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
long
|
||||
mouseread(Chan *c, void *va, long n, vlong offset)
|
||||
{
|
||||
char buf[4*12+1];
|
||||
uchar *p;
|
||||
int i, nn;
|
||||
ulong msec;
|
||||
/* static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 }; */
|
||||
|
||||
p = va;
|
||||
switch((long)c->qid.path){
|
||||
case Qdir:
|
||||
return devdirread(c, va, n, mousedir, NMOUSE, devgen);
|
||||
|
||||
case Qcursor:
|
||||
if(offset != 0)
|
||||
return 0;
|
||||
if(n < 2*4+2*2*16)
|
||||
error(Eshort);
|
||||
n = 2*4+2*2*16;
|
||||
lock(&cursor.lk);
|
||||
BPLONG(p+0, cursor.offset.x);
|
||||
BPLONG(p+4, cursor.offset.y);
|
||||
memmove(p+8, cursor.clr, 2*16);
|
||||
memmove(p+40, cursor.set, 2*16);
|
||||
unlock(&cursor.lk);
|
||||
return n;
|
||||
|
||||
case Qmouse:
|
||||
while(mousechanged(0) == 0)
|
||||
sleep(&mouse.r, mousechanged, 0);
|
||||
|
||||
lock(&screen.lk);
|
||||
if(screen.reshaped) {
|
||||
screen.reshaped = 0;
|
||||
sprint(buf, "t%11d %11d", 0, ticks());
|
||||
if(n > 1+2*12)
|
||||
n = 1+2*12;
|
||||
memmove(va, buf, n);
|
||||
unlock(&screen.lk);
|
||||
return n;
|
||||
}
|
||||
unlock(&screen.lk);
|
||||
|
||||
lock(&mouse.lk);
|
||||
i = mouse.ri;
|
||||
nn = (mouse.wi + Mousequeue - i) % Mousequeue;
|
||||
if(nn < 1)
|
||||
panic("empty mouse queue");
|
||||
msec = ticks();
|
||||
while(nn > 1) {
|
||||
if(mouse.queue[i].msec + Mousewindow > msec)
|
||||
break;
|
||||
i = (i+1)%Mousequeue;
|
||||
nn--;
|
||||
}
|
||||
sprint(buf, "m%11d %11d %11d %11d",
|
||||
mouse.queue[i].xy.x,
|
||||
mouse.queue[i].xy.y,
|
||||
mouse.queue[i].buttons,
|
||||
mouse.queue[i].msec);
|
||||
mouse.ri = (i+1)%Mousequeue;
|
||||
unlock(&mouse.lk);
|
||||
if(n > 1+4*12)
|
||||
n = 1+4*12;
|
||||
memmove(va, buf, n);
|
||||
return n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
mousewrite(Chan *c, void *va, long n, vlong offset)
|
||||
{
|
||||
char *p;
|
||||
Point pt;
|
||||
char buf[64];
|
||||
|
||||
USED(offset);
|
||||
|
||||
p = va;
|
||||
switch((long)c->qid.path){
|
||||
case Qdir:
|
||||
error(Eisdir);
|
||||
|
||||
case Qcursor:
|
||||
if(n < 2*4+2*2*16){
|
||||
cursorarrow();
|
||||
}else{
|
||||
n = 2*4+2*2*16;
|
||||
lock(&cursor.lk);
|
||||
cursor.offset.x = BGLONG(p+0);
|
||||
cursor.offset.y = BGLONG(p+4);
|
||||
memmove(cursor.clr, p+8, 2*16);
|
||||
memmove(cursor.set, p+40, 2*16);
|
||||
unlock(&cursor.lk);
|
||||
setcursor();
|
||||
}
|
||||
return n;
|
||||
|
||||
case Qmouse:
|
||||
if(n > sizeof buf-1)
|
||||
n = sizeof buf -1;
|
||||
memmove(buf, va, n);
|
||||
buf[n] = 0;
|
||||
p = 0;
|
||||
pt.x = strtoul(buf+1, &p, 0);
|
||||
if(p == 0)
|
||||
error(Eshort);
|
||||
pt.y = strtoul(p, 0, 0);
|
||||
if(ptinrect(pt, gscreen->r))
|
||||
mouseset(pt);
|
||||
return n;
|
||||
}
|
||||
|
||||
error(Egreg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
mousechanged(void *a)
|
||||
{
|
||||
USED(a);
|
||||
|
||||
return mouse.ri != mouse.wi || screen.reshaped;
|
||||
}
|
||||
|
||||
Dev mousedevtab = {
|
||||
'm',
|
||||
"mouse",
|
||||
|
||||
devreset,
|
||||
devinit,
|
||||
devshutdown,
|
||||
mouseattach,
|
||||
mousewalk,
|
||||
mousestat,
|
||||
mouseopen,
|
||||
devcreate,
|
||||
mouseclose,
|
||||
mouseread,
|
||||
devbread,
|
||||
mousewrite,
|
||||
devbwrite,
|
||||
devremove,
|
||||
devwstat,
|
||||
};
|
||||
|
704
kern/devntfs.c
Normal file
704
kern/devntfs.c
Normal file
@ -0,0 +1,704 @@
|
||||
#include <windows.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef NAME_MAX
|
||||
# define NAME_MAX 256
|
||||
#endif
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
typedef struct DIR DIR;
|
||||
typedef struct Ufsinfo Ufsinfo;
|
||||
|
||||
enum
|
||||
{
|
||||
NUID = 256,
|
||||
NGID = 256,
|
||||
MAXPATH = 1024,
|
||||
MAXCOMP = 128
|
||||
};
|
||||
|
||||
struct DIR
|
||||
{
|
||||
HANDLE handle;
|
||||
char* path;
|
||||
int index;
|
||||
WIN32_FIND_DATA wfd;
|
||||
};
|
||||
|
||||
struct Ufsinfo
|
||||
{
|
||||
int mode;
|
||||
int fd;
|
||||
int uid;
|
||||
int gid;
|
||||
DIR* dir;
|
||||
ulong offset;
|
||||
QLock oq;
|
||||
char nextname[NAME_MAX];
|
||||
};
|
||||
|
||||
DIR* opendir(char*);
|
||||
int readdir(char*, DIR*);
|
||||
void closedir(DIR*);
|
||||
void rewinddir(DIR*);
|
||||
|
||||
char *base = "c:/.";
|
||||
|
||||
static Qid fsqid(char*, struct stat *);
|
||||
static void fspath(Chan*, char*, char*);
|
||||
// static void fsperm(Chan*, int);
|
||||
static ulong fsdirread(Chan*, uchar*, int, ulong);
|
||||
static int fsomode(int);
|
||||
static int chown(char *path, int uid, int);
|
||||
static int link(char *path, char *next);
|
||||
|
||||
/* clumsy hack, but not worse than the Path stuff in the last one */
|
||||
static char*
|
||||
uc2name(Chan *c)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if(c->name == nil)
|
||||
return "/";
|
||||
s = c2name(c);
|
||||
if(s[0]=='#' && s[1]=='U')
|
||||
return s+2;
|
||||
return s;
|
||||
}
|
||||
|
||||
static char*
|
||||
lastelem(Chan *c)
|
||||
{
|
||||
char *s, *t;
|
||||
|
||||
s = uc2name(c);
|
||||
if((t = strrchr(s, '/')) == nil)
|
||||
return s;
|
||||
if(t[1] == 0)
|
||||
return t;
|
||||
return t+1;
|
||||
}
|
||||
|
||||
static Chan*
|
||||
fsattach(void *spec)
|
||||
{
|
||||
Chan *c;
|
||||
struct stat stbuf;
|
||||
static int devno;
|
||||
Ufsinfo *uif;
|
||||
|
||||
if(stat(base, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
c = devattach('U', spec);
|
||||
|
||||
uif = mallocz(sizeof(Ufsinfo), 1);
|
||||
uif->gid = stbuf.st_gid;
|
||||
uif->uid = stbuf.st_uid;
|
||||
uif->mode = stbuf.st_mode;
|
||||
|
||||
c->aux = uif;
|
||||
c->dev = devno++;
|
||||
c->qid.type = QTDIR;
|
||||
/*print("fsattach %s\n", c2name(c));*/
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static Chan*
|
||||
fsclone(Chan *c, Chan *nc)
|
||||
{
|
||||
Ufsinfo *uif;
|
||||
|
||||
uif = mallocz(sizeof(Ufsinfo), 1);
|
||||
*uif = *(Ufsinfo*)c->aux;
|
||||
nc->aux = uif;
|
||||
|
||||
return nc;
|
||||
}
|
||||
|
||||
static int
|
||||
fswalk1(Chan *c, char *name)
|
||||
{
|
||||
struct stat stbuf;
|
||||
char path[MAXPATH];
|
||||
Ufsinfo *uif;
|
||||
|
||||
fspath(c, name, path);
|
||||
|
||||
/* print("** fs walk '%s' -> %s\n", path, name); /**/
|
||||
|
||||
if(stat(path, &stbuf) < 0)
|
||||
return 0;
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
uif->gid = stbuf.st_gid;
|
||||
uif->uid = stbuf.st_uid;
|
||||
uif->mode = stbuf.st_mode;
|
||||
|
||||
c->qid = fsqid(path, &stbuf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern Cname* addelem(Cname*, char*);
|
||||
|
||||
static Walkqid*
|
||||
fswalk(Chan *c, Chan *nc, char **name, int nname)
|
||||
{
|
||||
int i;
|
||||
Cname *cname;
|
||||
Walkqid *wq;
|
||||
|
||||
if(nc != nil)
|
||||
panic("fswalk: nc != nil");
|
||||
wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
|
||||
nc = devclone(c);
|
||||
cname = c->name;
|
||||
incref(&cname->ref);
|
||||
|
||||
fsclone(c, nc);
|
||||
wq->clone = nc;
|
||||
for(i=0; i<nname; i++){
|
||||
nc->name = cname;
|
||||
if(fswalk1(nc, name[i]) == 0)
|
||||
break;
|
||||
cname = addelem(cname, name[i]);
|
||||
wq->qid[i] = nc->qid;
|
||||
}
|
||||
nc->name = nil;
|
||||
cnameclose(cname);
|
||||
if(i != nname){
|
||||
cclose(nc);
|
||||
wq->clone = nil;
|
||||
}
|
||||
wq->nqid = i;
|
||||
return wq;
|
||||
}
|
||||
|
||||
static int
|
||||
fsstat(Chan *c, uchar *buf, int n)
|
||||
{
|
||||
Dir d;
|
||||
struct stat stbuf;
|
||||
char path[MAXPATH];
|
||||
|
||||
if(n < BIT16SZ)
|
||||
error(Eshortstat);
|
||||
|
||||
fspath(c, 0, path);
|
||||
if(stat(path, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
d.name = lastelem(c);
|
||||
d.uid = "unknown";
|
||||
d.gid = "unknown";
|
||||
d.muid = "unknown";
|
||||
d.qid = c->qid;
|
||||
d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777);
|
||||
d.atime = stbuf.st_atime;
|
||||
d.mtime = stbuf.st_mtime;
|
||||
d.length = stbuf.st_size;
|
||||
d.type = 'U';
|
||||
d.dev = c->dev;
|
||||
return convD2M(&d, buf, n);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
fsopen(Chan *c, int mode)
|
||||
{
|
||||
char path[MAXPATH];
|
||||
int m, isdir;
|
||||
Ufsinfo *uif;
|
||||
|
||||
/*print("fsopen %s\n", c2name(c));*/
|
||||
m = mode & (OTRUNC|3);
|
||||
switch(m) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
case 1|16:
|
||||
break;
|
||||
case 2:
|
||||
case 0|16:
|
||||
case 2|16:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
error(Ebadarg);
|
||||
}
|
||||
|
||||
isdir = c->qid.type & QTDIR;
|
||||
|
||||
if(isdir && mode != OREAD)
|
||||
error(Eperm);
|
||||
|
||||
m = fsomode(m & 3);
|
||||
c->mode = openmode(mode);
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
fspath(c, 0, path);
|
||||
if(isdir) {
|
||||
uif->dir = opendir(path);
|
||||
if(uif->dir == 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
else {
|
||||
if(mode & OTRUNC)
|
||||
m |= O_TRUNC;
|
||||
uif->fd = open(path, m|_O_BINARY, 0666);
|
||||
|
||||
if(uif->fd < 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
uif->offset = 0;
|
||||
|
||||
c->offset = 0;
|
||||
c->flag |= COPEN;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void
|
||||
fscreate(Chan *c, char *name, int mode, ulong perm)
|
||||
{
|
||||
int fd, m;
|
||||
char path[MAXPATH];
|
||||
struct stat stbuf;
|
||||
Ufsinfo *uif;
|
||||
|
||||
m = fsomode(mode&3);
|
||||
|
||||
fspath(c, name, path);
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
if(perm & DMDIR) {
|
||||
if(m)
|
||||
error(Eperm);
|
||||
|
||||
if(mkdir(path) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
fd = open(path, 0);
|
||||
if(fd >= 0) {
|
||||
chmod(path, perm & 0777);
|
||||
chown(path, uif->uid, uif->uid);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
uif->dir = opendir(path);
|
||||
if(uif->dir == 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
else {
|
||||
fd = open(path, _O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC, 0666);
|
||||
if(fd >= 0) {
|
||||
if(m != 1) {
|
||||
close(fd);
|
||||
fd = open(path, m|_O_BINARY);
|
||||
}
|
||||
chmod(path, perm & 0777);
|
||||
chown(path, uif->uid, uif->gid);
|
||||
}
|
||||
if(fd < 0)
|
||||
error(strerror(errno));
|
||||
uif->fd = fd;
|
||||
}
|
||||
|
||||
if(stat(path, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
c->qid = fsqid(path, &stbuf);
|
||||
c->offset = 0;
|
||||
c->flag |= COPEN;
|
||||
c->mode = openmode(mode);
|
||||
}
|
||||
|
||||
static void
|
||||
fsclose(Chan *c)
|
||||
{
|
||||
Ufsinfo *uif;
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
if(c->flag & COPEN) {
|
||||
if(c->qid.type & QTDIR)
|
||||
closedir(uif->dir);
|
||||
else
|
||||
close(uif->fd);
|
||||
}
|
||||
|
||||
free(uif);
|
||||
}
|
||||
|
||||
static long
|
||||
fsread(Chan *c, void *va, long n, ulong offset)
|
||||
{
|
||||
int fd, r;
|
||||
Ufsinfo *uif;
|
||||
|
||||
/*print("fsread %s\n", c2name(c));*/
|
||||
if(c->qid.type & QTDIR)
|
||||
return fsdirread(c, va, n, offset);
|
||||
|
||||
uif = c->aux;
|
||||
qlock(&uif->oq);
|
||||
if(waserror()) {
|
||||
qunlock(&uif->oq);
|
||||
nexterror();
|
||||
}
|
||||
fd = uif->fd;
|
||||
if(uif->offset != offset) {
|
||||
r = lseek(fd, offset, 0);
|
||||
if(r < 0)
|
||||
error(strerror(errno));
|
||||
uif->offset = offset;
|
||||
}
|
||||
|
||||
n = read(fd, va, n);
|
||||
if(n < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif->offset += n;
|
||||
qunlock(&uif->oq);
|
||||
poperror();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static long
|
||||
fswrite(Chan *c, void *va, long n, ulong offset)
|
||||
{
|
||||
int fd, r;
|
||||
Ufsinfo *uif;
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
qlock(&uif->oq);
|
||||
if(waserror()) {
|
||||
qunlock(&uif->oq);
|
||||
nexterror();
|
||||
}
|
||||
fd = uif->fd;
|
||||
if(uif->offset != offset) {
|
||||
r = lseek(fd, offset, 0);
|
||||
if(r < 0)
|
||||
error(strerror(errno));
|
||||
uif->offset = offset;
|
||||
}
|
||||
|
||||
n = write(fd, va, n);
|
||||
if(n < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif->offset += n;
|
||||
qunlock(&uif->oq);
|
||||
poperror();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
fsremove(Chan *c)
|
||||
{
|
||||
int n;
|
||||
char path[MAXPATH];
|
||||
|
||||
fspath(c, 0, path);
|
||||
if(c->qid.type & QTDIR)
|
||||
n = rmdir(path);
|
||||
else
|
||||
n = remove(path);
|
||||
if(n < 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
|
||||
static int
|
||||
fswstat(Chan *c, uchar *buf, int n)
|
||||
{
|
||||
Dir d;
|
||||
struct stat stbuf;
|
||||
char old[MAXPATH], new[MAXPATH];
|
||||
char strs[MAXPATH*3], *p;
|
||||
Ufsinfo *uif;
|
||||
|
||||
if (convM2D(buf, n, &d, strs) != n)
|
||||
error(Ebadstat);
|
||||
|
||||
fspath(c, 0, old);
|
||||
if(stat(old, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
// if(uif->uid != stbuf.st_uid)
|
||||
// error(Eowner);
|
||||
|
||||
if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) {
|
||||
fspath(c, 0, old);
|
||||
strcpy(new, old);
|
||||
p = strrchr(new, '/');
|
||||
strcpy(p+1, d.name);
|
||||
if(rename(old, new) < 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
|
||||
fspath(c, 0, old);
|
||||
if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
|
||||
if(chmod(old, d.mode&0777) < 0)
|
||||
error(strerror(errno));
|
||||
uif->mode &= ~0777;
|
||||
uif->mode |= d.mode&0777;
|
||||
}
|
||||
/*
|
||||
p = name2pass(gid, d.gid);
|
||||
if(p == 0)
|
||||
error(Eunknown);
|
||||
|
||||
if(p->id != stbuf.st_gid) {
|
||||
if(chown(old, stbuf.st_uid, p->id) < 0)
|
||||
error(sys_errlist[errno]);
|
||||
|
||||
uif->gid = p->id;
|
||||
}
|
||||
*/
|
||||
return n;
|
||||
}
|
||||
|
||||
static Qid
|
||||
fsqid(char *p, struct stat *st)
|
||||
{
|
||||
Qid q;
|
||||
int dev;
|
||||
ulong h;
|
||||
static int nqdev;
|
||||
static uchar *qdev;
|
||||
|
||||
if(qdev == 0)
|
||||
qdev = mallocz(65536U, 1);
|
||||
|
||||
q.type = 0;
|
||||
if((st->st_mode&S_IFMT) == S_IFDIR)
|
||||
q.type = QTDIR;
|
||||
|
||||
dev = st->st_dev & 0xFFFFUL;
|
||||
if(qdev[dev] == 0)
|
||||
qdev[dev] = ++nqdev;
|
||||
|
||||
h = 0;
|
||||
while(*p != '\0')
|
||||
h += *p++ * 13;
|
||||
|
||||
q.path = (vlong)qdev[dev]<<32;
|
||||
q.path |= h;
|
||||
q.vers = st->st_mtime;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
static void
|
||||
fspath(Chan *c, char *ext, char *path)
|
||||
{
|
||||
strcpy(path, base);
|
||||
strcat(path, "/");
|
||||
strcat(path, uc2name(c));
|
||||
if(ext) {
|
||||
strcat(path, "/");
|
||||
strcat(path, ext);
|
||||
}
|
||||
cleanname(path);
|
||||
}
|
||||
|
||||
static int
|
||||
isdots(char *name)
|
||||
{
|
||||
if(name[0] != '.')
|
||||
return 0;
|
||||
if(name[1] == '\0')
|
||||
return 1;
|
||||
if(name[1] != '.')
|
||||
return 0;
|
||||
if(name[2] == '\0')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
p9readdir(char *name, Ufsinfo *uif)
|
||||
{
|
||||
if(uif->nextname[0]){
|
||||
strcpy(name, uif->nextname);
|
||||
uif->nextname[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return readdir(name, uif->dir);
|
||||
}
|
||||
|
||||
static ulong
|
||||
fsdirread(Chan *c, uchar *va, int count, ulong offset)
|
||||
{
|
||||
int i;
|
||||
Dir d;
|
||||
long n;
|
||||
char de[NAME_MAX];
|
||||
struct stat stbuf;
|
||||
char path[MAXPATH], dirpath[MAXPATH];
|
||||
Ufsinfo *uif;
|
||||
|
||||
/*print("fsdirread %s\n", c2name(c));*/
|
||||
i = 0;
|
||||
uif = c->aux;
|
||||
|
||||
errno = 0;
|
||||
if(uif->offset != offset) {
|
||||
if(offset != 0)
|
||||
error("bad offset in fsdirread");
|
||||
uif->offset = offset; /* sync offset */
|
||||
uif->nextname[0] = 0;
|
||||
rewinddir(uif->dir);
|
||||
}
|
||||
|
||||
fspath(c, 0, dirpath);
|
||||
|
||||
while(i+BIT16SZ < count) {
|
||||
if(!p9readdir(de, uif))
|
||||
break;
|
||||
|
||||
if(de[0]==0 || isdots(de))
|
||||
continue;
|
||||
|
||||
d.name = de;
|
||||
sprint(path, "%s/%s", dirpath, de);
|
||||
memset(&stbuf, 0, sizeof stbuf);
|
||||
|
||||
if(stat(path, &stbuf) < 0) {
|
||||
print("dir: bad path %s\n", path);
|
||||
/* but continue... probably a bad symlink */
|
||||
}
|
||||
|
||||
d.uid = "unknown";
|
||||
d.gid = "unknown";
|
||||
d.muid = "unknown";
|
||||
d.qid = fsqid(path, &stbuf);
|
||||
d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777);
|
||||
d.atime = stbuf.st_atime;
|
||||
d.mtime = stbuf.st_mtime;
|
||||
d.length = stbuf.st_size;
|
||||
d.type = 'U';
|
||||
d.dev = c->dev;
|
||||
n = convD2M(&d, (char*)va+i, count-i);
|
||||
if(n == BIT16SZ){
|
||||
strcpy(uif->nextname, de);
|
||||
break;
|
||||
}
|
||||
i += n;
|
||||
}
|
||||
/*print("got %d\n", i);*/
|
||||
uif->offset += i;
|
||||
return i;
|
||||
}
|
||||
|
||||
static int
|
||||
fsomode(int m)
|
||||
{
|
||||
switch(m) {
|
||||
case 0: /* OREAD */
|
||||
case 3: /* OEXEC */
|
||||
return 0;
|
||||
case 1: /* OWRITE */
|
||||
return 1;
|
||||
case 2: /* ORDWR */
|
||||
return 2;
|
||||
}
|
||||
error(Ebadarg);
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
closedir(DIR *d)
|
||||
{
|
||||
FindClose(d->handle);
|
||||
free(d->path);
|
||||
}
|
||||
|
||||
int
|
||||
readdir(char *name, DIR *d)
|
||||
{
|
||||
if(d->index != 0) {
|
||||
if(FindNextFile(d->handle, &d->wfd) == FALSE)
|
||||
return 0;
|
||||
}
|
||||
strcpy(name, d->wfd.cFileName);
|
||||
d->index++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
rewinddir(DIR *d)
|
||||
{
|
||||
FindClose(d->handle);
|
||||
d->handle = FindFirstFile(d->path, &d->wfd);
|
||||
d->index = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
chown(char *path, int uid, int perm)
|
||||
{
|
||||
/* panic("chown"); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
DIR*
|
||||
opendir(char *p)
|
||||
{
|
||||
DIR *d;
|
||||
char path[MAX_PATH];
|
||||
|
||||
|
||||
snprint(path, sizeof(path), "%s/*.*", p);
|
||||
|
||||
d = mallocz(sizeof(DIR), 1);
|
||||
if(d == 0)
|
||||
return 0;
|
||||
|
||||
d->index = 0;
|
||||
|
||||
d->handle = FindFirstFile(path, &d->wfd);
|
||||
if(d->handle == INVALID_HANDLE_VALUE) {
|
||||
free(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
d->path = strdup(path);
|
||||
return d;
|
||||
}
|
||||
|
||||
Dev fsdevtab = {
|
||||
'U',
|
||||
"fs",
|
||||
|
||||
devreset,
|
||||
devinit,
|
||||
devshutdown,
|
||||
fsattach,
|
||||
fswalk,
|
||||
fsstat,
|
||||
fsopen,
|
||||
fscreate,
|
||||
fsclose,
|
||||
fsread,
|
||||
devbread,
|
||||
fswrite,
|
||||
devbwrite,
|
||||
fsremove,
|
||||
fswstat,
|
||||
};
|
398
kern/devpipe.c
Normal file
398
kern/devpipe.c
Normal file
@ -0,0 +1,398 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "netif.h"
|
||||
|
||||
typedef struct Pipe Pipe;
|
||||
struct Pipe
|
||||
{
|
||||
QLock lk;
|
||||
Pipe *next;
|
||||
int ref;
|
||||
ulong path;
|
||||
Queue *q[2];
|
||||
int qref[2];
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
Lock lk;
|
||||
ulong path;
|
||||
} pipealloc;
|
||||
|
||||
enum
|
||||
{
|
||||
Qdir,
|
||||
Qdata0,
|
||||
Qdata1,
|
||||
};
|
||||
|
||||
Dirtab pipedir[] =
|
||||
{
|
||||
".", {Qdir,0,QTDIR}, 0, DMDIR|0500,
|
||||
"data", {Qdata0}, 0, 0600,
|
||||
"data1", {Qdata1}, 0, 0600,
|
||||
};
|
||||
#define NPIPEDIR 3
|
||||
|
||||
static void
|
||||
pipeinit(void)
|
||||
{
|
||||
if(conf.pipeqsize == 0){
|
||||
if(conf.nmach > 1)
|
||||
conf.pipeqsize = 256*1024;
|
||||
else
|
||||
conf.pipeqsize = 32*1024;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* create a pipe, no streams are created until an open
|
||||
*/
|
||||
static Chan*
|
||||
pipeattach(char *spec)
|
||||
{
|
||||
Pipe *p;
|
||||
Chan *c;
|
||||
|
||||
c = devattach('|', spec);
|
||||
p = malloc(sizeof(Pipe));
|
||||
if(p == 0)
|
||||
exhausted("memory");
|
||||
p->ref = 1;
|
||||
|
||||
p->q[0] = qopen(conf.pipeqsize, 0, 0, 0);
|
||||
if(p->q[0] == 0){
|
||||
free(p);
|
||||
exhausted("memory");
|
||||
}
|
||||
p->q[1] = qopen(conf.pipeqsize, 0, 0, 0);
|
||||
if(p->q[1] == 0){
|
||||
free(p->q[0]);
|
||||
free(p);
|
||||
exhausted("memory");
|
||||
}
|
||||
|
||||
lock(&pipealloc.lk);
|
||||
p->path = ++pipealloc.path;
|
||||
unlock(&pipealloc.lk);
|
||||
|
||||
mkqid(&c->qid, NETQID(2*p->path, Qdir), 0, QTDIR);
|
||||
c->aux = p;
|
||||
c->dev = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
static int
|
||||
pipegen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
|
||||
{
|
||||
Qid q;
|
||||
int len;
|
||||
Pipe *p;
|
||||
|
||||
USED(name);
|
||||
|
||||
if(i == DEVDOTDOT){
|
||||
devdir(c, c->qid, "#|", 0, eve, DMDIR|0555, dp);
|
||||
return 1;
|
||||
}
|
||||
i++; /* skip . */
|
||||
if(tab==0 || i>=ntab)
|
||||
return -1;
|
||||
|
||||
tab += i;
|
||||
p = c->aux;
|
||||
switch((ulong)tab->qid.path){
|
||||
case Qdata0:
|
||||
len = qlen(p->q[0]);
|
||||
break;
|
||||
case Qdata1:
|
||||
len = qlen(p->q[1]);
|
||||
break;
|
||||
default:
|
||||
len = tab->length;
|
||||
break;
|
||||
}
|
||||
mkqid(&q, NETQID(NETID(c->qid.path), tab->qid.path), 0, QTFILE);
|
||||
devdir(c, q, tab->name, len, eve, tab->perm, dp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static Walkqid*
|
||||
pipewalk(Chan *c, Chan *nc, char **name, int nname)
|
||||
{
|
||||
Walkqid *wq;
|
||||
Pipe *p;
|
||||
|
||||
wq = devwalk(c, nc, name, nname, pipedir, NPIPEDIR, pipegen);
|
||||
if(wq != nil && wq->clone != nil && wq->clone != c){
|
||||
p = c->aux;
|
||||
qlock(&p->lk);
|
||||
p->ref++;
|
||||
if(c->flag & COPEN){
|
||||
print("channel open in pipewalk\n");
|
||||
switch(NETTYPE(c->qid.path)){
|
||||
case Qdata0:
|
||||
p->qref[0]++;
|
||||
break;
|
||||
case Qdata1:
|
||||
p->qref[1]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
qunlock(&p->lk);
|
||||
}
|
||||
return wq;
|
||||
}
|
||||
|
||||
static int
|
||||
pipestat(Chan *c, uchar *db, int n)
|
||||
{
|
||||
Pipe *p;
|
||||
Dir dir;
|
||||
|
||||
p = c->aux;
|
||||
|
||||
switch(NETTYPE(c->qid.path)){
|
||||
case Qdir:
|
||||
devdir(c, c->qid, ".", 0, eve, DMDIR|0555, &dir);
|
||||
break;
|
||||
case Qdata0:
|
||||
devdir(c, c->qid, "data", qlen(p->q[0]), eve, 0600, &dir);
|
||||
break;
|
||||
case Qdata1:
|
||||
devdir(c, c->qid, "data1", qlen(p->q[1]), eve, 0600, &dir);
|
||||
break;
|
||||
default:
|
||||
panic("pipestat");
|
||||
}
|
||||
n = convD2M(&dir, db, n);
|
||||
if(n < BIT16SZ)
|
||||
error(Eshortstat);
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* if the stream doesn't exist, create it
|
||||
*/
|
||||
static Chan*
|
||||
pipeopen(Chan *c, int omode)
|
||||
{
|
||||
Pipe *p;
|
||||
|
||||
if(c->qid.type & QTDIR){
|
||||
if(omode != OREAD)
|
||||
error(Ebadarg);
|
||||
c->mode = omode;
|
||||
c->flag |= COPEN;
|
||||
c->offset = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
p = c->aux;
|
||||
qlock(&p->lk);
|
||||
switch(NETTYPE(c->qid.path)){
|
||||
case Qdata0:
|
||||
p->qref[0]++;
|
||||
break;
|
||||
case Qdata1:
|
||||
p->qref[1]++;
|
||||
break;
|
||||
}
|
||||
qunlock(&p->lk);
|
||||
|
||||
c->mode = openmode(omode);
|
||||
c->flag |= COPEN;
|
||||
c->offset = 0;
|
||||
c->iounit = qiomaxatomic;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void
|
||||
pipeclose(Chan *c)
|
||||
{
|
||||
Pipe *p;
|
||||
|
||||
p = c->aux;
|
||||
qlock(&p->lk);
|
||||
|
||||
if(c->flag & COPEN){
|
||||
/*
|
||||
* closing either side hangs up the stream
|
||||
*/
|
||||
switch(NETTYPE(c->qid.path)){
|
||||
case Qdata0:
|
||||
p->qref[0]--;
|
||||
if(p->qref[0] == 0){
|
||||
qhangup(p->q[1], 0);
|
||||
qclose(p->q[0]);
|
||||
}
|
||||
break;
|
||||
case Qdata1:
|
||||
p->qref[1]--;
|
||||
if(p->qref[1] == 0){
|
||||
qhangup(p->q[0], 0);
|
||||
qclose(p->q[1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* if both sides are closed, they are reusable
|
||||
*/
|
||||
if(p->qref[0] == 0 && p->qref[1] == 0){
|
||||
qreopen(p->q[0]);
|
||||
qreopen(p->q[1]);
|
||||
}
|
||||
|
||||
/*
|
||||
* free the structure on last close
|
||||
*/
|
||||
p->ref--;
|
||||
if(p->ref == 0){
|
||||
qunlock(&p->lk);
|
||||
free(p->q[0]);
|
||||
free(p->q[1]);
|
||||
free(p);
|
||||
} else
|
||||
qunlock(&p->lk);
|
||||
}
|
||||
|
||||
static long
|
||||
piperead(Chan *c, void *va, long n, vlong offset)
|
||||
{
|
||||
Pipe *p;
|
||||
|
||||
USED(offset);
|
||||
|
||||
p = c->aux;
|
||||
|
||||
switch(NETTYPE(c->qid.path)){
|
||||
case Qdir:
|
||||
return devdirread(c, va, n, pipedir, NPIPEDIR, pipegen);
|
||||
case Qdata0:
|
||||
return qread(p->q[0], va, n);
|
||||
case Qdata1:
|
||||
return qread(p->q[1], va, n);
|
||||
default:
|
||||
panic("piperead");
|
||||
}
|
||||
return -1; /* not reached */
|
||||
}
|
||||
|
||||
static Block*
|
||||
pipebread(Chan *c, long n, ulong offset)
|
||||
{
|
||||
Pipe *p;
|
||||
|
||||
p = c->aux;
|
||||
|
||||
switch(NETTYPE(c->qid.path)){
|
||||
case Qdata0:
|
||||
return qbread(p->q[0], n);
|
||||
case Qdata1:
|
||||
return qbread(p->q[1], n);
|
||||
}
|
||||
|
||||
return devbread(c, n, offset);
|
||||
}
|
||||
|
||||
/*
|
||||
* a write to a closed pipe causes a note to be sent to
|
||||
* the process.
|
||||
*/
|
||||
static long
|
||||
pipewrite(Chan *c, void *va, long n, vlong offset)
|
||||
{
|
||||
Pipe *p;
|
||||
|
||||
USED(offset);
|
||||
if(!islo())
|
||||
print("pipewrite hi %lux\n", getcallerpc(&c));
|
||||
|
||||
if(waserror()) {
|
||||
/* avoid notes when pipe is a mounted queue */
|
||||
if((c->flag & CMSG) == 0)
|
||||
postnote(up, 1, "sys: write on closed pipe", NUser);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
p = c->aux;
|
||||
|
||||
switch(NETTYPE(c->qid.path)){
|
||||
case Qdata0:
|
||||
n = qwrite(p->q[1], va, n);
|
||||
break;
|
||||
|
||||
case Qdata1:
|
||||
n = qwrite(p->q[0], va, n);
|
||||
break;
|
||||
|
||||
default:
|
||||
panic("pipewrite");
|
||||
}
|
||||
|
||||
poperror();
|
||||
return n;
|
||||
}
|
||||
|
||||
static long
|
||||
pipebwrite(Chan *c, Block *bp, ulong offset)
|
||||
{
|
||||
long n;
|
||||
Pipe *p;
|
||||
|
||||
USED(offset);
|
||||
|
||||
if(waserror()) {
|
||||
/* avoid notes when pipe is a mounted queue */
|
||||
if((c->flag & CMSG) == 0)
|
||||
postnote(up, 1, "sys: write on closed pipe", NUser);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
p = c->aux;
|
||||
switch(NETTYPE(c->qid.path)){
|
||||
case Qdata0:
|
||||
n = qbwrite(p->q[1], bp);
|
||||
break;
|
||||
|
||||
case Qdata1:
|
||||
n = qbwrite(p->q[0], bp);
|
||||
break;
|
||||
|
||||
default:
|
||||
n = 0;
|
||||
panic("pipebwrite");
|
||||
}
|
||||
|
||||
poperror();
|
||||
return n;
|
||||
}
|
||||
|
||||
Dev pipedevtab = {
|
||||
'|',
|
||||
"pipe",
|
||||
|
||||
devreset,
|
||||
pipeinit,
|
||||
devshutdown,
|
||||
pipeattach,
|
||||
pipewalk,
|
||||
pipestat,
|
||||
pipeopen,
|
||||
devcreate,
|
||||
pipeclose,
|
||||
piperead,
|
||||
pipebread,
|
||||
pipewrite,
|
||||
pipebwrite,
|
||||
devremove,
|
||||
devwstat,
|
||||
};
|
268
kern/devroot.c
Normal file
268
kern/devroot.c
Normal file
@ -0,0 +1,268 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
enum
|
||||
{
|
||||
Qdir = 0,
|
||||
Qboot = 0x1000,
|
||||
|
||||
Nrootfiles = 32,
|
||||
Nbootfiles = 32,
|
||||
};
|
||||
|
||||
typedef struct Dirlist Dirlist;
|
||||
struct Dirlist
|
||||
{
|
||||
uint base;
|
||||
Dirtab *dir;
|
||||
uchar **data;
|
||||
int ndir;
|
||||
int mdir;
|
||||
};
|
||||
|
||||
static Dirtab rootdir[Nrootfiles] = {
|
||||
"#/", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
|
||||
"boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555,
|
||||
};
|
||||
static uchar *rootdata[Nrootfiles];
|
||||
static Dirlist rootlist =
|
||||
{
|
||||
0,
|
||||
rootdir,
|
||||
rootdata,
|
||||
2,
|
||||
Nrootfiles
|
||||
};
|
||||
|
||||
static Dirtab bootdir[Nbootfiles] = {
|
||||
"boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555,
|
||||
};
|
||||
static uchar *bootdata[Nbootfiles];
|
||||
static Dirlist bootlist =
|
||||
{
|
||||
Qboot,
|
||||
bootdir,
|
||||
bootdata,
|
||||
1,
|
||||
Nbootfiles
|
||||
};
|
||||
|
||||
/*
|
||||
* add a file to the list
|
||||
*/
|
||||
static void
|
||||
addlist(Dirlist *l, char *name, uchar *contents, ulong len, int perm)
|
||||
{
|
||||
Dirtab *d;
|
||||
|
||||
if(l->ndir >= l->mdir)
|
||||
panic("too many root files");
|
||||
l->data[l->ndir] = contents;
|
||||
d = &l->dir[l->ndir];
|
||||
strcpy(d->name, name);
|
||||
d->length = len;
|
||||
d->perm = perm;
|
||||
d->qid.type = 0;
|
||||
d->qid.vers = 0;
|
||||
d->qid.path = ++l->ndir + l->base;
|
||||
if(perm & DMDIR)
|
||||
d->qid.type |= QTDIR;
|
||||
}
|
||||
|
||||
/*
|
||||
* add a root file
|
||||
*/
|
||||
void
|
||||
addbootfile(char *name, uchar *contents, ulong len)
|
||||
{
|
||||
addlist(&bootlist, name, contents, len, 0555);
|
||||
}
|
||||
|
||||
/*
|
||||
* add a root directory
|
||||
*/
|
||||
static void
|
||||
addrootdir(char *name)
|
||||
{
|
||||
addlist(&rootlist, name, nil, 0, DMDIR|0555);
|
||||
}
|
||||
|
||||
static void
|
||||
rootreset(void)
|
||||
{
|
||||
addrootdir("bin");
|
||||
addrootdir("dev");
|
||||
addrootdir("env");
|
||||
addrootdir("fd");
|
||||
addrootdir("mnt");
|
||||
addrootdir("net");
|
||||
addrootdir("net.alt");
|
||||
addrootdir("proc");
|
||||
addrootdir("root");
|
||||
addrootdir("srv");
|
||||
}
|
||||
|
||||
static Chan*
|
||||
rootattach(char *spec)
|
||||
{
|
||||
return devattach('/', spec);
|
||||
}
|
||||
|
||||
static int
|
||||
rootgen(Chan *c, char *name, Dirtab *dirt, int ndirt, int s, Dir *dp)
|
||||
{
|
||||
int t;
|
||||
Dirtab *d;
|
||||
Dirlist *l;
|
||||
|
||||
USED(dirt);
|
||||
USED(ndirt);
|
||||
|
||||
switch((int)c->qid.path){
|
||||
case Qdir:
|
||||
if(s == DEVDOTDOT){
|
||||
Qid tqiddir = {Qdir, 0, QTDIR};
|
||||
devdir(c, tqiddir, "#/", 0, eve, 0555, dp);
|
||||
return 1;
|
||||
}
|
||||
return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp);
|
||||
case Qboot:
|
||||
if(s == DEVDOTDOT){
|
||||
Qid tqiddir = {Qdir, 0, QTDIR};
|
||||
devdir(c, tqiddir, "#/", 0, eve, 0555, dp);
|
||||
return 1;
|
||||
}
|
||||
return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp);
|
||||
default:
|
||||
if(s == DEVDOTDOT){
|
||||
Qid tqiddir = {Qdir, 0, QTDIR};
|
||||
if((int)c->qid.path < Qboot)
|
||||
devdir(c, tqiddir, "#/", 0, eve, 0555, dp);
|
||||
else {
|
||||
tqiddir.path = Qboot;
|
||||
devdir(c, tqiddir, "#/", 0, eve, 0555, dp);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if(s != 0)
|
||||
return -1;
|
||||
if((int)c->qid.path < Qboot){
|
||||
t = c->qid.path-1;
|
||||
l = &rootlist;
|
||||
}else{
|
||||
t = c->qid.path - Qboot - 1;
|
||||
l = &bootlist;
|
||||
}
|
||||
if(t >= l->ndir)
|
||||
return -1;
|
||||
if(t < 0){
|
||||
print("rootgen %llud %d %d\n", c->qid.path, s, t);
|
||||
panic("whoops");
|
||||
}
|
||||
d = &l->dir[t];
|
||||
devdir(c, d->qid, d->name, d->length, eve, d->perm, dp);
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static Walkqid*
|
||||
rootwalk(Chan *c, Chan *nc, char **name, int nname)
|
||||
{
|
||||
return devwalk(c, nc, name, nname, nil, 0, rootgen);
|
||||
}
|
||||
|
||||
static int
|
||||
rootstat(Chan *c, uchar *dp, int n)
|
||||
{
|
||||
return devstat(c, dp, n, nil, 0, rootgen);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
rootopen(Chan *c, int omode)
|
||||
{
|
||||
return devopen(c, omode, nil, 0, devgen);
|
||||
}
|
||||
|
||||
/*
|
||||
* sysremove() knows this is a nop
|
||||
*/
|
||||
static void
|
||||
rootclose(Chan *c)
|
||||
{
|
||||
USED(c);
|
||||
}
|
||||
|
||||
static long
|
||||
rootread(Chan *c, void *buf, long n, vlong off)
|
||||
{
|
||||
ulong t;
|
||||
Dirtab *d;
|
||||
Dirlist *l;
|
||||
uchar *data;
|
||||
ulong offset = off;
|
||||
|
||||
t = c->qid.path;
|
||||
switch(t){
|
||||
case Qdir:
|
||||
case Qboot:
|
||||
return devdirread(c, buf, n, nil, 0, rootgen);
|
||||
}
|
||||
|
||||
if(t<Qboot)
|
||||
l = &rootlist;
|
||||
else{
|
||||
t -= Qboot;
|
||||
l = &bootlist;
|
||||
}
|
||||
|
||||
t--;
|
||||
if(t >= l->ndir)
|
||||
error(Egreg);
|
||||
|
||||
d = &l->dir[t];
|
||||
data = l->data[t];
|
||||
if(offset >= d->length)
|
||||
return 0;
|
||||
if(offset+n > d->length)
|
||||
n = d->length - offset;
|
||||
memmove(buf, data+offset, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
static long
|
||||
rootwrite(Chan *c, void *v, long n, vlong o)
|
||||
{
|
||||
USED(c);
|
||||
USED(v);
|
||||
USED(n);
|
||||
USED(o);
|
||||
|
||||
error(Egreg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Dev rootdevtab = {
|
||||
'/',
|
||||
"root",
|
||||
|
||||
rootreset,
|
||||
devinit,
|
||||
devshutdown,
|
||||
rootattach,
|
||||
rootwalk,
|
||||
rootstat,
|
||||
rootopen,
|
||||
devcreate,
|
||||
rootclose,
|
||||
rootread,
|
||||
devbread,
|
||||
rootwrite,
|
||||
devbwrite,
|
||||
devremove,
|
||||
devwstat,
|
||||
};
|
||||
|
1512
kern/devssl.c
Normal file
1512
kern/devssl.c
Normal file
File diff suppressed because it is too large
Load Diff
27
kern/devtab.c
Normal file
27
kern/devtab.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
extern Dev consdevtab;
|
||||
extern Dev rootdevtab;
|
||||
extern Dev pipedevtab;
|
||||
extern Dev ssldevtab;
|
||||
extern Dev mousedevtab;
|
||||
extern Dev drawdevtab;
|
||||
extern Dev ipdevtab;
|
||||
extern Dev fsdevtab;
|
||||
|
||||
Dev *devtab[] = {
|
||||
&rootdevtab,
|
||||
&consdevtab,
|
||||
&pipedevtab,
|
||||
&ssldevtab,
|
||||
&mousedevtab,
|
||||
&drawdevtab,
|
||||
&ipdevtab,
|
||||
&fsdevtab,
|
||||
0
|
||||
};
|
||||
|
50
kern/error.c
Normal file
50
kern/error.c
Normal file
@ -0,0 +1,50 @@
|
||||
char Enoerror[] = "no error";
|
||||
char Emount[] = "inconsistent mount";
|
||||
char Eunmount[] = "not mounted";
|
||||
char Eunion[] = "not in union";
|
||||
char Emountrpc[] = "mount rpc error";
|
||||
char Eshutdown[] = "device shut down";
|
||||
char Enocreate[] = "mounted directory forbids creation";
|
||||
char Enonexist[] = "file does not exist";
|
||||
char Eexist[] = "file already exists";
|
||||
char Ebadsharp[] = "unknown device in # filename";
|
||||
char Enotdir[] = "not a directory";
|
||||
char Eisdir[] = "file is a directory";
|
||||
char Ebadchar[] = "bad character in file name";
|
||||
char Efilename[] = "file name syntax";
|
||||
char Eperm[] = "permission denied";
|
||||
char Ebadusefd[] = "inappropriate use of fd";
|
||||
char Ebadarg[] = "bad arg in system call";
|
||||
char Einuse[] = "device or object already in use";
|
||||
char Eio[] = "i/o error";
|
||||
char Etoobig[] = "read or write too large";
|
||||
char Etoosmall[] = "read or write too small";
|
||||
char Enoport[] = "network port not available";
|
||||
char Ehungup[] = "i/o on hungup channel";
|
||||
char Ebadctl[] = "bad process or channel control request";
|
||||
char Enodev[] = "no free devices";
|
||||
char Eprocdied[] = "process exited";
|
||||
char Enochild[] = "no living children";
|
||||
char Eioload[] = "i/o error in demand load";
|
||||
char Enovmem[] = "virtual memory allocation failed";
|
||||
char Ebadfd[] = "fd out of range or not open";
|
||||
char Enofd[] = "no free file descriptors";
|
||||
char Eisstream[] = "seek on a stream";
|
||||
char Ebadexec[] = "exec header invalid";
|
||||
char Etimedout[] = "connection timed out";
|
||||
char Econrefused[] = "connection refused";
|
||||
char Econinuse[] = "connection in use";
|
||||
char Eintr[] = "interrupted";
|
||||
char Enomem[] = "kernel allocate failed";
|
||||
char Enoswap[] = "swap space full";
|
||||
char Esoverlap[] = "segments overlap";
|
||||
char Emouseset[] = "mouse type already set";
|
||||
char Eshort[] = "i/o count too small";
|
||||
char Egreg[] = "ken has left the building";
|
||||
char Ebadspec[] = "bad attach specifier";
|
||||
char Enoreg[] = "process has no saved registers";
|
||||
char Enoattach[] = "mount/attach disallowed";
|
||||
char Eshortstat[] = "stat buffer too small";
|
||||
char Ebadstat[] = "malformed stat buffer";
|
||||
char Enegoff[] = "negative i/o offset";
|
||||
char Ecmdargs[] = "wrong #args in control message";
|
50
kern/error.h
Normal file
50
kern/error.h
Normal file
@ -0,0 +1,50 @@
|
||||
extern char Enoerror[]; /* no error */
|
||||
extern char Emount[]; /* inconsistent mount */
|
||||
extern char Eunmount[]; /* not mounted */
|
||||
extern char Eunion[]; /* not in union */
|
||||
extern char Emountrpc[]; /* mount rpc error */
|
||||
extern char Eshutdown[]; /* device shut down */
|
||||
extern char Enocreate[]; /* mounted directory forbids creation */
|
||||
extern char Enonexist[]; /* file does not exist */
|
||||
extern char Eexist[]; /* file already exists */
|
||||
extern char Ebadsharp[]; /* unknown device in # filename */
|
||||
extern char Enotdir[]; /* not a directory */
|
||||
extern char Eisdir[]; /* file is a directory */
|
||||
extern char Ebadchar[]; /* bad character in file name */
|
||||
extern char Efilename[]; /* file name syntax */
|
||||
extern char Eperm[]; /* permission denied */
|
||||
extern char Ebadusefd[]; /* inappropriate use of fd */
|
||||
extern char Ebadarg[]; /* bad arg in system call */
|
||||
extern char Einuse[]; /* device or object already in use */
|
||||
extern char Eio[]; /* i/o error */
|
||||
extern char Etoobig[]; /* read or write too large */
|
||||
extern char Etoosmall[]; /* read or write too small */
|
||||
extern char Enoport[]; /* network port not available */
|
||||
extern char Ehungup[]; /* i/o on hungup channel */
|
||||
extern char Ebadctl[]; /* bad process or channel control request */
|
||||
extern char Enodev[]; /* no free devices */
|
||||
extern char Eprocdied[]; /* process exited */
|
||||
extern char Enochild[]; /* no living children */
|
||||
extern char Eioload[]; /* i/o error in demand load */
|
||||
extern char Enovmem[]; /* virtual memory allocation failed */
|
||||
extern char Ebadfd[]; /* fd out of range or not open */
|
||||
extern char Enofd[]; /* no free file descriptors */
|
||||
extern char Eisstream[]; /* seek on a stream */
|
||||
extern char Ebadexec[]; /* exec header invalid */
|
||||
extern char Etimedout[]; /* connection timed out */
|
||||
extern char Econrefused[]; /* connection refused */
|
||||
extern char Econinuse[]; /* connection in use */
|
||||
extern char Eintr[]; /* interrupted */
|
||||
extern char Enomem[]; /* kernel allocate failed */
|
||||
extern char Enoswap[]; /* swap space full */
|
||||
extern char Esoverlap[]; /* segments overlap */
|
||||
extern char Emouseset[]; /* mouse type already set */
|
||||
extern char Eshort[]; /* i/o count too small */
|
||||
extern char Egreg[]; /* ken has left the building */
|
||||
extern char Ebadspec[]; /* bad attach specifier */
|
||||
extern char Enoreg[]; /* process has no saved registers */
|
||||
extern char Enoattach[]; /* mount/attach disallowed */
|
||||
extern char Eshortstat[]; /* stat buffer too small */
|
||||
extern char Ebadstat[]; /* malformed stat buffer */
|
||||
extern char Enegoff[]; /* negative i/o offset */
|
||||
extern char Ecmdargs[]; /* wrong #args in control message */
|
821
kern/exportfs.c
Normal file
821
kern/exportfs.c
Normal file
@ -0,0 +1,821 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
typedef struct Fid Fid;
|
||||
typedef struct Export Export;
|
||||
typedef struct Exq Exq;
|
||||
|
||||
#define nil ((void*)0)
|
||||
|
||||
enum
|
||||
{
|
||||
Nfidhash = 1,
|
||||
MAXRPC = MAXMSG+MAXFDATA,
|
||||
MAXDIRREAD = (MAXFDATA/DIRLEN)*DIRLEN
|
||||
};
|
||||
|
||||
struct Export
|
||||
{
|
||||
Ref r;
|
||||
Exq* work;
|
||||
Lock fidlock;
|
||||
Fid* fid[Nfidhash];
|
||||
Chan* root;
|
||||
Chan* io;
|
||||
Pgrp* pgrp;
|
||||
int npart;
|
||||
char part[MAXRPC];
|
||||
};
|
||||
|
||||
struct Fid
|
||||
{
|
||||
Fid* next;
|
||||
Fid** last;
|
||||
Chan* chan;
|
||||
long offset;
|
||||
int fid;
|
||||
int ref; /* fcalls using the fid; locked by Export.Lock */
|
||||
int attached; /* fid attached or cloned but not clunked */
|
||||
};
|
||||
|
||||
struct Exq
|
||||
{
|
||||
Lock lk;
|
||||
int nointr;
|
||||
int noresponse; /* don't respond to this one */
|
||||
Exq* next;
|
||||
int shut; /* has been noted for shutdown */
|
||||
Export* export;
|
||||
void* slave;
|
||||
Fcall rpc;
|
||||
char buf[MAXRPC];
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
Lock l;
|
||||
Qlock qwait;
|
||||
Rendez rwait;
|
||||
Exq *head; /* work waiting for a slave */
|
||||
Exq *tail;
|
||||
}exq;
|
||||
|
||||
static void exshutdown(Export*);
|
||||
static void exflush(Export*, int, int);
|
||||
static void exslave(void*);
|
||||
static void exfree(Export*);
|
||||
static void exportproc(Export*);
|
||||
|
||||
static char* Exauth(Export*, Fcall*);
|
||||
static char* Exattach(Export*, Fcall*);
|
||||
static char* Exclunk(Export*, Fcall*);
|
||||
static char* Excreate(Export*, Fcall*);
|
||||
static char* Exopen(Export*, Fcall*);
|
||||
static char* Exread(Export*, Fcall*);
|
||||
static char* Exremove(Export*, Fcall*);
|
||||
static char* Exstat(Export*, Fcall*);
|
||||
static char* Exwalk(Export*, Fcall*);
|
||||
static char* Exwrite(Export*, Fcall*);
|
||||
static char* Exwstat(Export*, Fcall*);
|
||||
static char* Exversion(Export*, Fcall*);
|
||||
|
||||
static char *(*fcalls[Tmax])(Export*, Fcall*);
|
||||
|
||||
static char Enofid[] = "no such fid";
|
||||
static char Eseekdir[] = "can't seek on a directory";
|
||||
static char Ereaddir[] = "unaligned read of a directory";
|
||||
static int exdebug = 0;
|
||||
|
||||
int
|
||||
sysexport(int fd)
|
||||
{
|
||||
Chan *c;
|
||||
Export *fs;
|
||||
|
||||
if(waserror())
|
||||
return -1;
|
||||
|
||||
c = fdtochan(fd, ORDWR, 1, 1);
|
||||
poperror();
|
||||
c->flag |= CMSG;
|
||||
|
||||
fs = mallocz(sizeof(Export));
|
||||
fs->r.ref = 1;
|
||||
fs->pgrp = up->pgrp;
|
||||
refinc(&fs->pgrp->r);
|
||||
refinc(&up->slash->r);
|
||||
fs->root = up->slash;
|
||||
refinc(&fs->root->r);
|
||||
fs->root = domount(fs->root);
|
||||
fs->io = c;
|
||||
|
||||
exportproc(fs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
exportinit(void)
|
||||
{
|
||||
lock(&exq.l);
|
||||
if(fcalls[Tversion] != nil) {
|
||||
unlock(&exq.l);
|
||||
return;
|
||||
}
|
||||
|
||||
fmtinstall('F', fcallfmt);
|
||||
fmtinstall('D', dirfmt);
|
||||
fmtinstall('M', dirmodefmt);
|
||||
fcalls[Tversion] = Exversion;
|
||||
fcalls[Tauth] = Exauth;
|
||||
fcalls[Tattach] = Exattach;
|
||||
fcalls[Twalk] = Exwalk;
|
||||
fcalls[Topen] = Exopen;
|
||||
fcalls[Tcreate] = Excreate;
|
||||
fcalls[Tread] = Exread;
|
||||
fcalls[Twrite] = Exwrite;
|
||||
fcalls[Tclunk] = Exclunk;
|
||||
fcalls[Tremove] = Exremove;
|
||||
fcalls[Tstat] = Exstat;
|
||||
fcalls[Twstat] = Exwstat;
|
||||
unlock(&exq.l);
|
||||
}
|
||||
|
||||
void
|
||||
exportproc(Export *fs)
|
||||
{
|
||||
Exq *q;
|
||||
char *buf;
|
||||
int n, cn, len;
|
||||
|
||||
exportinit();
|
||||
|
||||
for(;;){
|
||||
q = mallocz(sizeof(Exq));
|
||||
if(q == 0)
|
||||
panic("no memory");
|
||||
|
||||
q->rpc.data = q->buf + MAXMSG;
|
||||
|
||||
buf = q->buf;
|
||||
len = MAXRPC;
|
||||
if(fs->npart) {
|
||||
memmove(buf, fs->part, fs->npart);
|
||||
buf += fs->npart;
|
||||
len -= fs->npart;
|
||||
goto chk;
|
||||
}
|
||||
for(;;) {
|
||||
if(waserror())
|
||||
goto bad;
|
||||
|
||||
n = (*devtab[fs->io->type].read)(fs->io, buf, len, 0);
|
||||
poperror();
|
||||
|
||||
if(n <= 0)
|
||||
goto bad;
|
||||
|
||||
buf += n;
|
||||
len -= n;
|
||||
chk:
|
||||
n = buf - q->buf;
|
||||
|
||||
/* convM2S returns size of correctly decoded message */
|
||||
cn = convM2S(q->buf, &q->rpc, n);
|
||||
if(cn < 0){
|
||||
iprint("bad message type in devmnt\n");
|
||||
goto bad;
|
||||
}
|
||||
if(cn > 0) {
|
||||
n -= cn;
|
||||
if(n < 0){
|
||||
iprint("negative size in devmnt");
|
||||
goto bad;
|
||||
}
|
||||
fs->npart = n;
|
||||
if(n != 0)
|
||||
memmove(fs->part, q->buf+cn, n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(exdebug)
|
||||
iprint("export %d <- %F\n", getpid(), &q->rpc);
|
||||
|
||||
if(q->rpc.type == Tflush){
|
||||
exflush(fs, q->rpc.tag, q->rpc.oldtag);
|
||||
free(q);
|
||||
continue;
|
||||
}
|
||||
|
||||
q->export = fs;
|
||||
refinc(&fs->r);
|
||||
|
||||
lock(&exq.l);
|
||||
if(exq.head == nil)
|
||||
exq.head = q;
|
||||
else
|
||||
exq.tail->next = q;
|
||||
q->next = nil;
|
||||
exq.tail = q;
|
||||
unlock(&exq.l);
|
||||
if(exq.qwait.first == nil) {
|
||||
n = thread("exportfs", exslave, nil);
|
||||
/* iprint("launch export (pid=%ux)\n", n); */
|
||||
}
|
||||
rendwakeup(&exq.rwait);
|
||||
}
|
||||
bad:
|
||||
free(q);
|
||||
exshutdown(fs);
|
||||
exfree(fs);
|
||||
}
|
||||
|
||||
void
|
||||
exflush(Export *fs, int flushtag, int tag)
|
||||
{
|
||||
Exq *q, **last;
|
||||
int n;
|
||||
Fcall fc;
|
||||
char buf[MAXMSG];
|
||||
|
||||
/* hasn't been started? */
|
||||
lock(&exq.l);
|
||||
last = &exq.head;
|
||||
for(q = exq.head; q != nil; q = q->next){
|
||||
if(q->export == fs && q->rpc.tag == tag){
|
||||
*last = q->next;
|
||||
unlock(&exq.l);
|
||||
exfree(fs);
|
||||
free(q);
|
||||
goto Respond;
|
||||
}
|
||||
last = &q->next;
|
||||
}
|
||||
unlock(&exq.l);
|
||||
|
||||
/* in progress? */
|
||||
lock(&fs->r.l);
|
||||
for(q = fs->work; q != nil; q = q->next){
|
||||
if(q->rpc.tag == tag && !q->noresponse){
|
||||
lock(&q->lk);
|
||||
q->noresponse = 1;
|
||||
if(!q->nointr)
|
||||
intr(q->slave);
|
||||
unlock(&q->lk);
|
||||
unlock(&fs->r.l);
|
||||
goto Respond;
|
||||
return;
|
||||
}
|
||||
}
|
||||
unlock(&fs->r.l);
|
||||
|
||||
if(exdebug) iprint("exflush: did not find rpc: %d\n", tag);
|
||||
|
||||
Respond:
|
||||
fc.type = Rflush;
|
||||
fc.tag = flushtag;
|
||||
n = convS2M(&fc, buf);
|
||||
if(exdebug) iprint("exflush -> %F\n", &fc);
|
||||
if(!waserror()){
|
||||
(*devtab[fs->io->type].write)(fs->io, buf, n, 0);
|
||||
poperror();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
exshutdown(Export *fs)
|
||||
{
|
||||
Exq *q, **last;
|
||||
|
||||
lock(&exq.l);
|
||||
last = &exq.head;
|
||||
for(q = exq.head; q != nil; q = *last){
|
||||
if(q->export == fs){
|
||||
*last = q->next;
|
||||
exfree(fs);
|
||||
free(q);
|
||||
continue;
|
||||
}
|
||||
last = &q->next;
|
||||
}
|
||||
unlock(&exq.l);
|
||||
|
||||
lock(&fs->r.l);
|
||||
q = fs->work;
|
||||
while(q != nil){
|
||||
if(q->shut){
|
||||
q = q->next;
|
||||
continue;
|
||||
}
|
||||
q->shut = 1;
|
||||
unlock(&fs->r.l);
|
||||
/* postnote(q->slave, 1, "interrupted", NUser); */
|
||||
iprint("postnote 2!\n");
|
||||
lock(&fs->r.l);
|
||||
q = fs->work;
|
||||
}
|
||||
unlock(&fs->r.l);
|
||||
}
|
||||
|
||||
void
|
||||
exfree(Export *fs)
|
||||
{
|
||||
Fid *f, *n;
|
||||
int i;
|
||||
|
||||
if(refdec(&fs->r) != 0)
|
||||
return;
|
||||
closepgrp(fs->pgrp);
|
||||
cclose(fs->root);
|
||||
cclose(fs->io);
|
||||
for(i = 0; i < Nfidhash; i++){
|
||||
for(f = fs->fid[i]; f != nil; f = n){
|
||||
if(f->chan != nil)
|
||||
cclose(f->chan);
|
||||
n = f->next;
|
||||
free(f);
|
||||
}
|
||||
}
|
||||
free(fs);
|
||||
}
|
||||
|
||||
int
|
||||
exwork(void *a)
|
||||
{
|
||||
return exq.head != nil;
|
||||
}
|
||||
|
||||
void
|
||||
exslave(void *a)
|
||||
{
|
||||
Export *fs;
|
||||
Exq *q, *t, **last;
|
||||
char *err;
|
||||
int n;
|
||||
/*
|
||||
closepgrp(up->pgrp);
|
||||
up->pgrp = nil;
|
||||
*/
|
||||
for(;;){
|
||||
qlock(&exq.qwait);
|
||||
rendsleep(&exq.rwait, exwork, nil);
|
||||
|
||||
lock(&exq.l);
|
||||
q = exq.head;
|
||||
if(q == nil) {
|
||||
unlock(&exq.l);
|
||||
qunlock(&exq.qwait);
|
||||
continue;
|
||||
}
|
||||
exq.head = q->next;
|
||||
q->slave = curthread();
|
||||
unlock(&exq.l);
|
||||
|
||||
qunlock(&exq.qwait);
|
||||
|
||||
q->noresponse = 0;
|
||||
q->nointr = 0;
|
||||
fs = q->export;
|
||||
lock(&fs->r.l);
|
||||
q->next = fs->work;
|
||||
fs->work = q;
|
||||
unlock(&fs->r.l);
|
||||
|
||||
up->pgrp = q->export->pgrp;
|
||||
|
||||
if(exdebug > 1)
|
||||
iprint("exslave dispatch %d %F\n", getpid(), &q->rpc);
|
||||
|
||||
if(waserror()){
|
||||
iprint("exslave err %r\n");
|
||||
err = up->errstr;
|
||||
goto Err;
|
||||
}
|
||||
if(q->rpc.type >= Tmax || !fcalls[q->rpc.type])
|
||||
err = "bad fcall type";
|
||||
else
|
||||
err = (*fcalls[q->rpc.type])(fs, &q->rpc);
|
||||
|
||||
poperror();
|
||||
Err:;
|
||||
q->rpc.type++;
|
||||
if(err){
|
||||
q->rpc.type = Rerror;
|
||||
strncpy(q->rpc.ename, err, ERRLEN);
|
||||
}
|
||||
n = convS2M(&q->rpc, q->buf);
|
||||
|
||||
if(exdebug)
|
||||
iprint("exslve %d -> %F\n", getpid(), &q->rpc);
|
||||
|
||||
lock(&q->lk);
|
||||
if(q->noresponse == 0){
|
||||
q->nointr = 1;
|
||||
clearintr();
|
||||
if(!waserror()){
|
||||
(*devtab[fs->io->type].write)(fs->io, q->buf, n, 0);
|
||||
poperror();
|
||||
}
|
||||
}
|
||||
unlock(&q->lk);
|
||||
|
||||
/*
|
||||
* exflush might set noresponse at this point, but
|
||||
* setting noresponse means don't send a response now;
|
||||
* it's okay that we sent a response already.
|
||||
*/
|
||||
if(exdebug > 1)
|
||||
iprint("exslave %d written %d\n", getpid(), q->rpc.tag);
|
||||
|
||||
lock(&fs->r.l);
|
||||
last = &fs->work;
|
||||
for(t = fs->work; t != nil; t = t->next){
|
||||
if(t == q){
|
||||
*last = q->next;
|
||||
break;
|
||||
}
|
||||
last = &t->next;
|
||||
}
|
||||
unlock(&fs->r.l);
|
||||
|
||||
exfree(q->export);
|
||||
free(q);
|
||||
}
|
||||
iprint("exslave shut down");
|
||||
threadexit();
|
||||
}
|
||||
|
||||
Fid*
|
||||
Exmkfid(Export *fs, int fid)
|
||||
{
|
||||
ulong h;
|
||||
Fid *f, *nf;
|
||||
|
||||
nf = mallocz(sizeof(Fid));
|
||||
if(nf == nil)
|
||||
return nil;
|
||||
lock(&fs->fidlock);
|
||||
h = fid % Nfidhash;
|
||||
for(f = fs->fid[h]; f != nil; f = f->next){
|
||||
if(f->fid == fid){
|
||||
unlock(&fs->fidlock);
|
||||
free(nf);
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
nf->next = fs->fid[h];
|
||||
if(nf->next != nil)
|
||||
nf->next->last = &nf->next;
|
||||
nf->last = &fs->fid[h];
|
||||
fs->fid[h] = nf;
|
||||
|
||||
nf->fid = fid;
|
||||
nf->ref = 1;
|
||||
nf->attached = 1;
|
||||
nf->offset = 0;
|
||||
nf->chan = nil;
|
||||
unlock(&fs->fidlock);
|
||||
return nf;
|
||||
}
|
||||
|
||||
Fid*
|
||||
Exgetfid(Export *fs, int fid)
|
||||
{
|
||||
Fid *f;
|
||||
ulong h;
|
||||
|
||||
lock(&fs->fidlock);
|
||||
h = fid % Nfidhash;
|
||||
for(f = fs->fid[h]; f; f = f->next) {
|
||||
if(f->fid == fid){
|
||||
if(f->attached == 0)
|
||||
break;
|
||||
f->ref++;
|
||||
unlock(&fs->fidlock);
|
||||
return f;
|
||||
}
|
||||
}
|
||||
unlock(&fs->fidlock);
|
||||
return nil;
|
||||
}
|
||||
|
||||
void
|
||||
Exputfid(Export *fs, Fid *f)
|
||||
{
|
||||
lock(&fs->fidlock);
|
||||
f->ref--;
|
||||
if(f->ref == 0 && f->attached == 0){
|
||||
if(f->chan != nil)
|
||||
cclose(f->chan);
|
||||
f->chan = nil;
|
||||
*f->last = f->next;
|
||||
if(f->next != nil)
|
||||
f->next->last = f->last;
|
||||
unlock(&fs->fidlock);
|
||||
free(f);
|
||||
return;
|
||||
}
|
||||
unlock(&fs->fidlock);
|
||||
}
|
||||
|
||||
char*
|
||||
Exsession(Export *e, Fcall *rpc)
|
||||
{
|
||||
memset(rpc->authid, 0, sizeof(rpc->authid));
|
||||
memset(rpc->authdom, 0, sizeof(rpc->authdom));
|
||||
memset(rpc->chal, 0, sizeof(rpc->chal));
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
Exauth(Export *e, Fcall *f)
|
||||
{
|
||||
return "authentication not required";
|
||||
}
|
||||
|
||||
char*
|
||||
Exattach(Export *fs, Fcall *rpc)
|
||||
{
|
||||
Fid *f;
|
||||
|
||||
f = Exmkfid(fs, rpc->fid);
|
||||
if(f == nil)
|
||||
return Einuse;
|
||||
if(waserror()){
|
||||
f->attached = 0;
|
||||
Exputfid(fs, f);
|
||||
return up->errstr;
|
||||
}
|
||||
f->chan = clone(fs->root, nil);
|
||||
poperror();
|
||||
rpc->qid = f->chan->qid;
|
||||
Exputfid(fs, f);
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
Exclone(Export *fs, Fcall *rpc)
|
||||
{
|
||||
Fid *f, *nf;
|
||||
|
||||
if(rpc->fid == rpc->newfid)
|
||||
return Einuse;
|
||||
f = Exgetfid(fs, rpc->fid);
|
||||
if(f == nil)
|
||||
return Enofid;
|
||||
nf = Exmkfid(fs, rpc->newfid);
|
||||
if(nf == nil){
|
||||
Exputfid(fs, f);
|
||||
return Einuse;
|
||||
}
|
||||
if(waserror()){
|
||||
Exputfid(fs, f);
|
||||
Exputfid(fs, nf);
|
||||
return up->errstr;
|
||||
}
|
||||
nf->chan = clone(f->chan, nil);
|
||||
poperror();
|
||||
Exputfid(fs, f);
|
||||
Exputfid(fs, nf);
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
Exclunk(Export *fs, Fcall *rpc)
|
||||
{
|
||||
Fid *f;
|
||||
|
||||
f = Exgetfid(fs, rpc->fid);
|
||||
if(f != nil){
|
||||
f->attached = 0;
|
||||
Exputfid(fs, f);
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
Exwalk(Export *fs, Fcall *rpc)
|
||||
{
|
||||
Fid *f;
|
||||
Chan *c;
|
||||
|
||||
f = Exgetfid(fs, rpc->fid);
|
||||
if(f == nil)
|
||||
return Enofid;
|
||||
if(waserror()){
|
||||
Exputfid(fs, f);
|
||||
return up->errstr;
|
||||
}
|
||||
c = walk(f->chan, rpc->name, 1);
|
||||
if(c == nil)
|
||||
error(Enonexist);
|
||||
poperror();
|
||||
|
||||
f->chan = c;
|
||||
rpc->qid = c->qid;
|
||||
Exputfid(fs, f);
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
Exopen(Export *fs, Fcall *rpc)
|
||||
{
|
||||
Fid *f;
|
||||
Chan *c;
|
||||
|
||||
f = Exgetfid(fs, rpc->fid);
|
||||
if(f == nil)
|
||||
return Enofid;
|
||||
if(waserror()){
|
||||
Exputfid(fs, f);
|
||||
return up->errstr;
|
||||
}
|
||||
c = f->chan;
|
||||
c = (*devtab[c->type].open)(c, rpc->mode);
|
||||
poperror();
|
||||
|
||||
f->chan = c;
|
||||
f->offset = 0;
|
||||
rpc->qid = f->chan->qid;
|
||||
Exputfid(fs, f);
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
Excreate(Export *fs, Fcall *rpc)
|
||||
{
|
||||
Fid *f;
|
||||
Chan *c;
|
||||
|
||||
f = Exgetfid(fs, rpc->fid);
|
||||
if(f == nil)
|
||||
return Enofid;
|
||||
if(waserror()){
|
||||
Exputfid(fs, f);
|
||||
return up->errstr;
|
||||
}
|
||||
c = f->chan;
|
||||
if(c->mnt && !(c->flag&CCREATE))
|
||||
c = createdir(c);
|
||||
(*devtab[c->type].create)(c, rpc->name, rpc->mode, rpc->perm);
|
||||
poperror();
|
||||
|
||||
f->chan = c;
|
||||
rpc->qid = f->chan->qid;
|
||||
Exputfid(fs, f);
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
Exread(Export *fs, Fcall *rpc)
|
||||
{
|
||||
Fid *f;
|
||||
Chan *c;
|
||||
long off;
|
||||
int dir, n, seek;
|
||||
|
||||
f = Exgetfid(fs, rpc->fid);
|
||||
if(f == nil)
|
||||
return Enofid;
|
||||
|
||||
c = f->chan;
|
||||
dir = c->qid.path & CHDIR;
|
||||
if(dir){
|
||||
rpc->count -= rpc->count%DIRLEN;
|
||||
if(rpc->offset%DIRLEN || rpc->count==0){
|
||||
Exputfid(fs, f);
|
||||
return Ereaddir;
|
||||
}
|
||||
if(f->offset > rpc->offset){
|
||||
Exputfid(fs, f);
|
||||
return Eseekdir;
|
||||
}
|
||||
}
|
||||
|
||||
if(waserror()) {
|
||||
Exputfid(fs, f);
|
||||
return up->errstr;
|
||||
}
|
||||
|
||||
for(;;){
|
||||
n = rpc->count;
|
||||
seek = 0;
|
||||
off = rpc->offset;
|
||||
if(dir && f->offset != off){
|
||||
off = f->offset;
|
||||
n = rpc->offset - off;
|
||||
if(n > MAXDIRREAD)
|
||||
n = MAXDIRREAD;
|
||||
seek = 1;
|
||||
}
|
||||
if(dir && c->mnt != nil)
|
||||
n = unionread(c, rpc->data, n);
|
||||
else{
|
||||
c->offset = off;
|
||||
n = (*devtab[c->type].read)(c, rpc->data, n, off);
|
||||
}
|
||||
if(n == 0 || !seek)
|
||||
break;
|
||||
f->offset = off + n;
|
||||
c->offset += n;
|
||||
}
|
||||
rpc->count = n;
|
||||
poperror();
|
||||
Exputfid(fs, f);
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
Exwrite(Export *fs, Fcall *rpc)
|
||||
{
|
||||
Fid *f;
|
||||
Chan *c;
|
||||
|
||||
f = Exgetfid(fs, rpc->fid);
|
||||
if(f == nil)
|
||||
return Enofid;
|
||||
if(waserror()){
|
||||
Exputfid(fs, f);
|
||||
return up->errstr;
|
||||
}
|
||||
c = f->chan;
|
||||
if(c->qid.path & CHDIR)
|
||||
error(Eisdir);
|
||||
rpc->count = (*devtab[c->type].write)(c, rpc->data, rpc->count, rpc->offset);
|
||||
poperror();
|
||||
Exputfid(fs, f);
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
Exstat(Export *fs, Fcall *rpc)
|
||||
{
|
||||
Fid *f;
|
||||
Chan *c;
|
||||
|
||||
f = Exgetfid(fs, rpc->fid);
|
||||
if(f == nil)
|
||||
return Enofid;
|
||||
if(waserror()){
|
||||
Exputfid(fs, f);
|
||||
return up->errstr;
|
||||
}
|
||||
c = f->chan;
|
||||
(*devtab[c->type].stat)(c, rpc->stat);
|
||||
poperror();
|
||||
Exputfid(fs, f);
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
Exwstat(Export *fs, Fcall *rpc)
|
||||
{
|
||||
Fid *f;
|
||||
Chan *c;
|
||||
|
||||
f = Exgetfid(fs, rpc->fid);
|
||||
if(f == nil)
|
||||
return Enofid;
|
||||
if(waserror()){
|
||||
Exputfid(fs, f);
|
||||
return up->errstr;
|
||||
}
|
||||
c = f->chan;
|
||||
(*devtab[c->type].wstat)(c, rpc->stat);
|
||||
poperror();
|
||||
Exputfid(fs, f);
|
||||
return nil;
|
||||
}
|
||||
|
||||
char*
|
||||
Exremove(Export *fs, Fcall *rpc)
|
||||
{
|
||||
Fid *f;
|
||||
Chan *c;
|
||||
|
||||
f = Exgetfid(fs, rpc->fid);
|
||||
if(f == nil)
|
||||
return Enofid;
|
||||
if(waserror()){
|
||||
Exputfid(fs, f);
|
||||
return up->errstr;
|
||||
}
|
||||
c = f->chan;
|
||||
(*devtab[c->type].remove)(c);
|
||||
poperror();
|
||||
|
||||
/*
|
||||
* chan is already clunked by remove.
|
||||
* however, we need to recover the chan,
|
||||
* and follow sysremove's lead in making to point to root.
|
||||
*/
|
||||
c->type = 0;
|
||||
|
||||
f->attached = 0;
|
||||
Exputfid(fs, f);
|
||||
return nil;
|
||||
}
|
377
kern/fns.h
Normal file
377
kern/fns.h
Normal file
@ -0,0 +1,377 @@
|
||||
#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1))
|
||||
|
||||
void accounttime(void);
|
||||
void addclock0link(void (*)(void), int);
|
||||
int addphysseg(Physseg*);
|
||||
void addbootfile(char*, uchar*, ulong);
|
||||
Block* adjustblock(Block*, int);
|
||||
void alarmkproc(void*);
|
||||
Block* allocb(int);
|
||||
int anyhigher(void);
|
||||
int anyready(void);
|
||||
Page* auxpage(void);
|
||||
Block* bl2mem(uchar*, Block*, int);
|
||||
int blocklen(Block*);
|
||||
void callwithureg(void(*)(Ureg*));
|
||||
char* c2name(Chan*);
|
||||
int cangetc(void*);
|
||||
int canlock(Lock*);
|
||||
int canpage(Proc*);
|
||||
int canputc(void*);
|
||||
int canqlock(QLock*);
|
||||
int canrlock(RWlock*);
|
||||
void chandevinit(void);
|
||||
void chandevreset(void);
|
||||
void chandevshutdown(void);
|
||||
void chanfree(Chan*);
|
||||
void chanrec(Mnt*);
|
||||
void checkalarms(void);
|
||||
void checkb(Block*, char*);
|
||||
void cinit(void);
|
||||
Chan* cclone(Chan*);
|
||||
void cclose(Chan*);
|
||||
char* clipread(void);
|
||||
int clipwrite(char*);
|
||||
void closeegrp(Egrp*);
|
||||
void closefgrp(Fgrp*);
|
||||
void closemount(Mount*);
|
||||
void closepgrp(Pgrp*);
|
||||
void closergrp(Rgrp*);
|
||||
long clrfpintr(void);
|
||||
void cmderror(Cmdbuf*, char*);
|
||||
int cmount(Chan**, Chan*, int, char*);
|
||||
void cnameclose(Cname*);
|
||||
void confinit(void);
|
||||
void confinit1(int);
|
||||
int consactive(void);
|
||||
void (*consdebug)(void);
|
||||
void copen(Chan*);
|
||||
Block* concatblock(Block*);
|
||||
Block* copyblock(Block*, int);
|
||||
void copypage(Page*, Page*);
|
||||
int cread(Chan*, uchar*, int, vlong);
|
||||
void cunmount(Chan*, Chan*);
|
||||
void cupdate(Chan*, uchar*, int, vlong);
|
||||
void cwrite(Chan*, uchar*, int, vlong);
|
||||
ulong dbgpc(Proc*);
|
||||
int decref(Ref*);
|
||||
int decrypt(void*, void*, int);
|
||||
void delay(int);
|
||||
Chan* devattach(int, char*);
|
||||
Block* devbread(Chan*, long, ulong);
|
||||
long devbwrite(Chan*, Block*, ulong);
|
||||
Chan* devclone(Chan*);
|
||||
int devconfig(int, char *, DevConf *);
|
||||
void devcreate(Chan*, char*, int, ulong);
|
||||
void devdir(Chan*, Qid, char*, vlong, char*, long, Dir*);
|
||||
long devdirread(Chan*, char*, long, Dirtab*, int, Devgen*);
|
||||
Devgen devgen;
|
||||
void devinit(void);
|
||||
int devno(int, int);
|
||||
Chan* devopen(Chan*, int, Dirtab*, int, Devgen*);
|
||||
void devpermcheck(char*, ulong, int);
|
||||
void devpower(int);
|
||||
void devremove(Chan*);
|
||||
void devreset(void);
|
||||
void devshutdown(void);
|
||||
int devstat(Chan*, uchar*, int, Dirtab*, int, Devgen*);
|
||||
Walkqid* devwalk(Chan*, Chan*, char**, int, Dirtab*, int, Devgen*);
|
||||
int devwstat(Chan*, uchar*, int);
|
||||
void drawactive(int);
|
||||
void drawcmap(void);
|
||||
void dumpaproc(Proc*);
|
||||
void dumpqueues(void);
|
||||
void dumpregs(Ureg*);
|
||||
void dumpstack(void);
|
||||
Fgrp* dupfgrp(Fgrp*);
|
||||
void duppage(Page*);
|
||||
void dupswap(Page*);
|
||||
int emptystr(char*);
|
||||
int encrypt(void*, void*, int);
|
||||
void envcpy(Egrp*, Egrp*);
|
||||
int eqchan(Chan*, Chan*, int);
|
||||
int eqqid(Qid, Qid);
|
||||
void error(char*);
|
||||
long execregs(ulong, ulong, ulong);
|
||||
void exhausted(char*);
|
||||
void exit(int);
|
||||
uvlong fastticks(uvlong*);
|
||||
int fault(ulong, int);
|
||||
void fdclose(int, int);
|
||||
Chan* fdtochan(int, int, int, int);
|
||||
int fixfault(Segment*, ulong, int, int);
|
||||
void flushmmu(void);
|
||||
void forkchild(Proc*, Ureg*);
|
||||
void forkret(void);
|
||||
void free(void*);
|
||||
void freeb(Block*);
|
||||
void freeblist(Block*);
|
||||
int freebroken(void);
|
||||
void freepte(Segment*, Pte*);
|
||||
void freesegs(int);
|
||||
void freesession(Session*);
|
||||
ulong getmalloctag(void*);
|
||||
ulong getrealloctag(void*);
|
||||
void gotolabel(Label*);
|
||||
char* getconfenv(void);
|
||||
int haswaitq(void*);
|
||||
long hostdomainwrite(char*, int);
|
||||
long hostownerwrite(char*, int);
|
||||
void hzsched(void);
|
||||
void iallocinit(void);
|
||||
Block* iallocb(int);
|
||||
void iallocsummary(void);
|
||||
long ibrk(ulong, int);
|
||||
void ilock(Lock*);
|
||||
void iunlock(Lock*);
|
||||
int incref(Ref*);
|
||||
void initseg(void);
|
||||
int iprint(char*, ...);
|
||||
void isdir(Chan*);
|
||||
int iseve(void);
|
||||
#define islo() (0)
|
||||
Segment* isoverlap(Proc*, ulong, int);
|
||||
int ispages(void*);
|
||||
int isphysseg(char*);
|
||||
void ixsummary(void);
|
||||
void kbdclock(void);
|
||||
int kbdcr2nl(Queue*, int);
|
||||
int kbdputc(Queue*, int);
|
||||
void kbdrepeat(int);
|
||||
long keyread(char*, int, long);
|
||||
void kickpager(void);
|
||||
void killbig(void);
|
||||
int kproc(char*, void(*)(void*), void*);
|
||||
void kprocchild(Proc*, void (*)(void*), void*);
|
||||
void (*kproftimer)(ulong);
|
||||
void ksetenv(char*, char*, int);
|
||||
void kstrcpy(char*, char*, int);
|
||||
void kstrdup(char**, char*);
|
||||
long latin1(Rune*, int);
|
||||
int lock(Lock*);
|
||||
void lockinit(void);
|
||||
void logopen(Log*);
|
||||
void logclose(Log*);
|
||||
char* logctl(Log*, int, char**, Logflag*);
|
||||
void logn(Log*, int, void*, int);
|
||||
long logread(Log*, void*, ulong, long);
|
||||
void log(Log*, int, char*, ...);
|
||||
Cmdtab* lookupcmd(Cmdbuf*, Cmdtab*, int);
|
||||
void machinit(void);
|
||||
void* mallocz(ulong, int);
|
||||
#define malloc kmalloc
|
||||
void* malloc(ulong);
|
||||
void mallocsummary(void);
|
||||
Block* mem2bl(uchar*, int);
|
||||
void mfreeseg(Segment*, ulong, int);
|
||||
void microdelay(int);
|
||||
void mkqid(Qid*, vlong, ulong, int);
|
||||
void mmurelease(Proc*);
|
||||
void mmuswitch(Proc*);
|
||||
Chan* mntauth(Chan*, char*);
|
||||
void mntdump(void);
|
||||
long mntversion(Chan*, char*, int, int);
|
||||
void mountfree(Mount*);
|
||||
ulong ms2tk(ulong);
|
||||
ulong msize(void*);
|
||||
ulong ms2tk(ulong);
|
||||
uvlong ms2fastticks(ulong);
|
||||
void muxclose(Mnt*);
|
||||
Chan* namec(char*, int, int, ulong);
|
||||
Chan* newchan(void);
|
||||
int newfd(Chan*);
|
||||
Mhead* newmhead(Chan*);
|
||||
Mount* newmount(Mhead*, Chan*, int, char*);
|
||||
Page* newpage(int, Segment **, ulong);
|
||||
Pgrp* newpgrp(void);
|
||||
Rgrp* newrgrp(void);
|
||||
Proc* newproc(void);
|
||||
char* nextelem(char*, char*);
|
||||
void nexterror(void);
|
||||
Cname* newcname(char*);
|
||||
int notify(Ureg*);
|
||||
int nrand(int);
|
||||
int okaddr(ulong, ulong, int);
|
||||
int openmode(ulong);
|
||||
Block* packblock(Block*);
|
||||
Block* padblock(Block*, int);
|
||||
void pagechainhead(Page*);
|
||||
void pageinit(void);
|
||||
void pagersummary(void);
|
||||
void panic(char*, ...);
|
||||
Cmdbuf* parsecmd(char *a, int n);
|
||||
ulong perfticks(void);
|
||||
void pexit(char*, int);
|
||||
int preempted(void);
|
||||
void printinit(void);
|
||||
int procindex(ulong);
|
||||
void pgrpcpy(Pgrp*, Pgrp*);
|
||||
void pgrpnote(ulong, char*, long, int);
|
||||
Pgrp* pgrptab(int);
|
||||
void pio(Segment *, ulong, ulong, Page **);
|
||||
#define poperror() up->nerrlab--
|
||||
void portclock(Ureg*);
|
||||
int postnote(Proc*, int, char*, int);
|
||||
int pprint(char*, ...);
|
||||
void prflush(void);
|
||||
ulong procalarm(ulong);
|
||||
int proccounter(char *name);
|
||||
void procctl(Proc*);
|
||||
void procdump(void);
|
||||
int procfdprint(Chan*, int, int, char*, int);
|
||||
void procinit0(void);
|
||||
void procflushseg(Segment*);
|
||||
void procpriority(Proc*, int, int);
|
||||
Proc* proctab(int);
|
||||
void procwired(Proc*, int);
|
||||
Pte* ptealloc(void);
|
||||
Pte* ptecpy(Pte*);
|
||||
int pullblock(Block**, int);
|
||||
Block* pullupblock(Block*, int);
|
||||
Block* pullupqueue(Queue*, int);
|
||||
void putmhead(Mhead*);
|
||||
void putmmu(ulong, ulong, Page*);
|
||||
void putpage(Page*);
|
||||
void putseg(Segment*);
|
||||
void putstr(char*);
|
||||
void putstrn(char*, int);
|
||||
void putswap(Page*);
|
||||
ulong pwait(Waitmsg*);
|
||||
Label* pwaserror(void);
|
||||
void qaddlist(Queue*, Block*);
|
||||
Block* qbread(Queue*, int);
|
||||
long qbwrite(Queue*, Block*);
|
||||
Queue* qbypass(void (*)(void*, Block*), void*);
|
||||
int qcanread(Queue*);
|
||||
void qclose(Queue*);
|
||||
int qconsume(Queue*, void*, int);
|
||||
Block* qcopy(Queue*, int, ulong);
|
||||
int qdiscard(Queue*, int);
|
||||
void qflush(Queue*);
|
||||
void qfree(Queue*);
|
||||
int qfull(Queue*);
|
||||
Block* qget(Queue*);
|
||||
void qhangup(Queue*, char*);
|
||||
int qisclosed(Queue*);
|
||||
void qinit(void);
|
||||
int qiwrite(Queue*, void*, int);
|
||||
int qlen(Queue*);
|
||||
void qlock(QLock*);
|
||||
Queue* qopen(int, int, void (*)(void*), void*);
|
||||
int qpass(Queue*, Block*);
|
||||
int qpassnolim(Queue*, Block*);
|
||||
int qproduce(Queue*, void*, int);
|
||||
void qputback(Queue*, Block*);
|
||||
long qread(Queue*, void*, int);
|
||||
Block* qremove(Queue*);
|
||||
void qreopen(Queue*);
|
||||
void qsetlimit(Queue*, int);
|
||||
void qunlock(QLock*);
|
||||
int qwindow(Queue*);
|
||||
int qwrite(Queue*, void*, int);
|
||||
void qnoblock(Queue*, int);
|
||||
int rand(void);
|
||||
void randominit(void);
|
||||
ulong randomread(void*, ulong);
|
||||
void rdb(void);
|
||||
int readnum(ulong, char*, ulong, ulong, int);
|
||||
int readstr(ulong, char*, ulong, char*);
|
||||
void ready(Proc*);
|
||||
void rebootcmd(int, char**);
|
||||
void reboot(void*, void*, ulong);
|
||||
void relocateseg(Segment*, ulong);
|
||||
void renameuser(char*, char*);
|
||||
void resched(char*);
|
||||
void resrcwait(char*);
|
||||
int return0(void*);
|
||||
void rlock(RWlock*);
|
||||
long rtctime(void);
|
||||
void runlock(RWlock*);
|
||||
Proc* runproc(void);
|
||||
void savefpregs(FPsave*);
|
||||
void (*saveintrts)(void);
|
||||
void sched(void);
|
||||
void scheddump(void);
|
||||
void schedinit(void);
|
||||
void (*screenputs)(char*, int);
|
||||
long seconds(void);
|
||||
ulong segattach(Proc*, ulong, char *, ulong, ulong);
|
||||
void segclock(ulong);
|
||||
void segpage(Segment*, Page*);
|
||||
void setkernur(Ureg*, Proc*);
|
||||
int setlabel(Label*);
|
||||
void setmalloctag(void*, ulong);
|
||||
void setrealloctag(void*, ulong);
|
||||
void setregisters(Ureg*, char*, char*, int);
|
||||
void setswapchan(Chan*);
|
||||
char* skipslash(char*);
|
||||
void sleep(Rendez*, int(*)(void*), void*);
|
||||
void* smalloc(ulong);
|
||||
int splhi(void);
|
||||
int spllo(void);
|
||||
void splx(int);
|
||||
void splxpc(int);
|
||||
char* srvname(Chan*);
|
||||
int swapcount(ulong);
|
||||
int swapfull(void);
|
||||
void swapinit(void);
|
||||
void timeradd(Timer*);
|
||||
void timerdel(Timer*);
|
||||
void timersinit(void);
|
||||
void timerintr(Ureg*, uvlong);
|
||||
void timerset(uvlong);
|
||||
ulong tk2ms(ulong);
|
||||
#define TK2MS(x) ((x)*(1000/HZ))
|
||||
vlong todget(vlong*);
|
||||
void todfix(void);
|
||||
void todsetfreq(vlong);
|
||||
void todinit(void);
|
||||
void todset(vlong, vlong, int);
|
||||
Block* trimblock(Block*, int, int);
|
||||
void tsleep(Rendez*, int (*)(void*), void*, int);
|
||||
int uartctl(Uart*, char*);
|
||||
int uartgetc(void);
|
||||
void uartkick(void*);
|
||||
void uartmouse(Uart*, int (*)(Queue*, int), int);
|
||||
void uartputc(int);
|
||||
void uartputs(char*, int);
|
||||
void uartrecv(Uart*, char);
|
||||
Uart* uartsetup(Uart*);
|
||||
int uartstageoutput(Uart*);
|
||||
void unbreak(Proc*);
|
||||
void uncachepage(Page*);
|
||||
long unionread(Chan*, void*, long);
|
||||
void unlock(Lock*);
|
||||
Proc** uploc(void);
|
||||
void userinit(void);
|
||||
ulong userpc(void);
|
||||
long userwrite(char*, int);
|
||||
#define validaddr(a, b, c)
|
||||
void validname(char*, int);
|
||||
void validstat(uchar*, int);
|
||||
void vcacheinval(Page*, ulong);
|
||||
void* vmemchr(void*, int, int);
|
||||
Proc* wakeup(Rendez*);
|
||||
int walk(Chan**, char**, int, int, int*);
|
||||
#define waserror() (setjmp(pwaserror()->buf))
|
||||
void wlock(RWlock*);
|
||||
void wunlock(RWlock*);
|
||||
void* xalloc(ulong);
|
||||
void* xallocz(ulong, int);
|
||||
void xfree(void*);
|
||||
void xhole(ulong, ulong);
|
||||
void xinit(void);
|
||||
int xmerge(void*, void*);
|
||||
void* xspanalloc(ulong, int, ulong);
|
||||
void xsummary(void);
|
||||
void yield(void);
|
||||
Segment* data2txt(Segment*);
|
||||
Segment* dupseg(Segment**, int, int);
|
||||
Segment* newseg(int, ulong, ulong);
|
||||
Segment* seg(Proc*, ulong, int);
|
||||
void hnputv(void*, vlong);
|
||||
void hnputl(void*, ulong);
|
||||
void hnputs(void*, ushort);
|
||||
vlong nhgetv(void*);
|
||||
ulong nhgetl(void*);
|
||||
ushort nhgets(void*);
|
47
kern/mkfile
Normal file
47
kern/mkfile
Normal file
@ -0,0 +1,47 @@
|
||||
<$DSRC/mkfile-$CONF
|
||||
TARG=libkern.$L
|
||||
|
||||
OFILES=\
|
||||
allocb.$O\
|
||||
cache.$O\
|
||||
chan.$O\
|
||||
data.$O\
|
||||
dev.$O\
|
||||
devcons.$O\
|
||||
devdraw.$O\
|
||||
devip.$O\
|
||||
devmnt.$O\
|
||||
devmouse.$O\
|
||||
devpipe.$O\
|
||||
devroot.$O\
|
||||
devssl.$O\
|
||||
devtab.$O\
|
||||
error.$O\
|
||||
parse.$O\
|
||||
pgrp.$O\
|
||||
procinit.$O\
|
||||
rwlock.$O\
|
||||
sleep.$O\
|
||||
smalloc.$O\
|
||||
stub.$O\
|
||||
sysfile.$O\
|
||||
sysproc.$O\
|
||||
qio.$O\
|
||||
qlock.$O\
|
||||
term.$O\
|
||||
todo.$O\
|
||||
uart.$O\
|
||||
waserror.$O\
|
||||
$DEVIP.$O\
|
||||
$OSHOOKS.$O\
|
||||
$DEVFS.$O
|
||||
|
||||
HFILE=\
|
||||
dat.h\
|
||||
devip.h\
|
||||
error.h\
|
||||
fns.h\
|
||||
netif.h\
|
||||
screen.h
|
||||
|
||||
<$DSRC/mklib-$CONF
|
133
kern/netif.h
Normal file
133
kern/netif.h
Normal file
@ -0,0 +1,133 @@
|
||||
typedef struct Etherpkt Etherpkt;
|
||||
typedef struct Netaddr Netaddr;
|
||||
typedef struct Netfile Netfile;
|
||||
typedef struct Netif Netif;
|
||||
|
||||
enum
|
||||
{
|
||||
Nmaxaddr= 64,
|
||||
Nmhash= 31,
|
||||
|
||||
Ncloneqid= 1,
|
||||
Naddrqid,
|
||||
N2ndqid,
|
||||
N3rdqid,
|
||||
Ndataqid,
|
||||
Nctlqid,
|
||||
Nstatqid,
|
||||
Ntypeqid,
|
||||
Nifstatqid,
|
||||
};
|
||||
|
||||
/*
|
||||
* Macros to manage Qid's used for multiplexed devices
|
||||
*/
|
||||
#define NETTYPE(x) (((ulong)x)&0x1f)
|
||||
#define NETID(x) ((((ulong)x))>>5)
|
||||
#define NETQID(i,t) ((((ulong)i)<<5)|(t))
|
||||
|
||||
/*
|
||||
* one per multiplexed connection
|
||||
*/
|
||||
struct Netfile
|
||||
{
|
||||
QLock lk;
|
||||
|
||||
int inuse;
|
||||
ulong mode;
|
||||
char owner[KNAMELEN];
|
||||
|
||||
int type; /* multiplexor type */
|
||||
int prom; /* promiscuous mode */
|
||||
int scan; /* base station scanning interval */
|
||||
int bridge; /* bridge mode */
|
||||
int headersonly; /* headers only - no data */
|
||||
uchar maddr[8]; /* bitmask of multicast addresses requested */
|
||||
int nmaddr; /* number of multicast addresses */
|
||||
|
||||
Queue *in; /* input buffer */
|
||||
};
|
||||
|
||||
/*
|
||||
* a network address
|
||||
*/
|
||||
struct Netaddr
|
||||
{
|
||||
Netaddr *next; /* allocation chain */
|
||||
Netaddr *hnext;
|
||||
uchar addr[Nmaxaddr];
|
||||
int ref;
|
||||
};
|
||||
|
||||
/*
|
||||
* a network interface
|
||||
*/
|
||||
struct Netif
|
||||
{
|
||||
QLock lk;
|
||||
|
||||
/* multiplexing */
|
||||
char name[KNAMELEN]; /* for top level directory */
|
||||
int nfile; /* max number of Netfiles */
|
||||
Netfile **f;
|
||||
|
||||
/* about net */
|
||||
int limit; /* flow control */
|
||||
int alen; /* address length */
|
||||
int mbps; /* megabits per sec */
|
||||
uchar addr[Nmaxaddr];
|
||||
uchar bcast[Nmaxaddr];
|
||||
Netaddr *maddr; /* known multicast addresses */
|
||||
int nmaddr; /* number of known multicast addresses */
|
||||
Netaddr *mhash[Nmhash]; /* hash table of multicast addresses */
|
||||
int prom; /* number of promiscuous opens */
|
||||
int scan; /* number of base station scanners */
|
||||
int all; /* number of -1 multiplexors */
|
||||
|
||||
/* statistics */
|
||||
int misses;
|
||||
int inpackets;
|
||||
int outpackets;
|
||||
int crcs; /* input crc errors */
|
||||
int oerrs; /* output errors */
|
||||
int frames; /* framing errors */
|
||||
int overflows; /* packet overflows */
|
||||
int buffs; /* buffering errors */
|
||||
int soverflows; /* software overflow */
|
||||
|
||||
/* routines for touching the hardware */
|
||||
void *arg;
|
||||
void (*promiscuous)(void*, int);
|
||||
void (*multicast)(void*, uchar*, int);
|
||||
void (*scanbs)(void*, uint); /* scan for base stations */
|
||||
};
|
||||
|
||||
void netifinit(Netif*, char*, int, ulong);
|
||||
Walkqid* netifwalk(Netif*, Chan*, Chan*, char **, int);
|
||||
Chan* netifopen(Netif*, Chan*, int);
|
||||
void netifclose(Netif*, Chan*);
|
||||
long netifread(Netif*, Chan*, void*, long, ulong);
|
||||
Block* netifbread(Netif*, Chan*, long, ulong);
|
||||
long netifwrite(Netif*, Chan*, void*, long);
|
||||
int netifwstat(Netif*, Chan*, uchar*, int);
|
||||
int netifstat(Netif*, Chan*, uchar*, int);
|
||||
int activemulti(Netif*, uchar*, int);
|
||||
|
||||
/*
|
||||
* Ethernet specific
|
||||
*/
|
||||
enum
|
||||
{
|
||||
Eaddrlen= 6,
|
||||
ETHERMINTU = 60, /* minimum transmit size */
|
||||
ETHERMAXTU = 1514, /* maximum transmit size */
|
||||
ETHERHDRSIZE = 14, /* size of an ethernet header */
|
||||
};
|
||||
|
||||
struct Etherpkt
|
||||
{
|
||||
uchar d[Eaddrlen];
|
||||
uchar s[Eaddrlen];
|
||||
uchar type[2];
|
||||
uchar data[1500];
|
||||
};
|
184
kern/os-windows.c
Normal file
184
kern/os-windows.c
Normal file
@ -0,0 +1,184 @@
|
||||
#include <windows.h>
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
typedef struct Oproc Oproc;
|
||||
struct Oproc {
|
||||
int tid;
|
||||
HANDLE *sema;
|
||||
};
|
||||
|
||||
char *argv0;
|
||||
_declspec(thread) Proc *CT;
|
||||
|
||||
Proc*
|
||||
_getproc(void)
|
||||
{
|
||||
return CT;
|
||||
}
|
||||
|
||||
void
|
||||
_setproc(Proc *p)
|
||||
{
|
||||
CT = p;
|
||||
}
|
||||
|
||||
void
|
||||
oserrstr(void)
|
||||
{
|
||||
char *p;
|
||||
char buf[ERRMAX];
|
||||
|
||||
if((p = strerror(errno)) != nil)
|
||||
strecpy(up->errstr, up->errstr+ERRMAX, p);
|
||||
else
|
||||
snprint(up->errstr, ERRMAX, "unix error %d", errno);
|
||||
}
|
||||
|
||||
void
|
||||
oserror(void)
|
||||
{
|
||||
oserrstr();
|
||||
nexterror();
|
||||
}
|
||||
|
||||
void
|
||||
osinit(void)
|
||||
{
|
||||
Oproc *t;
|
||||
static Proc firstprocCTstore;
|
||||
|
||||
CT = &firstprocCTstore;
|
||||
t = (Oproc*) CT->oproc;
|
||||
assert(t != 0);
|
||||
|
||||
t->tid = GetCurrentThreadId();
|
||||
t->sema = CreateSemaphore(0, 0, 1000, 0);
|
||||
if(t->sema == 0) {
|
||||
oserror();
|
||||
fatal("could not create semaphore: %r");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
osnewproc(Proc *p)
|
||||
{
|
||||
Oproc *op;
|
||||
|
||||
op = (Oproc*)p->oproc;
|
||||
op->sema = CreateSemaphore(0, 0, 1000, 0);
|
||||
if (op->sema == 0) {
|
||||
oserror();
|
||||
fatal("could not create semaphore: %r");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
osmsleep(int ms)
|
||||
{
|
||||
Sleep((DWORD) ms);
|
||||
}
|
||||
|
||||
void
|
||||
osyield(void)
|
||||
{
|
||||
Sleep(0);
|
||||
}
|
||||
|
||||
static DWORD WINAPI tramp(LPVOID vp);
|
||||
|
||||
void
|
||||
osproc(Proc *p)
|
||||
{
|
||||
int tid;
|
||||
|
||||
if(CreateThread(0, 0, tramp, p, 0, &tid) == 0) {
|
||||
oserror();
|
||||
fatal("osproc: %r");
|
||||
}
|
||||
|
||||
Sleep(0);
|
||||
}
|
||||
|
||||
static DWORD WINAPI
|
||||
tramp(LPVOID vp)
|
||||
{
|
||||
Proc *p = (Proc *) vp;
|
||||
Oproc *op = (Oproc*) p->oproc;
|
||||
|
||||
CT = p;
|
||||
op->tid = GetCurrentThreadId();
|
||||
op->sema = CreateSemaphore(0, 0, 1000, 0);
|
||||
if(op->sema == 0) {
|
||||
oserror();
|
||||
fatal("could not create semaphore: %r");
|
||||
}
|
||||
|
||||
(*p->fn)(p->arg);
|
||||
ExitThread(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
procsleep(void)
|
||||
{
|
||||
Proc *p;
|
||||
Oproc *op;
|
||||
|
||||
p = up;
|
||||
op = (Oproc*)p->oproc;
|
||||
WaitForSingleObject(op->sema, INFINITE);}
|
||||
|
||||
void
|
||||
procwakeup(Proc *p)
|
||||
{
|
||||
Oproc *op;
|
||||
|
||||
op = (Oproc*)p->oproc;
|
||||
ReleaseSemaphore(op->sema, 1, 0);
|
||||
}
|
||||
|
||||
void
|
||||
randominit(void)
|
||||
{
|
||||
srand(seconds());
|
||||
}
|
||||
|
||||
ulong
|
||||
randomread(void *v, ulong n)
|
||||
{
|
||||
int m, i, *r;
|
||||
|
||||
m = (n / sizeof(int)) * sizeof(int);
|
||||
for (i = 0, r = (int*)v; i < m; i += sizeof(int)) {
|
||||
*r = rand();
|
||||
r += sizeof(int);
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
long
|
||||
seconds(void)
|
||||
{
|
||||
return time(0);
|
||||
}
|
||||
|
||||
int
|
||||
ticks(void)
|
||||
{
|
||||
return GetTickCount();
|
||||
}
|
||||
|
||||
extern int main(int, char*[]);
|
||||
static int args(char *argv[], int n, char *p);
|
||||
|
||||
int PASCAL
|
||||
WinMain(HANDLE hInst, HANDLE hPrev, LPSTR arg, int nshow)
|
||||
{
|
||||
main(__argc, __argv);
|
||||
ExitThread(0);
|
||||
return 0;
|
||||
}
|
113
kern/parse.c
Normal file
113
kern/parse.c
Normal file
@ -0,0 +1,113 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
/*
|
||||
* Generous estimate of number of fields, including terminal nil pointer
|
||||
*/
|
||||
static int
|
||||
ncmdfield(char *p, int n)
|
||||
{
|
||||
int white, nwhite;
|
||||
char *ep;
|
||||
int nf;
|
||||
|
||||
if(p == nil)
|
||||
return 1;
|
||||
|
||||
nf = 0;
|
||||
ep = p+n;
|
||||
white = 1; /* first text will start field */
|
||||
while(p < ep){
|
||||
nwhite = (strchr(" \t\r\n", *p++ & 0xFF) != 0); /* UTF is irrelevant */
|
||||
if(white && !nwhite) /* beginning of field */
|
||||
nf++;
|
||||
white = nwhite;
|
||||
}
|
||||
return nf+1; /* +1 for nil */
|
||||
}
|
||||
|
||||
/*
|
||||
* parse a command written to a device
|
||||
*/
|
||||
Cmdbuf*
|
||||
parsecmd(char *p, int n)
|
||||
{
|
||||
Cmdbuf *volatile cb;
|
||||
int nf;
|
||||
char *sp;
|
||||
|
||||
nf = ncmdfield(p, n);
|
||||
|
||||
/* allocate Cmdbuf plus string pointers plus copy of string including \0 */
|
||||
sp = smalloc(sizeof(*cb) + nf * sizeof(char*) + n + 1);
|
||||
cb = (Cmdbuf*)sp;
|
||||
cb->f = (char**)(&cb[1]);
|
||||
cb->buf = (char*)(&cb->f[nf]);
|
||||
|
||||
if(up!=nil && waserror()){
|
||||
free(cb);
|
||||
nexterror();
|
||||
}
|
||||
memmove(cb->buf, p, n);
|
||||
if(up != nil)
|
||||
poperror();
|
||||
|
||||
/* dump new line and null terminate */
|
||||
if(n > 0 && cb->buf[n-1] == '\n')
|
||||
n--;
|
||||
cb->buf[n] = '\0';
|
||||
|
||||
cb->nf = tokenize(cb->buf, cb->f, nf-1);
|
||||
cb->f[cb->nf] = nil;
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reconstruct original message, for error diagnostic
|
||||
*/
|
||||
void
|
||||
cmderror(Cmdbuf *cb, char *s)
|
||||
{
|
||||
int i;
|
||||
char *p, *e;
|
||||
|
||||
p = up->genbuf;
|
||||
e = p+ERRMAX-10;
|
||||
p = seprint(p, e, "%s \"", s);
|
||||
for(i=0; i<cb->nf; i++){
|
||||
if(i > 0)
|
||||
p = seprint(p, e, " ");
|
||||
p = seprint(p, e, "%q", cb->f[i]);
|
||||
}
|
||||
strcpy(p, "\"");
|
||||
error(up->genbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look up entry in table
|
||||
*/
|
||||
Cmdtab*
|
||||
lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab)
|
||||
{
|
||||
int i;
|
||||
Cmdtab *ct;
|
||||
|
||||
if(cb->nf == 0)
|
||||
error("empty control message");
|
||||
|
||||
for(ct = ctab, i=0; i<nctab; i++, ct++){
|
||||
if(strcmp(ct->cmd, "*") !=0) /* wildcard always matches */
|
||||
if(strcmp(ct->cmd, cb->f[0]) != 0)
|
||||
continue;
|
||||
if(ct->narg != 0 && ct->narg != cb->nf)
|
||||
cmderror(cb, Ecmdargs);
|
||||
return ct;
|
||||
}
|
||||
|
||||
cmderror(cb, "unknown control message");
|
||||
return nil;
|
||||
}
|
272
kern/pgrp.c
Normal file
272
kern/pgrp.c
Normal file
@ -0,0 +1,272 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
static Ref pgrpid;
|
||||
static Ref mountid;
|
||||
|
||||
#ifdef NOTDEF
|
||||
void
|
||||
pgrpnote(ulong noteid, char *a, long n, int flag)
|
||||
{
|
||||
Proc *p, *ep;
|
||||
char buf[ERRMAX];
|
||||
|
||||
if(n >= ERRMAX-1)
|
||||
error(Etoobig);
|
||||
|
||||
memmove(buf, a, n);
|
||||
buf[n] = 0;
|
||||
p = proctab(0);
|
||||
ep = p+conf.nproc;
|
||||
for(; p < ep; p++) {
|
||||
if(p->state == Dead)
|
||||
continue;
|
||||
if(up != p && p->noteid == noteid && p->kp == 0) {
|
||||
qlock(&p->debug);
|
||||
if(p->pid == 0 || p->noteid != noteid){
|
||||
qunlock(&p->debug);
|
||||
continue;
|
||||
}
|
||||
if(!waserror()) {
|
||||
postnote(p, 0, buf, flag);
|
||||
poperror();
|
||||
}
|
||||
qunlock(&p->debug);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
Pgrp*
|
||||
newpgrp(void)
|
||||
{
|
||||
Pgrp *p;
|
||||
|
||||
p = smalloc(sizeof(Pgrp));
|
||||
p->ref.ref = 1;
|
||||
p->pgrpid = incref(&pgrpid);
|
||||
return p;
|
||||
}
|
||||
|
||||
Rgrp*
|
||||
newrgrp(void)
|
||||
{
|
||||
Rgrp *r;
|
||||
|
||||
r = smalloc(sizeof(Rgrp));
|
||||
r->ref.ref = 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
closergrp(Rgrp *r)
|
||||
{
|
||||
if(decref(&r->ref) == 0)
|
||||
free(r);
|
||||
}
|
||||
|
||||
void
|
||||
closepgrp(Pgrp *p)
|
||||
{
|
||||
Mhead **h, **e, *f, *next;
|
||||
|
||||
if(decref(&p->ref) != 0)
|
||||
return;
|
||||
|
||||
qlock(&p->debug);
|
||||
wlock(&p->ns);
|
||||
p->pgrpid = -1;
|
||||
|
||||
e = &p->mnthash[MNTHASH];
|
||||
for(h = p->mnthash; h < e; h++) {
|
||||
for(f = *h; f; f = next) {
|
||||
wlock(&f->lock);
|
||||
cclose(f->from);
|
||||
mountfree(f->mount);
|
||||
f->mount = nil;
|
||||
next = f->hash;
|
||||
wunlock(&f->lock);
|
||||
putmhead(f);
|
||||
}
|
||||
}
|
||||
wunlock(&p->ns);
|
||||
qunlock(&p->debug);
|
||||
free(p);
|
||||
}
|
||||
|
||||
void
|
||||
pgrpinsert(Mount **order, Mount *m)
|
||||
{
|
||||
Mount *f;
|
||||
|
||||
m->order = 0;
|
||||
if(*order == 0) {
|
||||
*order = m;
|
||||
return;
|
||||
}
|
||||
for(f = *order; f; f = f->order) {
|
||||
if(m->mountid < f->mountid) {
|
||||
m->order = f;
|
||||
*order = m;
|
||||
return;
|
||||
}
|
||||
order = &f->order;
|
||||
}
|
||||
*order = m;
|
||||
}
|
||||
|
||||
/*
|
||||
* pgrpcpy MUST preserve the mountid allocation order of the parent group
|
||||
*/
|
||||
void
|
||||
pgrpcpy(Pgrp *to, Pgrp *from)
|
||||
{
|
||||
int i;
|
||||
Mount *n, *m, **link, *order;
|
||||
Mhead *f, **tom, **l, *mh;
|
||||
|
||||
wlock(&from->ns);
|
||||
order = 0;
|
||||
tom = to->mnthash;
|
||||
for(i = 0; i < MNTHASH; i++) {
|
||||
l = tom++;
|
||||
for(f = from->mnthash[i]; f; f = f->hash) {
|
||||
rlock(&f->lock);
|
||||
mh = newmhead(f->from);
|
||||
*l = mh;
|
||||
l = &mh->hash;
|
||||
link = &mh->mount;
|
||||
for(m = f->mount; m; m = m->next) {
|
||||
n = newmount(mh, m->to, m->mflag, m->spec);
|
||||
m->copy = n;
|
||||
pgrpinsert(&order, m);
|
||||
*link = n;
|
||||
link = &n->next;
|
||||
}
|
||||
runlock(&f->lock);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Allocate mount ids in the same sequence as the parent group
|
||||
*/
|
||||
lock(&mountid.lk);
|
||||
for(m = order; m; m = m->order)
|
||||
m->copy->mountid = mountid.ref++;
|
||||
unlock(&mountid.lk);
|
||||
wunlock(&from->ns);
|
||||
}
|
||||
|
||||
Fgrp*
|
||||
dupfgrp(Fgrp *f)
|
||||
{
|
||||
Fgrp *new;
|
||||
Chan *c;
|
||||
int i;
|
||||
|
||||
new = smalloc(sizeof(Fgrp));
|
||||
if(f == nil){
|
||||
new->fd = smalloc(DELTAFD*sizeof(Chan*));
|
||||
new->nfd = DELTAFD;
|
||||
new->ref.ref = 1;
|
||||
return new;
|
||||
}
|
||||
|
||||
lock(&f->ref.lk);
|
||||
/* Make new fd list shorter if possible, preserving quantization */
|
||||
new->nfd = f->maxfd+1;
|
||||
i = new->nfd%DELTAFD;
|
||||
if(i != 0)
|
||||
new->nfd += DELTAFD - i;
|
||||
new->fd = malloc(new->nfd*sizeof(Chan*));
|
||||
if(new->fd == 0){
|
||||
unlock(&f->ref.lk);
|
||||
error("no memory for fgrp");
|
||||
}
|
||||
new->ref.ref = 1;
|
||||
|
||||
new->maxfd = f->maxfd;
|
||||
for(i = 0; i <= f->maxfd; i++) {
|
||||
if(c = f->fd[i]){
|
||||
incref(&c->ref);
|
||||
new->fd[i] = c;
|
||||
}
|
||||
}
|
||||
unlock(&f->ref.lk);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
void
|
||||
closefgrp(Fgrp *f)
|
||||
{
|
||||
int i;
|
||||
Chan *c;
|
||||
|
||||
if(f == 0)
|
||||
return;
|
||||
|
||||
if(decref(&f->ref) != 0)
|
||||
return;
|
||||
|
||||
for(i = 0; i <= f->maxfd; i++)
|
||||
if(c = f->fd[i])
|
||||
cclose(c);
|
||||
|
||||
free(f->fd);
|
||||
free(f);
|
||||
}
|
||||
|
||||
Mount*
|
||||
newmount(Mhead *mh, Chan *to, int flag, char *spec)
|
||||
{
|
||||
Mount *m;
|
||||
|
||||
m = smalloc(sizeof(Mount));
|
||||
m->to = to;
|
||||
m->head = mh;
|
||||
incref(&to->ref);
|
||||
m->mountid = incref(&mountid);
|
||||
m->mflag = flag;
|
||||
if(spec != 0)
|
||||
kstrdup(&m->spec, spec);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
void
|
||||
mountfree(Mount *m)
|
||||
{
|
||||
Mount *f;
|
||||
|
||||
while(m) {
|
||||
f = m->next;
|
||||
cclose(m->to);
|
||||
m->mountid = 0;
|
||||
free(m->spec);
|
||||
free(m);
|
||||
m = f;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NOTDEF
|
||||
void
|
||||
resrcwait(char *reason)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if(up == 0)
|
||||
panic("resrcwait");
|
||||
|
||||
p = up->psstate;
|
||||
if(reason) {
|
||||
up->psstate = reason;
|
||||
print("%s\n", reason);
|
||||
}
|
||||
|
||||
tsleep(&up->sleep, return0, 0, 300);
|
||||
up->psstate = p;
|
||||
}
|
||||
#endif
|
190
kern/posix.c
Normal file
190
kern/posix.c
Normal file
@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Posix generic OS implementation for drawterm.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
typedef struct Oproc Oproc;
|
||||
struct Oproc
|
||||
{
|
||||
int p[2];
|
||||
};
|
||||
|
||||
static pthread_key_t prdakey;
|
||||
|
||||
Proc*
|
||||
_getproc(void)
|
||||
{
|
||||
void *v;
|
||||
|
||||
if((v = pthread_getspecific(prdakey)) == nil)
|
||||
panic("cannot getspecific");
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
_setproc(Proc *p)
|
||||
{
|
||||
if(pthread_setspecific(prdakey, p) != 0)
|
||||
panic("cannot setspecific");
|
||||
}
|
||||
|
||||
void
|
||||
osinit(void)
|
||||
{
|
||||
if(pthread_key_create(&prdakey, 0))
|
||||
panic("cannot pthread_key_create");
|
||||
}
|
||||
|
||||
#undef pipe
|
||||
void
|
||||
osnewproc(Proc *p)
|
||||
{
|
||||
Oproc *op;
|
||||
|
||||
op = (Oproc*)p->oproc;
|
||||
if(pipe(op->p) < 0)
|
||||
panic("cannot pipe");
|
||||
}
|
||||
|
||||
void
|
||||
osmsleep(int ms)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
tv.tv_sec = ms / 1000;
|
||||
tv.tv_usec = (ms % 1000) * 1000; /* micro */
|
||||
if(select(0, NULL, NULL, NULL, &tv) < 0)
|
||||
panic("select");
|
||||
}
|
||||
|
||||
void
|
||||
osyield(void)
|
||||
{
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
void
|
||||
oserrstr(void)
|
||||
{
|
||||
char *p;
|
||||
char buf[ERRMAX];
|
||||
|
||||
if((p = strerror(errno)) != nil)
|
||||
strecpy(up->errstr, up->errstr+ERRMAX, p);
|
||||
else
|
||||
snprint(up->errstr, ERRMAX, "unix error %d", errno);
|
||||
}
|
||||
|
||||
void
|
||||
oserror(void)
|
||||
{
|
||||
oserrstr();
|
||||
nexterror();
|
||||
}
|
||||
|
||||
static void* tramp(void*);
|
||||
|
||||
void
|
||||
osproc(Proc *p)
|
||||
{
|
||||
pthread_t pid;
|
||||
|
||||
if(pthread_create(&pid, nil, tramp, p)){
|
||||
oserrstr();
|
||||
panic("osproc: %r");
|
||||
}
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
static void*
|
||||
tramp(void *vp)
|
||||
{
|
||||
Proc *p;
|
||||
|
||||
p = vp;
|
||||
if(pthread_setspecific(prdakey, p))
|
||||
panic("cannot setspecific");
|
||||
(*p->fn)(p->arg);
|
||||
/* BUG: leaks Proc */
|
||||
pthread_setspecific(prdakey, 0);
|
||||
pthread_exit(0);
|
||||
}
|
||||
|
||||
void
|
||||
procsleep(void)
|
||||
{
|
||||
int c;
|
||||
Proc *p;
|
||||
Oproc *op;
|
||||
|
||||
p = up;
|
||||
op = (Oproc*)p->oproc;
|
||||
while(read(op->p[0], &c, 1) != 1)
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
procwakeup(Proc *p)
|
||||
{
|
||||
char c;
|
||||
Oproc *op;
|
||||
|
||||
op = (Oproc*)p->oproc;
|
||||
c = 'a';
|
||||
write(op->p[1], &c, 1);
|
||||
}
|
||||
|
||||
int randfd;
|
||||
#undef open
|
||||
void
|
||||
randominit(void)
|
||||
{
|
||||
if((randfd = open("/dev/urandom", OREAD)) < 0)
|
||||
if((randfd = open("/dev/random", OREAD)) < 0)
|
||||
panic("open /dev/random: %r");
|
||||
}
|
||||
|
||||
#undef read
|
||||
ulong
|
||||
randomread(void *v, ulong n)
|
||||
{
|
||||
int m;
|
||||
|
||||
if((m = read(randfd, v, n)) != n)
|
||||
panic("short read from /dev/random: %d but %d", n, m);
|
||||
return m;
|
||||
}
|
||||
|
||||
#undef time
|
||||
long
|
||||
seconds(void)
|
||||
{
|
||||
return time(0);
|
||||
}
|
||||
|
||||
ulong
|
||||
ticks(void)
|
||||
{
|
||||
static long sec0 = 0, usec0;
|
||||
struct timeval t;
|
||||
|
||||
if(gettimeofday(&t, nil) < 0)
|
||||
return 0;
|
||||
if(sec0 == 0){
|
||||
sec0 = t.tv_sec;
|
||||
usec0 = t.tv_usec;
|
||||
}
|
||||
return (t.tv_sec-sec0)*1000+(t.tv_usec-usec0+500)/1000;
|
||||
}
|
||||
|
67
kern/procinit.c
Normal file
67
kern/procinit.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
Rgrp *thergrp;
|
||||
|
||||
void
|
||||
procinit0(void)
|
||||
{
|
||||
Proc *p;
|
||||
|
||||
p = newproc();
|
||||
p->fgrp = dupfgrp(nil);
|
||||
p->rgrp = newrgrp();
|
||||
p->pgrp = newpgrp();
|
||||
_setproc(p);
|
||||
|
||||
up->slash = namec("#/", Atodir, 0, 0);
|
||||
cnameclose(up->slash->name);
|
||||
up->slash->name = newcname("/");
|
||||
up->dot = cclone(up->slash);
|
||||
}
|
||||
|
||||
Ref pidref;
|
||||
|
||||
Proc*
|
||||
newproc(void)
|
||||
{
|
||||
Proc *p;
|
||||
|
||||
p = mallocz(sizeof(Proc), 1);
|
||||
p->pid = incref(&pidref);
|
||||
strcpy(p->user, eve);
|
||||
p->syserrstr = p->errbuf0;
|
||||
p->errstr = p->errbuf1;
|
||||
strcpy(p->text, "drawterm");
|
||||
osnewproc(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
int
|
||||
kproc(char *name, void (*fn)(void*), void *arg)
|
||||
{
|
||||
Proc *p;
|
||||
|
||||
p = newproc();
|
||||
p->fn = fn;
|
||||
p->arg = arg;
|
||||
p->slash = cclone(up->slash);
|
||||
p->dot = cclone(up->dot);
|
||||
p->rgrp = up->rgrp;
|
||||
if(p->rgrp)
|
||||
incref(&p->rgrp->ref);
|
||||
p->pgrp = up->pgrp;
|
||||
if(up->pgrp)
|
||||
incref(&up->pgrp->ref);
|
||||
p->fgrp = up->fgrp;
|
||||
if(p->fgrp)
|
||||
incref(&p->fgrp->ref);
|
||||
strecpy(p->text, sizeof p->text, name);
|
||||
|
||||
osproc(p);
|
||||
return p->pid;
|
||||
}
|
||||
|
1524
kern/qio.c
Normal file
1524
kern/qio.c
Normal file
File diff suppressed because it is too large
Load Diff
94
kern/qlock.c
Normal file
94
kern/qlock.c
Normal file
@ -0,0 +1,94 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
static void
|
||||
queue(Proc **first, Proc **last)
|
||||
{
|
||||
Proc *t;
|
||||
|
||||
t = *last;
|
||||
if(t == 0)
|
||||
*first = up;
|
||||
else
|
||||
t->qnext = up;
|
||||
*last = up;
|
||||
up->qnext = 0;
|
||||
}
|
||||
|
||||
static Proc*
|
||||
dequeue(Proc **first, Proc **last)
|
||||
{
|
||||
Proc *t;
|
||||
|
||||
t = *first;
|
||||
if(t == 0)
|
||||
return 0;
|
||||
*first = t->qnext;
|
||||
if(*first == 0)
|
||||
*last = 0;
|
||||
return t;
|
||||
}
|
||||
|
||||
void
|
||||
qlock(QLock *q)
|
||||
{
|
||||
lock(&q->lk);
|
||||
|
||||
if(q->hold == 0) {
|
||||
q->hold = up;
|
||||
unlock(&q->lk);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Can't assert this because of RWLock
|
||||
assert(q->hold != up);
|
||||
*/
|
||||
|
||||
queue((Proc**)&q->first, (Proc**)&q->last);
|
||||
unlock(&q->lk);
|
||||
procsleep();
|
||||
}
|
||||
|
||||
int
|
||||
canqlock(QLock *q)
|
||||
{
|
||||
lock(&q->lk);
|
||||
if(q->hold == 0) {
|
||||
q->hold = up;
|
||||
unlock(&q->lk);
|
||||
return 1;
|
||||
}
|
||||
unlock(&q->lk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
qunlock(QLock *q)
|
||||
{
|
||||
Proc *p;
|
||||
|
||||
lock(&q->lk);
|
||||
/*
|
||||
* Can't assert this because of RWlock
|
||||
assert(q->hold == CT);
|
||||
*/
|
||||
p = dequeue((Proc**)&q->first, (Proc**)&q->last);
|
||||
if(p) {
|
||||
q->hold = p;
|
||||
unlock(&q->lk);
|
||||
procwakeup(p);
|
||||
} else {
|
||||
q->hold = 0;
|
||||
unlock(&q->lk);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
holdqlock(QLock *q)
|
||||
{
|
||||
return q->hold == up;
|
||||
}
|
||||
|
90
kern/rendez.c
Normal file
90
kern/rendez.c
Normal file
@ -0,0 +1,90 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
void
|
||||
sleep(Rendez *r, int (*f)(void*), void *arg)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splhi();
|
||||
|
||||
lock(&r->lk);
|
||||
lock(&up->rlock);
|
||||
if(r->p){
|
||||
print("double sleep %lud %lud\n", r->p->pid, up->pid);
|
||||
dumpstack();
|
||||
}
|
||||
|
||||
/*
|
||||
* Wakeup only knows there may be something to do by testing
|
||||
* r->p in order to get something to lock on.
|
||||
* Flush that information out to memory in case the sleep is
|
||||
* committed.
|
||||
*/
|
||||
r->p = up;
|
||||
|
||||
if((*f)(arg) || up->notepending){
|
||||
/*
|
||||
* if condition happened or a note is pending
|
||||
* never mind
|
||||
*/
|
||||
r->p = nil;
|
||||
unlock(&up->rlock);
|
||||
unlock(&r->lk);
|
||||
} else {
|
||||
/*
|
||||
* now we are committed to
|
||||
* change state and call scheduler
|
||||
*/
|
||||
up->state = Wakeme;
|
||||
up->r = r;
|
||||
|
||||
/* statistics */
|
||||
/* m->cs++; */
|
||||
|
||||
unlock(&up->rlock);
|
||||
unlock(&r->lk);
|
||||
|
||||
procsleep();
|
||||
}
|
||||
|
||||
if(up->notepending) {
|
||||
up->notepending = 0;
|
||||
splx(s);
|
||||
error(Eintr);
|
||||
}
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
Proc*
|
||||
wakeup(Rendez *r)
|
||||
{
|
||||
Proc *p;
|
||||
int s;
|
||||
|
||||
s = splhi();
|
||||
|
||||
lock(&r->lk);
|
||||
p = r->p;
|
||||
|
||||
if(p != nil){
|
||||
lock(&p->rlock);
|
||||
if(p->state != Wakeme || p->r != r)
|
||||
panic("wakeup: state");
|
||||
r->p = nil;
|
||||
p->r = nil;
|
||||
p->state = Running;
|
||||
procwakeup(p);
|
||||
unlock(&p->rlock);
|
||||
}
|
||||
unlock(&r->lk);
|
||||
|
||||
splx(s);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
39
kern/rwlock.c
Normal file
39
kern/rwlock.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
void
|
||||
rlock(RWlock *l)
|
||||
{
|
||||
qlock(&l->x); /* wait here for writers and exclusion */
|
||||
lock(&l->lk);
|
||||
l->readers++;
|
||||
canqlock(&l->k); /* block writers if we are the first reader */
|
||||
unlock(&l->lk);
|
||||
qunlock(&l->x);
|
||||
}
|
||||
|
||||
void
|
||||
runlock(RWlock *l)
|
||||
{
|
||||
lock(&l->lk);
|
||||
if(--l->readers == 0) /* last reader out allows writers */
|
||||
qunlock(&l->k);
|
||||
unlock(&l->lk);
|
||||
}
|
||||
|
||||
void
|
||||
wlock(RWlock *l)
|
||||
{
|
||||
qlock(&l->x); /* wait here for writers and exclusion */
|
||||
qlock(&l->k); /* wait here for last reader */
|
||||
}
|
||||
|
||||
void
|
||||
wunlock(RWlock *l)
|
||||
{
|
||||
qunlock(&l->k);
|
||||
qunlock(&l->x);
|
||||
}
|
59
kern/screen.h
Normal file
59
kern/screen.h
Normal file
@ -0,0 +1,59 @@
|
||||
typedef struct Mouseinfo Mouseinfo;
|
||||
typedef struct Mousestate Mousestate;
|
||||
typedef struct Cursorinfo Cursorinfo;
|
||||
typedef struct Screeninfo Screeninfo;
|
||||
|
||||
#define Mousequeue 16 /* queue can only have Mousequeue-1 elements */
|
||||
#define Mousewindow 500 /* mouse event window in millisec */
|
||||
|
||||
struct Mousestate {
|
||||
int buttons;
|
||||
Point xy;
|
||||
ulong msec;
|
||||
};
|
||||
|
||||
struct Mouseinfo {
|
||||
Lock lk;
|
||||
Mousestate queue[Mousequeue];
|
||||
int ri, wi;
|
||||
int lastb;
|
||||
int trans;
|
||||
int open;
|
||||
Rendez r;
|
||||
};
|
||||
|
||||
struct Cursorinfo {
|
||||
Lock lk;
|
||||
Point offset;
|
||||
uchar clr[2*16];
|
||||
uchar set[2*16];
|
||||
};
|
||||
|
||||
struct Screeninfo {
|
||||
Lock lk;
|
||||
Memimage *newsoft;
|
||||
int reshaped;
|
||||
int depth;
|
||||
int dibtype;
|
||||
};
|
||||
|
||||
extern Memimage *gscreen;
|
||||
extern Mouseinfo mouse;
|
||||
extern Cursorinfo cursor;
|
||||
extern Screeninfo screen;
|
||||
|
||||
void screeninit(void);
|
||||
void screenload(Rectangle, int, uchar *, Point, int);
|
||||
|
||||
void getcolor(ulong, ulong*, ulong*, ulong*);
|
||||
void setcolor(ulong, ulong, ulong, ulong);
|
||||
|
||||
void refreshrect(Rectangle);
|
||||
|
||||
void cursorarrow(void);
|
||||
void setcursor(void);
|
||||
void mouseset(Point);
|
||||
void drawflushr(Rectangle);
|
||||
void flushmemscreen(Rectangle);
|
||||
uchar *attachscreen(Rectangle*, ulong*, int*, int*, int*, void**);
|
||||
|
90
kern/sleep.c
Normal file
90
kern/sleep.c
Normal file
@ -0,0 +1,90 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
void
|
||||
sleep(Rendez *r, int (*f)(void*), void *arg)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splhi();
|
||||
|
||||
lock(&r->lk);
|
||||
lock(&up->rlock);
|
||||
if(r->p){
|
||||
print("double sleep %lud %lud\n", r->p->pid, up->pid);
|
||||
dumpstack();
|
||||
}
|
||||
|
||||
/*
|
||||
* Wakeup only knows there may be something to do by testing
|
||||
* r->p in order to get something to lock on.
|
||||
* Flush that information out to memory in case the sleep is
|
||||
* committed.
|
||||
*/
|
||||
r->p = up;
|
||||
|
||||
if((*f)(arg) || up->notepending){
|
||||
/*
|
||||
* if condition happened or a note is pending
|
||||
* never mind
|
||||
*/
|
||||
r->p = nil;
|
||||
unlock(&up->rlock);
|
||||
unlock(&r->lk);
|
||||
} else {
|
||||
/*
|
||||
* now we are committed to
|
||||
* change state and call scheduler
|
||||
*/
|
||||
up->state = Wakeme;
|
||||
up->r = r;
|
||||
|
||||
/* statistics */
|
||||
/* m->cs++; */
|
||||
|
||||
unlock(&up->rlock);
|
||||
unlock(&r->lk);
|
||||
|
||||
procsleep();
|
||||
}
|
||||
|
||||
if(up->notepending) {
|
||||
up->notepending = 0;
|
||||
splx(s);
|
||||
error(Eintr);
|
||||
}
|
||||
|
||||
splx(s);
|
||||
}
|
||||
|
||||
Proc*
|
||||
wakeup(Rendez *r)
|
||||
{
|
||||
Proc *p;
|
||||
int s;
|
||||
|
||||
s = splhi();
|
||||
|
||||
lock(&r->lk);
|
||||
p = r->p;
|
||||
|
||||
if(p != nil){
|
||||
lock(&p->rlock);
|
||||
if(p->state != Wakeme || p->r != r)
|
||||
panic("wakeup: state");
|
||||
r->p = nil;
|
||||
p->r = nil;
|
||||
p->state = Running;
|
||||
procwakeup(p);
|
||||
unlock(&p->rlock);
|
||||
}
|
||||
unlock(&r->lk);
|
||||
|
||||
splx(s);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
18
kern/smalloc.c
Normal file
18
kern/smalloc.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
void*
|
||||
smalloc(ulong n)
|
||||
{
|
||||
return mallocz(n, 1);
|
||||
}
|
||||
|
||||
void*
|
||||
malloc(ulong n)
|
||||
{
|
||||
return mallocz(n, 1);
|
||||
}
|
||||
|
170
kern/stub.c
Normal file
170
kern/stub.c
Normal file
@ -0,0 +1,170 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
void
|
||||
mallocsummary(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
pagersummary(void)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
iseve(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
setswapchan(Chan *c)
|
||||
{
|
||||
USED(c);
|
||||
}
|
||||
|
||||
void
|
||||
splx(int x)
|
||||
{
|
||||
USED(x);
|
||||
}
|
||||
|
||||
int
|
||||
splhi(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
spllo(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
procdump(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
scheddump(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
killbig(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
dumpstack(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
xsummary(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
rebootcmd(int argc, char **argv)
|
||||
{
|
||||
USED(argc);
|
||||
USED(argv);
|
||||
}
|
||||
|
||||
void
|
||||
kickpager(void)
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
userwrite(char *a, int n)
|
||||
{
|
||||
error(Eperm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
vlong
|
||||
todget(vlong *p)
|
||||
{
|
||||
if(p)
|
||||
*p = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
todset(vlong a, vlong b, int c)
|
||||
{
|
||||
USED(a);
|
||||
USED(b);
|
||||
USED(c);
|
||||
}
|
||||
|
||||
void
|
||||
todsetfreq(vlong a)
|
||||
{
|
||||
USED(a);
|
||||
}
|
||||
|
||||
long
|
||||
hostdomainwrite(char *a, int n)
|
||||
{
|
||||
USED(a);
|
||||
USED(n);
|
||||
error(Eperm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
hostownerwrite(char *a, int n)
|
||||
{
|
||||
USED(a);
|
||||
USED(n);
|
||||
error(Eperm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
todinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
rdb(void)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
setmalloctag(void *v, ulong tag)
|
||||
{
|
||||
USED(v);
|
||||
USED(tag);
|
||||
}
|
||||
|
||||
int
|
||||
postnote(Proc *p, int x, char *msg, int flag)
|
||||
{
|
||||
USED(p);
|
||||
USED(x);
|
||||
USED(msg);
|
||||
USED(flag);
|
||||
}
|
||||
|
||||
void
|
||||
exhausted(char *s)
|
||||
{
|
||||
panic("out of %s", s);
|
||||
}
|
||||
|
||||
uvlong
|
||||
fastticks(uvlong *v)
|
||||
{
|
||||
if(v)
|
||||
*v = 1;
|
||||
return 0;
|
||||
}
|
||||
|
837
kern/syscall.c
Normal file
837
kern/syscall.c
Normal file
@ -0,0 +1,837 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
Chan*
|
||||
fdtochan(int fd, int mode, int chkmnt, int iref)
|
||||
{
|
||||
Fgrp *f;
|
||||
Chan *c;
|
||||
|
||||
c = 0;
|
||||
f = up->fgrp;
|
||||
|
||||
lock(&f->ref.lk);
|
||||
if(fd<0 || NFD<=fd || (c = f->fd[fd])==0) {
|
||||
unlock(&f->ref.lk);
|
||||
error(Ebadfd);
|
||||
}
|
||||
if(iref)
|
||||
refinc(&c->ref);
|
||||
unlock(&f->ref.lk);
|
||||
|
||||
if(chkmnt && (c->flag&CMSG))
|
||||
goto bad;
|
||||
if(mode<0 || c->mode==ORDWR)
|
||||
return c;
|
||||
if((mode&OTRUNC) && c->mode==OREAD)
|
||||
goto bad;
|
||||
if((mode&~OTRUNC) != c->mode)
|
||||
goto bad;
|
||||
return c;
|
||||
bad:
|
||||
if(iref)
|
||||
cclose(c);
|
||||
error(Ebadusefd);
|
||||
return nil; /* shut up compiler */
|
||||
}
|
||||
|
||||
static void
|
||||
fdclose(int fd, int flag)
|
||||
{
|
||||
int i;
|
||||
Chan *c;
|
||||
Fgrp *f;
|
||||
|
||||
f = up->fgrp;
|
||||
|
||||
lock(&f->ref.lk);
|
||||
c = f->fd[fd];
|
||||
if(c == 0) {
|
||||
unlock(&f->ref.lk);
|
||||
return;
|
||||
}
|
||||
if(flag) {
|
||||
if(c==0 || !(c->flag&flag)) {
|
||||
unlock(&f->ref.lk);
|
||||
return;
|
||||
}
|
||||
}
|
||||
f->fd[fd] = 0;
|
||||
if(fd == f->maxfd)
|
||||
for(i=fd; --i>=0 && f->fd[i]==0; )
|
||||
f->maxfd = i;
|
||||
|
||||
unlock(&f->ref.lk);
|
||||
cclose(c);
|
||||
}
|
||||
|
||||
static int
|
||||
newfd(Chan *c)
|
||||
{
|
||||
int i;
|
||||
Fgrp *f;
|
||||
|
||||
f = up->fgrp;
|
||||
lock(&f->ref.lk);
|
||||
for(i=0; i<NFD; i++)
|
||||
if(f->fd[i] == 0){
|
||||
if(i > f->maxfd)
|
||||
f->maxfd = i;
|
||||
f->fd[i] = c;
|
||||
unlock(&f->ref.lk);
|
||||
return i;
|
||||
}
|
||||
unlock(&f->ref.lk);
|
||||
error("no file descriptors");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sysclose(int fd)
|
||||
{
|
||||
if(waserror())
|
||||
return -1;
|
||||
|
||||
fdtochan(fd, -1, 0, 0);
|
||||
fdclose(fd, 0);
|
||||
poperror();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
syscreate(char *path, int mode, ulong perm)
|
||||
{
|
||||
int fd;
|
||||
Chan *c = 0;
|
||||
|
||||
if(waserror()) {
|
||||
cclose(c);
|
||||
return -1;
|
||||
}
|
||||
|
||||
openmode(mode); /* error check only */
|
||||
c = namec(path, Acreate, mode, perm);
|
||||
fd = newfd((Chan*)c);
|
||||
poperror();
|
||||
return fd;
|
||||
}
|
||||
|
||||
int
|
||||
sysdup(int old, int new)
|
||||
{
|
||||
Chan *oc;
|
||||
Fgrp *f = up->fgrp;
|
||||
Chan *c = 0;
|
||||
|
||||
if(waserror())
|
||||
return -1;
|
||||
|
||||
c = fdtochan(old, -1, 0, 1);
|
||||
if(new != -1) {
|
||||
if(new < 0 || NFD <= new) {
|
||||
cclose(c);
|
||||
error(Ebadfd);
|
||||
}
|
||||
lock(&f->ref.lk);
|
||||
if(new > f->maxfd)
|
||||
f->maxfd = new;
|
||||
oc = f->fd[new];
|
||||
f->fd[new] = (Chan*)c;
|
||||
unlock(&f->ref.lk);
|
||||
if(oc != 0)
|
||||
cclose(oc);
|
||||
}
|
||||
else {
|
||||
if(waserror()) {
|
||||
cclose(c);
|
||||
nexterror();
|
||||
}
|
||||
new = newfd((Chan*)c);
|
||||
poperror();
|
||||
}
|
||||
poperror();
|
||||
return new;
|
||||
}
|
||||
|
||||
int
|
||||
sysfstat(int fd, char *buf)
|
||||
{
|
||||
Chan *c = 0;
|
||||
|
||||
if(waserror()) {
|
||||
cclose(c);
|
||||
return -1;
|
||||
}
|
||||
c = fdtochan(fd, -1, 0, 1);
|
||||
devtab[c->type]->stat((Chan*)c, buf);
|
||||
poperror();
|
||||
cclose(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sysfwstat(int fd, char *buf)
|
||||
{
|
||||
Chan *c = 0;
|
||||
|
||||
if(waserror()) {
|
||||
cclose(c);
|
||||
return -1;
|
||||
}
|
||||
nameok(buf);
|
||||
c = fdtochan(fd, -1, 1, 1);
|
||||
devtab[c->type]->wstat((Chan*)c, buf);
|
||||
poperror();
|
||||
cclose(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
syschdir(char *dir)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
bindmount(Chan *c0, char *old, int flag, char *spec)
|
||||
{
|
||||
int ret;
|
||||
Chan *c1 = 0;
|
||||
|
||||
if(flag>MMASK || (flag&MORDER) == (MBEFORE|MAFTER))
|
||||
error(Ebadarg);
|
||||
|
||||
c1 = namec(old, Amount, 0, 0);
|
||||
if(waserror()){
|
||||
cclose(c1);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
ret = cmount(c0, c1, flag, spec);
|
||||
|
||||
poperror();
|
||||
cclose(c1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
sysbind(char *new, char *old, int flags)
|
||||
{
|
||||
long r;
|
||||
Chan *c0 = 0;
|
||||
|
||||
if(waserror()) {
|
||||
cclose(c0);
|
||||
return -1;
|
||||
}
|
||||
c0 = namec(new, Aaccess, 0, 0);
|
||||
r = bindmount(c0, old, flags, "");
|
||||
poperror();
|
||||
cclose(c0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sysmount(int fd, char *old, int flags, char *spec)
|
||||
{
|
||||
long r;
|
||||
Chan *c0 = 0, *bc = 0;
|
||||
struct {
|
||||
Chan* chan;
|
||||
char* spec;
|
||||
int flags;
|
||||
} mntparam;
|
||||
|
||||
if(waserror()) {
|
||||
cclose(bc);
|
||||
cclose(c0);
|
||||
return -1;
|
||||
}
|
||||
bc = fdtochan(fd, ORDWR, 0, 1);
|
||||
mntparam.chan = (Chan*)bc;
|
||||
mntparam.spec = spec;
|
||||
mntparam.flags = flags;
|
||||
c0 = (*devtab[devno('M', 0)].attach)(&mntparam);
|
||||
cclose(bc);
|
||||
r = bindmount(c0, old, flags, spec);
|
||||
poperror();
|
||||
cclose(c0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
sysunmount(char *old, char *new)
|
||||
{
|
||||
Chan *cmount = 0, *cmounted = 0;
|
||||
|
||||
if(waserror()) {
|
||||
cclose(cmount);
|
||||
cclose(cmounted);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cmount = namec(new, Amount, OREAD, 0);
|
||||
if(old != 0)
|
||||
cmounted = namec(old, Aopen, OREAD, 0);
|
||||
|
||||
cunmount(cmount, cmounted);
|
||||
poperror();
|
||||
cclose(cmount);
|
||||
cclose(cmounted);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sysopen(char *path, int mode)
|
||||
{
|
||||
int fd;
|
||||
Chan *c = 0;
|
||||
|
||||
if(waserror()){
|
||||
cclose(c);
|
||||
return -1;
|
||||
}
|
||||
openmode(mode); /* error check only */
|
||||
c = namec(path, Aopen, mode, 0);
|
||||
fd = newfd((Chan*)c);
|
||||
poperror();
|
||||
return fd;
|
||||
}
|
||||
|
||||
long
|
||||
unionread(Chan *c, void *va, long n)
|
||||
{
|
||||
long nr;
|
||||
Chan *nc = 0;
|
||||
Pgrp *pg = 0;
|
||||
|
||||
pg = up->pgrp;
|
||||
rlock(&pg->ns);
|
||||
|
||||
for(;;) {
|
||||
if(waserror()) {
|
||||
runlock(&pg->ns);
|
||||
nexterror();
|
||||
}
|
||||
nc = clone(c->mnt->to, 0);
|
||||
poperror();
|
||||
|
||||
if(c->mountid != c->mnt->mountid) {
|
||||
runlock(&pg->ns);
|
||||
cclose(nc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Error causes component of union to be skipped */
|
||||
if(waserror()) {
|
||||
cclose(nc);
|
||||
goto next;
|
||||
}
|
||||
|
||||
nc = (*devtab[nc->type].open)((Chan*)nc, OREAD);
|
||||
nc->offset = c->offset;
|
||||
nr = (*devtab[nc->type].read)((Chan*)nc, va, n, nc->offset);
|
||||
/* devdirread e.g. changes it */
|
||||
c->offset = nc->offset;
|
||||
poperror();
|
||||
|
||||
cclose(nc);
|
||||
if(nr > 0) {
|
||||
runlock(&pg->ns);
|
||||
return nr;
|
||||
}
|
||||
/* Advance to next element */
|
||||
next:
|
||||
c->mnt = c->mnt->next;
|
||||
if(c->mnt == 0)
|
||||
break;
|
||||
c->mountid = c->mnt->mountid;
|
||||
c->offset = 0;
|
||||
}
|
||||
runlock(&pg->ns);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
sysread(int fd, void *va, long n)
|
||||
{
|
||||
int dir;
|
||||
Lock *cl;
|
||||
Chan *c = 0;
|
||||
|
||||
if(waserror()) {
|
||||
cclose(c);
|
||||
return -1;
|
||||
}
|
||||
c = fdtochan(fd, OREAD, 1, 1);
|
||||
|
||||
dir = c->qid.path&CHDIR;
|
||||
if(dir) {
|
||||
n -= n%DIRLEN;
|
||||
if(c->offset%DIRLEN || n==0)
|
||||
error(Etoosmall);
|
||||
}
|
||||
|
||||
if(dir && c->mnt)
|
||||
n = unionread((Chan*)c, va, n);
|
||||
else
|
||||
n = (*devtab[c->type].read)((Chan*)c, va, n, c->offset);
|
||||
|
||||
cl = (Lock*)&c->r.l;
|
||||
lock(cl);
|
||||
c->offset += n;
|
||||
unlock(cl);
|
||||
|
||||
poperror();
|
||||
cclose(c);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
sysremove(char *path)
|
||||
{
|
||||
Chan *c = 0;
|
||||
|
||||
if(waserror()) {
|
||||
if(c != 0)
|
||||
c->type = 0; /* see below */
|
||||
cclose(c);
|
||||
return -1;
|
||||
}
|
||||
c = namec(path, Aaccess, 0, 0);
|
||||
(*devtab[c->type].remove)((Chan*)c);
|
||||
/*
|
||||
* Remove clunks the fid, but we need to recover the Chan
|
||||
* so fake it up. rootclose() is known to be a nop.
|
||||
*/
|
||||
c->type = 0;
|
||||
poperror();
|
||||
cclose(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
sysseek(int fd, long off, int whence)
|
||||
{
|
||||
Dir dir;
|
||||
Chan *c;
|
||||
char buf[DIRLEN];
|
||||
|
||||
if(waserror())
|
||||
return -1;
|
||||
|
||||
c = fdtochan(fd, -1, 1, 0);
|
||||
if(c->qid.path & CHDIR)
|
||||
error(Eisdir);
|
||||
|
||||
switch(whence) {
|
||||
case 0:
|
||||
c->offset = off;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
lock(&c->r.l); /* lock for read/write update */
|
||||
c->offset += off;
|
||||
off = c->offset;
|
||||
unlock(&c->r.l);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
(*devtab[c->type].stat)(c, buf);
|
||||
convM2D(buf, &dir);
|
||||
c->offset = dir.length + off;
|
||||
off = c->offset;
|
||||
break;
|
||||
}
|
||||
poperror();
|
||||
return off;
|
||||
}
|
||||
|
||||
int
|
||||
sysstat(char *path, char *buf)
|
||||
{
|
||||
Chan *c = 0;
|
||||
|
||||
if(waserror()){
|
||||
cclose(c);
|
||||
return -1;
|
||||
}
|
||||
c = namec(path, Aaccess, 0, 0);
|
||||
(*devtab[c->type].stat)((Chan*)c, buf);
|
||||
poperror();
|
||||
cclose(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
long
|
||||
syswrite(int fd, void *va, long n)
|
||||
{
|
||||
Lock *cl;
|
||||
Chan *c = 0;
|
||||
|
||||
if(waserror()) {
|
||||
cclose(c);
|
||||
return -1;
|
||||
}
|
||||
c = fdtochan(fd, OWRITE, 1, 1);
|
||||
if(c->qid.path & CHDIR)
|
||||
error(Eisdir);
|
||||
|
||||
n = (*devtab[c->type].write)((Chan*)c, va, n, c->offset);
|
||||
|
||||
cl = (Lock*)&c->r.l;
|
||||
lock(cl);
|
||||
c->offset += n;
|
||||
unlock(cl);
|
||||
|
||||
poperror();
|
||||
cclose(c);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
syswstat(char *path, char *buf)
|
||||
{
|
||||
Chan *c = 0;
|
||||
|
||||
if(waserror()) {
|
||||
cclose(c);
|
||||
return -1;
|
||||
}
|
||||
|
||||
nameok(buf);
|
||||
c = namec(path, Aaccess, 0, 0);
|
||||
(*devtab[c->type].wstat)((Chan*)c, buf);
|
||||
poperror();
|
||||
cclose(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sysdirstat(char *name, Dir *dir)
|
||||
{
|
||||
char buf[DIRLEN];
|
||||
|
||||
if(sysstat(name, buf) == -1)
|
||||
return -1;
|
||||
convM2D(buf, dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sysdirfstat(int fd, Dir *dir)
|
||||
{
|
||||
char buf[DIRLEN];
|
||||
|
||||
if(sysfstat(fd, buf) == -1)
|
||||
return -1;
|
||||
|
||||
convM2D(buf, dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sysdirwstat(char *name, Dir *dir)
|
||||
{
|
||||
char buf[DIRLEN];
|
||||
|
||||
convD2M(dir, buf);
|
||||
return syswstat(name, buf);
|
||||
}
|
||||
|
||||
int
|
||||
sysdirfwstat(int fd, Dir *dir)
|
||||
{
|
||||
char buf[DIRLEN];
|
||||
|
||||
convD2M(dir, buf);
|
||||
return sysfwstat(fd, buf);
|
||||
}
|
||||
|
||||
long
|
||||
sysdirread(int fd, Dir *dbuf, long count)
|
||||
{
|
||||
int c, n, i, r;
|
||||
char buf[DIRLEN*50];
|
||||
|
||||
n = 0;
|
||||
count = (count/sizeof(Dir)) * DIRLEN;
|
||||
while(n < count) {
|
||||
c = count - n;
|
||||
if(c > sizeof(buf))
|
||||
c = sizeof(buf);
|
||||
r = sysread(fd, buf, c);
|
||||
if(r == 0)
|
||||
break;
|
||||
if(r < 0 || r % DIRLEN)
|
||||
return -1;
|
||||
for(i=0; i<r; i+=DIRLEN) {
|
||||
convM2D(buf+i, dbuf);
|
||||
dbuf++;
|
||||
}
|
||||
n += r;
|
||||
if(r != c)
|
||||
break;
|
||||
}
|
||||
|
||||
return (n/DIRLEN) * sizeof(Dir);
|
||||
}
|
||||
|
||||
static int
|
||||
call(char *clone, char *dest, int *cfdp, char *dir, char *local)
|
||||
{
|
||||
int fd, cfd, n;
|
||||
char *p, name[3*NAMELEN+5], data[3*NAMELEN+10];
|
||||
|
||||
cfd = sysopen(clone, ORDWR);
|
||||
if(cfd < 0){
|
||||
werrstr("%s: %r", clone);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* get directory name */
|
||||
n = sysread(cfd, name, sizeof(name)-1);
|
||||
if(n < 0) {
|
||||
sysclose(cfd);
|
||||
return -1;
|
||||
}
|
||||
name[n] = 0;
|
||||
sprint(name, "%d", strtoul(name, 0, 0));
|
||||
p = strrchr(clone, '/');
|
||||
*p = 0;
|
||||
if(dir)
|
||||
snprint(dir, 2*NAMELEN, "%s/%s", clone, name);
|
||||
snprint(data, sizeof(data), "%s/%s/data", clone, name);
|
||||
|
||||
/* connect */
|
||||
/* set local side (port number, for example) if we need to */
|
||||
if(local)
|
||||
snprint(name, sizeof(name), "connect %s %s", dest, local);
|
||||
else
|
||||
snprint(name, sizeof(name), "connect %s", dest);
|
||||
if(syswrite(cfd, name, strlen(name)) < 0){
|
||||
werrstr("%s failed: %r", name);
|
||||
sysclose(cfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* open data connection */
|
||||
fd = sysopen(data, ORDWR);
|
||||
if(fd < 0){
|
||||
werrstr("can't open %s: %r", data);
|
||||
sysclose(cfd);
|
||||
return -1;
|
||||
}
|
||||
if(cfdp)
|
||||
*cfdp = cfd;
|
||||
else
|
||||
sysclose(cfd);
|
||||
return fd;
|
||||
}
|
||||
|
||||
int
|
||||
sysdial(char *dest, char *local, char *dir, int *cfdp)
|
||||
{
|
||||
int n, fd, rv;
|
||||
char *p, net[128], clone[NAMELEN+12];
|
||||
|
||||
/* go for a standard form net!... */
|
||||
p = strchr(dest, '!');
|
||||
if(p == 0){
|
||||
snprint(net, sizeof(net), "net!%s", dest);
|
||||
} else {
|
||||
strncpy(net, dest, sizeof(net)-1);
|
||||
net[sizeof(net)-1] = 0;
|
||||
}
|
||||
|
||||
/* call the connection server */
|
||||
fd = sysopen("/net/cs", ORDWR);
|
||||
if(fd < 0){
|
||||
/* no connection server, don't translate */
|
||||
p = strchr(net, '!');
|
||||
*p++ = 0;
|
||||
snprint(clone, sizeof(clone), "/net/%s/clone", net);
|
||||
return call(clone, p, cfdp, dir, local);
|
||||
}
|
||||
|
||||
/*
|
||||
* send dest to connection to translate
|
||||
*/
|
||||
if(syswrite(fd, net, strlen(net)) < 0){
|
||||
werrstr("%s: %r", net);
|
||||
sysclose(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* loop through each address from the connection server till
|
||||
* we get one that works.
|
||||
*/
|
||||
rv = -1;
|
||||
sysseek(fd, 0, 0);
|
||||
while((n = sysread(fd, net, sizeof(net) - 1)) > 0){
|
||||
net[n] = 0;
|
||||
p = strchr(net, ' ');
|
||||
if(p == 0)
|
||||
continue;
|
||||
*p++ = 0;
|
||||
rv = call(net, p, cfdp, dir, local);
|
||||
if(rv >= 0)
|
||||
break;
|
||||
}
|
||||
sysclose(fd);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int
|
||||
identtrans(char *addr, char *naddr, int na, char *file, int nf)
|
||||
{
|
||||
char *p;
|
||||
char reply[4*NAMELEN];
|
||||
|
||||
/* parse the network */
|
||||
strncpy(reply, addr, sizeof(reply));
|
||||
reply[sizeof(reply)-1] = 0;
|
||||
p = strchr(reply, '!');
|
||||
if(p)
|
||||
*p++ = 0;
|
||||
|
||||
sprint(file, "/net/%.*s/clone", na - sizeof("/net//clone"), reply);
|
||||
strncpy(naddr, p, na);
|
||||
naddr[na-1] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
nettrans(char *addr, char *naddr, int na, char *file, int nf)
|
||||
{
|
||||
long n;
|
||||
int fd;
|
||||
char *cp;
|
||||
char reply[4*NAMELEN];
|
||||
|
||||
/*
|
||||
* ask the connection server
|
||||
*/
|
||||
fd = sysopen("/net/cs", ORDWR);
|
||||
if(fd < 0)
|
||||
return identtrans(addr, naddr, na, file, nf);
|
||||
if(syswrite(fd, addr, strlen(addr)) < 0){
|
||||
sysclose(fd);
|
||||
return -1;
|
||||
}
|
||||
sysseek(fd, 0, 0);
|
||||
n = sysread(fd, reply, sizeof(reply)-1);
|
||||
sysclose(fd);
|
||||
if(n <= 0)
|
||||
return -1;
|
||||
reply[n] = '\0';
|
||||
|
||||
/*
|
||||
* parse the reply
|
||||
*/
|
||||
cp = strchr(reply, ' ');
|
||||
if(cp == 0)
|
||||
return -1;
|
||||
*cp++ = 0;
|
||||
strncpy(naddr, cp, na);
|
||||
naddr[na-1] = 0;
|
||||
strncpy(file, reply, nf);
|
||||
file[nf-1] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
sysannounce(char *addr, char *dir)
|
||||
{
|
||||
char *cp;
|
||||
int ctl, n, m;
|
||||
char buf[3*NAMELEN];
|
||||
char buf2[3*NAMELEN];
|
||||
char netdir[2*NAMELEN];
|
||||
char naddr[3*NAMELEN];
|
||||
|
||||
/*
|
||||
* translate the address
|
||||
*/
|
||||
if(nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0){
|
||||
werrstr("can't translate address");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* get a control channel
|
||||
*/
|
||||
ctl = sysopen(netdir, ORDWR);
|
||||
if(ctl<0){
|
||||
werrstr("can't open control channel");
|
||||
return -1;
|
||||
}
|
||||
cp = strrchr(netdir, '/');
|
||||
*cp = 0;
|
||||
|
||||
/*
|
||||
* find out which line we have
|
||||
*/
|
||||
n = sprint(buf, "%.*s/", 2*NAMELEN+1, netdir);
|
||||
m = sysread(ctl, &buf[n], sizeof(buf)-n-1);
|
||||
if(m <= 0) {
|
||||
sysclose(ctl);
|
||||
werrstr("can't read control file");
|
||||
return -1;
|
||||
}
|
||||
buf[n+m] = 0;
|
||||
|
||||
/*
|
||||
* make the call
|
||||
*/
|
||||
n = sprint(buf2, "announce %.*s", 2*NAMELEN, naddr);
|
||||
if(syswrite(ctl, buf2, n) != n) {
|
||||
sysclose(ctl);
|
||||
werrstr("announcement fails");
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(dir, buf);
|
||||
|
||||
return ctl;
|
||||
}
|
||||
|
||||
int
|
||||
syslisten(char *dir, char *newdir)
|
||||
{
|
||||
char *cp;
|
||||
int ctl, n, m;
|
||||
char buf[3*NAMELEN];
|
||||
|
||||
/*
|
||||
* open listen, wait for a call
|
||||
*/
|
||||
sprint(buf, "%.*s/listen", 2*NAMELEN+1, dir);
|
||||
ctl = sysopen(buf, ORDWR);
|
||||
if(ctl < 0)
|
||||
return -1;
|
||||
|
||||
/*
|
||||
* find out which line we have
|
||||
*/
|
||||
strcpy(buf, dir);
|
||||
cp = strrchr(buf, '/');
|
||||
*++cp = 0;
|
||||
n = cp-buf;
|
||||
m = sysread(ctl, cp, sizeof(buf) - n - 1);
|
||||
if(n<=0){
|
||||
sysclose(ctl);
|
||||
return -1;
|
||||
}
|
||||
buf[n+m] = 0;
|
||||
|
||||
strcpy(newdir, buf);
|
||||
return ctl;
|
||||
}
|
1242
kern/sysfile.c
Normal file
1242
kern/sysfile.c
Normal file
File diff suppressed because it is too large
Load Diff
32
kern/sysproc.c
Normal file
32
kern/sysproc.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
long
|
||||
sysexits(ulong *arg)
|
||||
{
|
||||
char *status;
|
||||
char *inval = "invalid exit string";
|
||||
char buf[ERRMAX];
|
||||
|
||||
status = (char*)arg[0];
|
||||
if(status){
|
||||
if(waserror())
|
||||
status = inval;
|
||||
else{
|
||||
validaddr((ulong)status, 1, 0);
|
||||
if(vmemchr(status, 0, ERRMAX) == 0){
|
||||
memmove(buf, status, ERRMAX);
|
||||
buf[ERRMAX-1] = 0;
|
||||
status = buf;
|
||||
}
|
||||
}
|
||||
poperror();
|
||||
|
||||
}
|
||||
pexit(status, 1);
|
||||
return 0; /* not reached */
|
||||
}
|
||||
|
204
kern/term.c
Normal file
204
kern/term.c
Normal file
@ -0,0 +1,204 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
#include "screen.h"
|
||||
|
||||
#define MINX 8
|
||||
#define Backgnd 0xFF /* white */
|
||||
|
||||
Memsubfont *memdefont;
|
||||
|
||||
struct{
|
||||
Point pos;
|
||||
int bwid;
|
||||
}out;
|
||||
|
||||
Lock screenlock;
|
||||
|
||||
Memimage *conscol;
|
||||
Memimage *back;
|
||||
extern Memimage *gscreen;
|
||||
|
||||
static Rectangle flushr;
|
||||
static Rectangle window;
|
||||
static Point curpos;
|
||||
static int h, w;
|
||||
static void termscreenputs(char*, int);
|
||||
|
||||
Point ZP;
|
||||
|
||||
static void
|
||||
screenflush(void)
|
||||
{
|
||||
drawflushr(flushr);
|
||||
flushr = Rect(10000, 10000, -10000, -10000);
|
||||
}
|
||||
|
||||
static void
|
||||
addflush(Rectangle r)
|
||||
{
|
||||
if(flushr.min.x >= flushr.max.x)
|
||||
flushr = r;
|
||||
else
|
||||
combinerect(&flushr, r);
|
||||
}
|
||||
|
||||
static void
|
||||
screenwin(void)
|
||||
{
|
||||
Point p, q;
|
||||
char *greet;
|
||||
Memimage *grey;
|
||||
|
||||
back = memwhite;
|
||||
conscol = memblack;
|
||||
memfillcolor(gscreen, 0x444488FF);
|
||||
|
||||
w = memdefont->info[' '].width;
|
||||
h = memdefont->height;
|
||||
|
||||
window.min = addpt(gscreen->r.min, Pt(20,20));
|
||||
window.max.x = window.min.x + Dx(gscreen->r)*3/4-40;
|
||||
window.max.y = window.min.y + Dy(gscreen->r)*3/4-100;
|
||||
|
||||
memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S);
|
||||
window = insetrect(window, 4);
|
||||
memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
|
||||
|
||||
/* a lot of work to get a grey color */
|
||||
grey = allocmemimage(Rect(0,0,1,1), CMAP8);
|
||||
grey->flags |= Frepl;
|
||||
grey->clipr = gscreen->r;
|
||||
memfillcolor(grey, 0xAAAAAAFF);
|
||||
memimagedraw(gscreen, Rect(window.min.x, window.min.y,
|
||||
window.max.x, window.min.y+h+5+6), grey, ZP, nil, ZP, S);
|
||||
freememimage(grey);
|
||||
window = insetrect(window, 5);
|
||||
|
||||
greet = " Plan 9 Console ";
|
||||
p = addpt(window.min, Pt(10, 0));
|
||||
q = memsubfontwidth(memdefont, greet);
|
||||
memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
|
||||
window.min.y += h+6;
|
||||
curpos = window.min;
|
||||
window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
|
||||
flushmemscreen(gscreen->r);
|
||||
}
|
||||
|
||||
void
|
||||
terminit(void)
|
||||
{
|
||||
memdefont = getmemdefont();
|
||||
out.pos.x = MINX;
|
||||
out.pos.y = 0;
|
||||
out.bwid = memdefont->info[' '].width;
|
||||
screenwin();
|
||||
screenputs = termscreenputs;
|
||||
}
|
||||
|
||||
static void
|
||||
scroll(void)
|
||||
{
|
||||
int o;
|
||||
Point p;
|
||||
Rectangle r;
|
||||
|
||||
o = 8*h;
|
||||
r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
|
||||
p = Pt(window.min.x, window.min.y+o);
|
||||
memimagedraw(gscreen, r, gscreen, p, nil, p, S);
|
||||
r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
|
||||
memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
|
||||
flushmemscreen(gscreen->r);
|
||||
|
||||
curpos.y -= o;
|
||||
}
|
||||
|
||||
static void
|
||||
screenputc(char *buf)
|
||||
{
|
||||
Point p;
|
||||
int w, pos;
|
||||
Rectangle r;
|
||||
static int *xp;
|
||||
static int xbuf[256];
|
||||
|
||||
if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
|
||||
xp = xbuf;
|
||||
|
||||
switch(buf[0]) {
|
||||
case '\n':
|
||||
if(curpos.y+h >= window.max.y)
|
||||
scroll();
|
||||
curpos.y += h;
|
||||
screenputc("\r");
|
||||
break;
|
||||
case '\r':
|
||||
xp = xbuf;
|
||||
curpos.x = window.min.x;
|
||||
break;
|
||||
case '\t':
|
||||
p = memsubfontwidth(memdefont, " ");
|
||||
w = p.x;
|
||||
*xp++ = curpos.x;
|
||||
pos = (curpos.x-window.min.x)/w;
|
||||
pos = 8-(pos%8);
|
||||
r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
|
||||
memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
|
||||
addflush(r);
|
||||
curpos.x += pos*w;
|
||||
break;
|
||||
case '\b':
|
||||
if(xp <= xbuf)
|
||||
break;
|
||||
xp--;
|
||||
r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
|
||||
memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
|
||||
addflush(r);
|
||||
curpos.x = *xp;
|
||||
break;
|
||||
default:
|
||||
p = memsubfontwidth(memdefont, buf);
|
||||
w = p.x;
|
||||
|
||||
if(curpos.x >= window.max.x-w)
|
||||
screenputc("\n");
|
||||
|
||||
*xp++ = curpos.x;
|
||||
r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h);
|
||||
memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
|
||||
memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
|
||||
addflush(r);
|
||||
curpos.x += w;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
termscreenputs(char *s, int n)
|
||||
{
|
||||
int i;
|
||||
Rune r;
|
||||
char buf[4];
|
||||
|
||||
lock(&screenlock);
|
||||
while(n > 0){
|
||||
i = chartorune(&r, s);
|
||||
if(i == 0){
|
||||
s++;
|
||||
--n;
|
||||
continue;
|
||||
}
|
||||
memmove(buf, s, i);
|
||||
buf[i] = 0;
|
||||
n -= i;
|
||||
s += i;
|
||||
screenputc(buf);
|
||||
}
|
||||
screenflush();
|
||||
unlock(&screenlock);
|
||||
}
|
0
kern/todo.c
Normal file
0
kern/todo.c
Normal file
14
kern/uart.c
Normal file
14
kern/uart.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
#undef write
|
||||
void
|
||||
uartputs(char *s, int n)
|
||||
{
|
||||
write(1, s, n);
|
||||
}
|
||||
|
||||
|
27
kern/waserror.c
Normal file
27
kern/waserror.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
Label*
|
||||
pwaserror(void)
|
||||
{
|
||||
if(up->nerrlab == NERR)
|
||||
panic("error stack overflow");
|
||||
return &up->errlab[up->nerrlab++];
|
||||
}
|
||||
|
||||
void
|
||||
nexterror(void)
|
||||
{
|
||||
longjmp(up->errlab[--up->nerrlab].buf, 1);
|
||||
}
|
||||
|
||||
void
|
||||
error(char *e)
|
||||
{
|
||||
kstrcpy(up->errstr, e, ERRMAX);
|
||||
setjmp(up->errlab[NERR-1].buf);
|
||||
nexterror();
|
||||
}
|
18
kern/winduhz.h
Normal file
18
kern/winduhz.h
Normal file
@ -0,0 +1,18 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <setjmp.h>
|
||||
#include <direct.h>
|
||||
#include <process.h>
|
||||
#include <time.h>
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* disable various silly warnings */
|
||||
#pragma warning( disable : 4245 4305 4244 4102 4761 4090 4028 4024)
|
||||
|
||||
typedef __int64 p9_vlong;
|
||||
typedef unsigned __int64 p9_uvlong;
|
601
kern/x
Normal file
601
kern/x
Normal file
@ -0,0 +1,601 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h> /* for remove, rename */
|
||||
#include <limits.h>
|
||||
|
||||
#ifndef NAME_MAX
|
||||
# define NAME_MAX 256
|
||||
#endif
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
|
||||
typedef struct Ufsinfo Ufsinfo;
|
||||
|
||||
enum
|
||||
{
|
||||
NUID = 256,
|
||||
NGID = 256,
|
||||
MAXPATH = 1024,
|
||||
MAXCOMP = 128
|
||||
};
|
||||
|
||||
struct Ufsinfo
|
||||
{
|
||||
int mode;
|
||||
int fd;
|
||||
DIR* dir;
|
||||
ulong offset;
|
||||
QLock oq;
|
||||
char nextname[NAME_MAX];
|
||||
};
|
||||
|
||||
char *base = "/";
|
||||
|
||||
static Qid fsqid(char*, struct stat *);
|
||||
static void fspath(Chan*, char*, char*);
|
||||
static ulong fsdirread(Chan*, uchar*, int, ulong);
|
||||
static int fsomode(int);
|
||||
|
||||
static char*
|
||||
lastelem(Chan *c)
|
||||
{
|
||||
char *s, *t;
|
||||
|
||||
s = c2name(c);
|
||||
if((t = strrchr(s, '/')) == nil)
|
||||
return s;
|
||||
if(t[1] == 0)
|
||||
return t;
|
||||
return t+1;
|
||||
}
|
||||
|
||||
static Chan*
|
||||
fsattach(char *spec)
|
||||
{
|
||||
Chan *c;
|
||||
struct stat stbuf;
|
||||
static int devno;
|
||||
Ufsinfo *uif;
|
||||
|
||||
if(stat(base, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
c = devattach('U', spec);
|
||||
|
||||
uif = mallocz(sizeof(Ufsinfo), 1);
|
||||
uif->mode = stbuf.st_mode;
|
||||
|
||||
c->aux = uif;
|
||||
c->dev = devno++;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static Chan*
|
||||
fsclone(Chan *c, Chan *nc)
|
||||
{
|
||||
Ufsinfo *uif;
|
||||
|
||||
uif = mallocz(sizeof(Ufsinfo), 1);
|
||||
*uif = *(Ufsinfo*)c->aux;
|
||||
nc->aux = uif;
|
||||
|
||||
return nc;
|
||||
}
|
||||
|
||||
static int
|
||||
fswalk1(Chan *c, char *name)
|
||||
{
|
||||
struct stat stbuf;
|
||||
char path[MAXPATH];
|
||||
Ufsinfo *uif;
|
||||
|
||||
fspath(c, name, path);
|
||||
|
||||
/* print("** fs walk '%s' -> %s\n", path, name); */
|
||||
|
||||
if(stat(path, &stbuf) < 0)
|
||||
return 0;
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
uif->mode = stbuf.st_mode;
|
||||
|
||||
c->qid = fsqid(path, &stbuf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static Walkqid*
|
||||
fswalk(Chan *c, Chan *nc, char **name, int nname)
|
||||
{
|
||||
int i;
|
||||
Walkqid *wq;
|
||||
|
||||
if(nc != nil)
|
||||
panic("fswalk: nc != nil");
|
||||
wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
|
||||
nc = devclone(c);
|
||||
fsclone(c, nc);
|
||||
wq->clone = nc;
|
||||
for(i=0; i<nname; i++){
|
||||
if(fswalk1(nc, name[i]) == 0)
|
||||
break;
|
||||
wq->qid[i] = nc->qid;
|
||||
}
|
||||
if(i != nname){
|
||||
cclose(nc);
|
||||
wq->clone = nil;
|
||||
}
|
||||
wq->nqid = i;
|
||||
return wq;
|
||||
}
|
||||
|
||||
static int
|
||||
fsstat(Chan *c, uchar *buf, int n)
|
||||
{
|
||||
Dir d;
|
||||
struct stat stbuf;
|
||||
char path[MAXPATH];
|
||||
|
||||
if(n < BIT16SZ)
|
||||
error(Eshortstat);
|
||||
|
||||
fspath(c, 0, path);
|
||||
if(stat(path, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
d.name = lastelem(c);
|
||||
d.uid = "unknown";
|
||||
d.gid = "unknown";
|
||||
d.qid = c->qid;
|
||||
d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777);
|
||||
d.atime = stbuf.st_atime;
|
||||
d.mtime = stbuf.st_mtime;
|
||||
d.length = stbuf.st_size;
|
||||
d.type = 'U';
|
||||
d.dev = c->dev;
|
||||
return convD2M(&d, buf, n);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
fsopen(Chan *c, int mode)
|
||||
{
|
||||
char path[MAXPATH];
|
||||
int m, isdir;
|
||||
Ufsinfo *uif;
|
||||
|
||||
m = mode & (OTRUNC|3);
|
||||
switch(m) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
case 1|16:
|
||||
break;
|
||||
case 2:
|
||||
case 0|16:
|
||||
case 2|16:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
error(Ebadarg);
|
||||
}
|
||||
|
||||
isdir = c->qid.type & QTDIR;
|
||||
|
||||
if(isdir && mode != OREAD)
|
||||
error(Eperm);
|
||||
|
||||
m = fsomode(m & 3);
|
||||
c->mode = openmode(mode);
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
fspath(c, 0, path);
|
||||
if(isdir) {
|
||||
uif->dir = opendir(path);
|
||||
if(uif->dir == 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
else {
|
||||
if(mode & OTRUNC)
|
||||
m |= O_TRUNC;
|
||||
uif->fd = open(path, m, 0666);
|
||||
|
||||
if(uif->fd < 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
uif->offset = 0;
|
||||
|
||||
c->offset = 0;
|
||||
c->flag |= COPEN;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void
|
||||
fscreate(Chan *c, char *name, int mode, ulong perm)
|
||||
{
|
||||
int fd, m;
|
||||
char path[MAXPATH];
|
||||
struct stat stbuf;
|
||||
Ufsinfo *uif;
|
||||
|
||||
m = fsomode(mode&3);
|
||||
|
||||
fspath(c, name, path);
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
if(perm & DMDIR) {
|
||||
if(m)
|
||||
error(Eperm);
|
||||
|
||||
if(mkdir(path, perm & 0777) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
fd = open(path, 0);
|
||||
if(fd >= 0) {
|
||||
chmod(path, perm & 0777);
|
||||
chown(path, uif->uid, uif->uid);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
uif->dir = opendir(path);
|
||||
if(uif->dir == 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
else {
|
||||
fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0666);
|
||||
if(fd >= 0) {
|
||||
if(m != 1) {
|
||||
close(fd);
|
||||
fd = open(path, m);
|
||||
}
|
||||
chmod(path, perm & 0777);
|
||||
chown(path, uif->uid, uif->gid);
|
||||
}
|
||||
if(fd < 0)
|
||||
error(strerror(errno));
|
||||
uif->fd = fd;
|
||||
}
|
||||
|
||||
if(stat(path, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
c->qid = fsqid(path, &stbuf);
|
||||
c->offset = 0;
|
||||
c->flag |= COPEN;
|
||||
c->mode = openmode(mode);
|
||||
}
|
||||
|
||||
static void
|
||||
fsclose(Chan *c)
|
||||
{
|
||||
Ufsinfo *uif;
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
if(c->flag & COPEN) {
|
||||
if(c->qid.type & QTDIR)
|
||||
closedir(uif->dir);
|
||||
else
|
||||
close(uif->fd);
|
||||
}
|
||||
|
||||
free(uif);
|
||||
}
|
||||
|
||||
static long
|
||||
fsread(Chan *c, void *va, long n, vlong offset)
|
||||
{
|
||||
int fd, r;
|
||||
Ufsinfo *uif;
|
||||
|
||||
if(c->qid.type & QTDIR)
|
||||
return fsdirread(c, va, n, offset);
|
||||
|
||||
uif = c->aux;
|
||||
qlock(&uif->oq);
|
||||
if(waserror()) {
|
||||
qunlock(&uif->oq);
|
||||
nexterror();
|
||||
}
|
||||
fd = uif->fd;
|
||||
if(uif->offset != offset) {
|
||||
r = lseek(fd, offset, 0);
|
||||
if(r < 0)
|
||||
error(strerror(errno));
|
||||
uif->offset = offset;
|
||||
}
|
||||
|
||||
n = read(fd, va, n);
|
||||
if(n < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif->offset += n;
|
||||
qunlock(&uif->oq);
|
||||
poperror();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static long
|
||||
fswrite(Chan *c, void *va, long n, vlong offset)
|
||||
{
|
||||
int fd, r;
|
||||
Ufsinfo *uif;
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
qlock(&uif->oq);
|
||||
if(waserror()) {
|
||||
qunlock(&uif->oq);
|
||||
nexterror();
|
||||
}
|
||||
fd = uif->fd;
|
||||
if(uif->offset != offset) {
|
||||
r = lseek(fd, offset, 0);
|
||||
if(r < 0)
|
||||
error(strerror(errno));
|
||||
uif->offset = offset;
|
||||
}
|
||||
|
||||
n = write(fd, va, n);
|
||||
if(n < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif->offset += n;
|
||||
qunlock(&uif->oq);
|
||||
poperror();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
fsremove(Chan *c)
|
||||
{
|
||||
int n;
|
||||
char path[MAXPATH];
|
||||
|
||||
fspath(c, 0, path);
|
||||
if(c->qid.type & QTDIR)
|
||||
n = rmdir(path);
|
||||
else
|
||||
n = remove(path);
|
||||
if(n < 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
|
||||
void
|
||||
fswstat(Chan *c, uchar *buf, int n)
|
||||
{
|
||||
Dir d;
|
||||
struct stat stbuf;
|
||||
char old[MAXPATH], new[MAXPATH], dir[MAXPATH];
|
||||
char strs[MAXPATH*3];
|
||||
Ufsinfo *uif;
|
||||
|
||||
if(convM2D(buf, n, &d, strs) != n)
|
||||
error(Ebadstat);
|
||||
|
||||
fspath(c, 0, old);
|
||||
if(stat(old, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) {
|
||||
fspath(c->parent, 0, dir);
|
||||
fspath(c, 0, old);
|
||||
strcpy(new, old);
|
||||
p = strrchr(new, '/');
|
||||
strcpy(p+1, d.name);
|
||||
if(rename(old, new) < 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
|
||||
fspath(c, 0, old);
|
||||
if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
|
||||
if(chmod(old, d.mode&0777) < 0)
|
||||
error(strerror(errno));
|
||||
uif->mode &= ~0777;
|
||||
uif->mode |= d.mode&0777;
|
||||
}
|
||||
/*
|
||||
p = name2pass(gid, d.gid);
|
||||
if(p == 0)
|
||||
error(Eunknown);
|
||||
|
||||
if(p->id != stbuf.st_gid) {
|
||||
if(chown(old, stbuf.st_uid, p->id) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif->gid = p->id;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
static Qid
|
||||
fsqid(char *p, struct stat *st)
|
||||
{
|
||||
Qid q;
|
||||
int dev;
|
||||
ulong h;
|
||||
static int nqdev;
|
||||
static uchar *qdev;
|
||||
|
||||
if(qdev == 0)
|
||||
qdev = mallocz(65536U, 1);
|
||||
|
||||
q.type = 0;
|
||||
if((st->st_mode&S_IFMT) == S_IFDIR)
|
||||
q.type = QTDIR;
|
||||
|
||||
dev = st->st_dev & 0xFFFFUL;
|
||||
if(qdev[dev] == 0)
|
||||
qdev[dev] = ++nqdev;
|
||||
|
||||
h = 0;
|
||||
while(*p != '\0')
|
||||
h += *p++ * 13;
|
||||
|
||||
q.path = (vlong)qdev[dev]<<32;
|
||||
q.path |= h;
|
||||
q.vers = st->st_mtime;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
static void
|
||||
fspath(Chan *c, char *ext, char *path)
|
||||
{
|
||||
int i, n;
|
||||
char *comp[MAXCOMP];
|
||||
|
||||
strcpy(path, base);
|
||||
strcat(path, "/");
|
||||
strcat(path, c2name(c));
|
||||
if(ext){
|
||||
strcat(path, "/");
|
||||
strcat(path, ext);
|
||||
}
|
||||
cleanname(path);
|
||||
}
|
||||
|
||||
static int
|
||||
isdots(char *name)
|
||||
{
|
||||
if(name[0] != '.')
|
||||
return 0;
|
||||
if(name[1] == '\0')
|
||||
return 1;
|
||||
if(name[1] != '.')
|
||||
return 0;
|
||||
if(name[2] == '\0')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
p9readdir(char *name, Ufsinfo *uif)
|
||||
{
|
||||
struct dirent *de;
|
||||
|
||||
if(uif->nextname[0]){
|
||||
strcpy(name, uif->nextname);
|
||||
uif->nextname[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
de = readdir(uif->dir);
|
||||
if(de == NULL)
|
||||
return 0;
|
||||
|
||||
strcpy(name, de->d_name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ulong
|
||||
fsdirread(Chan *c, uchar *va, int count, ulong offset)
|
||||
{
|
||||
int i;
|
||||
Dir d;
|
||||
long n;
|
||||
char de[NAME_MAX];
|
||||
struct stat stbuf;
|
||||
char path[MAXPATH], dirpath[MAXPATH];
|
||||
Ufsinfo *uif;
|
||||
int n;
|
||||
|
||||
i = 0;
|
||||
uif = c->aux;
|
||||
|
||||
errno = 0;
|
||||
if(uif->offset != offset) {
|
||||
if(offset != 0)
|
||||
error("bad offset in fsdirread");
|
||||
uif->offset = offset; /* sync offset */
|
||||
uif->nextname[0] = 0;
|
||||
rewinddir(uif->dir);
|
||||
}
|
||||
|
||||
fspath(c, 0, dirpath);
|
||||
|
||||
while(i+BIT16SZ < count) {
|
||||
if(!p9readdir(de, uif))
|
||||
break;
|
||||
|
||||
if(de[0]==0 || isdots(de))
|
||||
continue;
|
||||
|
||||
d.name = de;
|
||||
sprint(path, "%s/%s", dirpath, de);
|
||||
memset(&stbuf, 0, sizeof stbuf);
|
||||
|
||||
if(stat(path, &stbuf) < 0) {
|
||||
fprint(2, "dir: bad path %s\n", path);
|
||||
/* but continue... probably a bad symlink */
|
||||
}
|
||||
|
||||
d.uid = "unknown";
|
||||
d.gid = "unknown";
|
||||
d.qid = fsqid(path, &stbuf);
|
||||
d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777);
|
||||
d.atime = stbuf.st_atime;
|
||||
d.mtime = stbuf.st_mtime;
|
||||
d.length = stbuf.st_size;
|
||||
d.type = 'U';
|
||||
d.dev = c->dev;
|
||||
n = convD2M(&d, (char*)va+i, count-i);
|
||||
if(n == BIT16SZ){
|
||||
strcpy(uif->nextname, de);
|
||||
break;
|
||||
}
|
||||
i += n;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int
|
||||
fsomode(int m)
|
||||
{
|
||||
switch(m) {
|
||||
case 0: /* OREAD */
|
||||
case 3: /* OEXEC */
|
||||
return 0;
|
||||
case 1: /* OWRITE */
|
||||
return 1;
|
||||
case 2: /* ORDWR */
|
||||
return 2;
|
||||
}
|
||||
error(Ebadarg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Dev fsdevtab = {
|
||||
'U',
|
||||
"fs",
|
||||
|
||||
devreset,
|
||||
devinit,
|
||||
devshutdown,
|
||||
fsattach,
|
||||
fswalk,
|
||||
fsstat,
|
||||
fsopen,
|
||||
fscreate,
|
||||
fsclose,
|
||||
fsread,
|
||||
devbread,
|
||||
fswrite,
|
||||
devbwrite,
|
||||
fsremove,
|
||||
fswstat,
|
||||
};
|
177
latin1.c
Normal file
177
latin1.c
Normal file
@ -0,0 +1,177 @@
|
||||
#include "u.h"
|
||||
#include "libc.h"
|
||||
|
||||
/*
|
||||
* The code makes two assumptions: strlen(ld) is 1 or 2; latintab[i].ld can be a
|
||||
* prefix of latintab[j].ld only when j<i.
|
||||
*/
|
||||
struct cvlist
|
||||
{
|
||||
char *ld; /* must be seen before using this conversion */
|
||||
char *si; /* options for last input characters */
|
||||
Rune so[50]; /* the corresponding Rune for each si entry */
|
||||
} latintab[] = {
|
||||
" ", " i", { 0x2423, 0x0131 },
|
||||
"w", "kqrbnp", { 0x2654, 0x2655, 0x2656, 0x2657, 0x2658, 0x2659, },
|
||||
"x", "O", { 0x2297, },
|
||||
"f", "a", { 0x2200, },
|
||||
"=", "V:=O<>", { 0x21D2, 0x2255, 0x2261, 0x229C, 0x22DC, 0x22DD, },
|
||||
"V", "=", { 0x21D0, },
|
||||
"7", "8", { 0x215E, },
|
||||
"5", "68", { 0x215A, 0x215D, },
|
||||
"4", "5", { 0x2158, },
|
||||
"R", "R", { 0x211D, },
|
||||
"Q", "Q", { 0x211A, },
|
||||
"P", "P", { 0x2119, },
|
||||
"C", "CAU", { 0x2102, 0x22C2, 0x22C3, },
|
||||
"e", "nmsl", { 0x2013, 0x2014, 0x2205, 0x22EF, },
|
||||
"b", "u0123456789+-=()kqrbnp", { 0x2022, 0x2080, 0x2081, 0x2082, 0x2083, 0x2084, 0x2085, 0x2086, 0x2087, 0x2088, 0x2089, 0x208A, 0x208B, 0x208C, 0x208D, 0x208E, 0x265A, 0x265B, 0x265C, 0x265D, 0x265E, 0x265F, },
|
||||
"@e", "h", { 0x44D, },
|
||||
"@\'", "\'", { 0x44A, },
|
||||
"@s", "hc", { 0x448, 0x449, },
|
||||
"@c", "h", { 0x447, },
|
||||
"@t", "s", { 0x446, },
|
||||
"@k", "h", { 0x445, },
|
||||
"@z", "h", { 0x436, },
|
||||
"@y", "euao", { 0x435, 0x44E, 0x44F, 0x451, },
|
||||
"@E", "Hh", { 0x42D, 0x42D, },
|
||||
"@S", "HhCc", { 0x428, 0x428, 0x429, 0x429, },
|
||||
"@C", "Hh", { 0x427, 0x427, },
|
||||
"@T", "Ss", { 0x426, 0x426, },
|
||||
"@K", "Hh", { 0x425, 0x425, },
|
||||
"@Z", "Hh", { 0x416, 0x416, },
|
||||
"@@", "EZKSTYezksty\'", { 0x415, 0x417, 0x41A, 0x421, 0x422, 0x42B, 0x435, 0x437, 0x43A, 0x441, 0x442, 0x44B, 0x44C, },
|
||||
"@Y", "OoEeUuAa", { 0x401, 0x401, 0x415, 0x415, 0x42E, 0x42E, 0x42F, 0x42F, },
|
||||
"@", "ABVGDIJLMNOPRUFXabvgdijlmnoprufx", { 0x410, 0x411, 0x412, 0x413, 0x414, 0x418, 0x419, 0x41B, 0x41C, 0x41D, 0x41E, 0x41F, 0x420, 0x423, 0x424, 0x425, 0x430, 0x431, 0x432, 0x433, 0x434, 0x438, 0x439, 0x43B, 0x43C, 0x43D, 0x43E, 0x43F, 0x440, 0x443, 0x444, 0x445, },
|
||||
"*", "ABGDEZYHIKLMNCOPRSTUFXQWabgdezyhiklmncoprstufxqw*", { 0x391, 0x392, 0x393, 0x394, 0x395, 0x396, 0x397, 0x398, 0x399, 0x39A, 0x39B, 0x39C, 0x39D, 0x39E, 0x39F, 0x3A0, 0x3A1, 0x3A3, 0x3A4, 0x3A5, 0x3A6, 0x3A7, 0x3A8, 0x3A9, 0x3B1, 0x3B2, 0x3B3, 0x3B4, 0x3B5, 0x3B6, 0x3B7, 0x3B8, 0x3B9, 0x3BA, 0x3BB, 0x3BC, 0x3BD, 0x3BE, 0x3BF, 0x3C0, 0x3C1, 0x3C3, 0x3C4, 0x3C5, 0x3C6, 0x3C7, 0x3C8, 0x3C9, 0x2217, },
|
||||
"G", "-", { 0x1E4, },
|
||||
"N", "JjN", { 0x1CA, 0x1CB, 0x2115, },
|
||||
"2", "-35", { 0x1BB, 0x2154, 0x2156, },
|
||||
"z", "-", { 0x1B6, },
|
||||
"Z", "-Z", { 0x1B5, 0x2124, },
|
||||
"Y", "R", { 0x1A6, },
|
||||
"h", "v-", { 0x195, 0x210F, },
|
||||
"$*", "hfk", { 0x3D1, 0x3D5, 0x3F0, },
|
||||
"$", "fVavgHILlpRBeEFMo", { 0x192, 0x1B2, 0x251, 0x28B, 0x210A, 0x210B, 0x2110, 0x2112, 0x2113, 0x2118, 0x211B, 0x212C, 0x212F, 0x2130, 0x2131, 0x2133, 0x2134, },
|
||||
"t", "-smefu", { 0x167, 0x3C2, 0x2122, 0x2203, 0x2234, 0x22A2, },
|
||||
"T", "-u", { 0x166, 0x22A8, },
|
||||
"L", "-Jj&|", { 0x141, 0x1C7, 0x1C8, 0x22C0, 0x22C1, },
|
||||
"i", "j-fsbp", { 0x133, 0x268, 0x221E, 0x222B, 0x2286, 0x2287, },
|
||||
"I", "J-", { 0x132, 0x197, },
|
||||
"H", "-H", { 0x126, 0x210D, },
|
||||
"v\"", "Uu", { 0x1D9, 0x1DA, },
|
||||
"v", "CcDdEeLlNnRrSsTtZzAaIiOoUuGgKkj", { 0x10C, 0x10D, 0x10E, 0x10F, 0x11A, 0x11B, 0x13D, 0x13E, 0x147, 0x148, 0x158, 0x159, 0x160, 0x161, 0x164, 0x165, 0x17D, 0x17E, 0x1CD, 0x1CE, 0x1CF, 0x1D0, 0x1D1, 0x1D2, 0x1D3, 0x1D4, 0x1E6, 0x1E7, 0x1E8, 0x1E9, 0x1F0, },
|
||||
"u", "AEeGgIiOoUu-a", { 0x102, 0x114, 0x115, 0x11E, 0x11F, 0x12C, 0x12D, 0x14E, 0x14F, 0x16C, 0x16D, 0x289, 0x2191, },
|
||||
":", "-=()", { 0xF7, 0x2254, 0x2639, 0x263A, },
|
||||
"a", "ebn", { 0xE6, 0x2194, 0x2220, },
|
||||
"/", "Oo", { 0xD8, 0xF8, },
|
||||
"Dv", "Zz", { 0x1C4, 0x1C5, },
|
||||
"D", "-e", { 0xD0, 0x2206, },
|
||||
"A", "E", { 0xC6, },
|
||||
"o", "AaeUuiO", { 0xC5, 0xE5, 0x153, 0x16E, 0x16F, 0x1A3, 0x229A, },
|
||||
"~!", "=", { 0x2246, },
|
||||
"~", "ANOanoIiUu-=~", { 0xC3, 0xD1, 0xD5, 0xE3, 0xF1, 0xF5, 0x128, 0x129, 0x168, 0x169, 0x2243, 0x2245, 0x2248, },
|
||||
"^", "AEIOUaeiouCcGgHhJjSsWwYy", { 0xC2, 0xCA, 0xCE, 0xD4, 0xDB, 0xE2, 0xEA, 0xEE, 0xF4, 0xFB, 0x108, 0x109, 0x11C, 0x11D, 0x124, 0x125, 0x134, 0x135, 0x15C, 0x15D, 0x174, 0x175, 0x176, 0x177, },
|
||||
"`\"", "Uu", { 0x1DB, 0x1DC, },
|
||||
"`", "AEIOUaeiou", { 0xC0, 0xC8, 0xCC, 0xD2, 0xD9, 0xE0, 0xE8, 0xEC, 0xF2, 0xF9, },
|
||||
"?", "?!", { 0xBF, 0x203D, },
|
||||
"3", "458", { 0xBE, 0x2157, 0x215C, },
|
||||
"1", "423568", { 0xBC, 0xBD, 0x2153, 0x2155, 0x2159, 0x215B, },
|
||||
">!", "=~", { 0x2269, 0x22E7, },
|
||||
">", ">=~<", { 0xBB, 0x2265, 0x2273, 0x2277, },
|
||||
",", ",CcAaEeGgIiKkLlNnRrSsTtUuOo", { 0xB8, 0xC7, 0xE7, 0x104, 0x105, 0x118, 0x119, 0x122, 0x123, 0x12E, 0x12F, 0x136, 0x137, 0x13B, 0x13C, 0x145, 0x146, 0x156, 0x157, 0x15E, 0x15F, 0x162, 0x163, 0x172, 0x173, 0x1EA, 0x1EB, },
|
||||
".", ".CcEeGgILlZzO", { 0xB7, 0x10A, 0x10B, 0x116, 0x117, 0x120, 0x121, 0x130, 0x13F, 0x140, 0x17B, 0x17C, 0x2299, },
|
||||
"p", "gOdrt", { 0xB6, 0x2117, 0x2202, 0x220F, 0x221D, },
|
||||
"m", "iuo", { 0xB5, 0xD7, 0x2208, },
|
||||
"\'\"", "Uu", { 0x1D7, 0x1D8, },
|
||||
"\'", "\'AEIOUYaeiouyCcgLlNnRrSsZz", { 0xB4, 0xC1, 0xC9, 0xCD, 0xD3, 0xDA, 0xDD, 0xE1, 0xE9, 0xED, 0xF3, 0xFA, 0xFD, 0x106, 0x107, 0x123, 0x139, 0x13A, 0x143, 0x144, 0x154, 0x155, 0x15A, 0x15B, 0x179, 0x17A, },
|
||||
"+", "-O", { 0xB1, 0x2295, },
|
||||
"dv", "z", { 0x1C6, },
|
||||
"d", "e-zgda", { 0xB0, 0xF0, 0x2A3, 0x2020, 0x2021, 0x2193, },
|
||||
"_,", "Oo", { 0x1EC, 0x1ED, },
|
||||
"_.", "Aa", { 0x1E0, 0x1E1, },
|
||||
"_\"", "UuAa", { 0x1D5, 0x1D6, 0x1DE, 0x1DF, },
|
||||
"_", "_AaEeIiOoUu", { 0xAF, 0x100, 0x101, 0x112, 0x113, 0x12A, 0x12B, 0x14C, 0x14D, 0x16A, 0x16B, },
|
||||
"r", "O\'\"", { 0xAE, 0x2019, 0x201D, },
|
||||
"-*", "l", { 0x19B, },
|
||||
"-", "-Dd:HLlTtbIZz2Ggiuh>+~O", { 0xAD, 0xD0, 0xF0, 0xF7, 0x126, 0x141, 0x142, 0x166, 0x167, 0x180, 0x197, 0x1B5, 0x1B6, 0x1BB, 0x1E4, 0x1E5, 0x268, 0x289, 0x210F, 0x2192, 0x2213, 0x2242, 0x2296, },
|
||||
"n", "oj", { 0xAC, 0x1CC, },
|
||||
"<!", "=~", { 0x2268, 0x22E6, },
|
||||
"<", "<-=~>", { 0xAB, 0x2190, 0x2264, 0x2272, 0x2276, },
|
||||
"s", "a231os0456789+-=()nturbp", { 0xAA, 0xB2, 0xB3, 0xB9, 0xBA, 0xDF, 0x2070, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079, 0x207A, 0x207B, 0x207C, 0x207D, 0x207E, 0x207F, 0x220D, 0x2211, 0x221A, 0x2282, 0x2283, },
|
||||
"O", "crEIp+-x/.o*=", { 0xA9, 0xAE, 0x152, 0x1A2, 0x2117, 0x2295, 0x2296, 0x2297, 0x2298, 0x2299, 0x229A, 0x229B, 0x229C, },
|
||||
"\"*", "IUiu", { 0x3AA, 0x3AB, 0x3CA, 0x3CB, },
|
||||
"\"", "\"AEIOUaeiouyY", { 0xA8, 0xC4, 0xCB, 0xCF, 0xD6, 0xDC, 0xE4, 0xEB, 0xEF, 0xF6, 0xFC, 0xFF, 0x178, },
|
||||
"S", "S", { 0xA7, },
|
||||
"|", "|Pp", { 0xA6, 0xDE, 0xFE, },
|
||||
"y", "$", { 0xA5, },
|
||||
"g", "$-r", { 0xA4, 0x1E5, 0x2207, },
|
||||
"l", "$-j\'\"&|z", { 0xA3, 0x142, 0x1C9, 0x2018, 0x201C, 0x2227, 0x2228, 0x22C4, },
|
||||
"c", "$Oaug", { 0xA2, 0xA9, 0x2229, 0x222A, 0x2245, },
|
||||
"!~", "-=~", { 0x2244, 0x2247, 0x2249, },
|
||||
"!", "!?m=<>bp", { 0xA1, 0x203D, 0x2209, 0x2260, 0x226E, 0x226F, 0x2284, 0x2285, },
|
||||
0, 0, { 0, }
|
||||
};
|
||||
|
||||
/*
|
||||
* Given 5 characters k[0]..k[4], find the rune or return -1 for failure.
|
||||
*/
|
||||
long
|
||||
unicode(Rune *k)
|
||||
{
|
||||
long i, c;
|
||||
|
||||
k++; /* skip 'X' */
|
||||
c = 0;
|
||||
for(i=0; i<4; i++,k++){
|
||||
c <<= 4;
|
||||
if('0'<=*k && *k<='9')
|
||||
c += *k-'0';
|
||||
else if('a'<=*k && *k<='f')
|
||||
c += 10 + *k-'a';
|
||||
else if('A'<=*k && *k<='F')
|
||||
c += 10 + *k-'A';
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given n characters k[0]..k[n-1], find the corresponding rune or return -1 for
|
||||
* failure, or something < -1 if n is too small. In the latter case, the result
|
||||
* is minus the required n.
|
||||
*/
|
||||
long
|
||||
latin1(Rune *k, int n)
|
||||
{
|
||||
struct cvlist *l;
|
||||
int c;
|
||||
char* p;
|
||||
|
||||
if(k[0] == 'X'){
|
||||
if(n>=5)
|
||||
return unicode(k);
|
||||
else
|
||||
return -5;
|
||||
}
|
||||
|
||||
for(l=latintab; l->ld!=0; l++)
|
||||
if(k[0] == l->ld[0]){
|
||||
if(n == 1)
|
||||
return -2;
|
||||
if(l->ld[1] == 0)
|
||||
c = k[1];
|
||||
else if(l->ld[1] != k[1])
|
||||
continue;
|
||||
else if(n == 2)
|
||||
return -3;
|
||||
else
|
||||
c = k[2];
|
||||
for(p=l->si; *p!=0; p++)
|
||||
if(*p == c)
|
||||
return l->so[p - l->si];
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
28
libauthsrv/Makefile
Normal file
28
libauthsrv/Makefile
Normal file
@ -0,0 +1,28 @@
|
||||
LIB=libauthsrv.a
|
||||
CC=gcc
|
||||
CFLAGS=-I../include -I. -c -ggdb -D_THREAD_SAFE -pthread
|
||||
O=o
|
||||
|
||||
OFILES=\
|
||||
_asgetticket.$O\
|
||||
_asrdresp.$O\
|
||||
convA2M.$O\
|
||||
convM2A.$O\
|
||||
convM2PR.$O\
|
||||
convM2T.$O\
|
||||
convM2TR.$O\
|
||||
convPR2M.$O\
|
||||
convT2M.$O\
|
||||
convTR2M.$O\
|
||||
nvcsum.$O\
|
||||
opasstokey.$O\
|
||||
passtokey.$O\
|
||||
readnvram.$O\
|
||||
|
||||
$(LIB): $(OFILES)
|
||||
ar r $(LIB) $(OFILES)
|
||||
ranlib $(LIB)
|
||||
|
||||
%.$O: %.c
|
||||
$(CC) $(CFLAGS) $*.c
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user