[BACK]Return to root.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

Annotation of src/usr.bin/cvs/root.c, Revision 1.44

1.44    ! gilles      1: /*     $OpenBSD: root.c,v 1.43 2007/09/10 19:11:08 joris Exp $ */
1.1       jfb         2: /*
                      3:  * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
1.13      tedu        4:  * All rights reserved.
1.1       jfb         5:  *
1.13      tedu        6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
1.1       jfb         9:  *
1.13      tedu       10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
1.1       jfb        12:  * 2. The name of the author may not be used to endorse or promote products
1.13      tedu       13:  *    derived from this software without specific prior written permission.
1.1       jfb        14:  *
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                     16:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                     17:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
                     18:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     19:  * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     20:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     21:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     22:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     23:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
1.13      tedu       24:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1       jfb        25:  */
                     26:
1.36      otto       27: #include <errno.h>
                     28: #include <stdlib.h>
                     29: #include <string.h>
1.1       jfb        30:
                     31: #include "cvs.h"
                     32:
                     33: extern char *cvs_rootstr;
                     34:
                     35: /* keep these ordered with the defines */
                     36: const char *cvs_methods[] = {
                     37:        "",
                     38:        "local",
                     39:        "ssh",
                     40:        "pserver",
                     41:        "kserver",
                     42:        "gserver",
                     43:        "ext",
                     44:        "fork",
                     45: };
                     46:
1.20      xsa        47: #define CVS_NBMETHODS  (sizeof(cvs_methods)/sizeof(cvs_methods[0]))
1.6       jfb        48:
                     49: /*
1.1       jfb        50:  * cvsroot_parse()
                     51:  *
                     52:  * Parse a CVS root string (as found in CVS/Root files or the CVSROOT
                     53:  * environment variable) and store the fields in a dynamically
                     54:  * allocated cvs_root structure.  The format of the string is as follows:
1.39      xsa        55:  *     [:method:][[user[:pass]@]host[:port]:]path
1.1       jfb        56:  * Returns a pointer to the allocated information on success, or NULL
                     57:  * on failure.
                     58:  */
