xref: /openbsd/gnu/usr.bin/cvs/src/wrapper.c (revision f9bbbf45)
1780d15dfStholo /* This program is free software; you can redistribute it and/or modify
2780d15dfStholo    it under the terms of the GNU General Public License as published by
3780d15dfStholo    the Free Software Foundation; either version 2, or (at your option)
4780d15dfStholo    any later version.
5780d15dfStholo 
6780d15dfStholo    This program is distributed in the hope that it will be useful,
7780d15dfStholo    but WITHOUT ANY WARRANTY; without even the implied warranty of
8780d15dfStholo    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9780d15dfStholo    GNU General Public License for more details.  */
10780d15dfStholo 
111e72d8d2Sderaadt #include "cvs.h"
12780d15dfStholo #include "getline.h"
131e72d8d2Sderaadt 
141e72d8d2Sderaadt /*
151e72d8d2Sderaadt   Original Author:  athan@morgan.com <Andrew C. Athan> 2/1/94
161e72d8d2Sderaadt   Modified By:      vdemarco@bou.shl.com
171e72d8d2Sderaadt 
181e72d8d2Sderaadt   This package was written to support the NEXTSTEP concept of
191e72d8d2Sderaadt   "wrappers."  These are essentially directories that are to be
201e72d8d2Sderaadt   treated as "files."  This package allows such wrappers to be
211e72d8d2Sderaadt   "processed" on the way in and out of CVS.  The intended use is to
221e72d8d2Sderaadt   wrap up a wrapper into a single tar, such that that tar can be
231e72d8d2Sderaadt   treated as a single binary file in CVS.  To solve the problem
241e72d8d2Sderaadt   effectively, it was also necessary to be able to prevent rcsmerge
251e72d8d2Sderaadt   application at appropriate times.
261e72d8d2Sderaadt 
271e72d8d2Sderaadt   ------------------
281e72d8d2Sderaadt   Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
291e72d8d2Sderaadt 
301e72d8d2Sderaadt   wildcard	[option value][option value]...
311e72d8d2Sderaadt 
321e72d8d2Sderaadt   where option is one of
331e72d8d2Sderaadt   -f		from cvs filter		value: path to filter
341e72d8d2Sderaadt   -t		to cvs filter		value: path to filter
351e72d8d2Sderaadt   -m		update methodology	value: MERGE or COPY
3650bf276cStholo   -k		default -k rcs option to use on import or add
371e72d8d2Sderaadt 
381e72d8d2Sderaadt   and value is a single-quote delimited value.
391e72d8d2Sderaadt 
401e72d8d2Sderaadt   E.g:
411e72d8d2Sderaadt   *.nib		-f 'gunzipuntar' -t 'targzip' -m 'COPY'
421e72d8d2Sderaadt */
431e72d8d2Sderaadt 
441e72d8d2Sderaadt 
451e72d8d2Sderaadt typedef struct {
461e72d8d2Sderaadt     char *wildCard;
471e72d8d2Sderaadt     char *tocvsFilter;
481e72d8d2Sderaadt     char *fromcvsFilter;
4950bf276cStholo     char *rcsOption;
501e72d8d2Sderaadt     WrapMergeMethod mergeMethod;
511e72d8d2Sderaadt } WrapperEntry;
521e72d8d2Sderaadt 
531e72d8d2Sderaadt static WrapperEntry **wrap_list=NULL;
541e72d8d2Sderaadt static WrapperEntry **wrap_saved_list=NULL;
551e72d8d2Sderaadt 
561e72d8d2Sderaadt static int wrap_size=0;
571e72d8d2Sderaadt static int wrap_count=0;
581e72d8d2Sderaadt static int wrap_tempcount=0;
5950bf276cStholo 
602286d8edStholo /* FIXME: the relationship between wrap_count, wrap_tempcount,
612286d8edStholo  * wrap_saved_count, and wrap_saved_tempcount is not entirely clear;
622286d8edStholo  * it is certainly suspicious that wrap_saved_count is never set to a
632286d8edStholo  * value other than zero!  If the variable isn't being used, it should
642286d8edStholo  * be removed.  And in general, we should describe how temporary
652286d8edStholo  * vs. permanent wrappers are implemented, and then make sure the
662286d8edStholo  * implementation is actually doing that.
672286d8edStholo  *
682286d8edStholo  * Right now things seem to be working, but that's no guarantee there
692286d8edStholo  * isn't a bug lurking somewhere in the murk.
702286d8edStholo  */
7150bf276cStholo 
721e72d8d2Sderaadt static int wrap_saved_count=0;
7350bf276cStholo 
741e72d8d2Sderaadt static int wrap_saved_tempcount=0;
751e72d8d2Sderaadt 
761e72d8d2Sderaadt #define WRAPPER_GROW	8
771e72d8d2Sderaadt 
781e72d8d2Sderaadt void wrap_add_entry PROTO((WrapperEntry *e,int temp));
791e72d8d2Sderaadt void wrap_kill PROTO((void));
801e72d8d2Sderaadt void wrap_kill_temp PROTO((void));
811e72d8d2Sderaadt void wrap_free_entry PROTO((WrapperEntry *e));
821e72d8d2Sderaadt void wrap_free_entry_internal PROTO((WrapperEntry *e));
831e72d8d2Sderaadt void wrap_restore_saved PROTO((void));
841e72d8d2Sderaadt 
wrap_setup()851e72d8d2Sderaadt void wrap_setup()
861e72d8d2Sderaadt {
872286d8edStholo     /* FIXME-reentrancy: if we do a multithreaded server, will need to
882286d8edStholo        move this to a per-connection data structure, or better yet
892286d8edStholo        think about a cleaner solution.  */
902286d8edStholo     static int wrap_setup_already_done = 0;
912286d8edStholo     char *homedir;
922286d8edStholo 
932286d8edStholo     if (wrap_setup_already_done != 0)
942286d8edStholo         return;
952286d8edStholo     else
962286d8edStholo         wrap_setup_already_done = 1;
971e72d8d2Sderaadt 
9850bf276cStholo #ifdef CLIENT_SUPPORT
9943c1707eStholo     if (!current_parsed_root->isremote)
10050bf276cStholo #endif
10150bf276cStholo     {
102780d15dfStholo 	char *file;
103780d15dfStholo 
10443c1707eStholo 	file = xmalloc (strlen (current_parsed_root->directory)
105780d15dfStholo 			+ sizeof (CVSROOTADM)
106780d15dfStholo 			+ sizeof (CVSROOTADM_WRAPPER)
10743c1707eStholo 			+ 3);
10850bf276cStholo 	/* Then add entries found in repository, if it exists.  */
10943c1707eStholo 	(void) sprintf (file, "%s/%s/%s", current_parsed_root->directory, CVSROOTADM,
11050bf276cStholo 			CVSROOTADM_WRAPPER);
11150bf276cStholo 	if (isfile (file))
11250bf276cStholo 	{
1131e72d8d2Sderaadt 	    wrap_add_file(file,0);
1141e72d8d2Sderaadt 	}
115780d15dfStholo 	free (file);
11650bf276cStholo     }
1171e72d8d2Sderaadt 
11850bf276cStholo     /* Then add entries found in home dir, (if user has one) and file
1192286d8edStholo        exists.  */
1202286d8edStholo     homedir = get_homedir ();
121c71bc7e2Stholo     /* If we can't find a home directory, ignore ~/.cvswrappers.  This may
122c71bc7e2Stholo        make tracking down problems a bit of a pain, but on the other
123c71bc7e2Stholo        hand it might be obnoxious to complain when CVS will function
124c71bc7e2Stholo        just fine without .cvswrappers (and many users won't even know what
125c71bc7e2Stholo        .cvswrappers is).  */
1262286d8edStholo     if (homedir != NULL)
12750bf276cStholo     {
128780d15dfStholo 	char *file;
129780d15dfStholo 
1302286d8edStholo 	file = xmalloc (strlen (homedir) + sizeof (CVSDOTWRAPPER) + 10);
1312286d8edStholo 	(void) sprintf (file, "%s/%s", homedir, CVSDOTWRAPPER);
13250bf276cStholo 	if (isfile (file))
13350bf276cStholo 	{
1341e72d8d2Sderaadt 	    wrap_add_file (file, 0);
1351e72d8d2Sderaadt 	}
136780d15dfStholo 	free (file);
1371e72d8d2Sderaadt     }
1381e72d8d2Sderaadt 
1392286d8edStholo     /* FIXME: calling wrap_add() below implies that the CVSWRAPPERS
1402286d8edStholo      * environment variable contains exactly one "wrapper" -- a line
1412286d8edStholo      * of the form
1422286d8edStholo      *
1432286d8edStholo      *    FILENAME_PATTERN	FLAG  OPTS [ FLAG OPTS ...]
1442286d8edStholo      *
1452286d8edStholo      * This may disagree with the documentation, which states:
1462286d8edStholo      *
1472286d8edStholo      *   `$CVSWRAPPERS'
1482286d8edStholo      *      A whitespace-separated list of file name patterns that CVS
1492286d8edStholo      *      should treat as wrappers. *Note Wrappers::.
1502286d8edStholo      *
1512286d8edStholo      * Does this mean the environment variable can hold multiple
1522286d8edStholo      * wrappers lines?  If so, a single call to wrap_add() is
1532286d8edStholo      * insufficient.
1542286d8edStholo      */
1552286d8edStholo 
1561e72d8d2Sderaadt     /* Then add entries found in CVSWRAPPERS environment variable. */
1571e72d8d2Sderaadt     wrap_add (getenv (WRAPPER_ENV), 0);
1581e72d8d2Sderaadt }
1591e72d8d2Sderaadt 
16050bf276cStholo #ifdef CLIENT_SUPPORT
16150bf276cStholo /* Send -W arguments for the wrappers to the server.  The command must
16250bf276cStholo    be one that accepts them (e.g. update, import).  */
16350bf276cStholo void
wrap_send()16450bf276cStholo wrap_send ()
16550bf276cStholo {
16650bf276cStholo     int i;
16750bf276cStholo 
16850bf276cStholo     for (i = 0; i < wrap_count + wrap_tempcount; ++i)
16950bf276cStholo     {
17050bf276cStholo 	if (wrap_list[i]->tocvsFilter != NULL
17150bf276cStholo 	    || wrap_list[i]->fromcvsFilter != NULL)
17250bf276cStholo 	    /* For greater studliness we would print the offending option
17350bf276cStholo 	       and (more importantly) where we found it.  */
17450bf276cStholo 	    error (0, 0, "\
17550bf276cStholo -t and -f wrapper options are not supported remotely; ignored");
17650bf276cStholo 	if (wrap_list[i]->mergeMethod == WRAP_COPY)
17750bf276cStholo 	    /* For greater studliness we would print the offending option
17850bf276cStholo 	       and (more importantly) where we found it.  */
17950bf276cStholo 	    error (0, 0, "\
18050bf276cStholo -m wrapper option is not supported remotely; ignored");
18150bf276cStholo 	if (wrap_list[i]->rcsOption != NULL)
18250bf276cStholo 	{
18350bf276cStholo 	    send_to_server ("Argument -W\012Argument ", 0);
18450bf276cStholo 	    send_to_server (wrap_list[i]->wildCard, 0);
18550bf276cStholo 	    send_to_server (" -k '", 0);
18650bf276cStholo 	    send_to_server (wrap_list[i]->rcsOption, 0);
18750bf276cStholo 	    send_to_server ("'\012", 0);
18850bf276cStholo 	}
18950bf276cStholo     }
19050bf276cStholo }
19150bf276cStholo #endif /* CLIENT_SUPPORT */
19250bf276cStholo 
1932286d8edStholo #if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
1942286d8edStholo /* Output wrapper entries in the format of cvswrappers lines.
1952286d8edStholo  *
1962286d8edStholo  * This is useful when one side of a client/server connection wants to
1972286d8edStholo  * send its wrappers to the other; since the receiving side would like
1982286d8edStholo  * to use wrap_add() to incorporate the wrapper, it's best if the
1992286d8edStholo  * entry arrives in this format.
2002286d8edStholo  *
2012286d8edStholo  * The entries are stored in `line', which is allocated here.  Caller
2022286d8edStholo  * can free() it.
2032286d8edStholo  *
2042286d8edStholo  * If first_call_p is nonzero, then start afresh.  */
2052286d8edStholo void
wrap_unparse_rcs_options(line,first_call_p)2062286d8edStholo wrap_unparse_rcs_options (line, first_call_p)
2072286d8edStholo     char **line;
2082286d8edStholo     int first_call_p;
2092286d8edStholo {
2102286d8edStholo     /* FIXME-reentrancy: we should design a reentrant interface, like
2112286d8edStholo        a callback which gets handed each wrapper (a multithreaded
2122286d8edStholo        server being the most concrete reason for this, but the
2132286d8edStholo        non-reentrant interface is fairly unnecessary/ugly).  */
2142286d8edStholo     static int i;
2152286d8edStholo 
2162286d8edStholo     if (first_call_p)
2172286d8edStholo         i = 0;
2182286d8edStholo 
2192286d8edStholo     for (; i < wrap_count + wrap_tempcount; ++i)
2202286d8edStholo     {
2212286d8edStholo 	if (wrap_list[i]->rcsOption != NULL)
2222286d8edStholo 	{
2232286d8edStholo             *line = xmalloc (strlen (wrap_list[i]->wildCard)
2242286d8edStholo                              + strlen ("\t")
2252286d8edStholo                              + strlen (" -k '")
2262286d8edStholo                              + strlen (wrap_list[i]->rcsOption)
2272286d8edStholo                              + strlen ("'")
2282286d8edStholo                              + 1);  /* leave room for '\0' */
2292286d8edStholo 
2302286d8edStholo             strcpy (*line, wrap_list[i]->wildCard);
2312286d8edStholo             strcat (*line, " -k '");
2322286d8edStholo             strcat (*line, wrap_list[i]->rcsOption);
2332286d8edStholo             strcat (*line, "'");
2342286d8edStholo 
2352286d8edStholo             /* We're going to miss the increment because we return, so
2362286d8edStholo                do it by hand. */
2372286d8edStholo             ++i;
2382286d8edStholo 
2392286d8edStholo             return;
2402286d8edStholo 	}
2412286d8edStholo     }
2422286d8edStholo 
2432286d8edStholo     *line = NULL;
2442286d8edStholo     return;
2452286d8edStholo }
2462286d8edStholo #endif /* SERVER_SUPPORT || CLIENT_SUPPORT */
2472286d8edStholo 
2481e72d8d2Sderaadt /*
2492ddaa231Sotto  * Remove fmt str specifier other than %% or %s. And allow
2502ddaa231Sotto  * only max_s %s specifiers
2512ddaa231Sotto  */
25297e794f8Sjsg void
wrap_clean_fmt_str(char * fmt,int max_s)2532ddaa231Sotto wrap_clean_fmt_str(char *fmt, int max_s)
2542ddaa231Sotto {
2552ddaa231Sotto     while (*fmt) {
2562ddaa231Sotto 	if (fmt[0] == '%' && fmt[1])
2572ddaa231Sotto 	{
2582ddaa231Sotto 	    if (fmt[1] == '%')
2592ddaa231Sotto 		fmt++;
2602ddaa231Sotto 	    else
2612ddaa231Sotto 		if (fmt[1] == 's' && max_s > 0)
2622ddaa231Sotto 		{
2632ddaa231Sotto 		    max_s--;
2642ddaa231Sotto 		    fmt++;
2652ddaa231Sotto 		} else
2662ddaa231Sotto 		    *fmt = ' ';
2672ddaa231Sotto 	}
2682ddaa231Sotto 	fmt++;
2692ddaa231Sotto     }
2702ddaa231Sotto }
2712ddaa231Sotto 
2722ddaa231Sotto /*
2731e72d8d2Sderaadt  * Open a file and read lines, feeding each line to a line parser. Arrange
2741e72d8d2Sderaadt  * for keeping a temporary list of wrappers at the end, if the "temp"
2751e72d8d2Sderaadt  * argument is set.
2761e72d8d2Sderaadt  */
2771e72d8d2Sderaadt void
wrap_add_file(file,temp)2781e72d8d2Sderaadt wrap_add_file (file, temp)
2791e72d8d2Sderaadt     const char *file;
2801e72d8d2Sderaadt     int temp;
2811e72d8d2Sderaadt {
2821e72d8d2Sderaadt     FILE *fp;
283780d15dfStholo     char *line = NULL;
284780d15dfStholo     size_t line_allocated = 0;
2851e72d8d2Sderaadt 
2861e72d8d2Sderaadt     wrap_restore_saved ();
2871e72d8d2Sderaadt     wrap_kill_temp ();
2881e72d8d2Sderaadt 
289780d15dfStholo     /* Load the file.  */
290780d15dfStholo     fp = CVS_FOPEN (file, "r");
291780d15dfStholo     if (fp == NULL)
292780d15dfStholo     {
293780d15dfStholo 	if (!existence_error (errno))
294780d15dfStholo 	    error (0, errno, "cannot open %s", file);
2951e72d8d2Sderaadt 	return;
296780d15dfStholo     }
297*f9bbbf45Sfgsch     while (get_line (&line, &line_allocated, fp) >= 0)
2981e72d8d2Sderaadt 	wrap_add (line, temp);
2992770ece5Stholo     if (line)
3002770ece5Stholo         free (line);
301780d15dfStholo     if (ferror (fp))
302780d15dfStholo 	error (0, errno, "cannot read %s", file);
303780d15dfStholo     if (fclose (fp) == EOF)
304780d15dfStholo 	error (0, errno, "cannot close %s", file);
3051e72d8d2Sderaadt }
3061e72d8d2Sderaadt 
3071e72d8d2Sderaadt void
wrap_kill()3081e72d8d2Sderaadt wrap_kill()
3091e72d8d2Sderaadt {
3101e72d8d2Sderaadt     wrap_kill_temp();
3111e72d8d2Sderaadt     while(wrap_count)
3121e72d8d2Sderaadt 	wrap_free_entry(wrap_list[--wrap_count]);
3131e72d8d2Sderaadt }
3141e72d8d2Sderaadt 
3151e72d8d2Sderaadt void
wrap_kill_temp()3161e72d8d2Sderaadt wrap_kill_temp()
3171e72d8d2Sderaadt {
3181e72d8d2Sderaadt     WrapperEntry **temps=wrap_list+wrap_count;
3191e72d8d2Sderaadt 
3201e72d8d2Sderaadt     while(wrap_tempcount)
3211e72d8d2Sderaadt 	wrap_free_entry(temps[--wrap_tempcount]);
3221e72d8d2Sderaadt }
3231e72d8d2Sderaadt 
3241e72d8d2Sderaadt void
wrap_free_entry(e)3251e72d8d2Sderaadt wrap_free_entry(e)
3261e72d8d2Sderaadt      WrapperEntry *e;
3271e72d8d2Sderaadt {
3281e72d8d2Sderaadt     wrap_free_entry_internal(e);
3291e72d8d2Sderaadt     free(e);
3301e72d8d2Sderaadt }
3311e72d8d2Sderaadt 
3321e72d8d2Sderaadt void
wrap_free_entry_internal(e)3331e72d8d2Sderaadt wrap_free_entry_internal(e)
3341e72d8d2Sderaadt     WrapperEntry *e;
3351e72d8d2Sderaadt {
3361e72d8d2Sderaadt     free (e->wildCard);
3371e72d8d2Sderaadt     if (e->tocvsFilter)
3381e72d8d2Sderaadt 	free (e->tocvsFilter);
3391e72d8d2Sderaadt     if (e->fromcvsFilter)
3401e72d8d2Sderaadt 	free (e->fromcvsFilter);
34150bf276cStholo     if (e->rcsOption)
34250bf276cStholo 	free (e->rcsOption);
3431e72d8d2Sderaadt }
3441e72d8d2Sderaadt 
3451e72d8d2Sderaadt void
wrap_restore_saved()3461e72d8d2Sderaadt wrap_restore_saved()
3471e72d8d2Sderaadt {
3481e72d8d2Sderaadt     if(!wrap_saved_list)
3491e72d8d2Sderaadt 	return;
3501e72d8d2Sderaadt 
3511e72d8d2Sderaadt     wrap_kill();
3521e72d8d2Sderaadt 
3531e72d8d2Sderaadt     free(wrap_list);
3541e72d8d2Sderaadt 
3551e72d8d2Sderaadt     wrap_list=wrap_saved_list;
3561e72d8d2Sderaadt     wrap_count=wrap_saved_count;
3571e72d8d2Sderaadt     wrap_tempcount=wrap_saved_tempcount;
3581e72d8d2Sderaadt 
3591e72d8d2Sderaadt     wrap_saved_list=NULL;
3601e72d8d2Sderaadt     wrap_saved_count=0;
3611e72d8d2Sderaadt     wrap_saved_tempcount=0;
3621e72d8d2Sderaadt }
3631e72d8d2Sderaadt 
3641e72d8d2Sderaadt void
wrap_add(line,isTemp)3651e72d8d2Sderaadt wrap_add (line, isTemp)
3661e72d8d2Sderaadt    char *line;
3671e72d8d2Sderaadt    int         isTemp;
3681e72d8d2Sderaadt {
3691e72d8d2Sderaadt     char *temp;
3701e72d8d2Sderaadt     char ctemp;
3711e72d8d2Sderaadt     WrapperEntry e;
3721e72d8d2Sderaadt     char opt;
3731e72d8d2Sderaadt 
3741e72d8d2Sderaadt     if (!line || line[0] == '#')
3751e72d8d2Sderaadt 	return;
3761e72d8d2Sderaadt 
3771e72d8d2Sderaadt     memset (&e, 0, sizeof(e));
3781e72d8d2Sderaadt 
3791e72d8d2Sderaadt 	/* Search for the wild card */
380c71bc7e2Stholo     while (*line && isspace ((unsigned char) *line))
3811e72d8d2Sderaadt 	++line;
382c71bc7e2Stholo     for (temp = line;
383c71bc7e2Stholo 	 *line && !isspace ((unsigned char) *line);
384c71bc7e2Stholo 	 ++line)
3851e72d8d2Sderaadt 	;
3861e72d8d2Sderaadt     if(temp==line)
3871e72d8d2Sderaadt 	return;
3881e72d8d2Sderaadt 
3891e72d8d2Sderaadt     ctemp=*line;
3901e72d8d2Sderaadt     *line='\0';
3911e72d8d2Sderaadt 
3921e72d8d2Sderaadt     e.wildCard=xstrdup(temp);
3931e72d8d2Sderaadt     *line=ctemp;
3941e72d8d2Sderaadt 
3951e72d8d2Sderaadt     while(*line){
3961e72d8d2Sderaadt 	    /* Search for the option */
3971e72d8d2Sderaadt 	while(*line && *line!='-')
3981e72d8d2Sderaadt 	    ++line;
3991e72d8d2Sderaadt 	if(!*line)
4001e72d8d2Sderaadt 	    break;
4011e72d8d2Sderaadt 	++line;
4021e72d8d2Sderaadt 	if(!*line)
4031e72d8d2Sderaadt 	    break;
4041e72d8d2Sderaadt 	opt=*line;
4051e72d8d2Sderaadt 
4061e72d8d2Sderaadt 	    /* Search for the filter commandline */
4071e72d8d2Sderaadt 	for(++line;*line && *line!='\'';++line);
4081e72d8d2Sderaadt 	if(!*line)
4091e72d8d2Sderaadt 	    break;
4101e72d8d2Sderaadt 
4111e72d8d2Sderaadt 	for(temp=++line;*line && (*line!='\'' || line[-1]=='\\');++line)
4121e72d8d2Sderaadt 	    ;
4131e72d8d2Sderaadt 
41450bf276cStholo 	/* This used to "break;" (ignore the option) if there was a
41550bf276cStholo 	   single character between the single quotes (I'm guessing
41650bf276cStholo 	   that was accidental).  Now it "break;"s if there are no
41750bf276cStholo 	   characters.  I'm not sure either behavior is particularly
41850bf276cStholo 	   necessary--the current options might not require ''
41950bf276cStholo 	   arguments, but surely some future option legitimately
42050bf276cStholo 	   might.  Also I'm not sure that ignoring the option is a
42150bf276cStholo 	   swift way to handle syntax errors in general.  */
42250bf276cStholo 	if (line==temp)
4231e72d8d2Sderaadt 	    break;
4241e72d8d2Sderaadt 
4251e72d8d2Sderaadt 	ctemp=*line;
4261e72d8d2Sderaadt 	*line='\0';
4271e72d8d2Sderaadt 	switch(opt){
4281e72d8d2Sderaadt 	case 'f':
429b6f6614eStholo 	    /* Before this is reenabled, need to address the problem in
430b6f6614eStholo 	       commit.c (see http://www.cyclic.com/cvs/dev-wrap.txt).  */
431b6f6614eStholo 	    error (1, 0,
432b6f6614eStholo 		   "-t/-f wrappers not supported by this version of CVS");
433b6f6614eStholo 
4341e72d8d2Sderaadt 	    if(e.fromcvsFilter)
4351e72d8d2Sderaadt 		free(e.fromcvsFilter);
436c26070a5Stholo 	    /* FIXME: error message should say where the bad value
437c26070a5Stholo 	       came from.  */
438c26070a5Stholo 	    e.fromcvsFilter=expand_path (temp, "<wrapper>", 0);
43913571821Stholo             if (!e.fromcvsFilter)
440c26070a5Stholo 		error (1, 0, "Correct above errors first");
4411e72d8d2Sderaadt 	    break;
4421e72d8d2Sderaadt 	case 't':
443b6f6614eStholo 	    /* Before this is reenabled, need to address the problem in
444b6f6614eStholo 	       commit.c (see http://www.cyclic.com/cvs/dev-wrap.txt).  */
445b6f6614eStholo 	    error (1, 0,
446b6f6614eStholo 		   "-t/-f wrappers not supported by this version of CVS");
447b6f6614eStholo 
4481e72d8d2Sderaadt 	    if(e.tocvsFilter)
4491e72d8d2Sderaadt 		free(e.tocvsFilter);
450c26070a5Stholo 	    /* FIXME: error message should say where the bad value
451c26070a5Stholo 	       came from.  */
452c26070a5Stholo 	    e.tocvsFilter=expand_path (temp, "<wrapper>", 0);
45313571821Stholo             if (!e.tocvsFilter)
454c26070a5Stholo 		error (1, 0, "Correct above errors first");
4551e72d8d2Sderaadt 	    break;
4561e72d8d2Sderaadt 	case 'm':
4571e72d8d2Sderaadt 	    if(*temp=='C' || *temp=='c')
4581e72d8d2Sderaadt 		e.mergeMethod=WRAP_COPY;
4591e72d8d2Sderaadt 	    else
4601e72d8d2Sderaadt 		e.mergeMethod=WRAP_MERGE;
4611e72d8d2Sderaadt 	    break;
46250bf276cStholo 	case 'k':
46350bf276cStholo 	    if (e.rcsOption)
46450bf276cStholo 		free (e.rcsOption);
46550bf276cStholo 	    e.rcsOption = xstrdup (temp);
46650bf276cStholo 	    break;
4671e72d8d2Sderaadt 	default:
4681e72d8d2Sderaadt 	    break;
4691e72d8d2Sderaadt 	}
4701e72d8d2Sderaadt 	*line=ctemp;
4711e72d8d2Sderaadt 	if(!*line)break;
4721e72d8d2Sderaadt 	++line;
4731e72d8d2Sderaadt     }
4741e72d8d2Sderaadt 
4751e72d8d2Sderaadt     wrap_add_entry(&e, isTemp);
4761e72d8d2Sderaadt }
4771e72d8d2Sderaadt 
4781e72d8d2Sderaadt void
wrap_add_entry(e,temp)4791e72d8d2Sderaadt wrap_add_entry(e, temp)
4801e72d8d2Sderaadt     WrapperEntry *e;
4811e72d8d2Sderaadt     int temp;
4821e72d8d2Sderaadt {
4831e72d8d2Sderaadt     int x;
4841e72d8d2Sderaadt     if(wrap_count+wrap_tempcount>=wrap_size){
4851e72d8d2Sderaadt 	wrap_size += WRAPPER_GROW;
4861e72d8d2Sderaadt 	wrap_list = (WrapperEntry **) xrealloc ((char *) wrap_list,
4871e72d8d2Sderaadt 						wrap_size *
4881e72d8d2Sderaadt 						sizeof (WrapperEntry *));
4891e72d8d2Sderaadt     }
4901e72d8d2Sderaadt 
4911e72d8d2Sderaadt     if(!temp && wrap_tempcount){
4921e72d8d2Sderaadt 	for(x=wrap_count+wrap_tempcount-1;x>=wrap_count;--x)
4931e72d8d2Sderaadt 	    wrap_list[x+1]=wrap_list[x];
4941e72d8d2Sderaadt     }
4951e72d8d2Sderaadt 
4961e72d8d2Sderaadt     x=(temp ? wrap_count+(wrap_tempcount++):(wrap_count++));
4971e72d8d2Sderaadt     wrap_list[x]=(WrapperEntry *)xmalloc(sizeof(WrapperEntry));
4981e72d8d2Sderaadt     wrap_list[x]->wildCard=e->wildCard;
4991e72d8d2Sderaadt     wrap_list[x]->fromcvsFilter=e->fromcvsFilter;
5001e72d8d2Sderaadt     wrap_list[x]->tocvsFilter=e->tocvsFilter;
5011e72d8d2Sderaadt     wrap_list[x]->mergeMethod=e->mergeMethod;
50250bf276cStholo     wrap_list[x]->rcsOption = e->rcsOption;
5031e72d8d2Sderaadt }
5041e72d8d2Sderaadt 
5051e72d8d2Sderaadt /* Return 1 if the given filename is a wrapper filename */
5061e72d8d2Sderaadt int
wrap_name_has(name,has)5071e72d8d2Sderaadt wrap_name_has (name,has)
5081e72d8d2Sderaadt     const char   *name;
5091e72d8d2Sderaadt     WrapMergeHas  has;
5101e72d8d2Sderaadt {
5112286d8edStholo     int x,count=wrap_count+wrap_tempcount;
5121e72d8d2Sderaadt     char *temp;
5131e72d8d2Sderaadt 
5141e72d8d2Sderaadt     for(x=0;x<count;++x)
5152770ece5Stholo 	if (CVS_FNMATCH (wrap_list[x]->wildCard, name, 0) == 0){
5161e72d8d2Sderaadt 	    switch(has){
5171e72d8d2Sderaadt 	    case WRAP_TOCVS:
5181e72d8d2Sderaadt 		temp=wrap_list[x]->tocvsFilter;
5191e72d8d2Sderaadt 		break;
5201e72d8d2Sderaadt 	    case WRAP_FROMCVS:
5211e72d8d2Sderaadt 		temp=wrap_list[x]->fromcvsFilter;
5221e72d8d2Sderaadt 		break;
52350bf276cStholo 	    case WRAP_RCSOPTION:
52450bf276cStholo 		temp = wrap_list[x]->rcsOption;
5251e72d8d2Sderaadt 		break;
5261e72d8d2Sderaadt 	    default:
5271e72d8d2Sderaadt 	        abort ();
5281e72d8d2Sderaadt 	    }
5291e72d8d2Sderaadt 	    if(temp==NULL)
5301e72d8d2Sderaadt 		return (0);
5311e72d8d2Sderaadt 	    else
5321e72d8d2Sderaadt 		return (1);
5331e72d8d2Sderaadt 	}
5341e72d8d2Sderaadt     return (0);
5351e72d8d2Sderaadt }
5361e72d8d2Sderaadt 
537461cc63eStholo static WrapperEntry *wrap_matching_entry PROTO ((const char *));
538461cc63eStholo 
539461cc63eStholo static WrapperEntry *
wrap_matching_entry(name)5401e72d8d2Sderaadt wrap_matching_entry (name)
5411e72d8d2Sderaadt     const char *name;
5421e72d8d2Sderaadt {
5432286d8edStholo     int x,count=wrap_count+wrap_tempcount;
5441e72d8d2Sderaadt 
5451e72d8d2Sderaadt     for(x=0;x<count;++x)
5462770ece5Stholo 	if (CVS_FNMATCH (wrap_list[x]->wildCard, name, 0) == 0)
5471e72d8d2Sderaadt 	    return wrap_list[x];
5481e72d8d2Sderaadt     return (WrapperEntry *)NULL;
5491e72d8d2Sderaadt }
5501e72d8d2Sderaadt 
55150bf276cStholo /* Return the RCS options for FILENAME in a newly malloc'd string.  If
55250bf276cStholo    ASFLAG, then include "-k" at the beginning (e.g. "-kb"), otherwise
55350bf276cStholo    just give the option itself (e.g. "b").  */
55450bf276cStholo char *
wrap_rcsoption(filename,asflag)55550bf276cStholo wrap_rcsoption (filename, asflag)
55650bf276cStholo     const char *filename;
55750bf276cStholo     int asflag;
55850bf276cStholo {
55950bf276cStholo     WrapperEntry *e = wrap_matching_entry (filename);
56050bf276cStholo     char *buf;
56150bf276cStholo 
56250bf276cStholo     if (e == NULL || e->rcsOption == NULL || (*e->rcsOption == '\0'))
56350bf276cStholo 	return NULL;
56450bf276cStholo 
56550bf276cStholo     buf = xmalloc (strlen (e->rcsOption) + 3);
56650bf276cStholo     if (asflag)
56750bf276cStholo     {
56850bf276cStholo 	strcpy (buf, "-k");
56950bf276cStholo 	strcat (buf, e->rcsOption);
57050bf276cStholo     }
57150bf276cStholo     else
57250bf276cStholo     {
57350bf276cStholo 	strcpy (buf, e->rcsOption);
57450bf276cStholo     }
57550bf276cStholo     return buf;
57650bf276cStholo }
57750bf276cStholo 
5781e72d8d2Sderaadt char *
wrap_tocvs_process_file(fileName)5791e72d8d2Sderaadt wrap_tocvs_process_file(fileName)
5801e72d8d2Sderaadt     const char *fileName;
5811e72d8d2Sderaadt {
5821e72d8d2Sderaadt     WrapperEntry *e=wrap_matching_entry(fileName);
58350bf276cStholo     static char *buf = NULL;
5842286d8edStholo     char *args;
5851e72d8d2Sderaadt 
5861e72d8d2Sderaadt     if(e==NULL || e->tocvsFilter==NULL)
5871e72d8d2Sderaadt 	return NULL;
5881e72d8d2Sderaadt 
58950bf276cStholo     if (buf != NULL)
59050bf276cStholo 	free (buf);
59150bf276cStholo     buf = cvs_temp_name ();
5921e72d8d2Sderaadt 
5932286d8edStholo     args = xmalloc (strlen (e->tocvsFilter)
5942286d8edStholo 		    + strlen (fileName)
5952286d8edStholo 		    + strlen (buf));
5962ddaa231Sotto 
5972ddaa231Sotto     wrap_clean_fmt_str(e->tocvsFilter, 2);
5982286d8edStholo     sprintf (args, e->tocvsFilter, fileName, buf);
5992286d8edStholo     run_setup (args);
6001e72d8d2Sderaadt     run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY );
6012286d8edStholo     free (args);
6021e72d8d2Sderaadt 
6031e72d8d2Sderaadt     return buf;
6041e72d8d2Sderaadt }
6051e72d8d2Sderaadt 
6061e72d8d2Sderaadt int
wrap_merge_is_copy(fileName)6071e72d8d2Sderaadt wrap_merge_is_copy (fileName)
6081e72d8d2Sderaadt     const char *fileName;
6091e72d8d2Sderaadt {
6101e72d8d2Sderaadt     WrapperEntry *e=wrap_matching_entry(fileName);
6111e72d8d2Sderaadt     if(e==NULL || e->mergeMethod==WRAP_MERGE)
6121e72d8d2Sderaadt 	return 0;
6131e72d8d2Sderaadt 
6141e72d8d2Sderaadt     return 1;
6151e72d8d2Sderaadt }
6161e72d8d2Sderaadt 
617780d15dfStholo void
wrap_fromcvs_process_file(fileName)6181e72d8d2Sderaadt wrap_fromcvs_process_file(fileName)
6191e72d8d2Sderaadt     const char *fileName;
6201e72d8d2Sderaadt {
6212286d8edStholo     char *args;
6221e72d8d2Sderaadt     WrapperEntry *e=wrap_matching_entry(fileName);
6231e72d8d2Sderaadt 
6241e72d8d2Sderaadt     if(e==NULL || e->fromcvsFilter==NULL)
625780d15dfStholo 	return;
6261e72d8d2Sderaadt 
6272286d8edStholo     args = xmalloc (strlen (e->fromcvsFilter)
6282286d8edStholo 		    + strlen (fileName));
6292ddaa231Sotto 
6302ddaa231Sotto     wrap_clean_fmt_str(e->fromcvsFilter, 1);
6312286d8edStholo     sprintf (args, e->fromcvsFilter, fileName);
6322286d8edStholo     run_setup (args);
6331e72d8d2Sderaadt     run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL );
6342286d8edStholo     free (args);
635780d15dfStholo     return;
6361e72d8d2Sderaadt }
637