first commit

This commit is contained in:
Your Name 2024-07-01 13:23:00 +03:00
commit 21be7fd279
156 changed files with 6939 additions and 0 deletions

14
LICENSE Normal file
View File

@ -0,0 +1,14 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

5
README.md Normal file
View File

@ -0,0 +1,5 @@
# micro-utils
Own implementation of *nix utils
License: wtfpl
Author: 8nl

57
TODO Normal file
View File

@ -0,0 +1,57 @@
With "micro-" prefix
*Todo:
tail
expr
uniq
od
tr
cut
shuf
stty
sort
test
tar
sha*
md5
Other:
watch
ps
sysctl
ping
ncat
ntpd
ifconfig
dhcp-client
getopt
fdisk
less
free
swapon
swapoff
hexdump
Loginutils:
userctl
groupctl
getty
Modutils:
insmod
rmmod
lsmod
Findutils:
grep
find
BUGS:
ls (-l flag with long group/user name)
xargs (getopt with glibc)
FIX:
ps
head
echo (escape)
que (unicode)

0
bin/.gitignore vendored Executable file
View File

36
build.sh Executable file
View File

@ -0,0 +1,36 @@
#!/bin/sh
if [ -z $PROJECT_DIR ]; then
PROJECT_DIR=$(pwd)
fi
if [ -z $CFLAGS ]; then
CFLAGS="-pedantic -s -Os -Wall -Wextra -D_GNU_SOURCE -D_DEFAULT_SOURCE -D_BSD_SOURCE"
fi
if [ -z $CC ]; then
CC=cc
fi
if [ -z $projects ]; then
projects="editors sysutils-linux init console-tools coreutils findutils networking loginutils procps"
fi
#Compile
for project in $projects; do
echo "Chdir" $project
for p in src/$project/*; do
echo " * Makeing" $p
for i in $p; do
cd $PROJECT_DIR/$i
echo " * Compile" $i
chmod -v +x build.sh
env CC=$CC CFLAGS="$CFLAGS -I$PROJECT_DIR -I$PROJECT_DIR/include/libmu" OUTPUT="$PROJECT_DIR"/bin/ ./build.sh
cd $PROJECT_DIR
done
echo -ne "\n"
done
done
chmod -vR a+x bin/

60
config.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef _CONFIG_H
#define _CONFIG_H
/* (cat tee wc xargs rev split cp) text buffer */
#define BUF_SIZE 1024 * 1024
#ifdef _SHRED_C
/* Random source (shred) */
#define RAND_SOURCE "/dev/urandom"
#endif
#ifdef _HEAD_C
/* format for printf (head) */
#define HEAD_FMT "==> %s <==\n"
#endif
#ifdef _PW_CHECK_H
/* Pw_check. Salt for crypt() */
char MU_SALT_ENC[] = {'s', 'a', 'l', 't'};
char MU_SALT_BUF[sizeof(MU_SALT_ENC) + 1];
#endif
#ifdef _MOUNT_C
/* mount config */
#define MOUNT_CFG "/etc/fstab"
#define MOUNT_DEF_FS "ext4"
#define MOUNT_LIST "/proc/mounts"
#define MOUNT_OPT_SIZE 512
#endif
#ifdef _LS_C
/* colors for ls */
#define LS_DIR_COLOR "\033[1;34m"
#define LS_LINK_COLOR "\033[1;35m"
#define LS_SOCK_COLOR "\033[35m"
#define LS_FIFO_COLOR "\033[1;35m"
#define LS_BLOCK_COLOR "\033[1;33m"
#define LS_EXE_COLOR "\033[1;32m"
#endif
#ifdef INIT
/* Init scripts */
char *INIT_POWEROFF[] = {"/etc/rc.poweroff", NULL};
char *INIT_START[] = {"/etc/rc.init", NULL};
#define INIT_MSG "Starting micro-init..."
#endif
#ifdef _UNAME_C
/* Os name for uname */
/* #define OS_NAME "unknow" */
#endif
/* Options: To disable, comment line */
/* getloadavg() unavailable in android */
#ifndef __ANDROID__
#define UPTIME_LOADAVG
#endif
#endif

9
configs/fstab Normal file
View File

@ -0,0 +1,9 @@
#Example
#[SRC] [DST] [FS TYPE] [OPTIONS. Default: default] [Unused] [Unused]
#/dev/sda1 /boot ext4 rw 0 0
#/dev/disk/by-uuid/disk-uuid-12dfg /usr f2fs 0 0
proc /proc proc nosuid,noexec,nodev 0 0
sysfs /sys sysfs nosuid,noexec,nodev 0 0
devtmpfs /dev devtmpfs gid=5,mode=0620 0 0
tmpfs /tmp tmpfs nosuid,noexec,nodev,mode=0777 0 0

2
configs/group Normal file
View File

@ -0,0 +1,2 @@
root::0:root

1
configs/hostname Normal file
View File

@ -0,0 +1 @@
localhost

1
configs/motd Normal file
View File

@ -0,0 +1 @@
Welcome!

4
configs/os-release Normal file
View File

@ -0,0 +1,4 @@
NAME="Plain Os"
ID=plainos
VERSION_ID=0.1
PRETTY_NAME="PlainOs/Linux 0.1 "

2
configs/passwd Normal file
View File

@ -0,0 +1,2 @@
root::0:0:root:/usr/root:/bin/sh
nobody:*:65534:65534:nobody:/nonexistent:/bin/false

9
configs/rc.init Normal file
View File

@ -0,0 +1,9 @@
#!/bin/sh
echo "[*] Mounting..."
mount -a
echo "[*] Hostname..."
hostname -c /etc/hostname
cat /etc/motd
env TERM="linux" login

12
configs/rc.poweroff Normal file
View File

@ -0,0 +1,12 @@
#!/bin/sh
echo "[*] Umounting..."
umount -a
echo "[*] Syncing..."
sync
echo "[*] Closing processes..."
kill -a -s TERM
sleep 5
echo "[*] Poweroff..."

1
configs/resolv.conf Normal file
View File

@ -0,0 +1 @@
nameserver 192.168.0.1

48
include/libmu/duration.h Normal file
View File

@ -0,0 +1,48 @@
#ifndef _DURATION_H
#define _DURATION_H
#include <string.h>
unsigned long long parse_uint(const char *str) {
char *p = NULL;
unsigned long long res = strtoull(str, &p, 0);
/* Parse suffix */
if (*p) {
switch (p[0]) {
case 'm':
res *= 60;
break;
case 'h':
res *= 3600;
break;
case 'd':
res *= 86400;
break;
case 's':
default:
break;
}
}
return res;
}
unsigned long long mu_parse_duration(const char *arg) {
if (strchr(arg, '.')) {
/* TODO */
}
else {
/* Sec */
return parse_uint(arg) * 1000000;
}
return 0;
}
#endif

39
include/libmu/get_stat.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef _GET_STAT_H
#define _GET_STAT_H
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
int mu_get_stat(const char *prog_name, const char *path, struct stat *stat_path) {
if (stat(path, stat_path)) {
if (prog_name != NULL)
fprintf(stderr, "%s: %s: %s\n", prog_name, path, strerror(errno));
return 1;
}
return 0;
}
int mu_get_lstat(const char *prog_name, const char *path, struct stat *stat_path) {
if (lstat(path, stat_path)) {
if (prog_name != NULL)
fprintf(stderr, "%s: %s: %s\n", prog_name, path, strerror(errno));
return 1;
}
return 0;
}
int mu_get_stats(const char *prog_name, int flag, const char *path, struct stat *stat_path) {
if (flag)
return mu_get_lstat(prog_name, path, stat_path);
else
return mu_get_stat(prog_name, path, stat_path);
}
#endif

30
include/libmu/human.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef _HUMAN_H
#define _HUMAN_H
#include <stdlib.h>
#include <stdint.h>
#define MU_HUMAN_BUF_SIZE 16
char *mu_humansize(off_t n, off_t block) {
static char mu_hs_buf[MU_HUMAN_BUF_SIZE + 1];
memset(mu_hs_buf, '\0', sizeof(mu_hs_buf));
char *postfixes = "BKMGTPE";
double size = n;
size_t i;
for (i = 0; i < strlen(postfixes) && size >= block; i++)
size /= block;
if (i)
snprintf(mu_hs_buf, sizeof(mu_hs_buf), "%.1f%c", size, postfixes[i]);
else
snprintf(mu_hs_buf, sizeof(mu_hs_buf), "%ju", n);
return mu_hs_buf;
}
#endif

39
include/libmu/make_path.h Normal file
View File

@ -0,0 +1,39 @@
#ifndef _MAKE_PATH_H
#define _MAKE_PATH_H
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *mu_make_path(const char *prog_name, const char *src, const char *dst) {
int flag = 0;
if (src == NULL) {
flag = 1;
src = "";
}
if (dst == NULL) {
flag = 1;
dst = "";
}
size_t len = strlen(src) + strlen(dst) + 2;
char *full_path = malloc(len + 1);
if (full_path == NULL) {
if (prog_name != NULL)
fprintf(stderr, "%s: malloc() failed\n", prog_name);
return NULL;
}
if (flag || src[strlen(src) - 1] == '/')
snprintf(full_path, len, "%s%s", src, dst);
else
snprintf(full_path, len, "%s/%s", src, dst);
return full_path;
}
#endif

View File

@ -0,0 +1,57 @@
#ifndef _MODE_TO_STR_H
#define _MODE_TO_STR_H
#include <stdio.h>
#include <sys/stat.h>
char *mu_mode_2_str(mode_t file_mode) {
static char mode[11];
snprintf(mode, sizeof(mode), "----------");
if (file_mode & S_IRUSR)
mode[1] = 'r';
if (file_mode & S_IRGRP)
mode[4] = 'r';
if (file_mode & S_IROTH)
mode[7] = 'r';
if (file_mode & S_IWUSR)
mode[2] = 'w';
if (file_mode & S_IWGRP)
mode[5] = 'w';
if (file_mode & S_IWOTH)
mode[8] = 'w';
if (file_mode & S_IXUSR)
mode[3] = 'x';
if (file_mode & S_IXGRP)
mode[6] = 'x';
if (file_mode & S_IXOTH)
mode[9] = 'x';
if (file_mode & S_ISUID) {
if (file_mode & S_IXUSR)
mode[3] = 's';
else
mode[3] = 'S';
}
if (file_mode & S_ISGID) {
if (file_mode & S_IRGRP)
mode[6] = 's';
else
mode[6] = 'S';
}
return mode;
}
#endif

