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