Various additions and fixes.

This commit is contained in:
rsc 2003-11-23 18:12:54 +00:00
parent 74f990ad84
commit fd04aacee1
57 changed files with 2176 additions and 159 deletions

23
src/lib9/9proc.h Normal file
View file

@ -0,0 +1,23 @@
enum
{
NPRIV = 16,
RENDHASH = 33,
PIDHASH = 33,
};
typedef struct Uproc Uproc;
struct Uproc
{
Uproc *next;
int pid;
int pipe[2];
int state;
void *priv[NPRIV];
ulong rendval;
ulong rendtag;
Uproc *rendhash;
p9jmp_buf notejb;
};
extern Uproc *_p9uproc(void);
extern void _p9uprocdie(void);

View file

@ -1,38 +0,0 @@
PLAN9=../..
include $(PLAN9)/src/Makehdr
LIB=lib9.a
OFILES=\
_exits.$O\
argv0.$O\
await.$O\
cleanname.$O\
dirstat.$O\
encodefmt.$O\
errstr.$O\
exits.$O\
ffork-$(SYSNAME).$O\
getcallerpc-$(OBJTYPE).$O\
getfields.$O\
lock.$O\
malloctag.$O\
mallocz.$O\
nrand.$O\
qlock.$O\
readn.$O\
rendez-$(SYSNAME).$O\
strecpy.$O\
sysfatal.$O\
tas-$(OBJTYPE).$O\
tokenize.$O\
u16.$O\
u32.$O\
u64.$O\
wait.$O\
HFILES=\
$(PLAN9)/include/lib9.h\
include $(PLAN9)/src/Makesyslib

View file