View File

@ -0,0 +1,99 @@
#ifndef _PARSE_MODE_H
#define _PARSE_MODE_H
#include <sys/stat.h>
#include <string.h>
#define U (S_ISUID | S_IRWXU)
#define G (S_ISGID | S_IRWXG)
#define O (S_IRWXO)
#define A (U | G | O)
#define WR_PERM (S_IWUSR | S_IWGRP | S_IWOTH)
#define EX_PERM (S_IXUSR | S_IXGRP | S_IXOTH)
#define RD_PERM (S_IRUSR | S_IRGRP | S_IROTH)
#define SU_PERM (S_ISUID | S_ISGID | S_ISVTX)
#define FULL_PERM (WR_PERM | EX_PERM | RD_PERM)
mode_t mu_parse_mode(const char *s, mode_t cur_mode) {
char *p = NULL;
mode_t mode = (mode_t)strtol(s, &p, 8);
if (!*p && mode < 07777U)
return mode;
else if (mode > 07777U)
return 0;
mode = 0;
/* Default + */
char append = 1;
mode_t mask = 0;
for (size_t i = 0; i < strlen(s); i++) {
switch (s[i]) {
case 'r':
mode |= RD_PERM;
break;
case 'w':
mode |= WR_PERM;
break;
case 'x':
mode |= EX_PERM;
break;
case 's':
mode |= SU_PERM;
break;
case '+':
append = 1;
break;
case '-':
append = 0;
break;
case '=':
append = 2;
break;
case 'g':
mask |= G;
break;
case 'u':
mask |= U;
break;
case 'o':
mask |= O;
break;
case 'a':
mask |= A;
break;
default:
return 0;
}
}
if (mask == 0)
mask = U;
mask &= mode;
if (append == 0)
mode = ~mode;
if (append == 2)
return mode & mask;
else
return (cur_mode & ~mask) | (mode & mask);
}
#endif

View File

@ -0,0 +1,72 @@
#ifndef _PARSE_MOUNT_H
#define _PARSE_MOUNT_H
#include <string.h>
typedef struct {
char *opt;
char *notopt;
char *desc;
unsigned int val;
} MU_MOUNT_OPTS;
MU_MOUNT_OPTS mu_options[] = {
{"defaults", NULL, NULL, 0},
{"ro", "rw", "Read only / Read and write", MS_RDONLY},
{"remount", NULL, "Remount a mounted filesystem", MS_REMOUNT},
{"sync", "async", "Writes are [a]synchronous", MS_SYNCHRONOUS},
{"nodev", "dev", "(Dis)allow use of special device files", MS_NODEV},
{"bind", "rbind", "Bind a file or directory", MS_BIND},
{"noexec", "exec", "(Dis)allow use of executable files", MS_NOEXEC},
{"noatime", "atime", "Disable/enable updates to inode access times", MS_NOATIME}
};
unsigned long mu_parse_opts(char *str, char *data, const size_t data_size) {
memset(data, '\0', data_size);
unsigned long opt = 0;
size_t data_len = 0;
char *token = strtok(str, ",");
while (token != NULL) {
int invalidopt = 1;
for (size_t i = 0; i < sizeof(mu_options) / sizeof(mu_options[0]); i++) {
if (mu_options[i].opt && !strcmp(token, mu_options[i].opt)) {
opt |= mu_options[i].val;
invalidopt = 0;
break;
}
if (mu_options[i].notopt && !strcmp(token, mu_options[i].notopt)) {
opt &= ~mu_options[i].val;
invalidopt = 0;
break;
}
}
/* Unknow opt, pass in mount() */
size_t len = strlen(token);
if (invalidopt && len > 0) {
/* Copy token string */
for (size_t i = 0; i < len; i++) {
if (data_len + 1 >= data_size)
break;
else {
data[data_len] = token[i];
data_len++;
}
}
if (data_len && data_len + 1 < data_size)
data[data_len++] = ',';
}
token = strtok(NULL, ",");
}
if (data_len > 0)
data[data_len - 1] = '\0';
return opt;
}
#endif

59
include/libmu/pw_check.h Normal file
View File

@ -0,0 +1,59 @@
#ifndef _PW_CHECK_H
#define _PW_CHECK_H
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "config.h"
void dec_salt(void) {
size_t i;
for (i = 0; i < sizeof(MU_SALT_ENC) / sizeof(int); i++)
MU_SALT_BUF[i] = MU_SALT_ENC[i];
MU_SALT_BUF[i + 1] = '\0';
}
/* Using not only there */
char *enc_password(const char *prog_name, const char *pass, const char *salt) {
if (salt == NULL)
dec_salt();
char *cpass = crypt(pass, (salt == NULL) ? MU_SALT_BUF : salt);
if (cpass == NULL) {
if (prog_name != NULL)
fprintf(stderr, "%s: %s\n", prog_name, strerror(errno));
return NULL;
}
return cpass;
}
int pw_check(const char *prog_name, const struct passwd *pw, const char *pass) {
if (pw->pw_passwd[0] == '\0' && pass[0] == '\0')
return 0;
if (pw->pw_passwd[0] == '!' || pw->pw_passwd[0] == '*') {
if (prog_name != NULL)
fprintf(stderr, "%s: Access denied\n", prog_name);
return 1;
}
char *cpass = enc_password(prog_name, pass, NULL);
if (cpass == NULL)
return 1;
if (!strcmp(pw->pw_passwd, cpass))
return 0;
if (prog_name != NULL)
fprintf(stderr, "%s: Incorrect password\n", prog_name);
return 1;
}
#endif

54
include/libmu/recurse.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef _RECURSE_H
#define _RECURSE_H
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include "make_path.h"
#include "get_stat.h"
int mu_recurse(const char *restrict prog_name, int link_flag, const char *restrict path, void *restrict arg, int (*file_act)(const char *path, void *p), int (*dir_act)(const char *path, void *p)) {
struct stat sb;
if (mu_get_stats(prog_name, link_flag, path, &sb))
return 1;
if (!S_ISDIR(sb.st_mode) || S_ISLNK(sb.st_mode)) {
if (file_act != NULL)
return file_act(path, arg);
}
DIR *dir = opendir(path);
if (dir == NULL) {
if (prog_name != NULL)
fprintf(stderr, "%s: %s: Can`t open directory\n", prog_name, path);
return 1;
}
int ret = 0;
struct dirent *ep;
while ((ep = readdir(dir)) != NULL) {
if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
continue;
char *full_path = mu_make_path(prog_name, path, ep->d_name);
if (full_path == NULL)
continue;
if (mu_recurse(prog_name, link_flag, full_path, arg, file_act, dir_act))
ret = 1;
free(full_path);
}
closedir(dir);
if (dir_act != NULL)
if (dir_act(path, arg))
ret = 1;
return ret;
}
#endif

6
include/libmu/unused.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef _UNUSED_H
#define _UNUSED_H
#define UNUSED(p) ((void)p)
#endif

View File

@ -0,0 +1,13 @@
#ifndef _UTF8_STRLEN
#define _UTF8_STRLEN
size_t utf8_strlen(const char *s) {
size_t i = 0;
while (*s++)
i += (*s & 0xC0) != 0x80;
return i;
}
#endif

View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,5 @@
#include <unistd.h>
int main(void) {
return write(1, "\033[H\033[J", 6) != 6;
}

View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,5 @@
#include <unistd.h>
int main(void) {
return write(1, "\033c\033(K\033[J\033[0m\033[?25h", 18) != 18;
}

View File

@ -0,0 +1,57 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <libgen.h>
char *bname(char *str, const char *suffix) {
char *base = basename(str);
if (suffix) {
char *ptr = base + strlen(base) - strlen(suffix);
if (!strcmp(ptr, suffix))
*ptr = '\0';
}
return base;
}
int main(int argc, char **argv) {
char *suffix = NULL;
char d_flag = 0;
int opt;
while ((opt = getopt(argc, argv, "s:d")) != -1) {
switch (opt) {
case 'd':
d_flag = 1;
break;
case 's':
suffix = optarg;
break;
default:
printf("bdname [sd] [str]\n\t-s SFX Set suffix\n\t-d Use dirname instead of basename\n");
return 0;
}
}
argv += optind;
argc -= optind;
if (argc == 0) {
fprintf(stderr, "bdname: missing operand\n");
return 1;
}
char *str = NULL;
if (d_flag)
str = dirname(argv[0]);
else
str = bname(argv[0], suffix);
puts(str);
return 0;
}

3
src/coreutils/bdname/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

3
src/coreutils/cat/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

54
src/coreutils/cat/cat.c Normal file
View File

@ -0,0 +1,54 @@
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "config.h"
int cat(const char *path) {
int fd = STDIN_FILENO;
if (strcmp(path, "-"))
fd = open(path, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "cat: %s: %s\n", path, strerror(errno));
return 1;
}
char buf[BUF_SIZE + 1];
off_t len = 0;
while ((len = read(fd, buf, sizeof(buf))) > 0)
if (write(STDOUT_FILENO, buf, len) != len) {
fprintf(stderr, "cat: %s\n", strerror(errno));
return 1;
}
if (strcmp(path, "-"))
close(fd);
return 0;
}
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "")) != -1) {
printf("cat [file1 file2...]\n");
return 0;
}
argv += optind;
argc -= optind;
if (argc == 0)
return cat("-");
else {
int ret = 0;
for (int i = 0; i < argc; i++)
if (cat(argv[i]))
ret = 1;
return ret;
}
}

3
src/coreutils/chgrp/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,92 @@
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include "make_path.h"
#include "get_stat.h"
#include "recurse.h"
char r_flag;
char *f_flag = "chgrp";
char H_flag;
char v_flag;
int change(const char *path, void *p) {
struct group *grp = (struct group *)p;
struct stat stat_path;
if (mu_get_stat(f_flag, path, &stat_path))
return 1;
if (lchown(path, stat_path.st_uid, grp->gr_gid)) {
if (f_flag)
fprintf(stderr, "chgrp: %s: %s\n", path, strerror(errno));
return 1;
}
if (v_flag)
printf("chgrp: %s: changed group to %s\n", path, grp->gr_name);
return 0;
}
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "RfHv")) != -1) {
switch (opt) {
case 'R':
r_flag = 1;
break;
case 'f':
f_flag = NULL;
break;
case 'H':
H_flag = 1;
break;
case 'v':
v_flag = 1;
break;
default:
printf("chgrp [RfHv] [group] [file1 file2...]\n\t-H Symbolic link\n\t-R Recursive\n\t-f Silent\n\t-v Verbose\n");
return 0;
}
}
argv += optind;
argc -= optind;
if (argc == 0) {
fprintf(stderr, "chgrp: missing operand\n");
return 1;
}
struct group *grp = getgrnam(argv[0]);
if (!grp) {
if (f_flag)
fprintf(stderr, "chgrp: unknow group\n");
return 1;
}
int ret = 0;
for (int i = 1; i < argc; i++) {
if (r_flag) {
if (mu_recurse(f_flag, H_flag, argv[i], (void *)grp, change, change))
ret = 1;
}
else
ret = change(argv[i], grp);
}
return ret;
}

