1b528cefcSMark Murray /* 28373020dSJacques Vidrine * Copyright (c) 1997-2002 Kungliga Tekniska H�gskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "krb5_locl.h" 35b528cefcSMark Murray 36*0cadf2f4SJacques Vidrine RCSID("$Id: log.c,v 1.31 2002/09/05 14:59:14 joda Exp $"); 37b528cefcSMark Murray 38b528cefcSMark Murray struct facility { 39b528cefcSMark Murray int min; 40b528cefcSMark Murray int max; 41b528cefcSMark Murray krb5_log_log_func_t log; 42b528cefcSMark Murray krb5_log_close_func_t close; 43b528cefcSMark Murray void *data; 44b528cefcSMark Murray }; 45b528cefcSMark Murray 46b528cefcSMark Murray static struct facility* 47b528cefcSMark Murray log_realloc(krb5_log_facility *f) 48b528cefcSMark Murray { 49b528cefcSMark Murray struct facility *fp; 50b528cefcSMark Murray f->len++; 51b528cefcSMark Murray fp = realloc(f->val, f->len * sizeof(*f->val)); 52b528cefcSMark Murray if(fp == NULL) 53b528cefcSMark Murray return NULL; 54b528cefcSMark Murray f->val = fp; 55b528cefcSMark Murray fp += f->len - 1; 56b528cefcSMark Murray return fp; 57b528cefcSMark Murray } 58b528cefcSMark Murray 59b528cefcSMark Murray struct s2i { 608373020dSJacques Vidrine const char *s; 61b528cefcSMark Murray int val; 62b528cefcSMark Murray }; 63b528cefcSMark Murray 64b528cefcSMark Murray #define L(X) { #X, LOG_ ## X } 65b528cefcSMark Murray 665e9cd1aeSAssar Westerlund static struct s2i syslogvals[] = { 67b528cefcSMark Murray L(EMERG), 68b528cefcSMark Murray L(ALERT), 69b528cefcSMark Murray L(CRIT), 70b528cefcSMark Murray L(ERR), 71b528cefcSMark Murray L(WARNING), 72b528cefcSMark Murray L(NOTICE), 73b528cefcSMark Murray L(INFO), 74b528cefcSMark Murray L(DEBUG), 75b528cefcSMark Murray 76b528cefcSMark Murray L(AUTH), 77b528cefcSMark Murray #ifdef LOG_AUTHPRIV 78b528cefcSMark Murray L(AUTHPRIV), 79b528cefcSMark Murray #endif 80b528cefcSMark Murray #ifdef LOG_CRON 81b528cefcSMark Murray L(CRON), 82b528cefcSMark Murray #endif 83b528cefcSMark Murray L(DAEMON), 84b528cefcSMark Murray #ifdef LOG_FTP 85b528cefcSMark Murray L(FTP), 86b528cefcSMark Murray #endif 87b528cefcSMark Murray L(KERN), 88b528cefcSMark Murray L(LPR), 89b528cefcSMark Murray L(MAIL), 90b528cefcSMark Murray #ifdef LOG_NEWS 91b528cefcSMark Murray L(NEWS), 92b528cefcSMark Murray #endif 93b528cefcSMark Murray L(SYSLOG), 94b528cefcSMark Murray L(USER), 95b528cefcSMark Murray #ifdef LOG_UUCP 96b528cefcSMark Murray L(UUCP), 97b528cefcSMark Murray #endif 98b528cefcSMark Murray L(LOCAL0), 99b528cefcSMark Murray L(LOCAL1), 100b528cefcSMark Murray L(LOCAL2), 101b528cefcSMark Murray L(LOCAL3), 102b528cefcSMark Murray L(LOCAL4), 103b528cefcSMark Murray L(LOCAL5), 104b528cefcSMark Murray L(LOCAL6), 105b528cefcSMark Murray L(LOCAL7), 106b528cefcSMark Murray { NULL, -1 } 107b528cefcSMark Murray }; 108b528cefcSMark Murray 109b528cefcSMark Murray static int 110b528cefcSMark Murray find_value(const char *s, struct s2i *table) 111b528cefcSMark Murray { 112b528cefcSMark Murray while(table->s && strcasecmp(table->s, s)) 113b528cefcSMark Murray table++; 114b528cefcSMark Murray return table->val; 115b528cefcSMark Murray } 116b528cefcSMark Murray 117b528cefcSMark Murray krb5_error_code 118b528cefcSMark Murray krb5_initlog(krb5_context context, 119b528cefcSMark Murray const char *program, 120b528cefcSMark Murray krb5_log_facility **fac) 121b528cefcSMark Murray { 122b528cefcSMark Murray krb5_log_facility *f = calloc(1, sizeof(*f)); 123adb0ddaeSAssar Westerlund if(f == NULL) { 124adb0ddaeSAssar Westerlund krb5_set_error_string (context, "malloc: out of memory"); 125b528cefcSMark Murray return ENOMEM; 126adb0ddaeSAssar Westerlund } 127b528cefcSMark Murray f->program = strdup(program); 128b528cefcSMark Murray if(f->program == NULL){ 129b528cefcSMark Murray free(f); 130adb0ddaeSAssar Westerlund krb5_set_error_string (context, "malloc: out of memory"); 131b528cefcSMark Murray return ENOMEM; 132b528cefcSMark Murray } 133b528cefcSMark Murray *fac = f; 134b528cefcSMark Murray return 0; 135b528cefcSMark Murray } 136b528cefcSMark Murray 137b528cefcSMark Murray krb5_error_code 138b528cefcSMark Murray krb5_addlog_func(krb5_context context, 139b528cefcSMark Murray krb5_log_facility *fac, 140b528cefcSMark Murray int min, 141b528cefcSMark Murray int max, 142b528cefcSMark Murray krb5_log_log_func_t log, 143b528cefcSMark Murray krb5_log_close_func_t close, 144b528cefcSMark Murray void *data) 145b528cefcSMark Murray { 146b528cefcSMark Murray struct facility *fp = log_realloc(fac); 147adb0ddaeSAssar Westerlund if(fp == NULL) { 148adb0ddaeSAssar Westerlund krb5_set_error_string (context, "malloc: out of memory"); 149b528cefcSMark Murray return ENOMEM; 150adb0ddaeSAssar Westerlund } 151b528cefcSMark Murray fp->min = min; 152b528cefcSMark Murray fp->max = max; 153b528cefcSMark Murray fp->log = log; 154b528cefcSMark Murray fp->close = close; 155b528cefcSMark Murray fp->data = data; 156b528cefcSMark Murray return 0; 157b528cefcSMark Murray } 158b528cefcSMark Murray 159b528cefcSMark Murray 1608373020dSJacques Vidrine struct _heimdal_syslog_data{ 161b528cefcSMark Murray int priority; 162b528cefcSMark Murray }; 163b528cefcSMark Murray 164b528cefcSMark Murray static void 165b528cefcSMark Murray log_syslog(const char *time, 166b528cefcSMark Murray const char *msg, 167b528cefcSMark Murray void *data) 168b528cefcSMark Murray 169b528cefcSMark Murray { 1708373020dSJacques Vidrine struct _heimdal_syslog_data *s = data; 171b528cefcSMark Murray syslog(s->priority, "%s", msg); 172b528cefcSMark Murray } 173b528cefcSMark Murray 174b528cefcSMark Murray static void 175b528cefcSMark Murray close_syslog(void *data) 176b528cefcSMark Murray { 177b528cefcSMark Murray free(data); 178b528cefcSMark Murray closelog(); 179b528cefcSMark Murray } 180b528cefcSMark Murray 181b528cefcSMark Murray static krb5_error_code 182b528cefcSMark Murray open_syslog(krb5_context context, 183b528cefcSMark Murray krb5_log_facility *facility, int min, int max, 184b528cefcSMark Murray const char *sev, const char *fac) 185b528cefcSMark Murray { 1868373020dSJacques Vidrine struct _heimdal_syslog_data *sd = malloc(sizeof(*sd)); 187b528cefcSMark Murray int i; 188b528cefcSMark Murray 189adb0ddaeSAssar Westerlund if(sd == NULL) { 190adb0ddaeSAssar Westerlund krb5_set_error_string (context, "malloc: out of memory"); 191b528cefcSMark Murray return ENOMEM; 192adb0ddaeSAssar Westerlund } 193b528cefcSMark Murray i = find_value(sev, syslogvals); 194b528cefcSMark Murray if(i == -1) 195b528cefcSMark Murray i = LOG_ERR; 196b528cefcSMark Murray sd->priority = i; 197b528cefcSMark Murray i = find_value(fac, syslogvals); 198b528cefcSMark Murray if(i == -1) 199b528cefcSMark Murray i = LOG_AUTH; 200b528cefcSMark Murray sd->priority |= i; 201b528cefcSMark Murray roken_openlog(facility->program, LOG_PID | LOG_NDELAY, i); 202b528cefcSMark Murray return krb5_addlog_func(context, facility, min, max, 203b528cefcSMark Murray log_syslog, close_syslog, sd); 204b528cefcSMark Murray } 205b528cefcSMark Murray 206b528cefcSMark Murray struct file_data{ 2078373020dSJacques Vidrine const char *filename; 2088373020dSJacques Vidrine const char *mode; 209b528cefcSMark Murray FILE *fd; 210b528cefcSMark Murray int keep_open; 211b528cefcSMark Murray }; 212b528cefcSMark Murray 213b528cefcSMark Murray static void 214b528cefcSMark Murray log_file(const char *time, 215b528cefcSMark Murray const char *msg, 216b528cefcSMark Murray void *data) 217b528cefcSMark Murray { 218b528cefcSMark Murray struct file_data *f = data; 219b528cefcSMark Murray if(f->keep_open == 0) 220b528cefcSMark Murray f->fd = fopen(f->filename, f->mode); 221b528cefcSMark Murray if(f->fd == NULL) 222b528cefcSMark Murray return; 223b528cefcSMark Murray fprintf(f->fd, "%s %s\n", time, msg); 224b528cefcSMark Murray if(f->keep_open == 0) 225b528cefcSMark Murray fclose(f->fd); 226b528cefcSMark Murray } 227b528cefcSMark Murray 228b528cefcSMark Murray static void 229b528cefcSMark Murray close_file(void *data) 230b528cefcSMark Murray { 231b528cefcSMark Murray struct file_data *f = data; 232b528cefcSMark Murray if(f->keep_open && f->filename) 233b528cefcSMark Murray fclose(f->fd); 234b528cefcSMark Murray free(data); 235b528cefcSMark Murray } 236b528cefcSMark Murray 237b528cefcSMark Murray static krb5_error_code 238b528cefcSMark Murray open_file(krb5_context context, krb5_log_facility *fac, int min, int max, 2398373020dSJacques Vidrine const char *filename, const char *mode, FILE *f, int keep_open) 240b528cefcSMark Murray { 241b528cefcSMark Murray struct file_data *fd = malloc(sizeof(*fd)); 242adb0ddaeSAssar Westerlund if(fd == NULL) { 243adb0ddaeSAssar Westerlund krb5_set_error_string (context, "malloc: out of memory"); 244b528cefcSMark Murray return ENOMEM; 245adb0ddaeSAssar Westerlund } 246b528cefcSMark Murray fd->filename = filename; 247b528cefcSMark Murray fd->mode = mode; 248b528cefcSMark Murray fd->fd = f; 249b528cefcSMark Murray fd->keep_open = keep_open; 250b528cefcSMark Murray 251b528cefcSMark Murray return krb5_addlog_func(context, fac, min, max, log_file, close_file, fd); 252b528cefcSMark Murray } 253b528cefcSMark Murray 254b528cefcSMark Murray 255b528cefcSMark Murray 256b528cefcSMark Murray krb5_error_code 257adb0ddaeSAssar Westerlund krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) 258b528cefcSMark Murray { 259b528cefcSMark Murray krb5_error_code ret = 0; 260b528cefcSMark Murray int min = 0, max = -1, n; 261b528cefcSMark Murray char c; 262adb0ddaeSAssar Westerlund const char *p = orig; 263adb0ddaeSAssar Westerlund 264b528cefcSMark Murray n = sscanf(p, "%d%c%d/", &min, &c, &max); 265b528cefcSMark Murray if(n == 2){ 266b528cefcSMark Murray if(c == '/') { 267b528cefcSMark Murray if(min < 0){ 268b528cefcSMark Murray max = -min; 269b528cefcSMark Murray min = 0; 270b528cefcSMark Murray }else{ 271b528cefcSMark Murray max = min; 272b528cefcSMark Murray } 273b528cefcSMark Murray } 274b528cefcSMark Murray } 275b528cefcSMark Murray if(n){ 276b528cefcSMark Murray p = strchr(p, '/'); 277adb0ddaeSAssar Westerlund if(p == NULL) { 278adb0ddaeSAssar Westerlund krb5_set_error_string (context, "failed to parse \"%s\"", orig); 279adb0ddaeSAssar Westerlund return HEIM_ERR_LOG_PARSE; 280adb0ddaeSAssar Westerlund } 281b528cefcSMark Murray p++; 282b528cefcSMark Murray } 283b528cefcSMark Murray if(strcmp(p, "STDERR") == 0){ 284b528cefcSMark Murray ret = open_file(context, f, min, max, NULL, NULL, stderr, 1); 285b528cefcSMark Murray }else if(strcmp(p, "CONSOLE") == 0){ 286b528cefcSMark Murray ret = open_file(context, f, min, max, "/dev/console", "w", NULL, 0); 287b528cefcSMark Murray }else if(strncmp(p, "FILE:", 4) == 0 && (p[4] == ':' || p[4] == '=')){ 288b528cefcSMark Murray char *fn; 289b528cefcSMark Murray FILE *file = NULL; 290b528cefcSMark Murray int keep_open = 0; 291b528cefcSMark Murray fn = strdup(p + 5); 292adb0ddaeSAssar Westerlund if(fn == NULL) { 293adb0ddaeSAssar Westerlund krb5_set_error_string (context, "malloc: out of memory"); 294b528cefcSMark Murray return ENOMEM; 295adb0ddaeSAssar Westerlund } 296b528cefcSMark Murray if(p[4] == '='){ 297b528cefcSMark Murray int i = open(fn, O_WRONLY | O_CREAT | 298b528cefcSMark Murray O_TRUNC | O_APPEND, 0666); 299adb0ddaeSAssar Westerlund if(i < 0) { 300adb0ddaeSAssar Westerlund ret = errno; 301adb0ddaeSAssar Westerlund krb5_set_error_string (context, "open(%s): %s", fn, 302adb0ddaeSAssar Westerlund strerror(ret)); 303adb0ddaeSAssar Westerlund return ret; 304adb0ddaeSAssar Westerlund } 305b528cefcSMark Murray file = fdopen(i, "a"); 306b528cefcSMark Murray if(file == NULL){ 307adb0ddaeSAssar Westerlund ret = errno; 308b528cefcSMark Murray close(i); 309adb0ddaeSAssar Westerlund krb5_set_error_string (context, "fdopen(%s): %s", fn, 310adb0ddaeSAssar Westerlund strerror(ret)); 311adb0ddaeSAssar Westerlund return ret; 312b528cefcSMark Murray } 313b528cefcSMark Murray keep_open = 1; 314b528cefcSMark Murray } 315b528cefcSMark Murray ret = open_file(context, f, min, max, fn, "a", file, keep_open); 316b528cefcSMark Murray }else if(strncmp(p, "DEVICE=", 6) == 0){ 317b528cefcSMark Murray ret = open_file(context, f, min, max, strdup(p + 7), "w", NULL, 0); 3188373020dSJacques Vidrine }else if(strncmp(p, "SYSLOG", 6) == 0 && (p[6] == '\0' || p[6] == ':')){ 3198373020dSJacques Vidrine char severity[128] = ""; 3208373020dSJacques Vidrine char facility[128] = ""; 3218373020dSJacques Vidrine p += 6; 3228373020dSJacques Vidrine if(*p != '\0') 3238373020dSJacques Vidrine p++; 3248373020dSJacques Vidrine if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1) 3258373020dSJacques Vidrine strsep_copy(&p, ":", facility, sizeof(facility)); 3268373020dSJacques Vidrine if(*severity == '\0') 3278373020dSJacques Vidrine strlcpy(severity, "ERR", sizeof(severity)); 3288373020dSJacques Vidrine if(*facility == '\0') 3298373020dSJacques Vidrine strlcpy(facility, "AUTH", sizeof(facility)); 330b528cefcSMark Murray ret = open_syslog(context, f, min, max, severity, facility); 331b528cefcSMark Murray }else{ 332adb0ddaeSAssar Westerlund krb5_set_error_string (context, "unknown log type: %s", p); 333b528cefcSMark Murray ret = HEIM_ERR_LOG_PARSE; /* XXX */ 334b528cefcSMark Murray } 335b528cefcSMark Murray return ret; 336b528cefcSMark Murray } 337b528cefcSMark Murray 338b528cefcSMark Murray 339b528cefcSMark Murray krb5_error_code 340b528cefcSMark Murray krb5_openlog(krb5_context context, 341b528cefcSMark Murray const char *program, 342b528cefcSMark Murray krb5_log_facility **fac) 343b528cefcSMark Murray { 344b528cefcSMark Murray krb5_error_code ret; 345b528cefcSMark Murray char **p, **q; 346b528cefcSMark Murray 347b528cefcSMark Murray ret = krb5_initlog(context, program, fac); 348b528cefcSMark Murray if(ret) 349b528cefcSMark Murray return ret; 350b528cefcSMark Murray 351b528cefcSMark Murray p = krb5_config_get_strings(context, NULL, "logging", program, NULL); 352b528cefcSMark Murray if(p == NULL) 353b528cefcSMark Murray p = krb5_config_get_strings(context, NULL, "logging", "default", NULL); 354b528cefcSMark Murray if(p){ 355b528cefcSMark Murray for(q = p; *q; q++) 356b528cefcSMark Murray ret = krb5_addlog_dest(context, *fac, *q); 357b528cefcSMark Murray krb5_config_free_strings(p); 358b528cefcSMark Murray }else 359b528cefcSMark Murray ret = krb5_addlog_dest(context, *fac, "SYSLOG"); 360b528cefcSMark Murray return 0; 361b528cefcSMark Murray } 362b528cefcSMark Murray 363b528cefcSMark Murray krb5_error_code 364b528cefcSMark Murray krb5_closelog(krb5_context context, 365b528cefcSMark Murray krb5_log_facility *fac) 366b528cefcSMark Murray { 367b528cefcSMark Murray int i; 368b528cefcSMark Murray for(i = 0; i < fac->len; i++) 3694137ff4cSJacques Vidrine (*fac->val[i].close)(fac->val[i].data); 370b528cefcSMark Murray return 0; 371b528cefcSMark Murray } 372b528cefcSMark Murray 373b528cefcSMark Murray #undef __attribute__ 374b528cefcSMark Murray #define __attribute__(X) 375b528cefcSMark Murray 376b528cefcSMark Murray krb5_error_code 377b528cefcSMark Murray krb5_vlog_msg(krb5_context context, 378b528cefcSMark Murray krb5_log_facility *fac, 379b528cefcSMark Murray char **reply, 380b528cefcSMark Murray int level, 381b528cefcSMark Murray const char *fmt, 382b528cefcSMark Murray va_list ap) 383b528cefcSMark Murray __attribute__((format (printf, 5, 0))) 384b528cefcSMark Murray { 385*0cadf2f4SJacques Vidrine 386*0cadf2f4SJacques Vidrine char *msg = NULL; 387*0cadf2f4SJacques Vidrine const char *actual = NULL; 388b528cefcSMark Murray char buf[64]; 389*0cadf2f4SJacques Vidrine time_t t = 0; 390b528cefcSMark Murray int i; 391b528cefcSMark Murray 392*0cadf2f4SJacques Vidrine for(i = 0; fac && i < fac->len; i++) 393*0cadf2f4SJacques Vidrine if(fac->val[i].min <= level && 394*0cadf2f4SJacques Vidrine (fac->val[i].max < 0 || fac->val[i].max >= level)) { 395*0cadf2f4SJacques Vidrine if(t == 0) { 396b528cefcSMark Murray t = time(NULL); 3975e9cd1aeSAssar Westerlund krb5_format_time(context, t, buf, sizeof(buf), TRUE); 398*0cadf2f4SJacques Vidrine } 399*0cadf2f4SJacques Vidrine if(actual == NULL) { 400*0cadf2f4SJacques Vidrine vasprintf(&msg, fmt, ap); 401*0cadf2f4SJacques Vidrine if(msg == NULL) 402*0cadf2f4SJacques Vidrine actual = fmt; 403*0cadf2f4SJacques Vidrine else 404*0cadf2f4SJacques Vidrine actual = msg; 405*0cadf2f4SJacques Vidrine } 4065e9cd1aeSAssar Westerlund (*fac->val[i].log)(buf, actual, fac->val[i].data); 407*0cadf2f4SJacques Vidrine } 408*0cadf2f4SJacques Vidrine if(reply == NULL) 409*0cadf2f4SJacques Vidrine free(msg); 410*0cadf2f4SJacques Vidrine else 411b528cefcSMark Murray *reply = msg; 412b528cefcSMark Murray return 0; 413b528cefcSMark Murray } 414b528cefcSMark Murray 415b528cefcSMark Murray krb5_error_code 416b528cefcSMark Murray krb5_vlog(krb5_context context, 417b528cefcSMark Murray krb5_log_facility *fac, 418b528cefcSMark Murray int level, 419b528cefcSMark Murray const char *fmt, 420b528cefcSMark Murray va_list ap) 421b528cefcSMark Murray __attribute__((format (printf, 4, 0))) 422b528cefcSMark Murray { 423*0cadf2f4SJacques Vidrine return krb5_vlog_msg(context, fac, NULL, level, fmt, ap); 424b528cefcSMark Murray } 425b528cefcSMark Murray 426b528cefcSMark Murray krb5_error_code 427b528cefcSMark Murray krb5_log_msg(krb5_context context, 428b528cefcSMark Murray krb5_log_facility *fac, 429b528cefcSMark Murray int level, 430b528cefcSMark Murray char **reply, 431b528cefcSMark Murray const char *fmt, 432b528cefcSMark Murray ...) 433b528cefcSMark Murray __attribute__((format (printf, 5, 6))) 434b528cefcSMark Murray { 435b528cefcSMark Murray va_list ap; 436b528cefcSMark Murray krb5_error_code ret; 437b528cefcSMark Murray 438b528cefcSMark Murray va_start(ap, fmt); 439b528cefcSMark Murray ret = krb5_vlog_msg(context, fac, reply, level, fmt, ap); 440b528cefcSMark Murray va_end(ap); 441b528cefcSMark Murray return ret; 442b528cefcSMark Murray } 443b528cefcSMark Murray 444b528cefcSMark Murray 445b528cefcSMark Murray krb5_error_code 446b528cefcSMark Murray krb5_log(krb5_context context, 447b528cefcSMark Murray krb5_log_facility *fac, 448b528cefcSMark Murray int level, 449b528cefcSMark Murray const char *fmt, 450b528cefcSMark Murray ...) 451b528cefcSMark Murray __attribute__((format (printf, 4, 5))) 452b528cefcSMark Murray { 453b528cefcSMark Murray va_list ap; 454b528cefcSMark Murray krb5_error_code ret; 455b528cefcSMark Murray 456b528cefcSMark Murray va_start(ap, fmt); 457b528cefcSMark Murray ret = krb5_vlog(context, fac, level, fmt, ap); 458b528cefcSMark Murray va_end(ap); 459b528cefcSMark Murray return ret; 460b528cefcSMark Murray } 461b528cefcSMark Murray 462