[pd] shell and ongoing processes

rat at telecoma.net rat at telecoma.net
Sun May 26 18:22:50 CEST 2002


> this is great, thank you for the patch, I had the zombie thing fixed some
> days ago, but I think the patch didnt make it to the list and I haven't
> put a new version of ggee on the web.

the "no zombie" version was sent to the dev-list
here it is again

lg

e.

-------------- next part --------------
/* (C) Guenter Geiger <geiger at epy.co.at> */





#include <m_pd.h>

#ifdef NT

#pragma warning( disable : 4244 )

#pragma warning( disable : 4305 )

#endif



#include <unistd.h>

#include <stdio.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <signal.h>



/* ------------------------ shell ----------------------------- */



#define INBUFSIZE 1024



static t_class *shell_class;





typedef struct _shell

{

     t_object x_obj;

     int      x_echo;

     char *sr_inbuf;

     int sr_inhead;

     int sr_intail;

     void* x_binbuf;

     int fdpipe[2];

     int pid;

} t_shell;



static int shell_pid;



void child_handler(int n)

{

	int ret;

	waitpid(-1,&ret,WNOHANG);

}



void shell_bang(t_shell *x)

{

     post("bang");

}



#if 1

static void shell_doit(void *z, t_binbuf *b)

{

    t_atom messbuf[1024];

    t_shell *x = (t_shell *)z;

    int msg, natom = binbuf_getnatom(b);

    t_atom *at = binbuf_getvec(b);



    for (msg = 0; msg < natom;)

    {

    	int emsg;

	for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA

	    && at[emsg].a_type != A_SEMI; emsg++)

	    	;

	if (emsg > msg)

	{

	    int i;

	    for (i = msg; i < emsg; i++)

	    	if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)

	    {

	    	pd_error(x, "netreceive: got dollar sign in message");

		goto nodice;

	    }

	    if (at[msg].a_type == A_FLOAT)

	    {

	    	if (emsg > msg + 1)

		    outlet_list(x->x_obj.ob_outlet,  0, emsg-msg, at + msg);

		else outlet_float(x->x_obj.ob_outlet,  at[msg].a_w.w_float);

	    }

	    else if (at[msg].a_type == A_SYMBOL)

	    	outlet_anything(x->x_obj.ob_outlet,  at[msg].a_w.w_symbol,

		    emsg-msg-1, at + msg + 1);

	}

    nodice:

    	msg = emsg + 1;

    }

}





void shell_read(t_shell *x, int fd)

{

     char buf[INBUFSIZE];

     t_binbuf* bbuf = binbuf_new();

     int i;

     int readto =

	  (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1);

     int ret;



     ret = read(fd, buf,INBUFSIZE);

     buf[ret] = '\0';



     for (i=0;i<ret;i++)

       if (buf[i] == '\n') buf[i] = ';';

     if (ret < 0)

       {

	 error("shell: pipe read error");

	 sys_rmpollfn(fd);

	 x->fdpipe[0] = -1;

	 close(fd);

	 return;

       }

     else if (ret == 0)

       {

	 post("EOF on socket %d\n", fd);

	 sys_rmpollfn(fd);

	 x->fdpipe[0] = -1;

	 close(fd);

	 return;

       }

     else

       {

	 int natom;

	 t_atom *at;

	 binbuf_text(bbuf, buf, strlen(buf));

	 

	 natom = binbuf_getnatom(bbuf);

	 at = binbuf_getvec(bbuf);

	 shell_doit(x,bbuf);

	 

       }

     binbuf_free(bbuf);

}



#endif



static void shell_anything(t_shell *x, t_symbol *s, int ac, t_atom *at)

{

     int i;

     char* argv[20];



     argv[0] = s->s_name;



     if (x->fdpipe[0] != -1) {

	  close(x->fdpipe[0]);

	  close(x->fdpipe[1]);

	  sys_rmpollfn(x->fdpipe[0]);

	  x->fdpipe[0] = -1;

	  x->fdpipe[1] = -1;

	  kill(x->pid,SIGKILL);

     }





	  

     for (i=1;i<=ac;i++) {

	  argv[i] = atom_getsymbolarg(i-1,ac,at)->s_name;

	  /* post("argument %s",argv[i]);*/

     }

     argv[i] = 0;



     if (pipe(x->fdpipe) < 0)

	  error("unable to create pipe");



     sys_addpollfn(x->fdpipe[0],shell_read,x);



     if (!(x->pid = fork())) {

	  /* reassign stdout */

	  dup2(x->fdpipe[1],1);

	  execvp(s->s_name,argv);

	  exit(0);

     }



     if (x->x_echo)

	  outlet_anything(x->x_obj.ob_outlet, s, ac, at); 

}







void shell_free(t_shell* x)

{

    binbuf_free(x->x_binbuf);

}



static void *shell_new()

{

    t_shell *x = (t_shell *)pd_new(shell_class);



    x->x_echo = 0;

    x->fdpipe[0] = -1;

    x->fdpipe[1] = -1;



    x->sr_inhead = x->sr_intail = 0;

    if (!(x->sr_inbuf = (char*) malloc(INBUFSIZE))) bug("t_shell");;



    x->x_binbuf = binbuf_new();



    outlet_new(&x->x_obj, &s_list);

    return (x);

}



void shell_setup(void)

{

    shell_class = class_new(gensym("shell"), (t_newmethod)shell_new, 

			    (t_method)shell_free,sizeof(t_shell), 0,0);

    class_addbang(shell_class,shell_bang);

    class_addanything(shell_class, shell_anything);

    signal(SIGCHLD, child_handler);

}







More information about the Pd-list mailing list