3
src/coreutils/chmod/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

103
src/coreutils/chmod/chmod.c Normal file
View File

@ -0,0 +1,103 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include "mode_to_str.h"
#include "make_path.h"
#include "get_stat.h"
#include "parse_mode.h"
#include "recurse.h"
char r_flag;
char *f_flag = "chmod";
char H_flag;
char v_flag;
int change(const char *file, void *p) {
char *mode_arg = (char *)p;
struct stat sb;
if (mu_get_stats(f_flag, H_flag, file, &sb))
return 1;
mode_t mode = mu_parse_mode(mode_arg, sb.st_mode);
if (chmod(file, mode) != 0) {
if (f_flag)
fprintf(stderr, "chmod: unable to chown %s: %s\n", file, strerror(errno));
return 1;
}
if (v_flag)
printf("chmod: %s: changed mode to %s\n", file, mu_mode_2_str(mode));
return 0;
}
int main(int argc, char **argv) {
/* Arg hacking */
char *arg = NULL;
for (int i = 1; i < argc; i++) {
if (argv[i][0] != '-' || strlen(argv[i]) <= 1)
break;
else if (argv[i][1] == 'x' || argv[i][1] == 'r' || argv[i][1] == 'w') {
argv[i][0] = 'a';
arg = argv[i];
break;
}
}
int opt;
while ((opt = getopt(argc, argv, "RfHv")) != -1) {
switch (opt) {
case 'R':
r_flag = 1;
break;
case 'f':
f_flag = NULL;
break;
case 'H':
H_flag = 1;
break;
case 'v':
v_flag = 1;
break;
default:
printf("chmod [RfHv] [ugoa]{+|-}[rwxXst] / [0 - 777] [file1 file2...]\n\t-H Symbolic link\n\t-R Recursive\n\t-f Silent\n\t-v Verbose\n");
return 0;
}
}
argv += optind;
argc -= optind;
if (argc == 0) {
fprintf(stderr, "chmod: missing operand\n");
return 0;
}
/* Restore arg */
if (arg)
arg[0] = '-';
int ret = 0;
for (int i = 1; i < argc; i++) {
if (r_flag) {
if (mu_recurse(f_flag, H_flag, argv[i], argv[0], change, change))
ret = 1;
}
else
change(argv[i], argv[0]);
}
return ret;
}

3
src/coreutils/chown/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

131
src/coreutils/chown/chown.c Normal file
View File

@ -0,0 +1,131 @@
#include <pwd.h>
#include <grp.h>
#include <stdio.h>
#include <errno.h>
#include <dirent.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "make_path.h"
#include "get_stat.h"
#include "recurse.h"
#include "unused.h"
char r_flag;
char *f_flag = "chown";
char H_flag;
char v_flag;
int (*chown_func)(const char *pathname, uid_t owner, gid_t group);
long gid;
long uid;
int change(const char *path, void *p) {
char *name = (char *)p;
if (chown_func(path, uid, gid)) {
if (f_flag)
fprintf(stderr, "chown: unable to chown %s: %s\n", path, strerror(errno));
return 1;
}
if (v_flag)
printf("chown: %s: changed to %s\n", path, name);
return 0;
}
void get_owner(const char *arg) {
char *group = strchr(arg, ':');
char g_flag = 1;
char u_flag = 1;
if (group == arg)
u_flag = 0;
else if (!group)
g_flag = 0;
if (g_flag) {
group[0] = '\0';
group++;
struct group *grp = getgrnam(group);
if (!grp) {
if (f_flag)
fprintf(stderr, "chown: invalid group: %s\n", group);
exit(1);
}
gid = grp->gr_gid;
}
if (u_flag) {
struct passwd *pwd = getpwnam(arg);
if (!pwd) {
if (f_flag)
fprintf(stderr, "chown: invalid user: %s\n", arg);
exit(1);
}
uid = pwd->pw_gid;
}
}
int main(int argc, char **argv) {
chown_func = lchown;
int opt;
while ((opt = getopt(argc, argv, "RfHv")) != -1) {
switch (opt) {
case 'R':
r_flag = 1;
break;
case 'f':
f_flag = NULL;
break;
case 'H':
H_flag = 1;
chown_func = chown;
break;
case 'v':
v_flag = 1;
break;
default:
printf("chown [RfHf] USER[:[GRP]] [file1 file2...]\n\t-H Symbolic link\n\t-R Recursive\n\t-f Silent\n\t-v Verbose\n");
return 0;
}
}
argv += optind;
argc -= optind;
if (argc == 0) {
fprintf(stderr, "chown: missing operand\n");
return 1;
}
gid = -1;
uid = -1;
get_owner(argv[0]);
int ret = 0;
for (int i = 1; i < argc; i++) {
if (r_flag) {
if (mu_recurse(f_flag, H_flag, argv[i], argv[0], change, change))
ret = 1;
}
else
ret = change(argv[i], argv[0]);
}
return ret;
}

3
src/coreutils/chroot/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,29 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
int main(const int argc, char **argv) {
if (argc < 3 || !strcmp(argv[argc - 1], "--help")) {
printf("chroot [dir] [command] [arg arg2...]\n");
return 0;
}
if (chroot(argv[1]) < 0) {
fprintf(stderr, "chroot: %s\n", strerror(errno));
return 1;
}
if (chdir("/") < 0) {
fprintf(stderr, "chroot: %s\n", strerror(errno));
return 1;
}
if (execvp(argv[2], argv + 2) < 0) {
fprintf(stderr, "chroot: %s\n", strerror(errno));
return 1;
}
return 0;
}

3
src/coreutils/cmp/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

126
src/coreutils/cmp/cmp.c Normal file
View File

@ -0,0 +1,126 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
char s_flag;
int compare(FILE *fp1, FILE *fp2) {
if (fp1 == fp2)
return 0;
int ch1;
int ch2;
size_t byte = 1;
size_t lines = 1;
do {
ch1 = getc(fp1);
ch2 = getc(fp2);
if (ch1 != ch2) {
if (!s_flag)
printf("files differ at byte %zu and line %zu\n", byte, lines);
return 1;
}
if (ch1 == '\n')
lines++;
byte++;
} while(ch1 != EOF);
return 0;
}
long parse_int(const char *str) {
char *ptr;
long val = strtol(str, &ptr, 0);
if (*ptr || val < 0) {
fprintf(stderr, "cmp: invalid offset: %s\n", str);
exit(1);
}
return val;
}
FILE *file_open(const char *path) {
if (!strcmp(path, "-"))
return stdin;
FILE *fp = fopen(path, "r");
if (fp == NULL) {
fprintf(stderr, "cmp: %s\n", strerror(errno));
exit(1);
}
return fp;
}
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "s")) != -1) {
switch (opt) {
case 's':
s_flag = 1;
break;
default:
printf("cmp [s] [file1] [file2] [skip1] [skip2]\n\t-s Silent\n");
return 0;
}
}
argv += optind;
argc -= optind;
long skip1 = 0;
long skip2 = 0;
FILE *fp1 = NULL;
FILE *fp2 = stdin;
switch (argc) {
case 4:
skip2 = parse_int(argv[3]);
/* fallthrough */
case 3:
skip1 = parse_int(argv[2]);
/* fallthrough */
case 2:
fp2 = file_open(argv[1]);
/* fallthrough */
case 1:
fp1 = file_open(argv[0]);
break;
default:
fprintf(stderr, "cmp: missing operand\n");
return 1;
}
if (skip1 && fseek(fp1, skip1, SEEK_SET) < 0) {
if (!s_flag)
fprintf(stderr, "cmp: %s\n", strerror(errno));
return 1;
}
if (skip2 && fseek(fp2, skip2, SEEK_SET) < 0) {
if (!s_flag)
fprintf(stderr, "cmp: %s\n", strerror(errno));
return 1;
}
int ret = compare(fp1, fp2);
fclose(fp1);
fclose(fp2);
return ret;
}

3
src/coreutils/cp/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

213
src/coreutils/cp/cp.c Normal file
View File

