xref: /openbsd/gnu/usr.bin/cvs/src/cvsrc.c (revision 898184e3)
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
20 char cvsrc[] = CVSRC_FILENAME;
21 
22 #define	GROW	10
23 
24 extern char *strtok ();
25 
26 /* Read cvsrc, processing options matching CMDNAME ("cvs" for global
27    options, and update *ARGC and *ARGV accordingly.  */
28 
29 void
30 read_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