1 /* (C) Guenter Geiger <geiger@epy.co.at> */
5 #pragma warning( disable : 4244 )
6 #pragma warning( disable : 4305 )
13 #include <sys/types.h>
18 void sys_rmpollfn(int fd
);
19 void sys_addpollfn(int fd
, void* fn
, void *ptr
);
21 /* ------------------------ shell ----------------------------- */
23 #define INBUFSIZE 1024
25 static t_class
*shell_class
;
28 static void drop_priority(void)
30 #ifdef _POSIX_PRIORITY_SCHEDULING
31 struct sched_param par
;
33 par
.sched_priority
= 0;
34 sched_setscheduler(0,SCHED_OTHER
,&par
);
58 void shell_cleanup(t_shell
* x
)
60 sys_rmpollfn(x
->fdpipe
[0]);
62 if (x
->fdpipe
[0]>0) close(x
->fdpipe
[0]);
63 if (x
->fdpipe
[1]>0) close(x
->fdpipe
[1]);
64 if (x
->fdinpipe
[0]>0) close(x
->fdinpipe
[0]);
65 if (x
->fdinpipe
[1]>0) close(x
->fdinpipe
[1]);
71 clock_unset(x
->x_clock
);
74 void shell_check(t_shell
* x
)
78 ret
= waitpid(x
->pid
,&status
,WNOHANG
);
81 if (WIFEXITED(status
)) {
82 outlet_float(x
->x_done
,WEXITSTATUS(status
));
84 else outlet_float(x
->x_done
,0);
87 if (x
->x_del
< 100) x
->x_del
+=2; /* increment poll times */
88 clock_delay(x
->x_clock
,x
->x_del
);
93 void shell_bang(t_shell
*x
)
98 /* snippet from pd's code */
99 static void shell_doit(void *z
, t_binbuf
*b
)
101 t_shell
*x
= (t_shell
*)z
;
102 int msg
, natom
= binbuf_getnatom(b
);
103 t_atom
*at
= binbuf_getvec(b
);
105 for (msg
= 0; msg
< natom
;)
108 for (emsg
= msg
; emsg
< natom
&& at
[emsg
].a_type
!= A_COMMA
109 && at
[emsg
].a_type
!= A_SEMI
; emsg
++)
114 for (i
= msg
; i
< emsg
; i
++)
115 if (at
[i
].a_type
== A_DOLLAR
|| at
[i
].a_type
== A_DOLLSYM
)
117 pd_error(x
, "netreceive: got dollar sign in message");
120 if (at
[msg
].a_type
== A_FLOAT
)
123 outlet_list(x
->x_obj
.ob_outlet
, 0, emsg
-msg
, at
+ msg
);
124 else outlet_float(x
->x_obj
.ob_outlet
, at
[msg
].a_w
.w_float
);
126 else if (at
[msg
].a_type
== A_SYMBOL
)
127 outlet_anything(x
->x_obj
.ob_outlet
, at
[msg
].a_w
.w_symbol
,
128 emsg
-msg
-1, at
+ msg
+ 1);
136 void shell_read(t_shell
*x
, int fd
)
139 t_binbuf
* bbuf
= binbuf_new();
142 (x
->sr_inhead
>= x
->sr_intail
? INBUFSIZE
: x
->sr_intail
-1);
145 ret
= read(fd
, buf
,INBUFSIZE
-1);
149 if (buf
[i
] == '\n') buf
[i
] = ';';
152 error("shell: pipe read error");
160 post("EOF on socket %d\n", fd
);
170 binbuf_text(bbuf
, buf
, strlen(buf
));
172 natom
= binbuf_getnatom(bbuf
);
173 at
= binbuf_getvec(bbuf
);
180 static void shell_send(t_shell
*x
, t_symbol
*s
,int ac
, t_atom
*at
)
183 char tmp
[MAXPDSTRING
];
186 if (x
->fdinpipe
[0] == -1) return; /* nothing to send to */
189 atom_string(at
,tmp
+size
,MAXPDSTRING
- size
);
195 post("sending %s",tmp
);
196 write(x
->fdinpipe
[0],tmp
,strlen(tmp
));
199 static void shell_anything(t_shell
*x
, t_symbol
*s
, int ac
, t_atom
*at
)
205 if (!strcmp(s
->s_name
,"send")) {
207 shell_send(x
,s
,ac
,at
);
213 if (x
->fdpipe
[0] != -1) {
214 post("shell: old process still running");
215 kill(x
->pid
,SIGKILL
);
220 if (pipe(x
->fdpipe
) < 0) {
221 error("unable to create pipe");
225 if (pipe(x
->fdinpipe
) < 0) {
226 error("unable to create input pipe");
231 sys_addpollfn(x
->fdpipe
[0],shell_read
,x
);
233 if (!(x
->pid
= fork())) {
235 char* cmd
= getbytes(1024);
236 char* tcmd
= getbytes(1024);
237 strcpy(cmd
,s
->s_name
);
240 for (i
=1;i
<=ac
;i
++) {
241 argv
[i
] = getbytes(255);
242 atom_string(at
,argv
[i
],255);
243 /* post("argument %s",argv[i]); */
248 for (i
=1;i
<=ac
;i
++) {
249 atom_string(at
,tcmd
,255);
256 /* reassign stdout */
257 dup2(x
->fdpipe
[1],1);
258 dup2(x
->fdinpipe
[1],0);
260 /* drop privileges */
262 seteuid(getuid()); /* lose setuid priveliges */
264 post("executing %s",cmd
);
266 // execvp(s->s_name,argv);
270 clock_delay(x
->x_clock
,x
->x_del
);
273 outlet_anything(x
->x_obj
.ob_outlet
, s
, ac
, at
);
278 void shell_free(t_shell
* x
)
280 binbuf_free(x
->x_binbuf
);
283 static void *shell_new(void)
285 t_shell
*x
= (t_shell
*)pd_new(shell_class
);
293 x
->sr_inhead
= x
->sr_intail
= 0;
294 if (!(x
->sr_inbuf
= (char*) malloc(INBUFSIZE
))) bug("t_shell");;
296 x
->x_binbuf
= binbuf_new();
298 outlet_new(&x
->x_obj
, &s_list
);
299 x
->x_done
= outlet_new(&x
->x_obj
, &s_bang
);
300 x
->x_clock
= clock_new(x
, (t_method
) shell_check
);
304 void shell_setup(void)
306 shell_class
= class_new(gensym("shell"), (t_newmethod
)shell_new
,
307 (t_method
)shell_free
,sizeof(t_shell
), 0,0);
308 class_addbang(shell_class
,shell_bang
);
309 class_addanything(shell_class
, shell_anything
);
313 /* (C) Guenter Geiger <geiger@epy.co.at> */
317 #pragma warning( disable : 4244 )
318 #pragma warning( disable : 4305 )
325 #include <sys/types.h>
326 #include <sys/wait.h>
330 void sys_rmpollfn(int fd
);
331 void sys_addpollfn(int fd
, void* fn
, void *ptr
);
333 /* ------------------------ shell ----------------------------- */
335 #define INBUFSIZE 1024
337 static t_class
*shell_class
;
340 static void drop_priority(void)
342 #ifdef _POSIX_PRIORITY_SCHEDULING
343 struct sched_param par
;
345 par
.sched_priority
= 0;
346 sched_setscheduler(0,SCHED_OTHER
,&par
);
351 typedef struct _shell
367 static int shell_pid
;
370 void shell_cleanup(t_shell
* x
)
372 sys_rmpollfn(x
->fdpipe
[0]);
374 if (x
->fdpipe
[0]>0) close(x
->fdpipe
[0]);
375 if (x
->fdpipe
[1]>0) close(x
->fdpipe
[1]);
376 if (x
->fdinpipe
[0]>0) close(x
->fdinpipe
[0]);
377 if (x
->fdinpipe
[1]>0) close(x
->fdinpipe
[1]);
383 clock_unset(x
->x_clock
);
386 void shell_check(t_shell
* x
)
390 ret
= waitpid(x
->pid
,&status
,WNOHANG
);
393 if (WIFEXITED(status
)) {
394 outlet_float(x
->x_done
,WEXITSTATUS(status
));
396 else outlet_float(x
->x_done
,0);
399 if (x
->x_del
< 100) x
->x_del
+=2; /* increment poll times */
400 clock_delay(x
->x_clock
,x
->x_del
);
405 void shell_bang(t_shell
*x
)
410 /* snippet from pd's code */
411 static void shell_doit(void *z
, t_binbuf
*b
)
413 t_shell
*x
= (t_shell
*)z
;
414 int msg
, natom
= binbuf_getnatom(b
);
415 t_atom
*at
= binbuf_getvec(b
);
417 for (msg
= 0; msg
< natom
;)
420 for (emsg
= msg
; emsg
< natom
&& at
[emsg
].a_type
!= A_COMMA
421 && at
[emsg
].a_type
!= A_SEMI
; emsg
++)
426 for (i
= msg
; i
< emsg
; i
++)
427 if (at
[i
].a_type
== A_DOLLAR
|| at
[i
].a_type
== A_DOLLSYM
)
429 pd_error(x
, "netreceive: got dollar sign in message");
432 if (at
[msg
].a_type
== A_FLOAT
)
435 outlet_list(x
->x_obj
.ob_outlet
, 0, emsg
-msg
, at
+ msg
);
436 else outlet_float(x
->x_obj
.ob_outlet
, at
[msg
].a_w
.w_float
);
438 else if (at
[msg
].a_type
== A_SYMBOL
)
439 outlet_anything(x
->x_obj
.ob_outlet
, at
[msg
].a_w
.w_symbol
,
440 emsg
-msg
-1, at
+ msg
+ 1);
448 void shell_read(t_shell
*x
, int fd
)
451 t_binbuf
* bbuf
= binbuf_new();
454 (x
->sr_inhead
>= x
->sr_intail
? INBUFSIZE
: x
->sr_intail
-1);
457 ret
= read(fd
, buf
,INBUFSIZE
-1);
461 if (buf
[i
] == '\n') buf
[i
] = ';';
464 error("shell: pipe read error");
472 post("EOF on socket %d\n", fd
);
482 binbuf_text(bbuf
, buf
, strlen(buf
));
484 natom
= binbuf_getnatom(bbuf
);
485 at
= binbuf_getvec(bbuf
);
492 static void shell_send(t_shell
*x
, t_symbol
*s
,int ac
, t_atom
*at
)
495 char tmp
[MAXPDSTRING
];
498 if (x
->fdinpipe
[0] == -1) return; /* nothing to send to */
501 atom_string(at
,tmp
+size
,MAXPDSTRING
- size
);
507 post("sending %s",tmp
);
508 write(x
->fdinpipe
[0],tmp
,strlen(tmp
));
511 static void shell_anything(t_shell
*x
, t_symbol
*s
, int ac
, t_atom
*at
)
517 if (!strcmp(s
->s_name
,"send")) {
519 shell_send(x
,s
,ac
,at
);
525 if (x
->fdpipe
[0] != -1) {
526 post("shell: old process still running");
527 kill(x
->pid
,SIGKILL
);
532 if (pipe(x
->fdpipe
) < 0) {
533 error("unable to create pipe");
537 if (pipe(x
->fdinpipe
) < 0) {
538 error("unable to create input pipe");
543 sys_addpollfn(x
->fdpipe
[0],shell_read
,x
);
545 if (!(x
->pid
= fork())) {
547 char* cmd
= getbytes(1024);
548 char* tcmd
= getbytes(1024);
549 strcpy(cmd
,s
->s_name
);
552 for (i
=1;i
<=ac
;i
++) {
553 argv
[i
] = getbytes(255);
554 atom_string(at
,argv
[i
],255);
555 /* post("argument %s",argv[i]); */
560 for (i
=1;i
<=ac
;i
++) {
561 atom_string(at
,tcmd
,255);
568 /* reassign stdout */
569 dup2(x
->fdpipe
[1],1);
570 dup2(x
->fdinpipe
[1],0);
572 /* drop privileges */
574 seteuid(getuid()); /* lose setuid priveliges */
576 post("executing %s",cmd
);
578 // execvp(s->s_name,argv);
582 clock_delay(x
->x_clock
,x
->x_del
);
585 outlet_anything(x
->x_obj
.ob_outlet
, s
, ac
, at
);
590 void shell_free(t_shell
* x
)
592 binbuf_free(x
->x_binbuf
);
595 static void *shell_new(void)
597 t_shell
*x
= (t_shell
*)pd_new(shell_class
);
605 x
->sr_inhead
= x
->sr_intail
= 0;
606 if (!(x
->sr_inbuf
= (char*) malloc(INBUFSIZE
))) bug("t_shell");;
608 x
->x_binbuf
= binbuf_new();
610 outlet_new(&x
->x_obj
, &s_list
);
611 x
->x_done
= outlet_new(&x
->x_obj
, &s_bang
);
612 x
->x_clock
= clock_new(x
, (t_method
) shell_check
);
616 void shell_setup(void)
618 shell_class
= class_new(gensym("shell"), (t_newmethod
)shell_new
,
619 (t_method
)shell_free
,sizeof(t_shell
), 0,0);
620 class_addbang(shell_class
,shell_bang
);
621 class_addanything(shell_class
, shell_anything
);