📄 command.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 + -