@ -0,0 +1,213 @@
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <limits.h>
#include <sys/mman.h>
#include "make_path.h"
#include "get_stat.h"
#include "config.h"
char *f_flag = "cp";
char r_flag;
char v_flag;
char L_flag;
char copy_reg(int mode, const char *src, const char *dst) {
int ret = 1;
int ifd = open(src, O_RDONLY);
if (ifd < 0)
return 1;
int ofd = open(dst, O_WRONLY | O_TRUNC | O_CREAT, mode);
if (ofd < 0)
goto CLOSE_OFD;
char buf[BUF_SIZE + 1];
while (1) {
ssize_t n = read(ifd, buf, sizeof(buf));
if (n <= 0) {
if (n < 0)
goto CLOSE;
break;
}
if (write(ofd, buf, n) != n)
goto CLOSE;
}
ret = 0;
CLOSE:
close(ofd);
CLOSE_OFD:
close(ifd);
return ret;
}
char copy_lnk(const char *src, const char *dst) {
char path[PATH_MAX + 1];
ssize_t ret = readlink(src, path, sizeof(path));
if (ret < 0)
return 1;
path[ret] = '\0';
if (symlink(path, dst) < 0)
return 1;
return 0;
}
char copy(struct stat st, const char *src, const char *dst) {
if (v_flag)
printf("Copying '%s' to '%s'\n", src, dst);
if (S_ISLNK(st.st_mode))
return copy_lnk(src, dst);
else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) || S_ISFIFO(st.st_mode)) {
if (mknod(dst, st.st_mode, st.st_dev) < 0)
return 1;
}
else
return copy_reg(st.st_mode, src, dst);
return 0;
}
int cptree(const char *src, const char *dst) {
struct stat src_stat;
if (mu_get_stats(f_flag, !L_flag, src, &src_stat))
return 1;
if (!S_ISDIR(src_stat.st_mode)) {
if (copy(src_stat, src, dst)) {
if (f_flag)
fprintf(stderr, "cp: %s: %s\n", dst, strerror(errno));
return 1;
}
return 0;
}
else if (!r_flag) {
if (f_flag)
fprintf(stderr, "cp: omitting directory: %s\n", dst);
return 1;
}
else if (mkdir(dst, 0777) < 0) {
if (f_flag)
fprintf(stderr, "cp: %s: %s\n", dst, strerror(errno));
return 1;
}
DIR *dir = opendir(src);
if (dir == NULL) {
if (f_flag)
fprintf(stderr, "cp: %s: Can`t open directory\n", src);
return 1;
}
int ret = 0;
struct dirent *ep;
while ((ep = readdir(dir)) != NULL) {
if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, "..") || !strcmp(dst, ep->d_name))
continue;
/* Copy */
char *src_path = mu_make_path(f_flag, src, ep->d_name);
if (src_path == NULL)
continue;
char *dst_path = mu_make_path(f_flag, dst, ep->d_name);
if (dst_path == NULL) {
free(src_path);
continue;
}
if (cptree(src_path, dst_path))
ret = 1;
free(src_path);
free(dst_path);
if (ret)
break;
}
closedir(dir);
return ret;
}
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "frvL")) != -1) {
switch (opt) {
case 'f':
f_flag = NULL;
break;
case 'r':
r_flag = 1;
break;
case 'v':
v_flag = 1;
break;
case 'L':
L_flag = 1;
break;
default:
printf("cp [frvL] [src1 src2...] [dst]\n\t-f Silent\n\t-r Recursive\n\t-v Verbose\n\t-L Follow all symlinks\n");
return 0;
}
}
argv += optind;
argc -= optind;
if (argc < 2) {
fprintf(stderr, "cp: missing operand\n");
return 1;
}
int ret = 0;
struct stat sb;
if (!mu_get_stat(NULL, argv[argc - 1], &sb))
if (S_ISDIR(sb.st_mode))
goto IF_EXSIST;
if (argc == 2)
ret = cptree(argv[0], argv[argc - 1]);
else {
IF_EXSIST:
for (int i = 0; i < argc - 1; i++) {
char *new_path = mu_make_path(f_flag, argv[argc - 1], basename(argv[i]));
if (new_path == NULL)
return 1;
if (cptree(argv[i], new_path))
ret = 1;
free(new_path);
}
}
return ret;
}

3
src/coreutils/date/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

109
src/coreutils/date/date.c Normal file
View File

@ -0,0 +1,109 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#include <sys/stat.h>
#include "get_stat.h"
const char *fmts[] = {
"%R",
"%T",
"%m.%d-%R",
"%m.%d-%T",
"%Y.%m.%d-%R",
"%Y.%m.%d-%T",
"%Y-%m-%d %R %z",
"%Y-%m-%d %T %z",
"%T %d-%m-%Y",
"%H %d-%m-%Y",
"%Y-%m-%d %H",
"%Y-%m-%d",
"%d-%m-%Y"
};
time_t parse_date(char *str) {
time_t local = time(NULL);
struct tm *tm = localtime(&local);
for (size_t i = 0; i < sizeof(fmts) / sizeof(char *); i++) {
char *res = strptime(str, fmts[i], tm);
if (res && *res == '\0')
break;
}
time_t rt = mktime(tm);
if (rt == -1) {
fprintf(stderr, "date: %s\n", strerror(errno));
exit(1);
}
return rt;
}
int main(int argc, char **argv) {
time_t t = time(NULL);
char *fmt = "%a %b %e %H:%M:%S %Z %Y";
char *r_flag = 0;
/* For -s flag */
struct timespec ts;
int opt;
while ((opt = getopt(argc, argv, "s:d:r:u")) != -1) {
switch (opt) {
case 'r':
r_flag = optarg;
break;
case 's':
ts.tv_sec = parse_date(optarg);
if (clock_settime(CLOCK_REALTIME, &ts) < 0) {
fprintf(stderr, "date: %s\n", strerror(errno));
return 1;
}
return 0;
case 'd':
t = parse_date(optarg);
break;
case 'u':
if (setenv("TZ", "UTC0", 1) < 0) {
fprintf(stderr, "date: %s\n", strerror(errno));
return 1;
}
break;
default:
printf("date [rsdu] [+\"fmt\"]\n\t-s DATE Set new date\n\t-d DATE Print new date\n\t-u Work in UTC\n\t-r FILE Display last modification time of FILE\n");
return 0;
}
}
argv += optind;
argc -= optind;
if (argc != 0)
if (argv[0][0] == '+')
fmt = argv[0] + 1;
struct stat sb;
if (r_flag) {
if (mu_get_stat("date", r_flag, &sb))
return 1;
t = sb.st_mtime;
}
struct tm *tm = localtime(&t);
char buf[256];
strftime(buf, sizeof(buf), fmt, tm);
puts(buf);
return 0;
}

3
src/coreutils/dd/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

249
src/coreutils/dd/dd.c Normal file
View File

@ -0,0 +1,249 @@
#include <fcntl.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "human.h"
off_t infull, inpart;
off_t outfull, outpart;
off_t tbytes;
void summary(void) {
fprintf(stderr, "%jd+%jd records in\n", infull, inpart);
fprintf(stderr, "%jd+%jd records out\n", outfull, outpart);
fprintf(stderr, "%s total bytes copied\n", mu_humansize(tbytes, 1024));
}
int openfile(int flag, char *path, int mode) {
if (!strcmp(path, "-")) {
if (flag)
return STDOUT_FILENO;
return STDIN_FILENO;
}
int fd = open(path, mode, 0666);
if (fd < 0) {
fprintf(stderr, "dd: %s: %s\n", path, strerror(errno));
exit(1);
}
return fd;
}
off_t strtonum(char *str) {
char *p = NULL;
off_t res = strtoll(str, &p, 0);
if (str != p) {
if (!strcmp(p, "b"))
res *= 512;
else if (!strcmp(p, "m"))
res *= 1000000;
else if (!strcmp(p, "M"))
res *= 1048576;
else if (!strcmp(p, "K"))
res *= 1024;
else if (!strcmp(p, "k"))
res *= 1000;
else if (!strcmp(p, "g"))
res *= 1000000000;
else if (!strcmp(p, "G"))
res *= 1073741824;
}
if (res < 0)
res = 0;
return res;
}
int copy(int fd, void *buf, off_t len, off_t max) {
off_t n = write(fd, buf, len);
if (n < 0) {
fprintf(stderr, "dd: %s\n", strerror(errno));
return 1;
}
else if (n == max)
outfull++;
else if (n == len)
outpart++;
tbytes += n;
return 0;
}
int main(int argc, char **argv) {
signal(SIGPIPE, SIG_IGN);
char *ifp = "-";
char *ofp = "-";
off_t count = -1;
off_t skip = 0;
off_t seek = 0;
off_t bs = 0;
off_t ibs = 512;
off_t obs = 512;
int ofd = STDOUT_FILENO;
int ifd = STDIN_FILENO;
/* Return value */
int ret = 1;
for (int i = 1; i < argc; i++) {
char *arg = argv[i];
char *val = strchr(arg, '=');
if (val == NULL) {
printf("dd\n\tif=InputFile\n\tof=OutputFile\n\tbs=ibs and obs\n\tibs=Input buffer size\n\tobs=Output buffer size\n\tseek=Skip N obs-sized output blocks\n\tskip=Skip N ibs-sized output blocks\n\tcount=Copy only N input blocks\n\nN and BYTES may be followed by the following multiplicative\nsuffixes: w=2, b=512, k=1000, K=1024, m=1000*1000,\nM=1024*1024, g=1000*1000*1000, G=1024*1024*1024\n");
return 1;
}
*val = '\0';
val++;
/* Get value */
if (!strcmp(arg, "if"))
ifp = val;
else if (!strcmp(arg, "of"))
ofp = val;
else if (!strcmp(arg, "seek"))
seek = strtonum(val);
else if (!strcmp(arg, "skip"))
skip = strtonum(val);
else if (!strcmp(arg, "count"))
count = strtonum(val);
else if (!strcmp(arg, "bs"))
bs = strtonum(val);
else if (!strcmp(arg, "ibs"))
ibs = strtonum(val);
else if (!strcmp(arg, "obs"))
obs = strtonum(val);
}
if (bs) {
ibs = bs;
obs = bs;
}
/* Make input ibuffer */
char *ibuf = malloc(ibs);
if (ibuf == NULL) {
fprintf(stderr, "dd: %s\n", strerror(errno));
return 1;
}
char *obuf = NULL;
if (ibs != obs) {
obuf = malloc(obs);
if (obuf == NULL) {
free(ibuf);
fprintf(stderr, "dd: %s\n", strerror(errno));
return 1;
}
}
/* Open files. Input */
ifd = openfile(0, ifp, O_RDONLY);
if (skip) {
if (lseek(ifd, skip * ibs, SEEK_CUR) < 0)
goto CLOSE;
}
/* Output */
int oflag = O_WRONLY | O_CREAT;
if (seek)
oflag |= O_TRUNC;
ofd = openfile(1, ofp, oflag);
if (seek) {
if (ftruncate(ofd, seek * ibs) < 0 || lseek(ofd, seek * ibs, SEEK_SET) < 0) {
fprintf(stderr, "dd: %s\n", strerror(errno));
goto CLOSE;
}
}
/* dd */
off_t opos = 0;
while (1) {
if (count == infull + inpart)
break;
off_t n = read(ifd, ibuf, ibs);
if (n <= 0)
break;
else if (ibs == n)
infull++;
else
inpart++;
if (ibs == obs) {
if (copy(ofd, ibuf, n, ibs))
goto CLOSE;
}
else {
char *tmp = ibuf;
while (n) {
off_t i = obs - opos;
if (i > n)
i = n;
memcpy(obuf + opos, tmp, i);
n -= i;
tmp += i;
opos += i;
if (opos == obs) {
if (copy(ofd, obuf, obs, obs))
goto CLOSE;
opos = 0;
}
}
}
}
if (opos != 0) {
if (copy(ofd, obuf, obs, obs))
goto CLOSE;
}
/* End */
fsync(ofd);
summary();
ret = 0;
CLOSE:
free(ibuf);
if (ibs != obs)
free(obuf);
close(ifd);
close(ofd);
return ret;
}

3
src/coreutils/df/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

95
src/coreutils/df/df.c Normal file
View File

