3c39d0 | 1997-10-05 | Per Hedbor | | #include "config.h"
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | #include "machine.h"
#include <sys/types.h>
#include <sys/stat.h>
|
1aac00 | 1997-05-22 | Henrik Grubbström (Grubba) | | #include <errno.h>
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | #ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#else
#ifdef HAVE_LINUX_MMAN_H
#include <linux/mman.h>
#else
#ifdef HAVE_MMAP
#include <sys/mman.h>
#endif
#endif
#endif
#include <fcntl.h>
#include "global.h"
|
d6ac73 | 1998-04-20 | Henrik Grubbström (Grubba) | | RCSID("$Id: pipe.c,v 1.21 1998/04/20 18:53:46 grubba Exp $");
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
|
3c39d0 | 1997-10-05 | Per Hedbor | | #include "threads.h"
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | #include "stralloc.h"
|
bb55f8 | 1997-03-16 | Fredrik Hübinette (Hubbe) | | #include "pike_macros.h"
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | #include "object.h"
#include "constants.h"
#include "interpret.h"
#include "svalue.h"
#include "error.h"
|
9c6f7d | 1997-04-15 | Fredrik Hübinette (Hubbe) | | #include "builtin_functions.h"
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
#ifndef S_ISREG
#ifdef S_IFREG
#define S_ISREG(mode) (((mode) & (S_IFMT)) == (S_IFREG))
#else
#define S_ISREG(mode) (((mode) & (_S_IFMT)) == (_S_IFREG))
#endif
#endif
#if 0
#define INSISTANT_WRITE
#endif
#ifndef MAP_FILE
# define MAP_FILE 0
#endif
|
3c39d0 | 1997-10-05 | Per Hedbor | | #define READ_BUFFER_SIZE 65536
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | #define MAX_BYTES_IN_BUFFER 65536
static struct program *pipe_program, *output_program;
|
b1f4eb | 1998-01-13 | Fredrik Hübinette (Hubbe) | | #ifdef THIS
#undef THIS
#endif
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | #define THIS ((struct pipe *)(fp->current_storage))
#define THISOBJ (fp->current_object)
struct input
{
|
dc16b4 | 1998-04-03 | Henrik Grubbström (Grubba) | | enum { I_NONE,I_OBJ,I_BLOCKING_OBJ,I_STRING,I_MMAP } type;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | union
{
struct object *obj;
struct pike_string *str;
char *mmap;
} u;
unsigned long len;
int set_blocking_offset, set_nonblocking_offset;
struct input *next;
};
struct output
{
struct object *obj;
int write_offset, set_blocking_offset, set_nonblocking_offset;
int fd;
enum
{
O_RUN,
O_SLEEP
} mode;
unsigned long pos;
struct object *next;
struct pipe *the_pipe;
};
struct buffer
{
struct pike_string *s;
struct buffer *next;
};
struct pipe
{
int living_outputs;
struct svalue done_callback;
struct svalue output_closed_callback;
struct svalue id;
int fd;
unsigned long bytes_in_buffer;
unsigned long pos;
struct buffer *firstbuffer,*lastbuffer;
short sleeping;
short done;
struct input *firstinput,*lastinput;
struct object *firstoutput;
|
a4dbbb | 1997-08-29 | Marcus Comstedt | | unsigned long sent;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | };
static int offset_input_read_callback;
static int offset_input_close_callback;
static int offset_output_write_callback;
static int offset_output_close_callback;
static int mmapped, nobjects, nstrings, noutputs, ninputs, nbuffers, sbuffers;
void close_and_free_everything(struct object *o,struct pipe *);
static INLINE void output_finish(struct object *obj);
static INLINE void output_try_write_some(struct object *obj);
static void push_callback(int no)
{
|
d6ac73 | 1998-04-20 | Henrik Grubbström (Grubba) | | add_ref(sp->u.object=THISOBJ);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | sp->subtype=no+fp->context.identifier_level;
sp->type=T_FUNCTION;
sp++;
}
static INLINE struct input *new_input(void)
{
struct input *i;
ninputs++;
i=ALLOC_STRUCT(input);
i->type=I_NONE;
i->next=NULL;
if (THIS->lastinput)
THIS->lastinput->next=i;
else
THIS->firstinput=i;
THIS->lastinput=i;
return i;
}
static INLINE void free_input(struct input *i)
{
ninputs--;
switch (i->type)
{
case I_OBJ:
|
dc16b4 | 1998-04-03 | Henrik Grubbström (Grubba) | | case I_BLOCKING_OBJ:
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | if (!i->u.obj) break;
if (i->u.obj->prog)
{
#ifdef BLOCKING_CLOSE
apply_low(i->u.obj,i->set_blocking_offset,0);
pop_stack();
#endif
apply(i->u.obj,"close",0);
pop_stack();
destruct(i->u.obj);
}
free_object(i->u.obj);
nobjects--;
i->u.obj=0;
break;
case I_STRING:
free_string(i->u.str);
nstrings--;
break;
case I_MMAP:
#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
munmap(i->u.mmap,i->len);
mmapped -= i->len;
#else
error("I_MMAP input when MMAP is diabled!");
#endif
break;
|
9c6f7d | 1997-04-15 | Fredrik Hübinette (Hubbe) | |
case I_NONE: break;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
free((char *)i);
}
static INLINE void pipe_done(void)
{
if (THIS->done_callback.type!=T_INT)
{
assign_svalue_no_free(sp++,&THIS->id);
apply_svalue(&(THIS->done_callback),1);
pop_stack();
if(!THISOBJ->prog)
return;
}
close_and_free_everything(THISOBJ,THIS);
}
static void finished_p(void)
{
if(THIS->done) return;
if(THIS->fd != -1)
{
if(THIS->living_outputs > 1) return;
if(THIS->firstinput) return;
}else{
if(THIS->living_outputs) return;
}
pipe_done();
}
static INLINE int append_buffer(struct pike_string *s)
{
struct buffer *b;
if(THIS->fd!= -1)
{
lseek(THIS->fd,THIS->pos,0);
write(THIS->fd,s->str,s->len);
THIS->pos+=s->len;
return 0;
}
else
{
nbuffers++;
b=ALLOC_STRUCT(buffer);
b->next=NULL;
b->s=s;
sbuffers += s->len;
|
d6ac73 | 1998-04-20 | Henrik Grubbström (Grubba) | | add_ref(s);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
if (THIS->lastbuffer)
THIS->lastbuffer->next=b;
else
THIS->firstbuffer=b;
THIS->lastbuffer=b;
THIS->bytes_in_buffer+=s->len;
}
return THIS->bytes_in_buffer > MAX_BYTES_IN_BUFFER;
}
|
be478c | 1997-08-30 | Henrik Grubbström (Grubba) | | static void low_start(void)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
struct object *obj, *next;
struct output *o;
|
d6ac73 | 1998-04-20 | Henrik Grubbström (Grubba) | | add_ref(THISOBJ);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | for(obj=THIS->firstoutput;obj;obj=next)
{
|
d6ac73 | 1998-04-20 | Henrik Grubbström (Grubba) | | add_ref(obj);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | o=(struct output *)(obj->storage);
if (o->obj && o->mode==O_SLEEP)
{
if (!o->obj->prog)
{
output_finish(obj);
}
else
{
#if 0
push_int(0);
push_callback(offset_output_write_callback);
push_callback(offset_output_close_callback);
apply_low(o->obj,o->set_nonblocking_offset,3);
#endif
output_try_write_some(obj);
o->mode=O_RUN;
}
}
next=o->next;
free_object(obj);
}
free_object(THISOBJ);
}
|
7dd0c6 | 1998-04-03 | Henrik Grubbström (Grubba) | |
static int read_some_data(void)
{
struct pipe *this = THIS;
struct input * i = this->firstinput;
if (!i || i->type != I_BLOCKING_OBJ) {
fatal("PIPE: read_some_data(): Bad input type!\n");
|
a4cbce | 1998-04-06 | Fredrik Hübinette (Hubbe) | | return -1;
|
7dd0c6 | 1998-04-03 | Henrik Grubbström (Grubba) | | }
push_int(8192);
push_int(1);
apply(i->u.obj, "read", 2);
if ((sp[-1].type == T_STRING) && (sp[-1].u.string->len > 0)) {
append_buffer(sp[-1].u.string);
pop_stack();
THIS->sleeping = 1;
return(1);
}
pop_stack();
return(0);
}
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
static INLINE void input_finish(void)
{
struct input *i;
while(1)
{
|
dc16b4 | 1998-04-03 | Henrik Grubbström (Grubba) | |
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | i=THIS->firstinput->next;
free_input(THIS->firstinput);
THIS->firstinput=i;
if(!i) break;
switch(i->type)
{
case I_OBJ:
THIS->sleeping=0;
push_callback(offset_input_read_callback);
push_int(0);
push_callback(offset_input_close_callback);
apply_low(i->u.obj,i->set_nonblocking_offset,3);
pop_stack();
return;
|
dc16b4 | 1998-04-03 | Henrik Grubbström (Grubba) | | case I_BLOCKING_OBJ:
|
7dd0c6 | 1998-04-03 | Henrik Grubbström (Grubba) | | if (read_some_data())
|
dc16b4 | 1998-04-03 | Henrik Grubbström (Grubba) | | return;
|
7dd0c6 | 1998-04-03 | Henrik Grubbström (Grubba) | | continue;
|
dc16b4 | 1998-04-03 | Henrik Grubbström (Grubba) | |
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | case I_MMAP:
if (THIS->fd==-1) return;
continue;
case I_STRING:
append_buffer(i->u.str);
|
9c6f7d | 1997-04-15 | Fredrik Hübinette (Hubbe) | |
case I_NONE: break;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
}
THIS->sleeping=0;
low_start();
finished_p();
}
static INLINE struct pike_string* gimme_some_data(unsigned long pos)
{
struct buffer *b;
|
1aac00 | 1997-05-22 | Henrik Grubbström (Grubba) | | long len;
|
8c2ec7 | 1997-10-10 | Henrik Grubbström (Grubba) | | struct pipe *this = THIS;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
|
3c39d0 | 1997-10-05 | Per Hedbor | | if (this->fd!=-1)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
|
3c39d0 | 1997-10-05 | Per Hedbor | | char buffer[READ_BUFFER_SIZE];
if (this->pos<=pos) return NULL;
len=this->pos-pos;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | if (len>READ_BUFFER_SIZE) len=READ_BUFFER_SIZE;
|
3c39d0 | 1997-10-05 | Per Hedbor | | THREADS_ALLOW();
|
8c2ec7 | 1997-10-10 | Henrik Grubbström (Grubba) | | lseek(this->fd, pos, 0);
|
3c39d0 | 1997-10-05 | Per Hedbor | | THREADS_DISALLOW();
|
1aac00 | 1997-05-22 | Henrik Grubbström (Grubba) | | do {
|
3c39d0 | 1997-10-05 | Per Hedbor | | THREADS_ALLOW();
|
8c2ec7 | 1997-10-10 | Henrik Grubbström (Grubba) | | len = read(this->fd, buffer, len);
|
3c39d0 | 1997-10-05 | Per Hedbor | | THREADS_DISALLOW();
|
1aac00 | 1997-05-22 | Henrik Grubbström (Grubba) | | if (len < 0) {
if (errno != EINTR) {
return(NULL);
}
}
} while(len < 0);
|
3c39d0 | 1997-10-05 | Per Hedbor | | return make_shared_binary_string(buffer,len);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
|
3c39d0 | 1997-10-05 | Per Hedbor | | if (pos<this->pos)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | return make_shared_string("buffer underflow");
|
3c39d0 | 1997-10-05 | Per Hedbor | | while (this->firstbuffer && pos>=this->pos+this->firstbuffer->s->len)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
|
3c39d0 | 1997-10-05 | Per Hedbor | | b=this->firstbuffer;
this->pos+=b->s->len;
this->bytes_in_buffer-=b->s->len;
this->firstbuffer=b->next;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | if (!b->next)
|
3c39d0 | 1997-10-05 | Per Hedbor | | this->lastbuffer=NULL;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | sbuffers-=b->s->len;
nbuffers--;
free_string(b->s);
free((char *)b);
|
3c39d0 | 1997-10-05 | Per Hedbor | | if (this->sleeping &&
this->firstinput &&
this->bytes_in_buffer<MAX_BYTES_IN_BUFFER)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
|
eb7d4c | 1998-04-03 | Henrik Grubbström (Grubba) | | if (this->firstinput->type == I_BLOCKING_OBJ) {
|
7dd0c6 | 1998-04-03 | Henrik Grubbström (Grubba) | | if (!read_some_data()) {
|
eb7d4c | 1998-04-03 | Henrik Grubbström (Grubba) | | this->sleeping = 0;
|
b9795b | 1998-04-03 | Henrik Grubbström (Grubba) | | input_finish();
|
dc16b4 | 1998-04-03 | Henrik Grubbström (Grubba) | | }
} else {
this->sleeping=0;
push_callback(offset_input_read_callback);
push_int(0);
push_callback(offset_input_close_callback);
apply(this->firstinput->u.obj, "set_nonblocking", 3);
pop_stack();
}
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
}
|
3c39d0 | 1997-10-05 | Per Hedbor | | while (!this->firstbuffer)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
|
3c39d0 | 1997-10-05 | Per Hedbor | | if (this->firstinput)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
|
3c39d0 | 1997-10-05 | Per Hedbor | | if (this->firstinput->type==I_MMAP)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
|
8c2ec7 | 1997-10-10 | Henrik Grubbström (Grubba) | | char *src;
struct pike_string *tmp;
|
3c39d0 | 1997-10-05 | Per Hedbor | | if (pos >= this->firstinput->len + this->pos)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
|
8c2ec7 | 1997-10-10 | Henrik Grubbström (Grubba) | | this->pos += this->firstinput->len;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | input_finish();
continue;
}
|
8c2ec7 | 1997-10-10 | Henrik Grubbström (Grubba) | | len = this->firstinput->len + this->pos - pos;
|
3c39d0 | 1997-10-05 | Per Hedbor | | if (len > READ_BUFFER_SIZE) len=READ_BUFFER_SIZE;
tmp = begin_shared_string( len );
|
8c2ec7 | 1997-10-10 | Henrik Grubbström (Grubba) | | src = this->firstinput->u.mmap + pos - this->pos;
|
3c39d0 | 1997-10-05 | Per Hedbor | |
THREADS_ALLOW();
|
8c2ec7 | 1997-10-10 | Henrik Grubbström (Grubba) | | MEMCPY(tmp->str, src, len);
|
3c39d0 | 1997-10-05 | Per Hedbor | | THREADS_DISALLOW();
return end_shared_string(tmp);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
else
#endif
|
3c39d0 | 1997-10-05 | Per Hedbor | | if (this->firstinput->type!=I_OBJ)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
|
dc16b4 | 1998-04-03 | Henrik Grubbström (Grubba) | |
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | input_finish();
}
}
return NULL;
}
|
3c39d0 | 1997-10-05 | Per Hedbor | | if (pos==this->pos)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
|
d6ac73 | 1998-04-20 | Henrik Grubbström (Grubba) | | add_ref(this->firstbuffer->s);
|
3c39d0 | 1997-10-05 | Per Hedbor | | return this->firstbuffer->s;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
|
3c39d0 | 1997-10-05 | Per Hedbor | | return make_shared_binary_string(this->firstbuffer->s->str+
pos-this->pos,
this->firstbuffer->s->len-
pos+this->pos);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
static INLINE void output_finish(struct object *obj)
{
struct output *o;
o=(struct output *)(obj->storage);
if (o->obj)
{
if(o->obj->prog)
{
#ifdef BLOCKING_CLOSE
apply_low(o->obj,o->set_blocking_offset,0);
pop_stack();
#endif
push_int(0);
apply(o->obj,"set_id",1);
pop_stack();
apply(o->obj,"close",0);
pop_stack();
if(!THISOBJ->prog)
error("Pipe done callback destructed pipe.\n");
destruct(o->obj);
}
free_object(o->obj);
noutputs--;
o->obj=NULL;
THIS->living_outputs--;
finished_p();
free_object(THISOBJ);
}
}
static INLINE void output_try_write_some(struct object *obj)
{
struct output *out;
struct pike_string *s;
unsigned long len;
INT32 ret;
out=(struct output*)(obj->storage);
#ifdef INSISTANT_WRITE
do
{
#endif
s=gimme_some_data(out->pos);
if (!s)
{
if (!THIS->firstinput || !out->obj->prog)
{
output_finish(obj);
}
else
{
#if 0
apply_low(out->obj, out->set_blocking_offset, 0);
pop_stack();
#endif
out->mode=O_SLEEP;
}
return;
}
len=s->len;
push_string(s);
apply_low(out->obj,out->write_offset,1);
out->mode=O_RUN;
ret=-1;
if(sp[-1].type == T_INT) ret=sp[-1].u.integer;
pop_stack();
if (ret==-1)
{
output_finish(obj);
return;
}
out->pos+=ret;
|
a4dbbb | 1997-08-29 | Marcus Comstedt | | THIS->sent+=ret;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
#ifdef INSISTANT_WRITE
} while(ret == len);
#endif
}
static void pipe_input(INT32 args)
{
struct input *i;
int fd=-1;
char *m;
struct stat s;
struct object *obj;
if (args<1 || sp[-args].type != T_OBJECT)
error("Bad/missing argument 1 to pipe->input().\n");
obj=sp[-args].u.object;
if(!obj || !obj->prog)
error("pipe->input() on destructed object.\n");
push_int(0);
apply(sp[-args-1].u.object,"set_id", 1);
pop_stack();
i=new_input();
#if defined(HAVE_MMAP) && defined(HAVE_MUNMAP)
if(THIS->fd == -1)
{
apply(obj, "query_fd", 0);
if(sp[-1].type == T_INT) fd=sp[-1].u.integer;
pop_stack();
if (fd != -1 && fstat(fd,&s)==0)
{
|
a369b8 | 1997-05-08 | Per Hedbor | | int filep=lseek(fd, 0L, SEEK_CUR);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | if(S_ISREG(s.st_mode)
|
a369b8 | 1997-05-08 | Per Hedbor | | && ((long)(m=(char *)mmap(0,s.st_size - filep,PROT_READ,
MAP_FILE|MAP_SHARED,fd,filep))!=-1))
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
|
3c39d0 | 1997-10-05 | Per Hedbor | | #ifdef HAVE_GETEUID
int ou = 0;
#endif
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | mmapped += s.st_size;
i->type=I_MMAP;
i->len=s.st_size;
i->u.mmap=m;
|
3c39d0 | 1997-10-05 | Per Hedbor | | #ifdef HAVE_MADVISE
|
d7f088 | 1997-10-05 | Henrik Grubbström (Grubba) | |
|
3c39d0 | 1997-10-05 | Per Hedbor | | #ifdef HAVE_GETEUID
|
d7f088 | 1997-10-05 | Henrik Grubbström (Grubba) | | if((ou=geteuid()) && !getuid()) {
#ifdef HAVE_SETEUID
seteuid(0);
#else /* ! HAVE_SETEUID */
#ifdef HAVE_SETREUID
setresuid(-1, 0, -1);
#endif /* HAVE_SETRESUID */
#endif /* HAVE_SETEUID */
}
|
3c39d0 | 1997-10-05 | Per Hedbor | | #endif
madvise(m, s.st_size, MADV_SEQUENTIAL);
#ifdef HAVE_GETEUID
|
d7f088 | 1997-10-05 | Henrik Grubbström (Grubba) | | if(ou) {
#ifdef HAVE_SETEUID
|
eb7d4c | 1998-04-03 | Henrik Grubbström (Grubba) | | seteuid(ou);
|
d7f088 | 1997-10-05 | Henrik Grubbström (Grubba) | | #else /* ! HAVE_SETEUID */
#ifdef HAVE_SETREUID
setresuid(-1, ou, -1);
#endif /* HAVE_SETRESUID */
#endif /* HAVE_SETEUID */
}
|
3c39d0 | 1997-10-05 | Per Hedbor | | #endif
#endif
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | pop_n_elems(args);
push_int(0);
return;
}
}
}
#endif
i->u.obj=obj;
nobjects++;
i->type=I_OBJ;
|
d6ac73 | 1998-04-20 | Henrik Grubbström (Grubba) | | add_ref(i->u.obj);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | i->set_nonblocking_offset=find_identifier("set_nonblocking",i->u.obj->prog);
i->set_blocking_offset=find_identifier("set_blocking",i->u.obj->prog);
if (i->set_nonblocking_offset<0 ||
i->set_blocking_offset<0)
{
|
dc16b4 | 1998-04-03 | Henrik Grubbström (Grubba) | | if (find_identifier("read", i->u.obj->prog) < 0) {
free_object(i->u.obj);
i->u.obj=NULL;
i->type=I_NONE;
nobjects--;
error("illegal file object%s%s\n",
((i->set_nonblocking_offset<0)?"; no set_nonblocking":""),
((i->set_blocking_offset<0)?"; no set_blocking":""));
} else {
i->type = I_BLOCKING_OBJ;
|
7dd0c6 | 1998-04-03 | Henrik Grubbström (Grubba) | | if (i==THIS->firstinput) {
read_some_data();
}
|
dc16b4 | 1998-04-03 | Henrik Grubbström (Grubba) | | return;
}
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
if (i==THIS->firstinput)
{
push_callback(offset_input_read_callback);
push_int(0);
push_callback(offset_input_close_callback);
apply_low(i->u.obj,i->set_nonblocking_offset,3);
pop_stack();
}
else
{
push_int(0);
push_int(0);
push_callback(offset_input_close_callback);
apply_low(i->u.obj,i->set_nonblocking_offset,3);
pop_stack();
}
pop_n_elems(args);
push_int(0);
}
static void pipe_write(INT32 args)
{
struct input *i;
if (args<1 || sp[-args].type!=T_STRING)
error("illegal argument to pipe->write()\n");
if (!THIS->firstinput)
{
append_buffer(sp[-args].u.string);
pop_n_elems(args);
push_int(0);
return;
}
i=new_input();
i->type=I_STRING;
nstrings++;
|
d6ac73 | 1998-04-20 | Henrik Grubbström (Grubba) | | add_ref(i->u.str=sp[-args].u.string);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | pop_n_elems(args-1);
}
void f_mark_fd(INT32 args);
static void pipe_output(INT32 args)
{
struct object *obj;
struct output *o;
int fd;
struct stat s;
struct buffer *b;
if (args<1 ||
sp[-args].type != T_OBJECT ||
!sp[-args].u.object ||
!sp[-args].u.object->prog)
error("Bad/missing argument 1 to pipe->output().\n");
if (THIS->fd==-1)
{
apply(sp[-args].u.object,"query_fd",0);
if ((sp[-1].type==T_INT)
&& (fd=sp[-1].u.integer)>=0
&& (fstat(fd,&s)==0)
&& S_ISREG(s.st_mode)
&& (THIS->fd=dup(fd))!=-1 )
{
|
41362a | 1997-03-20 | Wilhelm Köhler | |
THIS->pos=lseek(fd, 0L, SEEK_CUR);
|
dfa11d | 1997-02-20 | Henrik Grubbström (Grubba) | | #if 0
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | push_int(THIS->fd);
push_string(make_shared_string("pipe.c: file buffer"));
f_mark_fd(2);
pop_stack();
|
dfa11d | 1997-02-20 | Henrik Grubbström (Grubba) | | #endif /* 0 */
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
THIS->living_outputs++;
while (THIS->firstbuffer)
{
b=THIS->firstbuffer;
THIS->firstbuffer=b->next;
lseek(THIS->fd,THIS->pos,0);
write(THIS->fd,b->s->str,b->s->len);
sbuffers-=b->s->len;
nbuffers--;
free_string(b->s);
free((char *)b);
}
THIS->lastbuffer=NULL;
|
41362a | 1997-03-20 | Wilhelm Köhler | |
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | push_int(0);
apply(sp[-args-2].u.object,"set_id", 1);
pop_n_elems(args+2);
return;
}
pop_stack();
}
THIS->living_outputs++;
|
d6ac73 | 1998-04-20 | Henrik Grubbström (Grubba) | | add_ref(THISOBJ);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
|
e70975 | 1997-03-12 | Fredrik Hübinette (Hubbe) | | obj=clone_object(output_program,0);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | o=(struct output *)(obj->storage);
o->next=THIS->firstoutput;
THIS->firstoutput=obj;
noutputs++;
o->obj=NULL;
|
d6ac73 | 1998-04-20 | Henrik Grubbström (Grubba) | | add_ref(o->obj=sp[-args].u.object);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
o->write_offset=find_identifier("write",o->obj->prog);
o->set_nonblocking_offset=find_identifier("set_nonblocking",o->obj->prog);
o->set_blocking_offset=find_identifier("set_blocking",o->obj->prog);
if (o->write_offset<0 || o->set_nonblocking_offset<0 ||
o->set_blocking_offset<0)
{
free_object(o->obj);
error("illegal file object%s%s%s\n",
((o->write_offset<0)?"; no write":""),
((o->set_nonblocking_offset<0)?"; no set_nonblocking":""),
((o->set_blocking_offset<0)?"; no set_blocking":""));
}
o->mode=O_RUN;
|
41362a | 1997-03-20 | Wilhelm Köhler | |
o->pos=THIS->pos;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
|
d6ac73 | 1998-04-20 | Henrik Grubbström (Grubba) | | ref_push_object(obj);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | apply(o->obj,"set_id",1);
pop_stack();
push_int(0);
push_callback(offset_output_write_callback);
push_callback(offset_output_close_callback);
apply_low(o->obj,o->set_nonblocking_offset,3);
pop_stack();
pop_n_elems(args-1);
}
static void pipe_set_done_callback(INT32 args)
{
if (args==0)
{
free_svalue(&THIS->done_callback);
THIS->done_callback.type=T_INT;
return;
}
if (args<1 || (sp[-args].type!=T_FUNCTION && sp[-args].type!=T_ARRAY))
error("Illegal argument to set_done_callback()\n");
if (args>1)
{
free_svalue(&THIS->id);
assign_svalue_no_free(&(THIS->id),sp-args+1);
}
free_svalue(&THIS->done_callback);
assign_svalue_no_free(&(THIS->done_callback),sp-args);
pop_n_elems(args-1);
}
static void pipe_set_output_closed_callback(INT32 args)
{
if (args==0)
{
free_svalue(&THIS->done_callback);
THIS->output_closed_callback.type=T_INT;
return;
}
if (args<1 || (sp[-args].type!=T_FUNCTION && sp[-args].type!=T_ARRAY))
error("Illegal argument to set_output_closed_callback()\n");
if (args>1)
{
free_svalue(&THIS->id);
assign_svalue_no_free(&(THIS->id),sp-args+1);
}
free_svalue(&THIS->output_closed_callback);
assign_svalue_no_free(&(THIS->output_closed_callback),sp-args);
pop_n_elems(args-1);
}
static void pipe_finish(INT32 args)
{
pop_n_elems(args);
push_int(0);
pipe_done();
}
static void pipe_start(INT32 args)
{
low_start();
if(args)
pop_n_elems(args-1);
}
|
a4dbbb | 1997-08-29 | Marcus Comstedt | | static void f_bytes_sent(INT32 args)
{
pop_n_elems(args);
push_int(THIS->sent);
}
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
static void pipe_write_output_callback(INT32 args)
{
if (args<1 || sp[-args].type!=T_OBJECT)
error("Illegal argument to pipe->write_output_callback\n");
if(!sp[-args].u.object->prog) return;
if(sp[-args].u.object->prog != output_program)
error("Illegal argument to pipe->write_output_callback\n");
output_try_write_some(sp[-args].u.object);
pop_n_elems(args-1);
}
static void pipe_close_output_callback(INT32 args)
{
struct output *o;
if (args<1 || sp[-args].type!=T_OBJECT)
if(!sp[-args].u.object->prog) return;
if(sp[-args].u.object->prog != output_program)
error("Illegal argument to pipe->close_output_callback\n");
o=(struct output *)(sp[-args].u.object->storage);
if (THIS->output_closed_callback.type!=T_INT)
{
assign_svalue_no_free(sp++,&THIS->id);
push_object(o->obj);
apply_svalue(&(THIS->output_closed_callback),2);
pop_stack();
}
output_finish(sp[-args].u.object);
pop_n_elems(args-1);
}
static void pipe_read_input_callback(INT32 args)
{
struct input *i;
struct pike_string *s;
if (args<2 || sp[1-args].type!=T_STRING)
error("Illegal argument to pipe->read_input_callback\n");
i=THIS->firstinput;
if (!i)
error("Pipe read callback without any inputs left.\n");
s=sp[1-args].u.string;
if(append_buffer(s))
{
push_int(0);
push_int(0);
push_callback(offset_input_close_callback);
apply_low(i->u.obj,i->set_nonblocking_offset,3);
pop_stack();
THIS->sleeping=1;
}
low_start();
pop_n_elems(args-1);
}
static void pipe_close_input_callback(INT32 args)
{
struct input *i;
i=THIS->firstinput;
if(!i)
error("Input close callback without inputs!\n");
if(i->type != I_OBJ)
error("Premature close callback on pipe!.\n");
if (i->u.obj->prog)
{
#ifdef BLOCKING_CLOSE
apply_low(i->u.obj,i->set_blocking_offset,0);
pop_stack();
#endif
apply(i->u.obj,"close",0);
pop_stack();
}
nobjects--;
free_object(i->u.obj);
i->type=I_NONE;
input_finish();
if(args)
pop_n_elems(args-1);
}
static void pipe_version(INT32 args)
{
pop_n_elems(args);
push_string(make_shared_string("PIPE ver 2.0"));
}
void close_and_free_everything(struct object *thisobj,struct pipe *p)
{
struct buffer *b;
struct input *i;
struct output *o;
struct object *obj;
p->done=1;
if (thisobj)
|
d6ac73 | 1998-04-20 | Henrik Grubbström (Grubba) | | add_ref(thisobj);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | |
while (p->firstbuffer)
{
b=p->firstbuffer;
p->firstbuffer=b->next;
sbuffers-=b->s->len;
nbuffers--;
free_string(b->s);
b->next=NULL;
free((char *)b);
}
p->lastbuffer=NULL;
while (p->firstinput)
{
i=p->firstinput;
p->firstinput=i->next;
free_input(i);
}
p->lastinput=NULL;
while (p->firstoutput)
{
obj=p->firstoutput;
o=(struct output *)(obj->storage);
p->firstoutput=o->next;
output_finish(obj);
free_object(obj);
}
if (p->fd!=-1)
{
close(p->fd);
p->fd=-1;
}
p->living_outputs=0;
if (thisobj)
free_object(thisobj);
free_svalue(& p->done_callback);
free_svalue(& p->output_closed_callback);
free_svalue(& p->id);
p->done_callback.type=T_INT;
p->output_closed_callback.type=T_INT;
p->id.type=T_INT;
p->done=0;
}
static void init_pipe_struct(struct object *o)
{
THIS->firstbuffer=THIS->lastbuffer=NULL;
THIS->firstinput=THIS->lastinput=NULL;
THIS->firstoutput=NULL;
THIS->bytes_in_buffer=0;
THIS->pos=0;
THIS->sleeping=0;
THIS->done=0;
THIS->fd=-1;
THIS->done_callback.type=T_INT;
THIS->output_closed_callback.type=T_INT;
THIS->id.type=T_INT;
THIS->id.u.integer=0;
THIS->living_outputs=0;
|
a4dbbb | 1997-08-29 | Marcus Comstedt | | THIS->sent=0;
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | }
static void exit_pipe_struct(struct object *o)
{
close_and_free_everything(NULL,THIS);
}
static void exit_output_struct(struct object *obj)
{
struct output *o;
o=(struct output *)(fp->current_storage);
if (o->obj)
{
if(o->obj->prog)
{
#ifdef BLOCKING_CLOSE
apply_low(o->obj,o->set_blocking_offset,0);
pop_stack();
#endif
push_int(0);
apply(o->obj,"set_id",1);
pop_stack();
apply(o->obj,"close",0);
pop_stack();
if(!THISOBJ->prog)
error("Pipe done callback destructed pipe.\n");
}
free_object(o->obj);
noutputs--;
o->obj=0;
}
}
static void init_output_struct(struct object *ob)
{
struct output *o;
o=(struct output *)(fp->current_storage);
o->obj=0;
}
void port_setup_program(void);
void f__pipe_debug(INT32 args)
{
pop_n_elems(args);
push_int(noutputs);
push_int(ninputs);
push_int(nstrings);
push_int(nobjects);
push_int(mmapped);
push_int(nbuffers);
push_int(sbuffers);
f_aggregate(7);
}
|
be478c | 1997-08-30 | Henrik Grubbström (Grubba) | | void pike_module_init(void)
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | {
start_new_program();
add_storage(sizeof(struct pipe));
add_efun("_pipe_debug", f__pipe_debug, "function(:array)", 0);
add_function("input",pipe_input,"function(object:void)",0);
add_function("output",pipe_output,"function(object:void)",0);
add_function("write",pipe_write,"function(string:void)",0);
add_function("start",pipe_start,"function(:void)",0);
add_function("finish",pipe_finish,"function(:void)",0);
add_function("set_output_closed_callback",pipe_set_output_closed_callback,
"function(void|function(mixed,object:mixed),void|mixed:void)",0);
add_function("set_done_callback",pipe_set_done_callback,
"function(void|function(mixed:mixed),void|mixed:void)",0);
add_function("_output_close_callback",pipe_close_output_callback,
"function(int:void)",0);
add_function("_input_close_callback",pipe_close_input_callback,
"function(int:void)",0);
add_function("_output_write_callback",pipe_write_output_callback,
"function(int:void)",0);
add_function("_input_read_callback",pipe_read_input_callback,
"function(int,string:void)",0);
add_function("version",pipe_version,"function(:string)",0);
|
a4dbbb | 1997-08-29 | Marcus Comstedt | | add_function("bytes_sent",f_bytes_sent,"function(:int)",0);
|
ab6aec | 1997-02-11 | Fredrik Hübinette (Hubbe) | | set_init_callback(init_pipe_struct);
set_exit_callback(exit_pipe_struct);
pipe_program=end_program();
add_program_constant("pipe",pipe_program, 0);
offset_output_close_callback=find_identifier("_output_close_callback",
pipe_program);
offset_input_close_callback=find_identifier("_input_close_callback",
pipe_program);
offset_output_write_callback=find_identifier("_output_write_callback",
pipe_program);
offset_input_read_callback=find_identifier("_input_read_callback",
pipe_program);
start_new_program();
add_storage(sizeof(struct output));
set_init_callback(init_output_struct);
set_exit_callback(exit_output_struct);
output_program=end_program();
add_program_constant("__output",output_program, 0);
}
void pike_module_exit(void)
{
if(pipe_program) free_program(pipe_program);
pipe_program=0;
if(output_program) free_program(output_program);
output_program=0;
}
|