Compare commits

...

5 Commits

Author SHA1 Message Date
Victor Antonovich 3bed375c44 Refactor log file name command line option parsing 2023-12-25 17:58:48 +03:00
Victor Antonovich 2b32d097d2 Move string trim functions to util.c 2023-12-25 17:55:55 +03:00
Victor Antonovich 8591a2f1c1 Move CRC calculation function to modbus.c 2023-12-25 16:34:09 +03:00
Victor Antonovich d6e6b74a53 Default log file name changed to /var/log/mbusd.log 2023-12-25 13:00:12 +03:00
kpr0th 7475bdf141
Logging fix and enhancement (#90)
* Logging fix and enhancement

Corrected issue where loglevel in mbusd.conf wasn't parsed correctly. Added support for logfile in mbusd.conf.  Updated README and mbusd..conf.example to true-up with "-h" output and new logging options.

* Updated README

Sync'd up verbiage in the usage details with the usage summary.

* Additional adjustments to sync up README w/ -h output
2023-12-25 12:52:43 +03:00
11 changed files with 221 additions and 135 deletions

View File

@ -70,10 +70,10 @@ set(mbusd_SOURCES
src/conn.c src/conn.c
src/queue.c src/queue.c
src/modbus.c src/modbus.c
src/crc16.c
src/state.c src/state.c
src/sig.c src/sig.c
src/sock.c src/sock.c
src/util.c
) )
add_executable(mbusd ${mbusd_SOURCES}) add_executable(mbusd ${mbusd_SOURCES})
install(TARGETS mbusd DESTINATION bin) install(TARGETS mbusd DESTINATION bin)

View File

@ -78,11 +78,11 @@ Usage:
-S Enable RS-485 support for given serial port device (Linux only) -S Enable RS-485 support for given serial port device (Linux only)
-t Enable RTS RS-485 data direction control using RTS, active transmit. -t Enable RTS RS-485 data direction control using RTS, active transmit.
-r Enable RTS RS-485 data direction control using RTS, active receive. -r Enable RTS RS-485 data direction control using RTS, active receive.
-y file -y sysfsfile
Enable RS-485 direction data direction control by writing '1' to file Enable RS-485 direction data direction control by writing '1' to sysfs file
for transmitter enable and '0' to file for transmitter disable. for transmitter enable and '0' to file for transmitter disable.
-Y file -Y sysfsfile
Enable RS-485 direction data direction control by writing '0' to file Enable RS-485 direction data direction control by writing '0' to sysfs file
for transmitter enable and '1' to file for transmitter disable. for transmitter enable and '1' to file for transmitter disable.
-A address -A address
Specifies TCP server address to bind (default is 0.0.0.0). Specifies TCP server address to bind (default is 0.0.0.0).

View File

@ -4,6 +4,14 @@
# # # #
############################################# #############################################
########## Logging settings #############
# Logging verbosity level
loglevel = 2
# Logfile (fully-qualified path, or filename [stored at /var/log/] or - for STDOUT only)
logfile = /var/log/mbusd.log
########## Serial port settings ############# ########## Serial port settings #############
# Serial port device name # Serial port device name

View File

