/*
* ----------------------------------------------------------------
* Night Light System Functions
* ----------------------------------------------------------------
* Copyright (C) 1997-2003 Jonas Kvinge <jonas@night-light.net>
* All rights reserved.
*
* 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.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Last modified by:
* Jonas Kvinge (15.11.2006)
*
*/
#define SYSCALLS_C
#define NEED_SYS_TYPES_H 1 /* Extra types */
#define NEED_SYS_PARAM_H 1 /* Some systems need this */
#define NEED_LIMITS_H 1 /* Kernel limits */
#define NEED_STDARG_H 1 /* va_list, etc */
#define NEED_ERRNO_H 1 /* errno */
#define NEED_CTYPE_H 1 /* isdigit(), etc */
#define NEED_NETINET_IN_H 1 /* in_addr, sockaddr_in, etc */
#define NEED_ARPA_INET_H 1 /* inet_ntoa(), inet_aton(), etc */
#define NEED_STDIO_H 1 /* Standard C UNIX functions */
#define NEED_STDLIB_H 1 /* malloc(), exit(), atoi(), etc */
#define NEED_TIME_H 1 /* time(), etc */
#define NEED_SYSCTL_H 0 /* sysctl(), etc */
#define NEED_SYS_STAT_H 1 /* chmod(), mkdir(), etc */
#define NEED_SYS_UIO_H 0 /* iovec, etc */
#define NEED_FCNTL_H 1 /* open(), creat(), fcntl(), etc */
#define NEED_SYS_IOCTL_H 1 /* ioctl(), etc */
#define NEED_SYS_FILIO_H 1 /* Solaris need this for ioctl(), etc */
#define NEED_UNISTD_H 1 /* Unix standard functions */
#define NEED_STRING_H 1 /* C string functions */
#define NEED_SIGNAL_H 1 /* Signal functions */
#define NEED_SYS_SOCKET_H 1 /* Socket functions */
#define NEED_NETDB_H 0 /* Network database functions */
#define NEED_ARPA_NAMESER_H 0 /* Nameserver definitions */
#define NEED_GETUSERPW_HEADERS 1 /* Functions to retrive system passwords */
#include "includes.h"
#include "nlstrsignal.h"
#include "main.h"
#include "conf.h"
#if DCC
#include "dcc_conn.h"
#endif
/* VARIABLES - JONAS (23.08.2001) */
const char SYSCALLS_VERSION[] = "1.3.5d";
unsigned short int ScreenMode = TRUE;
unsigned short int ScreenPrint = TRUE;
unsigned short int ScreenDTS = TRUE;
unsigned short int Run = TRUE;
unsigned short int Exit = FALSE;
unsigned short int Root = FALSE;
static pid_t PID = 0;
time_t StartTime = 0;
time_t FlushTime = 0;
time_t ExitTime = 0;
#if !WIN32
uid_t UID_Current = 0;
uid_t EUID_Current = 0;
uid_t UID_Normal = 0;
uid_t EUID_Normal = 0;
gid_t GID_Current = 0;
gid_t EGID_Current = 0;
gid_t GID_Normal = 0;
gid_t EGID_Normal = 0;
#endif
unsigned short int ExitSignals = 0;
char *TMPSTRPT = NULL;
extern unsigned long int ScreenBitmask;
extern struct PrintFile_Struct PrintFileS[];
extern unsigned short int PrintFileS_Len;
extern struct Conf_Struct ConfS;
/* SYSINIT FUNCTION - JONAS (27.02.2002) */
void sysinit(void) {
signed long int Flags = 0;
signed long int Result = 0;
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "System initialization.");
PID = getpid();
NOW = time(NULL);
srand(NOW);
StartTime = NOW;
#if defined(NBLOCK_SYSV)
Flags = 1;
Result = ioctl(STDIN_FILENO, FIONBIO, &Flags);
#else
Flags = fcntl(STDIN_FILENO, F_GETFL);
if (Flags <= ERROR) { Flags = 0; }
#if defined(NBLOCK_BSD)
Flags |= O_NDELAY;
#elif defined(NBLOCK_POSIX)
Flags |= O_NONBLOCK;
#else
#warning "This system does not support non-blocking sockets?"
Flags |= O_NONBLOCK;
#endif
Result = fcntl(STDIN_FILENO, F_SETFL, Flags);
#endif
strgetunameinfo();
strgetplatform();
strgetosname();
strgetosrelease();
strgethostname();
}
#if !WIN32
/* SYSINITID FUNCTION - JONAS (18.07.2001) */
void sysinitid(void) {
signed long int Result = 0;
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Initializing ID.");
UID_Current = getuid();
EUID_Current = geteuid();
GID_Current = getgid();
EGID_Current = getegid();
UID_Normal = UID_Current;
GID_Normal = GID_Current;
if (UID_Current == 0) {
Root = TRUE;
assert(ConfS.EUser != NULL);
EUID_Normal = sysgetuidfromuser(ConfS.EUser);
if (aerrno != AESUCCESS) {
printf("%s: No such user.\n", ConfS.EUser);
printf("Cannot start %s from root without a vaild EUSER.\n", PACKAGE);
exit(ERROR);
}
if (EUID_Normal == 0) {
printf("You must set EUSER to something else than root!\n");
exit(ERROR);
}
EGID_Normal = sysgetgidfromgroup(ConfS.EGroup);
if (aerrno != AESUCCESS) {
printf("%s: No such group.\n", ConfS.EGroup);
printf("Cannot start %s from root without a vaild EGROUP.\n", PACKAGE);
exit(ERROR);
}
if (EGID_Normal == 0) {
printf("You must set EGROUP to something else than (root/system/wheel)!\n");
exit(ERROR);
}
}
else {
Root = FALSE;
EUID_Normal = EUID_Current;
EGID_Normal = EGID_Current;
}
if (ConfS.ChDir == TRUE) {
Result = chdir(ConfS.ChDirPath);
if (Result == ERROR) {
printf("Unable to change working directory to %s (CHDIRPATH): [%d] %s\n", ConfS.ChDirPath, errno, strerror(errno));
exit(ERROR);
}
}
if (GID_Current == 0) {
Result = setegid(EGID_Normal);
if (Result <= ERROR) { printf("Unable to change effective group ID to %ld: [%d] %s\n", (PRINT_GID_T) EGID_Normal, errno, strerror(errno)); exit(1); }
EGID_Current = EGID_Normal;
}
if (UID_Current == 0) {
Result = seteuid(EUID_Normal);
if (Result <= ERROR) { printf("Unable to change effective user ID to %ld: [%d] %s\n", (PRINT_UID_T) EUID_Normal, errno, strerror(errno)); exit(1); }
EUID_Current = EUID_Normal;
}
assert(EUID_Current == EUID_Normal);
assert(EGID_Current == EGID_Normal);
assert(EUID_Current == geteuid());
assert(EGID_Current == getegid());
assert(EUID_Current != 0);
assert(EGID_Current != 0);
}
#endif
#if !WIN32
/* SYSSETEUIDNORMAL FUNCTION - JONAS (01.07.2000) */
signed long int sysseteuidnormal(void) {
signed long int Result = 0;
if (EUID_Current == EUID_Normal) { return(SUCCESS); }
if (EUID_Current != 0) {
Result = seteuid(0);
if (Result <= ERROR) { sysprint(BITMASK_ERROR, "Unable to change effective user ID to root (0): [%d] %s", errno, strerror(errno)); exit(1); }
EUID_Current = 0;
}
Result = seteuid(EUID_Normal);
if (Result <= ERROR) { sysprint(BITMASK_ERROR, "Unable to change effective user ID to normal (%ld): [%d] %s", (PRINT_UID_T) EUID_Normal, errno, strerror(errno)); exit(1); }
EUID_Current = EUID_Normal;
return(SUCCESS);
}
#endif
#if !WIN32
/* SYSSETUID FUNCTION - JONAS (01.07.2000) */
signed long int sysseteuid(const uid_t UID) {
signed long int Result = 0;
if (UID_Current != 0) { return(ERROR); }
if (EUID_Current == UID) { return(SUCCESS); }
Result = seteuid(0);
if (Result <= ERROR) { sysprint(BITMASK_ERROR, "Unable to change effective user ID to root (0): [%d] %s", errno, strerror(errno)); return(ERROR); }
EUID_Current = 0;
if (UID == 0) { return(SUCCESS); }
Result = seteuid(UID);
if (Result <= ERROR) {
sysprint(BITMASK_ERROR, "Unable to change effective user ID to %ld: [%d] %s", (PRINT_UID_T) UID, errno, strerror(errno));
Result = seteuid(EUID_Normal);
if (Result <= ERROR) { sysprint(BITMASK_ERROR, "Unable to change effective user ID to normal (%ld): [%d] %s", (PRINT_UID_T) EUID_Normal, errno, strerror(errno)); exit(1); }
return(ERROR);
}
EUID_Current = UID;
return(SUCCESS);
}
#endif
#if !WIN32
/* SYSSETUIDBYUSER FUNCTION - JONAS (01.07.2000) */
signed long int sysseteuidbyuser(const char *const UserPT) {
signed long int Result = 0;
uid_t UID = 0;
assert(UserPT != NULL);
if (UID_Current != 0) { return(ERROR); }
UID = sysgetuidfromuser(UserPT);
if (aerrno != AESUCCESS) { return(ERROR); }
if (EUID_Current == UID) { return(SUCCESS); }
Result = sysseteuid(UID);
return(Result);
}
#endif
/* SYSINITFILES FUNCTION - JONAS (27.02.2002) */
void sysinitfiles(void) {
unsigned short int Index = 0;
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Initializing all files.");
for (Index = 0 ; Index < PrintFileS_Len ; Index++) {
char File[FILELEN+1] = "";
assert(PrintFileS[Index].Name != NULL);
if ((strncmp(PrintFileS[Index].Name, ConfS.LogPath, strlen(ConfS.LogPath)) != FALSE) && (PrintFileS[Index].Name[0] != '/')) {
memset(File, 0, FILELEN+1);
strncat(File, ConfS.LogPath, (FILELEN - strlen(File)));
if (File[strlen(File)] != '/') { strncat(File, "/", (FILELEN - strlen(File))); }
strncat(File, PrintFileS[Index].Name, (FILELEN - strlen(File)));
PrintFileS[Index].Name = strrealloc(PrintFileS[Index].Name, File);
}
assert(PrintFileS[Index].Name != NULL);
if (Index == 2) { PrintFileS[Index].FilePT = stderr; }
else { PrintFileS[Index].FilePT = stdout; }
}
}
/* SYSCLOSEFILES FUNCTION - JONAS (25.06.2000) */
void sysclosefiles(void) {
unsigned long int FD = 0;
unsigned long int FDL = sysconf(_SC_OPEN_MAX);
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Closing all files.");
for (FD = 0 ; FD <= FDL ; FD++) { close(FD); }
}
/* SYSOPENFILES_FG FUNCTION - JONAS (18.07.2001) */
void sysopenfiles_fg(void) {
unsigned short int Index = 0;
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Opening files (foreground).");
for (Index = 1 ; Index < PrintFileS_Len ; ++Index) {
assert(PrintFileS[Index].Name != NULL);
PrintFileS[Index].FilePT = fopen(PrintFileS[Index].Name, "a");
if (PrintFileS[Index].FilePT == NULL) {
printf("Unable to open %s: [%d] %s\n", PrintFileS[Index].Name, errno, strerror(errno));
exit(1);
}
}
}
#if !WIN32
/* SYSOPENFILES_BG FUNCTION - JONAS (18.07.2001) */
void sysopenfiles_bg(void) {
signed long int Result = 0;
unsigned short int Index = 0;
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Opening files (background).");
for (Index = 0 ; Index < PrintFileS_Len ; ++Index) {
if ((PrintFileS[Index].FilePT == NULL) || (PrintFileS[Index].FilePT == stdin) || (PrintFileS[Index].FilePT == stdout) || (PrintFileS[Index].FilePT == stderr)) { continue; }
Result = fclose(PrintFileS[Index].FilePT);
if (Result == EOF) {
sysprint(BITMASK_ERROR, "Unable to close %s: [%d] %s", PrintFileS[Index].Name, errno, strerror(errno));
exit(1);
}
PrintFileS[Index].FilePT = NULL;
}
close(0);
close(1);
close(2);
#if 0
FD_CLR(0, &ReadFDS);
FD_CLR(0, &WriteFDS);
FD_CLR(1, &ReadFDS);
FD_CLR(1, &WriteFDS);
FD_CLR(2, &ReadFDS);
FD_CLR(2, &WriteFDS);
#endif
for (Index = 0 ; Index < PrintFileS_Len ; ++Index) {
switch (Index) {
case 0:
case 1:
case 2:
Result = open(PrintFileS[Index].Name, (O_CREAT|O_NONBLOCK|O_WRONLY|O_APPEND), (S_IRUSR|S_IWUSR|S_IRGRP));
assert(Result == Index);
if (Result != Index) { abort(); }
if (Index == 0) { PrintFileS[Index].FilePT = NULL; }
else if (Index == 1) { PrintFileS[Index].FilePT = stdout; }
else if (Index == 2) { PrintFileS[Index].FilePT = stderr; }
break;
default:
PrintFileS[Index].FilePT = fopen(PrintFileS[Index].Name, "a");
if (PrintFileS[Index].FilePT == NULL) {
sysprint(BITMASK_ERROR, "Unable to open %s: [%d] %s", PrintFileS[Index].Name, errno, strerror(errno));
exit(1);
}
}
}
}
#endif
/* SYSFLUSHFILES FUNCTION - JONAS (18.07.2001) */
void sysflushfiles(void) {
signed long int Result = 0;
unsigned long int Index = 0;
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Flushing all file descriptors...");
FlushTime = NOW;
for (Index = 0 ; Index < PrintFileS_Len ; Index++) {
if (PrintFileS[Index].Name == NULL) { continue; }
if (PrintFileS[Index].FilePT == NULL) { continue; }
Result = fflush(PrintFileS[Index].FilePT);
if (Result <= ERROR) {
sysprint(BITMASK_ERROR, "Unable to flush %s: [%d] %s", PrintFileS[Index].Name, errno, strerror(errno));
exit(1);
}
}
}
#if !WIN32
/* SYSCHECKPID FUNCTION - JONAS (11.07.2001) */
void syscheckpid(void) {
FILE *FilePT = NULL;
char Line[LINELEN+1] = "";
char *LinePT = NULL;
unsigned long int pid = 0;
signed long int Result = 0;
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Checking PID file.");
if ((UID_Current == 0) && (EUID_Current != 0)) {
Result = seteuid(0);
if (Result <= ERROR) { sysprint(BITMASK_ERROR, "Unable to change effective user ID to root (0): [%d] %s", errno, strerror(errno)); }
else { EUID_Current = 0; }
}
FilePT = fopen(ConfS.PIDFile, "r");
if (FilePT == NULL) {
if (errno != ENOENT) { sysprint(BITMASK_ERROR, "Unable to open %s for reading: [%d] %s", ConfS.PIDFile, errno, strerror(errno)); }
}
else {
LinePT = fgets(Line, LINELEN, FilePT);
if (LinePT != NULL) pid = atoi(LinePT);
if (pid <= 1) { fclose(FilePT); }
else {
Result = kill(pid, SIGUSR1);
if (Result != ERROR) {
fclose(FilePT);
printf("%s already running, PID: %ld\n", PACKAGE, (PRINT_PID_T) pid);
exit(1);
}
fclose(FilePT);
}
}
if (EUID_Current != EUID_Normal) {
Result = seteuid(EUID_Normal);
if (Result <= ERROR) { sysprint(BITMASK_ERROR, "Unable to change effective user ID to %ld: [%d] %s", (PRINT_UID_T) EUID_Normal, errno, strerror(errno)); exit(1); }
EUID_Current = EUID_Normal;
}
}
#endif
#if !WIN32
/* SYSWRITEPID FUNCTION - JONAS (25.06.2000) */
void syswritepid(void) {
signed long int Result = 0;
FILE *FilePT = NULL;
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Writing PID file, current PID: %ld.", (PRINT_PID_T) PID);
if ((UID_Current == 0) && (EUID_Current != 0)) {
Result = seteuid(0);
if (Result <= ERROR) { sysprint(BITMASK_ERROR, "Unable to change effective user ID to root (0): [%d] %s", errno, strerror(errno)); }
else { EUID_Current = 0; }
}
FilePT = fopen(ConfS.PIDFile, "w");
if (FilePT == NULL) {
sysprint(BITMASK_ERROR, "Unable to open %s for writing: [%d] %s", ConfS.PIDFile, errno, strerror(errno));
exit(1);
}
fprintf(FilePT, "%ld%s", (PRINT_PID_T) PID, LINEFEED);
fclose(FilePT);
if (EUID_Current != EUID_Normal) {
Result = seteuid(EUID_Normal);
if (Result <= ERROR) { sysprint(BITMASK_ERROR, "Unable to change effective user ID to %ld: [%d] %s", (PRINT_UID_T) EUID_Normal, errno, strerror(errno)); exit(1); }
EUID_Current = EUID_Normal;
}
}
#endif
/* SYSSETSIGNALS FUNCTION - JONAS (25.06.2000) */
void syssetsignals(void) {
void *ResultPT = NULL;
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Setting signals.");
#ifdef SIGHUP
ResultPT = signal(SIGHUP, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Hangup\"."); }
#endif
#ifdef SIGINT
ResultPT = signal(SIGINT, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Interrupt\"."); }
#endif
#ifdef SIGQUIT
ResultPT = signal(SIGQUIT, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Quit\"."); }
#endif
#ifdef SIGILL
ResultPT = signal(SIGILL, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Illegal instruction\"."); }
#endif
#ifdef SIGTRAP
ResultPT = signal(SIGTRAP, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Trace trap\"."); }
#endif
#ifdef SIGABRT
ResultPT = signal(SIGABRT, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Abort\"."); }
#endif
#ifdef SIGIOT
ResultPT = signal(SIGIOT, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Abort\"."); }
#endif
#ifdef SIGEMT
ResultPT = signal(SIGEMT, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"EMT instruction\"."); }
#endif
#ifdef SIGFPE
ResultPT = signal(SIGFPE, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Floating-point exception\"."); }
#endif
#ifdef SIGBUS
ResultPT = signal(SIGBUS, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Bus error\"."); }
#endif
#ifdef SIGSEGV
ResultPT = signal(SIGSEGV, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Segmentation violation\"."); }
#endif
#ifdef SIGSYS
ResultPT = signal(SIGSYS, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Non-existent system call invoked\"."); }
#endif
#ifdef SIGPIPE
ResultPT = signal(SIGPIPE, SIG_IGN);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Broken pipe\"."); }
#endif
#ifdef SIGALRM
ResultPT = signal(SIGALRM, SIG_IGN);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Alarm clock\"."); }
#endif
#ifdef SIGTERM
ResultPT = signal(SIGTERM, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Termination\"."); }
#endif
#ifdef SIGURG
ResultPT = signal(SIGURG, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Urgent condition on IO channel\"."); }
#endif
#ifdef SIGTSTP
ResultPT = signal(SIGTSTP, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Stop signal from tty\"."); }
#endif
#ifdef SIGCONT
ResultPT = signal(SIGCONT, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Continue a stopped process\"."); }
#endif
#ifdef SIGCHLD
ResultPT = signal(SIGCHLD, SIG_IGN);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Signal to parent on child stop or exit\"."); }
#endif
#ifdef SIGTTIN
ResultPT = signal(SIGTTIN, SIG_IGN);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Background read from tty\"."); }
#endif
#ifdef SIGTTOU
ResultPT = signal(SIGTTOU, SIG_IGN);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Background write to tty\"."); }
#endif
#ifdef SIGIO
ResultPT = signal(SIGIO, SIG_IGN);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"I/O possible\"."); }
#endif
#ifdef SIGXCPU
ResultPT = signal(SIGXCPU, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Exceeded CPU time limit\"."); }
#endif
#ifdef SIGXFSZ
ResultPT = signal(SIGXFSZ, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Exceeded file size limit\"."); }
#endif
#ifdef SIGVTALRM
ResultPT = signal(SIGVTALRM, SIG_IGN);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Virtual alarm clock\"."); }
#endif
#ifdef SIGPROF
ResultPT = signal(SIGPROF, SIG_IGN);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Profiling alarm clock\"."); }
#endif
#ifdef SIGWINCH
ResultPT = signal(SIGWINCH, SIG_IGN);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Window size change\"."); }
#endif
#if 0
ResultPT = signal(SIGINFO, SIG_IGN);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Information request\"."); }
#endif
#ifdef SIGUSR1
ResultPT = signal(SIGUSR1, SIG_IGN);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"User-defined signal 1\"."); }
#endif
#ifdef SIGUSR2
ResultPT = signal(SIGUSR2, SIG_IGN);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"User-defined signal 1\"."); }
#endif
#ifdef SIGPWR
ResultPT = signal(SIGPWR, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Power failure restart\"."); }
#endif
#ifdef SIGSTKFLT
ResultPT = signal(SIGSTKFLT, syshandlesignal);
if (ResultPT == SIG_ERR) { sysprint(BITMASK_ERROR, "Unable to install signal handler for \"Stack fault\"."); }
#endif
}
/* SYSHANDLESIGNAL FUNCTION - JONAS (26.03.2002) */
void syshandlesignal(int Signal) {
signal(Signal, syshandlesignal);
/* Signals telling us to rehash the configuration */
#ifdef SIGHUP
if (Signal == SIGHUP) { /* Hangup */
sysprint(BITMASK_MAIN, "Caught signal %d, %s.", Signal, nlstrsignal(Signal));
main_rehash();
return;
}
#endif
/* Signals telling us to exit normally */
if
(
(1 == 2)
#ifdef SIGINT
||
(Signal == SIGINT) /* Interrupt */
#endif
#ifdef SIGTERM
||
(Signal == SIGTERM) /* Termination */
#endif
) {
ExitSignals++;
if (ExitSignals >= 3) { exit(0); }
sysprint(BITMASK_MAIN, "Caught signal %d, %s.", Signal, nlstrsignal(Signal));
sysflushfiles();
main_exit("Caught signal %d, %s", Signal, nlstrsignal(Signal));
return;
}
/* Signals telling us something went wrong */
if
(
(1 == 2)
#ifdef SIGQUIT
||
(Signal == SIGQUIT) /* Quit */
#endif
#ifdef SIGILL
||
(Signal == SIGILL) /* Illegal instruction */
#endif
#ifdef SIGTRAP
||
(Signal == SIGTRAP) /* Trace trap */
#endif
#ifdef SIGABRT
||
(Signal == SIGABRT) /* Abort */
#endif
#ifdef SIGIOT
||
(Signal == SIGIOT) /* Abort? */
#endif
#ifdef SIGEMT
||
(Signal == SIGEMT) /* EMT instruction */
#endif
#ifdef SIGFPE
||
(Signal == SIGFPE) /* Floating-point exception */
#endif
#ifdef SIGBUS
||
(Signal == SIGBUS) /* BUS error */
#endif
#ifdef SIGSEGV
||
(Signal == SIGSEGV) /* Segmentation violation */
#endif
#ifdef SIGSYS
||
(Signal == SIGSYS) /* Non-existent system call invoked */
#endif
#ifdef SIGSTKFLT
||
(Signal == SIGSTKFLT) /* Stack fault */
#endif
#ifdef SIGPWR
||
(Signal == SIGPWR) /* Power failure restart */
#endif
#ifdef SIGTSTP
||
(Signal == SIGTSTP) /* Stop signal from tty */
#endif
#ifdef SIGXCPU
||
(Signal == SIGXCPU) /* Exceeded CPU time limit */
#endif
#ifdef SIGXFSZ
||
(Signal == SIGXFSZ) /* Exceeded file size limit */
#endif
) {
ExitSignals++;
if (ExitSignals >= 3) { exit(0); }
sysprint(BITMASK_ERROR, "Caught signal %d, %s.", Signal, nlstrsignal(Signal));
sysflushfiles();
main_exit("Caught signal %d, %s", Signal, nlstrsignal(Signal));
main_loop();
return;
}
/* And basically just print anything else */
sysprint(BITMASK_MAIN, "Caught signal %d, %s.", Signal, nlstrsignal(Signal));
}
#if !WIN32
/* SYSFORK FUNCTION - JONAS (25.06.2000) */
void sysfork(void) {
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Going into the background...");
PID = fork();
switch(PID) {
case ERROR:
sysprint(BITMASK_ERROR, "Unable to create a child process: [%d] %s", errno, strerror(errno));
exit(1);
case SUCCESS:
if (setsid() == ERROR) {
sysprint(BITMASK_ERROR, "Unable to request a new session: [%d] %s", errno, strerror(errno));
exit(1);
}
break;
default:
exit(0);
}
sysopenfiles_bg();
PID = getpid();
syswritepid();
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Successfully went into the background, PID: %ld", (PRINT_PID_T) PID);
ScreenMode = FALSE;
}
#endif
/* SYSPRINT FUNCTION - JONAS (25.06.2000) */
void sysprint(const unsigned long int Bitmask, const char *const LinePT, ...) {
char Line[LINELEN+1] = "";
va_list Args = { 0 };
unsigned short int Index = 0;
assert(LinePT != NULL);
va_start(Args, LinePT);
vsnprintf(Line, LINELEN+1, LinePT, Args);
va_end(Args);
for (Index = 0 ; Index < PrintFileS_Len ; Index++) {
if (PrintFileS[Index].FilePT == NULL) { continue; }
if ((ScreenMode == TRUE) && (ScreenPrint == TRUE) && ((PrintFileS[Index].FilePT == stdout) || (PrintFileS[Index].FilePT == stderr))) { continue; }
if (PrintFileS[Index].Bitmask & Bitmask) {
fprintf(PrintFileS[Index].FilePT, "%s *** %s%s", dtstamp(), Line, LINEFEED);
fflush(PrintFileS[Index].FilePT);
}
}
if ((ScreenMode == TRUE) && (ScreenPrint == TRUE) && (ScreenBitmask & Bitmask)) {
if (ScreenDTS == TRUE) { fprintf(stdout, "%s *** %s\n", dtstamp(), Line); }
else { fprintf(stdout, "%s\n", Line); }
fflush(stdin);
fflush(stdout);
fflush(stderr);
}
#if DCC
dcc_conn_sendall(Bitmask, "*** %s\r\n", Line);
#endif
}
/* DEBUGPRINT FUNCTION - JONAS (01.12.2007) */
void debugprint(const char *const FilePT, const unsigned short int Line, const char *const FunctionPT, const char *const TextLinePT, ...) {
char TextLine[LINELEN+1] = "";
va_list Args = { 0 };
unsigned short int Index = 0;
assert(FilePT != NULL);
assert(FunctionPT != NULL);
assert(TextLinePT != NULL);
va_start(Args, TextLinePT);
vsnprintf(TextLine, LINELEN+1, TextLinePT, Args);
va_end(Args);
for (Index = 0 ; Index < PrintFileS_Len ; Index++) {
if ((PrintFileS[Index].Bitmask & BITMASK_DEBUG) && (PrintFileS[Index].FilePT != NULL)) {
fprintf(PrintFileS[Index].FilePT, "%s *** DEBUG *** FILE: %s LINE: %d FUNCTION: %s *** %s%s", dtstamp(), FilePT, Line, FunctionPT, TextLine, LINEFEED);
fflush(PrintFileS[Index].FilePT);
}
}
if ((ScreenMode == TRUE) && (ScreenPrint == TRUE) && (ScreenBitmask & BITMASK_DEBUG)) {
if (ScreenDTS == TRUE) { fprintf(stdout, "%s *** DEBUG *** FILE: %s LINE: %d FUNCTION: %s *** %s%s", dtstamp(), FilePT, Line, FunctionPT, TextLine, LINEFEED); }
else { fprintf(stdout, "*** DEBUG *** FILE: %s LINE: %d FUNCTION: %s *** %s%s", FilePT, Line, FunctionPT, TextLine, LINEFEED); }
fflush(stdin);
fflush(stdout);
fflush(stderr);
}
#if DCC
dcc_conn_sendall(BITMASK_DEBUG, "*** %s\r\n", Line);
#endif
}
/* SYSREHASH FUNCTION - JONAS (01.07.2000) */
void sysrehash(void) {
FILE *FilePT = fopen(ConfS.PIDFile, "r");
char Line[LINELEN+1] = "";
char *LinePT = NULL;
pid_t pid = 0;
signed long int Result = 0;
if (FilePT == NULL) {
printf("Cannot rehash %s: Unable to open PID file %s: [%d] %s\n", PACKAGE, ConfS.PIDFile, errno, strerror(errno));
return;
}
LinePT = fgets(Line, LINELEN, FilePT);
if (LinePT != NULL) pid = atoi(LinePT);
if (pid <= 1) {
printf("Cannot rehash %s: Invalid PID: %ld.\n", PACKAGE, (PRINT_PID_T) pid);
return;
}
Result = kill(pid, SIGHUP);
if (Result == ERROR) {
printf("Cannot rehash %s, PID: %ld: [%d] %s\n", PACKAGE, (PRINT_PID_T) pid, errno, strerror(errno));
fclose(FilePT);
return;
}
printf("Sent HUP signal to %s, PID: %ld.\n", PACKAGE, (PRINT_PID_T) pid);
fclose(FilePT);
}
/* SYSTERM FUNCTION - JONAS (01.07.2000) */
void systerm(void) {
FILE *FilePT = fopen(ConfS.PIDFile, "r");
char Line[LINELEN+1] = "";
char *LinePT = NULL;
pid_t pid = 0;
signed long int Result = 0;
if (FilePT == NULL) {
printf("Cannot terminate %s: Unable to open PID file %s: [%d] %s\n", PACKAGE, ConfS.PIDFile, errno, strerror(errno));
return;
}
LinePT = fgets(Line, LINELEN, FilePT);
if (LinePT != NULL) pid = atoi(Line);
if (pid <= 1) {
printf("Cannot terminate %s: Invalid PID: %ld.\n", PACKAGE, (PRINT_PID_T) pid);
return;
}
Result = kill(pid, SIGTERM);
if (Result == ERROR) {
printf("Cannot terminate %s, PID: %ld: [%d] %s\n", PACKAGE, (PRINT_PID_T) pid, errno, strerror(errno));
fclose(FilePT);
return;
}
printf("Sent TERM signal to %s, PID: %ld.\n", PACKAGE, (PRINT_PID_T) pid);
fclose(FilePT);
}
/* SYSRUN FUNCTION - JONAS (01.07.2000) */
signed short int sysrun(const char *const CmdPT, char *ResultPT) {
FILE *FilePT = NULL;
signed long int Result = 0;
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Running shell command: %s", CmdPT);
FilePT = popen(CmdPT, "r");
if (FilePT == NULL) { return(ERROR); }
Result = fread(ResultPT, sizeof(char), RECVBUFFERLEN, FilePT);
pclose(FilePT);
return(Result);
}
#if !WIN32
/* SYSGETUIDFROMUSER FUNCTION - JONAS (01.07.2000) */
#if HAVE_GETPWNAM
uid_t sysgetuidfromuser(const char *const UserPT) {
struct passwd *PasswdPT = NULL;
assert(UserPT != NULL);
PasswdPT = getpwnam(UserPT);
if (PasswdPT == NULL) {
aerrno = AENOMATCH;
return(0);
}
aerrno = AESUCCESS;
return(PasswdPT->pw_uid);
}
#else
uid_t sysgetuidfromuser(const char *const UserPT) {
FILE *FilePT = NULL;
char *TempPT = NULL;
char Line[LINELEN+1] = "";
uid_t UID = 0;
assert(UserPT != NULL);
FilePT = fopen(PASSWD_FILE, "r");
if (FilePT == NULL) {
sysprint(BITMASK_ERROR, "Unable to open %s: [%d] %s", PASSWD_FILE, errno, strerror(errno));
aerrno = AENORESOURCE;
return(0);
}
FOREVERLOOP {
TempPT = fgets(Line, LINELEN, FilePT);
if (TempPT == NULL) { break; }
while ((TempPT = strchr(Line, '\r')) != NULL) { *TempPT = '\0'; }
while ((TempPT = strchr(Line, '\n')) != NULL) { *TempPT = '\0'; }
if ((Line[0] == '#') || (Line[0] == ';') || (Line[0] == '\0')) { continue; }
TempPT = strtok(Line, ":");
if (TempPT == NULL) { continue; }
if (strcmp(TempPT, UserPT) != FALSE) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
UID = strtoul(TempPT, NULL, 0);
fclose(FilePT);
aerrno = AESUCCESS;
return(UID);
}
fclose(FilePT);
aerrno = AENOMATCH;
return(0);
}
#endif /* HAVE_GETPWNAM */
#endif /* !WIN32 */
#if !WIN32
/* SYSGETNAMEFROMUSER FUNCTION - JONAS (01.07.2000) */
#if HAVE_GETPWNAM
char *sysgetnamefromuser(const char *const UserPT) {
struct passwd *PasswdPT = NULL;
assert(UserPT != NULL);
PasswdPT = getpwnam(UserPT);
if (PasswdPT == NULL) { return(NULL); }
TMPSTRPT = strrealloc(TMPSTRPT, PasswdPT->pw_gecos);
return(TMPSTRPT);
}
#else
char *sysgetnamefromuser(const char *const UserPT) {
FILE *FilePT = NULL;
char *TempPT = NULL;
char Line[LINELEN+1] = "";
assert(UserPT != NULL);
FilePT = fopen(PASSWD_FILE, "r");
if (FilePT == NULL) {
sysprint(BITMASK_ERROR, "Unable to open %s: [%d] %s", PASSWD_FILE, errno, strerror(errno));
return(NULL);
}
FOREVERLOOP {
TempPT = fgets(Line, LINELEN, FilePT);
if (TempPT == NULL) { break; }
while ((TempPT = strchr(Line, '\r')) != NULL) { *TempPT = '\0'; }
while ((TempPT = strchr(Line, '\n')) != NULL) { *TempPT = '\0'; }
if ((Line[0] == '#') || (Line[0] == ';') || (Line[0] == '\0')) { continue; }
TempPT = strtok(Line, ":");
if (TempPT == NULL) { continue; }
if (strcmp(TempPT, UserPT) != FALSE) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
fclose(FilePT);
TMPSTRPT = strrealloc(TMPSTRPT, TempPT);
return(TMPSTRPT);
}
fclose(FilePT);
return(NULL);
}
#endif
#endif
#if !WIN32
/* SYSGETHOMEDIRFROMUSER FUNCTION - JONAS (01.07.2000) */
#if HAVE_GETPWNAM
char *sysgethomedirfromuser(const char *const UserPT) {
struct passwd *PasswdPT = NULL;
assert(UserPT != NULL);
PasswdPT = getpwnam(UserPT);
if (PasswdPT == NULL) { return(NULL); }
TMPSTRPT = strrealloc(TMPSTRPT, PasswdPT->pw_dir);
return(TMPSTRPT);
}
#else
char *sysgethomedirfromuser(const char *const UserPT) {
FILE *FilePT = NULL;
char *TempPT = NULL;
char Line[LINELEN+1] = "";
assert(UserPT != NULL);
FilePT = fopen(PASSWD_FILE, "r");
if (FilePT == NULL) {
sysprint(BITMASK_ERROR, "Unable to open %s: [%d] %s", PASSWD_FILE, errno, strerror(errno));
return(NULL);
}
FOREVERLOOP {
TempPT = fgets(Line, LINELEN, FilePT);
if (TempPT == NULL) { break; }
while ((TempPT = strchr(Line, '\r')) != NULL) { *TempPT = '\0'; }
while ((TempPT = strchr(Line, '\n')) != NULL) { *TempPT = '\0'; }
if ((Line[0] == '#') || (Line[0] == ';') || (Line[0] == '\0')) { continue; }
TempPT = strtok(Line, ":");
if (TempPT == NULL) { continue; }
if (strcmp(TempPT, UserPT) != FALSE) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
fclose(FilePT);
TMPSTRPT = strrealloc(TMPSTRPT, TempPT);
return(TMPSTRPT);
}
fclose(FilePT);
return(NULL);
}
#endif
#endif
#if !WIN32
/* SYSGETGIDFROMGROUP FUNCTION - JONAS (01.07.2000) */
gid_t sysgetgidfromgroup(const char *const GroupPT) {
FILE *FilePT = NULL;
char *TempPT = NULL;
char Line[LINELEN+1] = "";
gid_t GID = 0;
assert(GroupPT != NULL);
FilePT = fopen(GROUP_FILE, "r");
if (FilePT == NULL) {
sysprint(BITMASK_ERROR, "Unable to open %s: [%d] %s", GROUP_FILE, errno, strerror(errno));
aerrno = AENORESOURCE;
return(0);
}
FOREVERLOOP {
TempPT = fgets(Line, LINELEN, FilePT);
if (TempPT == NULL) { break; }
while ((TempPT = strchr(Line, '\r')) != NULL) { *TempPT = '\0'; }
while ((TempPT = strchr(Line, '\n')) != NULL) { *TempPT = '\0'; }
if ((Line[0] == '#') || (Line[0] == ';') || (Line[0] == '\0')) { continue; }
TempPT = strtok(Line, ":");
if (TempPT == NULL) { continue; }
if (strcmp(TempPT, GroupPT) != FALSE) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
TempPT = strtok(NULL, ":");
if (TempPT == NULL) { continue; }
GID = strtoul(TempPT, NULL, 0);
fclose(FilePT);
aerrno = AESUCCESS;
return(GID);
}
aerrno = AENOMATCH;
fclose(FilePT);
return(0);
}
#endif
/* SYSCLEANUP FUNCTION - JONAS (01.07.2000) */
void syscleanup(void) {
unsigned short int Index = 0;
DEBUGPRINT(BITMASK_DEBUG_SYSCALLS, "Freeing %s allocated memory.", __FILE__);
FREE(TMPSTRPT);
for (Index = 0 ; Index < PrintFileS_Len ; ++Index) {
FREE(PrintFileS[Index].Name);
}
}
/* NL_NET_ATON FUNCTION - JONAS (01.07.2000) */
int nl_net_aton(const char *HostIPS, struct in_addr *InAddr) {
signed long int Result = INADDR_NONE;
Result = inet_addr(HostIPS);
if (Result == INADDR_NONE) {
return(0);
}
InAddr->s_addr = Result;
return(1);
}
syntax highlighted by Code2HTML, v. 0.9.1