Fix ttyname problem on Android.
[gpgme.git] / m4 / gnupg-ttyname.m4
1 # gnupg-ttyname.m4
2 # Copyright (C) 2010-2012 Free Software Foundation, Inc.
3 # This file is free software; the Free Software Foundation
4 # gives unlimited permission to copy and/or distribute it,
5 # with or without modifications, as long as this notice is preserved.
6 #
7 # This file is based on gnulib/m4/ttyname_r.m4 serial 8.
8 #
9
10
11 # gnupg_REPLACE_TTYNAME_R
12 #
13 # This macro is an extended version of AC_REPLACE_FUNCS(ttyname_r).
14 # It takes peculiarities in the implementation of ttyname_r in account.
15 #
16 # The macro HAVE_TTYNAME_R will be defined to 1 if the function
17 # exists; it will be defined to 0 if it does not exists or no
18 # declaration is available.
19 #
20 # The macro HAVE_POSIXDECL_TTYNAME_R is defined if ttyname_r conforms
21 # to the Posix declaration.
22 #
23 # The macro HAVE_BROKEN_TTYNAME_R is defined it ttyname_r does not work
24 # correctly with the supplied buffer size.  If this is defined the function
25 # will also be replaced.
26 #
27 # The macro REPLACE_TTYNAME_R is defined if ttyname_r is a replacement
28 # function.  This macro is useful for the definition of the prototype.
29 #
30 # If the macro "have_android_system" has a value of "yes", ttyname_r
31 # will also be replaced by our own function.
32 #
33 AC_DEFUN([gnupg_REPLACE_TTYNAME_R],
34 [
35   AC_CHECK_HEADERS([unistd.h])
36
37   AC_CHECK_DECLS_ONCE([ttyname_r])
38   if test $ac_cv_have_decl_ttyname_r = no; then
39     HAVE_DECL_TTYNAME_R=0
40   fi
41
42   AC_CHECK_FUNCS([ttyname_r])
43   if test $ac_cv_func_ttyname_r = no; then
44     HAVE_TTYNAME_R=0
45     AC_LIBOBJ([ttyname_r])
46     AC_DEFINE([REPLACE_TTYNAME_R],[1],
47               [Define to 1 if ttyname_r is a replacement function.])
48   else
49     HAVE_TTYNAME_R=1
50     dnl On MacOS X 10.4 (and Solaris 10 without __EXTENSIONS__)
51     dnl the return type is 'char *', not 'int'.
52     AC_CACHE_CHECK([whether ttyname_r is compatible with its POSIX signature],
53       [gnupg_cv_func_ttyname_r_posix],
54       [AC_COMPILE_IFELSE(
55          [AC_LANG_PROGRAM(
56             [[#include <stddef.h>
57               #include <unistd.h>]],
58             [[*ttyname_r (0, NULL, 0);]])
59          ],
60          [gnupg_cv_func_ttyname_r_posix=no],
61          [gnupg_cv_func_ttyname_r_posix=yes])
62       ])
63     if test $gnupg_cv_func_ttyname_r_posix = no; then
64       AC_LIBOBJ([ttyname_r])
65       AC_DEFINE([REPLACE_TTYNAME_R],[1])
66     elif test "$have_android_system" = yes; then
67       # Android has ttyname and ttyname_r but they are only stubs and
68       # print an annoying warning message.  Thus we need to replace
69       # ttyname_r with our own dummy function.
70       AC_LIBOBJ([ttyname_r])
71       AC_DEFINE([REPLACE_TTYNAME_R],[1])
72     else
73       AC_DEFINE([HAVE_POSIXDECL_TTYNAME_R], [1],
74         [Define if the ttyname_r function has a POSIX compliant declaration.])
75       dnl On Solaris 10, both ttyname_r functions (the one with the non-POSIX
76       dnl declaration and the one with the POSIX declaration) refuse to do
77       dnl anything when the output buffer is less than 128 bytes large.
78       dnl On OSF/1 5.1, ttyname_r ignores the buffer size and assumes the
79       dnl buffer is large enough.
80       AC_REQUIRE([AC_CANONICAL_HOST])
81       AC_CACHE_CHECK([whether ttyname_r works with small buffers],
82         [gnupg_cv_func_ttyname_r_works],
83         [
84           dnl Initial guess, used when cross-compiling or when /dev/tty cannot
85           dnl be opened.
86 changequote(,)dnl
87           case "$host_os" in
88                       # Guess no on Solaris.
89             solaris*) gnupg_cv_func_ttyname_r_works="guessing no" ;;
90                       # Guess no on OSF/1.
91             osf*)     gnupg_cv_func_ttyname_r_works="guessing no" ;;
92                       # Guess yes otherwise.
93             *)        gnupg_cv_func_ttyname_r_works="guessing yes" ;;
94           esac
95 changequote([,])dnl
96           AC_RUN_IFELSE(
97             [AC_LANG_SOURCE([[
98 #include <fcntl.h>
99 #include <unistd.h>
100 int
101 main (void)
102 {
103   int result = 0;
104   int fd;
105   char buf[31]; /* use any size < 128 here */
106
107   fd = open ("/dev/tty", O_RDONLY);
108   if (fd < 0)
109     result |= 16;
110   else if (ttyname_r (fd, buf, sizeof (buf)) != 0)
111     result |= 17;
112   else if (ttyname_r (fd, buf, 1) == 0)
113     result |= 18;
114   return result;
115 }]])],
116             [gnupg_cv_func_ttyname_r_works=yes],
117             [case $? in
118                17 | 18) gnupg_cv_func_ttyname_r_works=no ;;
119              esac],
120             [:])
121         ])
122       case "$gnupg_cv_func_ttyname_r_works" in
123         *yes) ;;
124         *) AC_LIBOBJ([ttyname_r])
125            AC_DEFINE([REPLACE_TTYNAME_R],[1])
126            AC_DEFINE([HAVE_BROKEN_TTYNAME_R], [1],
127                      [Define if ttyname_r is does not work with small buffers])
128            ;;
129       esac
130     fi
131   fi
132 ])