Fix configure check for realpath and dirname. Also streamline dirname usage.
[sxemacs] / m4 / sxe-fs-funs.m4
1 dnl sxe-fs-funs.m4 -- Functions for file system access
2
3 AC_DEFUN([SXE_CHECK_REALPATH], [dnl
4         ## defines have_realpath
5
6         ## for the dirname proto
7         AC_CHECK_DECLS([realpath], [], [], [
8 #ifdef HAVE_STDLIB_H
9 #  include <stdlib.h>
10 #endif
11                 ])
12         AC_CHECK_FUNCS([realpath])
13         AC_CHECK_LIB([c], [realpath])
14
15         if test "$ac_cv_func_realpath" = "yes"; then
16                 SXE_CHECK_BROKEN_REALPATH
17         elif test "$ac_cv_lib_c_realpath" = "yes"; then
18                 LDFLAGS="$LDFLAGS -lc"
19                 SXE_CHECK_BROKEN_REALPATH
20         else
21                 have_realpath=no
22         fi
23
24         if test "$sxe_func_realpath_broken" != "no"; then
25                 SXE_ADD_CORE_OBJS([realpath.o])
26         fi
27 ])dnl SXE_CHECK_REALPATH
28
29 AC_DEFUN([_SXE_CHECK_REALPATH_RETVAL], [dnl
30         ## arg #1 is the return type, char* by default
31         ## arg #2 is the final test,
32         ##        pass something that is expected to be true here
33         ##        the return value is stored in a variable `r'
34         ## defines sxe_func_realpath_returns_<ret_t> and
35         ## sxe_func_realpath_returns=$1 if true
36         pushdef([ret_t], ifelse($1, [], [char*],$1))
37         pushdef([resvar_body], [sxe_func_realpath_returns])
38         pushdef([resvar], resvar_body[_]translit(ret_t, [ -*], [__X]))
39         pushdef([rettest], ifelse($2, [], [[[[r[0] == '/']]]],$2))
40
41         AC_MSG_CHECKING([whether realpath returns ]ret_t)
42         AC_RUN_IFELSE([AC_LANG_SOURCE([[
43 #ifdef HAVE_STDLIB_H
44 #  include <stdlib.h>
45 #endif
46
47 #ifndef PATH_MAX
48 #define PATH_MAX 4096
49 #endif
50
51 int realpath_returns_]]ret_t[[() {
52         ]]ret_t[[ r;
53         char p[8] = "/bin/sh\000";
54         char resv[PATH_MAX];
55         int res;
56
57         resv[0] = '\0';
58         r = realpath(p, resv);
59         if (r) {
60                 res = ((]]rettest[[) == 0);
61         } else {
62                 res = 0;
63         }
64         return res;
65 }
66
67 int main()
68 {
69         return realpath_returns_]]ret_t[[();
70 }
71                 ]])],
72                 resvar[=yes],
73                 resvar[=no],
74                 resvar[=no])
75         AC_MSG_RESULT([$]resvar)
76
77         if test "$[]resvar[]" = "yes"; then
78                 resvar_body[=]ret_t
79                 AC_DEFINE_UNQUOTED([REALPATH_RET_T], ret_t,
80                         [return type of realpath()])
81         fi
82
83         popdef([resvar_body])
84         popdef([resvar])
85         popdef([ret_t])
86         popdef([rettest])
87 ])dnl _SXE_CHECK_REALPATH_RETVAL
88
89 AC_DEFUN([_SXE_CHECK_REALPATH_RETVAL_OWNER], [dnl
90         ## defines sxe_func_realpath_retval_owner,
91         ## values are either "sys" or "user"
92         pushdef([resvar], [sxe_func_realpath_retval_owner])
93
94         ## this test is especially critical, because some systems do not
95         ## allocate memory for the user when the return value is "."
96         ## instead they point to a static const char somewhere in their
97         ## guts which, of course, must not be furtherly modified, free'd or
98         ## anything ... took me fucking ages to find out what's going on
99         ## so let's drink to the morons responsible for THAT!
100         AC_MSG_CHECKING([to whom belongs the object returned by realpath])
101         if test "$opsys" = "darwin"; then
102            resvar=user
103         else
104         AC_RUN_IFELSE([AC_LANG_SOURCE([[
105 #ifdef HAVE_STDLIB_H
106 #  include <stdlib.h>
107 #endif
108
109 #ifndef PATH_MAX
110 #define PATH_MAX 4096
111 #endif
112
113 #define FOLLOW_FREE_STRATEGY            1
114 #define FOLLOW_REALLOC_STRATEGY         1
115 #define FOLLOW_DOUBLE_CALL_STRATEGY     1
116
117 int owner_of_object_returned_by_realpath()
118 {
119         void *r;  /* any pointer is just fine */
120         char p[8] = "/bin/sh\000";
121
122         r = (void*)realpath(p, NULL);
123 #if FOLLOW_DOUBLE_CALL_STRATEGY
124         {
125                 char p[8] = "/bin/cp\000";
126
127                 if (r == (void*)realpath(p, NULL)) {
128                         /* System owns when 2 calls yield same pointer */
129                         return 1;
130                 }
131         }
132 #endif
133 #if FOLLOW_REALLOC_STRATEGY
134         /* reallocation would help already */
135         r = realloc(r, 4096);
136 #endif
137 #if FOLLOW_FREE_STRATEGY
138         /* if r was ours we should be able to free it */
139         free(r);
140 #endif
141 #if FOLLOW_FREE_STRATEGY || FOLLOW_REALLOC_STRATEGY
142         return 0;
143 #else
144         return 1;
145 #endif
146 }
147
148 int main()
149 {
150         return owner_of_object_returned_by_realpath();
151 }
152                 ]])],
153                 resvar[=user],
154                 resvar[=sys],
155                 resvar[=sys])
156         fi
157         AC_MSG_RESULT([$]resvar)
158
159         if test "$[]resvar[]" = "user"; then
160                 AC_DEFINE([REALPATH_USER_OWNS_RETVAL], [1],
161                         [Whether the user space owns the retval of realpath()])
162         elif test "$[]resvar[]" = "sys"; then
163                 AC_DEFINE([REALPATH_SYS_OWNS_RETVAL], [1],
164                         [Whether the system owns the retval of realpath()])
165         fi
166
167         popdef([resvar])
168 ])dnl _SXE_CHECK_REALPATH_RETVAL_OWNER
169
170 AC_DEFUN([_SXE_CHECK_REALPATH_ON_PROTECTED_MEMORY], [dnl
171         ## defines sxe_func_realpath_accepts_protmem
172         pushdef([resvar], [sxe_func_realpath_accepts_protmem])
173
174         AC_MSG_CHECKING([whether realpath can operate on protected mem blocks])
175         if test "$opsys" = "darwin"; then
176            resvar=no
177         else
178         AC_RUN_IFELSE([AC_LANG_SOURCE([[
179 #ifdef HAVE_STDLIB_H
180 #  include <stdlib.h>
181 #endif
182
183 #ifndef PATH_MAX
184 #define PATH_MAX 4096
185 #endif
186
187 int realpath_can_operate_on_protected_mem_blocks()
188 {
189         char resv[PATH_MAX];
190         realpath("/bin/sh", NULL);
191         realpath("/bin/sh", resv);
192         return 0;
193 }
194
195 int main()
196 {
197         return realpath_can_operate_on_protected_mem_blocks();
198 }
199                 ]])],
200                 resvar[=yes],
201                 resvar[=no],
202                 resvar[=no])
203         fi
204         AC_MSG_RESULT([$]resvar)
205
206         if test "$[]resvar[]" = "yes"; then
207                 AC_DEFINE([REALPATH_ACCEPTS_PROTMEM], [1],
208                         [Whether realpath() accepts protected memory blocks])
209         fi
210
211         popdef([resvar])
212 ])dnl _SXE_CHECK_REALPATH_ON_PROTECTED_MEMORY
213
214 AC_DEFUN([_SXE_CHECK_REALPATH_SANE_ON_NON_EXISTENT], [dnl
215         ## defines sxe_func_realpath_
216         pushdef([resvar], [sxe_func_realpath_sane_on_non_existent])
217
218         AC_MSG_CHECKING([whether realpath survives if we pass non-existent stuff])
219         AC_RUN_IFELSE([AC_LANG_SOURCE([[
220 #ifdef HAVE_STDLIB_H
221 #  include <stdlib.h>
222 #endif
223
224 #ifndef PATH_MAX
225 #define PATH_MAX 4096
226 #endif
227
228 static char p[24] = "/nobody/has/this/file\000";
229
230 int realpath_survives_non_existent_path()
231 {
232         char *r;
233         char resv[PATH_MAX];
234         r = realpath((char*)p, resv);
235
236         return ((r == NULL) == 0);
237 }
238
239 int main()
240 {
241         return realpath_survives_non_existent_path();
242 }
243                 ]])],
244                 resvar[=yes],
245                 resvar[=no],
246                 resvar[=no])
247         AC_MSG_RESULT([$]resvar)
248
249         if test "$[]resvar[]" = "yes"; then
250                 AC_DEFINE([REALPATH_SANE_ON_NON_EXISTENT], [1],
251                         [Whether realpath() accepts and handles non-existent files])
252         fi
253
254         popdef([resvar])
255 ])dnl _SXE_CHECK_REALPATH_SANE_ON_NON_EXISTENT
256
257 AC_DEFUN([SXE_CHECK_BROKEN_REALPATH], [dnl
258         ## defines 3 vars, look in the sub macros to see which ones
259         _SXE_CHECK_REALPATH_ON_PROTECTED_MEMORY
260         _SXE_CHECK_REALPATH_SANE_ON_NON_EXISTENT
261         _SXE_CHECK_REALPATH_RETVAL
262         _SXE_CHECK_REALPATH_RETVAL_OWNER
263
264         AC_MSG_CHECKING([if realpath is considered broken])
265         if test "$sxe_func_realpath_returns" = "char*" -a \
266                 "$sxe_func_realpath_sane_on_non_existent" = "yes" -a \
267                 "$sxe_func_realpath_retval_owner" = "user"; then
268                 sxe_func_realpath_broken="no"
269         else
270                 sxe_func_realpath_broken="yes"
271         fi
272         AC_MSG_RESULT([$sxe_func_realpath_broken])
273 ])dnl SXE_CHECK_BROKEN_REALPATH
274
275
276 AC_DEFUN([SXE_CHECK_DIRNAME], [dnl
277         ## defines have_dirname
278
279         ## of course posix standards are just rough draughts
280         ## and by no means obliging in any way ...
281         ## and since we all hate working systems we do our best
282         ## to break these so called standards wherever we can
283         ##
284         ## Passage from coreutils:
285         ## In general, we can't use the builtin `dirname' function if available,
286         ## since it has different meanings in different environments. In some
287         ## environments the builtin `dirname' modifies its argument.
288
289         ## for the dirname proto
290         SXE_CHECK_HEADERS([libgen.h])
291         AC_CHECK_DECLS([dirname], [], [], [
292 #ifdef HAVE_LIBGEN_H
293 #  include <libgen.h>
294 #endif
295                 ])
296         AC_CHECK_FUNCS([dirname])       dnl should be part of glibc
297         AC_CHECK_LIB([c], [dirname])
298
299         if test "$ac_cv_func_dirname" = "yes"; then
300                 SXE_CHECK_BROKEN_DIRNAME
301         elif test "$ac_cv_lib_c_dirname" = "yes"; then
302                 LDFLAGS="$LDFLAGS -lc"
303                 SXE_CHECK_BROKEN_DIRNAME
304         else
305                 have_dirname=no
306         fi
307 ])dnl SXE_CHECK_DIRNAME
308
309 AC_DEFUN([_SXE_CHECK_DIRNAME_SIDE_EFFECT], [dnl
310         ## defines sxe_func_dirname_side_effect
311         ## and DIRNAME_SIDE_EFFECT
312         pushdef([resvar], [sxe_func_dirname_side_effect])
313
314         AC_MSG_CHECKING([whether dirname modifies its argument by side-effect])
315         AC_RUN_IFELSE([AC_LANG_SOURCE([[
316 #ifdef HAVE_LIBGEN_H
317 #  include <libgen.h>
318 #endif
319
320 int dirname_modifies_argument()
321 {
322         char p[11] = "somefile\000";
323         dirname(p);
324         return ((p[0] == '.' && p[1] == '\0') == 0);
325 }
326
327 int main()
328 {
329         return dirname_modifies_argument();
330 }
331                 ]])],
332                 resvar[=yes],
333                 resvar[=no],
334                 resvar[=no])
335         AC_MSG_RESULT([$]resvar)
336
337         if test "$[]resvar[]" = "yes"; then
338                 AC_DEFINE([DIRNAME_SIDE_EFFECT], [1],
339                         [Whether dirname() operates by side effect])
340         fi
341
342         popdef([resvar])
343 ])dnl _SXE_CHECK_DIRNAME_SIDE_EFFECT
344
345 AC_DEFUN([_SXE_CHECK_DIRNAME_RETVAL], [dnl
346         ## arg #1 is the return type, char* by default
347         ## arg #2 is the final test,
348         ##        pass something that is expected to be true here
349         ##        the return value is stored in a variable `r'
350         ## defines sxe_func_dirname_returns_<ret_t> and
351         ## sxe_func_dirname_returns=$1 if true
352         pushdef([ret_t], ifelse($1, [], [char*],$1))
353         pushdef([resvar_body], [sxe_func_dirname_returns])
354         pushdef([resvar], resvar_body[_]translit(ret_t, [ -*], [__X]))
355         pushdef([rettest], ifelse($2, [], [[[[r[0] == '.' && r[1] == '\000']]]],$2))
356
357         AC_MSG_CHECKING([whether dirname returns ]ret_t)
358         AC_RUN_IFELSE([AC_LANG_SOURCE([[
359 #ifdef HAVE_LIBGEN_H
360 #  include <libgen.h>
361 #endif
362
363 int main()
364 {
365         ]]ret_t[[ r;
366         char p[11] = "somefile\000";
367         int res;
368
369         r = dirname(p);
370         res = ((]]rettest[[) == 0);
371         return res;
372 }
373                 ]])],
374                 resvar[=yes],
375                 resvar[=no],
376                 resvar[=no])
377         AC_MSG_RESULT([$]resvar)
378
379         if test "$[]resvar[]" = "yes"; then
380                 resvar_body[=]ret_t
381                 AC_DEFINE_UNQUOTED([DIRNAME_RET_T], ret_t,
382                         [return type of dirname()])
383         fi
384
385         popdef([resvar_body])
386         popdef([resvar])
387         popdef([ret_t])
388         popdef([rettest])
389 ])dnl _SXE_CHECK_DIRNAME_RETVAL
390
391 AC_DEFUN([_SXE_CHECK_DIRNAME_RETVAL_OWNER], [dnl
392         ## defines sxe_func_dirname_retval_owner,
393         ## values are either "sys" or "user"
394         pushdef([resvar], [sxe_func_dirname_retval_owner])
395
396         malloc_check=${MALLOC_CHECK_}
397         ## Turn off the stupid glibc 2.5 stack trace check. We *know* we may
398         ## do something bad here :-)
399         MALLOC_CHECK_=0
400         export MALLOC_CHECK_
401         ## this test is especially critical, because some systems do not
402         ## allocate memory for the user when the return value is "."
403         ## instead they point to a static const char somewhere in their
404         ## guts which, of course, must not be furtherly modified, free'd or
405         ## anything ... took me fucking ages to find out what's going on
406         ## so let's drink to the morons responsible for THAT!
407         AC_MSG_CHECKING([to whom belongs the object returned by dirname])
408         if test "$opsys" = "darwin" ; then
409            resvar=sys
410         else
411         AC_RUN_IFELSE([AC_LANG_SOURCE([[
412 #ifdef HAVE_LIBGEN_H
413 #  include <libgen.h>
414 #endif
415
416 #define FOLLOW_FREE_STRATEGY            1
417 #define FOLLOW_REALLOC_STRATEGY         1
418
419 int owner_of_object_returned_by_dirname()
420 {
421         void *r;  /* any pointer is just fine */
422         char p[11] = "./somefile\000";
423
424         r = (void*)dirname(p);
425 #if FOLLOW_REALLOC_STRATEGY
426         /* reallocation would help already */
427         r = realloc(r, 4096);
428 #endif
429 #if FOLLOW_FREE_STRATEGY
430         /* if r was ours we should be able to free it */
431         free(r);
432 #endif
433 #if FOLLOW_FREE_STRATEGY || FOLLOW_REALLOC_STRATEGY
434         return 0;
435 #else
436         return 1;
437 #endif
438 }
439
440 int main()
441 {
442         return owner_of_object_returned_by_dirname();
443 }
444                 ]])],
445                 resvar[=user],
446                 resvar[=sys],
447                 resvar[=sys])
448         fi
449         if test "${malloc_check}" = "" ; then
450                 unset MALLOC_CHECK_
451         else
452                 MALLOC_CHECK_=${malloc_check}
453         fi
454         AC_MSG_RESULT([$]resvar)
455
456         if test "$[]resvar[]" = "user"; then
457                 AC_DEFINE([DIRNAME_USER_OWNS_RETVAL], [1],
458                         [Whether the user space owns the retval of dirname()])
459         elif test "$[]resvar[]" = "sys"; then
460                 AC_DEFINE([DIRNAME_SYS_OWNS_RETVAL], [1],
461                         [Whether the system owns the retval of dirname()])
462         fi
463
464         popdef([resvar])
465 ])dnl _SXE_CHECK_DIRNAME_RETVAL_OWNER
466
467 AC_DEFUN([_SXE_CHECK_DIRNAME_ON_PROTECTED_MEMORY], [dnl
468         ## defines sxe_func_dirname_accepts_protmem
469         pushdef([resvar], [sxe_func_dirname_accepts_protmem])
470
471         AC_MSG_CHECKING([whether dirname can operate on protected mem blocks])
472         AC_RUN_IFELSE([AC_LANG_SOURCE([[
473 #ifdef HAVE_LIBGEN_H
474 #  include <libgen.h>
475 #endif
476
477 int dirname_can_operate_on_protected_mem_blocks()
478 {
479         dirname("./somefile");
480         return 0;
481 }
482
483 int main()
484 {
485         return dirname_can_operate_on_protected_mem_blocks();
486 }
487                 ]])],
488                 resvar[=yes],
489                 resvar[=no],
490                 resvar[=no])
491         AC_MSG_RESULT([$]resvar)
492
493         if test "$[]resvar[]" = "yes"; then
494                 AC_DEFINE([DIRNAME_ACCEPTS_PROTMEM], [1],
495                         [Whether dirname() accepts protected memory blocks])
496         fi
497
498         popdef([resvar])
499 ])dnl _SXE_CHECK_DIRNAME_ON_PROTECTED_MEMORY
500
501 AC_DEFUN([_SXE_CHECK_DIRNAME_ON_C99_RESTRICT_MEMORY], [dnl
502         ## defines sxe_func_dirname_accepts_restrmem
503         pushdef([resvar], [sxe_func_dirname_accepts_restrmem])
504
505         AC_MSG_CHECKING([whether dirname can operate on C99 restrict mem blocks])
506         AC_RUN_IFELSE([AC_LANG_SOURCE([[
507 #ifdef HAVE_STDIO_H
508 #  inlcude <stdio.h>
509 #endif
510 #ifdef HAVE_LIBGEN_H
511 #  include <libgen.h>
512 #endif
513
514 static char f[11] = "./somefile\000";
515
516 int dirname_can_operate_on_c99_restrict()
517 {
518         const char *restrict p = &f;
519         dirname((char*)p);
520         return 0;
521 }
522
523 int main()
524 {
525         return dirname_can_operate_on_c99_restrict();
526 }
527                 ]])],
528                 resvar[=yes],
529                 resvar[=no],
530                 resvar[=no])
531         AC_MSG_RESULT([$]resvar)
532
533         if test "$[]resvar[]" = "yes"; then
534                 AC_DEFINE([DIRNAME_ACCEPTS_RESTRMEM], [1],
535                         [Whether dirname() accepts restricted memory blocks])
536         fi
537
538         popdef([resvar])
539 ])dnl _SXE_CHECK_DIRNAME_ON_C99_RESTRICT_MEMORY
540
541 AC_DEFUN([SXE_CHECK_BROKEN_DIRNAME], [dnl
542         ## defines 3 vars, look in the sub macros to see which ones
543         _SXE_CHECK_DIRNAME_SIDE_EFFECT
544         _SXE_CHECK_DIRNAME_ON_PROTECTED_MEMORY
545         _SXE_CHECK_DIRNAME_ON_C99_RESTRICT_MEMORY
546         _SXE_CHECK_DIRNAME_RETVAL
547         _SXE_CHECK_DIRNAME_RETVAL_OWNER
548 ])dnl SXE_CHECK_BROKEN_DIRNAME
549
550
551 AC_DEFUN([SXE_CHECK_FILE_LOCK], [dnl
552         ## Determine type of mail locking from configure args and s&m headers
553         AC_MSG_CHECKING([for a type of mail spool file locking])
554         AC_MSG_RESULT([])
555
556         AC_CHECK_FUNCS([lockf flock locking])
557         ## The mail_use_xxx variables are set according to the s&m headers.
558         if test "$with_mail_locking" != "no" -a \
559                 "$mail_use_flock" = "yes"; then
560                 with_mail_locking=flock
561         elif test "$with_mail_locking" != "no" -a \
562                 "$mail_use_lockf" = "yes"; then
563                 with_mail_locking=lockf
564         elif test "$with_mail_locking" != "no" -a \
565                 "$mail_use_locking" = "yes"; then
566                 with_mail_locking=locking
567         fi
568
569         if test "$with_mail_locking" = "lockf"; then
570                 AC_DEFINE([MAIL_LOCK_LOCKF], [1], [Description here!])
571         elif test "$with_mail_locking" = "flock"; then
572                 AC_DEFINE([MAIL_LOCK_FLOCK], [1], [Description here!])
573         elif test "$with_mail_locking" = "locking"; then
574                 AC_DEFINE([MAIL_LOCK_LOCKING], [1], [Description here!])
575         elif test "$with_mail_locking" = "pop"; then
576                 with_pop=yes
577                 with_mail_locking=
578         elif test "$with_mail_locking" = "mmdf"; then
579                 AC_DEFINE([MAIL_LOCK_MMDF], [1], [Description here!])
580         else
581                 with_mail_locking="file"
582                 AC_DEFINE([MAIL_LOCK_DOT], [1], [Description here!])
583         fi
584
585         if test "$with_mail_locking" = "lockf" -a \
586                 "$ac_cv_func_lockf" != "yes"; then
587                 SXE_DIE([lockf mail locking requested but not available.])
588         elif test "$with_mail_locking" = "flock" -a \
589                 "$ac_cv_func_flock" != "yes"; then
590                 SXE_DIE([flock mail locking requested but not available.])
591         elif test "$with_mail_locking" = "locking" -a \
592                 "$ac_cv_func_locking" != "yes"; then
593                 SXE_DIE([locking mail locking requested but not available.])
594         fi
595 ])dnl SXE_CHECK_FILE_LOCK
596
597
598 dnl sxe-fs-funs.m4 ends here