Today's changes.

More changes.
This commit is contained in:
rsc 2004-03-25 23:03:57 +00:00
parent cb27443abf
commit 8ad517944e
73 changed files with 2865 additions and 1293 deletions

View file

@ -80,6 +80,7 @@ extern int fmtfdflush(Fmt*);
extern int fmtstrinit(Fmt*); extern int fmtstrinit(Fmt*);
extern char* fmtstrflush(Fmt*); extern char* fmtstrflush(Fmt*);
extern int runefmtstrinit(Fmt*); extern int runefmtstrinit(Fmt*);
extern Rune* runefmtstrflush(Fmt*);
extern int quotestrfmt(Fmt *f); extern int quotestrfmt(Fmt *f);
extern void quotefmtinstall(void); extern void quotefmtinstall(void);

View file

@ -1,874 +1,2 @@
/* #include <u.h>
* Lib9 is miscellany from the Plan 9 C library that doesn't #include <libc.h>
* fit into libutf or into libfmt, but is still missing from traditional
* Unix C libraries.
*/
#ifndef _LIB9_H_
#define _LIB9_H_ 1
#if defined(__cplusplus)
extern "C" {
#endif
#define _BSD_SOURCE 1
#define _SVID_SOURCE 1
#define _XOPEN_SOURCE 1000
#define _XOPEN_SOURCE_EXTENDED 1
#define _LARGEFILE64_SOURCE 1
#define _FILE_OFFSET_BITS 64
#define __EXTENSIONS__ 1 /* SunOS */
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <assert.h>
#include <setjmp.h>
#include <stddef.h>
#include <utf.h>
#include <fmt.h>
#include <math.h>
/*
* OS-specific crap
*/
#define _NEEDUCHAR 1
#define _NEEDUSHORT 1
#define _NEEDUINT 1
#define _NEEDULONG 1
typedef long p9jmp_buf[sizeof(sigjmp_buf)/sizeof(long)];
#if defined(__linux__)
# include <sys/types.h>
# if defined(__USE_MISC)
# undef _NEEDUSHORT
# undef _NEEDUINT
# undef _NEEDULONG
# endif
#endif
#if defined(__sun__)
# include <sys/types.h>
# undef _NEEDUSHORT
# undef _NEEDUINT
# undef _NEEDULONG
#endif
#if defined(__FreeBSD__)
# include <sys/types.h>
# if !defined(_POSIX_SOURCE)
# undef _NEEDUSHORT
# undef _NEEDUINT
# endif
#endif
#if defined(__APPLE__)
# include <sys/types.h>
# undef _NEEDUSHORT
# undef _NEEDUINT
# define _NEEDLL 1
#endif
typedef signed char schar;
typedef unsigned int u32int;
#ifdef _NEEDUCHAR
typedef unsigned char uchar;
#endif
#ifdef _NEEDUSHORT
typedef unsigned short ushort;
#endif
#ifdef _NEEDUINT
typedef unsigned int uint;
#endif
#ifdef _NEEDULONG
typedef unsigned long ulong;
#endif
typedef unsigned long long uvlong;
typedef long long vlong;
typedef uvlong u64int;
typedef uchar u8int;
typedef ushort u16int;
#undef _NEEDUCHAR
#undef _NEEDUSHORT
#undef _NEEDUINT
#undef _NEEDULONG
/*
* Begin usual libc.h
*/
#define nil ((void*)0)
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
#ifndef offsetof
#define offsetof(s, m) (ulong)(&(((s*)0)->m))
#endif
/*
* mem routines (provided by system <string.h>)
*
extern void* memccpy(void*, void*, int, ulong);
extern void* memset(void*, int, ulong);
extern int memcmp(void*, void*, ulong);
extern void* memcpy(void*, void*, ulong);
extern void* memmove(void*, void*, ulong);
extern void* memchr(void*, int, ulong);
*/
/*
* string routines (provided by system <string.h>)
*
extern char* strcat(char*, char*);
extern char* strchr(char*, int);
extern int strcmp(char*, char*);
extern char* strcpy(char*, char*);
*/
extern char* strecpy(char*, char*, char*);
/*
extern char* strdup(char*);
extern char* strncat(char*, char*, long);
extern char* strncpy(char*, char*, long);
extern int strncmp(char*, char*, long);
extern char* strpbrk(char*, char*);
extern char* strrchr(char*, int);
extern char* strtok(char*, char*);
extern long strlen(char*);
extern long strspn(char*, char*);
extern long strcspn(char*, char*);
extern char* strstr(char*, char*);
*/
extern int cistrncmp(char*, char*, int);
extern int cistrcmp(char*, char*);
extern char* cistrstr(char*, char*);
extern int tokenize(char*, char**, int);
/*
enum
{
UTFmax = 3,
Runesync = 0x80,
Runeself = 0x80,
Runeerror = 0x80,
};
*/
/*
* rune routines (provided by <utf.h>
*
extern int runetochar(char*, Rune*);
extern int chartorune(Rune*, char*);
extern int runelen(long);
extern int runenlen(Rune*, int);
extern int fullrune(char*, int);
extern int utflen(char*);
extern int utfnlen(char*, long);
extern char* utfrune(char*, long);
extern char* utfrrune(char*, long);
extern char* utfutf(char*, char*);
extern char* utfecpy(char*, char*, char*);
extern Rune* runestrcat(Rune*, Rune*);
extern Rune* runestrchr(Rune*, Rune);
extern int runestrcmp(Rune*, Rune*);
extern Rune* runestrcpy(Rune*, Rune*);
extern Rune* runestrncpy(Rune*, Rune*, long);
extern Rune* runestrecpy(Rune*, Rune*, Rune*);
extern Rune* runestrdup(Rune*);
extern Rune* runestrncat(Rune*, Rune*, long);
extern int runestrncmp(Rune*, Rune*, long);
extern Rune* runestrrchr(Rune*, Rune);
extern long runestrlen(Rune*);
extern Rune* runestrstr(Rune*, Rune*);
extern Rune tolowerrune(Rune);
extern Rune totitlerune(Rune);
extern Rune toupperrune(Rune);
extern int isalpharune(Rune);
extern int islowerrune(Rune);
extern int isspacerune(Rune);
extern int istitlerune(Rune);
extern int isupperrune(Rune);
*/
/*
* malloc (provied by system <stdlib.h>)
*
extern void* malloc(ulong);
*/
extern void* p9malloc(ulong);
extern void* mallocz(ulong, int);
/*
extern void free(void*);
extern ulong msize(void*);
extern void* calloc(ulong, ulong);
extern void* realloc(void*, ulong);
*/
extern void setmalloctag(void*, ulong);
extern void setrealloctag(void*, ulong);
extern ulong getmalloctag(void*);
extern ulong getrealloctag(void*);
/*
extern void* malloctopoolblock(void*);
*/
#ifndef NOPLAN9DEFINES
#define malloc p9malloc
#endif
/*
* print routines (provided by <fmt.h>)
*
typedef struct Fmt Fmt;
struct Fmt{
uchar runes;
void *start;
void *to;
void *stop;
int (*flush)(Fmt *);
void *farg;
int nfmt;
va_list args;
int r;
int width;
int prec;
ulong flags;
};
enum{
FmtWidth = 1,
FmtLeft = FmtWidth << 1,
FmtPrec = FmtLeft << 1,
FmtSharp = FmtPrec << 1,
FmtSpace = FmtSharp << 1,
FmtSign = FmtSpace << 1,
FmtZero = FmtSign << 1,
FmtUnsigned = FmtZero << 1,
FmtShort = FmtUnsigned << 1,
FmtLong = FmtShort << 1,
FmtVLong = FmtLong << 1,
FmtComma = FmtVLong << 1,
FmtByte = FmtComma << 1,
FmtFlag = FmtByte << 1
};
extern int print(char*, ...);
extern char* seprint(char*, char*, char*, ...);
extern char* vseprint(char*, char*, char*, va_list);
extern int snprint(char*, int, char*, ...);
extern int vsnprint(char*, int, char*, va_list);
extern char* smprint(char*, ...);
extern char* vsmprint(char*, va_list);
extern int sprint(char*, char*, ...);
extern int fprint(int, char*, ...);
extern int vfprint(int, char*, va_list);
extern int runesprint(Rune*, char*, ...);
extern int runesnprint(Rune*, int, char*, ...);
extern int runevsnprint(Rune*, int, char*, va_list);
extern Rune* runeseprint(Rune*, Rune*, char*, ...);
extern Rune* runevseprint(Rune*, Rune*, char*, va_list);
extern Rune* runesmprint(char*, ...);
extern Rune* runevsmprint(char*, va_list);
extern int fmtfdinit(Fmt*, int, char*, int);
extern int fmtfdflush(Fmt*);
extern int fmtstrinit(Fmt*);
extern char* fmtstrflush(Fmt*);
extern int runefmtstrinit(Fmt*);
extern Rune* runefmtstrflush(Fmt*);
extern int fmtinstall(int, int (*)(Fmt*));
extern int dofmt(Fmt*, char*);
extern int dorfmt(Fmt*, Rune*);
extern int fmtprint(Fmt*, char*, ...);
extern int fmtvprint(Fmt*, char*, va_list);
extern int fmtrune(Fmt*, int);
extern int fmtstrcpy(Fmt*, char*);
extern int fmtrunestrcpy(Fmt*, Rune*);
*/
/*
* error string for %r
* supplied on per os basis, not part of fmt library
*
* (provided by lib9, but declared in fmt.h)
*
extern int errfmt(Fmt *f);
*/
/*
* quoted strings
*/
extern char *unquotestrdup(char*);
extern Rune *unquoterunestrdup(Rune*);
extern char *quotestrdup(char*);
extern Rune *quoterunestrdup(Rune*);
/*
* in fmt.h
*
extern void quotefmtinstall(void);
extern int quotestrfmt(Fmt*);
extern int quoterunestrfmt(Fmt*);
*/
#ifndef NOPLAN9DEFINES
#define doquote fmtdoquote
#endif
extern int needsrcquote(int);
/*
* random number (in <stdlib.h>)
*
extern void srand(long);
extern int rand(void);
*/
extern int nrand(int);
extern long lrand(void);
extern long lnrand(long);
extern double frand(void);
extern ulong truerand(void); /* uses /dev/random */
extern ulong ntruerand(ulong); /* uses /dev/random */
/*
* math
*/
extern ulong getfcr(void);
extern void setfsr(ulong);
extern ulong getfsr(void);
extern void setfcr(ulong);
extern double NaN(void);
extern double Inf(int);
extern int isNaN(double);
extern int isInf(double, int);
extern ulong umuldiv(ulong, ulong, ulong);
extern long muldiv(long, long, long);
/*
* provided by math.h
*
extern double pow(double, double);
extern double atan2(double, double);
extern double fabs(double);
extern double atan(double);
extern double log(double);
extern double log10(double);
extern double exp(double);
extern double floor(double);
extern double ceil(double);
extern double hypot(double, double);
extern double sin(double);
extern double cos(double);
extern double tan(double);
extern double asin(double);
extern double acos(double);
extern double sinh(double);
extern double cosh(double);
extern double tanh(double);
extern double sqrt(double);
extern double fmod(double, double);
#define HUGE 3.4028234e38
#define PIO2 1.570796326794896619231e0
#define PI (PIO2+PIO2)
*/
#define PI M_PI
#define PIO2 M_PI_2
/*
* Time-of-day
*/
typedef
struct Tm
{
int sec;
int min;
int hour;
int mday;
int mon;
int year;
int wday;
int yday;
char zone[4];
int tzoff;
} Tm;
extern Tm* p9gmtime(long);
extern Tm* p9localtime(long);
extern char* p9asctime(Tm*);
extern char* p9ctime(long);
extern double p9cputime(void);
extern long p9times(long*);
extern long p9tm2sec(Tm*);
extern vlong p9nsec(void);
#ifndef NOPLAN9DEFINES
#define gmtime p9gmtime
#define localtime p9localtime
#define asctime p9asctime
#define ctime p9ctime
#define cputime p9cputime
#define times p9times
#define tm2sec p9tm2sec
#define nsec p9nsec
#endif
/*
* one-of-a-kind
*/
enum
{
PNPROC = 1,
PNGROUP = 2,
};
/* extern int abs(int); <stdlib.h> */
extern int p9atexit(void(*)(void));
extern void p9atexitdont(void(*)(void));
extern int atnotify(int(*)(void*, char*), int);
/*
* <stdlib.h>
extern double atof(char*); <stdlib.h>
extern int atoi(char*);
extern long atol(char*);
*/
extern vlong atoll(const char*);
extern double charstod(int(*)(void*), void*);
extern char* cleanname(char*);
extern int p9decrypt(void*, void*, int);
extern int p9encrypt(void*, void*, int);
extern int dec64(uchar*, int, char*, int);
extern int enc64(char*, int, uchar*, int);
extern int dec32(uchar*, int, char*, int);
extern int enc32(char*, int, uchar*, int);
extern int dec16(uchar*, int, char*, int);
extern int enc16(char*, int, uchar*, int);
extern int encodefmt(Fmt*);
extern int dirmodefmt(Fmt*);
extern void exits(char*);
extern double frexp(double, int*);
extern ulong getcallerpc(void*);
extern char* p9getenv(char*);
extern int p9putenv(char*, char*);
extern int getfields(char*, char**, int, int, char*);
extern int gettokens(char *, char **, int, char *);
extern char* getuser(void);
extern char* p9getwd(char*, int);
extern int iounit(int);
/* extern long labs(long); <math.h> */
/* extern double ldexp(double, int); <math.h> */
extern void p9longjmp(p9jmp_buf, int);
extern char* mktemp(char*);
extern int opentemp(char*);
/* extern double modf(double, double*); <math.h> */
extern int netcrypt(void*, void*);
extern void p9notejmp(void*, p9jmp_buf, int);
extern void perror(const char*);
extern int postnote(int, int, char *);
extern double pow10(int);
/* extern int putenv(char*, char*); <stdlib.h. */
/* extern void qsort(void*, long, long, int (*)(void*, void*)); <stdlib.h> */
/* extern int p9setjmp(p9jmp_buf); */
#define p9setjmp(b) sigsetjmp((void*)(b), 1)
/*
* <stdlib.h>
extern double strtod(char*, char**);
extern long strtol(char*, char**, int);
extern ulong strtoul(char*, char**, int);
extern vlong strtoll(char*, char**, int);
extern uvlong strtoull(char*, char**, int);
*/
extern void sysfatal(char*, ...);
extern void p9syslog(int, char*, char*, ...);
extern long time(long*);
/* extern int tolower(int); <ctype.h> */
/* extern int toupper(int); <ctype.h> */
#ifndef NOPLAN9DEFINES
#define atexit p9atexit
#define atexitdont p9atexitdont
#define encrypt p9encrypt
#define decrypt p9decrypt
#define getenv p9getenv
#define getwd p9getwd
#define longjmp p9longjmp
#undef setjmp
#define setjmp p9setjmp
#define putenv p9putenv
#define notejmp p9notejmp
#define jmp_buf p9jmp_buf
#define syslog p9syslog
#endif
/*
* synchronization
*/
typedef
struct Lock {
int val;
} Lock;
extern int _tas(int*);
extern void lock(Lock*);
extern void unlock(Lock*);
extern int canlock(Lock*);
typedef struct QLp QLp;
struct QLp
{
int inuse;
QLp *next;
char state;
};
typedef
struct QLock
{
Lock lock;
int locked;
QLp *head;
QLp *tail;
} QLock;
extern void qlock(QLock*);
extern void qunlock(QLock*);
extern int canqlock(QLock*);
extern void _qlockinit(ulong (*)(ulong, ulong)); /* called only by the thread library */
typedef
struct RWLock
{
Lock lock;
int readers; /* number of readers */
int writer; /* number of writers */
QLp *head; /* list of waiting processes */
QLp *tail;
} RWLock;
extern void rlock(RWLock*);
extern void runlock(RWLock*);
extern int canrlock(RWLock*);
extern void wlock(RWLock*);
extern void wunlock(RWLock*);
extern int canwlock(RWLock*);
typedef
struct Rendez
{
QLock *l;
QLp *head;
QLp *tail;
} Rendez;
extern void rsleep(Rendez*); /* unlocks r->l, sleeps, locks r->l again */
extern int rwakeup(Rendez*);
extern int rwakeupall(Rendez*);
extern void** privalloc(void);
extern void privfree(void**);
/*
* network dialing
*/
#define NETPATHLEN 40
extern int p9accept(int, char*);
extern int p9announce(char*, char*);
extern int p9dial(char*, char*, char*, int*);
extern void p9setnetmtpt(char*, int, char*);
extern int p9hangup(int);
extern int p9listen(char*, char*);
extern char* p9netmkaddr(char*, char*, char*);
extern int p9reject(int, char*, char*);
#ifndef NOPLAN9DEFINES
#define accept p9accept
#define announce p9announce
#define dial p9dial
#define setnetmtpt p9setnetmtpt
#define hangup p9hangup
#define listen p9listen
#define netmkaddr p9netmkaddr
#define reject p9reject
#endif
/*
* encryption
*/
extern int pushssl(int, char*, char*, char*, int*);
extern int pushtls(int, char*, char*, int, char*, char*);
/*
* network services
*/
typedef struct NetConnInfo NetConnInfo;
struct NetConnInfo
{
char *dir; /* connection directory */
char *root; /* network root */
char *spec; /* binding spec */
char *lsys; /* local system */
char *lserv; /* local service */
char *rsys; /* remote system */
char *rserv; /* remote service */
};
extern NetConnInfo* getnetconninfo(char*, int);
extern void freenetconninfo(NetConnInfo*);
/*
* system calls
*
*/
#define STATMAX 65535U /* max length of machine-independent stat structure */
#define DIRMAX (sizeof(Dir)+STATMAX) /* max length of Dir structure */
#define ERRMAX 128 /* max length of error string */
#define MORDER 0x0003 /* mask for bits defining order of mounting */
#define MREPL 0x0000 /* mount replaces object */
#define MBEFORE 0x0001 /* mount goes before others in union directory */
#define MAFTER 0x0002 /* mount goes after others in union directory */
#define MCREATE 0x0004 /* permit creation in mounted directory */
#define MCACHE 0x0010 /* cache some data */
#define MMASK 0x0017 /* all bits on */
#define OREAD 0 /* open for read */
#define OWRITE 1 /* write */
#define ORDWR 2 /* read and write */
#define OEXEC 3 /* execute, == read but check execute permission */
#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
#define OCEXEC 32 /* or'ed in, close on exec */
#define ORCLOSE 64 /* or'ed in, remove on close */
#define OEXCL 0x1000 /* or'ed in, exclusive use (create only) */
#define AEXIST 0 /* accessible: exists */
#define AEXEC 1 /* execute access */
#define AWRITE 2 /* write access */
#define AREAD 4 /* read access */
/* Segattch */
#define SG_RONLY 0040 /* read only */
#define SG_CEXEC 0100 /* detach on exec */
#define NCONT 0 /* continue after note */
#define NDFLT 1 /* terminate after note */
#define NSAVE 2 /* clear note but hold state */
#define NRSTR 3 /* restore saved state */
/* bits in Qid.type */
#define QTDIR 0x80 /* type bit for directories */
#define QTAPPEND 0x40 /* type bit for append only files */
#define QTEXCL 0x20 /* type bit for exclusive use files */
#define QTMOUNT 0x10 /* type bit for mounted channel */
#define QTAUTH 0x08 /* type bit for authentication file */
#define QTFILE 0x00 /* plain file */
/* bits in Dir.mode */
#define DMDIR 0x80000000 /* mode bit for directories */
#define DMAPPEND 0x40000000 /* mode bit for append only files */
#define DMEXCL 0x20000000 /* mode bit for exclusive use files */
#define DMMOUNT 0x10000000 /* mode bit for mounted channel */
#define DMAUTH 0x08000000 /* mode bit for authentication file */
#define DMREAD 0x4 /* mode bit for read permission */
#define DMWRITE 0x2 /* mode bit for write permission */
#define DMEXEC 0x1 /* mode bit for execute permission */
#if defined(__FreeBSD__)
#undef RFFDG
#undef RFNOTEG
#undef RFPROC
#undef RFMEM
#undef RFNOWAIT
#undef RFCFDG
#undef RFNAMEG
#undef RFENVG
#undef RFCENVG
#undef RFCFDG
#undef RFCNAMEG
#endif
enum
{
RFNAMEG = (1<<0),
RFENVG = (1<<1),
RFFDG = (1<<2),
RFNOTEG = (1<<3),
RFPROC = (1<<4),
RFMEM = (1<<5),
RFNOWAIT = (1<<6),
RFCNAMEG = (1<<10),
RFCENVG = (1<<11),
RFCFDG = (1<<12),
/* RFREND = (1<<13), */
/* RFNOMNT = (1<<14) */
};
extern int ffork(int, void(*)(void*), void*);
typedef
struct Qid
{
uvlong path;
ulong vers;
uchar type;
} Qid;
typedef
struct Dir {
/* system-modified data */
ushort type; /* server type */
uint dev; /* server subtype */
/* file data */
Qid qid; /* unique id from server */
ulong mode; /* permissions */
ulong atime; /* last read time */
ulong mtime; /* last write time */
vlong length; /* file length */
char *name; /* last element of path */
char *uid; /* owner name */
char *gid; /* group name */
char *muid; /* last modifier name */
} Dir;
/* keep /sys/src/ape/lib/ap/plan9/sys9.h in sync with this -rsc */
typedef
struct Waitmsg
{
int pid; /* of loved one */
ulong time[3]; /* of loved one & descendants */
char *msg;
} Waitmsg;
typedef
struct IOchunk
{
void *addr;
ulong len;
} IOchunk;
extern void _exits(char*);
extern void abort(void);
extern int p9access(char*, int);
extern long p9alarm(ulong);
extern int await(char*, int);
extern int awaitnohang(char*, int);
/* extern int bind(char*, char*, int); give up */
/* extern int brk(void*); <unistd.h> */
extern int p9chdir(char*);
extern int close(int);
extern int p9create(char*, int, ulong);
extern int p9dup(int, int);
extern int errstr(char*, uint);
extern int p9exec(char*, char*[]);
/* extern int execl(char*, ...); <unistd.h> */
/* extern int fork(void); <unistd.h> */
extern int p9rfork(int);
/* not implemented
extern int fauth(int, char*);
extern int fstat(int, uchar*, int);
extern int fwstat(int, uchar*, int);
extern int fversion(int, int, char*, int);
extern int mount(int, int, char*, int, char*);
extern int unmount(char*, char*);
*/
extern int noted(int);
extern int notify(void(*)(void*, char*));
extern int p9open(char*, int);
extern int fd2path(int, char*, int);
extern int p9pipe(int*);
/*
* use defs from <unistd.h>
extern long pread(int, void*, long, vlong);
extern long preadv(int, IOchunk*, int, vlong);
extern long pwrite(int, void*, long, vlong);
extern long pwritev(int, IOchunk*, int, vlong);
extern long read(int, void*, long);
*/
extern long readn(int, void*, long);
/* extern long readv(int, IOchunk*, int); <unistd.h> */
extern int remove(const char*);
/* extern void* sbrk(ulong); <unistd.h> */
/* extern long oseek(int, long, int); */
extern vlong p9seek(int, vlong, int);
/* give up
extern long segattach(int, char*, void*, ulong);
extern int segbrk(void*, void*);
extern int segdetach(void*);
extern int segflush(void*, ulong);
extern int segfree(void*, ulong);
*/
extern int p9sleep(long);
/* extern int stat(char*, uchar*, int); give up */
extern Waitmsg* p9wait(void);
extern Waitmsg* waitnohang(void);
extern int p9waitpid(void);
/* <unistd.h>
extern long write(int, void*, long);
extern long writev(int, IOchunk*, int);
*/
/* extern int wstat(char*, uchar*, int); give up */
extern ulong rendezvous(ulong, ulong);
#ifndef NOPLAN9DEFINES
#define alarm p9alarm
#define dup p9dup
#define exec p9exec
#define seek p9seek
#define sleep p9sleep
#define wait p9wait
#define waitpid p9waitpid
#define rfork p9rfork
#define access p9access
#define create p9create
#define open p9open
#define pipe p9pipe
#endif
extern Dir* dirstat(char*);
extern Dir* dirfstat(int);
extern int dirwstat(char*, Dir*);
extern int dirfwstat(int, Dir*);
extern long dirread(int, Dir**);
extern void nulldir(Dir*);
extern long dirreadall(int, Dir**);
/* extern int getpid(void); <unistd.h> */
/* extern int getppid(void); */
extern void rerrstr(char*, uint);
extern char* sysname(void);
extern void werrstr(char*, ...);
extern char* getns(void);
extern int sendfd(int, int);
extern int recvfd(int);
extern int post9pservice(int, char*);
/* external names that we don't want to step on */
#ifndef NOPLAN9DEFINES
#define main p9main
#endif
/* compiler directives on plan 9 */
#define USED(x) if(x){}else{}
#define SET(x) ((x)=0)
/* command line */
extern char *argv0;
extern void __fixargv0(void);
#define ARGBEGIN for((argv0?0:(argv0=(__fixargv0(),*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
#if defined(__cplusplus)
}
#endif
#endif /* _LIB9_H_ */

