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