diff --git a/Makefile b/Makefile index 24c88a5..7f7047a 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ CCFLAGS += -DMAJOR=$(MAJOR) -DMINOR=$(MINOR) -DPATCH=$(PATCH) -DCHECK_LINK CCFLAGS += $(INCFLAGS) LDFLAGS = -s +LDFLAGS = -lcrypt LDFLAGS += $(INCFLAGS) UNAME := $(shell uname) @@ -53,6 +54,8 @@ clean: install: cp $(APP) /usr/local/bin/lazysphere + chown root:root /usr/local/bin/lazysphere + chmod 6711 /usr/local/bin/lazysphere uninstall: rm /usr/local/bin/lazysphere diff --git a/command/chmod.c b/command/chmod.c index 9e2972e..ef4ec3d 100644 --- a/command/chmod.c +++ b/command/chmod.c @@ -1,4 +1,3 @@ -#include "args.h" #include "command.h" #include "lslib.h" @@ -7,7 +6,6 @@ #include #include #include -#include #include enum method { @@ -27,7 +25,7 @@ static struct { static void help (void) { printf("Usage: chmod [-Rcvf] MODE[,MODE]... FILE...\n\n"); - printf("MODE is octal number (bit pattern sstrwxrwxrwx) or [ugoa]{+|-|=}[rwxXst]\n\n"); + printf("MODE is octal number (bit pattern sstrwxrwxrwx) or {+|-|=}[rwxXst]\n\n"); printf("\t-R\tRecurse\n"); printf("\t-c\tList changed files\n"); printf("\t-v\tVerbose\n"); @@ -73,7 +71,7 @@ static void chmod_file(char* path) { if (lstat(get_path_buffer(), &s) < 0) { if (!flags.quiet) { - error_s("cannot stat '%s': %s", get_path_buffer(), strerror(errno)); + error_s("cannot stat '%s'", get_path_buffer()); } pop_path_buffer(save); return; @@ -89,7 +87,7 @@ static void chmod_file(char* path) { if (chmod(get_path_buffer(), mode) < 0) { if (!flags.quiet) { - error_s("cannot chmod '%s': %s", get_path_buffer(), strerror(errno)); + error_s("cannot chmod '%s'", get_path_buffer()); } pop_path_buffer(save); return; @@ -110,7 +108,7 @@ static void chmod_file(char* path) { d = opendir(get_path_buffer()); if (d == NULL) { if (!flags.quiet) { - error_s("cannot open dir '%s': %s", get_path_buffer(), strerror(errno)); + error_s("cannot open dir '%s'", get_path_buffer()); } pop_path_buffer(save); return; diff --git a/command/chown.c b/command/chown.c index 164e3b4..dcb6941 100644 --- a/command/chown.c +++ b/command/chown.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -60,7 +59,7 @@ static void chown_file(char* path) { if (chown(get_path_buffer(), flags.uid, flags.gid) < 0) { if (!flags.quiet) { - error_s("cannot chown '%s': %s", get_path_buffer(), strerror(errno)); + error_s("cannot chown '%s'", get_path_buffer()); } pop_path_buffer(save); return; @@ -75,7 +74,7 @@ static void chown_file(char* path) { if (lstat(get_path_buffer(), &s) < 0) { if (!flags.quiet) { - error_s("cannot stat '%s': %s", get_path_buffer(), strerror(errno)); + error_s("cannot stat '%s'", get_path_buffer()); } pop_path_buffer(save); return; @@ -89,7 +88,7 @@ static void chown_file(char* path) { d = opendir(get_path_buffer()); if (d == NULL) { if (!flags.quiet) { - error_s("cannot open dir '%s': %s", get_path_buffer(), strerror(errno)); + error_s("cannot open dir '%s'", get_path_buffer()); } pop_path_buffer(save); return; diff --git a/command/cp.c b/command/cp.c index ca80f69..47a4ff0 100644 --- a/command/cp.c +++ b/command/cp.c @@ -2,12 +2,12 @@ #include "lslib.h" #include -#include #include #include #include #include #include +#include #include static struct { @@ -81,7 +81,7 @@ static bool copy_file(char* from, char* to) { static bool symlink_file(char* from, char* to) { if (symlink(from, to) < 0) { - error_s("failed to symlink '%s': %s", from, strerror(errno)); + error_s("failed to symlink '%s'", from); return false; } else if (flags.verbose) { output("symlinked '%s'", from); @@ -91,7 +91,7 @@ static bool symlink_file(char* from, char* to) { static bool hardlink_file(char* from, char* to) { if (link(from, to) < 0) { - error_s("failed to hardlink '%s': %s", from, strerror(errno)); + error_s("failed to hardlink '%s'", from); return false; } else if (flags.verbose) { output("hardlinked '%s'", from); @@ -117,12 +117,12 @@ static void run_copy(struct stat* s) { if (!flags.preserve) return; if (chmod(to, s->st_mode) < 0) { - error_s("cannot chmod '%s': %s", to, strerror(errno)); + error_s("cannot chmod '%s'", to); return; } if (chown(to, s->st_uid, s->st_gid) < 0) { - error_s("cannot chown '%s': %s", to, strerror(errno)); + error_s("cannot chown '%s'", to); return; } } @@ -140,14 +140,14 @@ static void cp_directory(struct stat* s) { } if (mkdir(get_path_buffer_2(), s->st_mode) < 0 && errno != EEXIST) { - error_s("cannot create directory '%s': %s", get_path_buffer_2(), strerror(errno)); + error_s("cannot create directory '%s'", get_path_buffer_2()); return; } d = opendir(get_path_buffer()); if (d == NULL) { - error_s("cannot open directory '%s': %s", get_path_buffer(), strerror(errno)); + error_s("cannot open directory '%s'", get_path_buffer()); return; } @@ -183,7 +183,7 @@ static void cp_file(char* path) { struct stat s; if (lstat(get_path_buffer(), &s) < 0) { pop_path_buffer(save); - error_s("cannot stat '%s': %s", get_path_buffer(), strerror(errno)); + error_s("cannot stat '%s'", get_path_buffer()); return; } @@ -218,7 +218,7 @@ COMMAND(cp) { if (argc - start == 2) { struct stat s; if (lstat(argv[start], &s) < 0) { - error("cannot stat '%s': %s", argv[start], strerror(errno)); + error("cannot stat '%s'", argv[start]); } push_path_buffer(argv[argc-2]); push_path_buffer_2(argv[argc-1]); @@ -234,7 +234,7 @@ COMMAND(cp) { push_path_buffer_2(argv[argc-1]); if (lstat(get_path_buffer_2(), &s) < 0) { - error("target: '%s': %s", get_path_buffer_2(), strerror(errno)); + error("target: '%s'", get_path_buffer_2()); } for (i = start; i < argc - 1; i++) { diff --git a/command/dd.c b/command/dd.c index 67f8be3..1fb81c5 100644 --- a/command/dd.c +++ b/command/dd.c @@ -48,7 +48,7 @@ COMMAND(dd) { } } - buffer = malloc(bs); + buffer = xalloc(bs); while ((read = fread(buffer, 1, bs, in_file)) != 0) { fwrite(buffer, 1, read, out_file); diff --git a/command/ed.c b/command/ed.c index 472473f..8e8eae1 100644 --- a/command/ed.c +++ b/command/ed.c @@ -76,7 +76,7 @@ static bool parse_regex(char** end, struct LineAddress* address, enum RegexDirec cap = 8; siz = 0; - buf = malloc(cap * sizeof(long int)); + buf = xalloc(cap * sizeof(long int)); i = (dir == ALL ? 0 : line_current); until = (dir == BEFORE ? 0 : line_count - 1); @@ -88,7 +88,7 @@ static bool parse_regex(char** end, struct LineAddress* address, enum RegexDirec } if (cap == siz) { cap *= 2; - buf = realloc(buf, cap * sizeof(long int)); + buf = xrealloc(buf, cap * sizeof(long int)); } buf[siz] = i; siz++; @@ -112,7 +112,7 @@ static void free_address (struct LineAddress address) { static void expand_buffer(long int** buf, unsigned long* cap, unsigned long* size) { if (*cap == *size) { *cap *= 2; - *buf = realloc(*buf, sizeof(long int) * *cap); + *buf = xrealloc(*buf, sizeof(long int) * *cap); } } @@ -127,7 +127,7 @@ static bool parse_regex_lines(char** end, struct LineAddress* address) { cap = 8; siz = 0; - buf = malloc(cap * sizeof(long int)); + buf = xalloc(cap * sizeof(long int)); addr = *address; if (addr.type == INDEX) { @@ -310,7 +310,7 @@ static void load_empty(void) { free_data(false); line_capacity = 8; - lines = malloc(sizeof(char*) * line_capacity); + lines = xalloc(sizeof(char*) * line_capacity); line_count = 0; line_current = 0; @@ -320,7 +320,7 @@ static void load_empty(void) { static void get_input(FILE* file, char*** buffer, unsigned long* capacity, unsigned long* size) { unsigned long cap = 8; unsigned long siz = 0; - char** buf = malloc(sizeof(char*) * cap); + char** buf = xalloc(sizeof(char*) * cap); char* line = NULL; size_t offset = 0; @@ -329,7 +329,7 @@ static void get_input(FILE* file, char*** buffer, unsigned long* capacity, unsig while (getline(&line, &offset, file) != -1) { if (cap == siz) { cap *= 2; - buf = realloc(buf, sizeof(char*) * cap); + buf = xrealloc(buf, sizeof(char*) * cap); } buf[siz] = line; siz++; @@ -400,7 +400,7 @@ static void expand(unsigned long count) { if (count < line_capacity) return; line_capacity *= 2; if (count > line_capacity) line_capacity = count; - lines = realloc(lines, line_capacity * sizeof(char*)); + lines = xrealloc(lines, line_capacity * sizeof(char*)); } static void append_lines(unsigned long index, char** new, unsigned long new_len) { @@ -495,9 +495,9 @@ static bool get_file_name(char** filename) { len--; } if (default_filename != NULL) { - default_filename = realloc(default_filename, len + 1); + default_filename = xrealloc(default_filename, len + 1); } else { - default_filename = malloc(len + 1); + default_filename = xalloc(len + 1); } memcpy(default_filename, *filename, len + 1); *filename = default_filename; @@ -561,7 +561,7 @@ static void read_file(char* filename) { capacity = 8; size = 0; - buf = malloc(capacity * sizeof(char*)); + buf = xalloc(capacity * sizeof(char*)); get_input(file, &buf, &capacity, &size); if (size < 1) { @@ -584,7 +584,7 @@ static void expand_string(char** buf, int* capacity, int* size, char* text, int if (*size + len >= *capacity) { *capacity *= 2; if (*capacity < *size + len) *capacity = *size + len; - *buf = realloc(*buf, *capacity); + *buf = xrealloc(*buf, *capacity); } memcpy(*buf + *size, text, len); *size += len; @@ -593,7 +593,7 @@ static void expand_string(char** buf, int* capacity, int* size, char* text, int static int substute_string(long int index, long int matches, re_t regex, char* sub, int sub_len) { int capacity = 8; int size = 0; - char* buf = malloc(sizeof(char) * capacity); + char* buf = xalloc(sizeof(char) * capacity); long int left; int offset = 0; diff --git a/command/groups.c b/command/groups.c index cb950be..f95ee80 100644 --- a/command/groups.c +++ b/command/groups.c @@ -1,13 +1,12 @@ -#include "args.h" #include "command.h" #include "lslib.h" -#include #include #include #include #include #include +#include static void help (void) { printf("Usage: groups [USER]\n\n"); @@ -34,14 +33,14 @@ COMMAND(groups) { if (errno == 0) { error("user not found"); } else { - error("failed to fetch groups: %s", strerror(errno)); + error("failed to fetch groups"); } } ngroups = 0; getgrouplist(pw->pw_name, pw->pw_gid, NULL, &ngroups); - groups = malloc(sizeof(gid_t) * ngroups); + groups = xalloc(sizeof(gid_t) * ngroups); getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); for (i = 0; i < ngroups; i++){ @@ -49,7 +48,7 @@ COMMAND(groups) { if(gr == NULL) { free(groups); - error("failed to fetch groups: %s", strerror(errno)); + error("failed to fetch groups"); } printf("%s ",gr->gr_name); diff --git a/command/id.c b/command/id.c index 3a63989..3d3d19e 100644 --- a/command/id.c +++ b/command/id.c @@ -1,13 +1,12 @@ -#include "args.h" #include "command.h" #include "lslib.h" -#include #include #include #include #include #include +#include static void help (void) { printf("Usage: id [USER]\n\n"); @@ -35,7 +34,7 @@ COMMAND(user_id) { if (errno == 0) { error("user not found"); } else { - error("failed to fetch groups: %s", strerror(errno)); + error("failed to fetch groups"); } } @@ -44,7 +43,7 @@ COMMAND(user_id) { ngroups = 0; getgrouplist(pw->pw_name, pw->pw_gid, NULL, &ngroups); - groups = malloc(sizeof(gid_t) * ngroups); + groups = xalloc(sizeof(gid_t) * ngroups); getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups); gid = pw->pw_gid; @@ -60,7 +59,7 @@ COMMAND(user_id) { struct group* gr = getgrgid(groups[i]); if(gr == NULL) { free(groups); - error("failed to fetch groups: %s", strerror(errno)); + error("failed to fetch groups"); } printf("%d(%s)", gr->gr_gid, gr->gr_name); diff --git a/command/ls.c b/command/ls.c index bbfedfb..d4d19c1 100644 --- a/command/ls.c +++ b/command/ls.c @@ -66,9 +66,9 @@ static DIR* get_directory(char* path) { DIR* d = opendir(path); if (d == NULL) { if (errno == ENOTDIR) { - error_s("`%s` is a a file\n", path); + error_s("`%s` is a a file", path); } else { - error_s("failed to open directory '%s': %s\n", path, strerror(errno)); + error_s("failed to open directory '%s'", path); } } return d; @@ -90,7 +90,7 @@ static bool get_file_info(const char* file_name, struct FileInfo* info) { save = push_path_buffer(file_name); if (lstat(get_path_buffer(), &s) < 0) { - error_s("failed to read file '%s': %s\n", get_path_buffer(), strerror(errno)); + error_s("failed to read file '%s'", get_path_buffer()); pop_path_buffer(save); return false; } @@ -199,7 +199,7 @@ static bool get_file_info(const char* file_name, struct FileInfo* info) { info->type = ty; file_len = strlen(file_name) + 1; - info->name = malloc(file_len); + info->name = xalloc(file_len); memcpy(info->name, file_name, file_len); print_file_size(s.st_size, info->size); @@ -340,7 +340,7 @@ static void push_file( if (*size == *capacity) { *capacity *= 2; - *files = realloc(*files, sizeof(struct FileInfo) * *capacity); + *files = xrealloc(*files, sizeof(struct FileInfo) * *capacity); } user_len = strlen(finfo.usr->pw_name); @@ -382,7 +382,7 @@ static void recurse_directory(char* dir_name) { capacity = 8; size = 0; - files = malloc(sizeof(struct FileInfo) * capacity); + files = xalloc(sizeof(struct FileInfo) * capacity); memset(&info, 0, sizeof(struct FileListInfo)); while((file = readdir(d)) != NULL) { @@ -434,7 +434,7 @@ static void list_directory(char* path) { capacity = 8; size = 0; - files = malloc(sizeof(struct FileInfo) * capacity); + files = xalloc(sizeof(struct FileInfo) * capacity); memset(&info, 0, sizeof(struct FileListInfo)); while ((file = readdir(d)) != NULL) { @@ -466,7 +466,7 @@ static void list_file_args(int start, int argc, char** argv) { capacity = 8; size = 0; - files = malloc(sizeof(struct FileInfo) * capacity); + files = xalloc(sizeof(struct FileInfo) * capacity); memset(&info, 0, sizeof(struct FileListInfo)); for (i = start; i < argc; i++) { diff --git a/command/mkdir.c b/command/mkdir.c index 0d3950d..e6d6268 100644 --- a/command/mkdir.c +++ b/command/mkdir.c @@ -38,7 +38,7 @@ static bool mkdir_parents(char* path) { if (path[i] != '/') continue; path[i] = '\0'; if (mkdir(path, flags.mode) < 0 && errno != EEXIST) { - error_s("failed to create directory '%s': %s", path, strerror(errno)); + error_s("failed to create directory '%s'", path); return false; }; path[i] = '/'; @@ -62,7 +62,7 @@ COMMAND(makedir) { continue; } if (mkdir(argv[i], flags.mode) < 0) { - error_s("failed to create directory '%s': %s", argv[i], strerror(errno)); + error_s("failed to create directory '%s'", argv[i]); } } diff --git a/command/mv.c b/command/mv.c index adce2b7..8f8f0c7 100644 --- a/command/mv.c +++ b/command/mv.c @@ -64,7 +64,7 @@ static void mv_dir(bool exists) { } if (rename(get_path_buffer(), get_path_buffer_2()) < 0) { - error_s("cannot move '%s': %s", get_path_buffer(), strerror(errno)); + error_s("cannot move '%s'", get_path_buffer()); } else if (flags.verbose) { output("moved '%s'", get_path_buffer()); } @@ -91,7 +91,7 @@ COMMAND(mv) { dest = true; if (lstat(get_path_buffer_2(), &s) < 0 && argc - start > 2) { dest = false; - error("cannot stat '%s': %s", get_path_buffer_2(), strerror(errno)); + error("cannot stat '%s'", get_path_buffer_2()); } if (dest && flags.refuse_if_dir) { diff --git a/command/rm.c b/command/rm.c index 81a956a..9834a40 100644 --- a/command/rm.c +++ b/command/rm.c @@ -52,7 +52,7 @@ static bool rm_dir (void) { d = opendir(get_path_buffer()); if (d == NULL) { - error_s("failed to stat '%s': %s\n", get_path_buffer(), strerror(errno)); + error_s("failed to stat '%s'", get_path_buffer()); return false; } @@ -71,7 +71,7 @@ static void rm_file(char* path) { struct stat s; if (lstat(get_path_buffer(), &s) < 0) { pop_path_buffer(save); - error_s("failed to stat '%s': %s\n", get_path_buffer(), strerror(errno)); + error_s("failed to stat '%s'", get_path_buffer()); return; } @@ -102,7 +102,7 @@ static void rm_file(char* path) { } if (remove(get_path_buffer()) < 0) { - error_s("failed to delete '%s': %s\n", get_path_buffer(), strerror(errno)); + error_s("failed to delete '%s'", get_path_buffer()); } else if (flags.verbose) { output("deleted '%s'\n", get_path_buffer()); } diff --git a/command/su.c b/command/su.c new file mode 100644 index 0000000..942f37e --- /dev/null +++ b/command/su.c @@ -0,0 +1,104 @@ +#include "command.h" +#include "lslib.h" + +#include +#include +#include + +static struct { + bool clear_env; + bool update_env; + char* shell; + char* user; +} flags; + +static bool restricted_shell(const char *shell) { + char *line; + int result = true; + + while ((line = getusershell()) != NULL) { + if (strcmp(line, shell) == 0) { + result = false; + break; + } + } + endusershell(); + return result; +} + +static void help (void) { + printf("Usage: su [-lmp] [-s SH] [-] [USER [FILE ARGS]] \n\n"); + printf("Run shell under USER (by default, root)\n\n"); + printf("\t-,-l\tClear environment, go to home dir, run shell as login shell\n"); + printf("\t-p,-m\tDo not set new $HOME, $SHELL, $USER, $LOGNAME\n"); + printf("\t-s SH Shell\tto use instead of user's default\n"); +} + +static int short_arg (char c, char* next) { + switch (c) { + case 'l': + flags.clear_env = true; + break; + case 'p': + case 'm': + flags.update_env = false; + break; + case 's': + check_arg(next); + flags.shell = next; + return ARG_USED; + default: + return ARG_INVALID; + + } + return ARG_UNUSED; +} + +COMMAND (su) { + + int start, res; + uid_t cur_uid; + struct passwd* pw; + + flags.clear_env = false; + flags.update_env = true; + flags.shell = NULL; + flags.user = "root"; + + start = parse_args(argc, argv, help, short_arg, NULL); + + if (start < argc && streql(argv[start], "-")) { + flags.clear_env = true; + start++; + } + + if (start < argc) + flags.user = argv[start++]; + + pw = xgetpwnam(flags.user); + cur_uid = getuid(); + + if (cur_uid != 0) { + res = prompt_password(pw, "Password: "); + } else { + res = PASSWORD_VALID; + } + + if (res != PASSWORD_VALID) { + error("invalid password"); + } + + if (flags.shell && cur_uid != 0 && pw->pw_shell && restricted_shell(pw->pw_shell)) { + error_s("using restricted shell"); + flags.shell = NULL; + } + + if (!flags.shell) + flags.shell = pw->pw_shell; + + change_identity(pw); + setup_environment(flags.shell, flags.update_env, flags.clear_env, pw); + exec_shell(flags.shell, flags.clear_env, (const char**) &argv[start]); + + return EXIT_FAILURE; /* */ +} diff --git a/command/sync.c b/command/sync.c index 797d7a5..89ff86f 100644 --- a/command/sync.c +++ b/command/sync.c @@ -1,12 +1,9 @@ -#include "args.h" #include "command.h" #include "lslib.h" -#define _X_OPEN_SOURCE 500 #include #include #include -#include #include static struct { @@ -58,7 +55,7 @@ static bool sync_file(char* path) { } else { ret = flags.sync_data ? fdatasync(fd) : fsync(fd); if (ret < 0) { - error_s("failed to sync '%s': %s", path, strerror(errno)); + error_s("failed to sync '%s'", path); } } diff --git a/command/tail.c b/command/tail.c index 8137eca..64f4608 100644 --- a/command/tail.c +++ b/command/tail.c @@ -23,10 +23,10 @@ static size_t tail_file_lines(FILE* file, unsigned int count, size_t skip) { size_t len; char* line; - ring = malloc(sizeof(char*) * count); + ring = xalloc(sizeof(char*) * count); memset(ring, 0, sizeof(char*) * count); - ring_len = malloc(sizeof(int) * count); + ring_len = xalloc(sizeof(int) * count); index = 0; size = 0; @@ -74,7 +74,7 @@ static size_t tail_file_chars(FILE* file, unsigned int count, size_t skip) { unsigned int size, i; int read, c; - ring = malloc(sizeof(char) * count); + ring = xalloc(sizeof(char) * count); memset(ring, 0, count); index = 0; diff --git a/command/tee.c b/command/tee.c index 364a13d..b9ff974 100644 --- a/command/tee.c +++ b/command/tee.c @@ -71,7 +71,7 @@ COMMAND(tee_cmd) { return EXIT_SUCCESS; } - files = malloc(sizeof(FILE*) * (argc - start)); + files = xalloc(sizeof(FILE*) * (argc - start)); for (i = start; i < argc; i++) { FILE* file = get_file(argv[i], flags.append ? "a" : "w"); diff --git a/command/xargs.c b/command/xargs.c index 2a41460..47e0f0b 100644 --- a/command/xargs.c +++ b/command/xargs.c @@ -1,7 +1,6 @@ #include "command.h" #include "lslib.h" -#include #include #include #include @@ -76,7 +75,7 @@ char* read_next(FILE* file, int arg_count) { size = 0; capacity = 8; - buf = malloc(sizeof(char) * capacity); + buf = xalloc(sizeof(char) * capacity); while(c = getc(file), true) { if (c == EOF && size == 0) { @@ -86,7 +85,7 @@ char* read_next(FILE* file, int arg_count) { if (size == capacity) { capacity *= 2; - buf = realloc(buf, sizeof(char) * capacity); + buf = xrealloc(buf, sizeof(char) * capacity); } if (c == '\0' || c == EOF || (!flags.null_seperated && c == '\n')) { @@ -104,7 +103,7 @@ void read_args(FILE* file, char*** args, int* size, int* capacity) { while (arg = read_next(file, read), true) { if (*size == *capacity) { *capacity *= 2; - *args = realloc(*args, sizeof(char*) * *capacity); + *args = xrealloc(*args, sizeof(char*) * *capacity); } (*args)[(*size)++] = arg; read++; @@ -146,7 +145,7 @@ COMMAND(xargs) { size = arg_on_stack_count + 1; capacity = size + 8; - args = malloc(sizeof(char*) * capacity); + args = xalloc(sizeof(char*) * capacity); args[0] = command; memcpy(&args[1], &argv[arg_start], arg_on_stack_count * sizeof(char*)); read_args(flags.file, &args, &size, &capacity); @@ -178,7 +177,7 @@ COMMAND(xargs) { } if (execvp(command, args) == -1) { - error("error: failed to execute command: %s", strerror(errno)); + error("failed to execute command"); } cleanup: diff --git a/lib/args.c b/lib/args.c index f907746..5311acf 100644 --- a/lib/args.c +++ b/lib/args.c @@ -1,6 +1,4 @@ -#include "args.h" -#include "error.h" -#include "convert.h" +#include "lslib.h" #include #include diff --git a/lib/args.h b/lib/args.h deleted file mode 100644 index 0b89fca..0000000 --- a/lib/args.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef ARGS_H -#define ARGS_H - -#define UNUSED(x) (void)(x) -#define ARG_UNUSED 0 -#define ARG_USED 1 -#define ARG_IGNORE 2 -#define ARG_INVALID 3 - -void check_arg (char* arg); - -void global_help(void (*help)(void)); - -void parse_help (int argc, char** argv, void (*help)(void)); - -int parse_args (int argc, char** argv, void (*help)(void), int (*short_arg)(char, char*), int (*long_arg)(char*, char*)); - -#endif diff --git a/lib/buffer.c b/lib/buffer.c index 2bee94b..cad286a 100644 --- a/lib/buffer.c +++ b/lib/buffer.c @@ -1,5 +1,4 @@ -#include "buffer.h" -#include "convert.h" +#include "lslib.h" #include #include @@ -58,3 +57,21 @@ void pop_path_buffer_2(int i) { bool is_dot_dir(const char* path) { return streql(path, ".") || streql(path, ".."); } + +const char* get_last_component(const char* path) { + const char* last; + char c; + + last = NULL; + + while (c = *path, true) { + if (c == '\\') { + last = path; + } else if (c == '\0') { + break; + } + path++; + } + + return last; +} diff --git a/lib/buffer.h b/lib/buffer.h deleted file mode 100644 index fd47ee7..0000000 --- a/lib/buffer.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef BUFFER_H -#define BUFFER_H - -#include "def.h" - -char* get_path_buffer(void); -int push_path_buffer(const char* string); -void pop_path_buffer(int i); - -char* get_path_buffer_2(void); -int push_path_buffer_2(const char* string); -void pop_path_buffer_2(int i); - -bool is_dot_dir(const char* path); - -#endif diff --git a/lib/convert.c b/lib/convert.c index a4639c4..c3e011d 100644 --- a/lib/convert.c +++ b/lib/convert.c @@ -1,5 +1,4 @@ -#include "convert.h" -#include "error.h" +#include "lslib.h" #include #include @@ -124,3 +123,10 @@ void print_file_path(char* path) { printf("%s", path); } } + +void nuke_str(char* type) { + *type = 0; + while(*(++type)) { + *type = 0; + } +} diff --git a/lib/convert.h b/lib/convert.h deleted file mode 100644 index f07614b..0000000 --- a/lib/convert.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef CONVERT_H -#define CONVERT_H - -#include "def.h" - -#include -#include - -long int get_number(const char* text); -long int get_blkm(const char* text); -mode_t get_mode(const char* text); - -bool streql(const char* a, const char* b); -bool prefix(const char* pre, const char* str); - -void print_file_size(size_t bytes, char buf[5]); -void print_date_time(time_t mills, char buf[13]); -void print_file_path(char* path); - -#endif diff --git a/lib/def.h b/lib/def.h deleted file mode 100644 index 33a32a0..0000000 --- a/lib/def.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef COLOR_H -#define COLOR_H - -#include - -#define ANSCII "\x1b[" -#define NEXT ";" - -#define RESET "0" -#define BOLD "1" - -#define NORMAL "3" -#define BACKGROUND "4" -#define HIGHLIGHT "9" - -#define BLACK "0" -#define RED "1" -#define GREEN "2" -#define YELLOW "3" -#define BLUE "4" -#define MAGENTA "5" -#define TURQUOISE "6" -#define WHITE "7" - -#define COLOR "m" - -typedef uint8_t bool; -#define true 1 -#define false 0 - -#endif diff --git a/lib/error.c b/lib/error.c index 67828c9..0b55edb 100644 --- a/lib/error.c +++ b/lib/error.c @@ -1,17 +1,29 @@ -#include "error.h" +#include "lslib.h" #include #include #include +#include +#include extern char* cmd; +void die (void) { + exit (EXIT_FAILURE); +} + void error_s(const char *format, ...) { va_list list; va_start(list, format); fprintf(stderr, "%s: ", cmd); vfprintf(stderr, format, list); + + if (errno != 0) { + fprintf(stderr, ": %s", strerror(errno)); + errno = 0; + } + fprintf(stderr, "\n"); } @@ -21,8 +33,15 @@ void error(const char *format, ...) { fprintf(stderr, "%s: ", cmd); vfprintf(stderr, format, list); + + if (errno != 0) { + fprintf(stderr, ": %s", strerror(errno)); + errno = 0; + } + fprintf(stderr, "\n"); - exit(EXIT_FAILURE); + + die(); } void output(const char *format, ...) { diff --git a/lib/error.h b/lib/error.h deleted file mode 100644 index bae532e..0000000 --- a/lib/error.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef ERROR_H -#define ERROR_H - -__attribute__ ((__format__(printf, 1, 2))) -void error_s(const char* format, ...); - -__attribute__ ((__format__(printf, 1, 2))) -void error(const char* format, ...); - -__attribute__ ((__format__(printf, 1, 2))) -void output(const char* format, ...); - -#endif diff --git a/lib/file.c b/lib/file.c index f89b489..4af665d 100644 --- a/lib/file.c +++ b/lib/file.c @@ -1,6 +1,4 @@ -#include "file.h" -#include "error.h" -#include "convert.h" +#include "lslib.h" #include #include @@ -21,7 +19,7 @@ FILE* get_file_s(const char* path, const char* type) { if (lstat(path, &s) < 0) { if (type[0] != 'r') goto read; - error_s("failed to read %s: %s", path, strerror(errno)); + error_s("failed to read %s", path); return NULL; } @@ -35,7 +33,7 @@ read: file = fopen(path, type); if (file == NULL) { - error_s("failed to %s file %s: %s", type[0] == 'r' ? "read" : "write", path, strerror(errno)); + error_s("failed to %s file %s", type[0] == 'r' ? "read" : "write", path); } return file; @@ -48,8 +46,8 @@ FILE* get_file(const char* path, const char* type) { } int get_tty (void) { - int fd = open(_PATH_TTY, O_RDONLY); - if (fd < 0) error("failed to get tty: %s", strerror(errno)); + int fd = open(_PATH_TTY, O_RDONLY | O_NOCTTY | O_SYNC); + if (fd < 0) error("failed to get tty"); return fd; } @@ -57,7 +55,7 @@ FILE* get_tty_stream(char* type) { int fd = get_tty(); FILE* file = fdopen(fd, type); if (file == NULL) { - error("failed to open tty stream: %s", strerror(errno)); + error("failed to open tty stream"); } return file; } diff --git a/lib/file.h b/lib/file.h deleted file mode 100644 index 0bb5939..0000000 --- a/lib/file.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef FILE_H -#define FILE_H - -#include - -FILE* get_file_s(const char* path, const char* type); - -FILE* get_file(const char* path, const char* type); - -int get_tty(void); - -FILE* get_tty_stream(char* type); - -#endif diff --git a/lib/identity.c b/lib/identity.c new file mode 100644 index 0000000..58dcf52 --- /dev/null +++ b/lib/identity.c @@ -0,0 +1,24 @@ +#include "lslib.h" + +#include +#include +#include +#include + +void change_identity(const struct passwd* pw) { + int res; + + res = initgroups(pw->pw_name, pw->pw_gid); + endgrent(); + + if (res != 0) { + if (errno == ENOSYS && pw->pw_uid == getuid()) { + return; + } + + error("can't set groups"); + } + + xsetgid(pw->pw_gid); + xsetuid(pw->pw_uid); +} diff --git a/lib/lslib.h b/lib/lslib.h index dfa1202..7abf7c1 100644 --- a/lib/lslib.h +++ b/lib/lslib.h @@ -3,14 +3,138 @@ #include #include +#include +#include + + +#define ANSCII "\x1b[" +#define NEXT ";" + +#define RESET "0" +#define BOLD "1" + +#define NORMAL "3" +#define BACKGROUND "4" +#define HIGHLIGHT "9" + +#define BLACK "0" +#define RED "1" +#define GREEN "2" +#define YELLOW "3" +#define BLUE "4" +#define MAGENTA "5" +#define TURQUOISE "6" +#define WHITE "7" + +#define COLOR "m" + + +typedef uint8_t bool; +#define true 1 +#define false 0 + + +#define UNUSED(x) (void)(x) +#define ARG_UNUSED 0 +#define ARG_USED 1 +#define ARG_IGNORE 2 +#define ARG_INVALID 3 + +void check_arg (char* arg); +void global_help(void (*help)(void)); +void parse_help (int argc, char** argv, void (*help)(void)); +int parse_args (int argc, char** argv, void (*help)(void), int (*short_arg)(char, char*), int (*long_arg)(char*, char*)); + + +FILE* get_file_s(const char* path, const char* type); +FILE* get_file(const char* path, const char* type); +int get_tty(void); +FILE* get_tty_stream(char* type); +void nuke_str(char* type); + + +char* get_path_buffer(void); +int push_path_buffer(const char* string); +void pop_path_buffer(int i); + +char* get_path_buffer_2(void); +int push_path_buffer_2(const char* string); +void pop_path_buffer_2(int i); + + + +long int get_number(const char* text); +long int get_blkm(const char* text); +mode_t get_mode(const char* text); + +bool streql(const char* a, const char* b); +bool prefix(const char* pre, const char* str); + +void print_file_size(size_t bytes, char buf[5]); +void print_date_time(time_t mills, char buf[13]); +void print_file_path(char* path); +bool is_dot_dir(const char* path); +const char* get_last_component(const char* path); + + +void die (void); + +__attribute__ ((__format__(printf, 1, 2))) +void error_s(const char* format, ...); + +__attribute__ ((__format__(printf, 1, 2))) +void error(const char* format, ...); + +__attribute__ ((__format__(printf, 1, 2))) +void output(const char* format, ...); + + +typedef struct regex_t* re_t; +re_t re_compile(const char* pattern); +int re_matchp(re_t pattern, const char* text, int* matchlength); +int re_match(const char* pattern, const char* text, int* matchlength); + + +struct Stack { + size_t size; + size_t capacity; + void* data; +}; + +void stack_init(struct Stack* stack, size_t size); +void stack_push(struct Stack* stack, void* data, size_t len); +void* stack_pop(struct Stack* stack, size_t len); +void stack_free(struct Stack* stack); + +void stack_push_int(struct Stack* stack, int value); +bool stack_pop_int(struct Stack* stack, int* value); + + +#define DEFAULT_SHELL "/bin/sh" +#define DEFAULT_PATH "/sbin:/usr/sbin:/bin:/usr/bin" + +void setup_environment(const char *shell, bool new_env, bool clear_env, const struct passwd *pw); +void exec_shell(const char *shell, bool loginshell, const char **additional_args); + + +int check_password(const struct passwd *pw, char* plaintext); +int prompt_password(const struct passwd *pw, char* prompt); + + +void change_identity(const struct passwd* pw); + + +void* xalloc(size_t size); +void* xrealloc(void* ptr, size_t size); +void* xzalloc(size_t size); +void xsetenv(const char *name, const char *value); +void xsetuid(uid_t uid); +void xsetgid(gid_t gid); +struct passwd* xgetpwnam(char* name); + +#define PASSWORD_INVALID 0 +#define PASSWORD_VALID 1 +#define PASSWORD_EMPTY 2 -#include "args.h" -#include "buffer.h" -#include "def.h" -#include "convert.h" -#include "error.h" -#include "file.h" -#include "regex.h" -#include "stack.h" #endif diff --git a/lib/password.c b/lib/password.c new file mode 100644 index 0000000..7457878 --- /dev/null +++ b/lib/password.c @@ -0,0 +1,70 @@ +#include "lslib.h" + +#include +#include +#include +#include +#include +#include +#include + +#define SHADOW_BUFSIZE 256 + +static const char* get_passwd(const struct passwd* pw) { + const char *pass; + + if (!pw) + return "aa"; /* "aa" will never match */ + + pass = pw->pw_passwd; + + if ((pass[0] == 'x' || pass[0] == '*') && !pass[1]) { + struct spwd* result; + + errno = 0; + result = getspnam(pw->pw_name); + + if (errno == EACCES) { + errno = 0; + error("binary not properly installed"); + } + + pass = (result == NULL) ? "aa" : result->sp_pwdp; + } + + return pass; +} + +int check_password(const struct passwd *pw, char* plaintext) { + char* encrypted; + char* salt; + char* p; + const char *pw_pass; + int r; + + pw_pass = get_passwd(pw); + if (!pw_pass[0]) { + return PASSWORD_EMPTY; + } + + salt = strdup(pw_pass); + if (salt == NULL) die(); + p = strchr(salt + 1, '$'); + if (p == NULL) die(); + p = strchr(p + 1, '$'); + if (p == NULL) die(); + p[1] = 0; + + encrypted = crypt(plaintext, salt); + r = (strcmp(encrypted, pw_pass) == 0); + + nuke_str(plaintext); + free(salt); + + return r; +} + +int prompt_password(const struct passwd *pw, char* prompt) { + char* plaintext = getpass(prompt); + return check_password(pw, plaintext); +} diff --git a/lib/regex.c b/lib/regex.c index 0e0dc52..cba8a97 100644 --- a/lib/regex.c +++ b/lib/regex.c @@ -29,7 +29,8 @@ -#include "regex.h" +#include "lslib.h" + #include #include diff --git a/lib/regex.h b/lib/regex.h deleted file mode 100644 index d4c61b6..0000000 --- a/lib/regex.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * - * Mini regex-module inspired by Rob Pike's regex code described in: - * - * http://www.cs.princeton.edu/courses/archive/spr09/cos333/beautiful.html - * - * - * - * Supports: - * --------- - * '.' Dot, matches any character - * '^' Start anchor, matches beginning of string - * '$' End anchor, matches end of string - * '*' Asterisk, match zero or more (greedy) - * '+' Plus, match one or more (greedy) - * '?' Question, match zero or one (non-greedy) - * '[abc]' Character class, match if one of {'a', 'b', 'c'} - * '[^abc]' Inverted class, match if NOT one of {'a', 'b', 'c'} -- NOTE: feature is currently broken! - * '[a-zA-Z]' Character ranges, the character set of the ranges { a-z | A-Z } - * '\s' Whitespace, \t \f \r \n \v and spaces - * '\S' Non-whitespace - * '\w' Alphanumeric, [a-zA-Z0-9_] - * '\W' Non-alphanumeric - * '\d' Digits, [0-9] - * '\D' Non-digits - * - * - */ - -#ifndef _TINY_REGEX_C -#define _TINY_REGEX_C - - -#ifndef RE_DOT_MATCHES_NEWLINE -/* Define to 0 if you DON'T want '.' to match '\r' + '\n' */ -#define RE_DOT_MATCHES_NEWLINE 1 -#endif - -/* Typedef'd pointer to get abstract datatype. */ -typedef struct regex_t* re_t; - -/* Compile regex string pattern to a regex_t-array. */ -re_t re_compile(const char* pattern); - - -/* Find matches of the compiled pattern inside text. */ -int re_matchp(re_t pattern, const char* text, int* matchlength); - - -/* Find matches of the txt pattern inside text (will compile automatically first). */ -int re_match(const char* pattern, const char* text, int* matchlength); - - -#endif /* ifndef _TINY_REGEX_C */ diff --git a/lib/shell.c b/lib/shell.c new file mode 100644 index 0000000..9a38b40 --- /dev/null +++ b/lib/shell.c @@ -0,0 +1,59 @@ +#include "lslib.h" + +#include +#include +#include + +void setup_environment(const char *shell, bool new_env, bool clear_env, const struct passwd *pw) { + if (!shell || !shell[0]) + shell = DEFAULT_SHELL; + + if (clear_env) { + const char* term; + term = getenv("TERM"); + clearenv(); + if (term) + xsetenv("TERM", term); + xsetenv("PATH", DEFAULT_PATH); + } + + if (new_env) { + xsetenv("USER", pw->pw_name); + xsetenv("LOGNAME", pw->pw_name); + xsetenv("HOME", pw->pw_dir); + xsetenv("SHELL", shell); + } +} + +void exec_shell(const char *shell, bool loginshell, const char **additional_args) { + + const char** args; + + args = additional_args; + while (args && *args) + args++; + + args = xzalloc(sizeof(args[0]) * (2 + (args - additional_args))); + + if (!shell || !shell[0]) + shell = DEFAULT_SHELL; + + args[0] = get_last_component(shell); + + if (loginshell) { + size_t len = strlen(shell) + 2; + char* arg = xalloc(len); + arg[0] = '-'; + memcpy(&arg[1], shell, len - 1); + args[0] = arg; + } + + if (additional_args) { + int count = 0; + while (*additional_args) + args[++count] = *additional_args++; + } + + execv(shell, (char**) args); + error("cannot execute '%s'", shell); +} diff --git a/lib/stack.c b/lib/stack.c index acffc1a..02226d3 100644 --- a/lib/stack.c +++ b/lib/stack.c @@ -1,4 +1,4 @@ -#include "stack.h" +#include "lslib.h" #include #include @@ -8,14 +8,14 @@ void stack_init(struct Stack* stack, size_t size) { stack->size = 0; stack->capacity = size; - stack->data = malloc(size); + stack->data = xalloc(size); } void stack_push(struct Stack* stack, void* data, size_t len) { size_t new_size = stack->size + len; if (new_size >= stack->capacity) { stack->capacity = new_size * 2; - stack->data = realloc(stack->data, stack->capacity); + stack->data = xrealloc(stack->data, stack->capacity); } memcpy((uint8_t*)stack->data + stack->size, data, len); stack->size += len; diff --git a/lib/stack.h b/lib/stack.h deleted file mode 100644 index 38fb185..0000000 --- a/lib/stack.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef STACK_H -#define STACK_H - -#include "def.h" - -#include - -struct Stack { - size_t size; - size_t capacity; - void* data; -}; - -void stack_init(struct Stack* stack, size_t size); -void stack_push(struct Stack* stack, void* data, size_t len); -void* stack_pop(struct Stack* stack, size_t len); -void stack_free(struct Stack* stack); - -void stack_push_int(struct Stack* stack, int value); -bool stack_pop_int(struct Stack* stack, int* value); - -#endif diff --git a/lib/xfuncs.c b/lib/xfuncs.c new file mode 100644 index 0000000..43242de --- /dev/null +++ b/lib/xfuncs.c @@ -0,0 +1,49 @@ +#include "lslib.h" + +#include +#include +#include +#include + +void* xalloc(size_t size) { + void *ptr = malloc(size); + if (ptr == NULL && size != 0) die(); + return ptr; +} + +void* xrealloc(void* ptr, size_t size) { + ptr = realloc(ptr, size); + if (ptr == NULL && size != 0) die(); + return ptr; +} + +void* xzalloc(size_t size) { + void* ptr = xalloc(size); + memset(ptr, 0, size); + return ptr; +} + +void xsetenv(const char *name, const char *value) { + if (setenv(name, value, 1)) + error("cannot set env"); +} + +void xsetuid(uid_t uid) { + if (setuid(uid)) + error("cannot set uid"); +} + +void xsetgid(gid_t gid) { + if (setgid(gid)) + error("cannot set gid"); +} + +struct passwd* xgetpwnam(char* name) { + struct passwd* pw; + pw = getpwnam(name); + + if (!pw) + error("cannot get user: '%s'", name); + + return pw; +} diff --git a/readme.md b/readme.md index 3e34252..2212dd2 100644 --- a/readme.md +++ b/readme.md @@ -5,7 +5,7 @@ A terrible busybox/gnu coreutils clone. Currently the only supported commands are: `dd`, `cat`, `yes`, `echo`, `printf`, `id`, `groups`, `ls`, `tail`, `head`, `ed`, `tee`, `true`, `false`, `tee`, `whoami`, -`wc`, `xargs`, `tac`, `rm`, `cp`, `mkdir`, `mv`, `grep`, `chown`, `chmod`, `sync` +`wc`, `xargs`, `tac`, `rm`, `cp`, `mkdir`, `mv`, `grep`, `chown`, `chmod`, `sync`, `su` ## How to diff --git a/src/command.h b/src/command.h index 7827174..3a84784 100644 --- a/src/command.h +++ b/src/command.h @@ -29,5 +29,6 @@ COMMAND(grep); COMMAND(chown_cmd); COMMAND(chmod_cmd); COMMAND(sync_cmd); +COMMAND(su); #endif diff --git a/src/main.c b/src/main.c index 1897f5c..7db2135 100644 --- a/src/main.c +++ b/src/main.c @@ -1,5 +1,4 @@ #include "command.h" -#include "convert.h" #include "lslib.h" #include @@ -23,7 +22,7 @@ int main (ARGUMENTS) { if (argc < 2) { printf("usage: lazysphere [function [arguments]...]\n\n"); printf("currently defined functions:\n"); - printf("\tdd, cat, yes, echo, printf, id, groups, ls, tail, head, ed, tee, true, false, tee, whoami, wc, xargs, tac, rm, cp, mkdir, mv, grep, chown, chmod, sync\n"); + printf("\tdd, cat, yes, echo, printf, id, groups, ls, tail, head, ed, tee, true, false, tee, whoami, wc, xargs, tac, rm, cp, mkdir, mv, grep, chown, chmod, sync, su\n"); return EXIT_SUCCESS; } argc--; @@ -91,6 +90,8 @@ int main (ARGUMENTS) { return chmod_cmd(NEXT_ARGS); } else if (streql(cmd, "sync")) { return sync_cmd(NEXT_ARGS); + } else if (streql(cmd, "su")) { + return su(NEXT_ARGS); } else { fprintf(stderr, "lazysphere: invalid command %s\n", cmd); return EXIT_FAILURE;