⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 portserver.c

📁 网络端口的服务程序
💻 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 + -