186d7f5d3SJohn Marino /* This program is free software; you can redistribute it and/or modify
286d7f5d3SJohn Marino it under the terms of the GNU General Public License as published by
386d7f5d3SJohn Marino the Free Software Foundation; either version 2, or (at your option)
486d7f5d3SJohn Marino any later version.
586d7f5d3SJohn Marino
686d7f5d3SJohn Marino This program is distributed in the hope that it will be useful,
786d7f5d3SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
886d7f5d3SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
986d7f5d3SJohn Marino GNU General Public License for more details. */
1086d7f5d3SJohn Marino
1186d7f5d3SJohn Marino #include "cvs.h"
1286d7f5d3SJohn Marino #include "getline.h"
1386d7f5d3SJohn Marino
1486d7f5d3SJohn Marino /*
1586d7f5d3SJohn Marino Original Author: athan@morgan.com <Andrew C. Athan> 2/1/94
1686d7f5d3SJohn Marino Modified By: vdemarco@bou.shl.com
1786d7f5d3SJohn Marino
1886d7f5d3SJohn Marino This package was written to support the NEXTSTEP concept of
1986d7f5d3SJohn Marino "wrappers." These are essentially directories that are to be
2086d7f5d3SJohn Marino treated as "files." This package allows such wrappers to be
2186d7f5d3SJohn Marino "processed" on the way in and out of CVS. The intended use is to
2286d7f5d3SJohn Marino wrap up a wrapper into a single tar, such that that tar can be
2386d7f5d3SJohn Marino treated as a single binary file in CVS. To solve the problem
2486d7f5d3SJohn Marino effectively, it was also necessary to be able to prevent rcsmerge
2586d7f5d3SJohn Marino application at appropriate times.
2686d7f5d3SJohn Marino
2786d7f5d3SJohn Marino ------------------
2886d7f5d3SJohn Marino Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers)
2986d7f5d3SJohn Marino
3086d7f5d3SJohn Marino wildcard [option value][option value]...
3186d7f5d3SJohn Marino
3286d7f5d3SJohn Marino where option is one of
3386d7f5d3SJohn Marino -m update methodology value: MERGE or COPY
3486d7f5d3SJohn Marino -k default -k rcs option to use on import or add
3586d7f5d3SJohn Marino
3686d7f5d3SJohn Marino and value is a single-quote delimited value.
3786d7f5d3SJohn Marino
3886d7f5d3SJohn Marino E.g:
3986d7f5d3SJohn Marino *.nib -f 'gunzipuntar' -t 'targzip' -m 'COPY'
4086d7f5d3SJohn Marino */
4186d7f5d3SJohn Marino
4286d7f5d3SJohn Marino
4386d7f5d3SJohn Marino typedef struct {
4486d7f5d3SJohn Marino char *wildCard;
4586d7f5d3SJohn Marino char *tocvsFilter;
4686d7f5d3SJohn Marino char *fromcvsFilter;
4786d7f5d3SJohn Marino char *rcsOption;
4886d7f5d3SJohn Marino WrapMergeMethod mergeMethod;
4986d7f5d3SJohn Marino } WrapperEntry;
5086d7f5d3SJohn Marino
5186d7f5d3SJohn Marino static WrapperEntry **wrap_list=NULL;
5286d7f5d3SJohn Marino static WrapperEntry **wrap_saved_list=NULL;
5386d7f5d3SJohn Marino
5486d7f5d3SJohn Marino static int wrap_size=0;
5586d7f5d3SJohn Marino static int wrap_count=0;
5686d7f5d3SJohn Marino static int wrap_tempcount=0;
5786d7f5d3SJohn Marino
5886d7f5d3SJohn Marino /* FIXME: the relationship between wrap_count, wrap_tempcount,
5986d7f5d3SJohn Marino * wrap_saved_count, and wrap_saved_tempcount is not entirely clear;
6086d7f5d3SJohn Marino * it is certainly suspicious that wrap_saved_count is never set to a
6186d7f5d3SJohn Marino * value other than zero! If the variable isn't being used, it should
6286d7f5d3SJohn Marino * be removed. And in general, we should describe how temporary
6386d7f5d3SJohn Marino * vs. permanent wrappers are implemented, and then make sure the
6486d7f5d3SJohn Marino * implementation is actually doing that.
6586d7f5d3SJohn Marino *
6686d7f5d3SJohn Marino * Right now things seem to be working, but that's no guarantee there
6786d7f5d3SJohn Marino * isn't a bug lurking somewhere in the murk.
6886d7f5d3SJohn Marino */
6986d7f5d3SJohn Marino
7086d7f5d3SJohn Marino static int wrap_saved_count=0;
7186d7f5d3SJohn Marino
7286d7f5d3SJohn Marino static int wrap_saved_tempcount=0;
7386d7f5d3SJohn Marino
7486d7f5d3SJohn Marino #define WRAPPER_GROW 8
7586d7f5d3SJohn Marino
7686d7f5d3SJohn Marino void wrap_add_entry (WrapperEntry *e,int temp);
7786d7f5d3SJohn Marino void wrap_kill (void);
7886d7f5d3SJohn Marino void wrap_kill_temp (void);
7986d7f5d3SJohn Marino void wrap_free_entry (WrapperEntry *e);
8086d7f5d3SJohn Marino void wrap_free_entry_internal (WrapperEntry *e);
8186d7f5d3SJohn Marino void wrap_restore_saved (void);
8286d7f5d3SJohn Marino
wrap_setup(void)8386d7f5d3SJohn Marino void wrap_setup(void)
8486d7f5d3SJohn Marino {
8586d7f5d3SJohn Marino /* FIXME-reentrancy: if we do a multithreaded server, will need to
8686d7f5d3SJohn Marino move this to a per-connection data structure, or better yet
8786d7f5d3SJohn Marino think about a cleaner solution. */
8886d7f5d3SJohn Marino static int wrap_setup_already_done = 0;
8986d7f5d3SJohn Marino char *homedir;
9086d7f5d3SJohn Marino
9186d7f5d3SJohn Marino if (wrap_setup_already_done != 0)
9286d7f5d3SJohn Marino return;
9386d7f5d3SJohn Marino else
9486d7f5d3SJohn Marino wrap_setup_already_done = 1;
9586d7f5d3SJohn Marino
9686d7f5d3SJohn Marino if (!current_parsed_root->isremote)
9786d7f5d3SJohn Marino {
9886d7f5d3SJohn Marino char *file;
9986d7f5d3SJohn Marino
10086d7f5d3SJohn Marino /* Then add entries found in repository, if it exists. */
10186d7f5d3SJohn Marino file = Xasprintf ("%s/%s/%s", current_parsed_root->directory,
10286d7f5d3SJohn Marino CVSROOTADM, CVSROOTADM_WRAPPER);
10386d7f5d3SJohn Marino if (isfile (file))
10486d7f5d3SJohn Marino {
10586d7f5d3SJohn Marino wrap_add_file(file,0);
10686d7f5d3SJohn Marino }
10786d7f5d3SJohn Marino free (file);
10886d7f5d3SJohn Marino }
10986d7f5d3SJohn Marino
11086d7f5d3SJohn Marino /* Then add entries found in home dir, (if user has one) and file
11186d7f5d3SJohn Marino exists. */
11286d7f5d3SJohn Marino homedir = get_homedir ();
11386d7f5d3SJohn Marino /* If we can't find a home directory, ignore ~/.cvswrappers. This may
11486d7f5d3SJohn Marino make tracking down problems a bit of a pain, but on the other
11586d7f5d3SJohn Marino hand it might be obnoxious to complain when CVS will function
11686d7f5d3SJohn Marino just fine without .cvswrappers (and many users won't even know what
11786d7f5d3SJohn Marino .cvswrappers is). */
11886d7f5d3SJohn Marino if (homedir != NULL)
11986d7f5d3SJohn Marino {
12086d7f5d3SJohn Marino char *file = strcat_filename_onto_homedir (homedir, CVSDOTWRAPPER);
12186d7f5d3SJohn Marino if (isfile (file))
12286d7f5d3SJohn Marino {
12386d7f5d3SJohn Marino wrap_add_file (file, 0);
12486d7f5d3SJohn Marino }
12586d7f5d3SJohn Marino free (file);
12686d7f5d3SJohn Marino }
12786d7f5d3SJohn Marino
12886d7f5d3SJohn Marino /* FIXME: calling wrap_add() below implies that the CVSWRAPPERS
12986d7f5d3SJohn Marino * environment variable contains exactly one "wrapper" -- a line
13086d7f5d3SJohn Marino * of the form
13186d7f5d3SJohn Marino *
13286d7f5d3SJohn Marino * FILENAME_PATTERN FLAG OPTS [ FLAG OPTS ...]
13386d7f5d3SJohn Marino *
13486d7f5d3SJohn Marino * This may disagree with the documentation, which states:
13586d7f5d3SJohn Marino *
13686d7f5d3SJohn Marino * `$CVSWRAPPERS'
13786d7f5d3SJohn Marino * A whitespace-separated list of file name patterns that CVS
13886d7f5d3SJohn Marino * should treat as wrappers. *Note Wrappers::.
13986d7f5d3SJohn Marino *
14086d7f5d3SJohn Marino * Does this mean the environment variable can hold multiple
14186d7f5d3SJohn Marino * wrappers lines? If so, a single call to wrap_add() is
14286d7f5d3SJohn Marino * insufficient.
14386d7f5d3SJohn Marino */
14486d7f5d3SJohn Marino
14586d7f5d3SJohn Marino /* Then add entries found in CVSWRAPPERS environment variable. */
14686d7f5d3SJohn Marino wrap_add (getenv (WRAPPER_ENV), 0);
14786d7f5d3SJohn Marino }
14886d7f5d3SJohn Marino
14986d7f5d3SJohn Marino #ifdef CLIENT_SUPPORT
15086d7f5d3SJohn Marino /* Send -W arguments for the wrappers to the server. The command must
15186d7f5d3SJohn Marino be one that accepts them (e.g. update, import). */
15286d7f5d3SJohn Marino void
wrap_send(void)15386d7f5d3SJohn Marino wrap_send (void)
15486d7f5d3SJohn Marino {
15586d7f5d3SJohn Marino int i;
15686d7f5d3SJohn Marino
15786d7f5d3SJohn Marino for (i = 0; i < wrap_count + wrap_tempcount; ++i)
15886d7f5d3SJohn Marino {
15986d7f5d3SJohn Marino if (wrap_list[i]->tocvsFilter != NULL
16086d7f5d3SJohn Marino || wrap_list[i]->fromcvsFilter != NULL)
16186d7f5d3SJohn Marino /* For greater studliness we would print the offending option
16286d7f5d3SJohn Marino and (more importantly) where we found it. */
16386d7f5d3SJohn Marino error (0, 0, "\
16486d7f5d3SJohn Marino -t and -f wrapper options are not supported remotely; ignored");
16586d7f5d3SJohn Marino if (wrap_list[i]->mergeMethod == WRAP_COPY)
16686d7f5d3SJohn Marino /* For greater studliness we would print the offending option
16786d7f5d3SJohn Marino and (more importantly) where we found it. */
16886d7f5d3SJohn Marino error (0, 0, "\
16986d7f5d3SJohn Marino -m wrapper option is not supported remotely; ignored");
17086d7f5d3SJohn Marino send_to_server ("Argument -W\012Argument ", 0);
17186d7f5d3SJohn Marino send_to_server (wrap_list[i]->wildCard, 0);
17286d7f5d3SJohn Marino send_to_server (" -k '", 0);
17386d7f5d3SJohn Marino if (wrap_list[i]->rcsOption != NULL)
17486d7f5d3SJohn Marino send_to_server (wrap_list[i]->rcsOption, 0);
17586d7f5d3SJohn Marino else
17686d7f5d3SJohn Marino send_to_server ("kv", 0);
17786d7f5d3SJohn Marino send_to_server ("'\012", 0);
17886d7f5d3SJohn Marino }
17986d7f5d3SJohn Marino }
18086d7f5d3SJohn Marino #endif /* CLIENT_SUPPORT */
18186d7f5d3SJohn Marino
18286d7f5d3SJohn Marino #if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
18386d7f5d3SJohn Marino /* Output wrapper entries in the format of cvswrappers lines.
18486d7f5d3SJohn Marino *
18586d7f5d3SJohn Marino * This is useful when one side of a client/server connection wants to
18686d7f5d3SJohn Marino * send its wrappers to the other; since the receiving side would like
18786d7f5d3SJohn Marino * to use wrap_add() to incorporate the wrapper, it's best if the
18886d7f5d3SJohn Marino * entry arrives in this format.
18986d7f5d3SJohn Marino *
19086d7f5d3SJohn Marino * The entries are stored in `line', which is allocated here. Caller
19186d7f5d3SJohn Marino * can free() it.
19286d7f5d3SJohn Marino *
19386d7f5d3SJohn Marino * If first_call_p is nonzero, then start afresh. */
19486d7f5d3SJohn Marino void
wrap_unparse_rcs_options(char ** line,int first_call_p)19586d7f5d3SJohn Marino wrap_unparse_rcs_options (char **line, int first_call_p)
19686d7f5d3SJohn Marino {
19786d7f5d3SJohn Marino /* FIXME-reentrancy: we should design a reentrant interface, like
19886d7f5d3SJohn Marino a callback which gets handed each wrapper (a multithreaded
19986d7f5d3SJohn Marino server being the most concrete reason for this, but the
20086d7f5d3SJohn Marino non-reentrant interface is fairly unnecessary/ugly). */
20186d7f5d3SJohn Marino static int i;
20286d7f5d3SJohn Marino
20386d7f5d3SJohn Marino if (first_call_p)
20486d7f5d3SJohn Marino i = 0;
20586d7f5d3SJohn Marino
20686d7f5d3SJohn Marino if (i >= wrap_count + wrap_tempcount) {
20786d7f5d3SJohn Marino *line = NULL;
20886d7f5d3SJohn Marino return;
20986d7f5d3SJohn Marino }
21086d7f5d3SJohn Marino
21186d7f5d3SJohn Marino *line = Xasprintf ("%s -k '%s'",
21286d7f5d3SJohn Marino wrap_list[i]->wildCard,
21386d7f5d3SJohn Marino wrap_list[i]->rcsOption
21486d7f5d3SJohn Marino ? wrap_list[i]->rcsOption : "kv");
21586d7f5d3SJohn Marino ++i;
21686d7f5d3SJohn Marino }
21786d7f5d3SJohn Marino #endif /* SERVER_SUPPORT || CLIENT_SUPPORT */
21886d7f5d3SJohn Marino
21986d7f5d3SJohn Marino /*
22086d7f5d3SJohn Marino * Remove fmt str specifier other than %% or %s. And allow
22186d7f5d3SJohn Marino * only max_s %s specifiers
22286d7f5d3SJohn Marino */
22386d7f5d3SJohn Marino static void
wrap_clean_fmt_str(char * fmt,int max_s)22486d7f5d3SJohn Marino wrap_clean_fmt_str(char *fmt, int max_s)
22586d7f5d3SJohn Marino {
22686d7f5d3SJohn Marino while (*fmt) {
22786d7f5d3SJohn Marino if (fmt[0] == '%' && fmt[1])
22886d7f5d3SJohn Marino {
22986d7f5d3SJohn Marino if (fmt[1] == '%')
23086d7f5d3SJohn Marino fmt++;
23186d7f5d3SJohn Marino else
23286d7f5d3SJohn Marino if (fmt[1] == 's' && max_s > 0)
23386d7f5d3SJohn Marino {
23486d7f5d3SJohn Marino max_s--;
23586d7f5d3SJohn Marino fmt++;
23686d7f5d3SJohn Marino } else
23786d7f5d3SJohn Marino *fmt = ' ';
23886d7f5d3SJohn Marino }
23986d7f5d3SJohn Marino fmt++;
24086d7f5d3SJohn Marino }
24186d7f5d3SJohn Marino }
24286d7f5d3SJohn Marino
24386d7f5d3SJohn Marino /*
24486d7f5d3SJohn Marino * Open a file and read lines, feeding each line to a line parser. Arrange
24586d7f5d3SJohn Marino * for keeping a temporary list of wrappers at the end, if the "temp"
24686d7f5d3SJohn Marino * argument is set.
24786d7f5d3SJohn Marino */
24886d7f5d3SJohn Marino void
wrap_add_file(const char * file,int temp)24986d7f5d3SJohn Marino wrap_add_file (const char *file, int temp)
25086d7f5d3SJohn Marino {
25186d7f5d3SJohn Marino FILE *fp;
25286d7f5d3SJohn Marino char *line = NULL;
25386d7f5d3SJohn Marino size_t line_allocated = 0;
25486d7f5d3SJohn Marino
25586d7f5d3SJohn Marino wrap_restore_saved ();
25686d7f5d3SJohn Marino wrap_kill_temp ();
25786d7f5d3SJohn Marino
25886d7f5d3SJohn Marino /* Load the file. */
25986d7f5d3SJohn Marino fp = CVS_FOPEN (file, "r");
26086d7f5d3SJohn Marino if (fp == NULL)
26186d7f5d3SJohn Marino {
26286d7f5d3SJohn Marino if (!existence_error (errno))
26386d7f5d3SJohn Marino error (0, errno, "cannot open %s", file);
26486d7f5d3SJohn Marino return;
26586d7f5d3SJohn Marino }
26686d7f5d3SJohn Marino while (getline (&line, &line_allocated, fp) >= 0)
26786d7f5d3SJohn Marino wrap_add (line, temp);
26886d7f5d3SJohn Marino if (line)
26986d7f5d3SJohn Marino free (line);
27086d7f5d3SJohn Marino if (ferror (fp))
27186d7f5d3SJohn Marino error (0, errno, "cannot read %s", file);
27286d7f5d3SJohn Marino if (fclose (fp) == EOF)
27386d7f5d3SJohn Marino error (0, errno, "cannot close %s", file);
27486d7f5d3SJohn Marino }
27586d7f5d3SJohn Marino
27686d7f5d3SJohn Marino void
wrap_kill(void)27786d7f5d3SJohn Marino wrap_kill(void)
27886d7f5d3SJohn Marino {
27986d7f5d3SJohn Marino wrap_kill_temp();
28086d7f5d3SJohn Marino while(wrap_count)
28186d7f5d3SJohn Marino wrap_free_entry(wrap_list[--wrap_count]);
28286d7f5d3SJohn Marino }
28386d7f5d3SJohn Marino
28486d7f5d3SJohn Marino void
wrap_kill_temp(void)28586d7f5d3SJohn Marino wrap_kill_temp(void)
28686d7f5d3SJohn Marino {
28786d7f5d3SJohn Marino WrapperEntry **temps=wrap_list+wrap_count;
28886d7f5d3SJohn Marino
28986d7f5d3SJohn Marino while(wrap_tempcount)
29086d7f5d3SJohn Marino wrap_free_entry(temps[--wrap_tempcount]);
29186d7f5d3SJohn Marino }
29286d7f5d3SJohn Marino
29386d7f5d3SJohn Marino void
wrap_free_entry(WrapperEntry * e)29486d7f5d3SJohn Marino wrap_free_entry(WrapperEntry *e)
29586d7f5d3SJohn Marino {
29686d7f5d3SJohn Marino wrap_free_entry_internal(e);
29786d7f5d3SJohn Marino free(e);
29886d7f5d3SJohn Marino }
29986d7f5d3SJohn Marino
30086d7f5d3SJohn Marino void
wrap_free_entry_internal(WrapperEntry * e)30186d7f5d3SJohn Marino wrap_free_entry_internal(WrapperEntry *e)
30286d7f5d3SJohn Marino {
30386d7f5d3SJohn Marino free (e->wildCard);
30486d7f5d3SJohn Marino if (e->tocvsFilter)
30586d7f5d3SJohn Marino free (e->tocvsFilter);
30686d7f5d3SJohn Marino if (e->fromcvsFilter)
30786d7f5d3SJohn Marino free (e->fromcvsFilter);
30886d7f5d3SJohn Marino if (e->rcsOption)
30986d7f5d3SJohn Marino free (e->rcsOption);
31086d7f5d3SJohn Marino }
31186d7f5d3SJohn Marino
31286d7f5d3SJohn Marino void
wrap_restore_saved(void)31386d7f5d3SJohn Marino wrap_restore_saved(void)
31486d7f5d3SJohn Marino {
31586d7f5d3SJohn Marino if(!wrap_saved_list)
31686d7f5d3SJohn Marino return;
31786d7f5d3SJohn Marino
31886d7f5d3SJohn Marino wrap_kill();
31986d7f5d3SJohn Marino
32086d7f5d3SJohn Marino free(wrap_list);
32186d7f5d3SJohn Marino
32286d7f5d3SJohn Marino wrap_list=wrap_saved_list;
32386d7f5d3SJohn Marino wrap_count=wrap_saved_count;
32486d7f5d3SJohn Marino wrap_tempcount=wrap_saved_tempcount;
32586d7f5d3SJohn Marino
32686d7f5d3SJohn Marino wrap_saved_list=NULL;
32786d7f5d3SJohn Marino wrap_saved_count=0;
32886d7f5d3SJohn Marino wrap_saved_tempcount=0;
32986d7f5d3SJohn Marino }
33086d7f5d3SJohn Marino
33186d7f5d3SJohn Marino void
wrap_add(char * line,int isTemp)33286d7f5d3SJohn Marino wrap_add (char *line, int isTemp)
33386d7f5d3SJohn Marino {
33486d7f5d3SJohn Marino char *temp;
33586d7f5d3SJohn Marino char ctemp;
33686d7f5d3SJohn Marino WrapperEntry e;
33786d7f5d3SJohn Marino char opt;
33886d7f5d3SJohn Marino
33986d7f5d3SJohn Marino if (!line || line[0] == '#')
34086d7f5d3SJohn Marino return;
34186d7f5d3SJohn Marino
34286d7f5d3SJohn Marino memset (&e, 0, sizeof(e));
34386d7f5d3SJohn Marino
34486d7f5d3SJohn Marino /* Search for the wild card */
34586d7f5d3SJohn Marino while (*line && isspace ((unsigned char) *line))
34686d7f5d3SJohn Marino ++line;
34786d7f5d3SJohn Marino for (temp = line;
34886d7f5d3SJohn Marino *line && !isspace ((unsigned char) *line);
34986d7f5d3SJohn Marino ++line)
35086d7f5d3SJohn Marino ;
35186d7f5d3SJohn Marino if(temp==line)
35286d7f5d3SJohn Marino return;
35386d7f5d3SJohn Marino
35486d7f5d3SJohn Marino ctemp=*line;
35586d7f5d3SJohn Marino *line='\0';
35686d7f5d3SJohn Marino
35786d7f5d3SJohn Marino e.wildCard=xstrdup(temp);
35886d7f5d3SJohn Marino *line=ctemp;
35986d7f5d3SJohn Marino
36086d7f5d3SJohn Marino while(*line){
36186d7f5d3SJohn Marino /* Search for the option */
36286d7f5d3SJohn Marino while(*line && *line!='-')
36386d7f5d3SJohn Marino ++line;
36486d7f5d3SJohn Marino if(!*line)
36586d7f5d3SJohn Marino break;
36686d7f5d3SJohn Marino ++line;
36786d7f5d3SJohn Marino if(!*line)
36886d7f5d3SJohn Marino break;
36986d7f5d3SJohn Marino opt=*line;
37086d7f5d3SJohn Marino
37186d7f5d3SJohn Marino /* Search for the filter commandline */
37286d7f5d3SJohn Marino for(++line;*line && *line!='\'';++line);
37386d7f5d3SJohn Marino if(!*line)
37486d7f5d3SJohn Marino break;
37586d7f5d3SJohn Marino
37686d7f5d3SJohn Marino for(temp=++line;*line && (*line!='\'' || line[-1]=='\\');++line)
37786d7f5d3SJohn Marino ;
37886d7f5d3SJohn Marino
37986d7f5d3SJohn Marino /* This used to "break;" (ignore the option) if there was a
38086d7f5d3SJohn Marino single character between the single quotes (I'm guessing
38186d7f5d3SJohn Marino that was accidental). Now it "break;"s if there are no
38286d7f5d3SJohn Marino characters. I'm not sure either behavior is particularly
38386d7f5d3SJohn Marino necessary--the current options might not require ''
38486d7f5d3SJohn Marino arguments, but surely some future option legitimately
38586d7f5d3SJohn Marino might. Also I'm not sure that ignoring the option is a
38686d7f5d3SJohn Marino swift way to handle syntax errors in general. */
38786d7f5d3SJohn Marino if (line==temp)
38886d7f5d3SJohn Marino break;
38986d7f5d3SJohn Marino
39086d7f5d3SJohn Marino ctemp=*line;
39186d7f5d3SJohn Marino *line='\0';
39286d7f5d3SJohn Marino switch(opt){
39386d7f5d3SJohn Marino case 'f':
39486d7f5d3SJohn Marino /* Before this is reenabled, need to address the problem in
39586d7f5d3SJohn Marino commit.c (see
39686d7f5d3SJohn Marino <http://ximbiot.com/cvs/cvshome/docs/infowrapper.html>). */
39786d7f5d3SJohn Marino error (1, 0,
39886d7f5d3SJohn Marino "-t/-f wrappers not supported by this version of CVS");
39986d7f5d3SJohn Marino
40086d7f5d3SJohn Marino if(e.fromcvsFilter)
40186d7f5d3SJohn Marino free(e.fromcvsFilter);
40286d7f5d3SJohn Marino /* FIXME: error message should say where the bad value
40386d7f5d3SJohn Marino came from. */
40486d7f5d3SJohn Marino e.fromcvsFilter =
40586d7f5d3SJohn Marino expand_path (temp, current_parsed_root->directory, false,
40686d7f5d3SJohn Marino "<wrapper>", 0);
40786d7f5d3SJohn Marino if (!e.fromcvsFilter)
40886d7f5d3SJohn Marino error (1, 0, "Correct above errors first");
40986d7f5d3SJohn Marino break;
41086d7f5d3SJohn Marino case 't':
41186d7f5d3SJohn Marino /* Before this is reenabled, need to address the problem in
41286d7f5d3SJohn Marino commit.c (see
41386d7f5d3SJohn Marino <http://ximbiot.com/cvs/cvshome/docs/infowrapper.html>). */
41486d7f5d3SJohn Marino error (1, 0,
41586d7f5d3SJohn Marino "-t/-f wrappers not supported by this version of CVS");
41686d7f5d3SJohn Marino
41786d7f5d3SJohn Marino if(e.tocvsFilter)
41886d7f5d3SJohn Marino free(e.tocvsFilter);
41986d7f5d3SJohn Marino /* FIXME: error message should say where the bad value
42086d7f5d3SJohn Marino came from. */
42186d7f5d3SJohn Marino e.tocvsFilter = expand_path (temp, current_parsed_root->directory,
42286d7f5d3SJohn Marino false, "<wrapper>", 0);
42386d7f5d3SJohn Marino if (!e.tocvsFilter)
42486d7f5d3SJohn Marino error (1, 0, "Correct above errors first");
42586d7f5d3SJohn Marino break;
42686d7f5d3SJohn Marino case 'm':
42786d7f5d3SJohn Marino if(*temp=='C' || *temp=='c')
42886d7f5d3SJohn Marino e.mergeMethod=WRAP_COPY;
42986d7f5d3SJohn Marino else
43086d7f5d3SJohn Marino e.mergeMethod=WRAP_MERGE;
43186d7f5d3SJohn Marino break;
43286d7f5d3SJohn Marino case 'k':
43386d7f5d3SJohn Marino if (e.rcsOption)
43486d7f5d3SJohn Marino free (e.rcsOption);
43586d7f5d3SJohn Marino e.rcsOption = strcmp (temp, "kv") ? xstrdup (temp) : NULL;
43686d7f5d3SJohn Marino break;
43786d7f5d3SJohn Marino default:
43886d7f5d3SJohn Marino break;
43986d7f5d3SJohn Marino }
44086d7f5d3SJohn Marino *line=ctemp;
44186d7f5d3SJohn Marino if(!*line)break;
44286d7f5d3SJohn Marino ++line;
44386d7f5d3SJohn Marino }
44486d7f5d3SJohn Marino
44586d7f5d3SJohn Marino wrap_add_entry(&e, isTemp);
44686d7f5d3SJohn Marino }
44786d7f5d3SJohn Marino
44886d7f5d3SJohn Marino void
wrap_add_entry(WrapperEntry * e,int temp)44986d7f5d3SJohn Marino wrap_add_entry (WrapperEntry *e, int temp)
45086d7f5d3SJohn Marino {
45186d7f5d3SJohn Marino int x;
45286d7f5d3SJohn Marino if (wrap_count + wrap_tempcount >= wrap_size)
45386d7f5d3SJohn Marino {
45486d7f5d3SJohn Marino wrap_size += WRAPPER_GROW;
45586d7f5d3SJohn Marino wrap_list = xnrealloc (wrap_list, wrap_size, sizeof (WrapperEntry *));
45686d7f5d3SJohn Marino }
45786d7f5d3SJohn Marino
45886d7f5d3SJohn Marino if (!temp && wrap_tempcount)
45986d7f5d3SJohn Marino {
46086d7f5d3SJohn Marino for (x = wrap_count + wrap_tempcount - 1; x >= wrap_count; --x)
46186d7f5d3SJohn Marino wrap_list[x + 1] = wrap_list[x];
46286d7f5d3SJohn Marino }
46386d7f5d3SJohn Marino
46486d7f5d3SJohn Marino x = (temp ? wrap_count + (wrap_tempcount++) : (wrap_count++));
46586d7f5d3SJohn Marino wrap_list[x] = xmalloc (sizeof (WrapperEntry));
46686d7f5d3SJohn Marino *wrap_list[x] = *e;
46786d7f5d3SJohn Marino }
46886d7f5d3SJohn Marino
46986d7f5d3SJohn Marino /* Return 1 if the given filename is a wrapper filename */
47086d7f5d3SJohn Marino int
wrap_name_has(const char * name,WrapMergeHas has)47186d7f5d3SJohn Marino wrap_name_has (const char *name, WrapMergeHas has)
47286d7f5d3SJohn Marino {
47386d7f5d3SJohn Marino int x,count=wrap_count+wrap_tempcount;
47486d7f5d3SJohn Marino char *temp;
47586d7f5d3SJohn Marino
47686d7f5d3SJohn Marino for(x=0;x<count;++x)
47786d7f5d3SJohn Marino if (CVS_FNMATCH (wrap_list[x]->wildCard, name, 0) == 0){
47886d7f5d3SJohn Marino switch(has){
47986d7f5d3SJohn Marino case WRAP_TOCVS:
48086d7f5d3SJohn Marino temp=wrap_list[x]->tocvsFilter;
48186d7f5d3SJohn Marino break;
48286d7f5d3SJohn Marino case WRAP_FROMCVS:
48386d7f5d3SJohn Marino temp=wrap_list[x]->fromcvsFilter;
48486d7f5d3SJohn Marino break;
48586d7f5d3SJohn Marino case WRAP_RCSOPTION:
48686d7f5d3SJohn Marino temp = wrap_list[x]->rcsOption;
48786d7f5d3SJohn Marino break;
48886d7f5d3SJohn Marino default:
48986d7f5d3SJohn Marino abort ();
49086d7f5d3SJohn Marino }
49186d7f5d3SJohn Marino if(temp==NULL)
49286d7f5d3SJohn Marino return (0);
49386d7f5d3SJohn Marino else
49486d7f5d3SJohn Marino return (1);
49586d7f5d3SJohn Marino }
49686d7f5d3SJohn Marino return (0);
49786d7f5d3SJohn Marino }
49886d7f5d3SJohn Marino
49986d7f5d3SJohn Marino static WrapperEntry *wrap_matching_entry (const char *);
50086d7f5d3SJohn Marino
50186d7f5d3SJohn Marino static WrapperEntry *
wrap_matching_entry(const char * name)50286d7f5d3SJohn Marino wrap_matching_entry (const char *name)
50386d7f5d3SJohn Marino {
50486d7f5d3SJohn Marino int x,count=wrap_count+wrap_tempcount;
50586d7f5d3SJohn Marino
50686d7f5d3SJohn Marino for(x=0;x<count;++x)
50786d7f5d3SJohn Marino if (CVS_FNMATCH (wrap_list[x]->wildCard, name, 0) == 0)
50886d7f5d3SJohn Marino return wrap_list[x];
50986d7f5d3SJohn Marino return NULL;
51086d7f5d3SJohn Marino }
51186d7f5d3SJohn Marino
51286d7f5d3SJohn Marino /* Return the RCS options for FILENAME in a newly malloc'd string. If
51386d7f5d3SJohn Marino ASFLAG, then include "-k" at the beginning (e.g. "-kb"), otherwise
51486d7f5d3SJohn Marino just give the option itself (e.g. "b"). */
51586d7f5d3SJohn Marino char *
wrap_rcsoption(const char * filename,int asflag)51686d7f5d3SJohn Marino wrap_rcsoption (const char *filename, int asflag)
51786d7f5d3SJohn Marino {
51886d7f5d3SJohn Marino WrapperEntry *e = wrap_matching_entry (filename);
51986d7f5d3SJohn Marino
52086d7f5d3SJohn Marino if (e == NULL || e->rcsOption == NULL || (*e->rcsOption == '\0'))
52186d7f5d3SJohn Marino return NULL;
52286d7f5d3SJohn Marino
52386d7f5d3SJohn Marino return Xasprintf ("%s%s", asflag ? "-k" : "", e->rcsOption);
52486d7f5d3SJohn Marino }
52586d7f5d3SJohn Marino
52686d7f5d3SJohn Marino char *
wrap_tocvs_process_file(const char * fileName)52786d7f5d3SJohn Marino wrap_tocvs_process_file(const char *fileName)
52886d7f5d3SJohn Marino {
52986d7f5d3SJohn Marino WrapperEntry *e=wrap_matching_entry(fileName);
53086d7f5d3SJohn Marino static char *buf = NULL;
53186d7f5d3SJohn Marino char *args;
53286d7f5d3SJohn Marino
53386d7f5d3SJohn Marino if(e==NULL || e->tocvsFilter==NULL)
53486d7f5d3SJohn Marino return NULL;
53586d7f5d3SJohn Marino
53686d7f5d3SJohn Marino if (buf != NULL)
53786d7f5d3SJohn Marino free (buf);
53886d7f5d3SJohn Marino buf = cvs_temp_name ();
53986d7f5d3SJohn Marino
54086d7f5d3SJohn Marino wrap_clean_fmt_str (e->tocvsFilter, 2);
54186d7f5d3SJohn Marino args = Xasprintf (e->tocvsFilter, fileName, buf);
54286d7f5d3SJohn Marino run_setup (args);
54386d7f5d3SJohn Marino run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL | RUN_REALLY );
54486d7f5d3SJohn Marino free (args);
54586d7f5d3SJohn Marino
54686d7f5d3SJohn Marino return buf;
54786d7f5d3SJohn Marino }
54886d7f5d3SJohn Marino
54986d7f5d3SJohn Marino int
wrap_merge_is_copy(const char * fileName)55086d7f5d3SJohn Marino wrap_merge_is_copy (const char *fileName)
55186d7f5d3SJohn Marino {
55286d7f5d3SJohn Marino WrapperEntry *e=wrap_matching_entry(fileName);
55386d7f5d3SJohn Marino if(e==NULL || e->mergeMethod==WRAP_MERGE)
55486d7f5d3SJohn Marino return 0;
55586d7f5d3SJohn Marino
55686d7f5d3SJohn Marino return 1;
55786d7f5d3SJohn Marino }
55886d7f5d3SJohn Marino
55986d7f5d3SJohn Marino void
wrap_fromcvs_process_file(const char * fileName)56086d7f5d3SJohn Marino wrap_fromcvs_process_file(const char *fileName)
56186d7f5d3SJohn Marino {
56286d7f5d3SJohn Marino char *args;
56386d7f5d3SJohn Marino WrapperEntry *e = wrap_matching_entry(fileName);
56486d7f5d3SJohn Marino
56586d7f5d3SJohn Marino if (e != NULL && e->fromcvsFilter != NULL)
56686d7f5d3SJohn Marino {
56786d7f5d3SJohn Marino wrap_clean_fmt_str (e->fromcvsFilter, 1);
56886d7f5d3SJohn Marino args = Xasprintf (e->fromcvsFilter, fileName);
56986d7f5d3SJohn Marino run_setup (args);
57086d7f5d3SJohn Marino run_exec (RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL);
57186d7f5d3SJohn Marino free (args);
57286d7f5d3SJohn Marino }
57386d7f5d3SJohn Marino return;
57486d7f5d3SJohn Marino }
575