This is rcvs_subr.c in view mode; [Download] [Up]
/*
* Copyright (c) 1992, Brian Berliner and Jeff Polk
* Copyright (c) 1989-1992, Brian Berliner
*
* You may distribute under the terms of the GNU General Public License
* as specified in the README file that comes with the CVS 1.3 kit.
*/
#include "cvs.h"
/* rcvs: */
#include "rcvs.h"
#include "patchlevel.h"
#if __STDC__
char *rcvs_get_repos (char *dir, char **Id, char **Repository);
#else
char *rcvs_get_repos ();
#endif /* __STDC__ */
/*
* insert item p at end of list "list", do not hash
*/
int
rcvs_addnode (list, p)
List *list;
Node *p;
{
int hashval;
Node *q;
/* put it into the regular list */
p->prev = list->list->prev;
p->next = list->list;
list->list->prev->next = p;
list->list->prev = p;
return (0);
}
/* rcvs: add all folders under one directory to list */
int
rcvs_add_onedir(argc, argv, p)
int argc;
char *argv[];
Node *p;
{
char *ID;
char *repos;
char *Repository;
char *dir = p->key;
repos = rcvs_get_repos (dir, &ID, &Repository);
rcvs_put_options (argc, argv, ID);
if (repos != NULL)
rcvs_addlist (&rcvs_dirlist, ID, dir, repos );
else
error (0, 0, "rcvs_add_dir: warnig: repos is NULL");
return (0);
}
/*
* rcvs: Add a node to a list, then initialize a sub-list with the data
* field. The 'key' of a node holds the original arguments of cvs while
* the data field of a node holds the relative path needed by sync.
*/
int
rcvs_addlist (listp, lkey, pkey, pdata)
List **listp;
char *lkey;
char *pkey;
char *pdata;
{
Node *p;
Node *P;
List *L;
if (trace)
{
char *cp;
char *cp2;
cp = pkey;
if (cp == NULL)
cp = xstrdup ("");
cp2 = pdata;
if (cp2 == NULL)
cp2 = xstrdup ("");
fprintf (stderr, "-> #addlist: %s %s (%s)\n", lkey, cp, cp2);
}
if (*listp == NULL)
*listp = getlist ();
if (pdata == NULL)
error(1, 0, "rcvs_addlist: bug#1 pdata == NULL");
/* rcvs: search this list first */
if (lkey == NULL)
error(1, 0, "rcvs_addlist bug #1: lkey == NULL");
P = findnode(*listp, lkey);
/* rcvs: add server node to list */
if (P == NULL)
{
P = getnode ();
P->type = DIRS;
P->key = xstrdup (lkey);
(void) addnode (*listp, P);
L = getlist ();
}
else
L = (void *) P->data;
p = getnode ();
p->type = FILES;
p->key = xstrdup (pkey);
p->data = xstrdup (pdata);
(void) rcvs_addnode (L, p);
/* store address of list into data field */
P->data = (void *) L;
return (0);
}
/* figure out old CVSROOT from new CVSROOT and old repository.
* This routine is needed when '-C' or '-c' was used to change
* repository.
*/
int
rcvs_change_cvsroot (old_repos, newroot, oldroot, relpath)
char *old_repos;
char *newroot;
char **oldroot;
char **relpath;
{
char oldROOT [PATH_MAX];
char tmp [PATH_MAX];
char *cp;
char *rel;
int found = FALSE;
(void) strcpy (oldROOT, old_repos);
rel = old_repos + strlen(old_repos);
cp = oldROOT;
while (cp)
{
cp = rindex ( oldROOT, '/');
if (cp)
rel -= strlen(cp);
else
break;
sprintf (tmp, "%s%s", newroot, rel);
if (isdir (tmp))
found = TRUE;
else if (found)
break;
*cp = '\0';
}
if (!found)
{
command_name = xstrdup ("rcvs_change_cvsroot");
error (0, 0, "problem with new %s '%s'", CVSROOT_ENV, newroot);
error (1, 0, "old repository: %s", old_repos);
}
if (trace)
fprintf (stderr, "-> oldroot=%s \n", oldROOT);
*oldroot = xstrdup(oldROOT);
*relpath = old_repos + strlen(oldROOT) +1;
return (0);
}
/* rcvs: recreate Admin file for '-C' or '-c' option. Called by
* update_dirent_proc(). Calls Create_Admin().
*/
int
rcvs_remake_adm (dir, repository)
char *dir;
char *repository;
{
char tmp[PATH_MAX];
char new_repos[PATH_MAX];
char *oldroot = NULL;
char *relpath = NULL;
if (trace)
fprintf (stderr, "-> #rcvs_remake_adm: %s %s\n", dir, repository);
if (strcmp (command_name, "update") == 0) /* update */
{
char *repos;
char *ID;
rcvs_module = rcvs_get_repos (dir, &ID, &repos);
if (ID == NULL)
error (1, 0, "rcvs_remake_adm, bug: ID==NULL");
if (index(ID, ':') == NULL)
{
if (rcvs_Copt_change_repos)
{
command_name = xstrdup ("rcvs_remake_adm");
error (1, 0, "%s is a local folder, use -c", dir);
}
}
else
{
if (rcvs_copt_change_repos)
{
command_name = xstrdup ("rcvs_remake_adm");
error (1, 0, "%s is a remote folder, use -C", dir);
}
}
repos = Name_Repository (dir,"");
(void) rcvs_change_cvsroot (repos, CVSroot, &oldroot, &relpath);
sprintf (new_repos, "%s/%s", CVSroot, relpath);
}
else /* checkout */
(void) strcpy (new_repos, repository);
if (!quiet)
{
if (dir != NULL)
(void) sprintf (tmp, "%s/%s", dir, CVSADM);
else
(void) strcpy (tmp, CVSADM);
if (isfile (tmp))
fprintf (stderr, "remake %s/%s !!\n", dir, CVSADM);
}
if (trace)
fprintf (stderr, "-> %s: dir=%s new_repos=%s \n",
command_name, dir, new_repos);
/*sprintf (tmp, "rm -r -f %s/%s", dir, CVSADM);
(void) system (tmp);*/
Create_Admin (dir, new_repos, (char *) NULL, (char *) NULL);
return (0);
}
/* rcvs: create Remote Admin file, called by Create_Admin */
int
rcvs_create_adm (dir, repos)
char *dir;
char *repos;
{
static char *rcvs_source = NULL;
static char *rel_path = NULL;
FILE *fout;
char *repository;
char tmp[PATH_MAX];
char path[PATH_MAX];
char *Command_Name;
char *command;
Command_Name = command_name;
command = xstrdup ("rcvs_create_adm");
command_name = command;
rel_path = NULL;
if (strcmp(repos,"") == 0)
repository = Name_Repository (dir,"");
else
repository = repos;
if (!isdir (repository))
error (1, 0, "there is no repository '%s'", repository);
/* recording original source */
if (rcvs_level++ == 0)
{
(void) sprintf (tmp, "%s/", CVSroot);
if (strncmp (repository, tmp, strlen (tmp)) == 0)
rcvs_source = xstrdup (repository);
else
error (1, 0, "'%s' does not prefixed with CVSROOT %s", repository, CVSroot);
if (rcvs_module != NULL)
rel_path = rcvs_module;
rcvs_module = NULL;
}
/* derive relative path */
if (rel_path == NULL)
{
(void) sprintf (tmp, "%s/", CVSroot);
if (strncmp (repository, tmp, strlen (tmp)) != 0)
error (1, 0, "bug #2, %s does not prefixed with CVSROOT %s", repository, CVSroot);
rel_path = repository + strlen (tmp);
}
/* create Remote file */
if (dir != NULL)
(void) sprintf (tmp, "%s/%s", dir, RCVSADM_REMOTE);
else
(void) strcpy (tmp, RCVSADM_REMOTE);
fout = open_file (tmp, "w+");
if (RCVSuser == NULL || RCVShost == NULL || RCVSroot == NULL)
error (1, 0, "bug#3, %s@%s:%s:%s\n ", RCVSuser,
RCVShost, RCVSroot, RCVSdir );
(void ) sprintf (path, "%s@%s:%s:%s %s", RCVSuser, RCVShost,
RCVSroot, RCVSdir, rel_path );
if (fprintf (fout, "%s\n", path) == EOF)
error (1, 0, "write to %s failed", tmp);
if (fclose (fout) == EOF)
error (1, errno, "cannot close %s", tmp);
if (trace)
{
char *curDir;
curDir = xmalloc (PATH_MAX);
(void) getwd (curDir);
CurDir = xstrdup (curDir);
free (curDir);
fprintf (stderr, "-> rcvs_create_adm: CurDir =%s\n", CurDir, tmp);
fprintf (stderr, "-> rcvs_create_adm: remote = %s\n", tmp);
fprintf (stderr, "-> rcvs_create_adm: %s\n", path);
}
free (command);
command_name = Command_Name;
return (0);
}
/* rcvs: dump a list */
int
rcvs_dump_list ( msg, mlist )
char *msg;
List *mlist;
{
if (msg != NULL)
fprintf(stderr, "-> %s", msg);
walklist (mlist, rcvs_Print_Node);
fprintf(stderr, "\n");
return (0);
}
/* rcvs: get host.domain for local host */
char *
rcvs_gethostdomain()
{
#include <netdb.h>
struct hostent *hp;
char host[PATH_MAX];
char tmp[PATH_MAX];
char *HostDomain;
char *hostdomain = NULL;
char *cp;
/* get host */
(void) gethostname ( host, sizeof(host) );
if (host != NULL)
cp = index( host, '.');
if ( cp != NULL)
*cp = '\0';
/* get domain, see if it's set with CVSDOMAIN */
if (rcvs_domain != NULL)
{
sprintf (tmp, "%s.%s", host, rcvs_domain);
return (xstrdup(tmp));
}
/* get domain, try gethostbyname */
hp = gethostbyname(host);
HostDomain = hp->h_name;
if (HostDomain != NULL)
cp = index( HostDomain, '.');
if (cp != NULL)
hostdomain = xstrdup (HostDomain);
/* get domain, try getdomainname */
if ( hostdomain == NULL)
{
char domain [PATH_MAX];
(void) getdomainname ( domain, sizeof(domain));
if (domain != NULL)
cp = index( domain, '.');
if ( cp != NULL)
{
char tmp [PATH_MAX];
sprintf (tmp, "%s.%s", host, cp+1);
hostdomain = xstrdup (tmp);
}
}
if ( hostdomain == NULL)
{
command_name = xstrdup ("rcvs_gethostdomain");
error (0, 0, "can not find network domain");
error (0, 0, "set CVSDOMAIN to network domain of your machine");
error (1, 0, "not including hostname !!! (e.g. dec.com)");
}
return (hostdomain);
}
/* rcvs: parse CVSROOT */
int
rcvs_Parse_ID (Str, rcvsuser, rcvshost, rcvsroot, rcvsdir, cvsroot)
char *Str;
char **rcvsuser;
char **rcvshost;
char **rcvsroot;
char **rcvsdir;
char **cvsroot;
{
char *cp;
char *Cp;
char *str;
int count = 0;
if ( Str == "" || Str == NULL )
error (1, 0, "rcvs_Parse_ID: bug #1, Str=null string");
str = xstrdup (Str);
if ((cp = index (str, ':')) == NULL)
{
if ((cp = index (str, '@')) != NULL)
error (1, 0, "rcvs_Parse_ID: bad CVSROOT: '%s'\n", str);
else
*cvsroot = xstrdup (str);
}
else
{
if ((Cp = index (cp+1, ':')) != NULL)
{
*rcvsdir = xstrdup (Cp+1);
*Cp = '\0';
}
else
error (1, 0, "rcvs_Parse_ID: bad CVSROOT '%s'\n", str);
*rcvsroot = xstrdup (cp+1);
*cp = '\0';
/* rcvs: has RCVSuser (rcvsuser@rcvshost) */
if ((cp = index (str, '@')) != NULL)
{
*rcvshost = xstrdup (cp+1);
*cp = '\0';
*rcvsuser = xstrdup (str);
}
else
*rcvshost = xstrdup (str);
*cvsroot = *rcvsdir;
}
/* check results */
{
if (*rcvsuser == NULL || strcmp (*rcvsuser, "") == 0)
*rcvsuser = rcvs_username;
if (*rcvsuser != NULL) count++;
if (*rcvshost != NULL) count++;
if (*rcvsroot != NULL) count++;
if (*rcvsdir != NULL) count++;
if (count >1 && count < 4)
error(1,0,"%s is not in RCVSUSER@RCVSHOST:CVSROOT:RCVSDIR format",
CVSROOT_ENV);
}
free (str);
return (0);
}
/* rcvs: print the key of a node to stdio, called by rcvs_dump_list */
int
rcvs_Print_Node (p)
Node *p;
{
List *L;
if (p->type == DIRS)
fprintf(stderr, " %s", p->key);
else
fprintf(stderr, " %s (%s)", p->key, p->data);
if (p->type == DIRS && p->data != NULL)
{
L = (void *) p->data;
rcvs_dump_list( (char *) NULL, L);
}
return (0);
}
/* check repository of a local folder
* cvsroot: current CVSROOT value
* dir: name of folder
* repository: the repository of existing folder
*/
int
rcvs_check_local_repos (cvsroot, dir, repository)
char *cvsroot;
char *dir;
char *repository;
{
char path[PATH_MAX];
char *Command_Name;
char *command;
Command_Name = command_name;
command = xstrdup ("rcvs_check_local_repos");
command_name = command;
if (!cvsroot || !*cvsroot)
error (1, 0,"You don't have a %s environment variable",CVSROOT_ENV);
(void) sprintf (path, "%s/%s", cvsroot, CVSROOTADM);
if (access (path, R_OK | X_OK))
{
error (0, 0,
"you don't have sufficient access to %s: %s", CVSROOT_ENV,
cvsroot);
error (1, 0, "%s", path);
}
(void) sprintf (path, "%s/", cvsroot);
if (strncmp (repository, path, strlen (path)) != 0
&& !rcvs_copt_change_repos)
{
error (0, 0, "%s does not match local folder '%s'", CVSROOT_ENV, dir);
error (1, 0, "%s = %s", CVSADM_REP, repository);
}
free (command);
command_name = Command_Name;
return (0);
}
/* get information from CVS/Repository and CVS/Remote,
* dir: path relative to current directory
* &Id: the CVSROOTr stored in CVS/Remote.
* &Repository: the repository relative to local CVSROOT
*/
char *
rcvs_get_repos (dir, Id, Repository)
char *dir;
char **Id;
char **Repository;
{
char *ID;
char repository[PATH_MAX];
char *Repos = NULL;
char *Command_Name;
char *command;
Command_Name = command_name;
command = xstrdup ("rcvs_get_repos");
command_name = command;
if (dir == NULL)
error(1, 0, "rcvs_get_repos: #bug: dir is null");
sprintf (repository, "%s/%s", dir, CVSADM_REP);
if (isreadable ( repository )) /* CVS/Repository */
{
FILE *fpin;
char repos[PATH_MAX];
char tmp[PATH_MAX];
char *cp;
int remote_exist = FALSE;
ID = NULL;
if (dir == NULL)
error (1, 0, "#bug:, dir==NULL");
if (dir != NULL)
(void) sprintf (tmp, "%s/%s", dir, RCVSADM_REMOTE);
else
(void) strcpy (tmp, RCVSADM_REMOTE);
if (isreadable (tmp)) /* CVS/Remote */
{
remote_exist = TRUE;
fpin = open_file (tmp, "r");
if (fgets (repos, PATH_MAX, fpin) == NULL)
error (1, 0, "#bug: cannot read %s",tmp);
if (fclose (fpin) == EOF)
error (1, 0, "#bug: cannot close %s", tmp);
if (repos == NULL)
error(1, 0, "#bug:, repos = NULL");
if ((cp = rindex (repos, '\n')) != NULL)
*cp = '\0';
if (repos == "")
error(1, 0, "#bug:, repos = NULL");
else
{
char *str;
str = xstrdup (repos);
if ((cp = index (str, ' ')) == NULL)
error (1, 0, "bad %s file", RCVSADM_REMOTE);
else
{
*cp++ = '\0';
ID = xstrdup (str);
Repos = xstrdup (cp);
}
}
}
if (rcvs_Copt_change_repos)
{
char *rep;
rep = Name_Repository (dir,"");
if ( rep != NULL && index (rep, '/') == NULL)
error (1, 0, "%s is corrupted", CVSADM_REP);
if (!remote_exist)
{
char *rcvsuser;
char *rcvshost;
char *rcvsroot;
char *rcvsdir;
char *cvsroot;
(void) rcvs_Parse_ID (rcvs_ID, &rcvsuser, &rcvshost,
&rcvsroot,&rcvsdir, &cvsroot);
if (strncmp (rep, rcvsdir, strlen (rcvsdir)) != 0)
{
error (0, 0, "%s does not match local folder %s",
rcvs_Id, dir);
error (1, 0, "%s = %s", CVSADM_REP, rep);
}
if (!quiet)
fprintf (stderr, "hum.. this must be a rcvs-0.3.9 folder\n");
Repos = xstrdup(rep + strlen(rcvsdir) + 1);
}
if (trace)
fprintf (stderr, "-> -C option, use %s and ignore %s if it exist\n", rcvs_Id, RCVSADM_REMOTE);
ID = xstrdup (rcvs_ID);
}
else if (!remote_exist) /* no CVS/Remote */
{
if (trace)
fprintf (stderr, "-> %s un-accessible, assume it's local folder\n",tmp);
}
if (ID != NULL && index (ID,':') != NULL) /* remote folder */
{
char *rcvsuser;
char *rcvshost;
char *rcvsroot;
char *rcvsdir;
char *cvsroot;
rcvs_native_RCVS = TRUE;
*Id = ID;
if (Repos != NULL && strncmp (Repos, RCVSMOD, strlen(RCVSMOD)) == 0)
Repos += strlen(RCVSMOD);
(void) rcvs_Parse_ID (ID, &rcvsuser, &rcvshost,
&rcvsroot,&rcvsdir, &cvsroot);
*Repository = xstrdup (rcvsdir);
if ( trace && !rcvs_Copt_change_repos)
{
fprintf (stderr, "-> remote folder '%s' exist \n", dir);
fprintf (stderr, "-> repository = %s\n", ID);
}
}
else /* local folder */
{
*Repository = Name_Repository (dir,"");
if ( CVSroot_v != NULL && index(CVSroot_v,':') != NULL)
{
error (0, 0, "'%s' is local folder", dir);
error (1, 0, "%s cannot be in remote format ",CVSROOT_ENV);
}
if (rcvs_CM->need_repos)
{
if (!rcvs_copt_change_repos)
(void) rcvs_check_local_repos (CVSroot_v, dir, *Repository);
}
*Id = xstrdup (CVSroot);
Repos = xstrdup (dir);
}
}
else
error (1,0,"#bug: %s is not a CVS folder", dir);
free (command);
command_name = Command_Name;
return (Repos);
}
/*
* rcvs: walk a list with a specific proc and argument
*/
int
rcvs_walklist (argc, argv, msg, list, proc)
int argc;
char *argv[];
char *msg;
List *list;
int (*proc) ();
{
Node *head, *p;
int err = 0;
if (list == NULL)
{
error (1, 0, "rcvs_walklist: bug %s, list==NULL", msg);
return (0);
}
head = list->list;
for (p = head->next; p != head; p = p->next)
err += proc (argc, argv, p);
return (err);
}
/* rcvs: return size of file */
int
filesize (repository)
char *repository;
{
struct stat sbuf;
if ( stat(repository, &sbuf) == 0)
return (sbuf.st_size);
else
return(0);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.