xref: /dragonfly/contrib/cvs-1.12/src/cvsrc.c (revision 3142e03f)
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
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 
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 = strcat_filename_onto_homedir (homedir, cvsrc);
77 
78     /* if it can't be read, there's no point to continuing */
79 
80     if (!isreadable (homeinit))
81     {
82 	free (homeinit);
83 	return;
84     }
85 
86     /* now scan the file until we find the line for the command in question */
87 
88     line = NULL;
89     line_chars_allocated = 0;
90     command_len = strlen (cmdname);
91     cvsrcfile = xfopen (homeinit, "r");
92     while ((line_length = getline (&line, &line_chars_allocated, cvsrcfile))
93 	   >= 0)
94     {
95 	/* skip over comment lines */
96 	if (line[0] == '#')
97 	    continue;
98 
99 	/* stop if we match the current command */
100 	if (!strncmp (line, cmdname, command_len)
101 	    && isspace ((unsigned char) *(line + command_len)))
102 	{
103 	    found = 1;
104 	    break;
105 	}
106     }
107 
108     if (line_length < 0 && !feof (cvsrcfile))
109 	error (0, errno, "cannot read %s", homeinit);
110 
111     fclose (cvsrcfile);
112 
113     /* setup the new options list */
114 
115     new_argc = 1;
116     max_new_argv = (*argc) + GROW;
117     new_argv = xnmalloc (max_new_argv, sizeof (char *));
118     new_argv[0] = xstrdup ((*argv)[0]);
119 
120     if (found)
121     {
122 	/* skip over command in the options line */
123 	for (optstart = strtok (line + command_len, "\t \n");
124 	     optstart;
125 	     optstart = strtok (NULL, "\t \n"))
126 	{
127 	    new_argv [new_argc++] = xstrdup (optstart);
128 
129 	    if (new_argc >= max_new_argv)
130 	    {
131 		max_new_argv += GROW;
132 		new_argv = xnrealloc (new_argv, max_new_argv, sizeof (char *));
133 	    }
134 	}
135     }
136 
137     if (line != NULL)
138 	free (line);
139 
140     /* now copy the remaining arguments */
141 
142     if (new_argc + *argc > max_new_argv)
143     {
144 	max_new_argv = new_argc + *argc;
145 	new_argv = xnrealloc (new_argv, max_new_argv, sizeof (char *));
146     }
147     for (i = 1; i < *argc; i++)
148 	new_argv [new_argc++] = xstrdup ((*argv)[i]);
149 
150     if (old_argv != NULL)
151     {
152 	/* Free the memory which was allocated in the previous
153            read_cvsrc call.  */
154 	free_names (&old_argc, old_argv);
155     }
156 
157     old_argc = *argc = new_argc;
158     old_argv = *argv = new_argv;
159 
160     free (homeinit);
161     return;
162 }
163