@ -34,9 +34,10 @@
#include "cfg.h" #include "cfg.h"
#include <stdlib.h> #include <stdlib.h>
#include <ctype.h>
#include <string.h> #include <string.h>
#include "util.h"
#define CFG_MAX_LINE_LENGTH 200 #define CFG_MAX_LINE_LENGTH 200
#define CFG_NAME_MATCH(n) strcmp(n, name) == 0 #define CFG_NAME_MATCH(n) strcmp(n, name) == 0
@ -81,23 +82,6 @@ cfg_init(void)
cfg.replyonbroadcast=0; cfg.replyonbroadcast=0;
} }
static char *
cfg_rtrim(char *s)
{
char *p = s + strlen(s);
while (p > s && isspace((unsigned char )(*--p)))
*p = '\0';
return s;
}
static char *
cfg_ltrim(const char *s)
{
while (*s && isspace((unsigned char )(*s)))
s++;
return (char *) s;
}
int int
cfg_handle_param(char *name, char *value) cfg_handle_param(char *name, char *value)
{ {
@ -231,7 +215,40 @@ cfg_handle_param(char *name, char *value)
} }
else if (CFG_NAME_MATCH("loglevel")) else if (CFG_NAME_MATCH("loglevel"))
{ {
cfg.dbglvl = (char)strtol(optarg, NULL, 0); cfg.dbglvl = (char)strtol(value, NULL, 0);
# ifdef DEBUG
if (!(isdigit(*value)) || cfg.dbglvl < 0 || cfg.dbglvl > 9)
{ /* report about invalid log level */
CFG_ERR("invalid loglevel value: %s (must be 0-9)", value);
# else
if (!(isdigit(*value)) || cfg.dbglvl < 0 || cfg.dbglvl > 2)
{ /* report about invalid log level */
CFG_ERR("invalid loglevel value: %s (must be 0-2)", value);
# endif
return 0;
}
}
else if (CFG_NAME_MATCH("logfile"))
{
if (!strlen(value))
{
CFG_ERR("missing logfile value", value);
return 0;
}
else if (*value != '/')
{
if (*value == '-')
{
/* logging to file disabled */
*cfg.logname = '\0';
}
else
{ /* concatenate given log file name with default path */
strncpy(cfg.logname, LOGPATH, INTBUFSIZE);
strncat(cfg.logname, value, INTBUFSIZE - strlen(cfg.logname));
}
}
else strncpy(cfg.logname, value, INTBUFSIZE);
#endif #endif
} }
else { else {
@ -265,7 +282,7 @@ cfg_parse_file(void *file)
{ {
lineno++; lineno++;
start = cfg_ltrim(cfg_rtrim(line)); start = util_trim(line);
if (*start == '#') if (*start == '#')
{ {
@ -280,8 +297,8 @@ cfg_parse_file(void *file)
{ {
*end = '\0'; *end = '\0';
name = cfg_rtrim(start); name = util_rtrim(start);
value = cfg_ltrim(cfg_rtrim(end + 1)); value = util_trim(end + 1);
/* handle name/value pair */ /* handle name/value pair */
if (!cfg_handle_param(name, value)) if (!cfg_handle_param(name, value))

View File

@ -1,79 +0,0 @@
/*
* OpenMODBUS/TCP to RS-232/485 MODBUS RTU gateway
*
* crc16.c - Cyclic Redundant Checks calculating
*
* Copyright (c) 2002-2003, 2013, Victor Antonovich (v.antonovich@gmail.com)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: crc16.c,v 1.3 2015/02/25 10:33:57 kapyar Exp $
*/
#include "crc16.h"
unsigned short
crc_16_tab[] = {
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
};
unsigned short
crc16(unsigned char *buf, unsigned int bsize)
{
unsigned short crc = 0xffff;
while (bsize--)
crc = (unsigned short)(crc >> 8) ^ crc_16_tab[(crc ^ *buf++) & 0xff];
return crc;
}

View File

@ -40,7 +40,7 @@ extern int isdaemon;
/* Default log file path and name */ /* Default log file path and name */
#define LOGPATH "/var/log/" #define LOGPATH "/var/log/"
#define LOGNAME "mbus.log" #define LOGNAME "mbusd.log"
#ifdef LOG #ifdef LOG
int log_init(char *logname); int log_init(char *logname);

View File

@ -40,6 +40,7 @@
#include "conn.h" #include "conn.h"
#include "queue.h" #include "queue.h"
#include "sig.h" #include "sig.h"
#include "util.h"
#ifdef LOG #ifdef LOG
# include "log.h" # include "log.h"
#endif #endif
@ -119,7 +120,7 @@ usage(char *exename)
" [-R pause] [-W wait] [-T timeout] [-b]\n\n" " [-R pause] [-W wait] [-T timeout] [-b]\n\n"
"Options:\n" "Options:\n"
" -h : this help\n" " -h : this help\n"
" -d : don't daemonize\n" " -d : don't fork (non-daemonize)\n"
#ifdef LOG #ifdef LOG
" -L logfile : set log file name (default is %s%s, \n" " -L logfile : set log file name (default is %s%s, \n"
" '-' for logging to STDOUT only)\n" " '-' for logging to STDOUT only)\n"
@ -136,14 +137,16 @@ usage(char *exename)
#ifdef HAVE_TIOCRS485 #ifdef HAVE_TIOCRS485
" -S : enable Linux RS-485 support for given serial port device\n" " -S : enable Linux RS-485 support for given serial port device\n"
#endif #endif
" -A address : set TCP server address to bind (default is %s)\n"
" -P port : set TCP server port number (default is %d)\n"
#ifdef TRXCTL #ifdef TRXCTL
" -t : enable RTS RS-485 data direction control using RTS, active transmit\n" " -t : enable RTS RS-485 data direction control using RTS, active transmit\n"
" -r : enable RTS RS-485 data direction control using RTS, active receive\n" " -r : enable RTS RS-485 data direction control using RTS, active receive\n"
" -y : enable RTS RS-485 data direction control using sysfs file, active transmit\n" " -y : enable RTS RS-485 data direction control using sysfs file, active transmit\n"
" (writes '1' to sysfs file for transmit enable, '0' for transmit disable)\n"
" -Y : enable RTS RS-485 data direction control using sysfs file, active receive\n" " -Y : enable RTS RS-485 data direction control using sysfs file, active receive\n"
" (writes '0' to sysfs file for transmit enable, '1' for transmit disable)\n"
#endif #endif
" -A address : set TCP server address to bind (default is %s)\n"
" -P port : set TCP server port number (default is %d)\n"
" -C maxconn : set maximum number of simultaneous TCP connections\n" " -C maxconn : set maximum number of simultaneous TCP connections\n"
" (1-%d, default is %d)\n" " (1-%d, default is %d)\n"
" -N retries : set maximum number of request retries\n" " -N retries : set maximum number of request retries\n"
@ -167,6 +170,7 @@ usage(char *exename)
exit(0); exit(0);
} }
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
@ -242,23 +246,30 @@ main(int argc, char *argv[])
case 'v': case 'v':
cfg.dbglvl = (char)strtol(optarg, NULL, 0); cfg.dbglvl = (char)strtol(optarg, NULL, 0);
# ifdef DEBUG # ifdef DEBUG
if (cfg.dbglvl > 9) if (!(isdigit(*optarg)) || cfg.dbglvl < 0 || cfg.dbglvl > 9)
{ /* report about invalid log level */ { /* report about invalid log level */
printf("%s: -v: invalid loglevel value" printf("%s: -v: invalid loglevel value"
" (%d, must be 0-9)\n", exename, cfg.dbglvl); " (%s, must be 0-9)\n", exename, optarg);
# else # else
if (cfg.dbglvl < 0 || cfg.dbglvl > 9) if (!(isdigit(*optarg)) || cfg.dbglvl < 0 || cfg.dbglvl > 2)
{ /* report about invalid log level */ { /* report about invalid log level */
printf("%s: -v: invalid loglevel value" printf("%s: -v: invalid loglevel value"
" (%d, must be 0-2)\n", exename, cfg.dbglvl); " (%s, must be 0-2)\n", exename, optarg);
# endif # endif
exit(-1); exit(-1);
} }
break; break;
case 'L': case 'L':
if (*optarg != '/') char *logfilenamevalue = strdup(optarg);
char *logfilename = util_trim(logfilenamevalue);
if (!strlen(logfilename))
{ /* report about empty log file */
printf("%s: -L: log file name is empty, exiting...\n", exename);
exit(-1);
}
else if (*logfilename != '/')
{ {
if (*optarg == '-') if (*logfilename == '-')
{ {
/* logging to file disabled */ /* logging to file disabled */
*cfg.logname = '\0'; *cfg.logname = '\0';
@ -266,10 +277,11 @@ main(int argc, char *argv[])
else else
{ /* concatenate given log file name with default path */ { /* concatenate given log file name with default path */
strncpy(cfg.logname, LOGPATH, INTBUFSIZE); strncpy(cfg.logname, LOGPATH, INTBUFSIZE);
strncat(cfg.logname, optarg, INTBUFSIZE - strlen(cfg.logname)); strncat(cfg.logname, logfilename, INTBUFSIZE - strlen(cfg.logname));
} }
} }
else strncpy(cfg.logname, optarg, INTBUFSIZE); else strncpy(cfg.logname, logfilename, INTBUFSIZE);
free(logfilenamevalue);
break; break;
#endif #endif
case 'p': case 'p':

View File

@ -34,6 +34,57 @@
#include "modbus.h" #include "modbus.h"
#include "conn.h" #include "conn.h"
static const unsigned short
modbus_crc16_table[] = {
0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
};
/*
* Calculate Modbus frame CRC (Cyclical Redundancy Checking) value
* Parameters: FRAME - address of the frame,
* LEN - frame length;
* Return: calculated CRC value
*/
static unsigned short
modbus_crc_calculate(unsigned char *frame, unsigned int len)
{
unsigned short crc = 0xffff;
while (len--)
crc = (unsigned short)(crc >> 8) ^ modbus_crc16_table[(crc ^ *frame++) & 0xff];
return crc;
}
/* /*
* Check CRC of MODBUS frame * Check CRC of MODBUS frame
* Parameters: FRAME - address of the frame, * Parameters: FRAME - address of the frame,
@ -44,7 +95,7 @@
int int
modbus_crc_correct(unsigned char *frame, unsigned int len) modbus_crc_correct(unsigned char *frame, unsigned int len)
{ {
return (!crc16(frame, len)); return (!modbus_crc_calculate(frame, len));
} }
/* /*
@ -56,7 +107,7 @@ modbus_crc_correct(unsigned char *frame, unsigned int len)
void void
modbus_crc_write(unsigned char *frame, unsigned int len) modbus_crc_write(unsigned char *frame, unsigned int len)
{ {
WORD_WR_LE(frame + len, crc16(frame, len)); WORD_WR_LE(frame + len, modbus_crc_calculate(frame, len));
} }
/* /*

View File

@ -35,7 +35,6 @@
#define _MODBUS_H #define _MODBUS_H
#include "globals.h" #include "globals.h"
#include "crc16.h"
/* /*
* Macro for accessing data in MODBUS frame * Macro for accessing data in MODBUS frame

80
src/util.c Normal file
View File

@ -0,0 +1,80 @@
/*
* OpenMODBUS/TCP to RS-232/485 MODBUS RTU gateway
*
* util.h - utility functions
*
* Copyright (c) 2002-2023, Victor Antonovich (v.antonovich@gmail.com)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "util.h"
#include <ctype.h>
#include <string.h>
/**
* Removes leading whitespace from the string.
* Parameters: s - the string to be trimmed.
* Return: a pointer to the first non-whitespace character in string.
*/
char *
util_ltrim(const char *s)
{
while (*s && isspace((unsigned char )(*s)))
s++;
return (char *) s;
}
/**
* Removes trailing whitespace from the string.
* The first trailing whitespace is replaced with a NUL-terminator
* in the given string.
* Parameters: s - the string to be trimmed.
* Return: a pointer to the string.
*/
char *
util_rtrim(char *s)
{
char *p = s + strlen(s);
while (p > s && isspace((unsigned char )(*--p)))
*p = '\0';
return s;
}
/**
* Removes leading and trailing whitespace from the string.
* The first trailing whitespace is replaced with a NUL-terminator
* in the given string.
* Parameters: s - the string to be trimmed.
* Return: a pointer to the first non-whitespace character in string.
*/
char *
util_trim(char *s)
{
if (!strlen(s))
return s;
return util_ltrim(util_rtrim(s));
}

View File

@ -1,21 +1,21 @@
/* /*
* OpenMODBUS/TCP to RS-232/485 MODBUS RTU gateway * OpenMODBUS/TCP to RS-232/485 MODBUS RTU gateway
* *
* crc16.h - Cyclic Redundant Checks calculating * util.h - utility functions
*
* Copyright (c) 2002-2023, Victor Antonovich (v.antonovich@gmail.com)
* *
* Copyright (c) 2002-2003, 2013, Victor Antonovich (v.antonovich@gmail.com)
*
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions
* are met: * are met:
* *
* - Redistributions of source code must retain the above copyright * - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* *
* - Redistributions in binary form must reproduce the above copyright * - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@ -27,15 +27,13 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: crc16.h,v 1.3 2015/02/25 10:33:57 kapyar Exp $
*/ */
#ifndef _CRC_H
#define _CRC_H
#include "globals.h" #ifndef _UTIL_H
#define _UTIL_H
unsigned short crc16(unsigned char *buf, unsigned int bsize); char *util_ltrim(const char *s);
char *util_rtrim(char *s);
char *util_trim(char *s);
#endif /*_CRC_H */ #endif /* _UTIL_H */