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];