Mercurial > dropbear
comparison dbutil.c @ 481:357a2e2e9bcc
- Generalise spawn_command function
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Mon, 15 Sep 2008 13:41:18 +0000 |
parents | c216212001fc |
children | 7ad49f34a122 |
comparison
equal
deleted
inserted
replaced
480:c302c7383282 | 481:357a2e2e9bcc |
---|---|
387 | 387 |
388 TRACE(("leave connect_remote: sock %d\n", sock)) | 388 TRACE(("leave connect_remote: sock %d\n", sock)) |
389 return sock; | 389 return sock; |
390 } | 390 } |
391 | 391 |
392 /* Sets up a pipe for a, returning three non-blocking file descriptors | |
393 * and the pid. exec_fn is the function that will actually execute the child process, | |
394 * it will be run after the child has fork()ed, and is passed exec_data. */ | |
395 int spawn_command(void(*exec_fn)(void *user_data), void *exec_data, | |
396 int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) | |
397 { | |
398 int infds[2]; | |
399 int outfds[2]; | |
400 int errfds[2]; | |
401 pid_t pid; | |
402 | |
403 const int FDIN = 0; | |
404 const int FDOUT = 1; | |
405 | |
406 /* redirect stdin/stdout/stderr */ | |
407 if (pipe(infds) != 0) | |
408 return DROPBEAR_FAILURE; | |
409 if (pipe(outfds) != 0) | |
410 return DROPBEAR_FAILURE; | |
411 if (pipe(errfds) != 0) | |
412 return DROPBEAR_FAILURE; | |
413 | |
414 #ifdef __uClinux__ | |
415 pid = vfork(); | |
416 #else | |
417 pid = fork(); | |
418 #endif | |
419 | |
420 if (pid < 0) | |
421 return DROPBEAR_FAILURE; | |
422 | |
423 if (!pid) { | |
424 /* child */ | |
425 | |
426 TRACE(("back to normal sigchld")) | |
427 /* Revert to normal sigchld handling */ | |
428 if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) { | |
429 dropbear_exit("signal() error"); | |
430 } | |
431 | |
432 /* redirect stdin/stdout */ | |
433 | |
434 if ((dup2(infds[FDIN], STDIN_FILENO) < 0) || | |
435 (dup2(outfds[FDOUT], STDOUT_FILENO) < 0) || | |
436 (dup2(errfds[FDOUT], STDERR_FILENO) < 0)) { | |
437 TRACE(("leave noptycommand: error redirecting FDs")) | |
438 dropbear_exit("child dup2() failure"); | |
439 } | |
440 | |
441 close(infds[FDOUT]); | |
442 close(infds[FDIN]); | |
443 close(outfds[FDIN]); | |
444 close(outfds[FDOUT]); | |
445 close(errfds[FDIN]); | |
446 close(errfds[FDOUT]); | |
447 | |
448 exec_fn(exec_data); | |
449 /* not reached */ | |
450 return DROPBEAR_FAILURE; | |
451 } else { | |
452 /* parent */ | |
453 close(infds[FDIN]); | |
454 close(outfds[FDOUT]); | |
455 close(errfds[FDOUT]); | |
456 | |
457 setnonblocking(errfds[FDIN]); | |
458 setnonblocking(outfds[FDIN]); | |
459 setnonblocking(infds[FDOUT]); | |
460 | |
461 *ret_pid = pid; | |
462 *ret_writefd = infds[FDOUT]; | |
463 *ret_readfd = outfds[FDIN]; | |
464 *ret_errfd = errfds[FDIN]; | |
465 return DROPBEAR_SUCCESS; | |
466 } | |
467 } | |
468 | |
392 /* Return a string representation of the socket address passed. The return | 469 /* Return a string representation of the socket address passed. The return |
393 * value is allocated with malloc() */ | 470 * value is allocated with malloc() */ |
394 unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) { | 471 unsigned char * getaddrstring(struct sockaddr_storage* addr, int withport) { |
395 | 472 |
396 char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; | 473 char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; |