@ -1,8 +1,12 @@
#include <lib9.h>
#include <u.h>
#include <libc.h>
#include "9proc.h"
void
_exits(char *s)
{
_p9uprocdie();
if(s && *s)
_exit(1);
_exit(0);

151
src/lib9/_p9dialparse.c Normal file
View file

@ -0,0 +1,151 @@
#include <u.h>
#include <libc.h>
#include <netdb.h>
#include <sys/un.h>
static char *nets[] = { "tcp", "udp", nil };
#define CLASS(p) ((*(uchar*)(p))>>6)
static int
parseip(char *host, u32int *pip)
{
uchar addr[4];
int x, i;
char *p;
p = host;
for(i=0; i<4 && *p; i++){
x = strtoul(p, &p, 0);
if(x < 0 || x >= 256)
return -1;
if(*p != '.' && *p != 0)
return -1;
if(*p == '.')
p++;
addr[i] = x;
}
switch(CLASS(addr)){
case 0:
case 1:
if(i == 3){
addr[3] = addr[2];
addr[2] = addr[1];
addr[1] = 0;
}else if(i == 2){
addr[3] = addr[1];
addr[2] = 0;
addr[1] = 0;
}else if(i != 4)
return -1;
break;
case 2:
if(i == 3){
addr[3] = addr[2];
addr[2] = 0;
}else if(i != 4)
return -1;
break;
}
*pip = *(u32int*)addr;
return 0;
}
int
_p9dialparse(char *addr, char **pnet, char **punix, u32int *phost, int *pport)
{
char *net, *host, *port, *e;
int i;
struct servent *se;
struct hostent *he;
struct sockaddr_un *sun;
if(strncmp(addr, "/net/", 5) == 0)
addr += 5;
net = addr;
if((host = strchr(net, '!')) == nil){
werrstr("malformed address");
return -1;
}
*host++ = 0;
if((port = strchr(host, '!')) == nil){
if(strcmp(net, "unix")==0 || strcmp(net, "net")==0){
Unix:
if(strlen(host)+1 > sizeof sun->sun_path){
werrstr("unix socket name too long");
return -1;
}
*punix = host;
*pnet = "unix";
*phost = 0;
*pport = 0;
return 0;
}
werrstr("malformed address");
return -1;
}
*port++ = 0;
if(*host == 0){
werrstr("malformed address (empty host)");
return -1;
}
if(*port == 0){
werrstr("malformed address (empty port)");
return -1;
}
if(strcmp(net, "unix") == 0)
goto Unix;
if(strcmp(net, "tcp")!=0 && strcmp(net, "udp")!=0){
werrstr("bad network %s!%s!%s", net, host, port);
return -1;
}
/* translate host */
if(strcmp(host, "*") == 0)
*phost = 0;
else if(parseip(host, phost) == 0)
{}
else if((he = gethostbyname(host)) != nil)
*phost = *(u32int*)(he->h_addr);
else{
werrstr("unknown host %s", host);
return -1;
}
/* translate network and port; should return list rather than first */
if(strcmp(net, "net") == 0){
for(i=0; nets[i]; i++){
if((se = getservbyname(port, nets[i])) != nil){
*pnet = nets[i];
*pport = ntohs(se->s_port);
return 0;
}
}
werrstr("unknown service %s", port);
return -1;
}
if(strcmp(net, "tcp") != 0 && strcmp(net, "udp") != 0){
werrstr("unknown network %s", net);
return -1;
}
*pnet = net;
i = strtol(port, &e, 0);
if(*e == 0){
*pport = i;
return 0;
}
if((se = getservbyname(port, net)) != nil){
*pport = ntohs(se->s_port);
return 0;
}
werrstr("unknown service %s", port);
return -1;
}

121
src/lib9/_p9dir.c Normal file
View file

@ -0,0 +1,121 @@
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include <sys/stat.h>
#include <sys/disklabel.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
int
_p9dir(struct stat *st, char *name, Dir *d, char **str, char *estr)
{
char *s;
char tmp[20];
struct group *g;
struct passwd *p;
int sz;
sz = 0;
if(d)
memset(d, 0, sizeof *d);
/* name */
s = strrchr(name, '/');
if(s)
s++;
if(!s || !*s)
s = name;
if(*s == '/')
s++;
if(*s == 0)
s = "/";
if(d){
if(*str + strlen(s)+1 > estr)
d->name = "oops";
else{
strcpy(*str, s);
d->name = *str;
*str += strlen(*str)+1;
}
}
sz += strlen(s)+1;
/* user */
p = getpwuid(st->st_uid);
if(p == nil){
snprint(tmp, sizeof tmp, "%d", (int)st->st_uid);
s = tmp;
}else
s = p->pw_name;
sz += strlen(s)+1;
if(d){
if(*str+strlen(s)+1 > estr)
d->uid = "oops";
else{
strcpy(*str, s);
d->uid = *str;
*str += strlen(*str)+1;
}
}
/* group */
g = getgrgid(st->st_gid);
if(g == nil){
snprint(tmp, sizeof tmp, "%d", (int)st->st_gid);
s = tmp;
}else
s = g->gr_name;
sz += strlen(s)+1;
if(d){
if(*str + strlen(s)+1 > estr)
d->gid = "oops";
else{
strcpy(*str, s);
d->gid = *str;
*str += strlen(*str)+1;
}
}
if(d){
d->type = 'M';
d->muid = "";
d->qid.path = ((uvlong)st->st_dev<<32) | st->st_ino;
d->qid.vers = st->st_gen;
d->mode = st->st_mode&0777;
d->atime = st->st_atime;
d->mtime = st->st_mtime;
d->length = st->st_size;
if(S_ISDIR(st->st_mode)){
d->length = 0;
d->mode |= DMDIR;
d->qid.type = QTDIR;
}
/* fetch real size for disks */
if(S_ISCHR(st->st_mode)){
int fd, n;
struct disklabel lab;
if((fd = open(name, O_RDONLY)) < 0)
goto nosize;
if(ioctl(fd, DIOCGDINFO, &lab) < 0)
goto nosize;
n = minor(st->st_rdev)&7;
if(n >= lab.d_npartitions)
goto nosize;
d->length = (vlong)(lab.d_partitions[n].p_size) * lab.d_secsize;
nosize:
if(fd >= 0)
close(fd);
}
}
return sz;
}

73
src/lib9/_p9proc.c Normal file
View file

@ -0,0 +1,73 @@
#include <u.h>
#include <libc.h>
#include "9proc.h"
static Lock uproclock;
static Uproc *phash[PIDHASH];
Uproc*
_p9uproc(void)
{
/* for now, assume getpid is fast or cached */
int pid;
Uproc *up;
pid = getpid();
again:
if(0)print("find %d\n", pid);
lock(&uproclock);
for(up=phash[pid%PIDHASH]; up; up=up->next){
if(up->pid == pid){
if(0)print("found %d\n", pid);
unlock(&uproclock);
return up;
}
}
up = mallocz(sizeof(Uproc), 1);
if(up == nil){
if(0)print("again %d\n", pid);
unlock(&uproclock);
sleep(1000);
goto again;
}
againpipe:
if(pipe(up->pipe) < 0){
if(0)print("againpipe %d\n", pid);
sleep(1000);
goto againpipe;
}
up->pid = pid;
up->next = phash[pid%PIDHASH];
phash[pid%PIDHASH] = up;
if(0)print("link %d\n", pid);
unlock(&uproclock);
return up;
}
void
_p9uprocdie(void)
{
Uproc **l, *up;
int pid;
pid = getpid();
if(0)print("die %d\n", pid);
lock(&uproclock);
for(l=&phash[pid%33]; *l; l=&(*l)->next){
if((*l)->pid == pid){
up = *l;
*l = up->next;
if(0)print("died %d\n", pid);
unlock(&uproclock);
close(up->pipe[0]);
close(up->pipe[1]);
free(up);
return;
}
}
if(0)print("not started %d\n", pid);
unlock(&uproclock);
}

137
src/lib9/announce.c Normal file
View file

@ -0,0 +1,137 @@
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
extern int _p9dialparse(char*, char**, char**, u32int*, int*);
static int
getfd(char *dir)
{
int fd;
if(strncmp(dir, "/dev/fd/", 8) != 0)
return -1;
fd = strtol(dir+8, &dir, 0);
if(*dir != 0)
return -1;
return fd;
}
static void
putfd(char *dir, int fd)
{
snprint(dir, NETPATHLEN, "/dev/fd/%d", fd);
}
#undef unix
int
p9announce(char *addr, char *dir)
{
int proto;
char *buf, *unix;
char *net;
u32int host;
int port, s;
int n, sn;
struct sockaddr_in sa;
struct sockaddr_un sun;
buf = strdup(addr);
if(buf == nil)
return -1;
if(_p9dialparse(buf, &net, &unix, &host, &port) < 0){
free(buf);
return -1;
}
if(strcmp(net, "tcp") == 0)
proto = SOCK_STREAM;
else if(strcmp(net, "udp") == 0)
proto = SOCK_DGRAM;
else if(strcmp(net, "unix") == 0)
goto Unix;
else{
werrstr("can only handle tcp, udp, and unix: not %s", net);
free(buf);
return -1;
}
free(buf);
memset(&sa, 0, sizeof sa);
memmove(&sa.sin_addr, &host, 4);
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
if((s = socket(AF_INET, proto, 0)) < 0)
return -1;
sn = sizeof n;
if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&n, &sn) >= 0
&& n == SOCK_STREAM){
n = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n);
}
if(bind(s, (struct sockaddr*)&sa, sizeof sa) < 0){
close(s);
return -1;
}
if(proto == SOCK_STREAM){
listen(s, 8);
putfd(dir, s);
print("announce dir: %s\n", dir);
}
return s;
Unix:
memset(&sun, 0, sizeof sun);
sun.sun_family = AF_UNIX;
sun.sun_len = sizeof sun;
strcpy(sun.sun_path, unix);
if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
return -1;
sn = sizeof sun;
if(bind(s, (struct sockaddr*)&sun, sizeof sun) < 0){
close(s);
return -1;
}
listen(s, 8);
putfd(dir, s);
return s;
}
int
p9listen(char *dir, char *newdir)
{
int fd;
if((fd = getfd(dir)) < 0){
werrstr("bad 'directory' in listen: %s", dir);
return -1;
}
print("accept %d", fd);
if((fd = accept(fd, nil, nil)) < 0)
return -1;
print(" -> %d\n", fd);
putfd(newdir, fd);
print("listen dir: %s\n", newdir);
return fd;
}
int
p9accept(int cfd, char *dir)
{
int fd;
if((fd = getfd(dir)) < 0){
werrstr("bad 'directory' in accept");
return -1;
}
/* need to dup because the listen fd will be closed */
return dup(fd);
}

54
src/lib9/atexit.c Normal file
View file

@ -0,0 +1,54 @@
#include <u.h>
#include <libc.h>
#define NEXIT 33
static Lock onexlock;
static struct
{
void (*f)(void);
int pid;
}onex[NEXIT];
int
atexit(void (*f)(void))
{
int i;
lock(&onexlock);
for(i=0; i<NEXIT; i++)
if(onex[i].f == 0) {
onex[i].pid = getpid();
onex[i].f = f;
unlock(&onexlock);
return 1;
}
unlock(&onexlock);
return 0;
}
void
atexitdont(void (*f)(void))
{
int i, pid;
pid = getpid();
for(i=0; i<NEXIT; i++)
if(onex[i].f == f && onex[i].pid == pid)
onex[i].f = 0;
}
void
exits(char *s)
{
int i, pid;
void (*f)(void);
pid = getpid();
for(i = NEXIT-1; i >= 0; i--)
if((f = onex[i].f) && pid == onex[i].pid) {
onex[i].f = 0;
(*f)();
}
_exits(s);
}

58
src/lib9/atnotify.c Normal file
View file

