1 /* (C) Guenter Geiger <geiger@epy.co.at> */
3 #include "../src/m_pd.h"
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
);