haas/spring2026/unix/projects/pwn0.md
... ...
@@ -0,0 +1,939 @@
1
+# CSCS1730 UNIX/Linux Fundamentals
2
+
3
+# PROJECT: PROCESSING WARRANTED NUMBERS (pwn0)
4
+
5
+## TOOLBOX
6
+
7
+In addition to the tools you're already familiar with, it is recommended
8
+you check out the following tools for possible application in this
9
+project (you may not need to use them in your solution, but they
10
+definitely offer up functionality that some solutions can make use of):
11
+
12
+ * **bc(1)**
13
+ * **comm(1)**
14
+ * **diff(1)**
15
+ * **grep(1)**
16
+ * **join(1)**
17
+ * **printf(1)**
18
+ * **seq(1)**
19
+ * **sort(1)**
20
+ * **uniq(1)**
21
+
22
+## REFERENCE
23
+
24
+For additional information on the **printf(1)** tool recommended for use
25
+in this project, please check out this paper:
26
+
27
+ * {{:haas:printf.pdf|printf PDF}}
28
+
29
+NOTE that while it focuses on the C and Perl variants of printf, the
30
+conceptual underpinnings are the same, and many of the examples are
31
+likely portable to the UNIX variant of the tool.
32
+
33
+## OBJECTIVE
34
+
35
+To create a script that can, with or without information provided by the
36
+user, display useful reference data in various number bases.
37
+
38
+## BACKGROUND
39
+
40
+We've encountered many things in our UNIX journey so far, and have been
41
+readily building upon past experiences as we achieve newer and better
42
+successes. Of particular focus, we've been looking at shell scripting,
43
+and that will be the primary focus of this week's project.
44
+
45
+There are collections of information quite useful to anyone journeying
46
+in a discipline, and computing is no different: We often encounter
47
+information represented in certain units more than others, or various
48
+quantities, or even particular number bases.
49
+
50
+### BINARY/OCTAL/HEX
51
+
52
+One particular collection of information involves that of binary, octal,
53
+decimal (in signed and unsigned capacities) and hexadecimal numbers. We
54
+may encounter a tool that gives us information in octal and we need to
55
+feed it into another tool as binary or decimal; these sorts of
56
+transactions are common and crop up time and time again.
57
+
58
+Having a strong handle on this information is vital for on-going success
59
+in the computing field.
60
+
61
+As such, it is important to have close at hand the knowledge of the
62
+following number bases:
63
+
64
+ * base 2 (binary)
65
+ * base 8 (octal)
66
+ * base 10 (decimal, specifically signed and unsigned quantities)
67
+ * base 16 (hexadecimal)
68
+
69
+While we don't need to have hundreds of values memorized, it IS a good
70
+idea to have a rather quick recollection of enough values that can be
71
+used for debugging purposes. The first 16 values of each of these is such
72
+a preferred range. Not only does it give us a range of information, but
73
+for the powers-of-two bases, can actually fit in and be propagated quite
74
+nicely with little added effort.
75
+
76
+## PROCESS
77
+
78
+It is your task to write a script that, when run without any arguments,
79
+produces the following table of information (and displayed/formatted in
80
+this exact manner):
81
+
82
+```
83
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh
84
+ base 2 | base 8 | base10 | base16 |
85
+----------+----------+----------+----------+
86
+ 0 | 0 | 0 | 0 |
87
+ 1 | 1 | 1 | 1 |
88
+ 10 | 2 | 2 | 2 |
89
+ 11 | 3 | 3 | 3 |
90
+ 100 | 4 | 4 | 4 |
91
+ 101 | 5 | 5 | 5 |
92
+ 110 | 6 | 6 | 6 |
93
+ 111 | 7 | 7 | 7 |
94
+ 1000 | 10 | 8 | 8 |
95
+ 1001 | 11 | 9 | 9 |
96
+ 1010 | 12 | 10 | A |
97
+ 1011 | 13 | 11 | B |
98
+ 1100 | 14 | 12 | C |
99
+ 1101 | 15 | 13 | D |
100
+ 1110 | 16 | 14 | E |
101
+ 1111 | 17 | 15 | F |
102
+lab46:~/src/SEMESTER/unix/pwn0$
103
+```
104
+
105
+Your script should also take the following optional arguments (in this
106
+order):
107
+
108
+ * **$1**- starting value (some value greater than or equal to 0, and less than 256)
109
+ * **$2**- ending value (some value greater than or equal to 0, and less than 256)
110
+
111
+Numerical arguments are to be given in decimal.
112
+
113
+Additional arguments your script should support:
114
+
115
+ * **by#** - iterate through values by # (default: 1)
116
+ * **with#** - include base # in the list of bases to display
117
+ * **sans#** - remove base # in the list of bases to display
118
+ * **help** - display script usage and exit
119
+
120
+With any of these arguments validly provided, they should adjust the
121
+script's processing and output accordingly.
122
+
123
+Some additional constraints/assumptions you can make:
124
+
125
+ * the minimum lower limit your script should process for is **0**. If an input goes negative, cap it to 0.
126
+ * the maximum upper limit you can implement for is **255** (base 10). If an input goes in excess of this, cap it to 255.
127
+
128
+### ONLY SPECIFYING STARTING VALUE
129
+
130
+In the event only the starting value is specified, assume a count of 16
131
+(so display 16 values, starting at the starting value).
132
+
133
+For example:
134
+
135
+```
136
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 12
137
+ base 2 | base 8 | base10 | base16 |
138
+----------+----------+----------+----------+
139
+ 1100 | 14 | 12 | C |
140
+ 1101 | 15 | 13 | D |
141
+ 1110 | 16 | 14 | E |
142
+ 1111 | 17 | 15 | F |
143
+ 10000 | 20 | 16 | 10 |
144
+ 10001 | 21 | 17 | 11 |
145
+ 10010 | 22 | 18 | 12 |
146
+ 10011 | 23 | 19 | 13 |
147
+ 10100 | 24 | 20 | 14 |
148
+ 10101 | 25 | 21 | 15 |
149
+ 10110 | 26 | 22 | 16 |
150
+ 10111 | 27 | 23 | 17 |
151
+ 11000 | 30 | 24 | 18 |
152
+ 11001 | 31 | 25 | 19 |
153
+ 11010 | 32 | 26 | 1A |
154
+ 11011 | 33 | 27 | 1B |
155
+lab46:~/src/SEMESTER/unix/pwn0$
156
+```
157
+
158
+### SPECIFYING STARTING AND ENDING VALUE
159
+
160
+We can adjust the range displayed by specifying an ending value as well:
161
+
162
+```
163
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 37 42
164
+ base 2 | base 8 | base10 | base16 |
165
+----------+----------+----------+----------+
166
+ 100101 | 45 | 37 | 25 |
167
+ 100110 | 46 | 38 | 26 |
168
+ 100111 | 47 | 39 | 27 |
169
+ 101000 | 50 | 40 | 28 |
170
+ 101001 | 51 | 41 | 29 |
171
+ 101010 | 52 | 42 | 2A |
172
+lab46:~/src/SEMESTER/unix/pwn0$
173
+```
174
+
175
+With a specified starting/ending value pair, we can display as little as
176
+1 value and (theoretically) as many as we want.
177
+
178
+### GOING BACKWARDS
179
+
180
+It shouldn't matter the relationship of starting and ending values. In
181
+fact, if the starting value is HIGHER than the ending value, the count
182
+should go backwards:
183
+
184
+```
185
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 73 59
186
+ base 2 | base 8 | base10 | base16 |
187
+----------+----------+----------+----------+
188
+ 1001001 | 111 | 73 | 49 |
189
+ 1001000 | 110 | 72 | 48 |
190
+ 1000111 | 107 | 71 | 47 |
191
+ 1000110 | 106 | 70 | 46 |
192
+ 1000101 | 105 | 69 | 45 |
193
+ 1000100 | 104 | 68 | 44 |
194
+ 1000011 | 103 | 67 | 43 |
195
+ 1000010 | 102 | 66 | 42 |
196
+ 1000001 | 101 | 65 | 41 |
197
+ 1000000 | 100 | 64 | 40 |
198
+ 111111 | 77 | 63 | 3F |
199
+ 111110 | 76 | 62 | 3E |
200
+ 111101 | 75 | 61 | 3D |
201
+ 111100 | 74 | 60 | 3C |
202
+ 111011 | 73 | 59 | 3B |
203
+lab46:~/src/SEMESTER/unix/pwn0$
204
+```
205
+
206
+### SKIPPING VALUES
207
+
208
+With the 'by#' argument, we can cause numbers to iterate by more than 1.
209
+For example, if we wanted to go from 3 to 81 skipping 3 values each turn:
210
+
211
+```
212
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 3 81 by3
213
+ base 2 | base 8 | base10 | base16 |
214
+----------+----------+----------+----------+
215
+ 11 | 3 | 3 | 3 |
216
+ 110 | 6 | 6 | 6 |
217
+ 1001 | 11 | 9 | 9 |
218
+ 1100 | 14 | 12 | C |
219
+ 1111 | 17 | 15 | F |
220
+ 10010 | 22 | 18 | 12 |
221
+ 10101 | 25 | 21 | 15 |
222
+ 11000 | 30 | 24 | 18 |
223
+ 11011 | 33 | 27 | 1B |
224
+ 11110 | 36 | 30 | 1E |
225
+ 100001 | 41 | 33 | 21 |
226
+ 100100 | 44 | 36 | 24 |
227
+ 100111 | 47 | 39 | 27 |
228
+ 101010 | 52 | 42 | 2A |
229
+ 101101 | 55 | 45 | 2D |
230
+ 110000 | 60 | 48 | 30 |
231
+ 110011 | 63 | 51 | 33 |
232
+ 110110 | 66 | 54 | 36 |
233
+ 111001 | 71 | 57 | 39 |
234
+ 111100 | 74 | 60 | 3C |
235
+ 111111 | 77 | 63 | 3F |
236
+ 1000010 | 102 | 66 | 42 |
237
+ 1000101 | 105 | 69 | 45 |
238
+ 1001000 | 110 | 72 | 48 |
239
+ 1001011 | 113 | 75 | 4B |
240
+ 1001110 | 116 | 78 | 4E |
241
+ 1010001 | 121 | 81 | 51 |
242
+lab46:~/src/SEMESTER/unix/pwn0$
243
+```
244
+
245
+This should be flexible whether going forward or backward in count:
246
+
247
+```
248
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 32 2 by4
249
+ base 2 | base 8 | base10 | base16 |
250
+----------+----------+----------+----------+
251
+ 100000 | 40 | 32 | 20 |
252
+ 11100 | 34 | 28 | 1C |
253
+ 11000 | 30 | 24 | 18 |
254
+ 10100 | 24 | 20 | 14 |
255
+ 10000 | 20 | 16 | 10 |
256
+ 1100 | 14 | 12 | C |
257
+ 1000 | 10 | 8 | 8 |
258
+ 100 | 4 | 4 | 4 |
259
+lab46:~/src/SEMESTER/unix/pwn0$
260
+```
261
+
262
+### EXCEEDING BOUNDS
263
+
264
+Although our script does not need to iterate values outside the 0-255
265
+range, it does need to check and cap values that exceed these bounds.
266
+
267
+For example, if a starting or ending value falls beyond 255, cap it to
268
+255:
269
+
270
+```
271
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 250
272
+ base 2 | base 8 | base10 | base16 |
273
+----------+----------+----------+----------+
274
+ 11111010 | 372 | 250 | FA |
275
+ 11111011 | 373 | 251 | FB |
276
+ 11111100 | 374 | 252 | FC |
277
+ 11111101 | 375 | 253 | FD |
278
+ 11111110 | 376 | 254 | FE |
279
+ 11111111 | 377 | 255 | FF |
280
+lab46:~/src/SEMESTER/unix/pwn0$
281
+```
282
+
283
+If we have a negative value of any sort:
284
+
285
+```
286
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 4 -8
287
+ base 2 | base 8 | base10 | base16 |
288
+----------+----------+----------+----------+
289
+ 100 | 4 | 4 | 4 |
290
+ 11 | 3 | 3 | 3 |
291
+ 10 | 2 | 2 | 2 |
292
+ 1 | 1 | 1 | 1 |
293
+ 0 | 0 | 0 | 0 |
294
+lab46:~/src/SEMESTER/unix/pwn0$
295
+```
296
+
297
+Both starting and ending values need to appropriately fall within the
298
+0-255 bounds, however they may be situated.
299
+
300
+### ADDITIONAL BASES
301
+
302
+Your script should also support the inclusion of additional bases (valid
303
+bases are any base between 2 and 16, inclusive). The default bases
304
+assumed included are 2, 8, 10, and 16, but additional ones may be
305
+specified with a **with#** argument.
306
+
307
+For instance, let's say we wanted to include base 7:
308
+
309
+```
310
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh with7
311
+ base 2 | base 7 | base 8 | base10 | base16 |
312
+----------+----------+----------+----------+----------+
313
+ 0 | 0 | 0 | 0 | 0 |
314
+ 1 | 1 | 1 | 1 | 1 |
315
+ 10 | 2 | 2 | 2 | 2 |
316
+ 11 | 3 | 3 | 3 | 3 |
317
+ 100 | 4 | 4 | 4 | 4 |
318
+ 101 | 5 | 5 | 5 | 5 |
319
+ 110 | 6 | 6 | 6 | 6 |
320
+ 111 | 10 | 7 | 7 | 7 |
321
+ 1000 | 11 | 10 | 8 | 8 |
322
+ 1001 | 12 | 11 | 9 | 9 |
323
+ 1010 | 13 | 12 | 10 | A |
324
+ 1011 | 14 | 13 | 11 | B |
325
+ 1100 | 15 | 14 | 12 | C |
326
+ 1101 | 16 | 15 | 13 | D |
327
+ 1110 | 20 | 16 | 14 | E |
328
+ 1111 | 21 | 17 | 15 | F |
329
+lab46:~/src/SEMESTER/unix/pwn0$
330
+```
331
+
332
+And this should work even with the potential inclusion of starting,
333
+ending, or a by# option (forward or backward):
334
+
335
+```
336
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 13 255 by13 with7
337
+ base 2 | base 7 | base 8 | base10 | base16 |
338
+----------+----------+----------+----------+----------+
339
+ 1101 | 16 | 15 | 13 | D |
340
+ 11010 | 35 | 32 | 26 | 1A |
341
+ 100111 | 54 | 47 | 39 | 27 |
342
+ 110100 | 103 | 64 | 52 | 34 |
343
+ 1000001 | 122 | 101 | 65 | 41 |
344
+ 1001110 | 141 | 116 | 78 | 4E |
345
+ 1011011 | 160 | 133 | 91 | 5B |
346
+ 1101000 | 206 | 150 | 104 | 68 |
347
+ 1110101 | 225 | 165 | 117 | 75 |
348
+ 10000010 | 244 | 202 | 130 | 82 |
349
+ 10001111 | 263 | 217 | 143 | 8F |
350
+ 10011100 | 312 | 234 | 156 | 9C |
351
+ 10101001 | 331 | 251 | 169 | A9 |
352
+ 10110110 | 350 | 266 | 182 | B6 |
353
+ 11000011 | 366 | 303 | 195 | C3 |
354
+ 11010000 | 415 | 320 | 208 | D0 |
355
+ 11011101 | 434 | 335 | 221 | DD |
356
+ 11101010 | 453 | 352 | 234 | EA |
357
+ 11110111 | 502 | 367 | 247 | F7 |
358
+lab46:~/src/SEMESTER/unix/pwn0$
359
+```
360
+
361
+Multiple additional bases can be included... you merely append additional
362
+**with#** arguments:
363
+
364
+```
365
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 196 2 with3 by14 with12
366
+ base 2 | base 3 | base 8 | base10 | base12 | base16 |
367
+----------+----------+----------+----------+----------+----------+
368
+ 11000100 | 21021 | 304 | 196 | 144 | C4 |
369
+ 10110110 | 20202 | 266 | 182 | 132 | B6 |
370
+ 10101000 | 20020 | 250 | 168 | 120 | A8 |
371
+ 10011010 | 12201 | 232 | 154 | 10A | 9A |
372
+ 10001100 | 12012 | 214 | 140 | B8 | 8C |
373
+ 1111110 | 11200 | 176 | 126 | A6 | 7E |
374
+ 1110000 | 11011 | 160 | 112 | 94 | 70 |
375
+ 1100010 | 10122 | 142 | 98 | 82 | 62 |
376
+ 1010100 | 10010 | 124 | 84 | 70 | 54 |
377
+ 1000110 | 2121 | 106 | 70 | 5A | 46 |
378
+ 111000 | 2002 | 70 | 56 | 48 | 38 |
379
+ 101010 | 1120 | 52 | 42 | 36 | 2A |
380
+ 11100 | 1001 | 34 | 28 | 24 | 1C |
381
+ 1110 | 112 | 16 | 14 | 12 | E |
382
+lab46:~/src/SEMESTER/unix/pwn0$
383
+```
384
+
385
+### OMITTING BASES
386
+
387
+With the **sans#** option, we can leave out specified bases (useful for
388
+excluding any of the default 2, 8, 10, or 16).
389
+
390
+Here we will omit base 8 from a default run:
391
+
392
+```
393
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh sans8
394
+ base 2 | base10 | base16 |
395
+----------+----------+----------+
396
+ 0 | 0 | 0 |
397
+ 1 | 1 | 1 |
398
+ 10 | 2 | 2 |
399
+ 11 | 3 | 3 |
400
+ 100 | 4 | 4 |
401
+ 101 | 5 | 5 |
402
+ 110 | 6 | 6 |
403
+ 111 | 7 | 7 |
404
+ 1000 | 8 | 8 |
405
+ 1001 | 9 | 9 |
406
+ 1010 | 10 | A |
407
+ 1011 | 11 | B |
408
+ 1100 | 12 | C |
409
+ 1101 | 13 | D |
410
+ 1110 | 14 | E |
411
+ 1111 | 15 | F |
412
+lab46:~/src/SEMESTER/unix/pwn0$
413
+```
414
+
415
+Of course, this option can be validly mixed with any of the other valid
416
+options, and needs to work as appropriate (here you'll see a run we did
417
+prior, with the only difference being the omission of base 8):
418
+
419
+```
420
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 196 2 with3 by14 with12 sans8
421
+ base 2 | base 3 | base10 | base12 | base16 |
422
+----------+----------+----------+----------+----------+
423
+ 11000100 | 21021 | 196 | 144 | C4 |
424
+ 10110110 | 20202 | 182 | 132 | B6 |
425
+ 10101000 | 20020 | 168 | 120 | A8 |
426
+ 10011010 | 12201 | 154 | 10A | 9A |
427
+ 10001100 | 12012 | 140 | B8 | 8C |
428
+ 1111110 | 11200 | 126 | A6 | 7E |
429
+ 1110000 | 11011 | 112 | 94 | 70 |
430
+ 1100010 | 10122 | 98 | 82 | 62 |
431
+ 1010100 | 10010 | 84 | 70 | 54 |
432
+ 1000110 | 2121 | 70 | 5A | 46 |
433
+ 111000 | 2002 | 56 | 48 | 38 |
434
+ 101010 | 1120 | 42 | 36 | 2A |
435
+ 11100 | 1001 | 28 | 24 | 1C |
436
+ 1110 | 112 | 14 | 12 | E |
437
+lab46:~/src/SEMESTER/unix/pwn0$
438
+```
439
+
440
+Multiple **sans#** options can be given, and will cancel out any present
441
+base (including those specified with a **with#** option). A **sans#**
442
+option for a non-existent base should be silently ignored.
443
+
444
+### ONLINE HELP
445
+
446
+Your script should also, when prompted, display usage information with
447
+the **help** option:
448
+
449
+```
450
+lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh help
451
+
452
+ pwn0.sh - render a number table in the specified bases,
453
+ displaying from starting value to ending value.
454
+
455
+ behavior: by default, bases 2, 8, 10, and 16 will be
456
+ displayed, in a range of 0 to 15 (inclusive).
457
+
458
+ note: valid bases range from 2-16, and values should
459
+ not go negative nor exceed 255. If a starting
460
+ value but no ending value is given, assume an
461
+ ending value +15 away (or capped by 255).
462
+
463
+ usage: pwn0.sh [start#] [end#] [OPTION]...
464
+
465
+ options:
466
+ $1 - if a positive decimal value, override the
467
+ starting value (0)
468
+ $2 - if a positive decimal value, override the
469
+ ending value (15)
470
+
471
+ other options:
472
+ by# - iterate through values by # (default: 1)
473
+ with# - include base # in the list of bases to display
474
+ sans# - remove base # in the list of bases to display
475
+ help - display script usage and exit
476
+
477
+lab46:~/src/SEMESTER/unix/pwn0$
478
+```
479
+
480
+## SPECIFICATIONS
481
+
482
+Evaluation will be based on correctness of values as well as on
483
+formatting/spacing.
484
+
485
+You'll notice that everything lines up and is positioned similarly:
486
+
487
+ * each column exists within 10 characters of on-screen real estate:
488
+ * 8 characters for actual value display,
489
+ * with one space padding either side
490
+ * columns are separated with a `|` symbol, appended to the right edge of the column (effectively making each column 11 characters wide).
491
+ * note that the rightmost column is ended with this `|`.
492
+ * 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
493
+ * The dashes and vertical bars set up an ASCII art-like table pattern that helps make the data more readable.
494
+ * The values are right justified with each column
495
+ * justification is essential. Everything should line up on its respective right margin.
496
+ * base headings are right justified, with a 2 spaces being allocated for reference of the base:
497
+ * you'll see "base 2" vs. "base16"; your script needs to accommodate this.
498
+ * You are to literally print out no more than 2 consecutive spaces at a time in your output statements. 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).
499
+ * You need to check your arguments to ensure they are present and valid. Some examples:
500
+ * starting value is a valid (whole) number
501
+ * if less than 0, or greater than 255, needs to be capped to whichever extreme it exceeds
502
+ * if -4, cap to 0
503
+ * if 300, cap to 255
504
+ * ending value is a valid (whole) number
505
+ * if less than 0, or greater than 255, needs to be capped to whichever extreme it exceeds
506
+ * if -8, cap to 0
507
+ * if 420, cap to 255
508
+ * any invalid arguments (nonsensical value in place of starting value, invalid base specification, etc.) should be silently dropped/ignored.
509
+ * 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.
510
+ * if starting and ending values are the same, the script will display just one line of number output (in addition to the header).
511
+ * if lacking any bases to display, silently exit
512
+ * your script needs to commence with a proper **shabang** to bash; your script needs to end with an "**exit 0**" at the very end
513
+ * comments and indentation are required and necessary
514
+ * comments should explain how or why you are doing something
515
+ * indentation should be consistent throughout the script
516
+ * indentation is to be no less than 3 on-screen spaces (I recommend tabstops of 4).
517
+ * continuing with our shell scripting, your script will need to employ in a core/central way:
518
+ * variables
519
+ * command expansions
520
+ * regular expressions
521
+ * if statements
522
+ * loops
523
+ * your logic needs to:
524
+ * flow (one thing leads into the next, as best as possible)
525
+ * make sense within the given context
526
+ * avoid redundancy
527
+ * be understood by you (no grabbing snippets that seem to "work" from the internet)
528
+ * if you gain inspiration from some external resource, please cite it
529
+ * 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)
530
+
531
+To be sure, I'll be checking to make sure you solution follows the spirit
532
+of what this project is about (that you implement functional, flowing
533
+logic utilizing the tools and concepts we've learned, in an application
534
+that helps demonstrate your comprehension). Don't try to weasel your way
535
+out of this or cut corners. This is an opportunity to further solidify
536
+your proficiency with everything.
537
+
538
+## SPIRIT OF PROJECT
539
+
540
+The spirit of the project embodies many aspects we've been focusing on
541
+throughout the semester:
542
+
543
+ * recognizing patterns to employ effective solutions in problem solving
544
+ * utilizing concepts and tools covered
545
+ * demonstrating comprehension of concepts, tools, and problems
546
+ * employing concepts in knowledgeable and thoughtful manner
547
+ * following instructions
548
+ * implementing to specifications
549
+ * utilizing creativity
550
+ * being able to control solution via consistent, clear, and organized presentation
551
+
552
+Basically: I want your solution to be the result of an honest, genuine
553
+brainstorming process where you have (on your own) figured out a path to
554
+solving the problem, you have dabbled and experimented and figured things
555
+out, and you can command the concepts and tools with a fluency enabling
556
+you to pull off such a feat. Your solution should demonstrate the real
557
+learning that took place and experience gained.
558
+
559
+Cutting corners, avoiding work, skimping on functionality, cheating
560
+through getting others to do work for you or finding pre-packaged
561
+"answers" on the internet violates the spirit of the project, for they
562
+betray your ability to pull off the task on your own.
563
+
564
+NOTE: some have instantiated controversy in the past by utilizing AI in a
565
+manner well beyond their abilities. In such cases, submitted work is not
566
+considered your own, and thereby inviting disciplinary action. Don't fall
567
+into that trap.
568
+
569
+### IDENTIFYING SHORTCOMINGS
570
+
571
+I would also like it if you provided an inventory of what functionality
572
+is lacking or out of spec when you submit the project. The better you can
573
+describe your deviations from stated requirements, the more forgiving I
574
+may be during evaluation (versus trying to hide the shortcomings and
575
+hoping I do not discover them).
576
+
577
+The more fluent you are in describing your shortcomings on accomplishing
578
+the project (ie "I didn't know how to do this" is far from fluent), the
579
+better I will be able to gauge your understanding on a particular aspect.
580
+
581
+This can be in the form of comments in your script, or even a separate
582
+file submitted at time of submission (if a file, be sure to make mention
583
+of it in your script so I can be sure to look for it).
584
+
585
+### OUTPUT FORMATTING WITH printf(1)
586
+
587
+You might be wondering how you can pull off some of these output
588
+formatting feats. The **echo** command, after all, is rather rudimentary.
589
+
590
+Fear not! The **printf(1)** tool comes to your rescue!
591
+
592
+Like **echo**, **printf** displays information to the screen (STDOUT). In
593
+fact, various programming languages (like C and C++) that want more
594
+powerful output formatting implement some form of printf into their vast
595
+libraries.
596
+
597
+Be sure to check the manual page for options and functionality; following
598
+will be a few usage examples.
599
+
600
+### printf: BASIC OPERATION
601
+
602
+Like **echo**, **printf** in its simplest form takes as an argument a
603
+string to display to STDOUT:
604
+
605
+```
606
+lab46:~$ printf "Hello, World"
607
+Hello, Worldlab46:~$
608
+```
609
+
610
+However, we notice one difference between the default behavior of
611
+**printf** vs. **echo**: **printf** does not automatically issue a
612
+newline by default, as **echo** does. So, we'll need to specify it
613
+manually with the **\n** character:
614
+
615
+```
616
+lab46:~$ printf "Hello, World\n"
617
+Hello, World
618
+lab46:~$
619
+```
620
+
621
+Those various escape characters we've learned about? Super useful here:
622
+
623
+ * **\n** - newline
624
+ * **\t** - tab
625
+
626
+Be sure to check the manual page for additional escape characters.
627
+
628
+### printf: FORMAT SPECIFIERS
629
+
630
+Now, we know from using **echo** we can utilize shell variable and
631
+command expansions to make our output more dynamic.
632
+
633
+But, **printf** adds additional formatting capability that **echo**
634
+lacks. If the string we are displaying contains **%** symbols,
635
+substitutions can be made and behaviors invoked; functionality that
636
+**echo** lacks.
637
+
638
+Some common format specifiers:
639
+
640
+ * **%d** - substitute integer (whole number) value
641
+ * **%s** - substitute string value
642
+ * **%c** - substitute single character
643
+ * **%f** - substitute floating point value
644
+ * **%o** - substitute integer (whole number) value and represent in octal
645
+ * **%x** - substitute integer (whole number) value and represent in hexadecimal
646
+
647
+First up, a simple example:
648
+
649
+```
650
+lab46:~$ printf "%d\n" 175
651
+175
652
+lab46:~$
653
+```
654
+
655
+Then, adding to it:
656
+
657
+```
658
+lab46:~$ printf "The number: %d\n" 175
659
+The number: 175
660
+lab46:~$
661
+```
662
+
663
+That 175 can also be in a variable:
664
+
665
+```
666
+lab46:~$ value=175
667
+lab46:~$ printf "The number: %d\n" ${value}
668
+The number: 175
669
+lab46:~$
670
+```
671
+
672
+You may want to wrap the variable in double quotes, to avoid cases where
673
+it might be NULL and otherwise generate an error (I generally quote all
674
+my variables to be on the safe side).
675
+
676
+How about substitutions with strings?
677
+
678
+```
679
+lab46:~$ printf "Your username is: %s\n" "${USER}"
680
+Your username is: username
681
+lab46:~$
682
+```
683
+
684
+And in general just crafting super effective format strings:
685
+
686
+```
687
+lab46:~$ value=175
688
+lab46:~$ printf "%d %s %X\n" "${value}" "is hexadecimal" "${value}"
689
+175 is hexadecimal AF
690
+lab46:~$
691
+```
692
+
693
+Please take note, where there are multiple format specifiers,
694
+substitution is in order of specification... **%d** was the first, **%s**
695
+was the second, and **%X** was the third in that particular string, so
696
+the first value following the string is grabbed by the **%d**, the next
697
+the **%s**, and the third the **%X**. Ordering matters (which should make
698
+sense).
699
+
700
+### printf: OUTPUT FORMATTING
701
+
702
+So now, getting to where **printf** really excels, formatting your
703
+output.
704
+
705
+It turns out, that between the **%** and whatever format option you
706
+specify, you can provide a numeric value which will impact how that
707
+number appears on the screen, commonly in the form of preallocated space
708
+to display within.
709
+
710
+For instance:
711
+
712
+```
713
+lab46:~$ printf "Testing: >>%4d<<\n" 47
714
+Testing: >> 47<<
715
+lab46:~$
716
+```
717
+
718
+See what happened there? 47 was displayed, but WITHIN a block of 4
719
+characters. Also of note, by default output is **right justified**.
720
+
721
+To **left** justify, simply make it negative:
722
+
723
+```
724
+lab46:~$ printf "Testing: >>%-4d<<\n" 47
725
+Testing: >>47 <<
726
+lab46:~$
727
+```
728
+
729
+We can also pad with zeros, that is represented by decimal values:
730
+
731
+```
732
+lab46:~$ printf "Testing: >>%.3d<<\n" 49
733
+Testing: >>049<<
734
+lab46:~$
735
+```
736
+
737
+This can be combined with justify and space allocation:
738
+
739
+```
740
+lab46:~$ printf "Testing: >>%-6.3d<<\n" 49
741
+Testing: >>049 <<
742
+lab46:~$
743
+```
744
+
745
+Other neat tricks? We can variable-ize the padding by using a
746
+`*`:
747
+
748
+```
749
+lab46:~$ spacing=4
750
+lab46:~$ printf "Testing: >>%*d<<\n" "${spacing}" 49
751
+Testing: >> 49<<
752
+lab46:~$
753
+```
754
+
755
+The **printf** tool is super-powerful and useful for output, so mastering
756
+its use adds an impressive capability to your repertoire.
757
+
758
+Play with **printf** and experiment... you'll find it can accomplish some
759
+impressive output feats that previously may have been more complicated.
760
+
761
+## SELECTION
762
+
763
+Occasionally during the automation of a task, you will have need for the
764
+computer to make a decision based on the state of a condition to decide
765
+how to proceed. We accomplish this via the **if** selection structure.
766
+
767
+In bash, an **if** takes the following form:
768
+
769
+```
770
+if [ condition ]; then
771
+ statement(s)
772
+fi
773
+```
774
+
775
+The "condition" are valid arguments posed to the `[`(1) command,
776
+resulting in a true or false result.
777
+
778
+There are one or more statements within the body of the if (to be run in
779
+the event the result of the condition tests true), and the structure is
780
+terminated with the trailing **fi** (if spelled backwards).
781
+
782
+We also have the ability to react in the event the **if** condition tests
783
+false, and that is with an optional **else** statement (which is used 0
784
+or 1 times per if, and must always follow the if):
785
+
786
+```
787
+if [ condition ]; then
788
+ statement(s)
789
+else
790
+ statement(s)
791
+fi
792
+```
793
+
794
+The **else** has no condition: it is a reaction to the previously tested
795
+condition being false.
796
+
797
+### CONDITIONS
798
+
799
+The conditions we pose to the computer must be such that resolve
800
+ultimately to a true or false result.
801
+
802
+Each condition can be unary or binary in nature, meaning we can directly
803
+check the state of one thing, or compare the relationship between two
804
+things.
805
+
806
+For example, the **-z** argument to **[**(**1**) tests for a NULL string.
807
+If we wanted to see if a variable as a result of some operation were NULL
808
+or populated, we could do:
809
+
810
+```
811
+check=$(/usr/bin/who | grep 'jsmith12' | wc -l | grep '^1$')
812
+if [ -z "${check}" ]; then
813
+ statement(s) # do this if check is NULL
814
+fi
815
+```
816
+
817
+Note that we could also check the opposite. We can use the **!** symbol
818
+to require the opposite (NOT):
819
+
820
+```
821
+check=$(/usr/bin/who | grep 'jsmith12' | wc -l | grep '^1$')
822
+if [ ! -z "${check}" ]; then
823
+ statement(s) # do this if check is NOT NULL
824
+fi
825
+```
826
+
827
+Comparing two strings, the two common scenarios we tend to care about is
828
+whether or not the two strings are equal or not equal:
829
+
830
+```
831
+string1="blah"
832
+string2="boop"
833
+
834
+if [ "${string1}" = "${string2}" ]; then
835
+ statement(s) # do this in the event strings are equal
836
+fi
837
+
838
+if [ ! "${string1}" = "${string2}" ]; then
839
+ statement(s) # do this in the event strings are NOT equal
840
+fi
841
+```
842
+
843
+It should be stated that instead of negating the result, we could also
844
+just use an **else** clause:
845
+
846
+```
847
+string1="blah"
848
+string2="boop"
849
+
850
+if [ "${string1}" = "${string2}" ]; then
851
+ statement(s) # do this in the event strings are equal
852
+else
853
+ statement(s) # do this in the event strings are not equal
854
+fi
855
+```
856
+
857
+As a matter of style (and to potentially avoid syntax/logic errors being
858
+committed), one should not pose a condition just for the sake of ensuring
859
+its opposite (ie no empty clauses).
860
+
861
+If comparing numerical values, especially in numerical contexts, we have
862
+a set of arguments we can choose from:
863
+
864
+ * **-eq** - is equal to
865
+ * **-ne** - is not equal to
866
+ * **-lt** - is less than
867
+ * **-le** - is less than or equal to
868
+ * **-gt** - is greater than
869
+ * **-ge** - is greater than or equal to
870
+
871
+These of course are binary conditions, meaning we compare TWO variables
872
+to see if they possess the indicated relation (which results in a true or
873
+false result produced).
874
+
875
+## LOOPS
876
+
877
+When you have a section of code you would like to repeat some number of
878
+times, a loop can be used to achieve this.
879
+
880
+Here we will explore the **while** conditional loop. If an if statement
881
+can run 0 or 1 times, a while loop can run 0 or more.
882
+
883
+```
884
+count=10
885
+while [ "${count}" -gt 0 ]; do
886
+ echo "count is: ${count}"
887
+```
888
+
889
+=====Submission=====
890
+
891
+By successfully performing this project, you should have a fully
892
+functioning script by the name of **pwn0.sh**, which is all you need to
893
+submit for project completion (no steps file, as your "steps" file IS the
894
+script you wrote).
895
+
896
+To submit this project to me using the **submit** tool, run the following
897
+command at your lab46 prompt:
898
+
899
+```
900
+$ submit unix pwn0 pwn0.sh
901
+Submitting unix project "pwn0":
902
+ -> pwn0.sh(OK)
903
+
904
+SUCCESSFULLY SUBMITTED
905
+```
906
+
907
+You should get some sort of confirmation indicating successful submission
908
+if all went according to plan. If not, check for typos and or locational
909
+mismatches.
910
+
911
+I'll be looking for the following:
912
+
913
+```
914
+312:pwn0:final tally of results (312/312)
915
+*:pwn0:pwn0.sh on help displays informative usage and exits [18/18]
916
+*:pwn0:pwn0.sh effectively utilizes variables in operations [18/18]
917
+*:pwn0:pwn0.sh effectively utilizes command expansions [18/18]
918
+*:pwn0:pwn0.sh effectively utilizes regular expressions [18/18]
919
+*:pwn0:pwn0.sh effectively utilizes selection statements [18/18]
920
+*:pwn0:pwn0.sh effectively utilizes looping structures [18/18]
921
+*:pwn0:pwn0.sh is a proper bash script with shabang and exit [17/17]
922
+*:pwn0:pwn0.sh parses command-line arguments as appropriate [17/17]
923
+*:pwn0:pwn0.sh accurately displays values in proper alignment [17/17]
924
+*:pwn0:pwn0.sh accurately displays values in requested bases [17/17]
925
+*:pwn0:pwn0.sh accurately displays values in specified range [17/17]
926
+*:pwn0:pwn0.sh range logic flexibly works forward and reverse [17/17]
927
+*:pwn0:pwn0.sh iterates as appropriate in given scenarios [17/17]
928
+*:pwn0:pwn0.sh includes additional bases as requested [17/17]
929
+*:pwn0:pwn0.sh omits specified bases as requested [17/17]
930
+*:pwn0:pwn0.sh properly manages input violations [17/17]
931
+*:pwn0:pwn0.sh operates according to specifications [17/17]
932
+*:pwn0:pwn0.sh logic is organized and easy to read [17/17]
933
+</code>
934
+
935
+Additionally:
936
+ * Solutions not abiding by **SPIRIT** of project will be subject to a 25% overall deduction
937
+ * Solutions not utilizing descriptive why and how **COMMENTS** will be subject to a 25% overall deduction
938
+ * Solutions not utilizing **INDENTATION** to promote scope and clarity will be subject to a 25% overall deduction
939
+ * Solutions lacking **ORGANIZATION** ior are not easy to read (within 90 char width) are subject to a 25% overall deduction