View file

@ -43,4 +43,4 @@ typedef struct Sinstack Sinstack;
extern char *s_rdinstack(Sinstack*, String*); extern char *s_rdinstack(Sinstack*, String*);
extern Sinstack *s_allocinstack(char*); extern Sinstack *s_allocinstack(char*);
extern void s_freeinstack(Sinstack*); extern void s_freeinstack(Sinstack*);
#endif BGETC #endif /* BGETC */

View file

@ -1,2 +1,794 @@
#include <lib9.h> /*
* Lib9 is miscellany from the Plan 9 C library that doesn't
* fit into libutf or into libfmt, but is still missing from traditional
* Unix C libraries.
*/
#ifndef _LIBC_H_
#define _LIBC_H_ 1
#if defined(__cplusplus)
extern "C" {
#endif
/*
* Begin usual libc.h
*/
#define nil ((void*)0)
#define nelem(x) (sizeof(x)/sizeof((x)[0]))
#ifndef offsetof
#define offsetof(s, m) (ulong)(&(((s*)0)->m))
#endif
/*
* mem routines (provided by system <string.h>)
*
extern void* memccpy(void*, void*, int, ulong);
extern void* memset(void*, int, ulong);
extern int memcmp(void*, void*, ulong);
extern void* memcpy(void*, void*, ulong);
extern void* memmove(void*, void*, ulong);
extern void* memchr(void*, int, ulong);
*/
/*
* string routines (provided by system <string.h>)
*
extern char* strcat(char*, char*);
extern char* strchr(char*, int);
extern int strcmp(char*, char*);
extern char* strcpy(char*, char*);
*/
extern char* strecpy(char*, char*, char*);
/*
extern char* strdup(char*);
extern char* strncat(char*, char*, long);
extern char* strncpy(char*, char*, long);
extern int strncmp(char*, char*, long);
extern char* strpbrk(char*, char*);
extern char* strrchr(char*, int);
extern char* strtok(char*, char*);
extern long strlen(char*);
extern long strspn(char*, char*);
extern long strcspn(char*, char*);
extern char* strstr(char*, char*);
*/
extern int cistrncmp(char*, char*, int);
extern int cistrcmp(char*, char*);
extern char* cistrstr(char*, char*);
extern int tokenize(char*, char**, int);
/*
enum
{
UTFmax = 3,
Runesync = 0x80,
Runeself = 0x80,
Runeerror = 0x80,
};
*/
/*
* rune routines (provided by <utf.h>
*
extern int runetochar(char*, Rune*);
extern int chartorune(Rune*, char*);
extern int runelen(long);
extern int runenlen(Rune*, int);
extern int fullrune(char*, int);
extern int utflen(char*);
extern int utfnlen(char*, long);
extern char* utfrune(char*, long);
extern char* utfrrune(char*, long);
extern char* utfutf(char*, char*);
extern char* utfecpy(char*, char*, char*);
extern Rune* runestrcat(Rune*, Rune*);
extern Rune* runestrchr(Rune*, Rune);
extern int runestrcmp(Rune*, Rune*);
extern Rune* runestrcpy(Rune*, Rune*);
extern Rune* runestrncpy(Rune*, Rune*, long);
extern Rune* runestrecpy(Rune*, Rune*, Rune*);
extern Rune* runestrdup(Rune*);
extern Rune* runestrncat(Rune*, Rune*, long);
extern int runestrncmp(Rune*, Rune*, long);
extern Rune* runestrrchr(Rune*, Rune);
extern long runestrlen(Rune*);
extern Rune* runestrstr(Rune*, Rune*);
extern Rune tolowerrune(Rune);
extern Rune totitlerune(Rune);
extern Rune toupperrune(Rune);
extern int isalpharune(Rune);
extern int islowerrune(Rune);
extern int isspacerune(Rune);
extern int istitlerune(Rune);
extern int isupperrune(Rune);
*/
/*
* malloc (provied by system <stdlib.h>)
*
extern void* malloc(ulong);
*/
extern void* p9malloc(ulong);
extern void* mallocz(ulong, int);
/*
extern void free(void*);
extern ulong msize(void*);
extern void* calloc(ulong, ulong);
extern void* realloc(void*, ulong);
*/
extern void setmalloctag(void*, ulong);
extern void setrealloctag(void*, ulong);
extern ulong getmalloctag(void*);
extern ulong getrealloctag(void*);
/*
extern void* malloctopoolblock(void*);
*/
#ifndef NOPLAN9DEFINES
#define malloc p9malloc
#endif
/*
* print routines (provided by <fmt.h>)
*
typedef struct Fmt Fmt;
struct Fmt{
uchar runes;
void *start;
void *to;
void *stop;
int (*flush)(Fmt *);
void *farg;
int nfmt;
va_list args;
int r;
int width;
int prec;
ulong flags;
};
enum{
FmtWidth = 1,
FmtLeft = FmtWidth << 1,
FmtPrec = FmtLeft << 1,
FmtSharp = FmtPrec << 1,
FmtSpace = FmtSharp << 1,
FmtSign = FmtSpace << 1,
FmtZero = FmtSign << 1,
FmtUnsigned = FmtZero << 1,
FmtShort = FmtUnsigned << 1,
FmtLong = FmtShort << 1,
FmtVLong = FmtLong << 1,
FmtComma = FmtVLong << 1,
FmtByte = FmtComma << 1,
FmtFlag = FmtByte << 1
};
extern int print(char*, ...);
extern char* seprint(char*, char*, char*, ...);
extern char* vseprint(char*, char*, char*, va_list);
extern int snprint(char*, int, char*, ...);
extern int vsnprint(char*, int, char*, va_list);
extern char* smprint(char*, ...);
extern char* vsmprint(char*, va_list);
extern int sprint(char*, char*, ...);
extern int fprint(int, char*, ...);
extern int vfprint(int, char*, va_list);
extern int runesprint(Rune*, char*, ...);
extern int runesnprint(Rune*, int, char*, ...);
extern int runevsnprint(Rune*, int, char*, va_list);
extern Rune* runeseprint(Rune*, Rune*, char*, ...);
extern Rune* runevseprint(Rune*, Rune*, char*, va_list);
extern Rune* runesmprint(char*, ...);
extern Rune* runevsmprint(char*, va_list);
extern int fmtfdinit(Fmt*, int, char*, int);
extern int fmtfdflush(Fmt*);
extern int fmtstrinit(Fmt*);
extern char* fmtstrflush(Fmt*);
extern int runefmtstrinit(Fmt*);
extern Rune* runefmtstrflush(Fmt*);
extern int fmtinstall(int, int (*)(Fmt*));
extern int dofmt(Fmt*, char*);
extern int dorfmt(Fmt*, Rune*);
extern int fmtprint(Fmt*, char*, ...);
extern int fmtvprint(Fmt*, char*, va_list);
extern int fmtrune(Fmt*, int);
extern int fmtstrcpy(Fmt*, char*);
extern int fmtrunestrcpy(Fmt*, Rune*);
*/
/*
* error string for %r
* supplied on per os basis, not part of fmt library
*
* (provided by lib9, but declared in fmt.h)
*
extern int errfmt(Fmt *f);
*/
/*
* quoted strings
*/
extern char *unquotestrdup(char*);
extern Rune *unquoterunestrdup(Rune*);
extern char *quotestrdup(char*);
extern Rune *quoterunestrdup(Rune*);
/*
* in fmt.h
*
extern void quotefmtinstall(void);
extern int quotestrfmt(Fmt*);
extern int quoterunestrfmt(Fmt*);
*/
#ifndef NOPLAN9DEFINES
#define doquote fmtdoquote
#endif
extern int needsrcquote(int);
/*
* random number (in <stdlib.h>)
*
extern void srand(long);
extern int rand(void);
*/
extern int nrand(int);
extern long lrand(void);
extern long lnrand(long);
extern double frand(void);
extern ulong truerand(void); /* uses /dev/random */
extern ulong ntruerand(ulong); /* uses /dev/random */
/*
* math
*/
extern ulong getfcr(void);
extern void setfsr(ulong);
extern ulong getfsr(void);
extern void setfcr(ulong);
extern double NaN(void);
extern double Inf(int);
extern int isNaN(double);
extern int isInf(double, int);
extern ulong umuldiv(ulong, ulong, ulong);
extern long muldiv(long, long, long);
/*
* provided by math.h
*
extern double pow(double, double);
extern double atan2(double, double);
extern double fabs(double);
extern double atan(double);
extern double log(double);
extern double log10(double);
extern double exp(double);
extern double floor(double);
extern double ceil(double);
extern double hypot(double, double);
extern double sin(double);
extern double cos(double);
extern double tan(double);
extern double asin(double);
extern double acos(double);
extern double sinh(double);
extern double cosh(double);
extern double tanh(double);
extern double sqrt(double);
extern double fmod(double, double);
#define HUGE 3.4028234e38
#define PIO2 1.570796326794896619231e0
#define PI (PIO2+PIO2)
*/
#define PI M_PI
#define PIO2 M_PI_2
/*
* Time-of-day
*/
typedef
struct Tm
{
int sec;
int min;
int hour;
int mday;
int mon;
int year;
int wday;
int yday;
char zone[4];
int tzoff;
} Tm;
extern Tm* p9gmtime(long);
extern Tm* p9localtime(long);
extern char* p9asctime(Tm*);
extern char* p9ctime(long);
extern double p9cputime(void);
extern long p9times(long*);
extern long p9tm2sec(Tm*);
extern vlong p9nsec(void);
#ifndef NOPLAN9DEFINES
#define gmtime p9gmtime
#define localtime p9localtime
#define asctime p9asctime
#define ctime p9ctime
#define cputime p9cputime
#define times p9times
#define tm2sec p9tm2sec
#define nsec p9nsec
#endif
/*
* one-of-a-kind
*/
enum
{
PNPROC = 1,
PNGROUP = 2,
};
/* extern int abs(int); <stdlib.h> */
extern int p9atexit(void(*)(void));
extern void p9atexitdont(void(*)(void));
extern int atnotify(int(*)(void*, char*), int);
/*
* <stdlib.h>
extern double atof(char*); <stdlib.h>
extern int atoi(char*);
extern long atol(char*);
*/
extern vlong atoll(const char*);
extern double charstod(int(*)(void*), void*);
extern char* cleanname(char*);
extern int p9decrypt(void*, void*, int);
extern int p9encrypt(void*, void*, int);
extern int dec64(uchar*, int, char*, int);
extern int enc64(char*, int, uchar*, int);
extern int dec32(uchar*, int, char*, int);
extern int enc32(char*, int, uchar*, int);
extern int dec16(uchar*, int, char*, int);
extern int enc16(char*, int, uchar*, int);
extern int encodefmt(Fmt*);
extern int dirmodefmt(Fmt*);
extern void exits(char*);
extern double frexp(double, int*);
extern ulong getcallerpc(void*);
extern char* p9getenv(char*);
extern int p9putenv(char*, char*);
extern int getfields(char*, char**, int, int, char*);
extern int gettokens(char *, char **, int, char *);
extern char* getuser(void);
extern char* p9getwd(char*, int);
extern int iounit(int);
/* extern long labs(long); <math.h> */
/* extern double ldexp(double, int); <math.h> */
extern void p9longjmp(p9jmp_buf, int);
extern char* mktemp(char*);
extern int opentemp(char*);
/* extern double modf(double, double*); <math.h> */
extern int netcrypt(void*, void*);
extern void p9notejmp(void*, p9jmp_buf, int);
extern void perror(const char*);
extern int postnote(int, int, char *);
extern double pow10(int);
/* extern int putenv(char*, char*); <stdlib.h. */
/* extern void qsort(void*, long, long, int (*)(void*, void*)); <stdlib.h> */
/* extern int p9setjmp(p9jmp_buf); */
#define p9setjmp(b) sigsetjmp((void*)(b), 1)
/*
* <stdlib.h>
extern double strtod(char*, char**);
extern long strtol(char*, char**, int);
extern ulong strtoul(char*, char**, int);
extern vlong strtoll(char*, char**, int);
extern uvlong strtoull(char*, char**, int);
*/
extern void sysfatal(char*, ...);
extern void p9syslog(int, char*, char*, ...);
extern long p9time(long*);
/* extern int tolower(int); <ctype.h> */
/* extern int toupper(int); <ctype.h> */
#ifndef NOPLAN9DEFINES
#define atexit p9atexit
#define atexitdont p9atexitdont
#define encrypt p9encrypt
#define decrypt p9decrypt
#define getenv p9getenv
#define getwd p9getwd
#define longjmp p9longjmp
#undef setjmp
#define setjmp p9setjmp
#define putenv p9putenv
#define notejmp p9notejmp
#define jmp_buf p9jmp_buf
#define syslog p9syslog
#define time p9time
#endif
/*
* synchronization
*/
typedef
struct Lock {
int val;
} Lock;
extern int _tas(int*);
extern void lock(Lock*);
extern void unlock(Lock*);
extern int canlock(Lock*);
typedef struct QLp QLp;
struct QLp
{
int inuse;
QLp *next;
char state;
};
typedef
struct QLock
{
Lock lock;
int locked;
QLp *head;
QLp *tail;
} QLock;
extern void qlock(QLock*);
extern void qunlock(QLock*);
extern int canqlock(QLock*);
extern void _qlockinit(ulong (*)(ulong, ulong)); /* called only by the thread library */
typedef
struct RWLock
{
Lock lock;
int readers; /* number of readers */
int writer; /* number of writers */
QLp *head; /* list of waiting processes */
QLp *tail;
} RWLock;
extern void rlock(RWLock*);
extern void runlock(RWLock*);
extern int canrlock(RWLock*);
extern void wlock(RWLock*);
extern void wunlock(RWLock*);
extern int canwlock(RWLock*);
typedef
struct Rendez
{
QLock *l;
QLp *head;
QLp *tail;
} Rendez;
extern void rsleep(Rendez*); /* unlocks r->l, sleeps, locks r->l again */
extern int rwakeup(Rendez*);
extern int rwakeupall(Rendez*);
extern void** privalloc(void);
extern void privfree(void**);
/*
* network dialing
*/
#define NETPATHLEN 40
extern int p9accept(int, char*);
extern int p9announce(char*, char*);
extern int p9dial(char*, char*, char*, int*);
extern void p9setnetmtpt(char*, int, char*);
extern int p9hangup(int);
extern int p9listen(char*, char*);
extern char* p9netmkaddr(char*, char*, char*);
extern int p9reject(int, char*, char*);
#ifndef NOPLAN9DEFINES
#define accept p9accept
#define announce p9announce
#define dial p9dial
#define setnetmtpt p9setnetmtpt
#define hangup p9hangup
#define listen p9listen
#define netmkaddr p9netmkaddr
#define reject p9reject
#endif
/*
* encryption
*/
extern int pushssl(int, char*, char*, char*, int*);
extern int pushtls(int, char*, char*, int, char*, char*);
/*
* network services
*/
typedef struct NetConnInfo NetConnInfo;
struct NetConnInfo
{
char *dir; /* connection directory */
char *root; /* network root */
char *spec; /* binding spec */
char *lsys; /* local system */
char *lserv; /* local service */
char *rsys; /* remote system */
char *rserv; /* remote service */
};
extern NetConnInfo* getnetconninfo(char*, int);
extern void freenetconninfo(NetConnInfo*);
/*
* system calls
*
*/
#define STATMAX 65535U /* max length of machine-independent stat structure */
#define DIRMAX (sizeof(Dir)+STATMAX) /* max length of Dir structure */
#define ERRMAX 128 /* max length of error string */
#define MORDER 0x0003 /* mask for bits defining order of mounting */
#define MREPL 0x0000 /* mount replaces object */
#define MBEFORE 0x0001 /* mount goes before others in union directory */
#define MAFTER 0x0002 /* mount goes after others in union directory */
#define MCREATE 0x0004 /* permit creation in mounted directory */
#define MCACHE 0x0010 /* cache some data */
#define MMASK 0x0017 /* all bits on */
#define OREAD 0 /* open for read */
#define OWRITE 1 /* write */
#define ORDWR 2 /* read and write */
#define OEXEC 3 /* execute, == read but check execute permission */
#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
#define OCEXEC 32 /* or'ed in, close on exec */
#define ORCLOSE 64 /* or'ed in, remove on close */
#define OEXCL 0x1000 /* or'ed in, exclusive use (create only) */
#define AEXIST 0 /* accessible: exists */
#define AEXEC 1 /* execute access */
#define AWRITE 2 /* write access */
#define AREAD 4 /* read access */
/* Segattch */
#define SG_RONLY 0040 /* read only */
#define SG_CEXEC 0100 /* detach on exec */
#define NCONT 0 /* continue after note */
#define NDFLT 1 /* terminate after note */
#define NSAVE 2 /* clear note but hold state */
#define NRSTR 3 /* restore saved state */
/* bits in Qid.type */
#define QTDIR 0x80 /* type bit for directories */
#define QTAPPEND 0x40 /* type bit for append only files */
#define QTEXCL 0x20 /* type bit for exclusive use files */
#define QTMOUNT 0x10 /* type bit for mounted channel */
#define QTAUTH 0x08 /* type bit for authentication file */
#define QTFILE 0x00 /* plain file */
/* bits in Dir.mode */
#define DMDIR 0x80000000 /* mode bit for directories */
#define DMAPPEND 0x40000000 /* mode bit for append only files */
#define DMEXCL 0x20000000 /* mode bit for exclusive use files */
#define DMMOUNT 0x10000000 /* mode bit for mounted channel */
#define DMAUTH 0x08000000 /* mode bit for authentication file */
#define DMREAD 0x4 /* mode bit for read permission */
#define DMWRITE 0x2 /* mode bit for write permission */
#define DMEXEC 0x1 /* mode bit for execute permission */
#if defined(__FreeBSD__)
#undef RFFDG
#undef RFNOTEG
#undef RFPROC
#undef RFMEM
#undef RFNOWAIT
#undef RFCFDG
#undef RFNAMEG
#undef RFENVG
#undef RFCENVG
#undef RFCFDG
#undef RFCNAMEG
#endif
enum
{
RFNAMEG = (1<<0),
RFENVG = (1<<1),
RFFDG = (1<<2),
RFNOTEG = (1<<3),
RFPROC = (1<<4),
RFMEM = (1<<5),
RFNOWAIT = (1<<6),
RFCNAMEG = (1<<10),
RFCENVG = (1<<11),
RFCFDG = (1<<12),
/* RFREND = (1<<13), */
/* RFNOMNT = (1<<14) */
};
extern int ffork(int, void(*)(void*), void*);
typedef
struct Qid
{
uvlong path;
ulong vers;
uchar type;
} Qid;
typedef
struct Dir {
/* system-modified data */
ushort type; /* server type */
uint dev; /* server subtype */
/* file data */
Qid qid; /* unique id from server */
ulong mode; /* permissions */
ulong atime; /* last read time */
ulong mtime; /* last write time */
vlong length; /* file length */
char *name; /* last element of path */
char *uid; /* owner name */
char *gid; /* group name */
char *muid; /* last modifier name */
} Dir;
/* keep /sys/src/ape/lib/ap/plan9/sys9.h in sync with this -rsc */
typedef
struct Waitmsg
{
int pid; /* of loved one */
ulong time[3]; /* of loved one & descendants */
char *msg;
} Waitmsg;
typedef
struct IOchunk
{
void *addr;
ulong len;
} IOchunk;
extern void _exits(char*);
extern void abort(void);
extern int p9access(char*, int);
extern long p9alarm(ulong);
extern int await(char*, int);
extern int awaitnohang(char*, int);
/* extern int bind(char*, char*, int); give up */
/* extern int brk(void*); <unistd.h> */
extern int p9chdir(char*);
extern int close(int);
extern int p9create(char*, int, ulong);
extern int p9dup(int, int);
extern int errstr(char*, uint);
extern int p9exec(char*, char*[]);
/* extern int execl(char*, ...); <unistd.h> */
/* extern int fork(void); <unistd.h> */
extern int p9rfork(int);
/* not implemented
extern int fauth(int, char*);
extern int fstat(int, uchar*, int);
extern int fwstat(int, uchar*, int);
extern int fversion(int, int, char*, int);
extern int mount(int, int, char*, int, char*);
extern int unmount(char*, char*);
*/
extern int noted(int);
extern int notify(void(*)(void*, char*));
extern int p9open(char*, int);
extern int fd2path(int, char*, int);
extern int p9pipe(int*);
/*
* use defs from <unistd.h>
extern long pread(int, void*, long, vlong);
extern long preadv(int, IOchunk*, int, vlong);
extern long pwrite(int, void*, long, vlong);
extern long pwritev(int, IOchunk*, int, vlong);
extern long read(int, void*, long);
*/
extern long readn(int, void*, long);
/* extern long readv(int, IOchunk*, int); <unistd.h> */
extern int remove(const char*);
/* extern void* sbrk(ulong); <unistd.h> */
/* extern long oseek(int, long, int); */
extern vlong p9seek(int, vlong, int);
/* give up
extern long segattach(int, char*, void*, ulong);
extern int segbrk(void*, void*);
extern int segdetach(void*);
extern int segflush(void*, ulong);
extern int segfree(void*, ulong);
*/
extern int p9sleep(long);
/* extern int stat(char*, uchar*, int); give up */
extern Waitmsg* p9wait(void);
extern Waitmsg* waitnohang(void);
extern int p9waitpid(void);
/* <unistd.h>
extern long write(int, void*, long);
extern long writev(int, IOchunk*, int);
*/
/* extern int wstat(char*, uchar*, int); give up */
extern ulong rendezvous(ulong, ulong);
#ifndef NOPLAN9DEFINES
#define alarm p9alarm
#define dup p9dup
#define exec p9exec
#define seek p9seek
#define sleep p9sleep
#define wait p9wait
#define waitpid p9waitpid
#define rfork p9rfork
#define access p9access
#define create p9create
#define open p9open
#define pipe p9pipe
#endif
extern Dir* dirstat(char*);
extern Dir* dirfstat(int);
extern int dirwstat(char*, Dir*);
extern int dirfwstat(int, Dir*);
extern long dirread(int, Dir**);
extern void nulldir(Dir*);
extern long dirreadall(int, Dir**);
/* extern int getpid(void); <unistd.h> */
/* extern int getppid(void); */
extern void rerrstr(char*, uint);
extern char* sysname(void);
extern void werrstr(char*, ...);
extern char* getns(void);
extern char* get9root(void);
extern char* unsharp(char*);
extern int sendfd(int, int);
extern int recvfd(int);
extern int post9pservice(int, char*);
/* external names that we don't want to step on */
#ifndef NOPLAN9DEFINES
#define main p9main
#endif
/* compiler directives on plan 9 */
#define USED(x) if(x){}else{}
#define SET(x) ((x)=0)
/* command line */
extern char *argv0;
extern void __fixargv0(void);
#define ARGBEGIN for((argv0?0:(argv0=(__fixargv0(),*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
#if defined(__cplusplus)
}
#endif
#endif /* _LIB9_H_ */