@ -0,0 +1,58 @@
#include <u.h>
#include <libc.h>
#define NFN 33
static int (*onnot[NFN])(void*, char*);
static Lock onnotlock;
static
void
notifier(void *v, char *s)
{
int i;
for(i=0; i<NFN; i++)
if(onnot[i] && ((*onnot[i])(v, s))){
noted(NCONT);
return;
}
noted(NDFLT);
}
int
atnotify(int (*f)(void*, char*), int in)
{
int i, n, ret;
static int init;
if(!init){
notify(notifier);
init = 1; /* assign = */
}
ret = 0;
lock(&onnotlock);
if(in){
for(i=0; i<NFN; i++)
if(onnot[i] == 0) {
onnot[i] = f;
ret = 1;
break;
}
}else{
n = 0;
for(i=0; i<NFN; i++)
if(onnot[i]){
if(ret==0 && onnot[i]==f){
onnot[i] = 0;
ret = 1;
}else
n++;
}
if(n == 0){
init = 0;
notify(0);
}
}
unlock(&onnotlock);
return ret;
}

View file

@ -1,12 +1,12 @@
#define NOPLAN9DEFINES
#include <u.h>
#include <libc.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <string.h>
#include <errno.h>
#include <lib9.h>
static struct {
int sig;
@ -18,9 +18,7 @@ static struct {
SIGILL, "sys: trap: illegal instruction",
SIGTRAP, "sys: trace trap",
SIGABRT, "sys: abort",
#ifdef SIGEMT
SIGEMT, "sys: emulate instruction executed",
#endif
SIGFPE, "sys: fp: trap",
SIGKILL, "sys: kill",
SIGBUS, "sys: bus error",
@ -40,14 +38,12 @@ static struct {
SIGVTALRM, "sys: virtual time alarm",
SIGPROF, "sys: profiling timer alarm",
SIGWINCH, "sys: window size change",
#ifdef SIGINFO
SIGINFO, "sys: status request",
#endif
SIGUSR1, "sys: usr1",
SIGUSR2, "sys: usr2",
};
static char*
char*
_p9sigstr(int sig, char *tmp)
{
int i;
@ -59,8 +55,7 @@ _p9sigstr(int sig, char *tmp)
return tmp;
}
/*
static int
int
_p9strsig(char *s)
{
int i;
@ -70,7 +65,6 @@ _p9strsig(char *s)
return tab[i].sig;
return 0;
}
*/
int
await(char *str, int n)
@ -89,16 +83,16 @@ await(char *str, int n)
if(WIFEXITED(status)){
status = WEXITSTATUS(status);
if(status)
snprint(buf, sizeof buf, "%d %lu %lu %lu %d", pid, u, s, u+s, status);
snprint(buf, sizeof buf, "%d %lud %lud %lud %d", pid, u, s, u+s, status);
else
snprint(buf, sizeof buf, "%d %lu %lu %lu ''", pid, u, s, u+s);
snprint(buf, sizeof buf, "%d %lud %lud %lud ''", pid, u, s, u+s, status);
strecpy(str, str+n, buf);
return strlen(str);
}
if(WIFSIGNALED(status)){
cd = WCOREDUMP(status);
USED(cd);
snprint(buf, sizeof buf, "%d %lu %lu %lu '%s'", pid, u, s, u+s, _p9sigstr(WTERMSIG(status), tmp));
snprint(buf, sizeof buf, "%d %lud %lud %lud '%s'", pid, u, s, u+s, _p9sigstr(WTERMSIG(status), tmp));
strecpy(str, str+n, buf);
return strlen(str);
}

26
src/lib9/cistrcmp.c Normal file
View file

@ -0,0 +1,26 @@
#include <u.h>
#include <libc.h>
int
cistrcmp(char *s1, char *s2)
{
int c1, c2;
while(*s1){
c1 = *(uchar*)s1++;
c2 = *(uchar*)s2++;
if(c1 == c2)
continue;
if(c1 >= 'A' && c1 <= 'Z')
c1 -= 'A' - 'a';
if(c2 >= 'A' && c2 <= 'Z')
c2 -= 'A' - 'a';
if(c1 != c2)
return c1 - c2;
}
return -*s2;
}

28
src/lib9/cistrncmp.c Normal file
View file

@ -0,0 +1,28 @@
#include <u.h>
#include <libc.h>
int
cistrncmp(char *s1, char *s2, int n)
{
int c1, c2;
while(*s1 && n-- > 0){
c1 = *(uchar*)s1++;
c2 = *(uchar*)s2++;
if(c1 == c2)
continue;
if(c1 >= 'A' && c1 <= 'Z')
c1 -= 'A' - 'a';
if(c2 >= 'A' && c2 <= 'Z')
c2 -= 'A' - 'a';
if(c1 != c2)
return c1 - c2;
}
if(n <= 0)
return 0;
return -*s2;
}

23
src/lib9/cistrstr.c Normal file
View file

@ -0,0 +1,23 @@
#include <u.h>
#include <libc.h>
char*
cistrstr(char *s, char *sub)
{
int c, csub, n;
csub = *sub;
if(csub == '\0')
return s;
if(csub >= 'A' && csub <= 'Z')
csub -= 'A' - 'a';
sub++;
n = strlen(sub);
for(; c = *s; s++){
if(c >= 'A' && c <= 'Z')
c -= 'A' - 'a';
if(c == csub && cistrncmp(s+1, sub, n) == 0)
return s;
}
return nil;
}

8
src/lib9/create.c Normal file
View file

@ -0,0 +1,8 @@
#include <u.h>
#include <libc.h>
int
create(char *path, int mode, ulong perm)
{
return open(path, mode|O_CREAT|O_TRUNC, perm);
}

51
src/lib9/ctime.c Normal file
View file

@ -0,0 +1,51 @@
#include <u.h>
#include <libc.h>
static
void
ct_numb(char *cp, int n)
{
cp[0] = ' ';
if(n >= 10)
cp[0] = (n/10)%10 + '0';
cp[1] = n%10 + '0';
}
char*
asctime(Tm *t)
{
char *ncp;
static char cbuf[30];
strcpy(cbuf, "Thu Jan 01 00:00:00 GMT 1970\n");
ncp = &"SunMonTueWedThuFriSat"[t->wday*3];
cbuf[0] = *ncp++;
cbuf[1] = *ncp++;
cbuf[2] = *ncp;
ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[t->mon*3];
cbuf[4] = *ncp++;
cbuf[5] = *ncp++;
cbuf[6] = *ncp;
ct_numb(cbuf+8, t->mday);
ct_numb(cbuf+11, t->hour+100);
ct_numb(cbuf+14, t->min+100);
ct_numb(cbuf+17, t->sec+100);
ncp = t->zone;
cbuf[20] = *ncp++;
cbuf[21] = *ncp++;
cbuf[22] = *ncp;
if(t->year >= 100) {
cbuf[24] = '2';
cbuf[25] = '0';
}
ct_numb(cbuf+26, t->year+100);
return cbuf;
}
char*
ctime(long t)
{
return asctime(localtime(t));
}

77
src/lib9/date.c Normal file
View file

@ -0,0 +1,77 @@
#include <u.h>
#include <libc.h>
#undef gmtime
#undef localtime
#undef asctime
#undef ctime
#undef cputime
#undef times
#undef tm2sec
#undef nsec
#include <time.h>
static Tm bigtm;
static void
tm2Tm(struct tm *tm, Tm *bigtm)
{
memset(bigtm, 0, sizeof *bigtm);
bigtm->sec = tm->tm_sec;
bigtm->min = tm->tm_min;
bigtm->hour = tm->tm_hour;
bigtm->mday = tm->tm_mday;
bigtm->mon = tm->tm_mon;
bigtm->year = tm->tm_year;
bigtm->wday = tm->tm_wday;
strecpy(bigtm->zone, bigtm->zone+4, tm->tm_zone);
bigtm->tzoff = tm->tm_gmtoff;
}
static void
Tm2tm(Tm *bigtm, struct tm *tm)
{
memset(tm, 0, sizeof *tm);
tm->tm_sec = bigtm->sec;
tm->tm_min = bigtm->min;
tm->tm_hour = bigtm->hour;
tm->tm_mday = bigtm->mday;
tm->tm_mon = bigtm->mon;
tm->tm_year = bigtm->year;
tm->tm_wday = bigtm->wday;
tm->tm_zone = bigtm->zone;
tm->tm_gmtoff = bigtm->tzoff;
}
Tm*
p9gmtime(long t)
{
struct tm tm;
tm = *gmtime(&t);
tm2Tm(&tm, &bigtm);
return &bigtm;
}
Tm*
p9localtime(long t)
{
struct tm tm;
tm = *localtime(&t);
tm2Tm(&tm, &bigtm);
return &bigtm;
}
long
p9tm2sec(Tm *bigtm)
{
struct tm tm;
Tm2tm(bigtm, &tm);
if(strcmp(bigtm->zone, "GMT") == 0 || strcmp(bigtm->zone, "UCT") == 0)
return timegm(&tm);
return mktime(&tm); /* local time zone */
}

92
src/lib9/dial.c Normal file
View file

@ -0,0 +1,92 @@
#include <u.h>
#include <libc.h>
#undef accept
#undef announce
#undef dial
#undef setnetmtpt
#undef hangup
#undef listen
#undef netmkaddr
#undef reject
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <netdb.h>
extern int _p9dialparse(char*, char**, char**, u32int*, int*);
#undef unix
int
p9dial(char *addr, char *dummy1, char *dummy2, int *dummy3)
{
char *buf;
char *net, *unix;
u32int host;
int port;
int proto;
struct sockaddr_in sa;
struct sockaddr_un su;
int s;
if(dummy1 || dummy2 || dummy3){
werrstr("cannot handle extra arguments in dial");
return -1;
}
buf = strdup(addr);
if(buf == nil)
return -1;
if(_p9dialparse(buf, &net, &unix, &host, &port) < 0){
free(buf);
return -1;
}
if(strcmp(net, "tcp") == 0)
proto = SOCK_STREAM;
else if(strcmp(net, "udp") == 0)
proto = SOCK_DGRAM;
else if(strcmp(net, "unix") == 0)
goto Unix;
else{
werrstr("can only handle tcp, udp, and unix: not %s", net);
free(buf);
return -1;
}
free(buf);
memset(&sa, 0, sizeof sa);
memmove(&sa.sin_addr, &host, 4);
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
if((s = socket(AF_INET, proto, 0)) < 0)
return -1;
if(connect(s, (struct sockaddr*)&sa, sizeof sa) < 0){
close(s);
return -1;
}
return s;
Unix:
memset(&su, 0, sizeof su);
su.sun_len = sizeof su;
su.sun_family = AF_UNIX;
if(strlen(unix)+1 > sizeof su.sun_path){
werrstr("unix socket name too long");
free(buf);
return -1;
}
strcpy(su.sun_path, unix);
free(buf);
if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
return -1;
if(connect(s, (struct sockaddr*)&su, sizeof su) < 0){
close(s);
return -1;
}
return s;
}

29
src/lib9/dirfstat.c Normal file
View file

@ -0,0 +1,29 @@
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include <sys/stat.h>
extern int _p9dir(struct stat*, char*, Dir*, char**, char*);
Dir*
dirfstat(int fd)
{
struct stat st;
int nstr;
Dir *d;
char *str, tmp[100];
if(fstat(fd, &st) < 0)
return nil;
snprint(tmp, sizeof tmp, "/dev/fd/%d", fd);
nstr = _p9dir(&st, tmp, nil, nil, nil);
d = mallocz(sizeof(Dir)+nstr, 1);
if(d == nil)
return nil;
str = (char*)&d[1];
_p9dir(&st, tmp, d, &str, str+nstr);
return d;
}

21
src/lib9/dirfwstat.c Normal file
View file

@ -0,0 +1,21 @@
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include <sys/time.h>
int
dirfwstat(int fd, Dir *dir)
{
struct timeval tv[2];
/* BUG handle more */
if(dir->mtime == ~0ULL)
return 0;
tv[0].tv_sec = dir->mtime;
tv[0].tv_usec = 0;
tv[1].tv_sec = dir->mtime;
tv[1].tv_usec = 0;
return futimes(fd, tv);
}

47
src/lib9/dirmodefmt.c Normal file
View file

@ -0,0 +1,47 @@
#include <u.h>
#include <libc.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
dirmodefmt(Fmt *f)
{
static char buf[16];
ulong m;
m = va_arg(f->args, ulong);
if(m & DMDIR)
buf[0]='d';
else if(m & DMAPPEND)
buf[0]='a';
else if(m & DMAUTH)
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;
return fmtstrcpy(f, buf);
}

155
src/lib9/dirread.c Normal file
View file

@ -0,0 +1,155 @@
#include <u.h>
#include <libc.h>
#undef asctime
#undef ctime
#undef gmtime
#undef localtime
#include <sys/stat.h>
#include <dirent.h>
extern int _p9dir(struct stat*, char*, Dir*, char**, char*);
static int
countde(char *p, int n)
{
char *e;
int m;
struct dirent *de;
e = p+n;
m = 0;
while(p < e){
de = (struct dirent*)p;
if(de->d_reclen <= 4+2+2+1 || p+de->d_reclen > e)
break;
if(de->d_namlen == 1 && de->d_name[0]=='.')
de->d_namlen = 0;
else if(de->d_namlen == 2 && de->d_name[0]=='.' && de->d_name[1]=='.')
de->d_namlen = 0;
else
m++;
p += de->d_reclen;
}
return m;
}
static int
dirpackage(int fd, char *buf, int n, Dir **dp)
{
int oldwd;
char *p, *str, *estr;
int i, nstr, m;
struct dirent *de;
struct stat st;
Dir *d;
n = countde(buf, n);
if(n <= 0)
return n;
if((oldwd = open(".", O_RDONLY)) < 0)
return -1;
if(fchdir(fd) < 0)
return -1;
p = buf;
nstr = 0;
for(i=0; i<n; i++){
de = (struct dirent*)p;
if(stat(de->d_name, &st) < 0)
de->d_namlen = 0;
else
nstr += _p9dir(&st, de->d_name, nil, nil, nil);
p += de->d_reclen;
}
d = malloc(sizeof(Dir)*n+nstr);
if(d == nil){
fchdir(oldwd);
close(oldwd);
return -1;
}
str = (char*)&d[n];
estr = str+nstr;
p = buf;
m = 0;
for(i=0; i<n; i++){
de = (struct dirent*)p;
if(de->d_namlen != 0 && stat(de->d_name, &st) >= 0)
_p9dir(&st, de->d_name, &d[m++], &str, estr);
p += de->d_reclen;
}
fchdir(oldwd);
close(oldwd);
*dp = d;
return m;
}
long
dirread(int fd, Dir **dp)
{
char *buf;
struct stat st;
int n;
*dp = 0;
if(fstat(fd, &st) < 0)
return -1;
if(st.st_blksize < 8192)
st.st_blksize = 8192;
buf = malloc(st.st_blksize);
if(buf == nil)
return -1;
n = getdents(fd, buf, st.st_blksize);
if(n < 0){
free(buf);
return -1;
}
n = dirpackage(fd, buf, n, dp);
free(buf);
return n;
}
long
dirreadall(int fd, Dir **d)
{
uchar *buf, *nbuf;
long n, ts;
struct stat st;
if(fstat(fd, &st) < 0)
return -1;
if(st.st_blksize < 8192)
st.st_blksize = 8192;
buf = nil;
ts = 0;
for(;;){
nbuf = realloc(buf, ts+st.st_blksize);
if(nbuf == nil){
free(buf);
return -1;
}
buf = nbuf;
n = getdents(fd, buf+ts, st.st_blksize);
if(n <= 0)
break;
ts += n;
}
if(ts >= 0)
ts = dirpackage(fd, buf, ts, d);
free(buf);
if(ts == 0 && n < 0)
return -1;
return ts;
}

View file

@ -1,83 +1,28 @@
#include "u.h"
#include "libc.h"
#include <sys/types.h>
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
static void
statconv(Dir *dir, struct stat *s)
extern int _p9dir(struct stat*, char*, Dir*, char**, char*);
Dir*
dirstat(char *file)
{
struct passwd *p;
struct group *g;
ulong q;
struct stat st;
int nstr;
Dir *d;
char *str;
p = getpwuid(s->st_uid);
if (p)
strncpy(dir->uid, p->pw_name, NAMELEN);
g = getgrgid(s->st_gid);
if (g)
strncpy(dir->gid, g->gr_name, NAMELEN);
q = 0;
if(S_ISDIR(s->st_mode))
q = CHDIR;
q |= s->st_ino & 0x00FFFFFFUL;
dir->qid.path = q;
dir->qid.vers = s->st_mtime;
dir->mode = (dir->qid.path&CHDIR)|(s->st_mode&0777);
dir->atime = s->st_atime;
dir->mtime = s->st_mtime;
dir->length = s->st_size;
dir->dev = s->st_dev;
dir->type = 'M';
if(S_ISFIFO(s->st_mode))
dir->type = '|';
if(stat(file, &st) < 0)
return nil;
nstr = _p9dir(&st, file, nil, nil, nil);
d = mallocz(sizeof(Dir)+nstr, 1);
if(d == nil)
return nil;
str = (char*)&d[1];
_p9dir(&st, file, d, &str, str+nstr);
return d;
}
int
dirfstat(int fd, Dir *d)
{
struct stat sbuf;
if(fstat(fd, &sbuf) < 0)
return -1;
statconv(d, &sbuf);
return 0;
}
static char *
lelem(char *path)
{
char *pr;
pr = utfrrune(path, '/');
if(pr)
pr++;
else
pr = path;
return pr;
}
int
dirstat(char *f, Dir *d)
{
struct stat sbuf;
if(stat(f, &sbuf) < 0)
return -1;
statconv(d, &sbuf);
strncpy(d->name, lelem(f), NAMELEN);
return 0;
}
int
dirfwstat(int fd, Dir *d)
{
return -1;
}
int
dirwstat(char *name, Dir *d)
{
return -1;
}

21
src/lib9/dirwstat.c Normal file
View file

@ -0,0 +1,21 @@
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include <sys/time.h>
int
dirwstat(char *file, Dir *dir)
{
struct timeval tv[2];
/* BUG handle more */
if(dir->mtime == ~0ULL)
return 0;
tv[0].tv_sec = dir->mtime;
tv[0].tv_usec = 0;
tv[1].tv_sec = dir->mtime;
tv[1].tv_usec = 0;
return utimes(file, tv);
}

12
src/lib9/dup.c Normal file
View file

@ -0,0 +1,12 @@
#include <u.h>
#include <libc.h>
#undef dup
int
p9dup(int old, int new)
{
if(new == -1)
return dup(old);
return dup2(old, new);
}

View file

@ -78,3 +78,16 @@ werrstr(char *fmt, ...)
va_end(arg);
errstr(buf, ERRMAX);
}
char*
gerrstr(void)
{
char *s;
s = getsyserr();
if(errno != EPLAN9)
strcpy(s, strerror(errno));
return s;
}

9
src/lib9/exec.c Normal file
View file

@ -0,0 +1,9 @@
#include <u.h>
#include <libc.h>
int
exec(char *prog, char *argv[])
{
/* to mimic plan 9 should be just exec, but execvp is a better fit for unix */
return execvp(prog, argv);
}

View file

@ -1,10 +1,22 @@
#include <lib9.h>
#include <u.h>
#include <libc.h>
extern void _privdie(void);
void
exits(char *s)
{
_privdie();
if(s && *s)
exit(1);
exit(0);
}
void
_exits(char *s)
{
_privdie();
if(s && *s)
_exit(1);
_exit(0);
}

View file

@ -1,26 +1 @@
#include <lib9.h>
#include <pthread.h>
extern int __isthreaded;
int
ffork(int flags, void(*fn)(void*), void *arg)
{
void *p;
pthread_t tid;
if(flags != (RFMEM|RFNOWAIT)){
werrstr("ffork unsupported");
return -1;
}
if(pthread_create(&tid, NULL, (void*(*)(void*))fn, arg) < 0)
return -1;
return (int)tid;
}
int
getfforkid(void)
{
return (int)pthread_self();
}
#include "ffork-pthread.c"

1
src/lib9/ffork-SunOS.c Normal file
View file

@ -0,0 +1 @@
#include "ffork-pthread.c"

26
src/lib9/ffork-pthread.c Normal file
View file

@ -0,0 +1,26 @@
#include <lib9.h>
#include <pthread.h>
extern int __isthreaded;
int
ffork(int flags, void(*fn)(void*), void *arg)
{
void *p;
pthread_t tid;
if(flags != (RFMEM|RFNOWAIT)){
werrstr("ffork unsupported");
return -1;
}
if(pthread_create(&tid, NULL, (void*(*)(void*))fn, arg) < 0)
return -1;
return (int)tid;
}
int
getfforkid(void)
{
return (int)pthread_self();
}

View file

@ -0,0 +1,5 @@
.text
.globl getcallerpc
getcallerpc:
retl
or %o7, %r0, %o0

15
src/lib9/getenv.c Normal file
View file

@ -0,0 +1,15 @@
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
char*
p9getenv(char *s)
{
char *t;
t = getenv(s);
if(t == 0)
return 0;
return strdup(t);
}

17
src/lib9/getuser.c Normal file
View file

@ -0,0 +1,17 @@
#include <pwd.h>
#include <u.h>
#include <libc.h>
char*
getuser(void)
{
static char user[64];
struct passwd *pw;
pw = getpwuid(getuid());
if(pw == nil)
return "none";
strecpy(user, user+sizeof user, pw->pw_name);
return user;
}

10
src/lib9/getwd.c Normal file
View file

@ -0,0 +1,10 @@
#include <u.h>
#include <libc.h>
#undef getwd
char*
p9getwd(char *s, int ns)
{
return getcwd(s, ns);
}

3
src/lib9/jmp-FreeBSD.s Normal file
View file

@ -0,0 +1,3 @@
.globl sigsetjmp, p9setjmp
p9setjmp:
jmp sigsetjmp

17
src/lib9/jmp.c Normal file
View file

@ -0,0 +1,17 @@
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
void
p9longjmp(p9jmp_buf buf, int val)
{
siglongjmp((void*)buf, val);
}
void
p9notejmp(void *x, p9jmp_buf buf, int val)
{
USED(x);
siglongjmp((void*)buf, val);
}

13
src/lib9/main.c Normal file
View file

@ -0,0 +1,13 @@
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
extern void p9main(int, char**);
int
main(int argc, char **argv)
{
p9main(argc, argv);
exits("main");
return 99;
}

73
src/lib9/mkfile Normal file
View file

@ -0,0 +1,73 @@
PLAN9=../..
<$PLAN9/src/mkhdr
LIB=lib9.a
OFILES=\
_exits.$O\
_p9dialparse.$O\
_p9dir.$O\
_p9proc.$O\
announce.$O\
argv0.$O\
atexit.$O\
atnotify.$O\
await.$O\
cistrcmp.$O\
cistrncmp.$O\
cistrstr.$O\
cleanname.$O\
create.$O\
ctime.$O\
date.$O\
dial.$O\
dirfstat.$O\
dirfwstat.$O\
dirmodefmt.$O\
dirread.$O\
dirstat.$O\
dirwstat.$O\
dup.$O\
encodefmt.$O\
errstr.$O\
exec.$O\
ffork-$SYSNAME.$O\
getcallerpc-$OBJTYPE.$O\
getenv.$O\
getfields.$O\
getuser.$O\
getwd.$O\
jmp.$O\
jmp-FreeBSD.$O\
lock.$O\
main.$O\
malloctag.$O\
mallocz.$O\
needsrcquote.$O\
netmkaddr.$O\
notify.$O\
nrand.$O\
nulldir.$O\
postnote.$O\
qlock.$O\
quote.$O\
readn.$O\
rendez-$SYSNAME.$O\
rfork.$O\
seek.$O\
sleep.$O\
strecpy.$O\
sysfatal.$O\
tas-$OBJTYPE.$O\
time.$O\
tokenize.$O\
u16.$O\
u32.$O\
u64.$O\
wait.$O\
waitpid.$O\
HFILES=\
$PLAN9/include/lib9.h\
<$PLAN9/src/mksyslib

12
src/lib9/needsrcquote.c Normal file
View file

@ -0,0 +1,12 @@
#include <u.h>
#include <libc.h>
int
needsrcquote(int c)
{
if(c <= ' ')
return 1;
if(strchr("`^#*[]=|\\?${}()'<>&;", c))
return 1;
return 0;
}

52
src/lib9/netmkaddr.c Normal file
View file

@ -0,0 +1,52 @@
#include <u.h>
#include <libc.h>
#include <ctype.h>
/*
* make an address, add the defaults
*/
char *
netmkaddr(char *linear, char *defnet, char *defsrv)
{
static char addr[256];
char *cp;
/*
* dump network name
*/
cp = strchr(linear, '!');
if(cp == 0){
if(defnet==0){
if(defsrv)
snprint(addr, sizeof(addr), "net!%s!%s",
linear, defsrv);
else
snprint(addr, sizeof(addr), "net!%s", linear);
}
else {
if(defsrv)
snprint(addr, sizeof(addr), "%s!%s!%s", defnet,
linear, defsrv);
else
snprint(addr, sizeof(addr), "%s!%s", defnet,
linear);
}
return addr;
}
/*
* if there is already a service, use it
*/
cp = strchr(cp+1, '!');
if(cp)
return linear;
/*
* add default service
*/
if(defsrv == 0)
return linear;
snprint(addr, sizeof(addr), "%s!%s", linear, defsrv);
return addr;
}

83
src/lib9/notify.c Normal file
View file

@ -0,0 +1,83 @@
#include <signal.h>
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include "9proc.h"
extern char *_p9sigstr(int, char*);
static int sigs[] = {
SIGHUP,
SIGINT,
SIGQUIT,
SIGILL,
SIGTRAP,
SIGABRT,
SIGEMT,
SIGFPE,
SIGBUS,
SIGSEGV,
SIGSYS,
SIGPIPE,
SIGALRM,
SIGTERM,
SIGTSTP,
SIGTTIN,
SIGTTOU,
SIGXCPU,
SIGXFSZ,
SIGVTALRM,
SIGUSR1,
SIGUSR2,
};
static void (*notifyf)(void*, char*);
static void
notifysigf(int sig)
{
int v;
char tmp[64];
Uproc *up;
up = _p9uproc();
v = p9setjmp(up->notejb);
if(v == 0 && notifyf)
(*notifyf)(nil, _p9sigstr(sig, tmp));
else if(v == 2){
if(0)print("HANDLED %d\n", sig);
return;
}
if(0)print("DEFAULT %d\n", sig);
signal(sig, SIG_DFL);
kill(getpid(), sig);
}
int
notify(void (*f)(void*, char*))
{
int i;
void (*sf)(int);
if(f == nil)
sf = SIG_DFL;
else{
notifyf = f;
sf = notifysigf;
}
for(i=0; i<nelem(sigs); i++)
signal(sigs[i], sf);
return 0;
}
int
noted(int v)
{
Uproc *up;
up = _p9uproc();
p9longjmp(up->notejb, v==NCONT ? 2 : 1);
abort();
return 0;
}

9
src/lib9/nulldir.c Normal file
View file

@ -0,0 +1,9 @@
#include <u.h>
#include <libc.h>
void
nulldir(Dir *d)
{
memset(d, ~0, sizeof(Dir));
d->name = d->uid = d->gid = d->muid = "";
}

34
src/lib9/postnote.c Normal file
View file

@ -0,0 +1,34 @@
#include <signal.h>
#include <u.h>
#define _NO9DEFINES_
#include <libc.h>
extern int _p9strsig(char*);
int
postnote(int who, int pid, char *msg)
{
int sig;
sig = _p9strsig(msg);
if(sig == 0){
werrstr("unknown note");
return -1;
}
switch(who){
default:
werrstr("bad who in postnote");
return -1;
case PNPROC:
return kill(pid, sig);
case PNGROUP:
if((pid = getpgid(pid)) < 0)
return -1;
return killpg(pid, sig);
}
}

32
src/lib9/priv.c Normal file
View file

@ -0,0 +1,32 @@
#include <u.h>
#include <libc.h>
#include "9proc.h"
static Lock privlock;
static ulong privmap;
int
privalloc(void)
{
int i;
lock(&privlock);
for(i=0; i<NPRIV; i++)
if((privmap&(1<<i)) == 0){
privmap |= (1<<i);
unlock(&privlock);
return i;
}
unlock(&privlock);
return -1;
}
void**
privmem(int i)
{
Uproc *up;
up = _p9uproc();
return &up->priv[i];
}

136
src/lib9/quote.c Normal file
View file

@ -0,0 +1,136 @@
#include <u.h>
#include <libc.h>
int (*doquote)(int);
/* in libfmt */
extern int __needsquotes(char*, int*);
extern int __runeneedsquotes(Rune*, int*);
char*
unquotestrdup(char *s)
{
char *t, *ret;
int quoting;
ret = s = strdup(s); /* return unquoted copy */
if(ret == nil)
return ret;
quoting = 0;
t = s; /* s is output string, t is input string */
while(*t!='\0' && (quoting || (*t!=' ' && *t!='\t'))){
if(*t != '\''){
*s++ = *t++;
continue;
}
/* *t is a quote */
if(!quoting){
quoting = 1;
t++;
continue;
}
/* quoting and we're on a quote */
if(t[1] != '\''){
/* end of quoted section; absorb closing quote */
t++;
quoting = 0;
continue;
}
/* doubled quote; fold one quote into two */
t++;
*s++ = *t++;
}
if(t != s)
memmove(s, t, strlen(t)+1);
return ret;
}
Rune*
unquoterunestrdup(Rune *s)
{
Rune *t, *ret;
int quoting;
ret = s = runestrdup(s); /* return unquoted copy */
if(ret == nil)
return ret;
quoting = 0;
t = s; /* s is output string, t is input string */
while(*t!='\0' && (quoting || (*t!=' ' && *t!='\t'))){
if(*t != '\''){
*s++ = *t++;
continue;
}
/* *t is a quote */
if(!quoting){
quoting = 1;
t++;
continue;
}
/* quoting and we're on a quote */
if(t[1] != '\''){
/* end of quoted section; absorb closing quote */
t++;
quoting = 0;
continue;
}
/* doubled quote; fold one quote into two */
t++;
*s++ = *t++;
}
if(t != s)
memmove(s, t, (runestrlen(t)+1)*sizeof(Rune));
return ret;
}
char*
quotestrdup(char *s)
{
char *t, *u, *ret;
int quotelen;
Rune r;
if(__needsquotes(s, &quotelen) == 0)
return strdup(s);
ret = malloc(quotelen+1);
if(ret == nil)
return nil;
u = ret;
*u++ = '\'';
for(t=s; *t; t++){
r = *t;
if(r == L'\'')
*u++ = r; /* double the quote */
*u++ = r;
}
*u++ = '\'';
*u = '\0';
return ret;
}
Rune*
quoterunestrdup(Rune *s)
{
Rune *t, *u, *ret;
int quotelen;
Rune r;
if(__runeneedsquotes(s, &quotelen) == 0)
return runestrdup(s);
ret = malloc((quotelen+1)*sizeof(Rune));
if(ret == nil)
return nil;
u = ret;
*u++ = '\'';
for(t=s; *t; t++){
r = *t;
if(r == L'\'')
*u++ = r; /* double the quote */
*u++ = r;
}
*u++ = '\'';
*u = '\0';
return ret;
}

1
src/lib9/rendez-SunOS.c Normal file
View file

@ -0,0 +1 @@
#include "rendez-pthread.c"

View file

@ -33,6 +33,7 @@
*/
#include <pthread.h>
#include <signal.h>
#include <lib9.h>
enum

42
src/lib9/rendez.c Normal file
View file

@ -0,0 +1,42 @@
#include <u.h>
#include <libc.h>
#include "9proc.h"
static Lock rendlock;
static Uproc *rendhash[RENDHASH];
ulong
rendezvous(ulong tag, ulong val)
{
char c;
ulong ret;
Uproc *t, *self, **l;
self = _p9uproc();
lock(&rendlock);
l = &rendhash[tag%RENDHASH];
for(t=*l; t; l=&t->rendhash, t=*l){
if(t->rendtag==tag){
*l = t->rendhash;
ret = t->rendval;
t->rendval = val;
t->rendtag++;
c = 0;
unlock(&rendlock);
write(t->pipe[1], &c, 1);
return ret;
}
}
/* Going to sleep here. */
t = self;
t->rendtag = tag;
t->rendval = val;
t->rendhash = *l;
*l = t;
unlock(&rendlock);
do
read(t->pipe[0], &c, 1);
while(t->rendtag == tag);
return t->rendval;
}

20
src/lib9/rfork.c Normal file
View file

@ -0,0 +1,20 @@
#define NOPLAN9DEFINES
#include <lib9.h>
int
p9rfork(int flags)
{
if(flags&RFPROC){
werrstr("cannot use rfork to fork -- use ffork");
return -1;
}
if(flags&RFNOTEG){
setpgrp(0, 0);
flags &= ~RFNOTEG;
}
if(flags){
werrstr("unknown flags %08ux in rfork", flags);
return -1;
}
return 0;
}

8
src/lib9/seek.c Normal file
View file

@ -0,0 +1,8 @@
#include <u.h>
#include <libc.h>
vlong
seek(int fd, vlong offset, int whence)
{
return lseek(fd, offset, whence);
}

35
src/lib9/sleep.c Normal file
View file

@ -0,0 +1,35 @@
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include <sys/time.h>
#include <sched.h>
int
p9sleep(long milli)
{
struct timeval tv;
if(milli == 0){
sched_yield();
return 0;
}
tv.tv_sec = milli/1000;
tv.tv_usec = (milli%1000)*1000;
return select(0, 0, 0, 0, &tv);
}
long
p9alarm(ulong milli)
{
struct itimerval itv;
struct itimerval oitv;
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = milli/1000;
itv.it_value.tv_usec = (milli%1000)*1000;
if(setitimer(ITIMER_REAL, &itv, &oitv) < 0)
return -1;
return oitv.it_value.tv_sec*1000+oitv.it_value.tv_usec/1000;
}

116
src/lib9/stat2dir.c Normal file
View file

@ -0,0 +1,116 @@
#include <u.h>
#include <libc.h>
#include <sys/stat.h>
#include <sys/disklabel.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
int
_p9dir(struct stat *st, char *name, Dir *d, char **str, char *estr)
{
char *s;
char tmp[20];
struct group *g;
struct pwd *p;
int sz;
sz = 0;
/* name */
s = strrchr(name, '/');
if(s && s[1])
s++;
else
s = "/";
if(d){
if(*str + strlen(s)+1 > estr)
d->name = "oops";
else{
strcpy(*str, s);
d->name = *str;
*str += strlen(*str)+1;
}
}
sz += strlen(s)+1;
/* user */
p = getpwuid(st->st_uid);
if(p == nil){
snprint(tmp, sizeof tmp, "%d", (int)st->st_uid);
s = tmp;
}else
s = p->pw_name;
sz += strlen(s)+1;
if(d){
if(*str+strlen(s)+1 > estr)
d->uid = "oops";
else{
strcpy(*str, s);
d->uid = *str;
*str += strlen(*str)+1;
}
}
/* group */
g = getgrgid(st->st_gid);
if(g == nil){
snprint(tmp, sizeof tmp, "%d", (int)st->st_gid);
s = tmp;
}else
s = g->gr_name;
sz += strlen(s)+1;
if(d){
if(*str + strlen(s)+1 > estr){
d->gid = "oops";
else{
strcpy(*str, s);
d->gid = *str;
*str += strlen(*str)+1;
}
}
if(d){
d->muid = "";
d->qid.path = ((uvlong)st->st_dev<<32) | st->st_ino;
d->qid.vers = st->st_gen;
d->mode = st->st_mode&0777;
if(S_ISDIR(st->st_mode)){
d->mode |= DMDIR;
d->qid.type = QTDIR;
}
d->atime = st->st_atime;
d->mtime = st->st_mtime;
d->length = st->st_size;
/* fetch real size for disks */
if(S_ISCHR(st->st_mode)){
int fd, n;
struct disklabel lab;
if((fd = open(name, O_RDONLY)) < 0)
goto nosize;
if(ioctl(fd, DIOCGDINFO, &lab) < 0)
goto nosize;
n = minor(st->st_rdev)&0xFFFF;
if(n >= lab.d_npartitions)
goto nosize;
d->length = (vlong)lab.d_npartitions[n].p_size * lab.d_secsize;
nosize:
if(fd >= 0)
close(fd);
}
}
return sz;
}
Dir*
_dirfstat(char *name, int fd)
{
Dir *d;
int size;
}

4
src/lib9/tas-sun4u.s Normal file
View file

@ -0,0 +1,4 @@
.globl _tas
_tas:
retl
ldstub [%o0], %o0

58
src/lib9/time.c Normal file
View file

@ -0,0 +1,58 @@
#include <sys/time.h>
#include <sys/resource.h>
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
long
p9times(long *t)
{
struct rusage ru, cru;
if(getrusage(0, &ru) < 0 || getrusage(-1, &cru) < 0)
return -1;
t[0] = ru.ru_utime.tv_sec*1000 + ru.ru_utime.tv_usec/1000;
t[1] = ru.ru_stime.tv_sec*1000 + ru.ru_stime.tv_usec/1000;
t[2] = cru.ru_utime.tv_sec*1000 + cru.ru_utime.tv_usec/1000;
t[3] = cru.ru_stime.tv_sec*1000 + cru.ru_stime.tv_usec/1000;
/* BUG */
return t[0]+t[1]+t[2]+t[3];
}
double
p9cputime(void)
{
long t[4];
double d;
if(p9times(t) < 0)
return -1.0;
d = (double)t[0]+(double)t[1]+(double)t[2]+(double)t[3];
return d/1000.0;
}
vlong
p9nsec(void)
{
struct timeval tv;
if(gettimeofday(&tv, 0) < 0)
return -1;
return (vlong)tv.tv_sec*1000*1000*1000 + tv.tv_usec*1000;
}
long
p9time(long *tt)
{
long t;
t = time(0);
if(tt)
*tt = t;
return t;
}

52
src/lib9/udp.c Normal file
View file

@ -0,0 +1,52 @@
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
#include <ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
/*
* prefix of all v4 addresses
* copied from libip because libc cannot depend on libip
*/
static uchar v4prefix[IPaddrlen] = {
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0xff, 0xff,
0, 0, 0, 0
};
long
udpread(int fd, Udphdr *hdr, void *buf, long n)
{
struct sockaddr_in sin;
socklen_t len;
len = sizeof sin;
n = recvfrom(fd, buf, n, 0, (struct sockaddr*)&sin, &len);
if(len != sizeof sin){
werrstr("recvfrom acting weird");
return -1;
}
if(n < 0)
return -1;
memset(hdr, 0, sizeof *hdr);
memmove(hdr->raddr, v4prefix, IPaddrlen);
*(u32int*)(hdr->raddr+12) = *(u32int*)&sin.sin_addr;
*(u16int*)hdr->rport = *(u16int*)&sin.sin_port;
return n;
}
long
udpwrite(int fd, Udphdr *hdr, void *buf, long n)
{
struct sockaddr_in sin;
memset(&sin, 0, sizeof sin);
sin.sin_family = AF_INET;
*(u32int*)&sin.sin_addr = *(u32int*)(hdr->raddr+12);
*(u16int*)&sin.sin_port = *(u16int*)hdr->rport;
return sendto(fd, buf, n, 0, (struct sockaddr*)&sin, sizeof sin);
}

View file

@ -1,4 +1,5 @@
#include <lib9.h>
#include <u.h>
#include <libc.h>
Waitmsg*
wait(void)

20
src/lib9/waitpid.c Normal file
View file

@ -0,0 +1,20 @@
#include <u.h>
#include <libc.h>
int
waitpid(void)
{
int n;
char buf[512], *fld[5];
n = await(buf, sizeof buf-1);
if(n <= 0)
return -1;
buf[n] = '\0';
if(tokenize(buf, fld, nelem(fld)) != nelem(fld)){
werrstr("couldn't parse wait message");
return -1;
}
return atoi(fld[0]);
}