summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/extra/shell.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/extra/shell.c')
-rw-r--r--apps/plugins/pdbox/PDa/extra/shell.c624
1 files changed, 624 insertions, 0 deletions
diff --git a/apps/plugins/pdbox/PDa/extra/shell.c b/apps/plugins/pdbox/PDa/extra/shell.c
new file mode 100644
index 0000000000..a0b6cef5b5
--- /dev/null
+++ b/apps/plugins/pdbox/PDa/extra/shell.c
@@ -0,0 +1,624 @@
1/* (C) Guenter Geiger <geiger@epy.co.at> */
2
3#include "m_pd.h"
4#ifdef NT
5#pragma warning( disable : 4244 )
6#pragma warning( disable : 4305 )
7#endif
8
9#include <unistd.h>
10#include <stdlib.h>
11#include <string.h>
12#include <stdio.h>
13#include <sys/types.h>
14#include <sys/wait.h>
15#include <signal.h>
16#include <sched.h>
17
18void sys_rmpollfn(int fd);
19void sys_addpollfn(int fd, void* fn, void *ptr);
20
21/* ------------------------ shell ----------------------------- */
22
23#define INBUFSIZE 1024
24
25static t_class *shell_class;
26
27
28static void drop_priority(void)
29{
30#ifdef _POSIX_PRIORITY_SCHEDULING
31 struct sched_param par;
32 int p1 ,p2, p3;
33 par.sched_priority = 0;
34 sched_setscheduler(0,SCHED_OTHER,&par);
35#endif
36}
37
38
39typedef struct _shell
40{
41 t_object x_obj;
42 int x_echo;
43 char *sr_inbuf;
44 int sr_inhead;
45 int sr_intail;
46 void* x_binbuf;
47 int fdpipe[2];
48 int fdinpipe[2];
49 int pid;
50 int x_del;
51 t_outlet* x_done;
52 t_clock* x_clock;
53} t_shell;
54
55static int shell_pid;
56
57
58void shell_cleanup(t_shell* x)
59{
60 sys_rmpollfn(x->fdpipe[0]);
61
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]);
66
67 x->fdpipe[0] = -1;
68 x->fdpipe[1] = -1;
69 x->fdinpipe[0] = -1;
70 x->fdinpipe[1] = -1;
71 clock_unset(x->x_clock);
72}
73
74void shell_check(t_shell* x)
75{
76 int ret;
77 int status;
78 ret = waitpid(x->pid,&status,WNOHANG);
79 if (ret == x->pid) {
80 shell_cleanup(x);
81 if (WIFEXITED(status)) {
82 outlet_float(x->x_done,WEXITSTATUS(status));
83 }
84 else outlet_float(x->x_done,0);
85 }
86 else {
87 if (x->x_del < 100) x->x_del+=2; /* increment poll times */
88 clock_delay(x->x_clock,x->x_del);
89 }
90}
91
92
93void shell_bang(t_shell *x)
94{
95 post("bang");
96}
97
98/* snippet from pd's code */
99static void shell_doit(void *z, t_binbuf *b)
100{
101 t_shell *x = (t_shell *)z;
102 int msg, natom = binbuf_getnatom(b);
103 t_atom *at = binbuf_getvec(b);
104
105 for (msg = 0; msg < natom;)
106 {
107 int emsg;
108 for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
109 && at[emsg].a_type != A_SEMI; emsg++)
110 ;
111 if (emsg > msg)
112 {
113 int i;
114 for (i = msg; i < emsg; i++)
115 if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)
116 {
117 pd_error(x, "netreceive: got dollar sign in message");
118 goto nodice;
119 }
120 if (at[msg].a_type == A_FLOAT)
121 {
122 if (emsg > msg + 1)
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);
125 }
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);
129 }
130 nodice:
131 msg = emsg + 1;
132 }
133}
134
135
136void shell_read(t_shell *x, int fd)
137{
138 char buf[INBUFSIZE];
139 t_binbuf* bbuf = binbuf_new();
140 int i;
141 int readto =
142 (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1);
143 int ret;
144
145 ret = read(fd, buf,INBUFSIZE-1);
146 buf[ret] = '\0';
147
148 for (i=0;i<ret;i++)
149 if (buf[i] == '\n') buf[i] = ';';
150 if (ret < 0)
151 {
152 error("shell: pipe read error");
153 sys_rmpollfn(fd);
154 x->fdpipe[0] = -1;
155 close(fd);
156 return;
157 }
158 else if (ret == 0)
159 {
160 post("EOF on socket %d\n", fd);
161 sys_rmpollfn(fd);
162 x->fdpipe[0] = -1;
163 close(fd);
164 return;
165 }
166 else
167 {
168 int natom;
169 t_atom *at;
170 binbuf_text(bbuf, buf, strlen(buf));
171
172 natom = binbuf_getnatom(bbuf);
173 at = binbuf_getvec(bbuf);
174 shell_doit(x,bbuf);
175 }
176 binbuf_free(bbuf);
177}
178
179
180static void shell_send(t_shell *x, t_symbol *s,int ac, t_atom *at)
181{
182 int i;
183 char tmp[MAXPDSTRING];
184 int size = 0;
185
186 if (x->fdinpipe[0] == -1) return; /* nothing to send to */
187
188 for (i=0;i<ac;i++) {
189 atom_string(at,tmp+size,MAXPDSTRING - size);
190 at++;
191 size=strlen(tmp);
192 tmp[size++] = ' ';
193 }
194 tmp[size-1] = '\0';
195 post("sending %s",tmp);
196 write(x->fdinpipe[0],tmp,strlen(tmp));
197}
198
199static void shell_anything(t_shell *x, t_symbol *s, int ac, t_atom *at)
200{
201 int i;
202 char* argv[20];
203 t_symbol* sym;
204
205 if (!strcmp(s->s_name,"send")) {
206 post("send");
207 shell_send(x,s,ac,at);
208 return;
209 }
210
211 argv[0] = s->s_name;
212
213 if (x->fdpipe[0] != -1) {
214 post("shell: old process still running");
215 kill(x->pid,SIGKILL);
216 shell_cleanup(x);
217 }
218
219
220 if (pipe(x->fdpipe) < 0) {
221 error("unable to create pipe");
222 return;
223 }
224
225 if (pipe(x->fdinpipe) < 0) {
226 error("unable to create input pipe");
227 return;
228 }
229
230
231 sys_addpollfn(x->fdpipe[0],shell_read,x);
232
233 if (!(x->pid = fork())) {
234 int status;
235 char* cmd = getbytes(1024);
236 char* tcmd = getbytes(1024);
237 strcpy(cmd,s->s_name);
238
239#if 0
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]); */
244 at++;
245 }
246 argv[i] = 0;
247#endif
248 for (i=1;i<=ac;i++) {
249 atom_string(at,tcmd,255);
250 strcat(cmd," ");
251 strcat(cmd,tcmd);
252 at++;
253 }
254
255
256 /* reassign stdout */
257 dup2(x->fdpipe[1],1);
258 dup2(x->fdinpipe[1],0);
259
260 /* drop privileges */
261 drop_priority();
262 seteuid(getuid()); /* lose setuid priveliges */
263
264 post("executing %s",cmd);
265 system(cmd);
266// execvp(s->s_name,argv);
267 exit(0);
268 }
269 x->x_del = 4;
270 clock_delay(x->x_clock,x->x_del);
271
272 if (x->x_echo)
273 outlet_anything(x->x_obj.ob_outlet, s, ac, at);
274}
275
276
277
278void shell_free(t_shell* x)
279{
280 binbuf_free(x->x_binbuf);
281}
282
283static void *shell_new(void)
284{
285 t_shell *x = (t_shell *)pd_new(shell_class);
286
287 x->x_echo = 0;
288 x->fdpipe[0] = -1;
289 x->fdpipe[1] = -1;
290 x->fdinpipe[0] = -1;
291 x->fdinpipe[1] = -1;
292
293 x->sr_inhead = x->sr_intail = 0;
294 if (!(x->sr_inbuf = (char*) malloc(INBUFSIZE))) bug("t_shell");;
295
296 x->x_binbuf = binbuf_new();
297
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);
301 return (x);
302}
303
304void shell_setup(void)
305{
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);
310}
311
312
313/* (C) Guenter Geiger <geiger@epy.co.at> */
314
315#include "m_pd.h"
316#ifdef NT
317#pragma warning( disable : 4244 )
318#pragma warning( disable : 4305 )
319#endif
320
321#include <unistd.h>
322#include <stdlib.h>
323#include <string.h>
324#include <stdio.h>
325#include <sys/types.h>
326#include <sys/wait.h>
327#include <signal.h>
328#include <sched.h>
329
330void sys_rmpollfn(int fd);
331void sys_addpollfn(int fd, void* fn, void *ptr);
332
333/* ------------------------ shell ----------------------------- */
334
335#define INBUFSIZE 1024
336
337static t_class *shell_class;
338
339
340static void drop_priority(void)
341{
342#ifdef _POSIX_PRIORITY_SCHEDULING
343 struct sched_param par;
344 int p1 ,p2, p3;
345 par.sched_priority = 0;
346 sched_setscheduler(0,SCHED_OTHER,&par);
347#endif
348}
349
350
351typedef struct _shell
352{
353 t_object x_obj;
354 int x_echo;
355 char *sr_inbuf;
356 int sr_inhead;
357 int sr_intail;
358 void* x_binbuf;
359 int fdpipe[2];
360 int fdinpipe[2];
361 int pid;
362 int x_del;
363 t_outlet* x_done;
364 t_clock* x_clock;
365} t_shell;
366
367static int shell_pid;
368
369
370void shell_cleanup(t_shell* x)
371{
372 sys_rmpollfn(x->fdpipe[0]);
373
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]);
378
379 x->fdpipe[0] = -1;
380 x->fdpipe[1] = -1;
381 x->fdinpipe[0] = -1;
382 x->fdinpipe[1] = -1;
383 clock_unset(x->x_clock);
384}
385
386void shell_check(t_shell* x)
387{
388 int ret;
389 int status;
390 ret = waitpid(x->pid,&status,WNOHANG);
391 if (ret == x->pid) {
392 shell_cleanup(x);
393 if (WIFEXITED(status)) {
394 outlet_float(x->x_done,WEXITSTATUS(status));
395 }
396 else outlet_float(x->x_done,0);
397 }
398 else {
399 if (x->x_del < 100) x->x_del+=2; /* increment poll times */
400 clock_delay(x->x_clock,x->x_del);
401 }
402}
403
404
405void shell_bang(t_shell *x)
406{
407 post("bang");
408}
409
410/* snippet from pd's code */
411static void shell_doit(void *z, t_binbuf *b)
412{
413 t_shell *x = (t_shell *)z;
414 int msg, natom = binbuf_getnatom(b);
415 t_atom *at = binbuf_getvec(b);
416
417 for (msg = 0; msg < natom;)
418 {
419 int emsg;
420 for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA
421 && at[emsg].a_type != A_SEMI; emsg++)
422 ;
423 if (emsg > msg)
424 {
425 int i;
426 for (i = msg; i < emsg; i++)
427 if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM)
428 {
429 pd_error(x, "netreceive: got dollar sign in message");
430 goto nodice;
431 }
432 if (at[msg].a_type == A_FLOAT)
433 {
434 if (emsg > msg + 1)
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);
437 }
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);
441 }
442 nodice:
443 msg = emsg + 1;
444 }
445}
446
447
448void shell_read(t_shell *x, int fd)
449{
450 char buf[INBUFSIZE];
451 t_binbuf* bbuf = binbuf_new();
452 int i;
453 int readto =
454 (x->sr_inhead >= x->sr_intail ? INBUFSIZE : x->sr_intail-1);
455 int ret;
456
457 ret = read(fd, buf,INBUFSIZE-1);
458 buf[ret] = '\0';
459
460 for (i=0;i<ret;i++)
461 if (buf[i] == '\n') buf[i] = ';';
462 if (ret < 0)
463 {
464 error("shell: pipe read error");
465 sys_rmpollfn(fd);
466 x->fdpipe[0] = -1;
467 close(fd);
468 return;
469 }
470 else if (ret == 0)
471 {
472 post("EOF on socket %d\n", fd);
473 sys_rmpollfn(fd);
474 x->fdpipe[0] = -1;
475 close(fd);
476 return;
477 }
478 else
479 {
480 int natom;
481 t_atom *at;
482 binbuf_text(bbuf, buf, strlen(buf));
483
484 natom = binbuf_getnatom(bbuf);
485 at = binbuf_getvec(bbuf);
486 shell_doit(x,bbuf);
487 }
488 binbuf_free(bbuf);
489}
490
491
492static void shell_send(t_shell *x, t_symbol *s,int ac, t_atom *at)
493{
494 int i;
495 char tmp[MAXPDSTRING];
496 int size = 0;
497
498 if (x->fdinpipe[0] == -1) return; /* nothing to send to */
499
500 for (i=0;i<ac;i++) {
501 atom_string(at,tmp+size,MAXPDSTRING - size);
502 at++;
503 size=strlen(tmp);
504 tmp[size++] = ' ';
505 }
506 tmp[size-1] = '\0';
507 post("sending %s",tmp);
508 write(x->fdinpipe[0],tmp,strlen(tmp));
509}
510
511static void shell_anything(t_shell *x, t_symbol *s, int ac, t_atom *at)
512{
513 int i;
514 char* argv[20];
515 t_symbol* sym;
516
517 if (!strcmp(s->s_name,"send")) {
518 post("send");
519 shell_send(x,s,ac,at);
520 return;
521 }
522
523 argv[0] = s->s_name;
524
525 if (x->fdpipe[0] != -1) {
526 post("shell: old process still running");
527 kill(x->pid,SIGKILL);
528 shell_cleanup(x);
529 }
530
531
532 if (pipe(x->fdpipe) < 0) {
533 error("unable to create pipe");
534 return;
535 }
536
537 if (pipe(x->fdinpipe) < 0) {
538 error("unable to create input pipe");
539 return;
540 }
541
542
543 sys_addpollfn(x->fdpipe[0],shell_read,x);
544
545 if (!(x->pid = fork())) {
546 int status;
547 char* cmd = getbytes(1024);
548 char* tcmd = getbytes(1024);
549 strcpy(cmd,s->s_name);
550
551#if 0
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]); */
556 at++;
557 }
558 argv[i] = 0;
559#endif
560 for (i=1;i<=ac;i++) {
561 atom_string(at,tcmd,255);
562 strcat(cmd," ");
563 strcat(cmd,tcmd);
564 at++;
565 }
566
567
568 /* reassign stdout */
569 dup2(x->fdpipe[1],1);
570 dup2(x->fdinpipe[1],0);
571
572 /* drop privileges */
573 drop_priority();
574 seteuid(getuid()); /* lose setuid priveliges */
575
576 post("executing %s",cmd);
577 system(cmd);
578// execvp(s->s_name,argv);
579 exit(0);
580 }
581 x->x_del = 4;
582 clock_delay(x->x_clock,x->x_del);
583
584 if (x->x_echo)
585 outlet_anything(x->x_obj.ob_outlet, s, ac, at);
586}
587
588
589
590void shell_free(t_shell* x)
591{
592 binbuf_free(x->x_binbuf);
593}
594
595static void *shell_new(void)
596{
597 t_shell *x = (t_shell *)pd_new(shell_class);
598
599 x->x_echo = 0;
600 x->fdpipe[0] = -1;
601 x->fdpipe[1] = -1;
602 x->fdinpipe[0] = -1;
603 x->fdinpipe[1] = -1;
604
605 x->sr_inhead = x->sr_intail = 0;
606 if (!(x->sr_inbuf = (char*) malloc(INBUFSIZE))) bug("t_shell");;
607
608 x->x_binbuf = binbuf_new();
609
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);
613 return (x);
614}
615
616void shell_setup(void)
617{
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);
622}
623
624