From 21be7fd2794a1c186b4e58cbc68c7cc57f255cc4 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 1 Jul 2024 13:23:00 +0300 Subject: [PATCH] first commit --- LICENSE | 14 + README.md | 5 + TODO | 57 ++ bin/.gitignore | 0 build.sh | 36 ++ config.h | 60 ++ configs/fstab | 9 + configs/group | 2 + configs/hostname | 1 + configs/motd | 1 + configs/os-release | 4 + configs/passwd | 2 + configs/rc.init | 9 + configs/rc.poweroff | 12 + configs/resolv.conf | 1 + include/libmu/duration.h | 48 ++ include/libmu/get_stat.h | 39 ++ include/libmu/human.h | 30 + include/libmu/make_path.h | 39 ++ include/libmu/mode_to_str.h | 57 ++ include/libmu/parse_mode.h | 99 ++++ include/libmu/parse_mount.h | 72 +++ include/libmu/pw_check.h | 59 ++ include/libmu/recurse.h | 54 ++ include/libmu/unused.h | 6 + include/libmu/utf8_strlen.h | 13 + src/console-tools/clear/build.sh | 3 + src/console-tools/clear/clear.c | 5 + src/console-tools/reset/build.sh | 3 + src/console-tools/reset/reset.c | 5 + src/coreutils/bdname/bdname.c | 57 ++ src/coreutils/bdname/build.sh | 3 + src/coreutils/cat/build.sh | 3 + src/coreutils/cat/cat.c | 54 ++ src/coreutils/chgrp/build.sh | 3 + src/coreutils/chgrp/chgrp.c | 92 +++ src/coreutils/chmod/build.sh | 3 + src/coreutils/chmod/chmod.c | 103 ++++ src/coreutils/chown/build.sh | 3 + src/coreutils/chown/chown.c | 131 +++++ src/coreutils/chroot/build.sh | 3 + src/coreutils/chroot/chroot.c | 29 + src/coreutils/cmp/build.sh | 3 + src/coreutils/cmp/cmp.c | 126 ++++ src/coreutils/cp/build.sh | 3 + src/coreutils/cp/cp.c | 213 +++++++ src/coreutils/date/build.sh | 3 + src/coreutils/date/date.c | 109 ++++ src/coreutils/dd/build.sh | 3 + src/coreutils/dd/dd.c | 249 ++++++++ src/coreutils/df/build.sh | 3 + src/coreutils/df/df.c | 95 +++ src/coreutils/du/build.sh | 3 + src/coreutils/du/du.c | 111 ++++ src/coreutils/echo/build.sh | 3 + src/coreutils/echo/echo.c | 94 +++ src/coreutils/env/build.sh | 3 + src/coreutils/env/env.c | 33 ++ src/coreutils/false/build.sh | 3 + src/coreutils/false/false.c | 3 + src/coreutils/head/build.sh | 3 + src/coreutils/head/head.c | 95 +++ src/coreutils/id/build.sh | 3 + src/coreutils/id/id.c | 130 +++++ src/coreutils/ln/build.sh | 3 + src/coreutils/ln/ln.c | 76 +++ src/coreutils/ls/build.sh | 3 + src/coreutils/ls/ls.c | 508 ++++++++++++++++ src/coreutils/mkdir/build.sh | 3 + src/coreutils/mkdir/mkdir.c | 85 +++ src/coreutils/mknod/build.sh | 3 + src/coreutils/mknod/mknod.c | 81 +++ src/coreutils/mktemp/build.sh | 3 + src/coreutils/mktemp/mktemp.c | 98 ++++ src/coreutils/mv/build.sh | 3 + src/coreutils/mv/mv.c | 62 ++ src/coreutils/nice/build.sh | 3 + src/coreutils/nice/nice.c | 43 ++ src/coreutils/nohup/build.sh | 3 + src/coreutils/nohup/nohup.c | 42 ++ src/coreutils/nproc/build.sh | 3 + src/coreutils/nproc/nproc.c | 11 + src/coreutils/printenv/build.sh | 3 + src/coreutils/printenv/printenv.c | 40 ++ src/coreutils/pwd/build.sh | 3 + src/coreutils/pwd/pwd.c | 19 + src/coreutils/readlink/build.sh | 3 + src/coreutils/readlink/readlink.c | 48 ++ src/coreutils/renice/build.sh | 3 + src/coreutils/renice/renice.c | 73 +++ src/coreutils/rm/build.sh | 3 + src/coreutils/rm/rm.c | 112 ++++ src/coreutils/seq/build.sh | 3 + src/coreutils/seq/seq.c | 58 ++ src/coreutils/setsid/build.sh | 3 + src/coreutils/setsid/setsid.c | 21 + src/coreutils/shred/build.sh | 3 + src/coreutils/shred/shred.c | 113 ++++ src/coreutils/sleep/build.sh | 3 + src/coreutils/sleep/sleep.c | 29 + src/coreutils/split/build.sh | 3 + src/coreutils/split/split.c | 119 ++++ src/coreutils/sync/build.sh | 3 + src/coreutils/sync/sync.c | 6 + src/coreutils/tee/build.sh | 3 + src/coreutils/tee/tee.c | 61 ++ src/coreutils/time/build.sh | 3 + src/coreutils/time/time.c | 56 ++ src/coreutils/touch/build.sh | 3 + src/coreutils/touch/touch.c | 147 +++++ src/coreutils/true/build.sh | 3 + src/coreutils/true/true.c | 3 + src/coreutils/tty/build.sh | 3 + src/coreutils/tty/tty.c | 13 + src/coreutils/uname/build.sh | 3 + src/coreutils/uname/uname.c | 132 +++++ src/coreutils/wc/build.sh | 3 + src/coreutils/wc/wc.c | 133 +++++ src/coreutils/whoami/build.sh | 3 + src/coreutils/whoami/whoami.c | 18 + src/coreutils/yes/build.sh | 3 + src/coreutils/yes/yes.c | 24 + src/editors/que/build.sh | 3 + src/editors/que/que.c | 637 +++++++++++++++++++++ src/findutils/grep/build.sh | 3 + src/findutils/grep/grep.c | 64 +++ src/findutils/xargs/build.sh | 3 + src/findutils/xargs/xargs.c | 318 ++++++++++ src/init/init/build.sh | 5 + src/init/init/init.c | 64 +++ src/init/init/poweroff | 2 + src/init/init/reboot | 2 + src/loginutils/cryptpw/build.sh | 3 + src/loginutils/cryptpw/cryptpw.c | 20 + src/loginutils/login/build.sh | 3 + src/loginutils/login/login.c | 123 ++++ src/loginutils/su/build.sh | 3 + src/loginutils/su/su.c | 149 +++++ src/miscutils/spark/build.sh | 3 + src/miscutils/spark/spark.c | 80 +++ src/networking/hostname/build.sh | 3 + src/networking/hostname/hostname.c | 74 +++ src/procps/kill/build.sh | 3 + src/procps/kill/kill.c | 124 ++++ src/procps/ps/build.sh | 3 + src/procps/ps/ps.c | 68 +++ src/procps/uptime/build.sh | 3 + src/procps/uptime/uptime.c | 59 ++ src/sysutils-linux/dmesg/build.sh | 3 + src/sysutils-linux/dmesg/dmesg.c | 68 +++ src/sysutils-linux/mount/build.sh | 3 + src/sysutils-linux/mount/mount.c | 110 ++++ src/sysutils-linux/pivot_root/build.sh | 3 + src/sysutils-linux/pivot_root/pivot_root.c | 19 + src/sysutils-linux/umount/build.sh | 3 + src/sysutils-linux/umount/umount.c | 70 +++ 156 files changed, 6939 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 TODO create mode 100755 bin/.gitignore create mode 100755 build.sh create mode 100644 config.h create mode 100644 configs/fstab create mode 100644 configs/group create mode 100644 configs/hostname create mode 100644 configs/motd create mode 100644 configs/os-release create mode 100644 configs/passwd create mode 100644 configs/rc.init create mode 100644 configs/rc.poweroff create mode 100644 configs/resolv.conf create mode 100644 include/libmu/duration.h create mode 100644 include/libmu/get_stat.h create mode 100644 include/libmu/human.h create mode 100644 include/libmu/make_path.h create mode 100644 include/libmu/mode_to_str.h create mode 100644 include/libmu/parse_mode.h create mode 100644 include/libmu/parse_mount.h create mode 100644 include/libmu/pw_check.h create mode 100644 include/libmu/recurse.h create mode 100644 include/libmu/unused.h create mode 100644 include/libmu/utf8_strlen.h create mode 100755 src/console-tools/clear/build.sh create mode 100644 src/console-tools/clear/clear.c create mode 100755 src/console-tools/reset/build.sh create mode 100644 src/console-tools/reset/reset.c create mode 100644 src/coreutils/bdname/bdname.c create mode 100755 src/coreutils/bdname/build.sh create mode 100755 src/coreutils/cat/build.sh create mode 100644 src/coreutils/cat/cat.c create mode 100755 src/coreutils/chgrp/build.sh create mode 100644 src/coreutils/chgrp/chgrp.c create mode 100755 src/coreutils/chmod/build.sh create mode 100644 src/coreutils/chmod/chmod.c create mode 100755 src/coreutils/chown/build.sh create mode 100644 src/coreutils/chown/chown.c create mode 100755 src/coreutils/chroot/build.sh create mode 100644 src/coreutils/chroot/chroot.c create mode 100755 src/coreutils/cmp/build.sh create mode 100644 src/coreutils/cmp/cmp.c create mode 100755 src/coreutils/cp/build.sh create mode 100644 src/coreutils/cp/cp.c create mode 100755 src/coreutils/date/build.sh create mode 100644 src/coreutils/date/date.c create mode 100755 src/coreutils/dd/build.sh create mode 100644 src/coreutils/dd/dd.c create mode 100755 src/coreutils/df/build.sh create mode 100644 src/coreutils/df/df.c create mode 100755 src/coreutils/du/build.sh create mode 100644 src/coreutils/du/du.c create mode 100755 src/coreutils/echo/build.sh create mode 100644 src/coreutils/echo/echo.c create mode 100755 src/coreutils/env/build.sh create mode 100644 src/coreutils/env/env.c create mode 100755 src/coreutils/false/build.sh create mode 100644 src/coreutils/false/false.c create mode 100755 src/coreutils/head/build.sh create mode 100644 src/coreutils/head/head.c create mode 100755 src/coreutils/id/build.sh create mode 100644 src/coreutils/id/id.c create mode 100755 src/coreutils/ln/build.sh create mode 100644 src/coreutils/ln/ln.c create mode 100755 src/coreutils/ls/build.sh create mode 100644 src/coreutils/ls/ls.c create mode 100755 src/coreutils/mkdir/build.sh create mode 100644 src/coreutils/mkdir/mkdir.c create mode 100755 src/coreutils/mknod/build.sh create mode 100644 src/coreutils/mknod/mknod.c create mode 100755 src/coreutils/mktemp/build.sh create mode 100644 src/coreutils/mktemp/mktemp.c create mode 100755 src/coreutils/mv/build.sh create mode 100644 src/coreutils/mv/mv.c create mode 100755 src/coreutils/nice/build.sh create mode 100644 src/coreutils/nice/nice.c create mode 100755 src/coreutils/nohup/build.sh create mode 100644 src/coreutils/nohup/nohup.c create mode 100755 src/coreutils/nproc/build.sh create mode 100644 src/coreutils/nproc/nproc.c create mode 100755 src/coreutils/printenv/build.sh create mode 100644 src/coreutils/printenv/printenv.c create mode 100755 src/coreutils/pwd/build.sh create mode 100644 src/coreutils/pwd/pwd.c create mode 100755 src/coreutils/readlink/build.sh create mode 100644 src/coreutils/readlink/readlink.c create mode 100755 src/coreutils/renice/build.sh create mode 100644 src/coreutils/renice/renice.c create mode 100755 src/coreutils/rm/build.sh create mode 100644 src/coreutils/rm/rm.c create mode 100755 src/coreutils/seq/build.sh create mode 100644 src/coreutils/seq/seq.c create mode 100755 src/coreutils/setsid/build.sh create mode 100644 src/coreutils/setsid/setsid.c create mode 100755 src/coreutils/shred/build.sh create mode 100644 src/coreutils/shred/shred.c create mode 100755 src/coreutils/sleep/build.sh create mode 100644 src/coreutils/sleep/sleep.c create mode 100755 src/coreutils/split/build.sh create mode 100644 src/coreutils/split/split.c create mode 100755 src/coreutils/sync/build.sh create mode 100644 src/coreutils/sync/sync.c create mode 100755 src/coreutils/tee/build.sh create mode 100644 src/coreutils/tee/tee.c create mode 100755 src/coreutils/time/build.sh create mode 100644 src/coreutils/time/time.c create mode 100755 src/coreutils/touch/build.sh create mode 100644 src/coreutils/touch/touch.c create mode 100755 src/coreutils/true/build.sh create mode 100644 src/coreutils/true/true.c create mode 100755 src/coreutils/tty/build.sh create mode 100644 src/coreutils/tty/tty.c create mode 100755 src/coreutils/uname/build.sh create mode 100644 src/coreutils/uname/uname.c create mode 100755 src/coreutils/wc/build.sh create mode 100644 src/coreutils/wc/wc.c create mode 100755 src/coreutils/whoami/build.sh create mode 100644 src/coreutils/whoami/whoami.c create mode 100755 src/coreutils/yes/build.sh create mode 100644 src/coreutils/yes/yes.c create mode 100755 src/editors/que/build.sh create mode 100644 src/editors/que/que.c create mode 100755 src/findutils/grep/build.sh create mode 100644 src/findutils/grep/grep.c create mode 100755 src/findutils/xargs/build.sh create mode 100644 src/findutils/xargs/xargs.c create mode 100755 src/init/init/build.sh create mode 100644 src/init/init/init.c create mode 100644 src/init/init/poweroff create mode 100644 src/init/init/reboot create mode 100755 src/loginutils/cryptpw/build.sh create mode 100644 src/loginutils/cryptpw/cryptpw.c create mode 100755 src/loginutils/login/build.sh create mode 100644 src/loginutils/login/login.c create mode 100755 src/loginutils/su/build.sh create mode 100644 src/loginutils/su/su.c create mode 100644 src/miscutils/spark/build.sh create mode 100644 src/miscutils/spark/spark.c create mode 100755 src/networking/hostname/build.sh create mode 100644 src/networking/hostname/hostname.c create mode 100755 src/procps/kill/build.sh create mode 100644 src/procps/kill/kill.c create mode 100755 src/procps/ps/build.sh create mode 100644 src/procps/ps/ps.c create mode 100755 src/procps/uptime/build.sh create mode 100644 src/procps/uptime/uptime.c create mode 100755 src/sysutils-linux/dmesg/build.sh create mode 100644 src/sysutils-linux/dmesg/dmesg.c create mode 100755 src/sysutils-linux/mount/build.sh create mode 100644 src/sysutils-linux/mount/mount.c create mode 100755 src/sysutils-linux/pivot_root/build.sh create mode 100644 src/sysutils-linux/pivot_root/pivot_root.c create mode 100755 src/sysutils-linux/umount/build.sh create mode 100644 src/sysutils-linux/umount/umount.c diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1691ec3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,14 @@ +DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE + +Version 2, December 2004 + +Copyright (C) 2004 Sam Hocevar + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..38b5698 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# micro-utils +Own implementation of *nix utils +License: wtfpl + +Author: 8nl diff --git a/TODO b/TODO new file mode 100644 index 0000000..27dd23c --- /dev/null +++ b/TODO @@ -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) diff --git a/bin/.gitignore b/bin/.gitignore new file mode 100755 index 0000000..e69de29 diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..79d3412 --- /dev/null +++ b/build.sh @@ -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/ diff --git a/config.h b/config.h new file mode 100644 index 0000000..5ba573f --- /dev/null +++ b/config.h @@ -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 diff --git a/configs/fstab b/configs/fstab new file mode 100644 index 0000000..207f03a --- /dev/null +++ b/configs/fstab @@ -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 diff --git a/configs/group b/configs/group new file mode 100644 index 0000000..d249592 --- /dev/null +++ b/configs/group @@ -0,0 +1,2 @@ +root::0:root + diff --git a/configs/hostname b/configs/hostname new file mode 100644 index 0000000..2fbb50c --- /dev/null +++ b/configs/hostname @@ -0,0 +1 @@ +localhost diff --git a/configs/motd b/configs/motd new file mode 100644 index 0000000..d8e9d74 --- /dev/null +++ b/configs/motd @@ -0,0 +1 @@ +Welcome! diff --git a/configs/os-release b/configs/os-release new file mode 100644 index 0000000..335acde --- /dev/null +++ b/configs/os-release @@ -0,0 +1,4 @@ +NAME="Plain Os" +ID=plainos +VERSION_ID=0.1 +PRETTY_NAME="PlainOs/Linux 0.1 " \ No newline at end of file diff --git a/configs/passwd b/configs/passwd new file mode 100644 index 0000000..013ee3d --- /dev/null +++ b/configs/passwd @@ -0,0 +1,2 @@ +root::0:0:root:/usr/root:/bin/sh +nobody:*:65534:65534:nobody:/nonexistent:/bin/false diff --git a/configs/rc.init b/configs/rc.init new file mode 100644 index 0000000..ea6b926 --- /dev/null +++ b/configs/rc.init @@ -0,0 +1,9 @@ +#!/bin/sh +echo "[*] Mounting..." +mount -a + +echo "[*] Hostname..." +hostname -c /etc/hostname + +cat /etc/motd +env TERM="linux" login diff --git a/configs/rc.poweroff b/configs/rc.poweroff new file mode 100644 index 0000000..ce8e6f6 --- /dev/null +++ b/configs/rc.poweroff @@ -0,0 +1,12 @@ +#!/bin/sh +echo "[*] Umounting..." +umount -a + +echo "[*] Syncing..." +sync + +echo "[*] Closing processes..." +kill -a -s TERM +sleep 5 + +echo "[*] Poweroff..." diff --git a/configs/resolv.conf b/configs/resolv.conf new file mode 100644 index 0000000..54ae34b --- /dev/null +++ b/configs/resolv.conf @@ -0,0 +1 @@ +nameserver 192.168.0.1 diff --git a/include/libmu/duration.h b/include/libmu/duration.h new file mode 100644 index 0000000..14a491e --- /dev/null +++ b/include/libmu/duration.h @@ -0,0 +1,48 @@ +#ifndef _DURATION_H +#define _DURATION_H + +#include + +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 diff --git a/include/libmu/get_stat.h b/include/libmu/get_stat.h new file mode 100644 index 0000000..da72aec --- /dev/null +++ b/include/libmu/get_stat.h @@ -0,0 +1,39 @@ +#ifndef _GET_STAT_H +#define _GET_STAT_H + +#include +#include +#include +#include + +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 diff --git a/include/libmu/human.h b/include/libmu/human.h new file mode 100644 index 0000000..8b7ba5d --- /dev/null +++ b/include/libmu/human.h @@ -0,0 +1,30 @@ +#ifndef _HUMAN_H +#define _HUMAN_H + +#include +#include + +#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 diff --git a/include/libmu/make_path.h b/include/libmu/make_path.h new file mode 100644 index 0000000..f042e73 --- /dev/null +++ b/include/libmu/make_path.h @@ -0,0 +1,39 @@ +#ifndef _MAKE_PATH_H +#define _MAKE_PATH_H + +#include +#include +#include + +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 diff --git a/include/libmu/mode_to_str.h b/include/libmu/mode_to_str.h new file mode 100644 index 0000000..de56f83 --- /dev/null +++ b/include/libmu/mode_to_str.h @@ -0,0 +1,57 @@ +#ifndef _MODE_TO_STR_H +#define _MODE_TO_STR_H + +#include +#include + +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 diff --git a/include/libmu/parse_mode.h b/include/libmu/parse_mode.h new file mode 100644 index 0000000..884e9db --- /dev/null +++ b/include/libmu/parse_mode.h @@ -0,0 +1,99 @@ +#ifndef _PARSE_MODE_H +#define _PARSE_MODE_H + +#include +#include + +#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 diff --git a/include/libmu/parse_mount.h b/include/libmu/parse_mount.h new file mode 100644 index 0000000..0f07c4d --- /dev/null +++ b/include/libmu/parse_mount.h @@ -0,0 +1,72 @@ +#ifndef _PARSE_MOUNT_H +#define _PARSE_MOUNT_H +#include + +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 diff --git a/include/libmu/pw_check.h b/include/libmu/pw_check.h new file mode 100644 index 0000000..7a6654f --- /dev/null +++ b/include/libmu/pw_check.h @@ -0,0 +1,59 @@ +#ifndef _PW_CHECK_H +#define _PW_CHECK_H + +#include +#include +#include +#include +#include +#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 diff --git a/include/libmu/recurse.h b/include/libmu/recurse.h new file mode 100644 index 0000000..0c8a0df --- /dev/null +++ b/include/libmu/recurse.h @@ -0,0 +1,54 @@ +#ifndef _RECURSE_H +#define _RECURSE_H + +#include +#include +#include +#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 diff --git a/include/libmu/unused.h b/include/libmu/unused.h new file mode 100644 index 0000000..09dfc9c --- /dev/null +++ b/include/libmu/unused.h @@ -0,0 +1,6 @@ +#ifndef _UNUSED_H +#define _UNUSED_H + +#define UNUSED(p) ((void)p) + +#endif diff --git a/include/libmu/utf8_strlen.h b/include/libmu/utf8_strlen.h new file mode 100644 index 0000000..29e2573 --- /dev/null +++ b/include/libmu/utf8_strlen.h @@ -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 diff --git a/src/console-tools/clear/build.sh b/src/console-tools/clear/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/console-tools/clear/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/console-tools/clear/clear.c b/src/console-tools/clear/clear.c new file mode 100644 index 0000000..5e22f71 --- /dev/null +++ b/src/console-tools/clear/clear.c @@ -0,0 +1,5 @@ +#include + +int main(void) { + return write(1, "\033[H\033[J", 6) != 6; +} diff --git a/src/console-tools/reset/build.sh b/src/console-tools/reset/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/console-tools/reset/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/console-tools/reset/reset.c b/src/console-tools/reset/reset.c new file mode 100644 index 0000000..012ae59 --- /dev/null +++ b/src/console-tools/reset/reset.c @@ -0,0 +1,5 @@ +#include + +int main(void) { + return write(1, "\033c\033(K\033[J\033[0m\033[?25h", 18) != 18; +} diff --git a/src/coreutils/bdname/bdname.c b/src/coreutils/bdname/bdname.c new file mode 100644 index 0000000..dd8f390 --- /dev/null +++ b/src/coreutils/bdname/bdname.c @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include + +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; +} diff --git a/src/coreutils/bdname/build.sh b/src/coreutils/bdname/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/bdname/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/cat/build.sh b/src/coreutils/cat/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/cat/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/cat/cat.c b/src/coreutils/cat/cat.c new file mode 100644 index 0000000..2c58ae4 --- /dev/null +++ b/src/coreutils/cat/cat.c @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#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; + } +} diff --git a/src/coreutils/chgrp/build.sh b/src/coreutils/chgrp/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/chgrp/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/chgrp/chgrp.c b/src/coreutils/chgrp/chgrp.c new file mode 100644 index 0000000..674321f --- /dev/null +++ b/src/coreutils/chgrp/chgrp.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/chmod/build.sh b/src/coreutils/chmod/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/chmod/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/chmod/chmod.c b/src/coreutils/chmod/chmod.c new file mode 100644 index 0000000..39a02e3 --- /dev/null +++ b/src/coreutils/chmod/chmod.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/chown/build.sh b/src/coreutils/chown/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/chown/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/chown/chown.c b/src/coreutils/chown/chown.c new file mode 100644 index 0000000..b7c8d33 --- /dev/null +++ b/src/coreutils/chown/chown.c @@ -0,0 +1,131 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/chroot/build.sh b/src/coreutils/chroot/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/chroot/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/chroot/chroot.c b/src/coreutils/chroot/chroot.c new file mode 100644 index 0000000..f88d2bf --- /dev/null +++ b/src/coreutils/chroot/chroot.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +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; +} diff --git a/src/coreutils/cmp/build.sh b/src/coreutils/cmp/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/cmp/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/cmp/cmp.c b/src/coreutils/cmp/cmp.c new file mode 100644 index 0000000..48b006e --- /dev/null +++ b/src/coreutils/cmp/cmp.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +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; +} diff --git a/src/coreutils/cp/build.sh b/src/coreutils/cp/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/cp/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/cp/cp.c b/src/coreutils/cp/cp.c new file mode 100644 index 0000000..0e6154e --- /dev/null +++ b/src/coreutils/cp/cp.c @@ -0,0 +1,213 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/date/build.sh b/src/coreutils/date/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/date/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/date/date.c b/src/coreutils/date/date.c new file mode 100644 index 0000000..08d2370 --- /dev/null +++ b/src/coreutils/date/date.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/dd/build.sh b/src/coreutils/dd/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/dd/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/dd/dd.c b/src/coreutils/dd/dd.c new file mode 100644 index 0000000..fbc483a --- /dev/null +++ b/src/coreutils/dd/dd.c @@ -0,0 +1,249 @@ +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/df/build.sh b/src/coreutils/df/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/df/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/df/df.c b/src/coreutils/df/df.c new file mode 100644 index 0000000..34a904d --- /dev/null +++ b/src/coreutils/df/df.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} + diff --git a/src/coreutils/du/build.sh b/src/coreutils/du/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/du/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/du/du.c b/src/coreutils/du/du.c new file mode 100644 index 0000000..b6c6fb8 --- /dev/null +++ b/src/coreutils/du/du.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/echo/build.sh b/src/coreutils/echo/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/echo/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/echo/echo.c b/src/coreutils/echo/echo.c new file mode 100644 index 0000000..c34eed0 --- /dev/null +++ b/src/coreutils/echo/echo.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include + +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; +} diff --git a/src/coreutils/env/build.sh b/src/coreutils/env/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/env/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/env/env.c b/src/coreutils/env/env.c new file mode 100644 index 0000000..09aa151 --- /dev/null +++ b/src/coreutils/env/env.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include + +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; +} diff --git a/src/coreutils/false/build.sh b/src/coreutils/false/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/false/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/false/false.c b/src/coreutils/false/false.c new file mode 100644 index 0000000..5015b2b --- /dev/null +++ b/src/coreutils/false/false.c @@ -0,0 +1,3 @@ +int main(void) { + return 1; +} diff --git a/src/coreutils/head/build.sh b/src/coreutils/head/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/head/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/head/head.c b/src/coreutils/head/head.c new file mode 100644 index 0000000..92110a8 --- /dev/null +++ b/src/coreutils/head/head.c @@ -0,0 +1,95 @@ +#define _HEAD_C + +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/id/build.sh b/src/coreutils/id/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/id/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/id/id.c b/src/coreutils/id/id.c new file mode 100644 index 0000000..5dcdc55 --- /dev/null +++ b/src/coreutils/id/id.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); +} diff --git a/src/coreutils/ln/build.sh b/src/coreutils/ln/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/ln/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/ln/ln.c b/src/coreutils/ln/ln.c new file mode 100644 index 0000000..3ad6150 --- /dev/null +++ b/src/coreutils/ln/ln.c @@ -0,0 +1,76 @@ +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/ls/build.sh b/src/coreutils/ls/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/ls/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/ls/ls.c b/src/coreutils/ls/ls.c new file mode 100644 index 0000000..ed81348 --- /dev/null +++ b/src/coreutils/ls/ls.c @@ -0,0 +1,508 @@ +#define _LS_C + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/mkdir/build.sh b/src/coreutils/mkdir/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/mkdir/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/mkdir/mkdir.c b/src/coreutils/mkdir/mkdir.c new file mode 100644 index 0000000..d3b1c1e --- /dev/null +++ b/src/coreutils/mkdir/mkdir.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/mknod/build.sh b/src/coreutils/mknod/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/mknod/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/mknod/mknod.c b/src/coreutils/mknod/mknod.c new file mode 100644 index 0000000..8b9f946 --- /dev/null +++ b/src/coreutils/mknod/mknod.c @@ -0,0 +1,81 @@ +#ifdef __linux__ +#include +#endif + +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/mktemp/build.sh b/src/coreutils/mktemp/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/mktemp/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/mktemp/mktemp.c b/src/coreutils/mktemp/mktemp.c new file mode 100644 index 0000000..b285da3 --- /dev/null +++ b/src/coreutils/mktemp/mktemp.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/mv/build.sh b/src/coreutils/mv/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/mv/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/mv/mv.c b/src/coreutils/mv/mv.c new file mode 100644 index 0000000..7cf88b0 --- /dev/null +++ b/src/coreutils/mv/mv.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/nice/build.sh b/src/coreutils/nice/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/nice/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/nice/nice.c b/src/coreutils/nice/nice.c new file mode 100644 index 0000000..fdb1988 --- /dev/null +++ b/src/coreutils/nice/nice.c @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/src/coreutils/nohup/build.sh b/src/coreutils/nohup/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/nohup/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/nohup/nohup.c b/src/coreutils/nohup/nohup.c new file mode 100644 index 0000000..ae5a54d --- /dev/null +++ b/src/coreutils/nohup/nohup.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/nproc/build.sh b/src/coreutils/nproc/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/nproc/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/nproc/nproc.c b/src/coreutils/nproc/nproc.c new file mode 100644 index 0000000..a54904e --- /dev/null +++ b/src/coreutils/nproc/nproc.c @@ -0,0 +1,11 @@ +#include +#include + +int main(void) { + long count = sysconf(_SC_NPROCESSORS_ONLN); + if (count <= 0) + count = 1; + + printf("%ld\n", count); + return 0; +} diff --git a/src/coreutils/printenv/build.sh b/src/coreutils/printenv/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/printenv/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/printenv/printenv.c b/src/coreutils/printenv/printenv.c new file mode 100644 index 0000000..79a595d --- /dev/null +++ b/src/coreutils/printenv/printenv.c @@ -0,0 +1,40 @@ +#include +#include +#include +#include + +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; +} diff --git a/src/coreutils/pwd/build.sh b/src/coreutils/pwd/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/pwd/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/pwd/pwd.c b/src/coreutils/pwd/pwd.c new file mode 100644 index 0000000..9b2068b --- /dev/null +++ b/src/coreutils/pwd/pwd.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include + +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; +} diff --git a/src/coreutils/readlink/build.sh b/src/coreutils/readlink/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/readlink/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/readlink/readlink.c b/src/coreutils/readlink/readlink.c new file mode 100644 index 0000000..168bbb6 --- /dev/null +++ b/src/coreutils/readlink/readlink.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/src/coreutils/renice/build.sh b/src/coreutils/renice/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/renice/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/renice/renice.c b/src/coreutils/renice/renice.c new file mode 100644 index 0000000..8cc8441 --- /dev/null +++ b/src/coreutils/renice/renice.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/src/coreutils/rm/build.sh b/src/coreutils/rm/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/rm/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/rm/rm.c b/src/coreutils/rm/rm.c new file mode 100644 index 0000000..616b269 --- /dev/null +++ b/src/coreutils/rm/rm.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/seq/build.sh b/src/coreutils/seq/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/seq/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/seq/seq.c b/src/coreutils/seq/seq.c new file mode 100644 index 0000000..57a57d8 --- /dev/null +++ b/src/coreutils/seq/seq.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include + +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; +} diff --git a/src/coreutils/setsid/build.sh b/src/coreutils/setsid/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/setsid/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/setsid/setsid.c b/src/coreutils/setsid/setsid.c new file mode 100644 index 0000000..09d5bb1 --- /dev/null +++ b/src/coreutils/setsid/setsid.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include +#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); +} diff --git a/src/coreutils/shred/build.sh b/src/coreutils/shred/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/shred/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/shred/shred.c b/src/coreutils/shred/shred.c new file mode 100644 index 0000000..93c257a --- /dev/null +++ b/src/coreutils/shred/shred.c @@ -0,0 +1,113 @@ +#define _SHRED_C + +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/sleep/build.sh b/src/coreutils/sleep/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/sleep/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/sleep/sleep.c b/src/coreutils/sleep/sleep.c new file mode 100644 index 0000000..2d6a21a --- /dev/null +++ b/src/coreutils/sleep/sleep.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include +#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; +} diff --git a/src/coreutils/split/build.sh b/src/coreutils/split/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/split/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/split/split.c b/src/coreutils/split/split.c new file mode 100644 index 0000000..8b2243d --- /dev/null +++ b/src/coreutils/split/split.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include +#include +#include "config.h" + +FILE *next_file(FILE *old, int x, int slen, char *prefix) { + if (old != NULL) + fclose(old); + + /* Gen file name */ + char name[BUF_SIZE + 1]; + int len = snprintf(name, sizeof(name), "%s", prefix); + + for (int i = slen; i >= 0; i--) { + if (len + i >= (int)(BUF_SIZE * sizeof(char))) + break; + + name[len + i] = 'a' + (x % 26); + x /= 26; + } + + /* Open file */ + FILE *fp = fopen(name, "w"); + if (fp == NULL) { + fprintf(stderr, "split: %s\n", strerror(errno)); + return NULL; + } + + return fp; +} + +int main(int argc, char **argv) { + off_t size = 0; + int a_flag = 1; + int b_flag = 0; + char *prefix = "x"; + + int opt; + while ((opt = getopt(argc, argv, "l:a:b:")) != -1) { + switch (opt) { + case 'a': + a_flag = atoi(optarg); + break; + + case 'l': + size = atoi(optarg); + break; + + case 'b': + switch (optarg[strlen(optarg) - 1]) { + case 'm': + sscanf(optarg, "%ld", &size); + size *= 1048576; + break; + + case 'k': + sscanf(optarg, "%ld", &size); + size *= 1024; + break; + + default: + sscanf(optarg, "%ld", &size); + break; + } + + b_flag = 1; + break; + + default: + printf("split [alb] [file1]\n\t-l N Split by N lines\n\t-a N Use N letters as prefix\n\t-b N[k|m] Split by N (kilo|mega)bytes\n"); + return 0; + } + } + + argv += optind; + argc -= optind; + + FILE *fp = stdin; + if (argv[0] != NULL && strcmp(argv[0], "-")) { + fp = fopen(argv[0], "r"); + if (fp == NULL) { + fprintf(stderr, "split: %s: %s\n", argv[0], strerror(errno)); + return 1; + } + } + + if (argc == 2 && argv[1] != NULL) + prefix = argv[1]; + + + int ret = 0; + int files = 0; + FILE *out = NULL; + + off_t n = 0; + int ch; + while ((ch = getc(fp)) != EOF) { + if (out == NULL || n >= size) { + out = next_file(out, files++, a_flag, prefix); + if (out == NULL) { + ret = 1; + break; + } + + n = 0; + } + + if (ch == '\n' || b_flag) + n++; + + putc(ch, out); + } + + fclose(fp); + return ret; +} diff --git a/src/coreutils/sync/build.sh b/src/coreutils/sync/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/sync/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/sync/sync.c b/src/coreutils/sync/sync.c new file mode 100644 index 0000000..95dd804 --- /dev/null +++ b/src/coreutils/sync/sync.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + sync(); + return 0; +} diff --git a/src/coreutils/tee/build.sh b/src/coreutils/tee/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/tee/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/tee/tee.c b/src/coreutils/tee/tee.c new file mode 100644 index 0000000..b82fdb5 --- /dev/null +++ b/src/coreutils/tee/tee.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include +#include "config.h" + +int main(int argc, char **argv) { + int flag = O_TRUNC; + + int opt; + while ((opt = getopt(argc, argv, "ai")) != -1) { + switch (opt) { + case 'a': + flag = O_APPEND; + break; + + case 'i': + signal(SIGINT, SIG_IGN); + break; + + default: + printf("tee [ai] [file]\n\t-a Append\n\t-i Ignore interrupt signals\n"); + return 0; + } + } + + argv += optind; + argc -= optind; + + int fd = STDOUT_FILENO; + if (argc > 0 && strcmp(argv[0], "-")) { + fd = open(argv[0], O_WRONLY | flag | O_CREAT, 0666); + if (fd < 0) { + fprintf(stderr, "tee: %s\n", strerror(errno)); + return 1; + } + } + + char buf[BUF_SIZE + 1]; + ssize_t bytes = 0; + while ((bytes = read(STDIN_FILENO, buf, sizeof(buf)))) { + int stat = write(STDOUT_FILENO, buf, bytes); + + int stat2 = bytes; + if (argc > 0) + stat2 = write(fd, buf, bytes); + + if (stat != bytes || stat2 != bytes) { + fprintf(stderr, "tee: %s\n", strerror(errno)); + return 1; + } + } + + if (argc > 0 && strcmp(argv[0], "-")) + close(fd); + + return 0; +} diff --git a/src/coreutils/time/build.sh b/src/coreutils/time/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/time/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/time/time.c b/src/coreutils/time/time.c new file mode 100644 index 0000000..5ef1e1b --- /dev/null +++ b/src/coreutils/time/time.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) { + + if (argc < 2) { + printf("time: missing operand\ntime [cmd]\n"); + return 0; + } + + long ticks = sysconf(_SC_CLK_TCK); + if (ticks <= 0) { + fprintf(stderr, "time: %s\n", strerror(errno)); + return 1; + } + + static struct tms tms; + clock_t r1 = times(&tms); + if (r1 == (clock_t)-1) { + fprintf(stderr, "time: %s\n", strerror(errno)); + return 1; + } + + /* Run */ + pid_t pid; + if ((pid = fork()) == 0) { + execvp(argv[1], argv + 1); + exit(1); + } + + int status = 0; + waitpid(pid, &status, 0); + + /* Get time */ + clock_t r2 = times(&tms); + if (r2 == (clock_t)-1) { + fprintf(stderr, "time: %s\n", strerror(errno)); + return 1; + } + + /* Print */ + long real = (r2 - r1) / ticks; + long user = tms.tms_cutime / ticks; + long sys = tms.tms_cstime / ticks; + + fprintf(stderr, "real:\t%ldm %ld.%lds\nsys:\t%ldm %ld.%lds\nuser:\t%ldm %ld.%lds\n", real / 60, real % 60, (r2 - r1) % 100, sys / 60, sys % 60, tms.tms_cstime % 100, user / 60, user % 60, tms.tms_cutime % 100); + if (status != 0) + printf("Proccess returned %d\n", status); + + return 0; +} diff --git a/src/coreutils/touch/build.sh b/src/coreutils/touch/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/touch/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/touch/touch.c b/src/coreutils/touch/touch.c new file mode 100644 index 0000000..b43a984 --- /dev/null +++ b/src/coreutils/touch/touch.c @@ -0,0 +1,147 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +char c_flag; +char m_flag; +char a_flag; + +int setdate(const char *path, const time_t date, char flag) { + struct utimbuf new_time; + + if (flag || a_flag) + new_time.actime = date; + + if (flag || m_flag) + new_time.modtime = date; + + if (utime(path, &new_time) < 0) { + fprintf(stderr, "touch: %s: %s\n", path, strerror(errno)); + return 1; + } + + return 0; +} + +int touch(const char *path, const time_t date) { + + if (!c_flag) { + int fd = open(path, O_CREAT | O_RDONLY, 0666); + if (fd < 0) { + fprintf(stderr, "touch: %s\n", strerror(errno)); + return 1; + } + + close(fd); + } + + /* Update the date to now */ + if (setdate(path, time(NULL), 1)) + return 1; + + /* Seting custom values */ + char flag = 0; + if (m_flag == 0 && a_flag == 0) + flag = 1; + + if (date != -1 && setdate(path, date, flag)) + return 1; + + return 0; +} + +time_t parse_date(char *str) { + char *fmt = NULL; + switch (strlen(str)) { + case 8: + fmt = "%m%d%H%M"; + break; + + case 10: + fmt = "%y%m%d%H%M"; + break; + + case 11: + fmt = "%m%d%H%M.%S"; + break; + + case 12: + fmt = "%Y%m%d%H%M"; + break; + + case 13: + fmt = "%y%m%d%H%M.%S"; + break; + + case 15: + fmt = "%Y%m%d%H%M.%S"; + break; + + case 19: + fmt = "%Y-%m-%dT%H:%M:%S"; + break; + + default: + fprintf(stderr, "touch: invalid date format\n"); + exit(1); + } + + time_t now = time(NULL); + struct tm tm = *localtime(&now); + + if (!strptime(str, fmt, &tm)) { + fprintf(stderr, "touch: %s\n", strerror(errno)); + exit(1); + } + + return mktime(&tm); +} + +int main(int argc, char **argv) { + time_t date = -1; + + int opt; + while ((opt = getopt(argc, argv, "cmad:t:")) != -1) { + switch (opt) { + case 'm': + m_flag = 1; + break; + + case 'a': + a_flag = 1; + break; + + case 'c': + c_flag = 1; + break; + + case 't': + case 'd': + date = parse_date(optarg); + break; + + default: + printf("touch [cmad] [file1 file2...]\n\t-c Don't create files\n\t-a Change only atime\n\t-m Change only mtime\n\t-d Date/time to use\n"); + return 0; + } + } + + argv += optind; + argc -= optind; + + if (argc == 0) { + printf("touch: missing operand\n"); + return 1; + } + + for (int i = 0; i < argc; i++) + if (touch(argv[i], date)) + return 1; + + return 0; +} diff --git a/src/coreutils/true/build.sh b/src/coreutils/true/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/true/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/true/true.c b/src/coreutils/true/true.c new file mode 100644 index 0000000..061ed7e --- /dev/null +++ b/src/coreutils/true/true.c @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff --git a/src/coreutils/tty/build.sh b/src/coreutils/tty/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/tty/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/tty/tty.c b/src/coreutils/tty/tty.c new file mode 100644 index 0000000..5b9a558 --- /dev/null +++ b/src/coreutils/tty/tty.c @@ -0,0 +1,13 @@ +#include +#include + +int main(void) { + char *tty = ttyname(STDIN_FILENO); + if (tty) + puts(tty); + + else + puts("not a tty"); + + return tty == NULL; +} diff --git a/src/coreutils/uname/build.sh b/src/coreutils/uname/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/uname/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/uname/uname.c b/src/coreutils/uname/uname.c new file mode 100644 index 0000000..7094803 --- /dev/null +++ b/src/coreutils/uname/uname.c @@ -0,0 +1,132 @@ +#define UNAME_C + +#include +#include +#include +#include +#include +#include "config.h" + +#if defined(OS_NAME) +#elif defined(__ANDROID__) +#define OS_NAME "Android" + +#elif defined(__linux__) +#define OS_NAME "Linux" + +#elif defined(__OpenBSD__) +#define OS_NAME "OpenBSD" + +#elif defined(__FreeBSD_) +#define OS_NAME "FreeBSD" + +#elif defined(__NetBSD_) +#define OS_NAME "NetBSD" + +#else +#define OS_NAME "unknow" + +#endif + +enum { + SYSNAME, + NODENAME, + RELEASE, + VERSION, + MACHINE, + OS, + CPU, + ALL, + COUNT +}; + +char flags[COUNT]; +unsigned int counter = 0; + +void print(const char *msg) { + if (counter > 0 && !flags[ALL]) + putchar(' '); + + printf("%s", msg); + counter++; + + if (flags[ALL] && counter <= COUNT) + putchar(' '); +} + +int main(int argc, char **argv) { + struct utsname uts; + if (uname(&uts)) { + fprintf(stderr, "uname: %s", strerror(errno)); + return 1; + } + + if (argc == 1) { + printf("%s\n", uts.sysname); + return 0; + } + + int opt; + while ((opt = getopt(argc, argv, "asnrvmop")) != -1) { + switch (opt) { + case 'a': + flags[ALL] = 1; + break; + + case 's': + flags[SYSNAME] = 1; + break; + + case 'n': + flags[NODENAME] = 1; + break; + + case 'r': + flags[RELEASE] = 1; + break; + + case 'v': + flags[VERSION] = 1; + break; + + case 'm': + flags[MACHINE] = 1; + break; + + case 'o': + flags[OS] = 1; + break; + + case 'p': + flags[CPU] = 1; + break; + + default: + printf("uname [asnrvmop]\n\t-a All\n\t-s Sys\n\t-n Nodename\n\t-r Release\n\t-v Version\n\t-m Machine\n\t-o Os name\n"); + return 0; + } + } + + if (flags[SYSNAME] || flags[ALL]) + print(uts.sysname); + + if (flags[NODENAME] || flags[ALL]) + print(uts.nodename); + + if (flags[RELEASE] || flags[ALL]) + print(uts.release); + + if (flags[VERSION] || flags[ALL]) + print(uts.version); + + if (flags[MACHINE] || flags[ALL]) + print(uts.machine); + + if (flags[OS] || flags[ALL]) + print(OS_NAME); + + if (flags[CPU] || flags[ALL]) + print("unknow"); + + putchar('\n'); +} diff --git a/src/coreutils/wc/build.sh b/src/coreutils/wc/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/wc/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/wc/wc.c b/src/coreutils/wc/wc.c new file mode 100644 index 0000000..cef6ed5 --- /dev/null +++ b/src/coreutils/wc/wc.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include +#include "config.h" + +/* cmd arguments l - lines c - bytes w - words */ +unsigned int l_flag; +unsigned int c_flag; +unsigned int w_flag; +unsigned int t_flag; + +unsigned int words; +unsigned int bytes; +unsigned int lines; + +/* Total */ +unsigned int twords; +unsigned int tbytes; +unsigned int tlines; + +void count(const int fd) { + char buf[BUF_SIZE + 1]; + off_t n = 0; + + int in_word = 1; + while ((n = read(fd, buf, sizeof(buf))) > 0) { + bytes += n; + + for (ssize_t i = 0; i < n; i++) { + if (buf[i] == '\n') + lines++; + + if (isspace(buf[i])) + in_word = 1; + + else { + if (in_word) + words++; + + in_word = 0; + } + } + } + + tbytes += bytes; + twords += words; + tlines += lines; +} + +void print_count(const char *path, unsigned int plines, unsigned int pwords, unsigned int pbytes) { + if (l_flag) + printf("%7u ", plines); + + if (w_flag) + printf(" %7u", pwords); + + if (c_flag) + printf(" %7u", pbytes); + + printf(" %s\n", path); +} + +int main(int argc, char **argv) { + int opt; + while ((opt = getopt(argc, argv, "lcwt")) != -1) { + switch (opt) { + case 'l': + l_flag = 1; + break; + + case 'c': + c_flag = 1; + break; + + case 'w': + w_flag = 1; + break; + + case 't': + t_flag = 1; + break; + + default: + printf("wc [lcwt] [file1 file2...]\n\t-l Lines\n\t-c Bytes\n\t-w Words\n\t-t Don't print total\n"); + return 0; + } + } + + argv += optind; + argc -= optind; + + if (!w_flag && !l_flag && !c_flag) { + w_flag = 1; + l_flag = 1; + c_flag = 1; + } + + if (argc == 0) { + count(STDIN_FILENO); + print_count("", lines, words, bytes); + return 0; + } + + for (int i = 0; i < argc; i++) { + if (argv[i][0] == '-') { + count(STDIN_FILENO); + print_count("-", lines, words, bytes); + } + + else { + int fd = open(argv[i], O_RDONLY); + if (fd < 0) { + fprintf(stderr, "wc: %s: %s\n", argv[i], strerror(errno)); + return 1; + } + + count(fd); + print_count(argv[i], lines, words, bytes); + + close(fd); + } + + words = bytes = lines = 0; + } + + if (!t_flag) + print_count("total", tlines, twords, tbytes); + + return 0; +} diff --git a/src/coreutils/whoami/build.sh b/src/coreutils/whoami/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/whoami/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/whoami/whoami.c b/src/coreutils/whoami/whoami.c new file mode 100644 index 0000000..0bee9cb --- /dev/null +++ b/src/coreutils/whoami/whoami.c @@ -0,0 +1,18 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(void) { + struct passwd *pw = getpwuid(getuid()); + if (!pw) { + fprintf(stderr, "whoami: %s\n", strerror(errno)); + return 1; + } + + puts(pw->pw_name); + return 0; +} diff --git a/src/coreutils/yes/build.sh b/src/coreutils/yes/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/coreutils/yes/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/coreutils/yes/yes.c b/src/coreutils/yes/yes.c new file mode 100644 index 0000000..2e07bef --- /dev/null +++ b/src/coreutils/yes/yes.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +void print(const char *buf, ssize_t len) { + if (write(STDOUT_FILENO, buf, len) < 0) + exit(1); +} + +int main(const int argc, const char **argv) { + if (argc == 1) + while (1) + print("y\n", 2); + + while (1) { + for (ssize_t i = 1; i < argc; i++) { + print(argv[i], strlen(argv[i])); + print(" ", 1); + } + + print("\n", 1); + } +} diff --git a/src/editors/que/build.sh b/src/editors/que/build.sh new file mode 100755 index 0000000..343d4bf --- /dev/null +++ b/src/editors/que/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo *.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/editors/que/que.c b/src/editors/que/que.c new file mode 100644 index 0000000..f7e8dde --- /dev/null +++ b/src/editors/que/que.c @@ -0,0 +1,637 @@ +/* Safe variant of kilo editor */ +/* Based on the web-tutorial and contain many edits */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CTRL_KEY(k) ((k) & 0x1f) +#define TAB_SIZE 8 + +struct termios orig_termios; +struct winsize ws; + +char *scr_buf; +size_t scr_buf_size; + +struct row { + char *buf; + size_t len; + + char *render; + size_t rlen; +}; + +struct row *row_s; +size_t row_size; + +/* Cursors */ +unsigned int curx; +unsigned int cury; +unsigned int renx; + +unsigned int rowoff; +unsigned int coloff; + +char *file_path; + +enum { + FAILED_SAVE = 1, + SUCCESS_SAVE, + MARK +}; +char status_type; +char modified_flag; + +/* for mark */ +char mark_flag; +unsigned int curx2; +unsigned int cury2; + +/* Cleaners */ +void bufFree(void) { + if (scr_buf != NULL) + free(scr_buf); + + scr_buf = NULL; + scr_buf_size = 0; +} + +void fileBufFree(void) { + if (row_s != NULL) { + if (row_size > 0) + for (size_t i = 0; i < row_size; i++) { + if (row_s[i].buf) + free(row_s[i].buf); + + if (row_s[i].render) + free(row_s[i].render); + } + + free(row_s); + } + + row_s = NULL; + row_size = 0; +} + +void die(int ret, char *msg) { + write(STDOUT_FILENO, "\033[H\033[J", 6); + + bufFree(); + fileBufFree(); + + if (msg != NULL) + fprintf(stderr, "que: %s: %s\n", msg, strerror(errno)); + + exit(ret); +} + +/* Save */ +char *buf2str(size_t *len) { + size_t totalen = 0; + for (size_t i = 0; i < row_size; i++) + totalen += row_s[i].len + 1; + + *len = totalen; + char *buf = malloc(totalen + 1); + if (buf == NULL) + die(1, "malloc in buf2str: Fatal error"); + + char *p = buf; + for (size_t i = 0; i < row_size; i++) { + memcpy(p, row_s[i].buf, row_s[i].len); + + p += row_s[i].len; + *p = '\n'; + p++; + } + + *p = '\0'; + return buf; +} + +void save(void) { + size_t len = 0; + char *buf = buf2str(&len); + + int fd = open(file_path, O_RDWR, 0644); + if (fd < 0) + goto BAD_SAVE; + + if (ftruncate(fd, len) < 0) + goto BAD_SAVE; + + ssize_t ret = write(fd, buf, len); + if (ret == -1) + goto BAD_SAVE; + + else if ((size_t)ret != len) + goto BAD_SAVE; + + close(fd); + free(buf); + status_type = SUCCESS_SAVE; + modified_flag = 0; + return; + +BAD_SAVE: + free(buf); + status_type = FAILED_SAVE; + return; +} + +/* Funcs */ +void bufAppend(const char *str, const size_t len) { + if (len == 0) + return; + + char *buf = NULL; + if (scr_buf_size == 0 || scr_buf == NULL) + buf = malloc(len); + + else + buf = realloc(scr_buf, scr_buf_size + len); + + if (buf == NULL) { + if (scr_buf) + free(scr_buf); + + scr_buf_size = 0; + return; + } + + scr_buf = buf; + + memcpy(&scr_buf[scr_buf_size], str, len); + scr_buf_size += len; +} + +int updateRenderStr(const unsigned int row) { + int tabs = 0; + for (size_t i = 0; i < row_s[row].len; i++) + if (row_s[row].buf[i] == '\t') + tabs++; + + if (row_s[row].render) + free(row_s[row].render); + + char *buf = malloc(row_s[row].len + tabs * TAB_SIZE + 1); + if (buf == NULL) + return 1; + row_s[row].render = buf; + + int j = 0; + for (size_t i = 0; i < row_s[row].len; i++) { + if (row_s[row].buf[i] == '\t') { + row_s[row].render[j++] = ' '; + while (j % TAB_SIZE != 0) + row_s[row].render[j++] = ' '; + } + + else + row_s[row].render[j++] = row_s[row].buf[i]; + } + + row_s[row].render[j] = '\0'; + row_s[row].rlen = j; + + return 0; +} + +int addRow(const unsigned int at, const char *buf, const size_t len) { + struct row *row_s2 = realloc(row_s, sizeof(struct row) * (row_size + 1)); + if (row_s2 == NULL) + return 1; + row_s = row_s2; + + memmove(&row_s[at + 1], &row_s[at], sizeof(struct row) * (row_size - at)); + + char *buf2 = malloc(len + 1); + if (buf2 == NULL) + return 1; + row_s[at].buf = buf2; + + memcpy(row_s[at].buf, buf, len); + row_s[at].len = len; + row_s[at].buf[len] = '\0'; + + row_s[at].render = NULL; + if (updateRenderStr(at)) + return 1; + + row_size++; + return 0; +} + +void readFile(const char *path) { + row_s = malloc(sizeof(struct row)); + if (row_s == NULL) + die(1, "malloc in readFIle"); + + FILE *fp = fopen(path, "r"); + if (fp == NULL) + die(1, "fopen in readFile"); + + char *buf = NULL; + size_t n = 0; + ssize_t len = 0; + while ((len = getline(&buf, &n, fp)) != -1) { + while (len > 0 && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) + len--; + + if (addRow(row_size, buf, len)) { + fclose(fp); + free(buf); + die(1, "addRow in readFile"); + } + } + + if (buf) + free(buf); + + fclose(fp); +} + +void insertChar(char c) { + if ((size_t)cury == row_size) { + if (addRow(row_size, "", 0)) { + save(); + die(1, "addRow in insertChar: Fatal error"); + } + } + + size_t i = (size_t)curx; + if (i > row_s[cury].len) + i = row_s[cury].len; + + char *buf = realloc(row_s[cury].buf, row_s[cury].len + 2); + if (buf == NULL) { + save(); + die(1, "realloc in insertChar: Fatal error"); + } + row_s[cury].buf = buf; + + memmove(&row_s[cury].buf[i + 1], &row_s[cury].buf[i], row_s[cury].len - i + 1); + + row_s[cury].len++; + row_s[cury].buf[i] = c; + if (updateRenderStr(cury)) { + save(); + die(1, "updateRenderStr in insertChar: Fatal error"); + } + + curx++; +} + +void insertNewline(void) { + if (curx == 0) { + if (addRow(cury, "", 0)) { + save(); + die(1, "addRow in insertNewline: Fatal error"); + } + } + + else { + if (addRow(cury + 1, &row_s[cury].buf[curx], row_s[cury].len - curx)) { + save(); + die(1, "addRow in insertNewline: Fatal error"); + } + + /* Resize */ + row_s[cury].len = (size_t)curx; + row_s[cury].buf[curx] = '\0'; + + char *buf = strdup(row_s[cury].buf); + if (buf == NULL) { + save(); + die(1, "strdup in insertNewline: Fatal error"); + } + + free(row_s[cury].buf); + row_s[cury].buf = buf; + + if (updateRenderStr(cury)) { + save(); + die(1, "updateRenderStr in insertNewline: Fatal error"); + } + } + + cury++; + curx = 0; +} + +void delChar(void) { + if ((curx == 0 && cury == 0) || cury == (unsigned int)row_size) + return; + + else if (curx > 0) { + if (curx - 1 >= (unsigned int)row_s[cury].len) + return; + + memmove(&row_s[cury].buf[curx - 1], &row_s[cury].buf[curx], row_s[cury].len - curx); + + row_s[cury].len--; + curx--; + } + + else { + curx = (unsigned int)row_s[cury - 1].len; + + char *buf = realloc(row_s[cury - 1].buf, row_s[cury - 1].len + row_s[cury].len + 1); + if (buf == NULL) { + save(); + die(1, "realloc in delChar: Fatal error"); + } + row_s[cury - 1].buf = buf; + + memcpy(&row_s[cury - 1].buf[row_s[cury - 1].len], row_s[cury].buf, row_s[cury].len); + row_s[cury - 1].len += row_s[cury].len; + row_s[cury - 1].buf[row_s[cury - 1].len] = '\0'; + + if (cury < (unsigned int)row_size) { + free(row_s[cury].buf); + free(row_s[cury].render); + + memmove(&row_s[cury], &row_s[cury + 1], sizeof(struct row) * (row_size - cury - 1)); + struct row *buf2 = realloc(row_s, sizeof(struct row) * row_size - 1); + if (buf == NULL) { + save(); + die(1, "relloc in delChar: Fatal error"); + } + + row_s = buf2; + row_size--; + } + + cury--; + } + + if (updateRenderStr(cury)) { + save(); + die(1, "updateRenderStr in delChar: Fatal error"); + } +} + +void cmd(void) { + /* Execute internal cmds */ +} + +/* Terminal */ +void DRawMode(void) { + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) < 0) + die(1, "tcsetattr"); +} + +void ERawMode(void) { + if (tcgetattr(STDIN_FILENO, &orig_termios) < 0) + die(1, "tcgetattr"); + + struct termios raw = orig_termios; + raw.c_oflag &= ~(OPOST); + raw.c_cflag |= (CS8); + raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + raw.c_lflag &= ~(ECHO | ICANON | ISIG | IEXTEN); + + raw.c_cc[VMIN] = 0; + raw.c_cc[VTIME] = 1; + + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) < 0) + die(1, "tcsetattr"); +} + +void winsize(void) { + if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0) + die(1, "ioctl"); + + if (ws.ws_col == 0 || ws.ws_row <= 1) + die(1, "winsize"); + + ws.ws_row--; +} + +void statusBar(const char *path) { + char info[124]; + int ret = 0; + + if (status_type == 0) + ret = snprintf(info, sizeof(info), "LINE: %u/%zu %s [%s]", cury + 1, row_size + 1, (modified_flag) ? "[modified]" : "", path); + + else if (status_type == FAILED_SAVE) + ret = snprintf(info, sizeof(info), "Failed save to %s: %s", path, strerror(errno)); + + else if (status_type == SUCCESS_SAVE) + ret = snprintf(info, sizeof(info), "File %s success saved", path); + + else if (status_type == MARK) + ret = snprintf(info, sizeof(info), "Mark set at %ux %uy", curx, cury); + + status_type = 0; + bufAppend(info, ret); +} + +/* Keyboard */ +char readkey(void) { + char c; + int ret; + + while ((ret = read(STDIN_FILENO, &c, 1)) != 1) { + if (ret < 0 && errno != EAGAIN) { + save(); + die(1, "read"); + } + } + + return c; +} + +void moveCursor(char c) { + switch (c) { + case 'A': + if (cury != 0) + cury--; + + break; + + case 'B': + if (cury < row_size) + cury++; + + break; + + case 'C': + if (curx < row_s[cury].len) + curx++; + + else if (curx == row_s[cury].len) { + cury++; + curx = 0; + } + + break; + + case 'D': + if (curx != 0) + curx--; + + + else if (cury > 0) { + cury--; + curx = row_s[cury].len; + } + + break; + + case '5': + if (readkey() == '~') { + cury = rowoff; + + size_t t = ws.ws_row; + while (t--) + if (cury != 0) + moveCursor('A'); + } + + break; + + case '6': + if (readkey() == '~') { + cury = rowoff + ws.ws_row + 1; + + if (cury > (unsigned int)row_size) + cury = row_size; + + size_t t = ws.ws_row; + while (t--) + moveCursor('B'); + } + + break; + + case 'H': + curx = 0; + break; + + case 'F': + curx = row_s[cury].len; + break; + } + + if (curx > row_s[cury].len) + curx = row_s[cury].len; +} + +void keyboard(void) { + char key = readkey(); + switch (key) { + case '\033': + if (readkey() != '[') + break; + + moveCursor(readkey()); + break; + + case '\r': + modified_flag = 1; + insertNewline(); + break; + + case CTRL_KEY('f'): + cmd(); + break; + + case CTRL_KEY('q'): + die(0, NULL); + break; + + case CTRL_KEY('s'): + save(); + break; + + case 127: + case CTRL_KEY('h'): + delChar(); + modified_flag = 1; + break; + + default: + modified_flag = 1; + insertChar(key); + break; + } +} + +int main(int argc, char **argv) { + if (argc < 2) { + printf("que [file]\n"); + return 0; + } + + file_path = argv[1]; + readFile(file_path); + winsize(); + atexit(DRawMode); + ERawMode(); + + while (1) { + bufAppend("\033[H\033[J", 6); + + renx = 0; + + if (cury < row_size) { + /* Buffer coord to Render buffer coord */ + for (unsigned int i = 0; i < curx; i++) { + if (row_s[cury].buf[i] == '\t') + renx += (TAB_SIZE - 1) - (renx % TAB_SIZE); + + renx++; + } + } + + if (cury < rowoff) + rowoff = cury; + + else if (cury >= rowoff + ws.ws_row) + rowoff = cury - ws.ws_row + 1; + + if (renx < coloff) + coloff = renx; + + else if (renx >= coloff + ws.ws_col) + coloff = renx - ws.ws_col + 1; + + for (size_t i = 0; i < ws.ws_row; i++) { + unsigned int row = rowoff + i; + + if (row_size > row) { + int len = row_s[row].rlen - coloff; + if (len < 0) + len = 0; + + else if (len > ws.ws_col) + len = ws.ws_col; + + bufAppend(&row_s[row].render[coloff], (size_t)len); + } + + bufAppend("\r\n", 2); + } + + statusBar(file_path); + + char buf[32]; + int ret = snprintf(buf, sizeof(buf), "\033[%u;%uH", cury - rowoff + 1, renx - coloff + 1); + bufAppend(buf, ret); + + write(STDOUT_FILENO, scr_buf, scr_buf_size); + bufFree(); + + keyboard(); + } +} diff --git a/src/findutils/grep/build.sh b/src/findutils/grep/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/findutils/grep/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/findutils/grep/grep.c b/src/findutils/grep/grep.c new file mode 100644 index 0000000..fd118de --- /dev/null +++ b/src/findutils/grep/grep.c @@ -0,0 +1,64 @@ +#include +#include +#include +#include +#include + +typedef struct { + char *pattern; + regex_t rgex; +} PATTERN; +PATTERN *regexs; +size_t r_size; + +int addpattern(char *str) { + if (regexs == NULL) { + regexs = malloc(sizeof(PATTERN)); + if (regexs == NULL) { + fprintf(stderr, "grep: malloc failed\n"); + return 1; + } + } + + PATTERN *regexs_tmp = realloc(regexs, (r_size + 1) * sizeof(PATTERN)); + if (regexs_tmp == NULL) { + free(regexs); + + fprintf(stderr, "grep: realloc failed\n"); + return 1; + } + regexs = regexs_tmp; + + regexs[r_size].pattern = str; + + r_size++; + return 0; +} + +int main(int argc, char **argv) { + + int opt; + while ((opt = getopt(argc, argv, "e:")) != -1) { + switch (opt) { + case 'e': + if (addpattern(optarg)) + return 1; + + break; + + default: + printf("grep [e] [FILE]\n\t-e PTRN Pattern to match\n"); + return 0; + } + } + + argv += optind; + argc -= optind; + if (r_size == 0) { + fprintf(stderr, "grep: no patterns specified\n"); + return 1; + } + + free(regexs); + return 0; +} diff --git a/src/findutils/xargs/build.sh b/src/findutils/xargs/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/findutils/xargs/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/findutils/xargs/xargs.c b/src/findutils/xargs/xargs.c new file mode 100644 index 0000000..4b38578 --- /dev/null +++ b/src/findutils/xargs/xargs.c @@ -0,0 +1,318 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef ARG_MAX +#define ARG_MAX 10000 +#endif + +int args; +char *cmd[ARG_MAX + 1]; + +char *I_flag; +char t_flag; +char r_flag; +char nl_flag; +int n_flag; +size_t s_flag; + +enum { + NORMAL, + CEOF, + ERROR, + I_FLAG +}; + +enum { + NONE, + QUOTE +}; + +void clear_cmd(void) { + for (int i = 0; i < args; i++) { + if (cmd[i] != NULL) { + free(cmd[i]); + cmd[i] = NULL; + } + } + + args = 0; +} + +int Iflag_push(const char *str, char **arg) { + size_t arg_len = strlen(*arg); + size_t str_len = strlen(str); + size_t Iflag_len = strlen(I_flag); + + char *buf = malloc(arg_len - Iflag_len + str_len + 1); + if (buf == NULL) { + fprintf(stderr, "xargs: malloc failed\n"); + return 1; + } + + strcpy(buf, *arg); + + /* Replace */ + char *ptr = strstr(buf, I_flag); + memmove(ptr + str_len, ptr + Iflag_len, strlen(ptr + Iflag_len) + 1); + strncpy(ptr, str, str_len); + + free(*arg); + *arg = buf; + return 0; +} + +int add_arg(const char *str, size_t chars, int flag) { + if (args >= ARG_MAX) + return ERROR; + + else if (n_flag > 0 && args > n_flag && I_flag == NULL) + return ERROR; + + else if (s_flag > 0 && chars > s_flag) + return ERROR; + + if (!flag && I_flag) { + for (int i = 0; i < args; i++) { + while (1) { + if (strstr(cmd[i], I_flag)) { + if (Iflag_push(str, &cmd[i])) + return ERROR; + } + + else + break; + } + } + + return I_FLAG; + } + + cmd[args] = strdup(str); + args++; + + return NORMAL; +} + +int is_correct(char c) { + if (nl_flag) + return c == '\0'; + + else + return isspace(c); +} + +int xargs(void) { + size_t arg_size = 0; + char *arg = malloc(1); + if (arg == NULL) { + fprintf(stderr, "xargs: malloc failed\n"); + return ERROR; + } + + size_t index = 0; + int flag = NONE; + int ret = NORMAL; + size_t chars = 0; + int args_passed = 0; + + while (1) { + int c = getchar(); + if (c == EOF) { + if (flag == QUOTE) { + fprintf(stderr, "xargs: unterminated quote\n"); + ret = ERROR; + } + + ret = CEOF; + break; + } + + if (flag == NONE && is_correct(c) && index > 0) { + arg[index] = '\0'; + + int r = add_arg(arg, chars, 0); + if (r == ERROR) { + ret = ERROR; + break; + } + + else if (r == I_FLAG) { + free(arg); + return NORMAL; + } + + index = 0; + arg_size = 0; + args_passed++; + free(arg); + + arg = malloc(1); + if (arg == NULL) { + fprintf(stderr, "xargs: malloc failed\n"); + return ERROR; + } + } + + else { + if (c == '"' || c == '\'') { + if (flag == QUOTE) + flag = NONE; + + else + flag = QUOTE; + + continue; + } + + else if (is_correct(c) && flag == NONE) + continue; + + char *tmp = realloc(arg, (++arg_size) + 1); + if (tmp == NULL) { + free(arg); + + fprintf(stderr, "xargs: realloc failed\n"); + return ERROR; + } + + arg = tmp; + arg[index] = (char)c; + + index++; + chars++; + } + } + + if (args_passed == 0 && ret != ERROR) + ret = CEOF; + + free(arg); + return ret; +} + +int spawn(void) { + if (t_flag) { + for (int i = 0; i < args; i++) + fprintf(stderr, "%s ", cmd[i]); + + fputc('\n', stderr); + } + + pid_t pid; + if ((pid = fork()) == 0) { + execvp(cmd[0], cmd); + fprintf(stderr, "xargs: exec: %s\n", strerror(errno)); + exit(1); + } + + int status = 0; + waitpid(pid, &status, 0); + + if (status == 255) + status = 124; + + else if (status >= 0x180) + status = 125; + + return status; +} + +int main(int argc, char **argv) { + /* For -s flag */ + char *p = NULL; + + int opt; + while ((opt = getopt(argc, argv, "tn:s:rP:0I:")) != -1) { + switch (opt) { + case 't': + t_flag = 1; + break; + + case 'n': + n_flag = atoi(optarg); + if (n_flag <= 0) { + fprintf(stderr, "xargs: -n: invalid number: %s\n", optarg); + return 1; + } + + break; + + case 's': + s_flag = strtoul(optarg, &p, 0); + if (s_flag <= 0 || *p) { + fprintf(stderr, "xargs: -s: invalid number: %zu%s\n", s_flag, (p) ? p : ""); + return 1; + } + + break; + + case 'r': + r_flag = 1; + break; + + case '0': + nl_flag = 1; + break; + + case 'I': + I_flag = optarg; + break; + + default: + printf("xargs [tnsrP0I] [cmd [arg1] [arg2...]\n\t-t Print the command before start\n\t-n Pass no more than N args\n\t-r Don't run command if input is empty\n\t-s Pass command line of no more than N bytes\n\t-0 NUL terminated input\n\t-I STR Replace STR within PROG ARGS with input line\n"); + return 0; + } + } + + argv += optind; + argc -= optind; + + int ret = 0; + while (1) { + + /* Arg */ + if (argc) { + for (int i = 0; i < argc; i++) + if (add_arg(argv[i], 0, 1)) + break; + } + + else + add_arg("echo", 0, 1); + + int stdin_stat = xargs(); + if (stdin_stat == ERROR) + ret = 1; + + /* Check NULL */ + for (int i = 0; i < args; i++) { + if (cmd[i] == NULL) { + fprintf(stderr, "xargs: strdup failed\n"); + clear_cmd(); + return 1; + } + } + + /* Run */ + if (stdin_stat == CEOF && I_flag == NULL) { + if (!r_flag) + ret = spawn(); + } + + else if (stdin_stat == NORMAL) + ret = spawn(); + + clear_cmd(); + if (stdin_stat) + break; + } + + return ret; +} diff --git a/src/init/init/build.sh b/src/init/init/build.sh new file mode 100755 index 0000000..3789ff3 --- /dev/null +++ b/src/init/init/build.sh @@ -0,0 +1,5 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC +cp reboot $OUTPUT/reboot +cp poweroff $OUTPUT/poweroff diff --git a/src/init/init/init.c b/src/init/init/init.c new file mode 100644 index 0000000..ac4ff31 --- /dev/null +++ b/src/init/init/init.c @@ -0,0 +1,64 @@ +#define INIT +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" + +void poweroff(int sig) { + printf("Syncing...\n"); + + sync(); + sleep(5); + + if (sig == SIGUSR1) + reboot(RB_POWER_OFF); + + else if (sig == SIGUSR2) + reboot(RB_AUTOBOOT); +} + +void execute(char *argv[]) { + if (fork() == 0) { + setsid(); + execvp(argv[0], argv); + + fprintf(stderr, "init: Failed to run %s\nRebooting...\n", argv[0]); + poweroff(SIGUSR2); + } +} + +int main(void) { + if (getpid() != 1) { + fprintf(stderr, "init: PID Must be 1\n"); + return 1; + } + + chdir("/"); + printf("%s\n", INIT_MSG); + + sigset_t set; + sigemptyset(&set); + sigaddset(&set, SIGUSR1); + sigaddset(&set, SIGUSR2); + + /* Start main service */ + sigprocmask(SIG_BLOCK, &set, NULL); + execute(INIT_START); + + /* Sig handler */ + int sig = 0; + while (1) { + if (sigwait(&set, &sig) == 0) + if (sig == SIGUSR2 || sig == SIGUSR1) { + execute(INIT_POWEROFF); + poweroff(sig); + } + } + + return 0; +} diff --git a/src/init/init/poweroff b/src/init/init/poweroff new file mode 100644 index 0000000..9784dcb --- /dev/null +++ b/src/init/init/poweroff @@ -0,0 +1,2 @@ +#!/bin/sh +kill -s USR1 1 diff --git a/src/init/init/reboot b/src/init/init/reboot new file mode 100644 index 0000000..3612dd2 --- /dev/null +++ b/src/init/init/reboot @@ -0,0 +1,2 @@ +#!/bin/sh +kill -s USR2 1 diff --git a/src/loginutils/cryptpw/build.sh b/src/loginutils/cryptpw/build.sh new file mode 100755 index 0000000..7bb1991 --- /dev/null +++ b/src/loginutils/cryptpw/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC -lcrypt diff --git a/src/loginutils/cryptpw/cryptpw.c b/src/loginutils/cryptpw/cryptpw.c new file mode 100644 index 0000000..74179bf --- /dev/null +++ b/src/loginutils/cryptpw/cryptpw.c @@ -0,0 +1,20 @@ +#include +#include "pw_check.h" + +int main(int argc, char **argv) { + if (argc < 2) { + printf("cryptpw: missing operand\ncryptpw [password] [own salt]\n"); + return 0; + } + + char *salt = NULL; + if (argc > 2) + salt = argv[2]; + + char *cpass = enc_password("cryptpw", argv[1], salt); + if (cpass == NULL) + return 1; + + puts(cpass); + return 0; +} diff --git a/src/loginutils/login/build.sh b/src/loginutils/login/build.sh new file mode 100755 index 0000000..7bb1991 --- /dev/null +++ b/src/loginutils/login/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC -lcrypt diff --git a/src/loginutils/login/login.c b/src/loginutils/login/login.c new file mode 100644 index 0000000..fc27859 --- /dev/null +++ b/src/loginutils/login/login.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pw_check.h" + +#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL) + +int hide_input(int fd, int flag) { + struct termios term; + if (tcgetattr(fd, &term) < 0) + return 1; + + if (flag) + term.c_lflag &= ~ECHOFLAGS; + + else + term.c_lflag |= ECHOFLAGS; + + if (tcsetattr(fd, TCSAFLUSH, &term) < 0) + return 1; + + return 0; +} + +void login(const struct passwd *pw) { + char *shell = (pw->pw_shell[0] == '\0') ? "/bin/sh" : pw->pw_shell; + + setenv("HOME", pw->pw_dir, 1); + setenv("SHELL", shell, 1); + setenv("USER", pw->pw_name, 1); + setenv("LOGNAME", pw->pw_name, 1); + setenv("PATH", "/bin", 1); + + if (chdir(pw->pw_dir) < 0) { + fprintf(stderr, "login: %s\n", strerror(errno)); + return; + } + + execlp(shell, shell, "-l", NULL); +} + +struct passwd *proccess_input(char *hostname) { + static char user[512]; + static char psswd[512]; + + /* Username */ + printf("Login on %s: ", hostname); + fflush(stdout); + + off_t ret = 0; + if ((ret = read(STDIN_FILENO, user, sizeof(user))) <= 0) + return NULL; + + user[ret - 1] = '\0'; + + struct passwd *pw = getpwnam(user); + if (!pw) { + fprintf(stderr, "login: Incorrent username\n"); + return NULL; + } + + /* Password */ + printf("Password: "); + fflush(stdout); + if (hide_input(STDIN_FILENO, 1)) + return NULL; + + if ((ret = read(STDIN_FILENO, psswd, sizeof(psswd))) <= 0) + return NULL; + + psswd[ret - 1] = '\0'; + printf("\n"); + if (pw_check("login", pw, psswd)) { + memset(psswd, '\0', sizeof(psswd)); + return NULL; + } + + memset(psswd, '\0', sizeof(psswd)); + return pw; +} + +int main(void) { + if ((!isatty(STDIN_FILENO) || !isatty(STDOUT_FILENO))) { + fprintf(stderr, "login: no tty\n"); + return 1; + } + + /* For prompt */ + char hostname[HOST_NAME_MAX + 1]; + if (gethostname(hostname, sizeof(hostname)) < 0) { + fprintf(stderr, "login: %s\n", strerror(errno)); + return 1; + } + + signal(SIGQUIT, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGHUP, SIG_IGN); + + struct passwd *pw = proccess_input(hostname); + hide_input(STDIN_FILENO, 0); + if (!pw) + return 1; + + /* Start */ + if (setgid(pw->pw_gid) < 0) { + fprintf(stderr, "login: %s\n", strerror(errno)); + return 1; + } + + if (setuid(pw->pw_uid) < 0) { + fprintf(stderr, "login: %s\n", strerror(errno)); + return 1; + } + + login(pw); + return 0; +} diff --git a/src/loginutils/su/build.sh b/src/loginutils/su/build.sh new file mode 100755 index 0000000..7bb1991 --- /dev/null +++ b/src/loginutils/su/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC -lcrypt diff --git a/src/loginutils/su/su.c b/src/loginutils/su/su.c new file mode 100644 index 0000000..a02035b --- /dev/null +++ b/src/loginutils/su/su.c @@ -0,0 +1,149 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pw_check.h" +#include "unused.h" + +#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL) + +char *c_flag = NULL; +char *s_flag = NULL; +char p_flag; + +int hide_input(int fd, int flag) { + struct termios term; + if (tcgetattr(fd, &term) < 0) + return 1; + + if (flag) + term.c_lflag &= ~ECHOFLAGS; + + else + term.c_lflag |= ECHOFLAGS; + + if (tcsetattr(fd, TCSAFLUSH, &term) < 0) + return 1; + + return 0; +} + +void su(const struct passwd *pw) { + char *shell = s_flag; + if (s_flag == NULL) + shell = (pw->pw_shell[0] == '\0') ? "/bin/sh" : pw->pw_shell; + + if (!p_flag) { + setenv("HOME", pw->pw_dir, 1); + setenv("SHELL", shell, 1); + setenv("USER", pw->pw_name, 1); + setenv("LOGNAME", pw->pw_name, 1); + setenv("PATH", "/bin", 1); + } + + if (c_flag) + execlp(shell, shell, "-c", c_flag, NULL); + + else + execlp(shell, shell, "-l", NULL); +} + +int password(const struct passwd *pw) { + static char psswd[512]; + + printf("Password: "); + fflush(stdout); + + if (hide_input(STDIN_FILENO, 1)) { + fprintf(stderr, "su: %s\n", strerror(errno)); + return 1; + } + + off_t ret = 0; + if ((ret = read(STDIN_FILENO, psswd, sizeof(psswd))) <= 0) { + fprintf(stderr, "su: %s\n", strerror(errno)); + return 1; + } + + psswd[ret - 1] = '\0'; + if (pw_check("su", pw, psswd)) { + memset(psswd, '\0', sizeof(psswd)); + return 1; + } + + printf("\n"); + memset(psswd, '\0', sizeof(psswd)); + return 0; +} + +void endwin(int sig) { + UNUSED(sig); + + hide_input(STDIN_FILENO, 0); + exit(1); +} + +int main(int argc, char **argv) { + int opt; + while ((opt = getopt(argc, argv, "c:s:p")) != -1) { + switch (opt) { + case 'c': + c_flag = optarg; + break; + + case 's': + s_flag = optarg; + break; + + case 'p': + p_flag = 1; + break; + + default: + printf("su [cps] [user Default: root]\n\t-c CMD Command to pass to \'sh -c\'\n\t-s SHELL Shell to use instead of user's default\n\t-p Do not set new env\n"); + return 0; + } + } + + argc -= optind; + argv += optind; + + char *user = "root"; + if (argv[0]) + user = argv[0]; + + struct passwd *pw = getpwnam(user); + if (!pw) { + fprintf(stderr, "su: Incorrent username\n"); + return 1; + } + + signal(SIGINT, endwin); + + if (getuid() != 0) { + int ret = password(pw); + hide_input(STDIN_FILENO, 0); + + if (ret) + return 1; + } + + /* Start */ + if (setgid(pw->pw_gid) < 0) { + fprintf(stderr, "su: %s\n", strerror(errno)); + return 1; + } + + if (setuid(pw->pw_uid) < 0) { + fprintf(stderr, "su: %s\n", strerror(errno)); + return 1; + } + + su(pw); + return 0; +} diff --git a/src/miscutils/spark/build.sh b/src/miscutils/spark/build.sh new file mode 100644 index 0000000..0ea3f65 --- /dev/null +++ b/src/miscutils/spark/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) -lm | xargs $CC diff --git a/src/miscutils/spark/spark.c b/src/miscutils/spark/spark.c new file mode 100644 index 0000000..a2c6871 --- /dev/null +++ b/src/miscutils/spark/spark.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include + +int parse_double(const char *str, double *res) { + char *ptr; + + *res = strtod(str, &ptr); + if (*ptr) + return 0; + + return 1; +} + +void print(double diff, char *str, double min) { + double val = 0; + if (!parse_double(str, &val)) + return; + + putchar('\xe2'); + putchar('\x96'); + putchar('\x81' + (int)round((val - min + 1) / diff * 7)); +} + +int main(int argc, char **argv) { + if (argc == 1) { + printf("spark: missing operands\nspark [num1] [num2]...\n"); + return 0; + } + + unsigned int r_flag = 0; + char ret = '\n'; + + double min = DBL_MAX; + double max = DBL_MIN; + + /* Remove programm name */ + argv++; + argc--; + + for (int i = 0; i < argc; i++) { + double val = 0; + if (strstr(argv[i], "r")) + r_flag = 1; + + else if (strstr(argv[i], "n")) + ret = '\r'; + + else if (parse_double(argv[i], &val)) { + if (val > max) + max = val; + + if (val < min) + min = val; + } + + else { + printf("spark [rn] [num1 num2...]\n\t-n Use \\r\n\t-r Reverse]\n"); + return 0; + } + } + + double diff = max - min + 1; + if (diff < 1) + diff = 1; + + if (r_flag) + for (int i = argc - 1; i >= 0; i--) + print(diff, argv[i], min); + + else + for (int i = 0; i < argc; i++) + print(diff, argv[i], min); + + putchar(ret); + return 0; +} diff --git a/src/networking/hostname/build.sh b/src/networking/hostname/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/networking/hostname/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/networking/hostname/hostname.c b/src/networking/hostname/hostname.c new file mode 100644 index 0000000..5ce2f26 --- /dev/null +++ b/src/networking/hostname/hostname.c @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include + +void readcfg(const char *cfg, char *buf, size_t len) { + FILE *fp = fopen(cfg, "r"); + if (fp == NULL) { + fprintf(stderr, "hostname: %s\n", strerror(errno)); + exit(1); + } + + if (fgets(buf, len, fp) == NULL) { + fprintf(stderr, "hostname: fgets returned NULL: %s\n", strerror(errno)); + + fclose(fp); + exit(1); + } + + /* Remove \n from string */ + *(strrchr(buf, '\n')) = '\0'; + + fclose(fp); +} + +int main(int argc, char **argv) { + char hostname[HOST_NAME_MAX + 1]; + char *newhost = NULL; + int config = 0; + + int opt; + while ((opt = getopt(argc, argv, "c:F:")) != -1) { + switch (opt) { + case 'F': + case 'c': + readcfg(optarg, hostname, sizeof(hostname)); + + config = 1; + newhost = hostname; + break; + + default: + printf("hostname [cF] [hostname]\n\t-c/-F PATH Use config file\n"); + return 0; + } + } + + argc -= optind; + argv += optind; + + if (newhost == NULL) + newhost = argv[0]; + + /* Set hostname */ + if (argc == 1 || config) { + if (sethostname(newhost, strlen(newhost)) < 0) { + fprintf(stderr, "hostname: %s\n", strerror(errno)); + return 1; + } + + return 0; + } + + /* Get hostname */ + if (gethostname(hostname, sizeof(hostname)) < 0) { + fprintf(stderr, "hostname: %s\n", strerror(errno)); + return 1; + } + + puts(hostname); + return 0; +} diff --git a/src/procps/kill/build.sh b/src/procps/kill/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/procps/kill/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/procps/kill/kill.c b/src/procps/kill/kill.c new file mode 100644 index 0000000..fbce6f5 --- /dev/null +++ b/src/procps/kill/kill.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + const char *name; + int signal; +} SIG; + +SIG signals[] = { + {"HUP", SIGHUP}, + {"INT", SIGINT}, + {"QUIT", SIGQUIT}, + {"ILL", SIGILL}, + {"TRAP", SIGTRAP}, + {"ABRT", SIGABRT}, + {"IOT", SIGIOT}, + {"BUS", SIGBUS}, + {"FPE", SIGFPE}, + {"KILL", SIGKILL}, + {"USR1", SIGUSR1}, + {"SEGV", SIGSEGV}, + {"USR2", SIGUSR2}, + {"PIPE", SIGPIPE}, + {"ALRM", SIGALRM}, + {"TERM", SIGTERM}, + {"CHLD", SIGCHLD}, + {"STOP", SIGSTOP} +}; + + +int parse_sig(char *arg) { + int sig = atoi(arg); + if (sig > 0 && sig <= NSIG) + return sig; + + if (!strncasecmp(arg, "SIG", 3)) + arg += 3; + + for (size_t i = 0; i < sizeof(signals) / sizeof(signals[0]); i++) + if (!strcasecmp(arg, signals[i].name)) + return signals[i].signal; + + return SIGTERM; +} + +int my_kill(pid_t pid, int signal) { + if (kill(pid, signal)) { + fprintf(stderr, "kill: %d: %s\n", pid, strerror(errno)); + return 1; + } + + return 0; +} + +int main(int argc, char **argv) { + unsigned int a_flag = 0; + int signal = SIGTERM; + + int opt; + while ((opt = getopt(argc, argv, "s:la")) != -1) { + switch (opt) { + case 'l': + for (size_t i = 0; i < sizeof(signals) / sizeof(signals[0]); i++) + printf("%zu) %s\n", i, signals[i].name); + + return 0; + + case 's': + signal = parse_sig(optarg); + break; + + case 'a': + a_flag = 1; + break; + + default: + printf("kill [lsa] [pid1 pid2...]\n\t-s SIG\n\t-l List all signals\n\t-a Kill all process\n"); + return 0; + } + } + + argv += optind; + argc -= optind; + + int ret = 0; + + if (a_flag) { + DIR *dp = opendir("/proc"); + if (dp == NULL) { + fprintf(stderr, "kill: /proc: %s\n", strerror(errno)); + return 1; + } + + pid_t my_pid = getpid(); + + struct dirent *ep; + while ((ep = readdir(dp)) != NULL) { + pid_t pid = atoi(ep->d_name); + if (pid == 0 || pid == my_pid) + continue; + + if (my_kill(pid, signal)) + ret = 1; + } + + closedir(dp); + } + + + else { + for (int i = 0; i < argc; i++) { + pid_t pid = atoi(argv[i]); + if (my_kill(pid, signal)) + ret = 1; + } + } + + return ret; +} diff --git a/src/procps/ps/build.sh b/src/procps/ps/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/procps/ps/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/procps/ps/ps.c b/src/procps/ps/ps.c new file mode 100644 index 0000000..cc0b88d --- /dev/null +++ b/src/procps/ps/ps.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +int open_file(const char *path) { + int fd = open(path, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "ps: %s: %s\n", path, strerror(errno)); + return -1; + } + + return fd; +} + +int pscan(const char *pid) { + char path[PATH_MAX + 1]; + char cmdline[PATH_MAX + 1]; + + /* Arguments */ + snprintf(path, sizeof(path), "/proc/%s/cmdline", pid); + int fd = open_file(path); + if (fd == -1) + return 1; + + read(fd, cmdline, sizeof(cmdline)); + close(fd); + + printf("%5s %5s\n", pid, cmdline); + return 0; +} + +int main(int argc, char **argv) { + + int opt; + while ((opt = getopt(argc, argv, "o:")) != -1) { + switch (opt) { + case 'o': + break; + + default: + printf("ps [o] [PID]\n\t-o Options (nice, tty, cmd, pid, nice)\n"); + return 0; + } + } + + DIR *dp = opendir("/proc"); + if (dp == NULL) { + fprintf(stderr, "ps: /proc: %s\n", strerror(errno)); + return 1; + } + + printf("PID CMD\n"); + + int ret = 0; + struct dirent *ep; + while ((ep = readdir(dp)) != NULL) + if (atoi(ep->d_name)) + if (pscan(ep->d_name)) + ret = 1; + + closedir(dp); + return ret; +} diff --git a/src/procps/uptime/build.sh b/src/procps/uptime/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/procps/uptime/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/procps/uptime/uptime.c b/src/procps/uptime/uptime.c new file mode 100644 index 0000000..4ff0b24 --- /dev/null +++ b/src/procps/uptime/uptime.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include +#include +#include "config.h" + +#if defined(CLOCK_BOOTTIME) + #define CLOCK CLOCK_BOOTTIME +#elif defined(CLOCK_UPTIME) + #define CLOCK CLOCK_UPTIME +#elif defined(__APPLE__) + #define CLOCK CLOCK_MONOTONIC +#endif + +int main(void) { + + /* Now date */ + time_t current_secs; + time(¤t_secs); + + struct tm *current_time = localtime(¤t_secs); + printf("%02d:%02d:%02d ", current_time->tm_hour, current_time->tm_min, current_time->tm_sec); + + /* How long system has beep up */ + struct timespec uptime; + if (clock_gettime(CLOCK, &uptime) != -1) { + int days = uptime.tv_sec / 86400; + int hours = uptime.tv_sec / 3600; + int mins = (uptime.tv_sec / 60) - (uptime.tv_sec / 3600 * 60); + + + printf("up:"); + + if (days > 0) + printf(" %d days", days); + + else if (hours > 0) + printf(" %d hours", hours); + + printf(" %d mins", mins); + } + +#ifdef UPTIME_LOADAVG + /* Print 1, 5 and 15 minute load averages */ + double avg[3] = {0, 0, 0}; + + if (getloadavg(avg, sizeof(avg) / sizeof(avg[0])) < 0) { + fprintf(stderr, "uptime: %s\n", strerror(errno)); + return 1; + } + + printf(" load average: %.2f %.2f %.2f", avg[0], avg[1], avg[2]); + +#endif + + putchar('\n'); + return 0; +} diff --git a/src/sysutils-linux/dmesg/build.sh b/src/sysutils-linux/dmesg/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/sysutils-linux/dmesg/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/sysutils-linux/dmesg/dmesg.c b/src/sysutils-linux/dmesg/dmesg.c new file mode 100644 index 0000000..5e40f1a --- /dev/null +++ b/src/sysutils-linux/dmesg/dmesg.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) { + unsigned int s_size = 0; + unsigned int n_level = 0; + + int opt; + while ((opt = getopt(argc, argv, "s:n:")) != -1) { + switch (opt) { + case 's': + s_size = atoi(optarg); + break; + + case 'n': + n_level = atoi(optarg); + break; + + default: + printf("dmesg [sn]\n\t-n LEVEL Set console logging level\n\t-s SIZE Buffer Size\n"); + return 0; + } + } + + /* Setup */ + if (n_level) + if (klogctl(8, NULL, (long)n_level) < 0) { + fprintf(stderr, "dmesg: %s\n", strerror(errno)); + return 1; + } + + if (!s_size) + s_size = klogctl(10, NULL, 0); + + + /* Get kernel log */ + char *buf = malloc(s_size + 1); + if (buf == NULL) { + fprintf(stderr, "dmesg: malloc failed\n"); + return 1; + } + + int n = klogctl(3, buf, s_size); + if (n <= 0) { + free(buf); + if (n == 0) + return 0; + + fprintf(stderr, "dmesg: %s\n", strerror(errno)); + return 1; + } + + + /* Print */ + if (write(STDOUT_FILENO, buf, n) != n) + fprintf(stderr, "dmesg: %s\n", strerror(errno)); + + putchar('\n'); + + free(buf); + return 0; +} + diff --git a/src/sysutils-linux/mount/build.sh b/src/sysutils-linux/mount/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/sysutils-linux/mount/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/sysutils-linux/mount/mount.c b/src/sysutils-linux/mount/mount.c new file mode 100644 index 0000000..2ac0280 --- /dev/null +++ b/src/sysutils-linux/mount/mount.c @@ -0,0 +1,110 @@ +#define _MOUNT_C + +#include +#include +#include +#include +#include +#include +#include +#include "parse_mount.h" +#include "config.h" + +int do_mount(const char *src, const char *dst, const char *fs_type, unsigned long opt, char *data) { + if (mount(src, dst, fs_type, opt, data) < 0) { + fprintf(stderr, "mount: %s: %s\n", src, strerror(errno)); + return 1; + } + + return 0; +} + +int parse_fstab(void) { + FILE *fp = setmntent(MOUNT_CFG, "r"); + if (fp == NULL) { + fprintf(stderr, "mount: %s\n", strerror(errno)); + return 1; + } + + char data[MOUNT_OPT_SIZE + 1]; + struct mntent *me; + + while ((me = getmntent(fp))) { + unsigned long mode = mu_parse_opts(me->mnt_opts, data, sizeof(data)); + do_mount(me->mnt_fsname, me->mnt_dir, me->mnt_type, mode, data); + } + + + endmntent(fp); + return 0; +} + +int print_mounts(void) { + FILE *fp = fopen(MOUNT_LIST, "r"); + if (fp == NULL) { + fprintf(stderr, "mount: %s\n", strerror(errno)); + return 1; + } + + char *buf = NULL; + size_t len = 0; + while (getline(&buf, &len, fp) != EOF) + printf("%s", buf); + + free(buf); + fclose(fp); + return 0; +} + +void print_opts(void) { + for (size_t i = 0; i < sizeof(mu_options) / sizeof(mu_options[0]); i++) { + printf("\t%s", mu_options[i].opt); + if (mu_options[i].notopt != NULL) + printf(" / %s", mu_options[i].notopt); + + if (mu_options[i].desc != NULL) + printf(" - %s", mu_options[i].desc); + + putchar('\n'); + } +} + +int main(int argc, char **argv) { + char *fs_type = MOUNT_DEF_FS; + char data[MOUNT_OPT_SIZE + 1]; + + unsigned long mode = 0; + + int opt; + while ((opt = getopt(argc, argv, "at:o:")) != -1) { + switch (opt) { + case 'a': + return parse_fstab(); + + case 't': + fs_type = optarg; + break; + + case 'o': + mode = mu_parse_opts(optarg, data, sizeof(data)); + break; + + default: + printf("mount [ato] [DEVICE] [NODE]\n\t-t Fs type, default %s\n\t-o Options\n\t-a Mount all fs in /etc/fstab\n\nOptions:\n", MOUNT_DEF_FS); + print_opts(); + return 0; + } + } + + argc -= optind; + argv += optind; + + if (argc == 2) + return do_mount(argv[0], argv[1], fs_type, mode, data); + + else if (argc == 1) + return do_mount(NULL, argv[0], fs_type, mode, data); + + else + return print_mounts(); +} diff --git a/src/sysutils-linux/pivot_root/build.sh b/src/sysutils-linux/pivot_root/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/sysutils-linux/pivot_root/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/sysutils-linux/pivot_root/pivot_root.c b/src/sysutils-linux/pivot_root/pivot_root.c new file mode 100644 index 0000000..a61f228 --- /dev/null +++ b/src/sysutils-linux/pivot_root/pivot_root.c @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include + +int main(int argc, char **argv) { + if (argc < 2) { + printf("pivot_root [new-root] [put-old]\n"); + return 0; + } + + if (syscall(SYS_pivot_root, argv[0], argv[1]) < 0) { + fprintf(stderr, "pivot_root: %s\n", strerror(errno)); + return 1; + } + + return 0; +} diff --git a/src/sysutils-linux/umount/build.sh b/src/sysutils-linux/umount/build.sh new file mode 100755 index 0000000..6d8974b --- /dev/null +++ b/src/sysutils-linux/umount/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +project_dir=$(pwd) +echo ./*.c $CFLAGS -o $OUTPUT$(basename $project_dir) | xargs $CC diff --git a/src/sysutils-linux/umount/umount.c b/src/sysutils-linux/umount/umount.c new file mode 100644 index 0000000..ee7ec47 --- /dev/null +++ b/src/sysutils-linux/umount/umount.c @@ -0,0 +1,70 @@ +#define _MOUNT_C + +#include +#include +#include +#include +#include +#include +#include +#include "config.h" + +int parse_fstab(unsigned long flag) { + FILE *fp = setmntent(MOUNT_CFG, "r"); + if (fp == NULL) { + fprintf(stderr, "umount: %s\n", strerror(errno)); + return 1; + } + + struct mntent *me; + + int ret = 0; + while ((me = getmntent(fp))) { + puts(me->mnt_dir); + if (umount2(me->mnt_dir, flag) < 0) { + fprintf(stderr, "umount: %s: %s\n", me->mnt_dir, strerror(errno)); + ret = 1; + } + + } + + endmntent(fp); + return ret; +} + +int main(int argc, char **argv) { + unsigned long flag = 0; + + int opt; + while ((opt = getopt(argc, argv, "afl")) != -1) { + switch (opt) { + case 'a': + return parse_fstab(flag); + + case 'f': + flag |= MNT_FORCE; + break; + + case 'l': + flag |= MNT_DETACH; + break; + + default: + printf("umount [afl] [dst1 dst2...]\n\t-a Umount all\n\t-f Force umount\n\t-l Lazy umount\n"); + return 0; + } + } + + argv += optind; + argc -= optind; + + int ret = 0; + for (int i = 0; i < argc; i++) { + if (umount2(argv[i], flag) < 0) { + fprintf(stderr, "umount: %s: %s\n", argv[i], strerror(errno)); + ret = 1; + } + } + + return ret; +}