1*c1c95addSBrooks Davis /* $Id: manpath.c,v 1.44 2021/11/05 18:03:08 schwarze Exp $ */ 261d06d6bSBaptiste Daroussin /* 345a5aec3SBaptiste Daroussin * Copyright (c) 2011,2014,2015,2017-2019 Ingo Schwarze <schwarze@openbsd.org> 461d06d6bSBaptiste Daroussin * Copyright (c) 2011 Kristaps Dzonsons <kristaps@bsd.lv> 561d06d6bSBaptiste Daroussin * 661d06d6bSBaptiste Daroussin * Permission to use, copy, modify, and distribute this software for any 761d06d6bSBaptiste Daroussin * purpose with or without fee is hereby granted, provided that the above 861d06d6bSBaptiste Daroussin * copyright notice and this permission notice appear in all copies. 961d06d6bSBaptiste Daroussin * 1061d06d6bSBaptiste Daroussin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES 1161d06d6bSBaptiste Daroussin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1261d06d6bSBaptiste Daroussin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR 1361d06d6bSBaptiste Daroussin * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1461d06d6bSBaptiste Daroussin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1561d06d6bSBaptiste Daroussin * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1661d06d6bSBaptiste Daroussin * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1761d06d6bSBaptiste Daroussin */ 1861d06d6bSBaptiste Daroussin #include "config.h" 1961d06d6bSBaptiste Daroussin 2061d06d6bSBaptiste Daroussin #include <sys/types.h> 2161d06d6bSBaptiste Daroussin #include <sys/stat.h> 2261d06d6bSBaptiste Daroussin 2361d06d6bSBaptiste Daroussin #include <ctype.h> 2445a5aec3SBaptiste Daroussin #include <errno.h> 2561d06d6bSBaptiste Daroussin #include <limits.h> 2661d06d6bSBaptiste Daroussin #include <stdio.h> 2761d06d6bSBaptiste Daroussin #include <stdlib.h> 2861d06d6bSBaptiste Daroussin #include <string.h> 2961d06d6bSBaptiste Daroussin 3061d06d6bSBaptiste Daroussin #include "mandoc_aux.h" 3145a5aec3SBaptiste Daroussin #include "mandoc.h" 3261d06d6bSBaptiste Daroussin #include "manconf.h" 3361d06d6bSBaptiste Daroussin 34*c1c95addSBrooks Davis static void manconf_file(struct manconf *, const char *, int); 3545a5aec3SBaptiste Daroussin static void manpath_add(struct manpaths *, const char *, char); 3645a5aec3SBaptiste Daroussin static void manpath_parseline(struct manpaths *, char *, char); 3761d06d6bSBaptiste Daroussin 3861d06d6bSBaptiste Daroussin 3961d06d6bSBaptiste Daroussin void 40*c1c95addSBrooks Davis manconf_parse(struct manconf *conf, const char *file, char *pend, char *pbeg) 4161d06d6bSBaptiste Daroussin { 42*c1c95addSBrooks Davis int use_path_from_file = 1; 4361d06d6bSBaptiste Daroussin 4461d06d6bSBaptiste Daroussin /* Always prepend -m. */ 45*c1c95addSBrooks Davis manpath_parseline(&conf->manpath, pbeg, 'm'); 4661d06d6bSBaptiste Daroussin 47*c1c95addSBrooks Davis if (pend != NULL && *pend != '\0') { 4861d06d6bSBaptiste Daroussin /* If -M is given, it overrides everything else. */ 49*c1c95addSBrooks Davis manpath_parseline(&conf->manpath, pend, 'M'); 50*c1c95addSBrooks Davis use_path_from_file = 0; 51*c1c95addSBrooks Davis pbeg = pend = NULL; 52*c1c95addSBrooks Davis } else if ((pbeg = getenv("MANPATH")) == NULL || *pbeg == '\0') { 5361d06d6bSBaptiste Daroussin /* No MANPATH; use man.conf(5) only. */ 54*c1c95addSBrooks Davis pbeg = pend = NULL; 55*c1c95addSBrooks Davis } else if (*pbeg == ':') { 5661d06d6bSBaptiste Daroussin /* Prepend man.conf(5) to MANPATH. */ 57*c1c95addSBrooks Davis pend = pbeg + 1; 58*c1c95addSBrooks Davis pbeg = NULL; 59*c1c95addSBrooks Davis } else if ((pend = strstr(pbeg, "::")) != NULL) { 6061d06d6bSBaptiste Daroussin /* Insert man.conf(5) into MANPATH. */ 61*c1c95addSBrooks Davis *pend = '\0'; 62*c1c95addSBrooks Davis pend += 2; 63*c1c95addSBrooks Davis } else if (pbeg[strlen(pbeg) - 1] == ':') { 64*c1c95addSBrooks Davis /* Append man.conf(5) to MANPATH. */ 65*c1c95addSBrooks Davis pend = NULL; 66*c1c95addSBrooks Davis } else { 67*c1c95addSBrooks Davis /* MANPATH overrides man.conf(5) completely. */ 68*c1c95addSBrooks Davis use_path_from_file = 0; 69*c1c95addSBrooks Davis pend = NULL; 7061d06d6bSBaptiste Daroussin } 7161d06d6bSBaptiste Daroussin 72*c1c95addSBrooks Davis manpath_parseline(&conf->manpath, pbeg, '\0'); 73*c1c95addSBrooks Davis 74*c1c95addSBrooks Davis if (file == NULL) 75*c1c95addSBrooks Davis file = MAN_CONF_FILE; 76*c1c95addSBrooks Davis manconf_file(conf, file, use_path_from_file); 77*c1c95addSBrooks Davis 78*c1c95addSBrooks Davis manpath_parseline(&conf->manpath, pend, '\0'); 7961d06d6bSBaptiste Daroussin } 8061d06d6bSBaptiste Daroussin 8161d06d6bSBaptiste Daroussin void 8261d06d6bSBaptiste Daroussin manpath_base(struct manpaths *dirs) 8361d06d6bSBaptiste Daroussin { 8461d06d6bSBaptiste Daroussin char path_base[] = MANPATH_BASE; 8545a5aec3SBaptiste Daroussin manpath_parseline(dirs, path_base, '\0'); 8661d06d6bSBaptiste Daroussin } 8761d06d6bSBaptiste Daroussin 8861d06d6bSBaptiste Daroussin /* 8961d06d6bSBaptiste Daroussin * Parse a FULL pathname from a colon-separated list of arrays. 9061d06d6bSBaptiste Daroussin */ 9161d06d6bSBaptiste Daroussin static void 9245a5aec3SBaptiste Daroussin manpath_parseline(struct manpaths *dirs, char *path, char option) 9361d06d6bSBaptiste Daroussin { 9461d06d6bSBaptiste Daroussin char *dir; 9561d06d6bSBaptiste Daroussin 9661d06d6bSBaptiste Daroussin if (NULL == path) 9761d06d6bSBaptiste Daroussin return; 9861d06d6bSBaptiste Daroussin 9961d06d6bSBaptiste Daroussin for (dir = strtok(path, ":"); dir; dir = strtok(NULL, ":")) 10045a5aec3SBaptiste Daroussin manpath_add(dirs, dir, option); 10161d06d6bSBaptiste Daroussin } 10261d06d6bSBaptiste Daroussin 10361d06d6bSBaptiste Daroussin /* 10461d06d6bSBaptiste Daroussin * Add a directory to the array, ignoring bad directories. 10561d06d6bSBaptiste Daroussin * Grow the array one-by-one for simplicity's sake. 10661d06d6bSBaptiste Daroussin */ 10761d06d6bSBaptiste Daroussin static void 10845a5aec3SBaptiste Daroussin manpath_add(struct manpaths *dirs, const char *dir, char option) 10961d06d6bSBaptiste Daroussin { 11061d06d6bSBaptiste Daroussin char buf[PATH_MAX]; 11161d06d6bSBaptiste Daroussin struct stat sb; 11261d06d6bSBaptiste Daroussin char *cp; 11361d06d6bSBaptiste Daroussin size_t i; 11461d06d6bSBaptiste Daroussin 11545a5aec3SBaptiste Daroussin if ((cp = realpath(dir, buf)) == NULL) 11645a5aec3SBaptiste Daroussin goto fail; 11761d06d6bSBaptiste Daroussin 11861d06d6bSBaptiste Daroussin for (i = 0; i < dirs->sz; i++) 11945a5aec3SBaptiste Daroussin if (strcmp(dirs->paths[i], dir) == 0) 12061d06d6bSBaptiste Daroussin return; 12161d06d6bSBaptiste Daroussin 12245a5aec3SBaptiste Daroussin if (stat(cp, &sb) == -1) 12345a5aec3SBaptiste Daroussin goto fail; 12461d06d6bSBaptiste Daroussin 12561d06d6bSBaptiste Daroussin dirs->paths = mandoc_reallocarray(dirs->paths, 12645a5aec3SBaptiste Daroussin dirs->sz + 1, sizeof(*dirs->paths)); 12761d06d6bSBaptiste Daroussin dirs->paths[dirs->sz++] = mandoc_strdup(cp); 12845a5aec3SBaptiste Daroussin return; 12945a5aec3SBaptiste Daroussin 13045a5aec3SBaptiste Daroussin fail: 13145a5aec3SBaptiste Daroussin if (option != '\0') 13245a5aec3SBaptiste Daroussin mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0, 13345a5aec3SBaptiste Daroussin "-%c %s: %s", option, dir, strerror(errno)); 13461d06d6bSBaptiste Daroussin } 13561d06d6bSBaptiste Daroussin 13661d06d6bSBaptiste Daroussin void 13761d06d6bSBaptiste Daroussin manconf_free(struct manconf *conf) 13861d06d6bSBaptiste Daroussin { 13961d06d6bSBaptiste Daroussin size_t i; 14061d06d6bSBaptiste Daroussin 14161d06d6bSBaptiste Daroussin for (i = 0; i < conf->manpath.sz; i++) 14261d06d6bSBaptiste Daroussin free(conf->manpath.paths[i]); 14361d06d6bSBaptiste Daroussin 14461d06d6bSBaptiste Daroussin free(conf->manpath.paths); 14561d06d6bSBaptiste Daroussin free(conf->output.includes); 14661d06d6bSBaptiste Daroussin free(conf->output.man); 14761d06d6bSBaptiste Daroussin free(conf->output.paper); 14861d06d6bSBaptiste Daroussin free(conf->output.style); 14961d06d6bSBaptiste Daroussin } 15061d06d6bSBaptiste Daroussin 15161d06d6bSBaptiste Daroussin static void 152*c1c95addSBrooks Davis manconf_file(struct manconf *conf, const char *file, int use_path_from_file) 15361d06d6bSBaptiste Daroussin { 1546d38604fSBaptiste Daroussin const char *const toks[] = { "manpath", "output" }; 15561d06d6bSBaptiste Daroussin char manpath_default[] = MANPATH_DEFAULT; 15661d06d6bSBaptiste Daroussin 15761d06d6bSBaptiste Daroussin FILE *stream; 15861d06d6bSBaptiste Daroussin char *line, *cp, *ep; 15961d06d6bSBaptiste Daroussin size_t linesz, tok, toklen; 16061d06d6bSBaptiste Daroussin ssize_t linelen; 16161d06d6bSBaptiste Daroussin 16261d06d6bSBaptiste Daroussin if ((stream = fopen(file, "r")) == NULL) 16361d06d6bSBaptiste Daroussin goto out; 16461d06d6bSBaptiste Daroussin 16561d06d6bSBaptiste Daroussin line = NULL; 16661d06d6bSBaptiste Daroussin linesz = 0; 16761d06d6bSBaptiste Daroussin 16861d06d6bSBaptiste Daroussin while ((linelen = getline(&line, &linesz, stream)) != -1) { 16961d06d6bSBaptiste Daroussin cp = line; 17061d06d6bSBaptiste Daroussin ep = cp + linelen - 1; 17161d06d6bSBaptiste Daroussin while (ep > cp && isspace((unsigned char)*ep)) 17261d06d6bSBaptiste Daroussin *ep-- = '\0'; 17361d06d6bSBaptiste Daroussin while (isspace((unsigned char)*cp)) 17461d06d6bSBaptiste Daroussin cp++; 17561d06d6bSBaptiste Daroussin if (cp == ep || *cp == '#') 17661d06d6bSBaptiste Daroussin continue; 17761d06d6bSBaptiste Daroussin 17861d06d6bSBaptiste Daroussin for (tok = 0; tok < sizeof(toks)/sizeof(toks[0]); tok++) { 17961d06d6bSBaptiste Daroussin toklen = strlen(toks[tok]); 18061d06d6bSBaptiste Daroussin if (cp + toklen < ep && 18161d06d6bSBaptiste Daroussin isspace((unsigned char)cp[toklen]) && 18261d06d6bSBaptiste Daroussin strncmp(cp, toks[tok], toklen) == 0) { 18361d06d6bSBaptiste Daroussin cp += toklen; 18461d06d6bSBaptiste Daroussin while (isspace((unsigned char)*cp)) 18561d06d6bSBaptiste Daroussin cp++; 18661d06d6bSBaptiste Daroussin break; 18761d06d6bSBaptiste Daroussin } 18861d06d6bSBaptiste Daroussin } 18961d06d6bSBaptiste Daroussin 19061d06d6bSBaptiste Daroussin switch (tok) { 19161d06d6bSBaptiste Daroussin case 0: /* manpath */ 192*c1c95addSBrooks Davis if (use_path_from_file) 19345a5aec3SBaptiste Daroussin manpath_add(&conf->manpath, cp, '\0'); 19461d06d6bSBaptiste Daroussin *manpath_default = '\0'; 19561d06d6bSBaptiste Daroussin break; 19661d06d6bSBaptiste Daroussin case 1: /* output */ 19761d06d6bSBaptiste Daroussin manconf_output(&conf->output, cp, 1); 19861d06d6bSBaptiste Daroussin break; 19961d06d6bSBaptiste Daroussin default: 20061d06d6bSBaptiste Daroussin break; 20161d06d6bSBaptiste Daroussin } 20261d06d6bSBaptiste Daroussin } 20361d06d6bSBaptiste Daroussin free(line); 20461d06d6bSBaptiste Daroussin fclose(stream); 20561d06d6bSBaptiste Daroussin 20661d06d6bSBaptiste Daroussin out: 207*c1c95addSBrooks Davis if (use_path_from_file && *manpath_default != '\0') 20845a5aec3SBaptiste Daroussin manpath_parseline(&conf->manpath, manpath_default, '\0'); 20961d06d6bSBaptiste Daroussin } 21061d06d6bSBaptiste Daroussin 21161d06d6bSBaptiste Daroussin int 21261d06d6bSBaptiste Daroussin manconf_output(struct manoutput *conf, const char *cp, int fromfile) 21361d06d6bSBaptiste Daroussin { 21461d06d6bSBaptiste Daroussin const char *const toks[] = { 2156d38604fSBaptiste Daroussin /* Tokens requiring an argument. */ 2167295610fSBaptiste Daroussin "includes", "man", "paper", "style", "indent", "width", 2176d38604fSBaptiste Daroussin "outfilename", "tagfilename", 2186d38604fSBaptiste Daroussin /* Token taking an optional argument. */ 2196d38604fSBaptiste Daroussin "tag", 2206d38604fSBaptiste Daroussin /* Tokens not taking arguments. */ 2216d38604fSBaptiste Daroussin "fragment", "mdoc", "noval", "toc" 22261d06d6bSBaptiste Daroussin }; 22345a5aec3SBaptiste Daroussin const size_t ntoks = sizeof(toks) / sizeof(toks[0]); 22461d06d6bSBaptiste Daroussin 22561d06d6bSBaptiste Daroussin const char *errstr; 22661d06d6bSBaptiste Daroussin char *oldval; 22761d06d6bSBaptiste Daroussin size_t len, tok; 22861d06d6bSBaptiste Daroussin 22945a5aec3SBaptiste Daroussin for (tok = 0; tok < ntoks; tok++) { 23061d06d6bSBaptiste Daroussin len = strlen(toks[tok]); 23145a5aec3SBaptiste Daroussin if (strncmp(cp, toks[tok], len) == 0 && 23261d06d6bSBaptiste Daroussin strchr(" = ", cp[len]) != NULL) { 23361d06d6bSBaptiste Daroussin cp += len; 23461d06d6bSBaptiste Daroussin if (*cp == '=') 23561d06d6bSBaptiste Daroussin cp++; 23661d06d6bSBaptiste Daroussin while (isspace((unsigned char)*cp)) 23761d06d6bSBaptiste Daroussin cp++; 23861d06d6bSBaptiste Daroussin break; 23961d06d6bSBaptiste Daroussin } 24061d06d6bSBaptiste Daroussin } 24161d06d6bSBaptiste Daroussin 2426d38604fSBaptiste Daroussin if (tok < 8 && *cp == '\0') { 24345a5aec3SBaptiste Daroussin mandoc_msg(MANDOCERR_BADVAL_MISS, 0, 0, "-O %s=?", toks[tok]); 24461d06d6bSBaptiste Daroussin return -1; 24561d06d6bSBaptiste Daroussin } 2466d38604fSBaptiste Daroussin if (tok > 8 && tok < ntoks && *cp != '\0') { 24745a5aec3SBaptiste Daroussin mandoc_msg(MANDOCERR_BADVAL, 0, 0, "-O %s=%s", toks[tok], cp); 24861d06d6bSBaptiste Daroussin return -1; 24961d06d6bSBaptiste Daroussin } 25061d06d6bSBaptiste Daroussin 25161d06d6bSBaptiste Daroussin switch (tok) { 25261d06d6bSBaptiste Daroussin case 0: 25361d06d6bSBaptiste Daroussin if (conf->includes != NULL) { 25461d06d6bSBaptiste Daroussin oldval = mandoc_strdup(conf->includes); 25561d06d6bSBaptiste Daroussin break; 25661d06d6bSBaptiste Daroussin } 25761d06d6bSBaptiste Daroussin conf->includes = mandoc_strdup(cp); 25861d06d6bSBaptiste Daroussin return 0; 25961d06d6bSBaptiste Daroussin case 1: 26061d06d6bSBaptiste Daroussin if (conf->man != NULL) { 26161d06d6bSBaptiste Daroussin oldval = mandoc_strdup(conf->man); 26261d06d6bSBaptiste Daroussin break; 26361d06d6bSBaptiste Daroussin } 26461d06d6bSBaptiste Daroussin conf->man = mandoc_strdup(cp); 26561d06d6bSBaptiste Daroussin return 0; 26661d06d6bSBaptiste Daroussin case 2: 26761d06d6bSBaptiste Daroussin if (conf->paper != NULL) { 26861d06d6bSBaptiste Daroussin oldval = mandoc_strdup(conf->paper); 26961d06d6bSBaptiste Daroussin break; 27061d06d6bSBaptiste Daroussin } 27161d06d6bSBaptiste Daroussin conf->paper = mandoc_strdup(cp); 27261d06d6bSBaptiste Daroussin return 0; 27361d06d6bSBaptiste Daroussin case 3: 27461d06d6bSBaptiste Daroussin if (conf->style != NULL) { 27561d06d6bSBaptiste Daroussin oldval = mandoc_strdup(conf->style); 27661d06d6bSBaptiste Daroussin break; 27761d06d6bSBaptiste Daroussin } 27861d06d6bSBaptiste Daroussin conf->style = mandoc_strdup(cp); 27961d06d6bSBaptiste Daroussin return 0; 28061d06d6bSBaptiste Daroussin case 4: 28161d06d6bSBaptiste Daroussin if (conf->indent) { 28261d06d6bSBaptiste Daroussin mandoc_asprintf(&oldval, "%zu", conf->indent); 28361d06d6bSBaptiste Daroussin break; 28461d06d6bSBaptiste Daroussin } 28561d06d6bSBaptiste Daroussin conf->indent = strtonum(cp, 0, 1000, &errstr); 28661d06d6bSBaptiste Daroussin if (errstr == NULL) 28761d06d6bSBaptiste Daroussin return 0; 28845a5aec3SBaptiste Daroussin mandoc_msg(MANDOCERR_BADVAL_BAD, 0, 0, 28945a5aec3SBaptiste Daroussin "-O indent=%s is %s", cp, errstr); 29061d06d6bSBaptiste Daroussin return -1; 29161d06d6bSBaptiste Daroussin case 5: 29261d06d6bSBaptiste Daroussin if (conf->width) { 29361d06d6bSBaptiste Daroussin mandoc_asprintf(&oldval, "%zu", conf->width); 29461d06d6bSBaptiste Daroussin break; 29561d06d6bSBaptiste Daroussin } 29661d06d6bSBaptiste Daroussin conf->width = strtonum(cp, 1, 1000, &errstr); 29761d06d6bSBaptiste Daroussin if (errstr == NULL) 29861d06d6bSBaptiste Daroussin return 0; 29945a5aec3SBaptiste Daroussin mandoc_msg(MANDOCERR_BADVAL_BAD, 0, 0, 30045a5aec3SBaptiste Daroussin "-O width=%s is %s", cp, errstr); 30161d06d6bSBaptiste Daroussin return -1; 30261d06d6bSBaptiste Daroussin case 6: 3036d38604fSBaptiste Daroussin if (conf->outfilename != NULL) { 3046d38604fSBaptiste Daroussin oldval = mandoc_strdup(conf->outfilename); 3056d38604fSBaptiste Daroussin break; 3066d38604fSBaptiste Daroussin } 3076d38604fSBaptiste Daroussin conf->outfilename = mandoc_strdup(cp); 3086d38604fSBaptiste Daroussin return 0; 3096d38604fSBaptiste Daroussin case 7: 3106d38604fSBaptiste Daroussin if (conf->tagfilename != NULL) { 3116d38604fSBaptiste Daroussin oldval = mandoc_strdup(conf->tagfilename); 3126d38604fSBaptiste Daroussin break; 3136d38604fSBaptiste Daroussin } 3146d38604fSBaptiste Daroussin conf->tagfilename = mandoc_strdup(cp); 3156d38604fSBaptiste Daroussin return 0; 3166d38604fSBaptiste Daroussin /* 3176d38604fSBaptiste Daroussin * If the index of the following token changes, 3186d38604fSBaptiste Daroussin * do not forget to adjust the range check above the switch. 3196d38604fSBaptiste Daroussin */ 3206d38604fSBaptiste Daroussin case 8: 3217295610fSBaptiste Daroussin if (conf->tag != NULL) { 3227295610fSBaptiste Daroussin oldval = mandoc_strdup(conf->tag); 3237295610fSBaptiste Daroussin break; 3247295610fSBaptiste Daroussin } 3257295610fSBaptiste Daroussin conf->tag = mandoc_strdup(cp); 32661d06d6bSBaptiste Daroussin return 0; 3276d38604fSBaptiste Daroussin case 9: 3287295610fSBaptiste Daroussin conf->fragment = 1; 32961d06d6bSBaptiste Daroussin return 0; 3306d38604fSBaptiste Daroussin case 10: 3317295610fSBaptiste Daroussin conf->mdoc = 1; 3327295610fSBaptiste Daroussin return 0; 3336d38604fSBaptiste Daroussin case 11: 33461d06d6bSBaptiste Daroussin conf->noval = 1; 33561d06d6bSBaptiste Daroussin return 0; 3366d38604fSBaptiste Daroussin case 12: 3377295610fSBaptiste Daroussin conf->toc = 1; 3387295610fSBaptiste Daroussin return 0; 33961d06d6bSBaptiste Daroussin default: 34045a5aec3SBaptiste Daroussin mandoc_msg(MANDOCERR_BADARG_BAD, 0, 0, "-O %s", cp); 34161d06d6bSBaptiste Daroussin return -1; 34261d06d6bSBaptiste Daroussin } 34345a5aec3SBaptiste Daroussin if (fromfile) { 34445a5aec3SBaptiste Daroussin free(oldval); 34545a5aec3SBaptiste Daroussin return 0; 34645a5aec3SBaptiste Daroussin } else { 34745a5aec3SBaptiste Daroussin mandoc_msg(MANDOCERR_BADVAL_DUPE, 0, 0, 34845a5aec3SBaptiste Daroussin "-O %s=%s: already set to %s", toks[tok], cp, oldval); 34961d06d6bSBaptiste Daroussin free(oldval); 35061d06d6bSBaptiste Daroussin return -1; 35161d06d6bSBaptiste Daroussin } 35245a5aec3SBaptiste Daroussin } 353