It echoes files or strings to output, never both at once. It does work (in both Linux and Windows), but I can NOT guarantee that it is bug free. It works much like echo, but it works with files as well, and has fewer formal arguments.

I'm looking for helpful and useful critiques, mainly in programming style, organization, and if it's easily understood (or if there was difficulty in understanding) source code. If any critiques are made, please add in how I can improve upon my "misdeeds".

```
//Problem 11-15
/*
*************************************************************
CHP 11 Problem #15
*************************************************************
Write a program that reads input until end-of-file and echoes 
it to the display. Have the program recognize and implement 
the following command-line arguments:
*************************************************************
-p -- Print input as is
-u -- Map input to all uppercase
-l -- Map input to all lowercase
*************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define TITLE "Chapter 11 Exercise 13"
_Bool true = 1, false = 0;
void display(char * string, char arg)
{ //display the string in stdout "as is"
    int col = 0;
    //go character by character to avoid bugs
    //while not null char '\0' or End-of-FILE
    if (arg == 'p')
        while (string[col] && string[col] != EOF)
            putchar(string[col++]);
    if (arg == 'u')
        while (string[col] && string[col] != EOF)
            putchar(toupper(string[col++]));        
    if (arg == 'l')
        while (string[col] && string[col] != EOF)
            putchar(tolower(string[col++]));
    putchar('\n'); //formatted padding
}
void pfile(char * fname, char arg)
{ //print the files contents to stdout "as is"
    FILE * fp;
    char ch;
    fp = fopen(fname, "r"); //open file for reading
    if(fp == NULL) //attempt failed
    {
        printf("Oops! Something went wrong while attempting to open the file.\n");
        puts("The file may be missing, corrupted, or may not exist.");
        exit(1); //quit program
    }
    //getc(fp) gets a character from the open file
    if (arg == 'p')
        while((ch = getc(fp)) != EOF)
            putchar(ch);
    if (arg == 'u')
        while((ch = getc(fp)) != EOF)
            putchar(toupper(ch));
    if (arg == 'l')
        while((ch = getc(fp)) != EOF)
            putchar(tolower(ch));
    fclose(fp); //close the file
}
int fext(char * string)
{//determine if there is a file extension
    //flag which value to return
    int i, ch, scan, place, flag = false;
    //while string is not a null character,
    //assign flag a boolean value,
    //break while if a character matches
    for (i = 0; string[i]; i++)
    {
        if (string[i] == '.')
        {
            //check if next char is a space char
            if (isspace(string[i + 1])) break;
            //count characters after '.'
            for (scan = i, place = 0; string[i+scan]; scan++) ++place;
            scan = i + 1; //advance by one character
            //only ASCII or Plain Text files are allowed
            if (!strncmp(string+scan,"txt",place))
            {
                flag = true;
                break;
            }
            if (!strncmp(string+scan,"asc",place))
            {
                flag = true;
                break;
            }
            if (!strncmp(string+scan,"c",place))
            {
                flag = true;
                break;
            }
            if (!strncmp(string+scan,"csv",place))
            {
                flag = true;
                break;
            }
            if (!strncmp(string+scan,"html",place))
            {
                flag = true;
                break;
            }
            if (!strncmp(string+scan,"log",place))
            {
                flag = true;
                break;
            }
            if (!strncmp(string+scan,"xhtml",place))
            {
                flag = true;
                break;
            }
            if (!strncmp(string+scan,"xml",place))
            {
                flag = true;
                break;
            }
        }
    }
    return flag; //assume *string is a string literal
}
int option(char * string)
{//determine if string is a formal argument
    auto int i, place, arg = false;
    if (string[0] == '-' && string[1] == '-' && isalpha(string[2]))
    {
        for (i = 0; string[i]; i++) //count alpha based chars
            if (isalpha(string[i])) 
                ++place;
        if (!strncmp((string + 2),"help",place))
        {
            arg = 'h'; //return the help argument
        }
        if (!strncmp((string + 2),"print",place))
        {
            arg = 'p'; //return the argument to print as is
        }
        if (!strncmp((string + 2),"uppercase",place))
        {
            arg = 'u'; //return the uppercase argument
        }
        if (!strncmp((string + 2),"lowercase",place))
        {
            arg = 'l'; //return the lowercase argument
        }
    }
    else if (string[0] == '-' && isalpha(string[1]))
    {
        switch (string[1])
        {
            case 'h':
                arg = 'h';
                break;
            case 'p':
                arg = 'p';
                break;
            case 'u':
                arg = 'u';
                break;
            case 'l':
                arg = 'l';
                break;
            default:
                arg = false;
                break;
        }
    }
    else 
    {
        arg = false;
    }
    return arg; //assume *string is a string literal
}
void help(char * string)
{
    printf("Usage: %s [OPTION]... [FILE] or [STRING]...\n", string);
    puts("Echoes FILE or STRING until End-of-FILE to the display.\n");
    printf("%s%50s\n", "-h, --help", "Prints this help text to the display.");
    printf("%s%49s\n", "-p, --print", "Prints the FILE as is to the display.");
    printf("%s%40s\n", "-u, --uppercase", "Maps the input to all uppercase.");
    printf("%s%40s\n", "-l, --lowercase", "Maps the input to all lowercase.");
}
int main(int argc, char *argv[])
{ //main program
    //extension, option
    auto int ext, opt; 
    switch(argc)
    {
        case 2:
            //check to see if input is an argument
            if ((opt = option(argv[1])) == 'h') //if argument is for help
            {
                help(argv[0]); //print only the help text to the display
                break;
            }
            if (opt) //if only an optional argument is made
            {
                printf("%s: missing FILE or STRING operand\n", argv[0]);
                printf("Try '%s --help' for more information.\n", argv[0]);
                break;
            }
            //check to see if input is string or file
            if (!opt && (ext = fext(argv[1]))) //if a file was provided with no opt
                pfile(argv[1], 'p'); //print FILE as is -- default argument
            else if (!opt && !ext)  //if no opt or file was provided
                display(argv[1], 'p'); //print STRING as is -- default argument
            break;
        case 3:
            if ((opt = option(argv[1])) == 'h')
            {
                help(argv[0]);
                break;
            }
            else if (opt)
                ext = fext(argv[2]);
            else
            {
                opt = false;
                ext = false;
            }
            if (opt && ext) //if option and file extension are valid and present
                pfile(argv[2], opt);
            else if (opt && !ext) //if option is present, but file is missing
                display(argv[2], opt);
            else
            {
                printf("%s: invalid OPTION was provided\n", argv[0]);
                printf("Try '%s --help' for more information.\n", argv[0]);
            }
            break;
        default:
            printf("%s: invalid arguments were made\n", argv[0]);
            printf("Try '%s --help' for more information.\n", argv[0]);
            break;
    }

    return 0;
}

```