/* This file is part of GNU cflow
Copyright (C) 1997, 2005, 2007, 2010, 2014-2016 Sergey Poznyakoff
GNU cflow is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
GNU cflow is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
#include
#include
#include
#include
#include
#ifndef LOCAL_RC
# define LOCAL_RC ".cflowrc"
#endif
static void
expand_argcv(int *argc_ptr, char ***argv_ptr, int argc, char **argv)
{
int i;
*argv_ptr = xrealloc(*argv_ptr,
(*argc_ptr + argc + 1) * sizeof **argv_ptr);
for (i = 0; i < argc; i++)
(*argv_ptr)[*argc_ptr + i] = xstrdup(argv[i]);
(*argv_ptr)[*argc_ptr + i] = NULL;
*argc_ptr += argc;
}
/* Parse rc file
*/
void
parse_rc(int *argc_ptr, char ***argv_ptr, char *name)
{
struct stat st;
FILE *rcfile;
int size;
char *buf, *p;
struct wordsplit ws;
int wsflags;
int line;
if (stat(name, &st))
return;
buf = xmalloc(st.st_size+1);
rcfile = fopen(name, "r");
if (!rcfile) {
error(EX_FATAL, errno, _("cannot open `%s'"), name);
return;
}
size = fread(buf, 1, st.st_size, rcfile);
buf[size] = 0;
fclose(rcfile);
ws.ws_comment = "#";
wsflags = WRDSF_DEFFLAGS | WRDSF_COMMENT;
line = 0;
for (p = strtok(buf, "\n"); p; p = strtok(NULL, "\n")) {
++line;
if (wordsplit(p, &ws, wsflags))
error(EX_FATAL, 0, "%s:%d: %s",
name, line, wordsplit_strerror(&ws));
wsflags |= WRDSF_REUSE;
if (ws.ws_wordc)
expand_argcv(argc_ptr, argv_ptr, ws.ws_wordc, ws.ws_wordv);
}
if (wsflags & WRDSF_REUSE)
wordsplit_free(&ws);
free(buf);
}
/* Process the value of the environment variable CFLOW_OPTIONS
* and of the rc file.
* Split the value into words and add them between (*ARGV_PTR)[0] and
* (*ARGV_PTR[1]) modifying *ARGC_PTR accordingly.
* NOTE: Since sourcerc() is not meant to take all SH command line processing
* burden, only word splitting is performed and no kind of expansion
* takes place.
*/
void
sourcerc(int *argc_ptr, char ***argv_ptr)
{
char *env;
int xargc = 1;
char **xargv;
xargv = xmalloc(2*sizeof *xargv);
xargv[0] = **argv_ptr;
xargv[1] = NULL;
env = getenv("CFLOW_OPTIONS");
if (env) {
struct wordsplit ws;
ws.ws_comment = "#";
if (wordsplit(env, &ws, WRDSF_DEFFLAGS | WRDSF_COMMENT))
error(EX_FATAL, 0, "failed to parse CFLOW_OPTIONS: %s",
wordsplit_strerror(&ws));
if (ws.ws_wordc)
expand_argcv(&xargc, &xargv, ws.ws_wordc, ws.ws_wordv);
wordsplit_free(&ws);
}
env = getenv("CFLOWRC");
if (env)
parse_rc(&xargc, &xargv, env);
else {
char *home = getenv("HOME");
if (home) {
int len = strlen(home);
char *buf = malloc(len + sizeof(LOCAL_RC)
+ (home[len-1] != '/') );
if (!buf)
return;
strcpy(buf, home);
if (home[len-1] != '/')
buf[len++] = '/';
strcpy(buf+len, LOCAL_RC);
parse_rc(&xargc, &xargv, buf);
free(buf);
}
}
if (xargc > 1) {
expand_argcv(&xargc, &xargv, *argc_ptr-1, *argv_ptr+1);
*argc_ptr = xargc;
*argv_ptr = xargv;
}
}