OSSP CVS Repository

ossp - ossp-pkg/path/path_self.c 1.1
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/path/path_self.c 1.1
/*
**  OSSP path - Filesystem Path Manipulation
**  Copyright (c) 2002 Ralf S. Engelschall <rse@engelschall.com>
**  Copyright (c) 2002 The OSSP Project <http://www.ossp.org/>
**  Copyright (c) 2002 Cable & Wireless Deutschland <http://www.cw.com/de/>
**
**  This file is part of OSSP path, a filesystem path manipulation library
**  which can be found at http://www.ossp.org/pkg/lib/path/.
**
**  Permission to use, copy, modify, and distribute this software for
**  any purpose with or without fee is hereby granted, provided that
**  the above copyright notice and this permission notice appear in all
**  copies.
**
**  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
**  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
**  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
**  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
**  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
**  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
**  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
**  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
**  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
**  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
**  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
**  SUCH DAMAGE.
**
**  path_self.c: resolve path to current program
*/

#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include "path.h"

#define PATH_DEFAULT "/bin:/sbin:/usr/bin:/usr/sbin:."

path_rc_t path_self(char *res_buf, size_t res_size, const char *argv0)
{
    char *path;
    size_t l;
    struct stat sb;
    char *cpB, *cpE;
    size_t argv0_len;

    if (res_buf == NULL || res_size == 0 || argv0 == NULL)
        return PATH_ERR_ARG;

    /* determine length of argv[0] */
    argv0_len = strlen(argv0);

    /* short-circuit if argv[0] already contains an absolute path */
    if (argv0[0] == '/') {
        if (argv0_len > res_size-1)
            return PATH_ERR_MEM;
        memcpy(res_buf, argv0, argv0_len);
        res_buf[argv0_len] = '\0';
        if (path_resolve(res_buf, res_size, res_buf) == NULL)
            return PATH_ERR_SYS;
        return PATH_OK;
    }

    /* short-circuit if argv[0] already contains a relative path */
    if (argv0[0] == '.') {
        if (getcwd(res_buf, res_size) == NULL)
            return PATH_ERR_SYS;
        l = strlen(res_buf);
        if (res_buf[l-1] == '/')
            l--;
        if (l+1+argv0_len+1 > res_size)
            return PATH_ERR_MEM;
        res_buf[l++] = '/';
        memcpy(res_buf+l, argv0, argv0_len);
        res_buf[l+argv0_len] = '\0';
        if (path_resolve(res_buf, res_size, res_buf) == NULL)
            return PATH_ERR_SYS;
        return PATH_OK;
    }

    /* else search argv[0] in $PATH */
    if ((path = getenv("PATH")) == NULL)
        path = PATH_DEFAULT;
    cpE = path;
    cpB = cpE;
    while (*cpE != '\0') {
        if ((cpE = strchr(cpB, ':')) == NULL)
            cpE = strchr(cpB, '\0');
        if ((l = cpE-cpB) > 0) {
            if (cpB[l-1] == '/')
                l--;
            if (l+1+argv0_len+1 <= res_size) {
                memcpy(res_buf, cpB, l);
                res_buf[l++] = '/';
                memcpy(res_buf+l, argv0, argv0_len);
                res_buf[l+argv0_len] = '\0';
                if (stat(res_buf, &sb) == 0) {
                    if (path_resolve(res_buf, res_size, res_buf) == NULL)
                        return PATH_ERR_SYS;
                    return PATH_OK;
                }
            }
        }
        if (*cpE == '\0')
            break;
        cpB = cpE+1;
    }

    return PATH_ERR_NFD;
}


CVSTrac 2.0.1