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

📄 command.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 <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>

#include "command.h"
#include "connection.h"
#include "port.h"
#include "portserver.h"
#include "status.h"

#define BEGIN_CMD_HANDLERS \
   if (FALSE) { 

#define HANDLE_CMD(cmd) \
   } else if (strcasecmp(#cmd, argv[0]) == 0) {         \
      status = Command_##cmd(connection, argc, argv, &response);

#define END_CMD_HANDLERS   \
   } else {                \
      status = ERR_BADCMD; \
   }

#define IMPL_CMD(cmd) \
   STATUS Command_##cmd (struct Connection *connection, \
                        int argc, char **argv, char **response)


static int MakeArgv(char *command, char **argv, int max_args);

/* This isn't the most efficient way of doing this... but it'll
   do for now */
STATUS AddToResponse(char **response, char *text)
{
   int new_length;
   char *new_response;

   if (*response == NULL) {
      *response = strdup(text);
      if (*response == NULL) {
         return ERR_NOMEMORY;
      }
   } else {
      new_length = strlen(*response) + strlen(text);

      new_response = realloc(*response, new_length + 1);
      if (new_response == NULL) {
         free(*response);
         *response = NULL;
         return ERR_NOMEMORY;
      }

      *response = new_response;
      strcat(*response, text);
   }

   return SUCCESS;
}

IMPL_CMD(open)
{
   struct Port *port;

   if (argc != 2) {
      return ERR_INVARG;
   }

   if (connection->port != NULL) {
      DeassignPort(connection);
   }

   port = FindPort(argv[1]);
   if (port == NULL) {
      return ERR_NOSUCHPORT;
   }

   return AssignPort(connection, port);
}



IMPL_CMD(quit)
{
   SignalShutdown();

   /* The response won't make it out anyway... */
   return SUCCESS;
}

IMPL_CMD(dump)
{
   DumpPortList();
   return SUCCESS;
}

IMPL_CMD(close)
{
   if (connection->port != NULL) {
      DeassignPort(connection);
      return SUCCESS;
   } else {
      return ERR_FAILURE;
   }
}

IMPL_CMD(disc)
{
   if (connection->port != NULL) {
      DeassignPort(connection);
   }

   connection->flags |= CONNECTION_CLOSING;

   return SUCCESS;
}

IMPL_CMD(echo)
{
   int i;
   int len;
   char *echo;

   len = 0;
   for (i=0; i<argc; i++) {
      len += strlen(argv[i]);
      len++;
   }

   echo = malloc(len+1);
   if (echo != NULL) {
      echo[0] = '\0';
      for (i=0; i<argc; i++) {
         strcat(echo, argv[i]);
         strcat(echo, " ");
      }
      *response = echo;
   }

   return SUCCESS;
}


IMPL_CMD(speed)
{
   int speed;
   int retval;

   if (argc != 2) {
      return ERR_INVARG;
   }

   retval = sscanf(argv[1], "%d", &speed);
   if (retval != 1) {
      return ERR_INVARG;
   }

   if (connection->port == NULL) {
      return ERR_BADCMD;
   }

   return PortSetSpeed(connection->port, speed);
}

IMPL_CMD(connections)
{
   struct Connection *conn;
   struct Port *port;
   char buf[1024];
   STATUS status;

   status = AddToResponse(response, "user,portname,device,description\n");
   if (IS_FAILURE(status)) {
      return status;
   }

   conn = connection_list.next;
   while (conn != &connection_list) {

      port = conn->port;
      if (port != NULL) {
         snprintf(buf, sizeof(buf), 
                    "%c,%s@%s,%s,%s,%s\n", (conn == connection) ? '*' : '-',
                    conn->remote_user, conn->remote_host,
                    port->port_name, port->device_name,
                    (port->description == NULL) ? "" : port->description);
      } else {
         snprintf(buf, sizeof(buf), 
                    "%c,%s@%s,none,none,none\n", (conn == connection) ? '*' : '-',
                    conn->remote_user, conn->remote_host);
      }

      buf[sizeof(buf)-1] = '\0';
      status = AddToResponse(response, buf);
      if (IS_FAILURE(status)) {
         return status;
      }

      conn = conn->next;
   }

   return SUCCESS;
}

