tee, whoami, wc
This commit is contained in:
parent
5aff541fd7
commit
317f7bf357
7 changed files with 277 additions and 3 deletions
|
@ -4,7 +4,7 @@
|
|||
A terrible busybox/gnu coreutils clone.
|
||||
|
||||
Currently the only supported commands are:
|
||||
`dd`, `cat`, `yes`, `echo`, `printf`, `id`, `groups`, `ls`, `tail`, `head`, `ed`
|
||||
`dd`, `cat`, `yes`, `echo`, `printf`, `id`, `groups`, `ls`, `tail`, `head`, `ed`, `tee`, `true`, `false`, `tee`, `whoami`, `wc`
|
||||
|
||||
## How to
|
||||
|
||||
|
|
|
@ -20,3 +20,6 @@ COMMAND(ls);
|
|||
COMMAND(tail);
|
||||
COMMAND(head);
|
||||
COMMAND(ed);
|
||||
COMMAND(tee);
|
||||
COMMAND(whoami);
|
||||
COMMAND(wc);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
COMMAND_EMPTY(user_id) {
|
||||
|
||||
|
|
75
src/commands/tee.c
Normal file
75
src/commands/tee.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
#include "../command.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static void help() {
|
||||
printf("Usage: tee [-ai] [FILE]...\n\n");
|
||||
printf("Copy stdin to each FILE, and also to stdout\n\n");
|
||||
printf("\t-a Append to the given FILEs, don't overwrite\n");
|
||||
printf("\t-i Ignore interrupt signals (SIGINT)\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
static void handle(){}
|
||||
|
||||
static void run_tee(int file_count, FILE* files[file_count]) {
|
||||
char c;
|
||||
while((c = getchar()) != EOF) {
|
||||
for (int i = 0; i < file_count; i++) {
|
||||
fwrite(&c, 1, 1, files[i]);
|
||||
fflush(files[i]);
|
||||
}
|
||||
putchar(c);
|
||||
}
|
||||
for (int i = 0; i < file_count; i++) {
|
||||
fclose(files[i]);
|
||||
}
|
||||
}
|
||||
|
||||
COMMAND(tee) {
|
||||
|
||||
bool append = false;
|
||||
bool handle_sigint = false;
|
||||
|
||||
int start = 0;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (!prefix("-", argv[i])) break;
|
||||
if (streql("--help", argv[i])) help();
|
||||
|
||||
start++;
|
||||
for (size_t j = 1; j < strlen(argv[i]); j++) {
|
||||
char o = argv[i][j];
|
||||
switch (o) {
|
||||
case 'a':
|
||||
append = true;
|
||||
break;
|
||||
case 'i':
|
||||
handle_sigint = true;
|
||||
break;
|
||||
default:
|
||||
error("error: unkown option: %c", o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (handle_sigint) {
|
||||
signal(SIGINT, handle);
|
||||
}
|
||||
|
||||
if (argc - start < 1) {
|
||||
run_tee(0, NULL);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
FILE* files[argc - start];
|
||||
for (int i = start; i < argc; i++) {
|
||||
FILE* file = get_file(argv[i], append ? "a" : "w");
|
||||
files[i - start] = file;
|
||||
}
|
||||
|
||||
run_tee(argc - start, files);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
161
src/commands/wc.c
Normal file
161
src/commands/wc.c
Normal file
|
@ -0,0 +1,161 @@
|
|||
#include "../command.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
struct Flags {
|
||||
bool newlines;
|
||||
bool words;
|
||||
bool characters;
|
||||
bool bytes;
|
||||
bool longest_line;
|
||||
};
|
||||
|
||||
static int lines = 0;
|
||||
static int words = 0;
|
||||
static int chars = 0;
|
||||
static int bytes = 0;
|
||||
static int logst = 0;
|
||||
|
||||
static void list(int l, int w, int c, int b, int lg, struct Flags* flags) {
|
||||
if (flags->newlines) {
|
||||
printf("\t%d", l);
|
||||
}
|
||||
if (flags->words) {
|
||||
printf("\t%d", w);
|
||||
}
|
||||
if (flags->characters) {
|
||||
printf("\t%d", c);
|
||||
}
|
||||
if (flags->bytes) {
|
||||
printf("\t%d", b);
|
||||
}
|
||||
if (flags->longest_line) {
|
||||
printf("\t%d", lg);
|
||||
}
|
||||
}
|
||||
|
||||
#define BS 1024
|
||||
|
||||
static bool is_delimiter(char c) {
|
||||
return c == ' ' || c == '\t' || c == '\n';
|
||||
}
|
||||
|
||||
static void run_wc(FILE* file, struct Flags* flags) {
|
||||
int l = 0, w = 0, c = 0, b = 0, lg = 0;
|
||||
|
||||
bool in_word = false;
|
||||
int current_length = 0;
|
||||
|
||||
int read;
|
||||
char buf[BS];
|
||||
while ((read = fread(buf, 1, 1024, file)) > 0) {
|
||||
for (int i = 0; i < read; i++) {
|
||||
char ch = buf[i];
|
||||
b++;
|
||||
if (ch == '\n') {
|
||||
l++;
|
||||
lg = lg > current_length ? lg : current_length;
|
||||
current_length = 0;
|
||||
} else {
|
||||
current_length++;
|
||||
}
|
||||
if (isprint(ch) || is_delimiter(ch)) c++;
|
||||
if (in_word && is_delimiter(ch)) {
|
||||
in_word = false;
|
||||
w++;
|
||||
} else if (!in_word && !is_delimiter(ch) && isprint(ch)) {
|
||||
in_word = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (in_word) w++;
|
||||
lg = lg > current_length ? lg : current_length;
|
||||
list(l, w, c, b, lg, flags);
|
||||
lines += l;
|
||||
words += w;
|
||||
chars += c;
|
||||
bytes += b;
|
||||
logst += lg;
|
||||
if (file != stdin)
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
static void help() {
|
||||
printf("Usage: wc [-cmlwL] [FILE]...\n\n");
|
||||
printf("Count lines, words, and bytes for FILEs (or stdin)\n\n");
|
||||
printf("\t-c Count bytes\n");
|
||||
printf("\t-m Count characters\n");
|
||||
printf("\t-l Count newlines\n");
|
||||
printf("\t-w Count words\n");
|
||||
printf("\t-L Print longest line length\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
COMMAND(wc) {
|
||||
struct Flags flags;
|
||||
flags.newlines = false;
|
||||
flags.words = false;
|
||||
flags.characters = false;
|
||||
flags.bytes = false;
|
||||
flags.longest_line = false;
|
||||
|
||||
bool has_flags = false;
|
||||
|
||||
int start = 0;
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (!prefix("-", argv[i])) break;
|
||||
if (streql("--help", argv[i])) help();
|
||||
|
||||
start++;
|
||||
for (size_t j = 1; j < strlen(argv[i]); j++) {
|
||||
char c = argv[i][j];
|
||||
switch (c) {
|
||||
case 'c':
|
||||
flags.bytes = true;
|
||||
break;
|
||||
case 'm':
|
||||
flags.characters = true;
|
||||
break;
|
||||
case 'l':
|
||||
flags.newlines = true;
|
||||
break;
|
||||
case 'w':
|
||||
flags.words = true;
|
||||
break;
|
||||
case 'L':
|
||||
flags.longest_line = true;
|
||||
break;
|
||||
default:
|
||||
error("error: invald option -%c", c);
|
||||
}
|
||||
has_flags = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_flags) {
|
||||
flags.newlines = true;
|
||||
flags.words = true;
|
||||
flags.characters = true;
|
||||
}
|
||||
|
||||
if (argc - start < 1) {
|
||||
run_wc(stdin, &flags);
|
||||
printf("\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
for (int i = start; i < argc; i++) {
|
||||
FILE* file = get_file(argv[i], "r");
|
||||
run_wc(file, &flags);
|
||||
printf("\t%s\n", argv[i]);
|
||||
}
|
||||
|
||||
if (argc - start > 1) {
|
||||
list(lines, words, chars, bytes, logst, &flags);
|
||||
printf("\ttotal\n");
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
24
src/commands/whoami.c
Normal file
24
src/commands/whoami.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
#include "../command.h"
|
||||
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void help() {
|
||||
printf("Usage: whoami\n\n");
|
||||
printf("Print the username associated with the current effective user id\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
COMMAND(whoami) {
|
||||
if (argc > 0 && streql("--help", argv[0])) help();
|
||||
|
||||
uid_t usr = getuid();
|
||||
struct passwd* passwd = getpwuid(usr);
|
||||
if (passwd == NULL) {
|
||||
printf("\x1b[1;91myou do not exist.\n");
|
||||
} else {
|
||||
printf("%s\n", passwd->pw_name);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
14
src/main.c
14
src/main.c
|
@ -20,7 +20,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\n");
|
||||
printf("\tdd, cat, yes, echo, printf, id, groups, ls, tail, head, ed, tee, true, false, tee, whoami, wc\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
argc--;
|
||||
|
@ -48,7 +48,7 @@ int main (ARGUMENTS) {
|
|||
return groups();
|
||||
} else if (streql(cmd, "id")) {
|
||||
return user_id();
|
||||
} else if (streql(cmd, "ls")) {
|
||||
} else if (streql(cmd, "ls") || streql(cmd, "dir")) {
|
||||
return ls(NEXT_ARGS);
|
||||
} else if (streql(cmd, "tail")) {
|
||||
return tail(NEXT_ARGS);
|
||||
|
@ -56,6 +56,16 @@ int main (ARGUMENTS) {
|
|||
return head(NEXT_ARGS);
|
||||
} else if (streql(cmd, "ed")) {
|
||||
return ed(NEXT_ARGS);
|
||||
} else if (streql(cmd, "tee")) {
|
||||
return tee(NEXT_ARGS);
|
||||
} else if (streql(cmd, "true")) {
|
||||
return EXIT_SUCCESS;
|
||||
} else if (streql(cmd, "false")) {
|
||||
return EXIT_FAILURE;
|
||||
} else if (streql(cmd, "whoami")) {
|
||||
return whoami(NEXT_ARGS);
|
||||
} else if (streql(cmd, "wc")) {
|
||||
return wc(NEXT_ARGS);
|
||||
} else {
|
||||
error("error: invalid command %s", cmd);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue