155682Smarkm/*
2178825Sdfr * Copyright (c) 1995 - 2000, 2002, 2004, 2005 Kungliga Tekniska H�gskolan
355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden).
455682Smarkm * All rights reserved.
555682Smarkm *
655682Smarkm * Redistribution and use in source and binary forms, with or without
755682Smarkm * modification, are permitted provided that the following conditions
855682Smarkm * are met:
955682Smarkm *
1055682Smarkm * 1. Redistributions of source code must retain the above copyright
1155682Smarkm *    notice, this list of conditions and the following disclaimer.
1255682Smarkm *
1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1455682Smarkm *    notice, this list of conditions and the following disclaimer in the
1555682Smarkm *    documentation and/or other materials provided with the distribution.
1655682Smarkm *
1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors
1855682Smarkm *    may be used to endorse or promote products derived from this software
1955682Smarkm *    without specific prior written permission.
2055682Smarkm *
2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2455682Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3155682Smarkm * SUCH DAMAGE.
3255682Smarkm */
3355682Smarkm
3455682Smarkm#include "kafs_locl.h"
3555682Smarkm
36178825SdfrRCSID("$Id: afssys.c 17050 2006-04-11 08:12:29Z lha $");
3755682Smarkm
38142403Snectarstruct procdata {
39142403Snectar    unsigned long param4;
40142403Snectar    unsigned long param3;
41142403Snectar    unsigned long param2;
42142403Snectar    unsigned long param1;
43142403Snectar    unsigned long syscall;
44142403Snectar};
45178825Sdfr#define VIOC_SYSCALL_PROC _IOW('C', 1, void *)
46142403Snectar
47178825Sdfrstruct devdata {
48178825Sdfr    unsigned long syscall;
49178825Sdfr    unsigned long param1;
50178825Sdfr    unsigned long param2;
51178825Sdfr    unsigned long param3;
52178825Sdfr    unsigned long param4;
53178825Sdfr    unsigned long param5;
54178825Sdfr    unsigned long param6;
55178825Sdfr    unsigned long retval;
56178825Sdfr};
57178825Sdfr#define VIOC_SYSCALL_DEV _IOWR('C', 2, struct devdata)
58178825Sdfr#define VIOC_SYSCALL_DEV_OPENAFS _IOWR('C', 1, struct devdata)
59142403Snectar
60178825Sdfr
6155682Smarkmint _kafs_debug; /* this should be done in a better way */
6255682Smarkm
63178825Sdfr#define UNKNOWN_ENTRY_POINT	(-1)
6455682Smarkm#define NO_ENTRY_POINT		0
6555682Smarkm#define SINGLE_ENTRY_POINT	1
6655682Smarkm#define MULTIPLE_ENTRY_POINT	2
6755682Smarkm#define SINGLE_ENTRY_POINT2	3
6855682Smarkm#define SINGLE_ENTRY_POINT3	4
69142403Snectar#define LINUX_PROC_POINT	5
70142403Snectar#define AIX_ENTRY_POINTS	6
71178825Sdfr#define MACOS_DEV_POINT		7
72178825Sdfr
7355682Smarkmstatic int afs_entry_point = UNKNOWN_ENTRY_POINT;
7455682Smarkmstatic int afs_syscalls[2];
75178825Sdfrstatic char *afs_ioctlpath;
76178825Sdfrstatic unsigned long afs_ioctlnum;
7755682Smarkm
7855682Smarkm/* Magic to get AIX syscalls to work */
7955682Smarkm#ifdef _AIX
8055682Smarkm
8155682Smarkmstatic int (*Pioctl)(char*, int, struct ViceIoctl*, int);
8255682Smarkmstatic int (*Setpag)(void);
8355682Smarkm
8455682Smarkm#include "dlfcn.h"
8555682Smarkm
8655682Smarkm/*
8755682Smarkm *
8855682Smarkm */
8955682Smarkm
9055682Smarkmstatic int
9155682Smarkmtry_aix(void)
9255682Smarkm{
9355682Smarkm#ifdef STATIC_AFS_SYSCALLS
9455682Smarkm    Pioctl = aix_pioctl;
9555682Smarkm    Setpag = aix_setpag;
9655682Smarkm#else
9755682Smarkm    void *ptr;
9855682Smarkm    char path[MaxPathLen], *p;
9955682Smarkm    /*
10055682Smarkm     * If we are root or running setuid don't trust AFSLIBPATH!
10155682Smarkm     */
10255682Smarkm    if (getuid() != 0 && !issuid() && (p = getenv("AFSLIBPATH")) != NULL)
10355682Smarkm	strlcpy(path, p, sizeof(path));
10455682Smarkm    else
10555682Smarkm	snprintf(path, sizeof(path), "%s/afslib.so", LIBDIR);
10655682Smarkm
10755682Smarkm    ptr = dlopen(path, RTLD_NOW);
10855682Smarkm    if(ptr == NULL) {
10955682Smarkm	if(_kafs_debug) {
11055682Smarkm	    if(errno == ENOEXEC && (p = dlerror()) != NULL)
11155682Smarkm		fprintf(stderr, "dlopen(%s): %s\n", path, p);
11255682Smarkm	    else if (errno != ENOENT)
11355682Smarkm		fprintf(stderr, "dlopen(%s): %s\n", path, strerror(errno));
11455682Smarkm	}
11555682Smarkm	return 1;
11655682Smarkm    }
11755682Smarkm    Setpag = (int (*)(void))dlsym(ptr, "aix_setpag");
11855682Smarkm    Pioctl = (int (*)(char*, int,
11955682Smarkm		      struct ViceIoctl*, int))dlsym(ptr, "aix_pioctl");
12055682Smarkm#endif
12155682Smarkm    afs_entry_point = AIX_ENTRY_POINTS;
12255682Smarkm    return 0;
12355682Smarkm}
12455682Smarkm#endif /* _AIX */
12555682Smarkm
12655682Smarkm/*
12755682Smarkm * This probably only works under Solaris and could get confused if
12855682Smarkm * there's a /etc/name_to_sysnum file.
12955682Smarkm */
13055682Smarkm
131178825Sdfr#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
132178825Sdfr
13355682Smarkm#define _PATH_ETC_NAME_TO_SYSNUM "/etc/name_to_sysnum"
13455682Smarkm
13555682Smarkmstatic int
13655682Smarkmmap_syscall_name_to_number (const char *str, int *res)
13755682Smarkm{
13855682Smarkm    FILE *f;
13955682Smarkm    char buf[256];
14055682Smarkm    size_t str_len = strlen (str);
14155682Smarkm
14255682Smarkm    f = fopen (_PATH_ETC_NAME_TO_SYSNUM, "r");
14355682Smarkm    if (f == NULL)
14455682Smarkm	return -1;
14555682Smarkm    while (fgets (buf, sizeof(buf), f) != NULL) {
14672445Sassar	if (buf[0] == '#')
14772445Sassar	    continue;
14872445Sassar
14955682Smarkm	if (strncmp (str, buf, str_len) == 0) {
15055682Smarkm	    char *begptr = buf + str_len;
15155682Smarkm	    char *endptr;
15255682Smarkm	    long val = strtol (begptr, &endptr, 0);
15355682Smarkm
15455682Smarkm	    if (val != 0 && endptr != begptr) {
15555682Smarkm		fclose (f);
15655682Smarkm		*res = val;
15755682Smarkm		return 0;
15855682Smarkm	    }
15955682Smarkm	}
16055682Smarkm    }
16155682Smarkm    fclose (f);
16255682Smarkm    return -1;
16355682Smarkm}
164178825Sdfr#endif
16555682Smarkm
166142403Snectarstatic int
167178825Sdfrtry_ioctlpath(const char *path, unsigned long ioctlnum, int entrypoint)
168142403Snectar{
169178825Sdfr    int fd, ret, saved_errno;
170178825Sdfr
171142403Snectar    fd = open(path, O_RDWR);
172142403Snectar    if (fd < 0)
173142403Snectar	return 1;
174178825Sdfr    switch (entrypoint) {
175178825Sdfr    case LINUX_PROC_POINT: {
176178825Sdfr	struct procdata data = { 0, 0, 0, 0, AFSCALL_PIOCTL };
177178825Sdfr	data.param2 = (unsigned long)VIOCGETTOK;
178178825Sdfr	ret = ioctl(fd, ioctlnum, &data);
179178825Sdfr	break;
180178825Sdfr    }
181178825Sdfr    case MACOS_DEV_POINT: {
182178825Sdfr	struct devdata data = { AFSCALL_PIOCTL, 0, 0, 0, 0, 0, 0, 0 };
183178825Sdfr	data.param2 = (unsigned long)VIOCGETTOK;
184178825Sdfr	ret = ioctl(fd, ioctlnum, &data);
185178825Sdfr	break;
186178825Sdfr    }
187178825Sdfr    default:
188178825Sdfr	abort();
189178825Sdfr    }
190178825Sdfr    saved_errno = errno;
191142403Snectar    close(fd);
192178825Sdfr    /*
193178825Sdfr     * Be quite liberal in what error are ok, the first is the one
194178825Sdfr     * that should trigger given that params is NULL.
195178825Sdfr     */
196178825Sdfr    if (ret &&
197178825Sdfr	(saved_errno != EFAULT &&
198178825Sdfr	 saved_errno != EDOM &&
199178825Sdfr	 saved_errno != ENOTCONN))
200142403Snectar	return 1;
201178825Sdfr    afs_ioctlnum = ioctlnum;
202178825Sdfr    afs_ioctlpath = strdup(path);
203178825Sdfr    if (afs_ioctlpath == NULL)
204178825Sdfr	return 1;
205178825Sdfr    afs_entry_point = entrypoint;
206142403Snectar    return 0;
207142403Snectar}
208142403Snectar
209142403Snectarstatic int
210178825Sdfrdo_ioctl(void *data)
211142403Snectar{
212142403Snectar    int fd, ret, saved_errno;
213178825Sdfr    fd = open(afs_ioctlpath, O_RDWR);
214142403Snectar    if (fd < 0) {
215142403Snectar	errno = EINVAL;
216142403Snectar	return -1;
217142403Snectar    }
218178825Sdfr    ret = ioctl(fd, afs_ioctlnum, data);
219142403Snectar    saved_errno = errno;
220142403Snectar    close(fd);
221142403Snectar    errno = saved_errno;
222142403Snectar    return ret;
223142403Snectar}
224142403Snectar
22555682Smarkmint
22655682Smarkmk_pioctl(char *a_path,
22755682Smarkm	 int o_opcode,
22855682Smarkm	 struct ViceIoctl *a_paramsP,
22955682Smarkm	 int a_followSymlinks)
23055682Smarkm{
23155682Smarkm#ifndef NO_AFS
23255682Smarkm    switch(afs_entry_point){
23355682Smarkm#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
23455682Smarkm    case SINGLE_ENTRY_POINT:
23555682Smarkm    case SINGLE_ENTRY_POINT2:
23655682Smarkm    case SINGLE_ENTRY_POINT3:
23755682Smarkm	return syscall(afs_syscalls[0], AFSCALL_PIOCTL,
23855682Smarkm		       a_path, o_opcode, a_paramsP, a_followSymlinks);
23955682Smarkm#endif
24055682Smarkm#if defined(AFS_PIOCTL)
24155682Smarkm    case MULTIPLE_ENTRY_POINT:
24255682Smarkm	return syscall(afs_syscalls[0],
24355682Smarkm		       a_path, o_opcode, a_paramsP, a_followSymlinks);
24455682Smarkm#endif
245142403Snectar    case LINUX_PROC_POINT: {
246142403Snectar	struct procdata data = { 0, 0, 0, 0, AFSCALL_PIOCTL };
247142403Snectar	data.param1 = (unsigned long)a_path;
248142403Snectar	data.param2 = (unsigned long)o_opcode;
249142403Snectar	data.param3 = (unsigned long)a_paramsP;
250142403Snectar	data.param4 = (unsigned long)a_followSymlinks;
251178825Sdfr	return do_ioctl(&data);
252142403Snectar    }
253178825Sdfr    case MACOS_DEV_POINT: {
254178825Sdfr	struct devdata data = { AFSCALL_PIOCTL, 0, 0, 0, 0, 0, 0, 0 };
255178825Sdfr	int ret;
256178825Sdfr
257178825Sdfr	data.param1 = (unsigned long)a_path;
258178825Sdfr	data.param2 = (unsigned long)o_opcode;
259178825Sdfr	data.param3 = (unsigned long)a_paramsP;
260178825Sdfr	data.param4 = (unsigned long)a_followSymlinks;
261178825Sdfr
262178825Sdfr	ret = do_ioctl(&data);
263178825Sdfr	if (ret)
264178825Sdfr	    return ret;
265178825Sdfr
266178825Sdfr	return data.retval;
267178825Sdfr    }
26855682Smarkm#ifdef _AIX
26955682Smarkm    case AIX_ENTRY_POINTS:
27055682Smarkm	return Pioctl(a_path, o_opcode, a_paramsP, a_followSymlinks);
27155682Smarkm#endif
272142403Snectar    }
27355682Smarkm    errno = ENOSYS;
27455682Smarkm#ifdef SIGSYS
275120945Snectar    kill(getpid(), SIGSYS);	/* You lose! */
27655682Smarkm#endif
27755682Smarkm#endif /* NO_AFS */
27855682Smarkm    return -1;
27955682Smarkm}
28055682Smarkm
28155682Smarkmint
28255682Smarkmk_afs_cell_of_file(const char *path, char *cell, int len)
28355682Smarkm{
28455682Smarkm    struct ViceIoctl parms;
28555682Smarkm    parms.in = NULL;
28655682Smarkm    parms.in_size = 0;
28755682Smarkm    parms.out = cell;
28855682Smarkm    parms.out_size = len;
289178825Sdfr    return k_pioctl(rk_UNCONST(path), VIOC_FILE_CELL_NAME, &parms, 1);
29055682Smarkm}
29155682Smarkm
29255682Smarkmint
29355682Smarkmk_unlog(void)
29455682Smarkm{
29555682Smarkm    struct ViceIoctl parms;
29655682Smarkm    memset(&parms, 0, sizeof(parms));
29755682Smarkm    return k_pioctl(0, VIOCUNLOG, &parms, 0);
29855682Smarkm}
29955682Smarkm
30055682Smarkmint
30155682Smarkmk_setpag(void)
30255682Smarkm{
30355682Smarkm#ifndef NO_AFS
30455682Smarkm    switch(afs_entry_point){
30555682Smarkm#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
30655682Smarkm    case SINGLE_ENTRY_POINT:
30755682Smarkm    case SINGLE_ENTRY_POINT2:
30855682Smarkm    case SINGLE_ENTRY_POINT3:
30955682Smarkm	return syscall(afs_syscalls[0], AFSCALL_SETPAG);
31055682Smarkm#endif
31155682Smarkm#if defined(AFS_PIOCTL)
31255682Smarkm    case MULTIPLE_ENTRY_POINT:
31355682Smarkm	return syscall(afs_syscalls[1]);
31455682Smarkm#endif
315142403Snectar    case LINUX_PROC_POINT: {
316142403Snectar	struct procdata data = { 0, 0, 0, 0, AFSCALL_SETPAG };
317178825Sdfr	return do_ioctl(&data);
318142403Snectar    }
319178825Sdfr    case MACOS_DEV_POINT: {
320178825Sdfr	struct devdata data = { AFSCALL_SETPAG, 0, 0, 0, 0, 0, 0, 0 };
321178825Sdfr	int ret = do_ioctl(&data);
322178825Sdfr	if (ret)
323178825Sdfr	    return ret;
324178825Sdfr	return data.retval;
325178825Sdfr     }
32655682Smarkm#ifdef _AIX
32755682Smarkm    case AIX_ENTRY_POINTS:
32855682Smarkm	return Setpag();
32955682Smarkm#endif
33055682Smarkm    }
33155682Smarkm
33255682Smarkm    errno = ENOSYS;
33355682Smarkm#ifdef SIGSYS
334120945Snectar    kill(getpid(), SIGSYS);	/* You lose! */
33555682Smarkm#endif
33655682Smarkm#endif /* NO_AFS */
33755682Smarkm    return -1;
33855682Smarkm}
33955682Smarkm
34055682Smarkmstatic jmp_buf catch_SIGSYS;
34155682Smarkm
34255682Smarkm#ifdef SIGSYS
34355682Smarkm
34455682Smarkmstatic RETSIGTYPE
34555682SmarkmSIGSYS_handler(int sig)
34655682Smarkm{
34755682Smarkm    errno = 0;
34855682Smarkm    signal(SIGSYS, SIGSYS_handler); /* Need to reinstall handler on SYSV */
34955682Smarkm    longjmp(catch_SIGSYS, 1);
35055682Smarkm}
35155682Smarkm
35255682Smarkm#endif
35355682Smarkm
35455682Smarkm/*
35555682Smarkm * Try to see if `syscall' is a pioctl.  Return 0 iff succesful.
35655682Smarkm */
35755682Smarkm
35855682Smarkm#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
35955682Smarkmstatic int
36055682Smarkmtry_one (int syscall_num)
36155682Smarkm{
36255682Smarkm    struct ViceIoctl parms;
36355682Smarkm    memset(&parms, 0, sizeof(parms));
36455682Smarkm
36555682Smarkm    if (setjmp(catch_SIGSYS) == 0) {
36655682Smarkm	syscall(syscall_num, AFSCALL_PIOCTL,
36755682Smarkm		0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
36855682Smarkm	if (errno == EINVAL) {
36955682Smarkm	    afs_entry_point = SINGLE_ENTRY_POINT;
37055682Smarkm	    afs_syscalls[0] = syscall_num;
37155682Smarkm	    return 0;
37255682Smarkm	}
37355682Smarkm    }
37455682Smarkm    return 1;
37555682Smarkm}
37655682Smarkm#endif
37755682Smarkm
37855682Smarkm/*
37955682Smarkm * Try to see if `syscall_pioctl' is a pioctl syscall.  Return 0 iff
38055682Smarkm * succesful.
38155682Smarkm *
38255682Smarkm */
38355682Smarkm
38455682Smarkm#ifdef AFS_PIOCTL
38555682Smarkmstatic int
38655682Smarkmtry_two (int syscall_pioctl, int syscall_setpag)
38755682Smarkm{
38855682Smarkm    struct ViceIoctl parms;
38955682Smarkm    memset(&parms, 0, sizeof(parms));
39055682Smarkm
39155682Smarkm    if (setjmp(catch_SIGSYS) == 0) {
39255682Smarkm	syscall(syscall_pioctl,
39355682Smarkm		0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
39455682Smarkm	if (errno == EINVAL) {
39555682Smarkm	    afs_entry_point = MULTIPLE_ENTRY_POINT;
39655682Smarkm	    afs_syscalls[0] = syscall_pioctl;
39755682Smarkm	    afs_syscalls[1] = syscall_setpag;
39855682Smarkm	    return 0;
39955682Smarkm	}
40055682Smarkm    }
40155682Smarkm    return 1;
40255682Smarkm}
40355682Smarkm#endif
40455682Smarkm
40555682Smarkmint
40655682Smarkmk_hasafs(void)
40755682Smarkm{
40855682Smarkm#if !defined(NO_AFS) && defined(SIGSYS)
40972445Sassar    RETSIGTYPE (*saved_func)(int);
41055682Smarkm#endif
411178825Sdfr    int saved_errno, ret;
412178825Sdfr    char *env = NULL;
413178825Sdfr
414178825Sdfr    if (!issuid())
415178825Sdfr	env = getenv ("AFS_SYSCALL");
41655682Smarkm
41755682Smarkm    /*
41855682Smarkm     * Already checked presence of AFS syscalls?
41955682Smarkm     */
42055682Smarkm    if (afs_entry_point != UNKNOWN_ENTRY_POINT)
42155682Smarkm	return afs_entry_point != NO_ENTRY_POINT;
42255682Smarkm
42355682Smarkm    /*
42455682Smarkm     * Probe kernel for AFS specific syscalls,
42555682Smarkm     * they (currently) come in two flavors.
42655682Smarkm     * If the syscall is absent we recive a SIGSYS.
42755682Smarkm     */
42855682Smarkm    afs_entry_point = NO_ENTRY_POINT;
42955682Smarkm
43055682Smarkm    saved_errno = errno;
43155682Smarkm#ifndef NO_AFS
43255682Smarkm#ifdef SIGSYS
43355682Smarkm    saved_func = signal(SIGSYS, SIGSYS_handler);
43455682Smarkm#endif
435178825Sdfr    if (env && strstr(env, "..") == NULL) {
43655682Smarkm
437178825Sdfr	if (strncmp("/proc/", env, 6) == 0) {
438178825Sdfr	    if (try_ioctlpath(env, VIOC_SYSCALL_PROC, LINUX_PROC_POINT) == 0)
439178825Sdfr		goto done;
440178825Sdfr	}
441178825Sdfr	if (strncmp("/dev/", env, 5) == 0) {
442178825Sdfr	    if (try_ioctlpath(env, VIOC_SYSCALL_DEV, MACOS_DEV_POINT) == 0)
443178825Sdfr		goto done;
444178825Sdfr	    if (try_ioctlpath(env,VIOC_SYSCALL_DEV_OPENAFS,MACOS_DEV_POINT) ==0)
445178825Sdfr		goto done;
446178825Sdfr	}
447178825Sdfr    }
448178825Sdfr
449178825Sdfr    ret = try_ioctlpath("/proc/fs/openafs/afs_ioctl",
450178825Sdfr			VIOC_SYSCALL_PROC, LINUX_PROC_POINT);
451178825Sdfr    if (ret == 0)
452178825Sdfr	goto done;
453178825Sdfr    ret = try_ioctlpath("/proc/fs/nnpfs/afs_ioctl",
454178825Sdfr			VIOC_SYSCALL_PROC, LINUX_PROC_POINT);
455178825Sdfr    if (ret == 0)
456178825Sdfr	goto done;
457178825Sdfr
458178825Sdfr    ret = try_ioctlpath("/dev/openafs_ioctl",
459178825Sdfr			VIOC_SYSCALL_DEV_OPENAFS, MACOS_DEV_POINT);
460178825Sdfr    if (ret == 0)
461178825Sdfr	goto done;
462178825Sdfr    ret = try_ioctlpath("/dev/nnpfs_ioctl", VIOC_SYSCALL_DEV, MACOS_DEV_POINT);
463178825Sdfr    if (ret == 0)
464178825Sdfr	goto done;
465178825Sdfr
46655682Smarkm#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
46755682Smarkm    {
46855682Smarkm	int tmp;
46955682Smarkm
47055682Smarkm	if (env != NULL) {
47155682Smarkm	    if (sscanf (env, "%d", &tmp) == 1) {
47255682Smarkm		if (try_one (tmp) == 0)
47355682Smarkm		    goto done;
47455682Smarkm	    } else {
47555682Smarkm		char *end = NULL;
47655682Smarkm		char *p;
47755682Smarkm		char *s = strdup (env);
47855682Smarkm
47955682Smarkm		if (s != NULL) {
48055682Smarkm		    for (p = strtok_r (s, ",", &end);
48155682Smarkm			 p != NULL;
48255682Smarkm			 p = strtok_r (NULL, ",", &end)) {
48355682Smarkm			if (map_syscall_name_to_number (p, &tmp) == 0)
48455682Smarkm			    if (try_one (tmp) == 0) {
48555682Smarkm				free (s);
48655682Smarkm				goto done;
48755682Smarkm			    }
48855682Smarkm		    }
48955682Smarkm		    free (s);
49055682Smarkm		}
49155682Smarkm	    }
49255682Smarkm	}
49355682Smarkm    }
49455682Smarkm#endif /* AFS_SYSCALL || AFS_SYSCALL2 || AFS_SYSCALL3 */
49555682Smarkm
49655682Smarkm#ifdef AFS_SYSCALL
49755682Smarkm    if (try_one (AFS_SYSCALL) == 0)
49855682Smarkm	goto done;
49955682Smarkm#endif /* AFS_SYSCALL */
50055682Smarkm
50155682Smarkm#ifdef AFS_PIOCTL
50255682Smarkm    {
50355682Smarkm	int tmp[2];
50455682Smarkm
50555682Smarkm	if (env != NULL && sscanf (env, "%d%d", &tmp[0], &tmp[1]) == 2)
50655682Smarkm	    if (try_two (tmp[0], tmp[1]) == 2)
50755682Smarkm		goto done;
50855682Smarkm    }
50955682Smarkm#endif /* AFS_PIOCTL */
51055682Smarkm
51155682Smarkm#ifdef AFS_PIOCTL
51255682Smarkm    if (try_two (AFS_PIOCTL, AFS_SETPAG) == 0)
51355682Smarkm	goto done;
51455682Smarkm#endif /* AFS_PIOCTL */
51555682Smarkm
51655682Smarkm#ifdef AFS_SYSCALL2
51755682Smarkm    if (try_one (AFS_SYSCALL2) == 0)
51855682Smarkm	goto done;
51955682Smarkm#endif /* AFS_SYSCALL2 */
52055682Smarkm
52155682Smarkm#ifdef AFS_SYSCALL3
52255682Smarkm    if (try_one (AFS_SYSCALL3) == 0)
52355682Smarkm	goto done;
52455682Smarkm#endif /* AFS_SYSCALL3 */
52555682Smarkm
52655682Smarkm#ifdef _AIX
52755682Smarkm#if 0
52855682Smarkm    if (env != NULL) {
52955682Smarkm	char *pos = NULL;
53055682Smarkm	char *pioctl_name;
53155682Smarkm	char *setpag_name;
53255682Smarkm
53355682Smarkm	pioctl_name = strtok_r (env, ", \t", &pos);
53455682Smarkm	if (pioctl_name != NULL) {
53555682Smarkm	    setpag_name = strtok_r (NULL, ", \t", &pos);
53655682Smarkm	    if (setpag_name != NULL)
53755682Smarkm		if (try_aix (pioctl_name, setpag_name) == 0)
53855682Smarkm		    goto done;
53955682Smarkm	}
54055682Smarkm    }
54155682Smarkm#endif
54255682Smarkm
54355682Smarkm    if(try_aix() == 0)
54455682Smarkm	goto done;
54555682Smarkm#endif
54655682Smarkm
547142403Snectar
54855682Smarkmdone:
54955682Smarkm#ifdef SIGSYS
55055682Smarkm    signal(SIGSYS, saved_func);
55155682Smarkm#endif
55255682Smarkm#endif /* NO_AFS */
55355682Smarkm    errno = saved_errno;
55455682Smarkm    return afs_entry_point != NO_ENTRY_POINT;
55555682Smarkm}
556178825Sdfr
557178825Sdfrint
558178825Sdfrk_hasafs_recheck(void)
559178825Sdfr{
560178825Sdfr    afs_entry_point = UNKNOWN_ENTRY_POINT;
561178825Sdfr    return k_hasafs();
562178825Sdfr}
563