@ -0,0 +1,95 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
#include <mntent.h>
#include <sys/statvfs.h>
#include "human.h"
#include "config.h"
char a_flag;
char h_flag;
off_t block = 1024;
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "hHka")) != -1) {
switch (opt) {
case 'h':
h_flag = 1;
break;
case 'H':
h_flag = 1;
block = 1000;
break;
case 'a':
a_flag = 1;
break;
default:
printf("df [rHa]\n\t-h Human readable (1024)\n\t-a Show all\n\t-H Human readable (1000)\n");
return 0;
}
}
FILE *fp = setmntent("/proc/mounts", "r");
if (fp == NULL) {
fprintf(stderr, "df: %s\n", strerror(errno));
return 1;
}
if (h_flag)
puts("Filesystem Size Used Available Use% Mounted on");
else
puts("Filesystem Size Used Available Use% Mounted on");
int ret = 0;
struct mntent *me;
struct statvfs disk;
while ((me = getmntent(fp)) != NULL) {
if (!strcmp(me->mnt_fsname, "none"))
continue;
if (statvfs(me->mnt_dir, &disk) < 0) {
ret = 1;
continue;
}
if (!a_flag)
if (!strcmp(me->mnt_fsname, "/dev/root") || disk.f_blocks == 0)
continue;
off_t bs = disk.f_frsize / block;
off_t total = disk.f_blocks * bs;
off_t avail = disk.f_bfree * bs;
off_t used = total - avail;
off_t capacity = (used * 100 + 1) / (avail + used + 1);
if (!h_flag)
printf("%-20s %12jd %12jd %12jd %12jd%% %s\n", me->mnt_fsname, total, used, avail, capacity, me->mnt_dir);
else {
char total_s[MU_HUMAN_BUF_SIZE + 1];
char used_s[MU_HUMAN_BUF_SIZE + 1];
char avail_s[MU_HUMAN_BUF_SIZE + 1];
snprintf(total_s, sizeof(total_s), "%s", mu_humansize(total * block, block));
snprintf(used_s, sizeof(used_s), "%s", mu_humansize(used * block, block));
snprintf(avail_s, sizeof(avail_s), "%s", mu_humansize(avail * block, block));
printf("%-20s %10s %9s %9s %3jd%% %s\n", me->mnt_fsname, total_s, used_s, avail_s, capacity, me->mnt_dir);
}
}
endmntent(fp);
return ret;
}

3
src/coreutils/du/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

111
src/coreutils/du/du.c Normal file
View File

@ -0,0 +1,111 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <stdint.h>
#include "get_stat.h"
#include "make_path.h"
#include "human.h"
char h_flag;
char s_flag;
char c_flag;
off_t total;
void print(off_t size, const char *filename) {
if (h_flag)
printf("%s\t%s\n", mu_humansize(size * 512, 1024), filename);
else
printf("%jd\t%s\n", (intmax_t)size / 2, filename);
}
off_t du(const char *path, int recurs_flag) {
struct stat sb;
if (mu_get_lstat("du", path, &sb))
return 0;
off_t sum = sb.st_blocks;
if (c_flag)
total += sum;
if (S_ISDIR(sb.st_mode)) {
DIR *dp = opendir(path);
if (!dp) {
fprintf(stderr, "du: %s\n", strerror(errno));
return 0;
}
struct dirent *ep;
while ((ep = readdir(dp)) != NULL) {
if (!strcmp(ep->d_name, ".") || !strcmp(ep->d_name, ".."))
continue;
char *new_path = mu_make_path("du", path, ep->d_name);
if (new_path == NULL)
return 0;
sum += du(new_path, 1);
free(new_path);
}
closedir(dp);
if (!s_flag && recurs_flag) {
print(sum, path);
return sum;
}
/* Silent mode */
else if (!recurs_flag)
print(sum, path);
}
else if (!recurs_flag)
print(sum, path);
return sum;
}
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "hsc")) != -1) {
switch (opt) {
case 'h':
h_flag = 1;
break;
case 's':
s_flag = 1;
break;
case 'c':
c_flag = 1;
break;
default:
printf("du [hsc] [src1 src2...]\n\t-h Sizes in human readable format\n\t-s Display only a total for each argument\n\t-c produce a grand total\n");
return 0;
}
}
if (argv[optind] == NULL)
du(".", 0);
else {
argv += optind;
argc -= optind;
for (int i = 0; i < argc; i++)
du(argv[i], 0);
}
if (c_flag)
print(total, "total");
return 0;
}

3
src/coreutils/echo/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

94
src/coreutils/echo/echo.c Normal file
View File

@ -0,0 +1,94 @@
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
char n_flag = 0;
char e_flag = 0;
void format(char *str) {
for (size_t i = 0; i < strlen(str); i++) {
unsigned int c = str[i];
if (c == '\\') {
switch (str[i + 1]) {
case 'a':
c = '\a';
break;
case 'n':
c = '\n';
break;
case 't':
c = '\t';
break;
case 'c':
exit(0);
case 'v':
c = '\v';
break;
case 'r':
c = '\r';
break;
case 'f':
c = '\f';
break;
case 'e':
c = '\033';
break;
case 'b':
c = '\b';
break;
default:
c = '\\';
}
i++;
}
putchar(c);
}
}
int main(int argc, char **argv) {
argv++;
argc--;
for (int i = 0; i < argc; i++) {
if (argv[i][0] == '-') {
if (strstr(argv[i] + 1, "n"))
n_flag = 1;
else if (strstr(argv[i] + 1, "e"))
e_flag = 1;
argc--;
argv++;
}
}
for (int i = 0; i < argc; i++) {
if (e_flag)
format(argv[i]);
else
fputs(argv[i], stdout);
if (i < argc - 1)
putchar(' ');
}
if (!n_flag)
putchar('\n');
return 0;
}

3
src/coreutils/env/build.sh vendored Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

33
src/coreutils/env/env.c vendored Normal file
View File

@ -0,0 +1,33 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(const int argc, char **argv, const char **envp) {
int i;
for (i = 1; i < argc; i++) {
char *val = strchr(argv[i], '=');
if (!val)
break;
val[0] = '\0';
if (setenv(argv[i], val + 1, 1)) {
fprintf(stderr, "env: %s\n", strerror(errno));
return 1;
}
}
/* Print env */
if (i == argc) {
while (*envp)
puts(*envp++);
return 0;
}
execvp(argv[i], argv + i);
fprintf(stderr, "env: %s: %s\n", argv[i], strerror(errno));
return 1;
}

3
src/coreutils/false/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,3 @@
int main(void) {
return 1;
}

3
src/coreutils/head/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

95
src/coreutils/head/head.c Normal file
View File

@ -0,0 +1,95 @@
#define _HEAD_C
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "config.h"
char v_flag;
char c_flag;
long parse_long(const char *str) {
char *ptr;
long ret = strtol(str, &ptr, 0);
if (*ptr) {
fprintf(stderr, "head: %s invalid number\n", ptr);
exit(1);
}
return ret;
}
void print(const char *file, FILE *fp, long lines, long bytes) {
if (v_flag)
printf(HEAD_FMT, file);
long lcount = 0;
long bcount = 0;
while (1) {
int c = getc(fp);
bcount++;
if (c == '\n')
lcount++;
if (c == EOF || lcount == lines || (c_flag && bcount == bytes))
break;
putchar(c);
}
}
int main(int argc, char **argv) {
long lines = 10;
long bytes = 0;
int opt;
while ((opt = getopt(argc, argv, "n:c:v")) != -1) {
switch (opt) {
case 'n':
lines = parse_long(optarg);
break;
case 'c':
c_flag = 1;
bytes = parse_long(optarg);
break;
case 'v':
v_flag = 1;
break;
default:
printf("head [ncv] [file1 file2...]\n\t-n Print N lines\n\t-c Print N bytes\n\t-v Print headers\n");
return 0;
}
}
argv += optind;
argc -= optind;
if (argc == 0)
print("-", stdin, lines, bytes);
for (int i = 0; i < argc; i++) {
FILE *fp = NULL;
if (argv[i][0] == '-')
fp = stdin;
else
fp = fopen(argv[i], "r");
if (fp == NULL) {
fprintf(stderr, "head: %s: %s\n", argv[i], strerror(errno));
return 1;
}
print(argv[i], fp, lines, bytes);
fclose(fp);
}
return 0;
}

3
src/coreutils/id/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

130
src/coreutils/id/id.c Normal file
View File

@ -0,0 +1,130 @@
#include <grp.h>
#include <pwd.h>
#include <stdio.h>
#include <errno.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <limits.h>
#include <sys/types.h>
char g_flag;
char G_flag;
char n_flag;
char r_flag;
char u_flag;
int print_groups(const struct passwd *pwd, const char *fmt, const int flag) {
gid_t groups[NGROUPS_MAX];
int ngroups = NGROUPS_MAX;
if (getgrouplist(pwd->pw_name, pwd->pw_gid, groups, &ngroups) < 0)
return 1;
for (int i = 0; i < ngroups; i++) {
struct group *grp = getgrgid(groups[i]);
if (grp && !n_flag)
printf("%u", groups[i]);
if ((!r_flag && n_flag) || flag)
printf(fmt, grp->gr_name);
if (g_flag && i == 0)
break;
putchar(' ');
}
return 0;
}
int ids(uid_t uid, struct passwd *pwd) {
if (u_flag) {
if (n_flag)
printf("%s", pwd->pw_name);
else
printf("%u", uid);
}
else if (G_flag || g_flag)
print_groups(pwd, "%s", 0);
putchar('\n');
return 0;
}
int def_ids(uid_t uid, struct passwd *pwd) {
printf("uid=%d(%s) gid=%d", uid, pwd->pw_name, pwd->pw_gid);
struct group *grp = getgrgid(pwd->pw_gid);
if (grp)
printf("(%s)", grp->gr_name);
printf(" groups=");
print_groups(pwd, "(%s)", 1);
putchar('\n');
return 0;
}
void usage(int sig) {
printf("id [gGurn] [user]\n\t-u User ID\n\t-g Group ID\n\t-G Supplementary group IDs\n\t-n Print names instead of numbers\n\t-r Print real ID instead of effective ID\n");
exit(sig);
}
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "gGnru")) != -1) {
switch (opt) {
case 'g':
if (G_flag || u_flag)
usage(1);
g_flag = 1;
break;
case 'G':
if (g_flag || u_flag)
usage(1);
G_flag = 1;
break;
case 'u':
if (G_flag || g_flag)
usage(1);
u_flag = 1;
break;
case 'r':
r_flag = 1;
break;
case 'n':
n_flag = 1;
break;
default:
usage(0);
}
}
argv += optind;
argc -= optind;
uid_t uid = getuid();
struct passwd *pwd = getpwuid(uid);
if (argv[0] != NULL)
pwd = getpwnam(argv[0]);
if (!pwd) {
fprintf(stderr, "id: %s\n", strerror(errno));
return 1;
}
if (u_flag || G_flag || g_flag)
return ids(uid, pwd);
return def_ids(uid, pwd);
}