View file

@ -0,0 +1,93 @@
#ifndef _U_H_
#define _U_H_ 1
#if defined(__cplusplus)
extern "C" {
#endif
#define _BSD_SOURCE 1
#define _SVID_SOURCE 1
#define _XOPEN_SOURCE 1000
#define _XOPEN_SOURCE_EXTENDED 1
#define _LARGEFILE64_SOURCE 1
#define _FILE_OFFSET_BITS 64
#define __EXTENSIONS__ 1 /* SunOS */
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <assert.h>
#include <setjmp.h>
#include <stddef.h>
#include <utf.h>
#include <fmt.h>
#include <math.h>
/*
* OS-specific crap
*/
#define _NEEDUCHAR 1
#define _NEEDUSHORT 1
#define _NEEDUINT 1
#define _NEEDULONG 1
typedef long p9jmp_buf[sizeof(sigjmp_buf)/sizeof(long)];
#if defined(__linux__)
# include <sys/types.h>
# if defined(__USE_MISC)
# undef _NEEDUSHORT
# undef _NEEDUINT
# undef _NEEDULONG
# endif
#endif
#if defined(__sun__)
# include <sys/types.h>
# undef _NEEDUSHORT
# undef _NEEDUINT
# undef _NEEDULONG
#endif
#if defined(__FreeBSD__)
# include <sys/types.h>
# if !defined(_POSIX_SOURCE)
# undef _NEEDUSHORT
# undef _NEEDUINT
# endif
#endif
#if defined(__APPLE__)
# include <sys/types.h>
# undef _NEEDUSHORT
# undef _NEEDUINT
# define _NEEDLL 1
#endif
typedef signed char schar;
typedef unsigned int u32int;
#ifdef _NEEDUCHAR
typedef unsigned char uchar;
#endif
#ifdef _NEEDUSHORT
typedef unsigned short ushort;
#endif
#ifdef _NEEDUINT
typedef unsigned int uint;
#endif
#ifdef _NEEDULONG
typedef unsigned long ulong;
#endif
typedef unsigned long long uvlong;
typedef long long vlong;
typedef uvlong u64int;
typedef uchar u8int;
typedef ushort u16int;
#undef _NEEDUCHAR
#undef _NEEDUSHORT
#undef _NEEDUINT
#undef _NEEDULONG
#if defined(__cplusplus)
}
#endif
#endif

View file

