CSCS1730 UNIX/Linux Fundamentals

PROJECT: PROCESSING WARRANTED NUMBERS (pwn0)

Part 1 of 2 (the script is completed in pwn1)

TOOLBOX

In addition to the tools you're already familiar with, it is recommended you check out the following tools for possible application in this project (you may not need to use them in your solution, but they definitely offer up functionality that some solutions can make use of):

  • bc(1)
  • comm(1)
  • diff(1)
  • grep(1)
  • join(1)
  • printf(1)
  • seq(1)
  • sort(1)
  • uniq(1)

Don't forget the manual pages for bash(1) itself (see the sections on arithmetic evaluation, parameter expansion, and conditional expressions). Reading manual pages to discover capabilities is part of the exercise.

REFERENCE

For additional information on the printf(1) tool recommended for use in this project, please check out this paper:

  • https://lab46.g7n.org/downloads/printf.pdf

NOTE that while it focuses on the C and Perl variants of printf, the conceptual underpinnings are the same, and many of the examples are likely portable to the UNIX variant of the tool.

OBJECTIVE

To create a script that can, with or without information provided by the user, display useful reference data in various number bases.

This is the first of two projects that build one script:

  • pwn0 (this project)- the foundation: a basic table of binary, octal, decimal, and hexadecimal values, a starting and ending value (counting forward or backward), bounds checking, and online help.
  • pwn1- completes the script: skipping values (by#), adding and removing bases (with#/sans#), and hardening the argument handling.

Do not implement the pwn1 features here. In pwn0, those arguments are simply unrecognized, and are to be silently ignored (see the argument rules).

BACKGROUND

We've encountered many things in our UNIX journey so far, and have been readily building upon past experiences as we achieve newer and better successes. Of particular focus, we've been looking at shell scripting, and that will be the primary focus of this week's project.

There are collections of information quite useful to anyone journeying in a discipline, and computing is no different: We often encounter information represented in certain units more than others, or various quantities, or even particular number bases.

BINARY/OCTAL/HEX

One particular collection of information involves that of binary, octal, decimal (in signed and unsigned capacities) and hexadecimal numbers. We may encounter a tool that gives us information in octal and we need to feed it into another tool as binary or decimal; these sorts of transactions are common and crop up time and time again.

Having a strong handle on this information is vital for on-going success in the computing field.

As such, it is important to have close at hand the knowledge of the following number bases:

  • base 2 (binary)
  • base 8 (octal)
  • base 10 (decimal, specifically signed and unsigned quantities)
  • base 16 (hexadecimal)

While we don't need to have hundreds of values memorized, it IS a good idea to have a rather quick recollection of enough values that can be used for debugging purposes. The first 16 values of each of these is such a preferred range. Not only does it give us a range of information, but for the powers-of-two bases, can actually fit in and be propagated quite nicely with little added effort.

PROCESS

It is your task to write a script that, when run without any arguments, produces the following table of information (and displayed/formatted in this exact manner):

lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh
   base 2 |   base 8 |   base10 |   base16 |
----------+----------+----------+----------+
        0 |        0 |        0 |        0 |
        1 |        1 |        1 |        1 |
       10 |        2 |        2 |        2 |
       11 |        3 |        3 |        3 |
      100 |        4 |        4 |        4 |
      101 |        5 |        5 |        5 |
      110 |        6 |        6 |        6 |
      111 |        7 |        7 |        7 |
     1000 |       10 |        8 |        8 |
     1001 |       11 |        9 |        9 |
     1010 |       12 |       10 |        A |
     1011 |       13 |       11 |        B |
     1100 |       14 |       12 |        C |
     1101 |       15 |       13 |        D |
     1110 |       16 |       14 |        E |
     1111 |       17 |       15 |        F |
lab46:~/src/SEMESTER/unix/pwn0$ 

Your script should also take the following optional arguments (in this order):

  • $1- starting value (a whole number, in decimal)
  • $2- ending value (a whole number, in decimal)

Additional argument your script should support:

  • help - display script usage and exit

With any of these arguments validly provided, they should adjust the script's processing and output accordingly.

Some additional constraints/assumptions you can make:

  • the minimum lower limit your script should process for is 0. If an input goes negative, cap it to 0.
  • the maximum upper limit you can implement for is 255 (base 10). If an input goes in excess of this, cap it to 255.
  • the bases displayed are always 2, 8, 10, and 16 (in that order)

ONLY SPECIFYING STARTING VALUE

In the event only the starting value is specified, assume a count of 16 (so display 16 values, starting at the starting value; that is, an ending value of the starting value + 15, capped at 255).

For example:

lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 12
   base 2 |   base 8 |   base10 |   base16 |
----------+----------+----------+----------+
     1100 |       14 |       12 |        C |
     1101 |       15 |       13 |        D |
     1110 |       16 |       14 |        E |
     1111 |       17 |       15 |        F |
    10000 |       20 |       16 |       10 |
    10001 |       21 |       17 |       11 |
    10010 |       22 |       18 |       12 |
    10011 |       23 |       19 |       13 |
    10100 |       24 |       20 |       14 |
    10101 |       25 |       21 |       15 |
    10110 |       26 |       22 |       16 |
    10111 |       27 |       23 |       17 |
    11000 |       30 |       24 |       18 |
    11001 |       31 |       25 |       19 |
    11010 |       32 |       26 |       1A |
    11011 |       33 |       27 |       1B |
lab46:~/src/SEMESTER/unix/pwn0$ 

SPECIFYING STARTING AND ENDING VALUE

We can adjust the range displayed by specifying an ending value as well:

lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 37 42
   base 2 |   base 8 |   base10 |   base16 |
----------+----------+----------+----------+
   100101 |       45 |       37 |       25 |
   100110 |       46 |       38 |       26 |
   100111 |       47 |       39 |       27 |
   101000 |       50 |       40 |       28 |
   101001 |       51 |       41 |       29 |
   101010 |       52 |       42 |       2A |
lab46:~/src/SEMESTER/unix/pwn0$ 

With a specified starting/ending value pair, we can display as little as 1 value and (theoretically) as many as we want.

GOING BACKWARDS

It shouldn't matter the relationship of starting and ending values. In fact, if the starting value is HIGHER than the ending value, the count should go backwards:

lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 73 59
   base 2 |   base 8 |   base10 |   base16 |
----------+----------+----------+----------+
  1001001 |      111 |       73 |       49 |
  1001000 |      110 |       72 |       48 |
  1000111 |      107 |       71 |       47 |
  1000110 |      106 |       70 |       46 |
  1000101 |      105 |       69 |       45 |
  1000100 |      104 |       68 |       44 |
  1000011 |      103 |       67 |       43 |
  1000010 |      102 |       66 |       42 |
  1000001 |      101 |       65 |       41 |
  1000000 |      100 |       64 |       40 |
   111111 |       77 |       63 |       3F |
   111110 |       76 |       62 |       3E |
   111101 |       75 |       61 |       3D |
   111100 |       74 |       60 |       3C |
   111011 |       73 |       59 |       3B |
lab46:~/src/SEMESTER/unix/pwn0$ 

EXCEEDING BOUNDS

Although our script does not need to iterate values outside the 0-255 range, it does need to check and cap values that exceed these bounds.

For example, if a starting or ending value falls beyond 255, cap it to 255:

lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 250
   base 2 |   base 8 |   base10 |   base16 |
----------+----------+----------+----------+
 11111010 |      372 |      250 |       FA |
 11111011 |      373 |      251 |       FB |
 11111100 |      374 |      252 |       FC |
 11111101 |      375 |      253 |       FD |
 11111110 |      376 |      254 |       FE |
 11111111 |      377 |      255 |       FF |
lab46:~/src/SEMESTER/unix/pwn0$ 

If we have a negative value of any sort:

lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 4 -8
   base 2 |   base 8 |   base10 |   base16 |
----------+----------+----------+----------+
      100 |        4 |        4 |        4 |
       11 |        3 |        3 |        3 |
       10 |        2 |        2 |        2 |
        1 |        1 |        1 |        1 |
        0 |        0 |        0 |        0 |
lab46:~/src/SEMESTER/unix/pwn0$ 

Both starting and ending values need to appropriately fall within the 0-255 bounds, however they may be situated.

ONLINE HELP

Your script should also, when prompted, display usage information with the help option:

lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh help

      pwn0.sh - render a number table in bases 2, 8, 10, and 16,
                displaying from starting value to ending value.

      behavior: by default, values 0 to 15 (inclusive) will
                be displayed.

          note: values should not go negative nor exceed 255. If
                a starting value but no ending value is given,
                assume an ending value +15 away (or capped by 255).

         usage: pwn0.sh [start#] [end#]

       options:
           $1 - if a non-negative decimal value, override the
                starting value (0)
           $2 - if a non-negative decimal value, override the
                ending value (15)

 other options:
         help - display script usage and exit

lab46:~/src/SEMESTER/unix/pwn0$ 

(The online help is provided in the starter script; the point is for you to produce it correctly, and to understand how it works.)

ARGUMENT RULES (CLARIFICATIONS)

To remove ambiguity, here is exactly how arguments are to be treated:

  • help anywhere on the command line wins: display usage and exit (even if other arguments are present).
  • Arguments are examined in the order given. The first whole number encountered is the starting value, the second is the ending value. Any further whole numbers are silently ignored.
  • A "whole number" is an optional leading - followed by one or more digits. Things like 12.5, abc, +5, or 0x1F are not whole numbers.
  • Anything that is neither help nor a whole number is silently dropped (as if never given). This includes by#, with#, and sans#, which you will meet in pwn1 but which mean nothing yet.
  • Values below 0 become 0; values above 255 become 255 (this includes ridiculously long numbers). This applies to the start and the end value.
  • If only a starting value is given (or none at all), the ending value is the starting value + 15, capped at 255.
  • If the starting value is higher than the ending value, count backward (one at a time). If they are equal, display a single row.
  • Nothing goes to STDERR, ever: this script has no error messages. The exit status is always 0.

For example, unrecognized arguments are simply ignored:

lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 5 8 by2 foo
   base 2 |   base 8 |   base10 |   base16 |
----------+----------+----------+----------+
      101 |        5 |        5 |        5 |
      110 |        6 |        6 |        6 |
      111 |        7 |        7 |        7 |
     1000 |       10 |        8 |        8 |
lab46:~/src/SEMESTER/unix/pwn0$ 

SPECIFICATIONS

Evaluation will be based on correctness of values as well as on formatting/spacing.

You'll notice that everything lines up and is positioned similarly:

  • each column exists within 10 characters of on-screen real estate:
    • 8 characters for actual value display,
    • with one space padding either side
  • columns are separated with a | symbol, appended to the right edge of the column (effectively making each column 11 characters wide).
    • note that the rightmost column is ended with this |.
  • there is a heading/header at the top of the output table, and it uses a '+' to "connect" the horizontal and vertical lines being drawn
    • The dashes and vertical bars set up an ASCII art-like table pattern that helps make the data more readable.
  • The values are right justified with each column
    • justification is essential. Everything should line up on its respective right margin.
  • base headings are right justified; the word "base" is followed by the base number in a field 2 characters wide:
    • you'll see "base 2" vs. "base16"; your script needs to accommodate this.
  • You are to literally print out no more than 2 consecutive spaces at a time in your output statements (the help text is exempt from this rule). If you need more, use one of the formatting tools to generate spaces for you (printf(1) may be able to help you with this).
  • You need to check your arguments to ensure they are present and valid. Some examples:
    • starting value is a valid (whole) number
      • if less than 0, or greater than 255, needs to be capped to whichever extreme it exceeds
        • if -4, cap to 0
        • if 300, cap to 255
    • ending value is a valid (whole) number
      • if less than 0, or greater than 255, needs to be capped to whichever extreme it exceeds
        • if -8, cap to 0
        • if 420, cap to 255
    • any invalid arguments (nonsensical value in place of starting value, etc.) should be silently dropped/ignored.
  • default starting value is 0, default ending value is 15. If nothing else is validly provided, these are the values the script should run with.
  • if starting and ending values are the same, the script will display just one line of number output (in addition to the header).
  • your script needs to commence with a proper shabang to bash; your script needs to end with an "exit 0" at the very end
  • comments and indentation are required and necessary
    • comments should explain how or why you are doing something
    • indentation should be consistent throughout the script
    • indentation is to be no less than 3 on-screen spaces (I recommend tabstops of 4).
  • continuing with our shell scripting, your script will need to employ in a core/central way:
    • variables
    • command expansions
    • regular expressions
    • if statements
    • loops
  • your logic needs to:
    • flow (one thing leads into the next, as best as possible)
    • make sense within the given context
    • avoid redundancy
    • be understood by you (no grabbing snippets that seem to "work" from the internet)
      • if you gain inspiration from some external resource, please cite it
      • comments are a great way of demonstrating understanding (if you explain the why and how effectively, and it isn't in violation of other aspects, I'll know you are in control of things)

To be sure, I'll be checking to make sure your solution follows the spirit of what this project is about (that you implement functional, flowing logic utilizing the tools and concepts we've learned, in an application that helps demonstrate your comprehension). Don't try to weasel your way out of this or cut corners. This is an opportunity to further solidify your proficiency with everything.

SPIRIT OF PROJECT

The spirit of the project embodies many aspects we've been focusing on throughout the semester:

  • recognizing patterns to employ effective solutions in problem solving
  • utilizing concepts and tools covered
  • demonstrating comprehension of concepts, tools, and problems
  • employing concepts in knowledgeable and thoughtful manner
  • following instructions
  • implementing to specifications
  • utilizing creativity
  • being able to control solution via consistent, clear, and organized presentation

Basically: I want your solution to be the result of an honest, genuine brainstorming process where you have (on your own) figured out a path to solving the problem, you have dabbled and experimented and figured things out, and you can command the concepts and tools with a fluency enabling you to pull off such a feat. Your solution should demonstrate the real learning that took place and experience gained.

Cutting corners, avoiding work, skimping on functionality, cheating through getting others to do work for you or finding pre-packaged "answers" on the internet violates the spirit of the project, for they betray your ability to pull off the task on your own.

NOTE: some have instantiated controversy in the past by utilizing AI in a manner well beyond their abilities. In such cases, submitted work is not considered your own, and thereby inviting disciplinary action. Don't fall into that trap.

IDENTIFYING SHORTCOMINGS

I would also like it if you provided an inventory of what functionality is lacking or out of spec when you submit the project. The better you can describe your deviations from stated requirements, the more forgiving I may be during evaluation (versus trying to hide the shortcomings and hoping I do not discover them).

The more fluent you are in describing your shortcomings on accomplishing the project (ie "I didn't know how to do this" is far from fluent), the better I will be able to gauge your understanding on a particular aspect.

This can be in the form of comments in your script, or even a separate file submitted at time of submission (if a file, be sure to make mention of it in your script so I can be sure to look for it).

OUTPUT FORMATTING WITH printf(1)

You might be wondering how you can pull off some of these output formatting feats. The echo command, after all, is rather rudimentary.

Fear not! The printf(1) tool comes to your rescue!

Like echo, printf displays information to the screen (STDOUT). In fact, various programming languages (like C and C++) that want more powerful output formatting implement some form of printf into their vast libraries.

Be sure to check the manual page for options and functionality; following will be a few usage examples.

printf: BASIC OPERATION

Like echo, printf in its simplest form takes as an argument a string to display to STDOUT:

lab46:~$ printf "Hello, World"
Hello, Worldlab46:~$ 

However, we notice one difference between the default behavior of printf vs. echo: printf does not automatically issue a newline by default, as echo does. So, we'll need to specify it manually with the \n character:

lab46:~$ printf "Hello, World\n"
Hello, World
lab46:~$ 

Those various escape characters we've learned about? Super useful here:

  • \n - newline
  • \t - tab

Be sure to check the manual page for additional escape characters.

printf: FORMAT SPECIFIERS

Now, we know from using echo we can utilize shell variable and command expansions to make our output more dynamic.

But, printf adds additional formatting capability that echo lacks. If the string we are displaying contains % symbols, substitutions can be made and behaviors invoked; functionality that echo lacks.

Some common format specifiers:

  • %d - substitute integer (whole number) value
  • %s - substitute string value
  • %c - substitute single character
  • %f - substitute floating point value
  • %o - substitute integer (whole number) value and represent in octal
  • %x - substitute integer (whole number) value and represent in hexadecimal

First up, a simple example:

lab46:~$ printf "%d\n" 175
175
lab46:~$ 

Then, adding to it:

lab46:~$ printf "The number: %d\n" 175
The number: 175
lab46:~$ 

That 175 can also be in a variable:

lab46:~$ value=175
lab46:~$ printf "The number: %d\n" ${value}
The number: 175
lab46:~$ 

You may want to wrap the variable in double quotes, to avoid cases where it might be NULL and otherwise generate an error (I generally quote all my variables to be on the safe side).

How about substitutions with strings?

lab46:~$ printf "Your username is: %s\n" "${USER}"
Your username is: username
lab46:~$ 

And in general just crafting super effective format strings:

lab46:~$ value=175
lab46:~$ printf "%d %s %X\n" "${value}" "is hexadecimal" "${value}"
175 is hexadecimal AF
lab46:~$ 

Please take note, where there are multiple format specifiers, substitution is in order of specification… %d was the first, %s was the second, and %X was the third in that particular string, so the first value following the string is grabbed by the %d, the next the %s, and the third the %X. Ordering matters (which should make sense).

printf: OUTPUT FORMATTING

So now, getting to where printf really excels, formatting your output.

It turns out, that between the % and whatever format option you specify, you can provide a numeric value which will impact how that number appears on the screen, commonly in the form of preallocated space to display within.

For instance:

lab46:~$ printf "Testing: >>%4d<<\n" 47
Testing: >>  47<<
lab46:~$ 

See what happened there? 47 was displayed, but WITHIN a block of 4 characters. Also of note, by default output is right justified.

To left justify, simply make it negative:

lab46:~$ printf "Testing: >>%-4d<<\n" 47
Testing: >>47  <<
lab46:~$ 

We can also pad with zeros, that is represented by decimal values:

lab46:~$ printf "Testing: >>%.3d<<\n" 49
Testing: >>049<<
lab46:~$ 

This can be combined with justify and space allocation:

lab46:~$ printf "Testing: >>%-6.3d<<\n" 49
Testing: >>049   <<
lab46:~$ 

Other neat tricks? We can variable-ize the padding by using a *:

lab46:~$ spacing=4
lab46:~$ printf "Testing: >>%*d<<\n" "${spacing}" 49
Testing: >>  49<<
lab46:~$ 

The printf tool is super-powerful and useful for output, so mastering its use adds an impressive capability to your repertoire.

Play with printf and experiment… you'll find it can accomplish some impressive output feats that previously may have been more complicated.

SELECTION

Occasionally during the automation of a task, you will have need for the computer to make a decision based on the state of a condition to decide how to proceed. We accomplish this via the if selection structure.

In bash, an if takes the following form:

if [ condition ]; then
    statement(s)
fi

The "condition" are valid arguments posed to the [(1) command, resulting in a true or false result.

There are one or more statements within the body of the if (to be run in the event the result of the condition tests true), and the structure is terminated with the trailing fi (if spelled backwards).

We also have the ability to react in the event the if condition tests false, and that is with an optional else statement (which is used 0 or 1 times per if, and must always follow the if):

if [ condition ]; then
    statement(s)
else
    statement(s)
fi

The else has no condition: it is a reaction to the previously tested condition being false.

CONDITIONS

The conditions we pose to the computer must be such that resolve ultimately to a true or false result.

Each condition can be unary or binary in nature, meaning we can directly check the state of one thing, or compare the relationship between two things.

For example, the -z argument to [(1) tests for a NULL string. If we wanted to see if a variable as a result of some operation were NULL or populated, we could do:

check=$(/usr/bin/who | grep 'jsmith12' | wc -l | grep '^1$')
if [ -z "${check}" ]; then
    statement(s) # do this if check is NULL
fi

Note that we could also check the opposite. We can use the ! symbol to require the opposite (NOT):

check=$(/usr/bin/who | grep 'jsmith12' | wc -l | grep '^1$')
if [ ! -z "${check}" ]; then
    statement(s) # do this if check is NOT NULL
fi

Comparing two strings, the two common scenarios we tend to care about is whether or not the two strings are equal or not equal:

string1="blah"
string2="boop"

if [ "${string1}" = "${string2}" ]; then
    statement(s) # do this in the event strings are equal
fi

if [ ! "${string1}" = "${string2}" ]; then
    statement(s) # do this in the event strings are NOT equal
fi

It should be stated that instead of negating the result, we could also just use an else clause:

string1="blah"
string2="boop"

if [ "${string1}" = "${string2}" ]; then
    statement(s) # do this in the event strings are equal
else
    statement(s) # do this in the event strings are not equal
fi

As a matter of style (and to potentially avoid syntax/logic errors being committed), one should not pose a condition just for the sake of ensuring its opposite (ie no empty clauses).

If comparing numerical values, especially in numerical contexts, we have a set of arguments we can choose from:

  • -eq - is equal to
  • -ne - is not equal to
  • -lt - is less than
  • -le - is less than or equal to
  • -gt - is greater than
  • -ge - is greater than or equal to

These of course are binary conditions, meaning we compare TWO variables to see if they possess the indicated relation (which results in a true or false result produced).

LOOPS

When you have a section of code you would like to repeat some number of times, a loop can be used to achieve this.

Here we will explore the while conditional loop. If an if statement can run 0 or 1 times, a while loop can run 0 or more.

count=10
while [ "${count}" -gt 0 ]; do
    echo "count is: ${count}"
    count=$((count - 1))
done

The condition works just like it does for an if (it is the arguments given to [(1)), but the body repeats for as long as that condition remains true. Something inside the loop must eventually change the outcome of the condition (above, the count=$((count - 1)) line), or you have created an infinite loop (Ctrl-C will rescue you).

Arithmetic in bash is performed with the $(( )) construct, as seen above.

FOR LOOPS

When you know in advance what you want to iterate through, a for loop is often cleaner. A list-based for loop visits each item in a list:

for base in 2 8 10 16; do
    echo "now working on base ${base}"
done

A numeric (C-style) for loop manages a counter for you:

for ((i = 0; i < 5; i++)); do
    echo "i is: ${i}"
done

Either is fine for this project. Think about which loop best fits each repetitive task you identify (walking the arguments, walking the values, walking the bases…).

PATTERN MATCHING

You'll need to decide what each command-line argument IS (the word help? a whole number? something nonsensical?). Rather than a long chain of string comparisons, the course objective on pattern matching asks you to describe the shape of what you expect with a regular expression.

A few places where regular expressions can be applied in a bash script (check the manual pages and your notes on regular expressions, and experiment!):

  • grep(1) / egrep(1) (or grep -E), commonly with -q to test a match
  • the [[ string =~ regex ]] test (captured groups land in BASH_REMATCH)
  • sed(1) substitutions to strip or transform text
  • case statement patterns (these are shell globs, a close relative)

Anchors (^ and $) matter. A whole number (with an optional leading minus) could be described as ^-?[0-9]+$:

lab46:~$ [[ "-8" =~ ^-?[0-9]+$ ]] && echo "whole number"
whole number
lab46:~$ [[ "42abc" =~ ^-?[0-9]+$ ]] || echo "42abc rejected"
42abc rejected
lab46:~$

Without the anchors, "42abc" would match too (it contains digits), and "12.5" would sneak through as well. Test your patterns against near-misses.

LOOKING AHEAD: PWN1

The pwn1 project picks up right where this one leaves off: you will extend this very script to skip values (by#), add bases (with#), and remove bases (sans#). Today's table is a fixed list of four bases; next time it will be a list that changes. Write your pwn0 so that:

  • the work of converting and displaying ONE value lives in one place (rather than being copy/pasted four times)
  • your loops and conditions are tidy and easy to follow
  • your comments make it obvious how everything fits together

Future you (and your pwn1 grade) will thank you.

SUBMISSION

By successfully performing this project, you should have a fully functioning script by the name of pwn0.sh, which is all you need to submit for project completion (no steps file, as your "steps" file IS the script you wrote).

A starter script is available to give you a base to work from (it contains the identification block, the complete help text, and an outline of suggested steps):

$ cp /var/public/fall2026/UNIX/pwn0/pwn0.sh ~/src/SEMESTER/unix/pwn0/pwn0.sh

Using the starter is optional, but whatever you submit must still satisfy everything in this document.

To submit this project to me using the submit tool, run the following command at your lab46 prompt:

$ submit unix pwn0 pwn0.sh
Submitting unix project "pwn0":
    -> pwn0.sh(OK)

SUCCESSFULLY SUBMITTED

What I'm looking for:

286:pwn0:final tally of results (286/286)
*:pwn0:pwn0.sh is a proper bash script: shabang, clean exit 0, parses, no hard-coded paths [13/13]
*:pwn0:pwn0.sh on help displays informative usage and exits [13/13]
*:pwn0:pwn0.sh formats output with printf width specifiers (no >2 literal spaces) [13/13]
*:pwn0:pwn0.sh accurately displays values in proper alignment [26/26]
*:pwn0:pwn0.sh effectively utilizes variables in operations [13/13]
*:pwn0:pwn0.sh effectively utilizes command expansions [13/13]
*:pwn0:pwn0.sh effectively utilizes selection statements [13/13]
*:pwn0:pwn0.sh effectively utilizes looping structures [13/13]
*:pwn0:pwn0.sh accurately displays the default table (no arguments) [26/26]
*:pwn0:pwn0.sh accurately displays values for starting and ending values [26/26]
*:pwn0:pwn0.sh employs discrete single-purpose utilities [13/13]
*:pwn0:pwn0.sh uses regular expressions to validate numeric input [13/13]
*:pwn0:pwn0.sh displays 16 values when only a starting value is given [13/13]
*:pwn0:pwn0.sh range logic flexibly works forward and reverse [13/13]
*:pwn0:pwn0.sh caps starting/ending values to the 0 to 255 bounds [13/13]
*:pwn0:pwn0.sh silently drops invalid arguments and still runs [13/13]
*:pwn0:pwn0.sh comments explain how/why (header block, density, reasoning) [13/13]
*:pwn0:pwn0.sh logic is organized: consistent indentation (>=3), lines within 90 chars [13/13]
*:pwn0:pwn0.sh identifies shortcomings, deviations from specification [13/13]

Additionally:

  • Solutions not abiding by the SPIRIT of the project (including hard-coded output) will be subject to a 25% overall deduction
  • Solutions not utilizing descriptive why and how COMMENTS will be subject to a 25% overall deduction
  • Solutions not utilizing INDENTATION to promote scope and clarity will be subject to a 25% overall deduction
  • Solutions lacking ORGANIZATION or that are not easy to read (within 90 char width) are subject to a 25% overall deduction