diff --git a/src/configure.in b/src/configure.in index f336bea3daca1ea74dbbe1d15564bf537506c14d..ac63f3d79044fc0d95f1a4623210cfd0c8a7dd03 100644 --- a/src/configure.in +++ b/src/configure.in @@ -1,4 +1,4 @@ -AC_REVISION("$Id: configure.in,v 1.146 1998/01/02 08:18:42 hubbe Exp $") +AC_REVISION("$Id: configure.in,v 1.147 1998/01/08 17:20:05 hubbe Exp $") AC_INIT(interpret.c) AC_CONFIG_HEADER(machine.h) @@ -927,6 +927,8 @@ AC_CHECK_FUNCS( \ strdup \ kill \ alarm \ + fork \ + fork1 \ ) if test $ac_cv_func_crypt$ac_cv_func__crypt = nono ; then @@ -1313,6 +1315,22 @@ int main() ############################################################################# +AC_MSG_CHECKING(if we can declare environ) +AC_CACHE_VAL(pike_cv_declare_environ,[ +AC_TRY_COMPILE([ +#include <stdlib.h> +],[ + extern char **environ; + exit(0); +],pike_cv_declare_environ=yes,pike_cv_declare_environ=no,pike_cv_declare_environ=yes) +]) + +AC_MSG_RESULT($pike_cv_declare_environ) +if test "x$pike_cv_declare_environ" = xyes ; then + AC_DEFINE(DECLARE_ENVIRON) +fi + +############################################################################# AC_MSG_CHECKING(how to extract an unsigned char) AC_CACHE_VAL(pike_cv_method_extract_uchar, diff --git a/src/fdlib.c b/src/fdlib.c index a6f5fadba48a442f4baed7fff675fbdf02f7f483..7395872c64b0a27520812778fd1c2f9cd63a73be 100644 --- a/src/fdlib.c +++ b/src/fdlib.c @@ -406,7 +406,7 @@ FD fd_dup(FD from) { FD fd; HANDLE x,p=GetCurrentProcess(); - if(!DuplicateHandle(p,(HANDLE)da_handle[from],p,&x,NULL,1,DUPLICATE_SAME_ACCESS)) + if(!DuplicateHandle(p,(HANDLE)da_handle[from],p,&x,NULL,0,DUPLICATE_SAME_ACCESS)) { errno=GetLastError(); return -1; @@ -424,7 +424,7 @@ FD fd_dup(FD from) FD fd_dup2(FD from, FD to) { HANDLE x,p=GetCurrentProcess(); - if(!DuplicateHandle(p,(HANDLE)da_handle[from],p,&x,NULL,1,DUPLICATE_SAME_ACCESS)) + if(!DuplicateHandle(p,(HANDLE)da_handle[from],p,&x,NULL,0,DUPLICATE_SAME_ACCESS)) { errno=GetLastError(); return -1; @@ -563,43 +563,1332 @@ void *fd_mapper_get(struct fd_mapper *x, FD fd) #endif +#if 0 +struct fd_data_hash +{ + FD fd; + int key; + struct fd_data_hash *next; + void *data; +}; + +#define FD_DATA_PER_BLOCK 255 + +struct fd_data_hash_block +{ + struct fd_data_hash_block *next; + struct fd_data_hash data[FD_DATA_PER_BLOCk]; +}; + +static int keynum=0; +static unsigned int num_stored_keys=0; +static unsigned int hash_size=0; +static struct fd_data_hash *free_blocks=0; +static struct fd_data_hash **htable=0; +static fd_data_hash_block *hash_blocks=0; + +int get_fd_data_key(void) +{ + return ++keynum; +} + +void store_fd_data(FD fd, int key, void *data) +{ + struct fd_data_hash *p,**last; + unsigned int hval=(fd + key * 53) % hash_size; + + for(last=htable[e];p=*last;last=&p->next) + { + if(p->fd == fd && p->key == key) + { + if(data) + { + p->data=data; + }else{ + *last=p->next; + p->next=free_blocks; + free_blocks=p; + num_stored_keys--; + } + return; + } + } + if(!data) return; + + num_stored_keys++; + + if(num_stored_keys * 2 >= hash_size) + { + /* time to rehash */ + unsigned int h; + unsigned int old_hsize=hash_size; + unsigned fd_data_hash **old_htable=htable; + if(!hash_size) + hash_size=127; + else + hash_size*=3; + + htable=(struct fd_data_hash **)xalloc(hash_size * sizeof(struct fd_data_hash *)); + + for(h=0;h<old_hsize;h++) + { + for(last=old_htable+e;p=*last;last=&p->next) + store_fd_data(p->fd, p->key, p->data); + *last=free_blocks; + free_blocks=old_htable[h]; + } + if(old_htable) + free((char *)old_htable); + } + + + if(!free_blocks) + { + struct fd_data_hash_block *n; + int e; + n=ALLOC_STRUCT(fd_data_hash_block); + n->next=hash_blocks; + hash_blocks=n; + for(e=0;e<FD_DATA_PER_BLOCK;e++) + { + n->data[e].next=free_blocks; + free_blocks=n->data+e; + } + } + + p=free_blocks; + free_blocks=p->next; + p->fd=fd; + p->key=key; + p->data=data; + p->next=htable[hval]; + htable[hval]=p; +} + +void *get_fd_data(FD fd, int key) +{ + struct fd_data_hash *p,**last; + unsigned int hval=(fd + key * 53) % hash_size; + + for(p=htable[hval];p;p=p->next) + if(p->fd == fd && p->key == key) + return p->data; + + return 0; +} + + +#endif + +#ifdef FDLIB_USE_SELECT + +struct fd_waitor +{ + fd_FDSET storage; + fd_FDSET temporary; +static long convert_filetime_to_time_t(FILETIME tmp) +{ + double t; + t=tmp.dwHighDateTime * pow(2.0,32.0) + (double)tmp.dwLowDateTime; + t/=10000000.0; + t-=11644473600.0; + return (long)floor(t); +} + +int fd_fstat(FD fd, struct stat *s) +{ + DWORD x; + int ret; + FILETIME c,a,m; + FDDEBUG(fprintf(stderr,"fstat on %d (%d)\n",fd,da_handle[fd])); + if(fd_type[fd]!=FD_FILE) + { + errno=ENOTSUPP; + return -1; + } + + MEMSET(s, 0, sizeof(struct stat)); + s->st_nlink=1; + + switch(fd_type[fd]) + { + case FD_SOCKET: + s->st_mode=S_IFSOCK; + break; + + default: + switch(GetFileType((HANDLE)da_handle[fd])) + { + default: + case FILE_TYPE_UNKNOWN: s->st_mode=0; break; + case FILE_TYPE_DISK: + s->st_mode=S_IFREG; + s->st_size=GetFileSize((HANDLE)da_handle[fd],&x); + if(x) + { + s->st_size=0x7fffffff; + } + if(!GetFileTime((HANDLE)da_handle[fd], &c, &a, &m)) + { + errno=GetLastError(); + return -1; + } + s->st_ctime=convert_filetime_to_time_t(c); + s->st_atime=convert_filetime_to_time_t(a); + s->st_mtime=convert_filetime_to_time_t(m); + break; + case FILE_TYPE_CHAR: s->st_mode=S_IFCHR; break; + case FILE_TYPE_PIPE: s->st_mode=S_IFFIFO; break; + } + } + s->st_mode |= 0666; + return 0; +} + +int fd_select(int fds, FD_SET *a, FD_SET *b, FD_SET *c, struct timeval *t) +{ + int ret; + ret=select(fds,a,b,c,t); + if(ret==SOCKET_ERROR) + { + errno=WSAGetLastError(); + return -1; + } + return ret; +} + + +int fd_ioctl(FD fd, int cmd, void *data) +{ + int ret; + switch(fd_type[fd]) + { + case FD_SOCKET: + ret=ioctlsocket((SOCKET)da_handle[fd], cmd, data); + if(ret==SOCKET_ERROR) + { + errno=WSAGetLastError(); + return -1; + } + return ret; + + default: + errno=ENOTSUPP; + return -1; + } +} + + +FD fd_dup(FD from) +{ + FD fd; + HANDLE x,p=GetCurrentProcess(); + if(!DuplicateHandle(p,(HANDLE)da_handle[from],p,&x,NULL,0,DUPLICATE_SAME_ACCESS)) + { + errno=GetLastError(); + return -1; + } + + fd=first_free_handle; + first_free_handle=fd_type[fd]; + fd_type[fd]=fd_type[from]; + da_handle[fd]=(long)x; + + FDDEBUG(fprintf(stderr,"Dup %d (%d) to %d (%d)\n",from,da_handle[from],fd,x)); + return fd; +} + +FD fd_dup2(FD from, FD to) +{ + HANDLE x,p=GetCurrentProcess(); + if(!DuplicateHandle(p,(HANDLE)da_handle[from],p,&x,NULL,0,DUPLICATE_SAME_ACCESS)) + { + errno=GetLastError(); + return -1; + } + + if(fd_type[to] < FD_NO_MORE_FREE) + { + if(!CloseHandle((HANDLE)da_handle[to])) + { + errno=GetLastError(); + return -1; + } + }else{ + int *prev,next; + for(prev=&first_free_handle;(next=*prev) != FD_NO_MORE_FREE;prev=fd_type+next) + { + if(next==to) + { + *prev=fd_type[next]; + break; + } + } + } + fd_type[to]=fd_type[from]; + da_handle[to]=(long)x; + + FDDEBUG(fprintf(stderr,"Dup2 %d (%d) to %d (%d)\n",from,da_handle[from],to,x)); + + return to; +} + +#endif + +#if 0 + +#ifdef FD_LINEAR +struct fd_mapper +{ + int size; + void **data; +}; + +void init_fd_mapper(struct fd_mapper *x) +{ + x->size=64; + x->data=(void **)xalloc(x->size*sizeof(void *)); +} + +void exit_fd_mapper(struct fd_mapper *x) +{ + free((char *)x->data); +} + +void fd_mapper_set(struct fd_mapper *x, FD fd, void *data) +{ + while(fd>=x->size) + { + x->size*=2; + x->data=(void **)realloc((char *)x->data, x->size*sizeof(void *)); + if(!x->data) + fatal("Out of memory.\n"); + x->data=nd; + } + x->data[fd]=data; + +} + +void *fd_mapper_get(struct fd_mapper *x, FD fd) +{ + return x->data[fd]; +} +#else +struct fd_mapper_data +{ + FD x; + void *data; +}; +struct fd_mapper +{ + int num; + int hsize; + struct fd_mapper_data *data; +}; + +void init_fd_mapper(struct fd_mapper *x) +{ + int i; + x->num=0; + x->hsize=127; + x->data=(struct fd_mapper_data *)xalloc(x->hsize*sizeof(struct fd_mapper_data)); + for(i=0;i<x->hsize;i++) x->data[i].fd=-1; +} + +void exit_fd_mapper(struct fd_mapper *x) +{ + free((char *)x->data); +} + +void fd_mapper_set(struct fd_mapper *x, FD fd, void *data) +{ + int hval; + x->num++; + if(x->num*2 > x->hsize) + { + struct fd_mapper_data *old=x->data; + int i,old_size=x->hsize; + x->hsize*=3; + x->num=0; + x->data=(struct fd_mapper_data *)xalloc(x->size*sizeof(struct fd_mapper_data *)); + for(i=0;i<x->size;i++) x->data[i].fd=-1; + for(i=0;i<old_size;i++) + if(old[i].fd!=-1) + fd_mapper_set(x, old[i].fd, old[i].data); + } + + hval=fd % x->hsize; + while(x->data[hval].fd != -1) + { + hval++; + if(hval==x->hsize) hval=0; + } + x->data[hval].fd=fd; + x->data[hval].data=data; +} + +void *fd_mapper_get(struct fd_mapper *x, FD fd) +{ + int hval=fd % x->hsize; + while(x->data[hval].fd != fd) + { + hval++; + if(hval==x->hsize) hval=0; + } + return x->data[hval].data; +} +#endif + + +#if 0 +struct fd_data_hash +{ + FD fd; + int key; + struct fd_data_hash *next; + void *data; +}; + +#define FD_DATA_PER_BLOCK 255 + +struct fd_data_hash_block +{ + struct fd_data_hash_block *next; + struct fd_data_hash data[FD_DATA_PER_BLOCk]; +}; + +static int keynum=0; +static unsigned int num_stored_keys=0; +static unsigned int hash_size=0; +static struct fd_data_hash *free_blocks=0; +static struct fd_data_hash **htable=0; +static fd_data_hash_block *hash_blocks=0; + +int get_fd_data_key(void) +{ + return ++keynum; +} + +void store_fd_data(FD fd, int key, void *data) +{ + struct fd_data_hash *p,**last; + unsigned int hval=(fd + key * 53) % hash_size; + + for(last=htable[e];p=*last;last=&p->next) + { + if(p->fd == fd && p->key == key) + { + if(data) + { + p->data=data; + }else{ + *last=p->next; + p->next=free_blocks; + free_blocks=p; + num_stored_keys--; + } + return; + } + } + if(!data) return; + + num_stored_keys++; + + if(num_stored_keys * 2 >= hash_size) + { + /* time to rehash */ + unsigned int h; + unsigned int old_hsize=hash_size; + unsigned fd_data_hash **old_htable=htable; + if(!hash_size) + hash_size=127; + else + hash_size*=3; + + htable=(struct fd_data_hash **)xalloc(hash_size * sizeof(struct fd_data_hash *)); + + for(h=0;h<old_hsize;h++) + { + for(last=old_htable+e;p=*last;last=&p->next) + store_fd_data(p->fd, p->key, p->data); + *last=free_blocks; + free_blocks=old_htable[h]; + } + if(old_htable) + free((char *)old_htable); + } + + + if(!free_blocks) + { + struct fd_data_hash_block *n; + int e; + n=ALLOC_STRUCT(fd_data_hash_block); + n->next=hash_blocks; + hash_blocks=n; + for(e=0;e<FD_DATA_PER_BLOCK;e++) + { + n->data[e].next=free_blocks; + free_blocks=n->data+e; + } + } + + p=free_blocks; + free_blocks=p->next; + p->fd=fd; + p->key=key; + p->data=data; + p->next=htable[hval]; + htable[hval]=p; +} + +void *get_fd_data(FD fd, int key) +{ + struct fd_data_hash *p,**last; + unsigned int hval=(fd + key * 53) % hash_size; + + for(p=htable[hval];p;p=p->next) + if(p->fd == fd && p->key == key) + return p->data; + + return 0; +} + + +#endif + +#ifdef FDLIB_USE_SELECT + +struct fd_waitor +{ + fd_FDSET storage; + fd_FDSET temporary; +static long convert_filetime_to_time_t(FILETIME tmp) +{ + double t; + t=tmp.dwHighDateTime * pow(2.0,32.0) + (double)tmp.dwLowDateTime; + t/=10000000.0; + t-=11644473600.0; + return (long)floor(t); +} + +int fd_fstat(FD fd, struct stat *s) +{ + DWORD x; + int ret; + FILETIME c,a,m; + FDDEBUG(fprintf(stderr,"fstat on %d (%d)\n",fd,da_handle[fd])); + if(fd_type[fd]!=FD_FILE) + { + errno=ENOTSUPP; + return -1; + } + + MEMSET(s, 0, sizeof(struct stat)); + s->st_nlink=1; + + switch(fd_type[fd]) + { + case FD_SOCKET: + s->st_mode=S_IFSOCK; + break; + + default: + switch(GetFileType((HANDLE)da_handle[fd])) + { + default: + case FILE_TYPE_UNKNOWN: s->st_mode=0; break; + case FILE_TYPE_DISK: + s->st_mode=S_IFREG; + s->st_size=GetFileSize((HANDLE)da_handle[fd],&x); + if(x) + { + s->st_size=0x7fffffff; + } + if(!GetFileTime((HANDLE)da_handle[fd], &c, &a, &m)) + { + errno=GetLastError(); + return -1; + } + s->st_ctime=convert_filetime_to_time_t(c); + s->st_atime=convert_filetime_to_time_t(a); + s->st_mtime=convert_filetime_to_time_t(m); + break; + case FILE_TYPE_CHAR: s->st_mode=S_IFCHR; break; + case FILE_TYPE_PIPE: s->st_mode=S_IFFIFO; break; + } + } + s->st_mode |= 0666; + return 0; +} + +int fd_select(int fds, FD_SET *a, FD_SET *b, FD_SET *c, struct timeval *t) +{ + int ret; + ret=select(fds,a,b,c,t); + if(ret==SOCKET_ERROR) + { + errno=WSAGetLastError(); + return -1; + } + return ret; +} + + +int fd_ioctl(FD fd, int cmd, void *data) +{ + int ret; + switch(fd_type[fd]) + { + case FD_SOCKET: + ret=ioctlsocket((SOCKET)da_handle[fd], cmd, data); + if(ret==SOCKET_ERROR) + { + errno=WSAGetLastError(); + return -1; + } + return ret; + + default: + errno=ENOTSUPP; + return -1; + } +} + + +FD fd_dup(FD from) +{ + FD fd; + HANDLE x,p=GetCurrentProcess(); + if(!DuplicateHandle(p,(HANDLE)da_handle[from],p,&x,NULL,0,DUPLICATE_SAME_ACCESS)) + { + errno=GetLastError(); + return -1; + } + + fd=first_free_handle; + first_free_handle=fd_type[fd]; + fd_type[fd]=fd_type[from]; + da_handle[fd]=(long)x; + + FDDEBUG(fprintf(stderr,"Dup %d (%d) to %d (%d)\n",from,da_handle[from],fd,x)); + return fd; +} + +FD fd_dup2(FD from, FD to) +{ + HANDLE x,p=GetCurrentProcess(); + if(!DuplicateHandle(p,(HANDLE)da_handle[from],p,&x,NULL,0,DUPLICATE_SAME_ACCESS)) + { + errno=GetLastError(); + return -1; + } + + if(fd_type[to] < FD_NO_MORE_FREE) + { + if(!CloseHandle((HANDLE)da_handle[to])) + { + errno=GetLastError(); + return -1; + } + }else{ + int *prev,next; + for(prev=&first_free_handle;(next=*prev) != FD_NO_MORE_FREE;prev=fd_type+next) + { + if(next==to) + { + *prev=fd_type[next]; + break; + } + } + } + fd_type[to]=fd_type[from]; + da_handle[to]=(long)x; + + FDDEBUG(fprintf(stderr,"Dup2 %d (%d) to %d (%d)\n",from,da_handle[from],to,x)); + + return to; +} + +#endif + +#if 0 + +#ifdef FD_LINEAR +struct fd_mapper +{ + int size; + void **data; +}; + +void init_fd_mapper(struct fd_mapper *x) +{ + x->size=64; + x->data=(void **)xalloc(x->size*sizeof(void *)); +} + +void exit_fd_mapper(struct fd_mapper *x) +{ + free((char *)x->data); +} + +void fd_mapper_set(struct fd_mapper *x, FD fd, void *data) +{ + while(fd>=x->size) + { + x->size*=2; + x->data=(void **)realloc((char *)x->data, x->size*sizeof(void *)); + if(!x->data) + fatal("Out of memory.\n"); + x->data=nd; + } + x->data[fd]=data; + +} + +void *fd_mapper_get(struct fd_mapper *x, FD fd) +{ + return x->data[fd]; +} +#else +struct fd_mapper_data +{ + FD x; + void *data; +}; +struct fd_mapper +{ + int num; + int hsize; + struct fd_mapper_data *data; +}; + +void init_fd_mapper(struct fd_mapper *x) +{ + int i; + x->num=0; + x->hsize=127; + x->data=(struct fd_mapper_data *)xalloc(x->hsize*sizeof(struct fd_mapper_data)); + for(i=0;i<x->hsize;i++) x->data[i].fd=-1; +} + +void exit_fd_mapper(struct fd_mapper *x) +{ + free((char *)x->data); +} + +void fd_mapper_set(struct fd_mapper *x, FD fd, void *data) +{ + int hval; + x->num++; + if(x->num*2 > x->hsize) + { + struct fd_mapper_data *old=x->data; + int i,old_size=x->hsize; + x->hsize*=3; + x->num=0; + x->data=(struct fd_mapper_data *)xalloc(x->size*sizeof(struct fd_mapper_data *)); + for(i=0;i<x->size;i++) x->data[i].fd=-1; + for(i=0;i<old_size;i++) + if(old[i].fd!=-1) + fd_mapper_set(x, old[i].fd, old[i].data); + } + + hval=fd % x->hsize; + while(x->data[hval].fd != -1) + { + hval++; + if(hval==x->hsize) hval=0; + } + x->data[hval].fd=fd; + x->data[hval].data=data; +} + +void *fd_mapper_get(struct fd_mapper *x, FD fd) +{ + int hval=fd % x->hsize; + while(x->data[hval].fd != fd) + { + hval++; + if(hval==x->hsize) hval=0; + } + return x->data[hval].data; +} +#endif + + +#if 0 +struct fd_data_hash +{ + FD fd; + int key; + struct fd_data_hash *next; + void *data; +}; + +#define FD_DATA_PER_BLOCK 255 + +struct fd_data_hash_block +{ + struct fd_data_hash_block *next; + struct fd_data_hash data[FD_DATA_PER_BLOCk]; +}; + +static int keynum=0; +static unsigned int num_stored_keys=0; +static unsigned int hash_size=0; +static struct fd_data_hash *free_blocks=0; +static struct fd_data_hash **htable=0; +static fd_data_hash_block *hash_blocks=0; + +int get_fd_data_key(void) +{ + return ++keynum; +} + +void store_fd_data(FD fd, int key, void *data) +{ + struct fd_data_hash *p,**last; + unsigned int hval=(fd + key * 53) % hash_size; + + for(last=htable[e];p=*last;last=&p->next) + { + if(p->fd == fd && p->key == key) + { + if(data) + { + p->data=data; + }else{ + *last=p->next; + p->next=free_blocks; + free_blocks=p; + num_stored_keys--; + } + return; + } + } + if(!data) return; + + num_stored_keys++; + + if(num_stored_keys * 2 >= hash_size) + { + /* time to rehash */ + unsigned int h; + unsigned int old_hsize=hash_size; + unsigned fd_data_hash **old_htable=htable; + if(!hash_size) + hash_size=127; + else + hash_size*=3; + + htable=(struct fd_data_hash **)xalloc(hash_size * sizeof(struct fd_data_hash *)); + + for(h=0;h<old_hsize;h++) + { + for(last=old_htable+e;p=*last;last=&p->next) + store_fd_data(p->fd, p->key, p->data); + *last=free_blocks; + free_blocks=old_htable[h]; + } + if(old_htable) + free((char *)old_htable); + } + + + if(!free_blocks) + { + struct fd_data_hash_block *n; + int e; + n=ALLOC_STRUCT(fd_data_hash_block); + n->next=hash_blocks; + hash_blocks=n; + for(e=0;e<FD_DATA_PER_BLOCK;e++) + { + n->data[e].next=free_blocks; + free_blocks=n->data+e; + } + } + + p=free_blocks; + free_blocks=p->next; + p->fd=fd; + p->key=key; + p->data=data; + p->next=htable[hval]; + htable[hval]=p; +} + +void *get_fd_data(FD fd, int key) +{ + struct fd_data_hash *p,**last; + unsigned int hval=(fd + key * 53) % hash_size; + + for(p=htable[hval];p;p=p->next) + if(p->fd == fd && p->key == key) + return p->data; + + return 0; +} + + +#endif + +#ifdef FDLIB_USE_SELECT + +struct fd_waitor +{ + fd_FDSET storage; + fd_FDSET temporary; +static long convert_filetime_to_time_t(FILETIME tmp) +{ + double t; + t=tmp.dwHighDateTime * pow(2.0,32.0) + (double)tmp.dwLowDateTime; + t/=10000000.0; + t-=11644473600.0; + return (long)floor(t); +} + +int fd_fstat(FD fd, struct stat *s) +{ + DWORD x; + int ret; + FILETIME c,a,m; + FDDEBUG(fprintf(stderr,"fstat on %d (%d)\n",fd,da_handle[fd])); + if(fd_type[fd]!=FD_FILE) + { + errno=ENOTSUPP; + return -1; + } + + MEMSET(s, 0, sizeof(struct stat)); + s->st_nlink=1; + + switch(fd_type[fd]) + { + case FD_SOCKET: + s->st_mode=S_IFSOCK; + break; + + default: + switch(GetFileType((HANDLE)da_handle[fd])) + { + default: + case FILE_TYPE_UNKNOWN: s->st_mode=0; break; + case FILE_TYPE_DISK: + s->st_mode=S_IFREG; + s->st_size=GetFileSize((HANDLE)da_handle[fd],&x); + if(x) + { + s->st_size=0x7fffffff; + } + if(!GetFileTime((HANDLE)da_handle[fd], &c, &a, &m)) + { + errno=GetLastError(); + return -1; + } + s->st_ctime=convert_filetime_to_time_t(c); + s->st_atime=convert_filetime_to_time_t(a); + s->st_mtime=convert_filetime_to_time_t(m); + break; + case FILE_TYPE_CHAR: s->st_mode=S_IFCHR; break; + case FILE_TYPE_PIPE: s->st_mode=S_IFFIFO; break; + } + } + s->st_mode |= 0666; + return 0; +} + +int fd_select(int fds, FD_SET *a, FD_SET *b, FD_SET *c, struct timeval *t) +{ + int ret; + ret=select(fds,a,b,c,t); + if(ret==SOCKET_ERROR) + { + errno=WSAGetLastError(); + return -1; + } + return ret; +} + + +int fd_ioctl(FD fd, int cmd, void *data) +{ + int ret; + switch(fd_type[fd]) + { + case FD_SOCKET: + ret=ioctlsocket((SOCKET)da_handle[fd], cmd, data); + if(ret==SOCKET_ERROR) + { + errno=WSAGetLastError(); + return -1; + } + return ret; + + default: + errno=ENOTSUPP; + return -1; + } +} + + +FD fd_dup(FD from) +{ + FD fd; + HANDLE x,p=GetCurrentProcess(); + if(!DuplicateHandle(p,(HANDLE)da_handle[from],p,&x,NULL,0,DUPLICATE_SAME_ACCESS)) + { + errno=GetLastError(); + return -1; + } + + fd=first_free_handle; + first_free_handle=fd_type[fd]; + fd_type[fd]=fd_type[from]; + da_handle[fd]=(long)x; + + FDDEBUG(fprintf(stderr,"Dup %d (%d) to %d (%d)\n",from,da_handle[from],fd,x)); + return fd; +} + +FD fd_dup2(FD from, FD to) +{ + HANDLE x,p=GetCurrentProcess(); + if(!DuplicateHandle(p,(HANDLE)da_handle[from],p,&x,NULL,0,DUPLICATE_SAME_ACCESS)) + { + errno=GetLastError(); + return -1; + } + + if(fd_type[to] < FD_NO_MORE_FREE) + { + if(!CloseHandle((HANDLE)da_handle[to])) + { + errno=GetLastError(); + return -1; + } + }else{ + int *prev,next; + for(prev=&first_free_handle;(next=*prev) != FD_NO_MORE_FREE;prev=fd_type+next) + { + if(next==to) + { + *prev=fd_type[next]; + break; + } + } + } + fd_type[to]=fd_type[from]; + da_handle[to]=(long)x; + + FDDEBUG(fprintf(stderr,"Dup2 %d (%d) to %d (%d)\n",from,da_handle[from],to,x)); + + return to; +} + +#endif + +#if 0 + +#ifdef FD_LINEAR +struct fd_mapper +{ + int size; + void **data; +}; + +void init_fd_mapper(struct fd_mapper *x) +{ + x->size=64; + x->data=(void **)xalloc(x->size*sizeof(void *)); +} + +void exit_fd_mapper(struct fd_mapper *x) +{ + free((char *)x->data); +} + +void fd_mapper_set(struct fd_mapper *x, FD fd, void *data) +{ + while(fd>=x->size) + { + x->size*=2; + x->data=(void **)realloc((char *)x->data, x->size*sizeof(void *)); + if(!x->data) + fatal("Out of memory.\n"); + x->data=nd; + } + x->data[fd]=data; + +} + +void *fd_mapper_get(struct fd_mapper *x, FD fd) +{ + return x->data[fd]; +} +#else +struct fd_mapper_data +{ + FD x; + void *data; +}; +struct fd_mapper +{ + int num; + int hsize; + struct fd_mapper_data *data; +}; + +void init_fd_mapper(struct fd_mapper *x) +{ + int i; + x->num=0; + x->hsize=127; + x->data=(struct fd_mapper_data *)xalloc(x->hsize*sizeof(struct fd_mapper_data)); + for(i=0;i<x->hsize;i++) x->data[i].fd=-1; +} + +void exit_fd_mapper(struct fd_mapper *x) +{ + free((char *)x->data); +} + +void fd_mapper_set(struct fd_mapper *x, FD fd, void *data) +{ + int hval; + x->num++; + if(x->num*2 > x->hsize) + { + struct fd_mapper_data *old=x->data; + int i,old_size=x->hsize; + x->hsize*=3; + x->num=0; + x->data=(struct fd_mapper_data *)xalloc(x->size*sizeof(struct fd_mapper_data *)); + for(i=0;i<x->size;i++) x->data[i].fd=-1; + for(i=0;i<old_size;i++) + if(old[i].fd!=-1) + fd_mapper_set(x, old[i].fd, old[i].data); + } + + hval=fd % x->hsize; + while(x->data[hval].fd != -1) + { + hval++; + if(hval==x->hsize) hval=0; + } + x->data[hval].fd=fd; + x->data[hval].data=data; +} + +void *fd_mapper_get(struct fd_mapper *x, FD fd) +{ + int hval=fd % x->hsize; + while(x->data[hval].fd != fd) + { + hval++; + if(hval==x->hsize) hval=0; + } + return x->data[hval].data; +} +#endif + + +#if 0 +struct fd_data_hash +{ + FD fd; + int key; + struct fd_data_hash *next; + void *data; +}; + +#define FD_DATA_PER_BLOCK 255 + +struct fd_data_hash_block +{ + struct fd_data_hash_block *next; + struct fd_data_hash data[FD_DATA_PER_BLOCk]; +}; + +static int keynum=0; +static unsigned int num_stored_keys=0; +static unsigned int hash_size=0; +static struct fd_data_hash *free_blocks=0; +static struct fd_data_hash **htable=0; +static fd_data_hash_block *hash_blocks=0; + +int get_fd_data_key(void) +{ + return ++keynum; +} + +void store_fd_data(FD fd, int key, void *data) +{ + struct fd_data_hash *p,**last; + unsigned int hval=(fd + key * 53) % hash_size; + + for(last=htable[e];p=*last;last=&p->next) + { + if(p->fd == fd && p->key == key) + { + if(data) + { + p->data=data; + }else{ + *last=p->next; + p->next=free_blocks; + free_blocks=p; + num_stored_keys--; + } + return; + } + } + if(!data) return; + + num_stored_keys++; + + if(num_stored_keys * 2 >= hash_size) + { + /* time to rehash */ + unsigned int h; + unsigned int old_hsize=hash_size; + unsigned fd_data_hash **old_htable=htable; + if(!hash_size) + hash_size=127; + else + hash_size*=3; + + htable=(struct fd_data_hash **)xalloc(hash_size * sizeof(struct fd_data_hash *)); + + for(h=0;h<old_hsize;h++) + { + for(last=old_htable+e;p=*last;last=&p->next) + store_fd_data(p->fd, p->key, p->data); + *last=free_blocks; + free_blocks=old_htable[h]; + } + if(old_htable) + free((char *)old_htable); + } + + + if(!free_blocks) + { + struct fd_data_hash_block *n; + int e; + n=ALLOC_STRUCT(fd_data_hash_block); + n->next=hash_blocks; + hash_blocks=n; + for(e=0;e<FD_DATA_PER_BLOCK;e++) + { + n->data[e].next=free_blocks; + free_blocks=n->data+e; + } + } + + p=free_blocks; + free_blocks=p->next; + p->fd=fd; + p->key=key; + p->data=data; + p->next=htable[hval]; + htable[hval]=p; +} + +void *get_fd_data(FD fd, int key) +{ + struct fd_data_hash *p,**last; + unsigned int hval=(fd + key * 53) % hash_size; + + for(p=htable[hval];p;p=p->next) + if(p->fd == fd && p->key == key) + return p->data; + + return 0; +} + + +#endif + +#define FD_EVENT_READ 1 +#define FD_EVENT_WRITE 2 +#define FD_EVENT_OOB 4 + +struct event +{ + int fd; + int events; +}; + #ifdef FDLIB_USE_SELECT struct fd_waitor { - fd_FDSET storage; - fd_FDSET temporary; + fd_FDSET rcustomers,wcustomers,xcustomers; + fd_FDSET rtmp,wtmp,xtmp; FD last; int numleft; int max; }; -#define init_waitor(X) do { (X)->numleft=0; (X)->max=0; fd_FDZERO(&X->storage); } while(0) +#define init_waitor(X) do { (X)->numleft=0; (X)->max=0; \ + fd_FDZERO(&X->rcustomers); \ + fd_FDZERO(&X->wcustomers); \ + fd_FDZERO(&X->xcustomers); \ + } while(0) -void fd_waitor_add_customer(fd_waitor *x, FD customer) +void fd_waitor_set_customer(fd_waitor *x, FD customer, int flags) { - fd_FD_SET(& x->storage, customer); - if(customer>x->max) x->max=customer; -} + if(flags & FD_EVENT_READ) + { + fd_FD_SET(& x->rcustomer, customer); + }else{ + fd_FD_CLR(& x->rcustomer, customer); + } -void fd_waitor_remove_customer(fd_waitor *x, FD customer) -{ - fd_FD_CLR(& x->storage, customer); - if(customer == x->max) + if(flags & FD_EVENT_WRITE) + { + fd_FD_SET(& x->wcustomer, customer); + }else{ + fd_FD_CLR(& x->wcustomer, customer); + } + + if(flags & FD_EVENT_OOB) { - x->max--; - while(!fd_ISSET(& x->storage), x->max) x->max--; + fd_FD_SET(& x->xcustomer, customer); + }else{ + fd_FD_CLR(& x->xcustomer, customer); } + + if(flags) + if(customer>x->max) x->max=customer; + else + if(customer == x->max) + { + x->max--; + while( + !fd_ISSET(& x->rcustomers,x->max) && + !fd_ISSET(& x->wcustomers,x->max) && + !fd_ISSET(& x->xcustomers,x->max) + ) + x->max--; + } } -FD fd_waitor_idle(fd_waitor *x) +int fd_waitor_idle(fd_waitor *x, + struct timeval *t, + struct event *e) { int tmp; if(!x->numleft) { - x->temporary=x->storage; - tmp=select(x->max, & x->temporary, 0, 0, 0); - if(tmp<0) return -1; + x->rtmp=x->rcustomers; + x->wtmp=x->wcustomers; + x->xtmp=x->xcustomers; + + tmp=select(x->max, & x->rtmp, & x->wtmp, & x->xtmp, &t); + if(tmp<0) return 0; x->last=0; x->numleft=tmp; @@ -608,18 +1897,27 @@ FD fd_waitor_idle(fd_waitor *x) { while(x->last<x->max) { - if(fd_FD_ISSET(& x->temporary, x->last)) + int flags= + (fd_FD_ISSET(& x->rtmp, x->last) ? FD_EVENT_READ : 0) | + (fd_FD_ISSET(& x->wtmp, x->last) ? FD_EVENT_WRITE : 0) | + (fd_FD_ISSET(& x->xtmp, x->last) ? FD_EVENT_OOB: 0); + + if(flags) { numleft--; + + e->fd=x->last + e->event=flags; return 1; } } } + return 0; } #endif -#ifdef FDLIB_USE_WAITFORMULTIPLEOBJECTSEX +#ifdef FDLIB_USE_WAITFORMULTIPLEOBJECTS #define FD_MAX 16384 @@ -628,22 +1926,68 @@ struct fd_waitor int occupied; HANDLE customers[FD_MAX]; FD pos_to_fd[FD_MAX]; + int fd_to_pos_key; + int last_swap; }; -void fd_waitor_add_customer(fd_waitor *x, FD customer) +void fd_waitor_set_customer(fd_waitor *x, FD customer, int flags) { HANDLE h=CreateEvent(); - customers[x->occupied]=h; - pos_to_fd[x->occupied]=customer; + x->customers[x->occupied]=h; + x->pos_to_fd[x->occupied]=customer; + fd_mapper_store(customer, x->fd_to_pos_key, x->occupied); x->occupied++; } void fd_waitor_remove_customer(fd_waitor *x, FD customer) { - CloseHandle(customers[x]); + int pos=(int)fd_mapper_get(customer, x->fd_to_pos_key); + + CloseHandle(x->customers[pos]); - customers[x]= - pos_to_fd[x + fd_mapper_store(customer, x->fd_to_pos_key, (void *)0); + x->occupied--; + if(x->occupied != pos) + { + x->customer[pos]=x->customer[x->occupied]; + x->pos_to_fd[pos]=x->pos_to_fd[x->occupied]; + fd_mapper_store(x->pos_to_fd[pos], x->fd_to_pos_key, (void *)pos); + } +} + +FD fd_waitor_idle(fd_waitor *x, struct timeval delay) +{ + DWORD ret,d=delay.tv_usec/1000; + d+=MINIMUM(100000,delay.tv_sec) *1000; + + ret=WaitForMultipleObjects(x->occupied, + x->customers, + 0, + delay); + + if(ret>= WAIT_OBJECT_0 && ret< WAIT_OBJECT_0 + x->occupied) + { + long tmp; + ret-=WAIT_OBJECT_0; + if(-- (x->last_swap) <= ret) + { + x->last_swap=x->occupied; + if(x->occupied == ret) return ret; + } + tmp=customers[ret]; + customers[ret]=customers[x->last_swap]; + customers[x->last_swap]=tmp; + + tmp=pos_to_fd[ret]; + pos_to_fd[ret]=pos_to_fd[x->last_swap]; + pos_to_fd[x->last_swap]=tmp; + + fd_mapper_store(x->pos_to_fd[ret], x->fd_to_pos_key, ret); + fd_mapper_store(x->pos_to_fd[x->last_swap], x->fd_to_pos_key, x->last_swap); + return x->pos_to_fd[ret]; + }else{ + return -1; + } } #endif diff --git a/src/main.c b/src/main.c index c4c53ef9c964c14f1aeda4a287baef2ab173a0d9..8a83f044624be5493694c6fe89c682174ee9ce71 100644 --- a/src/main.c +++ b/src/main.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: main.c,v 1.29 1998/01/02 01:05:48 hubbe Exp $"); +RCSID("$Id: main.c,v 1.30 1998/01/08 17:20:07 hubbe Exp $"); #include "fdlib.h" #include "backend.h" #include "module.h" @@ -68,6 +68,9 @@ void main(int argc, char **argv) int e, num; char *p; struct array *a; +#ifdef DECLARE_ENVIRON + extern char **environ; +#endif ARGV=argv; diff --git a/src/mapping.c b/src/mapping.c index b0663a51a7fe546e9417e8c304e3ee4babaf57ed..fedde3d49623cd71d2eceebe9e87a352e391232c 100644 --- a/src/mapping.c +++ b/src/mapping.c @@ -4,7 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" -RCSID("$Id: mapping.c,v 1.24 1997/11/08 01:34:41 hubbe Exp $"); +RCSID("$Id: mapping.c,v 1.25 1998/01/08 17:20:07 hubbe Exp $"); #include "main.h" #include "object.h" #include "mapping.h" @@ -494,6 +494,15 @@ struct svalue *low_mapping_string_lookup(struct mapping *m, return low_mapping_lookup(m, &tmp); } +struct svalue *simple_mapping_string_lookup(struct mapping *m, + char *p) +{ + struct pike_string *tmp; + if((tmp=findstring(p))) + return low_mapping_string_lookup(m,tmp); + return 0; +} + void mapping_index_no_free(struct svalue *dest, struct mapping *m, struct svalue *key) diff --git a/src/mapping.h b/src/mapping.h index 5d7fce75bace51fd3baf29e6c0ee8a82e1b23ecd..4e50607b52821f7c6d2305272e97b7bd11875cdb 100644 --- a/src/mapping.h +++ b/src/mapping.h @@ -41,6 +41,8 @@ struct svalue *low_mapping_lookup(struct mapping *m, struct svalue *key); struct svalue *low_mapping_string_lookup(struct mapping *m, struct pike_string *p); +struct svalue *simple_mapping_string_lookup(struct mapping *m, + char *p); void mapping_index_no_free(struct svalue *dest, struct mapping *m, struct svalue *key); diff --git a/src/modules/files/acconfig.h b/src/modules/files/acconfig.h index d4e6e3124f8dadd60a8c825d1e387e5ba852d086..b203e40dd68ac34c7e9a66e144398cf4acc421e9 100644 --- a/src/modules/files/acconfig.h +++ b/src/modules/files/acconfig.h @@ -1,5 +1,5 @@ /* - * $Id: acconfig.h,v 1.5 1997/12/23 06:26:09 hubbe Exp $ + * $Id: acconfig.h,v 1.6 1998/01/08 17:21:14 hubbe Exp $ */ #ifndef FILE_MACHINE_H @@ -44,8 +44,5 @@ /* Number of args to mkdir() */ #define MKDIR_ARGS 2 -/* Can we declare 'extern char ** environ;' ? */ -#undef DECLARE_ENVIRON - #endif diff --git a/src/modules/files/configure.in b/src/modules/files/configure.in index eb6d1352056eedb996295a64cee065177a746b3e..3f5e9a02aec5de0c44b47e21ea3e25a08a933556 100644 --- a/src/modules/files/configure.in +++ b/src/modules/files/configure.in @@ -11,22 +11,7 @@ AC_HEADER_DIRENT AC_CHECK_LIB(bind, __inet_ntoa) AC_CHECK_LIB(socket, socket) -AC_HAVE_FUNCS(getwd perror fork1 readdir_r statvfs statfs ustat fork lstat) - -AC_MSG_CHECKING(if we can declare environ) -AC_CACHE_VAL(pike_cv_declare_environ,[ -AC_TRY_COMPILE([ -#include <stdlib.h> -],[ - extern char **environ; - exit(0); -],pike_cv_declare_environ=yes,pike_cv_declare_environ=no) -]) - -AC_MSG_RESULT($pike_cv_declare_environ) -if test "x$pike_cv_declare_environ" = xyes ; then - AC_DEFINE(DECLARE_ENVIRON) -fi +AC_HAVE_FUNCS(getwd perror readdir_r statvfs statfs ustat lstat) AC_MSG_CHECKING(if mkdir takes 1 or 2 arguments) AC_CACHE_VAL(pike_cv_func_mkdir_args,[ diff --git a/src/modules/files/efuns.c b/src/modules/files/efuns.c index 7a1cfba574149b082d723b204010362043d0a3f2..fdb99d8b7ad2fb954324f5dcba85fd201caac8b0 100644 --- a/src/modules/files/efuns.c +++ b/src/modules/files/efuns.c @@ -563,40 +563,15 @@ void f_getcwd(INT32 args) free(e); } -#ifdef HAVE_FORK -void f_fork(INT32 args) -{ - int res; - do_set_close_on_exec(); - pop_n_elems(args); -#if defined(HAVE_FORK1) && defined(_REENTRANT) - push_int(res=fork1()); -#else - push_int(res=fork()); -#endif - if(!res && res!=-1) - { - call_callback(&fork_child_callback, 0); - } -#if defined(_REENTRANT) - if(!res) - { - /* forked copy. there is now only one thread running, this one. */ - num_threads=1; - } -#endif -} -#endif - void f_exece(INT32 args) { INT32 e; char **argv, **env; + struct svalue *save_sp; + struct mapping *en; #ifdef DECLARE_ENVIRON extern char **environ; #endif - struct svalue *save_sp; - struct mapping *en; save_sp=sp-args; @@ -750,9 +725,6 @@ void init_files_efuns(void) add_efun("get_dir",f_get_dir,"function(string:string *)",OPT_EXTERNAL_DEPEND); add_efun("cd",f_cd,"function(string:int)",OPT_SIDE_EFFECT); add_efun("getcwd",f_getcwd,"function(:string)",OPT_EXTERNAL_DEPEND); -#ifdef HAVE_FORK - add_efun("fork",f_fork,"function(:int)",OPT_SIDE_EFFECT); -#endif add_efun("exece",f_exece,"function(string,mixed*,void|mapping(string:string):int)",OPT_SIDE_EFFECT); #ifdef HAVE_STRERROR diff --git a/src/modules/files/file.c b/src/modules/files/file.c index 9daad37195613623cba995b831c5f3bd7d0657d3..ee5a71cf261f8344d333dbc27c379a0b2bbdf605 100644 --- a/src/modules/files/file.c +++ b/src/modules/files/file.c @@ -6,7 +6,7 @@ #define READ_BUFFER 8192 #include "global.h" -RCSID("$Id: file.c,v 1.64 1998/01/03 07:13:05 hubbe Exp $"); +RCSID("$Id: file.c,v 1.65 1998/01/08 17:21:16 hubbe Exp $"); #include "fdlib.h" #include "interpret.h" #include "svalue.h" @@ -1261,7 +1261,7 @@ static void file_dup2(INT32 args) * /precompiled/file */ if(!o->prog || o->prog->inherits[0].prog != file_program) - error("Argument 1 to file->assign() must be a clone of Stdio.File\n"); + error("Argument 1 to file->dup2() must be a clone of Stdio.File\n"); fd=((struct file_struct *)(o->storage))->fd; diff --git a/src/modules/files/testsuite.in b/src/modules/files/testsuite.in index 03dec921ca44f185c3ff91d51a13131e7da30470..890210ffb1315ff20146a15a2727b84f3a044f3b 100644 --- a/src/modules/files/testsuite.in +++ b/src/modules/files/testsuite.in @@ -69,7 +69,7 @@ test_any([[object o=clone(Stdio.File); o->open("conftest","r"); o=o->dup(); retu est_any([[object o=clone(Stdio.File),o2=clone(Stdio.File); o->open("conftest","r"); o2->assign(o); return o2->read(100)]] ,sprintf("%'+-*'100s","")) // - file->dup2 -test_any([[object o=clone(Stdio.File),o2=clone(Stdio.File); o2->pipe(); o->open("conftest","r"); o2->dup2(o); return o2->read(100)]] ,sprintf("%'+-*'100s","")) +test_any([[object o=clone(Stdio.File),o2=clone(Stdio.File); o2->pipe(); o->open("conftest","r"); o->dup2(o2); return o2->read(100)]] ,sprintf("%'+-*'100s","")) test_eq(Process.popen("echo foo"),"foo\n") diff --git a/src/signal_handler.c b/src/signal_handler.c index a3a4a801d14a9c7a8cf6d32469f7937b9409b78f..6281ccdb07ddbaae5809cafc16ad38ca5c42939a 100644 --- a/src/signal_handler.c +++ b/src/signal_handler.c @@ -4,6 +4,7 @@ ||| See the files COPYING and DISCLAIMER for more information. \*/ #include "global.h" +#include "fdlib.h" #include "svalue.h" #include "interpret.h" #include "stralloc.h" @@ -12,7 +13,16 @@ #include "backend.h" #include "error.h" #include "callback.h" +#include "mapping.h" +#include "threads.h" +#include "signal_handler.h" +#include "module_support.h" #include <signal.h> + +#ifdef HAVE_WINBASE_H +#include <winbase.h> +#endif + #ifdef HAVE_SYS_WAIT_H #include <sys/wait.h> #endif @@ -35,6 +45,7 @@ #endif #define SIGNAL_BUFFER 16384 +#define WAIT_BUFFER 4096 static struct svalue signal_callbacks[MAX_SIGNALS]; @@ -42,6 +53,16 @@ static unsigned char sigbuf[SIGNAL_BUFFER]; static int firstsig, lastsig; static struct callback *signal_evaluator_callback =0; +#ifndef __NT__ +struct wait_data { + pid_t pid; + int status; +}; + +static struct wait_data wait_buf[WAIT_BUFFER]; +static int firstwait=0, lastwait=0; + +#endif /* ! NT */ struct sigdesc { @@ -205,52 +226,560 @@ static void my_signal(int sig, sigfunctype fun) #endif } -static RETSIGTYPE sig_child(int arg) +static RETSIGTYPE receive_signal(int signum) { - /* We carefully reap what we saw */ + int tmp; + + tmp=firstsig+1; + if(tmp == SIGNAL_BUFFER) tmp=0; + if(tmp != lastsig) + { + sigbuf[tmp]=signum; + firstsig=tmp; + } + +#ifndef __NT__ + if(signum==SIGCHLD) + { + pid_t pid; + int status; + /* We carefully reap what we saw */ #ifdef HAVE_WAITPID - while(waitpid(-1,0,WNOHANG) > 0); + pid=waitpid(-1,& status,WNOHANG); #else #ifdef HAVE_WAIT3 - while( wait3(0,WNOHANG,0) > 0); + pid=wait3(&status,WNOHANG,0); #else #ifdef HAVE_WAIT4 - while( wait4(-1,0,WNOHANG,0) > 0); + pid=wait4(-1,&status,WNOHANG,0); #else + pid=-1; +#endif +#endif +#endif + if(pid>0) + { + int tmp2=firstwait+1; + if(tmp2 == WAIT_BUFFER) tmp=0; + if(tmp2 != lastwait) + { + wait_buf[tmp2].pid=pid; + wait_buf[tmp2].status=status; + firstwait=tmp2; + } + } + } +#endif + + wake_up_backend(); + +#ifndef SIGNAL_ONESHOT + my_signal(signum, receive_signal); +#endif +} - /* Leave'em hanging */ +#define PROCESS_UNKNOWN -1 +#define PROCESS_RUNNING 0 +#define PROCESS_EXITED 2 -#endif /* HAVE_WAIT4 */ -#endif /* HAVE_WAIT3 */ -#endif /* HAVE_WAITPID */ +#undef THIS +#define THIS ((struct pid_status *)fp->current_storage) -#ifdef SIGNAL_ONESHOT -#ifdef SIGCHLD - my_signal(SIGCHLD, sig_child); +struct pid_status +{ + int pid; +#ifdef __NT__ + HANDLE handle; +#else + int state; + int result; +#endif +}; + +#ifndef __NT__ +static struct mapping *pid_mapping=0; #endif +static struct program *pid_status_program=0; + + +static void init_pid_status(struct object *o) +{ + THIS->pid=-1; +#ifdef __NT__ + THIS->handle=INVALID_HANDLE_VALUE; +#else + THIS->state=PROCESS_UNKNOWN; + THIS->result=-1; #endif } -static RETSIGTYPE receive_signal(int signum) +static void exit_pid_status(struct object *o) { - int tmp; +#ifndef __NT__ + if(pid_mapping) + { + struct svalue key; + key.type=T_INT; + key.u.integer=THIS->pid; + map_delete(pid_mapping, &key); + } +#else + CloseHandle(THIS->handle); +#endif +} - tmp=firstsig+1; - if(tmp == SIGNAL_BUFFER) tmp=0; - if(tmp != lastsig) - sigbuf[firstsig=tmp]=signum; +#ifndef __NT__ +static void report_child(int pid, + int status) +{ +/* fprintf(stderr,"pid %d exited with status %d\n",pid,status); */ -#ifdef SIGCHLD - if(signum==SIGCHLD) sig_child(signum); + if(pid_mapping) + { + struct svalue *s, key; + key.type=T_INT; + key.u.integer=pid; + if((s=low_mapping_lookup(pid_mapping, &key))) + { + if(s->type == T_OBJECT) + { + struct pid_status *p; + if((p=(struct pid_status *)get_storage(s->u.object, + pid_status_program))) + { + p->state = PROCESS_EXITED; + p->result = WEXITSTATUS(status); + } + } + map_delete(pid_mapping, &key); + } + } +} #endif - wake_up_backend(); +static void f_pid_status_wait(INT32 args) +{ + pop_n_elems(args); + if(THIS->pid == -1) + error("This process object has no process associated with it.\n"); +#ifdef __NT__ + { + int err=0; + DWORD xcode; + HANDLE h=THIS->handle; + THREADS_ALLOW(); + while(1) + { + if(GetExitCodeProcess(h, &xcode)) + { + if(xcode == STILL_ACTIVE) + { + WaitForSingleObject(h, INFINITE); + }else{ + break; + } + }else{ + err=1; + break; + } + } + THREADS_DISALLOW(); + if(err) + error("Failed to get status of process.\n"); + push_int(xcode); + } +#else -#ifndef SIGNAL_ONESHOT - my_signal(signum, receive_signal); +#if 1 + while(THIS->state == PROCESS_RUNNING) + { + int pid, status; + pid=THIS->pid; + THREADS_ALLOW(); +#ifdef HAVE_WAITPID + pid=waitpid(pid,& status,0); +#else +#ifdef HAVE_WAIT4 + pid=wait4(pid,&status,0,0); +#else + pid=-1; #endif +#endif + THREADS_DISALLOW(); + if(pid >= -1) + report_child(pid, status); + check_signals(0,0,0); + } +#else + init_signal_wait(); + while(THIS->state == PROCESS_RUNNING) + { + wait_for_signal(); + check_threads_etc(); + } + exit_signal_wait(); +#endif + push_int(THIS->result); +#endif /* __NT__ */ } +static void f_pid_status_status(INT32 args) +{ + pop_n_elems(args); +#ifdef __NT__ + { + DWORD x; + if(GetExitCodeProcess(THIS->handle, &x)) + { + push_int( x == STILL_ACTIVE ? PROCESS_RUNNING : PROCESS_EXITED); + }else{ + push_int(PROCESS_UNKNOWN); + } + } +#else + push_int(THIS->state); +#endif +} + +static void f_pid_status_pid(INT32 args) +{ + pop_n_elems(args); + push_int(THIS->pid); +} + +#ifdef __NT__ +static TCHAR *convert_string(char *str, int len) +{ + int e; + TCHAR *ret=(TCHAR *)xalloc((len+1) * sizeof(TCHAR)); + for(e=0;e<len;e++) ret[e]=EXTRACT_UCHAR(str+e); + ret[e]=0; + return ret; +} + +static HANDLE get_inheritable_handle(struct mapping *optional, char *name) +{ + HANDLE ret=INVALID_HANDLE_VALUE; + struct svalue *tmp; + if((tmp=simple_mapping_string_lookup(optional, name))) + { + if(tmp->type == T_OBJECT) + { + apply(tmp->u.object,"query_fd",0); + if(sp[-1].type == T_INT) + { + DuplicateHandle(GetCurrentProcess(), + (HANDLE)da_handle[sp[-1].u.integer], + GetCurrentProcess(), + &ret, + NULL, + 1, + 0); + } + } + } + return ret; +} +#endif + +/* + * create_process(string *arguments, mapping optional_data); + */ +void f_create_process(INT32 args) +{ + struct array *cmd=0; + struct mapping *optional=0; + struct svalue *tmp; + int e; + + if(!args) return; + + check_all_args("create_process",args, BIT_ARRAY, BIT_MAPPING | BIT_VOID, 0); + + switch(args) + { + default: + optional=sp[1-args].u.mapping; + mapping_fix_type_field(optional); + + if(m_ind_types(optional) & ~BIT_STRING) + error("Bad index type in argument 2 to Process->create()\n"); + + case 1: cmd=sp[-args].u.array; + if(cmd->size < 1) + error("Too few elements in argument array.\n"); + + for(e=0;e<cmd->size;e++) + if(ITEM(cmd)[e].type!=T_STRING) + error("Argument is not a string.\n"); + + array_fix_type_field(cmd); + + if(cmd->type_field & ~BIT_STRING) + error("Bad argument 1 to Process().\n"); + } + + +#ifdef __NT__ + { + HANDLE t1=INVALID_HANDLE_VALUE; + HANDLE t2=INVALID_HANDLE_VALUE; + HANDLE t3=INVALID_HANDLE_VALUE; + STARTUPINFO info; + PROCESS_INFORMATION proc; + int ret; + TCHAR *filename=NULL, *command_line=NULL, *dir=NULL; + struct pike_string *p1,*p2; + + + /* FIX QUOTING LATER */ + p1=make_shared_string(" "); + p2=implode(cmd, p1); + command_line=convert_string(p2->str, p2->len); + free_string(p1); + free_string(p2); + + GetStartupInfo(&info); + + info.dwFlags|=STARTF_USESTDHANDLES; + info.hStdInput=GetStdHandle(STD_INPUT_HANDLE); + info.hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE); + info.hStdError=GetStdHandle(STD_ERROR_HANDLE); + + if(optional) + { + if(tmp=simple_mapping_string_lookup(optional, "cwd")) + if(tmp->type == T_STRING) + dir=convert_string(tmp->u.string->str, tmp->u.string->len); + + t1=get_inheritable_handle(optional, "stdin"); + if(t1!=INVALID_HANDLE_VALUE) info.hStdInput=t1; + + t2=get_inheritable_handle(optional, "stdout"); + if(t1!=INVALID_HANDLE_VALUE) info.hStdOutput=t2; + + t3=get_inheritable_handle(optional, "stdout"); + if(t1!=INVALID_HANDLE_VALUE) info.hStdError=t3; + + /* FIX: env, cleanup */ + } + + THREADS_ALLOW(); + ret=CreateProcess(filename, + command_line, + NULL, /* process security attribute */ + NULL, /* thread security attribute */ + 1, /* inherithandles */ + 0, /* create flags */ + NULL, /* environment */ + dir, /* current dir */ + &info, + &proc); + THREADS_DISALLOW(); + + if(dir) free((char *)dir); + if(command_line) free((char *)command_line); + if(filename) free((char *)filename); + if(t1!=INVALID_HANDLE_VALUE) CloseHandle(t1); + if(t2!=INVALID_HANDLE_VALUE) CloseHandle(t2); + if(t3!=INVALID_HANDLE_VALUE) CloseHandle(t3); + + if(ret) + { + CloseHandle(proc.hThread); + THIS->handle=proc.hProcess; + THIS->pid=proc.dwProcessId; + }else{ + error("Failed to start process (%d).\n",GetLastError()); + } + } +#else /* __NT__ */ + { + pid_t pid; +#if defined(HAVE_FORK1) && defined(_REENTRANT) + pid=fork1(); +#else + pid=fork(); +#endif + if(pid==-1) error("Failed to start process.\n"); + if(pid) + { + if(!signal_evaluator_callback) + { + signal_evaluator_callback=add_to_callback(&evaluator_callbacks, + check_signals, + 0,0); + } + THIS->pid=pid; + THIS->state=PROCESS_RUNNING; + ref_push_object(fp->current_object); + push_int(pid); + mapping_insert(pid_mapping,sp-1, sp-2); + pop_n_elems(2); + }else{ + char **argv; +#ifdef DECLARE_ENVIRON + extern char **environ; +#endif + extern void my_set_close_on_exec(int,int); + extern void do_set_close_on_exec(void); + +#ifdef _REENTRANT + /* forked copy. there is now only one thread running, this one. */ + num_threads=1; +#endif + call_callback(&fork_child_callback, 0); + + + argv=(char **)xalloc((1+cmd->size) * sizeof(char *)); + + for(e=0;e<cmd->size;e++) + argv[e]=ITEM(cmd)[e].u.string->str; + + argv[e]=0; + + if(optional) + { + int toclose[3]; + int fd; + + if((tmp=simple_mapping_string_lookup(optional, "cwd"))) + if(tmp->type == T_STRING) + if(!chdir(tmp->u.string->str)) + exit(69); + + for(fd=0;fd<3;fd++) + { + char *fdname; + switch(fd) + { + case 0: fdname="stdin"; break; + case 1: fdname="stdout"; break; + default: fdname="stderr"; break; + } + + if((tmp=simple_mapping_string_lookup(optional, fdname))) + { + if(tmp->type == T_OBJECT) + { + apply(tmp->u.object,"query_fd",0); + if(sp[-1].type == T_INT) + dup2(toclose[fd]=sp[-1].u.integer, fd); + } + } + } + + for(fd=0;fd<3;fd++) + { + int f2; + if(toclose[fd]<0) continue; + + for(f2=0;f2<fd;f2++) + if(toclose[fd]==toclose[f2]) + break; + + if(f2 == fd) + close(toclose[fd]); + } + + /* Left to do: env, cleanup */ + } + + + my_set_close_on_exec(0,0); + my_set_close_on_exec(1,0); + my_set_close_on_exec(2,0); + do_set_close_on_exec(); + + execvp(argv[0],argv); + exit(69); + } + } +#endif /* __NT__ */ + pop_n_elems(args); + push_int(0); +} + +#ifdef HAVE_FORK +void f_fork(INT32 args) +{ + struct object *o; + pid_t pid; + pop_n_elems(args); +#if defined(HAVE_FORK1) && defined(_REENTRANT) + pid=fork1(); +#else + pid=fork(); +#endif + if(pid==-1) error("Fork failed\n"); + + if(pid) + { + struct pid_status *p; + if(!signal_evaluator_callback) + { + signal_evaluator_callback=add_to_callback(&evaluator_callbacks, + check_signals, + 0,0); + } + o=clone_object(pid_status_program,0); + p=(struct pid_status *)get_storage(o,pid_status_program); + p->pid=pid; + p->state=PROCESS_RUNNING; + push_object(o); + push_int(pid); + mapping_insert(pid_mapping,sp-1, sp-2); + pop_stack(); + }else{ +#ifdef _REENTRANT + /* forked copy. there is now only one thread running, this one. */ + num_threads=1; +#endif + call_callback(&fork_child_callback, 0); + push_int(0); + } +} +#endif /* HAVE_FORK */ + + +#ifdef HAVE_KILL +static void f_kill(INT32 args) +{ + pid_t pid; + if(args < 2) + error("Too few arguments to kill().\n"); + switch(sp[-args].type) + { + case T_INT: + pid=sp[-args].u.integer; + break; + + case T_OBJECT: + { + struct pid_status *p; + if((p=(struct pid_status *)get_storage(sp[-args].u.object, + pid_status_program))) + { + pid=p->pid; + break; + } + } + default: + error("Bad argument 1 to kill().\n"); + } + + if(sp[-args].type != T_INT) + if(sp[1-args].type != T_INT) + error("Bad argument 1 to kill().\n"); + + sp[-args].u.integer=!kill(sp[-args].u.integer,sp[1-args].u.integer); + check_signals(0,0,0); + pop_n_elems(args-1); +} + +#endif + + static int signalling=0; static void unset_signalling(void *notused) { signalling=0; } @@ -353,7 +882,7 @@ static void f_signal(int args) { #ifdef SIGCHLD case SIGCHLD: - func=sig_child; + func=receive_signal; break; #endif @@ -410,20 +939,6 @@ static void f_signame(int args) push_int(0); } -#ifdef HAVE_KILL -static void f_kill(INT32 args) -{ - if(args < 2) - error("Too few arguments to kill().\n"); - if(sp[-args].type != T_INT) - error("Bad argument 1 to kill().\n"); - if(sp[1-args].type != T_INT) - error("Bad argument 1 to kill().\n"); - - sp[-args].u.integer=!kill(sp[-args].u.integer,sp[1-args].u.integer); - pop_n_elems(args-1); -} -#endif static void f_getpid(INT32 args) { @@ -476,7 +991,7 @@ void init_signals(void) int e; #ifdef SIGCHLD - my_signal(SIGCHLD, sig_child); + my_signal(SIGCHLD, receive_signal); #endif #ifdef SIGPIPE @@ -488,10 +1003,29 @@ void init_signals(void) firstsig=lastsig=0; +#ifndef __NT__ + pid_mapping=allocate_mapping(2); +#endif + + start_new_program(); + add_storage(sizeof(struct pid_status)); + set_init_callback(init_pid_status); + set_exit_callback(exit_pid_status); + add_function("wait",f_pid_status_wait,"function(:int)",0); + add_function("status",f_pid_status_status,"function(:int)",0); + add_function("pid",f_pid_status_pid,"function(:int)",0); + add_function("create",f_create_process,"function(array(string),void|mapping(string:mixed):object)",0); + pid_status_program=end_program(); + add_program_constant("create_process",pid_status_program,0); + add_efun("signal",f_signal,"function(int,mixed|void:void)",OPT_SIDE_EFFECT); #ifdef HAVE_KILL - add_efun("kill",f_kill,"function(int,int:int)",OPT_SIDE_EFFECT); + add_efun("kill",f_kill,"function(int|object,int:int)",OPT_SIDE_EFFECT); #endif +#ifdef HAVE_FORK + add_efun("fork",f_fork,"function(void:object)",OPT_SIDE_EFFECT); +#endif + add_efun("signame",f_signame,"function(int:string)",0); add_efun("signum",f_signum,"function(string:int)",0); add_efun("getpid",f_getpid,"function(:int)",0); @@ -506,6 +1040,20 @@ void init_signals(void) void exit_signals(void) { int e; +#ifndef __NT__ + if(pid_mapping) + { + free_mapping(pid_mapping); + pid_mapping=0; + } +#endif + if(pid_status_program) + { + free_program(pid_status_program); + pid_status_program=0; + } + + for(e=0;e<MAX_SIGNALS;e++) { free_svalue(signal_callbacks+e); diff --git a/src/signal_handler.h b/src/signal_handler.h index 9a83975b45f1e42c129940c742c4529ac44135a5..4436a1ecc5e9547bd0d030f2b9d93b70148b9afb 100644 --- a/src/signal_handler.h +++ b/src/signal_handler.h @@ -7,7 +7,11 @@ #define SIGNAL_H /* Prototypes begin here */ +struct wait_data; struct sigdesc; +struct pid_status; +void f_create_process(INT32 args); +void f_fork(INT32 args); void check_signals(struct callback *foo, void *bar, void *gazonk); void init_signals(void); void exit_signals(void); diff --git a/src/stralloc.c b/src/stralloc.c index 5f4c51d6996ccc1b3bdd3bb590afb6d26843299b..68a80f4517e600b450b62a76c17a651308696ee1 100644 --- a/src/stralloc.c +++ b/src/stralloc.c @@ -576,7 +576,7 @@ struct pike_string *string_replace(struct pike_string *str, /*** init/exit memory ***/ void init_shared_string_table(void) { - for(hashprimes_entry;hashprimes[hashprimes_entry]<BEGIN_HASH_SIZE;hashprimes_entry++); + for(hashprimes_entry=0;hashprimes[hashprimes_entry]<BEGIN_HASH_SIZE;hashprimes_entry++); htable_size=hashprimes[hashprimes_entry]; base_table=(struct pike_string **)xalloc(sizeof(struct pike_string *)*htable_size); MEMSET((char *)base_table,0,sizeof(struct pike_string *)*htable_size);