Squash commits for public release
This commit is contained in:
115
libs/libc/stdlib/env.c
Normal file
115
libs/libc/stdlib/env.c
Normal file
@@ -0,0 +1,115 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static void free_var(const char* string)
|
||||
{
|
||||
// TODO: Implement me!
|
||||
}
|
||||
|
||||
char* getenv(const char* name)
|
||||
{
|
||||
size_t len = strlen(name);
|
||||
for (int i = 0; environ[i]; i++) {
|
||||
const char* envv = environ[i];
|
||||
char* eqpos = strchr(envv, '=');
|
||||
if (!eqpos) {
|
||||
continue;
|
||||
}
|
||||
size_t curlen = (size_t)(eqpos - envv);
|
||||
if (curlen == len && strncmp(name, envv, len) == 0) {
|
||||
return (char*)&envv[len + 1];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int setenv(const char* name, const char* value, int overwrite)
|
||||
{
|
||||
if (!overwrite && getenv(name)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int name_len = strlen(name);
|
||||
int value_len = strlen(value);
|
||||
int len = name_len + 1 + value_len;
|
||||
char* string = (char*)malloc(len + 1);
|
||||
strncpy(string, name, name_len);
|
||||
string[name_len] = '=';
|
||||
strncpy(&string[name_len + 1], value, value_len);
|
||||
string[len] = '\0';
|
||||
return putenv(string);
|
||||
}
|
||||
|
||||
int putenv(char* string)
|
||||
{
|
||||
char* pos = strchr(string, '=');
|
||||
if (!pos) {
|
||||
return unsetenv(string);
|
||||
}
|
||||
|
||||
size_t len = (size_t)(pos - string);
|
||||
int env_i = 0;
|
||||
for (; environ[env_i]; env_i++) {
|
||||
const char* envv = environ[env_i];
|
||||
char* eqpos = strchr(envv, '=');
|
||||
if (!eqpos) {
|
||||
continue;
|
||||
}
|
||||
size_t curlen = (size_t)(eqpos - envv);
|
||||
if (len != curlen) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp(string, envv, len) == 0) {
|
||||
free_var(envv);
|
||||
environ[env_i] = string;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char** new_environ = (char**)malloc(sizeof(char*) * (env_i + 2));
|
||||
for (int i = 0; i < env_i; i++) {
|
||||
new_environ[i] = environ[i];
|
||||
}
|
||||
new_environ[env_i] = string;
|
||||
new_environ[env_i + 1] = NULL;
|
||||
|
||||
extern int __environ_malloced;
|
||||
if (__environ_malloced) {
|
||||
free(environ);
|
||||
}
|
||||
environ = new_environ;
|
||||
__environ_malloced = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int unsetenv(const char* name)
|
||||
{
|
||||
size_t len = strlen(name);
|
||||
int env_i = 0;
|
||||
int remove_pos = 0;
|
||||
const char* remove_env = NULL;
|
||||
for (; environ[env_i]; env_i++) {
|
||||
const char* envv = environ[env_i];
|
||||
char* eqpos = strchr(envv, '=');
|
||||
if (!eqpos) {
|
||||
continue;
|
||||
}
|
||||
size_t curlen = (size_t)(eqpos - envv);
|
||||
if (len != curlen) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strncmp(name, envv, len) == 0) {
|
||||
remove_pos = env_i;
|
||||
remove_env = envv;
|
||||
}
|
||||
}
|
||||
|
||||
size_t move_len = ((env_i - 1) - remove_pos) * sizeof(char*);
|
||||
memmove(&environ[remove_pos], &environ[remove_pos + 1], move_len);
|
||||
free_var(remove_env);
|
||||
return 0;
|
||||
}
|
||||
15
libs/libc/stdlib/exit.c
Normal file
15
libs/libc/stdlib/exit.c
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
void exit(int status)
|
||||
{
|
||||
DO_SYSCALL_1(SYS_EXIT, status);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
void abort()
|
||||
{
|
||||
raise(SIGABRT);
|
||||
exit(127);
|
||||
}
|
||||
50
libs/libc/stdlib/pts.c
Normal file
50
libs/libc/stdlib/pts.c
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#define _PATH_PTS "/dev/pts"
|
||||
#define MASTER_PTY(dev) (major(dev) == 128)
|
||||
#define SLAVE_PTY(dev) (major(dev) == 136)
|
||||
|
||||
int posix_openpt(int flags)
|
||||
{
|
||||
return open("/dev/ptmx", flags);
|
||||
}
|
||||
|
||||
int ptsname_r(int fd, char* buf, size_t buflen)
|
||||
{
|
||||
int len = strlen(_PATH_PTS);
|
||||
if (buflen < len + 2) {
|
||||
set_errno(ERANGE);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
stat_t stat;
|
||||
if (fstat(fd, &stat) < 0) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
if (!MASTER_PTY(stat.st_dev)) {
|
||||
set_errno(ENOTTY);
|
||||
return -ENOTTY;
|
||||
}
|
||||
|
||||
int ptyno = minor(stat.st_dev);
|
||||
|
||||
char* p = strcpy(buf, _PATH_PTS);
|
||||
p[len + 0] = '0' + ptyno;
|
||||
p[len + 1] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char ptsbuf[32];
|
||||
char* ptsname(int fd)
|
||||
{
|
||||
if (ptsname_r(fd, ptsbuf, sizeof(ptsbuf)) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return ptsbuf;
|
||||
}
|
||||
144
libs/libc/stdlib/tools.c
Normal file
144
libs/libc/stdlib/tools.c
Normal file
@@ -0,0 +1,144 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int atoi(const char* s)
|
||||
{
|
||||
// FIXME: Add overflow checks
|
||||
int res = 0;
|
||||
int len = strlen(s);
|
||||
int mul = 1;
|
||||
for (int i = 0; i < len; i++) {
|
||||
mul *= 10;
|
||||
}
|
||||
for (int i = 0; i < len; i++) {
|
||||
mul /= 10;
|
||||
res += (s[i] - '0') * mul;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
long strtol(const char* nptr, char** endptr, int base)
|
||||
{
|
||||
const char* p = nptr;
|
||||
const char* endp = nptr;
|
||||
bool negative = false;
|
||||
bool overflow = false;
|
||||
unsigned long n = 0;
|
||||
|
||||
if (base < 0 || base == 1 || base > 36) {
|
||||
set_errno(EINVAL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (isspace(*p)) {
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p == '+') {
|
||||
p++;
|
||||
} else if (*p == '-') {
|
||||
negative = 1;
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p == '0') {
|
||||
p++;
|
||||
endp = p;
|
||||
if (base == 16 && (*p == 'X' || *p == 'x')) {
|
||||
p++;
|
||||
} else if (base == 0) {
|
||||
if (*p == 'X' || *p == 'x') {
|
||||
base = 16, p++;
|
||||
} else {
|
||||
base = 8;
|
||||
}
|
||||
}
|
||||
} else if (base == 0) {
|
||||
base = 10;
|
||||
}
|
||||
|
||||
unsigned long cutoff = (negative) ? -(LONG_MIN / base) : LONG_MAX / base;
|
||||
int cutlim = (negative) ? -(LONG_MIN % base) : LONG_MAX % base;
|
||||
|
||||
for (;;) {
|
||||
int digit;
|
||||
if (*p >= 'a') {
|
||||
digit = (*p - 'a') + 10;
|
||||
} else if (*p >= 'A') {
|
||||
digit = *p - 'A' + 10;
|
||||
} else if (*p <= '9') {
|
||||
digit = *p - '0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (digit < 0 || digit >= base) {
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
endp = p;
|
||||
|
||||
if (overflow) {
|
||||
if (endptr) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (n > cutoff || (n == cutoff && digit > cutlim)) {
|
||||
overflow = 1;
|
||||
continue;
|
||||
}
|
||||
n = n * base + digit;
|
||||
}
|
||||
|
||||
if (endptr) {
|
||||
*endptr = (char*)endp;
|
||||
}
|
||||
|
||||
if (overflow) {
|
||||
set_errno(ERANGE);
|
||||
return ((negative) ? LONG_MIN : LONG_MAX);
|
||||
}
|
||||
return (long)((negative) ? -n : n);
|
||||
}
|
||||
|
||||
#define SWAPARR(a, b, size) \
|
||||
do { \
|
||||
size_t __size = (size); \
|
||||
char *__a = (a), *__b = (b); \
|
||||
do { \
|
||||
char __tmp = *__a; \
|
||||
*__a++ = *__b; \
|
||||
*__b++ = __tmp; \
|
||||
} while (--__size > 0); \
|
||||
} while (0)
|
||||
|
||||
void __qsortimpl(void* vbase, size_t n, size_t size, int (*compar)(const void*, const void*), int l, int r)
|
||||
{
|
||||
char* base = (char*)vbase;
|
||||
|
||||
if (l >= r) {
|
||||
return;
|
||||
}
|
||||
|
||||
int lm = l - 1;
|
||||
for (int rm = l; rm < r; rm++) {
|
||||
if (compar(&base[rm * size], &base[r * size]) < 0) {
|
||||
lm++;
|
||||
SWAPARR(&base[lm * size], &base[rm * size], size);
|
||||
}
|
||||
}
|
||||
SWAPARR(&base[(lm + 1) * size], &base[r * size], size);
|
||||
|
||||
__qsortimpl(vbase, n, size, compar, l, lm);
|
||||
__qsortimpl(vbase, n, size, compar, lm + 2, r);
|
||||
}
|
||||
|
||||
void qsort(void* vbase, size_t n, size_t size, int (*compar)(const void*, const void*))
|
||||
{
|
||||
__qsortimpl(vbase, n, size, compar, 0, n - 1);
|
||||
}
|
||||
Reference in New Issue
Block a user