afssys.c revision 267654
1193323Sed/*
2193323Sed * Copyright (c) 1995 - 2000, 2002, 2004, 2005 Kungliga Tekniska H�gskolan
3193323Sed * (Royal Institute of Technology, Stockholm, Sweden).
4193323Sed * All rights reserved.
5193323Sed *
6193323Sed * Redistribution and use in source and binary forms, with or without
7193323Sed * modification, are permitted provided that the following conditions
8193323Sed * are met:
9193323Sed *
10193323Sed * 1. Redistributions of source code must retain the above copyright
11193323Sed *    notice, this list of conditions and the following disclaimer.
12193323Sed *
13193323Sed * 2. Redistributions in binary form must reproduce the above copyright
14193323Sed *    notice, this list of conditions and the following disclaimer in the
15193323Sed *    documentation and/or other materials provided with the distribution.
16193323Sed *
17193323Sed * 3. Neither the name of the Institute nor the names of its contributors
18193323Sed *    may be used to endorse or promote products derived from this software
19234353Sdim *    without specific prior written permission.
20234353Sdim *
21234353Sdim * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22193323Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23193323Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24193323Sed * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27198090Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28198090Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30263508Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31263508Sdim * SUCH DAMAGE.
32263508Sdim */
33218893Sdim
34193323Sed#include "kafs_locl.h"
35193323Sed
36249423SdimRCSID("$Id: afssys.c 17050 2006-04-11 08:12:29Z lha $");
37249423Sdim
38249423Sdimstruct procdata {
39249423Sdim    unsigned long param4;
40193323Sed    unsigned long param3;
41193323Sed    unsigned long param2;
42193323Sed    unsigned long param1;
43193323Sed    unsigned long syscall;
44193323Sed};
45193323Sed#define VIOC_SYSCALL_PROC _IOW('C', 1, void *)
46193323Sed
47193323Sedstruct devdata {
48193323Sed    unsigned long syscall;
49193323Sed    unsigned long param1;
50193323Sed    unsigned long param2;
51193323Sed    unsigned long param3;
52193323Sed    unsigned long param4;
53234353Sdim    unsigned long param5;
54234353Sdim    unsigned long param6;
55234353Sdim    unsigned long retval;
56234353Sdim};
57234353Sdim#define VIOC_SYSCALL_DEV _IOWR('C', 2, struct devdata)
58234353Sdim#define VIOC_SYSCALL_DEV_OPENAFS _IOWR('C', 1, struct devdata)
59193323Sed
60234353Sdim
61234353Sdimint _kafs_debug; /* this should be done in a better way */
62193323Sed
63243830Sdim#define UNKNOWN_ENTRY_POINT	(-1)
64243830Sdim#define NO_ENTRY_POINT		0
65243830Sdim#define SINGLE_ENTRY_POINT	1
66243830Sdim#define MULTIPLE_ENTRY_POINT	2
67249423Sdim#define SINGLE_ENTRY_POINT2	3
68249423Sdim#define SINGLE_ENTRY_POINT3	4
69193323Sed#define LINUX_PROC_POINT	5
70263508Sdim#define AIX_ENTRY_POINTS	6
71263508Sdim#define MACOS_DEV_POINT		7
72263508Sdim
73263508Sdimstatic int afs_entry_point = UNKNOWN_ENTRY_POINT;
74263508Sdimstatic int afs_syscalls[2];
75263508Sdimstatic char *afs_ioctlpath;
76263508Sdimstatic unsigned long afs_ioctlnum;
77263508Sdim
78263508Sdim/* Magic to get AIX syscalls to work */
79263508Sdim#ifdef _AIX
80263508Sdim
81263508Sdimstatic int (*Pioctl)(char*, int, struct ViceIoctl*, int);
82263508Sdimstatic int (*Setpag)(void);
83263508Sdim
84263508Sdim#include "dlfcn.h"
85263508Sdim
86263508Sdim/*
87263508Sdim *
88263508Sdim */
89263508Sdim
90263508Sdimstatic int
91263508Sdimtry_aix(void)
92263508Sdim{
93234353Sdim#ifdef STATIC_AFS_SYSCALLS
94243830Sdim    Pioctl = aix_pioctl;
95239462Sdim    Setpag = aix_setpag;
96249423Sdim#else
97263508Sdim    void *ptr;
98263508Sdim    char path[MaxPathLen], *p;
99263508Sdim    /*
100263508Sdim     * If we are root or running setuid don't trust AFSLIBPATH!
101263508Sdim     */
102263508Sdim    if (getuid() != 0 && !issuid() && (p = getenv("AFSLIBPATH")) != NULL)
103263508Sdim	strlcpy(path, p, sizeof(path));
104263508Sdim    else
105263508Sdim	snprintf(path, sizeof(path), "%s/afslib.so", LIBDIR);
106263508Sdim
107263508Sdim    ptr = dlopen(path, RTLD_NOW);
108263508Sdim    if(ptr == NULL) {
109249423Sdim	if(_kafs_debug) {
110234353Sdim	    if(errno == ENOEXEC && (p = dlerror()) != NULL)
111249423Sdim		fprintf(stderr, "dlopen(%s): %s\n", path, p);
112193323Sed	    else if (errno != ENOENT)
113249423Sdim		fprintf(stderr, "dlopen(%s): %s\n", path, strerror(errno));
114249423Sdim	}
115200581Srdivacky	return 1;
116263508Sdim    }
117200581Srdivacky    Setpag = (int (*)(void))dlsym(ptr, "aix_setpag");
118263508Sdim    Pioctl = (int (*)(char*, int,
119193323Sed		      struct ViceIoctl*, int))dlsym(ptr, "aix_pioctl");
120263508Sdim#endif
121249423Sdim    afs_entry_point = AIX_ENTRY_POINTS;
122263508Sdim    return 0;
123224145Sdim}
124224145Sdim#endif /* _AIX */
125218893Sdim
126263508Sdim/*
127224145Sdim * This probably only works under Solaris and could get confused if
128195098Sed * there's a /etc/name_to_sysnum file.
129218893Sdim */
130195098Sed
131195098Sed#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
132195098Sed
133198090Srdivacky#define _PATH_ETC_NAME_TO_SYSNUM "/etc/name_to_sysnum"
134198090Srdivacky
135198090Srdivackystatic int
136193323Sedmap_syscall_name_to_number (const char *str, int *res)
137193323Sed{
138193323Sed    FILE *f;
139198090Srdivacky    char buf[256];
140193323Sed    size_t str_len = strlen (str);
141198090Srdivacky
142198090Srdivacky    f = fopen (_PATH_ETC_NAME_TO_SYSNUM, "r");
143198090Srdivacky    if (f == NULL)
144198090Srdivacky	return -1;
145198090Srdivacky    while (fgets (buf, sizeof(buf), f) != NULL) {
146193323Sed	if (buf[0] == '#')
147193323Sed	    continue;
148193323Sed
149198090Srdivacky	if (strncmp (str, buf, str_len) == 0) {
150193323Sed	    char *begptr = buf + str_len;
151193323Sed	    char *endptr;
152193323Sed	    long val = strtol (begptr, &endptr, 0);
153193323Sed
154198090Srdivacky	    if (val != 0 && endptr != begptr) {
155193323Sed		fclose (f);
156193323Sed		*res = val;
157193323Sed		return 0;
158249423Sdim	    }
159193323Sed	}
160193323Sed    }
161198090Srdivacky    fclose (f);
162193323Sed    return -1;
163198090Srdivacky}
164198090Srdivacky#endif
165218893Sdim
166198090Srdivackystatic int
167198090Srdivackytry_ioctlpath(const char *path, unsigned long ioctlnum, int entrypoint)
168198090Srdivacky{
169218893Sdim    int fd, ret, saved_errno;
170198090Srdivacky
171198090Srdivacky    fd = open(path, O_RDWR);
172218893Sdim    if (fd < 0)
173198090Srdivacky	return 1;
174198090Srdivacky    switch (entrypoint) {
175234353Sdim    case LINUX_PROC_POINT: {
176234353Sdim	struct procdata data = { 0, 0, 0, 0, AFSCALL_PIOCTL };
177239462Sdim	data.param2 = (unsigned long)VIOCGETTOK;
178239462Sdim	ret = ioctl(fd, ioctlnum, &data);
179193323Sed	break;
180198090Srdivacky    }
181198090Srdivacky    case MACOS_DEV_POINT: {
182198090Srdivacky	struct devdata data = { AFSCALL_PIOCTL, 0, 0, 0, 0, 0, 0, 0 };
183198090Srdivacky	data.param2 = (unsigned long)VIOCGETTOK;
184198090Srdivacky	ret = ioctl(fd, ioctlnum, &data);
185239462Sdim	break;
186239462Sdim    }
187193323Sed    default:
188193323Sed	abort();
189198090Srdivacky    }
190198090Srdivacky    saved_errno = errno;
191198090Srdivacky    close(fd);
192198090Srdivacky    /*
193198090Srdivacky     * Be quite liberal in what error are ok, the first is the one
194218893Sdim     * that should trigger given that params is NULL.
195243830Sdim     */
196243830Sdim    if (ret &&
197243830Sdim	(saved_errno != EFAULT &&
198243830Sdim	 saved_errno != EDOM &&
199243830Sdim	 saved_errno != ENOTCONN))
200243830Sdim	return 1;
201243830Sdim    afs_ioctlnum = ioctlnum;
202243830Sdim    afs_ioctlpath = strdup(path);
203243830Sdim    if (afs_ioctlpath == NULL)
204243830Sdim	return 1;
205243830Sdim    afs_entry_point = entrypoint;
206243830Sdim    return 0;
207239462Sdim}
208239462Sdim
209239462Sdimstatic int
210239462Sdimdo_ioctl(void *data)
211263508Sdim{
212239462Sdim    int fd, ret, saved_errno;
213239462Sdim    fd = open(afs_ioctlpath, O_RDWR);
214239462Sdim    if (fd < 0) {
215239462Sdim	errno = EINVAL;
216239462Sdim	return -1;
217239462Sdim    }
218239462Sdim    ret = ioctl(fd, afs_ioctlnum, data);
219239462Sdim    saved_errno = errno;
220239462Sdim    close(fd);
221239462Sdim    errno = saved_errno;
222239462Sdim    return ret;
223239462Sdim}
224239462Sdim
225239462Sdimint
226239462Sdimk_pioctl(char *a_path,
227239462Sdim	 int o_opcode,
228239462Sdim	 struct ViceIoctl *a_paramsP,
229239462Sdim	 int a_followSymlinks)
230249423Sdim{
231249423Sdim#ifndef NO_AFS
232249423Sdim    switch(afs_entry_point){
233239462Sdim#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
234239462Sdim    case SINGLE_ENTRY_POINT:
235239462Sdim    case SINGLE_ENTRY_POINT2:
236239462Sdim    case SINGLE_ENTRY_POINT3:
237239462Sdim	return syscall(afs_syscalls[0], AFSCALL_PIOCTL,
238239462Sdim		       a_path, o_opcode, a_paramsP, a_followSymlinks);
239239462Sdim#endif
240202375Srdivacky#if defined(AFS_PIOCTL)
241198090Srdivacky    case MULTIPLE_ENTRY_POINT:
242198090Srdivacky	return syscall(afs_syscalls[0],
243198090Srdivacky		       a_path, o_opcode, a_paramsP, a_followSymlinks);
244198090Srdivacky#endif
245198090Srdivacky    case LINUX_PROC_POINT: {
246218893Sdim	struct procdata data = { 0, 0, 0, 0, AFSCALL_PIOCTL };
247198090Srdivacky	data.param1 = (unsigned long)a_path;
248198090Srdivacky	data.param2 = (unsigned long)o_opcode;
249212904Sdim	data.param3 = (unsigned long)a_paramsP;
250198090Srdivacky	data.param4 = (unsigned long)a_followSymlinks;
251212904Sdim	return do_ioctl(&data);
252212904Sdim    }
253212904Sdim    case MACOS_DEV_POINT: {
254212904Sdim	struct devdata data = { AFSCALL_PIOCTL, 0, 0, 0, 0, 0, 0, 0 };
255198090Srdivacky	int ret;
256200581Srdivacky
257200581Srdivacky	data.param1 = (unsigned long)a_path;
258200581Srdivacky	data.param2 = (unsigned long)o_opcode;
259200581Srdivacky	data.param3 = (unsigned long)a_paramsP;
260200581Srdivacky	data.param4 = (unsigned long)a_followSymlinks;
261200581Srdivacky
262218893Sdim	ret = do_ioctl(&data);
263198090Srdivacky	if (ret)
264198090Srdivacky	    return ret;
265198090Srdivacky
266239462Sdim	return data.retval;
267243830Sdim    }
268243830Sdim#ifdef _AIX
269243830Sdim    case AIX_ENTRY_POINTS:
270249423Sdim	return Pioctl(a_path, o_opcode, a_paramsP, a_followSymlinks);
271249423Sdim#endif
272249423Sdim    }
273263508Sdim    errno = ENOSYS;
274198090Srdivacky#ifdef SIGSYS
275198090Srdivacky    kill(getpid(), SIGSYS);	/* You lose! */
276198090Srdivacky#endif
277198090Srdivacky#endif /* NO_AFS */
278249423Sdim    return -1;
279249423Sdim}
280243830Sdim
281198090Srdivackyint
282198090Srdivackyk_afs_cell_of_file(const char *path, char *cell, int len)
283198090Srdivacky{
284249423Sdim    struct ViceIoctl parms;
285249423Sdim    parms.in = NULL;
286243830Sdim    parms.in_size = 0;
287198090Srdivacky    parms.out = cell;
288198090Srdivacky    parms.out_size = len;
289239462Sdim    return k_pioctl(rk_UNCONST(path), VIOC_FILE_CELL_NAME, &parms, 1);
290239462Sdim}
291198090Srdivacky
292198090Srdivackyint
293208599Srdivackyk_unlog(void)
294239462Sdim{
295239462Sdim    struct ViceIoctl parms;
296263508Sdim    memset(&parms, 0, sizeof(parms));
297263508Sdim    return k_pioctl(0, VIOCUNLOG, &parms, 0);
298263508Sdim}
299263508Sdim
300198090Srdivackyint
301198090Srdivackyk_setpag(void)
302249423Sdim{
303249423Sdim#ifndef NO_AFS
304263508Sdim    switch(afs_entry_point){
305198090Srdivacky#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
306249423Sdim    case SINGLE_ENTRY_POINT:
307249423Sdim    case SINGLE_ENTRY_POINT2:
308198090Srdivacky    case SINGLE_ENTRY_POINT3:
309198090Srdivacky	return syscall(afs_syscalls[0], AFSCALL_SETPAG);
310218893Sdim#endif
311198090Srdivacky#if defined(AFS_PIOCTL)
312198090Srdivacky    case MULTIPLE_ENTRY_POINT:
313198090Srdivacky	return syscall(afs_syscalls[1]);
314239462Sdim#endif
315249423Sdim    case LINUX_PROC_POINT: {
316249423Sdim	struct procdata data = { 0, 0, 0, 0, AFSCALL_SETPAG };
317249423Sdim	return do_ioctl(&data);
318249423Sdim    }
319249423Sdim    case MACOS_DEV_POINT: {
320243830Sdim	struct devdata data = { AFSCALL_SETPAG, 0, 0, 0, 0, 0, 0, 0 };
321198090Srdivacky	int ret = do_ioctl(&data);
322239462Sdim	if (ret)
323239462Sdim	    return ret;
324249423Sdim	return data.retval;
325249423Sdim     }
326249423Sdim#ifdef _AIX
327198090Srdivacky    case AIX_ENTRY_POINTS:
328198090Srdivacky	return Setpag();
329198090Srdivacky#endif
330208599Srdivacky    }
331263508Sdim
332249423Sdim    errno = ENOSYS;
333249423Sdim#ifdef SIGSYS
334243830Sdim    kill(getpid(), SIGSYS);	/* You lose! */
335198090Srdivacky#endif
336198090Srdivacky#endif /* NO_AFS */
337198090Srdivacky    return -1;
338198090Srdivacky}
339263508Sdim
340198090Srdivackystatic jmp_buf catch_SIGSYS;
341198090Srdivacky
342243830Sdim#ifdef SIGSYS
343198090Srdivacky
344198090Srdivackystatic RETSIGTYPE
345198090SrdivackySIGSYS_handler(int sig)
346198090Srdivacky{
347234353Sdim    errno = 0;
348198090Srdivacky    signal(SIGSYS, SIGSYS_handler); /* Need to reinstall handler on SYSV */
349198090Srdivacky    longjmp(catch_SIGSYS, 1);
350263508Sdim}
351243830Sdim
352243830Sdim#endif
353263508Sdim
354263508Sdim/*
355263508Sdim * Try to see if `syscall' is a pioctl.  Return 0 iff succesful.
356198090Srdivacky */
357198090Srdivacky
358218893Sdim#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
359198090Srdivackystatic int
360198090Srdivackytry_one (int syscall_num)
361263508Sdim{
362263508Sdim    struct ViceIoctl parms;
363263508Sdim    memset(&parms, 0, sizeof(parms));
364263508Sdim
365198090Srdivacky    if (setjmp(catch_SIGSYS) == 0) {
366234353Sdim	syscall(syscall_num, AFSCALL_PIOCTL,
367198090Srdivacky		0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
368198090Srdivacky	if (errno == EINVAL) {
369198090Srdivacky	    afs_entry_point = SINGLE_ENTRY_POINT;
370249423Sdim	    afs_syscalls[0] = syscall_num;
371234353Sdim	    return 0;
372249423Sdim	}
373249423Sdim    }
374198090Srdivacky    return 1;
375243830Sdim}
376243830Sdim#endif
377243830Sdim
378263508Sdim/*
379243830Sdim * Try to see if `syscall_pioctl' is a pioctl syscall.  Return 0 iff
380198090Srdivacky * succesful.
381234353Sdim *
382243830Sdim */
383243830Sdim
384243830Sdim#ifdef AFS_PIOCTL
385198090Srdivackystatic int
386198090Srdivackytry_two (int syscall_pioctl, int syscall_setpag)
387249423Sdim{
388198090Srdivacky    struct ViceIoctl parms;
389234353Sdim    memset(&parms, 0, sizeof(parms));
390249423Sdim
391263508Sdim    if (setjmp(catch_SIGSYS) == 0) {
392243830Sdim	syscall(syscall_pioctl,
393218893Sdim		0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
394198090Srdivacky	if (errno == EINVAL) {
395198090Srdivacky	    afs_entry_point = MULTIPLE_ENTRY_POINT;
396249423Sdim	    afs_syscalls[0] = syscall_pioctl;
397198090Srdivacky	    afs_syscalls[1] = syscall_setpag;
398198090Srdivacky	    return 0;
399198090Srdivacky	}
400198090Srdivacky    }
401263508Sdim    return 1;
402263508Sdim}
403263508Sdim#endif
404198090Srdivacky
405198090Srdivackyint
406198090Srdivackyk_hasafs(void)
407198090Srdivacky{
408198090Srdivacky#if !defined(NO_AFS) && defined(SIGSYS)
409198090Srdivacky    RETSIGTYPE (*saved_func)(int);
410198090Srdivacky#endif
411198090Srdivacky    int saved_errno, ret;
412263508Sdim    char *env = NULL;
413198090Srdivacky
414198090Srdivacky    if (!issuid())
415198090Srdivacky	env = getenv ("AFS_SYSCALL");
416198090Srdivacky
417198090Srdivacky    /*
418198090Srdivacky     * Already checked presence of AFS syscalls?
419198090Srdivacky     */
420198090Srdivacky    if (afs_entry_point != UNKNOWN_ENTRY_POINT)
421249423Sdim	return afs_entry_point != NO_ENTRY_POINT;
422249423Sdim
423239462Sdim    /*
424249423Sdim     * Probe kernel for AFS specific syscalls,
425249423Sdim     * they (currently) come in two flavors.
426249423Sdim     * If the syscall is absent we recive a SIGSYS.
427239462Sdim     */
428198090Srdivacky    afs_entry_point = NO_ENTRY_POINT;
429198090Srdivacky
430218893Sdim    saved_errno = errno;
431218893Sdim#ifndef NO_AFS
432218893Sdim#ifdef SIGSYS
433218893Sdim    saved_func = signal(SIGSYS, SIGSYS_handler);
434218893Sdim#endif
435218893Sdim    if (env && strstr(env, "..") == NULL) {
436218893Sdim
437218893Sdim	if (strncmp("/proc/", env, 6) == 0) {
438218893Sdim	    if (try_ioctlpath(env, VIOC_SYSCALL_PROC, LINUX_PROC_POINT) == 0)
439218893Sdim		goto done;
440218893Sdim	}
441218893Sdim	if (strncmp("/dev/", env, 5) == 0) {
442218893Sdim	    if (try_ioctlpath(env, VIOC_SYSCALL_DEV, MACOS_DEV_POINT) == 0)
443249423Sdim		goto done;
444249423Sdim	    if (try_ioctlpath(env,VIOC_SYSCALL_DEV_OPENAFS,MACOS_DEV_POINT) ==0)
445249423Sdim		goto done;
446249423Sdim	}
447249423Sdim    }
448249423Sdim
449249423Sdim    ret = try_ioctlpath("/proc/fs/openafs/afs_ioctl",
450249423Sdim			VIOC_SYSCALL_PROC, LINUX_PROC_POINT);
451249423Sdim    if (ret == 0)
452249423Sdim	goto done;
453249423Sdim    ret = try_ioctlpath("/proc/fs/nnpfs/afs_ioctl",
454249423Sdim			VIOC_SYSCALL_PROC, LINUX_PROC_POINT);
455249423Sdim    if (ret == 0)
456249423Sdim	goto done;
457249423Sdim
458249423Sdim    ret = try_ioctlpath("/dev/openafs_ioctl",
459249423Sdim			VIOC_SYSCALL_DEV_OPENAFS, MACOS_DEV_POINT);
460249423Sdim    if (ret == 0)
461249423Sdim	goto done;
462249423Sdim    ret = try_ioctlpath("/dev/nnpfs_ioctl", VIOC_SYSCALL_DEV, MACOS_DEV_POINT);
463249423Sdim    if (ret == 0)
464193323Sed	goto done;
465193323Sed
466193323Sed#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
467234353Sdim    {
468234353Sdim	int tmp;
469234353Sdim
470193323Sed	if (env != NULL) {
471198090Srdivacky	    if (sscanf (env, "%d", &tmp) == 1) {
472193323Sed		if (try_one (tmp) == 0)
473198090Srdivacky		    goto done;
474193323Sed	    } else {
475198090Srdivacky		char *end = NULL;
476193323Sed		char *p;
477198090Srdivacky		char *s = strdup (env);
478193323Sed
479193323Sed		if (s != NULL) {
480218893Sdim		    for (p = strtok_r (s, ",", &end);
481193323Sed			 p != NULL;
482193323Sed			 p = strtok_r (NULL, ",", &end)) {
483193323Sed			if (map_syscall_name_to_number (p, &tmp) == 0)
484198090Srdivacky			    if (try_one (tmp) == 0) {
485193323Sed				free (s);
486198090Srdivacky				goto done;
487193323Sed			    }
488198090Srdivacky		    }
489193323Sed		    free (s);
490198090Srdivacky		}
491193323Sed	    }
492198090Srdivacky	}
493193323Sed    }
494198090Srdivacky#endif /* AFS_SYSCALL || AFS_SYSCALL2 || AFS_SYSCALL3 */
495193323Sed
496198090Srdivacky#ifdef AFS_SYSCALL
497193323Sed    if (try_one (AFS_SYSCALL) == 0)
498193323Sed	goto done;
499218893Sdim#endif /* AFS_SYSCALL */
500193323Sed
501198090Srdivacky#ifdef AFS_PIOCTL
502193323Sed    {
503193323Sed	int tmp[2];
504243830Sdim
505243830Sdim	if (env != NULL && sscanf (env, "%d%d", &tmp[0], &tmp[1]) == 2)
506243830Sdim	    if (try_two (tmp[0], tmp[1]) == 2)
507243830Sdim		goto done;
508243830Sdim    }
509249423Sdim#endif /* AFS_PIOCTL */
510249423Sdim
511243830Sdim#ifdef AFS_PIOCTL
512198090Srdivacky    if (try_two (AFS_PIOCTL, AFS_SETPAG) == 0)
513263508Sdim	goto done;
514198090Srdivacky#endif /* AFS_PIOCTL */
515198090Srdivacky
516198090Srdivacky#ifdef AFS_SYSCALL2
517198090Srdivacky    if (try_one (AFS_SYSCALL2) == 0)
518198090Srdivacky	goto done;
519249423Sdim#endif /* AFS_SYSCALL2 */
520193323Sed
521198090Srdivacky#ifdef AFS_SYSCALL3
522243830Sdim    if (try_one (AFS_SYSCALL3) == 0)
523198090Srdivacky	goto done;
524198090Srdivacky#endif /* AFS_SYSCALL3 */
525198090Srdivacky
526198090Srdivacky#ifdef _AIX
527249423Sdim#if 0
528193323Sed    if (env != NULL) {
529198090Srdivacky	char *pos = NULL;
530243830Sdim	char *pioctl_name;
531198090Srdivacky	char *setpag_name;
532198090Srdivacky
533198090Srdivacky	pioctl_name = strtok_r (env, ", \t", &pos);
534239462Sdim	if (pioctl_name != NULL) {
535193323Sed	    setpag_name = strtok_r (NULL, ", \t", &pos);
536198090Srdivacky	    if (setpag_name != NULL)
537198090Srdivacky		if (try_aix (pioctl_name, setpag_name) == 0)
538198090Srdivacky		    goto done;
539198090Srdivacky	}
540208599Srdivacky    }
541239462Sdim#endif
542193323Sed
543234353Sdim    if(try_aix() == 0)
544234353Sdim	goto done;
545263508Sdim#endif
546263508Sdim
547234353Sdim
548198090Srdivackydone:
549263508Sdim#ifdef SIGSYS
550198090Srdivacky    signal(SIGSYS, saved_func);
551198090Srdivacky#endif
552198090Srdivacky#endif /* NO_AFS */
553249423Sdim    errno = saved_errno;
554193323Sed    return afs_entry_point != NO_ENTRY_POINT;
555198090Srdivacky}
556263508Sdim
557198090Srdivackyint
558198090Srdivackyk_hasafs_recheck(void)
559249423Sdim{
560193323Sed    afs_entry_point = UNKNOWN_ENTRY_POINT;
561193323Sed    return k_hasafs();
562198090Srdivacky}
563193323Sed