@ -1150,7 +1150,7 @@ rewritehdr(Fcall *f, uchar *pkt)
} }
} }
#ifdef _LIB9_H_ #ifdef _LIBC_H_
/* unix select-based polling */ /* unix select-based polling */
struct Ioproc struct Ioproc
{ {

View file

@ -1,15 +1,24 @@
#include "9term.h" #include <u.h>
#include <libc.h>
#define fatal sysfatal #include <ctype.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <cursor.h>
#include <keyboard.h>
#include <frame.h>
#include <plumb.h>
#include <complete.h>
#include "term.h"
typedef struct Text Text; typedef struct Text Text;
typedef struct Readbuf Readbuf; typedef struct Readbuf Readbuf;
enum enum
{ {
/* these are chosen to use malloc()'s properties well */
HiWater = 640000, /* max size of history */ HiWater = 640000, /* max size of history */
LoWater = 330000, /* min size of history after max'ed */ LoWater = 400000, /* min size of history after max'ed */
MinWater = 20000,
}; };
/* various geometric paramters */ /* various geometric paramters */
@ -30,21 +39,22 @@ enum
Scroll, Scroll,
}; };
#define SCROLLKEY Kdown
#define ESC 0x1B #define ESC 0x1B
#define CUT 0x18 /* ctrl-x */ #define CUT 0x18 /* ctrl-x */
#define COPY 0x03 /* crtl-c */ #define COPY 0x03 /* crtl-c */
#define PASTE 0x16 /* crtl-v */ #define PASTE 0x16 /* crtl-v */
#define BACKSCROLLKEY Kup
#define READBUFSIZE 8192 #define READBUFSIZE 8192
#define TRUE 1
#define FALSE 0
struct Text struct Text
{ {
Frame *f; /* frame ofr terminal */ Frame *f; /* frame ofr terminal */
Mouse m; Mouse m;
uint nr; /* num of runes in term */ uint nr; /* num of runes in term */
uint maxr; /* max num of runes in r */
Rune *r; /* runes for term */ Rune *r; /* runes for term */
uint nraw; /* num of runes in raw buffer */ uint nraw; /* num of runes in raw buffer */
Rune *raw; /* raw buffer */ Rune *raw; /* raw buffer */
@ -72,7 +82,6 @@ void fill(void);
void tcheck(void); void tcheck(void);
void updatesel(void); void updatesel(void);
void doreshape(void); void doreshape(void);
void rcstart(int fd[2], int, char**);
void runewrite(Rune*, int); void runewrite(Rune*, int);
void consread(void); void consread(void);
void conswrite(char*, int); void conswrite(char*, int);
@ -99,11 +108,10 @@ void scrdraw(void);
void scroll(int); void scroll(int);
void hostproc(void *arg); void hostproc(void *arg);
void hoststart(void); void hoststart(void);
int getchildwd(int, char*, int);
void plumbstart(void); void plumbstart(void);
void plumb(uint, uint); void plumb(uint, uint);
void plumbclick(uint*, uint*); void plumbclick(uint*, uint*);
int getpts(int fd[], char *slave); uint insert(Rune*, int, uint, int);
#define runemalloc(n) malloc((n)*sizeof(Rune)) #define runemalloc(n) malloc((n)*sizeof(Rune))
#define runerealloc(a, n) realloc(a, (n)*sizeof(Rune)) #define runerealloc(a, n) realloc(a, (n)*sizeof(Rune))
@ -115,7 +123,7 @@ int rawon; /* raw mode */
int scrolling; /* window scrolls */ int scrolling; /* window scrolls */
int clickmsec; /* time of last click */ int clickmsec; /* time of last click */
uint clickq0; /* point of last click */ uint clickq0; /* point of last click */
int rcfd[2]; int rcfd;
int rcpid; int rcpid;
int maxtab; int maxtab;
int use9wm; int use9wm;
@ -211,7 +219,7 @@ threadmain(int argc, char *argv[])
mc = initmouse(nil, screen); mc = initmouse(nil, screen);
kc = initkeyboard(nil); kc = initkeyboard(nil);
rcstart(rcfd, argc, argv); rcpid = rcstart(argc, argv, &rcfd);
hoststart(); hoststart();
plumbstart(); plumbstart();
@ -265,8 +273,9 @@ hostproc(void *arg)
i = 0; i = 0;
for(;;){ for(;;){
/* Let typing have a go -- maybe there's a rubout waiting. */
i = 1-i; /* toggle */ i = 1-i; /* toggle */
n = threadread(rcfd[0], rcbuf[i].data, sizeof rcbuf[i].data); n = threadread(rcfd, rcbuf[i].data, sizeof rcbuf[i].data);
if(n <= 0){ if(n <= 0){
if(n < 0) if(n < 0)
fprint(2, "9term: host read error: %r\n"); fprint(2, "9term: host read error: %r\n");
@ -308,7 +317,7 @@ loop(void)
a[2].op = CHANNOP;; a[2].op = CHANNOP;;
switch(alt(a)) { switch(alt(a)) {
default: default:
fatal("impossible"); sysfatal("impossible");
case 0: case 0:
t.m = mc->m; t.m = mc->m;
mouse(); mouse();
@ -330,23 +339,23 @@ void
doreshape(void) doreshape(void)
{ {
if(getwindow(display, Refnone) < 0) if(getwindow(display, Refnone) < 0)
fatal("can't reattach to window"); sysfatal("can't reattach to window");
draw(screen, screen->r, cols[BACK], nil, ZP); draw(screen, screen->r, cols[BACK], nil, ZP);
geom(); geom();
scrdraw(); scrdraw();
} }
struct winsize ows;
void void
geom(void) geom(void)
{ {
struct winsize ws;
Point p; Point p;
Rectangle r; Rectangle r;
r = screen->r; r = screen->r;
scrollr = screen->r; r.min.y++;
r.max.y--;
scrollr = r;
scrollr.max.x = r.min.x+Scrollwid; scrollr.max.x = r.min.x+Scrollwid;
lastsr = Rect(0,0,0,0); lastsr = Rect(0,0,0,0);
@ -362,13 +371,7 @@ geom(void)
if(p.x == 0 || p.y == 0) if(p.x == 0 || p.y == 0)
return; return;
ws.ws_row = Dy(r)/p.y; updatewinsize(Dy(r)/p.y, Dx(r)/p.x, Dx(r), Dy(r));
ws.ws_col = Dx(r)/p.x;
ws.ws_xpixel = Dx(r);
ws.ws_ypixel = Dy(r);
if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col)
if(ioctl(rcfd[0], TIOCSWINSZ, &ws) < 0)
fprint(2, "ioctl: %r\n");
} }
void void
@ -585,7 +588,10 @@ domenu2(int but)
show(t.q0); show(t.q0);
break; break;
case Send: case Send:
snarf(); if(t.q0 != t.q1)
snarf();
else
snarfupdate();
t.q0 = t.q1 = t.nr; t.q0 = t.q1 = t.nr;
updatesel(); updatesel();
paste(t.snarf, t.nsnarf, 1); paste(t.snarf, t.nsnarf, 1);
@ -605,37 +611,182 @@ domenu2(int but)
plumb(t.q0, t.q1); plumb(t.q0, t.q1);
break; break;
default: default:
fatal("bad menu item"); sysfatal("bad menu item");
} }
} }
int
windfilewidth(uint q0, int oneelement)
{
uint q;
Rune r;
q = q0;
while(q > 0){
r = t.r[q-1];
if(r<=' ')
break;
if(oneelement && r=='/')
break;
--q;
}
return q0-q;
}
void
showcandidates(Completion *c)
{
int i;
Fmt f;
Rune *rp;
uint nr, qline, q0;
char *s;
runefmtstrinit(&f);
if (c->nmatch == 0)
s = "[no matches in ";
else
s = "[";
if(c->nfile > 32)
fmtprint(&f, "%s%d files]\n", s, c->nfile);
else{
fmtprint(&f, "%s", s);
for(i=0; i<c->nfile; i++){
if(i > 0)
fmtprint(&f, " ");
fmtprint(&f, "%s", c->filename[i]);
}
fmtprint(&f, "]\n");
}
/* place text at beginning of line before host point */
qline = t.qh;
while(qline>0 && t.r[qline-1] != '\n')
qline--;
rp = runefmtstrflush(&f);
nr = runestrlen(rp);
q0 = t.q0;
q0 += insert(rp, nr, qline, 0) - qline;
free(rp);
t.q0 = q0+nr;
t.q1 = q0+nr;
updatesel();
}
Rune*
namecomplete(void)
{
int nstr, npath;
Rune *rp, *path, *str;
Completion *c;
char *s, *dir, *root;
/* control-f: filename completion; works back to white space or / */
if(t.q0<t.nr && t.r[t.q0]>' ') /* must be at end of word */
return nil;
nstr = windfilewidth(t.q0, TRUE);
str = runemalloc(nstr);
runemove(str, t.r+(t.q0-nstr), nstr);
npath = windfilewidth(t.q0-nstr, FALSE);
path = runemalloc(npath);
runemove(path, t.r+(t.q0-nstr-npath), npath);
rp = nil;
/* is path rooted? if not, we need to make it relative to window path */
if(npath>0 && path[0]=='/'){
dir = malloc(UTFmax*npath+1);
sprint(dir, "%.*S", npath, path);
}else{
if(strcmp(wdir, "") == 0)
root = ".";
else
root = wdir;
dir = malloc(strlen(root)+1+UTFmax*npath+1);
sprint(dir, "%s/%.*S", root, npath, path);
}
dir = cleanname(dir);
s = smprint("%.*S", nstr, str);
c = complete(dir, s);
free(s);
if(c == nil)
goto Return;
if(!c->advance)
showcandidates(c);
if(c->advance)
rp = runesmprint("%s", c->string);
Return:
freecompletion(c);
free(dir);
free(path);
free(str);
return rp;
}
void void
key(Rune r) key(Rune r)
{ {
uint sig; Rune *rp;
int nr;
if(r == 0) if(r == 0)
return; return;
if(r==SCROLLKEY){ /* scroll key */ switch(r){
case Kpgup:
setorigin(backnl(t.org, t.f->maxlines*2/3), 1);
return;
case Kpgdown:
setorigin(line2q(t.f->maxlines*2/3), 1); setorigin(line2q(t.f->maxlines*2/3), 1);
if(t.qh<=t.org+t.f->nchars) if(t.qh<=t.org+t.f->nchars)
consread(); consread();
return; return;
}else if(r == BACKSCROLLKEY){ case Kup:
setorigin(backnl(t.org, t.f->maxlines*2/3), 1); setorigin(backnl(t.org, t.f->maxlines/3), 1);
return; return;
}else if(r == CUT){ case Kdown:
setorigin(line2q(t.f->maxlines/3), 1);
if(t.qh<=t.org+t.f->nchars)
consread();
return;
case Kleft:
if(t.q0 > 0){
t.q0--;
t.q1 = t.q0;
updatesel();
show(t.q0);
}
return;
case Kright:
if(t.q1 < t.nr){
t.q1++;
t.q0 = t.q1;
updatesel();
show(t.q1);
}
return;
case Khome:
show(0);
return;
case Kend:
case 0x05:
show(t.nr);
return;
case CUT:
snarf(); snarf();
cut(); cut();
if(scrolling) if(scrolling)
show(t.q0); show(t.q0);
return; return;
}else if(r == COPY){ case COPY:
snarf(); snarf();
if(scrolling) if(scrolling)
show(t.q0); show(t.q0);
return; return;
}else if(r == PASTE){ case PASTE:
snarfupdate(); snarfupdate();
paste(t.snarf, t.nsnarf, 0); paste(t.snarf, t.nsnarf, 0);
if(scrolling) if(scrolling)
@ -661,19 +812,21 @@ key(Rune r)
snarf(); snarf();
switch(r) { switch(r) {
case 0x03: /* ^C: send interrupt */
case 0x7F: /* DEL: send interrupt */ case 0x7F: /* DEL: send interrupt */
t.qh = t.q0 = t.q1 = t.nr; t.qh = t.q0 = t.q1 = t.nr;
show(t.q0); show(t.q0);
goto Default; write(rcfd, "\x7F", 1);
fprint(2, "send interrupt to %d group\n", rcpid);
#ifdef TIOCSIG
sig = 2; /* SIGINT */
if(ioctl(rcfd[0], TIOCSIG, &sig) < 0)
fprint(2, "sending interrupt: %r\n");
#else
postnote(PNGROUP, rcpid, "interrupt");
#endif
break; break;
case 0x06: /* ^F: file name completion */
case Kins: /* Insert: file name completion */
rp = namecomplete();
if(rp == nil)
return;
nr = runestrlen(rp);
paste(rp, nr, 1);
free(rp);
return;
case 0x08: /* ^H: erase character */ case 0x08: /* ^H: erase character */
case 0x15: /* ^U: erase line */ case 0x15: /* ^U: erase line */
case 0x17: /* ^W: erase word */ case 0x17: /* ^W: erase word */
@ -682,7 +835,6 @@ fprint(2, "send interrupt to %d group\n", rcpid);
cut(); cut();
break; break;
default: default:
Default:
paste(&r, 1, 1); paste(&r, 1, 1);
break; break;
} }
@ -773,7 +925,7 @@ consread(void)
} }
/* take out control-d when not doing a zero length write */ /* take out control-d when not doing a zero length write */
n = p-buf; n = p-buf;
if(write(rcfd[1], buf, n) < 0) if(write(rcfd, buf, n) < 0)
exits(0); exits(0);
/* mallocstats(); */ /* mallocstats(); */
} }
@ -833,7 +985,6 @@ conswrite(char *p, int n)
void void
runewrite(Rune *r, int n) runewrite(Rune *r, int n)
{ {
uint m;
int i; int i;
uint initial; uint initial;
uint q0, q1; uint q0, q1;
@ -896,37 +1047,7 @@ runewrite(Rune *r, int n)
updatesel(); updatesel();
} }
if(t.nr>HiWater && t.qh>=t.org){ insert(r, n, t.qh, 1);
m = HiWater-LoWater;
if(m > t.org);
m = t.org;
t.org -= m;
t.qh -= m;
if(t.q0 > m)
t.q0 -= m;
else
t.q0 = 0;
if(t.q1 > m)
t.q1 -= m;
else
t.q1 = 0;
t.nr -= m;
runemove(t.r, t.r+m, t.nr);
}
t.r = runerealloc(t.r, t.nr+n);
runemove(t.r+t.qh+n, t.r+t.qh, t.nr-t.qh);
runemove(t.r+t.qh, r, n);
t.nr += n;
if(t.qh < t.org)
t.org += n;
else if(t.qh <= t.f->nchars+t.org)
frinsert(t.f, r, r+n, t.qh-t.org);
if (t.qh <= t.q0)
t.q0 += n;
if (t.qh <= t.q1)
t.q1 += n;
t.qh += n;
updatesel();
} }
@ -1009,12 +1130,83 @@ snarf(void)
putsnarf(sbuf); putsnarf(sbuf);
} }
uint
min(uint x, uint y)
{
if(x < y)
return x;
return y;
}
uint
max(uint x, uint y)
{
if(x > y)
return x;
return y;
}
uint
insert(Rune *r, int n, uint q0, int hostwrite)
{
uint m;
if(n == 0)
return q0;
if(t.nr+n>HiWater && q0>=t.org && q0>=t.qh){
m = min(HiWater-LoWater, min(t.org, t.qh));
t.org -= m;
t.qh -= m;
if(t.q0 > m)
t.q0 -= m;
else
t.q0 = 0;
if(t.q1 > m)
t.q1 -= m;
else
t.q1 = 0;
t.nr -= m;
runemove(t.r, t.r+m, t.nr);
q0 -= m;
}
if(t.nr+n > t.maxr){
/*
* Minimize realloc breakage:
* Allocate at least MinWater
* Double allocation size each time
* But don't go much above HiWater
*/
m = max(min(2*(t.nr+n), HiWater), t.nr+n)+MinWater;
if(m > HiWater)
m = max(HiWater+MinWater, t.nr+n);
if(m > t.maxr){
t.r = runerealloc(t.r, m);
t.maxr = m;
}
}
runemove(t.r+q0+n, t.r+q0, t.nr-q0);
runemove(t.r+q0, r, n);
t.nr += n;
/* if output touches, advance selection, not qh; works best for keyboard and output */
if(q0 <= t.q1)
t.q1 += n;
if(q0 <= t.q0)
t.q0 += n;
if(q0 < t.qh || (q0==t.qh && hostwrite))
t.qh += n;
else
consread();
if(q0 < t.org)
t.org += n;
else if(q0 <= t.org+t.f->nchars)
frinsert(t.f, r, r+n, q0-t.org);
return q0;
}
void void
paste(Rune *r, int n, int advance) paste(Rune *r, int n, int advance)
{ {
Rune *rbuf; Rune *rbuf;
uint m;
uint q0;
if(rawon && t.q0==t.nr){ if(rawon && t.q0==t.nr){
addraw(r, n); addraw(r, n);
@ -1024,6 +1216,7 @@ paste(Rune *r, int n, int advance)
cut(); cut();
if(n == 0) if(n == 0)
return; return;
/* /*
* if this is a button2 execute then we might have been passed * if this is a button2 execute then we might have been passed
* runes inside the buffer. must save them before realloc. * runes inside the buffer. must save them before realloc.
@ -1035,36 +1228,7 @@ paste(Rune *r, int n, int advance)
r = rbuf; r = rbuf;
} }
if(t.nr>HiWater && t.q0>=t.org && t.q0>=t.qh){ insert(r, n, t.q0, 0);
m = HiWater-LoWater;
if(m > t.org)
m = t.org;
if(m > t.qh);
m = t.qh;
t.org -= m;
t.qh -= m;
t.q0 -= m;
t.q1 -= m;
t.nr -= m;
runemove(t.r, t.r+m, t.nr);
}
t.r = runerealloc(t.r, t.nr+n);
q0 = t.q0;
runemove(t.r+q0+n, t.r+q0, t.nr-q0);
runemove(t.r+q0, r, n);
t.nr += n;
if(q0 < t.qh)
t.qh += n;
else
consread();
if(q0 < t.org)
t.org += n;
else if(q0 <= t.f->nchars+t.org)
frinsert(t.f, r, r+n, q0-t.org);
if(advance)
t.q0 += n;
t.q1 += n;
updatesel(); updatesel();
free(rbuf); free(rbuf);
} }
@ -1321,61 +1485,6 @@ clickmatch(int cl, int cr, int dir, uint *q)
return cl=='\n' && nest==1; return cl=='\n' && nest==1;
} }
void
rcstart(int fd[2], int argc, char **argv)
{
int pid;
char *xargv[3];
char slave[256];
int sfd;
if(argc == 0){
argc = 2;
argv = xargv;
argv[0] = getenv("SHELL");
if(argv[0] == 0)
argv[0] = "rc";
argv[1] = "-i";
argv[2] = 0;
}
/*
* fd0 is slave (tty), fd1 is master (pty)
*/
fd[0] = fd[1] = -1;
if(getpts(fd, slave) < 0)
fprint(2, "getpts: %r\n");
switch(pid = fork()) {
case 0:
putenv("TERM", "9term");
close(fd[1]);
setsid();
// tcsetpgrp(0, pid);
sfd = open(slave, ORDWR);
if(sfd < 0)
fprint(2, "open %s: %r\n", slave);
if(ioctl(sfd, TIOCSCTTY, 0) < 0)
fprint(2, "ioctl TIOCSCTTY: %r\n");
// ioctl(sfd, I_PUSH, "ptem");
// ioctl(sfd, I_PUSH, "ldterm");
dup(sfd, 0);
dup(sfd, 1);
dup(sfd, 2);
system("stty tabs -onlcr -echo erase ^h intr ^?");
execvp(argv[0], argv);
fprint(2, "exec %s failed: %r\n", argv[0]);
_exits("oops");
break;
case -1:
fatal("proc failed: %r");
break;
}
close(fd[0]);
fd[0] = fd[1];
rcpid = pid;
}
void void
tcheck(void) tcheck(void)
{ {
@ -1421,7 +1530,7 @@ scrdraw(void)
freeimage(scrx); freeimage(scrx);
scrx = allocimage(display, Rect(0, 0, 32, r.max.y), screen->chan, 1, DPaleyellow); scrx = allocimage(display, Rect(0, 0, 32, r.max.y), screen->chan, 1, DPaleyellow);
if(scrx == 0) if(scrx == 0)
fatal("scroll balloc"); sysfatal("scroll balloc");
} }
r1.min.x = 0; r1.min.x = 0;
r1.max.x = Dx(r); r1.max.x = Dx(r);
@ -1525,16 +1634,11 @@ plumb(uint q0, uint q1)
char *p; char *p;
int i, p0, n; int i, p0, n;
char cbuf[100]; char cbuf[100];
char *w;
if(getchildwd(rcpid, childwdir, sizeof childwdir) == 0)
w = childwdir;
else
w = wdir;
pm = malloc(sizeof(Plumbmsg)); pm = malloc(sizeof(Plumbmsg));
pm->src = strdup("9term"); pm->src = strdup("9term");
pm->dst = 0; pm->dst = 0;
pm->wdir = strdup(w); pm->wdir = strdup(wdir);
pm->type = strdup("text"); pm->type = strdup("text");
pm->data = nil; pm->data = nil;
if(q1 > q0) if(q1 > q0)

View file

@ -1,19 +1,4 @@
#include <u.h>
#include <libc.h>
#include <ctype.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <cursor.h>
#include <keyboard.h>
#include <frame.h>
#include <plumb.h>
#include <termios.h>
#include <sys/termios.h>
#ifdef __linux__
#include <pty.h>
#endif
extern int getchildwd(int, char*, int);
extern int getpts(int[], char*); extern int getpts(int[], char*);
extern int childpty(int[], char*);
extern void updatewinsize(int, int, int, int);
extern int rcfd[];

View file

@ -1,17 +1,43 @@
#include "9term.h" #include "9term.h"
#include <termios.h>
#include <sys/termios.h>
#include <libutil.h> #include <libutil.h>
int
getchildwd(int pid, char *wdir, int bufn)
{
USED(pid);
USED(wdir);
USED(bufn);
return -1;
}
int int
getpts(int fd[], char *slave) getpts(int fd[], char *slave)
{ {
return openpty(&fd[1], &fd[0], slave, 0, 0); return openpty(&fd[1], &fd[0], slave, 0, 0);
} }
int
childpty(int fd[], char *slave)
{
int sfd;
close(fd[1]);
setsid();
sfd = open(slave, ORDWR);
if(sfd < 0)
sysfatal("open %s: %r\n", slave);
if(ioctl(sfd, TIOCSCTTY, 0) < 0)
fprint(2, "ioctl TIOCSCTTY: %r\n");
return sfd;
}
struct winsize ows;
void
updatewinsize(int row, int col, int dx, int dy)
{
struct winsize ws;
ws.ws_row = row;
ws.ws_col = col;
ws.ws_xpixel = dx;
ws.ws_ypixel = dy;
if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col)
if(ioctl(rcfd[0], TIOCSWINSZ, &ws) < 0)
fprint(2, "ioctl: %r\n");
ows = ws;
}

View file

@ -1,22 +1,46 @@
#include <u.h>
#include <termios.h>
#include <sys/termios.h>
#include <pty.h>
#include <libc.h>
#include "9term.h" #include "9term.h"
int
getchildwd(int pid, char *wdir, int bufn)
{
char path[256];
int n;
snprint(path, sizeof path, "/proc/%d/cwd", pid);
n = readlink(path, wdir, bufn);
if(n < 0)
return -1;
wdir[n] = '\0';
return 0;
}
int int
getpts(int fd[], char *slave) getpts(int fd[], char *slave)
{ {
openpty(&fd[1], &fd[0], slave, 0, 0); openpty(&fd[1], &fd[0], slave, 0, 0);
return 0; return 0;
} }
int
childpty(int fd[], char *slave)
{
int sfd;
close(fd[1]);
setsid();
sfd = open(slave, ORDWR);
if(sfd < 0)
sysfatal("open %s: %r\n", slave);
if(ioctl(sfd, TIOCSCTTY, 0) < 0)
fprint(2, "ioctl TIOCSCTTY: %r\n");
return sfd;
}
struct winsize ows;
void
updatewinsize(int row, int col, int dx, int dy)
{
struct winsize ws;
ws.ws_row = row;
ws.ws_col = col;
ws.ws_xpixel = dx;
ws.ws_ypixel = dy;
if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col)
if(ioctl(rcfd[0], TIOCSWINSZ, &ws) < 0)
fprint(2, "ioctl: %r\n");
ows = ws;
}

View file

@ -1,21 +1,6 @@
#include "9term.h" #include "9term.h"
#include <termios.h>
int #include <sys/termios.h>
getchildwd(int pid, char *wdir, int bufn)
{
char path[256];
char cwd[256];
if(getcwd(cwd, sizeof cwd) < 0)
return -1;
snprint(path, sizeof path, "/proc/%d/cwd", pid);
if(chdir(path) < 0)
return -1;
if(getcwd(wdir, bufn) < 0)
return -1;
chdir(cwd);
return 0;
}
int int
getpts(int fd[], char *slave) getpts(int fd[], char *slave)
@ -28,3 +13,21 @@ getpts(int fd[], char *slave)
fd[0] = open(slave, OREAD); fd[0] = open(slave, OREAD);
return 0; return 0;
} }
struct winsize ows;
void
updatewinsize(int row, int col, int dx, int dy)
{
struct winsize ws;
ws.ws_row = row;
ws.ws_col = col;
ws.ws_xpixel = dx;
ws.ws_ypixel = dy;
if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col)
if(ioctl(rcfd[0], TIOCSWINSZ, &ws) < 0)
fprint(2, "ioctl: %r\n");
ows = ws;
}

View file

@ -1,15 +1,15 @@
PLAN9=../../.. PLAN9=../../..
<$PLAN9/src/mkhdr <$PLAN9/src/mkhdr
TARG=9term TARG=9term win
OFILES=\ OFILES=\
9term.$O\ rcstart.$O\
$SYSNAME.$O\ $SYSNAME.$O\
SHORTLIB=frame draw plumb fs mux thread 9 SHORTLIB=complete frame draw plumb fs mux thread 9
<$PLAN9/src/mkone <$PLAN9/src/mkmany
LDFLAGS=-L$X11/lib -lX11 -lutil LDFLAGS=-L$X11/lib -lX11 -lutil

51
src/cmd/9term/rcstart.c Normal file
View file