3
src/coreutils/ln/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

76
src/coreutils/ln/ln.c Normal file
View File

@ -0,0 +1,76 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "make_path.h"
char s_flag;
char f_flag;
char v_flag;
int ln(const char *src, const char *dst) {
if (f_flag)
if (unlink(dst) && v_flag)
fprintf(stderr, "ln: removed %s\n", dst);
int ret = 0;
if (s_flag)
ret = symlink(src, dst);
else
ret = link(src, dst);
if (!ret && v_flag)
fprintf(stderr, "ln: linked %s to %s\n", src, dst);
return ret;
}
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "sfv")) != -1) {
switch (opt) {
case 's':
s_flag = 1;
break;
case 'f':
f_flag = 1;
break;
case 'v':
v_flag = 1;
break;
default:
printf("ln [sfv] [src] [dst]\n\t-f Force\n\t-s Symbolic\n\t-v Verbose\n");
return 0;
}
}
argv += optind;
argc -= optind;
if (argc == 2) {
if (ln(argv[0], argv[1])) {
char *new_path = mu_make_path("ln", argv[1], argv[0]);
if (new_path == NULL)
return 1;
if (ln(argv[0], new_path)) {
free(new_path);
fprintf(stderr, "ln: %s %s\n", argv[1], strerror(errno));
return 1;
}
free(new_path);
}
}
else {
fprintf(stderr, "ln: missing operand\n");
return 1;
}
return 0;
}

3
src/coreutils/ls/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

508
src/coreutils/ls/ls.c Normal file
View File

@ -0,0 +1,508 @@
#define _LS_C
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include "mode_to_str.h"
#include "utf8_strlen.h"
#include "make_path.h"
#include "get_stat.h"
#include "config.h"
#include "human.h"
char O_flag;
char a_flag;
char l_flag;
char F_flag;
char c_flag;
char R_flag;
char d_flag;
char L_flag;
char h_flag;
char s_flag;
char i_flag;
char p_flag;
char nul_flag;
int sortd(const void *p1, const void *p2);
int (*sorter)(const void *p1, const void *p2) = sortd;
struct d_node {
/* basename */
char *name;
/* For free */
char *full_name;
struct d_node *next;
struct stat stats;
};
/* Work with dir */
struct d_node *stat_file(char *filename, const int lfile) {
/* lfile its flag. 1 if passed file from list_one() */
struct d_node *file = malloc(sizeof(struct d_node));
if (file == NULL) {
fprintf(stderr, "ls: malloc: %s\n", strerror(errno));
return NULL;
}
if (mu_get_stats("ls", !L_flag, filename, &file->stats)) {
free(file);
return NULL;
}
file->full_name = filename;
file->name = strrchr(filename, '/');
if (file->name == NULL || lfile)
file->name = filename;
else
file->name++;
return file;
}
void dfree(struct d_node **dir, const size_t files) {
for (size_t i = 0; i < files; i++) {
if (dir[i]->full_name != NULL)
free(dir[i]->full_name);
if (dir[i] != NULL)
free(dir[i]);
}
free(dir);
}
struct d_node **list(const char *path, off_t *total_size, size_t *nfiles, int *ret) {
DIR *dp = opendir(path);
if (dp == NULL) {
fprintf(stderr, "ls: %s: %s\n", path, strerror(errno));
return NULL;
}
struct d_node **dn = malloc(sizeof(struct d_node *));
if (dn == NULL) {
fprintf(stderr, "ls: malloc: %s\n", strerror(errno));
return NULL;
}
struct dirent *ep;
while ((ep = readdir(dp)) != NULL) {
if (ep->d_name[0] == '.' && !a_flag)
continue;
char *full_path = mu_make_path("ls", path, ep->d_name);
if (full_path == NULL)
continue;
struct d_node **bckp = realloc(dn, sizeof(struct d_node *) * (*nfiles + 1));
if (bckp == NULL) {
free(full_path);
dfree(dn, *nfiles);
closedir(dp);
fprintf(stderr, "ls: realloc: %s\n", strerror(errno));
return NULL;
}
dn = bckp;
dn[*nfiles] = stat_file(full_path, 0);
if (dn[*nfiles] == NULL) {
*ret = 1;
free(full_path);
continue;
}
*total_size += dn[*nfiles]->stats.st_blocks;
(*nfiles)++;
}
closedir(dp);
return dn;
}
char *get_date(const time_t mtime) {
static char date[100];
strftime(date, sizeof(date), "%b %d %H:%M", localtime(&mtime));
return date;
}
/* Print */
int print(const struct d_node *node) {
char suf = ' ';
char *color = "";
char *mode = mu_mode_2_str(node->stats.st_mode);
if (S_ISDIR(node->stats.st_mode)) {
if (node->name[strlen(node->name) - 1] != '/')
suf = '/';
mode[0] = 'd';
color = LS_DIR_COLOR;
}
else if (S_ISLNK(node->stats.st_mode)) {
suf = '@';
mode[0] = 'l';
color = LS_LINK_COLOR;
}
else if (S_ISSOCK(node->stats.st_mode)) {
suf = '=';
mode[0] = 's';
color = LS_SOCK_COLOR;
}
else if (S_ISBLK(node->stats.st_mode)) {
mode[0] = 'b';
color = LS_BLOCK_COLOR;
}
else if (S_ISFIFO(node->stats.st_mode)) {
suf = '|';
mode[0] = 'p';
color = LS_FIFO_COLOR;
}
else if ((node->stats.st_mode & S_IXUSR) || (node->stats.st_mode & S_IXGRP) || (node->stats.st_mode & S_IXOTH)) {
suf = '*';
color = LS_EXE_COLOR;
}
int ret = 0;
if (i_flag)
ret += printf("%7ju ", (uintmax_t)node->stats.st_ino);
if (s_flag) {
off_t size = 512 * node->stats.st_blocks;
if (h_flag)
ret += printf("%7s ", mu_humansize(size, 1024));
else
ret += printf("%7jd ", size / 1024);
}
if (l_flag) {
printf("%s", mode);
struct passwd *pw = getpwuid(node->stats.st_uid);
struct group *gr = getgrgid(node->stats.st_gid);
if (pw == NULL || gr == NULL) {
fprintf(stderr, "ls: print: %s\n", strerror(errno));
return -1;
}
if (h_flag)
ret += printf(" %4ju %4s %6s %6s %s ", (uintmax_t)node->stats.st_nlink, pw->pw_name, gr->gr_name, mu_humansize(node->stats.st_size, 1024), get_date(node->stats.st_mtime));
else
ret += printf(" %4ju %4s %6s %10ld %s ", (uintmax_t)node->stats.st_nlink, pw->pw_name, gr->gr_name, node->stats.st_size, get_date(node->stats.st_mtime));
}
if (c_flag && p_flag)
printf("%s", color);
printf("%s", node->name);
ret += utf8_strlen(node->name);
if (c_flag && p_flag)
printf("\033[0m");
if (F_flag)
printf("%c", suf);
return ret;
}
int col_print(struct d_node **node, const size_t files, const struct winsize w) {
/* Get max len */
size_t maxlen = 0;
for (size_t i = 0; i < files; i++) {
size_t len = utf8_strlen(node[i]->name);
if (len > maxlen)
maxlen = len;
}
/* Calc */
maxlen += 3;
if (i_flag)
maxlen += 10;
if (s_flag)
maxlen += 10;
size_t ncols = w.ws_col / maxlen;
size_t nrows = files;
if (ncols > 1) {
nrows = files / ncols;
if (nrows * ncols < files)
nrows++;
}
else
ncols = 1;
int col = 0;
int nexttab = 0;
/* Mc print */
for (size_t i = 0; i < nrows; i++) {
for (size_t j = 0; j < ncols; j++) {
size_t index = j * nrows + i;
if (index < files) {
if (col > 0) {
nexttab -= col;
col += nexttab;
for (int k = 0; k < nexttab; k++)
putchar(' ');
}
nexttab = col + (int)maxlen;
int ret = print(node[index]);
if (ret == -1)
return 1;
col += ret;
}
}
putchar((nul_flag) ? '\0' : '\n');
col = 0;
}
return 0;
}
int struct_print(struct d_node **dir, const size_t files, const struct winsize w) {
int ret = 0;
/* pipe print */
if (!p_flag || l_flag || O_flag) {
for (size_t i = 0; i < files; i++) {
if (print(dir[i]) == -1)
ret = 1;
putchar((nul_flag) ? '\0' : '\n');
}
}
else
if (col_print(dir, files, w))
ret = 1;
return ret;
}
/* Sort */
int sortt(const void *p1, const void *p2) {
return (*(struct d_node **)p2)->stats.st_mtime - (*(struct d_node **)p1)->stats.st_mtime;
}
int sorts(const void *p1, const void *p2) {
return (*(struct d_node **)p2)->stats.st_size - (*(struct d_node **)p1)->stats.st_size;
}
int sortd(const void *p1, const void *p2) {
return strcmp((*(struct d_node **)p1)->full_name, (*(struct d_node **)p2)->full_name);
}
/* Ls */
int ls_dir(const char *dir_name, const int label, const struct winsize w) {
if (dir_name == NULL)
return 0;
int ret = 0;
size_t files = 0;
off_t total_size = 0;
struct d_node **dir = list(dir_name, &total_size, &files, &ret);
/* Title */
if ((label || R_flag) && !d_flag)
printf("\n%s:\n", dir_name);
if (l_flag) {
if (h_flag)
printf("total: %s\n", mu_humansize(total_size * 512, 1024));
else
printf("total: %jd\n", (intmax_t)total_size / 2);
}
if (dir == NULL)
return 1;
qsort(dir, files, sizeof(struct d_node *), sorter);
if (struct_print(dir, files, w))
ret = 1;
if (R_flag)
for (size_t i = 0; i < files; i++)
if (S_ISDIR(dir[i]->stats.st_mode) && strcmp(dir[i]->name, "..") && strcmp(dir[i]->name, "."))
ls_dir(dir[i]->full_name, 1, w);
dfree(dir, files);
return ret;
}
int ls_files(int argc, char **argv, const struct winsize w) {
size_t files = 0;
struct d_node **file = malloc(sizeof(struct d_node *));
if (file == NULL) {
fprintf(stderr, "ls: malloc: %s\n", strerror(errno));
return 1;
}
int ret = 0;
for (int i = 0; i < argc; i++) {
struct stat sb;
if (mu_get_lstat("ls", argv[i], &sb)) {
ret = 1;
continue;
}
if (S_ISDIR(sb.st_mode))
continue;
struct d_node **tmp = realloc(file, sizeof(struct d_node *) * (files + 1));
if (tmp == NULL) {
dfree(file, files);
return 1;
}
file = tmp;
file[files] = stat_file(argv[i], 1);
if (file[files] == NULL) {
dfree(file, files);
ret = 1;
break;
}
files++;
argv[i] = NULL;
}
qsort(file, files, sizeof(struct d_node *), sorter);
if (struct_print(file, files, w))
ret = 1;
return ret;
}
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "1alFcRdLhistS0")) != -1) {
switch (opt) {
case '1':
O_flag = 1;
break;
case 'a':
a_flag = 1;
break;
case 'l':
l_flag = 1;
break;
case 'F':
F_flag = 1;
break;
case 'c':
c_flag = 1;
break;
case 'R':
d_flag = 0;
R_flag = 1;
break;
case 'd':
R_flag = 0;
d_flag = 1;
break;
case 'L':
L_flag = 1;
break;
case 'h':
h_flag = 1;
break;
case 'i':
i_flag = 1;
break;
case 's':
s_flag = 1;
break;
case 't':
sorter = sortt;
break;
case 'S':
sorter = sorts;
break;
case '0':
nul_flag = 1;
break;
default:
printf("ls [1alFcRdLhistS0] [dir1 file2...]\n\t-a Show hidden files\n\t-l Use a long listing format\n\t-F Append indicator to names\n\t-c Color mode\n\t-R Recursive\n\t-1 One column\n\t-d Print only dir names\n\t-L Follow symlinks\n\t-h Sizes in human readable format\n\t-i Listen inodes\n\t-t Sort by mtime\n\t-S Sort by size\n\t-s Print file size\n\t-0 End line with \\0\n");
return 0;
}
}
argv += optind;
argc -= optind;
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
/* Check if programm piped, 1 - false, 0 - true */
p_flag = isatty(STDOUT_FILENO);
int ret = 0;
if (ls_files(argc, argv, w))
ret = 1;
if (argc == 0) {
if (ls_dir(".", 0, w))
ret = 1;
}
else if (argc == 1) {
if (ls_dir(argv[0], 0, w))
ret = 1;
}
else {
for (int i = 0; i < argc; i++)
if (ls_dir(argv[i], 1, w))
ret = 1;
}
return ret;
}

