home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / cvs-1.8.7-src.tgz / tar.out / fsf / cvs / src / root.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  10KB  |  408 lines

  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"
  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
  248.     {
  249.         error (0, 0, "unknown method in CVSroot: %s", CVSroot);
  250.         return 1;
  251.     }
  252.     }
  253.     else
  254.     {
  255.     /* If the method isn't specified, assume SERVER_METHOD if the
  256.        string contains a colon or LOCAL_METHOD otherwise. */
  257.  
  258.     CVSroot_method = ((strchr (cvsroot_copy, ':'))
  259.               ? server_method
  260.               : local_method);
  261.     }
  262.  
  263.     client_active = (CVSroot_method != local_method);
  264.  
  265.     /* Check for username/hostname if we're not LOCAL_METHOD. */
  266.  
  267.     CVSroot_username = NULL;
  268.     CVSroot_hostname = NULL;
  269.  
  270.     if (CVSroot_method != local_method)
  271.     {
  272.     /* Check to see if there is a username in the string. */
  273.  
  274.     if ((p = strchr (cvsroot_copy, '@')))
  275.     {
  276.         CVSroot_username = cvsroot_copy;
  277.         *p = '\0';
  278.         cvsroot_copy = ++p;
  279.         if (*CVSroot_username == '\0')
  280.         CVSroot_username = NULL;
  281.     }
  282.  
  283.     if ((p = strchr (cvsroot_copy, ':')))
  284.     {
  285.         CVSroot_hostname = cvsroot_copy;
  286.         *p = '\0';
  287.         cvsroot_copy = ++p;
  288.       
  289.         if (*CVSroot_hostname == '\0')
  290.         CVSroot_hostname = NULL;
  291.     }
  292.     }
  293.  
  294.     CVSroot_directory = cvsroot_copy;
  295.  
  296. #if ! defined (CLIENT_SUPPORT) && ! defined (DEBUG)
  297.     if (CVSroot_method != local_method)
  298.     {
  299.     error (0, 0, "Your CVSROOT is set for a remote access method");
  300.     error (0, 0, "but your CVS executable doesn't support it");
  301.     error (0, 0, "(%s)", CVSroot);
  302.     return 1;
  303.     }
  304. #endif
  305.   
  306.     /* Do various sanity checks. */
  307.  
  308.     if (CVSroot_username && ! CVSroot_hostname)
  309.     {
  310.     error (0, 0, "missing hostname in CVSROOT: %s", CVSroot);
  311.     return 1;
  312.     }
  313.  
  314.     switch (CVSroot_method)
  315.     {
  316.     case local_method:
  317.     if (CVSroot_username || CVSroot_hostname)
  318.     {
  319.         error (0, 0, "can't specify hostname and username in CVSROOT");
  320.         error (0, 0, "when using local access method");
  321.         error (0, 0, "(%s)", CVSroot);
  322.         return 1;
  323.     }
  324.     break;
  325.     case kserver_method:
  326. #ifndef HAVE_KERBEROS
  327.     error (0, 0, "Your CVSROOT is set for a kerberos access method");
  328.     error (0, 0, "but your CVS executable doesn't support it");
  329.     error (0, 0, "(%s)", CVSroot);
  330.     return 1;
  331. #endif
  332.     case server_method:
  333.     case pserver_method:
  334.     if (! CVSroot_hostname)
  335.     {
  336.         error (0, 0, "didn't specify hostname in CVSROOT: %s", CVSroot);
  337.         return 1;
  338.     }
  339.     break;
  340.     }
  341.  
  342.     if (*CVSroot_directory == '\0')
  343.     {
  344.     error (0, 0, "missing directory in CVSROOT: %s", CVSroot);
  345.     return 1;
  346.     }
  347.     
  348.     /* Hooray!  We finally parsed it! */
  349.     return 0;
  350. }
  351.  
  352.  
  353. /* Set up the global CVSroot* variables as if we're using the local
  354.    repository DIR. */
  355.  
  356. void
  357. set_local_cvsroot (dir)
  358.     char *dir;
  359. {
  360.     CVSroot_original = xstrdup (dir);
  361.     CVSroot_method = local_method;
  362.     CVSroot_directory = CVSroot_original;
  363.     CVSroot_username = NULL;
  364.     CVSroot_hostname = NULL;
  365.     client_active = 0;
  366. }
  367.  
  368.  
  369. #ifdef DEBUG
  370. /* This is for testing the parsing function. */
  371.  
  372. #include <stdio.h>
  373.  
  374. char *CVSroot;
  375. char *program_name = "testing";
  376. char *command_name = "parse_cvsroot";        /* XXX is this used??? */
  377.  
  378. void
  379. main (argc, argv)
  380.     int argc;
  381.     char *argv[];
  382. {
  383.     program_name = argv[0];
  384.  
  385.     if (argc != 2)
  386.     {
  387.     fprintf (stderr, "Usage: %s <CVSROOT>\n", program_name);
  388.     exit (2);
  389.     }
  390.   
  391.     if (parse_cvsroot (argv[1]))
  392.     {
  393.     fprintf (stderr, "%s: Parsing failed.", program_name);
  394.     exit (1);
  395.     }
  396.     printf ("CVSroot: %s\n", argv[1]);
  397.     printf ("CVSroot_method: %s\n", method_names[CVSroot_method]);
  398.     printf ("CVSroot_username: %s\n",
  399.         CVSroot_username ? CVSroot_username : "NULL");
  400.     printf ("CVSroot_hostname: %s\n",
  401.         CVSroot_hostname ? CVSroot_hostname : "NULL");
  402.     printf ("CVSroot_directory: %s\n", CVSroot_directory);
  403.  
  404.    exit (0);
  405.    /* NOTREACHED */
  406. }
  407. #endif
  408.