ftp.nice.ch/pub/next/unix/developer/rcvs.0.7.9.s.tar.gz#/src/rcvs_subr.c

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.