1/****************************************************************************
2 * Copyright (c) 1998-2011,2012 Free Software Foundation, Inc.              *
3 *                                                                          *
4 * Permission is hereby granted, free of charge, to any person obtaining a  *
5 * copy of this software and associated documentation files (the            *
6 * "Software"), to deal in the Software without restriction, including      *
7 * without limitation the rights to use, copy, modify, merge, publish,      *
8 * distribute, distribute with modifications, sublicense, and/or sell       *
9 * copies of the Software, and to permit persons to whom the Software is    *
10 * furnished to do so, subject to the following conditions:                 *
11 *                                                                          *
12 * The above copyright notice and this permission notice shall be included  *
13 * in all copies or substantial portions of the Software.                   *
14 *                                                                          *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
22 *                                                                          *
23 * Except as contained in this notice, the name(s) of the above copyright   *
24 * holders shall not be used in advertising or otherwise to promote the     *
25 * sale, use or other dealings in this Software without prior written       *
26 * authorization.                                                           *
27 ****************************************************************************/
28
29/****************************************************************************
30 *  Author: Thomas E. Dickey                                                *
31 ****************************************************************************/
32
33#include <curses.priv.h>
34
35#include <ctype.h>
36
37#include <tic.h>
38
39MODULE_ID("$Id: access.c,v 1.23 2012/09/01 19:21:29 tom Exp $")
40
41#ifdef __TANDEM
42#define ROOT_UID 65535
43#endif
44
45#ifndef ROOT_UID
46#define ROOT_UID 0
47#endif
48
49#define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
50
51NCURSES_EXPORT(char *)
52_nc_rootname(char *path)
53{
54    char *result = _nc_basename(path);
55#if !MIXEDCASE_FILENAMES || defined(PROG_EXT)
56    static char *temp;
57    char *s;
58
59    temp = strdup(result);
60    result = temp;
61#if !MIXEDCASE_FILENAMES
62    for (s = result; *s != '\0'; ++s) {
63	*s = (char) LOWERCASE(*s);
64    }
65#endif
66#if defined(PROG_EXT)
67    if ((s = strrchr(result, '.')) != 0) {
68	if (!strcmp(s, PROG_EXT))
69	    *s = '\0';
70    }
71#endif
72#endif
73    return result;
74}
75
76/*
77 * Check if a string appears to be an absolute pathname.
78 */
79NCURSES_EXPORT(bool)
80_nc_is_abs_path(const char *path)
81{
82#if defined(__EMX__) || defined(__DJGPP__)
83#define is_pathname(s) ((((s) != 0) && ((s)[0] == '/')) \
84		  || (((s)[0] != 0) && ((s)[1] == ':')))
85#else
86#define is_pathname(s) ((s) != 0 && (s)[0] == '/')
87#endif
88    return is_pathname(path);
89}
90
91/*
92 * Return index of the basename
93 */
94NCURSES_EXPORT(unsigned)
95_nc_pathlast(const char *path)
96{
97    const char *test = strrchr(path, '/');
98#ifdef __EMX__
99    if (test == 0)
100	test = strrchr(path, '\\');
101#endif
102    if (test == 0)
103	test = path;
104    else
105	test++;
106    return (unsigned) (test - path);
107}
108
109NCURSES_EXPORT(char *)
110_nc_basename(char *path)
111{
112    return path + _nc_pathlast(path);
113}
114
115NCURSES_EXPORT(int)
116_nc_access(const char *path, int mode)
117{
118    int result;
119
120    if (path == 0) {
121	result = -1;
122    } else if (access(path, mode) < 0) {
123	if ((mode & W_OK) != 0
124	    && errno == ENOENT
125	    && strlen(path) < PATH_MAX) {
126	    char head[PATH_MAX];
127	    char *leaf;
128
129	    _nc_STRCPY(head, path, sizeof(head));
130	    leaf = _nc_basename(head);
131	    if (leaf == 0)
132		leaf = head;
133	    *leaf = '\0';
134	    if (head == leaf)
135		_nc_STRCPY(head, ".", sizeof(head));
136
137	    result = access(head, R_OK | W_OK | X_OK);
138	} else {
139	    result = -1;
140	}
141    } else {
142	result = 0;
143    }
144    return result;
145}
146
147NCURSES_EXPORT(bool)
148_nc_is_dir_path(const char *path)
149{
150    bool result = FALSE;
151    struct stat sb;
152
153    if (stat(path, &sb) == 0
154	&& S_ISDIR(sb.st_mode)) {
155	result = TRUE;
156    }
157    return result;
158}
159
160NCURSES_EXPORT(bool)
161_nc_is_file_path(const char *path)
162{
163    bool result = FALSE;
164    struct stat sb;
165
166    if (stat(path, &sb) == 0
167	&& S_ISREG(sb.st_mode)) {
168	result = TRUE;
169    }
170    return result;
171}
172
173#ifndef USE_ROOT_ENVIRON
174/*
175 * Returns true if we allow application to use environment variables that are
176 * used for searching lists of directories, etc.
177 */
178NCURSES_EXPORT(int)
179_nc_env_access(void)
180{
181#if HAVE_ISSETUGID
182    if (issetugid())
183	return FALSE;
184#elif HAVE_GETEUID && HAVE_GETEGID
185    if (getuid() != geteuid()
186	|| getgid() != getegid())
187	return FALSE;
188#endif
189    /* ...finally, disallow root */
190    return (getuid() != ROOT_UID) && (geteuid() != ROOT_UID);
191}
192#endif
193