User Tools

Site Tools


Sidebar

projects

wcp1 (due 20240124)
pct0 (bonus; due 20240125)
pct1 (bonus; due 20240125)
abc0 (due 20240131)
pct2 (due 20240131)
wcp2 (due 20240131)
dac0 (due 20240207)
pct3 (bonus; due 20240207)
wcp3 (due 20240207)
gtf0 (due 20240214)
pct4 (due 20240214)
wcp4 (due 20240214)
bwp1 (bonus; due 20240228)
pct5 (bonus; due 20240228)
usr0 (due 20240228)
wcp5 (due 20240228)
gfo0 (due 20240306)
pct6 (due 20240306)
tpb0 (due 20240306)
wcp6 (due 20240306)
pct7 (bonus; due 20240313)
tpb1 (due 20240313)
wcp7 (due 20240313)
pct8 (due 20240320)
tpb2 (due 20240320)
wcp8 (due 20240320)
pct9 (bonus; due 20240327)
wcp9 (due 20240327)
bwp2 (bonus; due 20240410)
fwg0 (due 20240410)
gfo1 (due 20240410)
pctA (due 20240410)
wcpA (due 20240410)
wpa0 (due 20240410)
pctB (bonus; due 20240417)
upf0 (due 20240417)
wcpB (due 20240417)
ldg0 (due 20240424)
pctC (due 20240424)
wcpC (due 20240424)
pctD (bonus; due 20240501)
wcpD (bonus; due 20240501)
gfo2 (due 20240508)
pctE (bonus; due 20240508)
wcpE (bonus; due 20240508)
EoCE (due 20240516)
haas:spring2024:unix:projects:upf0

Corning Community College

CSCS1730 UNIX/Linux Fundamentals

Project: UNIX PIPE FUN (upf0)

Errata

  • any bugfixes or project updates will be posted here

Objective

To continue to cultivate your problem solving skills, to practice your shell skills, and to demonstrate your basic scripting skills.

Background

Pipes and command expansions are important concepts and skills that you need to be familiar with as we proceed down the shell scripting rabbit hole.

This project has us playing with various examples that will require regular use of these skills, for the purpose of throwing numbers and math operations together to produce desired results (and in desired composition).

It can be helpful to fully read and understand the instructions associated with resources. This can take the form of comments in a source code or configuration file, or even actual instructions. If you see conspicuously-named files hinting at some action that you can take, you may want to investigate said file to see if it might aid you in some capacity.

Get started

This week's project has 2 points of origin.

First, in the upf0/ sub-directory of the UNIX Public Directory, you will find the following archive:

  • numbers.tgz

Then, under a directory by the name of your username within that same directory, there will be another file:

  • TASK

Copy both of these files into your project directory.

The TASK file will contain the particular command-line equations you have to perform, along with their stated constraints.

The numbers.tgz file needs to be extracted, compiled, and installed; there is a README file located within the archive with further instructions on how to do this.

Next, you will want to grab the latest version of the pipemath suite from the following URL:

You will want to use a tool like wget(1) or curl(1) to non-interactively download it into your work directory, and similarly extract, compile, and install that (check its own README file).

There may be multiple versions of pipemath available at the download link. Unless you have specific reason otherwise (for this project, you do not), you want to go for the latest version, which will be reflected by the most recent datestamp encoded in the file's name.

For example, say you have the following:

  • pipemath-20160731-10.tar.gz
  • pipemath-20161024-14.tar.gz
  • pipemath-20170123-13.tar.gz
  • pipemath-20170201-09.tar.gz
  • pipemath-20210321-17.tar.gz
  • pipemath-20220401-02.tar.gz

From visual inspection, you would select the “20220401-02” one, because the date it encodes (April 1st, 2022 at 2am) is the most recent in that group. You will find this to be a common practice with many software projects on the internet.

Note, however, that visual inspection alone is not good enough for your steps file. New versions may be released, and your steps file needs to obtain the most recent version available. To facilitate this task, the latest and greatest version of pipemath will be listed in a text file called “LATEST” (which you should see near the top of the directory index listing). You can make use of this file to assist you in automating the process of determining and downloading the latest version of the pipemath tools.

Once those two steps are complete, you can begin on the tasks listed in your TASK file.

numbers suite

The numbers suite is basically a collection of command-line tools whose purpose is to display a single digit number, in accordance with the tool's name.

For example, when you run the zero tool, a 0 is displayed. For one, a 1 is displayed. And so on up through nine.

You are to use these tools for producing the numbers needed for calculation, and only these tools.

Note that they may have a default mode of operation, which may be inconvenient or incompatible with what other tools or facilities require for normal operation. If you read the instructions you can determine how to alter this default behaviour at runtime.

pipemath suite

The pipemath suite is a collection of command-line tools that perform various basic math operations you may find useful for this project. The tools include:

  • plus - addition
  • minus - subtraction
  • multby - multiplication
  • divideby - division
  • modulus - modulus/remainder
  • abs - absolute value
  • negate - negation
  • negify - absolute negation
  • sqrt - square root

With the exception of abs, negate, negify, and sqrt, all the tools require two inputs (known as a binary operator; note, this is NOT saying you need to enter binary numbers into them… they expect decimal values). The first input MUST come from STDIN. The second input MUST come from the first command-line argument.

The tool, with the appropriate inputs, will perform the operation and output its result to STDOUT.

The abs, negate, negify, and sqrt tools require only one input (known as a unary operator). That input must come from STDIN. When given an appropriate input, the operation is performed and will output its result to STDOUT.

Process

