#include "cvs.h"
#include "getline.h"
typedef struct {
char *wildCard;
char *tocvsFilter;
char *fromcvsFilter;
char *rcsOption;
WrapMergeMethod mergeMethod;
} WrapperEntry;
static WrapperEntry **wrap_list=NULL;
static WrapperEntry **wrap_saved_list=NULL;
static int wrap_size=0;
static int wrap_count=0;
static int wrap_tempcount=0;
static int wrap_saved_count=0;
static int wrap_saved_tempcount=0;
#define WRAPPER_GROW 8
void wrap_add_entry PROTO((WrapperEntry *e,int temp));
void wrap_kill PROTO((void));
void wrap_kill_temp PROTO((void));
void wrap_free_entry PROTO((WrapperEntry *e));
void wrap_free_entry_internal PROTO((WrapperEntry *e));
void wrap_restore_saved PROTO((void));
void wrap_setup()
{
static int wrap_setup_already_done = 0;
char *homedir;
#ifdef WRAPPERS_USE_TAR_FOR_TRANSFER
char *wfile;
#endif
if (wrap_setup_already_done != 0)
return;
else
wrap_setup_already_done = 1;
#ifdef CLIENT_SUPPORT
if (!client_active)
#endif
{
char *file;
file = xmalloc (strlen (CVSroot_directory)
+ sizeof (CVSROOTADM)
+ sizeof (CVSROOTADM_WRAPPER)
+ 10);
(void) sprintf (file, "%s/%s/%s", CVSroot_directory, CVSROOTADM,
CVSROOTADM_WRAPPER);
if (isfile (file))
{
wrap_add_file(file,0);
}
free (file);
}
homedir = get_homedir ();
if (homedir != NULL)
{
char *file;
file = xmalloc (strlen (homedir) + sizeof (CVSDOTWRAPPER) + 10);
(void) sprintf (file, "%s/%s", homedir, CVSDOTWRAPPER);
if (isfile (file))
{
wrap_add_file (file, 0);
}
free (file);
}
#ifdef WRAPPERS_USE_TAR_FOR_TRANSFER
if (wfile = getenv("CVS_CLIENT_WRAPPER_FILE")) {
wrap_add_file(wfile, 0);
}
#endif
wrap_add (getenv (WRAPPER_ENV), 0);
}
#ifdef CLIENT_SUPPORT
void
wrap_send ()
{
int i;
for (i = 0; i < wrap_count + wrap_tempcount; ++i)
{
send_to_server ("Argument -W\012Argument ", 0);
send_to_server (wrap_list[i]->wildCard, 0);
if (wrap_list[i]->tocvsFilter != NULL)
{
send_to_server (" -t '", 0);
send_to_server (wrap_list[i]->tocvsFilter, 0);
send_to_server ("' ", 0);
}
if (wrap_list[i]->fromcvsFilter != NULL)
{
send_to_server (" -f '", 0);
send_to_server (wrap_list[i]->fromcvsFilter, 0);
send_to_server ("' ", 0);
}
if (wrap_list[i]->mergeMethod == WRAP_COPY)
{
send_to_server (" -m 'COPY' ", 0);
}
if (wrap_list[i]->rcsOption != NULL)
{
send_to_server (" -k '", 0);
send_to_server (wrap_list[i]->rcsOption, 0);
send_to_server ("' ", 0);
}
send_to_server ("\012", 0);
}
}
#endif
#if defined(SERVER_SUPPORT) || defined(CLIENT_SUPPORT)
void
wrap_unparse_rcs_options (line, first_call_p)
char **line;
int first_call_p;
{
static int i;
if (first_call_p)
i = 0;
for (; i < wrap_count + wrap_tempcount; ++i)
{
if (wrap_list[i]->rcsOption != NULL)
{
*line = xmalloc (strlen (wrap_list[i]->wildCard)
+ strlen ("\t")
+ strlen (" -k '")
+ strlen (wrap_list[i]->rcsOption)
+ strlen ("'")
+ 1);
strcpy (*line, wrap_list[i]->wildCard);
strcat (*line, " -k '");
strcat (*line, wrap_list[i]->rcsOption);
strcat (*line, "'");
++i;
return;
}
}
*line = NULL;
return;
}
#endif
void
wrap_add_file (file, temp)
const char *file;
int temp;
{
FILE *fp;
char *line = NULL;
size_t line_allocated = 0;
wrap_restore_saved ();
wrap_kill_temp ();
fp = CVS_FOPEN (file, "r");
if (fp == NULL)
{
if (!existence_error (errno))
error (0, errno, "cannot open %s", file);
return;
}
while (getline (&line, &line_allocated, fp) >= 0)
wrap_add (line, temp);
if (line)
free (line);
if (ferror (fp))
error (0, errno, "cannot read %s", file);
if (fclose (fp) == EOF)
error (0, errno, "cannot close %s", file);
}
void
wrap_kill()
{
wrap_kill_temp();
while(wrap_count)
wrap_free_entry(wrap_list[--wrap_count]);
}
void
wrap_kill_temp()
{
WrapperEntry **temps=wrap_list+wrap_count;
while(wrap_tempcount)
wrap_free_entry(temps[--wrap_tempcount]);
}
void
wrap_free_entry(e)
WrapperEntry *e;
{
wrap_free_entry_internal(e);
free(e);
}
void
wrap_free_entry_internal(e)
WrapperEntry *e;
{
free (e->wildCard);
if (e->tocvsFilter)
free (e->tocvsFilter);
if (e->fromcvsFilter)
free (e->fromcvsFilter);
if (e->rcsOption)
free (e->rcsOption);
}
void
wrap_restore_saved()
{
if(!wrap_saved_list)
return;
wrap_kill();
free(wrap_list);
wrap_list=wrap_saved_list;
wrap_count=wrap_saved_count;
wrap_tempcount=wrap_saved_tempcount;
wrap_saved_list=NULL;
wrap_saved_count=0;
wrap_saved_tempcount=0;
}
void
wrap_add (line, isTemp)
char *line;
int isTemp;
{
char *temp;
char ctemp;
WrapperEntry e;
char opt;
if (!line || line[0] == '#')
return;
memset (&e, 0, sizeof(e));
while(*line && isspace(*line))
++line;
for(temp=line;*line && !isspace(*line);++line)
;
if(temp==line)
return;
ctemp=*line;
*line='\0';
e.wildCard=xstrdup(temp);
*line=ctemp;
while(*line){
while(*line && *line!='-')
++line;
if(!*line)
break;
++line;
if(!*line)
break;
opt=*line;
for(++line;*line && *line!='\'';++line);
if(!*line)
break;
for(temp=++line;*line && (*line!='\'' || line[-1]=='\\');++line)
;
if (line==temp)
break;
ctemp=*line;
*line='\0';
switch(opt){
case 'f':
if(e.fromcvsFilter)
free(e.fromcvsFilter);
e.fromcvsFilter=expand_path (temp, "<wrapper>", 0);
if (!e.fromcvsFilter)
error (1, 0, "Correct above errors first");
break;
case 't':
if(e.tocvsFilter)
free(e.tocvsFilter);
e.tocvsFilter=expand_path (temp, "<wrapper>", 0);
if (!e.tocvsFilter)
error (1, 0, "Correct above errors first");
break;
case 'm':
if(*temp=='C' || *temp=='c')
e.mergeMethod=WRAP_COPY;
else
e.mergeMethod=WRAP_MERGE;
break;
case 'k':
if (e.rcsOption)
free (e.rcsOption);
e.rcsOption = xstrdup (temp);
break;
default:
break;
}
*line=ctemp;
if(!*line)break;
++line;
}
wrap_add_entry(&e, isTemp);
}
void
wrap_add_entry(e, temp)
WrapperEntry *e;
int temp;
{
int x;
if(wrap_count+wrap_tempcount>=wrap_size){
wrap_size += WRAPPER_GROW;
wrap_list = (WrapperEntry **) xrealloc ((char *) wrap_list,
wrap_size *
sizeof (WrapperEntry *));
}
if(!temp && wrap_tempcount){
for(x=wrap_count+wrap_tempcount-1;x>=wrap_count;--x)
wrap_list[x+1]=wrap_list[x];
}
x=(temp ? wrap_count+(wrap_tempcount++):(wrap_count++));
wrap_list[x]=(WrapperEntry *)xmalloc(sizeof(WrapperEntry));
wrap_list[x]->wildCard=e->wildCard;
wrap_list[x]->fromcvsFilter=e->fromcvsFilter;
wrap_list[x]->tocvsFilter=e->tocvsFilter;
wrap_list[x]->mergeMethod=e->mergeMethod;
wrap_list[x]->rcsOption = e->rcsOption;
}
int
wrap_name_has (name,has)
const char *name;
WrapMergeHas has;
{
int x,count=wrap_count+wrap_tempcount;
char *temp;
for(x=0;x<count;++x)
if (CVS_FNMATCH (wrap_list[x]->wildCard, name, 0) == 0){
switch(has){
case WRAP_TOCVS:
temp=wrap_list[x]->tocvsFilter;
break;
case WRAP_FROMCVS:
temp=wrap_list[x]->fromcvsFilter;
break;
case WRAP_RCSOPTION:
temp = wrap_list[x]->rcsOption;
break;
default:
abort ();
}
if(temp==NULL)
return (0);
else
return (1);
}
return (0);
}
static WrapperEntry *wrap_matching_entry PROTO ((const char *));
static WrapperEntry *
wrap_matching_entry (name)
const char *name;
{
int x,count=wrap_count+wrap_tempcount;
for(x=0;x<count;++x)
if (CVS_FNMATCH (wrap_list[x]->wildCard, name, 0) == 0)
return wrap_list[x];
return (WrapperEntry *)NULL;
}
char *
wrap_rcsoption (filename, asflag)
const char *filename;
int asflag;
{
WrapperEntry *e = wrap_matching_entry (filename);
char *buf;
if (e == NULL || e->rcsOption == NULL || (*e->rcsOption == '\0'))
return NULL;
buf = xmalloc (strlen (e->rcsOption) + 3);
if (asflag)
{
strcpy (buf, "-k");
strcat (buf, e->rcsOption);
}
else
{
strcpy (buf, e->rcsOption);
}
return buf;
}
char *
wrap_tocvs_process_file(fileName)
const char *fileName;
{
WrapperEntry *e=wrap_matching_entry(fileName);
static char *buf = NULL;
char *args;
if(e==NULL || e->tocvsFilter==NULL)
return NULL;
if (buf != NULL)
free (buf);
buf = cvs_temp_name ();
args = xmalloc (strlen (e->tocvsFilter)
+ strlen (fileName)
+ strlen (buf));
sprintf (args, e->tocvsFilter, fileName, buf);
run_setup (args);
run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL|RUN_REALLY );
free (args);
return buf;
}
int
wrap_merge_is_copy (fileName)
const char *fileName;
{
WrapperEntry *e=wrap_matching_entry(fileName);
if(e==NULL || e->mergeMethod==WRAP_MERGE)
return 0;
return 1;
}
void
wrap_fromcvs_process_file(fileName)
const char *fileName;
{
char *args;
WrapperEntry *e=wrap_matching_entry(fileName);
if(e==NULL || e->fromcvsFilter==NULL)
return;
args = xmalloc (strlen (e->fromcvsFilter)
+ strlen (fileName));
sprintf (args, e->fromcvsFilter, fileName);
run_setup (args);
run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL );
free (args);
return;
}