Serenity Operating System
at master 139 lines 3.8 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7// Has to be defined before including due to legacy Unices 8#define SYSLOG_NAMES 1 9 10#include <AK/DeprecatedString.h> 11#include <AK/StringBuilder.h> 12#include <stdio.h> 13#include <string.h> 14#include <syslog.h> 15#include <unistd.h> 16 17// This implementation doesn't talk to a syslog server. Any options related to 18// that are no-ops. 19 20extern "C" { 21 22// For implementation simplicity, we actually only use the re-entrant version 23// of each function, and the version that isn't just redirects with a static 24// struct to share. 25static struct syslog_data global_log_data = { 26 .ident = nullptr, 27 .logopt = 0, 28 .facility = LOG_USER, 29 .maskpri = LOG_UPTO(LOG_DEBUG) 30}; 31 32// Used when ident is null, since syslog traditionally prints the program's 33// own name; the process name will always be the same unless we exec. 34static char program_name_buffer[256]; 35static bool program_name_set = false; 36 37// Convenience function for initialization and checking what string to use 38// for the program name. 39static char const* get_syslog_ident(struct syslog_data* data) 40{ 41 if (!program_name_set && data->ident == nullptr) 42 program_name_set = get_process_name(program_name_buffer, sizeof(program_name_buffer)) >= 0; 43 44 if (data->ident != nullptr) 45 return data->ident; 46 else if (program_name_set) 47 return program_name_buffer; 48 49 VERIFY_NOT_REACHED(); 50} 51 52void openlog_r(char const* ident, int logopt, int facility, struct syslog_data* data) 53{ 54 data->ident = ident; 55 data->logopt = logopt; 56 data->facility = facility; 57 // default value 58 data->maskpri = LOG_UPTO(LOG_DEBUG); 59 // would be where we connect to a daemon 60} 61 62void openlog(char const* ident, int logopt, int facility) 63{ 64 openlog_r(ident, logopt, facility, &global_log_data); 65} 66 67void closelog_r(struct syslog_data* data) 68{ 69 // would be where we disconnect from a daemon 70 // restore defaults 71 data->ident = nullptr; 72 data->logopt = 0; 73 data->facility = LOG_USER; 74 data->maskpri = LOG_UPTO(LOG_DEBUG); 75} 76 77void closelog(void) 78{ 79 closelog_r(&global_log_data); 80} 81 82int setlogmask_r(int maskpri, struct syslog_data* data) 83{ 84 // Remember, this takes the input of LOG_MASK/LOG_UPTO 85 int old_maskpri = data->maskpri; 86 data->maskpri = maskpri; 87 return old_maskpri; 88} 89 90int setlogmask(int maskpri) 91{ 92 return setlogmask_r(maskpri, &global_log_data); 93} 94 95void syslog_r(int priority, struct syslog_data* data, char const* message, ...) 96{ 97 va_list ap; 98 va_start(ap, message); 99 vsyslog_r(priority, data, message, ap); 100 va_end(ap); 101} 102 103void syslog(int priority, char const* message, ...) 104{ 105 va_list ap; 106 va_start(ap, message); 107 vsyslog_r(priority, &global_log_data, message, ap); 108 va_end(ap); 109} 110 111void vsyslog_r(int priority, struct syslog_data* data, char const* message, va_list args) 112{ 113 StringBuilder combined; 114 115 int real_priority = LOG_PRI(priority); 116 // Lots of parens, but it just extracts the priority from combo and masks. 117 if (!(data->maskpri & LOG_MASK(real_priority))) 118 return; 119 120 // Some metadata would be consumed by a syslog daemon, if we had one. 121 if (data->logopt & LOG_PID) 122 combined.appendff("{}[{}]: ", get_syslog_ident(data), getpid()); 123 else 124 combined.appendff("{}: ", get_syslog_ident(data)); 125 126 combined.appendvf(message, args); 127 auto combined_string = combined.to_deprecated_string(); 128 129 if (data->logopt & LOG_CONS) 130 dbgputstr(combined_string.characters(), combined_string.length()); 131 if (data->logopt & LOG_PERROR) 132 fputs(combined_string.characters(), stderr); 133} 134 135void vsyslog(int priority, char const* message, va_list args) 136{ 137 vsyslog_r(priority, &global_log_data, message, args); 138} 139}