fix: align POSIX stdio and argument handling, clarify Intel iwlwifi licensing
This commit is contained in:
@@ -12,4 +12,4 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define MONTAUK_BUILD_NUMBER 92
|
#define MONTAUK_BUILD_NUMBER 94
|
||||||
|
|||||||
@@ -5,7 +5,9 @@
|
|||||||
* Register offsets, firmware command IDs and wire-format structures follow
|
* Register offsets, firmware command IDs and wire-format structures follow
|
||||||
* Intel's dual BSD/GPLv2-licensed iwlwifi API headers, as consolidated in
|
* Intel's dual BSD/GPLv2-licensed iwlwifi API headers, as consolidated in
|
||||||
* OpenBSD's if_iwxreg.h (ISC/BSD). Only the subset used by this driver is
|
* OpenBSD's if_iwxreg.h (ISC/BSD). Only the subset used by this driver is
|
||||||
* kept. See 0:/os/licenses/NOTICES.txt for the full attribution.
|
* kept. MontaukOS relies on the BSD license option; see
|
||||||
|
* montaukos.org/THIRD-PARTY-NOTICES.txt and 0:/os/licenses/NOTICES.txt for
|
||||||
|
* the full attribution and license terms.
|
||||||
*
|
*
|
||||||
* Copyright (c) 2026 Daniel Hammer
|
* Copyright (c) 2026 Daniel Hammer
|
||||||
* Portions Copyright (c) 2017 Intel Deutschland GmbH
|
* Portions Copyright (c) 2017 Intel Deutschland GmbH
|
||||||
|
|||||||
+11
-2
@@ -714,8 +714,17 @@ namespace Ipc {
|
|||||||
g_handleTableLocks[slot].Acquire();
|
g_handleTableLocks[slot].Acquire();
|
||||||
uint64_t& bm0 = g_handleBitmaps[slot][0];
|
uint64_t& bm0 = g_handleBitmaps[slot][0];
|
||||||
uint64_t& bm1 = g_handleBitmaps[slot][1];
|
uint64_t& bm1 = g_handleBitmaps[slot][1];
|
||||||
// Find first zero bit in bitmap (free slot)
|
// Find first zero bit in bitmap (free slot).
|
||||||
uint64_t bits0 = ~bm0;
|
//
|
||||||
|
// Handles 0, 1 and 2 are never allocated: to POSIX code those numbers
|
||||||
|
// ARE stdin/stdout/stderr, and the libc routes read()/write() on them
|
||||||
|
// to the terminal (SYS_GETCHAR/SYS_PUTCHAR) rather than to this table.
|
||||||
|
// Handing them out as file handles makes the two meanings collide --
|
||||||
|
// a program's third open() would own "stderr", and every write(2, ...)
|
||||||
|
// it made would land in that file instead of on screen. Reserving them
|
||||||
|
// here rather than at process setup keeps the rule in one place and
|
||||||
|
// immune to a stale bitmap.
|
||||||
|
uint64_t bits0 = ~bm0 & ~0x7ULL;
|
||||||
uint64_t bits1 = ~bm1;
|
uint64_t bits1 = ~bm1;
|
||||||
if (bits0) {
|
if (bits0) {
|
||||||
int i = __builtin_ctzll(bits0);
|
int i = __builtin_ctzll(bits0);
|
||||||
|
|||||||
@@ -356,7 +356,64 @@ License: Intel redistributable firmware license
|
|||||||
|
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
14. Default wallpaper photograph
|
14. Intel iwlwifi register definitions
|
||||||
|
================================================================================
|
||||||
|
The register offsets, firmware command identifiers, and wire-format structures
|
||||||
|
in kernel/src/Drivers/Net/Wifi/IwxReg.hpp are an adapted subset of the Intel
|
||||||
|
iwlwifi API definitions as consolidated in OpenBSD's if_iwxreg.h. MontaukOS
|
||||||
|
relies on the BSD license option of the upstream dual BSD/GPLv2 license.
|
||||||
|
|
||||||
|
Copyright (c) 2017 Intel Deutschland GmbH
|
||||||
|
Copyright (c) 2018-2019 Intel Corporation
|
||||||
|
Copyright (c) 2026 Daniel Hammer
|
||||||
|
|
||||||
|
This file is provided under a dual BSD/GPLv2 license. When using or
|
||||||
|
redistributing the upstream material, you may do so under either license.
|
||||||
|
MontaukOS relies on the BSD license option for the adapted material.
|
||||||
|
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
* Neither the name Intel Corporation nor the names of its contributors may be
|
||||||
|
used to endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
15. Intel iwlwifi firmware
|
||||||
|
================================================================================
|
||||||
|
Shipped as binary firmware payloads in the bootable image:
|
||||||
|
|
||||||
|
programs/data/firmware/intel/iwlwifi-so-a0-gf-a0-89.ucode
|
||||||
|
programs/data/firmware/intel/iwlwifi-so-a0-gf-a0.pnvm
|
||||||
|
|
||||||
|
These files are redistributable Intel iwlwifi firmware obtained from the
|
||||||
|
linux-firmware project. The files remain Intel property and are not licensed
|
||||||
|
under the MontaukOS Software License. The full license text is included on
|
||||||
|
the MontaukOS ISO at 0:/os/licenses/Intel-iwlwifi-firmware.txt.
|
||||||
|
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
16. Default wallpaper photograph
|
||||||
================================================================================
|
================================================================================
|
||||||
Shipped as the default login-screen wallpaper on the ISO
|
Shipped as the default login-screen wallpaper on the ISO
|
||||||
(0:/os/wallpapers/default.jpg): a photograph of blossoms against misty hills.
|
(0:/os/wallpapers/default.jpg): a photograph of blossoms against misty hills.
|
||||||
@@ -374,7 +431,7 @@ License: Unsplash License (https://unsplash.com/license)
|
|||||||
similar or competing service.
|
similar or competing service.
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
15. Flanterm (text renderer for kernel debug log)
|
17. Flanterm (text renderer for kernel debug log)
|
||||||
================================================================================
|
================================================================================
|
||||||
Compiled into the MontaukOS kernel (see kernel/src/Libraries/flanterm).
|
Compiled into the MontaukOS kernel (see kernel/src/Libraries/flanterm).
|
||||||
The files are taken unmodified from the flanterm project.
|
The files are taken unmodified from the flanterm project.
|
||||||
@@ -410,7 +467,7 @@ License: BSD-2-Clause license (https://raw.githubusercontent.com/Mintsuki/Flante
|
|||||||
|
|
||||||
|
|
||||||
================================================================================
|
================================================================================
|
||||||
16. GNU Compiler Collection (GCC) and GNU Binutils (Montauk SDK)
|
18. GNU Compiler Collection (GCC) and GNU Binutils (Montauk SDK)
|
||||||
================================================================================
|
================================================================================
|
||||||
The MontaukOS SDK includes native ports of GCC 14.2.0 and GNU Binutils 2.43.1
|
The MontaukOS SDK includes native ports of GCC 14.2.0 and GNU Binutils 2.43.1
|
||||||
at 0:/sdk/. The GCC tools include gcc, g++, cpp, cc1, and cc1plus. The Binutils
|
at 0:/sdk/. The GCC tools include gcc, g++, cpp, cc1, and cc1plus. The Binutils
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
Copyright (c) 2006-2015, Intel Corporation.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution. Redistribution and use in binary form, without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions must reproduce the above copyright notice and the
|
||||||
|
following disclaimer in the documentation and/or other materials
|
||||||
|
provided with the distribution.
|
||||||
|
* Neither the name of Intel Corporation nor the names of its suppliers
|
||||||
|
may be used to endorse or promote products derived from this software
|
||||||
|
without specific prior written permission.
|
||||||
|
* No reverse engineering, decompilation, or disassembly of this software
|
||||||
|
is permitted.
|
||||||
|
|
||||||
|
Limited patent license. Intel Corporation grants a world-wide,
|
||||||
|
royalty-free, non-exclusive license under patents it now or hereafter
|
||||||
|
owns or controls to make, have made, use, import, offer to sell and
|
||||||
|
sell ("Utilize") this software, but solely to the extent that any
|
||||||
|
such patent is necessary to Utilize the software alone, or in
|
||||||
|
combination with an operating system licensed under an approved Open
|
||||||
|
Source license as listed by the Open Source Initiative at
|
||||||
|
http://opensource.org/licenses. The patent license shall not apply to
|
||||||
|
any other combinations which include this software. No hardware per
|
||||||
|
se is licensed hereunder.
|
||||||
|
|
||||||
|
DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||||
|
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||||
|
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||||
|
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGE.
|
||||||
@@ -34,8 +34,11 @@
|
|||||||
#define PRIxPTR "lx"
|
#define PRIxPTR "lx"
|
||||||
#define PRIXPTR "lX"
|
#define PRIXPTR "lX"
|
||||||
#define PRIdMAX "ld"
|
#define PRIdMAX "ld"
|
||||||
|
#define PRIiMAX "li"
|
||||||
#define PRIuMAX "lu"
|
#define PRIuMAX "lu"
|
||||||
|
#define PRIoMAX "lo"
|
||||||
#define PRIxMAX "lx"
|
#define PRIxMAX "lx"
|
||||||
|
#define PRIXMAX "lX"
|
||||||
|
|
||||||
#define SCNd8 "d"
|
#define SCNd8 "d"
|
||||||
#define SCNd16 "d"
|
#define SCNd16 "d"
|
||||||
@@ -56,5 +59,10 @@
|
|||||||
#define SCNdPTR "ld"
|
#define SCNdPTR "ld"
|
||||||
#define SCNuPTR "lu"
|
#define SCNuPTR "lu"
|
||||||
#define SCNxPTR "lx"
|
#define SCNxPTR "lx"
|
||||||
|
#define SCNdMAX "ld"
|
||||||
|
#define SCNiMAX "li"
|
||||||
|
#define SCNuMAX "lu"
|
||||||
|
#define SCNoMAX "lo"
|
||||||
|
#define SCNxMAX "lx"
|
||||||
|
|
||||||
#endif /* _LIBC_INTTYPES_H */
|
#endif /* _LIBC_INTTYPES_H */
|
||||||
|
|||||||
@@ -427,7 +427,7 @@ static inline int mtk_getargs(char *buf, unsigned long max_len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline int mtk_getexecpath(char *buf, unsigned long maxLen) {
|
static inline int mtk_getexecpath(char *buf, unsigned long maxLen) {
|
||||||
return (int)mtk_syscall2(MTK_SYS_GETEXECPATH, (long)buf, (long)maxLen);
|
return (int)_mtk_syscall2(MTK_SYS_GETEXECPATH, (long)buf, (long)maxLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int mtk_chdir(const char *path) {
|
static inline int mtk_chdir(const char *path) {
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ double atof(const char *s);
|
|||||||
int abs(int j);
|
int abs(int j);
|
||||||
long labs(long j);
|
long labs(long j);
|
||||||
|
|
||||||
void exit(int status);
|
void exit(int status) __attribute__((noreturn));
|
||||||
void abort(void);
|
void abort(void) __attribute__((noreturn));
|
||||||
int atexit(void (*func)(void));
|
int atexit(void (*func)(void));
|
||||||
|
|
||||||
char *getenv(const char *name);
|
char *getenv(const char *name);
|
||||||
|
|||||||
@@ -91,6 +91,14 @@ void _start(void) {
|
|||||||
|
|
||||||
argbuf[len] = '\0';
|
argbuf[len] = '\0';
|
||||||
|
|
||||||
|
/* Split on spaces, honouring '...' and "..." so an argument can
|
||||||
|
contain them: `git commit -m "two words"` has to reach main()
|
||||||
|
as two arguments, not three. The quotes are removed, and the
|
||||||
|
token is rewritten in place -- the unquoted form is never
|
||||||
|
longer than the quoted one, so it always fits. Quotes are the
|
||||||
|
only metacharacter: there is no escaping and no substitution,
|
||||||
|
which is deliberate. The kernel hands over one flat string
|
||||||
|
(SYS_GETARGS) and this is a tokenizer, not a shell. */
|
||||||
char* p = argbuf;
|
char* p = argbuf;
|
||||||
while (*p != '\0' && argc < 255) {
|
while (*p != '\0' && argc < 255) {
|
||||||
while (*p == ' ') {
|
while (*p == ' ') {
|
||||||
@@ -101,15 +109,27 @@ void _start(void) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
argv[argc++] = p;
|
char* out = p;
|
||||||
|
argv[argc++] = out;
|
||||||
|
|
||||||
while (*p != '\0' && *p != ' ') {
|
char quote = 0;
|
||||||
|
while (*p != '\0' && (quote != 0 || *p != ' ')) {
|
||||||
|
if (quote == 0 && (*p == '"' || *p == '\'')) {
|
||||||
|
quote = *p++;
|
||||||
|
} else if (quote != 0 && *p == quote) {
|
||||||
|
quote = 0;
|
||||||
|
p++;
|
||||||
|
} else {
|
||||||
|
*out++ = *p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Step over the separator before terminating: the write
|
||||||
|
below lands on the byte p is about to leave behind. */
|
||||||
|
if (*p != '\0') {
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
*out = '\0';
|
||||||
if (*p != '\0') {
|
|
||||||
*p++ = '\0';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -2081,8 +2081,35 @@ int open(const char *path, int flags, ...) {
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The standard descriptors are the terminal, NOT file handles.
|
||||||
|
*
|
||||||
|
* 0/1/2 are not handles the kernel ever issued -- SYS_OPEN allocates from its
|
||||||
|
* own space and would have to return 0 for these to line up, which it does
|
||||||
|
* not. Passing them to SYS_READ/SYS_FWRITE addresses whatever handle happens
|
||||||
|
* to hold that number, or fails: before this, every write(2, ...) was
|
||||||
|
* silently discarded, so a POSIX program that reports errors with write()
|
||||||
|
* rather than fprintf() printed nothing at all. stdio already routes std
|
||||||
|
* streams to SYS_PUTCHAR (see fwrite/fprintf); these do the same, so the two
|
||||||
|
* paths agree.
|
||||||
|
*/
|
||||||
int read(int fd, void *buf, size_t count) {
|
int read(int fd, void *buf, size_t count) {
|
||||||
if (buf == NULL) return -1;
|
if (buf == NULL) return -1;
|
||||||
|
|
||||||
|
if (fd == STDIN_FILENO) {
|
||||||
|
/* Line-oriented, like the terminal itself: return as soon as a
|
||||||
|
line is complete rather than blocking for the full count. */
|
||||||
|
char *dst = (char *)buf;
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < count) {
|
||||||
|
int c = fgetc(stdin);
|
||||||
|
if (c == EOF) break;
|
||||||
|
dst[i++] = (char)c;
|
||||||
|
if (c == '\n') break;
|
||||||
|
}
|
||||||
|
return (int)i;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long pos = (fd >= 0 && fd < _FD_POS_MAX) ? _fd_pos[fd] : 0;
|
unsigned long pos = (fd >= 0 && fd < _FD_POS_MAX) ? _fd_pos[fd] : 0;
|
||||||
int ret = (int)_zos_syscall4(SYS_READ, (long)fd, (long)buf, (long)pos, (long)count);
|
int ret = (int)_zos_syscall4(SYS_READ, (long)fd, (long)buf, (long)pos, (long)count);
|
||||||
if (ret > 0 && fd >= 0 && fd < _FD_POS_MAX)
|
if (ret > 0 && fd >= 0 && fd < _FD_POS_MAX)
|
||||||
@@ -2092,6 +2119,14 @@ int read(int fd, void *buf, size_t count) {
|
|||||||
|
|
||||||
int write(int fd, const void *buf, size_t count) {
|
int write(int fd, const void *buf, size_t count) {
|
||||||
if (buf == NULL) return -1;
|
if (buf == NULL) return -1;
|
||||||
|
|
||||||
|
if (fd == STDOUT_FILENO || fd == STDERR_FILENO) {
|
||||||
|
const char *src = (const char *)buf;
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
_zos_syscall1(SYS_PUTCHAR, (long)(unsigned char)src[i]);
|
||||||
|
return (int)count;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned long pos = (fd >= 0 && fd < _FD_POS_MAX) ? _fd_pos[fd] : 0;
|
unsigned long pos = (fd >= 0 && fd < _FD_POS_MAX) ? _fd_pos[fd] : 0;
|
||||||
int ret = (int)_zos_syscall4(SYS_FWRITE, (long)fd, (long)buf, (long)pos, (long)count);
|
int ret = (int)_zos_syscall4(SYS_FWRITE, (long)fd, (long)buf, (long)pos, (long)count);
|
||||||
if (ret > 0 && fd >= 0 && fd < _FD_POS_MAX)
|
if (ret > 0 && fd >= 0 && fd < _FD_POS_MAX)
|
||||||
|
|||||||
Binary file not shown.
@@ -34,8 +34,11 @@
|
|||||||
#define PRIxPTR "lx"
|
#define PRIxPTR "lx"
|
||||||
#define PRIXPTR "lX"
|
#define PRIXPTR "lX"
|
||||||
#define PRIdMAX "ld"
|
#define PRIdMAX "ld"
|
||||||
|
#define PRIiMAX "li"
|
||||||
#define PRIuMAX "lu"
|
#define PRIuMAX "lu"
|
||||||
|
#define PRIoMAX "lo"
|
||||||
#define PRIxMAX "lx"
|
#define PRIxMAX "lx"
|
||||||
|
#define PRIXMAX "lX"
|
||||||
|
|
||||||
#define SCNd8 "d"
|
#define SCNd8 "d"
|
||||||
#define SCNd16 "d"
|
#define SCNd16 "d"
|
||||||
@@ -56,5 +59,10 @@
|
|||||||
#define SCNdPTR "ld"
|
#define SCNdPTR "ld"
|
||||||
#define SCNuPTR "lu"
|
#define SCNuPTR "lu"
|
||||||
#define SCNxPTR "lx"
|
#define SCNxPTR "lx"
|
||||||
|
#define SCNdMAX "ld"
|
||||||
|
#define SCNiMAX "li"
|
||||||
|
#define SCNuMAX "lu"
|
||||||
|
#define SCNoMAX "lo"
|
||||||
|
#define SCNxMAX "lx"
|
||||||
|
|
||||||
#endif /* _LIBC_INTTYPES_H */
|
#endif /* _LIBC_INTTYPES_H */
|
||||||
|
|||||||
@@ -426,7 +426,7 @@ static inline int mtk_getargs(char *buf, unsigned long max_len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline int mtk_getexecpath(char *buf, unsigned long maxLen) {
|
static inline int mtk_getexecpath(char *buf, unsigned long maxLen) {
|
||||||
return (int)mtk_syscall2(MTK_SYS_GETEXECPATH, (long)buf, (long)maxLen);
|
return (int)_mtk_syscall2(MTK_SYS_GETEXECPATH, (long)buf, (long)maxLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int mtk_chdir(const char *path) {
|
static inline int mtk_chdir(const char *path) {
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ double atof(const char *s);
|
|||||||
int abs(int j);
|
int abs(int j);
|
||||||
long labs(long j);
|
long labs(long j);
|
||||||
|
|
||||||
void exit(int status);
|
void exit(int status) __attribute__((noreturn));
|
||||||
void abort(void);
|
void abort(void) __attribute__((noreturn));
|
||||||
int atexit(void (*func)(void));
|
int atexit(void (*func)(void));
|
||||||
|
|
||||||
char *getenv(const char *name);
|
char *getenv(const char *name);
|
||||||
|
|||||||
Reference in New Issue
Block a user