fixed. Support building in one binary

This commit is contained in:
Your Name 2024-07-09 22:33:45 +03:00
parent 7d0207ace2
commit 33b89e64da
38 changed files with 285 additions and 163 deletions

4
libmu/build-libmu.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/sh
cd obj
cc ../libmu/*.c -I ../configs -I ../libmu -c

44
libmu/duration.c Normal file
View file

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

7
libmu/duration.h Normal file
View file

@ -0,0 +1,7 @@
#ifndef _DURATION_H
#define _DURATION_H
unsigned long long parse_uint(const char *str);
unsigned long long mu_parse_duration(const char *arg);
#endif

34
libmu/get_stat.c Normal file
View file

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

9
libmu/get_stat.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef _GET_STAT_H
#define _GET_STAT_H
#include <sys/stat.h>
int mu_get_stat(const char *prog_name, const char *path, struct stat *stat_path);
int mu_get_lstat(const char *prog_name, const char *path, struct stat *stat_path);
int mu_get_stats(const char *prog_name, int flag, const char *path, struct stat *stat_path);
#endif

22
libmu/human.c Normal file
View file

@ -0,0 +1,22 @@
#include "human.h"
char *mu_humansize(off_t n, off_t block) {
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;
}

12
libmu/human.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef _HUMAN_H
#define _HUMAN_H
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define MU_HUMAN_BUF_SIZE 16
static char mu_hs_buf[MU_HUMAN_BUF_SIZE + 1];
char *mu_humansize(off_t n, off_t block);
#endif

34
libmu/make_path.c Normal file
View file

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

5
libmu/make_path.h Normal file
View file

@ -0,0 +1,5 @@
#ifndef _MAKE_PATH_H
#define _MAKE_PATH_H
char *mu_make_path(const char *prog_name, const char *src, const char *dst);
#endif

53
libmu/mode_to_str.c Normal file
View file

@ -0,0 +1,53 @@
#include <stdio.h>
#include <sys/stat.h>
#include "mode_to_str.h"
char *mu_mode_2_str(mode_t file_mode) {
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;
}

6
libmu/mode_to_str.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef _MODE_TO_STR_H
#define _MODE_TO_STR_H
static char mode[11];
char *mu_mode_2_str(mode_t file_mode);
#endif

11
libmu/mu_strlen.c Normal file
View file

@ -0,0 +1,11 @@
#include "mu_strlen.h"
size_t mu_strlen(const char *s) {
size_t i = 0;
while (*s++)
i += (*s & 0xC0) != 0x80;
return i;
}

6
libmu/mu_strlen.h Normal file
View file

@ -0,0 +1,6 @@
#ifndef _MU_STRLEN
#define _MU_STRLEN
#include <stdio.h>
size_t mu_strlen(const char *s);
#endif

96
libmu/parse_mode.c Normal file
View file

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

5
libmu/parse_mode.h Normal file
View file

@ -0,0 +1,5 @@
#ifndef _PARSE_MODE_H
#define _PARSE_MODE_H
mode_t mu_parse_mode(const char *s, mode_t cur_mode);
#endif

51
libmu/parse_mount.c Normal file
View file

@ -0,0 +1,51 @@
#include <string.h>
#include "parse_mount.h"
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;
}

24
libmu/parse_mount.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef _PARSE_MOUNT_H
#define _PARSE_MOUNT_H
#include <sys/mount.h>
typedef struct {
char *opt;
char *notopt;
char *desc;
unsigned int val;
} MU_MOUNT_OPTS;
static 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);
#endif

95
libmu/proc_parser.c Normal file
View file

@ -0,0 +1,95 @@
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include "proc_parser.h"
int mu_proc_status(const char *prog_name, const pid_t pid, struct mu_proc *proc_s) {
proc_s->uid = -1;
proc_s->gid = -1;
/* Proccess file */
char path[PATH_MAX + 1];
snprintf(path, sizeof(path), "/proc/%d/status", pid);
int fd = open(path, O_RDONLY);
if (fd < 0) {
if (prog_name)
fprintf(stderr, "%s: %s: %s\n", prog_name, path, strerror(errno));
return 1;
}
char status[2048];
ssize_t n = read(fd, status, sizeof(status) - 1);
status[n] = '\0';
close(fd);
char *token = strtok(status, "\n");
while (token) {
char *val = strchr(token, ':');
if (val == NULL) {
fprintf(stderr, "ps: incorrect %s file\n", path);
return 1;
}
*val = '\0';
val++;
/* Strip */
while (isspace(*val))
val++;
/* Write values */
if (!strncmp(token, "Name", 4))
strcpy(proc_s->prog, val);
else if (!strncmp(token, "Uid", 3))
proc_s->uid = strtoul(val, 0L, 10);
else if (!strncmp(token, "Gid", 3))
proc_s->gid = strtoul(val, 0L, 10);
token = strtok(NULL, "\n");
}
return 0;
}
int mu_proc_stat(const char *prog_name, const pid_t pid, struct mu_proc *proc_s) {
char path[PATH_MAX + 1];
snprintf(path, sizeof(path), "/proc/%d/stat", pid);
FILE *fp = fopen(path, "r");
if (fp == NULL) {
if (prog_name)
fprintf(stderr, "%s: %s: %s\n", prog_name, path, strerror(errno));
return 1;
}
fscanf(fp, "%d %s %c %d %d %d %d %d %u %lu %lu %lu %lu %lu %lu", &proc_s->pid, proc_s->cmdline, &proc_s->state, &proc_s->ppid, &proc_s->pgrp, &proc_s->sid, &proc_s->tty, &proc_s->tpgid, &proc_s->flags, &proc_s->minflt, &proc_s->cminflt, &proc_s->majflt, &proc_s->cmajflt, &proc_s->utime, &proc_s->stime);
fscanf(fp, "%ld %ld %ld %ld %ld %ld %llu %lu %ld %ld", &proc_s->cutime, &proc_s->cstime, &proc_s->priority, &proc_s->nice, &proc_s->num_threads, &proc_s->itrealvalue, &proc_s->starttime, &proc_s->vsize, &proc_s->rss, &proc_s->rsslim);
fclose(fp);
return 0;
}
int mu_proc_parser(const char *prog_name, const pid_t pid, struct mu_proc *proc_s) {
memset(proc_s, 0, sizeof(struct mu_proc));
int ret = 0;
/* STAT */
if (mu_proc_stat(prog_name, pid, proc_s))
ret = 1;
/* STATUS */
if (mu_proc_status(prog_name, pid, proc_s))
ret = 1;
return ret;
}

