1/*
2 * Copyright (c) 1993 david d zuhn
3 *
4 * Written by david d `zoo' zuhn while at Cygnus Support
5 *
6 * You may distribute under the terms of the GNU General Public License as
7 * specified in the README file that comes with the CVS source distribution.
8 *
9 */
10
11
12#include "cvs.h"
13#include "getline.h"
14
15/* this file is to be found in the user's home directory */
16
17#ifndef	CVSRC_FILENAME
18#define	CVSRC_FILENAME	".cvsrc"
19#endif
20char cvsrc[] = CVSRC_FILENAME;
21
22#define	GROW	10
23
24extern char *strtok ();
25
26/* Read cvsrc, processing options matching CMDNAME ("cvs" for global
27   options, and update *ARGC and *ARGV accordingly.  */
28
29void
30read_cvsrc (argc, argv, cmdname)
31    int *argc;
32    char ***argv;
33    char *cmdname;
34{
35    char *homedir;
36    char *homeinit;
37    FILE *cvsrcfile;
38
39    char *line;
40    int line_length;
41    size_t line_chars_allocated;
42
43    char *optstart;
44
45    int command_len;
46    int found = 0;
47
48    int i;
49
50    int new_argc;
51    int max_new_argv;
52    char **new_argv;
53
54    /* old_argc and old_argv hold the values returned from the
55       previous invocation of read_cvsrc and are used to free the
56       allocated memory.  The first invocation of read_cvsrc gets argv
57       from the system, this memory must not be free'd.  */
58    static int old_argc = 0;
59    static char **old_argv = NULL;
60
61    /* don't do anything if argc is -1, since that implies "help" mode */
62    if (*argc == -1)
63	return;
64
65    /* determine filename for ~/.cvsrc */
66
67    homedir = get_homedir ();
68    /* If we can't find a home directory, ignore ~/.cvsrc.  This may
69       make tracking down problems a bit of a pain, but on the other
70       hand it might be obnoxious to complain when CVS will function
71       just fine without .cvsrc (and many users won't even know what
72       .cvsrc is).  */
73    if (!homedir)
74	return;
75
76    homeinit = (char *) xmalloc (strlen (homedir) + strlen (cvsrc) + 10);
77    strcpy (homeinit, homedir);
78    strcat (homeinit, "/");
79    strcat (homeinit, cvsrc);
80
81    /* if it can't be read, there's no point to continuing */
82
83    if (!isreadable (homeinit))
84    {
85	free (homeinit);
86	return;
87    }
88
89    /* now scan the file until we find the line for the command in question */
90
91    line = NULL;
92    line_chars_allocated = 0;
93    command_len = strlen (cmdname);
94    cvsrcfile = open_file (homeinit, "r");
95    while ((line_length = get_line (&line, &line_chars_allocated, cvsrcfile))
96	   >= 0)
97    {
98	/* skip over comment lines */
99	if (line[0] == '#')
100	    continue;
101
102	/* stop if we match the current command */
103	if (!strncmp (line, cmdname, command_len)
104	    && isspace ((unsigned char) *(line + command_len)))
105	{
106	    found = 1;
107	    break;
108	}
109    }
110
111    if (line_length < 0 && !feof (cvsrcfile))
112	error (0, errno, "cannot read %s", homeinit);
113
114    fclose (cvsrcfile);
115
116    /* setup the new options list */
117
118    new_argc = 1;
119    max_new_argv = (*argc) + GROW;
120    new_argv = (char **) xmalloc (max_new_argv * sizeof (char*));
121    new_argv[0] = xstrdup ((*argv)[0]);
122
123    if (found)
124    {
125	/* skip over command in the options line */
126	for (optstart = strtok (line + command_len, "\t \n");
127	     optstart;
128	     optstart = strtok (NULL, "\t \n"))
129	{
130	    new_argv [new_argc++] = xstrdup (optstart);
131
132	    if (new_argc >= max_new_argv)
133	    {
134		max_new_argv += GROW;
135		new_argv = (char **) xrealloc (new_argv, max_new_argv * sizeof (char*));
136	    }
137	}
138    }
139
140    if (line != NULL)
141	free (line);
142
143    /* now copy the remaining arguments */
144
145    if (new_argc + *argc > max_new_argv)
146    {
147	max_new_argv = new_argc + *argc;
148	new_argv = (char **) xrealloc (new_argv, max_new_argv * sizeof (char*));
149    }
150    for (i=1; i < *argc; i++)
151    {
152	new_argv [new_argc++] = xstrdup ((*argv)[i]);
153    }
154
155    if (old_argv != NULL)
156    {
157	/* Free the memory which was allocated in the previous
158           read_cvsrc call.  */
159	free_names (&old_argc, old_argv);
160    }
161
162    old_argc = *argc = new_argc;
163    old_argv = *argv = new_argv;
164
165    free (homeinit);
166    return;
167}
168