Compare commits

..

No commits in common. "d91b47b1e25a40080962aa38ddeb681db9dc8352" and "0fa85040b328a9ac0c4294207ddbec7eeee4f2de" have entirely different histories.

12 changed files with 97 additions and 243 deletions

34
asa.c
View file

@ -9,42 +9,25 @@ int main(int argc, char ** argv) {
char c, c_temp; char c, c_temp;
for(i = 1; i < argc; i++) { for(i = 1; i < argc; i++) {
/* If - is passed as an argument, set the input file to stdin */ if(argv[i][0] == '-' && argv[i][1] == '\0')
if(argv[i][0] == '-' && argv[i][1] == '\0') {
in_file = stdin; in_file = stdin;
}
else { else {
/* Open the file given */
in_file = fopen(argv[i], "r"); in_file = fopen(argv[i], "r");
if(in_file == NULL) { if(in_file == NULL) {
/* If it can't open, set that we encountered an error */
/*
TODO: this should probably check errno instead of
assuming that we can't find the file
*/
fprintf(stderr, "Cannot find file %s\n", argv[i]); fprintf(stderr, "Cannot find file %s\n", argv[i]);
error = 1; error = 1;
continue; continue;
} }
} }
/*
Loop through the file line by line, applying transformations based on
the first character of the line, as given by the POSIX spec.
*/
eof_reached = 0; eof_reached = 0;
while(!eof_reached) { while(!eof_reached) {
c = fgetc(in_file); c = fgetc(in_file);
/*
Get the first character of the line and print the right thing
*/
switch(c) { switch(c) {
case '1': printf("\f"); break; /* Form feed on 1 */ case '1': printf("\f"); break;
case '0': printf("\n"); break; /* New line on 0 */ case '0': printf("\n"); break;
case '+': printf("\r"); break; /* Carriage return on + */ case '+': printf("\r"); break;
case EOF: eof_reached = 1; continue; /* Leave on EOF */ case EOF: eof_reached = 1; continue;
/* Anything else, don't do anything */
} }
/* Print out the rest of the line unless we hit an EOF, where we quit. */
for(c_temp = fgetc(in_file); c_temp != '\n'; c_temp = fgetc(in_file)) { for(c_temp = fgetc(in_file); c_temp != '\n'; c_temp = fgetc(in_file)) {
if(c_temp == EOF) { if(c_temp == EOF) {
eof_reached = 1; eof_reached = 1;
@ -57,11 +40,8 @@ int main(int argc, char ** argv) {
printf("\n"); printf("\n");
} }
/* If we ever hit an error, return 1. */ if(error)
if(error) {
return 1; return 1;
} else
else {
return 0; return 0;
}
} }

View file

@ -10,15 +10,6 @@ int main(int argc, char ** argv) {
int basename_length = 0, last_slash = 0; int basename_length = 0, last_slash = 0;
int suffix_length = 0; int suffix_length = 0;
/*
Basename takes two arguments, one for the path itself and an optional
one for a suffix to remove (e.g. ".c" to remove the C file extension).
Here, we check for that second argument to determine if we need to
remove an extension.
If there aren't multiple arguments, check if a path was even given. If
not, the POSIX spec says to just return a newline.
*/
if(argc > 2) { if(argc > 2) {
suffix_present = 1; suffix_present = 1;
} }
@ -27,9 +18,6 @@ int main(int argc, char ** argv) {
return 0; return 0;
} }
/*
If the path is just //, the POSIX spec also says to return newline
*/
if(strcmp(argv[1], "//") == 0) { if(strcmp(argv[1], "//") == 0) {
printf("\n"); printf("\n");
return 0; return 0;
@ -37,25 +25,16 @@ int main(int argc, char ** argv) {
i = 0; i = 0;
/*
Find the end of the path (probably could've just used strlen)
*/
for(c = argv[1][i]; c != '\0'; c = argv[1][i]) { for(c = argv[1][i]; c != '\0'; c = argv[1][i]) {
i++; i++;
} }
/*
If the last character of the path is /, then remove it
*/
if(argv[1][i-1] == '/') { if(argv[1][i-1] == '/') {
argv[1][i-1] = '\0'; argv[1][i-1] = '\0';
} }
i = 0; i = 0;
/*
Find the last slash in the path
*/
for(c = argv[1][i]; c != '\0'; c = argv[1][i]) { for(c = argv[1][i]; c != '\0'; c = argv[1][i]) {
if(c == '/') { if(c == '/') {
last_slash = i; last_slash = i;
@ -65,16 +44,10 @@ int main(int argc, char ** argv) {
i = last_slash + 1; i = last_slash + 1;
/*
Figure out how long the basename is
*/
for(c = argv[1][i]; c != '\0'; c = argv[1][i]) { for(c = argv[1][i]; c != '\0'; c = argv[1][i]) {
basename_length++; i++; basename_length++; i++;
} }
/*
Allocate memory for the basename; fail out if we can't
*/
basename = calloc(basename_length + 1, sizeof(*basename)); basename = calloc(basename_length + 1, sizeof(*basename));
if(basename == NULL) { if(basename == NULL) {
fprintf(stderr, "%s: Could not allocate sufficient memory\n", argv[0]); fprintf(stderr, "%s: Could not allocate sufficient memory\n", argv[0]);
@ -83,21 +56,13 @@ int main(int argc, char ** argv) {
i = last_slash + 1; i = last_slash + 1;
/*
Transfer the basename to the array
*/
for(c = argv[1][i]; c != '\0'; c = argv[1][i]) { for(c = argv[1][i]; c != '\0'; c = argv[1][i]) {
basename[i - (last_slash + 1)] = c; basename[i - (last_slash + 1)] = c;
i++; i++;
} }
basename[basename_length] = '\0'; /* don't forget the null! */ basename[basename_length] = '\0';
/*
If we need to remove a suffix, check if the end of the string is
actually equal to the suffix and, if it is, replace the first character
of the suffix with a null character.
*/
if(suffix_present && strcmp(basename, argv[2]) != 0) { if(suffix_present && strcmp(basename, argv[2]) != 0) {
i = 0; i = 0;
for(c = argv[2][i]; c != '\0'; c = argv[2][i]) { for(c = argv[2][i]; c != '\0'; c = argv[2][i]) {
@ -119,9 +84,6 @@ int main(int argc, char ** argv) {
} }
} }
/*
Print the basename, free the memory, and quit!
*/
printf("%s\n", basename); printf("%s\n", basename);
free(basename); free(basename);

15
cat.c
View file

@ -12,28 +12,17 @@ int main(int argc, char *argv[]) {
int error_occurred; int error_occurred;
/*
Check for -u and use unbuffered output if present
*/
while((c = getopt(argc, argv, "u")) != -1) { while((c = getopt(argc, argv, "u")) != -1) {
if(c == 'u') { if(c == 'u') {
using_unbuffered_output = 1; using_unbuffered_output = 1;
} }
} }
/*
Set unbuffered output. We do this for both stdin and stdout, let setvbuf
allocate the buffer (that we don't need), _IONBF tells it to not buffer,
and we just say 15 character buffer because, well, eh, who cares?
*/
if(using_unbuffered_output) { if(using_unbuffered_output) {
setvbuf(stdin, NULL, _IONBF, 15); setvbuf(stdin, NULL, _IONBF, 15);
setvbuf(stdout, NULL, _IONBF, 15); setvbuf(stdout, NULL, _IONBF, 15);
} }
/*
If no input files were given, just open up stdin
*/
if(argc == 1 || optind == argc) { if(argc == 1 || optind == argc) {
cur_in_file = stdin; cur_in_file = stdin;
for(c = fgetc(cur_in_file); c != EOF; c = fgetc(cur_in_file)) { for(c = fgetc(cur_in_file); c != EOF; c = fgetc(cur_in_file)) {
@ -42,10 +31,6 @@ int main(int argc, char *argv[]) {
fclose(cur_in_file); fclose(cur_in_file);
} }
/*
Open up each file given (or stdin if - was given), print it to stdout,
then close it and move to the next while there are still files
*/
for(i = optind; i < argc; i++) { for(i = optind; i < argc; i++) {
if(argv[i][0] == '-' && argv[i][1] == '\0') { if(argv[i][0] == '-' && argv[i][1] == '\0') {
cur_in_file = stdin; cur_in_file = stdin;

24
cksum.c
View file

@ -6,10 +6,6 @@
unsigned int crc32(FILE * in_file); unsigned int crc32(FILE * in_file);
int count_octets(FILE * in_file); int count_octets(FILE * in_file);
/*
I think this can technically be computed (don't quote me on that), but it's
easier and faster to implement it as a lookup table.
*/
unsigned int crc32_table[256] = { unsigned int crc32_table[256] = {
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
@ -81,20 +77,14 @@ int main(int argc, char ** argv) {
int i, error = 0; int i, error = 0;
FILE *in_file; FILE *in_file;
/*
Open each file (set that we encountered an error if we couldn't) then
print the CRC32 checksum and number of octets in the file.
*/
for(i = 1; i < argc; i++) { for(i = 1; i < argc; i++) {
in_file = fopen(argv[i], "r"); in_file = fopen(argv[i], "r");
if(in_file == NULL) { if(in_file == NULL) {
error = 1; error = 1;
fprintf(stderr, "Cannot find file %s\n", argv[i]); fprintf(stderr, "Cannot find file %s\n", argv[i]);
} }
else { else
printf("%u %d %s\n", crc32(in_file), count_octets(in_file), argv[i]); printf("%u %d %s\n", crc32(in_file), count_octets(in_file), argv[i]);
fclose(in_file);
}
} }
if(error) if(error)
@ -105,37 +95,27 @@ int main(int argc, char ** argv) {
/* Based off the CRC-32 psuedocode implementation on the Wikipedia article for CRC */ /* Based off the CRC-32 psuedocode implementation on the Wikipedia article for CRC */
unsigned int crc32(FILE * in_file) { unsigned int crc32(FILE * in_file) {
/* the CRC starts off as 0xFFFFFFFF */
unsigned int crc = 0xffffffff; unsigned int crc = 0xffffffff;
int nLookupIndex; int nLookupIndex;
char c; char c;
/* Make sure we're at the start of the file */
fseek(in_file, 0, SEEK_SET); fseek(in_file, 0, SEEK_SET);
/*
For each character, set nLookupIndex to CRC XOR that character ANDed with
256, then set the CRC to a new value by right-shifting it 8 and XORing with
the appropriate value from the lookup table
*/
for(c = fgetc(in_file); c != EOF; c = fgetc(in_file)) { for(c = fgetc(in_file); c != EOF; c = fgetc(in_file)) {
nLookupIndex = (crc ^ c) & 0xff; nLookupIndex = (crc ^ c) & 0xff;
crc = (crc >> 8) ^ crc32_table[nLookupIndex]; crc = (crc >> 8) ^ crc32_table[nLookupIndex];
} }
/* When all's said and done, invert all the bits and return. */
crc ^= 0xffffffff; crc ^= 0xffffffff;
return crc; return crc;
} }
int count_octets(FILE * in_file) { int count_octets(FILE * in_file) {
int total_octets = 0; int total_octets = 0;
char c; /* I may be assuming 8-bit character...uh... */ char c;
/* Ensure we're at the start */
fseek(in_file, 0, SEEK_SET); fseek(in_file, 0, SEEK_SET);
/* Count the octets, one by one. There may be an easier way, but eh. */
for(c = fgetc(in_file); c != EOF; c = fgetc(in_file)) for(c = fgetc(in_file); c != EOF; c = fgetc(in_file))
total_octets++; total_octets++;

View file

@ -6,50 +6,41 @@
int main(int argc, char ** argv) { int main(int argc, char ** argv) {
int i, last_slash = -1, length; int i, last_slash = -1, length;
/* If no path given, print / per the POSIX spec */
if(argc == 1) { if(argc == 1) {
printf("/\n"); printf("/\n");
return 0; return 0;
} }
/* Same if // is given */
if(strcmp(argv[1], "//") == 0) { if(strcmp(argv[1], "//") == 0) {
printf("/\n"); printf("/\n");
return 0; return 0;
} }
/* Oh, look, we use strlen here. */
length = strlen(argv[1]); length = strlen(argv[1]);
/* Replace terminal slash (if present) with null */
if(argv[1][length - 1] == '/') { if(argv[1][length - 1] == '/') {
argv[1][length - 1] = '\0'; argv[1][length - 1] = '\0';
} }
/* Find last slash */
for(i = 0; i < length; i++) { for(i = 0; i < length; i++) {
if(argv[1][i] == '/') { if(argv[1][i] == '/') {
last_slash = i; last_slash = i;
} }
} }
/* If we didn't find a slash, assume PWD per POSIX spec */
if(last_slash == -1) { if(last_slash == -1) {
printf(".\n"); printf(".\n");
return 0; return 0;
} }
/* Replace last slash with null to truncate basename */
argv[1][last_slash] = '\0'; argv[1][last_slash] = '\0';
/* If the dirname is //, /, or blank, print a single slash. */
if(strcmp(argv[1], "//") == 0 || strcmp(argv[1], "") == 0 || if(strcmp(argv[1], "//") == 0 || strcmp(argv[1], "") == 0 ||
strcmp(argv[1], "/") == 0) { strcmp(argv[1], "/") == 0) {
printf("/\n"); printf("/\n");
return 0; return 0;
} }
/* Remove any trailing slashes from the dirname */
for(i = last_slash - 1; argv[1][i] == '/'; i--) { for(i = last_slash - 1; argv[1][i] == '/'; i--) {
argv[1][i] = '\0'; argv[1][i] = '\0';
} }

103
echo.c
View file

@ -2,77 +2,59 @@
#include <stdio.h> #include <stdio.h>
int ctoi(char c); /* A bit of a helper function */ int ctoi(char c);
int main(int argc, char ** argv) { int main(int argc, char ** argv) {
int i, j, oct_temp; int i, j, oct_temp;
char char_temp; char char_temp;
/* int trailing_newline = 1; //1 if true, 0 if \c present
If /c is present in the text, we're not supposed to print a trailing
newline at the end. Otherwise, we do. Hence, we start with 1 (true)
for printing this and switch it to 0 if \c shows up
*/
int trailing_newline = 1;
/*
Outer loop handles each word passed in,
inner loop handles characters within each word.
*/
for(i = 1; i < argc; i++) { for(i = 1; i < argc; i++) {
for(j = 0; argv[i][j] != '\0'; j++) { for(j = 0; argv[i][j] != '\0'; j++) {
/* We need to handle escape sequences ourself. */
if(argv[i][j] == '\\') { if(argv[i][j] == '\\') {
j++; j++;
switch(argv[i][j]) { switch(argv[i][j]) {
case 'a': printf("\a"); break; /* alert */ case 'a': printf("\a"); break;
case 'b': printf("\b"); break; /* backspace */ case 'b': printf("\b"); break;
case 'c': trailing_newline = 0; break; /* suppress trailing newline */ case 'c': trailing_newline = 0; break;
case 'f': printf("\f"); break; /* form feed */ case 'f': printf("\f"); break;
case 'n': printf("\n"); break; /* new line */ case 'n': printf("\n"); break;
case 'r': printf("\r"); break; /* carriage return */ case 'r': printf("\r"); break;
case 't': printf("\t"); break; /* horizontal tab */ case 't': printf("\t"); break;
case 'v': printf("\v"); break; /* vertical tab */ case 'v': printf("\v"); break;
case '\\': printf("\\"); break; /* just print a backslash */ case '\\': printf("\\"); break;
/* Octal sequences */ case '0': {
case '0': { j++;
j++; oct_temp = ctoi(argv[i][j]);
oct_temp = ctoi(argv[i][j]); /* 1 digit escape (e.g. 08) */ j++;
j++; if(ctoi(argv[i][j] != -1)) {
/* 2 digit escape (e.g. 063) */ oct_temp *= 8;
if(ctoi(argv[i][j] != -1)) { oct_temp += ctoi(argv[i][j]);
oct_temp *= 8; j++;
oct_temp += ctoi(argv[i][j]); if(ctoi(argv[i][j] != -1)) {
j++; oct_temp *= 8;
/* oct_temp += ctoi(argv[i][j]);
3 digit escape (e.g. 0127) }
This is all the POSIX spec allows. else {
*/ 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;
else { default: printf("\\%c", argv[i][j]);
j--; break;
} }
printf("%c", (char)oct_temp);
}
break;
/* On unrecognized escape, just print it literal */
default: printf("\\%c", argv[i][j]);
break;
}
} }
else { else {
printf("%c", argv[i][j]); /* Not a backslash? Print the character */ printf("%c", argv[i][j]);
} }
} }
} }
/* Print trailing newline */
if(trailing_newline) { if(trailing_newline) {
printf("\n"); printf("\n");
} }
@ -80,13 +62,6 @@ int main(int argc, char ** argv) {
return 0; return 0;
} }
/*
I'm really not sure whether writing a ctoi function was ideal here.
Maybe I should have just used atoi? I dunno. But, at this point, I'm
just gonna leave it as is.
- Kat
*/
int ctoi(char c) { int ctoi(char c) {
switch(c) { switch(c) {
case '0': return 0; case '0': return 0;

View file

@ -27,20 +27,20 @@ int main(int argc, char ** argv) {
} }
else { else {
while(is_integer(argv[j]) && j < (argc - 1)) { while(is_integer(argv[j]) && j < (argc - 1)) {
num_tab_stops++; num_tab_stops++;
i++; i++;
j++; j++;
} }
tab_stops = calloc(num_tab_stops, sizeof(*tab_stops)); tab_stops = calloc(num_tab_stops, sizeof(*tab_stops));
for(j = 2; j < num_tab_stops + 2; j++) { for(j = 2; j < num_tab_stops + 2; j++) {
tab_stops[j-2] = stoi_mini(argv[j]); tab_stops[j-2] = stoi_mini(argv[j]);
} }
} }
} }
else if(argv[1][0] == '-' && argv[1][1] == 't' && else if(argv[1][0] == '-' && argv[1][1] == 't' &&
argv[1][2] <= '9' && argv[1][2] >= '0'){ argv[1][2] <= '9' && argv[1][2] >= '0'){
char * str = strtok(argv[1], "t"); char * str = strtok(argv[1], "t");
str = strtok(NULL, "\0"); str = strtok(NULL, "\0");
num_tab_stops = comma_list_num_stops(str); num_tab_stops = comma_list_num_stops(str);
@ -62,38 +62,38 @@ int main(int argc, char ** argv) {
else { else {
cur_stop = 0; col_pos = 0; cur_stop = 0; col_pos = 0;
for(c = fgetc(current_file); c != EOF; c = fgetc(current_file)) { for(c = fgetc(current_file); c != EOF; c = fgetc(current_file)) {
if(c == '\t') { if(c == '\t') {
if(num_tab_stops == 1) { if(num_tab_stops == 1) {
cur_stop++; cur_stop++;
printf(" "); col_pos++; printf(" "); col_pos++;
while(col_pos % *tab_stops != 0) { while(col_pos % *tab_stops != 0) {
printf(" "); col_pos++; printf(" "); col_pos++;
} }
} }
else { else {
if(cur_stop >= num_tab_stops) { if(cur_stop >= num_tab_stops) {
printf(" "); printf(" ");
col_pos++; col_pos++;
cur_stop++; cur_stop++;
} }
else { else {
printf(" "); col_pos++; printf(" "); col_pos++;
while(col_pos % tab_stops[cur_stop] != 0) { while(col_pos % tab_stops[cur_stop] != 0) {
printf(" "); col_pos++; printf(" "); col_pos++;
} }
cur_stop++; cur_stop++;
} }
} }
} }
else if(c == '\n') { else if(c == '\n') {
printf("%c", c); printf("%c", c);
col_pos = 0; col_pos = 0;
cur_stop = 0; cur_stop = 0;
} }
else { else {
printf("%c", c); printf("%c", c);
col_pos++; col_pos++;
} }
} }
fclose(current_file); fclose(current_file);
} }

4
link.c
View file

@ -5,9 +5,6 @@
#include <stdlib.h> #include <stdlib.h>
int main(int argc, char * argv[]) { int main(int argc, char * argv[]) {
/*
link(3) takes 2 arguments, no more, no less.
*/
if(argc < 3) { if(argc < 3) {
fprintf(stderr, "%s: missing file operand\n", argv[0]); fprintf(stderr, "%s: missing file operand\n", argv[0]);
exit(1); exit(1);
@ -18,6 +15,5 @@ int main(int argc, char * argv[]) {
exit(1); exit(1);
} }
/* Yep, this just calls link(3) */
return link(argv[1], argv[2]); return link(argv[1], argv[2]);
} }

View file

@ -5,9 +5,8 @@
#include <errno.h> #include <errno.h>
int main(int argc, char * argv[]) { int main(int argc, char * argv[]) {
char * logname = getlogin(); /* get current user's name */ char * logname = getlogin();
/* If we didn't get their name, find out why. */
if(logname == NULL) { if(logname == NULL) {
switch(errno) { switch(errno) {
case EMFILE: fprintf(stderr, "%s: all file descriptors open\n", argv[0]); case EMFILE: fprintf(stderr, "%s: all file descriptors open\n", argv[0]);
@ -18,7 +17,7 @@ int main(int argc, char * argv[]) {
return 1; return 1;
} }
else { else {
printf("%s\n", logname); /* Print their name */ printf("%s\n", logname);
return 0; return 0;
} }
} }

10
pwd.c
View file

@ -5,15 +5,7 @@
#include <stdlib.h> #include <stdlib.h>
int main(int argc, char * argv[]) { int main(int argc, char * argv[]) {
/* int mode = 01; /* 01: print PWD -L, 02: print physical path -P */
The -L option prints the logical path, corresponding to the PWD envar.
-P prints the physical path. The logical path includes any symbolic
links followed to get there, where as the physical path doesn't. So,
for example, if /lib links to /usr/lib, then if we cd /lib, pwd -L will
print /lib, whereas pwd -P will print /usr/lib, even though cd .. will
take us back to /
*/
int mode = 01; /* 01: -L, 02: -P */
char c; char c;
while((c = getopt(argc, argv, "LP")) != -1) { while((c = getopt(argc, argv, "LP")) != -1) {

1
tty.c
View file

@ -5,7 +5,6 @@
#include <stdio.h> #include <stdio.h>
int main() { int main() {
/* Check if we're in a tty and, if so, print the devfile for it. */
if(isatty(fileno(stdin))) { if(isatty(fileno(stdin))) {
printf("%s\n", ttyname(0)); printf("%s\n", ttyname(0));
return 0; return 0;

21
uname.c
View file

@ -15,18 +15,16 @@ int main(int argc, char * argv[]) {
int stuff_printed = 0; int stuff_printed = 0;
char c; char c;
/* /*
This variable holds what all we need to print, corresponding For stuff_print:
to the following options: 01: -m
01: -m (Machine type) 02: -n
02: -n (Hostname) 04: -r
04: -r (Release) 010: -s
010: -s (Operating system) 020: -v
020: -v (Version) 037: -a
037: -a (Everything)
*/ */
int stuff_print = 0; int stuff_print = 0;
/* Get options */
while((c = getopt(argc, argv, "amnrsv")) != -1) { while((c = getopt(argc, argv, "amnrsv")) != -1) {
switch(c) { switch(c) {
case 'm': stuff_print |= 01; break; case 'm': stuff_print |= 01; break;
@ -36,23 +34,20 @@ int main(int argc, char * argv[]) {
case 'v': stuff_print |= 020; break; case 'v': stuff_print |= 020; break;
case 'a': stuff_print |= 037; break; case 'a': stuff_print |= 037; break;
} }
/* If we saw -a, then just leave, we're done here. */
if(c == 'a') { break; } if(c == 'a') { break; }
} }
/* If no options specified, print OS name */
if(stuff_print == 0) { if(stuff_print == 0) {
stuff_print = 010; stuff_print = 010;
} }
int got_uname = 0; int got_uname = 0;
got_uname = uname(sys_name); /* Try to get the utsname struct */ got_uname = uname(sys_name);
if(got_uname == -1) { if(got_uname == -1) {
fprintf(stderr, "%s: could not get uname\n", argv[0]); fprintf(stderr, "%s: could not get uname\n", argv[0]);
return 1; return 1;
} }
/* Print everything and trailing newline */
if(stuff_print & 010) { if(stuff_print & 010) {
printf("%s ", sys_name->sysname); printf("%s ", sys_name->sysname);
} }