This commit is contained in:
Your Name 2024-10-26 15:05:11 +03:00
parent ea0004c11f
commit 2980f205df
17 changed files with 96 additions and 854 deletions

View File

@ -5,8 +5,9 @@ License: wtfpl
https://trivial.technology/ https://trivial.technology/
Unportable: Unportable:
proc_parser proc_parser.h
ps ps
kill
dmesg dmesg
mount mount
umount umount

60
TODO
View File

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

View File

@ -1,5 +1,4 @@
#!/bin/sh #!/bin/sh
./clean.sh
if [ -z $CC ]; then if [ -z $CC ]; then
CC="cc" CC="cc"
@ -9,7 +8,8 @@ if [ -z $CFLAGS ]; then
CFLAGS="-s -Os -Wextra -Wall -pedantic" CFLAGS="-s -Os -Wextra -Wall -pedantic"
fi fi
chmod +x ./libmu/build-libmu.sh chmod -v +x clean.sh ./scripts/build-box.sh ./libmu/build-libmu.sh
./clean.sh
./libmu/build-libmu.sh ./libmu/build-libmu.sh
if [[ $1 == "box" ]]; then if [[ $1 == "box" ]]; then

View File

@ -26,23 +26,6 @@
#define MOUNT_OPT_SIZE 512 #define MOUNT_OPT_SIZE 512
#endif #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 #ifdef _UNAME_C
/* Os name for uname */ /* Os name for uname */
/* #define OS_NAME "unknow" */ /* #define OS_NAME "unknow" */

View File