@ -0,0 +1,51 @@
#include <u.h>
#include <libc.h>
#include "term.h"
int
rcstart(int argc, char **argv, int *pfd)
{
int pid;
int fd[2];
char *xargv[3];
char slave[256];
int sfd;
if(argc == 0){
argc = 2;
argv = xargv;
argv[0] = getenv("SHELL");
if(argv[0] == 0)
argv[0] = "rc";
argv[1] = "-i";
argv[2] = 0;
}
/*
* fd0 is slave (tty), fd1 is master (pty)
*/
fd[0] = fd[1] = -1;
if(getpts(fd, slave) < 0)
fprint(2, "getpts: %r\n");
switch(pid = fork()) {
case 0:
putenv("TERM", "9term");
sfd = childpty(fd, slave);
dup(sfd, 0);
dup(sfd, 1);
dup(sfd, 2);
system("stty tabs -onlcr -echo erase ^h intr ^?");
execvp(argv[0], argv);
fprint(2, "exec %s failed: %r\n", argv[0]);
_exits("oops");
break;
case -1:
sysfatal("proc failed: %r");
break;
}
close(fd[0]);
*pfd = fd[1];
return pid;
}

5
src/cmd/9term/term.h Normal file
View file

@ -0,0 +1,5 @@
extern int getpts(int[], char*);
extern int childpty(int[], char*);
extern void updatewinsize(int, int, int, int);
extern int rcfd;
extern int rcstart(int, char*[], int*);

View file

@ -3,6 +3,7 @@
#include <thread.h> #include <thread.h>
#include <fcall.h> #include <fcall.h>
#include <fs.h> #include <fs.h>
#include "term.h"
#define EVENTSIZE 256 #define EVENTSIZE 256
#define STACK 32768 #define STACK 32768
@ -51,11 +52,11 @@ int ntypeb;
int ntyper; int ntyper;
int ntypebreak; int ntypebreak;
int debug; int debug;
int rcfd;
char *name; char *name;
char **prog; char **prog;
int p[2];
Channel *cpid;
Channel *cwait; Channel *cwait;
int pid = -1; int pid = -1;
@ -124,9 +125,11 @@ threadmain(int argc, char **argv)
prog = argv; prog = argv;
if(argc > 0) if(argc > 0){
name = argv[0]; name = argv[0];
else argc--;
argv++;
}else
name = "gnot"; name = "gnot";
threadnotify(nopipes, 1); threadnotify(nopipes, 1);
@ -156,14 +159,9 @@ threadmain(int argc, char **argv)
*/ */
fsunmount(fs); fsunmount(fs);
if(pipe(p) < 0)
sysfatal("pipe: %r");
cpid = chancreate(sizeof(ulong), 1);
cwait = threadwaitchan(); cwait = threadwaitchan();
threadcreate(waitthread, nil, STACK); threadcreate(waitthread, nil, STACK);
threadcreate(runproc, nil, STACK); pid = rcstart(argc, argv, &rcfd);
pid = recvul(cpid);
if(pid == -1) if(pid == -1)
sysfatal("exec failed"); sysfatal("exec failed");
@ -179,30 +177,6 @@ threadmain(int argc, char **argv)
stdinproc(nil); stdinproc(nil);
} }
char *shell[] = { "rc", "-i", 0 };
void
runproc(void *v)
{
int fd[3];
char *sh;
USED(v);
fd[0] = p[1];
// fd[1] = bodyfd;
// fd[2] = bodyfd;
fd[1] = p[1];
fd[2] = p[1];
if(prog[0] == nil){
prog = shell;
if((sh = getenv("SHELL")) != nil)
shell[0] = sh;
}
threadexec(cpid, fd, prog[0], prog);
threadexits(nil);
}
void void
error(char *s) error(char *s)
{ {
@ -329,7 +303,7 @@ stdinproc(void *v)
Fid *efd = eventfd; Fid *efd = eventfd;
Fid *dfd = datafd; Fid *dfd = datafd;
Fid *afd = addrfd; Fid *afd = addrfd;
int fd0 = p[0]; int fd0 = rcfd;
Event e, e2, e3, e4; Event e, e2, e3, e4;
USED(v); USED(v);
@ -426,7 +400,7 @@ stdinproc(void *v)
void void
stdoutproc(void *v) stdoutproc(void *v)
{ {
int fd1 = p[0]; int fd1 = rcfd;
Fid *afd = addrfd; Fid *afd = addrfd;
Fid *dfd = datafd; Fid *dfd = datafd;
int n, m, w, npart; int n, m, w, npart;
@ -439,6 +413,8 @@ stdoutproc(void *v)
buf = malloc(8192+UTFmax+1); buf = malloc(8192+UTFmax+1);
npart = 0; npart = 0;
for(;;){ for(;;){
/* Let typing have a go -- maybe there's a rubout waiting. */
yield();
n = threadread(fd1, buf+npart, 8192); n = threadread(fd1, buf+npart, 8192);
if(n < 0) if(n < 0)
error(nil); error(nil);
@ -556,7 +532,7 @@ addtype(int c, uint p0, char *b, int nb, int nr)
for(i=0; i<nb; i+=w){ for(i=0; i<nb; i+=w){
w = chartorune(&r, b+i); w = chartorune(&r, b+i);
if((r==0x7F||r==3) && c=='K'){ if((r==0x7F||r==3) && c=='K'){
postnote(PNGROUP, pid, "interrupt"); write(rcfd, "\x7F", 1);
/* toss all typing */ /* toss all typing */
q.p += ntyper+nr; q.p += ntyper+nr;
ntypebreak = 0; ntypebreak = 0;

View file

@ -161,7 +161,8 @@ threadmain(int argc, char *argv[])
cerr = chancreate(sizeof(char*), 0); cerr = chancreate(sizeof(char*), 0);
cedit = chancreate(sizeof(int), 0); cedit = chancreate(sizeof(int), 0);
cexit = chancreate(sizeof(int), 0); cexit = chancreate(sizeof(int), 0);
if(cwait==nil || ccommand==nil || ckill==nil || cxfidalloc==nil || cxfidfree==nil || cerr==nil || cexit==nil){ cwarn = chancreate(sizeof(void*), 1);
if(cwait==nil || ccommand==nil || ckill==nil || cxfidalloc==nil || cxfidfree==nil || cerr==nil || cexit==nil || cwarn==nil){
fprint(2, "acme: can't create initial channels: %r\n"); fprint(2, "acme: can't create initial channels: %r\n");
exits("channels"); exits("channels");
} }
@ -251,7 +252,7 @@ readfile(Column *c, char *s)
w = coladd(c, nil, nil, -1); w = coladd(c, nil, nil, -1);
cvttorunes(s, strlen(s), rb, &nb, &nr, nil); cvttorunes(s, strlen(s), rb, &nb, &nr, nil);
rs = cleanrname((Runestr){rb, nr}); rs = cleanrname(runestr(rb, nr));
winsetname(w, rs.r, rs.nr); winsetname(w, rs.r, rs.nr);
textload(&w->body, 0, s, 1); textload(&w->body, 0, s, 1);
w->body.file->mod = FALSE; w->body.file->mod = FALSE;
@ -403,7 +404,6 @@ keyboardthread(void *v)
winlock(t->w, 'K'); winlock(t->w, 'K');
wincommit(t->w, t); wincommit(t->w, t);
winunlock(t->w); winunlock(t->w);
flushwarnings(1);
flushimage(display, 1); flushimage(display, 1);
} }
alts[KTimer].c = nil; alts[KTimer].c = nil;
@ -430,7 +430,6 @@ keyboardthread(void *v)
} }
if(nbrecv(keyboardctl->c, &r) > 0) if(nbrecv(keyboardctl->c, &r) > 0)
goto casekeyboard; goto casekeyboard;
flushwarnings(1);
flushimage(display, 1); flushimage(display, 1);
break; break;
} }
@ -447,7 +446,7 @@ mousethread(void *v)
Plumbmsg *pm; Plumbmsg *pm;
Mouse m; Mouse m;
char *act; char *act;
enum { MResize, MMouse, MPlumb, NMALT }; enum { MResize, MMouse, MPlumb, MWarnings, NMALT };
static Alt alts[NMALT+1]; static Alt alts[NMALT+1];
USED(v); USED(v);
@ -461,11 +460,18 @@ mousethread(void *v)
alts[MPlumb].c = cplumb; alts[MPlumb].c = cplumb;
alts[MPlumb].v = &pm; alts[MPlumb].v = &pm;
alts[MPlumb].op = CHANRCV; alts[MPlumb].op = CHANRCV;
alts[MWarnings].c = cwarn;
alts[MWarnings].v = nil;
alts[MWarnings].op = CHANRCV;
if(cplumb == nil) if(cplumb == nil)
alts[MPlumb].op = CHANNOP; alts[MPlumb].op = CHANNOP;
alts[NMALT].op = CHANEND; alts[NMALT].op = CHANEND;
for(;;){ for(;;){
qlock(&row.lk);
flushwarnings();
qunlock(&row.lk);
flushimage(display, 1);
switch(alt(alts)){ switch(alt(alts)){
case MResize: case MResize:
if(getwindow(display, Refnone) < 0) if(getwindow(display, Refnone) < 0)
@ -473,8 +479,6 @@ mousethread(void *v)
draw(screen, screen->r, display->white, nil, ZP); draw(screen, screen->r, display->white, nil, ZP);
scrlresize(); scrlresize();
rowresize(&row, screen->clipr); rowresize(&row, screen->clipr);
flushwarnings(1);
flushimage(display, 1);
break; break;
case MPlumb: case MPlumb:
if(strcmp(pm->type, "text") == 0){ if(strcmp(pm->type, "text") == 0){
@ -484,10 +488,10 @@ mousethread(void *v)
else if(strcmp(act, "showdata")==0) else if(strcmp(act, "showdata")==0)
plumbshow(pm); plumbshow(pm);
} }
flushwarnings(1);
flushimage(display, 1);
plumbfree(pm); plumbfree(pm);
break; break;
case MWarnings:
break;
case MMouse: case MMouse:
/* /*
* Make a copy so decisions are consistent; mousectl changes * Make a copy so decisions are consistent; mousectl changes
@ -570,8 +574,6 @@ mousethread(void *v)
goto Continue; goto Continue;
} }
Continue: Continue:
flushwarnings(0);
flushimage(display, 1);
qunlock(&row.lk); qunlock(&row.lk);
break; break;
} }

View file

@ -543,5 +543,6 @@ Channel *mouseexit1; /* chan(int) */
Channel *cexit; /* chan(int) */ Channel *cexit; /* chan(int) */
Channel *cerr; /* chan(char*) */ Channel *cerr; /* chan(char*) */
Channel *cedit; /* chan(int) */ Channel *cedit; /* chan(int) */
Channel *cwarn; /* chan(void*)[1] (really chan(unit)[1]) */
#define STACK 32768 #define STACK 32768

View file

@ -268,7 +268,7 @@ D_cmd(Text *t, Cmd *cp)
runemove(n, dir.r, dir.nr); runemove(n, dir.r, dir.nr);
n[dir.nr] = '/'; n[dir.nr] = '/';
runemove(n+dir.nr+1, r, nn); runemove(n+dir.nr+1, r, nn);
rs = cleanrname((Runestr){n, dir.nr+1+nn}); rs = cleanrname(runestr(n, dir.nr+1+nn));
} }
w = lookfile(rs.r, rs.nr); w = lookfile(rs.r, rs.nr);
if(w == nil){ if(w == nil){

View file

@ -25,6 +25,7 @@ void fontx(Text*, Text*, Text*, int, int, Rune*, int);
void get(Text*, Text*, Text*, int, int, Rune*, int); void get(Text*, Text*, Text*, int, int, Rune*, int);
void id(Text*, Text*, Text*, int, int, Rune*, int); void id(Text*, Text*, Text*, int, int, Rune*, int);
void incl(Text*, Text*, Text*, int, int, Rune*, int); void incl(Text*, Text*, Text*, int, int, Rune*, int);
void indent(Text*, Text*, Text*, int, int, Rune*, int);
void xkill(Text*, Text*, Text*, int, int, Rune*, int); void xkill(Text*, Text*, Text*, int, int, Rune*, int);
void local(Text*, Text*, Text*, int, int, Rune*, int); void local(Text*, Text*, Text*, int, int, Rune*, int);
void look(Text*, Text*, Text*, int, int, Rune*, int); void look(Text*, Text*, Text*, int, int, Rune*, int);
@ -58,6 +59,7 @@ static Rune LFont[] = { 'F', 'o', 'n', 't', 0 };
static Rune LGet[] = { 'G', 'e', 't', 0 }; static Rune LGet[] = { 'G', 'e', 't', 0 };
static Rune LID[] = { 'I', 'D', 0 }; static Rune LID[] = { 'I', 'D', 0 };
static Rune LIncl[] = { 'I', 'n', 'c', 'l', 0 }; static Rune LIncl[] = { 'I', 'n', 'c', 'l', 0 };
static Rune LIndent[] = { 'I', 'n', 'd', 'e', 'n', 't', 0 };
static Rune LKill[] = { 'K', 'i', 'l', 'l', 0 }; static Rune LKill[] = { 'K', 'i', 'l', 'l', 0 };
static Rune LLoad[] = { 'L', 'o', 'a', 'd', 0 }; static Rune LLoad[] = { 'L', 'o', 'a', 'd', 0 };
static Rune LLocal[] = { 'L', 'o', 'c', 'a', 'l', 0 }; static Rune LLocal[] = { 'L', 'o', 'c', 'a', 'l', 0 };
@ -87,6 +89,7 @@ Exectab exectab[] = {
{ LGet, get, FALSE, TRUE, XXX }, { LGet, get, FALSE, TRUE, XXX },
{ LID, id, FALSE, XXX, XXX }, { LID, id, FALSE, XXX, XXX },
{ LIncl, incl, FALSE, XXX, XXX }, { LIncl, incl, FALSE, XXX, XXX },
{ LIndent, indent, FALSE, XXX, XXX },
{ LKill, xkill, FALSE, XXX, XXX }, { LKill, xkill, FALSE, XXX, XXX },
{ LLoad, dump, FALSE, FALSE, XXX }, { LLoad, dump, FALSE, FALSE, XXX },
{ LLocal, local, FALSE, XXX, XXX }, { LLocal, local, FALSE, XXX, XXX },
@ -1443,7 +1446,6 @@ runproc(void *argvp)
goto Fail; goto Fail;
Hard: Hard:
/* /*
* ugly: set path = (. $cputype /bin) * ugly: set path = (. $cputype /bin)
* should honor $path if unusual. * should honor $path if unusual.

View file

@ -69,6 +69,7 @@ Rune* bytetorune(char*, int*);
void fsysinit(void); void fsysinit(void);
Mntdir* fsysmount(Rune*, int, Rune**, int); Mntdir* fsysmount(Rune*, int, Rune**, int);
void fsysdelid(Mntdir*); void fsysdelid(Mntdir*);
void fsysincid(Mntdir*);
Xfid* respond(Xfid*, Fcall*, char*); Xfid* respond(Xfid*, Fcall*, char*);
int rxcompile(Rune*); int rxcompile(Rune*);
int rgetc(void*, uint); int rgetc(void*, uint);
@ -86,9 +87,11 @@ int expand(Text*, uint, uint, Expand*);
Rune* skipbl(Rune*, int, int*); Rune* skipbl(Rune*, int, int*);
Rune* findbl(Rune*, int, int*); Rune* findbl(Rune*, int, int*);
char* edittext(Window*, int, Rune*, int); char* edittext(Window*, int, Rune*, int);
void flushwarnings(int); void flushwarnings(void);
void startplumbing(void); void startplumbing(void);
Runestr runestr(Rune*, uint);
#define runemalloc(a) (Rune*)emalloc((a)*sizeof(Rune)) #define runemalloc(a) (Rune*)emalloc((a)*sizeof(Rune))
#define runerealloc(a, b) (Rune*)erealloc((a), (b)*sizeof(Rune)) #define runerealloc(a, b) (Rune*)erealloc((a), (b)*sizeof(Rune))
#define runemove(a, b, c) memmove((a), (b), (c)*sizeof(Rune)) #define runemove(a, b, c) memmove((a), (b), (c)*sizeof(Rune))

View file

@ -37,22 +37,25 @@ static Xfid* fsysremove(Xfid*, Fid*);
static Xfid* fsysstat(Xfid*, Fid*); static Xfid* fsysstat(Xfid*, Fid*);
static Xfid* fsyswstat(Xfid*, Fid*); static Xfid* fsyswstat(Xfid*, Fid*);
Xfid* (*fcall[Tmax])(Xfid*, Fid*) = Xfid* (*fcall[Tmax])(Xfid*, Fid*);
static void
initfcall(void)
{ {
[Tflush] = fsysflush, fcall[Tflush] = fsysflush;
[Tversion] = fsysversion, fcall[Tversion] = fsysversion;
[Tauth] = fsysauth, fcall[Tauth] = fsysauth;
[Tattach] = fsysattach, fcall[Tattach] = fsysattach;
[Twalk] = fsyswalk, fcall[Twalk] = fsyswalk;
[Topen] = fsysopen, fcall[Topen] = fsysopen;
[Tcreate] = fsyscreate, fcall[Tcreate] = fsyscreate;
[Tread] = fsysread, fcall[Tread] = fsysread;
[Twrite] = fsyswrite, fcall[Twrite] = fsyswrite;
[Tclunk] = fsysclunk, fcall[Tclunk] = fsysclunk;
[Tremove]= fsysremove, fcall[Tremove]= fsysremove;
[Tstat] = fsysstat, fcall[Tstat] = fsysstat;
[Twstat] = fsyswstat, fcall[Twstat] = fsyswstat;
}; }
char Eperm[] = "permission denied"; char Eperm[] = "permission denied";
char Eexist[] = "file does not exist"; char Eexist[] = "file does not exist";
@ -113,6 +116,7 @@ fsysinit(void)
int p[2]; int p[2];
char *u; char *u;
initfcall();
if(pipe(p) < 0) if(pipe(p) < 0)
error("can't create pipe"); error("can't create pipe");
if(post9pservice(p[0], "acme") < 0) if(post9pservice(p[0], "acme") < 0)
@ -186,6 +190,14 @@ fsysaddid(Rune *dir, int ndir, Rune **incl, int nincl)
return m; return m;
} }
void
fsysincid(Mntdir *m)
{
qlock(&mnt.lk);
m->ref++;
qunlock(&mnt.lk);
}
void void
fsysdelid(Mntdir *idm) fsysdelid(Mntdir *idm)
{ {
@ -331,7 +343,7 @@ fsysattach(Xfid *x, Fid *f)
m->ref++; m->ref++;
break; break;
} }
if(m == nil){ if(m == nil && x->fcall.aname[0]){
snprint(buf, sizeof buf, "unknown id '%s' in attach", x->fcall.aname); snprint(buf, sizeof buf, "unknown id '%s' in attach", x->fcall.aname);
sendp(cerr, estrdup(buf)); sendp(cerr, estrdup(buf));
} }

View file

@ -259,7 +259,7 @@ plumbshow(Plumbmsg *m)
} }
cvttorunes(name, strlen(name), rb, &nb, &nr, nil); cvttorunes(name, strlen(name), rb, &nb, &nr, nil);
free(p); free(p);
rs = cleanrname((Runestr){rb, nr}); rs = cleanrname(runestr(rb, nr));
winsetname(w, rs.r, rs.nr); winsetname(w, rs.r, rs.nr);
r = runemalloc(m->ndata); r = runemalloc(m->ndata);
cvttorunes(m->data, m->ndata, r, &nb, &nr, nil); cvttorunes(m->data, m->ndata, r, &nb, &nr, nil);
@ -385,13 +385,13 @@ includefile(Rune *dir, Rune *file, int nfile)
n = access(a, 0); n = access(a, 0);
free(a); free(a);
if(n < 0) if(n < 0)
return (Runestr){nil, 0}; return runestr(nil, 0);
r = runemalloc(m+1+nfile); r = runemalloc(m+1+nfile);
runemove(r, dir, m); runemove(r, dir, m);
runemove(r+m, Lslash, 1); runemove(r+m, Lslash, 1);
runemove(r+m+1, file, nfile); runemove(r+m+1, file, nfile);
free(file); free(file);
return cleanrname((Runestr){r, m+1+nfile}); return cleanrname(runestr(r, m+1+nfile));
} }
static Rune *objdir; static Rune *objdir;
@ -442,7 +442,7 @@ includename(Text *t, Rune *r, int n)
return file; return file;
Rescue: Rescue:
return (Runestr){r, n}; return runestr(r, n);
} }
Runestr Runestr
@ -475,11 +475,11 @@ dirname(Text *t, Rune *r, int n)
goto Rescue; goto Rescue;
runemove(b+slash+1, r, n); runemove(b+slash+1, r, n);
free(r); free(r);
return cleanrname((Runestr){b, slash+1+n}); return cleanrname(runestr(b, slash+1+n));
Rescue: Rescue:
free(b); free(b);
tmp = (Runestr){r, n}; tmp = runestr(r, n);
if(r) if(r)
return cleanrname(tmp); return cleanrname(tmp);
return tmp; return tmp;

View file

@ -578,7 +578,7 @@ textcomplete(Text *t)
path[i] = textreadc(t, q++); path[i] = textreadc(t, q++);
/* is path rooted? if not, we need to make it relative to window path */ /* is path rooted? if not, we need to make it relative to window path */
if(npath>0 && path[0]=='/') if(npath>0 && path[0]=='/')
dir = (Runestr){path, npath}; dir = runestr(path, npath);
else{ else{
dir = dirname(t, nil, 0); dir = dirname(t, nil, 0);
if(dir.nr + 1 + npath > nelem(tmp)){ if(dir.nr + 1 + npath > nelem(tmp)){

View file

@ -14,6 +14,16 @@
static Point prevmouse; static Point prevmouse;
static Window *mousew; static Window *mousew;
Runestr
runestr(Rune *r, uint n)
{
Runestr rs;
rs.r = r;
rs.nr = n;
return rs;
}
void void
cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls) cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls)
{ {
@ -133,12 +143,17 @@ addwarningtext(Mntdir *md, Rune *r, int nr)
} }
warn = emalloc(sizeof(Warning)); warn = emalloc(sizeof(Warning));
warn->next = warnings; warn->next = warnings;
warn->md = md;
if(md)
fsysincid(md);
warnings = warn; warnings = warn;
bufinsert(&warn->buf, 0, r, nr); bufinsert(&warn->buf, 0, r, nr);
nbsendp(cwarn, 0);
} }
/* called while row is locked */
void void
flushwarnings(int dolock) flushwarnings(void)
{ {
Warning *warn, *next; Warning *warn, *next;
Window *w; Window *w;
@ -146,8 +161,6 @@ flushwarnings(int dolock)
int owner, nr, q0, n; int owner, nr, q0, n;
Rune *r; Rune *r;
if(dolock)
qlock(&row.lk);
if(row.ncol == 0){ /* really early error */ if(row.ncol == 0){ /* really early error */
rowinit(&row, screen->clipr); rowinit(&row, screen->clipr);
rowadd(&row, nil, -1); rowadd(&row, nil, -1);
@ -189,11 +202,11 @@ flushwarnings(int dolock)
winunlock(w); winunlock(w);
bufclose(&warn->buf); bufclose(&warn->buf);
next = warn->next; next = warn->next;
if(warn->md)
fsysdelid(warn->md);
free(warn); free(warn);
} }
warnings = nil; warnings = nil;
if(dolock)
qunlock(&row.lk);
} }
void void

View file

@ -543,7 +543,6 @@ xfidwrite(Xfid *x)
} }
if(w) if(w)
winunlock(w); winunlock(w);
flushwarnings(1);
} }
void void
@ -814,7 +813,6 @@ xfideventwrite(Xfid *x, Window *w)
qunlock(&row.lk); qunlock(&row.lk);
goto Rescue; goto Rescue;
} }
flushwarnings(0);
qunlock(&row.lk); qunlock(&row.lk);
} }
@ -1032,7 +1030,6 @@ xfidindexread(Xfid *x)
b[n++] = '\n'; b[n++] = '\n';
} }
} }
flushwarnings(0);
qunlock(&row.lk); qunlock(&row.lk);
off = x->fcall.offset; off = x->fcall.offset;
cnt = x->fcall.count; cnt = x->fcall.count;

