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