diff --git a/asa.c b/asa.c index e8d1505..e7643d0 100755 --- a/asa.c +++ b/asa.c @@ -9,25 +9,42 @@ int main(int argc, char ** argv) { char c, c_temp; for(i = 1; i < argc; i++) { - if(argv[i][0] == '-' && argv[i][1] == '\0') + /* If - is passed as an argument, set the input file to stdin */ + if(argv[i][0] == '-' && argv[i][1] == '\0') { in_file = stdin; + } else { + /* Open the file given */ in_file = fopen(argv[i], "r"); 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]); error = 1; 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; while(!eof_reached) { c = fgetc(in_file); + /* + Get the first character of the line and print the right thing + */ switch(c) { - case '1': printf("\f"); break; - case '0': printf("\n"); break; - case '+': printf("\r"); break; - case EOF: eof_reached = 1; continue; + case '1': printf("\f"); break; /* Form feed on 1 */ + case '0': printf("\n"); break; /* New line on 0 */ + case '+': printf("\r"); break; /* Carriage return on + */ + case EOF: eof_reached = 1; continue; /* Leave on EOF */ + /* 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)) { if(c_temp == EOF) { eof_reached = 1; @@ -40,8 +57,11 @@ int main(int argc, char ** argv) { printf("\n"); } - if(error) + /* If we ever hit an error, return 1. */ + if(error) { return 1; - else + } + else { return 0; + } } diff --git a/basename.c b/basename.c index fba1b1f..fe1d4a1 100755 --- a/basename.c +++ b/basename.c @@ -10,6 +10,15 @@ int main(int argc, char ** argv) { int basename_length = 0, last_slash = 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) { suffix_present = 1; } @@ -18,6 +27,9 @@ int main(int argc, char ** argv) { return 0; } + /* + If the path is just //, the POSIX spec also says to return newline + */ if(strcmp(argv[1], "//") == 0) { printf("\n"); return 0; @@ -25,16 +37,25 @@ int main(int argc, char ** argv) { 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]) { i++; } + /* + If the last character of the path is /, then remove it + */ if(argv[1][i-1] == '/') { argv[1][i-1] = '\0'; } i = 0; + /* + Find the last slash in the path + */ for(c = argv[1][i]; c != '\0'; c = argv[1][i]) { if(c == '/') { last_slash = i; @@ -44,10 +65,16 @@ int main(int argc, char ** argv) { i = last_slash + 1; + /* + Figure out how long the basename is + */ for(c = argv[1][i]; c != '\0'; c = argv[1][i]) { basename_length++; i++; } + /* + Allocate memory for the basename; fail out if we can't + */ basename = calloc(basename_length + 1, sizeof(*basename)); if(basename == NULL) { fprintf(stderr, "%s: Could not allocate sufficient memory\n", argv[0]); @@ -56,13 +83,21 @@ int main(int argc, char ** argv) { i = last_slash + 1; + /* + Transfer the basename to the array + */ for(c = argv[1][i]; c != '\0'; c = argv[1][i]) { basename[i - (last_slash + 1)] = c; i++; } - basename[basename_length] = '\0'; + basename[basename_length] = '\0'; /* don't forget the null! */ + /* + 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) { i = 0; for(c = argv[2][i]; c != '\0'; c = argv[2][i]) { @@ -84,6 +119,9 @@ int main(int argc, char ** argv) { } } + /* + Print the basename, free the memory, and quit! + */ printf("%s\n", basename); free(basename); diff --git a/cat.c b/cat.c index 3ccd213..b9726e1 100755 --- a/cat.c +++ b/cat.c @@ -12,17 +12,28 @@ int main(int argc, char *argv[]) { int error_occurred; + /* + Check for -u and use unbuffered output if present + */ while((c = getopt(argc, argv, "u")) != -1) { if(c == 'u') { 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) { setvbuf(stdin, NULL, _IONBF, 15); setvbuf(stdout, NULL, _IONBF, 15); } + /* + If no input files were given, just open up stdin + */ if(argc == 1 || optind == argc) { cur_in_file = stdin; for(c = fgetc(cur_in_file); c != EOF; c = fgetc(cur_in_file)) { @@ -31,6 +42,10 @@ int main(int argc, char *argv[]) { 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++) { if(argv[i][0] == '-' && argv[i][1] == '\0') { cur_in_file = stdin; diff --git a/cksum.c b/cksum.c index 72acd4e..eaee526 100755 --- a/cksum.c +++ b/cksum.c @@ -6,6 +6,10 @@ unsigned int crc32(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] = { 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, @@ -77,14 +81,20 @@ int main(int argc, char ** argv) { int i, error = 0; 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++) { in_file = fopen(argv[i], "r"); if(in_file == NULL) { error = 1; 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]); + fclose(in_file); + } } if(error) @@ -95,27 +105,37 @@ int main(int argc, char ** argv) { /* Based off the CRC-32 psuedocode implementation on the Wikipedia article for CRC */ unsigned int crc32(FILE * in_file) { + /* the CRC starts off as 0xFFFFFFFF */ unsigned int crc = 0xffffffff; int nLookupIndex; char c; + /* Make sure we're at the start of the file */ 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)) { nLookupIndex = (crc ^ c) & 0xff; crc = (crc >> 8) ^ crc32_table[nLookupIndex]; } + /* When all's said and done, invert all the bits and return. */ crc ^= 0xffffffff; return crc; } int count_octets(FILE * in_file) { int total_octets = 0; - char c; + char c; /* I may be assuming 8-bit character...uh... */ + /* Ensure we're at the start */ 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)) total_octets++; diff --git a/dirname.c b/dirname.c index d4ca49a..e72965c 100755 --- a/dirname.c +++ b/dirname.c @@ -6,41 +6,50 @@ int main(int argc, char ** argv) { int i, last_slash = -1, length; + /* If no path given, print / per the POSIX spec */ if(argc == 1) { printf("/\n"); return 0; } + /* Same if // is given */ if(strcmp(argv[1], "//") == 0) { printf("/\n"); return 0; } + /* Oh, look, we use strlen here. */ length = strlen(argv[1]); + /* Replace terminal slash (if present) with null */ if(argv[1][length - 1] == '/') { argv[1][length - 1] = '\0'; } + /* Find last slash */ for(i = 0; i < length; i++) { if(argv[1][i] == '/') { last_slash = i; } } + /* If we didn't find a slash, assume PWD per POSIX spec */ if(last_slash == -1) { printf(".\n"); return 0; } + /* Replace last slash with null to truncate basename */ argv[1][last_slash] = '\0'; + /* If the dirname is //, /, or blank, print a single slash. */ if(strcmp(argv[1], "//") == 0 || strcmp(argv[1], "") == 0 || strcmp(argv[1], "/") == 0) { printf("/\n"); return 0; } + /* Remove any trailing slashes from the dirname */ for(i = last_slash - 1; argv[1][i] == '/'; i--) { argv[1][i] = '\0'; } diff --git a/echo.c b/echo.c index fc5cc32..75c71fa 100755 --- a/echo.c +++ b/echo.c @@ -2,59 +2,77 @@ #include -int ctoi(char c); +int ctoi(char c); /* A bit of a helper function */ 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 + /* + 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(j = 0; argv[i][j] != '\0'; j++) { + /* We need to handle escape sequences ourself. */ 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; - } + j++; + switch(argv[i][j]) { + case 'a': printf("\a"); break; /* alert */ + case 'b': printf("\b"); break; /* backspace */ + case 'c': trailing_newline = 0; break; /* suppress trailing newline */ + case 'f': printf("\f"); break; /* form feed */ + case 'n': printf("\n"); break; /* new line */ + case 'r': printf("\r"); break; /* carriage return */ + case 't': printf("\t"); break; /* horizontal tab */ + case 'v': printf("\v"); break; /* vertical tab */ + case '\\': printf("\\"); break; /* just print a backslash */ + /* Octal sequences */ + case '0': { + j++; + oct_temp = ctoi(argv[i][j]); /* 1 digit escape (e.g. 08) */ + j++; + /* 2 digit escape (e.g. 063) */ + if(ctoi(argv[i][j] != -1)) { + oct_temp *= 8; + oct_temp += ctoi(argv[i][j]); + j++; + /* + 3 digit escape (e.g. 0127) + This is all the POSIX spec allows. + */ + 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; + /* On unrecognized escape, just print it literal */ + default: printf("\\%c", argv[i][j]); + break; + } } else { - printf("%c", argv[i][j]); + printf("%c", argv[i][j]); /* Not a backslash? Print the character */ } } } + /* Print trailing newline */ if(trailing_newline) { printf("\n"); } @@ -62,6 +80,13 @@ int main(int argc, char ** argv) { 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) { switch(c) { case '0': return 0; diff --git a/expand.c b/expand.c index 257aa8c..19b3727 100755 --- a/expand.c +++ b/expand.c @@ -27,20 +27,20 @@ int main(int argc, char ** argv) { } else { while(is_integer(argv[j]) && j < (argc - 1)) { - num_tab_stops++; - i++; - j++; + 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]); + 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'){ + 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); @@ -62,38 +62,38 @@ int main(int argc, char ** argv) { 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++; - } + 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); } diff --git a/link.c b/link.c index e6007af..c236153 100755 --- a/link.c +++ b/link.c @@ -5,6 +5,9 @@ #include int main(int argc, char * argv[]) { + /* + link(3) takes 2 arguments, no more, no less. + */ if(argc < 3) { fprintf(stderr, "%s: missing file operand\n", argv[0]); exit(1); @@ -15,5 +18,6 @@ int main(int argc, char * argv[]) { exit(1); } + /* Yep, this just calls link(3) */ return link(argv[1], argv[2]); } diff --git a/logname.c b/logname.c index c875aa3..c9e0458 100644 --- a/logname.c +++ b/logname.c @@ -5,8 +5,9 @@ #include int main(int argc, char * argv[]) { - char * logname = getlogin(); + char * logname = getlogin(); /* get current user's name */ + /* If we didn't get their name, find out why. */ if(logname == NULL) { switch(errno) { case EMFILE: fprintf(stderr, "%s: all file descriptors open\n", argv[0]); @@ -17,7 +18,7 @@ int main(int argc, char * argv[]) { return 1; } else { - printf("%s\n", logname); + printf("%s\n", logname); /* Print their name */ return 0; } } \ No newline at end of file diff --git a/pwd.c b/pwd.c index 09d6474..65247f3 100755 --- a/pwd.c +++ b/pwd.c @@ -5,7 +5,15 @@ #include 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; while((c = getopt(argc, argv, "LP")) != -1) { diff --git a/tty.c b/tty.c index 76ecf67..7334710 100755 --- a/tty.c +++ b/tty.c @@ -5,6 +5,7 @@ #include int main() { + /* Check if we're in a tty and, if so, print the devfile for it. */ if(isatty(fileno(stdin))) { printf("%s\n", ttyname(0)); return 0; diff --git a/uname.c b/uname.c index fe79578..41a2492 100644 --- a/uname.c +++ b/uname.c @@ -15,16 +15,18 @@ int main(int argc, char * argv[]) { int stuff_printed = 0; char c; /* - For stuff_print: - 01: -m - 02: -n - 04: -r - 010: -s - 020: -v - 037: -a + This variable holds what all we need to print, corresponding + to the following options: + 01: -m (Machine type) + 02: -n (Hostname) + 04: -r (Release) + 010: -s (Operating system) + 020: -v (Version) + 037: -a (Everything) */ int stuff_print = 0; + /* Get options */ while((c = getopt(argc, argv, "amnrsv")) != -1) { switch(c) { case 'm': stuff_print |= 01; break; @@ -34,20 +36,23 @@ int main(int argc, char * argv[]) { case 'v': stuff_print |= 020; break; case 'a': stuff_print |= 037; break; } + /* If we saw -a, then just leave, we're done here. */ if(c == 'a') { break; } } + /* If no options specified, print OS name */ if(stuff_print == 0) { stuff_print = 010; } int got_uname = 0; - got_uname = uname(sys_name); + got_uname = uname(sys_name); /* Try to get the utsname struct */ if(got_uname == -1) { fprintf(stderr, "%s: could not get uname\n", argv[0]); return 1; } + /* Print everything and trailing newline */ if(stuff_print & 010) { printf("%s ", sys_name->sysname); }