1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 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 #include <sys/time.h> 32 #include <err.h> 33 #include <langinfo.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #ifdef WITH_ICONV 38 #include <iconv.h> 39 #include <errno.h> 40 41 static iconv_t conv = (iconv_t)-1; 42 static char *currentEncoding = NULL; 43 44 #endif 45 46 #include "pathnames.h" 47 #include "calendar.h" 48 49 #ifdef WITH_ICONV 50 void 51 set_new_encoding(void) 52 { 53 const char *newenc; 54 55 newenc = nl_langinfo(CODESET); 56 if (currentEncoding == NULL) { 57 currentEncoding = strdup(newenc); 58 if (currentEncoding == NULL) 59 errx(1, "set_new_encoding: cannot allocate memory"); 60 return; 61 } 62 if (strcmp(currentEncoding, newenc) == 0) 63 return; 64 free(currentEncoding); 65 currentEncoding = strdup(newenc); 66 if (currentEncoding == NULL) 67 errx(1, "set_new_encoding: cannot allocate memory"); 68 if (conv != (iconv_t) -1) { 69 iconv_close(conv); 70 conv = (iconv_t) -1; 71 } 72 } 73 #endif 74 75 static char * 76 convert(char *input) 77 { 78 char *output; 79 #ifdef WITH_ICONV 80 size_t inleft, outleft, converted = 0; 81 char *outbuf, *tmp; 82 char *inbuf; 83 size_t outlen; 84 85 if (currentEncoding == NULL) { 86 output = strdup(input); 87 if (output == NULL) 88 errx(1, "convert: cannot allocate memory"); 89 return (output); 90 } 91 if (conv == (iconv_t)-1) { 92 conv = iconv_open(outputEncoding, currentEncoding); 93 if (conv == (iconv_t)-1) { 94 if (errno == EINVAL) 95 errx(1, "Conversion is not supported"); 96 else 97 err(1, "Initialization failure"); 98 } 99 } 100 101 inleft = strlen(input); 102 inbuf = input; 103 104 outlen = inleft; 105 if ((output = malloc(outlen + 1)) == NULL) 106 errx(1, "convert: cannot allocate memory"); 107 108 for (;;) { 109 errno = 0; 110 outbuf = output + converted; 111 outleft = outlen - converted; 112 113 converted = iconv(conv, (char **) &inbuf, &inleft, &outbuf, &outleft); 114 if (converted != (size_t) -1 || errno == EINVAL) { 115 /* finished or invalid multibyte, so truncate and ignore */ 116 break; 117 } 118 119 if (errno != E2BIG) { 120 free(output); 121 err(1, "convert"); 122 } 123 124 converted = outbuf - output; 125 outlen += inleft * 2; 126 127 if ((tmp = realloc(output, outlen + 1)) == NULL) { 128 free(output); 129 errx(1, "convert: cannot allocate memory"); 130 } 131 132 output = tmp; 133 outbuf = output + converted; 134 } 135 136 /* flush the iconv conversion */ 137 iconv(conv, NULL, NULL, &outbuf, &outleft); 138 139 /* null terminate the string */ 140 *outbuf = '\0'; 141 #else 142 output = strdup(input); 143 if (output == NULL) 144 errx(1, "convert: cannot allocate memory"); 145 #endif 146 147 return (output); 148 } 149 150 struct event * 151 event_add(int year, int month, int day, int var, char *txt, char *extra) 152 { 153 struct event *e; 154 155 /* 156 * Creating a new event: 157 * - Create a new event 158 * - Copy the machine readable day and month 159 * - Copy the text of the event 160 */ 161 e = (struct event *)calloc(1, sizeof(struct event)); 162 if (e == NULL) 163 errx(1, "event_add: cannot allocate memory"); 164 e->year = year; 165 e->month = month; 166 e->day = day; 167 e->var = var; 168 e->text = convert(txt); 169 if (e->text == NULL) 170 errx(1, "event_add: cannot allocate memory"); 171 e->extra = NULL; 172 if (extra != NULL && extra[0] != '\0') 173 e->extra = convert(extra); 174 addtodate(e); 175 return (e); 176 } 177 178 void 179 event_continue(struct event *e, char *txt) 180 { 181 char *oldtext, *text; 182 183 text = convert(txt); 184 oldtext = e->text; 185 if (oldtext == NULL) 186 errx(1, "event_continue: cannot allocate memory"); 187 188 asprintf(&e->text, "%s\n%s", oldtext, text); 189 if (e->text == NULL) 190 errx(1, "event_continue: cannot allocate memory"); 191 free(oldtext); 192 free(text); 193 194 return; 195 } 196 197 void 198 event_print_all(FILE *fp) 199 { 200 struct event *e; 201 struct tm tm; 202 char dbuf[80]; 203 static int d_first; 204 205 d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); 206 207 while (walkthrough_dates(&e) != 0) { 208 if (e) { 209 #ifdef DEBUG 210 fprintf(stderr, "event_print_all month: %d, day: %d\n", 211 e->month, e->day); 212 #endif 213 memset(&tm, 0, sizeof(struct tm)); 214 tm.tm_mday = e->day; 215 tm.tm_mon = e->month - 1; 216 tm.tm_year = e->year - 1900; 217 (void)strftime(dbuf, sizeof(dbuf), d_first ? "%e %b" : "%b %e", &tm); 218 } 219 220 /* 221 * Go through all events and print the text of the matching 222 * dates 223 */ 224 while (e != NULL) { 225 (void)fprintf(fp, "%s%c%s%s%s%s\n", dbuf, 226 e->var ? '*' : ' ', e->text, 227 e->extra != NULL ? " (" : "", 228 e->extra != NULL ? e->extra : "", 229 e->extra != NULL ? ")" : "" 230 ); 231 232 e = e->next; 233 } 234 } 235 } 236