xref: /dflybsd-src/contrib/cvs-1.12/src/wrapper.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
1*86d7f5d3SJohn Marino /* This program is free software; you can redistribute it and/or modify
2*86d7f5d3SJohn Marino    it under the terms of the GNU General Public License as published by
3*86d7f5d3SJohn Marino    the Free Software Foundation; either version 2, or (at your option)
4*86d7f5d3SJohn Marino    any later version.
5*86d7f5d3SJohn Marino 
6*86d7f5d3SJohn Marino    This program is distributed in the hope that it will be useful,
7*86d7f5d3SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
8*86d7f5d3SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9*86d7f5d3SJohn Marino    GNU General Public License for more details.  */
10*86d7f5d3SJohn Marino 
11*86d7f5d3SJohn Marino #include "cvs.h"
12*86d7f5d3SJohn Marino #include "getline.h"
13*86d7f5d3SJohn Marino 
14*86d7f5d3SJohn Marino /*
15*86d7f5d3SJohn Marino   Original Author:  athan@morgan.com <Andrew C. Athan> 2/1/94
16*86d7f5d3SJohn Marino   Modified By:      vdemarco@bou.shl.com
17*86d7f5d3SJohn Marino 
18*86d7f5d3SJohn Marino   This package was written to support the NEXTSTEP concept of
19*86d7f5d3SJohn Marino   "wrappers."  These are essentially directories that are to be
20*86d7f5d3SJohn Marino   treated as "files."  This package allows such wrappers to be
21*86d7f5d3SJohn Marino   "processed" on the way in and out of CVS.  The intended use is to
22*86d7f5d3SJohn Marino   wrap up a wrapper into a single tar, such that that tar can be
23*86d7f5d3SJohn Marino   treated as a single binary file in CVS.  To solve the problem
24*86d7f5d3SJohn Marino   effectively, it was also necessary to be able to prevent rcsmerge
25*86d7f5d3SJohn Marino   application at appropriate times.
26*86d7f5d3SJohn Marino 
27*86d7f5d3SJohn Marino   ------------------
28*86d7f5d3SJohn Marino   Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
29*86d7f5d3SJohn Marino 
30*86d7f5d3SJohn Marino   wildcard	[option value][option value]...
31*86d7f5d3SJohn Marino 
32*86d7f5d3SJohn Marino   where option is one of
33*86d7f5d3SJohn Marino   -m		update methodology	value: MERGE or COPY
34*86d7f5d3SJohn Marino   -k		default -k rcs option to use on import or add
35*86d7f5d3SJohn Marino 
36*86d7f5d3SJohn Marino   and value is a single-quote delimited value.
37*86d7f5d3SJohn Marino 
38*86d7f5d3SJohn Marino   E.g:
39*86d7f5d3SJohn Marino   *.nib		-f 'gunzipuntar' -t 'targzip' -m 'COPY'
40*86d7f5d3SJohn Marino */
41*86d7f5d3SJohn Marino 
42*86d7f5d3SJohn Marino 
43*86d7f5d3SJohn Marino typedef struct {
44*86d7f5d3SJohn Marino     char *wildCard;
45*86d7f5d3SJohn Marino     char *tocvsFilter;
46*86d7f5d3SJohn Marino     char *fromcvsFilter;
47*86d7f5d3SJohn Marino     char *rcsOption;
48*86d7f5d3SJohn Marino     WrapMergeMethod mergeMethod;
49*86d7f5d3SJohn Marino } WrapperEntry;
50*86d7f5d3SJohn Marino 
51*86d7f5d3SJohn Marino static WrapperEntry **wrap_list=NULL;
52*86d7f5d3SJohn Marino static WrapperEntry **wrap_saved_list=NULL;
53*86d7f5d3SJohn Marino 
54*86d7f5d3SJohn Marino static int wrap_size=0;
55*86d7f5d3SJohn Marino static int wrap_count=0;
56*86d7f5d3SJohn Marino static int wrap_tempcount=0;
57*86d7f5d3SJohn Marino 
58*86d7f5d3SJohn Marino /* FIXME: the relationship between wrap_count, wrap_tempcount,
59*86d7f5d3SJohn Marino  * wrap_saved_count, and wrap_saved_tempcount is not entirely clear;
60*86d7f5d3SJohn Marino  * it is certainly suspicious that wrap_saved_count is never set to a
61*86d7f5d3SJohn Marino  * value other than zero!  If the variable isn't being used, it should
62*86d7f5d3SJohn Marino  * be removed.  And in general, we should describe how temporary
63*86d7f5d3SJohn Marino  * vs. permanent wrappers are implemented, and then make sure the
64*86d7f5d3SJohn Marino  * implementation is actually doing that.
65*86d7f5d3SJohn Marino  *
66*86d7f5d3SJohn Marino  * Right now things seem to be working, but that's no guarantee there
67*86d7f5d3SJohn Marino  * isn't a bug lurking somewhere in the murk.
68*86d7f5d3SJohn Marino  */
69*86d7f5d3SJohn Marino 
70*86d7f5d3SJohn Marino static int wrap_saved_count=0;
71*86d7f5d3SJohn Marino 
72*86d7f5d3SJohn Marino static int wrap_saved_tempcount=0;
73*86d7f5d3SJohn Marino 
74*86d7f5d3SJohn Marino #define WRAPPER_GROW	8
75*86d7f5d3SJohn Marino 
76*86d7f5d3SJohn Marino void wrap_add_entry (WrapperEntry *e,int temp);
77*86d7f5d3SJohn Marino void wrap_kill (void);
78*86d7f5d3SJohn Marino void wrap_kill_temp (void);
79*86d7f5d3SJohn Marino void wrap_free_entry (WrapperEntry *e);
80*86d7f5d3SJohn Marino void wrap_free_entry_internal (WrapperEntry *e);
81*86d7f5d3SJohn Marino void wrap_restore_saved (void);
82*86d7f5d3SJohn Marino 
wrap_setup(void)83*86d7f5d3SJohn Marino void wrap_setup(void)
84*86d7f5d3SJohn Marino {
85*86d7f5d3SJohn Marino     /* FIXME-reentrancy: if we do a multithreaded server, will need to
86*86d7f5d3SJohn Marino        move this to a per-connection data structure, or better yet
87*86d7f5d3SJohn Marino        think about a cleaner solution.  */
88*86d7f5d3SJohn Marino     static int wrap_setup_already_done = 0;
89*86d7f5d3SJohn Marino     char *homedir;
90*86d7f5d3SJohn Marino 
91*86d7f5d3SJohn Marino     if (wrap_setup_already_done != 0)
92*86d7f5d3SJohn Marino         return;
93*86d7f5d3SJohn Marino     else
94*86d7f5d3SJohn Marino         wrap_setup_already_done = 1;
95*86d7f5d3SJohn Marino 
96*86d7f5d3SJohn Marino     if (!current_parsed_root->isremote)
97*86d7f5d3SJohn Marino     {
98*86d7f5d3SJohn Marino 	char *file;
99*86d7f5d3SJohn Marino 
100*86d7f5d3SJohn Marino 	/* Then add entries found in repository, if it exists.  */
101*86d7f5d3SJohn Marino 	file = Xasprintf ("%s/%s/%s", current_parsed_root->directory,
102*86d7f5d3SJohn Marino 			  CVSROOTADM, CVSROOTADM_WRAPPER);
103*86d7f5d3SJohn Marino 	if (isfile (file))
104*86d7f5d3SJohn Marino 	{
105*86d7f5d3SJohn Marino 	    wrap_add_file(file,0);
106*86d7f5d3SJohn Marino 	}
107*86d7f5d3SJohn Marino 	free (file);
108*86d7f5d3SJohn Marino     }
109*86d7f5d3SJohn Marino 
110*86d7f5d3SJohn Marino     /* Then add entries found in home dir, (if user has one) and file
111*86d7f5d3SJohn Marino        exists.  */
112*86d7f5d3SJohn Marino     homedir = get_homedir ();
113*86d7f5d3SJohn Marino     /* If we can't find a home directory, ignore ~/.cvswrappers.  This may
114*86d7f5d3SJohn Marino        make tracking down problems a bit of a pain, but on the other
115*86d7f5d3SJohn Marino        hand it might be obnoxious to complain when CVS will function
116*86d7f5d3SJohn Marino        just fine without .cvswrappers (and many users won't even know what
117*86d7f5d3SJohn Marino        .cvswrappers is).  */
118*86d7f5d3SJohn Marino     if (homedir != NULL)
119*86d7f5d3SJohn Marino     {
120*86d7f5d3SJohn Marino 	char *file = strcat_filename_onto_homedir (homedir, CVSDOTWRAPPER);
121*86d7f5d3SJohn Marino 	if (isfile (file))
122*86d7f5d3SJohn Marino 	{
123*86d7f5d3SJohn Marino 	    wrap_add_file (file, 0);
124*86d7f5d3SJohn Marino 	}
125*86d7f5d3SJohn Marino 	free (file);
126*86d7f5d3SJohn Marino     }
127*86d7f5d3SJohn Marino 
128*86d7f5d3SJohn Marino     /* FIXME: calling wrap_add() below implies that the CVSWRAPPERS
129*86d7f5d3SJohn Marino      * environment variable contains exactly one "wrapper" -- a line
130*86d7f5d3SJohn Marino      * of the form
131*86d7f5d3SJohn Marino      *
132*86d7f5d3SJohn Marino      *    FILENAME_PATTERN	FLAG  OPTS [ FLAG OPTS ...]
133*86d7f5d3SJohn Marino      *
134*86d7f5d3SJohn Marino      * This may disagree with the documentation, which states:
135*86d7f5d3SJohn Marino      *
136*86d7f5d3SJohn Marino      *   `$CVSWRAPPERS'
137*86d7f5d3SJohn Marino      *      A whitespace-separated list of file name patterns that CVS
138*86d7f5d3SJohn Marino      *      should treat as wrappers. *Note Wrappers::.
139*86d7f5d3SJohn Marino      *
140*86d7f5d3SJohn Marino      * Does this mean the environment variable can hold multiple
141*86d7f5d3SJohn Marino      * wrappers lines?  If so, a single call to wrap_add() is
142*86d7f5d3SJohn Marino      * insufficient.
143*86d7f5d3SJohn Marino      */
144*86d7f5d3SJohn Marino 
145*86d7f5d3SJohn Marino     /* Then add entries found in CVSWRAPPERS environment variable. */
146*86d7f5d3SJohn Marino     wrap_add (getenv (WRAPPER_ENV), 0);
147*86d7f5d3SJohn Marino }
148*86d7f5d3SJohn Marino 
149*86d7f5d3SJohn Marino #ifdef CLIENT_SUPPORT
150*86d7f5d3SJohn Marino /* Send -W arguments for the wrappers to the server.  The command must
151*86d7f5d3SJohn Marino    be one that accepts them (e.g. update, import).  */
152*86d7f5d3SJohn Marino void
wrap_send(void)153*86d7f5d3SJohn Marino wrap_send (void)
154*86d7f5d3SJohn Marino {
155*86d7f5d3SJohn Marino     int i;
156*86d7f5d3SJohn Marino 
157*86d7f5d3SJohn Marino     for (i = 0; i < wrap_count + wrap_tempcount; ++i)
158*86d7f5d3SJohn Marino     {
159*86d7f5d3SJohn Marino 	if (wrap_list[i]->tocvsFilter != NULL
160*86d7f5d3SJohn Marino 	    || wrap_list[i]->fromcvsFilter != NULL)
161*86d7f5d3SJohn Marino 	    /* For greater studliness we would print the offending option
162*86d7f5d3SJohn Marino 	       and (more importantly) where we found it.  */
163*86d7f5d3SJohn Marino 	    error (0, 0, "\
164*86d7f5d3SJohn Marino -t and -f wrapper options are not supported remotely; ignored");
165*86d7f5d3SJohn Marino 	if (wrap_list[i]->mergeMethod == WRAP_COPY)
166*86d7f5d3SJohn Marino 	    /* For greater studliness we would print the offending option
167*86d7f5d3SJohn Marino 	       and (more importantly) where we found it.  */
168*86d7f5d3SJohn Marino 	    error (0, 0, "\
169*86d7f5d3SJohn Marino -m wrapper option is not supported remotely; ignored");
170*86d7f5d3SJohn Marino 	send_to_server ("Argument -W\012Argument ", 0);
171*86d7f5d3SJohn Marino 	send_to_server (wrap_list[i]->wildCard, 0);
172*86d7f5d3SJohn Marino 	send_to_server (" -k '", 0);
173*86d7f5d3SJohn Marino 	if (wrap_list[i]->rcsOption != NULL)
174*86d7f5d3SJohn Marino 	    send_to_server (wrap_list[i]->rcsOption, 0);
175*86d7f5d3SJohn Marino 	else
176*86d7f5d3SJohn Marino 	    send_to_server ("kv", 0);
177*86d7f5d3SJohn Marino 	send_to_server ("'\012", 0);
178*86d7f5d3SJohn Marino     }
179*86d7f5d3SJohn Marino }
180*86d7f5d3SJohn Marino #endif /* CLIENT_SUPPORT */
181*86d7f5d3SJohn Marino 
182*86d7f5d3SJohn Marino #if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
183*86d7f5d3SJohn Marino /* Output wrapper entries in the format of cvswrappers lines.
184*86d7f5d3SJohn Marino  *
185*86d7f5d3SJohn Marino  * This is useful when one side of a client/server connection wants to
186*86d7f5d3SJohn Marino  * send its wrappers to the other; since the receiving side would like
187*86d7f5d3SJohn Marino  * to use wrap_add() to incorporate the wrapper, it's best if the
188*86d7f5d3SJohn Marino  * entry arrives in this format.
189*86d7f5d3SJohn Marino  *
190*86d7f5d3SJohn Marino  * The entries are stored in `line', which is allocated here.  Caller
191*86d7f5d3SJohn Marino  * can free() it.
192*86d7f5d3SJohn Marino  *
193*86d7f5d3SJohn Marino  * If first_call_p is nonzero, then start afresh.  */
194*86d7f5d3SJohn Marino void
wrap_unparse_rcs_options(char ** line,int first_call_p)195*86d7f5d3SJohn Marino wrap_unparse_rcs_options (char **line, int first_call_p)
196*86d7f5d3SJohn Marino {
197*86d7f5d3SJohn Marino     /* FIXME-reentrancy: we should design a reentrant interface, like
198*86d7f5d3SJohn Marino        a callback which gets handed each wrapper (a multithreaded
199*86d7f5d3SJohn Marino        server being the most concrete reason for this, but the
200*86d7f5d3SJohn Marino        non-reentrant interface is fairly unnecessary/ugly).  */
201*86d7f5d3SJohn Marino     static int i;
202*86d7f5d3SJohn Marino 
203*86d7f5d3SJohn Marino     if (first_call_p)
204*86d7f5d3SJohn Marino         i = 0;
205*86d7f5d3SJohn Marino 
206*86d7f5d3SJohn Marino     if (i >= wrap_count + wrap_tempcount) {
207*86d7f5d3SJohn Marino         *line = NULL;
208*86d7f5d3SJohn Marino         return;
209*86d7f5d3SJohn Marino     }
210*86d7f5d3SJohn Marino 
211*86d7f5d3SJohn Marino     *line = Xasprintf ("%s -k '%s'",
212*86d7f5d3SJohn Marino 		       wrap_list[i]->wildCard,
213*86d7f5d3SJohn Marino 		       wrap_list[i]->rcsOption
214*86d7f5d3SJohn Marino 		       ? wrap_list[i]->rcsOption : "kv");
215*86d7f5d3SJohn Marino     ++i;
216*86d7f5d3SJohn Marino }
217*86d7f5d3SJohn Marino #endif /* SERVER_SUPPORT || CLIENT_SUPPORT */
218*86d7f5d3SJohn Marino 
219*86d7f5d3SJohn Marino /*
220*86d7f5d3SJohn Marino  * Remove fmt str specifier other than %% or %s. And allow
221*86d7f5d3SJohn Marino  * only max_s %s specifiers
222*86d7f5d3SJohn Marino  */
223*86d7f5d3SJohn Marino static void
wrap_clean_fmt_str(char * fmt,int max_s)224*86d7f5d3SJohn Marino wrap_clean_fmt_str(char *fmt, int max_s)
225*86d7f5d3SJohn Marino {
226*86d7f5d3SJohn Marino     while (*fmt) {
227*86d7f5d3SJohn Marino 	if (fmt[0] == '%' && fmt[1])
228*86d7f5d3SJohn Marino 	{
229*86d7f5d3SJohn Marino 	    if (fmt[1] == '%')
230*86d7f5d3SJohn Marino 		fmt++;
231*86d7f5d3SJohn Marino 	    else
232*86d7f5d3SJohn Marino 		if (fmt[1] == 's' && max_s > 0)
233*86d7f5d3SJohn Marino 		{
234*86d7f5d3SJohn Marino 		    max_s--;
235*86d7f5d3SJohn Marino 		    fmt++;
236*86d7f5d3SJohn Marino 		} else
237*86d7f5d3SJohn Marino 		    *fmt = ' ';
238*86d7f5d3SJohn Marino 	}
239*86d7f5d3SJohn Marino 	fmt++;
240*86d7f5d3SJohn Marino     }
241*86d7f5d3SJohn Marino }
242*86d7f5d3SJohn Marino 
243*86d7f5d3SJohn Marino /*
244*86d7f5d3SJohn Marino  * Open a file and read lines, feeding each line to a line parser. Arrange
245*86d7f5d3SJohn Marino  * for keeping a temporary list of wrappers at the end, if the "temp"
246*86d7f5d3SJohn Marino  * argument is set.
247*86d7f5d3SJohn Marino  */
248*86d7f5d3SJohn Marino void
wrap_add_file(const char * file,int temp)249*86d7f5d3SJohn Marino wrap_add_file (const char *file, int temp)
250*86d7f5d3SJohn Marino {
251*86d7f5d3SJohn Marino     FILE *fp;
252*86d7f5d3SJohn Marino     char *line = NULL;
253*86d7f5d3SJohn Marino     size_t line_allocated = 0;
254*86d7f5d3SJohn Marino 
255*86d7f5d3SJohn Marino     wrap_restore_saved ();
256*86d7f5d3SJohn Marino     wrap_kill_temp ();
257*86d7f5d3SJohn Marino 
258*86d7f5d3SJohn Marino     /* Load the file.  */
259*86d7f5d3SJohn Marino     fp = CVS_FOPEN (file, "r");
260*86d7f5d3SJohn Marino     if (fp == NULL)
261*86d7f5d3SJohn Marino     {
262*86d7f5d3SJohn Marino 	if (!existence_error (errno))
263*86d7f5d3SJohn Marino 	    error (0, errno, "cannot open %s", file);
264*86d7f5d3SJohn Marino 	return;
265*86d7f5d3SJohn Marino     }
266*86d7f5d3SJohn Marino     while (getline (&line, &line_allocated, fp) >= 0)
267*86d7f5d3SJohn Marino 	wrap_add (line, temp);
268*86d7f5d3SJohn Marino     if (line)
269*86d7f5d3SJohn Marino         free (line);
270*86d7f5d3SJohn Marino     if (ferror (fp))
271*86d7f5d3SJohn Marino 	error (0, errno, "cannot read %s", file);
272*86d7f5d3SJohn Marino     if (fclose (fp) == EOF)
273*86d7f5d3SJohn Marino 	error (0, errno, "cannot close %s", file);
274*86d7f5d3SJohn Marino }
275*86d7f5d3SJohn Marino 
276*86d7f5d3SJohn Marino void
wrap_kill(void)277*86d7f5d3SJohn Marino wrap_kill(void)
278*86d7f5d3SJohn Marino {
279*86d7f5d3SJohn Marino     wrap_kill_temp();
280*86d7f5d3SJohn Marino     while(wrap_count)
281*86d7f5d3SJohn Marino 	wrap_free_entry(wrap_list[--wrap_count]);
282*86d7f5d3SJohn Marino }
283*86d7f5d3SJohn Marino 
284*86d7f5d3SJohn Marino void
wrap_kill_temp(void)285*86d7f5d3SJohn Marino wrap_kill_temp(void)
286*86d7f5d3SJohn Marino {
287*86d7f5d3SJohn Marino     WrapperEntry **temps=wrap_list+wrap_count;
288*86d7f5d3SJohn Marino 
289*86d7f5d3SJohn Marino     while(wrap_tempcount)
290*86d7f5d3SJohn Marino 	wrap_free_entry(temps[--wrap_tempcount]);
291*86d7f5d3SJohn Marino }
292*86d7f5d3SJohn Marino 
293*86d7f5d3SJohn Marino void
wrap_free_entry(WrapperEntry * e)294*86d7f5d3SJohn Marino wrap_free_entry(WrapperEntry *e)
295*86d7f5d3SJohn Marino {
296*86d7f5d3SJohn Marino     wrap_free_entry_internal(e);
297*86d7f5d3SJohn Marino     free(e);
298*86d7f5d3SJohn Marino }
299*86d7f5d3SJohn Marino 
300*86d7f5d3SJohn Marino void
wrap_free_entry_internal(WrapperEntry * e)301*86d7f5d3SJohn Marino wrap_free_entry_internal(WrapperEntry *e)
302*86d7f5d3SJohn Marino {
303*86d7f5d3SJohn Marino     free (e->wildCard);
304*86d7f5d3SJohn Marino     if (e->tocvsFilter)
305*86d7f5d3SJohn Marino 	free (e->tocvsFilter);
306*86d7f5d3SJohn Marino     if (e->fromcvsFilter)
307*86d7f5d3SJohn Marino 	free (e->fromcvsFilter);
308*86d7f5d3SJohn Marino     if (e->rcsOption)
309*86d7f5d3SJohn Marino 	free (e->rcsOption);
310*86d7f5d3SJohn Marino }
311*86d7f5d3SJohn Marino 
312*86d7f5d3SJohn Marino void
wrap_restore_saved(void)313*86d7f5d3SJohn Marino wrap_restore_saved(void)
314*86d7f5d3SJohn Marino {
315*86d7f5d3SJohn Marino     if(!wrap_saved_list)
316*86d7f5d3SJohn Marino 	return;
317*86d7f5d3SJohn Marino 
318*86d7f5d3SJohn Marino     wrap_kill();
319*86d7f5d3SJohn Marino 
320*86d7f5d3SJohn Marino     free(wrap_list);
321*86d7f5d3SJohn Marino 
322*86d7f5d3SJohn Marino     wrap_list=wrap_saved_list;
323*86d7f5d3SJohn Marino     wrap_count=wrap_saved_count;
324*86d7f5d3SJohn Marino     wrap_tempcount=wrap_saved_tempcount;
325*86d7f5d3SJohn Marino 
326*86d7f5d3SJohn Marino     wrap_saved_list=NULL;
327*86d7f5d3SJohn Marino     wrap_saved_count=0;
328*86d7f5d3SJohn Marino     wrap_saved_tempcount=0;
329*86d7f5d3SJohn Marino }
330*86d7f5d3SJohn Marino 
331*86d7f5d3SJohn Marino void
wrap_add(char * line,int isTemp)332*86d7f5d3SJohn Marino wrap_add (char *line, int isTemp)
333*86d7f5d3SJohn Marino {
334*86d7f5d3SJohn Marino     char *temp;
335*86d7f5d3SJohn Marino     char ctemp;
336*86d7f5d3SJohn Marino     WrapperEntry e;
337*86d7f5d3SJohn Marino     char opt;
338*86d7f5d3SJohn Marino 
339*86d7f5d3SJohn Marino     if (!line || line[0] == '#')
340*86d7f5d3SJohn Marino 	return;
341*86d7f5d3SJohn Marino 
342*86d7f5d3SJohn Marino     memset (&e, 0, sizeof(e));
343*86d7f5d3SJohn Marino 
344*86d7f5d3SJohn Marino 	/* Search for the wild card */
345*86d7f5d3SJohn Marino     while (*line && isspace ((unsigned char) *line))
346*86d7f5d3SJohn Marino 	++line;
347*86d7f5d3SJohn Marino     for (temp = line;
348*86d7f5d3SJohn Marino 	 *line && !isspace ((unsigned char) *line);
349*86d7f5d3SJohn Marino 	 ++line)
350*86d7f5d3SJohn Marino 	;
351*86d7f5d3SJohn Marino     if(temp==line)
352*86d7f5d3SJohn Marino 	return;
353*86d7f5d3SJohn Marino 
354*86d7f5d3SJohn Marino     ctemp=*line;
355*86d7f5d3SJohn Marino     *line='\0';
356*86d7f5d3SJohn Marino 
357*86d7f5d3SJohn Marino     e.wildCard=xstrdup(temp);
358*86d7f5d3SJohn Marino     *line=ctemp;
359*86d7f5d3SJohn Marino 
360*86d7f5d3SJohn Marino     while(*line){
361*86d7f5d3SJohn Marino 	    /* Search for the option */
362*86d7f5d3SJohn Marino 	while(*line && *line!='-')
363*86d7f5d3SJohn Marino 	    ++line;
364*86d7f5d3SJohn Marino 	if(!*line)
365*86d7f5d3SJohn Marino 	    break;
366*86d7f5d3SJohn Marino 	++line;
367*86d7f5d3SJohn Marino 	if(!*line)
368*86d7f5d3SJohn Marino 	    break;
369*86d7f5d3SJohn Marino 	opt=*line;
370*86d7f5d3SJohn Marino 
371*86d7f5d3SJohn Marino 	    /* Search for the filter commandline */
372*86d7f5d3SJohn Marino 	for(++line;*line && *line!='\'';++line);
373*86d7f5d3SJohn Marino 	if(!*line)
374*86d7f5d3SJohn Marino 	    break;
375*86d7f5d3SJohn Marino 
376*86d7f5d3SJohn Marino 	for(temp=++line;*line && (*line!='\'' || line[-1]=='\\');++line)
377*86d7f5d3SJohn Marino 	    ;
378*86d7f5d3SJohn Marino 
379*86d7f5d3SJohn Marino 	/* This used to "break;" (ignore the option) if there was a
380*86d7f5d3SJohn Marino 	   single character between the single quotes (I'm guessing
381*86d7f5d3SJohn Marino 	   that was accidental).  Now it "break;"s if there are no
382*86d7f5d3SJohn Marino 	   characters.  I'm not sure either behavior is particularly
383*86d7f5d3SJohn Marino 	   necessary--the current options might not require ''
384*86d7f5d3SJohn Marino 	   arguments, but surely some future option legitimately
385*86d7f5d3SJohn Marino 	   might.  Also I'm not sure that ignoring the option is a
386*86d7f5d3SJohn Marino 	   swift way to handle syntax errors in general.  */
387*86d7f5d3SJohn Marino 	if (line==temp)
388*86d7f5d3SJohn Marino 	    break;
389*86d7f5d3SJohn Marino 
390*86d7f5d3SJohn Marino 	ctemp=*line;
391*86d7f5d3SJohn Marino 	*line='\0';
392*86d7f5d3SJohn Marino 	switch(opt){
393*86d7f5d3SJohn Marino 	case 'f':
394*86d7f5d3SJohn Marino 	    /* Before this is reenabled, need to address the problem in
395*86d7f5d3SJohn Marino 	       commit.c (see
396*86d7f5d3SJohn Marino 	       <http://ximbiot.com/cvs/cvshome/docs/infowrapper.html>).  */
397*86d7f5d3SJohn Marino 	    error (1, 0,
398*86d7f5d3SJohn Marino 		   "-t/-f wrappers not supported by this version of CVS");
399*86d7f5d3SJohn Marino 
400*86d7f5d3SJohn Marino 	    if(e.fromcvsFilter)
401*86d7f5d3SJohn Marino 		free(e.fromcvsFilter);
402*86d7f5d3SJohn Marino 	    /* FIXME: error message should say where the bad value
403*86d7f5d3SJohn Marino 	       came from.  */
404*86d7f5d3SJohn Marino 	    e.fromcvsFilter =
405*86d7f5d3SJohn Marino 	      expand_path (temp, current_parsed_root->directory, false,
406*86d7f5d3SJohn Marino 			   "<wrapper>", 0);
407*86d7f5d3SJohn Marino             if (!e.fromcvsFilter)
408*86d7f5d3SJohn Marino 		error (1, 0, "Correct above errors first");
409*86d7f5d3SJohn Marino 	    break;
410*86d7f5d3SJohn Marino 	case 't':
411*86d7f5d3SJohn Marino 	    /* Before this is reenabled, need to address the problem in
412*86d7f5d3SJohn Marino 	       commit.c (see
413*86d7f5d3SJohn Marino 	       <http://ximbiot.com/cvs/cvshome/docs/infowrapper.html>).  */
414*86d7f5d3SJohn Marino 	    error (1, 0,
415*86d7f5d3SJohn Marino 		   "-t/-f wrappers not supported by this version of CVS");
416*86d7f5d3SJohn Marino 
417*86d7f5d3SJohn Marino 	    if(e.tocvsFilter)
418*86d7f5d3SJohn Marino 		free(e.tocvsFilter);
419*86d7f5d3SJohn Marino 	    /* FIXME: error message should say where the bad value
420*86d7f5d3SJohn Marino 	       came from.  */
421*86d7f5d3SJohn Marino 	    e.tocvsFilter = expand_path (temp, current_parsed_root->directory,
422*86d7f5d3SJohn Marino 					 false, "<wrapper>", 0);
423*86d7f5d3SJohn Marino             if (!e.tocvsFilter)
424*86d7f5d3SJohn Marino 		error (1, 0, "Correct above errors first");
425*86d7f5d3SJohn Marino 	    break;
426*86d7f5d3SJohn Marino 	case 'm':
427*86d7f5d3SJohn Marino 	    if(*temp=='C' || *temp=='c')
428*86d7f5d3SJohn Marino 		e.mergeMethod=WRAP_COPY;
429*86d7f5d3SJohn Marino 	    else
430*86d7f5d3SJohn Marino 		e.mergeMethod=WRAP_MERGE;
431*86d7f5d3SJohn Marino 	    break;
432*86d7f5d3SJohn Marino 	case 'k':
433*86d7f5d3SJohn Marino 	    if (e.rcsOption)
434*86d7f5d3SJohn Marino 		free (e.rcsOption);
435*86d7f5d3SJohn Marino 	    e.rcsOption = strcmp (temp, "kv") ? xstrdup (temp) : NULL;
436*86d7f5d3SJohn Marino 	    break;
437*86d7f5d3SJohn Marino 	default:
438*86d7f5d3SJohn Marino 	    break;
439*86d7f5d3SJohn Marino 	}
440*86d7f5d3SJohn Marino 	*line=ctemp;
441*86d7f5d3SJohn Marino 	if(!*line)break;
442*86d7f5d3SJohn Marino 	++line;
443*86d7f5d3SJohn Marino     }
444*86d7f5d3SJohn Marino 
445*86d7f5d3SJohn Marino     wrap_add_entry(&e, isTemp);
446*86d7f5d3SJohn Marino }
447*86d7f5d3SJohn Marino 
448*86d7f5d3SJohn Marino void
wrap_add_entry(WrapperEntry * e,int temp)449*86d7f5d3SJohn Marino wrap_add_entry (WrapperEntry *e, int temp)
450*86d7f5d3SJohn Marino {
451*86d7f5d3SJohn Marino     int x;
452*86d7f5d3SJohn Marino     if (wrap_count + wrap_tempcount >= wrap_size)
453*86d7f5d3SJohn Marino     {
454*86d7f5d3SJohn Marino 	wrap_size += WRAPPER_GROW;
455*86d7f5d3SJohn Marino 	wrap_list = xnrealloc (wrap_list, wrap_size, sizeof (WrapperEntry *));
456*86d7f5d3SJohn Marino     }
457*86d7f5d3SJohn Marino 
458*86d7f5d3SJohn Marino     if (!temp && wrap_tempcount)
459*86d7f5d3SJohn Marino     {
460*86d7f5d3SJohn Marino 	for (x = wrap_count + wrap_tempcount - 1; x >= wrap_count; --x)
461*86d7f5d3SJohn Marino 	    wrap_list[x + 1] = wrap_list[x];
462*86d7f5d3SJohn Marino     }
463*86d7f5d3SJohn Marino 
464*86d7f5d3SJohn Marino     x = (temp ? wrap_count + (wrap_tempcount++) : (wrap_count++));
465*86d7f5d3SJohn Marino     wrap_list[x] = xmalloc (sizeof (WrapperEntry));
466*86d7f5d3SJohn Marino     *wrap_list[x] = *e;
467*86d7f5d3SJohn Marino }
468*86d7f5d3SJohn Marino 
469*86d7f5d3SJohn Marino /* Return 1 if the given filename is a wrapper filename */
470*86d7f5d3SJohn Marino int
wrap_name_has(const char * name,WrapMergeHas has)471*86d7f5d3SJohn Marino wrap_name_has (const char *name, WrapMergeHas has)
472*86d7f5d3SJohn Marino {
473*86d7f5d3SJohn Marino     int x,count=wrap_count+wrap_tempcount;
474*86d7f5d3SJohn Marino     char *temp;
475*86d7f5d3SJohn Marino 
476*86d7f5d3SJohn Marino     for(x=0;x<count;++x)
477*86d7f5d3SJohn Marino 	if (CVS_FNMATCH (wrap_list[x]->wildCard, name, 0) == 0){
478*86d7f5d3SJohn Marino 	    switch(has){
479*86d7f5d3SJohn Marino 	    case WRAP_TOCVS:
480*86d7f5d3SJohn Marino 		temp=wrap_list[x]->tocvsFilter;
481*86d7f5d3SJohn Marino 		break;
482*86d7f5d3SJohn Marino 	    case WRAP_FROMCVS:
483*86d7f5d3SJohn Marino 		temp=wrap_list[x]->fromcvsFilter;
484*86d7f5d3SJohn Marino 		break;
485*86d7f5d3SJohn Marino 	    case WRAP_RCSOPTION:
486*86d7f5d3SJohn Marino 		temp = wrap_list[x]->rcsOption;
487*86d7f5d3SJohn Marino 		break;
488*86d7f5d3SJohn Marino 	    default:
489*86d7f5d3SJohn Marino 	        abort ();
490*86d7f5d3SJohn Marino 	    }
491*86d7f5d3SJohn Marino 	    if(temp==NULL)
492*86d7f5d3SJohn Marino 		return (0);
493*86d7f5d3SJohn Marino 	    else
494*86d7f5d3SJohn Marino 		return (1);
495*86d7f5d3SJohn Marino 	}
496*86d7f5d3SJohn Marino     return (0);
497*86d7f5d3SJohn Marino }
498*86d7f5d3SJohn Marino 
499*86d7f5d3SJohn Marino static WrapperEntry *wrap_matching_entry (const char *);
500*86d7f5d3SJohn Marino 
501*86d7f5d3SJohn Marino static WrapperEntry *
wrap_matching_entry(const char * name)502*86d7f5d3SJohn Marino wrap_matching_entry (const char *name)
503*86d7f5d3SJohn Marino {
504*86d7f5d3SJohn Marino     int x,count=wrap_count+wrap_tempcount;
505*86d7f5d3SJohn Marino 
506*86d7f5d3SJohn Marino     for(x=0;x<count;++x)
507*86d7f5d3SJohn Marino 	if (CVS_FNMATCH (wrap_list[x]->wildCard, name, 0) == 0)
508*86d7f5d3SJohn Marino 	    return wrap_list[x];
509*86d7f5d3SJohn Marino     return NULL;
510*86d7f5d3SJohn Marino }
511*86d7f5d3SJohn Marino 
512*86d7f5d3SJohn Marino /* Return the RCS options for FILENAME in a newly malloc'd string.  If
513*86d7f5d3SJohn Marino    ASFLAG, then include "-k" at the beginning (e.g. "-kb"), otherwise
514*86d7f5d3SJohn Marino    just give the option itself (e.g. "b").  */
515*86d7f5d3SJohn Marino char *
wrap_rcsoption(const char * filename,int asflag)516*86d7f5d3SJohn Marino wrap_rcsoption (const char *filename, int asflag)
517*86d7f5d3SJohn Marino {
518*86d7f5d3SJohn Marino     WrapperEntry *e = wrap_matching_entry (filename);
519*86d7f5d3SJohn Marino 
520*86d7f5d3SJohn Marino     if (e == NULL || e->rcsOption == NULL || (*e->rcsOption == '\0'))
521*86d7f5d3SJohn Marino 	return NULL;
522*86d7f5d3SJohn Marino 
523*86d7f5d3SJohn Marino     return Xasprintf ("%s%s", asflag ? "-k" : "", e->rcsOption);
524*86d7f5d3SJohn Marino }
525*86d7f5d3SJohn Marino 
526*86d7f5d3SJohn Marino char *
wrap_tocvs_process_file(const char * fileName)527*86d7f5d3SJohn Marino wrap_tocvs_process_file(const char *fileName)
528*86d7f5d3SJohn Marino {
529*86d7f5d3SJohn Marino     WrapperEntry *e=wrap_matching_entry(fileName);
530*86d7f5d3SJohn Marino     static char *buf = NULL;
531*86d7f5d3SJohn Marino     char *args;
532*86d7f5d3SJohn Marino 
533*86d7f5d3SJohn Marino     if(e==NULL || e->tocvsFilter==NULL)
534*86d7f5d3SJohn Marino 	return NULL;
535*86d7f5d3SJohn Marino 
536*86d7f5d3SJohn Marino     if (buf != NULL)
537*86d7f5d3SJohn Marino 	free (buf);
538*86d7f5d3SJohn Marino     buf = cvs_temp_name ();
539*86d7f5d3SJohn Marino 
540*86d7f5d3SJohn Marino     wrap_clean_fmt_str (e->tocvsFilter, 2);
541*86d7f5d3SJohn Marino     args = Xasprintf (e->tocvsFilter, fileName, buf);
542*86d7f5d3SJohn Marino     run_setup (args);
543*86d7f5d3SJohn Marino     run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL | RUN_REALLY );
544*86d7f5d3SJohn Marino     free (args);
545*86d7f5d3SJohn Marino 
546*86d7f5d3SJohn Marino     return buf;
547*86d7f5d3SJohn Marino }
548*86d7f5d3SJohn Marino 
549*86d7f5d3SJohn Marino int
wrap_merge_is_copy(const char * fileName)550*86d7f5d3SJohn Marino wrap_merge_is_copy (const char *fileName)
551*86d7f5d3SJohn Marino {
552*86d7f5d3SJohn Marino     WrapperEntry *e=wrap_matching_entry(fileName);
553*86d7f5d3SJohn Marino     if(e==NULL || e->mergeMethod==WRAP_MERGE)
554*86d7f5d3SJohn Marino 	return 0;
555*86d7f5d3SJohn Marino 
556*86d7f5d3SJohn Marino     return 1;
557*86d7f5d3SJohn Marino }
558*86d7f5d3SJohn Marino 
559*86d7f5d3SJohn Marino void
wrap_fromcvs_process_file(const char * fileName)560*86d7f5d3SJohn Marino wrap_fromcvs_process_file(const char *fileName)
561*86d7f5d3SJohn Marino {
562*86d7f5d3SJohn Marino     char *args;
563*86d7f5d3SJohn Marino     WrapperEntry *e = wrap_matching_entry(fileName);
564*86d7f5d3SJohn Marino 
565*86d7f5d3SJohn Marino     if (e != NULL && e->fromcvsFilter != NULL)
566*86d7f5d3SJohn Marino     {
567*86d7f5d3SJohn Marino 	wrap_clean_fmt_str (e->fromcvsFilter, 1);
568*86d7f5d3SJohn Marino 	args = Xasprintf (e->fromcvsFilter, fileName);
569*86d7f5d3SJohn Marino 	run_setup (args);
570*86d7f5d3SJohn Marino 	run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
571*86d7f5d3SJohn Marino 	free (args);
572*86d7f5d3SJohn Marino     }
573*86d7f5d3SJohn Marino     return;
574*86d7f5d3SJohn Marino }
575