📄 pipe-socket.c
字号:
#ifdef __MINGW32__/* Print text representation of given overlapped I/O structure. */static voidsvz_pipe_overlap (LPOVERLAPPED overlap){ if (overlap) { printf ("Internal: %ld (0x%08lX), InternalHigh: %ld (0x%08lX)\n" "Offset: %ld (0x%08lX), OffsetHigh: %ld (0x%08lX)\n" "Event: %p\n", overlap->Internal, overlap->Internal, overlap->InternalHigh, overlap->InternalHigh, overlap->Offset, overlap->Offset, overlap->OffsetHigh, overlap->OffsetHigh, overlap->hEvent); }}#endif /* __MINGW32__ *//* * The @code{svz_pipe_read_socket()} function reads as much data as * available on a readable pipe descriptor or handle on Win32. Return * a non-zero value on errors. */intsvz_pipe_read_socket (svz_socket_t *sock){ int num_read, do_read; /* Read as much space is left in the receive buffer and return * zero if there is no more space. */ do_read = sock->recv_buffer_size - sock->recv_buffer_fill; if (do_read <= 0) { svz_log (LOG_ERROR, "receive buffer overflow on pipe %d\n", sock->pipe_desc[READ]); if (sock->kicked_socket) sock->kicked_socket (sock, 0); return -1; }#ifdef __MINGW32__ /* Named pipes in Win32 cannot transfer more than 64KB at once. */ if (do_read > PIPE_MAX_READ) do_read = PIPE_MAX_READ; /* Use the PeekNamedPipe() call if there is no overlapped I/O in order to make the following ReadFile() non-blocking. */ if (sock->overlap[READ] == NULL) { /* Check how many bytes could have been read from the pipe without really reading them. */ if (!PeekNamedPipe (sock->pipe_desc[READ], NULL, 0, NULL, (DWORD *) &num_read, NULL)) { svz_log (LOG_ERROR, "pipe: PeekNamedPipe: %s\n", SYS_ERROR); return -1; } /* Leave this function if there is no data within the pipe. */ if (num_read <= 0) return 0; /* Adjust number of bytes to read. */ if (do_read > num_read) do_read = num_read; } /* Try to get the result of the last ReadFile(). */ if (sock->flags & SOCK_FLAG_READING) { if (!GetOverlappedResult (sock->pipe_desc[READ], sock->overlap[READ], (DWORD *) &num_read, FALSE)) { if (GetLastError () != ERROR_IO_INCOMPLETE) { svz_log (LOG_ERROR, "pipe: GetOverlappedResult: %s\n", SYS_ERROR); return -1; } return 0; } /* Schedule the pipe for the ReadFile() call again. */ else { sock->recv_pending = 0; sock->flags &= ~SOCK_FLAG_READING; } } /* Really read from the pipe. */ else if (!ReadFile (sock->pipe_desc[READ], sock->recv_buffer + sock->recv_buffer_fill, do_read, (DWORD *) &num_read, sock->overlap[READ])) { if (GetLastError () != ERROR_IO_PENDING) { svz_log (LOG_ERROR, "pipe: ReadFile: %s\n", SYS_ERROR); return -1; } /* Schedule the pipe for the GetOverlappedResult() call. */ sock->recv_pending = do_read; sock->flags |= SOCK_FLAG_READING; return 0; }#else /* not __MINGW32__ */ if ((num_read = read (sock->pipe_desc[READ], sock->recv_buffer + sock->recv_buffer_fill, do_read)) == -1) { svz_log (LOG_ERROR, "pipe: read: %s\n", SYS_ERROR); if (errno == EAGAIN) return 0; return -1; }#endif /* not __MINGW32__ */ /* Some data has been read from the pipe. */ if (num_read > 0) { sock->last_recv = time (NULL);#if ENABLE_FLOOD_PROTECTION if (svz_sock_flood_protect (sock, num_read)) { svz_log (LOG_ERROR, "kicked pipe %d (flood)\n", sock->pipe_desc[READ]); return -1; }#endif /* ENABLE_FLOOD_PROTECTION */ sock->recv_buffer_fill += num_read; if (sock->check_request) if (sock->check_request (sock)) return -1; }#ifndef __MINGW32__ /* The pipe was selected but there is no data. */ else { svz_log (LOG_ERROR, "pipe: read: no data on pipe %d\n", sock->pipe_desc[READ]); return -1; }#endif /* !__MINGW32__ */ return 0;}/* * This @code{svz_pipe_write_socket()} function writes as much data as * possible into a writable pipe descriptor. It returns a non-zero value * on errors. */intsvz_pipe_write_socket (svz_socket_t *sock){ int num_written, do_write; /* Write as many bytes as possible, remember how many were actually sent. */ do_write = sock->send_buffer_fill;#ifdef __MINGW32__ /* Named pipes in Win32 cannot transfer more than 64KB at once. */ if (do_write > PIPE_MAX_WRITE) do_write = PIPE_MAX_WRITE; /* Data bytes have been stored in system's cache. Now we are checking if pending write operation has been completed. */ if (sock->flags & SOCK_FLAG_WRITING) { if (!GetOverlappedResult (sock->pipe_desc[WRITE], sock->overlap[WRITE], (DWORD *) &num_written, FALSE)) { if (GetLastError () != ERROR_IO_INCOMPLETE) { svz_log (LOG_ERROR, "pipe: GetOverlappedResult: %s\n", SYS_ERROR); return -1; } return 0; } /* Reschedule the pipe descriptor for yet another WriteFile(). */ else { sock->send_pending -= num_written; sock->flags &= ~SOCK_FLAG_WRITING; if (sock->send_pending != 0) { svz_log (LOG_ERROR, "pipe: %d pending send bytes left\n", sock->send_pending); } } } /* Really write to the pipe. */ else if (!WriteFile (sock->pipe_desc[WRITE], sock->send_buffer, do_write, (DWORD *) &num_written, sock->overlap[WRITE])) { if (GetLastError () != ERROR_IO_PENDING) { svz_log (LOG_ERROR, "pipe: WriteFile: %s\n", SYS_ERROR); return -1; } sock->send_pending += do_write; sock->flags |= SOCK_FLAG_WRITING; return 0; }#else /* not __MINGW32__ */ if ((num_written = write (sock->pipe_desc[WRITE], sock->send_buffer, do_write)) == -1) { svz_log (LOG_ERROR, "pipe: write: %s\n", SYS_ERROR); if (svz_errno == SOCK_UNAVAILABLE) { sock->unavailable = time (NULL) + RELAX_FD_TIME; num_written = 0; } }#endif /* not __MINGW32__ */ /* Some data has been successfully written to the pipe. */ if (num_written > 0) { sock->last_send = time (NULL); if (sock->send_buffer_fill > num_written) { memmove (sock->send_buffer, sock->send_buffer + num_written, sock->send_buffer_fill - num_written); } sock->send_buffer_fill -= num_written; } return (num_written < 0) ? -1 : 0;}/* * Create a socket structure containing both the pipe descriptors * @var{recv_fd} and @var{send_fd}. Return @code{NULL} on errors. */svz_socket_t *svz_pipe_create (HANDLE recv_fd, HANDLE send_fd){ svz_socket_t *sock;#ifndef __MINGW32__ /* Try to set to non-blocking I/O. */ if (svz_fd_nonblock ((int) recv_fd) != 0) return NULL; if (svz_fd_nonblock ((int) send_fd) != 0) return NULL;#endif /* __MINGW32__ */ /* Do not inherit these pipes */ if (svz_fd_cloexec ((int) recv_fd) != 0) return NULL; if (svz_fd_cloexec ((int) send_fd) != 0) return NULL; if ((sock = svz_sock_alloc ()) != NULL) { svz_sock_unique_id (sock); sock->pipe_desc[READ] = recv_fd; sock->pipe_desc[WRITE] = send_fd; sock->flags |= (SOCK_FLAG_PIPE | SOCK_FLAG_CONNECTED); } return sock;}/* * Create a (non blocking) pair of pipes. This differs in Win32 and * Unices. Return a non-zero value on errors. */intsvz_pipe_create_pair (HANDLE pipe_desc[2]){#ifdef __MINGW32__ SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES), NULL, /* NULL security descriptor */ TRUE }; /* Inherit handles */ if (!CreatePipe (&pipe_desc[READ], &pipe_desc[WRITE], &sa, 0)) { svz_log (LOG_ERROR, "CreatePipe: %s\n", SYS_ERROR); return -1; }#else /* not __MINGW32__ */ if (pipe (pipe_desc) == -1) { svz_log (LOG_ERROR, "pipe: %s\n", SYS_ERROR); return -1; } /* * FIXME: Maybe cgi pipes MUST be blocking for *very* fast * outputs because thay cannot handle the EAGAIN error. */ /* Make both ends of the pipe non-blocking. */ if (svz_fd_nonblock (pipe_desc[READ]) != 0) return -1; if (svz_fd_nonblock (pipe_desc[WRITE]) != 0) return -1;#endif /* not __MINGW32__ */ return 0;}#ifndef __MINGW32__#if HAVE_SETEUID# define SETUID(id) seteuid (id)# define SETUID_FUNC "seteuid"#else# define SETUID(id) setuid (id)# define SETUID_FUNC "setuid"#endif#if HAVE_SETEGID# define SETGID(id) setegid (id)# define SETGID_FUNC "setegid"#else# define SETGID(id) setgid (id)# define SETGID_FUNC "setgid"#endif#if HAVE_GETEUID# define GETUID() geteuid ()#else# define GETUID() getuid ()#endif#if HAVE_GETEGID# define GETGID() getegid ()#else# define GETGID() getgid ()#endif/* * The following function saves the user and group permissions of the current * process. It stores the values for the umask, user id and group id in * @var{mask}, @var{uid} and @var{gid}. */static voidsvz_pipe_save_state (unsigned int *mask, unsigned int *uid, unsigned int *gid){ *mask = umask (0); *uid = GETUID (); *gid = GETGID ();}/* * This function sets the umask @var{mask}, the user id @var{uid} and the * group id @var{gid}. Returns zero on success, non-zero otherwise. */static intsvz_pipe_set_state (unsigned int mask, unsigned int uid, unsigned int gid){ umask (mask); if (SETUID (uid) < 0) { svz_log (LOG_ERROR, "pipe: " SETUID_FUNC " (%d): %s\n", uid, SYS_ERROR); return -1; } if (SETGID (gid) < 0) { svz_log (LOG_ERROR, "pipe: " SETGID_FUNC " (%d): %s\n", gid, SYS_ERROR); return -1; } return 0;}/* * Modify the current permissions state as specified by @var{pipe}. Returns
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -