1 /* Replacements for Posix functions and Posix functionality for MS-Windows.
2
3 Copyright (C) 2013-2022 Free Software Foundation, Inc.
4 This file is part of GNU Make.
5
6 GNU Make is free software; you can redistribute it and/or modify it under the
7 terms of the GNU General Public License as published by the Free Software
8 Foundation; either version 3 of the License, or (at your option) any later
9 version.
10
11 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along with
16 this program. If not, see <https://www.gnu.org/licenses/>. */
17
18 #include "makeint.h"
19
20 #include <string.h>
21 #include <io.h>
22 #include <stdarg.h>
23 #include <errno.h>
24 #include <windows.h>
25
26 #include "dlfcn.h"
27
28 #include "job.h"
29
30 #if MAKE_LOAD
31
32 /* Support for dynamic loading of objects. */
33
34 static DWORD last_err;
35
36 void *
37 dlopen (const char *file, int mode)
38 {
39 char dllfn[MAX_PATH], *p;
40 HANDLE dllhandle;
41
42 if ((mode & ~(RTLD_LAZY | RTLD_NOW | RTLD_GLOBAL)) != 0)
43 {
44 errno = EINVAL;
45 last_err = ERROR_INVALID_PARAMETER;
46 return NULL;
47 }
48
49 if (!file)
50 dllhandle = GetModuleHandle (NULL);
51 else
52 {
53 /* MSDN says to be sure to use backslashes in the DLL file name. */
54 strcpy (dllfn, file);
55 for (p = dllfn; *p; p++)
56 if (*p == '/')
57 *p = '\\';
58
59 dllhandle = LoadLibrary (dllfn);
60 }
61 if (!dllhandle)
62 last_err = GetLastError ();
63
64 return dllhandle;
65 }
66
67 char *
68 dlerror (void)
69 {
70 static char errbuf[1024];
71 DWORD ret;
72
73 if (!last_err)
74 return NULL;
75
76 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
77 | FORMAT_MESSAGE_IGNORE_INSERTS,
78 NULL, last_err, 0, errbuf, sizeof (errbuf), NULL);
79 while (ret > 0 && (errbuf[ret - 1] == '\n' || errbuf[ret - 1] == '\r'))
80 --ret;
81
82 errbuf[ret] = '\0';
83 if (!ret)
84 sprintf (errbuf, "Error code %lu", last_err);
85
86 last_err = 0;
87 return errbuf;
88 }
89
90 void *
91 dlsym (void *handle, const char *name)
92 {
93 FARPROC addr = NULL;
94
95 if (!handle || handle == INVALID_HANDLE_VALUE)
96 {
97 last_err = ERROR_INVALID_PARAMETER;
98 return NULL;
99 }
100
101 addr = GetProcAddress (handle, name);
102 if (!addr)
103 last_err = GetLastError ();
104
105 return (void *)addr;
106 }
107
108 int
109 dlclose (void *handle)
110 {
111 if (!handle || handle == INVALID_HANDLE_VALUE)
112 return -1;
113 if (!FreeLibrary (handle))
114 return -1;
115
116 return 0;
117 }
118
119
120 #endif /* MAKE_LOAD */
121
122
123 /* MS runtime's isatty returns non-zero for any character device,
124 including the null device, which is not what we want. */
125 int
126 isatty (int fd)
127 {
128 HANDLE fh = (HANDLE) _get_osfhandle (fd);
129 DWORD con_mode;
130
131 if (fh == INVALID_HANDLE_VALUE)
132 {
133 errno = EBADF;
134 return 0;
135 }
136 if (GetConsoleMode (fh, &con_mode))
137 return 1;
138
139 errno = ENOTTY;
140 return 0;
141 }
142
143 char *
144 ttyname (int fd)
145 {
146 /* This "knows" that Make only asks about stdout and stderr. A more
147 sophisticated implementation should test whether FD is open for
148 input or output. We can do that by looking at the mode returned
149 by GetConsoleMode. */
150 return "CONOUT$";
151 }