#include #if !defined(__OpenBSD__) #define __USE_GNU #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include "libglouglou.h" FILE *_logfile; static int _loglevel; static void logit(int, const char *, const char *, va_list); /* * Log * handles only one log file per process */ int gg_log_init(char *filename, int level) { _logfile = fopen(filename, "a+"); if (!_logfile) { printf("cannot open log file %s!\n", filename); return -1; } _loglevel = level; return 0; } void gg_log_shutdown(void) { fclose(_logfile); } void gg_log_tmp(const char *msg, ...) { va_list ap; va_start(ap, msg); logit(GGLOG_FORCED, "XXX ", msg, ap); va_end(ap); } void gg_log_debug(const char *msg, ...) { va_list ap; va_start(ap, msg); logit(GGLOG_DEBUG, "", msg, ap); va_end(ap); } void gg_log_info(const char *msg, ...) { va_list ap; va_start(ap, msg); logit(GGLOG_INFO, "", msg, ap); va_end(ap); } void gg_log_warn(const char *msg, ...) { va_list ap; va_start(ap, msg); logit(GGLOG_WARN, "", msg, ap); va_end(ap); } #if defined(__OpenBSD__) void __dead #else void #endif gg_log_fatal(const char *msg, ...) { va_list ap; va_start(ap, msg); logit(GGLOG_FATAL, "fatal: ", msg, ap); va_end(ap); exit(1); } /* XXX mpsafe */ static void logit(int level, const char *prefix, const char *msg, va_list ap) { time_t clock; if (level <= _loglevel) { time(&clock); fprintf(_logfile, "%d ", (int)clock); vfprintf(_logfile, prefix, ap); vfprintf(_logfile, msg, ap); fprintf(_logfile, "\n"); fflush(_logfile); } } /* * Various utils */ void * xmalloc(size_t size) { void *data; data = malloc(size); if (!data) err(1, "could not malloc %d", (int)size); return data; } void * xcalloc(size_t nmemb, size_t size) { void *data; data = calloc(nmemb, size); if (!data) err(1, "could not calloc %d", (int)size); return data; } void fd_nonblock(int fd) { int flags = fcntl(fd, F_GETFL, 0); int rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK); if (rc == -1) err(1, "failed to set fd %i non-blocking", fd); } void addrcpy(struct sockaddr_in *dst, struct sockaddr_in *src) { dst->sin_addr.s_addr = src->sin_addr.s_addr; dst->sin_port = src->sin_port; dst->sin_family = src->sin_family; } int addrcmp(struct sockaddr_in *a, struct sockaddr_in *b) { if (a->sin_addr.s_addr != b->sin_addr.s_addr) return -1; if (a->sin_port != b->sin_port) return -2; if (a->sin_family != b->sin_family) return -3; return 0; } void droppriv(char *user, int do_chroot, char *chroot_path) { struct passwd *pw; pw = getpwnam(user); if (!pw) err(1, "unknown user %s", user); if (do_chroot) { if (!chroot_path) chroot_path = pw->pw_dir; if (chroot(chroot_path) != 0) err(1, "unable to chroot"); } if (chdir("/") != 0) err(1, "unable to chdir"); if (setgroups(1, &pw->pw_gid) == -1) err(1, "setgroups() failed"); if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) err(1, "setresgid failed"); if (setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid) == -1) err(1, "setresuid() failed"); endpwent(); }