From 5e45486debf9867f57ba6a8818eaadde9d3e8991 Mon Sep 17 00:00:00 2001 From: Gitea Date: Tue, 11 Feb 2020 23:30:50 -0600 Subject: [PATCH] Initial version of utils up to 2020-02-11 --- README | 0 asa.c | 45 ++++++++++++++ cat.c | 35 +++++++++++ cksum.c | 123 +++++++++++++++++++++++++++++++++++++ cmp.c | 118 ++++++++++++++++++++++++++++++++++++ dc.c | 6 ++ echo.c | 77 +++++++++++++++++++++++ expand.c | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fenver.c | 7 +++ head.c | 89 +++++++++++++++++++++++++++ ln.c | 117 +++++++++++++++++++++++++++++++++++ pwd.c | 31 ++++++++++ sh.c | 128 +++++++++++++++++++++++++++++++++++++++ tty.c | 14 +++++ wc.c | 141 +++++++++++++++++++++++++++++++++++++++++++ 15 files changed, 1112 insertions(+) create mode 100755 README create mode 100755 asa.c create mode 100755 cat.c create mode 100755 cksum.c create mode 100755 cmp.c create mode 100755 dc.c create mode 100755 echo.c create mode 100755 expand.c create mode 100755 fenver.c create mode 100755 head.c create mode 100755 ln.c create mode 100755 pwd.c create mode 100755 sh.c create mode 100755 tty.c create mode 100755 wc.c diff --git a/README b/README new file mode 100755 index 0000000..e69de29 diff --git a/asa.c b/asa.c new file mode 100755 index 0000000..7a0072b --- /dev/null +++ b/asa.c @@ -0,0 +1,45 @@ +#include +#include + +int main(int argc, char ** argv) { + FILE *in_file; + int i, error = 0, eof_reached = 0; + char c, c_temp; + + for(i = 1; i < argc; i++) { + if(argv[i][0] == '-' && argv[i][1] == '\0') + in_file = stdin; + else { + in_file = fopen(argv[i], "r"); + if(in_file == NULL) { + fprintf(stderr, "Cannot find file %s\n", argv[i]); + error = 1; + continue; + } + } + eof_reached = 0; + while(!eof_reached) { + c = fgetc(in_file); + switch(c) { + case '1': printf("\f"); break; + case '0': printf("\n"); break; + case '+': printf("\r"); break; + case EOF: eof_reached = 1; continue; + } + for(c_temp = fgetc(in_file); c_temp != '\n'; c_temp = fgetc(in_file)) { + if(c_temp == EOF) { + eof_reached = 1; + break; + } + else + printf("%c", c_temp); + } + } + printf("\n"); + } + + if(error) + return 1; + else + return 0; +} diff --git a/cat.c b/cat.c new file mode 100755 index 0000000..dfbc980 --- /dev/null +++ b/cat.c @@ -0,0 +1,35 @@ +#include +#include + +int main(int argc, char *argv[]) { + FILE * in_file; + int i, error = 0; + char c; + + if(argc == 1) { + in_file = stdin; + for(c = fgetc(in_file); c != EOF; c = fgetc(in_file)) { + fprintf(stdout, "%c", c); + } + } + + for(i = 1; i < argc; i++) { + if(argv[i][0] == '-' && argv[i][1] == '\0') + in_file = stdin; + else { + in_file = fopen(argv[i], "r"); + if(in_file == NULL) { + fprintf(stderr, "Cannot find file %s\n", argv[i]); + error = 1; + continue; + } + } + for(c = fgetc(in_file); c != EOF; c = fgetc(in_file)) + fprintf(stdout, "%c", c); + } + + if(error) + return 1; + else + return 0; +} diff --git a/cksum.c b/cksum.c new file mode 100755 index 0000000..edee16f --- /dev/null +++ b/cksum.c @@ -0,0 +1,123 @@ +#include +#include + +unsigned int crc32(FILE * in_file); +int count_octets(FILE * in_file); + +unsigned int crc32_table[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; + + +int main(int argc, char ** argv) { + int i, error = 0; + FILE *in_file; + + for(i = 1; i < argc; i++) { + in_file = fopen(argv[i], "r"); + if(in_file == NULL) { + error = 1; + fprintf(stderr, "Cannot find file %s\n", argv[i]); + } + else + printf("%u %d %s\n", crc32(current_file), count_octets(current_file), + argv[i]); + } + + if(error) + return 1; + else + return 0; +} + +//Based off CRC-32 on the Wikipedia article for CRC +unsigned int crc32(FILE * in_file) { + unsigned int crc = 0xffffffff; + int nLookupIndex; + char c; + + fseek(in_file, 0, SEEK_SET); + + for(c = fgetc(in_file); c != EOF; c = fgetc(in_file)) { + nLookupIndex = (crc ^ c) & 0xff; + crc = (crc >> 8) ^ crc32_table[nLookupIndex]; + } + + crc ^= 0xffffffff; + return crc; +} + +int count_octets(FILE * in_file) { + int total_octets = 0; + char c; + + fseek(in_file, 0, SEEK_SET); + + for(c = fgetc(in_file); c != EOF; c = fgetc(in_file)) + total_octets++; + + return total_octets; +} diff --git a/cmp.c b/cmp.c new file mode 100755 index 0000000..e477566 --- /dev/null +++ b/cmp.c @@ -0,0 +1,118 @@ +#include +#include +#include + +int main(int argc, char ** argv) { + int silent_mode = 0; + int print_all_diff = 0; + int keep_printing = 1; + int files_differ = 0; + int i, f1num = 1; + FILE *file1, *file2; + char c1, c2; + int line = 1, byte = 1; + + if(argv[1][0] == '-' && argv[1][1] == 's' && argv[1][2] == '\0') { + silent_mode = 1; + f1num++; + if(argv[2][0] == '-' && argv[2][1] == 'l' && + argv[2][2] == '\0') { + f1num++; + } + } + else if(argv[1][0] == '-' && argv[1][1] == 'l' && + argv[1][2] == '\0') { + print_all_diff = 1; + f1num++; + if(argv[2][0] == '-' && argv[2][1] == 's' && + argv[2][2] == '\0') { + f1num++; + } + } + + if(strcmp(argv[f1num], "-") == 0 && strcmp(argv[f1num+1], "-") == 0) { + fprintf(stderr, "%s: Cannot accept stdin for both files\n", argv[0]); + return 2; + } + else if(strcmp(argv[f1num], "-") == 0) { + file1 = stdin; + file2 = fopen(argv[f1num+1], "r"); + } + else if(strcmp(argv[f1num+1], "-") == 0) { + file1 = fopen(argv[f1num], "r"); + file2 = stdin; + } + else { + file1 = fopen(argv[f1num], "r"); + file2 = fopen(argv[f1num+1], "r"); + } + + if(silent_mode) { + c1 = fgetc(file1); + c2 = fgetc(file2); + for(i = 0; !(c1 == EOF || c2 == EOF); i++) { + if(c1 != c2) { + return 1; + } + c1 = fgetc(file1); + c2 = fgetc(file2); + } + if(c1 != c2) { + return 1; + } + else { + return 0; + } + } + else if(print_all_diff) { + c1 = fgetc(file1); + c2 = fgetc(file2); + for(i = 0; !(c1 == EOF || c2 == EOF); i++) { + if(c1 != c2) { + printf("%d %o %o\n", byte, c1, c2); + files_differ = 1; + } + c1 = fgetc(file1); + c2 = fgetc(file2); + line++; + byte++; + } + if(c1 != c2) { + fprintf(stderr, "%s: EOF on %s%s\n", argv[0], + c1 == EOF ? argv[f1num] : argv[f1num+1], ""); + return 1; + } + else if(files_differ) { + return 1; + } + else { + return 0; + } + } + else { + c1 = fgetc(file1); + c2 = fgetc(file2); + for(i = 0; !(c1 == EOF || c2 == EOF); i++) { + if(c1 != c2 && keep_printing) { + keep_printing = 0; + printf("%s %s differ: char %d, line %d\n", argv[f1num], argv[f1num+1], byte, line); + files_differ = 1; + } + c1 = fgetc(file1); + c2 = fgetc(file2); + if(c1 == '\n') line++; + byte++; + } + if(c1 != c2) { + fprintf(stderr, "%s: EOF on %s%s\n", argv[0], + c1 == EOF ? argv[f1num] : argv[f1num+1], ""); + return 1; + } + else if(files_differ) { + return 1; + } + else { + return 0; + } + } +} diff --git a/dc.c b/dc.c new file mode 100755 index 0000000..f8605e1 --- /dev/null +++ b/dc.c @@ -0,0 +1,6 @@ +#include +#include + +int main(void) { + +} diff --git a/echo.c b/echo.c new file mode 100755 index 0000000..3225bf9 --- /dev/null +++ b/echo.c @@ -0,0 +1,77 @@ +#include + +int ctoi(char c); + +int main(int argc, char ** argv) { + int i, j, oct_temp; + char char_temp; + int trailing_newline = 1; //1 if true, 0 if \c present + + for(i = 1; i < argc; i++) { + for(j = 0; argv[i][j] != '\0'; j++) { + if(argv[i][j] == '\\') { + j++; + switch(argv[i][j]) { + case 'a': printf("\a"); break; + case 'b': printf("\b"); break; + case 'c': trailing_newline = 0; break; + case 'f': printf("\f"); break; + case 'n': printf("\n"); break; + case 'r': printf("\r"); break; + case 't': printf("\t"); break; + case 'v': printf("\v"); break; + case '\\': printf("\\"); break; + case '0': { + j++; + oct_temp = ctoi(argv[i][j]); + j++; + if(ctoi(argv[i][j] != -1)) { + oct_temp *= 8; + oct_temp += ctoi(argv[i][j]); + j++; + if(ctoi(argv[i][j] != -1)) { + oct_temp *= 8; + oct_temp += ctoi(argv[i][j]); + } + else { + j--; + } + } + else { + j--; + } + printf("%c", (char)oct_temp); + } + break; + default: printf("\\%c", argv[i][j]); + break; + } + } + else { + printf("%c", argv[i][j]); + } + } + } + + if(trailing_newline) { + printf("\n"); + } + + return 0; +} + +int ctoi(char c) { + switch(c) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + default: return -1; + } +} diff --git a/expand.c b/expand.c new file mode 100755 index 0000000..b4a54ba --- /dev/null +++ b/expand.c @@ -0,0 +1,181 @@ +#include +#include +#include + +int is_integer(char * str); +int is_comma_list(char * str); +int * comma_list_stops(char * str); +int comma_list_num_stops(char * str); +int stoi_mini(char * str); + +int main(int argc, char ** argv) { + int *tab_stops; + int col_pos, num_tab_stops = 0, cur_stop; + FILE *current_file; + int i = 1, j; char c; + int all_good = 1; + + if(argv[1][0] == '-' && argv[1][1] == 't' && argv[1][2] == '\0') { + i++; + j = 2; + if(is_comma_list(argv[j])) { + num_tab_stops = comma_list_num_stops(argv[j]); + tab_stops = comma_list_stops(argv[j]); + i++; + } + else { + while(is_integer(argv[j]) && j < (argc - 1)) { + num_tab_stops++; + i++; + j++; + } + + tab_stops = calloc(num_tab_stops, sizeof(*tab_stops)); + + for(j = 2; j < num_tab_stops + 2; j++) { + tab_stops[j-2] = stoi_mini(argv[j]); + } + } + } + else if(argv[1][0] == '-' && argv[1][1] == 't' && + argv[1][2] <= '9' && argv[1][2] >= '0'){ + char * str = strtok(argv[1], "t"); + str = strtok(NULL, "\0"); + num_tab_stops = comma_list_num_stops(str); + tab_stops = comma_list_stops(str); + i++; + } + else { + tab_stops = malloc(sizeof(*tab_stops)); + *tab_stops = 8; + num_tab_stops = 1; + } + + for(i = i; i < argc; i++) { + current_file = fopen(argv[i], "r"); + if(current_file == NULL) { + fprintf(stderr, "%s: %s: No such file or directory\n", argv[0], argv[i]); + all_good = 0; + } + else { + cur_stop = 0; col_pos = 0; + for(c = fgetc(current_file); c != EOF; c = fgetc(current_file)) { + if(c == '\t') { + if(num_tab_stops == 1) { + cur_stop++; + printf(" "); col_pos++; + while(col_pos % *tab_stops != 0) { + printf(" "); col_pos++; + } + } + else { + if(cur_stop >= num_tab_stops) { + printf(" "); + col_pos++; + cur_stop++; + } + else { + printf(" "); col_pos++; + while(col_pos % tab_stops[cur_stop] != 0) { + printf(" "); col_pos++; + } + cur_stop++; + } + } + } + else if(c == '\n') { + printf("%c", c); + col_pos = 0; + cur_stop = 0; + } + else { + printf("%c", c); + col_pos++; + } + } + fclose(current_file); + } + } +} + +int is_integer(char * str) { + int i = 0; + + while(str[i] != '\0' && str[i] != ',') { + if(str[i] > 57 || str[i] < 48) { + return 0; + } + i++; + } + + return 1; +} + +int is_comma_list(char * str) { + int i = 0, has_comma = 0; + + while(str[i] != '\0') { + if((str[i] > 57 || str[i] < 48) && str[i] != ',') { + return 0; + } + if(str[i] == ',') { + has_comma = 1; + } + i++; + } + + return has_comma; +} + +int stoi_mini(char * str) { + int i, str_int = 0; + + for(i = 0; str[i] != '\0' && str[i] != ','; i++) { + str_int *= 10; + switch(str[i]) { + case '0': str_int += 0; break; + case '1': str_int += 1; break; + case '2': str_int += 2; break; + case '3': str_int += 3; break; + case '4': str_int += 4; break; + case '5': str_int += 5; break; + case '6': str_int += 6; break; + case '7': str_int += 7; break; + case '8': str_int += 8; break; + case '9': str_int += 9; break; + default: return -1; + } + } + + return str_int; +} + +int comma_list_num_stops(char * str) { + int num_stops = 0; + + for(int i = 0; str[i] != '\0'; i++) { + if(str[i] == ',') { + num_stops++; + } + } + + return num_stops; +} + +int * comma_list_stops(char * str) { + int * tab_stops; + int num_stops = comma_list_num_stops(str), i; + + tab_stops = calloc(num_stops, sizeof(*tab_stops)); + + char * stop = strtok(str, ","); + i = 0; + + while(stop != NULL && i < num_stops) { + tab_stops[i] = stoi_mini(stop); + i++; + stop = strtok(NULL, ","); + } + + return tab_stops; +} diff --git a/fenver.c b/fenver.c new file mode 100755 index 0000000..93dbe25 --- /dev/null +++ b/fenver.c @@ -0,0 +1,7 @@ +#include + +/* TODO: Make this check the kernel for version instead */ +int main(void) { + printf("FENIX PRE_REL 20190903\n"); + return 0; +} diff --git a/head.c b/head.c new file mode 100755 index 0000000..08b5fa3 --- /dev/null +++ b/head.c @@ -0,0 +1,89 @@ +#include +#include +#include + +int stoi_mini(char * str); + +int main(int argc, char *argv[]) { + FILE * current_input_file; + int i = 1, j = 0; char c; + + int chars_copy = 10; + int print_head = 0; + + int error_occurred; + + + if(argv[i][0] == '-') { + if(argv[i][1] == 'n') { + i++; + chars_copy = stoi_mini(argv[i]); + i++; + } + } + + if(argc - i > 1) { + print_head = 1; + } + + for(i; i < argc; i++) { + if(argv[i][0] == '-' && argv[i][1] == '\0') { + current_input_file = stdin; + } + else { + current_input_file = fopen(argv[i], "r"); + if(current_input_file == NULL) { + fprintf(stderr, "%s: %s: No such file or directory\n", + argv[0], argv[i]); + error_occurred = 1; + } + } + if(print_head) { + printf("\n==> %s <==\n", argv[i]); + } + j = 0; + c = ' '; + while(c != EOF && j < chars_copy) { + c = fgetc(current_input_file); + if(c == '\n') { + j++; + } + if(c != EOF) { + fprintf(stdout, "%c", c); + } + } + if(current_input_file != stdin) { + fclose(current_input_file); + } + } + + if(error_occurred) { + return 1; + } + else { + return 0; + } +} + +int stoi_mini(char * str) { + int i, str_int = 0; + + for(i = 0; str[i] != '\0' && str[i] != ','; i++) { + str_int *= 10; + switch(str[i]) { + case '0': str_int += 0; break; + case '1': str_int += 1; break; + case '2': str_int += 2; break; + case '3': str_int += 3; break; + case '4': str_int += 4; break; + case '5': str_int += 5; break; + case '6': str_int += 6; break; + case '7': str_int += 7; break; + case '8': str_int += 8; break; + case '9': str_int += 9; break; + default: return -1; + } + } + + return str_int; +} diff --git a/ln.c b/ln.c new file mode 100755 index 0000000..15b7767 --- /dev/null +++ b/ln.c @@ -0,0 +1,117 @@ +#include +#include +#include +#include +#include +#include +#include + +int link_file(char *, char *); + +int force = 0; /* -f flag */ +int do_symlink = 0; /* -s flag */ +int follow_link = 0; /* -L/-P flag */ + +int main(int argc, char * argv[]) { + int file_start = 1; + int source_count = 0; + char * path_dir; + char * ln_name; + + if(argc < 3) { + fprintf(stderr, "%s: missing file operand\n", argv[0]); + exit(1); + } + + if(strcmp(argv[file_start], "-L") == 0) { + follow_link = AT_SYMLINK_FOLLOW; + file_start++; + } + else if(strcmp(argv[file_start], "-P") == 0) { + follow_link = 0; + file_start++; + } + + if(strcmp(argv[file_start], "-f") == 0) { + force = 1; + file_start++; + } + else if(strcmp(argv[file_start], "-s") == 0) { + do_symlink = 1; + file_start++; + } + else if(strcmp(argv[file_start], "-fs") == 0 + || strcmp(argv[file_start], "-sf") == 0) { + force = 1; + do_symlink = 1; + file_start++; + } + + if(strcmp(argv[file_start], "-L") == 0) { + follow_link = AT_SYMLINK_FOLLOW; + file_start++; + } + else if(strcmp(argv[file_start], "-P") == 0) { + follow_link = 0; + file_start++; + } + + if((argc - file_start) < 2) { + fprintf(stderr, "%s: missing file operand\n", argv[0]); + exit(1); + } + + source_count = argc - (file_start + 1); + + if(source_count == 1) { + int ret = link_file(argv[file_start], argv[file_start+1]); + if(ret == 1) { + fprintf(stderr, "%s: failed to create link '%s': File exists\n", + argv[0], argv[file_start + 1]); + exit(1); + } + return 0; + } + else { + path_dir = argv[argc - 1]; + for(int i = file_start; i < (argc - 1); i++) { + int length = strlen(path_dir); + length += strlen(argv[i]); + ln_name = calloc(length + 2, sizeof(*ln_name)); + strcpy(ln_name, path_dir); + strcat(ln_name, "/"); + strcat(ln_name, argv[i]); + int ret = link_file(argv[i], ln_name); + if(ret == 1) { + fprintf(stderr, "%s: failed to create link '%s': File exists\n", + argv[0], ln_name); + exit(1); + } + free(ln_name); + } + } +} + +int link_file(char * source, char * dest) { + struct stat buf; + lstat(source, &buf); + if(strcmp(source, dest) == 0 && !force) { + return 1; + } + else if(access(dest, F_OK) != -1 && !force) { + return 1; + } + else if(access(dest, F_OK) != -1 && force) { + unlink(dest); + } + + if(do_symlink) { + return symlink(source, dest); + } + else if(S_ISLNK(buf.st_mode)) { + return linkat(AT_FDCWD, source, AT_FDCWD, dest, follow_link); + } + else { + return link(source, dest); + } +} diff --git a/pwd.c b/pwd.c new file mode 100755 index 0000000..162b1f6 --- /dev/null +++ b/pwd.c @@ -0,0 +1,31 @@ +#include +#include +#include + +int main(int argc, char * argv[]) { + int mode = 01; /* 01: print PWD -L, 02: print physical path -P */ + + if(argc > 1) { + for(int i = 1; i < argc; i++) { + if(argv[i][1] == 'L' && argv[i][2] == '\0') { + mode = 01; + } + else if(argv[i][1] == 'P' && argv[i][2] == '\0') { + mode = 02; + } + else { + fprintf(stderr, "%s: invalid option: %s\n", argv[0], argv[i]); + exit(1); + } + } + } + + if(mode == 01) { + printf("%s\n", getenv("PWD")); + } + else { + printf("%s\n", getcwd(NULL, 0)); + } + + return 0; +} diff --git a/sh.c b/sh.c new file mode 100755 index 0000000..0791282 --- /dev/null +++ b/sh.c @@ -0,0 +1,128 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define ARG_SEP " " //Argument separator for commands +#define PROMPT " $ " + +char** create_argv(char* command); +int get_argc(char* command); +char* prompt(); +int cd(char* path); + +int main() { + char** argv; //The command with arguments + char* user_input; + pid_t child_pid; + int stat_loc; //??? (Needed for waitpid) + + signal(SIGINT, SIG_IGN); //Tell vsh to ignore SIGINT (^C) + + while(1) { + user_input = prompt(); + argv = create_argv(user_input); + + if(strcmp(argv[0], "cd") == 0) { + if(cd(&user_input[3]) < 0) { + perror(argv[1]); + } + //causes the fork to get skipped + continue; + } + else if(strcmp(argv[0], "exit") == 0 || + strcmp(argv[0], "quit") == 0) { + exit(0); + } + + child_pid = fork(); + if(child_pid < 0) { + //If the child couldn't run, assume no memory + perror("Out of memory"); + exit(1); + } + else if(child_pid == 0) { + //If we are the child, allow ^C + signal(SIGINT, SIG_DFL); + if(execvp(argv[0], argv) < 0) { + perror(argv[0]); + exit(1); + } + } + else { + waitpid(child_pid, &stat_loc, WUNTRACED); + } + + free(user_input); + free(argv); + } + + return 0; +} + +char** create_argv(char* command) { + int argc = get_argc(command) + 1; + char* temp; + int i = 0; + + char** argv = calloc(argc, sizeof(*argv)); + if(argv == NULL) { + //If couldn't allocate argv, assume no memory + perror("Out of memory"); + exit(1); + } + + for(temp = strtok(command, ARG_SEP); temp != NULL; + temp = strtok(NULL, ARG_SEP)) { + argv[i] = temp; + i++; + } + + //Set last item in argv to NULL, since execvp requires it + argv[i] = NULL; + return argv; +} + +char* prompt() { + char cwd[PATH_MAX]; + getcwd(cwd, sizeof(cwd)); + char* bname = basename(cwd); + char prompt[PATH_MAX + 5] = ""; + strcat(prompt, bname); + strcat(prompt, PROMPT); + char* input = calloc(512, sizeof(*input)); + if(input == NULL) { + //If input allocate failed, assume no memory + perror("Out of memory"); + exit(1); + } + printf("%s", prompt); + fgets(input, 512, stdin); + //Is 512 enough? What about really long commands? + input[strcspn(input, "\r\n")] = '\0'; + return input; +} + +int get_argc(char* command) { + int argc = 0, word = 0; + char* command_iter = command; + + do { + switch(*command_iter) { + case '\0': + case ' ': + case '\t': if(word) { word = 0; argc++; } + default: word = 1; + } + } while(*(command_iter++)); + + return argc; +} + +int cd(char* path) { + return chdir(path); +} diff --git a/tty.c b/tty.c new file mode 100755 index 0000000..4831e10 --- /dev/null +++ b/tty.c @@ -0,0 +1,14 @@ +#include +#include +#include + +int main() { + if(isatty(fileno(stdin))) { + printf("%s\n", ttyname(0)); + return 0; + } + else { + printf("not a tty\n"); + return 1; + } +} diff --git a/wc.c b/wc.c new file mode 100755 index 0000000..9ceee26 --- /dev/null +++ b/wc.c @@ -0,0 +1,141 @@ +#include +#include + +int count_words(FILE * file); +int count_newls(FILE * file); +int count_bytes(FILE * file); + +int main(int argc, char ** argv) { + int flags = 0; + int c_byte = 0, c_nl = 0, c_word = 0; + int t_byte = 0, t_nl = 0, t_word = 0; + int i, fstart = 1; + FILE * in_file; + + for(i = 1; i < argc; i++) { + if(argv[i][0] == '-') { + switch(argv[i][1]) { + case 'c': flags |= 04;fstart++; break; + case 'l': flags |= 01; fstart++; break; + case 'w': flags |= 02; fstart++; break; + default: break; + } + if(argv[i][2] != '\0') { + switch(argv[i][2]) { + case 'c': flags |= 04; break; + case 'l': flags |= 01; break; + case 'w': flags |= 02; break; + default: break; + } + if(argv[i][3] != '\0') { + switch(argv[i][3]) { + case 'c': flags |= 04; break; + case 'l': flags |= 01; break; + case 'w': flags |= 02; break; + default: break; + } + } + } + } + else break; + } + + if((flags & 03) == 0) { + flags |= 04; + } + + for(i = fstart; i < argc; i++) { + in_file = fopen(argv[i], "r"); + if(in_file == NULL) { + fprintf(stderr, "Cannot find file %s\n", argv[i]); + continue; + } + if(flags & 04) { + c_byte = count_bytes(in_file); + t_byte += c_byte; + } + if(flags & 01) { + c_nl = count_newls(in_file); + t_nl += c_nl; + } + if(flags & 02) { + c_word = count_words(in_file); + t_word += c_word; + } + + if(flags & 01) { + printf("%d ", c_nl); + } + if(flags & 02) { + printf("%d ", c_word); + } + if(flags & 04) { + printf("%d ", c_byte); + } + + printf("%s\n", argv[i]); + + fclose(in_file); + } + + if((argc - fstart) > 1) { + if(flags & 01) { + printf("%d ", t_nl); + } + if(flags & 02) { + printf("%d ", t_word); + } + if(flags & 04) { + printf("%d ", t_byte); + } + + printf("total\n"); + } +} + +int count_words(FILE * file) { + int ret_val = 0, in_word = 0; + char c; + + fseek(file, 0, SEEK_SET); + + for(c = fgetc(file); c != EOF; c = fgetc(file)) { + if(c != ' ' && c != '\t' && c != '\n') { + in_word = 1; + } + else if(in_word) { + ret_val++; + in_word = 0; + } + } + + if(in_word) ret_val++; + + return ret_val; +} + +int count_newls(FILE * file) { + char c; int ret_val = 0; + + fseek(file, 0, SEEK_SET); + + for(c = fgetc(file); c != EOF; c = fgetc(file)) { + if(c == '\n') { + ret_val++; + } + } + + return ret_val; +} + +int count_bytes(FILE * file) { + char c; int ret_val = 0; + + fseek(file, 0, SEEK_SET); + + for(c = fgetc(file); c != EOF; c = fgetc(file)) { + ret_val++; + } + + return ret_val; +}