mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
system/syslogd: Initial implementation
Initial implementation of syslogd including version information, simple usage help and UDP transmission. The current implementation transmits RFC 5424 formatted syslog entries over UDP for consumption by a syslog collector. Only some options from the manpage are implemented since NuttX doesn't currently have the ability for some of the more complex features (-l, etc.). Signed-off-by: Matteo Golin <matteo.golin@gmail.com>
This commit is contained in:
parent
7375f6574e
commit
5e50e2c1f9
6 changed files with 527 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -48,3 +48,4 @@ build
|
|||
compile_commands.json
|
||||
.aider*
|
||||
.clang-format
|
||||
.cache
|
||||
|
|
|
|||
36
system/syslogd/CMakeLists.txt
Normal file
36
system/syslogd/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# ##############################################################################
|
||||
# apps/system/syslogd/CMakeLists.txt
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||
# license agreements. See the NOTICE file distributed with this work for
|
||||
# additional information regarding copyright ownership. The ASF licenses this
|
||||
# file to you under the Apache License, Version 2.0 (the "License"); you may not
|
||||
# use this file except in compliance with the License. You may obtain a copy of
|
||||
# the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
# ##############################################################################
|
||||
|
||||
if(CONFIG_SYSTEM_SYSLOGD)
|
||||
nuttx_add_application(
|
||||
MODULE
|
||||
${CONFIG_SYSTEM_SYSLOGD}
|
||||
NAME
|
||||
${CONFIG_SYSTEM_SYSLOGD_PROGNAME}
|
||||
STACKSIZE
|
||||
${CONFIG_SYSTEM_SYSLOGD_STACKSIZE}
|
||||
PRIORITY
|
||||
${CONFIG_SYSTEM_SYSLOGD_PRIORITY}
|
||||
SRCS
|
||||
syslogd_main.c)
|
||||
|
||||
endif()
|
||||
53
system/syslogd/Kconfig
Normal file
53
system/syslogd/Kconfig
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config SYSTEM_SYSLOGD
|
||||
bool "syslogd utility"
|
||||
default n
|
||||
depends on NET_UDP && SYSLOG_RFC5424
|
||||
---help---
|
||||
Enable support for the 'syslogd' utility. This utility will read syslog
|
||||
messages from the syslog device and transmit them over UDP in RFC 5424
|
||||
compatible format. Ensure the syslog device being used is capable of being
|
||||
read from.
|
||||
|
||||
if SYSTEM_SYSLOGD
|
||||
|
||||
config SYSTEM_SYSLOGD_PROGNAME
|
||||
string "syslogd progname"
|
||||
default "syslogd"
|
||||
---help---
|
||||
This is the name of the program that will be used when the syslogd
|
||||
program is installed.
|
||||
|
||||
config SYSTEM_SYSLOGD_PRIORITY
|
||||
int "syslogd task priority"
|
||||
default 100
|
||||
|
||||
config SYSTEM_SYSLOGD_STACKSIZE
|
||||
int "syslogd stack size"
|
||||
default DEFAULT_TASK_STACKSIZE
|
||||
|
||||
config SYSTEM_SYSLOGD_ENTRYSIZE
|
||||
int "Max entry size"
|
||||
default 480
|
||||
---help---
|
||||
The maximum size (in bytes) of the UDP message buffer for sending syslog
|
||||
entries. Set this value to the expected maximum length of a syslog entry. RFC
|
||||
5424 specifies a minimum maximum of 480.
|
||||
|
||||
config SYSTEM_SYSLOGD_PORT
|
||||
int "syslogd port"
|
||||
default 514
|
||||
---help---
|
||||
The default port for syslogd to send UDP traffic to.
|
||||
|
||||
config SYSTEM_SYSLOGD_ADDR
|
||||
string "Log server address"
|
||||
default "127.0.0.1"
|
||||
---help---
|
||||
The network address for syslogd to send UDP traffic to.
|
||||
|
||||
endif
|
||||
25
system/syslogd/Make.defs
Normal file
25
system/syslogd/Make.defs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
############################################################################
|
||||
# apps/system/syslogd/Make.defs
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for asyslogditional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_SYSTEM_SYSLOGD),)
|
||||
CONFIGURED_APPS += $(APPDIR)/system/syslogd
|
||||
endif
|
||||
36
system/syslogd/Makefile
Normal file
36
system/syslogd/Makefile
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
############################################################################
|
||||
# apps/system/syslogd/Makefile
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
# Standalone syslogd command
|
||||
|
||||
PROGNAME = $(CONFIG_SYSTEM_SYSLOGD_PROGNAME)
|
||||
PRIORITY = $(CONFIG_SYSTEM_SYSLOGD_PRIORITY)
|
||||
STACKSIZE = $(CONFIG_SYSTEM_SYSLOGD_STACKSIZE)
|
||||
MODULE = $(CONFIG_SYSTEM_SYSLOGD)
|
||||
|
||||
# Files
|
||||
|
||||
MAINSRC = syslogd_main.c
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
376
system/syslogd/syslogd_main.c
Normal file
376
system/syslogd/syslogd_main.c
Normal file
|
|
@ -0,0 +1,376 @@
|
|||
/****************************************************************************
|
||||
* apps/system/syslogd/syslogd_main.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for asyslogditional information regarding copyright ownership.
|
||||
* The ASF licenses this file to you under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef CONFIG_LIBC_EXECFUNCS
|
||||
#include <spawn.h>
|
||||
#endif
|
||||
|
||||
#include <getopt.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* syslogd program version */
|
||||
|
||||
#define SYSLOGD_VERSION "0.0.0"
|
||||
|
||||
/* Minimum buffer size check */
|
||||
|
||||
#if CONFIG_SYSTEM_SYSLOGD_ENTRYSIZE < 480
|
||||
#error "SYSTEM_SYSLOGD_ENTRYSIZE must be more than 480 to satisfy RFC 5424"
|
||||
#endif
|
||||
|
||||
/* Maximum number of arguments that can be passed to syslogd */
|
||||
|
||||
#define MAX_ARGS 8
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: print_usage
|
||||
****************************************************************************/
|
||||
|
||||
static void print_usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage:\n");
|
||||
fprintf(stderr, " %s [-vdn]\n", CONFIG_SYSTEM_SYSLOGD_PROGNAME);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int main(int argc, FAR char **argv)
|
||||
{
|
||||
int fd;
|
||||
int sock;
|
||||
int c;
|
||||
ssize_t bread;
|
||||
ssize_t bsent;
|
||||
ssize_t endpos;
|
||||
char *end;
|
||||
size_t bufpos = 0;
|
||||
struct sockaddr_in server;
|
||||
char buffer[CONFIG_SYSTEM_SYSLOGD_ENTRYSIZE];
|
||||
bool debugmode = false;
|
||||
bool skiplog = false;
|
||||
#ifdef CONFIG_LIBC_EXECFUNCS
|
||||
pid_t pid;
|
||||
bool background = true;
|
||||
char *new_argv[MAX_ARGS + 1];
|
||||
#endif
|
||||
|
||||
/* Parse command line options */
|
||||
|
||||
while ((c = getopt(argc, argv, ":vdn")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'v':
|
||||
|
||||
/* Print version and exit */
|
||||
|
||||
printf("%s " SYSLOGD_VERSION " (NuttX)\n", argv[0]);
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
case 'd':
|
||||
|
||||
/* Enable debug mode and stay in foreground */
|
||||
|
||||
debugmode = true;
|
||||
printf("Enabling debug mode.\n");
|
||||
#ifdef CONFIG_LIBC_EXECFUNCS
|
||||
background = false;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
|
||||
/* Stay in foreground */
|
||||
|
||||
#ifdef CONFIG_LIBC_EXECFUNCS
|
||||
background = false;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case '?':
|
||||
print_usage();
|
||||
exit(EXIT_FAILURE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Run this program in the background as a spawned task if the background
|
||||
* option was selected.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_LIBC_EXECFUNCS
|
||||
if (background)
|
||||
{
|
||||
/* Set up the arguments, which is identical to the original except with
|
||||
* an added `-n` flag to ensure that the new process does not 'respawn'
|
||||
*/
|
||||
|
||||
if (argc > MAX_ARGS)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Cannot spawn syslogd daemon: arg count %d exceeds %d",
|
||||
argc, MAX_ARGS);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
new_argv[0] = argv[0]; /* Same program name */
|
||||
new_argv[1] = "-n"; /* Prevent daemon from spawning another child */
|
||||
memcpy(&new_argv[2], &argv[1], sizeof(char *) * (argc - 1));
|
||||
|
||||
/* Spawn the child for backgrounding now */
|
||||
|
||||
if (posix_spawn(&pid, argv[0], NULL, NULL, new_argv, NULL) != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to fork() to background process: %d\n",
|
||||
errno);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We succeeded in spawning, exit now. */
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_LIBC_EXECFUNCS */
|
||||
|
||||
/* Set up client connection information */
|
||||
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(CONFIG_SYSTEM_SYSLOGD_PORT);
|
||||
server.sin_addr.s_addr = inet_addr(CONFIG_SYSTEM_SYSLOGD_ADDR);
|
||||
|
||||
if (server.sin_addr.s_addr == INADDR_NONE)
|
||||
{
|
||||
fprintf(stderr, "Invalid address '%s'\n", CONFIG_SYSTEM_SYSLOGD_ADDR);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Create a UDP socket */
|
||||
|
||||
if (debugmode)
|
||||
{
|
||||
printf("Creating UDP socket %s:%u\n", CONFIG_SYSTEM_SYSLOGD_ADDR,
|
||||
CONFIG_SYSTEM_SYSLOGD_PORT);
|
||||
}
|
||||
|
||||
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sock < 0)
|
||||
{
|
||||
fprintf(stderr, "Couldn't create UDP socket: %d\n", errno);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Open syslog stream */
|
||||
|
||||
if (debugmode)
|
||||
{
|
||||
printf("Opening syslog device '%s' to read entries.\n",
|
||||
CONFIG_SYSLOG_DEVPATH);
|
||||
}
|
||||
|
||||
fd = open(CONFIG_SYSLOG_DEVPATH, O_RDWR);
|
||||
if (fd < 0)
|
||||
{
|
||||
fprintf(stderr, "Could not open syslog stream: %d", errno);
|
||||
close(sock);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Transmit syslog messages forever */
|
||||
|
||||
if (debugmode)
|
||||
{
|
||||
printf("Beginning to continuously transmit syslog entries.\n");
|
||||
}
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
/* Read as much data as possible into the remaining space in our buffer
|
||||
*/
|
||||
|
||||
bread = read(fd, &buffer[bufpos], sizeof(buffer) - bufpos);
|
||||
if (bread < 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to read from syslog: %d", errno);
|
||||
close(fd);
|
||||
close(sock);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (bread == 0 && bufpos == 0)
|
||||
{
|
||||
/* Stream is over, terminate the program. */
|
||||
|
||||
if (debugmode)
|
||||
{
|
||||
printf("Syslog stream depleted, exiting...\n");
|
||||
}
|
||||
|
||||
break; /* Successful exit */
|
||||
}
|
||||
|
||||
/* Get the position of the '\n' character of the syslog entry,
|
||||
* signifying its end.
|
||||
*/
|
||||
|
||||
end = memchr(buffer, '\n', bufpos + bread);
|
||||
if (end == NULL)
|
||||
{
|
||||
endpos = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
endpos = end - buffer;
|
||||
}
|
||||
|
||||
if (endpos < 0)
|
||||
{
|
||||
/* If we couldn't find a newline character in the buffer, it means
|
||||
* that the syslog entry doesn't end in our local buffer. We either
|
||||
* need to:
|
||||
*
|
||||
* 1) If `bread` is 0, acknowledge that there is no more data to be
|
||||
* read and our buffer will never contain a newline character. We
|
||||
* can exit successfully in this case.
|
||||
*
|
||||
* 2) Read more and try again if there's still room in our buffer
|
||||
*
|
||||
* 3) Acknowledge that the syslog entry is too long for our buffer
|
||||
* size, and skip it since we can't construct a UDP packet if
|
||||
* that's the case.
|
||||
*/
|
||||
|
||||
if (bread == 0)
|
||||
{
|
||||
break; /* Successful exit */
|
||||
}
|
||||
else if (bufpos + bread < sizeof(buffer))
|
||||
{
|
||||
/* Try to get more bytes in our buffer in case we read while
|
||||
* more bytes were coming.
|
||||
*/
|
||||
|
||||
bufpos += bread;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If we are here, there's no room left in our buffer. We need to
|
||||
* skip this entry.
|
||||
*/
|
||||
|
||||
fprintf(stderr, "Couldn't find end of log in local buffer, "
|
||||
"skipping entry until the next newline...\n");
|
||||
skiplog = true;
|
||||
bufpos = 0; /* Wipe all buffer contents */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Print out entry if we are in debug mode and not skipping this line.
|
||||
* `endpos` + 1 to print newline too.
|
||||
*/
|
||||
|
||||
if (debugmode && !skiplog)
|
||||
{
|
||||
bsent = write(0, buffer, endpos + 1);
|
||||
if (bsent < 0)
|
||||
{
|
||||
fprintf(stderr, "Couldn't print syslog entry: %d\n", errno);
|
||||
}
|
||||
}
|
||||
|
||||
/* Send entry over UDP (without newline) if we're not skipping this
|
||||
* line
|
||||
*/
|
||||
|
||||
if (!skiplog)
|
||||
{
|
||||
bsent = sendto(sock, buffer, endpos, 0,
|
||||
(const struct sockaddr *)&server, sizeof(server));
|
||||
if (bsent < 0)
|
||||
{
|
||||
fprintf(stderr, "Couldn't send syslog over UDP: %d\n", errno);
|
||||
}
|
||||
}
|
||||
|
||||
/* Take whatever bytes were leftover from our bulk read, and move them
|
||||
* to the front of the buffer. Mark the new starting point for the next
|
||||
* read so we don't overwrite them.
|
||||
*
|
||||
* endpos + 1 to overwrite vestigial newline character.
|
||||
*/
|
||||
|
||||
bufpos = (bufpos + bread) - (endpos + 1);
|
||||
|
||||
if (bufpos > 0)
|
||||
{
|
||||
/* Copy from right after the newline character up until the end of
|
||||
* unread bytes
|
||||
*/
|
||||
|
||||
memcpy(buffer, &buffer[endpos + 1], bufpos);
|
||||
}
|
||||
|
||||
/* If we got here while skipping a log, it means the endpos for the log
|
||||
* being skipped was found. Now we're done skipping the log.
|
||||
*/
|
||||
|
||||
if (skiplog)
|
||||
{
|
||||
skiplog = false;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
close(sock);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue