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