20110512-2206
This commit is contained in:
commit
44b904efbb
16
LICENSE
Normal file
16
LICENSE
Normal file
@ -0,0 +1,16 @@
|
||||
The authors of this software are Bob Flandrena, Ken Thompson,
|
||||
Rob Pike, and Russ Cox.
|
||||
|
||||
Copyright (c) 1992-2002 by Lucent Technologies.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose without fee is hereby granted, provided that this entire notice
|
||||
is included in all copies of any software which is or includes a copy
|
||||
or modification of this software and in all copies of the supporting
|
||||
documentation for such software.
|
||||
|
||||
THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
|
||||
WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY
|
||||
REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
|
||||
OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
|
25
authnone.c
Normal file
25
authnone.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include <plan9.h>
|
||||
#include <fcall.h>
|
||||
#include <u9fs.h>
|
||||
|
||||
static char*
|
||||
noneauth(Fcall *rx, Fcall *tx)
|
||||
{
|
||||
USED(rx);
|
||||
USED(tx);
|
||||
return "u9fs authnone: no authentication required";
|
||||
}
|
||||
|
||||
static char*
|
||||
noneattach(Fcall *rx, Fcall *tx)
|
||||
{
|
||||
USED(rx);
|
||||
USED(tx);
|
||||
return nil;
|
||||
}
|
||||
|
||||
Auth authnone = {
|
||||
"none",
|
||||
noneauth,
|
||||
noneattach,
|
||||
};
|
538
authp9any.c
Normal file
538
authp9any.c
Normal file
@ -0,0 +1,538 @@
|
||||
/*
|
||||
* 4th Edition p9any/p9sk1 authentication based on auth9p1.c
|
||||
* Nigel Roles (nigel@9fs.org) 2003
|
||||
*/
|
||||
|
||||
#include <plan9.h>
|
||||
#include <fcall.h>
|
||||
#include <u9fs.h>
|
||||
#include <stdlib.h> /* for random stuff */
|
||||
|
||||
typedef struct Ticket Ticket;
|
||||
typedef struct Ticketreq Ticketreq;
|
||||
typedef struct Authenticator Authenticator;
|
||||
|
||||
enum
|
||||
{
|
||||
DOMLEN= 48, /* length of an authentication domain name */
|
||||
CHALLEN= 8 /* length of a challenge */
|
||||
};
|
||||
|
||||
enum {
|
||||
HaveProtos,
|
||||
NeedProto,
|
||||
NeedChal,
|
||||
HaveTreq,
|
||||
NeedTicket,
|
||||
HaveAuth,
|
||||
Established,
|
||||
};
|
||||
|
||||
/* 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, /* http domain login */
|
||||
|
||||
|
||||
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[NAMELEN]; /* server's encryption id */
|
||||
char authdom[DOMLEN]; /* server's authentication domain */
|
||||
char chal[CHALLEN]; /* challenge from server */
|
||||
char hostid[NAMELEN]; /* host's encryption id */
|
||||
char uid[NAMELEN]; /* uid of requesting user on host */
|
||||
};
|
||||
#define TICKREQLEN (3*NAMELEN+CHALLEN+DOMLEN+1)
|
||||
|
||||
struct Ticket
|
||||
{
|
||||
char num; /* replay protection */
|
||||
char chal[CHALLEN]; /* server challenge */
|
||||
char cuid[NAMELEN]; /* uid on client */
|
||||
char suid[NAMELEN]; /* uid on server */
|
||||
char key[DESKEYLEN]; /* nonce DES key */
|
||||
};
|
||||
#define TICKETLEN (CHALLEN+2*NAMELEN+DESKEYLEN+1)
|
||||
|
||||
struct Authenticator
|
||||
{
|
||||
char num; /* replay protection */
|
||||
char chal[CHALLEN];
|
||||
ulong id; /* authenticator id, ++'d with each auth */
|
||||
};
|
||||
#define AUTHENTLEN (CHALLEN+4+1)
|
||||
|
||||
extern int chatty9p;
|
||||
|
||||
static int convT2M(Ticket*, char*, char*);
|
||||
static void convM2T(char*, Ticket*, char*);
|
||||
static void convM2Tnoenc(char*, Ticket*);
|
||||
static int convA2M(Authenticator*, char*, char*);
|
||||
static void convM2A(char*, Authenticator*, char*);
|
||||
static int convTR2M(Ticketreq*, char*);
|
||||
static void convM2TR(char*, Ticketreq*);
|
||||
static int passtokey(char*, char*);
|
||||
|
||||
/*
|
||||
* destructively encrypt the buffer, which
|
||||
* must be at least 8 characters long.
|
||||
*/
|
||||
static int
|
||||
encrypt9p(void *key, void *vbuf, int n)
|
||||
{
|
||||
char ekey[128], *buf;
|
||||
int i, r;
|
||||
|
||||
if(n < 8)
|
||||
return 0;
|
||||
key_setup(key, ekey);
|
||||
buf = vbuf;
|
||||
n--;
|
||||
r = n % 7;
|
||||
n /= 7;
|
||||
for(i = 0; i < n; i++){
|
||||
block_cipher(ekey, buf, 0);
|
||||
buf += 7;
|
||||
}
|
||||
if(r)
|
||||
block_cipher(ekey, buf - 7 + r, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* destructively decrypt the buffer, which
|
||||
* must be at least 8 characters long.
|
||||
*/
|
||||
static int
|
||||
decrypt9p(void *key, void *vbuf, int n)
|
||||
{
|
||||
char ekey[128], *buf;
|
||||
int i, r;
|
||||
|
||||
if(n < 8)
|
||||
return 0;
|
||||
key_setup(key, ekey);
|
||||
buf = vbuf;
|
||||
n--;
|
||||
r = n % 7;
|
||||
n /= 7;
|
||||
buf += n * 7;
|
||||
if(r)
|
||||
block_cipher(ekey, buf - 7 + r, 1);
|
||||
for(i = 0; i < n; i++){
|
||||
buf -= 7;
|
||||
block_cipher(ekey, buf, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define CHAR(x) *p++ = f->x
|
||||
#define SHORT(x) p[0] = f->x; p[1] = f->x>>8; p += 2
|
||||
#define VLONG(q) p[0] = (q); p[1] = (q)>>8; p[2] = (q)>>16; p[3] = (q)>>24; p += 4
|
||||
#define LONG(x) VLONG(f->x)
|
||||
#define STRING(x,n) memmove(p, f->x, n); p += n
|
||||
|
||||
static int
|
||||
convTR2M(Ticketreq *f, char *ap)
|
||||
{
|
||||
int n;
|
||||
uchar *p;
|
||||
|
||||
p = (uchar*)ap;
|
||||
CHAR(type);
|
||||
STRING(authid, NAMELEN);
|
||||
STRING(authdom, DOMLEN);
|
||||
STRING(chal, CHALLEN);
|
||||
STRING(hostid, NAMELEN);
|
||||
STRING(uid, NAMELEN);
|
||||
n = p - (uchar*)ap;
|
||||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
convT2M(Ticket *f, char *ap, char *key)
|
||||
{
|
||||
int n;
|
||||
uchar *p;
|
||||
|
||||
p = (uchar*)ap;
|
||||
CHAR(num);
|
||||
STRING(chal, CHALLEN);
|
||||
STRING(cuid, NAMELEN);
|
||||
STRING(suid, NAMELEN);
|
||||
STRING(key, DESKEYLEN);
|
||||
n = p - (uchar*)ap;
|
||||
if(key)
|
||||
encrypt9p(key, ap, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
convA2M(Authenticator *f, char *ap, char *key)
|
||||
{
|
||||
int n;
|
||||
uchar *p;
|
||||
|
||||
p = (uchar*)ap;
|
||||
CHAR(num);
|
||||
STRING(chal, CHALLEN);
|
||||
LONG(id);
|
||||
n = p - (uchar*)ap;
|
||||
if(key)
|
||||
encrypt9p(key, ap, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
#undef CHAR
|
||||
#undef SHORT
|
||||
#undef VLONG
|
||||
#undef LONG
|
||||
#undef STRING
|
||||
|
||||
#define CHAR(x) f->x = *p++
|
||||
#define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2
|
||||
#define VLONG(q) q = (p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24)); p += 4
|
||||
#define LONG(x) VLONG(f->x)
|
||||
#define STRING(x,n) memmove(f->x, p, n); p += n
|
||||
|
||||
void
|
||||
convM2A(char *ap, Authenticator *f, char *key)
|
||||
{
|
||||
uchar *p;
|
||||
|
||||
if(key)
|
||||
decrypt9p(key, ap, AUTHENTLEN);
|
||||
p = (uchar*)ap;
|
||||
CHAR(num);
|
||||
STRING(chal, CHALLEN);
|
||||
LONG(id);
|
||||
USED(p);
|
||||
}
|
||||
|
||||
void
|
||||
convM2T(char *ap, Ticket *f, char *key)
|
||||
{
|
||||
uchar *p;
|
||||
|
||||
if(key)
|
||||
decrypt9p(key, ap, TICKETLEN);
|
||||
p = (uchar*)ap;
|
||||
CHAR(num);
|
||||
STRING(chal, CHALLEN);
|
||||
STRING(cuid, NAMELEN);
|
||||
f->cuid[NAMELEN-1] = 0;
|
||||
STRING(suid, NAMELEN);
|
||||
f->suid[NAMELEN-1] = 0;
|
||||
STRING(key, DESKEYLEN);
|
||||
USED(p);
|
||||
}
|
||||
|
||||
#undef CHAR
|
||||
#undef SHORT
|
||||
#undef LONG
|
||||
#undef VLONG
|
||||
#undef STRING
|
||||
|
||||
static int
|
||||
passtokey(char *key, char *p)
|
||||
{
|
||||
uchar buf[NAMELEN], *t;
|
||||
int i, n;
|
||||
|
||||
n = strlen(p);
|
||||
if(n >= NAMELEN)
|
||||
n = NAMELEN-1;
|
||||
memset(buf, ' ', 8);
|
||||
t = buf;
|
||||
strncpy((char*)t, p, n);
|
||||
t[n] = 0;
|
||||
memset(key, 0, DESKEYLEN);
|
||||
for(;;){
|
||||
for(i = 0; i < DESKEYLEN; i++)
|
||||
key[i] = (t[i] >> i) + (t[i+1] << (8 - (i+1)));
|
||||
if(n <= 8)
|
||||
return 1;
|
||||
n -= 8;
|
||||
t += 8;
|
||||
if(n < 8){
|
||||
t -= 8 - n;
|
||||
n = 8;
|
||||
}
|
||||
encrypt9p(key, t, 8);
|
||||
}
|
||||
return 1; /* not reached */
|
||||
}
|
||||
|
||||
static char authkey[DESKEYLEN];
|
||||
static char *authid;
|
||||
static char *authdom;
|
||||
static char *haveprotosmsg;
|
||||
static char *needprotomsg;
|
||||
|
||||
static void
|
||||
p9anyinit(void)
|
||||
{
|
||||
int n, fd;
|
||||
char abuf[200];
|
||||
char *af, *f[4];
|
||||
|
||||
af = autharg;
|
||||
if(af == nil)
|
||||
af = "/etc/u9fs.key";
|
||||
|
||||
if((fd = open(af, OREAD)) < 0)
|
||||
sysfatal("can't open key file '%s'", af);
|
||||
|
||||
if((n = readn(fd, abuf, sizeof(abuf)-1)) < 0)
|
||||
sysfatal("can't read key file '%s'", af);
|
||||
if (n > 0 && abuf[n - 1] == '\n')
|
||||
n--;
|
||||
abuf[n] = '\0';
|
||||
|
||||
if(getfields(abuf, f, nelem(f), 0, "\n") != 3)
|
||||
sysfatal("key file '%s' not exactly 3 lines", af);
|
||||
|
||||
passtokey(authkey, f[0]);
|
||||
authid = strdup(f[1]);
|
||||
authdom = strdup(f[2]);
|
||||
haveprotosmsg = malloc(strlen("p9sk1") + 1 + strlen(authdom) + 1);
|
||||
sprint(haveprotosmsg, "p9sk1@%s", authdom);
|
||||
needprotomsg = malloc(strlen("p9sk1") + 1 + strlen(authdom) + 1);
|
||||
sprint(needprotomsg, "p9sk1 %s", authdom);
|
||||
}
|
||||
|
||||
typedef struct AuthSession {
|
||||
int state;
|
||||
char *uname;
|
||||
char *aname;
|
||||
char cchal[CHALLEN];
|
||||
Ticketreq tr;
|
||||
Ticket t;
|
||||
} AuthSession;
|
||||
|
||||
static char*
|
||||
p9anyauth(Fcall *rx, Fcall *tx)
|
||||
{
|
||||
AuthSession *sp;
|
||||
Fid *f;
|
||||
char *ep;
|
||||
|
||||
sp = malloc(sizeof(AuthSession));
|
||||
f = newauthfid(rx->afid, sp, &ep);
|
||||
if (f == nil) {
|
||||
free(sp);
|
||||
return ep;
|
||||
}
|
||||
if (chatty9p)
|
||||
fprint(2, "p9anyauth: afid %d\n", rx->afid);
|
||||
sp->state = HaveProtos;
|
||||
sp->uname = strdup(rx->uname);
|
||||
sp->aname = strdup(rx->aname);
|
||||
tx->aqid.type = QTAUTH;
|
||||
tx->aqid.path = 1;
|
||||
tx->aqid.vers = 0;
|
||||
return nil;
|
||||
}
|
||||
|
||||
static char *
|
||||
p9anyattach(Fcall *rx, Fcall *tx)
|
||||
{
|
||||
AuthSession *sp;
|
||||
Fid *f;
|
||||
char *ep;
|
||||
|
||||
f = oldauthfid(rx->afid, (void **)&sp, &ep);
|
||||
if (f == nil)
|
||||
return ep;
|
||||
if (chatty9p)
|
||||
fprint(2, "p9anyattach: afid %d state %d\n", rx->afid, sp->state);
|
||||
if (sp->state == Established && strcmp(rx->uname, sp->uname) == 0
|
||||
&& strcmp(rx->aname, sp->aname) == 0)
|
||||
return nil;
|
||||
return "authentication failed";
|
||||
}
|
||||
|
||||
static int
|
||||
readstr(Fcall *rx, Fcall *tx, char *s, int len)
|
||||
{
|
||||
if (rx->offset >= len)
|
||||
return 0;
|
||||
tx->count = len - rx->offset;
|
||||
if (tx->count > rx->count)
|
||||
tx->count = rx->count;
|
||||
memcpy(tx->data, s + rx->offset, tx->count);
|
||||
return tx->count;
|
||||
}
|
||||
|
||||
static char *
|
||||
p9anyread(Fcall *rx, Fcall *tx)
|
||||
{
|
||||
AuthSession *sp;
|
||||
char *ep;
|
||||
|
||||
Fid *f;
|
||||
f = oldauthfid(rx->afid, (void **)&sp, &ep);
|
||||
if (f == nil)
|
||||
return ep;
|
||||
if (chatty9p)
|
||||
fprint(2, "p9anyread: afid %d state %d\n", rx->fid, sp->state);
|
||||
switch (sp->state) {
|
||||
case HaveProtos:
|
||||
readstr(rx, tx, haveprotosmsg, strlen(haveprotosmsg) + 1);
|
||||
if (rx->offset + tx->count == strlen(haveprotosmsg) + 1)
|
||||
sp->state = NeedProto;
|
||||
return nil;
|
||||
case HaveTreq:
|
||||
if (rx->count != TICKREQLEN)
|
||||
goto botch;
|
||||
convTR2M(&sp->tr, tx->data);
|
||||
tx->count = TICKREQLEN;
|
||||
sp->state = NeedTicket;
|
||||
return nil;
|
||||
case HaveAuth: {
|
||||
Authenticator a;
|
||||
if (rx->count != AUTHENTLEN)
|
||||
goto botch;
|
||||
a.num = AuthAs;
|
||||
memmove(a.chal, sp->cchal, CHALLEN);
|
||||
a.id = 0;
|
||||
convA2M(&a, (char*)tx->data, sp->t.key);
|
||||
memset(sp->t.key, 0, sizeof(sp->t.key));
|
||||
tx->count = rx->count;
|
||||
sp->state = Established;
|
||||
return nil;
|
||||
}
|
||||
default:
|
||||
botch:
|
||||
return "protocol botch";
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
p9anywrite(Fcall *rx, Fcall *tx)
|
||||
{
|
||||
AuthSession *sp;
|
||||
char *ep;
|
||||
|
||||
Fid *f;
|
||||
|
||||
f = oldauthfid(rx->afid, (void **)&sp, &ep);
|
||||
if (f == nil)
|
||||
return ep;
|
||||
if (chatty9p)
|
||||
fprint(2, "p9anywrite: afid %d state %d\n", rx->fid, sp->state);
|
||||
switch (sp->state) {
|
||||
case NeedProto:
|
||||
if (rx->count != strlen(needprotomsg) + 1)
|
||||
return "protocol response wrong length";
|
||||
if (memcmp(rx->data, needprotomsg, rx->count) != 0)
|
||||
return "unacceptable protocol";
|
||||
sp->state = NeedChal;
|
||||
tx->count = rx->count;
|
||||
return nil;
|
||||
case NeedChal:
|
||||
if (rx->count != CHALLEN)
|
||||
goto botch;
|
||||
memmove(sp->cchal, rx->data, CHALLEN);
|
||||
sp->tr.type = AuthTreq;
|
||||
safecpy(sp->tr.authid, authid, sizeof(sp->tr.authid));
|
||||
safecpy(sp->tr.authdom, authdom, sizeof(sp->tr.authdom));
|
||||
randombytes((uchar *)sp->tr.chal, CHALLEN);
|
||||
safecpy(sp->tr.hostid, "", sizeof(sp->tr.hostid));
|
||||
safecpy(sp->tr.uid, "", sizeof(sp->tr.uid));
|
||||
tx->count = rx->count;
|
||||
sp->state = HaveTreq;
|
||||
return nil;
|
||||
case NeedTicket: {
|
||||
Authenticator a;
|
||||
|
||||
if (rx->count != TICKETLEN + AUTHENTLEN) {
|
||||
fprint(2, "bad length in attach");
|
||||
goto botch;
|
||||
}
|
||||
convM2T((char*)rx->data, &sp->t, authkey);
|
||||
if (sp->t.num != AuthTs) {
|
||||
fprint(2, "bad AuthTs in attach\n");
|
||||
goto botch;
|
||||
}
|
||||
if (memcmp(sp->t.chal, sp->tr.chal, CHALLEN) != 0) {
|
||||
fprint(2, "bad challenge in attach\n");
|
||||
goto botch;
|
||||
}
|
||||
convM2A((char*)rx->data + TICKETLEN, &a, sp->t.key);
|
||||
if (a.num != AuthAc) {
|
||||
fprint(2, "bad AuthAs in attach\n");
|
||||
goto botch;
|
||||
}
|
||||
if(memcmp(a.chal, sp->tr.chal, CHALLEN) != 0) {
|
||||
fprint(2, "bad challenge in attach 2\n");
|
||||
goto botch;
|
||||
}
|
||||
sp->state = HaveAuth;
|
||||
tx->count = rx->count;
|
||||
return nil;
|
||||
}
|
||||
default:
|
||||
botch:
|
||||
return "protocol botch";
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
safefree(char *p)
|
||||
{
|
||||
if (p) {
|
||||
memset(p, 0, strlen(p));
|
||||
free(p);
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
p9anyclunk(Fcall *rx, Fcall *tx)
|
||||
{
|
||||
Fid *f;
|
||||
AuthSession *sp;
|
||||
char *ep;
|
||||
|
||||
f = oldauthfid(rx->afid, (void **)&sp, &ep);
|
||||
if (f == nil)
|
||||
return ep;
|
||||
if (chatty9p)
|
||||
fprint(2, "p9anyclunk: afid %d\n", rx->fid);
|
||||
safefree(sp->uname);
|
||||
safefree(sp->aname);
|
||||
memset(sp, 0, sizeof(sp));
|
||||
free(sp);
|
||||
return nil;
|
||||
}
|
||||
|
||||
Auth authp9any = {
|
||||
"p9any",
|
||||
p9anyauth,
|
||||
p9anyattach,
|
||||
p9anyinit,
|
||||
p9anyread,
|
||||
p9anywrite,
|
||||
p9anyclunk,
|
||||
};
|
38
authrhosts.c
Normal file
38
authrhosts.c
Normal file
@ -0,0 +1,38 @@
|
||||
#include <plan9.h>
|
||||
#include <fcall.h>
|
||||
#include <u9fs.h>
|
||||
|
||||
/*
|
||||
* return whether the user is authenticated.
|
||||
* uses berkeley-style rhosts ``authentication''.
|
||||
* this is only a good idea behind a firewall,
|
||||
* where you trust your network, and even then
|
||||
* not such a great idea. it's grandfathered.
|
||||
*/
|
||||
|
||||
static char*
|
||||
rhostsauth(Fcall *rx, Fcall *tx)
|
||||
{
|
||||
USED(rx);
|
||||
USED(tx);
|
||||
|
||||
return "u9fs rhostsauth: no authentication required";
|
||||
}
|
||||
|
||||
static char*
|
||||
rhostsattach(Fcall *rx, Fcall *tx)
|
||||
{
|
||||
USED(tx);
|
||||
|
||||
if(ruserok(remotehostname, 0, rx->uname, rx->uname) < 0){
|
||||
fprint(2, "ruserok(%s, %s) not okay\n", remotehostname, rx->uname);
|
||||
return "u9fs: rhosts authentication failed";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Auth authrhosts = {
|
||||
"rhosts",
|
||||
rhostsauth,
|
||||
rhostsattach,
|
||||
};
|
89
convD2M.c
Normal file
89
convD2M.c
Normal file
@ -0,0 +1,89 @@
|
||||
#include <plan9.h>
|
||||
#include <fcall.h>
|
||||
|
||||
uint
|
||||
sizeD2M(Dir *d)
|
||||
{
|
||||
char *sv[4];
|
||||
int i, ns;
|
||||
|
||||
sv[0] = d->name;
|
||||
sv[1] = d->uid;
|
||||
sv[2] = d->gid;
|
||||
sv[3] = d->muid;
|
||||
|
||||
ns = 0;
|
||||
for(i = 0; i < 4; i++)
|
||||
ns += strlen(sv[i]);
|
||||
|
||||
return STATFIXLEN + ns;
|
||||
}
|
||||
|
||||
uint
|
||||
convD2M(Dir *d, uchar *buf, uint nbuf)
|
||||
{
|
||||
uchar *p, *ebuf;
|
||||
char *sv[4];
|
||||
int i, ns, nsv[4], ss;
|
||||
|
||||
if(nbuf < BIT16SZ)
|
||||
return 0;
|
||||
|
||||
p = buf;
|
||||
ebuf = buf + nbuf;
|
||||
|
||||
sv[0] = d->name;
|
||||
sv[1] = d->uid;
|
||||
sv[2] = d->gid;
|
||||
sv[3] = d->muid;
|
||||
|
||||
ns = 0;
|
||||
for(i = 0; i < 4; i++){
|
||||
nsv[i] = strlen(sv[i]);
|
||||
ns += nsv[i];
|
||||
}
|
||||
|
||||
ss = STATFIXLEN + ns;
|
||||
|
||||
/* set size befor erroring, so user can know how much is needed */
|
||||
/* note that length excludes count field itself */
|
||||
PBIT16(p, ss-BIT16SZ);
|
||||
p += BIT16SZ;
|
||||
|
||||
if(ss > nbuf)
|
||||
return BIT16SZ;
|
||||
|
||||
PBIT16(p, d->type);
|
||||
p += BIT16SZ;
|
||||
PBIT32(p, d->dev);
|
||||
p += BIT32SZ;
|
||||
PBIT8(p, d->qid.type);
|
||||
p += BIT8SZ;
|
||||
PBIT32(p, d->qid.vers);
|
||||
p += BIT32SZ;
|
||||
PBIT64(p, d->qid.path);
|
||||
p += BIT64SZ;
|
||||
PBIT32(p, d->mode);
|
||||
p += BIT32SZ;
|
||||
PBIT32(p, d->atime);
|
||||
p += BIT32SZ;
|
||||
PBIT32(p, d->mtime);
|
||||
p += BIT32SZ;
|
||||
PBIT64(p, d->length);
|
||||
p += BIT64SZ;
|
||||
|
||||
for(i = 0; i < 4; i++){
|
||||
ns = nsv[i];
|
||||
if(p + ns + BIT16SZ > ebuf)
|
||||
return 0;
|
||||
PBIT16(p, ns);
|
||||
p += BIT16SZ;
|
||||
memmove(p, sv[i], ns);
|
||||
p += ns;
|
||||
}
|
||||
|
||||
if(ss != p - buf)
|
||||
return 0;
|
||||
|
||||
return p - buf;
|
||||
}
|
92
convM2D.c
Normal file
92
convM2D.c
Normal file
@ -0,0 +1,92 @@
|
||||
#include <plan9.h>
|
||||
#include <fcall.h>
|
||||
|
||||
int
|
||||
statcheck(uchar *buf, uint nbuf)
|
||||
{
|
||||
uchar *ebuf;
|
||||
int i;
|
||||
|
||||
ebuf = buf + nbuf;
|
||||
|
||||
buf += STATFIXLEN - 4 * BIT16SZ;
|
||||
|
||||
for(i = 0; i < 4; i++){
|
||||
if(buf + BIT16SZ > ebuf)
|
||||
return -1;
|
||||
buf += BIT16SZ + GBIT16(buf);
|
||||
}
|
||||
|
||||
if(buf != ebuf)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char nullstring[] = "";
|
||||
|
||||
uint
|
||||
convM2D(uchar *buf, uint nbuf, Dir *d, char *strs)
|
||||
{
|
||||
uchar *p, *ebuf;
|
||||
char *sv[4];
|
||||
int i, ns;
|
||||
|
||||
p = buf;
|
||||
ebuf = buf + nbuf;
|
||||
|
||||
p += BIT16SZ; /* ignore size */
|
||||
d->type = GBIT16(p);
|
||||
p += BIT16SZ;
|
||||
d->dev = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
d->qid.type = GBIT8(p);
|
||||
p += BIT8SZ;
|
||||
d->qid.vers = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
d->qid.path = GBIT64(p);
|
||||
p += BIT64SZ;
|
||||
d->mode = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
d->atime = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
d->mtime = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
d->length = GBIT64(p);
|
||||
p += BIT64SZ;
|
||||
|
||||
d->name = nil;
|
||||
d->uid = nil;
|
||||
d->gid = nil;
|
||||
d->muid = nil;
|
||||
|
||||
for(i = 0; i < 4; i++){
|
||||
if(p + BIT16SZ > ebuf)
|
||||
return 0;
|
||||
ns = GBIT16(p);
|
||||
p += BIT16SZ;
|
||||
if(p + ns > ebuf)
|
||||
return 0;
|
||||
if(strs){
|
||||
sv[i] = strs;
|
||||
memmove(strs, p, ns);
|
||||
strs += ns;
|
||||
*strs++ = '\0';
|
||||
}
|
||||
p += ns;
|
||||
}
|
||||
|
||||
if(strs){
|
||||
d->name = sv[0];
|
||||
d->uid = sv[1];
|
||||
d->gid = sv[2];
|
||||
d->muid = sv[3];
|
||||
}else{
|
||||
d->name = nullstring;
|
||||
d->uid = nullstring;
|
||||
d->gid = nullstring;
|
||||
d->muid = nullstring;
|
||||
}
|
||||
|
||||
return p - buf;
|
||||
}
|
382
convM2S.c
Normal file
382
convM2S.c
Normal file
@ -0,0 +1,382 @@
|
||||
#include <plan9.h>
|
||||
#include <fcall.h>
|
||||
|
||||
static
|
||||
uchar*
|
||||
gstring(uchar *p, uchar *ep, char **s)
|
||||
{
|
||||
uint n;
|
||||
|
||||
if(p+BIT16SZ > ep)
|
||||
return nil;
|
||||
n = GBIT16(p);
|
||||
p += BIT16SZ - 1;
|
||||
if(p+n+1 > ep)
|
||||
return nil;
|
||||
/* move it down, on top of count, to make room for '\0' */
|
||||
memmove(p, p + 1, n);
|
||||
p[n] = '\0';
|
||||
*s = (char*)p;
|
||||
p += n+1;
|
||||
return p;
|
||||
}
|
||||
|
||||
static
|
||||
uchar*
|
||||
gqid(uchar *p, uchar *ep, Qid *q)
|
||||
{
|
||||
if(p+QIDSZ > ep)
|
||||
return nil;
|
||||
q->type = GBIT8(p);
|
||||
p += BIT8SZ;
|
||||
q->vers = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
q->path = GBIT64(p);
|
||||
p += BIT64SZ;
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* no syntactic checks.
|
||||
* three causes for error:
|
||||
* 1. message size field is incorrect
|
||||
* 2. input buffer too short for its own data (counts too long, etc.)
|
||||
* 3. too many names or qids
|
||||
* gqid() and gstring() return nil if they would reach beyond buffer.
|
||||
* main switch statement checks range and also can fall through
|
||||
* to test at end of routine.
|
||||
*/
|
||||
uint
|
||||
convM2S(uchar *ap, uint nap, Fcall *f)
|
||||
{
|
||||
uchar *p, *ep;
|
||||
uint i, size;
|
||||
|
||||
p = ap;
|
||||
ep = p + nap;
|
||||
|
||||
if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep)
|
||||
return 0;
|
||||
size = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
|
||||
if(size > nap)
|
||||
return 0;
|
||||
if(size < BIT32SZ+BIT8SZ+BIT16SZ)
|
||||
return 0;
|
||||
|
||||
f->type = GBIT8(p);
|
||||
p += BIT8SZ;
|
||||
f->tag = GBIT16(p);
|
||||
p += BIT16SZ;
|
||||
|
||||
switch(f->type)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
|
||||
case Tversion:
|
||||
if(p+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->msize = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
p = gstring(p, ep, &f->version);
|
||||
break;
|
||||
|
||||
/*
|
||||
case Tsession:
|
||||
if(p+BIT16SZ > ep)
|
||||
return 0;
|
||||
f->nchal = GBIT16(p);
|
||||
p += BIT16SZ;
|
||||
if(p+f->nchal > ep)
|
||||
return 0;
|
||||
f->chal = p;
|
||||
p += f->nchal;
|
||||
break;
|
||||
*/
|
||||
|
||||
case Tflush:
|
||||
if(p+BIT16SZ > ep)
|
||||
return 0;
|
||||
f->oldtag = GBIT16(p);
|
||||
p += BIT16SZ;
|
||||
break;
|
||||
|
||||
case Tauth:
|
||||
if(p+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->afid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
p = gstring(p, ep, &f->uname);
|
||||
if(p == nil)
|
||||
break;
|
||||
p = gstring(p, ep, &f->aname);
|
||||
if(p == nil)
|
||||
break;
|
||||
break;
|
||||
|
||||
/*
|
||||
b
|
||||
case Tattach:
|
||||
if(p+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->fid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
p = gstring(p, ep, &f->uname);
|
||||
if(p == nil)
|
||||
break;
|
||||
p = gstring(p, ep, &f->aname);
|
||||
if(p == nil)
|
||||
break;
|
||||
if(p+BIT16SZ > ep)
|
||||
return 0;
|
||||
f->nauth = GBIT16(p);
|
||||
p += BIT16SZ;
|
||||
if(p+f->nauth > ep)
|
||||
return 0;
|
||||
f->auth = p;
|
||||
p += f->nauth;
|
||||
break;
|
||||
*/
|
||||
|
||||
case Tattach:
|
||||
if(p+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->fid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
if(p+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->afid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
p = gstring(p, ep, &f->uname);
|
||||
if(p == nil)
|
||||
break;
|
||||
p = gstring(p, ep, &f->aname);
|
||||
if(p == nil)
|
||||
break;
|
||||
break;
|
||||
|
||||
|
||||
case Twalk:
|
||||
if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
|
||||
return 0;
|
||||
f->fid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
f->newfid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
f->nwname = GBIT16(p);
|
||||
p += BIT16SZ;
|
||||
if(f->nwname > MAXWELEM)
|
||||
return 0;
|
||||
for(i=0; i<f->nwname; i++){
|
||||
p = gstring(p, ep, &f->wname[i]);
|
||||
if(p == nil)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Topen:
|
||||
if(p+BIT32SZ+BIT8SZ > ep)
|
||||
return 0;
|
||||
f->fid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
f->mode = GBIT8(p);
|
||||
p += BIT8SZ;
|
||||
break;
|
||||
|
||||
case Tcreate:
|
||||
if(p+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->fid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
p = gstring(p, ep, &f->name);
|
||||
if(p == nil)
|
||||
break;
|
||||
if(p+BIT32SZ+BIT8SZ > ep)
|
||||
return 0;
|
||||
f->perm = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
f->mode = GBIT8(p);
|
||||
p += BIT8SZ;
|
||||
break;
|
||||
|
||||
case Tread:
|
||||
if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->fid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
f->offset = GBIT64(p);
|
||||
p += BIT64SZ;
|
||||
f->count = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Twrite:
|
||||
if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->fid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
f->offset = GBIT64(p);
|
||||
p += BIT64SZ;
|
||||
f->count = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
if(p+f->count > ep)
|
||||
return 0;
|
||||
f->data = (char*)p;
|
||||
p += f->count;
|
||||
break;
|
||||
|
||||
case Tclunk:
|
||||
case Tremove:
|
||||
if(p+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->fid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Tstat:
|
||||
if(p+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->fid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Twstat:
|
||||
if(p+BIT32SZ+BIT16SZ > ep)
|
||||
return 0;
|
||||
f->fid = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
f->nstat = GBIT16(p);
|
||||
p += BIT16SZ;
|
||||
if(p+f->nstat > ep)
|
||||
return 0;
|
||||
f->stat = p;
|
||||
p += f->nstat;
|
||||
break;
|
||||
|
||||
/*
|
||||
*/
|
||||
case Rversion:
|
||||
if(p+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->msize = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
p = gstring(p, ep, &f->version);
|
||||
break;
|
||||
|
||||
/*
|
||||
case Rsession:
|
||||
if(p+BIT16SZ > ep)
|
||||
return 0;
|
||||
f->nchal = GBIT16(p);
|
||||
p += BIT16SZ;
|
||||
if(p+f->nchal > ep)
|
||||
return 0;
|
||||
f->chal = p;
|
||||
p += f->nchal;
|
||||
p = gstring(p, ep, &f->authid);
|
||||
if(p == nil)
|
||||
break;
|
||||
p = gstring(p, ep, &f->authdom);
|
||||
break;
|
||||
*/
|
||||
|
||||
case Rerror:
|
||||
p = gstring(p, ep, &f->ename);
|
||||
break;
|
||||
|
||||
case Rflush:
|
||||
break;
|
||||
|
||||
/*
|
||||
case Rattach:
|
||||
p = gqid(p, ep, &f->qid);
|
||||
if(p == nil)
|
||||
break;
|
||||
if(p+BIT16SZ > ep)
|
||||
return 0;
|
||||
f->nrauth = GBIT16(p);
|
||||
p += BIT16SZ;
|
||||
if(p+f->nrauth > ep)
|
||||
return 0;
|
||||
f->rauth = p;
|
||||
p += f->nrauth;
|
||||
break;
|
||||
*/
|
||||
|
||||
case Rattach:
|
||||
p = gqid(p, ep, &f->qid);
|
||||
if(p == nil)
|
||||
break;
|
||||
break;
|
||||
|
||||
|
||||
case Rwalk:
|
||||
if(p+BIT16SZ > ep)
|
||||
return 0;
|
||||
f->nwqid = GBIT16(p);
|
||||
p += BIT16SZ;
|
||||
if(f->nwqid > MAXWELEM)
|
||||
return 0;
|
||||
for(i=0; i<f->nwqid; i++){
|
||||
p = gqid(p, ep, &f->wqid[i]);
|
||||
if(p == nil)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Ropen:
|
||||
case Rcreate:
|
||||
p = gqid(p, ep, &f->qid);
|
||||
if(p == nil)
|
||||
break;
|
||||
if(p+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->iounit = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Rread:
|
||||
if(p+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->count = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
if(p+f->count > ep)
|
||||
return 0;
|
||||
f->data = (char*)p;
|
||||
p += f->count;
|
||||
break;
|
||||
|
||||
case Rwrite:
|
||||
if(p+BIT32SZ > ep)
|
||||
return 0;
|
||||
f->count = GBIT32(p);
|
||||
p += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Rclunk:
|
||||
case Rremove:
|
||||
break;
|
||||
|
||||
case Rstat:
|
||||
if(p+BIT16SZ > ep)
|
||||
return 0;
|
||||
f->nstat = GBIT16(p);
|
||||
p += BIT16SZ;
|
||||
if(p+f->nstat > ep)
|
||||
return 0;
|
||||
f->stat = p;
|
||||
p += f->nstat;
|
||||
break;
|
||||
|
||||
case Rwstat:
|
||||
break;
|
||||
}
|
||||
|
||||
if(p==nil || p>ep)
|
||||
return 0;
|
||||
if(ap+size == p)
|
||||
return size;
|
||||
return 0;
|
||||
}
|
423
convS2M.c
Normal file
423
convS2M.c
Normal file
@ -0,0 +1,423 @@
|
||||
#include <plan9.h>
|
||||
#include <fcall.h>
|
||||
|
||||
static
|
||||
uchar*
|
||||
pstring(uchar *p, char *s)
|
||||
{
|
||||
uint n;
|
||||
|
||||
n = strlen(s);
|
||||
PBIT16(p, n);
|
||||
p += BIT16SZ;
|
||||
memmove(p, s, n);
|
||||
p += n;
|
||||
return p;
|
||||
}
|
||||
|
||||
static
|
||||
uchar*
|
||||
pqid(uchar *p, Qid *q)
|
||||
{
|
||||
PBIT8(p, q->type);
|
||||
p += BIT8SZ;
|
||||
PBIT32(p, q->vers);
|
||||
p += BIT32SZ;
|
||||
PBIT64(p, q->path);
|
||||
p += BIT64SZ;
|
||||
return p;
|
||||
}
|
||||
|
||||
static
|
||||
uint
|
||||
stringsz(char *s)
|
||||
{
|
||||
return BIT16SZ+strlen(s);
|
||||
}
|
||||
|
||||
static
|
||||
uint
|
||||
sizeS2M(Fcall *f)
|
||||
{
|
||||
uint n;
|
||||
int i;
|
||||
|
||||
n = 0;
|
||||
n += BIT32SZ; /* size */
|
||||
n += BIT8SZ; /* type */
|
||||
n += BIT16SZ; /* tag */
|
||||
|
||||
switch(f->type)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
|
||||
case Tversion:
|
||||
n += BIT32SZ;
|
||||
n += stringsz(f->version);
|
||||
break;
|
||||
|
||||
/*
|
||||
case Tsession:
|
||||
n += BIT16SZ;
|
||||
n += f->nchal;
|
||||
break;
|
||||
*/
|
||||
|
||||
case Tflush:
|
||||
n += BIT16SZ;
|
||||
break;
|
||||
|
||||
case Tauth:
|
||||
n += BIT32SZ;
|
||||
n += stringsz(f->uname);
|
||||
n += stringsz(f->aname);
|
||||
break;
|
||||
|
||||
case Tattach:
|
||||
n += BIT32SZ;
|
||||
n += BIT32SZ;
|
||||
n += stringsz(f->uname);
|
||||
n += stringsz(f->aname);
|
||||
break;
|
||||
|
||||
|
||||
case Twalk:
|
||||
n += BIT32SZ;
|
||||
n += BIT32SZ;
|
||||
n += BIT16SZ;
|
||||
for(i=0; i<f->nwname; i++)
|
||||
n += stringsz(f->wname[i]);
|
||||
break;
|
||||
|
||||
case Topen:
|
||||
n += BIT32SZ;
|
||||
n += BIT8SZ;
|
||||
break;
|
||||
|
||||
case Tcreate:
|
||||
n += BIT32SZ;
|
||||
n += stringsz(f->name);
|
||||
n += BIT32SZ;
|
||||
n += BIT8SZ;
|
||||
break;
|
||||
|
||||
case Tread:
|
||||
n += BIT32SZ;
|
||||
n += BIT64SZ;
|
||||
n += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Twrite:
|
||||
n += BIT32SZ;
|
||||
n += BIT64SZ;
|
||||
n += BIT32SZ;
|
||||
n += f->count;
|
||||
break;
|
||||
|
||||
case Tclunk:
|
||||
case Tremove:
|
||||
n += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Tstat:
|
||||
n += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Twstat:
|
||||
n += BIT32SZ;
|
||||
n += BIT16SZ;
|
||||
n += f->nstat;
|
||||
break;
|
||||
/*
|
||||
*/
|
||||
|
||||
case Rversion:
|
||||
n += BIT32SZ;
|
||||
n += stringsz(f->version);
|
||||
break;
|
||||
|
||||
/*
|
||||
case Rsession:
|
||||
n += BIT16SZ;
|
||||
n += f->nchal;
|
||||
n += stringsz(f->authid);
|
||||
n += stringsz(f->authdom);
|
||||
break;
|
||||
|
||||
*/
|
||||
case Rerror:
|
||||
n += stringsz(f->ename);
|
||||
break;
|
||||
|
||||
case Rflush:
|
||||
break;
|
||||
|
||||
case Rauth:
|
||||
n += QIDSZ;
|
||||
break;
|
||||
|
||||
/*
|
||||
case Rattach:
|
||||
n += QIDSZ;
|
||||
n += BIT16SZ;
|
||||
n += f->nrauth;
|
||||
break;
|
||||
*/
|
||||
|
||||
case Rattach:
|
||||
n += QIDSZ;
|
||||
break;
|
||||
|
||||
|
||||
case Rwalk:
|
||||
n += BIT16SZ;
|
||||
n += f->nwqid*QIDSZ;
|
||||
break;
|
||||
|
||||
case Ropen:
|
||||
case Rcreate:
|
||||
n += QIDSZ;
|
||||
n += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Rread:
|
||||
n += BIT32SZ;
|
||||
n += f->count;
|
||||
break;
|
||||
|
||||
case Rwrite:
|
||||
n += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Rclunk:
|
||||
break;
|
||||
|
||||
case Rremove:
|
||||
break;
|
||||
|
||||
case Rstat:
|
||||
n += BIT16SZ;
|
||||
n += f->nstat;
|
||||
break;
|
||||
|
||||
case Rwstat:
|
||||
break;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
uint
|
||||
convS2M(Fcall *f, uchar *ap, uint nap)
|
||||
{
|
||||
uchar *p;
|
||||
uint i, size;
|
||||
|
||||
size = sizeS2M(f);
|
||||
if(size == 0)
|
||||
return 0;
|
||||
if(size > nap)
|
||||
return 0;
|
||||
|
||||
p = (uchar*)ap;
|
||||
|
||||
PBIT32(p, size);
|
||||
p += BIT32SZ;
|
||||
PBIT8(p, f->type);
|
||||
p += BIT8SZ;
|
||||
PBIT16(p, f->tag);
|
||||
p += BIT16SZ;
|
||||
|
||||
switch(f->type)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
|
||||
case Tversion:
|
||||
PBIT32(p, f->msize);
|
||||
p += BIT32SZ;
|
||||
p = pstring(p, f->version);
|
||||
break;
|
||||
|
||||
/*
|
||||
case Tsession:
|
||||
PBIT16(p, f->nchal);
|
||||
p += BIT16SZ;
|
||||
f->chal = p;
|
||||
p += f->nchal;
|
||||
break;
|
||||
*/
|
||||
|
||||
case Tflush:
|
||||
PBIT16(p, f->oldtag);
|
||||
p += BIT16SZ;
|
||||
break;
|
||||
|
||||
case Tauth:
|
||||
PBIT32(p, f->afid);
|
||||
p += BIT32SZ;
|
||||
p = pstring(p, f->uname);
|
||||
p = pstring(p, f->aname);
|
||||
break;
|
||||
|
||||
case Tattach:
|
||||
PBIT32(p, f->fid);
|
||||
p += BIT32SZ;
|
||||
PBIT32(p, f->afid);
|
||||
p += BIT32SZ;
|
||||
p = pstring(p, f->uname);
|
||||
p = pstring(p, f->aname);
|
||||
break;
|
||||
|
||||
case Twalk:
|
||||
PBIT32(p, f->fid);
|
||||
p += BIT32SZ;
|
||||
PBIT32(p, f->newfid);
|
||||
p += BIT32SZ;
|
||||
PBIT16(p, f->nwname);
|
||||
p += BIT16SZ;
|
||||
if(f->nwname > MAXWELEM)
|
||||
return 0;
|
||||
for(i=0; i<f->nwname; i++)
|
||||
p = pstring(p, f->wname[i]);
|
||||
break;
|
||||
|
||||
case Topen:
|
||||
PBIT32(p, f->fid);
|
||||
p += BIT32SZ;
|
||||
PBIT8(p, f->mode);
|
||||
p += BIT8SZ;
|
||||
break;
|
||||
|
||||
case Tcreate:
|
||||
PBIT32(p, f->fid);
|
||||
p += BIT32SZ;
|
||||
p = pstring(p, f->name);
|
||||
PBIT32(p, f->perm);
|
||||
p += BIT32SZ;
|
||||
PBIT8(p, f->mode);
|
||||
p += BIT8SZ;
|
||||
break;
|
||||
|
||||
case Tread:
|
||||
PBIT32(p, f->fid);
|
||||
p += BIT32SZ;
|
||||
PBIT64(p, f->offset);
|
||||
p += BIT64SZ;
|
||||
PBIT32(p, f->count);
|
||||
p += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Twrite:
|
||||
PBIT32(p, f->fid);
|
||||
p += BIT32SZ;
|
||||
PBIT64(p, f->offset);
|
||||
p += BIT64SZ;
|
||||
PBIT32(p, f->count);
|
||||
p += BIT32SZ;
|
||||
memmove(p, f->data, f->count);
|
||||
p += f->count;
|
||||
break;
|
||||
|
||||
case Tclunk:
|
||||
case Tremove:
|
||||
PBIT32(p, f->fid);
|
||||
p += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Tstat:
|
||||
PBIT32(p, f->fid);
|
||||
p += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Twstat:
|
||||
PBIT32(p, f->fid);
|
||||
p += BIT32SZ;
|
||||
PBIT16(p, f->nstat);
|
||||
p += BIT16SZ;
|
||||
memmove(p, f->stat, f->nstat);
|
||||
p += f->nstat;
|
||||
break;
|
||||
/*
|
||||
*/
|
||||
|
||||
case Rversion:
|
||||
PBIT32(p, f->msize);
|
||||
p += BIT32SZ;
|
||||
p = pstring(p, f->version);
|
||||
break;
|
||||
|
||||
/*
|
||||
case Rsession:
|
||||
PBIT16(p, f->nchal);
|
||||
p += BIT16SZ;
|
||||
f->chal = p;
|
||||
p += f->nchal;
|
||||
p = pstring(p, f->authid);
|
||||
p = pstring(p, f->authdom);
|
||||
break;
|
||||
*/
|
||||
|
||||
case Rerror:
|
||||
p = pstring(p, f->ename);
|
||||
break;
|
||||
|
||||
case Rflush:
|
||||
break;
|
||||
|
||||
case Rauth:
|
||||
p = pqid(p, &f->aqid);
|
||||
break;
|
||||
|
||||
case Rattach:
|
||||
p = pqid(p, &f->qid);
|
||||
break;
|
||||
|
||||
case Rwalk:
|
||||
PBIT16(p, f->nwqid);
|
||||
p += BIT16SZ;
|
||||
if(f->nwqid > MAXWELEM)
|
||||
return 0;
|
||||
for(i=0; i<f->nwqid; i++)
|
||||
p = pqid(p, &f->wqid[i]);
|
||||
break;
|
||||
|
||||
case Ropen:
|
||||
case Rcreate:
|
||||
p = pqid(p, &f->qid);
|
||||
PBIT32(p, f->iounit);
|
||||
p += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Rread:
|
||||
PBIT32(p, f->count);
|
||||
p += BIT32SZ;
|
||||
memmove(p, f->data, f->count);
|
||||
p += f->count;
|
||||
break;
|
||||
|
||||
case Rwrite:
|
||||
PBIT32(p, f->count);
|
||||
p += BIT32SZ;
|
||||
break;
|
||||
|
||||
case Rclunk:
|
||||
break;
|
||||
|
||||
case Rremove:
|
||||
break;
|
||||
|
||||
case Rstat:
|
||||
PBIT16(p, f->nstat);
|
||||
p += BIT16SZ;
|
||||
memmove(p, f->stat, f->nstat);
|
||||
p += f->nstat;
|
||||
break;
|
||||
|
||||
case Rwstat:
|
||||
break;
|
||||
}
|
||||
if(size != p-ap)
|
||||
return 0;
|
||||
return size;
|
||||
}
|
62
cygwin.c
Normal file
62
cygwin.c
Normal file
@ -0,0 +1,62 @@
|
||||
/* compatability layer for u9fs support on CYGWIN */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
ssize_t
|
||||
pread(int fd, void *p, size_t n, off_t off)
|
||||
{
|
||||
off_t ooff;
|
||||
int oerrno;
|
||||
|
||||
if ((ooff = lseek(fd, off, SEEK_SET)) == -1)
|
||||
return -1;
|
||||
|
||||
n = read(fd, p, n);
|
||||
|
||||
oerrno = errno;
|
||||
lseek(fd, ooff, SEEK_SET);
|
||||
errno = oerrno;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
pwrite(int fd, const void *p, size_t n, off_t off)
|
||||
{
|
||||
off_t ooff;
|
||||
int oerrno;
|
||||
|
||||
if ((ooff = lseek(fd, off, SEEK_SET)) == -1)
|
||||
return -1;
|
||||
|
||||
n = write(fd, p, n);
|
||||
|
||||
oerrno = errno;
|
||||
lseek(fd, ooff, SEEK_SET);
|
||||
errno = oerrno;
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
setreuid(int ruid, int euid)
|
||||
{
|
||||
if (ruid != -1)
|
||||
if (setuid(ruid) == -1)
|
||||
return(-1);
|
||||
if (euid != -1)
|
||||
if (seteuid(euid) == -1)
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int
|
||||
setregid(int rgid, int egid)
|
||||
{
|
||||
if (rgid != -1)
|
||||
if (setgid(rgid) == -1)
|
||||
return(-1);
|
||||
if (egid != -1)
|
||||
if (setegid(egid) == -1)
|
||||
return(-1);
|
||||
}
|
355
des.c
Normal file
355
des.c
Normal file
@ -0,0 +1,355 @@
|
||||
#include <plan9.h>
|
||||
|
||||
/*
|
||||
* Data Encryption Standard
|
||||
* D.P.Mitchell 83/06/08.
|
||||
*
|
||||
* block_cipher(key, block, decrypting)
|
||||
*/
|
||||
|
||||
static long ip_low(char [8]);
|
||||
static long ip_high(char [8]);
|
||||
static void fp(long, long, char[8]);
|
||||
|
||||
extern int chatty9p;
|
||||
|
||||
/*
|
||||
* Tables for Combined S and P Boxes
|
||||
*/
|
||||
|
||||
static long s0p[] = {
|
||||
0x00410100,0x00010000,0x40400000,0x40410100,0x00400000,0x40010100,0x40010000,0x40400000,
|
||||
0x40010100,0x00410100,0x00410000,0x40000100,0x40400100,0x00400000,0x00000000,0x40010000,
|
||||
0x00010000,0x40000000,0x00400100,0x00010100,0x40410100,0x00410000,0x40000100,0x00400100,
|
||||
0x40000000,0x00000100,0x00010100,0x40410000,0x00000100,0x40400100,0x40410000,0x00000000,
|
||||
0x00000000,0x40410100,0x00400100,0x40010000,0x00410100,0x00010000,0x40000100,0x00400100,
|
||||
0x40410000,0x00000100,0x00010100,0x40400000,0x40010100,0x40000000,0x40400000,0x00410000,
|
||||
0x40410100,0x00010100,0x00410000,0x40400100,0x00400000,0x40000100,0x40010000,0x00000000,
|
||||
0x00010000,0x00400000,0x40400100,0x00410100,0x40000000,0x40410000,0x00000100,0x40010100,
|
||||
};
|
||||
|
||||
static long s1p[] = {
|
||||
0x08021002,0x00000000,0x00021000,0x08020000,0x08000002,0x00001002,0x08001000,0x00021000,
|
||||
0x00001000,0x08020002,0x00000002,0x08001000,0x00020002,0x08021000,0x08020000,0x00000002,
|
||||
0x00020000,0x08001002,0x08020002,0x00001000,0x00021002,0x08000000,0x00000000,0x00020002,
|
||||
0x08001002,0x00021002,0x08021000,0x08000002,0x08000000,0x00020000,0x00001002,0x08021002,
|
||||
0x00020002,0x08021000,0x08001000,0x00021002,0x08021002,0x00020002,0x08000002,0x00000000,
|
||||
0x08000000,0x00001002,0x00020000,0x08020002,0x00001000,0x08000000,0x00021002,0x08001002,
|
||||
0x08021000,0x00001000,0x00000000,0x08000002,0x00000002,0x08021002,0x00021000,0x08020000,
|
||||
0x08020002,0x00020000,0x00001002,0x08001000,0x08001002,0x00000002,0x08020000,0x00021000,
|
||||
};
|
||||
|
||||
static long s2p[] = {
|
||||
0x20800000,0x00808020,0x00000020,0x20800020,0x20008000,0x00800000,0x20800020,0x00008020,
|
||||
0x00800020,0x00008000,0x00808000,0x20000000,0x20808020,0x20000020,0x20000000,0x20808000,
|
||||
0x00000000,0x20008000,0x00808020,0x00000020,0x20000020,0x20808020,0x00008000,0x20800000,
|
||||
0x20808000,0x00800020,0x20008020,0x00808000,0x00008020,0x00000000,0x00800000,0x20008020,
|
||||
0x00808020,0x00000020,0x20000000,0x00008000,0x20000020,0x20008000,0x00808000,0x20800020,
|
||||
0x00000000,0x00808020,0x00008020,0x20808000,0x20008000,0x00800000,0x20808020,0x20000000,
|
||||
0x20008020,0x20800000,0x00800000,0x20808020,0x00008000,0x00800020,0x20800020,0x00008020,
|
||||
0x00800020,0x00000000,0x20808000,0x20000020,0x20800000,0x20008020,0x00000020,0x00808000,
|
||||
};
|
||||
|
||||
static long s3p[] = {
|
||||
0x00080201,0x02000200,0x00000001,0x02080201,0x00000000,0x02080000,0x02000201,0x00080001,
|
||||
0x02080200,0x02000001,0x02000000,0x00000201,0x02000001,0x00080201,0x00080000,0x02000000,
|
||||
0x02080001,0x00080200,0x00000200,0x00000001,0x00080200,0x02000201,0x02080000,0x00000200,
|
||||
0x00000201,0x00000000,0x00080001,0x02080200,0x02000200,0x02080001,0x02080201,0x00080000,
|
||||
0x02080001,0x00000201,0x00080000,0x02000001,0x00080200,0x02000200,0x00000001,0x02080000,
|
||||
0x02000201,0x00000000,0x00000200,0x00080001,0x00000000,0x02080001,0x02080200,0x00000200,
|
||||
0x02000000,0x02080201,0x00080201,0x00080000,0x02080201,0x00000001,0x02000200,0x00080201,
|
||||
0x00080001,0x00080200,0x02080000,0x02000201,0x00000201,0x02000000,0x02000001,0x02080200,
|
||||
};
|
||||
|
||||
static long s4p[] = {
|
||||
0x01000000,0x00002000,0x00000080,0x01002084,0x01002004,0x01000080,0x00002084,0x01002000,
|
||||
0x00002000,0x00000004,0x01000004,0x00002080,0x01000084,0x01002004,0x01002080,0x00000000,
|
||||
0x00002080,0x01000000,0x00002004,0x00000084,0x01000080,0x00002084,0x00000000,0x01000004,
|
||||
0x00000004,0x01000084,0x01002084,0x00002004,0x01002000,0x00000080,0x00000084,0x01002080,
|
||||
0x01002080,0x01000084,0x00002004,0x01002000,0x00002000,0x00000004,0x01000004,0x01000080,
|
||||
0x01000000,0x00002080,0x01002084,0x00000000,0x00002084,0x01000000,0x00000080,0x00002004,
|
||||
0x01000084,0x00000080,0x00000000,0x01002084,0x01002004,0x01002080,0x00000084,0x00002000,
|
||||
0x00002080,0x01002004,0x01000080,0x00000084,0x00000004,0x00002084,0x01002000,0x01000004,
|
||||
};
|
||||
|
||||
static long s5p[] = {
|
||||
0x10000008,0x00040008,0x00000000,0x10040400,0x00040008,0x00000400,0x10000408,0x00040000,
|
||||
0x00000408,0x10040408,0x00040400,0x10000000,0x10000400,0x10000008,0x10040000,0x00040408,
|
||||
0x00040000,0x10000408,0x10040008,0x00000000,0x00000400,0x00000008,0x10040400,0x10040008,
|
||||
0x10040408,0x10040000,0x10000000,0x00000408,0x00000008,0x00040400,0x00040408,0x10000400,
|
||||
0x00000408,0x10000000,0x10000400,0x00040408,0x10040400,0x00040008,0x00000000,0x10000400,
|
||||
0x10000000,0x00000400,0x10040008,0x00040000,0x00040008,0x10040408,0x00040400,0x00000008,
|
||||
0x10040408,0x00040400,0x00040000,0x10000408,0x10000008,0x10040000,0x00040408,0x00000000,
|
||||
0x00000400,0x10000008,0x10000408,0x10040400,0x10040000,0x00000408,0x00000008,0x10040008,
|
||||
};
|
||||
|
||||
static long s6p[] = {
|
||||
0x00000800,0x00000040,0x00200040,0x80200000,0x80200840,0x80000800,0x00000840,0x00000000,
|
||||
0x00200000,0x80200040,0x80000040,0x00200800,0x80000000,0x00200840,0x00200800,0x80000040,
|
||||
0x80200040,0x00000800,0x80000800,0x80200840,0x00000000,0x00200040,0x80200000,0x00000840,
|
||||
0x80200800,0x80000840,0x00200840,0x80000000,0x80000840,0x80200800,0x00000040,0x00200000,
|
||||
0x80000840,0x00200800,0x80200800,0x80000040,0x00000800,0x00000040,0x00200000,0x80200800,
|
||||
0x80200040,0x80000840,0x00000840,0x00000000,0x00000040,0x80200000,0x80000000,0x00200040,
|
||||
0x00000000,0x80200040,0x00200040,0x00000840,0x80000040,0x00000800,0x80200840,0x00200000,
|
||||
0x00200840,0x80000000,0x80000800,0x80200840,0x80200000,0x00200840,0x00200800,0x80000800,
|
||||
};
|
||||
|
||||
static long s7p[] = {
|
||||
0x04100010,0x04104000,0x00004010,0x00000000,0x04004000,0x00100010,0x04100000,0x04104010,
|
||||
0x00000010,0x04000000,0x00104000,0x00004010,0x00104010,0x04004010,0x04000010,0x04100000,
|
||||
0x00004000,0x00104010,0x00100010,0x04004000,0x04104010,0x04000010,0x00000000,0x00104000,
|
||||
0x04000000,0x00100000,0x04004010,0x04100010,0x00100000,0x00004000,0x04104000,0x00000010,
|
||||
0x00100000,0x00004000,0x04000010,0x04104010,0x00004010,0x04000000,0x00000000,0x00104000,
|
||||
0x04100010,0x04004010,0x04004000,0x00100010,0x04104000,0x00000010,0x00100010,0x04004000,
|
||||
0x04104010,0x00100000,0x04100000,0x04000010,0x00104000,0x00004010,0x04004010,0x04100000,
|
||||
0x00000010,0x04104000,0x00104010,0x00000000,0x04000000,0x04100010,0x00004000,0x00104010,
|
||||
};
|
||||
|
||||
/*
|
||||
* DES electronic codebook encryption of one block
|
||||
*/
|
||||
void
|
||||
block_cipher(char expanded_key[128], char text[8], int decrypting)
|
||||
{
|
||||
char *key;
|
||||
long crypto, temp, right, left;
|
||||
int i, key_offset;
|
||||
|
||||
key = expanded_key;
|
||||
left = ip_low(text);
|
||||
right = ip_high(text);
|
||||
if (decrypting) {
|
||||
key_offset = 16;
|
||||
key = key + 128 - 8;
|
||||
} else
|
||||
key_offset = 0;
|
||||
for (i = 0; i < 16; i++) {
|
||||
temp = (right << 1) | ((right >> 31) & 1);
|
||||
crypto = s0p[(temp & 0x3f) ^ *key++];
|
||||
crypto |= s1p[((temp >> 4) & 0x3f) ^ *key++];
|
||||
crypto |= s2p[((temp >> 8) & 0x3f) ^ *key++];
|
||||
crypto |= s3p[((temp >> 12) & 0x3f) ^ *key++];
|
||||
crypto |= s4p[((temp >> 16) & 0x3f) ^ *key++];
|
||||
crypto |= s5p[((temp >> 20) & 0x3f) ^ *key++];
|
||||
crypto |= s6p[((temp >> 24) & 0x3f) ^ *key++];
|
||||
temp = ((right & 1) << 5) | ((right >> 27) & 0x1f);
|
||||
crypto |= s7p[temp ^ *key++];
|
||||
temp = left;
|
||||
left = right;
|
||||
right = temp ^ crypto;
|
||||
key -= key_offset;
|
||||
}
|
||||
/*
|
||||
* standard final permutation (IPI)
|
||||
* left and right are reversed here
|
||||
*/
|
||||
fp(right, left, text);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initial Permutation
|
||||
*/
|
||||
static long iptab[] = {
|
||||
0x00000000, 0x00008000, 0x00000000, 0x00008000,
|
||||
0x00000080, 0x00008080, 0x00000080, 0x00008080
|
||||
};
|
||||
|
||||
static long
|
||||
ip_low(char block[8])
|
||||
{
|
||||
int i;
|
||||
long l;
|
||||
|
||||
l = 0;
|
||||
for(i = 0; i < 8; i++){
|
||||
l |= iptab[(block[i] >> 4) & 7] >> i;
|
||||
l |= iptab[block[i] & 7] << (16 - i);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
static long
|
||||
ip_high(char block[8])
|
||||
{
|
||||
int i;
|
||||
long l;
|
||||
|
||||
l = 0;
|
||||
for(i = 0; i < 8; i++){
|
||||
l |= iptab[(block[i] >> 5) & 7] >> i;
|
||||
l |= iptab[(block[i] >> 1) & 7] << (16 - i);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Final Permutation
|
||||
*/
|
||||
static unsigned long fptab[] = {
|
||||
0x00000000,0x80000000,0x00800000,0x80800000,0x00008000,0x80008000,0x00808000,0x80808000,
|
||||
0x00000080,0x80000080,0x00800080,0x80800080,0x00008080,0x80008080,0x00808080,0x80808080,
|
||||
};
|
||||
|
||||
static void
|
||||
fp(long left, long right, char text[8])
|
||||
{
|
||||
unsigned long ta[2], t, v[2];
|
||||
int i, j, sh;
|
||||
|
||||
ta[0] = right;
|
||||
ta[1] = left;
|
||||
v[0] = v[1] = 0;
|
||||
for(i = 0; i < 2; i++){
|
||||
t = ta[i];
|
||||
sh = i;
|
||||
for(j = 0; j < 4; j++){
|
||||
v[1] |= fptab[t & 0xf] >> sh;
|
||||
t >>= 4;
|
||||
v[0] |= fptab[t & 0xf] >> sh;
|
||||
t >>= 4;
|
||||
sh += 2;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < 2; i++)
|
||||
for(j = 0; j < 4; j++){
|
||||
*text++ = v[i];
|
||||
v[i] >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Key set-up
|
||||
*/
|
||||
static uchar keyexpand[][15][2] = {
|
||||
{ 3, 2, 9, 8, 18, 8, 27, 32, 33, 2, 42, 16, 48, 8, 65, 16,
|
||||
74, 2, 80, 2, 89, 4, 99, 16, 104, 4, 122, 32, 0, 0, },
|
||||
{ 1, 4, 8, 1, 18, 4, 25, 32, 34, 32, 41, 8, 50, 8, 59, 32,
|
||||
64, 16, 75, 4, 90, 1, 97, 16, 106, 2, 112, 2, 123, 1, },
|
||||
{ 2, 1, 19, 8, 35, 1, 40, 1, 50, 4, 57, 32, 75, 2, 80, 32,
|
||||
89, 1, 96, 16, 107, 4, 120, 8, 0, 0, 0, 0, 0, 0, },
|
||||
{ 4, 32, 20, 2, 31, 4, 37, 32, 47, 1, 54, 1, 63, 2, 68, 1,
|
||||
78, 4, 84, 8, 101, 16, 108, 4, 119, 16, 126, 8, 0, 0, },
|
||||
{ 5, 4, 15, 4, 21, 32, 31, 1, 38, 1, 47, 2, 53, 2, 68, 8,
|
||||
85, 16, 92, 4, 103, 16, 108, 32, 118, 32, 124, 2, 0, 0, },
|
||||
{ 15, 2, 21, 2, 39, 8, 46, 16, 55, 32, 61, 1, 71, 16, 76, 32,
|
||||
86, 32, 93, 4, 102, 2, 108, 16, 117, 8, 126, 1, 0, 0, },
|
||||
{ 14, 16, 23, 32, 29, 1, 38, 8, 52, 2, 63, 4, 70, 2, 76, 16,
|
||||
85, 8, 100, 1, 110, 4, 116, 8, 127, 8, 0, 0, 0, 0, },
|
||||
{ 1, 8, 8, 32, 17, 1, 24, 16, 35, 4, 50, 1, 57, 16, 67, 8,
|
||||
83, 1, 88, 1, 98, 4, 105, 32, 114, 32, 123, 2, 0, 0, },
|
||||
{ 0, 1, 11, 16, 16, 4, 35, 2, 40, 32, 49, 1, 56, 16, 65, 2,
|
||||
74, 16, 80, 8, 99, 8, 115, 1, 121, 4, 0, 0, 0, 0, },
|
||||
{ 9, 16, 18, 2, 24, 2, 33, 4, 43, 16, 48, 4, 66, 32, 73, 8,
|
||||
82, 8, 91, 32, 97, 2, 106, 16, 112, 8, 122, 1, 0, 0, },
|
||||
{ 14, 32, 21, 4, 30, 2, 36, 16, 45, 8, 60, 1, 69, 2, 87, 8,
|
||||
94, 16, 103, 32, 109, 1, 118, 8, 124, 32, 0, 0, 0, 0, },
|
||||
{ 7, 4, 14, 2, 20, 16, 29, 8, 44, 1, 54, 4, 60, 8, 71, 8,
|
||||
78, 16, 87, 32, 93, 1, 102, 8, 116, 2, 125, 4, 0, 0, },
|
||||
{ 7, 2, 12, 1, 22, 4, 28, 8, 45, 16, 52, 4, 63, 16, 70, 8,
|
||||
84, 2, 95, 4, 101, 32, 111, 1, 118, 1, 0, 0, 0, 0, },
|
||||
{ 6, 16, 13, 16, 20, 4, 31, 16, 36, 32, 46, 32, 53, 4, 62, 2,
|
||||
69, 32, 79, 1, 86, 1, 95, 2, 101, 2, 119, 8, 0, 0, },
|
||||
{ 0, 32, 10, 8, 19, 32, 25, 2, 34, 16, 40, 8, 59, 8, 66, 2,
|
||||
72, 2, 81, 4, 91, 16, 96, 4, 115, 2, 121, 8, 0, 0, },
|
||||
{ 3, 16, 10, 4, 17, 32, 26, 32, 33, 8, 42, 8, 51, 32, 57, 2,
|
||||
67, 4, 82, 1, 89, 16, 98, 2, 104, 2, 113, 4, 120, 1, },
|
||||
{ 1, 16, 11, 8, 27, 1, 32, 1, 42, 4, 49, 32, 58, 32, 67, 2,
|
||||
72, 32, 81, 1, 88, 16, 99, 4, 114, 1, 0, 0, 0, 0, },
|
||||
{ 6, 32, 12, 2, 23, 4, 29, 32, 39, 1, 46, 1, 55, 2, 61, 2,
|
||||
70, 4, 76, 8, 93, 16, 100, 4, 111, 16, 116, 32, 0, 0, },
|
||||
{ 6, 2, 13, 32, 23, 1, 30, 1, 39, 2, 45, 2, 63, 8, 77, 16,
|
||||
84, 4, 95, 16, 100, 32, 110, 32, 117, 4, 127, 4, 0, 0, },
|
||||
{ 4, 1, 13, 2, 31, 8, 38, 16, 47, 32, 53, 1, 62, 8, 68, 32,
|
||||
78, 32, 85, 4, 94, 2, 100, 16, 109, 8, 127, 2, 0, 0, },
|
||||
{ 5, 16, 15, 32, 21, 1, 30, 8, 44, 2, 55, 4, 61, 32, 68, 16,
|
||||
77, 8, 92, 1, 102, 4, 108, 8, 126, 16, 0, 0, 0, 0, },
|
||||
{ 2, 8, 9, 1, 16, 16, 27, 4, 42, 1, 49, 16, 58, 2, 75, 1,
|
||||
80, 1, 90, 4, 97, 32, 106, 32, 113, 8, 120, 32, 0, 0, },
|
||||
{ 2, 4, 8, 4, 27, 2, 32, 32, 41, 1, 48, 16, 59, 4, 66, 16,
|
||||
72, 8, 91, 8, 107, 1, 112, 1, 123, 16, 0, 0, 0, 0, },
|
||||
{ 3, 8, 10, 2, 16, 2, 25, 4, 35, 16, 40, 4, 59, 2, 65, 8,
|
||||
74, 8, 83, 32, 89, 2, 98, 16, 104, 8, 121, 16, 0, 0, },
|
||||
{ 4, 2, 13, 4, 22, 2, 28, 16, 37, 8, 52, 1, 62, 4, 79, 8,
|
||||
86, 16, 95, 32, 101, 1, 110, 8, 126, 32, 0, 0, 0, 0, },
|
||||
{ 5, 32, 12, 16, 21, 8, 36, 1, 46, 4, 52, 8, 70, 16, 79, 32,
|
||||
85, 1, 94, 8, 108, 2, 119, 4, 126, 2, 0, 0, 0, 0, },
|
||||
{ 5, 2, 14, 4, 20, 8, 37, 16, 44, 4, 55, 16, 60, 32, 76, 2,
|
||||
87, 4, 93, 32, 103, 1, 110, 1, 119, 2, 124, 1, 0, 0, },
|
||||
{ 7, 32, 12, 4, 23, 16, 28, 32, 38, 32, 45, 4, 54, 2, 60, 16,
|
||||
71, 1, 78, 1, 87, 2, 93, 2, 111, 8, 118, 16, 125, 16, },
|
||||
{ 1, 1, 11, 32, 17, 2, 26, 16, 32, 8, 51, 8, 64, 2, 73, 4,
|
||||
83, 16, 88, 4, 107, 2, 112, 32, 122, 8, 0, 0, 0, 0, },
|
||||
{ 0, 4, 9, 32, 18, 32, 25, 8, 34, 8, 43, 32, 49, 2, 58, 16,
|
||||
74, 1, 81, 16, 90, 2, 96, 2, 105, 4, 115, 16, 122, 4, },
|
||||
{ 2, 2, 19, 1, 24, 1, 34, 4, 41, 32, 50, 32, 57, 8, 64, 32,
|
||||
73, 1, 80, 16, 91, 4, 106, 1, 113, 16, 123, 8, 0, 0, },
|
||||
{ 3, 4, 10, 16, 16, 8, 35, 8, 51, 1, 56, 1, 67, 16, 72, 4,
|
||||
91, 2, 96, 32, 105, 1, 112, 16, 121, 2, 0, 0, 0, 0, },
|
||||
{ 4, 16, 15, 1, 22, 1, 31, 2, 37, 2, 55, 8, 62, 16, 69, 16,
|
||||
76, 4, 87, 16, 92, 32, 102, 32, 109, 4, 118, 2, 125, 32, },
|
||||
{ 6, 4, 23, 8, 30, 16, 39, 32, 45, 1, 54, 8, 70, 32, 77, 4,
|
||||
86, 2, 92, 16, 101, 8, 116, 1, 125, 2, 0, 0, 0, 0, },
|
||||
{ 4, 4, 13, 1, 22, 8, 36, 2, 47, 4, 53, 32, 63, 1, 69, 8,
|
||||
84, 1, 94, 4, 100, 8, 117, 16, 127, 32, 0, 0, 0, 0, },
|
||||
{ 3, 32, 8, 16, 19, 4, 34, 1, 41, 16, 50, 2, 56, 2, 67, 1,
|
||||
72, 1, 82, 4, 89, 32, 98, 32, 105, 8, 114, 8, 121, 1, },
|
||||
{ 1, 32, 19, 2, 24, 32, 33, 1, 40, 16, 51, 4, 64, 8, 83, 8,
|
||||
99, 1, 104, 1, 114, 4, 120, 4, 0, 0, 0, 0, 0, 0, },
|
||||
{ 8, 2, 17, 4, 27, 16, 32, 4, 51, 2, 56, 32, 66, 8, 75, 32,
|
||||
81, 2, 90, 16, 96, 8, 115, 8, 122, 2, 0, 0, 0, 0, },
|
||||
{ 2, 16, 18, 1, 25, 16, 34, 2, 40, 2, 49, 4, 59, 16, 66, 4,
|
||||
73, 32, 82, 32, 89, 8, 98, 8, 107, 32, 113, 2, 123, 4, },
|
||||
{ 7, 1, 13, 8, 28, 1, 38, 4, 44, 8, 61, 16, 71, 32, 77, 1,
|
||||
86, 8, 100, 2, 111, 4, 117, 32, 124, 16, 0, 0, 0, 0, },
|
||||
{ 12, 8, 29, 16, 36, 4, 47, 16, 52, 32, 62, 32, 68, 2, 79, 4,
|
||||
85, 32, 95, 1, 102, 1, 111, 2, 117, 2, 126, 4, 0, 0, },
|
||||
{ 5, 1, 15, 16, 20, 32, 30, 32, 37, 4, 46, 2, 52, 16, 61, 8,
|
||||
70, 1, 79, 2, 85, 2, 103, 8, 110, 16, 119, 32, 124, 4, },
|
||||
{ 0, 16, 9, 2, 18, 16, 24, 8, 43, 8, 59, 1, 65, 4, 75, 16,
|
||||
80, 4, 99, 2, 104, 32, 113, 1, 123, 32, 0, 0, 0, 0, },
|
||||
{ 10, 32, 17, 8, 26, 8, 35, 32, 41, 2, 50, 16, 56, 8, 66, 1,
|
||||
73, 16, 82, 2, 88, 2, 97, 4, 107, 16, 112, 4, 121, 32, },
|
||||
{ 0, 2, 11, 1, 16, 1, 26, 4, 33, 32, 42, 32, 49, 8, 58, 8,
|
||||
65, 1, 72, 16, 83, 4, 98, 1, 105, 16, 114, 2, 0, 0, },
|
||||
{ 8, 8, 27, 8, 43, 1, 48, 1, 58, 4, 64, 4, 83, 2, 88, 32,
|
||||
97, 1, 104, 16, 115, 4, 122, 16, 0, 0, 0, 0, 0, 0, },
|
||||
{ 5, 8, 14, 1, 23, 2, 29, 2, 47, 8, 54, 16, 63, 32, 68, 4,
|
||||
79, 16, 84, 32, 94, 32, 101, 4, 110, 2, 116, 16, 127, 1, },
|
||||
{ 4, 8, 15, 8, 22, 16, 31, 32, 37, 1, 46, 8, 60, 2, 69, 4,
|
||||
78, 2, 84, 16, 93, 8, 108, 1, 118, 4, 0, 0, 0, 0, },
|
||||
{ 7, 16, 14, 8, 28, 2, 39, 4, 45, 32, 55, 1, 62, 1, 76, 1,
|
||||
86, 4, 92, 8, 109, 16, 116, 4, 125, 1, 0, 0, 0, 0, },
|
||||
{ 1, 2, 11, 4, 26, 1, 33, 16, 42, 2, 48, 2, 57, 4, 64, 1,
|
||||
74, 4, 81, 32, 90, 32, 97, 8, 106, 8, 115, 32, 120, 16, },
|
||||
{ 2, 32, 11, 2, 16, 32, 25, 1, 32, 16, 43, 4, 58, 1, 75, 8,
|
||||
91, 1, 96, 1, 106, 4, 113, 32, 0, 0, 0, 0, 0, 0, },
|
||||
{ 3, 1, 9, 4, 19, 16, 24, 4, 43, 2, 48, 32, 57, 1, 67, 32,
|
||||
73, 2, 82, 16, 88, 8, 107, 8, 120, 2, 0, 0, 0, 0, },
|
||||
{ 0, 8, 10, 1, 17, 16, 26, 2, 32, 2, 41, 4, 51, 16, 56, 4,
|
||||
65, 32, 74, 32, 81, 8, 90, 8, 99, 32, 105, 2, 114, 16, },
|
||||
{ 6, 1, 20, 1, 30, 4, 36, 8, 53, 16, 60, 4, 69, 1, 78, 8,
|
||||
92, 2, 103, 4, 109, 32, 119, 1, 125, 8, 0, 0, 0, 0, },
|
||||
{ 7, 8, 21, 16, 28, 4, 39, 16, 44, 32, 54, 32, 61, 4, 71, 4,
|
||||
77, 32, 87, 1, 94, 1, 103, 2, 109, 2, 124, 8, 0, 0, },
|
||||
{ 6, 8, 12, 32, 22, 32, 29, 4, 38, 2, 44, 16, 53, 8, 71, 2,
|
||||
77, 2, 95, 8, 102, 16, 111, 32, 117, 1, 127, 16, 0, 0, }
|
||||
};
|
||||
|
||||
void
|
||||
key_setup(char key[DESKEYLEN], char *ek)
|
||||
{
|
||||
int i, j, k, mask;
|
||||
uchar (*x)[2];
|
||||
|
||||
memset(ek, 0, 128);
|
||||
x = keyexpand[0];
|
||||
for(i = 0; i < 7; i++){
|
||||
k = key[i];
|
||||
for(mask = 0x80; mask; mask >>= 1){
|
||||
if(k & mask)
|
||||
for(j = 0; j < 15; j++)
|
||||
ek[x[j][0]] |= x[j][1];
|
||||
x += 15;
|
||||
}
|
||||
}
|
||||
}
|
47
dirmodeconv.c
Normal file
47
dirmodeconv.c
Normal file
@ -0,0 +1,47 @@
|
||||
#include <plan9.h>
|
||||
#include <fcall.h>
|
||||
|
||||
static char *modes[] =
|
||||
{
|
||||
"---",
|
||||
"--x",
|
||||
"-w-",
|
||||
"-wx",
|
||||
"r--",
|
||||
"r-x",
|
||||
"rw-",
|
||||
"rwx",
|
||||
};
|
||||
|
||||
static void
|
||||
rwx(long m, char *s)
|
||||
{
|
||||
strncpy(s, modes[m], 3);
|
||||
}
|
||||
|
||||
int
|
||||
dirmodeconv(va_list *arg, Fconv *f)
|
||||
{
|
||||
static char buf[16];
|
||||
ulong m;
|
||||
|
||||
m = va_arg(*arg, ulong);
|
||||
|
||||
if(m & DMDIR)
|
||||
buf[0]='d';
|
||||
else if(m & DMAPPEND)
|
||||
buf[0]='a';
|
||||
else
|
||||
buf[0]='-';
|
||||
if(m & DMEXCL)
|
||||
buf[1]='l';
|
||||
else
|
||||
buf[1]='-';
|
||||
rwx((m>>6)&7, buf+2);
|
||||
rwx((m>>3)&7, buf+5);
|
||||
rwx((m>>0)&7, buf+8);
|
||||
buf[11] = 0;
|
||||
|
||||
strconv(buf, f);
|
||||
return 0;
|
||||
}
|
610
doprint.c
Normal file
610
doprint.c
Normal file
@ -0,0 +1,610 @@
|
||||
#include <plan9.h>
|
||||
|
||||
#define lock(x)
|
||||
#define unlock(x)
|
||||
|
||||
enum
|
||||
{
|
||||
IDIGIT = 40,
|
||||
MAXCONV = 40,
|
||||
FDIGIT = 30,
|
||||
FDEFLT = 6,
|
||||
NONE = -1000,
|
||||
MAXFMT = 512,
|
||||
|
||||
FPLUS = 1<<0,
|
||||
FMINUS = 1<<1,
|
||||
FSHARP = 1<<2,
|
||||
FLONG = 1<<3,
|
||||
FUNSIGN = 1<<5,
|
||||
FVLONG = 1<<6,
|
||||
FPOINTER= 1<<7
|
||||
};
|
||||
|
||||
int printcol;
|
||||
|
||||
static struct
|
||||
{
|
||||
/* Lock; */
|
||||
int convcount;
|
||||
char index[MAXFMT];
|
||||
int (*conv[MAXCONV])(va_list*, Fconv*);
|
||||
} fmtalloc;
|
||||
|
||||
static int noconv(va_list*, Fconv*);
|
||||
static int flags(va_list*, Fconv*);
|
||||
|
||||
static int cconv(va_list*, Fconv*);
|
||||
static int sconv(va_list*, Fconv*);
|
||||
static int percent(va_list*, Fconv*);
|
||||
static int column(va_list*, Fconv*);
|
||||
|
||||
extern int numbconv(va_list*, Fconv*);
|
||||
|
||||
|
||||
static void
|
||||
initfmt(void)
|
||||
{
|
||||
int cc;
|
||||
|
||||
lock(&fmtalloc);
|
||||
if(fmtalloc.convcount <= 0) {
|
||||
cc = 0;
|
||||
fmtalloc.conv[cc] = noconv;
|
||||
cc++;
|
||||
|
||||
fmtalloc.conv[cc] = flags;
|
||||
fmtalloc.index['+'] = cc;
|
||||
fmtalloc.index['-'] = cc;
|
||||
fmtalloc.index['#'] = cc;
|
||||
fmtalloc.index['l'] = cc;
|
||||
fmtalloc.index['u'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtalloc.conv[cc] = numbconv;
|
||||
fmtalloc.index['d'] = cc;
|
||||
fmtalloc.index['o'] = cc;
|
||||
fmtalloc.index['x'] = cc;
|
||||
fmtalloc.index['X'] = cc;
|
||||
fmtalloc.index['p'] = cc;
|
||||
cc++;
|
||||
|
||||
|
||||
fmtalloc.conv[cc] = cconv;
|
||||
fmtalloc.index['c'] = cc;
|
||||
fmtalloc.index['C'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtalloc.conv[cc] = sconv;
|
||||
fmtalloc.index['s'] = cc;
|
||||
fmtalloc.index['S'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtalloc.conv[cc] = percent;
|
||||
fmtalloc.index['%'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtalloc.conv[cc] = column;
|
||||
fmtalloc.index['|'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtalloc.convcount = cc;
|
||||
}
|
||||
unlock(&fmtalloc);
|
||||
}
|
||||
|
||||
int
|
||||
fmtinstall(int c, int (*f)(va_list*, Fconv*))
|
||||
{
|
||||
|
||||
if(fmtalloc.convcount <= 0)
|
||||
initfmt();
|
||||
|
||||
lock(&fmtalloc);
|
||||
if(c < 0 || c >= MAXFMT) {
|
||||
unlock(&fmtalloc);
|
||||
return -1;
|
||||
}
|
||||
if(fmtalloc.convcount >= MAXCONV) {
|
||||
unlock(&fmtalloc);
|
||||
return -1;
|
||||
}
|
||||
fmtalloc.conv[fmtalloc.convcount] = f;
|
||||
fmtalloc.index[c] = fmtalloc.convcount;
|
||||
fmtalloc.convcount++;
|
||||
|
||||
unlock(&fmtalloc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pchar(Rune c, Fconv *fp)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = fp->eout - fp->out;
|
||||
if(n > 0) {
|
||||
if(c < Runeself) {
|
||||
*fp->out++ = c;
|
||||
return;
|
||||
}
|
||||
if(n >= UTFmax || n >= runelen(c)) {
|
||||
n = runetochar(fp->out, &c);
|
||||
fp->out += n;
|
||||
return;
|
||||
}
|
||||
fp->eout = fp->out;
|
||||
}
|
||||
}
|
||||
|
||||
char*
|
||||
doprint(char *s, char *es, char *fmt, va_list *argp)
|
||||
{
|
||||
int n, c;
|
||||
Rune rune;
|
||||
Fconv local;
|
||||
|
||||
if(fmtalloc.convcount <= 0)
|
||||
initfmt();
|
||||
|
||||
if(s >= es)
|
||||
return s;
|
||||
local.out = s;
|
||||
local.eout = es-1;
|
||||
|
||||
loop:
|
||||
c = *fmt & 0xff;
|
||||
if(c >= Runeself) {
|
||||
n = chartorune(&rune, fmt);
|
||||
fmt += n;
|
||||
c = rune;
|
||||
} else
|
||||
fmt++;
|
||||
switch(c) {
|
||||
case 0:
|
||||
*local.out = 0;
|
||||
return local.out;
|
||||
|
||||
default:
|
||||
printcol++;
|
||||
goto common;
|
||||
|
||||
case '\n':
|
||||
printcol = 0;
|
||||
goto common;
|
||||
|
||||
case '\t':
|
||||
printcol = (printcol+8) & ~7;
|
||||
goto common;
|
||||
|
||||
common:
|
||||
pchar(c, &local);
|
||||
goto loop;
|
||||
|
||||
case '%':
|
||||
break;
|
||||
}
|
||||
local.f1 = NONE;
|
||||
local.f2 = NONE;
|
||||
local.f3 = 0;
|
||||
|
||||
/*
|
||||
* read one of the following
|
||||
* 1. number, => f1, f2 in order.
|
||||
* 2. '*' same as number (from args)
|
||||
* 3. '.' ignored (separates numbers)
|
||||
* 4. flag => f3
|
||||
* 5. verb and terminate
|
||||
*/
|
||||
l0:
|
||||
c = *fmt & 0xff;
|
||||
if(c >= Runeself) {
|
||||
n = chartorune(&rune, fmt);
|
||||
fmt += n;
|
||||
c = rune;
|
||||
} else
|
||||
fmt++;
|
||||
|
||||
l1:
|
||||
if(c == 0) {
|
||||
fmt--;
|
||||
goto loop;
|
||||
}
|
||||
if(c == '.') {
|
||||
if(local.f1 == NONE)
|
||||
local.f1 = 0;
|
||||
local.f2 = 0;
|
||||
goto l0;
|
||||
}
|
||||
if((c >= '1' && c <= '9') ||
|
||||
(c == '0' && local.f1 != NONE)) { /* '0' is a digit for f2 */
|
||||
n = 0;
|
||||
while(c >= '0' && c <= '9') {
|
||||
n = n*10 + c-'0';
|
||||
c = *fmt++;
|
||||
}
|
||||
if(local.f1 == NONE)
|
||||
local.f1 = n;
|
||||
else
|
||||
local.f2 = n;
|
||||
goto l1;
|
||||
}
|
||||
if(c == '*') {
|
||||
n = va_arg(*argp, int);
|
||||
if(local.f1 == NONE)
|
||||
local.f1 = n;
|
||||
else
|
||||
local.f2 = n;
|
||||
goto l0;
|
||||
}
|
||||
n = 0;
|
||||
if(c >= 0 && c < MAXFMT)
|
||||
n = fmtalloc.index[c];
|
||||
local.chr = c;
|
||||
n = (*fmtalloc.conv[n])(argp, &local);
|
||||
if(n < 0) {
|
||||
local.f3 |= -n;
|
||||
goto l0;
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
|
||||
int
|
||||
numbconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
char s[IDIGIT];
|
||||
int i, f, n, b, ucase;
|
||||
long v;
|
||||
vlong vl;
|
||||
|
||||
SET(v);
|
||||
SET(vl);
|
||||
|
||||
ucase = 0;
|
||||
b = fp->chr;
|
||||
switch(fp->chr) {
|
||||
case 'u':
|
||||
fp->f3 |= FUNSIGN;
|
||||
case 'd':
|
||||
b = 10;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
b = 2;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
b = 8;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
ucase = 1;
|
||||
case 'x':
|
||||
b = 16;
|
||||
break;
|
||||
case 'p':
|
||||
fp->f3 |= FPOINTER|FUNSIGN;
|
||||
b = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
f = 0;
|
||||
switch(fp->f3 & (FVLONG|FLONG|FUNSIGN|FPOINTER)) {
|
||||
case FVLONG|FLONG:
|
||||
vl = va_arg(*arg, vlong);
|
||||
break;
|
||||
|
||||
case FUNSIGN|FVLONG|FLONG:
|
||||
vl = va_arg(*arg, uvlong);
|
||||
break;
|
||||
|
||||
case FUNSIGN|FPOINTER:
|
||||
v = (ulong)va_arg(*arg, void*);
|
||||
break;
|
||||
|
||||
case FLONG:
|
||||
v = va_arg(*arg, long);
|
||||
break;
|
||||
|
||||
case FUNSIGN|FLONG:
|
||||
v = va_arg(*arg, ulong);
|
||||
break;
|
||||
|
||||
default:
|
||||
v = va_arg(*arg, int);
|
||||
break;
|
||||
|
||||
case FUNSIGN:
|
||||
v = va_arg(*arg, unsigned);
|
||||
break;
|
||||
}
|
||||
if(fp->f3 & FVLONG) {
|
||||
if(!(fp->f3 & FUNSIGN) && vl < 0) {
|
||||
vl = -vl;
|
||||
f = 1;
|
||||
}
|
||||
} else {
|
||||
if(!(fp->f3 & FUNSIGN) && v < 0) {
|
||||
v = -v;
|
||||
f = 1;
|
||||
}
|
||||
}
|
||||
s[IDIGIT-1] = 0;
|
||||
for(i = IDIGIT-2;; i--) {
|
||||
if(fp->f3 & FVLONG)
|
||||
n = (uvlong)vl % b;
|
||||
else
|
||||
n = (ulong)v % b;
|
||||
n += '0';
|
||||
if(n > '9') {
|
||||
n += 'a' - ('9'+1);
|
||||
if(ucase)
|
||||
n += 'A'-'a';
|
||||
}
|
||||
s[i] = n;
|
||||
if(i < 2)
|
||||
break;
|
||||
if(fp->f3 & FVLONG)
|
||||
vl = (uvlong)vl / b;
|
||||
else
|
||||
v = (ulong)v / b;
|
||||
if(fp->f2 != NONE && i >= IDIGIT-fp->f2)
|
||||
continue;
|
||||
if(fp->f3 & FVLONG) {
|
||||
if(vl <= 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if(v <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if(fp->f3 & FSHARP) {
|
||||
if(b == 8 && s[i] != '0')
|
||||
s[--i] = '0';
|
||||
if(b == 16) {
|
||||
if(ucase)
|
||||
s[--i] = 'X';
|
||||
else
|
||||
s[--i] = 'x';
|
||||
s[--i] = '0';
|
||||
}
|
||||
}
|
||||
if(f)
|
||||
s[--i] = '-';
|
||||
else if(fp->f3 & FPLUS)
|
||||
s[--i] = '+';
|
||||
|
||||
fp->f2 = NONE;
|
||||
strconv(s+i, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Strconv(Rune *s, Fconv *fp)
|
||||
{
|
||||
int n, c;
|
||||
|
||||
if(fp->f3 & FMINUS)
|
||||
fp->f1 = -fp->f1;
|
||||
n = 0;
|
||||
if(fp->f1 != NONE && fp->f1 >= 0) {
|
||||
for(; s[n]; n++)
|
||||
;
|
||||
while(n < fp->f1) {
|
||||
pchar(' ', fp);
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
for(;;) {
|
||||
c = *s++;
|
||||
if(c == 0)
|
||||
break;
|
||||
n++;
|
||||
if(fp->f2 == NONE || fp->f2 > 0) {
|
||||
pchar(c, fp);
|
||||
if(fp->f2 != NONE)
|
||||
fp->f2--;
|
||||
switch(c) {
|
||||
default:
|
||||
printcol++;
|
||||
break;
|
||||
case '\n':
|
||||
printcol = 0;
|
||||
break;
|
||||
case '\t':
|
||||
printcol = (printcol+8) & ~7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(fp->f1 != NONE && fp->f1 < 0) {
|
||||
fp->f1 = -fp->f1;
|
||||
while(n < fp->f1) {
|
||||
pchar(' ', fp);
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
strconv(char *s, Fconv *fp)
|
||||
{
|
||||
int n, c, i;
|
||||
Rune rune;
|
||||
|
||||
if(fp->f3 & FMINUS)
|
||||
fp->f1 = -fp->f1;
|
||||
n = 0;
|
||||
if(fp->f1 != NONE && fp->f1 >= 0) {
|
||||
n = utflen(s);
|
||||
while(n < fp->f1) {
|
||||
pchar(' ', fp);
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
for(;;) {
|
||||
c = *s & 0xff;
|
||||
if(c >= Runeself) {
|
||||
i = chartorune(&rune, s);
|
||||
s += i;
|
||||
c = rune;
|
||||
} else
|
||||
s++;
|
||||
if(c == 0)
|
||||
break;
|
||||
n++;
|
||||
if(fp->f2 == NONE || fp->f2 > 0) {
|
||||
pchar(c, fp);
|
||||
if(fp->f2 != NONE)
|
||||
fp->f2--;
|
||||
switch(c) {
|
||||
default:
|
||||
printcol++;
|
||||
break;
|
||||
case '\n':
|
||||
printcol = 0;
|
||||
break;
|
||||
case '\t':
|
||||
printcol = (printcol+8) & ~7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(fp->f1 != NONE && fp->f1 < 0) {
|
||||
fp->f1 = -fp->f1;
|
||||
while(n < fp->f1) {
|
||||
pchar(' ', fp);
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
noconv(va_list *va, Fconv *fp)
|
||||
{
|
||||
char s[10];
|
||||
|
||||
USED(va);
|
||||
s[0] = '*';
|
||||
s[1] = fp->chr;
|
||||
s[2] = '*';
|
||||
s[3] = 0;
|
||||
fp->f1 = 0;
|
||||
fp->f2 = NONE;
|
||||
fp->f3 = 0;
|
||||
strconv(s, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
char s[10];
|
||||
Rune rune;
|
||||
|
||||
rune = va_arg(*arg, int);
|
||||
if(fp->chr == 'c')
|
||||
rune &= 0xff;
|
||||
s[runetochar(s, &rune)] = 0;
|
||||
|
||||
fp->f2 = NONE;
|
||||
strconv(s, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Rune null[] = { L'<', L'n', L'u', L'l', L'l', L'>', L'\0' };
|
||||
|
||||
static int
|
||||
sconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
char *s;
|
||||
Rune *r;
|
||||
|
||||
if(fp->chr == 's') {
|
||||
s = va_arg(*arg, char*);
|
||||
if(s == 0)
|
||||
s = "<null>";
|
||||
strconv(s, fp);
|
||||
} else {
|
||||
r = va_arg(*arg, Rune*);
|
||||
if(r == 0)
|
||||
r = null;
|
||||
Strconv(r, fp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
percent(va_list *va, Fconv *fp)
|
||||
{
|
||||
USED(va);
|
||||
|
||||
pchar('%', fp);
|
||||
printcol++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
column(va_list *arg, Fconv *fp)
|
||||
{
|
||||
int col, pc;
|
||||
|
||||
col = va_arg(*arg, int);
|
||||
while(printcol < col) {
|
||||
pc = (printcol+8) & ~7;
|
||||
if(pc <= col) {
|
||||
pchar('\t', fp);
|
||||
printcol = pc;
|
||||
} else {
|
||||
pchar(' ', fp);
|
||||
printcol++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
flags(va_list *va, Fconv *fp)
|
||||
{
|
||||
int f;
|
||||
|
||||
USED(va);
|
||||
f = 0;
|
||||
switch(fp->chr) {
|
||||
case '+':
|
||||
f = FPLUS;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
f = FMINUS;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
f = FSHARP;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
f = FLONG;
|
||||
if(fp->f3 & FLONG)
|
||||
f = FVLONG;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
f = FUNSIGN;
|
||||
break;
|
||||
}
|
||||
return -f;
|
||||
}
|
||||
|
||||
/*
|
||||
* This code is superseded by the more accurate (but more complex)
|
||||
* algorithm in fltconv.c and dtoa.c. Uncomment this routine to avoid
|
||||
* using the more complex code.
|
||||
*
|
||||
*/
|
||||
|
123
fcall.h
Normal file
123
fcall.h
Normal file
@ -0,0 +1,123 @@
|
||||
#define VERSION9P "9P2000"
|
||||
#define MAXWELEM 16
|
||||
|
||||
typedef
|
||||
struct Fcall
|
||||
{
|
||||
uchar type;
|
||||
u32int fid;
|
||||
ushort tag;
|
||||
|
||||
u32int msize; /* Tversion, Rversion */
|
||||
char *version; /* Tversion, Rversion */
|
||||
|
||||
u32int oldtag; /* Tflush */
|
||||
|
||||
char *ename; /* Rerror */
|
||||
|
||||
Qid qid; /* Rattach, Ropen, Rcreate */
|
||||
u32int iounit; /* Ropen, Rcreate */
|
||||
|
||||
char *uname; /* Tattach, Tauth */
|
||||
char *aname; /* Tattach, Tauth */
|
||||
|
||||
|
||||
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 */
|
||||
|
||||
u32int afid; /* Tauth, Tattach */
|
||||
Qid aqid; /* Rauth */
|
||||
} 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) ((ulong)((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 MAXMSG 10000 /* max header sans data */
|
||||
#define NOTAG ~0U /* Dummy tag */
|
||||
#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);
|
||||
|
||||
int statcheck(uchar *abuf, uint nbuf);
|
||||
uint convM2D(uchar*, uint, Dir*, char*);
|
||||
uint convD2M(Dir*, uchar*, uint);
|
||||
uint sizeD2M(Dir*);
|
||||
|
||||
int fcallconv(va_list*, Fconv*);
|
||||
int dirconv(va_list*, Fconv*);
|
||||
int dirmodeconv(va_list*, Fconv*);
|
||||
|
||||
int read9pmsg(int, void*, uint);
|
||||
|
||||
enum {
|
||||
NOFID = 0xFFFFFFFF,
|
||||
};
|
228
fcallconv.c
Normal file
228
fcallconv.c
Normal file
@ -0,0 +1,228 @@
|
||||
#include <plan9.h>
|
||||
#include <fcall.h>
|
||||
#include <oldfcall.h>
|
||||
|
||||
extern int old9p;
|
||||
|
||||
static uint dumpsome(char*, char*, long);
|
||||
static void fdirconv(char*, Dir*);
|
||||
static char *qidtype(char*, uchar);
|
||||
|
||||
#define QIDFMT "(%.16llux %lud %s)"
|
||||
|
||||
int
|
||||
fcallconv(va_list *arg, Fconv *f1)
|
||||
{
|
||||
Fcall *f;
|
||||
int fid, type, tag, n, i;
|
||||
char buf[512], tmp[200];
|
||||
Dir *d;
|
||||
Qid *q;
|
||||
|
||||
f = va_arg(*arg, Fcall*);
|
||||
type = f->type;
|
||||
fid = f->fid;
|
||||
tag = f->tag;
|
||||
switch(type){
|
||||
case Tversion: /* 100 */
|
||||
sprint(buf, "Tversion tag %ud msize %ud version '%s'", tag, f->msize, f->version);
|
||||
break;
|
||||
case Rversion:
|
||||
sprint(buf, "Rversion tag %ud msize %ud version '%s'", tag, f->msize, f->version);
|
||||
break;
|
||||
case Tauth: /* 102 */
|
||||
sprint(buf, "Tauth tag %ud afid %d uname %s aname %s", tag,
|
||||
f->afid, f->uname, f->aname);
|
||||
break;
|
||||
case Rauth:
|
||||
sprint(buf, "Rauth tag %ud qid " QIDFMT, tag,
|
||||
f->aqid.path, f->aqid.vers, qidtype(tmp, f->aqid.type));
|
||||
break;
|
||||
case Tattach: /* 104 */
|
||||
sprint(buf, "Tattach tag %ud fid %d afid %d uname %s aname %s", tag,
|
||||
fid, f->afid, f->uname, f->aname);
|
||||
break;
|
||||
case Rattach:
|
||||
sprint(buf, "Rattach tag %ud qid " QIDFMT, tag,
|
||||
f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type));
|
||||
break;
|
||||
case Rerror: /* 107; 106 (Terror) illegal */
|
||||
sprint(buf, "Rerror tag %ud ename %s", tag, f->ename);
|
||||
break;
|
||||
case Tflush: /* 108 */
|
||||
sprint(buf, "Tflush tag %ud oldtag %ud", tag, f->oldtag);
|
||||
break;
|
||||
case Rflush:
|
||||
sprint(buf, "Rflush tag %ud", tag);
|
||||
break;
|
||||
case Twalk: /* 110 */
|
||||
n = sprint(buf, "Twalk tag %ud fid %d newfid %d nwname %d ", tag, fid, f->newfid, f->nwname);
|
||||
for(i=0; i<f->nwname; i++)
|
||||
n += sprint(buf+n, "%d:%s ", i, f->wname[i]);
|
||||
break;
|
||||
case Rwalk:
|
||||
n = sprint(buf, "Rwalk tag %ud nwqid %ud ", tag, f->nwqid);
|
||||
for(i=0; i<f->nwqid; i++){
|
||||
q = &f->wqid[i];
|
||||
n += sprint(buf+n, "%d:" QIDFMT " ", i,
|
||||
q->path, q->vers, qidtype(tmp, q->type));
|
||||
}
|
||||
break;
|
||||
case Topen: /* 112 */
|
||||
sprint(buf, "Topen tag %ud fid %ud mode %d", tag, fid, f->mode);
|
||||
break;
|
||||
case Ropen:
|
||||
sprint(buf, "Ropen tag %ud qid " QIDFMT " iounit %ud ", tag,
|
||||
f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit);
|
||||
break;
|
||||
case Tcreate: /* 114 */
|
||||
sprint(buf, "Tcreate tag %ud fid %ud perm %M mode %d", tag, fid, (ulong)f->perm, f->mode);
|
||||
break;
|
||||
case Rcreate:
|
||||
sprint(buf, "Rcreate tag %ud qid " QIDFMT " iounit %ud ", tag,
|
||||
f->qid.path, f->qid.vers, qidtype(tmp, f->qid.type), f->iounit);
|
||||
break;
|
||||
case Tread: /* 116 */
|
||||
sprint(buf, "Tread tag %ud fid %d offset %lld count %ud",
|
||||
tag, fid, f->offset, f->count);
|
||||
break;
|
||||
case Rread:
|
||||
n = sprint(buf, "Rread tag %ud count %ud ", tag, f->count);
|
||||
dumpsome(buf+n, f->data, f->count);
|
||||
break;
|
||||
case Twrite: /* 118 */
|
||||
n = sprint(buf, "Twrite tag %ud fid %d offset %lld count %ud ",
|
||||
tag, fid, f->offset, f->count);
|
||||
dumpsome(buf+n, f->data, f->count);
|
||||
break;
|
||||
case Rwrite:
|
||||
sprint(buf, "Rwrite tag %ud count %ud", tag, f->count);
|
||||
break;
|
||||
case Tclunk: /* 120 */
|
||||
sprint(buf, "Tclunk tag %ud fid %ud", tag, fid);
|
||||
break;
|
||||
case Rclunk:
|
||||
sprint(buf, "Rclunk tag %ud", tag);
|
||||
break;
|
||||
case Tremove: /* 122 */
|
||||
sprint(buf, "Tremove tag %ud fid %ud", tag, fid);
|
||||
break;
|
||||
case Rremove:
|
||||
sprint(buf, "Rremove tag %ud", tag);
|
||||
break;
|
||||
case Tstat: /* 124 */
|
||||
sprint(buf, "Tstat tag %ud fid %ud", tag, fid);
|
||||
break;
|
||||
case Rstat:
|
||||
n = sprint(buf, "Rstat tag %ud ", tag);
|
||||
if(f->nstat > sizeof tmp)
|
||||
sprint(buf+n, " stat(%d bytes)", f->nstat);
|
||||
else{
|
||||
d = (Dir*)tmp;
|
||||
(old9p?convM2Dold:convM2D)(f->stat, f->nstat, d, (char*)(d+1));
|
||||
sprint(buf+n, " stat ");
|
||||
fdirconv(buf+n+6, d);
|
||||
}
|
||||
break;
|
||||
case Twstat: /* 126 */
|
||||
n = sprint(buf, "Twstat tag %ud fid %ud", tag, fid);
|
||||
if(f->nstat > sizeof tmp)
|
||||
sprint(buf+n, " stat(%d bytes)", f->nstat);
|
||||
else{
|
||||
d = (Dir*)tmp;
|
||||
(old9p?convM2Dold:convM2D)(f->stat, f->nstat, d, (char*)(d+1));
|
||||
sprint(buf+n, " stat ");
|
||||
fdirconv(buf+n+6, d);
|
||||
}
|
||||
break;
|
||||
case Rwstat:
|
||||
sprint(buf, "Rwstat tag %ud", tag);
|
||||
break;
|
||||
default:
|
||||
sprint(buf, "unknown type %d", type);
|
||||
}
|
||||
strconv(buf, f1);
|
||||
return(sizeof(Fcall*));
|
||||
}
|
||||
|
||||
static char*
|
||||
qidtype(char *s, uchar t)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = s;
|
||||
if(t & QTDIR)
|
||||
*p++ = 'd';
|
||||
if(t & QTAPPEND)
|
||||
*p++ = 'a';
|
||||
if(t & QTEXCL)
|
||||
*p++ = 'l';
|
||||
if(t & QTMOUNT)
|
||||
*p++ = 'm';
|
||||
if(t & QTAUTH)
|
||||
*p++ = 'A';
|
||||
*p = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
int
|
||||
dirconv(va_list *arg, Fconv *f)
|
||||
{
|
||||
char buf[160];
|
||||
|
||||
fdirconv(buf, va_arg(*arg, Dir*));
|
||||
strconv(buf, f);
|
||||
return(sizeof(Dir*));
|
||||
}
|
||||
|
||||
static void
|
||||
fdirconv(char *buf, Dir *d)
|
||||
{
|
||||
char tmp[16];
|
||||
|
||||
sprint(buf, "'%s' '%s' '%s' '%s' "
|
||||
"q " QIDFMT " m %#luo "
|
||||
"at %ld mt %ld l %lld "
|
||||
"t %d d %d",
|
||||
d->name, d->uid, d->gid, d->muid,
|
||||
d->qid.path, d->qid.vers, qidtype(tmp, d->qid.type), d->mode,
|
||||
d->atime, d->mtime, d->length,
|
||||
d->type, d->dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* dump out count (or DUMPL, if count is bigger) bytes from
|
||||
* buf to ans, as a string if they are all printable,
|
||||
* else as a series of hex bytes
|
||||
*/
|
||||
#define DUMPL 64
|
||||
|
||||
static uint
|
||||
dumpsome(char *ans, char *buf, long count)
|
||||
{
|
||||
int i, printable;
|
||||
char *p;
|
||||
|
||||
printable = 1;
|
||||
if(count > DUMPL)
|
||||
count = DUMPL;
|
||||
for(i=0; i<count && printable; i++)
|
||||
if((buf[i]<32 && buf[i] !='\n' && buf[i] !='\t') || (uchar)buf[i]>127)
|
||||
printable = 0;
|
||||
p = ans;
|
||||
*p++ = '\'';
|
||||
if(printable){
|
||||
memmove(p, buf, count);
|
||||
p += count;
|
||||
}else{
|
||||
for(i=0; i<count; i++){
|
||||
if(i>0 && i%4==0)
|
||||
*p++ = ' ';
|
||||
sprint(p, "%2.2ux", (uchar)buf[i]);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
*p++ = '\'';
|
||||
*p = 0;
|
||||
return p - ans;
|
||||
}
|
63
makefile
Normal file
63
makefile
Normal file
@ -0,0 +1,63 @@
|
||||
#
|
||||
# The goal is to keep as much per-system stuff autodetected in plan9.h
|
||||
# as possible. Still, sometimes you can't help it. Look for your system.
|
||||
#
|
||||
|
||||
# SGI
|
||||
#
|
||||
# To correctly handle 64-bit files and offsets, add -64 to CFLAGS and LDFLAGS
|
||||
# On Irix 5.X, add -DIRIX5X to hack around their own #include problems (see plan9.h).
|
||||
#
|
||||
# SunOS
|
||||
#
|
||||
# SunOS 5.5.1 does not provide inttypes.h; add -lsunos to CFLAGS and
|
||||
# change CC and LD to gcc. Add -lsocket, -lnsl to LDTAIL.
|
||||
# If you need <inttypes.h> copy sun-inttypes.h to inttypes.h.
|
||||
#
|
||||
#CC=cc
|
||||
CFLAGS=-g -I.
|
||||
LD=cc
|
||||
LDFLAGS=
|
||||
LDTAIL=
|
||||
|
||||
OFILES=\
|
||||
authnone.o\
|
||||
authrhosts.o\
|
||||
authp9any.o\
|
||||
convD2M.o\
|
||||
convM2D.o\
|
||||
convM2S.o\
|
||||
convS2M.o\
|
||||
des.o\
|
||||
dirmodeconv.o\
|
||||
doprint.o\
|
||||
fcallconv.o\
|
||||
oldfcall.o\
|
||||
print.o\
|
||||
random.o\
|
||||
readn.o\
|
||||
remotehost.o\
|
||||
rune.o\
|
||||
safecpy.o\
|
||||
strecpy.o\
|
||||
tokenize.o\
|
||||
u9fs.o\
|
||||
utfrune.o
|
||||
|
||||
HFILES=\
|
||||
fcall.h\
|
||||
plan9.h
|
||||
|
||||
u9fs: $(OFILES)
|
||||
$(LD) $(LDFLAGS) -o u9fs $(OFILES) $(LDTAIL)
|
||||
|
||||
%.o: %.c $(HFILES)
|
||||
$(CC) $(CFLAGS) -c $*.c
|
||||
|
||||
clean:
|
||||
rm -f *.o u9fs
|
||||
|
||||
install: u9fs
|
||||
cp u9fs ../../bin
|
||||
|
||||
.PHONY: clean install
|
521
oldfcall.c
Normal file
521
oldfcall.c
Normal file
@ -0,0 +1,521 @@
|
||||
#include <plan9.h>
|
||||
#include <fcall.h>
|
||||
#include <oldfcall.h>
|
||||
|
||||
/*
|
||||
* routines to package the old protocol in the new structures.
|
||||
*/
|
||||
|
||||
#define SHORT(x) p[0]=f->x; p[1]=f->x>>8; p += 2
|
||||
#define LONG(x) p[0]=f->x; p[1]=f->x>>8; p[2]=f->x>>16; p[3]=f->x>>24; p += 4
|
||||
#define VLONG(x) p[0]=f->x; p[1]=f->x>>8;\
|
||||
p[2]=f->x>>16; p[3]=f->x>>24;\
|
||||
p[4]=f->x>>32; p[5]=f->x>>40;\
|
||||
p[6]=f->x>>48; p[7]=f->x>>56;\
|
||||
p += 8
|
||||
#define STRING(x,n) strecpy((char*)p, (char*)p+n, f->x); p += n;
|
||||
#define FIXQID(q) q.path ^= (q.path>>33); q.path &= 0x7FFFFFFF; q.path |= (q.type&0x80)<<24
|
||||
|
||||
uint
|
||||
oldhdrsize(uchar type)
|
||||
{
|
||||
switch(type){
|
||||
default:
|
||||
return 0;
|
||||
case oldTnop:
|
||||
return 3;
|
||||
case oldTflush:
|
||||
return 3+2;
|
||||
case oldTclone:
|
||||
return 3+2+2;
|
||||
case oldTwalk:
|
||||
return 3+2+28;
|
||||
case oldTopen:
|
||||
return 3+2+1;
|
||||
case oldTcreate:
|
||||
return 3+2+28+4+1;
|
||||
case oldTread:
|
||||
return 3+2+8+2;
|
||||
case oldTwrite:
|
||||
return 3+2+8+2+1;
|
||||
case oldTclunk:
|
||||
return 3+2;
|
||||
case oldTremove:
|
||||
return 3+2;
|
||||
case oldTstat:
|
||||
return 3+2;
|
||||
case oldTwstat:
|
||||
return 3+2+116;
|
||||
case oldTsession:
|
||||
return 3+8;
|
||||
case oldTattach:
|
||||
return 3+2+28+28+72+13;
|
||||
}
|
||||
}
|
||||
|
||||
uint
|
||||
iosize(uchar *p)
|
||||
{
|
||||
if(p[0] != oldTwrite)
|
||||
return 0;
|
||||
return p[3+2+8] | (p[3+2+8+1]<<8);
|
||||
}
|
||||
|
||||
uint
|
||||
sizeS2M(Fcall *f)
|
||||
{
|
||||
switch(f->type)
|
||||
{
|
||||
default:
|
||||
abort();
|
||||
return 0;
|
||||
|
||||
/* no T messages */
|
||||
|
||||
/*
|
||||
*/
|
||||
case Rversion:
|
||||
return 1+2;
|
||||
|
||||
/*
|
||||
case Rsession:
|
||||
return 1+2+8+28+48;
|
||||
*/
|
||||
|
||||
case Rattach:
|
||||
return 1+2+2+4+4+13;
|
||||
|
||||
case Rerror:
|
||||
return 1+2+64;
|
||||
|
||||
case Rflush:
|
||||
if(f->tag&0x8000)
|
||||
return 1+2+8+28+48; /* session */
|
||||
return 1+2;
|
||||
|
||||
/* assumes we don't ever see Tclwalk requests ... */
|
||||
case Rwalk:
|
||||
if(f->nwqid == 0)
|
||||
return 1+2+2;
|
||||
else
|
||||
return 1+2+2+4+4;
|
||||
|
||||
case Ropen:
|
||||
return 1+2+2+4+4;
|
||||
|
||||
case Rcreate:
|
||||
return 1+2+2+4+4;
|
||||
|
||||
case Rread:
|
||||
return 1+2+2+2+1+f->count;
|
||||
|
||||
case Rwrite:
|
||||
return 1+2+2+2;
|
||||
|
||||
case Rclunk:
|
||||
return 1+2+2;
|
||||
|
||||
case Rremove:
|
||||
return 1+2+2;
|
||||
|
||||
case Rstat:
|
||||
return 1+2+2+116;
|
||||
|
||||
case Rwstat:
|
||||
return 1+2+2;
|
||||
}
|
||||
}
|
||||
|
||||
uint
|
||||
convS2Mold(Fcall *f, uchar *ap, uint nap)
|
||||
{
|
||||
uchar *p;
|
||||
|
||||
if(nap < sizeS2M(f))
|
||||
return 0;
|
||||
|
||||
p = ap;
|
||||
switch(f->type)
|
||||
{
|
||||
default:
|
||||
abort();
|
||||
return 0;
|
||||
|
||||
/* no T messages */
|
||||
|
||||
/*
|
||||
*/
|
||||
case Rversion:
|
||||
*p++ = oldRnop;
|
||||
SHORT(tag);
|
||||
break;
|
||||
|
||||
/*
|
||||
case Rsession:
|
||||
*p++ = oldRsession;
|
||||
SHORT(tag);
|
||||
|
||||
if(f->nchal > 8)
|
||||
f->nchal = 8;
|
||||
memmove(p, f->chal, f->nchal);
|
||||
p += f->nchal;
|
||||
if(f->nchal < 8){
|
||||
memset(p, 0, 8 - f->nchal);
|
||||
p += 8 - f->nchal;
|
||||
}
|
||||
|
||||
STRING(authid, 28);
|
||||
STRING(authdom, 48);
|
||||
break;
|
||||
*/
|
||||
|
||||
case Rattach:
|
||||
*p++ = oldRattach;
|
||||
SHORT(tag);
|
||||
SHORT(fid);
|
||||
FIXQID(f->qid);
|
||||
LONG(qid.path);
|
||||
LONG(qid.vers);
|
||||
memset(p, 0, 13);
|
||||
p += 13;
|
||||
break;
|
||||
|
||||
case Rerror:
|
||||
*p++ = oldRerror;
|
||||
SHORT(tag);
|
||||
STRING(ename, 64);
|
||||
break;
|
||||
|
||||
case Rflush:
|
||||
if(f->tag&0x8000){
|
||||
*p++ = oldRsession;
|
||||
f->tag &= ~0x8000;
|
||||
SHORT(tag);
|
||||
memset(p, 0, 8+28+48);
|
||||
p += 8+28+48;
|
||||
}else{
|
||||
*p++ = oldRflush;
|
||||
SHORT(tag);
|
||||
}
|
||||
break;
|
||||
|
||||
/* assumes we don't ever see Tclwalk requests ... */
|
||||
case Rwalk:
|
||||
if(f->nwqid == 0){ /* successful clone */
|
||||
*p++ = oldRclone;
|
||||
SHORT(tag);
|
||||
SHORT(fid);
|
||||
}else{ /* successful 1-element walk */
|
||||
*p++ = oldRwalk;
|
||||
SHORT(tag);
|
||||
SHORT(fid);
|
||||
FIXQID(f->wqid[0]);
|
||||
LONG(wqid[0].path);
|
||||
LONG(wqid[0].vers);
|
||||
}
|
||||
break;
|
||||
|
||||
case Ropen:
|
||||
*p++ = oldRopen;
|
||||
SHORT(tag);
|
||||
SHORT(fid);
|
||||
FIXQID(f->qid);
|
||||
LONG(qid.path);
|
||||
LONG(qid.vers);
|
||||
break;
|
||||
|
||||
case Rcreate:
|
||||
*p++ = oldRcreate;
|
||||
SHORT(tag);
|
||||
SHORT(fid);
|
||||
FIXQID(f->qid);
|
||||
LONG(qid.path);
|
||||
LONG(qid.vers);
|
||||
break;
|
||||
|
||||
case Rread:
|
||||
*p++ = oldRread;
|
||||
SHORT(tag);
|
||||
SHORT(fid);
|
||||
SHORT(count);
|
||||
p++; /* pad(1) */
|
||||
memmove(p, f->data, f->count);
|
||||
p += f->count;
|
||||
break;
|
||||
|
||||
case Rwrite:
|
||||
*p++ = oldRwrite;
|
||||
SHORT(tag);
|
||||
SHORT(fid);
|
||||
SHORT(count);
|
||||
break;
|
||||
|
||||
case Rclunk:
|
||||
*p++ = oldRclunk;
|
||||
SHORT(tag);
|
||||
SHORT(fid);
|
||||
break;
|
||||
|
||||
case Rremove:
|
||||
*p++ = oldRremove;
|
||||
SHORT(tag);
|
||||
SHORT(fid);
|
||||
break;
|
||||
|
||||
case Rstat:
|
||||
*p++ = oldRstat;
|
||||
SHORT(tag);
|
||||
SHORT(fid);
|
||||
memmove(p, f->stat, 116);
|
||||
p += 116;
|
||||
break;
|
||||
|
||||
case Rwstat:
|
||||
*p++ = oldRwstat;
|
||||
SHORT(tag);
|
||||
SHORT(fid);
|
||||
break;
|
||||
}
|
||||
return p - ap;
|
||||
}
|
||||
|
||||
uint
|
||||
sizeD2Mold(Dir *d)
|
||||
{
|
||||
return 116;
|
||||
}
|
||||
|
||||
uint
|
||||
convD2Mold(Dir *f, uchar *ap, uint nap)
|
||||
{
|
||||
uchar *p;
|
||||
|
||||
if(nap < 116)
|
||||
return 0;
|
||||
|
||||
p = ap;
|
||||
STRING(name, 28);
|
||||
STRING(uid, 28);
|
||||
STRING(gid, 28);
|
||||
FIXQID(f->qid);
|
||||
LONG(qid.path);
|
||||
LONG(qid.vers);
|
||||
LONG(mode);
|
||||
LONG(atime);
|
||||
LONG(mtime);
|
||||
VLONG(length);
|
||||
SHORT(type);
|
||||
SHORT(dev);
|
||||
|
||||
return p - ap;
|
||||
}
|
||||
|
||||
#undef SHORT
|
||||
#undef LONG
|
||||
#undef VLONG
|
||||
#undef STRING
|
||||
#define CHAR(x) f->x = *p++
|
||||
#define SHORT(x) f->x = (p[0] | (p[1]<<8)); p += 2
|
||||
#define LONG(x) f->x = (p[0] | (p[1]<<8) |\
|
||||
(p[2]<<16) | (p[3]<<24)); p += 4
|
||||
#define VLONG(x) f->x = (ulong)(p[0] | (p[1]<<8) |\
|
||||
(p[2]<<16) | (p[3]<<24)) |\
|
||||
((vlong)(p[4] | (p[5]<<8) |\
|
||||
(p[6]<<16) | (p[7]<<24)) << 32); p += 8
|
||||
#define STRING(x,n) f->x = (char*)p; p += n
|
||||
|
||||
uint
|
||||
convM2Sold(uchar *ap, uint nap, Fcall *f)
|
||||
{
|
||||
uchar *p, *q, *ep;
|
||||
|
||||
p = ap;
|
||||
ep = p + nap;
|
||||
|
||||
if(p+3 > ep)
|
||||
return 0;
|
||||
|
||||
switch(*p++){
|
||||
case oldTnop:
|
||||
f->type = Tversion;
|
||||
SHORT(tag);
|
||||
f->msize = 0;
|
||||
f->version = "9P1";
|
||||
break;
|
||||
|
||||
case oldTflush:
|
||||
f->type = Tflush;
|
||||
SHORT(tag);
|
||||
if(p+2 > ep)
|
||||
return 0;
|
||||
SHORT(oldtag);
|
||||
break;
|
||||
|
||||
case oldTclone:
|
||||
f->type = Twalk;
|
||||
SHORT(tag);
|
||||
if(p+2+2 > ep)
|
||||
return 0;
|
||||
SHORT(fid);
|
||||
SHORT(newfid);
|
||||
f->nwname = 0;
|
||||
break;
|
||||
|
||||
case oldTwalk:
|
||||
f->type = Twalk;
|
||||
SHORT(tag);
|
||||
if(p+2+28 > ep)
|
||||
return 0;
|
||||
SHORT(fid);
|
||||
f->newfid = f->fid;
|
||||
f->nwname = 1;
|
||||
f->wname[0] = (char*)p;
|
||||
p += 28;
|
||||
break;
|
||||
|
||||
case oldTopen:
|
||||
f->type = Topen;
|
||||
SHORT(tag);
|
||||
if(p+2+1 > ep)
|
||||
return 0;
|
||||
SHORT(fid);
|
||||
CHAR(mode);
|
||||
break;
|
||||
|
||||
case oldTcreate:
|
||||
f->type = Tcreate;
|
||||
SHORT(tag);
|
||||
if(p+2+28+4+1 > ep)
|
||||
return 0;
|
||||
SHORT(fid);
|
||||
f->name = (char*)p;
|
||||
p += 28;
|
||||
LONG(perm);
|
||||
CHAR(mode);
|
||||
break;
|
||||
|
||||
case oldTread:
|
||||
f->type = Tread;
|
||||
SHORT(tag);
|
||||
if(p+2+8+2 > ep)
|
||||
return 0;
|
||||
SHORT(fid);
|
||||
VLONG(offset);
|
||||
SHORT(count);
|
||||
break;
|
||||
|
||||
case oldTwrite:
|
||||
f->type = Twrite;
|
||||
SHORT(tag);
|
||||
if(p+2+8+2+1 > ep)
|
||||
return 0;
|
||||
SHORT(fid);
|
||||
VLONG(offset);
|
||||
SHORT(count);
|
||||
p++; /* pad(1) */
|
||||
if(p+f->count > ep)
|
||||
return 0;
|
||||
f->data = (char*)p;
|
||||
p += f->count;
|
||||
break;
|
||||
|
||||
case oldTclunk:
|
||||
f->type = Tclunk;
|
||||
SHORT(tag);
|
||||
if(p+2 > ep)
|
||||
return 0;
|
||||
SHORT(fid);
|
||||
break;
|
||||
|
||||
case oldTremove:
|
||||
f->type = Tremove;
|
||||
SHORT(tag);
|
||||
if(p+2 > ep)
|
||||
return 0;
|
||||
SHORT(fid);
|
||||
break;
|
||||
|
||||
case oldTstat:
|
||||
f->type = Tstat;
|
||||
f->nstat = 116;
|
||||
SHORT(tag);
|
||||
if(p+2 > ep)
|
||||
return 0;
|
||||
SHORT(fid);
|
||||
break;
|
||||
|
||||
case oldTwstat:
|
||||
f->type = Twstat;
|
||||
SHORT(tag);
|
||||
if(p+2+116 > ep)
|
||||
return 0;
|
||||
SHORT(fid);
|
||||
f->stat = p;
|
||||
q = p+28*3+5*4;
|
||||
memset(q, 0xFF, 8); /* clear length to ``don't care'' */
|
||||
p += 116;
|
||||
break;
|
||||
|
||||
/*
|
||||
case oldTsession:
|
||||
f->type = Tsession;
|
||||
SHORT(tag);
|
||||
if(p+8 > ep)
|
||||
return 0;
|
||||
f->chal = p;
|
||||
p += 8;
|
||||
f->nchal = 8;
|
||||
break;
|
||||
*/
|
||||
case oldTsession:
|
||||
f->type = Tflush;
|
||||
SHORT(tag);
|
||||
f->tag |= 0x8000;
|
||||
f->oldtag = f->tag;
|
||||
p += 8;
|
||||
break;
|
||||
|
||||
case oldTattach:
|
||||
f->type = Tattach;
|
||||
SHORT(tag);
|
||||
if(p+2+28+28+72+13 > ep)
|
||||
return 0;
|
||||
SHORT(fid);
|
||||
STRING(uname, 28);
|
||||
STRING(aname, 28);
|
||||
p += 72+13;
|
||||
f->afid = NOFID;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return p-ap;
|
||||
}
|
||||
|
||||
uint
|
||||
convM2Dold(uchar *ap, uint nap, Dir *f, char *strs)
|
||||
{
|
||||
uchar *p;
|
||||
|
||||
USED(strs);
|
||||
|
||||
if(nap < 116)
|
||||
return 0;
|
||||
|
||||
p = (uchar*)ap;
|
||||
STRING(name, 28);
|
||||
STRING(uid, 28);
|
||||
STRING(gid, 28);
|
||||
LONG(qid.path);
|
||||
LONG(qid.vers);
|
||||
LONG(mode);
|
||||
LONG(atime);
|
||||
LONG(mtime);
|
||||
VLONG(length);
|
||||
SHORT(type);
|
||||
SHORT(dev);
|
||||
f->qid.type = (f->mode>>24)&0xF0;
|
||||
return p - (uchar*)ap;
|
||||
}
|
50
oldfcall.h
Normal file
50
oldfcall.h
Normal file
@ -0,0 +1,50 @@
|
||||
uint convM2Dold(uchar*, uint, Dir*, char*);
|
||||
uint convD2Mold(Dir*, uchar*, uint);
|
||||
uint sizeD2Mold(Dir*);
|
||||
uint convM2Sold(uchar*, uint, Fcall*);
|
||||
uint convS2Mold(Fcall*, uchar*, uint);
|
||||
uint oldhdrsize(uchar);
|
||||
uint iosize(uchar*);
|
||||
|
||||
enum
|
||||
{
|
||||
oldTnop = 50,
|
||||
oldRnop,
|
||||
oldTosession = 52, /* illegal */
|
||||
oldRosession, /* illegal */
|
||||
oldTerror = 54, /* illegal */
|
||||
oldRerror,
|
||||
oldTflush = 56,
|
||||
oldRflush,
|
||||
oldToattach = 58, /* illegal */
|
||||
oldRoattach, /* illegal */
|
||||
oldTclone = 60,
|
||||
oldRclone,
|
||||
oldTwalk = 62,
|
||||
oldRwalk,
|
||||
oldTopen = 64,
|
||||
oldRopen,
|
||||
oldTcreate = 66,
|
||||
oldRcreate,
|
||||
oldTread = 68,
|
||||
oldRread,
|
||||
oldTwrite = 70,
|
||||
oldRwrite,
|
||||
oldTclunk = 72,
|
||||
oldRclunk,
|
||||
oldTremove = 74,
|
||||
oldRremove,
|
||||
oldTstat = 76,
|
||||
oldRstat,
|
||||
oldTwstat = 78,
|
||||
oldRwstat,
|
||||
oldTclwalk = 80,
|
||||
oldRclwalk,
|
||||
oldTauth = 82, /* illegal */
|
||||
oldRauth, /* illegal */
|
||||
oldTsession = 84,
|
||||
oldRsession,
|
||||
oldTattach = 86,
|
||||
oldRattach,
|
||||
oldTmax
|
||||
};
|
198
plan9.h
Normal file
198
plan9.h
Normal file
@ -0,0 +1,198 @@
|
||||
/* magic to get SUSV2 standard, including pread, pwrite*/
|
||||
#define _XOPEN_SOURCE 500
|
||||
/* magic to get 64-bit pread/pwrite */
|
||||
#define _LARGEFILE64_SOURCE
|
||||
/* magic to get 64-bit stat on Linux, maybe others */
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#ifdef sgi
|
||||
#define _BSD_TYPES 1 /* for struct timeval */
|
||||
#include <sys/select.h>
|
||||
#define _BSD_SOURCE 1 /* for ruserok */
|
||||
/*
|
||||
* SGI IRIX 5.x doesn't allow inclusion of both inttypes.h and
|
||||
* sys/types.h. These definitions are the ones we need from
|
||||
* inttypes.h that aren't in sys/types.h.
|
||||
*
|
||||
* Unlike most of our #ifdef's, IRIX5X must be set in the makefile.
|
||||
*/
|
||||
#ifdef IRIX5X
|
||||
#define __inttypes_INCLUDED
|
||||
typedef unsigned int uint32_t;
|
||||
typedef signed long long int int64_t;
|
||||
typedef unsigned long long int uint64_t;
|
||||
#endif /* IRIX5X */
|
||||
#endif /* sgi */
|
||||
|
||||
|
||||
#ifdef sun /* sparc and __svr4__ are also defined on the offending machine */
|
||||
#define __EXTENSIONS__ 1 /* for struct timeval */
|
||||
#endif
|
||||
|
||||
#include <inttypes.h> /* for int64_t et al. */
|
||||
#include <stdarg.h> /* for va_list, vararg macros */
|
||||
#ifndef va_copy
|
||||
#ifdef __va_copy
|
||||
#define va_copy __va_copy
|
||||
#else
|
||||
#define va_copy(d, s) memmove(&(d), &(s), sizeof(va_list))
|
||||
#endif /* __va_copy */
|
||||
#endif /* va_copy */
|
||||
#include <sys/types.h>
|
||||
#include <string.h> /* for memmove */
|
||||
#include <unistd.h> /* for write */
|
||||
|
||||
#define ulong p9ulong /* because sys/types.h has some of these sometimes */
|
||||
#define ushort p9ushort
|
||||
#define uchar p9uchar
|
||||
#define uint p9uint
|
||||
#define vlong p9vlong
|
||||
#define uvlong p9uvlong
|
||||
#define u32int p9u32int
|
||||
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned int uint;
|
||||
typedef int64_t vlong;
|
||||
typedef uint64_t uvlong;
|
||||
typedef uint32_t u32int;
|
||||
typedef uint64_t u64int;
|
||||
typedef ushort Rune;
|
||||
|
||||
#define nil ((void*)0)
|
||||
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
|
||||
#ifndef offsetof
|
||||
#define offsetof(s, m) (ulong)(&(((s*)0)->m))
|
||||
#endif
|
||||
#define assert(x) if(x);else _assert("x")
|
||||
|
||||
extern char *argv0;
|
||||
#define ARGBEGIN for((void)(argv0||(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 EARGF(x) (_argt=_args, _args="",\
|
||||
(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))
|
||||
|
||||
#define ARGC() _argc
|
||||
|
||||
#define SET(x) (x) = 0
|
||||
#define USED(x) (void)(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 */
|
||||
};
|
||||
|
||||
extern int runetochar(char*, Rune*);
|
||||
extern int chartorune(Rune*, char*);
|
||||
extern int runelen(long);
|
||||
extern int utflen(char*);
|
||||
extern char* strecpy(char*, char*, char*);
|
||||
extern int tokenize(char*, char**, int);
|
||||
extern int getfields(char*, char**, int, int, char*);
|
||||
|
||||
/*
|
||||
* print routines
|
||||
*/
|
||||
typedef struct Fconv Fconv;
|
||||
struct Fconv
|
||||
{
|
||||
char* out; /* pointer to next output */
|
||||
char* eout; /* pointer to end */
|
||||
int f1;
|
||||
int f2;
|
||||
int f3;
|
||||
int chr;
|
||||
};
|
||||
extern char* doprint(char*, char*, char*, va_list *argp);
|
||||
extern int print(char*, ...);
|
||||
extern char* seprint(char*, char*, char*, ...);
|
||||
extern int snprint(char*, int, char*, ...);
|
||||
extern int sprint(char*, char*, ...);
|
||||
extern int fprint(int, char*, ...);
|
||||
|
||||
extern int fmtinstall(int, int (*)(va_list*, Fconv*));
|
||||
extern int numbconv(va_list*, Fconv*);
|
||||
extern void strconv(char*, Fconv*);
|
||||
extern int fltconv(va_list*, Fconv*);
|
||||
|
||||
#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 use */
|
||||
|
||||
/* 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
|
||||
#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 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 Qid
|
||||
{
|
||||
vlong 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: see <u.h> */
|
||||
char *name; /* last element of path */
|
||||
char *uid; /* owner name */
|
||||
char *gid; /* group name */
|
||||
char *muid; /* last modifier name */
|
||||
} Dir;
|
||||
|
||||
long readn(int, void*, long);
|
||||
void remotehost(char*, int);
|
||||
|
||||
enum {
|
||||
NAMELEN = 28,
|
||||
ERRLEN = 64
|
||||
};
|
||||
|
||||
/* DES */
|
||||
#define DESKEYLEN 7
|
||||
void key_setup(char key[DESKEYLEN], char expandedkey[128]);
|
||||
void block_cipher(char expandedkey[128], char buf[8], int decrypting);
|
87
print.c
Normal file
87
print.c
Normal file
@ -0,0 +1,87 @@
|
||||
#include <plan9.h>
|
||||
|
||||
#define SIZE 4096
|
||||
extern int printcol;
|
||||
|
||||
int
|
||||
print(char *fmt, ...)
|
||||
{
|
||||
char buf[SIZE], *out;
|
||||
va_list arg, temp;
|
||||
int n;
|
||||
|
||||
va_start(arg, fmt);
|
||||
va_copy(temp, arg);
|
||||
out = doprint(buf, buf+SIZE, fmt, &temp);
|
||||
va_end(temp);
|
||||
va_end(arg);
|
||||
n = write(1, buf, (long)(out-buf));
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
fprint(int f, char *fmt, ...)
|
||||
{
|
||||
char buf[SIZE], *out;
|
||||
va_list arg, temp;
|
||||
int n;
|
||||
|
||||
va_start(arg, fmt);
|
||||
va_copy(temp, arg);
|
||||
out = doprint(buf, buf+SIZE, fmt, &temp);
|
||||
va_end(temp);
|
||||
va_end(arg);
|
||||
n = write(f, buf, (long)(out-buf));
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
sprint(char *buf, char *fmt, ...)
|
||||
{
|
||||
char *out;
|
||||
va_list arg, temp;
|
||||
int scol;
|
||||
|
||||
scol = printcol;
|
||||
va_start(arg, fmt);
|
||||
va_copy(temp, arg);
|
||||
out = doprint(buf, buf+SIZE, fmt, &temp);
|
||||
va_end(temp);
|
||||
va_end(arg);
|
||||
printcol = scol;
|
||||
return out-buf;
|
||||
}
|
||||
|
||||
int
|
||||
snprint(char *buf, int len, char *fmt, ...)
|
||||
{
|
||||
char *out;
|
||||
va_list arg, temp;
|
||||
int scol;
|
||||
|
||||
scol = printcol;
|
||||
va_start(arg, fmt);
|
||||
va_copy(temp, arg);
|
||||
out = doprint(buf, buf+len, fmt, &temp);
|
||||
va_end(temp);
|
||||
va_end(arg);
|
||||
printcol = scol;
|
||||
return out-buf;
|
||||
}
|
||||
|
||||
char*
|
||||
seprint(char *buf, char *e, char *fmt, ...)
|
||||
{
|
||||
char *out;
|
||||
va_list arg, temp;
|
||||
int scol;
|
||||
|
||||
scol = printcol;
|
||||
va_start(arg, fmt);
|
||||
va_copy(temp, arg);
|
||||
out = doprint(buf, e, fmt, &temp);
|
||||
va_end(temp);
|
||||
va_end(arg);
|
||||
printcol = scol;
|
||||
return out;
|
||||
}
|
58
random.c
Normal file
58
random.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include <plan9.h>
|
||||
#include <fcall.h>
|
||||
#include <u9fs.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static long
|
||||
getseed(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
long seed;
|
||||
int fd, len;
|
||||
|
||||
len = 0;
|
||||
fd = open("/dev/urandom", O_RDONLY);
|
||||
if(fd > 0){
|
||||
len = readn(fd, &seed, sizeof(seed));
|
||||
close(fd);
|
||||
}
|
||||
if(len != sizeof(seed)){
|
||||
gettimeofday(&tv, nil);
|
||||
seed = tv.tv_sec ^ tv.tv_usec ^ (getpid()<<8);
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
|
||||
static int seeded;
|
||||
|
||||
void
|
||||
randombytes(uchar *r, uint nr)
|
||||
{
|
||||
int i;
|
||||
ulong l;
|
||||
|
||||
if(!seeded){
|
||||
seeded=1;
|
||||
srand48(getseed());
|
||||
}
|
||||
for(i=0; i+4<=nr; i+=4,r+=4){
|
||||
l = (ulong)mrand48();
|
||||
r[0] = l;
|
||||
r[1] = l>>8;
|
||||
r[2] = l>>16;
|
||||
r[3] = l>>24;
|
||||
}
|
||||
if(i<nr){
|
||||
l = (ulong)mrand48();
|
||||
switch(nr-i){
|
||||
case 3:
|
||||
r[2] = l>>16;
|
||||
case 2:
|
||||
r[1] = l>>8;
|
||||
case 1:
|
||||
r[0] = l;
|
||||
}
|
||||
}
|
||||
}
|
21
readn.c
Normal file
21
readn.c
Normal file
@ -0,0 +1,21 @@
|
||||
#include <plan9.h>
|
||||
|
||||
long
|
||||
readn(int f, void *av, long n)
|
||||
{
|
||||
char *a;
|
||||
long m, t;
|
||||
|
||||
a = av;
|
||||
t = 0;
|
||||
while(t < n){
|
||||
m = read(f, a+t, n-t);
|
||||
if(m <= 0){
|
||||
if(t == 0)
|
||||
return m;
|
||||
break;
|
||||
}
|
||||
t += m;
|
||||
}
|
||||
return t;
|
||||
}
|
32
remotehost.c
Normal file
32
remotehost.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h> /* various networking crud */
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netdb.h>
|
||||
#include <plan9.h>
|
||||
|
||||
void
|
||||
getremotehostname(char *name, int nname)
|
||||
{
|
||||
struct sockaddr_in sock;
|
||||
struct hostent *hp;
|
||||
uint len;
|
||||
int on;
|
||||
|
||||
strecpy(name, name+nname, "unknown");
|
||||
len = sizeof sock;
|
||||
if(getpeername(0, (struct sockaddr*)&sock, (void*)&len) < 0)
|
||||
return;
|
||||
|
||||
hp = gethostbyaddr((char *)&sock.sin_addr, sizeof (struct in_addr),
|
||||
sock.sin_family);
|
||||
if(hp == 0)
|
||||
return;
|
||||
|
||||
strecpy(name, name+nname, hp->h_name);
|
||||
on = 1;
|
||||
setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char*)&on, sizeof(on));
|
||||
|
||||
on = 1;
|
||||
setsockopt(0, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
|
||||
}
|
148
rune.c
Normal file
148
rune.c
Normal file
@ -0,0 +1,148 @@
|
||||
#include <plan9.h>
|
||||
|
||||
char *argv0;
|
||||
enum
|
||||
{
|
||||
Bit1 = 7,
|
||||
Bitx = 6,
|
||||
Bit2 = 5,
|
||||
Bit3 = 4,
|
||||
Bit4 = 3,
|
||||
|
||||
T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */
|
||||
Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */
|
||||
T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */
|
||||
T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */
|
||||
T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */
|
||||
|
||||
Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */
|
||||
Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */
|
||||
Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */
|
||||
|
||||
Maskx = (1<<Bitx)-1, /* 0011 1111 */
|
||||
Testx = Maskx ^ 0xFF, /* 1100 0000 */
|
||||
|
||||
Bad = Runeerror
|
||||
};
|
||||
|
||||
int
|
||||
chartorune(Rune *rune, char *str)
|
||||
{
|
||||
int c, c1, c2;
|
||||
long l;
|
||||
|
||||
/*
|
||||
* one character sequence
|
||||
* 00000-0007F => T1
|
||||
*/
|
||||
c = *(uchar*)str;
|
||||
if(c < Tx) {
|
||||
*rune = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* two character sequence
|
||||
* 0080-07FF => T2 Tx
|
||||
*/
|
||||
c1 = *(uchar*)(str+1) ^ Tx;
|
||||
if(c1 & Testx)
|
||||
goto bad;
|
||||
if(c < T3) {
|
||||
if(c < T2)
|
||||
goto bad;
|
||||
l = ((c << Bitx) | c1) & Rune2;
|
||||
if(l <= Rune1)
|
||||
goto bad;
|
||||
*rune = l;
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* three character sequence
|
||||
* 0800-FFFF => T3 Tx Tx
|
||||
*/
|
||||
c2 = *(uchar*)(str+2) ^ Tx;
|
||||
if(c2 & Testx)
|
||||
goto bad;
|
||||
if(c < T4) {
|
||||
l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3;
|
||||
if(l <= Rune2)
|
||||
goto bad;
|
||||
*rune = l;
|
||||
return 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* bad decoding
|
||||
*/
|
||||
bad:
|
||||
*rune = Bad;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
runetochar(char *str, Rune *rune)
|
||||
{
|
||||
long c;
|
||||
|
||||
/*
|
||||
* one character sequence
|
||||
* 00000-0007F => 00-7F
|
||||
*/
|
||||
c = *rune;
|
||||
if(c <= Rune1) {
|
||||
str[0] = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* two character sequence
|
||||
* 0080-07FF => T2 Tx
|
||||
*/
|
||||
if(c <= Rune2) {
|
||||
str[0] = T2 | (c >> 1*Bitx);
|
||||
str[1] = Tx | (c & Maskx);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* three character sequence
|
||||
* 0800-FFFF => T3 Tx Tx
|
||||
*/
|
||||
str[0] = T3 | (c >> 2*Bitx);
|
||||
str[1] = Tx | ((c >> 1*Bitx) & Maskx);
|
||||
str[2] = Tx | (c & Maskx);
|
||||
return 3;
|
||||
}
|
||||
|
||||
int
|
||||
runelen(long c)
|
||||
{
|
||||
Rune rune;
|
||||
char str[10];
|
||||
|
||||
rune = c;
|
||||
return runetochar(str, &rune);
|
||||
}
|
||||
|
||||
int
|
||||
utflen(char *s)
|
||||
{
|
||||
int c;
|
||||
long n;
|
||||
Rune rune;
|
||||
|
||||
n = 0;
|
||||
for(;;) {
|
||||
c = *(uchar*)s;
|
||||
if(c < Runeself) {
|
||||
if(c == 0)
|
||||
return n;
|
||||
s++;
|
||||
} else
|
||||
s += chartorune(&rune, s);
|
||||
n++;
|
||||
}
|
||||
return 0;
|
||||
}
|
12
safecpy.c
Normal file
12
safecpy.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
safecpy(char *to, char *from, int tolen)
|
||||
{
|
||||
int fromlen;
|
||||
memset(to, 0, tolen);
|
||||
fromlen = from ? strlen(from) : 0;
|
||||
if (fromlen > tolen)
|
||||
fromlen = tolen;
|
||||
memcpy(to, from, fromlen);
|
||||
}
|
14
strecpy.c
Normal file
14
strecpy.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include <plan9.h>
|
||||
|
||||
char*
|
||||
strecpy(char *to, char *e, char *from)
|
||||
{
|
||||
if(to >= e)
|
||||
return to;
|
||||
to = memccpy(to, from, '\0', e - to);
|
||||
if(to == nil){
|
||||
to = e - 1;
|
||||
*to = '\0';
|
||||
}
|
||||
return to;
|
||||
}
|
16
sun-inttypes.h
Normal file
16
sun-inttypes.h
Normal file
@ -0,0 +1,16 @@
|
||||
/* inttypes.h for SunOS cuff.link.cs.cmu.edu 5.5.1 Generic_103640-29 sun4u sparc SUNW,Ultra-Enterprise */
|
||||
#ifndef INTTYPES_H
|
||||
#define INTTYPES_H
|
||||
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef int int32_t;
|
||||
typedef long long int64_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
typedef long int intptr_t;
|
||||
typedef unsigned long int uintptr_t;
|
||||
|
||||
#endif
|
42
tokenize.c
Normal file
42
tokenize.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include <plan9.h>
|
||||
|
||||
int
|
||||
getfields(char *str, char **args, int max, int mflag, char *set)
|
||||
{
|
||||
Rune r;
|
||||
int nr, intok, narg;
|
||||
|
||||
if(max <= 0)
|
||||
return 0;
|
||||
|
||||
narg = 0;
|
||||
args[narg] = str;
|
||||
if(!mflag)
|
||||
narg++;
|
||||
intok = 0;
|
||||
for(;; str += nr) {
|
||||
nr = chartorune(&r, str);
|
||||
if(r == 0)
|
||||
break;
|
||||
if(utfrune(set, r)) {
|
||||
if(narg >= max)
|
||||
break;
|
||||
*str = 0;
|
||||
intok = 0;
|
||||
args[narg] = str + nr;
|
||||
if(!mflag)
|
||||
narg++;
|
||||
} else {
|
||||
if(!intok && mflag)
|
||||
narg++;
|
||||
intok = 1;
|
||||
}
|
||||
}
|
||||
return narg;
|
||||
}
|
||||
|
||||
int
|
||||
tokenize(char *str, char **args, int max)
|
||||
{
|
||||
return getfields(str, args, max, 1, " \t\n\r");
|
||||
}
|
30
u9fs.h
Normal file
30
u9fs.h
Normal file
@ -0,0 +1,30 @@
|
||||
typedef struct Auth Auth;
|
||||
struct Auth {
|
||||
char *name;
|
||||
|
||||
char* (*auth)(Fcall*, Fcall*);
|
||||
char* (*attach)(Fcall*, Fcall*);
|
||||
void (*init)(void);
|
||||
char* (*read)(Fcall*, Fcall*);
|
||||
char* (*write)(Fcall*, Fcall*);
|
||||
char* (*clunk)(Fcall*, Fcall*);
|
||||
};
|
||||
|
||||
extern char remotehostname[];
|
||||
extern char Eauth[];
|
||||
extern char *autharg;
|
||||
|
||||
extern Auth authp9any;
|
||||
extern Auth authrhosts;
|
||||
extern Auth authnone;
|
||||
|
||||
extern ulong truerand(void);
|
||||
extern void randombytes(uchar*, uint);
|
||||
|
||||
extern ulong msize;
|
||||
|
||||
typedef struct Fid Fid;
|
||||
Fid *newauthfid(int fid, void *magic, char **ep);
|
||||
Fid *oldauthfid(int fid, void **magic, char **ep);
|
||||
|
||||
void safecpy(char *to, char *from, int len);
|
7
u9fsauth.h
Normal file
7
u9fsauth.h
Normal file
@ -0,0 +1,7 @@
|
||||
typedef struct Auth Auth;
|
||||
struct Auth {
|
||||
char *name;
|
||||
|
||||
char *(*session)(Fcall*, Fcall*);
|
||||
char *(*attach)(Fcall*, Fcall*);
|
||||
};
|
29
utfrune.c
Normal file
29
utfrune.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <plan9.h>
|
||||
|
||||
char*
|
||||
utfrune(char *s, long c)
|
||||
{
|
||||
long c1;
|
||||
Rune r;
|
||||
int n;
|
||||
|
||||
if(c < Runesync) /* not part of utf sequence */
|
||||
return strchr(s, c);
|
||||
|
||||
for(;;) {
|
||||
c1 = *(uchar*)s;
|
||||
if(c1 < Runeself) { /* one byte rune */
|
||||
if(c1 == 0)
|
||||
return 0;
|
||||
if(c1 == c)
|
||||
return s;
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
n = chartorune(&r, s);
|
||||
if(r == c)
|
||||
return s;
|
||||
s += n;
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user