1/*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1992-2009 Edwin Groothuis <edwin@FreeBSD.org>. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 */ 29 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD$"); 32 33#include <sys/time.h> 34#include <err.h> 35#include <langinfo.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#ifdef WITH_ICONV 40#include <iconv.h> 41#include <errno.h> 42 43static iconv_t conv = (iconv_t)-1; 44static char *currentEncoding = NULL; 45 46#endif 47 48#include "pathnames.h" 49#include "calendar.h" 50 51#ifdef WITH_ICONV 52void 53set_new_encoding(void) 54{ 55 const char *newenc; 56 57 newenc = nl_langinfo(CODESET); 58 if (currentEncoding == NULL) { 59 currentEncoding = strdup(newenc); 60 if (currentEncoding == NULL) 61 errx(1, "set_new_encoding: cannot allocate memory"); 62 return; 63 } 64 if (strcmp(currentEncoding, newenc) == 0) 65 return; 66 free(currentEncoding); 67 currentEncoding = strdup(newenc); 68 if (currentEncoding == NULL) 69 errx(1, "set_new_encoding: cannot allocate memory"); 70 if (conv != (iconv_t) -1) { 71 iconv_close(conv); 72 conv = (iconv_t) -1; 73 } 74} 75#endif 76 77static char * 78convert(char *input) 79{ 80 char *output; 81#ifdef WITH_ICONV 82 size_t inleft, outleft, converted = 0; 83 char *outbuf, *tmp; 84 char *inbuf; 85 size_t outlen; 86 87 if (currentEncoding == NULL) { 88 output = strdup(input); 89 if (output == NULL) 90 errx(1, "convert: cannot allocate memory"); 91 return (output); 92 } 93 if (conv == (iconv_t)-1) { 94 conv = iconv_open(outputEncoding, currentEncoding); 95 if (conv == (iconv_t)-1) { 96 if (errno == EINVAL) 97 errx(1, "Conversion is not supported"); 98 else 99 err(1, "Initialization failure"); 100 } 101 } 102 103 inleft = strlen(input); 104 inbuf = input; 105 106 outlen = inleft; 107 if ((output = malloc(outlen + 1)) == NULL) 108 errx(1, "convert: cannot allocate memory"); 109 110 for (;;) { 111 errno = 0; 112 outbuf = output + converted; 113 outleft = outlen - converted; 114 115 converted = iconv(conv, (char **) &inbuf, &inleft, &outbuf, &outleft); 116 if (converted != (size_t) -1 || errno == EINVAL) { 117 /* finished or invalid multibyte, so truncate and ignore */ 118 break; 119 } 120 121 if (errno != E2BIG) { 122 free(output); 123 err(1, "convert"); 124 } 125 126 converted = outbuf - output; 127 outlen += inleft * 2; 128 129 if ((tmp = realloc(output, outlen + 1)) == NULL) { 130 free(output); 131 errx(1, "convert: cannot allocate memory"); 132 } 133 134 output = tmp; 135 outbuf = output + converted; 136 } 137 138 /* flush the iconv conversion */ 139 iconv(conv, NULL, NULL, &outbuf, &outleft); 140 141 /* null terminate the string */ 142 *outbuf = '\0'; 143#else 144 output = strdup(input); 145 if (output == NULL) 146 errx(1, "convert: cannot allocate memory"); 147#endif 148 149 return (output); 150} 151 152struct event * 153event_add(int year, int month, int day, int var, char *txt, char *extra) 154{ 155 struct event *e; 156 157 /* 158 * Creating a new event: 159 * - Create a new event 160 * - Copy the machine readable day and month 161 * - Copy the text of the event 162 */ 163 e = (struct event *)calloc(1, sizeof(struct event)); 164 if (e == NULL) 165 errx(1, "event_add: cannot allocate memory"); 166 e->year = year; 167 e->month = month; 168 e->day = day; 169 e->var = var; 170 e->text = convert(txt); 171 if (e->text == NULL) 172 errx(1, "event_add: cannot allocate memory"); 173 e->extra = NULL; 174 if (extra != NULL && extra[0] != '\0') 175 e->extra = convert(extra); 176 addtodate(e); 177 return (e); 178} 179 180void 181event_continue(struct event *e, char *txt) 182{ 183 char *oldtext, *text; 184 185 text = convert(txt); 186 oldtext = e->text; 187 if (oldtext == NULL) 188 errx(1, "event_continue: cannot allocate memory"); 189 190 asprintf(&e->text, "%s\n%s", oldtext, text); 191 if (e->text == NULL) 192 errx(1, "event_continue: cannot allocate memory"); 193 free(oldtext); 194 free(text); 195 196 return; 197} 198 199void 200event_print_all(FILE *fp) 201{ 202 struct event *e; 203 struct tm tm; 204 char dbuf[80]; 205 static int d_first; 206 207 d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 208 209 while (walkthrough_dates(&e) != 0) { 210 if (e) { 211#ifdef DEBUG 212 fprintf(stderr, "event_print_all month: %d, day: %d\n", 213 e->month, e->day); 214#endif 215 memset(&tm, 0, sizeof(struct tm)); 216 tm.tm_mday = e->day; 217 tm.tm_mon = e->month - 1; 218 tm.tm_year = e->year - 1900; 219 (void)strftime(dbuf, sizeof(dbuf), d_first ? "%e %b" : "%b %e", &tm); 220 } 221 222 /* 223 * Go through all events and print the text of the matching 224 * dates 225 */ 226 while (e != NULL) { 227 (void)fprintf(fp, "%s%c%s%s%s%s\n", dbuf, 228 e->var ? '*' : ' ', e->text, 229 e->extra != NULL ? " (" : "", 230 e->extra != NULL ? e->extra : "", 231 e->extra != NULL ? ")" : "" 232 ); 233 234 e = e->next; 235 } 236 } 237} 238