}
/**
- * perform user authentication and execute a command
+ * Perform user authentication and execute a command.
*
- * \param fd The file descriptor to send output to
- * \param peername Identifies the connecting peer.
- *
- * \return EXIT_SUCCESS or EXIT_FAILURE
+ * \param fd The file descriptor to send output to.
+ * \param peername Identifies the connecting peer.
*
* Whenever para_server accepts an incoming tcp connection on
* the port it listens on, it forks and the resulting child
*
* \sa alarm(2), rc4(3), crypt.c, crypt.h
*/
-int handle_connect(int fd, const char *peername)
+__noreturn void handle_connect(int fd, const char *peername)
{
int ret, argc, use_rc4 = 0;
char buf[4096];
PARA_NOTICE_LOG("calling com_%s() for %s@%s\n", cmd->name, u->name,
peername);
ret = cmd->handler(fd, argc, argv);
- if (ret >= 0) {
- ret = EXIT_SUCCESS;
+ if (ret >= 0)
goto out;
- }
err_out:
send_va_buffer(fd, "%s\n", para_strerror(-ret));
net_err:
PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
- ret = EXIT_FAILURE;
out:
free(command);
free(argv);
mmd->events++;
mmd->active_connections--;
mmd_unlock();
- return ret;
+ exit(ret < 0? EXIT_FAILURE : EXIT_SUCCESS);
}
static FILE *logfile;
static int mmd_mutex, mmd_shm_id;
static int signal_pipe;
+static int listen_fd;
/**
* para_server's log function
exit(EXIT_FAILURE);
}
-static unsigned init_network(void)
+static void init_network(void)
{
- int fd, ret = para_listen(AF_UNSPEC, IPPROTO_TCP, conf.port_arg);
+ int ret = para_listen(AF_UNSPEC, IPPROTO_TCP, conf.port_arg);
if (ret < 0)
goto err;
- fd = ret;
- ret = mark_fd_nonblocking(fd);
+ listen_fd = ret;
+ ret = mark_fd_nonblocking(listen_fd);
if (ret < 0)
goto err;
- add_close_on_fork_list(fd); /* child doesn't need the listener */
- return fd;
+ add_close_on_fork_list(listen_fd); /* child doesn't need the listener */
+ return;
err:
PARA_EMERG_LOG("%s\n", para_strerror(-ret));
exit(EXIT_FAILURE);
(unsigned) afs_socket_cookie);
}
-static unsigned server_init(int argc, char **argv)
+static void server_init(int argc, char **argv)
{
/* connector's address information */
- int sockfd;
struct server_cmdline_parser_params params = {
.override = 0,
.initialize = 1,
mmd_lock();
/* init network socket */
PARA_NOTICE_LOG("initializing tcp command socket\n");
- sockfd = init_network();
+ init_network();
PARA_NOTICE_LOG("server init complete\n");
- return sockfd;
}
/*
return ret;
}
+static void command_pre_select(int *max_fileno, fd_set *rfds)
+{
+ para_fd_set(listen_fd, rfds, max_fileno);
+}
+
+static void command_post_select(fd_set *rfds)
+{
+ int new_fd, ret;
+ char *peer_name;
+ pid_t child_pid;
+
+ if (!FD_ISSET(listen_fd, rfds))
+ return;
+ ret = para_accept(listen_fd, NULL, 0);
+ if (ret < 0)
+ goto out;
+ new_fd = ret;
+ peer_name = remote_name(new_fd);
+ PARA_INFO_LOG("got connection from %s, forking\n", peer_name);
+ mmd->num_connects++;
+ mmd->active_connections++;
+ random();
+ child_pid = fork();
+ if (child_pid < 0) {
+ ret = -ERRNO_TO_PARA_ERROR(errno);
+ goto out;
+ }
+ if (child_pid) {
+ close(new_fd);
+ /* parent keeps accepting connections */
+ return;
+ }
+ alarm(ALARM_TIMEOUT);
+ close_listed_fds();
+ para_signal_shutdown();
+ /*
+ * put info on who we are serving into argv[0] to make
+ * client ip visible in top/ps
+ */
+// for (i = argc - 1; i >= 0; i--)
+// memset(argv[i], 0, strlen(argv[i]));
+// sprintf(argv[0], "para_server (serving %s)", peer_name);
+ return handle_connect(new_fd, peer_name);
+out:
+ if (ret < 0)
+ PARA_CRIT_LOG("%s\n", para_strerror(-ret));
+}
+
/**
* the main function of para_server
*
*/
int main(int argc, char *argv[])
{
- /* listen on sock_fd, new connection on new_fd */
- int sockfd, new_fd;
- char *peer_name;
- int i, max_fileno, ret;
- pid_t chld_pid;
+ int max_fileno, ret;
fd_set rfds, wfds;
struct timeval *timeout;
valid_fd_012();
- sockfd = server_init(argc, argv);
+ server_init(argc, argv);
repeat:
FD_ZERO(&rfds);
FD_ZERO(&wfds);
max_fileno = -1;
- /* check socket and signal pipe in any case */
- para_fd_set(sockfd, &rfds, &max_fileno);
+ command_pre_select(&max_fileno, &rfds);
para_fd_set(signal_pipe, &rfds, &max_fileno);
timeout = vss_preselect(&rfds, &wfds, &max_fileno);
server_select(max_fileno + 1, &rfds, &wfds, timeout);
exit(EXIT_FAILURE);
}
}
- if (!FD_ISSET(sockfd, &rfds))
- goto repeat;
-
- new_fd = para_accept(sockfd, NULL, 0);
- if (new_fd < 0)
- goto repeat;
- peer_name = remote_name(new_fd);
- PARA_INFO_LOG("got connection from %s, forking\n", peer_name);
- mmd->num_connects++;
- mmd->active_connections++;
- random();
- chld_pid = fork();
- if (chld_pid < 0) {
- PARA_CRIT_LOG("fork failed\n");
- goto repeat;
- }
- if (chld_pid) {
- close(new_fd);
- /* parent keeps accepting connections */
- goto repeat;
- }
- alarm(ALARM_TIMEOUT);
- close_listed_fds();
- para_signal_shutdown();
- /*
- * put info on who we are serving into argv[0] to make
- * client ip visible in top/ps
- */
- for (i = argc - 1; i >= 0; i--)
- memset(argv[i], 0, strlen(argv[i]));
- sprintf(argv[0], "para_server (serving %s)", peer_name);
- return handle_connect(new_fd, peer_name);
+ command_post_select(&rfds);
+ goto repeat;
}