]> git.gag.com Git - debian/sudo/blob - logging.c
Imported Upstream version 1.7.2p5
[debian/sudo] / logging.c
1 /*
2  * Copyright (c) 1994-1996, 1998-2009 Todd C. Miller <Todd.Miller@courtesan.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  *
16  * Sponsored in part by the Defense Advanced Research Projects
17  * Agency (DARPA) and Air Force Research Laboratory, Air Force
18  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
19  */
20
21 #ifdef __TANDEM
22 # include <floss.h>
23 #endif
24
25 #include <config.h>
26
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <sys/stat.h>
30 #include <sys/ioctl.h>
31 #include <sys/wait.h>
32 #include <stdio.h>
33 #ifdef STDC_HEADERS
34 # include <stdlib.h>
35 # include <stddef.h>
36 #else
37 # ifdef HAVE_STDLIB_H
38 #  include <stdlib.h>
39 # endif
40 #endif /* STDC_HEADERS */
41 #ifdef HAVE_STRING_H
42 # include <string.h>
43 #else
44 # ifdef HAVE_STRINGS_H
45 #  include <strings.h>
46 # endif
47 #endif /* HAVE_STRING_H */
48 #ifdef HAVE_UNISTD_H
49 # include <unistd.h>
50 #endif /* HAVE_UNISTD_H */
51 #include <pwd.h>
52 #include <grp.h>
53 #include <signal.h>
54 #include <time.h>
55 #include <errno.h>
56 #include <fcntl.h>
57
58 #include "sudo.h"
59
60 #ifndef lint
61 __unused static const char rcsid[] = "$Sudo: logging.c,v 1.205 2009/05/25 12:02:41 millert Exp $";
62 #endif /* lint */
63
64 static void do_syslog           __P((int, char *));
65 static void do_logfile          __P((char *));
66 static void send_mail           __P((char *));
67 static int should_mail          __P((int));
68 static char *get_timestr        __P((void));
69 static void mysyslog            __P((int, const char *, ...));
70 static char *new_logline        __P((const char *, int));
71
72 #define MAXSYSLOGTRIES  16      /* num of retries for broken syslogs */
73
74 /*
75  * We do an openlog(3)/closelog(3) for each message because some
76  * authentication methods (notably PAM) use syslog(3) for their
77  * own nefarious purposes and may call openlog(3) and closelog(3).
78  * Note that because we don't want to assume that all systems have
79  * vsyslog(3) (HP-UX doesn't) "%m" will not be expanded.
80  * Sadly this is a maze of #ifdefs.
81  */
82 static void
83 #ifdef __STDC__
84 mysyslog(int pri, const char *fmt, ...)
85 #else
86 mysyslog(pri, fmt, va_alist)
87     int pri;
88     const char *fmt;
89     va_dcl
90 #endif
91 {
92 #ifdef BROKEN_SYSLOG
93     int i;
94 #endif
95     char buf[MAXSYSLOGLEN+1];
96     va_list ap;
97
98 #ifdef __STDC__
99     va_start(ap, fmt);
100 #else
101     va_start(ap);
102 #endif
103 #ifdef LOG_NFACILITIES
104     openlog("sudo", 0, def_syslog);
105 #else
106     openlog("sudo", 0);
107 #endif
108     vsnprintf(buf, sizeof(buf), fmt, ap);
109 #ifdef BROKEN_SYSLOG
110     /*
111      * Some versions of syslog(3) don't guarantee success and return
112      * an int (notably HP-UX < 10.0).  So, if at first we don't succeed,
113      * try, try again...
114      */
115     for (i = 0; i < MAXSYSLOGTRIES; i++)
116         if (syslog(pri, "%s", buf) == 0)
117             break;
118 #else
119     syslog(pri, "%s", buf);
120 #endif /* BROKEN_SYSLOG */
121     va_end(ap);
122     closelog();
123 }
124
125 #define FMT_FIRST "%8s : %s"
126 #define FMT_CONTD "%8s : (command continued) %s"
127
128 /*
129  * Log a message to syslog, pre-pending the username and splitting the
130  * message into parts if it is longer than MAXSYSLOGLEN.
131  */
132 static void
133 do_syslog(pri, msg)
134     int pri;
135     char *msg;
136 {
137     size_t len, maxlen;
138     char *p, *tmp, save;
139     const char *fmt;
140
141     /*
142      * Log the full line, breaking into multiple syslog(3) calls if necessary
143      */
144     fmt = FMT_FIRST;
145     maxlen = MAXSYSLOGLEN - (sizeof(FMT_FIRST) - 6 + strlen(user_name));
146     for (p = msg; *p != '\0'; ) {
147         len = strlen(p);
148         if (len > maxlen) {
149             /*
150              * Break up the line into what will fit on one syslog(3) line
151              * Try to avoid breaking words into several lines if possible.
152              */
153             tmp = memrchr(p, ' ', maxlen);
154             if (tmp == NULL)
155                 tmp = p + maxlen;
156
157             /* NULL terminate line, but save the char to restore later */
158             save = *tmp;
159             *tmp = '\0';
160
161             mysyslog(pri, fmt, user_name, p);
162
163             *tmp = save;                        /* restore saved character */
164
165             /* Advance p and eliminate leading whitespace */
166             for (p = tmp; *p == ' '; p++)
167                 ;
168         } else {
169             mysyslog(pri, fmt, user_name, p);
170             p += len;
171         }
172         fmt = FMT_CONTD;
173         maxlen = MAXSYSLOGLEN - (sizeof(FMT_CONTD) - 6 + strlen(user_name));
174     }
175 }
176
177 static void
178 do_logfile(msg)
179     char *msg;
180 {
181     char *full_line;
182     char *beg, *oldend, *end;
183     FILE *fp;
184     mode_t oldmask;
185     size_t maxlen;
186
187     oldmask = umask(077);
188     maxlen = def_loglinelen > 0 ? def_loglinelen : 0;
189     fp = fopen(def_logfile, "a");
190     (void) umask(oldmask);
191     if (fp == NULL) {
192         easprintf(&full_line, "Can't open log file: %s: %s",
193             def_logfile, strerror(errno));
194         send_mail(full_line);
195         efree(full_line);
196     } else if (!lock_file(fileno(fp), SUDO_LOCK)) {
197         easprintf(&full_line, "Can't lock log file: %s: %s",
198             def_logfile, strerror(errno));
199         send_mail(full_line);
200         efree(full_line);
201     } else {
202         if (def_loglinelen == 0) {
203             /* Don't pretty-print long log file lines (hard to grep) */
204             if (def_log_host)
205                 (void) fprintf(fp, "%s : %s : HOST=%s : %s\n", get_timestr(),
206                     user_name, user_shost, msg);
207             else
208                 (void) fprintf(fp, "%s : %s : %s\n", get_timestr(),
209                     user_name, msg);
210         } else {
211             if (def_log_host)
212                 easprintf(&full_line, "%s : %s : HOST=%s : %s", get_timestr(),
213                     user_name, user_shost, msg);
214             else
215                 easprintf(&full_line, "%s : %s : %s", get_timestr(),
216                     user_name, msg);
217
218             /*
219              * Print out full_line with word wrap
220              */
221             beg = end = full_line;
222             while (beg) {
223                 oldend = end;
224                 end = strchr(oldend, ' ');
225
226                 if (maxlen > 0 && end) {
227                     *end = '\0';
228                     if (strlen(beg) > maxlen) {
229                         /* too far, need to back up & print the line */
230
231                         if (beg == (char *)full_line)
232                             maxlen -= 4;        /* don't indent first line */
233
234                         *end = ' ';
235                         if (oldend != beg) {
236                             /* rewind & print */
237                             end = oldend-1;
238                             while (*end == ' ')
239                                 --end;
240                             *(++end) = '\0';
241                             (void) fprintf(fp, "%s\n    ", beg);
242                             *end = ' ';
243                         } else {
244                             (void) fprintf(fp, "%s\n    ", beg);
245                         }
246
247                         /* reset beg to point to the start of the new substr */
248                         beg = end;
249                         while (*beg == ' ')
250                             ++beg;
251                     } else {
252                         /* we still have room */
253                         *end = ' ';
254                     }
255
256                     /* remove leading whitespace */
257                     while (*end == ' ')
258                         ++end;
259                 } else {
260                     /* final line */
261                     (void) fprintf(fp, "%s\n", beg);
262                     beg = NULL;                 /* exit condition */
263                 }
264             }
265             efree(full_line);
266         }
267         (void) fflush(fp);
268         (void) lock_file(fileno(fp), SUDO_UNLOCK);
269         (void) fclose(fp);
270     }
271 }
272
273 /*
274  * Log and mail the denial message, optionally informing the user.
275  */
276 void
277 log_denial(status, inform_user)
278     int status;
279     int inform_user;
280 {
281     char *message;
282     char *logline;
283
284     /* Set error message. */
285     if (ISSET(status, FLAG_NO_USER))
286         message = "user NOT in sudoers";
287     else if (ISSET(status, FLAG_NO_HOST))
288         message = "user NOT authorized on host";
289     else
290         message = "command not allowed";
291
292     logline = new_logline(message, 0);
293
294     if (should_mail(status))
295         send_mail(logline);     /* send mail based on status */
296
297     /* Inform the user if they failed to authenticate.  */
298     if (inform_user) {
299         if (ISSET(status, FLAG_NO_USER))
300             (void) fprintf(stderr, "%s is not in the sudoers file.  %s",
301                 user_name, "This incident will be reported.\n");
302         else if (ISSET(status, FLAG_NO_HOST))
303             (void) fprintf(stderr, "%s is not allowed to run sudo on %s.  %s",
304                 user_name, user_shost, "This incident will be reported.\n");
305         else if (ISSET(status, FLAG_NO_CHECK))
306             (void) fprintf(stderr, "Sorry, user %s may not run sudo on %s.\n",
307                 user_name, user_shost);
308         else
309             (void) fprintf(stderr,
310                 "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n",
311                 user_name, user_cmnd, user_args ? " " : "",
312                 user_args ? user_args : "",
313                 list_pw ? list_pw->pw_name : runas_pw ?
314                 runas_pw->pw_name : user_name, runas_gr ? ":" : "",
315                 runas_gr ? runas_gr->gr_name : "", user_host);
316     }
317
318     /*
319      * Log via syslog and/or a file.
320      */
321     if (def_syslog)
322         do_syslog(def_syslog_badpri, logline);
323     if (def_logfile)
324         do_logfile(logline);
325
326     efree(logline);
327 }
328
329 /*
330  * Log and potentially mail the allowed command.
331  */
332 void
333 log_allowed(status)
334     int status;
335 {
336     char *logline;
337
338     logline = new_logline(NULL, 0);
339
340     if (should_mail(status))
341         send_mail(logline);     /* send mail based on status */
342
343     /*
344      * Log via syslog and/or a file.
345      */
346     if (def_syslog)
347         do_syslog(def_syslog_goodpri, logline);
348     if (def_logfile)
349         do_logfile(logline);
350
351     efree(logline);
352 }
353
354 void
355 #ifdef __STDC__
356 log_error(int flags, const char *fmt, ...)
357 #else
358 log_error(flags, fmt, va_alist)
359     int flags;
360     const char *fmt;
361     va_dcl
362 #endif
363 {
364     int serrno = errno;
365     char *message;
366     char *logline;
367     va_list ap;
368 #ifdef __STDC__
369     va_start(ap, fmt);
370 #else
371     va_start(ap);
372 #endif
373
374     /* Become root if we are not already to avoid user interference */
375     set_perms(PERM_ROOT|PERM_NOEXIT);
376
377     /* Expand printf-style format + args. */
378     evasprintf(&message, fmt, ap);
379     va_end(ap);
380
381     if (ISSET(flags, MSG_ONLY))
382         logline = message;
383     else
384         logline = new_logline(message, ISSET(flags, USE_ERRNO) ? serrno : 0);
385
386     /*
387      * Tell the user.
388      */
389     if (!ISSET(flags, NO_STDERR)) {
390         if (ISSET(flags, USE_ERRNO))
391             warning("%s", message);
392         else
393             warningx("%s", message);
394     }
395     if (logline != message)
396         efree(message);
397
398     /*
399      * Send a copy of the error via mail.
400      */
401     if (!ISSET(flags, NO_MAIL))
402         send_mail(logline);
403
404     /*
405      * Log to syslog and/or a file.
406      */
407     if (def_syslog)
408         do_syslog(def_syslog_badpri, logline);
409     if (def_logfile)
410         do_logfile(logline);
411
412     efree(logline);
413
414     if (!ISSET(flags, NO_EXIT)) {
415         cleanup(0);
416         exit(1);
417     }
418 }
419
420 #define MAX_MAILFLAGS   63
421
422 /*
423  * Send a message to MAILTO user
424  */
425 static void
426 send_mail(line)
427     char *line;
428 {
429     FILE *mail;
430     char *p;
431     int fd, pfd[2], status;
432     pid_t pid, rv;
433     sigaction_t sa;
434 #ifndef NO_ROOT_MAILER
435     static char *root_envp[] = {
436         "HOME=/",
437         "PATH=/usr/bin:/bin",
438         "LOGNAME=root",
439         "USERNAME=root",
440         "USER=root",
441         NULL
442     };
443 #endif
444
445     /* Just return if mailer is disabled. */
446     if (!def_mailerpath || !def_mailto)
447         return;
448
449     /* Fork and return, child will daemonize. */
450     switch (pid = fork()) {
451         case -1:
452             /* Error. */
453             error(1, "cannot fork");
454             break;
455         case 0:
456             /* Child. */
457             switch (pid = fork()) {
458                 case -1:
459                     /* Error. */
460                     mysyslog(LOG_ERR, "cannot fork: %m");
461                     _exit(1);
462                 case 0:
463                     /* Grandchild continues below. */
464                     break;
465                 default:
466                     /* Parent will wait for us. */
467                     _exit(0);
468             }
469             break;
470         default:
471             /* Parent. */
472             do {
473 #ifdef HAVE_WAITPID
474                 rv = waitpid(pid, &status, 0);
475 #else
476                 rv = wait(&status);
477 #endif
478             } while (rv == -1 && errno == EINTR);
479             return;
480     }
481
482     /* Daemonize - disassociate from session/tty. */
483 #ifdef HAVE_SETSID
484     if (setsid() == -1)
485       warning("setsid");
486 #else
487     setpgrp(0, 0);
488 # ifdef TIOCNOTTY
489     if ((fd = open(_PATH_TTY, O_RDWR, 0644)) != -1) {
490         ioctl(fd, TIOCNOTTY, NULL);
491         close(fd);
492     }
493 # endif
494 #endif
495     chdir("/");
496     if ((fd = open(_PATH_DEVNULL, O_RDWR, 0644)) != -1) {
497         (void) dup2(fd, STDIN_FILENO);
498         (void) dup2(fd, STDOUT_FILENO);
499         (void) dup2(fd, STDERR_FILENO);
500     }
501
502     /* Close password, group and other fds so we don't leak. */
503     sudo_endpwent();
504     sudo_endgrent();
505     closefrom(STDERR_FILENO + 1);
506
507     /* Ignore SIGPIPE in case mailer exits prematurely (or is missing). */
508     zero_bytes(&sa, sizeof(sa));
509     sigemptyset(&sa.sa_mask);
510     sa.sa_flags = 0;
511     sa.sa_handler = SIG_IGN;
512     (void) sigaction(SIGPIPE, &sa, NULL);
513
514     if (pipe(pfd) == -1) {
515         mysyslog(LOG_ERR, "cannot open pipe: %m");
516         _exit(1);
517     }
518
519     switch (pid = fork()) {
520         case -1:
521             /* Error. */
522             mysyslog(LOG_ERR, "cannot fork: %m");
523             _exit(1);
524             break;
525         case 0:
526             {
527                 char *argv[MAX_MAILFLAGS + 1];
528                 char *mpath, *mflags;
529                 int i;
530
531                 /* Child, set stdin to output side of the pipe */
532                 if (pfd[0] != STDIN_FILENO) {
533                     (void) dup2(pfd[0], STDIN_FILENO);
534                     (void) close(pfd[0]);
535                 }
536                 (void) close(pfd[1]);
537
538                 /* Build up an argv based the mailer path and flags */
539                 mflags = estrdup(def_mailerflags);
540                 mpath = estrdup(def_mailerpath);
541                 if ((argv[0] = strrchr(mpath, ' ')))
542                     argv[0]++;
543                 else
544                     argv[0] = mpath;
545
546                 i = 1;
547                 if ((p = strtok(mflags, " \t"))) {
548                     do {
549                         argv[i] = p;
550                     } while (++i < MAX_MAILFLAGS && (p = strtok(NULL, " \t")));
551                 }
552                 argv[i] = NULL;
553
554                 /*
555                  * Depending on the config, either run the mailer as root
556                  * (so user cannot kill it) or as the user (for the paranoid).
557                  */
558 #ifndef NO_ROOT_MAILER
559                 set_perms(PERM_ROOT|PERM_NOEXIT);
560                 execve(mpath, argv, root_envp);
561 #else
562                 set_perms(PERM_FULL_USER|PERM_NOEXIT);
563                 execv(mpath, argv);
564 #endif /* NO_ROOT_MAILER */
565                 mysyslog(LOG_ERR, "cannot execute %s: %m", mpath);
566                 _exit(127);
567             }
568             break;
569     }
570
571     (void) close(pfd[0]);
572     mail = fdopen(pfd[1], "w");
573
574     /* Pipes are all setup, send message. */
575     (void) fprintf(mail, "To: %s\nFrom: %s\nAuto-Submitted: %s\nSubject: ",
576         def_mailto, def_mailfrom ? def_mailfrom : user_name, "auto-generated");
577     for (p = def_mailsub; *p; p++) {
578         /* Expand escapes in the subject */
579         if (*p == '%' && *(p+1) != '%') {
580             switch (*(++p)) {
581                 case 'h':
582                     (void) fputs(user_host, mail);
583                     break;
584                 case 'u':
585                     (void) fputs(user_name, mail);
586                     break;
587                 default:
588                     p--;
589                     break;
590             }
591         } else
592             (void) fputc(*p, mail);
593     }
594     (void) fprintf(mail, "\n\n%s : %s : %s : %s\n\n", user_host,
595         get_timestr(), user_name, line);
596     fclose(mail);
597     do {
598 #ifdef HAVE_WAITPID
599         rv = waitpid(pid, &status, 0);
600 #else
601         rv = wait(&status);
602 #endif
603     } while (rv == -1 && errno == EINTR);
604     _exit(0);
605 }
606
607 /*
608  * Determine whether we should send mail based on "status" and defaults options.
609  */
610 static int
611 should_mail(status)
612     int status;
613 {
614
615     return(def_mail_always || ISSET(status, VALIDATE_ERROR) ||
616         (def_mail_no_user && ISSET(status, FLAG_NO_USER)) ||
617         (def_mail_no_host && ISSET(status, FLAG_NO_HOST)) ||
618         (def_mail_no_perms && !ISSET(status, VALIDATE_OK)));
619 }
620
621 /*
622  * Return an ascii string with the current date + time
623  * Uses strftime() if available, else falls back to ctime().
624  */
625 static char *
626 get_timestr()
627 {
628     char *s;
629     time_t now = time((time_t) 0);
630 #ifdef HAVE_STRFTIME
631     static char buf[128];
632     struct tm *timeptr;
633
634     timeptr = localtime(&now);
635     if (def_log_year)
636         s = "%h %e %T %Y";
637     else
638         s = "%h %e %T";
639
640     /* strftime() does not guarantee to NUL-terminate so we must check. */
641     buf[sizeof(buf) - 1] = '\0';
642     if (strftime(buf, sizeof(buf), s, timeptr) && buf[sizeof(buf) - 1] == '\0')
643         return(buf);
644
645 #endif /* HAVE_STRFTIME */
646
647     s = ctime(&now) + 4;                /* skip day of the week */
648     if (def_log_year)
649         s[20] = '\0';                   /* avoid the newline */
650     else
651         s[15] = '\0';                   /* don't care about year */
652
653     return(s);
654 }
655
656 #define LL_TTY_STR      "TTY="
657 #define LL_CWD_STR      "PWD="          /* XXX - should be CWD= */
658 #define LL_USER_STR     "USER="
659 #define LL_GROUP_STR    "GROUP="
660 #define LL_ENV_STR      "ENV="
661 #define LL_CMND_STR     "COMMAND="
662
663 /*
664  * Allocate and fill in a new logline.
665  */
666 static char *
667 new_logline(message, serrno)
668     const char *message;
669     int serrno;
670 {
671     size_t len = 0;
672     char *evstr = NULL;
673     char *errstr = NULL;
674     char *line;
675
676     /*
677      * Compute line length
678      */
679     if (message != NULL)
680         len += strlen(message) + 3;
681     if (serrno) {
682         errstr = strerror(serrno);
683         len += strlen(errstr) + 3;
684     }
685     len += sizeof(LL_TTY_STR) + 2 + strlen(user_tty);
686     len += sizeof(LL_CWD_STR) + 2 + strlen(user_cwd);
687     if (runas_pw != NULL)
688         len += sizeof(LL_USER_STR) + 2 + strlen(runas_pw->pw_name);
689     if (runas_gr != NULL)
690         len += sizeof(LL_GROUP_STR) + 2 + strlen(runas_gr->gr_name);
691     if (sudo_user.env_vars != NULL) {
692         size_t evlen = 0;
693         struct list_member *cur;
694         for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next)
695             evlen += strlen(cur->value) + 1;
696         evstr = emalloc(evlen);
697         evstr[0] = '\0';
698         for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next) {
699             strlcat(evstr, cur->value, evlen);
700             strlcat(evstr, " ", evlen); /* NOTE: last one will fail */
701         }
702         len += sizeof(LL_ENV_STR) + 2 + evlen;
703     }
704     len += sizeof(LL_CMND_STR) - 1 + strlen(user_cmnd);
705     if (user_args != NULL)
706         len += strlen(user_args) + 1;
707
708     /*
709      * Allocate and build up the line.
710      */
711     line = emalloc(++len);
712     line[0] = '\0';
713
714     if (message != NULL) {
715         if (strlcat(line, message, len) >= len ||
716             strlcat(line, errstr ? " : " : " ; ", len) >= len)
717             goto toobig;
718     }
719     if (serrno) {
720         if (strlcat(line, errstr, len) >= len ||
721             strlcat(line, " ; ", len) >= len)
722             goto toobig;
723     }
724     if (strlcat(line, LL_TTY_STR, len) >= len ||
725         strlcat(line, user_tty, len) >= len ||
726         strlcat(line, " ; ", len) >= len)
727         goto toobig;
728     if (strlcat(line, LL_CWD_STR, len) >= len ||
729         strlcat(line, user_cwd, len) >= len ||
730         strlcat(line, " ; ", len) >= len)
731         goto toobig;
732     if (runas_pw != NULL) {
733         if (strlcat(line, LL_USER_STR, len) >= len ||
734             strlcat(line, runas_pw->pw_name, len) >= len ||
735             strlcat(line, " ; ", len) >= len)
736             goto toobig;
737     }
738     if (runas_gr != NULL) {
739         if (strlcat(line, LL_GROUP_STR, len) >= len ||
740             strlcat(line, runas_gr->gr_name, len) >= len ||
741             strlcat(line, " ; ", len) >= len)
742             goto toobig;
743     }
744     if (evstr != NULL) {
745         if (strlcat(line, LL_ENV_STR, len) >= len ||
746             strlcat(line, evstr, len) >= len ||
747             strlcat(line, " ; ", len) >= len)
748             goto toobig;
749         efree(evstr);
750     }
751     if (strlcat(line, LL_CMND_STR, len) >= len ||
752         strlcat(line, user_cmnd, len) >= len)
753         goto toobig;
754     if (user_args != NULL) {
755         if (strlcat(line, " ", len) >= len ||
756             strlcat(line, user_args, len) >= len)
757             goto toobig;
758     }
759
760     return (line);
761 toobig:
762     errorx(1, "internal error: insufficient space for log line");
763 }