29#include <linux/limits.h>
41 va_start(args, format);
43 vsnprintf(str,
sizeof str, format, args);
45 fprintf(stderr,
"%s", str);
56 memset(computer_name, 0, len);
59 DWORD bufCharCount = len;
60 if (GetComputerName(infoBuf, &bufCharCount)) {
61 memcpy(computer_name, infoBuf, len);
63 strcpy(computer_name,
"Unknown_Host_Name");
67 if (gethostname(computer_name, len) == -1) {
69 strcpy(computer_name,
"Unknown_Host_Name");
84 if ((file = fopen(filename,
"r")) != NULL) {
96 char strbuf[PATH_MAX] =
"";
100 unsigned long int bytes = GetModuleFileName(NULL, strbuf, PATH_MAX);
103 return strdup(dirname(strbuf));
106 char procbuf[PATH_MAX] =
"";
108 sprintf(procbuf,
"/proc/%d/exe", (
int)getpid());
110 sprintf(procbuf,
"/proc/%d/path/a.out", (
int)getpid());
112 ssize_t bytes = MIN(readlink(procbuf, strbuf, PATH_MAX), PATH_MAX - 1);
115 strbuf[bytes] =
'\0';
116 return strdup(dirname(strbuf));
119 fprintf(stderr,
"%s", strerror(error));
128 char strbuf[PATH_MAX] =
"";
131 unsigned long int bytes = GetModuleFileName(NULL, strbuf, PATH_MAX);
134 return strdup(basename(strbuf));
137 char procbuf[PATH_MAX] =
"";
139 sprintf(procbuf,
"/proc/%d/exe", (
int)getpid());
141 sprintf(procbuf,
"/proc/%d/path/a.out", (
int)getpid());
143 ssize_t bytes = MIN(readlink(procbuf, strbuf, PATH_MAX), PATH_MAX - 1);
146 strbuf[bytes] =
'\0';
147 return strdup(basename(strbuf));
150 fprintf(stderr,
"%s", strerror(error));
162int n_popen(
char* cmd,
size_t read_buf_size,
void** nstr_output,
int* ret) {
165 if (read_buf_size > INT_MAX) {
166 n_log(
LOG_ERR,
"read_buf_size buffer size is too large for fgets (%zu>%d)", read_buf_size, INT_MAX);
174 char read_buf[read_buf_size];
176 fp = popen(cmd,
"r");
179 n_log(
LOG_ERR,
"popen( %s ) returned NULL , %s (%d)", cmd, strerror(err), err);
184 while (fgets(read_buf, (
int)read_buf_size, fp) != NULL) {
185 length = strlen(read_buf);
186 if (read_buf[length - 1] ==
'\n') {
187 read_buf[length - 1] =
'\0';
194 n_log(
LOG_ERR,
"pclose( %s ) returned -1 , %s (%d)", cmd, strerror(err), err);
195 if (WIFEXITED(status)) {
196 n_log(
LOG_ERR,
"Child exited with RC=%d", WEXITSTATUS(status));
197 (*ret) = WEXITSTATUS(status);
202 (*ret) = WEXITSTATUS(status);
203 (*nstr_output) = output_pointer;
214 int saved_errno = errno;
216 while (waitpid(-1, NULL, WNOHANG) > 0);
229 sigemptyset(&sa.sa_mask);
230 sa.sa_flags = SA_RESTART;
231 if (sigaction(SIGCHLD, &sa, NULL) == -1) {
244 extern char** environ;
245 for (
char** env = environ; *env != 0; env++) {
246 n_log(loglevel,
"env: %s", *env);
270 n_log(
LOG_ERR,
"Error: unable to fork child: %s", strerror(error));
283 n_log(
LOG_ERR,
"Error: unable to set session leader with setsid(): %s", strerror(error));
292 signal(SIGCHLD, SIG_IGN);
305 n_log(
LOG_ERR,
"Error: unable to double fork child: %s", strerror(error));
321 if (chdir(
"/") < 0) {
323 n_log(
LOG_ERR,
"couldn't chdir() to '/': %s", strerror(error));
330 for (
int x = 3; x < sysconf(_SC_OPEN_MAX); x++) {
337 int fd = open(
"/dev/null", O_RDWR, 0);
340 dup2(fd, STDIN_FILENO);
341 dup2(fd, STDOUT_FILENO);
342 dup2(fd, STDERR_FILENO);
347 n_log(
LOG_ERR,
"Failed to open /dev/null: %s", strerror(errno));
361pid_t
system_nb(
const char* command,
int* infp,
int* outfp) {
364 int p_stdin[2] = {-1, -1};
365 int p_stdout[2] = {-1, -1};
369 if (pipe(p_stdin) != 0)
373 if (pipe(p_stdout) != 0) {
403 dup2(p_stdout[1], 1);
405 execlp(
"sh",
"sh",
"-c", command, (
char*)NULL);
408 n_log(
LOG_ERR,
"%s:%d: exec failed: %s", __FILE__, __LINE__, strerror(error));
437 while ((arg = va_arg(args,
int))) {
458 while ((i > 0) && (path[i] !=
'.') && (path[i] !=
'/') && (path[i] !=
'\\')) {
461 if ((i > 0) && (i < n - 1) && (path[i] ==
'.') && (path[i - 1] !=
'/') && (path[i - 1] !=
'\\')) {
void log_environment(int loglevel)
log environment variables in syslog
#define N_DAEMON_NO_UMASK
daemonize flag: do not call umask( 0 )
char * get_prog_name(void)
get current program name
#define N_DAEMON_NO_DOUBLE_FORK
daemonize flag: do not double fork
void N_HIDE_STR(char *buf,...)
store a hidden version of a string
#define N_DAEMON_NO_SIGCHLD_IGN
daemonize flag: do not ignore SIGCHLD
#define N_DAEMON_NO_CHDIR
daemonize flag: do not call chdir("/")
#define __n_assert(__ptr, __ret)
macro to assert things
#define N_DAEMON_NO_CLOSE
daemonize flag: no descriptor close at all
#define N_DAEMON_NO_SIGCHLD_HANDLER
daemonize flag: do not use internal zombie SIGCHLD handler
#define N_DAEMON_NO_STD_REDIRECT
daemonize flag: just do not redirect stdin/out/err to /dev/null
int get_computer_name(char *computer_name, size_t len)
abort program with a text
#define N_DAEMON_NO_SETSID
daemonize flag: do not call setsid
void sigchld_handler(int sig)
Handles SIGCHLD issues when forking.
pid_t system_nb(const char *command, int *infp, int *outfp)
Non blocking system call.
char * n_get_file_extension(char path[])
get extension of path+filename
char * get_prog_dir(void)
get current program running directory
int n_daemonize_ex(int mode)
Daemonize program.
void n_abort(char const *format,...)
abort program with a text
int sigchld_handler_installer()
install signal SIGCHLD handler to reap zombie processes
int n_daemonize(void)
Daemonize program.
int file_exist(const char *filename)
test if file exist and if it's readable
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_DEBUG
debug-level messages
#define LOG_ERR
error conditions
#define LOG_NOTICE
normal but significant condition
#define free_nstr(__ptr)
free a N_STR structure and set the pointer to NULL
#define nstrprintf_cat(__nstr_var, __format,...)
Macro to quickly allocate and sprintf and cat to a N_STR.
N_STR * new_nstr(NSTRBYTE size)
create a new N_STR string
A box including a string and his lenght.
Common headers and low-level functions & define.
N_STR and string function declaration.