View file

@ -119,6 +119,8 @@ main(int argc, char **argv)
line = malloc(strlen(p)+5); line = malloc(strlen(p)+5);
sprint(line, "/%s/P\n", p); sprint(line, "/%s/P\n", p);
} }
dict->path = unsharp(dict->path);
dict->indexpath = unsharp(dict->indexpath);
bdict = Bopen(dict->path, OREAD); bdict = Bopen(dict->path, OREAD);
if(!bdict) { if(!bdict) {
err("can't open dictionary %s", dict->path); err("can't open dictionary %s", dict->path);

View file

@ -1,3 +1,5 @@
#define stdout bstdout
char mode; /* '\0', 'e', 'f', 'h' */ char mode; /* '\0', 'e', 'f', 'h' */
char bflag; /* ignore multiple and trailing blanks */ char bflag; /* ignore multiple and trailing blanks */
char rflag; /* recurse down directory trees */ char rflag; /* recurse down directory trees */

View file

@ -26,6 +26,8 @@ void
done(int status) done(int status)
{ {
rmtmpfiles(); rmtmpfiles();
Bflush(&stdout);
Bterm(&stdout);
switch(status) switch(status)
{ {
case 0: case 0:

View file

@ -4,8 +4,8 @@
#define index findex #define index findex
char choice[2048]; char choice[2048];
char index[] = "/sys/games/lib/fortunes.index"; char *index = "#9/lib/fortunes.index";
char fortunes[] = "/sys/games/lib/fortunes"; char *fortunes = "#9/lib/fortunes";
#define lrand rand #define lrand rand
@ -21,6 +21,9 @@ main(int argc, char *argv[])
Dir *fbuf, *ixbuf; Dir *fbuf, *ixbuf;
Biobuf *f, g; Biobuf *f, g;
index = unsharp(index);
fortunes = unsharp(index);
newindex = 0; newindex = 0;
oldindex = 0; oldindex = 0;
ix = offs = 0; ix = offs = 0;
@ -55,6 +58,7 @@ main(int argc, char *argv[])
} }
} }
if(oldindex){ if(oldindex){
srand(getpid());
seek(ix, lrand()%(ixbuf->length/sizeof(offs))*sizeof(offs), 0); seek(ix, lrand()%(ixbuf->length/sizeof(offs))*sizeof(offs), 0);
read(ix, off, sizeof(off)); read(ix, off, sizeof(off));
Bseek(f, off[0]|(off[1]<<8)|(off[2]<<16)|(off[3]<<24), 0); Bseek(f, off[0]|(off[1]<<8)|(off[2]<<16)|(off[3]<<24), 0);

277
src/cmd/grep/comp.c Normal file
View file

@ -0,0 +1,277 @@
#include "grep.h"
/*
* incremental compiler.
* add the branch c to the
* state s.
*/
void
increment(State *s, int c)
{
int i;
State *t, **tt;
Re *re1, *re2;
nfollow = 0;
gen++;
matched = 0;
for(i=0; i<s->count; i++)
fol1(s->re[i], c);
qsort(follow, nfollow, sizeof(*follow), fcmp);
for(tt=&state0; t = *tt;) {
if(t->count > nfollow) {
tt = &t->linkleft;
goto cont;
}
if(t->count < nfollow) {
tt = &t->linkright;
goto cont;
}
for(i=0; i<nfollow; i++) {
re1 = t->re[i];
re2 = follow[i];
if(re1 > re2) {
tt = &t->linkleft;
goto cont;
}
if(re1 < re2) {
tt = &t->linkright;
goto cont;
}
}
if(!!matched && !t->match) {
tt = &t->linkleft;
goto cont;
}
if(!matched && !!t->match) {
tt = &t->linkright;
goto cont;
}
s->next[c] = t;
return;
cont:;
}
t = sal(nfollow);
*tt = t;
for(i=0; i<nfollow; i++) {
re1 = follow[i];
t->re[i] = re1;
}
s->next[c] = t;
t->match = matched;
}
int
fcmp(const void *va, const void *vb)
{
Re **aa, **bb;
Re *a, *b;
aa = (Re**)va;
bb = (Re**)vb;
a = *aa;
b = *bb;
if(a > b)
return 1;
if(a < b)
return -1;
return 0;
}
void
fol1(Re *r, int c)
{
Re *r1;
loop:
if(r->gen == gen)
return;
if(nfollow >= maxfollow)
error("nfollow");
r->gen = gen;
switch(r->type) {
default:
error("fol1");
case Tcase:
if(c >= 0 && c < 256)
if(r1 = r->cases[c])
follow[nfollow++] = r1;
if(r = r->next)
goto loop;
break;
case Talt:
case Tor:
fol1(r->alt, c);
r = r->next;
goto loop;
case Tbegin:
if(c == '\n' || c == Cbegin)
follow[nfollow++] = r->next;
break;
case Tend:
if(c == '\n')
matched = 1;
break;
case Tclass:
if(c >= r->lo && c <= r->hi)
follow[nfollow++] = r->next;
break;
}
}
Rune tab1[] =
{
0x007f,
0x07ff,
};
Rune tab2[] =
{
0x003f,
0x0fff,
};
Re2
rclass(Rune p0, Rune p1)
{
char xc0[6], xc1[6];
int i, n, m;
Re2 x;
if(p0 > p1)
return re2char(0xff, 0xff); // no match
/*
* bust range into same length
* character sequences
*/
for(i=0; i<nelem(tab1); i++) {
m = tab1[i];
if(p0 <= m && p1 > m)
return re2or(rclass(p0, m), rclass(m+1, p1));
}
/*
* bust range into part of a single page
* or into full pages
*/
for(i=0; i<nelem(tab2); i++) {
m = tab2[i];
if((p0 & ~m) != (p1 & ~m)) {
if((p0 & m) != 0)
return re2or(rclass(p0, p0|m), rclass((p0|m)+1, p1));
if((p1 & m) != m)
return re2or(rclass(p0, (p1&~m)-1), rclass(p1&~m, p1));
}
}
n = runetochar(xc0, &p0);
i = runetochar(xc1, &p1);
if(i != n)
error("length");
x = re2char(xc0[0], xc1[0]);
for(i=1; i<n; i++)
x = re2cat(x, re2char(xc0[i], xc1[i]));
return x;
}
int
pcmp(const void *va, const void *vb)
{
int n;
Rune *a, *b;
a = (Rune*)va;
b = (Rune*)vb;
n = a[0] - b[0];
if(n)
return n;
return a[1] - b[1];
}
/*
* convert character chass into
* run-pair ranges of matches.
* this is 10646/utf specific and
* needs to be changed for some
* other input character set.
* this is the key to a fast
* regular search of characters
* by looking at sequential bytes.
*/
Re2
re2class(char *s)
{
Rune pairs[200], *p, *q, ov;
int nc;
Re2 x;
nc = 0;
if(*s == '^') {
nc = 1;
s++;
}
p = pairs;
s += chartorune(p, s);
for(;;) {
if(*p == '\\')
s += chartorune(p, s);
if(*p == 0)
break;
p[1] = *p;
p += 2;
s += chartorune(p, s);
if(*p != '-')
continue;
s += chartorune(p, s);
if(*p == '\\')
s += chartorune(p, s);
if(*p == 0)
break;
p[-1] = *p;
s += chartorune(p, s);
}
*p = 0;
qsort(pairs, (p-pairs)/2, 2*sizeof(*pairs), pcmp);
q = pairs;
for(p=pairs+2; *p; p+=2) {
if(p[0] > p[1])
continue;
if(p[0] > q[1] || p[1] < q[0]) {
q[2] = p[0];
q[3] = p[1];
q += 2;
continue;
}
if(p[0] < q[0])
q[0] = p[0];
if(p[1] > q[1])
q[1] = p[1];
}
q[2] = 0;
p = pairs;
if(nc) {
x = rclass(0, p[0]-1);
ov = p[1]+1;
for(p+=2; *p; p+=2) {
x = re2or(x, rclass(ov, p[0]-1));
ov = p[1]+1;
}
x = re2or(x, rclass(ov, 0xffff));
} else {
x = rclass(p[0], p[1]);
for(p+=2; *p; p+=2)
x = re2or(x, rclass(p[0], p[1]));
}
return x;
}

125
src/cmd/grep/grep.h Normal file
View file

@ -0,0 +1,125 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
#ifndef EXTERN
#define EXTERN extern
#endif
typedef struct Re Re;
typedef struct Re2 Re2;
typedef struct State State;
struct State
{
int count;
int match;
Re** re;
State* linkleft;
State* linkright;
State* next[256];
};
struct Re2
{
Re* beg;
Re* end;
};
struct Re
{
uchar type;
ushort gen;
union
{
Re* alt; /* Talt */
Re** cases; /* case */
struct /* class */
{
Rune lo;
Rune hi;
};
Rune val; /* char */
};
Re* next;
};
enum
{
Talt = 1,
Tbegin,
Tcase,
Tclass,
Tend,
Tor,
Caselim = 7,
Nhunk = 1<<16,
Cbegin = 0x10000,
Flshcnt = (1<<9)-1,
Cflag = 1<<0,
Hflag = 1<<1,
Iflag = 1<<2,
Llflag = 1<<3,
LLflag = 1<<4,
Nflag = 1<<5,
Sflag = 1<<6,
Vflag = 1<<7,
Bflag = 1<<8
};
EXTERN union
{
char string[16*1024];
struct
{
/*
* if a line requires multiple reads, we keep shifting
* buf down into pre and then do another read into
* buf. so you'll get the last 16-32k of the matching line.
* if pre were smaller than buf you'd get a suffix of the
* line with a hole cut out.
*/
uchar pre[16*1024]; /* to save to previous '\n' */
uchar buf[16*1024]; /* input buffer */
};
} u;
EXTERN char *filename;
EXTERN Biobuf bout;
EXTERN char flags[256];
EXTERN Re** follow;
EXTERN ushort gen;
EXTERN char* input;
EXTERN long lineno;
EXTERN int literal;
EXTERN int matched;
EXTERN long maxfollow;
EXTERN long nfollow;
EXTERN int peekc;
EXTERN Biobuf* rein;
EXTERN State* state0;
EXTERN Re2 topre;
extern Re* addcase(Re*);
extern void appendnext(Re*, Re*);
extern void error(char*);
extern int fcmp(const void*, const void*); /* (Re**, Re**) */
extern void fol1(Re*, int);
extern int getrec(void);
extern void increment(State*, int);
#define initstate grepinitstate
extern State* initstate(Re*);
extern void* mal(int);
extern void patchnext(Re*, Re*);
extern Re* ral(int);
extern Re2 re2cat(Re2, Re2);
extern Re2 re2class(char*);
extern Re2 re2or(Re2, Re2);
extern Re2 re2char(int, int);
extern Re2 re2star(Re2);
extern State* sal(int);
extern int search(char*, int);
extern void str2top(char*);
extern int yyparse(void);
extern void reprint(char*, Re*);
extern void yyerror(char*, ...);

226
src/cmd/grep/grep.y Normal file
View file

@ -0,0 +1,226 @@
%{
#include "grep.h"
%}
%union
{
int val;
char* str;
Re2 re;
}
%type <re> expr prog
%type <re> expr0 expr1 expr2 expr3 expr4
%token <str> LCLASS
%token <val> LCHAR
%token LLPAREN LRPAREN LALT LSTAR LPLUS LQUES
%token LBEGIN LEND LDOT LBAD LNEWLINE
%%
prog:
expr newlines
{
$$.beg = ral(Tend);
$$.end = $$.beg;
$$ = re2cat(re2star(re2or(re2char(0x00, '\n'-1), re2char('\n'+1, 0xff))), $$);
$$ = re2cat($1, $$);
$$ = re2cat(re2star(re2char(0x00, 0xff)), $$);
topre = $$;
}
expr:
expr0
| expr newlines expr0
{
$$ = re2or($1, $3);
}
expr0:
expr1
| LSTAR { literal = 1; } expr1
{
$$ = $3;
}
expr1:
expr2
| expr1 LALT expr2
{
$$ = re2or($1, $3);
}
expr2:
expr3
| expr2 expr3
{
$$ = re2cat($1, $2);
}
expr3:
expr4
| expr3 LSTAR
{
$$ = re2star($1);
}
| expr3 LPLUS
{
$$.beg = ral(Talt);
patchnext($1.end, $$.beg);
$$.beg->alt = $1.beg;
$$.end = $$.beg;
$$.beg = $1.beg;
}
| expr3 LQUES
{
$$.beg = ral(Talt);
$$.beg->alt = $1.beg;
$$.end = $1.end;
appendnext($$.end, $$.beg);
}
expr4:
LCHAR
{
$$.beg = ral(Tclass);
$$.beg->lo = $1;
$$.beg->hi = $1;
$$.end = $$.beg;
}
| LBEGIN
{
$$.beg = ral(Tbegin);
$$.end = $$.beg;
}
| LEND
{
$$.beg = ral(Tend);
$$.end = $$.beg;
}
| LDOT
{
$$ = re2class("^\n");
}
| LCLASS
{
$$ = re2class($1);
}
| LLPAREN expr1 LRPAREN
{
$$ = $2;
}
newlines:
LNEWLINE
| newlines LNEWLINE
%%
void
yyerror(char *e, ...)
{
if(filename)
fprint(2, "grep: %s:%ld: %s\n", filename, lineno, e);
else
fprint(2, "grep: %s\n", e);
exits("syntax");
}
long
yylex(void)
{
char *q, *eq;
int c, s;
if(peekc) {
s = peekc;
peekc = 0;
return s;
}
c = getrec();
if(literal) {
if(c != 0 && c != '\n') {
yylval.val = c;
return LCHAR;
}
literal = 0;
}
switch(c) {
default:
yylval.val = c;
s = LCHAR;
break;
case '\\':
c = getrec();
yylval.val = c;
s = LCHAR;
if(c == '\n')
s = LNEWLINE;
break;
case '[':
goto getclass;
case '(':
s = LLPAREN;
break;
case ')':
s = LRPAREN;
break;
case '|':
s = LALT;
break;
case '*':
s = LSTAR;
break;
case '+':
s = LPLUS;
break;
case '?':
s = LQUES;
break;
case '^':
s = LBEGIN;
break;
case '$':
s = LEND;
break;
case '.':
s = LDOT;
break;
case 0:
peekc = -1;
case '\n':
s = LNEWLINE;
break;
}
return s;
getclass:
q = u.string;
eq = q + nelem(u.string) - 5;
c = getrec();
if(c == '^') {
q[0] = '^';
q[1] = '\n';
q[2] = '-';
q[3] = '\n';
q += 4;
c = getrec();
}
for(;;) {
if(q >= eq)
error("class too long");
if(c == ']' || c == 0)
break;
if(c == '\\') {
*q++ = c;
c = getrec();
if(c == 0)
break;
}
*q++ = c;
c = getrec();
}
*q = 0;
if(c == 0)
return LBAD;
yylval.str = u.string;
return LCLASS;
}

260
src/cmd/grep/main.c Normal file
View file

@ -0,0 +1,260 @@
#define EXTERN
#include "grep.h"
char *validflags = "bchiLlnsv";
void
usage(void)
{
fprint(2, "usage: grep [-%s] [-f file] [-e expr] [file ...]\n", validflags);
exits("usage");
}
void
main(int argc, char *argv[])
{
int i, status;
ARGBEGIN {
default:
if(utfrune(validflags, ARGC()) == nil)
usage();
flags[ARGC()]++;
break;
case 'e':
flags['e']++;
lineno = 0;
str2top(ARGF());
break;
case 'f':
flags['f']++;
filename = ARGF();
rein = Bopen(filename, OREAD);
if(rein == 0) {
fprint(2, "grep: can't open %s: %r\n", filename);
exits("open");
}
lineno = 1;
str2top(filename);
break;
} ARGEND
if(flags['f'] == 0 && flags['e'] == 0) {
if(argc <= 0)
usage();
str2top(argv[0]);
argc--;
argv++;
}
follow = mal(maxfollow*sizeof(*follow));
state0 = initstate(topre.beg);
Binit(&bout, 1, OWRITE);
switch(argc) {
case 0:
status = search(0, 0);
break;
case 1:
status = search(argv[0], 0);
break;
default:
status = 0;
for(i=0; i<argc; i++)
status |= search(argv[i], Hflag);
break;
}
if(status)
exits(0);
exits("no matches");
}
int
search(char *file, int flag)
{
State *s, *ns;
int c, fid, eof, nl, empty;
long count, lineno, n;
uchar *elp, *lp, *bol;
if(file == 0) {
file = "stdin";
fid = 0;
flag |= Bflag;
} else
fid = open(file, OREAD);
if(fid < 0) {
fprint(2, "grep: can't open %s: %r\n", file);
return 0;
}
if(flags['b'])
flag ^= Bflag; /* dont buffer output */
if(flags['c'])
flag |= Cflag; /* count */
if(flags['h'])
flag &= ~Hflag; /* do not print file name in output */
if(flags['i'])
flag |= Iflag; /* fold upper-lower */
if(flags['l'])
flag |= Llflag; /* print only name of file if any match */
if(flags['L'])
flag |= LLflag; /* print only name of file if any non match */
if(flags['n'])
flag |= Nflag; /* count only */
if(flags['s'])
flag |= Sflag; /* status only */
if(flags['v'])
flag |= Vflag; /* inverse match */
s = state0;
lineno = 0;
count = 0;
eof = 0;
empty = 1;
nl = 0;
lp = u.buf;
bol = lp;
loop0:
n = lp-bol;
if(n > sizeof(u.pre))
n = sizeof(u.pre);
memmove(u.buf-n, bol, n);
bol = u.buf-n;
n = read(fid, u.buf, sizeof(u.buf));
/* if file has no final newline, simulate one to emit matches to last line */
if(n > 0) {
empty = 0;
nl = u.buf[n-1]=='\n';
} else {
if(n < 0){
fprint(2, "grep: read error on %s: %r\n", file);
return count != 0;
}
if(!eof && !nl && !empty) {
u.buf[0] = '\n';
n = 1;
eof = 1;
}
}
if(n <= 0) {
close(fid);
if(flag & Cflag) {
if(flag & Hflag)
Bprint(&bout, "%s:", file);
Bprint(&bout, "%ld\n", count);
}
if(((flag&Llflag) && count != 0) || ((flag&LLflag) && count == 0))
Bprint(&bout, "%s\n", file);
Bflush(&bout);
return count != 0;
}
lp = u.buf;
elp = lp+n;
if(flag & Iflag)
goto loopi;
/*
* normal character loop
*/
loop:
c = *lp;
ns = s->next[c];
if(ns == 0) {
increment(s, c);
goto loop;
}
// if(flags['2'])
// if(s->match)
// print("%d: %.2x**\n", s, c);
// else
// print("%d: %.2x\n", s, c);
lp++;
s = ns;
if(c == '\n') {
lineno++;
if(!!s->match == !(flag&Vflag)) {
count++;
if(flag & (Cflag|Sflag|Llflag|LLflag))
goto cont;
if(flag & Hflag)
Bprint(&bout, "%s:", file);
if(flag & Nflag)
Bprint(&bout, "%ld: ", lineno);
/* suppress extra newline at EOF unless we are labeling matches with file name */
Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
if(flag & Bflag)
Bflush(&bout);
}
if((lineno & Flshcnt) == 0)
Bflush(&bout);
cont:
bol = lp;
}
if(lp != elp)
goto loop;
goto loop0;
/*
* character loop for -i flag
* for speed
*/
loopi:
c = *lp;
if(c >= 'A' && c <= 'Z')
c += 'a'-'A';
ns = s->next[c];
if(ns == 0) {
increment(s, c);
goto loopi;
}
lp++;
s = ns;
if(c == '\n') {
lineno++;
if(!!s->match == !(flag&Vflag)) {
count++;
if(flag & (Cflag|Sflag|Llflag|LLflag))
goto conti;
if(flag & Hflag)
Bprint(&bout, "%s:", file);
if(flag & Nflag)
Bprint(&bout, "%ld: ", lineno);
/* suppress extra newline at EOF unless we are labeling matches with file name */
Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag)));
if(flag & Bflag)
Bflush(&bout);
}
if((lineno & Flshcnt) == 0)
Bflush(&bout);
conti:
bol = lp;
}
if(lp != elp)
goto loopi;
goto loop0;
}
State*
initstate(Re *r)
{
State *s;
int i;
addcase(r);
if(flags['1'])
reprint("r", r);
nfollow = 0;
gen++;
fol1(r, Cbegin);
follow[nfollow++] = r;
qsort(follow, nfollow, sizeof(*follow), fcmp);
s = sal(nfollow);
for(i=0; i<nfollow; i++)
s->re[i] = follow[i];
return s;
}

20
src/cmd/grep/mkfile Normal file
View file

@ -0,0 +1,20 @@
PLAN9=../../..
<$PLAN9/src/mkhdr
# Calling this grep breaks a LOT. Like egrep on Linux.
# And probably configure.
TARG=9grep
HFILES=\
grep.h\
OFILES=\
y.tab.$O\
main.$O\
comp.$O\
sub.$O\
YFILES=grep.y\
SHORTLIB=bio 9
<$PLAN9/src/mkone

317
src/cmd/grep/sub.c Normal file
View file

@ -0,0 +1,317 @@
#include "grep.h"
void*
mal(int n)
{
static char *s;
static int m = 0;
void *v;
n = (n+3) & ~3;
if(m < n) {
if(n > Nhunk) {
v = sbrk(n);
memset(v, 0, n);
return v;
}
s = sbrk(Nhunk);
m = Nhunk;
}
v = s;
s += n;
m -= n;
memset(v, 0, n);
return v;
}
State*
sal(int n)
{
State *s;
s = mal(sizeof(*s));
// s->next = mal(256*sizeof(*s->next));
s->count = n;
s->re = mal(n*sizeof(*state0->re));
return s;
}
Re*
ral(int type)
{
Re *r;
r = mal(sizeof(*r));
r->type = type;
maxfollow++;
return r;
}
void
error(char *s)
{
fprint(2, "grep: internal error: %s\n", s);
exits(s);
}
int
countor(Re *r)
{
int n;
n = 0;
loop:
switch(r->type) {
case Tor:
n += countor(r->alt);
r = r->next;
goto loop;
case Tclass:
return n + r->hi - r->lo + 1;
}
return n;
}
Re*
oralloc(int t, Re *r, Re *b)
{
Re *a;
if(b == 0)
return r;
a = ral(t);
a->alt = r;
a->next = b;
return a;
}
void
case1(Re *c, Re *r)
{
int n;
loop:
switch(r->type) {
case Tor:
case1(c, r->alt);
r = r->next;
goto loop;
case Tclass: /* add to character */
for(n=r->lo; n<=r->hi; n++)
c->cases[n] = oralloc(Tor, r->next, c->cases[n]);
break;
default: /* add everything unknown to next */
c->next = oralloc(Talt, r, c->next);
break;
}
}
Re*
addcase(Re *r)
{
int i, n;
Re *a;
if(r->gen == gen)
return r;
r->gen = gen;
switch(r->type) {
default:
error("addcase");
case Tor:
n = countor(r);
if(n >= Caselim) {
a = ral(Tcase);
a->cases = mal(256*sizeof(*a->cases));
case1(a, r);
for(i=0; i<256; i++)
if(a->cases[i]) {
r = a->cases[i];
if(countor(r) < n)
a->cases[i] = addcase(r);
}
return a;
}
return r;
case Talt:
r->next = addcase(r->next);
r->alt = addcase(r->alt);
return r;
case Tbegin:
case Tend:
case Tclass:
return r;
}
}
void
str2top(char *p)
{
Re2 oldtop;
oldtop = topre;
input = p;
topre.beg = 0;
topre.end = 0;
yyparse();
gen++;
if(topre.beg == 0)
yyerror("syntax");
if(oldtop.beg)
topre = re2or(oldtop, topre);
}
void
appendnext(Re *a, Re *b)
{
Re *n;
while(n = a->next)
a = n;
a->next = b;
}
void
patchnext(Re *a, Re *b)
{
Re *n;
while(a) {
n = a->next;
a->next = b;
a = n;
}
}
int
getrec(void)
{
int c;
if(flags['f']) {
c = Bgetc(rein);
if(c <= 0)
return 0;
} else
c = *input++ & 0xff;
if(flags['i'] && c >= 'A' && c <= 'Z')
c += 'a'-'A';
if(c == '\n')
lineno++;
return c;
}
Re2
re2cat(Re2 a, Re2 b)
{
Re2 c;
c.beg = a.beg;
c.end = b.end;
patchnext(a.end, b.beg);
return c;
}
Re2
re2star(Re2 a)
{
Re2 c;
c.beg = ral(Talt);
c.beg->alt = a.beg;
patchnext(a.end, c.beg);
c.end = c.beg;
return c;
}
Re2
re2or(Re2 a, Re2 b)
{
Re2 c;
c.beg = ral(Tor);
c.beg->alt = b.beg;
c.beg->next = a.beg;
c.end = b.end;
appendnext(c.end, a.end);
return c;
}
Re2
re2char(int c0, int c1)
{
Re2 c;
c.beg = ral(Tclass);
c.beg->lo = c0 & 0xff;
c.beg->hi = c1 & 0xff;
c.end = c.beg;
return c;
}
void
reprint1(Re *a)
{
int i, j;
loop:
if(a == 0)
return;
if(a->gen == gen)
return;
a->gen = gen;
print("%p: ", a);
switch(a->type) {
default:
print("type %d\n", a->type);
error("print1 type");
case Tcase:
print("case ->%p\n", a->next);
for(i=0; i<256; i++)
if(a->cases[i]) {
for(j=i+1; j<256; j++)
if(a->cases[i] != a->cases[j])
break;
print(" [%.2x-%.2x] ->%p\n", i, j-1, a->cases[i]);
i = j-1;
}
for(i=0; i<256; i++)
reprint1(a->cases[i]);
break;
case Tbegin:
print("^ ->%p\n", a->next);
break;
case Tend:
print("$ ->%p\n", a->next);
break;
case Tclass:
print("[%.2x-%.2x] ->%p\n", a->lo, a->hi, a->next);
break;
case Tor:
case Talt:
print("| %p ->%p\n", a->alt, a->next);
reprint1(a->alt);
break;
}
a = a->next;
goto loop;
}
void
reprint(char *s, Re *r)
{
print("%s:\n", s);
gen++;
reprint1(r);
print("\n\n");
}

View file

@ -3,11 +3,11 @@ PLAN9=../..
TARG=`ls *.c | sed 's/\.c//'` TARG=`ls *.c | sed 's/\.c//'`
LDFLAGS=$LDFLAGS LDFLAGS=$LDFLAGS
SHORTLIB=sec fs mux regexp9 thread bio 9 SHORTLIB=mach sec fs mux regexp9 thread bio 9
<$PLAN9/src/mkmany <$PLAN9/src/mkmany
BUGGERED='CVS|9term|faces|factotum|htmlfmt|mk|rio|upas|vac|venti' BUGGERED='CVS|faces|factotum|htmlfmt|mk|upas|vac|venti'
DIRS=`ls -l |sed -n 's/^d.* //p' |egrep -v "^($BUGGERED)$"` DIRS=`ls -l |sed -n 's/^d.* //p' |egrep -v "^($BUGGERED)$"`
<$PLAN9/src/mkdirs <$PLAN9/src/mkdirs

View file

@ -97,6 +97,7 @@ static Dirtab dir[NDIR] =
static int ndir = NQID; static int ndir = NQID;
static int srvfd; static int srvfd;
#define clock plumbclock /* SunOS name clash */
static int clock; static int clock;
static Fid *fids[Nhash]; static Fid *fids[Nhash];
static QLock readlock; static QLock readlock;

View file

@ -54,9 +54,10 @@ threadmain(int argc, char *argv[])
error("can't initialize $user or $home: %r"); error("can't initialize $user or $home: %r");
if(plumbfile == nil){ if(plumbfile == nil){
sprint(buf, "%s/lib/plumbing", home); sprint(buf, "%s/lib/plumbing", home);
if(access(buf, 0) < 0) if(access(buf, 0) >= 0)
sprint(buf, "#9/plumb/initial.plumbing"); plumbfile = estrdup(buf);
plumbfile = estrdup(buf); else
plumbfile = unsharp("#9/plumb/initial.plumbing");
} }
fd = open(plumbfile, OREAD); fd = open(plumbfile, OREAD);

View file

@ -415,7 +415,7 @@ include(char *s)
fd = open(t, OREAD); fd = open(t, OREAD);
if(fd<0 && t[0]!='/' && strncmp(t, "./", 2)!=0 && strncmp(t, "../", 3)!=0){ if(fd<0 && t[0]!='/' && strncmp(t, "./", 2)!=0 && strncmp(t, "../", 3)!=0){
snprint(buf, sizeof buf, "#9/plumb/%s", t); snprint(buf, sizeof buf, "#9/plumb/%s", t);
t = buf; t = unsharp(buf);
fd = open(t, OREAD); fd = open(t, OREAD);
} }
if(fd < 0) if(fd < 0)

View file

@ -27,20 +27,10 @@ char *syssigname[]={
char* char*
Rcmain(void) Rcmain(void)
{ {
return "#9/rcmain"; return unsharp("#9/rcmain");
/*
static char buf[256];
char *root;
root = getenv("PLAN9");
if(root == nil)
root = "/usr/local/plan9";
snprint(buf, sizeof buf, "%s/rcmain", root);
return buf;
*/
} }
char Fdprefix[]="#d/"; char Fdprefix[]="/dev/fd/";
void execfinit(void); void execfinit(void);
void execbind(void); void execbind(void);
void execmount(void); void execmount(void);

27
src/cmd/rio/Imakefile Normal file
View file

@ -0,0 +1,27 @@
INCLUDES = -I$(TOP)
DEPLIBS = $(DEPXLIB)
LOCAL_LIBRARIES = $(XLIB)
DEFINES = -DSHAPE # -g3 -DDEBUG -DDEBUG_EV
SRCS = main.c event.c manage.c menu.c client.c grab.c cursor.c error.c color.c
OBJS = main.o event.o manage.o menu.o client.o grab.o cursor.o error.o color.o
HFILES = dat.h fns.h patchlevel.h
MFILES = README 9wm.man Imakefile Makefile.no-imake
ComplexProgramTarget(rio)
bun:
bundle $(MFILES) $(SRCS) $(HFILES) >bun
dist:
bundle $(MFILES) main.c event.c manage.c >bun1
bundle menu.c client.c grab.c cursor.c error.c $(HFILES) >bun2
trout: 9wm.man
troff -man 9wm.man >trout
vu: trout
xditview trout
clean::
$(RM) bun bun[12] trout core

View file

@ -8,7 +8,7 @@
#include "fns.h" #include "fns.h"
unsigned long unsigned long
colorpixel(Display *dpy, int depth, ulong rgb) colorpixel(Display *dpy, int depth, unsigned long rgb)
{ {
int r, g, b; int r, g, b;

View file

@ -9,6 +9,9 @@
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/Xatom.h> #include <X11/Xatom.h>
#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif
#include "dat.h" #include "dat.h"
#include "fns.h" #include "fns.h"
#include "patchlevel.h" #include "patchlevel.h"
@ -70,12 +73,15 @@ main(int argc, char *argv[])
int i, background, do_exit, do_restart; int i, background, do_exit, do_restart;
char *fname; char *fname;
int shape_event; int shape_event;
#ifdef SHAPE
int dummy;
#endif
shape_event = 0; shape_event = 0;
myargv = argv; /* for restart */ myargv = argv; /* for restart */
do_exit = do_restart = 0; do_exit = do_restart = 0;
background = 1; background = 0;
font = 0; font = 0;
fname = 0; fname = 0;
for (i = 1; i < argc; i++) for (i = 1; i < argc; i++)
@ -289,12 +295,11 @@ initscreen(ScreenInfo *s, int i, int background)
XSync(dpy, False); XSync(dpy, False);
if (background) { if (background) {
/*
XSetWindowBackgroundPixmap(dpy, s->root, s->root_pixmap); XSetWindowBackgroundPixmap(dpy, s->root, s->root_pixmap);
XClearWindow(dpy, s->root); XClearWindow(dpy, s->root);
*/ } else
system("xsetroot -solid grey30"); system("xsetroot -solid grey30");
}
s->menuwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 2, colorpixel(dpy, s->depth, 0x88CC88), colorpixel(dpy, s->depth, 0xE9FFE9)); s->menuwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 2, colorpixel(dpy, s->depth, 0x88CC88), colorpixel(dpy, s->depth, 0xE9FFE9));
s->sweepwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 4, s->red, colorpixel(dpy, s->depth, 0xEEEEEE)); s->sweepwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 4, s->red, colorpixel(dpy, s->depth, 0xEEEEEE));
} }

View file

@ -1,3 +1,4 @@
PLAN9=../../..
<$PLAN9/src/mkhdr <$PLAN9/src/mkhdr
OFILES=\ OFILES=\
@ -18,3 +19,7 @@ TARG=rio
LDFLAGS=-L$X11/lib -lXext -lX11 LDFLAGS=-L$X11/lib -lXext -lX11
<$PLAN9/src/mkone <$PLAN9/src/mkone
CFLAGS=$CFLAGS -DSHAPE -I$X11/include

View file

@ -460,6 +460,9 @@ main(int argc, char *argv[])
int low; int low;
Bits h; Bits h;
codefile = unsharp(codefile);
brfile = unsharp(brfile);
Binit(&bin, 0, OREAD); Binit(&bin, 0, OREAD);
Binit(&bout, 1, OWRITE); Binit(&bout, 1, OWRITE);
for(i=0; c = "aeiouyAEIOUY"[i]; i++) for(i=0; c = "aeiouyAEIOUY"[i]; i++)

View file

@ -399,7 +399,7 @@ others(void)
{ {
int c, i, j; int c, i, j;
finput = Bopen(parser, OREAD); finput = Bopen(unsharp(parser), OREAD);
if(finput == 0) if(finput == 0)
error("cannot open parser %s: %r", parser); error("cannot open parser %s: %r", parser);
warray("yyr1", levprd, nprod); warray("yyr1", levprd, nprod);

View file

@ -14,7 +14,7 @@ static struct {
}; };
char* char*
_p9translate(char *old) plan9translate(char *old)
{ {
char *new; char *new;
int i, olen, nlen, len; int i, olen, nlen, len;
@ -36,7 +36,7 @@ _p9translate(char *old)
len = strlen(old)+nlen-olen; len = strlen(old)+nlen-olen;
new = malloc(len+1); new = malloc(len+1);
if(new == nil) if(new == nil)
return nil; return "<out of memory>";
strcpy(new, replace[i].new); strcpy(new, replace[i].new);
strcpy(new+nlen, old+olen); strcpy(new+nlen, old+olen);
assert(strlen(new) == len); assert(strlen(new) == len);

View file

@ -1,19 +0,0 @@
#include <u.h>
#define NOPLAN9DEFINES
#include <libc.h>
char *_p9translate(char*);
int
p9access(char *xname, int what)
{
int ret;
char *name;
if((name = _p9translate(xname)) == nil)
return -1;
ret = access(name, what);
if(name != xname)
free(name);
return ret;
}

View file

@ -40,7 +40,8 @@ p9announce(char *addr, char *dir)
char *net; char *net;
u32int host; u32int host;
int port, s; int port, s;
int n, sn; int n;
socklen_t sn;
struct sockaddr_in sa; struct sockaddr_in sa;
struct sockaddr_un sun; struct sockaddr_un sun;
@ -72,7 +73,7 @@ p9announce(char *addr, char *dir)
if((s = socket(AF_INET, proto, 0)) < 0) if((s = socket(AF_INET, proto, 0)) < 0)
return -1; return -1;
sn = sizeof n; sn = sizeof n;
if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&n, &sn) >= 0 if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0
&& n == SOCK_STREAM){ && n == SOCK_STREAM){
n = 1; n = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n); setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n);