In the TASK file, you will be given a set of tasks you need to construct command-lines for to solve, using the tools provided to you in both the numbers and pipemath suites. You will also want to make use of pipes and command expansions in your solutions.

There will also be result, numbers, operations, minimum pipes, and maximum pipes constraints listed for each problem, which you will need to abide by in order to receive full credit.

The potential constraints are as follows:

  • ANY: no restrictions, any in applicable category can be used
  • ONLY: you are restricted to only those listed
  • WITH_LIMITS: usually providing specific restrictions within an ANY domain
  • EXCEPT: you are explicitly not allowed to use the listed; usually restricting an existing ANY domain

There may also be quantity limits on how many times you can use each number or operation. If so, such will be shown in parenthesis following the item in question.

Also, no cheating with idle “filler” operations, like “plus 0 | plus 0 | plus 0” to rack up needed pipe counts.

As an example, take the following (formatted is it would appear in your TASK file):

task: 0
result: 4
numbers: ONLY(three(2), five, seven, nine)
operations: ANY
min_pipes: 2
max_pipes: ANY

With these in mind, we can set about solving this problem, using the tools in combination to arrive at the desired result.

A potential solution would be as follows:

yourpi~:~/src/SEMESTER/unix/upf0$ seven | minus `three`
4
yourpi~:~/src/SEMESTER/unix/upf0$ 

BUT, we see that the min_pipes requirement is 2, and we only have 1 here… so we'll need to come up with another solution.

How about:

yourpi~:~/src/SEMESTER/unix/upf0$ three | minus `seven` | negate
4
yourpi~:~/src/SEMESTER/unix/upf0$ 

There we go… still got our 4, but this time via the minimum required quantity of pipes.

In this case, we'll want to record our command-line in the appropriate place. Since this is task #0, we'll want to record it in a file called: task0.cli, which should basically just contain the command-line you ran, merely placed in a text file.

For example, if you cat the file, you should see the following:

yourpi~:~/src/SEMESTER/unix/upf0$ cat task0.cli
three | minus `seven` | negate
yourpi~:~/src/SEMESTER/unix/upf0$ 

Basically, each task#.cli can be its own script. If we were to execute it, the correct result should be produced.

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}"
    let count=count-1
done

A couple changes from the if syntax: we use do to open the body, and done to resolve it. There's also no else-type countercase logic available. The loop is either running, or it terminates.

To be sure, we can also run while loops on string comparisons:

value="true"
while [ ! "${value}" = "false" ]; do
    statement(s)
    if [ condition ]; then
        value="false"
    fi
    other_statement(s)
done

upf0steps

You will once again be creating a steps file that can automate your project.

As in previous projects, upf0steps will contain the steps you took from the point of downloading the pipemath suite up until the submit step (hint: just run the task#.cli scripts within the steps script).

  • To clarify: YES, downloading files in question, extracting, compiling, installing, and then of course running each individual task#.cli script.

There are some additional constraints you need to keep in mind:

  • your script should not produce ANY STDERR output
  • your script should ONLY produce STDOUT output in conformance with the below stated requirements. Any other output needs to be silenced.
  • For each task, you'll want to display things as follows:
    • “Task X result is: #”
      • where X is the task number (0, 1, 2, etc.)
      • where # is the calculated output matching the TASK file result requested (ie, you must run your task#.cli script to produce this output).
        • note that the task#.cli output appears on the SAME line as the “Task X result is:” text, and there is a single space separating it from the colon.
  • additionally, your upf0steps file will only create, alter files if run by you. If run by a user who is not you, skip the file manipulation and only output the results.
  • you will be making use of a loop to drive the execution of your results (the “Task # result is: …”).

For example, a sample output of your upf0steps script should appear like follows (but your # values will of course be different based on your individual TASK file):

yourpi~:~/src/SEMESTER/unix/upf0$ ./upf0steps
Task 0 result is: 13
Task 1 result is: 27
Task 2 result is: 32
Task 3 result is: 7
Task 4 result is: -4
Task 5 result is: 57
Task 6 result is: 2
Task 7 result is: 98
yourpi~:~/src/SEMESTER/unix/upf0$ 

Submission

By successfully performing this project, you should have a set of task#.cli files (one for each task). You will want to submit these, along with a upf0steps file.

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

$ submit unix upf0 upf0steps task*.cli
Submitting unix project "upf0":
    -> upf0steps(OK)
    -> task0.cli(OK)
    -> task1.cli(OK)
    -> task2.cli(OK)
    -> task3.cli(OK)
       ...

SUCCESSFULLY SUBMITTED

You should get some sort of confirmation indicating successful submission if all went according to plan. If not, check for typos and or locational mismatches.

I'll be looking for the following:

104:upf0:final tally of results (104/104)
*:upf0:upf0steps has valid list of non-interactive instructions [13/13]
*:upf0:upf0steps only modifies files if USER matches [13/13]
*:upf0:upf0steps obtains, builds latest pipemath release [13/13]
*:upf0:upf0steps only displays specified STDOUT output [13/13]
*:upf0:upf0steps uses command expansions to get information [13/13]
*:upf0:upf0steps uses a loop to drive numbers in final output [13/13]
*:upf0:all files are organized, clear, and easy to read [13/13]
*:upf0:task#.cli files have solution within given constraints [13/13]

Additionally:

  • Solutions not abiding by SPIRIT of project will be subject to a 50% 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 and are not easy to read (within 90 char width) are subject to a 25% overall deduction
haas/spring2024/unix/projects/upf0.txt · Last modified: 2023/10/21 16:23 by 127.0.0.1