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