IMPL_CMD(ports)
{
   struct Port *port;
   struct Connection *conn;
   char buf[1024];
   STATUS status;

   status = AddToResponse(response, "user,portname,device,description\n");
   if (IS_FAILURE(status)) {
      return status;
   }

   port = port_list.next;
   while (port != &port_list) {

      if ((port->flags & PORT_TEMPLATE) == 0) {
         conn = port->connection;

         if (conn != NULL) {
            snprintf(buf, sizeof(buf), 
                       "%c,%s@%s,%s,%s,%s\n", (conn == connection) ? '*' : '-',
                       conn->remote_user, conn->remote_host,
                       port->port_name, port->device_name,
                       (port->description == NULL) ? "" : port->description);
         } else {
            snprintf(buf, sizeof(buf),
                       "%c,none,%s,%s,%s\n", (conn == connection) ? '*' : '-',
                       port->port_name, port->device_name,
                       (port->description == NULL) ? "" : port->description);
         }
         buf[sizeof(buf)-1] = '\0';
         status = AddToResponse(response, buf);
         if (IS_FAILURE(status)) {
            return status;
         }
      }

      port = port->next;
   }

   return SUCCESS;
}

void HandleCommand(struct Connection *connection)
{
   char *response;
   static char resp_start[] = { RESPONSE_START, '\0' };
   static char resp_end[] = { RESPONSE_END, '\0' };
   char *command;
   int argc;
   char *argv[255];
   STATUS status;
   char *status_str;

   response = NULL;

   command = malloc(connection->command_len + 1);
   if (command == NULL) {
      syslog(LOG_ERR, "Connection fd=%d, malloc failed",  connection->fd);
      status = ERR_NOMEMORY;
   } else {

      memcpy(command, connection->command_buf, connection->command_len);
      command[connection->command_len] = '\0';

      argc = MakeArgv(command, argv, sizeof(argv)/sizeof(char *));

      if (argc == 0) {
         status = ERR_BADCMD;
      } else {

         BEGIN_CMD_HANDLERS

         HANDLE_CMD(quit)
         HANDLE_CMD(open)
         HANDLE_CMD(close)
         HANDLE_CMD(disc)
         HANDLE_CMD(dump)
         HANDLE_CMD(echo)
         HANDLE_CMD(speed)
         HANDLE_CMD(connections)
         HANDLE_CMD(ports)

         END_CMD_HANDLERS
      }
   
      free(command);
   }

   SendResponse(connection, resp_start);
   if (IS_SUCCESS(status)) {
      status_str = "+OK";
   } else {
      switch (status) {
         case ERR_BADCMD:
            status_str = "-BADCMD";   break;
         case ERR_NOMEMORY:
            status_str = "-INSFRES";  break;
         case ERR_INVARG:
            status_str = "-INVARG";   break;
         default:
            status_str = "-ERR";      break;
      }
   }
       
   SendResponse(connection, status_str);
   if (response != NULL) {
      SendResponse(connection, " ");
      SendResponse(connection, response);
   }

   SendResponse(connection, resp_end);

   connection->flags &= ~CONNECTION_COMMAND_MODE;
   connection->command_len = 0;
}


static int MakeArgv(char *command, char **argv, int max_args)
{
   int i;
   int len;
   int argc;
   int in_arg;

   len = strlen(command);

   argc = 0;
   in_arg = FALSE;

   for (i=0; i<len && argc<max_args; i++) {

      if (in_arg) {

         if (isspace(command[i])) {
            in_arg = FALSE;
            command[i] = '\0';
         }

      } else {
 
         if (!isspace(command[i])) {
            in_arg = TRUE;
            argv[argc] = command + i;
            argc++;
         }
      }
   }

   return argc;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -