/* * 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" #include "rcvs.h" #include "patchlevel.h" static int size_pstmp_key = 0; static int size_pstmp_data = 0; static int size_pstmp = 0; static int alloc_pstmp = 0; static int size_margv = 0; static FILE *fp; static struct cmd *cm; static char *CurDir = NULL; static char *host = NULL; static char *pstmp = NULL; static char **margv; static char msg1[] = "CVSROOT ----> clone"; static char msg2[] = "CVSROOT <---- clone"; static char bar[] = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"; static char *rcvsid = NULL; static int Margc = 0; static int margc = 0; static int lock_checked = FALSE; static int get_CVSROOT = FALSE; static int lockSet_onServer = FALSE; static int phase1_err_reported = FALSE; static char *cvsroot_gid; static int cvsroot_mode; static int local = FALSE; /* version number */ int ver_rcvs_client = 0; int ver_rcvs_server = 0; /* flow control variables */ int rcvs_inshell = FALSE; int rcvs_native = FALSE; int rcvs_native_CVS = FALSE; int rcvs_native_RCVS = FALSE; int rcvs_set_p3_lock = FALSE; int rcvs_sync = FALSE; int rcvs_sync_backward = FALSE; int rcvs_sync_forward = FALSE; int rcvs_sync_check_error = 1; int rcvs_copt_change_repos = FALSE; int rcvs_Copt_change_repos = FALSE; int rcvs_Ropt_remote = FALSE; char *rcvs_Popt_phases = NULL; /* lock variables */ int rcvs_lock_WFL_local = FALSE; int rcvs_lock_WFL_remote = FALSE; int rcvs_lock_RFL = FALSE; int rcvs_lock_wfl = FALSE; int rcvs_lock_rfl = FALSE; int rcvs_Uopt_unlock = FALSE; int rcvs_Lopt_lock = FALSE; int rcvs_lock_phase3 = FALSE; char *rcvs_ID = NULL; char *rcvs_Id = NULL; char *CVSroot_v = NULL; char *CVSroot_n = NULL; char *CVSrootr_v = NULL; char *CVSrootr_n = NULL; char *CVSrootd_v = NULL; char *CVSrootd_n = NULL; char *CVSrootD_v = NULL; char *CVSrootD_n = NULL; char *rcvs_domain = NULL; char *rcvs_cvsrec = NULL; char *rcvs_username = NULL; char *rcvs_tmpname = NULL; char *rcvs_module = NULL; char *rcvs_dopt_where = NULL; int rcvs_level = 0; int rcvs_gen_optind = 0; int rcvs_bypass = 0; char *RCVSdir = NULL; char *RCVShost = NULL; char *RCVSroot = NULL; char *RCVSuser = NULL; struct CMD *rcvs_CM; List *rcvs_chmodlist = (List *) NULL; List *rcvs_rmlist = (List *) NULL; List *rcvs_dirlist = (List *) NULL; List *rcvs_filelist = (List *) NULL; int rcvs_file_mode = FALSE; int rcvs_cmd_optind; int rcvs_parse_opt = FALSE; int rcvs_do_rdist = TRUE; char *rcvs_msgfile = NULL; FILE *msgfp = (FILE *) NULL; #if __STDC__ char *rcvs_get_repos (char *dir, char **Id, char **Repository); int rcvs_do_host (int argc, char *argv[], Node *p); int rcvs_add_sync_margv (int margc, char *margv[], Node *p); int rcvs_add_sync_pstmp (Node *p); int rcvs_add_original_pstmp (Node *p); #else char *rcvs_get_repos (); int rcvs_do_host (); int rcvs_add_sync_margv (); int rcvs_add_sync_pstmp (); int rcvs_add_original_pstmp (); #endif /* __STDC__ */ struct cmd { char *fullname; char *nick1; char *nick2; int (*func) (); }; /* rcvs: this is core of RCVS. Process all folders if there is remote one */ int rcvs_main (argc, argv, Cm) int argc; char *argv[]; struct cmd *Cm; { char tmp[PATH_MAX]; int err = 0; cm = Cm; /* initialization */ host = rcvs_gethostdomain (); (void) sprintf (tmp,"%s.%d",RCVSMSG, getpid ()); rcvs_msgfile = xstrdup(tmp); { char *curDir; curDir = xmalloc (PATH_MAX); (void) getwd (curDir); CurDir = xstrdup (curDir); if (curDir != NULL) free (curDir); } /* adjust argument pointer */ argc += rcvs_gen_optind; argv -= rcvs_gen_optind; /* e.g. ^cvs -t co -A me */ /* call rcvs_do_host */ if (rcvs_dirlist) rcvs_walklist (argc, argv, "#4", rcvs_dirlist, rcvs_do_host); else error (1, 0, "rcvs_main: bug #1: no directory found"); /* return to main() only if there is only local folder */ exit (err); } /* rcvs: create an empty file then do chmod */ int emptyfile (repository) char *repository; { FILE *histfp; if (!repository) return(2); histfp = open_file (repository, "w"); if (fclose (histfp)) { error(0, 0,"emptyfile: cannot access %s", repository); return(1); } (void) rcvs_chmod ( repository, cvsroot_gid, cvsroot_mode); return(0); } /* calculate size needed for [key] in pstmp */ int rcvs_size_pstmp_key (p) Node *p; { char *cp; cp = p->key; if (strcmp (cp, "") != 0) size_pstmp_key = size_pstmp_key + strlen(cp) + 1; return (0); } /* calculate size needed for [data] in pstmp */ int rcvs_size_pstmp_data (p) Node *p; { char *cp; cp = p->data; if (strcmp (cp, "") != 0) size_pstmp_data = size_pstmp_data + strlen(cp) + 1; return (0); } /* calculate size of pointer array margv */ int rcvs_size_margv (p) Node *p; { size_margv++; return (0); } /* allocate memory for pstmp */ int rcvs_allocate_pstmp (p) Node *p; { List *L; L = (void *) p->data; size_pstmp_key = 0; (void) walklist (L, rcvs_size_pstmp_key); size_pstmp_data = 0; (void) walklist (L, rcvs_size_pstmp_data); size_pstmp = (size_pstmp_key > size_pstmp_data) ? size_pstmp_key : size_pstmp_data; if (pstmp != NULL) free (pstmp); alloc_pstmp = PATH_MAX + size_pstmp; pstmp = xmalloc (alloc_pstmp); pstmp[0] = '\0'; return (0); } /* allocate memory for margv */ int rcvs_allocate_margv (p) Node *p; { List *L; margc = Margc = 0; L = (void *) p->data; size_margv = 0; (void) walklist(L, rcvs_size_margv); if (trace) fprintf (stderr, "-> rcvs_do_host: allocate margv: %d\n", size_margv); if (margv != NULL) free (margv); margv = (char **) xmalloc (size_margv * sizeof(char *) + 4); return (0); } /* rcvs: process folders that belong to a local or remote host. */ int rcvs_do_host ( argc, argv, p ) int argc; char *argv[]; Node *p; { int err = 0; local = 0; rcvsid = NULL; margc = Margc = 0; cvsroot_gid = NULL; cvsroot_mode = 0; /* allocate memory for pstmp */ (void) rcvs_allocate_pstmp (p); (void) rcvs_allocate_margv (p); if (rcvs_Popt_phases == NULL) { rcvs_Popt_phases = rcvs_CM->phases; if (rcvs_bypass != 0) { if (index (rcvs_Popt_phases, '3') == NULL && strcmp (rcvs_CM->sync_name, "checkout") == 0) { rcvs_Popt_phases++; printf("turn on BYPASS mode, bypass phase [1]\n"); } else { printf("BYPASS mode is defeated, '%s' deals with main repository directly\n", rcvs_CM->fullname); printf("this may take a while, specifying relevant files can speed up the process.\n"); } } } /* print name of folder */ { List *L; register int i; L = (void *) p->data; (void) walklist (L, rcvs_add_sync_pstmp); if (!quiet) { char title[PATH_MAX]; if (index (p->key, ':') == NULL ) (void) sprintf(title, "LOCAL FOLDER:"); else (void) sprintf(title, "REMOTE FOLDER:"); fprintf (stderr, "%s %s\n", title, pstmp); (void) strncpy (pstmp, bar, strlen(title)-1); *(pstmp+strlen(title)-1) = '\0'; fprintf (stderr, "%s\n", pstmp); } } /* parse RCVS ID */ rcvsid = p->key; (void) rcvs_Parse_ID (p->key, &RCVSuser, &RCVShost, &RCVSroot,&RCVSdir, &CVSroot); /* process this host in three phases */ { if (index (p->key, ':') == NULL) local = TRUE; err = 0; if (rcvs_msgfile != NULL && isfile(rcvs_msgfile)) if ( unlink_file (rcvs_msgfile) ) error (1, 0, "cannot remove message file %s\n", rcvs_msgfile); if ( !local && index (rcvs_Popt_phases,'1') ) if ( !really_quiet || !noexec || trace) err = rcvs_do_host_phase1 ( argc, argv, p ); if ( local || (! err && index (rcvs_Popt_phases,'2')) ) err = rcvs_do_host_phase2 (argc, argv, p); if ( !local && (! err && index (rcvs_Popt_phases,'3')) ) if ( !really_quiet || !noexec || trace) err = rcvs_do_host_phase3 (argc, argv, p, margv); /* append history + remove file + clear lock on server * if 1. remove list not empty 2. no error 3. phase-3 4. has history */ { char tmp[PATH_MAX]; char line[PATH_MAX]; (void) sprintf( tmp,"%s/CVSROOT/%s",CVSroot, CVSROOTADM_HISTORY_NEW); if (rcvs_rmlist != NULL || (!local && (index (rcvs_Popt_phases,'3') || filesize(tmp)))) (void) rcvs_hist_and_lock(err, CVSroot, RCVSuser, RCVShost, RCVSroot, RCVSdir); /* clean up temporary history and commit file */ if (isfile(tmp) && !local) unlink (tmp); (void) sprintf( tmp,"%s/CVSROOT/%s",CVSroot, CVSROOTADM_COMMITLOG_NEW); if (isfile(tmp) && !local) unlink (tmp); (void) sprintf( tmp,"%s/CVSROOT/%s",CVSroot, CVSROOTADM_HISTORY); if (isfile(tmp) && !local) emptyfile (tmp); (void) sprintf( tmp,"%s/CVSROOT/%s",CVSroot, CVSROOTADM_COMMITLOG); if (isfile(tmp) && !local) emptyfile (tmp); if (rcvs_msgfile != NULL && isfile(rcvs_msgfile)) (void) unlink(rcvs_msgfile); } rcvs_Clear_my_lock (); if (cvsroot_gid != NULL) free (cvsroot_gid); } if (margv != NULL) free (margv); return (err); } /* do chmod on a file or directory */ int rcvs_chmod (repository, gid, mode) char * repository; char * gid; int mode; { struct group *Gid; if (isfile(repository) && gid) { struct stat sbuf; uid_t uid; if ( stat(repository, &sbuf) == 0) { uid = getuid(); Gid = getgrnam(gid); if ( uid == sbuf.st_uid ) { /* chgrp only if has group write access */ if ( S_IWGRP&(mode)) { int err; err = ( Gid == NULL || chown (repository, -1, Gid->gr_gid)); if (trace && err) error(0,0, "cannot chgrp %s %s", gid, repository); } if ( chmod (repository, mode)) error(0,0, "cannot chmod %o %s", mode, repository); } } } } /* examine stdout for sync session */ int rcvs_check_sync_stdout(line) char * line; { char *cp = NULL; char tmp[PATH_MAX]; char repository[PATH_MAX]; int err = 0; { /* CVSROOT= */ if ( (strncmp ( "CVSROOT=", line, 8) == 0) || (strncmp ( "CVSroot=", line, 8) == 0) ) { if (trace) fprintf (stderr, "-> %s", line); if (RCVSroot == NULL) { *(line + strlen(line) -1) = '\0'; cp = line + 8; RCVSroot = xstrdup (cp); } /* CVSROOT= is a signal that CVS sync is ok !! * CVSroot= is a signal that CVS lock on server is ok !!*/ if (strncmp ( "CVSROOT=", line, 8) == 0) get_CVSROOT = TRUE; else lockSet_onServer = TRUE; } /* REMOVE= */ else if ( strncmp ( "REMOVE=", line, 7) == 0 ) { if (trace) fprintf (stderr, "-> %s", line); *(line + strlen(line) -1) = '\0'; cp = line + 7; sprintf (tmp, "%s/%s", CVSroot, cp); if (trace && unlink_file (tmp)) fprintf (stderr, "-> cannot remove %s\n", cp); } /* GROUP/MODE= */ else if ( strncmp ( "GROUP/MODE=", line, 11) == 0 ) { char dir[PATH_MAX]; char gid[PATH_MAX]; int mode; if (trace) fprintf (stderr, "-> %s", line); *(line + strlen(line) -1) = '\0'; cp = line + 11; sscanf (cp, "%s %s %o", dir, gid, &mode); if (strcmp(dir,CVSROOTADM)== 0) { cvsroot_mode=mode; cvsroot_gid=xstrdup(gid); } sprintf (repository, "%s/%s", CVSroot, dir); (void) rcvs_chmod (repository, gid, mode); } /* RCVSLOCK= */ else if ( strncmp ( "RCVSLOCK=", line, 9) == 0 ) { if (trace) fprintf (stderr, "-> %s", line); rcvs_lock_WFL_remote = TRUE; } else if ( strncmp ( "RSH_STATUS=", line, 11) == 0) /* RSH_STATUS */ { int Err; if (trace) fprintf (stderr, "-> %s", line); Err = atoi(line + 11); if (Err) { fprintf (stderr, "rsh return err <> 0\n"); phase1_err_reported = TRUE; err = Err; } } /* RDIST_STATUS */ else if ( strncmp ( "RDIST_STATUS=1", line, 14) == 0) { if (trace) fprintf (stderr, "-> %s", line); fprintf (stderr, "rdist returns err <> 0\n"); phase1_err_reported = TRUE; err = 1; } /* SERVER VERSION*/ else if ( strncmp ( "SERVER_VERSION=", line, 15) == 0) { if (trace) fprintf (stderr, "-> %s", line); *(line + strlen(line) -1) = '\0'; cp = line + 15; ver_rcvs_server = (int)cp; } else fprintf(stderr, "%s",line); } return (err); } /* rcvs: do forward sync for a remote folder. */ int rcvs_do_host_phase1 ( argc, argv, p ) int argc; char *argv[]; Node *p; { int err = 0; int err2 = 0; int err3 = 0; FILE *fp_err; char tmp[PATH_MAX]; char line[PATH_MAX]; List *L; register int i; get_CVSROOT = FALSE; /* create clone directory if not already exist */ (void) rcvs_mkdir (RCVSdir); /* check lock */ (void) rcvs_Check_lock (); lock_checked = TRUE; if (!quiet) { sprintf(line, "phase [1]. Sending rdist request to %s@%s", RCVSuser, RCVShost); fprintf (stderr, "%s\n", line); if (trace) { (void) strncpy (tmp, bar, strlen(line)); *(tmp+strlen(line)) = '\0'; fprintf (stderr, "%s\n", tmp); } fprintf(stderr, "%s\n", msg1); } /* generate command to do rsh */ /*+IS*/ (void) sprintf (pstmp,"%s %s -l %s ", rshcmd, RCVShost, RCVSuser ); /*-IS*/ (void) strcat ( pstmp, "cvs " ); if (index(rcvs_Popt_phases,'3')) (void) strcat ( pstmp, "-L " ); if (noexec) (void) strcat ( pstmp, "-n " ); if (quiet) (void) strcat ( pstmp, "-q " ); if (really_quiet) (void) strcat ( pstmp, "-Q " ); if (trace) (void) sprintf (pstmp+strlen(pstmp), "-t "); if ( rcvs_Uopt_unlock) (void) strcat ( pstmp, "-U " ); (void) sprintf (pstmp+strlen(pstmp),"-S -e %d -d %s@%s:%s:%s ", ver_rcvs, rcvs_username, host, RCVSdir, RCVSroot ); if (rcvs_cvsrec != NULL) (void) sprintf (pstmp+strlen(pstmp),"-X %s ", rcvs_cvsrec ); (void) sprintf (pstmp+strlen(pstmp),"%s ", rcvs_CM->sync_name ); /* add relative repository stored in data field to pstmp */ L = (void *) p->data; margc = Margc = 0; (void) walklist (L, rcvs_add_sync_pstmp); (void) strcat( pstmp, "2>&1; echo RSH_STATUS=$?" ); /*-> put all cvs message into stdout */ if (trace) (void) fprintf(stderr, "-> (%d/%d) %s\n",strlen(pstmp), alloc_pstmp, pstmp); /* open pipe to receive data back from rsh */ fp = popen (pstmp, "r"); /* check stdout, output from cvs's stdout */ if (trace) (void) fprintf(stderr, "-> rcvs_do_host_phase1: output from stdout ...\n"); while (fgets (line, sizeof (line), fp)) { if ( strncmp ( "|", line, 1) == 0) /* rdist message */ fprintf(stderr, "%s",line); else { err = rcvs_check_sync_stdout (line); if (err) break; (void) rcvs_check_rsh_output (line); /* give user suggestion */ } } err3 = pclose (fp); if (err3) { if (!phase1_err_reported) fprintf (stderr, "rsh return err <> 0\n"); phase1_err_reported = TRUE; err = 1; } if (!get_CVSROOT && !phase1_err_reported) { fprintf (stderr, "cvs on server return err <> 0\n"); err = 1; phase1_err_reported = TRUE; } if (err && !phase1_err_reported) fprintf (stderr, "phase 1 returns err <> 0\n"); if (err && rcvs_CM->need_repos) error (1, 0, "fail to get modules"); /* make sure history exist, it must exist to start history logging*/ (void) sprintf( line,"%s/CVSROOT/%s",CVSroot,CVSROOTADM_HISTORY); if (!local && !isfile(line)) (void) emptyfile (line); /* make sure commitlog exist */ (void) sprintf(line,"%s/CVSROOT/%s",CVSroot,CVSROOTADM_COMMITLOG); if (!local && !isfile(line)) (void) emptyfile (line); return (err); } /* rcvs: process folders locally. */ int rcvs_do_host_phase2 ( argc, argv, p ) int argc; char *argv[]; Node *p; { char tmp[PATH_MAX]; char line[PATH_MAX]; List *L; int err = 0; /* check lock */ if (!lock_checked) (void) rcvs_Check_lock (); lock_checked = TRUE; if ( (chdir (CurDir) < 0)) error (1, 0, "cannot chdir to %s", CurDir); /* run CVS command locally */ if (!quiet) { sprintf(line, "phase [2]. Local %s on clone",cm->fullname); fprintf (stderr, "%s\n", line); if (trace) { (void) strncpy (tmp, bar, strlen(line)); *(tmp+strlen(line)) = '\0'; fprintf (stderr, "%s\n", tmp); } fprintf(stderr,"%s\n", rcvs_CM->msg); } /* construct the argument for local cvs !! */ { int i = 0; int narg; narg = rcvs_gen_optind + rcvs_cmd_optind -1; (void) sprintf (pstmp, "CVSROOT=%s; export CVSROOT; ", CVSroot); for ( i = 0; i <= narg; i++) { if ( i == 1 ) { if (index (p->key, ':') == NULL ) /* local folder */ (void) sprintf (pstmp+strlen(pstmp), "-Y %s -d %s ", rcvs_msgfile, CVSroot_v); else (void) sprintf (pstmp+strlen(pstmp), "-Y %s -d %s ", rcvs_msgfile, rcvsid); } if ( index (argv[i], ' ') != NULL ) (void) sprintf (pstmp+strlen(pstmp), "\'%s\' ", argv[i]); else { if (i < rcvs_gen_optind && strcmp (argv[i], "-d") == 0) i++; else { (void) strcat ( pstmp, argv[i]); (void) strcat ( pstmp, " "); } } } /* add relative repository of this folder to pstmp */ L = (void *) p->data; margc = Margc = 0; (void) walklist (L, rcvs_add_original_pstmp); (void) strcat ( pstmp, " "); } /* run it in shell in order to catch error and/or set CVSROOT */ if (trace) fprintf(stderr, "-> (%d/%d) %s\n", strlen(pstmp), alloc_pstmp, pstmp); err = system ( pstmp ); if (trace && err) fprintf(stderr, "-> err=%d setlock=%d\n", err, rcvs_lock_WFL_local); /* copy history to history.tmp and commitlog to commitlog.tmp */ (void) sprintf( tmp,"%s/CVSROOT/%s",CVSroot,CVSROOTADM_HISTORY); (void) sprintf( line,"%s/CVSROOT/%s",CVSroot,CVSROOTADM_HISTORY_NEW); if (!local && filesize(tmp)) { copy_file (tmp, line); (void) emptyfile (tmp); } (void) sprintf( tmp,"%s/CVSROOT/%s",CVSroot,CVSROOTADM_COMMITLOG); (void) sprintf( line,"%s/CVSROOT/%s",CVSroot,CVSROOTADM_COMMITLOG_NEW); if (!local && filesize(tmp)) { copy_file (tmp, line); (void) emptyfile (tmp); } /* cleanup lock if error */ if ( err ) { int i; fprintf (stderr, "phase 2 returns err <> 0\n"); if (index(rcvs_Popt_phases,'3')) { err = 0; /* reset error to sync back */ fprintf (stderr, "sync clone back anyway for safety..\n"); } if (rcvs_native) rcvs_Clear_my_lock (); return (err); } return (0); } /* rcvs: do backward sync for remote folder that need to sync back. */ int rcvs_do_host_phase3 ( argc, argv, p, margv ) int argc; char *argv[]; Node *p; char *margv[]; { List *L; char tmp[PATH_MAX]; char line[PATH_MAX]; register int i; int err = 0; /* check lock */ if (!lock_checked) (void) rcvs_Check_lock (); lock_checked = TRUE; /* cleanup lock if commit, then sync modules back to server */ { /* rdist modules back to master repository, * simply call checkout once rcs_sync flag is set */ if (!quiet) { sprintf (line, "phase [3]. Rdist modules back to %s@%s", RCVSuser, RCVShost); fprintf (stderr, "%s\n", line); if (trace) { (void) strncpy (tmp, bar, strlen(line)); *(tmp+strlen(line)) = '\0'; fprintf (stderr, "%s\n", tmp); } fprintf(stderr, "%s\n", msg2); } /* add relative repository stored in data field to margv */ L = (void *) p->data; margc = Margc = 0; margv[0] = "checkout"; Margc++; rcvs_walklist (margc, margv, "#3", L, rcvs_add_sync_margv); if (trace) { for ( i = 0; i < Margc; i++) fprintf(stderr, "%s ", margv[i]); fprintf (stderr, "\n"); } rcvs_sync = rcvs_sync_backward = TRUE; rcvs_native = FALSE; rcvs_chmodlist = rcvs_dirlist = rcvs_filelist = NULL; /* skip phase 3 if -n */ if (noexec) return; if (strcmp (cm->fullname, "import") == 0) { err = rcvs_Rdist_init (); (void) addlist (&rcvs_dirlist, margv[1]); err = rcvs_Rdist(); } else err = checkout (Margc, margv); rcvs_sync = rcvs_sync_backward = FALSE; rcvs_native = TRUE; } if (err) { rcvs_lock_phase3 = TRUE; /* construct instruction for recovering */ (void) sprintf (tmp, "cvs -U -P 3 "); for ( i = 1; i < argc; i++) { if (strcmp(argv[i],"-P") == 0) { i++; continue; } if (strcmp(argv[i],"-U") == 0) continue; (void) strcat ( tmp, argv[i]); (void) strcat ( tmp, " "); } fprintf (stderr, "phase 3 returns err <> 0\n"); error (1, 0, "aborted, system remain locked.\nPlease do '%s' once the problem is solved ASAP !!!", tmp); } /* this is not the end yet. rcvs_hist_and_lock (in rcvs_lock.c) will conduct the additional tasks: 1. Append history file to main repository. 2. Cleanup lock for commit. 3. Remove files if rmlist is not empty. 4. chmod for added directories. */ return (err); } /* determine CVSROOT */ int rcvs_do_cvsroot (cvs_update_env) int cvs_update_env; { int remote_mode = FALSE; char *cvsroot; char *cp; if (rcvs_username == NULL) rcvs_username = xstrdup (getcaller()); if (rcvs_cvsrec == NULL) /* get CVSREC */ { if ((cp = getenv (CVSREC_ENV)) != NULL) rcvs_cvsrec = cp; } if (rcvs_sync) remote_mode = TRUE; else /* check CVSMODE */ { if ((cp = getenv (CVSMODE_ENV)) != NULL) { if ( strcmp (cp, "remote") == 0 || strcmp (cp, "REMOTE") == 0) remote_mode = TRUE; else if (!( strcmp (cp, "local") == 0 || strcmp (cp, "LOCAL") == 0)) error (1, 0, "set %s to 'local' or 'remote'", CVSMODE_ENV); } } if (CVSrootd_v != NULL) /* -d */ { rcvs_ID = CVSrootd_v; rcvs_Id = CVSrootd_n; if (index (rcvs_ID, ':') == NULL) /* local format */ { CVSroot = CVSrootd_v; CVSroot_v = CVSrootd_v; CVSroot_n = CVSrootd_n; } else /* remote format */ { if (rcvs_sync || rcvs_inshell) (void) rcvs_Parse_ID (rcvs_ID, &RCVSuser, &RCVShost, &RCVSroot,&RCVSdir, &CVSroot); else { CVSrootr_v = rcvs_ID; CVSrootr_n = rcvs_Id; } } } else /* no -d */ { if (!remote_mode && CVSroot_v != NULL) /* CVSROOT */ { rcvs_ID = CVSroot_v; rcvs_Id = CVSroot_n; if (index (rcvs_ID, ':') != NULL && (rcvs_sync || rcvs_inshell)) (void) rcvs_Parse_ID (rcvs_ID, &RCVSuser, &RCVShost, &RCVSroot,&RCVSdir, &CVSroot); } if ( (remote_mode && CVSrootr_v != NULL) || /* CVSMODE=remote*/ (CVSroot_v == NULL && CVSrootr_v != NULL) ) /* CVSROOTr only*/ { rcvs_ID = CVSrootr_v; rcvs_Id = CVSrootr_n; if (index (rcvs_ID, ':') != NULL) (void) rcvs_Parse_ID (rcvs_ID, &RCVSuser, &RCVShost, &RCVSroot,&RCVSdir, &cvsroot); } } if (rcvs_Ropt_remote) /* -R */ { if (CVSrootr_v == NULL || index (CVSrootr_v, ':') == NULL) error (1, 0, "set %s to user@host:cvsroot:clone to use -R option", CVSROOTr_ENV); rcvs_ID = CVSrootr_v; rcvs_Id = CVSrootr_n; } if (rcvs_Copt_change_repos) /* -C */ { if (CVSrootr_v == NULL || index (CVSrootr_v, ':') == NULL) error (1, 0, "set %s to user@host:cvsroot:clone to use -C option", CVSROOTr_ENV); rcvs_ID = CVSrootr_v; rcvs_Id = CVSrootr_n; } if (rcvs_copt_change_repos) /* -c */ { if (CVSroot_v == NULL) { CVSroot_v = rcvs_ID; CVSroot_n = rcvs_Id; } if (CVSroot_v != NULL) { if (index (CVSroot_v, ':') == NULL) { rcvs_ID = CVSroot_v; rcvs_Id = CVSroot_n; } else error (1, 0, "set %s to local format to use -c option", CVSROOT_ENV); } } /* add user's name to ID if it's missing */ if (rcvs_ID != NULL && index (rcvs_ID, ':') != NULL) { cp = index (rcvs_ID, '@'); if (cp == NULL || cp == rcvs_ID) { char tmp[PATH_MAX]; if (cp == NULL) sprintf (tmp, "%s@%s", rcvs_username, rcvs_ID); else sprintf (tmp, "%s%s", rcvs_username, rcvs_ID); rcvs_ID = xstrdup (tmp); } } if (rcvs_ID == NULL) /* neither CVSROOT nor CVSROOTr was set */ error (1, 0, "neither %s nor %s is set", CVSROOT_ENV, CVSROOTr_ENV); /* print a warm fuzzy message */ if (!quiet && rcvs_ID != NULL && !rcvs_sync && !rcvs_inshell) { if (remote_mode && index (rcvs_ID, ':') != NULL) { fprintf (stderr, "turn on remote mode\n"); fprintf (stderr, "%s = %s\n", rcvs_Id, rcvs_ID); } } } /* rcvs: add argument for sync to margv */ int rcvs_add_sync_margv(margc, margv, p) int margc; char *margv[]; Node *p; { char *cp; cp = p->data; if (strcmp (cp, "") != 0) { if (Margc > size_margv) error (1, 0, "rcvs_add_sync_margv: margv overflow, Margc=%d size_margv=%d", Margc, size_margv); margv[Margc++] = cp; } return 0; } /* rcvs: add argument for sync to pstmp */ int rcvs_add_sync_pstmp(p) Node *p; { char *cp; cp = p->data; if (strcmp (cp, "") != 0) sprintf(pstmp+strlen(pstmp),"%s ", cp); return 0; } /* rcvs: put original argument into pstmp */ int rcvs_add_original_pstmp(p) Node *p; { char *cp; cp = p->key; if (strcmp (cp, "") != 0) sprintf(pstmp+strlen(pstmp),"%s ", cp); return (0); } /* create $RCVSDIR if not already exist */ int rcvs_mkdir (rcvsdir) char *rcvsdir; { char *cp = NULL; char tmp[PATH_MAX]; char repository[PATH_MAX]; cp = rcvsdir; if (!isdir (cp)) { if ( mkdir ( cp, 0777) ) { program_name = xstrdup ("rcvs_mkdir"); error (1, 0 ,"cannot create %s", cp); } else { chmod ( cp, 0775); (void ) sprintf (tmp, "%s/%s", cp, RCVS_CLONE); fp = open_file (tmp, "w"); fprintf (fp, "This is label for RCVS clone directory\n"); fprintf (fp, "Do not remove this file!\n"); if (fclose (fp) == EOF) error (1, 0, "cannot close %s", tmp); } } else { if (!iswritable (cp)) { program_name = xstrdup ("rcvs_mkdir"); error (1, 0, "Sorry, you don't have sufficient access to %s", cp); } (void ) sprintf (tmp, "%s/%s", cp, RCVS_CLONE); if (!isreadable (tmp)) { fprintf(stderr,"Humm..directory %s is not labelled as clone,\n", cp); fprintf(stderr,"if you're sure it can be used as clone, \n"); fprintf(stderr,"please type 'touch %s/%s' to create a label \n", cp, RCVS_CLONE); exit (1); } } /* create CVSROOT if not already exist */ (void) strcpy(repository,rcvsdir); (void) strcat(repository,"/CVSROOT"); cp = repository; if (!isdir (cp)) if ( mkdir ( cp, 0777) ) { program_name = xstrdup ("rcvs_mkdir"); error (1, 0 ,"cannot create %s", cp); } else chmod ( cp, 0775); else if (!iswritable (cp)) { program_name = xstrdup ("rcvs_mkdir"); error (1, 0 , "Sorry, you don't have sufficient access to %s", cp); } return (0); } /* this is a special lock, if phase 3 is executed without phase 1, * we need to set lock on server. This is done by executing * 'cvs -S -L -P 9 co' on server */ int rcvs_set_phase3_lock( ) { int err = 0; char line[PATH_MAX]; char tmp[PATH_MAX]; char *host = NULL; host = rcvs_gethostdomain (); /* generate command to do rsh */ /*+IS*/ (void) sprintf (tmp,"%s %s -l %s ", rshcmd, RCVShost, RCVSuser ); /*-IS*/ (void) strcat ( tmp, "cvs " ); if (index(rcvs_Popt_phases,'3')) (void) strcat ( tmp, "-L -P 9 " ); if (trace) (void) sprintf (tmp+strlen(tmp), "-t "); if ( rcvs_Uopt_unlock) (void) strcat ( tmp, "-U " ); (void) sprintf (tmp+strlen(tmp), "-S -d %s@%s:%s:%s co 2>&1; echo RSH_STATUS=$?", rcvs_username, host, RCVSdir, RCVSroot ); if (trace) fprintf (stderr, "-> %s\n", tmp); /* open pipe to receive data back from rsh */ fp = popen (tmp, "r"); if (trace) (void) fprintf(stderr, "-> rcvs_set_phase3_lock: output from stdout ...\n"); while (fgets (line, sizeof (line), fp)) { err = rcvs_check_sync_stdout (line); if (err) error (1, 0, "abort rcvs_set_phase3_lock"); } if (pclose (fp)) error (1, 0, "rsh return err <> 0\n"); if (!lockSet_onServer) error (1, 0, "fail to set lock\n"); }