📄 passthrough.c
字号:
/* * passthrough.c - pass through connections to processes * * Copyright (C) 2001 Stefan Jahn <stefan@lkcc.org> * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this package; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * $Id: passthrough.c,v 1.7 2001/09/13 13:28:54 ela Exp $ * */#if HAVE_CONFIG_H# include <config.h>#endif#define _GNU_SOURCE#include <assert.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <sys/stat.h>#if HAVE_UNISTD_H# include <unistd.h>#endif#if !defined(__MINGW32__) && !defined(__CYGWIN__)extern char ** environ;#endif#ifdef __MINGW32__# include <winsock2.h># include <io.h># include <shellapi.h>#endif#include "libserveez/alloc.h"#include "libserveez/util.h"#include "libserveez/snprintf.h"#include "libserveez/socket.h"#include "libserveez/core.h"#include "libserveez/server-core.h"#include "libserveez/pipe-socket.h"#include "libserveez/passthrough.h"/* * This routine start a new program specified by @var{bin} passing the * socket descriptor in the socket structure @var{sock} to stdin and stdout. * The arguments and the environment of the new process can be passed by * @var{argv} and @var{envp}. The argument @var{flag} specifies the method * used to passthrough the connection. It can be either * @code{SVZ_PROCESS_FORK} (pass pipes or socket directly through * @code{fork()} and @code{exec()}) or @code{SVZ_PROCESS_SHUFFLE} (pass * socket transactions via a pair of pipes). */intsvz_sock_process (svz_socket_t *sock, char *bin, char **argv, svz_envblock_t *envp, int flag){ HANDLE in, out; char *dir = NULL, *p, *app, *file; int len, ret = -1; if (sock == NULL || bin == NULL) return -1; /* Setup descriptors depending on the type of socket structure. */ in = out = (HANDLE) sock->sock_desc; if (sock->flags & SOCK_FLAG_PIPE) { in = sock->pipe_desc[READ]; out = sock->pipe_desc[WRITE]; } /* Check executable. */ if (svz_process_check_executable (bin, &app) < 0) return -1; /* Extract the directory part of the binary. */ p = bin + strlen (bin) - 1; while (p > bin && *p != '/' && *p != '\\') p--; if (p > bin) { file = svz_strdup (p + 1); len = p - bin; dir = svz_malloc (len + 1); memcpy (dir, bin, len); dir[len] = '\0'; } else { file = svz_strdup (bin); } /* Depending on the given flag use different methods to passthrough the connection. */ switch (flag) { case SVZ_PROCESS_FORK: ret = svz_process_fork (file, dir, in, out, argv, envp, app); break; case SVZ_PROCESS_SHUFFLE: ret = svz_process_shuffle (sock, file, dir, (SOCKET) in, argv, envp, app); break; default: svz_log (LOG_ERROR, "invalid flag (%d)\n", flag); ret = -1; break; } svz_free (file); svz_free (dir); return ret;}intsvz_process_send_pipe (svz_socket_t *sock){ return -1;}intsvz_process_recv_pipe (svz_socket_t *sock){ return -1;}intsvz_process_create_child (char *file, char *dir, HANDLE in, HANDLE out, char **argv, svz_envblock_t *envp, char *app){ /* Change directory, make descriptors blocking, setup environment, set permissions, duplicate descriptors and finally execute the program. */#ifndef __MINGW32__ if (chdir (dir) < 0) { svz_log (LOG_ERROR, "chdir (%s): %s\n", dir, SYS_ERROR); return -1; } if (svz_fd_block (out) < 0 || svz_fd_block (in) < 0) return -1; if (dup2 (out, 1) != 1 || dup2 (in, 0) != 0) { svz_log (LOG_ERROR, "unable to redirect: %s\n", SYS_ERROR); return -1; } if (svz_process_check_access (file) < 0) return -1; /* Check the environment and create a default one if necessary. */ if (envp == NULL) { envp = svz_envblock_create (); svz_envblock_default (envp); } /* Execute the file itself here overwriting the current process. */ argv[0] = file; if (execve (file, argv, svz_envblock_get (envp)) == -1) { svz_log (LOG_ERROR, "execve: %s\n", SYS_ERROR); return -1; } return getpid ();#else /* __MINGW32__ */ STARTUPINFO startup_info; PROCESS_INFORMATION process_info; char *savedir, *application; int pid, n; /* Clean the Startup-Info, use the stdio handles, and store the pipe handles there if necessary. */ memset (&startup_info, 0, sizeof (startup_info)); startup_info.cb = sizeof (startup_info); startup_info.dwFlags = STARTF_USESTDHANDLES; startup_info.hStdOutput = out; startup_info.hStdInput = in; /* Save current directory and change into application's. */ savedir = svz_getcwd (); if (chdir (dir) < 0) { svz_log (LOG_ERROR, "getcwd: %s\n", SYS_ERROR); svz_free (savedir); return -1; } /* Check the access to the file. */ if (svz_process_check_access (file) < 0) { chdir (savedir); svz_free (savedir); return -1; } /* Create sane environment. */ if (envp == NULL) { envp = svz_envblock_create (); svz_envblock_default (envp); } /* Concatenate application name. */ if (app != NULL) { application = svz_malloc (strlen (file) + strlen (app) + 2); sprintf (application, "%s %s", app, file); } else application = svz_strdup (file); /* Append program arguments. */ for (n = 1; argv[n] != NULL; n++) { application = svz_realloc (application, strlen (application) + strlen (argv[n]) + 2); strcat (application, " "); strcat (application, argv[n]); } if (!CreateProcess (NULL, /* application name */ application, /* command line */ NULL, /* process attributes */ NULL, /* thread attributes */ TRUE, /* inherit handles */ DETACHED_PROCESS, /* creation flags */ svz_envblock_get (envp), /* environment */ NULL, /* current directory */ &startup_info, &process_info)) { svz_log (LOG_ERROR, "CreateProcess (%s): %s\n", application, SYS_ERROR); chdir (savedir); svz_free (savedir); svz_free (application); return -1; } chdir (savedir); svz_free (savedir); svz_free (application); pid = (int) process_info.hProcess;#ifdef ENABLE_DEBUG svz_log (LOG_DEBUG, "process `%s' got pid 0x%08X\n", file, process_info.dwProcessId);#endif return pid;#endif /* __MINGW32__ */}/* * Create two pairs of pipes in order to passthrough the transactions of the * given socket descriptor @var{socket}. */intsvz_process_shuffle (svz_socket_t *sock, char *file, char *dir, SOCKET socket, char **argv, svz_envblock_t *envp, char *app){ HANDLE process_to_serveez[2]; HANDLE serveez_to_process[2]; HANDLE in, out; svz_socket_t *xsock; int pid; /* create the pairs of pipes for the process */ if (svz_pipe_create_pair (process_to_serveez) == -1) return -1; if (svz_pipe_create_pair (serveez_to_process) == -1) return -1; /* create yet another socket structure */ if ((xsock = svz_sock_create (socket)) == NULL) { svz_log (LOG_ERROR, "failed to create passthrough socket\n"); return -1; } /* prepare everything for the pipe handling */ sock->pipe_desc[WRITE] = serveez_to_process[WRITE]; sock->flags |= SOCK_FLAG_SEND_PIPE; sock->write_socket = svz_process_send_pipe; svz_fd_cloexec ((int) serveez_to_process[WRITE]); xsock->pipe_desc[READ] = process_to_serveez[READ]; xsock->flags |= SOCK_FLAG_RECV_PIPE; xsock->read_socket = svz_process_recv_pipe; svz_fd_cloexec ((int) process_to_serveez[READ]); if (svz_sock_enqueue (xsock) < 0) return -1; in = serveez_to_process[READ]; out = process_to_serveez[WRITE];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -