haas/spring2026/unix/projects/upf0.md
... ...
@@ -0,0 +1,462 @@
1
+# CSCS1730 UNIX/Linux Fundamentals
2
+
3
+# PROJECT: UNIX PIPE FUN (upf0)
4
+
5
+## OBJECTIVE
6
+
7
+To continue to cultivate your problem solving skills, to practice your
8
+shell skills, and to demonstrate your basic scripting skills.
9
+
10
+## BACKGROUND
11
+
12
+Pipes and command expansions are important concepts and skills that you
13
+need to be familiar with as we proceed down the shell scripting rabbit
14
+hole.
15
+
16
+This project has us playing with various examples that will require
17
+regular use of these skills, for the purpose of throwing numbers and
18
+math operations together to produce desired results (and in desired
19
+composition).
20
+
21
+It can be helpful to fully read and understand the instructions
22
+associated with resources. This can take the form of comments in a source
23
+code or configuration file, or even actual instructions. If you see
24
+conspicuously-named files hinting at some action that you can take, you
25
+may want to investigate said file to see if it might aid you in some
26
+capacity.
27
+
28
+## SELECTION
29
+
30
+Occasionally during the automation of a task, you will have need for the
31
+computer to make a decision based on the state of a condition to decide
32
+how to proceed. We accomplish this via the **if** selection structure.
33
+
34
+In bash, an **if** takes the following form:
35
+
36
+```
37
+if [ condition ]; then
38
+ statement(s)
39
+fi
40
+```
41
+
42
+The "condition" are valid arguments posed to the `[`(1) command,
43
+resulting in a true or false result.
44
+
45
+There are one or more statements within the body of the if (to be run in
46
+the event the result of the condition tests true), and the structure is
47
+terminated with the trailing **fi** (if spelled backwards).
48
+
49
+We also have the ability to react in the event the **if** condition tests
50
+false, and that is with an optional **else** statement (which is used 0
51
+or 1 times per if, and must always follow the if):
52
+
53
+```
54
+if [ condition ]; then
55
+ statement(s)
56
+else
57
+ statement(s)
58
+fi
59
+```
60
+
61
+The **else** has no condition: it is a reaction to the previously tested
62
+condition being false.
63
+
64
+## CONDITIONS
65
+
66
+The conditions we pose to the computer must be such that resolve
67
+ultimately to a true or false result.
68
+
69
+Each condition can be unary or binary in nature, meaning we can directly
70
+check the state of one thing, or compare the relationship between two
71
+things.
72
+
73
+For example, the `-z` argument to `[`(1) tests for a NULL string. If we
74
+wanted to see if a variable as a result of some operation were NULL or
75
+populated, we could do:
76
+
77
+```
78
+check=$(/usr/bin/who | grep 'jsmith12' | wc -l | grep '^1$')
79
+if [ -z "${check}" ]; then
80
+ statement(s) # do this if check is NULL
81
+fi
82
+```
83
+
84
+Note that we could also check the opposite. We can use the **!** symbol
85
+to require the opposite (NOT):
86
+
87
+```
88
+check=$(/usr/bin/who | grep 'jsmith12' | wc -l | grep '^1$')
89
+if [ ! -z "${check}" ]; then
90
+ statement(s) # do this if check is NOT NULL
91
+fi
92
+```
93
+
94
+Comparing two strings, the two common scenarios we tend to care about is
95
+whether or not the two strings are equal or not equal:
96
+
97
+```
98
+string1="blah"
99
+string2="boop"
100
+
101
+if [ "${string1}" = "${string2}" ]; then
102
+ statement(s) # do this in the event strings are equal
103
+fi
104
+
105
+if [ ! "${string1}" = "${string2}" ]; then
106
+ statement(s) # do this in the event strings are NOT equal
107
+fi
108
+```
109
+
110
+It should be stated that instead of negating the result, we could also
111
+just use an **else** clause:
112
+
113
+```
114
+string1="blah"
115
+string2="boop"
116
+
117
+if [ "${string1}" = "${string2}" ]; then
118
+ statement(s) # do this in the event strings are equal
119
+else
120
+ statement(s) # do this in the event strings are not equal
121
+fi
122
+```
123
+
124
+As a matter of style (and to potentially avoid syntax/logic errors being
125
+committed), one should not pose a condition just for the sake of ensuring
126
+its opposite (ie no empty clauses).
127
+
128
+If comparing numerical values, especially in numerical contexts, we have
129
+a set of arguments we can choose from:
130
+
131
+ * **-eq** - is equal to
132
+ * **-ne** - is not equal to
133
+ * **-lt** - is less than
134
+ * **-le** - is less than or equal to
135
+ * **-gt** - is greater than
136
+ * **-ge** - is greater than or equal to
137
+
138
+These of course are binary conditions, meaning we compare TWO variables
139
+to see if they possess the indicated relation (which results in a true or
140
+false result produced).
141
+
142
+## LOOPS
143
+
144
+When you have a section of code you would like to repeat some number of
145
+times, a loop can be used to achieve this.
146
+
147
+Here we will explore the **while** conditional loop. If an if statement
148
+can run 0 or 1 times, a while loop can run 0 or more.
149
+
150
+```
151
+count=10
152
+while [ "${count}" -gt 0 ]; do
153
+ echo "count is: ${count}"
154
+ let count=count-1
155
+done
156
+```
157
+
158
+A couple changes from the if syntax: we use **do** to open the body, and
159
+**done** to resolve it. There's also no else-type countercase logic
160
+available. The loop is either running, or it terminates.
161
+
162
+To be sure, we can also run while loops on string comparisons:
163
+
164
+```
165
+value="true"
166
+while [ ! "${value}" = "false" ]; do
167
+ statement(s)
168
+ if [ condition ]; then
169
+ value="false"
170
+ fi
171
+ other_statement(s)
172
+done
173
+```
174
+
175
+## NO GRABIT
176
+
177
+As part of this activity is to test your ability to navigate around the
178
+filesystem and manipulate files on your own, there is no grabit
179
+configured for this project.
180
+
181
+Navigate to the UNIX PUBLIC DIRECTORY yourself and manually copy your
182
+project files back into your repository.
183
+
184
+## GET STARTED
185
+
186
+This week's project has 2 points of origin.
187
+
188
+First, in the **upf0/** sub-directory of the UNIX Public Directory, you
189
+will find the following archive:
190
+
191
+ * **numbers.tgz**
192
+
193
+Then, under a directory by the name of your username within that same
194
+directory, there will be another file:
195
+
196
+ * **TASK**
197
+
198
+Copy both of these files into your project directory.
199
+
200
+The **TASK** file will contain the particular command-line equations you
201
+have to perform, along with their stated constraints.
202
+
203
+The **numbers.tgz** file needs to be extracted, compiled, and installed;
204
+there is a README file located within the archive with further
205
+instructions on how to do this.
206
+
207
+Next, you will want to grab the latest version of the **pipemath** suite
208
+from the following URL:
209
+
210
+ * https://lab46.g7n.org/~wedge/projects/pipemath/
211
+
212
+You will want to use a tool like **wget(1)** or **curl(1)** to
213
+non-interactively download it into your work directory, and similarly
214
+extract, compile, and install that (check its own README file).
215
+
216
+There may be multiple versions of **pipemath** available at the download
217
+link. Unless you have specific reason otherwise (for this project, you do
218
+not), you want to go for the latest version, which will be reflected by
219
+the most recent datestamp encoded in the file's name.
220
+
221
+For example, say you have the following:
222
+
223
+ * pipemath-20160731-10.tar.gz
224
+ * pipemath-20161024-14.tar.gz
225
+ * pipemath-20170123-13.tar.gz
226
+ * pipemath-20170201-09.tar.gz
227
+ * pipemath-20210321-17.tar.gz
228
+ * pipemath-20220401-02.tar.gz
229
+
230
+From visual inspection, you would select the "20220401-02" one, because
231
+the date it encodes (April 1st, 2022 at 2am) is the most recent in that
232
+group. You will find this to be a common practice with many software
233
+projects on the internet.
234
+
235
+Note, however, that visual inspection alone is not good enough for your
236
+steps file. New versions may be released, and your steps file needs to
237
+obtain the most recent version available. To facilitate this task, the
238
+latest and greatest version of pipemath will be listed in a text file
239
+called "LATEST" (which you should see near the top of the directory index
240
+listing). You can make use of this file to assist you in automating the
241
+process of determining and downloading the latest version of the pipemath
242
+tools.
243
+
244
+Once those two steps are complete, you can begin on the tasks listed in
245
+your **TASK** file.
246
+
247
+### NUMBERS SUITE
248
+
249
+The numbers suite is basically a collection of command-line tools whose
250
+purpose is to display a single digit number, in accordance with the
251
+tool's name.
252
+
253
+For example, when you run the **zero** tool, a **0** is displayed. For
254
+**one**, a **1** is displayed. And so on up through **nine**.
255
+
256
+You are to use these tools for producing the numbers needed for
257
+calculation, and only these tools.
258
+
259
+Note that they may have a default mode of operation, which may be
260
+inconvenient or incompatible with what other tools or facilities require
261
+for normal operation. If you read the instructions you can determine how
262
+to alter this default behaviour at runtime.
263
+
264
+### PIPEMATH SUITE
265
+
266
+The pipemath suite is a collection of command-line tools that perform
267
+various basic math operations you may find useful for this project. The
268
+tools include:
269
+
270
+ * **plus** - addition
271
+ * **minus** - subtraction
272
+ * **multby** - multiplication
273
+ * **divideby** - division
274
+ * **modulus** - modulus/remainder
275
+ * **abs** - absolute value
276
+ * **negate** - negation
277
+ * **negify** - absolute negation
278
+ * **sqrt** - square root
279
+
280
+With the exception of **abs**, **negate**, **negify**, and **sqrt**, all
281
+the tools require two inputs (known as a binary operator; note, this is
282
+**NOT** saying you need to enter binary numbers into them... they expect
283
+decimal values). The first input **MUST** come from STDIN. The second
284
+input **MUST** come from the first command-line argument.
285
+
286
+The tool, with the appropriate inputs, will perform the operation and
287
+output its result to STDOUT.
288
+
289
+The **abs**, **negate**, **negify**, and **sqrt** tools require only one
290
+input (known as a unary operator). That input **must** come from STDIN.
291
+When given an appropriate input, the operation is performed and will
292
+output its result to STDOUT.
293
+
294
+## PROCESS
295
+
296
+In the **TASK** file, you will be given a set of tasks you need to
297
+construct command-lines for to solve, using the tools provided to you in
298
+both the **numbers** and **pipemath** suites. You will also want to make
299
+use of pipes and command expansions in your solutions.
300
+
301
+There will also be result, numbers, operations, minimum pipes, and
302
+maximum pipes constraints listed for each problem, which you will need to
303
+abide by in order to receive full credit.
304
+
305
+The potential constraints are as follows:
306
+
307
+ * **ANY:** no restrictions, any in applicable category can be used
308
+ * **ONLY:** you are restricted to only those listed
309
+ * **WITH_LIMITS:** usually providing specific restrictions within an **ANY** domain
310
+ * **EXCEPT:** you are explicitly not allowed to use the listed; usually restricting an existing **ANY** domain
311
+
312
+There may also be quantity limits on how many times you can use each
313
+number or operation. If so, such will be shown in parenthesis following
314
+the item in question.
315
+
316
+Also, no cheating with idle "filler" operations, like "plus 0 | plus 0 |
317
+plus 0" to rack up needed pipe counts.
318
+
319
+As an example, take the following (formatted is it would appear in your
320
+**TASK** file):
321
+
322
+```
323
+task: 0
324
+result: 4
325
+numbers: ONLY(three(2), five, seven, nine)
326
+operations: ANY
327
+min_pipes: 2
328
+max_pipes: ANY
329
+```
330
+
331
+With these in mind, we can set about solving this problem, using the
332
+tools in combination to arrive at the desired result.
333
+
334
+A potential solution would be as follows:
335
+
336
+```
337
+yoursystem~:~/src/SEMESTER/unix/upf0$ seven | minus `three`
338
+4
339
+yoursystem~:~/src/SEMESTER/unix/upf0$
340
+```
341
+
342
+BUT, we see that the **min_pipes** requirement is 2, and we only have 1
343
+here... so we'll need to come up with another solution.
344
+
345
+How about:
346
+
347
+```
348
+yoursystem~:~/src/SEMESTER/unix/upf0$ three | minus `seven` | negate
349
+4
350
+yoursystem~:~/src/SEMESTER/unix/upf0$
351
+```
352
+
353
+There we go... still got our 4, but this time via the minimum required
354
+quantity of pipes.
355
+
356
+In this case, we'll want to record our command-line in the appropriate
357
+place. Since this is task #0, we'll want to record it in a file called:
358
+**task0.cli**, which should basically just contain the command-line you
359
+ran, merely placed in a text file.
360
+
361
+For example, if you **cat** the file, you should see the following:
362
+
363
+```
364
+yoursystem~:~/src/SEMESTER/unix/upf0$ cat task0.cli
365
+three | minus `seven` | negate
366
+yoursystem~:~/src/SEMESTER/unix/upf0$
367
+```
368
+
369
+Basically, each task#.cli can be its own script. If we were to execute
370
+it, the correct result should be produced.
371
+
372
+## UPF0STEPS
373
+
374
+You will once again be creating a steps file that can automate your
375
+project.
376
+
377
+As in previous projects, **upf0steps** will contain the steps you took
378
+from the point of downloading the pipemath suite up until the submit step
379
+(hint: just run the task#.cli scripts within the steps script).
380
+
381
+To clarify: YES, downloading files in question, extracting, compiling,
382
+installing, and then of course running each individual task#.cli script.
383
+
384
+There are some additional constraints you need to keep in mind:
385
+
386
+ * your script should not produce ANY STDERR output
387
+ * your script should ONLY produce STDOUT output in conformance with the below stated requirements. Any other output needs to be silenced.
388
+ * For each task, you'll want to display things as follows:
389
+ * "Task X result is: #"
390
+ * where X is the task number (0, 1, 2, etc.)
391
+ * where # is the calculated output matching the TASK file result requested (ie, you must run your task#.cli script to produce this output).
392
+ * 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.
393
+ * 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.
394
+ * you will be making use of a loop to drive the execution of your results (the "Task # result is: ...").
395
+
396
+For example, a sample output of your **upf0steps** script should appear
397
+like follows (but your # values will of course be different based on your
398
+individual **TASK** file):
399
+
400
+```
401
+yoursystem~:~/src/SEMESTER/unix/upf0$ ./upf0steps
402
+Task 0 result is: 13
403
+Task 1 result is: 27
404
+Task 2 result is: 32
405
+Task 3 result is: 7
406
+Task 4 result is: -4
407
+Task 5 result is: 57
408
+Task 6 result is: 2
409
+Task 7 result is: 98
410
+yoursystem~:~/src/SEMESTER/unix/upf0$
411
+```
412
+
413
+## SUBMISSION
414
+
415
+By successfully performing this project, you should have a set of
416
+`task#.cli` files (one for each task). You will want to submit these,
417
+along with a **upf0steps** file.
418
+
419
+### SUBMIT TOOL USAGE
420
+
421
+To submit this project to me using the **submit** tool, run the following
422
+command at your lab46 prompt:
423
+
424
+```
425
+lab46:~/src/SEMESTER/unix/upf0$ submit unix upf0 upf0steps task*.cli
426
+Submitting unix project "upf0":
427
+ -> upf0steps(OK)
428
+ -> task0.cli(OK)
429
+ -> task1.cli(OK)
430
+ -> task2.cli(OK)
431
+ -> task3.cli(OK)
432
+ ...
433
+
434
+SUCCESSFULLY SUBMITTED
435
+```
436
+
437
+You should get some sort of confirmation indicating successful submission
438
+if all went according to plan. If not, check for typos and or locational
439
+mismatches.
440
+
441
+### RUBRIC
442
+
443
+I'll be looking for the following:
444
+
445
+```
446
+143:upf0:final tally of results (143/143)
447
+*:upf0:upf0steps has valid list of non-interactive instructions [13/13]
448
+*:upf0:upf0steps only modifies files if USER matches [26/26]
449
+*:upf0:upf0steps obtains, builds latest pipemath release [26/26]
450
+*:upf0:upf0steps only displays specified STDOUT output [13/13]
451
+*:upf0:upf0steps uses command expansions to get information [13/13]
452
+*:upf0:upf0steps uses a loop to drive numbers in final output [13/13]
453
+*:upf0:all files are organized, clear, and easy to read [13/13]
454
+*:upf0:task#.cli files have solution within given constraints [13/13]
455
+*:upf0:files tracked in lab46 semester repository [13/13]
456
+```
457
+
458
+Additionally:
459
+ * Solutions not abiding by spirit of project will be subject to a 50% overall deduction
460
+ * Solutions not utilizing descriptive why and how comments will be subject to a 25% overall deduction
461
+ * Solutions not utilizing indentation to promote scope and clarity will be subject to a 25% overall deduction
462
+ * Solutions not organized and easy to read are subject to a 25% overall deduction