📄 portserver.c
字号:
/*
Portserver - Use RTERM protocol to serve serial ports over a network
Copyright (C) 1998 Kenn Humborg
This program 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 of the License, or
(at your option) any later version.
This program 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 program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include "connection.h"
#include "init.h"
#include "port.h"
#include "portserver.h"
int main_socket; /* file descriptor for the main control socket */
int max_fd;
fd_set read_fds;
fd_set write_fds;
fd_set excep_fds;
enum {
SERVER_INIT,
SERVER_RUNNING,
SERVER_CLOSING
} server_state;
/* Argv[0] without path */
char *argv0;
/* Forward declarations of private functions */
static int MainLoop(void);
static void sigint_handler(int arg);
static void CleanUp(void);
int main(int argc, char **argv)
{
struct sigaction act;
int retval;
int exit_code;
/* Save argv[0] without path components */
if (strchr(argv[0], '/')) {
argv0 = strrchr(argv[0], '/') + 1;
} else {
argv0 = argv[0];
}
server_state = SERVER_INIT;
openlog("portserver", LOG_PERROR + LOG_PID, LOG_DAEMON);
syslog(LOG_INFO, "Initializing");
Initialize(argc, argv);
act.sa_handler = sigint_handler;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
retval = sigaction(SIGINT, &act, NULL);
if (retval == -1) {
syslog(LOG_ERR, "Error installing signal handler: %m");
exit(1);
}
DumpPortList();
server_state = SERVER_RUNNING;
syslog(LOG_INFO, "Initialization complete");
exit_code = MainLoop();
CleanUp();
exit(exit_code);
}
void SignalShutdown(void)
{
server_state = SERVER_CLOSING;
}
static void sigint_handler(int arg)
{
syslog(LOG_ERR, "SIGINT received, shutting down");
SignalShutdown();
}
static int MainLoop(void)
{
int retval;
fd_set tmp_read_fds;
fd_set tmp_write_fds;
fd_set tmp_excep_fds;
struct Connection *connection;
struct Connection *next_connection;
struct Port *port;
while (server_state == SERVER_RUNNING) {
tmp_read_fds = read_fds;
tmp_write_fds = write_fds;
tmp_excep_fds = excep_fds;
retval = select(max_fd+1, &tmp_read_fds, &tmp_write_fds, &tmp_excep_fds, NULL);
if (retval == -1) {
if (errno == EINTR) {
continue;
}
syslog(LOG_ERR, "Select failed: %m");
return(1);
}
if (FD_ISSET(main_socket, &tmp_excep_fds)) {
fprintf(stderr, "Exception on control socket\n");
}
/* Check for new connections */
if (FD_ISSET(main_socket, &tmp_read_fds)) {
NewConnection();
}
/* Loop through active connections to see if any work has to be done */
connection = connection_list.next;
while (connection != &connection_list) {
/* We need to read the forward link here because the Connection
structure might go away later */
next_connection = connection->next;
if (FD_ISSET(connection->fd, &tmp_excep_fds)) {
fprintf(stderr, "Exception on connection %d\n", connection->fd);
}
if (FD_ISSET(connection->fd, &tmp_read_fds)) {
SocketDataReceived(connection);
}
if (FD_ISSET(connection->fd, &tmp_write_fds)) {
SocketReady(connection);
}
if (connection->flags & CONNECTION_CLOSING) {
/* We don't want to receive any more data */
FD_CLR(connection->fd, &read_fds);
/* If all data is written then we can delete the connection */
if ( ! FD_ISSET(connection->fd, &write_fds)) {
FD_CLR(connection->fd, &write_fds);
FD_CLR(connection->fd, &excep_fds);
close(connection->fd);
RemoveConnection(connection);
DeleteConnection(connection);
GetMaxFD();
}
}
connection = next_connection;
}
/* Loop through active ports to see if any work has to be done */
port = port_list.next;
while (port != &port_list) {
if (port->connection != NULL) {
if (FD_ISSET(port->fd, &tmp_excep_fds)) {
fprintf(stderr, "Exception on port %s\n", port->port_name);
}
if (FD_ISSET(port->fd, &tmp_read_fds)) {
PortDataReceived(port);
}
if (FD_ISSET(port->fd, &tmp_write_fds)) {
PortReady(port);
}
}
port = port->next;
}
}
close(main_socket);
return 0;
}
/* Scan the lists of connections and ports to find the highest value file description */
void GetMaxFD(void)
{
struct Connection *connection;
struct Port *port;
/* Start with the main socket fd */
max_fd = main_socket;
connection = connection_list.next;
while (connection != &connection_list) {
if (connection->fd > max_fd) {
max_fd = connection->fd;
}
connection = connection->next;
}
port = port_list.next;
while (port != &port_list) {
if (port->fd > max_fd) {
max_fd = port->fd;
}
port = port->next;
}
}
static void CleanUp(void)
{
struct Connection *connection;
while (connection_list.next != &connection_list) {
connection = connection_list.next;
if (connection->port != NULL) {
DeassignPort(connection);
}
close(connection->fd);
RemoveConnection(connection);
DeleteConnection(connection);
}
close(main_socket);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -