#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;
if (wrap_setup_already_done != 0)
return;
else
wrap_setup_already_done = 1;
#ifdef CLIENT_SUPPORT
if (!current_parsed_root->isremote)
#endif
{
char *file;
file = xmalloc (strlen (current_parsed_root->directory)
+ sizeof (CVSROOTADM)
+ sizeof (CVSROOTADM_WRAPPER)
+ 3);
(void) sprintf (file, "%s/%s/%s", current_parsed_root->directory, CVSROOTADM,
CVSROOTADM_WRAPPER);
if (isfile (file))
{
wrap_add_file(file,0);
}
free (file);
}
homedir = get_homedir ();
if (homedir != NULL)
{
char *file = strcat_filename_onto_homedir (homedir, CVSDOTWRAPPER);
if (isfile (file))
{
wrap_add_file (file, 0);
}
free (file);
}
wrap_add (getenv (WRAPPER_ENV), 0);
}
#ifdef CLIENT_SUPPORT
void
wrap_send ()
{
int i;
for (i = 0; i < wrap_count + wrap_tempcount; ++i)
{
if (wrap_list[i]->tocvsFilter != NULL
|| wrap_list[i]->fromcvsFilter != NULL)
error (0, 0, "\
-t and -f wrapper options are not supported remotely; ignored");
if (wrap_list[i]->mergeMethod == WRAP_COPY)
error (0, 0, "\
-m wrapper option is not supported remotely; ignored");
send_to_server ("Argument -W\012Argument ", 0);
send_to_server (wrap_list[i]->wildCard, 0);
send_to_server (" -k '", 0);
if (wrap_list[i]->rcsOption != NULL)
send_to_server (wrap_list[i]->rcsOption, 0);
else
send_to_server ("kv", 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;
if (i >= wrap_count + wrap_tempcount) {
*line = NULL;
return;
}
*line = xmalloc (strlen (wrap_list[i]->wildCard)
+ strlen ("\t")
+ strlen (" -k '")
+ (wrap_list[i]->rcsOption != NULL ?
strlen (wrap_list[i]->rcsOption) : 2)
+ strlen ("'")
+ 1);
strcpy (*line, wrap_list[i]->wildCard);
strcat (*line, " -k '");
if (wrap_list[i]->rcsOption != NULL)
strcat (*line, wrap_list[i]->rcsOption);
else
strcat (*line, "kv");
strcat (*line, "'");
++i;
}
#endif
void
wrap_clean_fmt_str(char *fmt, int max_s)
{
while (*fmt) {
if (fmt[0] == '%' && fmt[1])
{
if (fmt[1] == '%')
fmt++;
else
if (fmt[1] == 's' && max_s > 0)
{
max_s--;
fmt++;
} else
*fmt = ' ';
}
fmt++;
}
}
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 ((unsigned char) *line))
++line;
for (temp = line;
*line && !isspace ((unsigned char) *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':
error (1, 0,
"-t/-f wrappers not supported by this version of CVS\nA legacy version of cvs with -t/-f wrapper support is available as: /usr/bin/ocvs.");
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':
error (1, 0,
"-t/-f wrappers not supported by this version of CVS\nA legacy version of cvs with -t/-f wrapper support is available as: /usr/bin/ocvs.");
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 = strcmp (temp, "kv") ? xstrdup (temp) : NULL;
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]=*e;
}
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));
wrap_clean_fmt_str(e->tocvsFilter, 2);
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));
wrap_clean_fmt_str(e->fromcvsFilter, 1);
sprintf (args, e->fromcvsFilter, fileName);
run_setup (args);
run_exec(RUN_TTY, RUN_TTY, RUN_TTY, RUN_NORMAL );
free (args);
return;
}