1 /* 2 * Copyright (c) 1992, Mark D. Baushke 3 * 4 * You may distribute under the terms of the GNU General Public License as 5 * specified in the README file that comes with the CVS 1.4 kit. 6 * 7 * Name of Root 8 * 9 * Determine the path to the CVSROOT and set "Root" accordingly. 10 * If this looks like of modified clone of Name_Repository() in 11 * repos.c, it is... 12 */ 13 14 #include "cvs.h" 15 16 /* Printable names for things in the CVSroot_method enum variable. 17 Watch out if the enum is changed in cvs.h! */ 18 19 char *method_names[] = { 20 "local", "server (rsh)", "pserver", "kserver", "ext" 21 }; 22 23 #ifndef DEBUG 24 25 char * 26 Name_Root(dir, update_dir) 27 char *dir; 28 char *update_dir; 29 { 30 FILE *fpin; 31 char *ret, *xupdate_dir; 32 char root[PATH_MAX]; 33 char tmp[PATH_MAX]; 34 char cvsadm[PATH_MAX]; 35 char *cp; 36 37 if (update_dir && *update_dir) 38 xupdate_dir = update_dir; 39 else 40 xupdate_dir = "."; 41 42 if (dir != NULL) 43 { 44 (void) sprintf (cvsadm, "%s/%s", dir, CVSADM); 45 (void) sprintf (tmp, "%s/%s", dir, CVSADM_ROOT); 46 } 47 else 48 { 49 (void) strcpy (cvsadm, CVSADM); 50 (void) strcpy (tmp, CVSADM_ROOT); 51 } 52 53 /* 54 * Do not bother looking for a readable file if there is no cvsadm 55 * directory present. 56 * 57 * It is possible that not all repositories will have a CVS/Root 58 * file. This is ok, but the user will need to specify -d 59 * /path/name or have the environment variable CVSROOT set in 60 * order to continue. */ 61 if ((!isdir (cvsadm)) || (!isreadable (tmp))) 62 return (NULL); 63 64 /* 65 * The assumption here is that the CVS Root is always contained in the 66 * first line of the "Root" file. 67 */ 68 fpin = open_file (tmp, "r"); 69 70 if (fgets (root, PATH_MAX, fpin) == NULL) 71 { 72 error (0, 0, "in directory %s:", xupdate_dir); 73 error (0, errno, "cannot read %s", CVSADM_ROOT); 74 error (0, 0, "please correct this problem"); 75 return (NULL); 76 } 77 (void) fclose (fpin); 78 if ((cp = strrchr (root, '\n')) != NULL) 79 *cp = '\0'; /* strip the newline */ 80 81 /* 82 * root now contains a candidate for CVSroot. It must be an 83 * absolute pathname 84 */ 85 86 #ifdef CLIENT_SUPPORT 87 /* It must specify a server via remote CVS or be an absolute pathname. */ 88 if ((strchr (root, ':') == NULL) 89 && ! isabsolute (root)) 90 #else /* ! CLIENT_SUPPORT */ 91 if (root[0] != '/') 92 #endif /* CLIENT_SUPPORT */ 93 { 94 error (0, 0, "in directory %s:", xupdate_dir); 95 error (0, 0, 96 "ignoring %s because it does not contain an absolute pathname.", 97 CVSADM_ROOT); 98 return (NULL); 99 } 100 101 #ifdef CLIENT_SUPPORT 102 if ((strchr (root, ':') == NULL) && !isdir (root)) 103 #else /* ! CLIENT_SUPPORT */ 104 if (!isdir (root)) 105 #endif /* CLIENT_SUPPORT */ 106 { 107 error (0, 0, "in directory %s:", xupdate_dir); 108 error (0, 0, 109 "ignoring %s because it specifies a non-existent repository %s", 110 CVSADM_ROOT, root); 111 return (NULL); 112 } 113 114 /* allocate space to return and fill it in */ 115 strip_path (root); 116 ret = xstrdup (root); 117 return (ret); 118 } 119 120 /* 121 * Returns non-zero if the two directories have the same stat values 122 * which indicates that they are really the same directories. 123 */ 124 int 125 same_directories (dir1, dir2) 126 char *dir1; 127 char *dir2; 128 { 129 struct stat sb1; 130 struct stat sb2; 131 int ret; 132 133 if ( CVS_STAT (dir1, &sb1) < 0) 134 return (0); 135 if ( CVS_STAT (dir2, &sb2) < 0) 136 return (0); 137 138 ret = 0; 139 if ( (memcmp( &sb1.st_dev, &sb2.st_dev, sizeof(dev_t) ) == 0) && 140 (memcmp( &sb1.st_ino, &sb2.st_ino, sizeof(ino_t) ) == 0)) 141 ret = 1; 142 143 return (ret); 144 } 145 146 147 /* 148 * Write the CVS/Root file so that the environment variable CVSROOT 149 * and/or the -d option to cvs will be validated or not necessary for 150 * future work. 151 */ 152 void 153 Create_Root (dir, rootdir) 154 char *dir; 155 char *rootdir; 156 { 157 FILE *fout; 158 char tmp[PATH_MAX]; 159 160 if (noexec) 161 return; 162 163 /* record the current cvs root */ 164 165 if (rootdir != NULL) 166 { 167 if (dir != NULL) 168 (void) sprintf (tmp, "%s/%s", dir, CVSADM_ROOT); 169 else 170 (void) strcpy (tmp, CVSADM_ROOT); 171 fout = open_file (tmp, "w+"); 172 if (fprintf (fout, "%s\n", rootdir) < 0) 173 error (1, errno, "write to %s failed", tmp); 174 if (fclose (fout) == EOF) 175 error (1, errno, "cannot close %s", tmp); 176 } 177 } 178 179 #endif /* ! DEBUG */ 180 181 182 /* Parse a CVSROOT variable into its constituent parts -- method, 183 * username, hostname, directory. The prototypical CVSROOT variable 184 * looks like: 185 * 186 * :method:user@host:path 187 * 188 * Some methods may omit fields; local, for example, doesn't need user 189 * and host. 190 * 191 * Returns zero on success, non-zero on failure. */ 192 193 char *CVSroot_original = NULL; /* the CVSroot that was passed in */ 194 int client_active; /* nonzero if we are doing remote access */ 195 CVSmethod CVSroot_method; /* one of the enum values defined in cvs.h */ 196 char *CVSroot_username; /* the username or NULL if method == local */ 197 char *CVSroot_hostname; /* the hostname or NULL if method == local */ 198 char *CVSroot_directory; /* the directory name */ 199 200 int 201 parse_cvsroot (CVSroot) 202 char *CVSroot; 203 { 204 static int cvsroot_parsed = 0; 205 char *cvsroot_copy, *p; 206 207 /* Don't go through the trouble twice. */ 208 if (cvsroot_parsed) 209 { 210 error (0, 0, "WARNING (parse_cvsroot): someone called me twice!\n"); 211 return 0; 212 } 213 214 CVSroot_original = xstrdup (CVSroot); 215 cvsroot_copy = xstrdup (CVSroot); 216 217 if ((*cvsroot_copy == ':')) 218 { 219 char *method = ++cvsroot_copy; 220 221 /* Access method specified, as in 222 * "cvs -d :pserver:user@host:/path", 223 * "cvs -d :local:e:\path", or 224 * "cvs -d :kserver:user@host:/path". 225 * We need to get past that part of CVSroot before parsing the 226 * rest of it. 227 */ 228 229 if (! (p = strchr (method, ':'))) 230 { 231 error (0, 0, "bad CVSroot: %s", CVSroot); 232 return 1; 233 } 234 *p = '\0'; 235 cvsroot_copy = ++p; 236 237 /* Now we have an access method -- see if it's valid. */ 238 239 if (strcmp (method, "local") == 0) 240 CVSroot_method = local_method; 241 else if (strcmp (method, "pserver") == 0) 242 CVSroot_method = pserver_method; 243 else if (strcmp (method, "kserver") == 0) 244 CVSroot_method = kserver_method; 245 else if (strcmp (method, "server") == 0) 246 CVSroot_method = server_method; 247 else if (strcmp (method, "ext") == 0) 248 CVSroot_method = ext_method; 249 else 250 { 251 error (0, 0, "unknown method in CVSroot: %s", CVSroot); 252 return 1; 253 } 254 } 255 else 256 { 257 /* If the method isn't specified, assume 258 SERVER_METHOD/EXT_METHOD if the string contains a colon or 259 LOCAL_METHOD otherwise. */ 260 261 CVSroot_method = ((strchr (cvsroot_copy, ':')) 262 #ifdef RSH_NOT_TRANSPARENT 263 ? server_method 264 #else 265 ? ext_method 266 #endif 267 : local_method); 268 } 269 270 client_active = (CVSroot_method != local_method); 271 272 /* Check for username/hostname if we're not LOCAL_METHOD. */ 273 274 CVSroot_username = NULL; 275 CVSroot_hostname = NULL; 276 277 if (CVSroot_method != local_method) 278 { 279 /* Check to see if there is a username in the string. */ 280 281 if ((p = strchr (cvsroot_copy, '@'))) 282 { 283 CVSroot_username = cvsroot_copy; 284 *p = '\0'; 285 cvsroot_copy = ++p; 286 if (*CVSroot_username == '\0') 287 CVSroot_username = NULL; 288 } 289 290 if ((p = strchr (cvsroot_copy, ':'))) 291 { 292 CVSroot_hostname = cvsroot_copy; 293 *p = '\0'; 294 cvsroot_copy = ++p; 295 296 if (*CVSroot_hostname == '\0') 297 CVSroot_hostname = NULL; 298 } 299 } 300 301 CVSroot_directory = cvsroot_copy; 302 303 #if ! defined (CLIENT_SUPPORT) && ! defined (DEBUG) 304 if (CVSroot_method != local_method) 305 { 306 error (0, 0, "Your CVSROOT is set for a remote access method"); 307 error (0, 0, "but your CVS executable doesn't support it"); 308 error (0, 0, "(%s)", CVSroot); 309 return 1; 310 } 311 #endif 312 313 /* Do various sanity checks. */ 314 315 if (CVSroot_username && ! CVSroot_hostname) 316 { 317 error (0, 0, "missing hostname in CVSROOT: %s", CVSroot); 318 return 1; 319 } 320 321 switch (CVSroot_method) 322 { 323 case local_method: 324 if (CVSroot_username || CVSroot_hostname) 325 { 326 error (0, 0, "can't specify hostname and username in CVSROOT"); 327 error (0, 0, "when using local access method"); 328 error (0, 0, "(%s)", CVSroot); 329 return 1; 330 } 331 break; 332 case kserver_method: 333 #ifndef HAVE_KERBEROS 334 error (0, 0, "Your CVSROOT is set for a kerberos access method"); 335 error (0, 0, "but your CVS executable doesn't support it"); 336 error (0, 0, "(%s)", CVSroot); 337 return 1; 338 #endif 339 case server_method: 340 case ext_method: 341 case pserver_method: 342 if (! CVSroot_hostname) 343 { 344 error (0, 0, "didn't specify hostname in CVSROOT: %s", CVSroot); 345 return 1; 346 } 347 break; 348 } 349 350 if (*CVSroot_directory == '\0') 351 { 352 error (0, 0, "missing directory in CVSROOT: %s", CVSroot); 353 return 1; 354 } 355 356 /* Hooray! We finally parsed it! */ 357 return 0; 358 } 359 360 361 /* Set up the global CVSroot* variables as if we're using the local 362 repository DIR. */ 363 364 void 365 set_local_cvsroot (dir) 366 char *dir; 367 { 368 CVSroot_original = xstrdup (dir); 369 CVSroot_method = local_method; 370 CVSroot_directory = CVSroot_original; 371 CVSroot_username = NULL; 372 CVSroot_hostname = NULL; 373 client_active = 0; 374 } 375 376 377 #ifdef DEBUG 378 /* This is for testing the parsing function. */ 379 380 #include <stdio.h> 381 382 char *CVSroot; 383 char *program_name = "testing"; 384 char *command_name = "parse_cvsroot"; /* XXX is this used??? */ 385 386 void 387 main (argc, argv) 388 int argc; 389 char *argv[]; 390 { 391 program_name = argv[0]; 392 393 if (argc != 2) 394 { 395 fprintf (stderr, "Usage: %s <CVSROOT>\n", program_name); 396 exit (2); 397 } 398 399 if (parse_cvsroot (argv[1])) 400 { 401 fprintf (stderr, "%s: Parsing failed.", program_name); 402 exit (1); 403 } 404 printf ("CVSroot: %s\n", argv[1]); 405 printf ("CVSroot_method: %s\n", method_names[CVSroot_method]); 406 printf ("CVSroot_username: %s\n", 407 CVSroot_username ? CVSroot_username : "NULL"); 408 printf ("CVSroot_hostname: %s\n", 409 CVSroot_hostname ? CVSroot_hostname : "NULL"); 410 printf ("CVSroot_directory: %s\n", CVSroot_directory); 411 412 exit (0); 413 /* NOTREACHED */ 414 } 415 #endif 416