1.40      joris      59: static struct cvsroot *
1.1       jfb        60: cvsroot_parse(const char *str)
                     61: {
                     62:        u_int i;
                     63:        char *cp, *sp, *pp;
1.37      xsa        64:        const char *errstr;
1.40      joris      65:        static struct cvsroot *root = NULL;
1.1       jfb        66:
1.40      joris      67:        if (root != NULL)
                     68:                return (root);
1.6       jfb        69:
1.31      ray        70:        root = xcalloc(1, sizeof(*root));
1.1       jfb        71:        root->cr_method = CVS_METHOD_NONE;
1.10      jfb        72:        CVS_RSTVR(root);
1.1       jfb        73:
1.26      joris      74:        root->cr_str = xstrdup(str);
                     75:        root->cr_buf = xstrdup(str);
1.1       jfb        76:
                     77:        sp = root->cr_buf;
                     78:        cp = root->cr_buf;
                     79:        if (*sp == ':') {
                     80:                sp++;
1.27      xsa        81:                if ((cp = strchr(sp, ':')) == NULL)
                     82:                        fatal("failed to parse CVSROOT: unterminated method");
                     83:
1.1       jfb        84:                *(cp++) = '\0';
                     85:
                     86:                for (i = 0; i < CVS_NBMETHODS; i++) {
                     87:                        if (strcmp(sp, cvs_methods[i]) == 0) {
                     88:                                root->cr_method = i;
                     89:                                break;
                     90:                        }
1.14      jfb        91:                }
1.27      xsa        92:                if (i == CVS_NBMETHODS)
                     93:                        fatal("cvsroot_parse: unknown method `%s'", sp);
1.1       jfb        94:        }
                     95:
                     96:        /* find the start of the actual path */
1.27      xsa        97:        if ((sp = strchr(cp, '/')) == NULL)
                     98:                fatal("no path specification in CVSROOT");
1.1       jfb        99:
                    100:        root->cr_dir = sp;
1.32      joris     101:        STRIP_SLASH(root->cr_dir);
1.1       jfb       102:        if (sp == cp) {
                    103:                if (root->cr_method == CVS_METHOD_NONE)
                    104:                        root->cr_method = CVS_METHOD_LOCAL;
                    105:                /* stop here, it's just a path */
                    106:                return (root);
                    107:        }
                    108:
1.27      xsa       109:        if (*(sp - 1) != ':')
                    110:                fatal("missing host/path delimiter in CVSROOT");
                    111:
1.1       jfb       112:        *(sp - 1) = '\0';
                    113:
                    114:        /*
                    115:         * looks like we have more than just a directory path, so
                    116:         * attempt to split it into user and host parts
                    117:         */
                    118:        sp = strchr(cp, '@');
                    119:        if (sp != NULL) {
                    120:                *(sp++) = '\0';
                    121:
                    122:                /* password ? */
                    123:                pp = strchr(cp, ':');
                    124:                if (pp != NULL) {
                    125:                        *(pp++) = '\0';
                    126:                        root->cr_pass = pp;
                    127:                }
                    128:
                    129:                root->cr_user = cp;
1.12      deraadt   130:        } else
1.11      jfb       131:                sp = cp;
1.1       jfb       132:
                    133:        pp = strchr(sp, ':');
                    134:        if (pp != NULL) {
                    135:                *(pp++) = '\0';
1.43      joris     136:                root->cr_port = strtonum(pp, 1, 65535, &errstr);
1.37      xsa       137:                if (errstr != NULL)
                    138:                        fatal("port specification in CVSROOT is %s", errstr);
1.1       jfb       139:
                    140:        }
                    141:
                    142:        root->cr_host = sp;
                    143:
                    144:        if (root->cr_method == CVS_METHOD_NONE) {
                    145:                /* no method found from start of CVSROOT, guess */
                    146:                if (root->cr_host != NULL)
                    147:                        root->cr_method = CVS_METHOD_SERVER;
                    148:                else
                    149:                        root->cr_method = CVS_METHOD_LOCAL;
                    150:        }
                    151:
                    152:        return (root);
1.25      joris     153: }
1.1       jfb       154:
                    155: /*
                    156:  * cvsroot_get()
                    157:  *
                    158:  * Get the CVSROOT information for a specific directory <dir>.  The
                    159:  * value is taken from one of 3 possible sources (in order of precedence):
                    160:  *
                    161:  * 1) the `-d' command-line option
                    162:  * 2) the CVS/Root file found in checked-out trees
                    163:  * 3) the CVSROOT environment variable
                    164:  */
1.21      xsa       165: struct cvsroot *
1.1       jfb       166: cvsroot_get(const char *dir)
                    167: {
1.5       jfb       168:        char rootpath[MAXPATHLEN], *rootstr, line[128];
1.1       jfb       169:        FILE *fp;
                    170:
                    171:        if (cvs_rootstr != NULL)
                    172:                return cvsroot_parse(cvs_rootstr);
1.41      tobias    173:
                    174:        if (cvs_server_active == 1)
                    175:                return cvsroot_parse(dir);
1.1       jfb       176:
1.35      xsa       177:        (void)xsnprintf(rootpath, MAXPATHLEN, "%s/%s", dir, CVS_PATH_ROOTSPEC);
1.16      xsa       178:
1.27      xsa       179:        if ((fp = fopen(rootpath, "r")) == NULL) {
1.1       jfb       180:                if (errno == ENOENT) {
                    181:                        /* try env as a last resort */
                    182:                        if ((rootstr = getenv("CVSROOT")) != NULL)
                    183:                                return cvsroot_parse(rootstr);
                    184:                        else
1.32      joris     185:                                return (NULL);
1.12      deraadt   186:                } else {
1.27      xsa       187:                        fatal("cvsroot_get: fopen: `%s': %s",
                    188:                            CVS_PATH_ROOTSPEC, strerror(errno));
1.1       jfb       189:                }
                    190:        }
                    191:
1.27      xsa       192:        if (fgets(line, (int)sizeof(line), fp) == NULL)
                    193:                fatal("cvsroot_get: fgets: `%s'", CVS_PATH_ROOTSPEC);
                    194:
1.5       jfb       195:        (void)fclose(fp);
1.1       jfb       196:
1.44    ! gilles    197:        line[strcspn(line, "\n")] = '\0';
        !           198:        if (line[0] == '\0')
1.32      joris     199:                cvs_log(LP_ERR, "empty %s file", CVS_PATH_ROOTSPEC);
1.1       jfb       200:
1.5       jfb       201:        return cvsroot_parse(line);
1.1       jfb       202: }