3
src/coreutils/mkdir/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,85 @@
#include <sys/stat.h>
#include <libgen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "parse_mode.h"
char v_flag;
char p_flag;
mode_t mode = 0777;
int do_mkdir(const char *path) {
if (mkdir(path, mode)) {
if (p_flag)
return 0;
fprintf(stderr, "mkdir: %s: %s\n", path, strerror(errno));
return 1;
}
else if (v_flag)
printf("mkdir: %s created with mode %u\n", path, mode);
return 0;
}
int do_parents(const char *path) {
if (path[0] == '.' || path[0] == '/')
return 0;
char *path2 = strdup(path);
if (!path2) {
fprintf(stderr, "mkdir: %s: %s\n", path, strerror(errno));
return 1;
}
const char *par = dirname(path2);
do_parents(par);
int ret = do_mkdir(path2);
free(path2);
return ret;
}
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "pm:v")) != -1) {
switch (opt) {
case 'p':
p_flag = 1;
break;
case 'm':
mode = mu_parse_mode(optarg, 0);
break;
case 'v':
v_flag = 1;
break;
default:
printf("mkdir [pmv] [dst1 dst2...]\n\t-p Make parent dir\n\t-m MODE Mode\n\t-v Verbose\n");
return 0;
}
}
argv += optind;
argc -= optind;
for (int i = 0; i < argc; i++) {
if (p_flag) {
if (do_parents(argv[i]))
return 1;
}
else {
if (do_mkdir(argv[i]))
return 1;
}
}
return 0;
}

3
src/coreutils/mknod/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,81 @@
#ifdef __linux__
#include <sys/sysmacros.h>
#endif
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include "parse_mode.h"
long parse_long(const char *str) {
char *ptr = NULL;
long value = strtol(str, &ptr, 10);
if (*ptr) {
fprintf(stderr, "mknod: not a number: %s\n", str);
exit(1);
}
else if (value < 0) {
fprintf(stderr, "mknod: number is negative: %s\n", str);
exit(1);
}
return value;
}
int main(int argc, char **argv) {
mode_t mode = 0666;
int opt;
while ((opt = getopt(argc, argv, "m:")) != -1) {
switch (opt) {
case 'm':
mode = mu_parse_mode(optarg, 0);
break;
default:
printf("mknod [m] [NAME] [TYPE] [MAJOR MINOR]\n\t-m MODE\n\n");
printf("Types:\n\tb - block device\n\tc or u - character device\n\tp - named pipe/fifo (MAJOR MINOR must be omitted)\n\ts - socket\n");
return 0;
}
}
argv += optind;
argc -= optind;
if (argc <= 1) {
fprintf(stderr, "mknod: missing operand\n");
return 1;
}
dev_t dev = 0;
if (argc == 4)
dev = makedev(parse_long(argv[2]), parse_long(argv[3]));
if (!strncmp("b", argv[1], 1))
mode |= S_IFBLK;
else if (!strncmp("c", argv[1], 1) || !strncmp("u", argv[1], 1))
mode |= S_IFCHR;
else if (!strncmp("p", argv[1], 1))
mode |= S_IFIFO;
else if (!strncmp("s", argv[1], 1))
mode |= S_IFSOCK;
else {
fprintf(stderr, "mknod: unknow file type\n");
return 1;
}
if (mknod(argv[0], mode, dev) < 0) {
fprintf(stderr, "mknod: %s\n", strerror(errno));
return 1;
}
return 0;
}

3
src/coreutils/mktemp/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,98 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include "make_path.h"
int make_temp_dir(char *tmp) {
if (!mkdtemp(tmp)) {
if (errno == EINVAL)
fprintf(stderr, "mktemp: template does not end in exactly 'XXXXX': %s\n", tmp);
else
fprintf(stderr, "mktemp: %s\n", strerror(errno));
return 1;
}
return 0;
}
int get_suffix(const char *str) {
size_t len = strlen(str);
for (size_t i = len - 1; i > 0; i--)
if (str[i] == 'X')
return len - i - 1;
return 0;
}
int make_temp_file(char *tmp) {
if (!strstr(tmp, "XXXXXX")) {
fprintf(stderr, "mktemp: too few X's in template: %s\n", tmp);
return 1;
}
int fd = mkstemps(tmp, get_suffix(tmp));
if (fd < 0) {
fprintf(stderr, "mktemp: %s\n", strerror(errno));
return 1;
}
close(fd);
return 0;
}
int main(int argc, char **argv) {
unsigned int d_flag = 0;
char *path = NULL;
int opt;
while ((opt = getopt(argc, argv, "dp:")) != -1) {
switch (opt) {
case 'd':
d_flag = 1;
break;
case 'p':
path = optarg;
break;
default:
printf("mktemp [dp] [file]\n\t-d Dir\n\t-p Base dir\n");
return 0;
}
}
argv += optind;
argc -= optind;
if (argc == 0 && path == NULL) {
path = getenv("TMPDIR");
if (!path || path[0] == '\0')
path = "/tmp/";
}
char *x = mu_make_path("mktemp", path, (argc == 0) ? "tmp.XXXXXX" : argv[0]);
if (x == NULL)
return 1;
if (d_flag) {
if (make_temp_dir(x)) {
free(x);
return 1;
}
}
else {
if (make_temp_file(x)) {
free(x);
return 1;
}
}
puts(x);
free(x);
return 0;
}

3
src/coreutils/mv/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

62
src/coreutils/mv/mv.c Normal file
View File

@ -0,0 +1,62 @@
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "make_path.h"
char *f_flag = "mv";
int move(const char *src, const char *dst) {
char *copy = strdup(src);
if (!copy)
return 1;
char *new_path = mu_make_path(f_flag, dst, basename(copy));
if (new_path == NULL) {
free(copy);
return 1;
}
int ret = 0;
if (rename(src, new_path) < 0)
ret = 1;
free(new_path);
free(copy);
return ret;
}
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "f")) != -1) {
switch (opt) {
case 'f':
f_flag = NULL;
break;
default:
printf("mv [f] [src1 src2...] [dst]\n\t-f Force\n");
return 0;
}
}
argv += optind;
argc -= optind;
/* Move code */
for (int i = 0; i < argc - 1; i++) {
if (move(argv[i], argv[argc - 1])) {
if (rename(argv[i], argv[argc - 1]) < 0) {
if (f_flag)
fprintf(stderr, "mv: %s %s\n", argv[i], strerror(errno));
return 1;
}
}
}
return 0;
}

3
src/coreutils/nice/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

43
src/coreutils/nice/nice.c Normal file
View File

@ -0,0 +1,43 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/resource.h>
int main(int argc, char **argv) {
int oldp = getpriority(PRIO_PROCESS, 0);
int adj = 10;
int opt;
while ((opt = getopt(argc, argv, "n:")) != -1) {
switch (opt) {
case 'n':
adj = atoi(optarg);
break;
default:
printf("nice [n] [cmd] [arg1] [arg2]\n\t-n N Add N to the niceness\n");
return 0;
}
}
argv += optind;
argc -= optind;
if (argc == 0) {
printf("%d\n", oldp);
return 0;
}
if (setpriority(PRIO_PROCESS, 0, oldp + adj) < 0) {
fprintf(stderr, "nice: %s\n", strerror(errno));
return 1;
}
execvp(argv[0], argv);
fprintf(stderr, "nice: %s: %s\n", argv[0], strerror(errno));
return 1;
}

