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 <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #ifdef WITH_ICONV 39 #include <iconv.h> 40 #include <errno.h> 41 #include <langinfo.h> 42 43 static iconv_t conv = (iconv_t)-1; 44 static char *currentEncoding = NULL; 45 46 #endif 47 48 #include "pathnames.h" 49 #include "calendar.h" 50 51 #ifdef WITH_ICONV 52 void 53 set_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 77 static char * 78 convert(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 152 struct event * 153 event_add(int year, int month, int day, char *date, int var, char *txt, 154 char *extra) 155 { 156 struct event *e; 157 158 /* 159 * Creating a new event: 160 * - Create a new event 161 * - Copy the machine readable day and month 162 * - Copy the human readable and language specific date 163 * - Copy the text of the event 164 */ 165 e = (struct event *)calloc(1, sizeof(struct event)); 166 if (e == NULL) 167 errx(1, "event_add: cannot allocate memory"); 168 e->month = month; 169 e->day = day; 170 e->var = var; 171 e->date = convert(date); 172 if (e->date == NULL) 173 errx(1, "event_add: cannot allocate memory"); 174 e->text = convert(txt); 175 if (e->text == NULL) 176 errx(1, "event_add: cannot allocate memory"); 177 e->extra = NULL; 178 if (extra != NULL && extra[0] != '\0') 179 e->extra = convert(extra); 180 addtodate(e, year, month, day); 181 return (e); 182 } 183 184 void 185 event_continue(struct event *e, char *txt) 186 { 187 char *oldtext, *text; 188 189 text = convert(txt); 190 oldtext = e->text; 191 if (oldtext == NULL) 192 errx(1, "event_continue: cannot allocate memory"); 193 194 asprintf(&e->text, "%s\n%s", oldtext, text); 195 if (e->text == NULL) 196 errx(1, "event_continue: cannot allocate memory"); 197 free(oldtext); 198 free(text); 199 200 return; 201 } 202 203 void 204 event_print_all(FILE *fp) 205 { 206 struct event *e; 207 208 while (walkthrough_dates(&e) != 0) { 209 #ifdef DEBUG 210 fprintf(stderr, "event_print_allmonth: %d, day: %d\n", 211 month, day); 212 #endif 213 214 /* 215 * Go through all events and print the text of the matching 216 * dates 217 */ 218 while (e != NULL) { 219 (void)fprintf(fp, "%s%c%s%s%s%s\n", e->date, 220 e->var ? '*' : ' ', e->text, 221 e->extra != NULL ? " (" : "", 222 e->extra != NULL ? e->extra : "", 223 e->extra != NULL ? ")" : "" 224 ); 225 226 e = e->next; 227 } 228 } 229 } 230