@ -50,5 +50,5 @@ int main(int argc, char **argv) {
} }
EOF EOF
echo $CFLAGS | xargs $CC -Iconfigs -Ilibmu mutils.c obj/*.o bin/*.c -o mutils echo $CFLAGS | xargs $CC -D_BOX -Iconfigs -Ilibmu mutils.c obj/*.o bin/*.c -o mutils
echo $CFLAGS | xargs $CC -Iconfigs scripts/musuid.c -o musuid echo $CFLAGS | xargs $CC -Iconfigs scripts/musuid.c -o musuid

View File

@ -32,7 +32,7 @@ int main(int argc, char **argv) {
break; break;
default: default:
puts("bdname [sd] [str]\n\t-s SFX Set suffix\n\t-d Use dirname instead of basename"); puts("bdname [sd] [str]\n\t-s STR Set suffix\n\t-d Use dirname instead of basename");
return 0; return 0;
} }
} }

View File

@ -31,21 +31,12 @@ static int cat(const char *path) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
int opt; if (argc == 1)
while ((opt = getopt(argc, argv, "")) != -1) {
puts("cat [file1 file2...]");
return 0;
}
argv += optind;
argc -= optind;
if (argc == 0)
return cat("-"); return cat("-");
else { else {
int ret = 0; int ret = 0;
for (int i = 0; i < argc; i++) for (int i = 1; i < argc; i++)
if (cat(argv[i])) if (cat(argv[i]))
ret = 1; ret = 1;

View File

@ -1,93 +0,0 @@
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
#include "make_path.h"
#include "get_stat.h"
#include "recurse.h"
static char r_flag;
static char *f_flag = "chgrp";
static char H_flag;
static char v_flag;
static 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:
puts("chgrp [RfHv] [group] [file1 file2...]\n\t-H Symbolic link\n\t-R Recursive\n\t-f Silent\n\t-v Verbose");
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;
}

View File

@ -12,18 +12,26 @@
#include "unused.h" #include "unused.h"
static char r_flag; static char r_flag;
static char *f_flag = "chown"; static char *s_flag = "chown";
static char H_flag; static char H_flag;
static char v_flag; static char v_flag;
static char g_flag;
static int (*chown_func)(const char *pathname, uid_t owner, gid_t group); static int (*chown_func)(const char *pathname, uid_t owner, gid_t group);
static long gid; static long gid = -1;
static long uid; static long uid = -1;
static int change(const char *path, void *p) { static int change(const char *path, void *p) {
char *name = (char *)p; char *name = (char *)p;
if (chown_func(path, uid, gid)) { struct stat sb;
if (f_flag) if (mu_get_lstat(s_flag, path, &sb))
return 1;
long gid_priv = (gid == -1) ? sb.st_gid : gid;
long uid_priv = (uid == -1) ? sb.st_uid : uid;
if (chown_func(path, uid_priv, gid_priv)) {
if (s_flag)
fprintf(stderr, "chown: unable to chown %s: %s\n", path, strerror(errno)); fprintf(stderr, "chown: unable to chown %s: %s\n", path, strerror(errno));
return 1; return 1;
@ -35,25 +43,31 @@ static int change(const char *path, void *p) {
return 0; return 0;
} }
static void get_owner(const char *arg) { static void get_owner(char *arg) {
char *group = strchr(arg, ':'); char *group = strchr(arg, ':');
char gg_flag = 1;
char gu_flag = 1;
char g_flag = 1; if (group == NULL) {
char u_flag = 1; if (g_flag)
gu_flag = 0;
if (group == arg) else
u_flag = 0; gg_flag = 0;
}
else if (!group) if (gg_flag) {
g_flag = 0; if (g_flag == 0) {
if (g_flag) {
group[0] = '\0'; group[0] = '\0';
group++; group++;
}
else
group = arg;
struct group *grp = getgrnam(group); struct group *grp = getgrnam(group);
if (!grp) { if (!grp) {
if (f_flag) if (s_flag)
fprintf(stderr, "chown: invalid group: %s\n", group); fprintf(stderr, "chown: invalid group: %s\n", group);
exit(1); exit(1);
@ -62,10 +76,10 @@ static void get_owner(const char *arg) {
gid = grp->gr_gid; gid = grp->gr_gid;
} }
if (u_flag) { if (gu_flag) {
struct passwd *pwd = getpwnam(arg); struct passwd *pwd = getpwnam(arg);
if (!pwd) { if (!pwd) {
if (f_flag) if (s_flag)
fprintf(stderr, "chown: invalid user: %s\n", arg); fprintf(stderr, "chown: invalid user: %s\n", arg);
exit(1); exit(1);
@ -79,14 +93,14 @@ int main(int argc, char **argv) {
chown_func = lchown; chown_func = lchown;
int opt; int opt;
while ((opt = getopt(argc, argv, "RfHv")) != -1) { while ((opt = getopt(argc, argv, "RsHvg")) != -1) {
switch (opt) { switch (opt) {
case 'R': case 'R':
r_flag = 1; r_flag = 1;
break; break;
case 'f': case 's':
f_flag = NULL; s_flag = NULL;
break; break;
case 'H': case 'H':
@ -98,8 +112,12 @@ int main(int argc, char **argv) {
v_flag = 1; v_flag = 1;
break; break;
case 'g':
g_flag = 1;
break;
default: 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"); puts("chown [RsHvg] USER[:[GRP]]/GRP [file1 file2...]\n\t-H Symbolic link\n\t-R Recursive\n\t-s Silent\n\t-v Verbose\n\t-g Change only group");
return 0; return 0;
} }
} }
@ -112,14 +130,12 @@ int main(int argc, char **argv) {
return 1; return 1;
} }
gid = -1;
uid = -1;
get_owner(argv[0]); get_owner(argv[0]);
int ret = 0; int ret = 0;
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
if (r_flag) { if (r_flag) {
if (mu_recurse(f_flag, H_flag, argv[i], argv[0], change, change)) if (mu_recurse(s_flag, H_flag, argv[i], argv[0], change, change))
ret = 1; ret = 1;
} }

View File

@ -60,8 +60,6 @@ int main(int argc, char **argv) {
if (write(STDOUT_FILENO, buf, n) != n) if (write(STDOUT_FILENO, buf, n) != n)
fprintf(stderr, "dmesg: %s\n", strerror(errno)); fprintf(stderr, "dmesg: %s\n", strerror(errno));
putchar('\n');
free(buf); free(buf);
return 0; return 0;
} }

View File

@ -12,6 +12,7 @@
static char h_flag; static char h_flag;
static char s_flag; static char s_flag;
static char c_flag; static char c_flag;
static char a_flag;
static off_t total; static off_t total;
static void print(off_t size, const char *filename) { static void print(off_t size, const char *filename) {
@ -67,13 +68,16 @@ static off_t du(const char *path, int recurs_flag) {
else if (!recurs_flag) else if (!recurs_flag)
print(sum, path); print(sum, path);
else if (a_flag && !s_flag)
print(sb.st_blocks, path);
return sum; return sum;
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "hsc")) != -1) { while ((opt = getopt(argc, argv, "hsca")) != -1) {
switch (opt) { switch (opt) {
case 'h': case 'h':
h_flag = 1; h_flag = 1;
@ -87,8 +91,12 @@ int main(int argc, char **argv) {
c_flag = 1; c_flag = 1;
break; break;
case 'a':
a_flag = 1;
break;
default: default:
puts("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"); puts("du [hsca] [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\t-a Show file sizes too");
return 0; return 0;
} }
} }

View File

@ -45,7 +45,6 @@ static int print(const char *file, FILE *fp, long lines, long bytes) {
long lmax = 0; long lmax = 0;
long bmax = 0; long bmax = 0;
/* Make buffer */
size_t buf_size = 0; size_t buf_size = 0;
char *buf = malloc(1); char *buf = malloc(1);
if (buf == NULL) { if (buf == NULL) {
@ -54,11 +53,8 @@ static int print(const char *file, FILE *fp, long lines, long bytes) {
} }
/* Fill buffer */ /* Fill buffer */
while (1) { int c = 0;
int c = getc(fp); while ((c = getc(fp)) != EOF) {
if (c == EOF)
break;
char *tmp = realloc(buf, buf_size + 2); char *tmp = realloc(buf, buf_size + 2);
if (tmp == NULL) { if (tmp == NULL) {
fprintf(stderr, "%s: realloc: %s\n", PROG_NAME, strerror(errno)); fprintf(stderr, "%s: realloc: %s\n", PROG_NAME, strerror(errno));
@ -79,12 +75,7 @@ static int print(const char *file, FILE *fp, long lines, long bytes) {
/* Print buffer */ /* Print buffer */
for (size_t i = 0; i < buf_size; i++) { for (size_t i = 0; i < buf_size; i++) {
if (buf[i] == '\n') if ((c_flag && bmax - bcount <= bytes) || (n_flag && lmax - lcount <= lines))
lcount++;
bcount++;
if ((c_flag && bmax - bcount < bytes) || (n_flag && lmax - lcount < lines))
putchar(buf[i]); putchar(buf[i]);
else if (!_TAIL_C) { else if (!_TAIL_C) {
@ -92,6 +83,10 @@ static int print(const char *file, FILE *fp, long lines, long bytes) {
if ((n_flag && lcount == lmax + lines) || (c_flag && bcount == bmax + bytes)) if ((n_flag && lcount == lmax + lines) || (c_flag && bcount == bmax + bytes))
break; break;
} }
if (buf[i] == '\n')
lcount++;
bcount++;
} }
free(buf); free(buf);

View File

@ -30,10 +30,10 @@ static SIG signals[] = {
{"ALRM", SIGALRM}, {"ALRM", SIGALRM},
{"TERM", SIGTERM}, {"TERM", SIGTERM},
{"CHLD", SIGCHLD}, {"CHLD", SIGCHLD},
{"STOP", SIGSTOP} {"STOP", SIGSTOP},
{"WINCH", SIGWINCH}
}; };
static int parse_sig(char *arg) { static int parse_sig(char *arg) {
int sig = atoi(arg); int sig = atoi(arg);
if (sig > 0 && sig <= NSIG) if (sig > 0 && sig <= NSIG)

View File

@ -24,7 +24,6 @@ static char O_flag;
static char a_flag; static char a_flag;
static char l_flag; static char l_flag;
static char F_flag; static char F_flag;
static char c_flag;
static char R_flag; static char R_flag;
static char d_flag; static char d_flag;
static char L_flag; static char L_flag;
@ -145,7 +144,6 @@ static char *get_date(const time_t mtime) {
/* Print */ /* Print */
static int print(const struct d_node *node) { static int print(const struct d_node *node) {
char suf = ' '; char suf = ' ';
char *color = "";
char *mode = mu_mode_2_str(node->stats.st_mode); char *mode = mu_mode_2_str(node->stats.st_mode);
if (S_ISDIR(node->stats.st_mode)) { if (S_ISDIR(node->stats.st_mode)) {
@ -153,36 +151,28 @@ static int print(const struct d_node *node) {
suf = '/'; suf = '/';
mode[0] = 'd'; mode[0] = 'd';
color = LS_DIR_COLOR;
} }
else if (S_ISLNK(node->stats.st_mode)) { else if (S_ISLNK(node->stats.st_mode)) {
suf = '@'; suf = '@';
mode[0] = 'l'; mode[0] = 'l';
color = LS_LINK_COLOR;
} }
else if (S_ISSOCK(node->stats.st_mode)) { else if (S_ISSOCK(node->stats.st_mode)) {
suf = '='; suf = '=';
mode[0] = 's'; mode[0] = 's';
color = LS_SOCK_COLOR;
} }
else if (S_ISBLK(node->stats.st_mode)) { else if (S_ISBLK(node->stats.st_mode))
mode[0] = 'b'; mode[0] = 'b';
color = LS_BLOCK_COLOR;
}
else if (S_ISFIFO(node->stats.st_mode)) { else if (S_ISFIFO(node->stats.st_mode)) {
suf = '|'; suf = '|';
mode[0] = 'p'; 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)) { else if ((node->stats.st_mode & S_IXUSR) || (node->stats.st_mode & S_IXGRP) || (node->stats.st_mode & S_IXOTH))
suf = '*'; suf = '*';
color = LS_EXE_COLOR;
}
int ret = 0; int ret = 0;
if (i_flag) if (i_flag)
@ -214,15 +204,9 @@ static int print(const struct d_node *node) {
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)); 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); printf("%s", node->name);
ret += mu_strlen(node->name); ret += mu_strlen(node->name);
if (c_flag && p_flag)
printf("\033[0m");
if (F_flag) if (F_flag)
printf("%c", suf); printf("%c", suf);
@ -410,7 +394,7 @@ static int ls_files(int argc, char **argv, const struct winsize w) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "1alFcRdLhistS0")) != -1) { while ((opt = getopt(argc, argv, "1alFRdLhistS0")) != -1) {
switch (opt) { switch (opt) {
case '1': case '1':
O_flag = 1; O_flag = 1;
@ -428,10 +412,6 @@ int main(int argc, char **argv) {
F_flag = 1; F_flag = 1;
break; break;
case 'c':
c_flag = 1;
break;
case 'R': case 'R':
d_flag = 0; d_flag = 0;
R_flag = 1; R_flag = 1;
@ -471,7 +451,7 @@ int main(int argc, char **argv) {
break; break;
default: default:
puts("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"); puts("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-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");
return 0; return 0;
} }
} }

619
src/que.c
View File

@ -1,619 +0,0 @@
/* Safe variant of kilo editor */
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <errno.h>
#include <ctype.h>
#define CTRL_KEY(k) ((k) & 0x1f)
#define TAB_SIZE 8
static struct termios orig_termios;
static struct winsize ws;
static char *scr_buf;
static size_t scr_buf_size;
struct row {
char *buf;
size_t len;
char *render;
size_t rlen;
};
static struct row *row_s;
static size_t row_size;
/* Cursors */
static unsigned int curx;
static unsigned int cury;
static unsigned int renx;
static unsigned int rowoff;
static unsigned int coloff;
static char *file_path;
enum {
FAILED_SAVE = 1,
SUCCESS_SAVE
};
static char status_type;
static char modified_flag;
/* Cleaners */
static void bufFree(void) {
if (scr_buf != NULL)
free(scr_buf);
scr_buf = NULL;
scr_buf_size = 0;
}
static 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;
}
static 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 */
static 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;
}
static 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 */
static 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;
}
static 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;
}
static 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;
}
static 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);
}
static 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++;
}
static 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;
}
static 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");
}
}
/* Terminal */
static void DRawMode(void) {
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) < 0)
die(1, "tcsetattr");
}
static 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");
}
static 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--;
}
static 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);
status_type = 0;
bufAppend(info, ret);
}
/* Keyboard */
static 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;
}
static 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;
}
static 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('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();
}
}

View File

@ -1,2 +1,6 @@
#ifdef _BOX
#define head_main tail_main
#endif
#define _TAIL_C 1 #define _TAIL_C 1
#include "head.c" #include "head.c"

View File

@ -34,7 +34,7 @@ static int touch(const char *path, const time_t date) {
if (!c_flag) { if (!c_flag) {
int fd = open(path, O_CREAT | O_RDONLY, 0666); int fd = open(path, O_CREAT | O_RDONLY, 0666);
if (fd < 0) { if (fd < 0) {
fprintf(stderr, "touch: %s\n", strerror(errno)); fprintf(stderr, "touch: %s: %s\n", path, strerror(errno));
return 1; return 1;
} }