3
src/coreutils/nohup/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,42 @@
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include "unused.h"
int main(int argc, char **argv) {
if (argc < 2) {
printf("nohup: missing operand\nnohup [cmd]\n");
return 0;
}
if (fork() != 0)
return 0;
signal(SIGHUP, SIG_IGN);
if (isatty(STDOUT_FILENO)) {
int fd = open("nohup.out", O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR);
if (fd < 0) {
fprintf(stderr, "nohup: nohup.out: %s\n", strerror(errno));
return 1;
}
if (dup2(fd, STDOUT_FILENO) < 0)
fprintf(stderr, "nohup: %s\n", strerror(errno));
close(fd);
}
if (isatty(STDERR_FILENO))
if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0)
fprintf(stderr, "nohup: %s\n", strerror(errno));
argv++;
execvp(argv[0], argv);
fprintf(stderr, "nohup: %s: %s\n", argv[0], strerror(errno));
return 1;
}

3
src/coreutils/nproc/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,11 @@
#include <stdio.h>
#include <unistd.h>
int main(void) {
long count = sysconf(_SC_NPROCESSORS_ONLN);
if (count <= 0)
count = 1;
printf("%ld\n", count);
return 0;
}

View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,40 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int printvars(int len, char **names) {
int ret = 0;
for (int i = 0; i < len; i++) {
char *val = getenv(names[i]);
if (!val) {
ret = 1;
continue;
}
printf("%s\n", val);
}
return ret;
}
int main(int argc, char **argv, const char **envp) {
int opt;
while ((opt = getopt(argc, argv, "0")) != -1) {
printf("printenv [var1 var2...]\n");
return 0;
}
argv += optind;
argc -= optind;
if (argc == 0)
while (*envp)
printf("%s\n", *envp++);
else
return printvars(argc, argv);
return 0;
}

3
src/coreutils/pwd/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

19
src/coreutils/pwd/pwd.c Normal file
View File

@ -0,0 +1,19 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
int main(void) {
char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd)))
puts(cwd);
else {
fprintf(stderr, "pwd: %s\n", strerror(errno));
return 1;
}
return 0;
}

View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,48 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
int main(int argc, char **argv) {
char n_flag = 0;
int opt;
while ((opt = getopt(argc, argv, "n")) != -1) {
switch (opt) {
case 'n':
n_flag = 1;
break;
default:
printf("readlink [n] [file1 file2...]\n\t-n Don't add newline\n");
return 0;
}
}
argv += optind;
argc -= optind;
for (int i = 0; i < argc; i++) {
char path[PATH_MAX + 1];
ssize_t r = readlink(argv[i], path, sizeof(path));
if (r < 0) {
fprintf(stderr, "readlink: %s: %s\n", argv[i], strerror(errno));
return 1;
}
if (r > (ssize_t)sizeof(path)) {
fprintf(stderr, "readlink: %s: path too long\n", argv[i]);
return 1;
}
if (n_flag)
fputs(path, stdout);
else
puts(path);
}
return 0;
}

3
src/coreutils/renice/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,73 @@
#include <pwd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/resource.h>
int renice(int which, int who, int adj) {
adj += getpriority(which, who);
if (setpriority(which, who, adj)) {
fprintf(stderr, "renice: %s\n", strerror(errno));
return 1;
}
return 0;
}
int main(int argc, char **argv) {
int adj = 10;
int which = PRIO_PROCESS;
int opt;
while ((opt = getopt(argc, argv, "n:gup")) != -1) {
switch (opt) {
case 'n':
adj = atoi(optarg);
break;
case 'g':
which = PRIO_PGRP;
break;
case 'u':
which = PRIO_USER;
break;
case 'p':
which = PRIO_PROCESS;
break;
default:
printf("renice [ngup] [id1 id2...]\n\t-n N Add N to the niceness\n\t-g Process group ids\n\t-u Process user names\n\t-p Process ids\n");
return 0;
}
}
argv += optind;
argc -= optind;
int who = 0;
int ret = 0;
for (int i = 0; i < argc; i++) {
if (which == PRIO_USER) {
struct passwd *pw = getpwnam(argv[i]);
if (pw == 0) {
fprintf(stderr, "renice: %s\n", strerror(errno));
return 1;
}
who = pw->pw_uid;
}
else
who = atoi(argv[i]);
if (renice(which, who, adj))
ret = 1;
}
return ret;
}

3
src/coreutils/rm/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

112
src/coreutils/rm/rm.c Normal file
View File

@ -0,0 +1,112 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <unistd.h>
#include <ctype.h>
#include "make_path.h"
#include "get_stat.h"
#include "recurse.h"
#include "unused.h"
char *f_flag = "rm";
char r_flag;
char v_flag;
int verbose(const char *path) {
if (v_flag) {
fprintf(stderr, "rm: remove %s? [y/n] ", path);
fflush(stderr);
int c = 0;
int key = 0;
while ((c = fgetc(stdin)) != EOF && c != '\n') {
if (c == 'y')
key = 1;
}
return key;
}
return 1;
}
void handle_error(const char *path) {
if (f_flag)
fprintf(stderr, "rm: %s: %s\n", path, strerror(errno));
}
int rm(const char *path, void *p) {
UNUSED(p);
if (verbose(path) && remove(path) < 0) {
handle_error(path);
return 1;
}
return 0;
}
int rmd(const char *path, void *p) {
UNUSED(p);
if (verbose(path) && rmdir(path) < 0) {
handle_error(path);
return 1;
}
return 0;
}
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "frRi")) != -1) {
switch (opt) {
case 'f':
f_flag = NULL;
break;
case 'r':
r_flag = 1;
break;
case 'i':
v_flag = 1;
break;
default:
printf("rm [rif] [file1 file2...]\n\t-f Force\n\t-r Recursive\n\t-i Print prompt before remove\n");
return 0;
}
}
argc -= optind;
argv += optind;
if (argc == 0) {
fprintf(stderr, "rm: missing operand\n");
return 1;
}
int ret = 0;
for (int i = 0; i < argc; i++) {
if (!strcmp(argv[i], ".") || !strcmp(argv[i], "..")){
printf("rm: refusing to remove '.' or '..' directory\n");
break;
}
if (r_flag) {
if (mu_recurse(f_flag, 1, argv[i], NULL, rm, rmd))
ret = 1;
}
else
if (rm(argv[i], NULL))
ret = 1;
}
return ret;
}

3
src/coreutils/seq/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

58
src/coreutils/seq/seq.c Normal file
View File

@ -0,0 +1,58 @@
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
double parse_double(const char *str) {
char *ptr;
double res = strtod(str, &ptr);
if (*ptr) {
fprintf(stderr, "seq: %s: cant parse\n", ptr);
exit(1);
}
return res;
}
int main(int argc, char **argv) {
double start = 1;
double last = 0;
double n = 1;
argv++;
argc--;
switch (argc) {
case 1:
last = parse_double(argv[0]);
break;
case 2:
start = parse_double(argv[0]);
last = parse_double(argv[1]);
break;
case 3:
n = parse_double(argv[1]);
start = parse_double(argv[0]);
last = parse_double(argv[2]);
break;
default:
fprintf(stderr, "seq: missing operands\n");
return 1;
}
if (start <= last && n >= 0) {
for (double i = start; i <= last; i += n)
printf("%g\n", i);
}
else if (n <= 0)
for (double i = start; i >= last; i += n)
printf("%g\n", i);
return 0;
}

3
src/coreutils/setsid/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,21 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include "unused.h"
int main(int argc, char **argv) {
UNUSED(argc);
if (argv[1] == NULL) {
printf("setsid [cmd] [arg1 arg2...]\n");
return 1;
}
if (fork() != 0)
return 0;
setsid();
execvp(argv[1], argv + 1);
}

3
src/coreutils/shred/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

113
src/coreutils/shred/shred.c Normal file
View File

@ -0,0 +1,113 @@
#define _SHRED_C
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include "config.h"
char f_flag;
char u_flag;
char z_flag;
int n_loops = 3;
int shred(int rand_fd, int fd) {
/* Get size */
off_t size = lseek(fd, 0, SEEK_END);
if (size <= 0)
return 1;
void *buf = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0);
if (buf == MAP_FAILED) {
fprintf(stderr, "shred: mmap: %s\n", strerror(errno));
return 1;
}
for (char n = 0; n < n_loops; n++) {
if (read(rand_fd, buf, size) == 0)
fprintf(stderr, "shred: %s", strerror(errno));
fsync(fd);
}
if (z_flag)
memset(buf, 0, size);
if (munmap(buf, size)) {
fprintf(stderr, "shred: munmap: %s\n", strerror(errno));
return 1;
}
return 0;
}
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "fuzn:")) != -1) {
switch (opt) {
case 'f':
f_flag = 1;
break;
case 'u':
u_flag = 1;
break;
case 'z':
z_flag = 1;
break;
case 'n':
n_loops = atoi(optarg);
break;
default:
printf("shred [fuzn] [file1 file2...]\n\t-n N Overwrite N times, default 3\n\t-z Final overwrite with zeros\n\t-u Remove file\n\t-f Chmod to ensure writability\n");
return 0;
}
}
argv += optind;
argc -= optind;
if (argc == 0) {
fprintf(stderr, "shred: missing operand\n");
return 1;
}
int rand_fd = open(RAND_SOURCE, O_RDONLY);
if (rand_fd < 0) {
fprintf(stderr, "shred: %s: %s\n", RAND_SOURCE, strerror(errno));
return 1;
}
for (int i = 0; i < argc; i++) {
int fd = open(argv[i], O_RDWR);
if (fd < 0) {
fprintf(stderr, "shred: %s is %s\n", argv[i], strerror(errno));
continue;
}
shred(rand_fd, fd);
fsync(fd);
close(fd);
if (f_flag) {
if (chmod(argv[i], 0) < 0)
fprintf(stderr, "shred: %s is %s\n", argv[i], strerror(errno));
}
if (u_flag) {
if (unlink(argv[i]) < 0)
fprintf(stderr, "shred: %s is %s\n", argv[i], strerror(errno));
}
}
close(rand_fd);
return 0;
}

3
src/coreutils/sleep/build.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
project_dir=$(pwd)
echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC

View File

@ -0,0 +1,29 @@
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include "duration.h"
int main(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "")) != -1 || argc == 1) {
printf("sleep [num[SUFFIX]] or [inf Infinity]\nSUFFIXES:\n\tm - minute\n\th - hour\n\td - days\n");
return 0;
}
argv += optind;
argc -= optind;
if (!strncasecmp(argv[0], "inf", 3))
while (1)
sleep(INT_MAX);
unsigned long long usec = 0;
for (int i = 0; i < argc; i++)
usec += mu_parse_duration(argv[i]);
usleep(usec);
return 0;
}

Some files were not shown because too many files have changed in this diff Show More