View file

@ -3,16 +3,10 @@
#include <libc.h> #include <libc.h>
#include <sys/stat.h> #include <sys/stat.h>
extern char *_p9translate(char*);
int int
p9create(char *xpath, int mode, ulong perm) p9create(char *path, int mode, ulong perm)
{ {
int fd, cexec, umode, rclose; int fd, cexec, umode, rclose;
char *path;
if((path = _p9translate(xpath)) == nil)
return -1;
cexec = mode&OCEXEC; cexec = mode&OCEXEC;
rclose = mode&ORCLOSE; rclose = mode&ORCLOSE;
@ -48,7 +42,5 @@ out:
if(rclose) if(rclose)
remove(path); remove(path);
} }
if(path != xpath)
free(path);
return fd; return fd;
} }

View file

@ -15,6 +15,7 @@ ct_numb(char *cp, int n)
char* char*
asctime(Tm *t) asctime(Tm *t)
{ {
int i;
char *ncp; char *ncp;
static char cbuf[30]; static char cbuf[30];
@ -32,6 +33,12 @@ asctime(Tm *t)
ct_numb(cbuf+14, t->min+100); ct_numb(cbuf+14, t->min+100);
ct_numb(cbuf+17, t->sec+100); ct_numb(cbuf+17, t->sec+100);
ncp = t->zone; ncp = t->zone;
for(i=0; i<3; i++)
if(ncp[i] == 0)
break;
for(; i<3; i++)
ncp[i] = '?';
ncp = t->zone;
cbuf[20] = *ncp++; cbuf[20] = *ncp++;
cbuf[21] = *ncp++; cbuf[21] = *ncp++;
cbuf[22] = *ncp; cbuf[22] = *ncp;

View file

@ -1,6 +1,5 @@
#include <stdlib.h> /* setenv etc. */
#include <u.h> #include <u.h>
#include <stdlib.h> /* setenv etc. */
#define NOPLAN9DEFINES #define NOPLAN9DEFINES
#include <libc.h> #include <libc.h>
#include <time.h> #include <time.h>
@ -25,6 +24,8 @@ static Tm bigtm;
static void static void
tm2Tm(struct tm *tm, Tm *bigtm) tm2Tm(struct tm *tm, Tm *bigtm)
{ {
char *s;
memset(bigtm, 0, sizeof *bigtm); memset(bigtm, 0, sizeof *bigtm);
bigtm->sec = tm->tm_sec; bigtm->sec = tm->tm_sec;
bigtm->min = tm->tm_min; bigtm->min = tm->tm_min;
@ -39,6 +40,13 @@ tm2Tm(struct tm *tm, Tm *bigtm)
#ifdef _HAVETZOFF #ifdef _HAVETZOFF
bigtm->tzoff = tm->tm_gmtoff; bigtm->tzoff = tm->tm_gmtoff;
#endif #endif
if(bigtm->zone[0] == 0){
s = getenv("TIMEZONE");
if(s){
strecpy(bigtm->zone, bigtm->zone+4, tm->tm_zone);
free(s);
}
}
} }
static void static void

View file

@ -18,7 +18,7 @@ mygetdents(int fd, struct dirent *buf, int n)
nn = getdirentries(fd, (void*)buf, n, &off); nn = getdirentries(fd, (void*)buf, n, &off);
return nn; return nn;
} }
#elif defined(__APPLE__) || defined(__FreeBSD__) #elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
static int static int
mygetdents(int fd, struct dirent *buf, int n) mygetdents(int fd, struct dirent *buf, int n)
{ {
@ -171,7 +171,7 @@ dirreadall(int fd, Dir **d)
ts += n; ts += n;
} }
if(ts >= 0) if(ts >= 0)
ts = dirpackage(fd, buf, ts, d); ts = dirpackage(fd, (char*)buf, ts, d);
free(buf); free(buf);
if(ts == 0 && n < 0) if(ts == 0 && n < 0)
return -1; return -1;

View file

@ -5,9 +5,10 @@
* okay. * okay.
*/ */
#include <u.h>
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <lib9.h> #include <libc.h>
enum enum
{ {

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

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

View file

@ -1,6 +1,5 @@
#include <pwd.h>
#include <u.h> #include <u.h>
#include <pwd.h>
#include <libc.h> #include <libc.h>
char* char*

View file

@ -1,6 +1,7 @@
#include <u.h>
#include <unistd.h> #include <unistd.h>
#include <sched.h> #include <sched.h>
#include <lib9.h> #include <libc.h>
int _ntas; int _ntas;
static int static int

View file

@ -1,6 +1,7 @@
#include <u.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <lib9.h> #include <libc.h>
void* void*
mallocz(unsigned long n, int clr) mallocz(unsigned long n, int clr)

View file

@ -69,8 +69,6 @@ LIB9OFILES=\
_p9dialparse.$O\ _p9dialparse.$O\
_p9dir.$O\ _p9dir.$O\
_p9proc.$O\ _p9proc.$O\
_p9translate.$O\
access.$O\
announce.$O\ announce.$O\
argv0.$O\ argv0.$O\
atexit.$O\ atexit.$O\
@ -100,6 +98,7 @@ LIB9OFILES=\
exec.$O\ exec.$O\
fcallfmt.$O\ fcallfmt.$O\
ffork-$SYSNAME.$O\ ffork-$SYSNAME.$O\
get9root.$O\
getcallerpc-$OBJTYPE.$O\ getcallerpc-$OBJTYPE.$O\
getenv.$O\ getenv.$O\
getfields.$O\ getfields.$O\
@ -142,6 +141,7 @@ LIB9OFILES=\
u16.$O\ u16.$O\
u32.$O\ u32.$O\
u64.$O\ u64.$O\
unsharp.$O\
wait.$O\ wait.$O\
waitpid.$O\ waitpid.$O\

View file

@ -1,6 +1,5 @@
#include <signal.h>
#include <u.h> #include <u.h>
#include <signal.h>
#define NOPLAN9DEFINES #define NOPLAN9DEFINES
#include <libc.h> #include <libc.h>
#include "9proc.h" #include "9proc.h"

View file

@ -2,12 +2,9 @@
#define NOPLAN9DEFINES #define NOPLAN9DEFINES
#include <libc.h> #include <libc.h>
extern char* _p9translate(char*);
int int
p9open(char *xname, int mode) p9open(char *name, int mode)
{ {
char *name;
int cexec, rclose; int cexec, rclose;
int fd, umode; int fd, umode;
@ -23,8 +20,6 @@ p9open(char *xname, int mode)
werrstr("mode not supported"); werrstr("mode not supported");
return -1; return -1;
} }
if((name = _p9translate(xname)) == nil)
return -1;
fd = open(name, umode); fd = open(name, umode);
if(fd >= 0){ if(fd >= 0){
if(cexec) if(cexec)
@ -32,7 +27,5 @@ p9open(char *xname, int mode)
if(rclose) if(rclose)
remove(name); remove(name);
} }
if(name != xname)
free(name);
return fd; return fd;
} }

View file

@ -1 +1,3 @@
/* Could use futex(2) here instead of signals? */
#include "rendez-signal.c" #include "rendez-signal.c"

View file

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

View file

@ -32,9 +32,10 @@
* shared memory and mutexes. * shared memory and mutexes.
*/ */
#include <u.h>
#include <pthread.h> #include <pthread.h>
#include <signal.h> #include <signal.h>
#include <lib9.h> #include <libc.h>
enum enum
{ {

View file

@ -1,7 +1,7 @@
#include <sys/time.h>
#include <sys/resource.h>
#include <u.h> #include <u.h>
#include <sys/time.h>
#include <time.h>
#include <sys/resource.h>
#define NOPLAN9DEFINES #define NOPLAN9DEFINES
#include <libc.h> #include <libc.h>

View file

@ -16,10 +16,12 @@ openfont(Display *d, char *name)
if(fd < 0 && strncmp(name, "/lib/font/bit/", 14) == 0){ if(fd < 0 && strncmp(name, "/lib/font/bit/", 14) == 0){
nambuf = smprint("#9/font/%s", name+14); nambuf = smprint("#9/font/%s", name+14);
if(nambuf == nil)
return 0;
nambuf = unsharp(nambuf);
if(nambuf == nil) if(nambuf == nil)
return 0; return 0;
if((fd = open(nambuf, OREAD)) < 0){ if((fd = open(nambuf, OREAD)) < 0){
fprint(2, "failed at %s\n", nambuf);
free(nambuf); free(nambuf);
return 0; return 0;
} }

View file

@ -185,26 +185,22 @@ xattach(char *label)
/* /*
* Figure out underlying screen format. * Figure out underlying screen format.
*/ */
_x.depth = DefaultDepth(_x.display, xrootid);
if(XMatchVisualInfo(_x.display, xrootid, 16, TrueColor, &xvi) if(XMatchVisualInfo(_x.display, xrootid, 16, TrueColor, &xvi)
|| XMatchVisualInfo(_x.display, xrootid, 16, DirectColor, &xvi)){ || XMatchVisualInfo(_x.display, xrootid, 16, DirectColor, &xvi)){
_x.vis = xvi.visual; _x.vis = xvi.visual;
_x.depth = 16; _x.depth = 16;
_x.usetable = 1;
} }
else else
if(XMatchVisualInfo(_x.display, xrootid, 15, TrueColor, &xvi) if(XMatchVisualInfo(_x.display, xrootid, 15, TrueColor, &xvi)
|| XMatchVisualInfo(_x.display, xrootid, 15, DirectColor, &xvi)){ || XMatchVisualInfo(_x.display, xrootid, 15, DirectColor, &xvi)){
_x.vis = xvi.visual; _x.vis = xvi.visual;
_x.depth = 15; _x.depth = 15;
_x.usetable = 1;
} }
else else
if(XMatchVisualInfo(_x.display, xrootid, 24, TrueColor, &xvi) if(XMatchVisualInfo(_x.display, xrootid, 24, TrueColor, &xvi)
|| XMatchVisualInfo(_x.display, xrootid, 24, DirectColor, &xvi)){ || XMatchVisualInfo(_x.display, xrootid, 24, DirectColor, &xvi)){
_x.vis = xvi.visual; _x.vis = xvi.visual;
_x.depth = 24; _x.depth = 24;
_x.usetable = 1;
} }
else else
if(XMatchVisualInfo(_x.display, xrootid, 8, PseudoColor, &xvi) if(XMatchVisualInfo(_x.display, xrootid, 8, PseudoColor, &xvi)
@ -218,6 +214,7 @@ xattach(char *label)
_x.depth = 8; _x.depth = 8;
} }
else{ else{
_x.depth = DefaultDepth(_x.display, xrootid);
if(_x.depth != 8){ if(_x.depth != 8){
werrstr("can't understand depth %d screen", _x.depth); werrstr("can't understand depth %d screen", _x.depth);
goto err0; goto err0;
@ -225,6 +222,9 @@ xattach(char *label)
_x.vis = DefaultVisual(_x.display, xrootid); _x.vis = DefaultVisual(_x.display, xrootid);
} }
if(DefaultDepth(_x.display, xrootid) == _x.depth)
_x.usetable = 1;
/* /*
* _x.depth is only the number of significant pixel bits, * _x.depth is only the number of significant pixel bits,
* not the total number of pixel bits. We need to walk the * not the total number of pixel bits. We need to walk the
@ -298,7 +298,7 @@ xattach(char *label)
Dx(r), /* width */ Dx(r), /* width */
Dy(r), /* height */ Dy(r), /* height */
0, /* border width */ 0, /* border width */
DefaultDepthOfScreen(xscreen), /* depth */ _x.depth, /* depth */
InputOutput, /* class */ InputOutput, /* class */
_x.vis, /* visual */ _x.vis, /* visual */
/* valuemask */ /* valuemask */
@ -562,6 +562,18 @@ setupcmap(XWindow w)
return 0; return 0;
if(_x.depth >= 24) { if(_x.depth >= 24) {
/*
* This is needed for SunOS. Ask Axel Belinfante.
*/
if(_x.usetable == 0){
_x.cmap = XCreateColormap(_x.display, w, _x.vis, AllocAll);
XStoreColors(_x.display, _x.cmap, _x.map, 256);
for(i = 0; i < 256; i++){
_x.tox11[i] = i;
_x.toplan9[i] = i;
}
}
/* /*
* The pixel value returned from XGetPixel needs to * The pixel value returned from XGetPixel needs to
* be converted to RGB so we can call rgb2cmap() * be converted to RGB so we can call rgb2cmap()
@ -573,7 +585,6 @@ setupcmap(XWindow w)
* some displays say MSB even though they run on LSB. * some displays say MSB even though they run on LSB.
* Besides, this is more anal. * Besides, this is more anal.
*/ */
c = _x.map[19]; /* known to have different R, G, B values */ c = _x.map[19]; /* known to have different R, G, B values */
if(!XAllocColor(_x.display, _x.cmap, &c)){ if(!XAllocColor(_x.display, _x.cmap, &c)){
werrstr("XAllocColor: %r"); werrstr("XAllocColor: %r");

View file

@ -11,6 +11,9 @@
#include <keyboard.h> #include <keyboard.h>
#include "x11-memdraw.h" #include "x11-memdraw.h"
#undef time
static int static int
__xtoplan9kbd(XEvent *e) __xtoplan9kbd(XEvent *e)
{ {

View file

@ -68,7 +68,6 @@ plumbsendtofid(Fid *fid, Plumbmsg *m)
if(buf == nil) if(buf == nil)
return -1; return -1;
n = fswrite(fid, buf, n); n = fswrite(fid, buf, n);
fprint(2, "fswrite %d\n", n);
free(buf); free(buf);
return n; return n;
} }

View file

@ -0,0 +1,49 @@
.globl _setlabel
.type _setlabel,@function
_setlabel:
movl 4(%esp), %eax
movl 0(%esp), %edx
movl %edx, 0(%eax)
movl %ebx, 4(%eax)
movl %esp, 8(%eax)
movl %ebp, 12(%eax)
movl %esi, 16(%eax)
movl %edi, 20(%eax)
xorl %eax, %eax
ret
.globl _gotolabel
.type _gotolabel,@function
_gotolabel:
movl 4(%esp), %edx
movl 0(%edx), %ecx
movl 4(%edx), %ebx
movl 8(%edx), %esp
movl 12(%edx), %ebp
movl 16(%edx), %esi
movl 20(%edx), %edi
xorl %eax, %eax
incl %eax
movl %ecx, 0(%esp)
ret
# .globl _xinc
# _xinc:
# movl 4(%esp), %eax
# lock incl 0(%eax)
# ret
#
# .globl _xdec
# _xdec:
# movl 4(%esp), %eax
# lock decl 0(%eax)
# jz iszero
# movl $1, %eax
# ret
# iszero:
# movl $0, %eax
# ret
#

View file

@ -3,8 +3,8 @@
#include "threadimpl.h" #include "threadimpl.h"
static void efork(int[3], int[2], char*, char**); static void efork(int[3], int[2], char*, char**);
void static void
threadexec(Channel *pidc, int fd[3], char *prog, char *args[]) _threadexec(Channel *pidc, int fd[3], char *prog, char *args[], int freeargs)
{ {
int pfd[2]; int pfd[2];
int n, pid; int n, pid;
@ -40,6 +40,8 @@ threadexec(Channel *pidc, int fd[3], char *prog, char *args[])
efork(fd, pfd, prog, args); efork(fd, pfd, prog, args);
_exit(0); _exit(0);
default: default:
if(freeargs)
free(args);
break; break;
} }
@ -68,10 +70,43 @@ Bad:
sendul(pidc, ~0); sendul(pidc, ~0);
} }
void
threadexec(Channel *pidc, int fd[3], char *prog, char *args[])
{
_threadexec(pidc, fd, prog, args, 0);
}
/*
* The &f+1 trick doesn't work on SunOS, so we might
* as well bite the bullet and do this correctly.
*/
void void
threadexecl(Channel *pidc, int fd[3], char *f, ...) threadexecl(Channel *pidc, int fd[3], char *f, ...)
{ {
threadexec(pidc, fd, f, &f+1); char **args, *s;
int n;
va_list arg;
va_start(arg, f);
for(n=0; va_arg(arg, char*) != 0; n++)
;
n++;
va_end(arg);
args = malloc(n*sizeof(args[0]));
if(args == nil){
if(pidc)
sendul(pidc, ~0);
return;
}
va_start(arg, f);
for(n=0; (s=va_arg(arg, char*)) != 0; n++)
args[n] = s;
args[n] = 0;
va_end(arg);
_threadexec(pidc, fd, f, args, 1);
} }
static void static void

View file

@ -7,7 +7,7 @@
typedef struct Label Label; typedef struct Label Label;
#define LABELDPC 0 #define LABELDPC 0
#if defined (__i386__) && (defined(__FreeBSD__) || defined(__linux__)) #if defined (__i386__) && (defined(__FreeBSD__) || defined(__linux__) || defined(__OpenBSD__))
struct Label struct Label
{ {
ulong pc; ulong pc;

View file

@ -1,6 +1,6 @@
<mkhdr <mkhdr
BUGGERED='9p|html|httpd|ip|venti' BUGGERED='9p|fmt|html|httpd|ip|utf|venti'
LIBDIRS=`ls -ld lib* | sed -n 's/^d.* //p' |egrep -v "^lib($BUGGERED)$"` LIBDIRS=`ls -ld lib* | sed -n 's/^d.* //p' |egrep -v "^lib($BUGGERED)$"`
DIRS=\ DIRS=\