/*1* SPDX-License-Identifier: ISC2*3* Copyright (c) 2011, 2014-2020 Todd C. Miller <[email protected]>4*5* Permission to use, copy, modify, and distribute this software for any6* purpose with or without fee is hereby granted, provided that the above7* copyright notice and this permission notice appear in all copies.8*9* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES10* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF11* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR12* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES13* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN14* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF15* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.16*/1718#include <config.h>1920#include <stdio.h>21#include <stdlib.h>22#include <string.h>2324#include <sudo_compat.h>25#include <sudo_debug.h>26#include <sudo_util.h>27#include <sudo_eventlog.h>2829size_t30eventlog_writeln(FILE * restrict fp, char * restrict line, size_t linelen, size_t maxlen)31{32const char *indent = "";33char *beg = line;34char *end;35int len;36size_t outlen = 0;37debug_decl(eventlog_writeln, SUDO_DEBUG_UTIL);3839if (maxlen < sizeof(EVENTLOG_INDENT)) {40/* Maximum length too small, disable wrapping. */41outlen = fwrite(line, 1, linelen, fp);42if (outlen != linelen)43debug_return_size_t((size_t)-1);44if (fputc('\n', fp) == EOF)45debug_return_size_t((size_t)-1);46debug_return_size_t(outlen + 1);47}4849/*50* Print out line with word wrap around maxlen characters.51*/52while (linelen > maxlen) {53end = beg + maxlen;54while (end != beg && *end != ' ')55end--;56if (beg == end) {57/* Unable to find word break within maxlen, look beyond. */58end = strchr(beg + maxlen, ' ');59if (end == NULL)60break; /* no word break */61}62len = fprintf(fp, "%s%.*s\n", indent, (int)(end - beg), beg);63if (len < 0)64debug_return_size_t((size_t)-1);65outlen += (size_t)len;66while (*end == ' ')67end++;68linelen -= (size_t)(end - beg);69beg = end;70if (indent[0] == '\0') {71indent = EVENTLOG_INDENT;72maxlen -= sizeof(EVENTLOG_INDENT) - 1;73}74}75/* Print remainder, if any. */76if (linelen) {77len = fprintf(fp, "%s%s\n", indent, beg);78if (len < 0)79debug_return_size_t((size_t)-1);80outlen += (size_t)len;81}8283debug_return_size_t(outlen);84}858687