45
libmu/proc_parser.h Normal file
View file

@ -0,0 +1,45 @@
#ifndef _PROC_PARSER
#define _PROC_PARSER
#include <pwd.h>
#include <grp.h>
#include <limits.h>
struct mu_proc {
/* from status */
char prog[PATH_MAX + 1];
uid_t uid;
gid_t gid;
/* from stat */
pid_t pid;
char cmdline[PATH_MAX + 1];
char state;
int ppid;
int pgrp;
int sid;
int tty;
int tpgid;
unsigned flags;
unsigned long minflt;
unsigned long cminflt;
unsigned long majflt;
unsigned long cmajflt;
unsigned long utime;
unsigned long stime;
long cutime;
long cstime;
long priority;
long nice;
long num_threads;
long itrealvalue;
unsigned long long starttime;
unsigned long vsize;
long rss;
long rsslim;
};
int mu_proc_status(const char *prog_name, const pid_t pid, struct mu_proc *proc_s);
int mu_proc_stat(const char *prog_name, const pid_t pid, struct mu_proc *proc_s);
int mu_proc_parser(const char *prog_name, const pid_t pid, struct mu_proc *proc_s);
#endif

54
libmu/pw_check.c Normal file
View file

@ -0,0 +1,54 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include "pw_check.h"
#include "config.h"
void dec_salt(void) {
size_t i;
for (i = 0; i < sizeof(MU_SALT_ENC) / sizeof(int); i++)
MU_SALT_BUF[i] = (char)MU_SALT_ENC[i];
MU_SALT_BUF[i + 1] = '\0';
}
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;
}

9
libmu/pw_check.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef _PW_CHECK_H
#define _PW_CHECK_H
#include <pwd.h>
void dec_salt(void);
char *enc_password(const char *prog_name, const char *pass, const char *salt);
int pw_check(const char *prog_name, const struct passwd *pw, const char *pass);
#endif

49
libmu/recurse.c Normal file
View file

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

5
libmu/recurse.h Normal file
View file

@ -0,0 +1,5 @@
#ifndef _RECURSE_H
#define _RECURSE_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));
#endif

6
libmu/unused.h Normal file
View file

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