32f1db06d6090d5bcd40a34b192fbcf82f38cabf
haas/fall2026/unix/projects/pwn0.md
| ... | ... | @@ -2,6 +2,8 @@ |
| 2 | 2 | |
| 3 | 3 | # PROJECT: PROCESSING WARRANTED NUMBERS (pwn0) |
| 4 | 4 | |
| 5 | +**Part 1 of 2** (the script is completed in **pwn1**) |
|
| 6 | + |
|
| 5 | 7 | ## TOOLBOX |
| 6 | 8 | |
| 7 | 9 | In addition to the tools you're already familiar with, it is recommended |
| ... | ... | @@ -19,6 +21,10 @@ definitely offer up functionality that some solutions can make use of): |
| 19 | 21 | * **sort(1)** |
| 20 | 22 | * **uniq(1)** |
| 21 | 23 | |
| 24 | +Don't forget the manual pages for **bash(1)** itself (see the sections on |
|
| 25 | +arithmetic evaluation, parameter expansion, and conditional expressions). |
|
| 26 | +Reading manual pages to discover capabilities is part of the exercise. |
|
| 27 | + |
|
| 22 | 28 | ## REFERENCE |
| 23 | 29 | |
| 24 | 30 | For additional information on the **printf(1)** tool recommended for use |
| ... | ... | @@ -32,9 +38,20 @@ likely portable to the UNIX variant of the tool. |
| 32 | 38 | |
| 33 | 39 | ## OBJECTIVE |
| 34 | 40 | |
| 35 | -To create a script that can, with or without information provided by the |
|
| 41 | +To create a script that can, with or without information provided by the |
|
| 36 | 42 | user, display useful reference data in various number bases. |
| 37 | 43 | |
| 44 | +This is the first of two projects that build one script: |
|
| 45 | + |
|
| 46 | + * **pwn0** (this project)- the foundation: a basic table of binary, octal, |
|
| 47 | + decimal, and hexadecimal values, a starting and ending value (counting |
|
| 48 | + forward or backward), bounds checking, and online help. |
|
| 49 | + * **pwn1**- completes the script: skipping values (**by#**), adding and |
|
| 50 | + removing bases (**with#**/**sans#**), and hardening the argument handling. |
|
| 51 | + |
|
| 52 | +Do **not** implement the pwn1 features here. In pwn0, those arguments are |
|
| 53 | +simply unrecognized, and are to be silently ignored (see the argument rules). |
|
| 54 | + |
|
| 38 | 55 | ## BACKGROUND |
| 39 | 56 | |
| 40 | 57 | We've encountered many things in our UNIX journey so far, and have been |
| ... | ... | @@ -105,16 +122,11 @@ lab46:~/src/SEMESTER/unix/pwn0$ |
| 105 | 122 | Your script should also take the following optional arguments (in this |
| 106 | 123 | order): |
| 107 | 124 | |
| 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. |
|
| 125 | + * **$1**- starting value (a whole number, in decimal) |
|
| 126 | + * **$2**- ending value (a whole number, in decimal) |
|
| 112 | 127 | |
| 113 | -Additional arguments your script should support: |
|
| 128 | +Additional argument your script should support: |
|
| 114 | 129 | |
| 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 | 130 | * **help** - display script usage and exit |
| 119 | 131 | |
| 120 | 132 | With any of these arguments validly provided, they should adjust the |
| ... | ... | @@ -124,11 +136,13 @@ Some additional constraints/assumptions you can make: |
| 124 | 136 | |
| 125 | 137 | * the minimum lower limit your script should process for is **0**. If an input goes negative, cap it to 0. |
| 126 | 138 | * the maximum upper limit you can implement for is **255** (base 10). If an input goes in excess of this, cap it to 255. |
| 139 | + * the bases displayed are always 2, 8, 10, and 16 (in that order) |
|
| 127 | 140 | |
| 128 | 141 | ### ONLY SPECIFYING STARTING VALUE |
| 129 | 142 | |
| 130 | 143 | In the event only the starting value is specified, assume a count of 16 |
| 131 | -(so display 16 values, starting at the starting value). |
|
| 144 | +(so display 16 values, starting at the starting value; that is, an ending |
|
| 145 | +value of the starting value + 15, capped at 255). |
|
| 132 | 146 | |
| 133 | 147 | For example: |
| 134 | 148 | |
| ... | ... | @@ -203,62 +217,6 @@ lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 73 59 |
| 203 | 217 | lab46:~/src/SEMESTER/unix/pwn0$ |
| 204 | 218 | ``` |
| 205 | 219 | |
| 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 | 220 | ### EXCEEDING BOUNDS |
| 263 | 221 | |
| 264 | 222 | Although our script does not need to iterate values outside the 0-255 |
| ... | ... | @@ -297,186 +255,77 @@ lab46:~/src/SEMESTER/unix/pwn0$ |
| 297 | 255 | Both starting and ending values need to appropriately fall within the |
| 298 | 256 | 0-255 bounds, however they may be situated. |
| 299 | 257 | |
| 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 | 258 | ### ONLINE HELP |
| 445 | 259 | |
| 446 | -Your script should also, when prompted, display usage information with |
|
| 260 | +Your script should also, when prompted, display usage information with |
|
| 447 | 261 | the **help** option: |
| 448 | 262 | |
| 449 | 263 | ``` |
| 450 | 264 | lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh help |
| 451 | 265 | |
| 452 | - pwn0.sh - render a number table in the specified bases, |
|
| 266 | + pwn0.sh - render a number table in bases 2, 8, 10, and 16, |
|
| 453 | 267 | displaying from starting value to ending value. |
| 454 | 268 | |
| 455 | - behavior: by default, bases 2, 8, 10, and 16 will be |
|
| 456 | - displayed, in a range of 0 to 15 (inclusive). |
|
| 269 | + behavior: by default, values 0 to 15 (inclusive) will |
|
| 270 | + be displayed. |
|
| 457 | 271 | |
| 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). |
|
| 272 | + note: values should not go negative nor exceed 255. If |
|
| 273 | + a starting value but no ending value is given, |
|
| 274 | + assume an ending value +15 away (or capped by 255). |
|
| 462 | 275 | |
| 463 | - usage: pwn0.sh [start#] [end#] [OPTION]... |
|
| 276 | + usage: pwn0.sh [start#] [end#] |
|
| 464 | 277 | |
| 465 | 278 | options: |
| 466 | - $1 - if a positive decimal value, override the |
|
| 279 | + $1 - if a non-negative decimal value, override the |
|
| 467 | 280 | starting value (0) |
| 468 | - $2 - if a positive decimal value, override the |
|
| 281 | + $2 - if a non-negative decimal value, override the |
|
| 469 | 282 | ending value (15) |
| 470 | 283 | |
| 471 | 284 | 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 | 285 | help - display script usage and exit |
| 476 | 286 | |
| 477 | 287 | lab46:~/src/SEMESTER/unix/pwn0$ |
| 478 | 288 | ``` |
| 479 | 289 | |
| 290 | +(The online help is provided in the starter script; the point is for you to |
|
| 291 | +produce it correctly, and to understand how it works.) |
|
| 292 | + |
|
| 293 | +### ARGUMENT RULES (CLARIFICATIONS) |
|
| 294 | + |
|
| 295 | +To remove ambiguity, here is exactly how arguments are to be treated: |
|
| 296 | + |
|
| 297 | + * **help** anywhere on the command line wins: display usage and exit (even |
|
| 298 | + if other arguments are present). |
|
| 299 | + * Arguments are examined in the order given. The first whole number |
|
| 300 | + encountered is the starting value, the second is the ending value. Any |
|
| 301 | + further whole numbers are silently ignored. |
|
| 302 | + * A "whole number" is an optional leading `-` followed by one or more digits. |
|
| 303 | + Things like `12.5`, `abc`, `+5`, or `0x1F` are not whole numbers. |
|
| 304 | + * Anything that is neither **help** nor a whole number is silently dropped |
|
| 305 | + (as if never given). This includes **by#**, **with#**, and **sans#**, |
|
| 306 | + which you will meet in pwn1 but which mean nothing yet. |
|
| 307 | + * Values below 0 become 0; values above 255 become 255 (this includes |
|
| 308 | + ridiculously long numbers). This applies to the start and the end value. |
|
| 309 | + * If only a starting value is given (or none at all), the ending value is |
|
| 310 | + the starting value + 15, capped at 255. |
|
| 311 | + * If the starting value is higher than the ending value, count backward |
|
| 312 | + (one at a time). If they are equal, display a single row. |
|
| 313 | + * Nothing goes to STDERR, ever: this script has no error messages. The exit |
|
| 314 | + status is always 0. |
|
| 315 | + |
|
| 316 | +For example, unrecognized arguments are simply ignored: |
|
| 317 | + |
|
| 318 | +``` |
|
| 319 | +lab46:~/src/SEMESTER/unix/pwn0$ ./pwn0.sh 5 8 by2 foo |
|
| 320 | + base 2 | base 8 | base10 | base16 | |
|
| 321 | +----------+----------+----------+----------+ |
|
| 322 | + 101 | 5 | 5 | 5 | |
|
| 323 | + 110 | 6 | 6 | 6 | |
|
| 324 | + 111 | 7 | 7 | 7 | |
|
| 325 | + 1000 | 10 | 8 | 8 | |
|
| 326 | +lab46:~/src/SEMESTER/unix/pwn0$ |
|
| 327 | +``` |
|
| 328 | + |
|
| 480 | 329 | ## SPECIFICATIONS |
| 481 | 330 | |
| 482 | 331 | Evaluation will be based on correctness of values as well as on |
| ... | ... | @@ -493,9 +342,9 @@ You'll notice that everything lines up and is positioned similarly: |
| 493 | 342 | * The dashes and vertical bars set up an ASCII art-like table pattern that helps make the data more readable. |
| 494 | 343 | * The values are right justified with each column |
| 495 | 344 | * 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: |
|
| 345 | + * base headings are right justified; the word "base" is followed by the base number in a field 2 characters wide: |
|
| 497 | 346 | * 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). |
|
| 347 | + * 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). |
|
| 499 | 348 | * You need to check your arguments to ensure they are present and valid. Some examples: |
| 500 | 349 | * starting value is a valid (whole) number |
| 501 | 350 | * if less than 0, or greater than 255, needs to be capped to whichever extreme it exceeds |
| ... | ... | @@ -505,10 +354,9 @@ You'll notice that everything lines up and is positioned similarly: |
| 505 | 354 | * if less than 0, or greater than 255, needs to be capped to whichever extreme it exceeds |
| 506 | 355 | * if -8, cap to 0 |
| 507 | 356 | * 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. |
|
| 357 | + * any invalid arguments (nonsensical value in place of starting value, etc.) should be silently dropped/ignored. |
|
| 509 | 358 | * 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 | 359 | * 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 | 360 | * 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 | 361 | * comments and indentation are required and necessary |
| 514 | 362 | * comments should explain how or why you are doing something |
| ... | ... | @@ -528,7 +376,7 @@ You'll notice that everything lines up and is positioned similarly: |
| 528 | 376 | * if you gain inspiration from some external resource, please cite it |
| 529 | 377 | * 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 | 378 | |
| 531 | -To be sure, I'll be checking to make sure you solution follows the spirit |
|
| 379 | +To be sure, I'll be checking to make sure your solution follows the spirit |
|
| 532 | 380 | of what this project is about (that you implement functional, flowing |
| 533 | 381 | logic utilizing the tools and concepts we've learned, in an application |
| 534 | 382 | that helps demonstrate your comprehension). Don't try to weasel your way |
| ... | ... | @@ -884,15 +732,102 @@ can run 0 or 1 times, a while loop can run 0 or more. |
| 884 | 732 | count=10 |
| 885 | 733 | while [ "${count}" -gt 0 ]; do |
| 886 | 734 | echo "count is: ${count}" |
| 735 | + count=$((count - 1)) |
|
| 736 | +done |
|
| 887 | 737 | ``` |
| 888 | 738 | |
| 889 | -=====Submission===== |
|
| 739 | +The condition works just like it does for an **if** (it is the |
|
| 740 | +arguments given to `[`(1)), but the body repeats for as long as that |
|
| 741 | +condition remains true. Something inside the loop **must** eventually change |
|
| 742 | +the outcome of the condition (above, the `count=$((count - 1))` line), or |
|
| 743 | +you have created an infinite loop (**Ctrl-C** will rescue you). |
|
| 744 | + |
|
| 745 | +Arithmetic in bash is performed with the `$(( ))` construct, as seen above. |
|
| 746 | + |
|
| 747 | +### FOR LOOPS |
|
| 748 | + |
|
| 749 | +When you know in advance what you want to iterate through, a **for** loop is |
|
| 750 | +often cleaner. A **list-based** for loop visits each item in a list: |
|
| 751 | + |
|
| 752 | +``` |
|
| 753 | +for base in 2 8 10 16; do |
|
| 754 | + echo "now working on base ${base}" |
|
| 755 | +done |
|
| 756 | +``` |
|
| 757 | + |
|
| 758 | +A **numeric** (C-style) for loop manages a counter for you: |
|
| 759 | + |
|
| 760 | +``` |
|
| 761 | +for ((i = 0; i < 5; i++)); do |
|
| 762 | + echo "i is: ${i}" |
|
| 763 | +done |
|
| 764 | +``` |
|
| 765 | + |
|
| 766 | +Either is fine for this project. Think about which loop best fits each |
|
| 767 | +repetitive task you identify (walking the arguments, walking the values, |
|
| 768 | +walking the bases...). |
|
| 769 | + |
|
| 770 | +## PATTERN MATCHING |
|
| 771 | + |
|
| 772 | +You'll need to decide what each command-line argument IS (the word |
|
| 773 | +`help`? a whole number? something nonsensical?). Rather than a long chain of |
|
| 774 | +string comparisons, the course objective on pattern matching asks you to |
|
| 775 | +describe the *shape* of what you expect with a **regular expression**. |
|
| 776 | + |
|
| 777 | +A few places where regular expressions can be applied in a bash script (check |
|
| 778 | +the manual pages and your notes on regular expressions, and experiment!): |
|
| 779 | + |
|
| 780 | + * **grep(1)** / **egrep(1)** (or `grep -E`), commonly with `-q` to test a match |
|
| 781 | + * the `[[ string =~ regex ]]` test (captured groups land in `BASH_REMATCH`) |
|
| 782 | + * **sed(1)** substitutions to strip or transform text |
|
| 783 | + * `case` statement patterns (these are shell globs, a close relative) |
|
| 784 | + |
|
| 785 | +Anchors (`^` and `$`) matter. A whole number (with an optional leading minus) |
|
| 786 | +could be described as `^-?[0-9]+$`: |
|
| 787 | + |
|
| 788 | +``` |
|
| 789 | +lab46:~$ [[ "-8" =~ ^-?[0-9]+$ ]] && echo "whole number" |
|
| 790 | +whole number |
|
| 791 | +lab46:~$ [[ "42abc" =~ ^-?[0-9]+$ ]] || echo "42abc rejected" |
|
| 792 | +42abc rejected |
|
| 793 | +lab46:~$ |
|
| 794 | +``` |
|
| 795 | + |
|
| 796 | +Without the anchors, "42abc" would match too (it contains digits), and |
|
| 797 | +"12.5" would sneak through as well. Test your patterns against near-misses. |
|
| 798 | + |
|
| 799 | +## LOOKING AHEAD: PWN1 |
|
| 800 | + |
|
| 801 | +The **pwn1** project picks up right where this one leaves off: you will |
|
| 802 | +extend this very script to skip values (**by#**), add bases (**with#**), and |
|
| 803 | +remove bases (**sans#**). Today's table is a fixed list of four bases; next |
|
| 804 | +time it will be a list that changes. Write your pwn0 so that: |
|
| 805 | + |
|
| 806 | + * the work of converting and displaying ONE value lives in one place |
|
| 807 | + (rather than being copy/pasted four times) |
|
| 808 | + * your loops and conditions are tidy and easy to follow |
|
| 809 | + * your comments make it obvious how everything fits together |
|
| 810 | + |
|
| 811 | +Future you (and your pwn1 grade) will thank you. |
|
| 812 | + |
|
| 813 | +## SUBMISSION |
|
| 890 | 814 | |
| 891 | 815 | By successfully performing this project, you should have a fully |
| 892 | 816 | functioning script by the name of **pwn0.sh**, which is all you need to |
| 893 | 817 | submit for project completion (no steps file, as your "steps" file IS the |
| 894 | 818 | script you wrote). |
| 895 | 819 | |
| 820 | +A **starter script** is available to give you a base to work from (it contains |
|
| 821 | +the identification block, the complete **help** text, and an outline of |
|
| 822 | +suggested steps): |
|
| 823 | + |
|
| 824 | +``` |
|
| 825 | +$ cp /var/public/fall2026/UNIX/pwn0/pwn0.sh ~/src/SEMESTER/unix/pwn0/pwn0.sh |
|
| 826 | +``` |
|
| 827 | + |
|
| 828 | +Using the starter is optional, but whatever you submit must still satisfy |
|
| 829 | +everything in this document. |
|
| 830 | + |
|
| 896 | 831 | To submit this project to me using the **submit** tool, run the following |
| 897 | 832 | command at your lab46 prompt: |
| 898 | 833 | |
| ... | ... | @@ -904,36 +839,35 @@ Submitting unix project "pwn0": |
| 904 | 839 | SUCCESSFULLY SUBMITTED |
| 905 | 840 | ``` |
| 906 | 841 | |
| 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: |
|
| 842 | +What I'm looking for: |
|
| 912 | 843 | |
| 913 | 844 | ``` |
| 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] |
|
| 845 | +286:pwn0:final tally of results (286/286) |
|
| 846 | +*:pwn0:pwn0.sh is a proper bash script: shabang, clean exit 0, parses, no hard-coded paths [13/13] |
|
| 847 | +*:pwn0:pwn0.sh on help displays informative usage and exits [13/13] |
|
| 848 | +*:pwn0:pwn0.sh formats output with printf width specifiers (no >2 literal spaces) [13/13] |
|
| 849 | +*:pwn0:pwn0.sh accurately displays values in proper alignment [26/26] |
|
| 850 | +*:pwn0:pwn0.sh effectively utilizes variables in operations [13/13] |
|
| 851 | +*:pwn0:pwn0.sh effectively utilizes command expansions [13/13] |
|
| 852 | +*:pwn0:pwn0.sh effectively utilizes selection statements [13/13] |
|
| 853 | +*:pwn0:pwn0.sh effectively utilizes looping structures [13/13] |
|
| 854 | +*:pwn0:pwn0.sh accurately displays the default table (no arguments) [26/26] |
|
| 855 | +*:pwn0:pwn0.sh accurately displays values for starting and ending values [26/26] |
|
| 856 | +*:pwn0:pwn0.sh employs discrete single-purpose utilities [13/13] |
|
| 857 | +*:pwn0:pwn0.sh uses regular expressions to validate numeric input [13/13] |
|
| 858 | +*:pwn0:pwn0.sh displays 16 values when only a starting value is given [13/13] |
|
| 859 | +*:pwn0:pwn0.sh range logic flexibly works forward and reverse [13/13] |
|
| 860 | +*:pwn0:pwn0.sh caps starting/ending values to the 0 to 255 bounds [13/13] |
|
| 861 | +*:pwn0:pwn0.sh silently drops invalid arguments and still runs [13/13] |
|
| 862 | +*:pwn0:pwn0.sh comments explain how/why (header block, density, reasoning) [13/13] |
|
| 863 | +*:pwn0:pwn0.sh logic is organized: consistent indentation (>=3), lines within 90 chars [13/13] |
|
| 864 | +*:pwn0:pwn0.sh identifies shortcomings, deviations from specification [13/13] |
|
| 933 | 865 | ``` |
| 934 | 866 | |
| 935 | 867 | Additionally: |
| 936 | - * Solutions not abiding by **SPIRIT** of project will be subject to a 25% overall deduction |
|
| 868 | + |
|
| 869 | + * Solutions not abiding by the **SPIRIT** of the project (including |
|
| 870 | + hard-coded output) will be subject to a 25% overall deduction |
|
| 937 | 871 | * Solutions not utilizing descriptive why and how **COMMENTS** will be subject to a 25% overall deduction |
| 938 | 872 | * 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 |
|
| 873 | + * Solutions lacking **ORGANIZATION** or that are not easy to read (within 90 char width) are subject to a 25% overall deduction |
haas/fall2026/unix/projects/pwn1.md
| ... | ... | @@ -0,0 +1,718 @@ |
| 1 | +# CSCS1730 UNIX/Linux Fundamentals |
|
| 2 | + |
|
| 3 | +# PROJECT: PROCESSING WARRANTED NUMBERS (pwn1) |
|
| 4 | + |
|
| 5 | +**Part 2 of 2** (builds directly on **pwn0**) |
|
| 6 | + |
|
| 7 | +## TOOLBOX |
|
| 8 | + |
|
| 9 | +In addition to the tools you're already familiar with, it is recommended |
|
| 10 | +you check out the following tools for possible application in this |
|
| 11 | +project (you may not need to use them in your solution, but they |
|
| 12 | +definitely offer up functionality that some solutions can make use of): |
|
| 13 | + |
|
| 14 | + * **bc(1)** |
|
| 15 | + * **comm(1)** |
|
| 16 | + * **diff(1)** |
|
| 17 | + * **grep(1)** |
|
| 18 | + * **join(1)** |
|
| 19 | + * **printf(1)** |
|
| 20 | + * **seq(1)** |
|
| 21 | + * **sort(1)** |
|
| 22 | + * **uniq(1)** |
|
| 23 | + |
|
| 24 | +Don't forget the manual pages for **bash(1)** itself (see the sections on |
|
| 25 | +arithmetic evaluation, parameter expansion, and conditional expressions). |
|
| 26 | +Reading manual pages to discover capabilities is part of the exercise. |
|
| 27 | + |
|
| 28 | +For this project in particular, give **bc(1)** a good look (its `obase` |
|
| 29 | +setting is a natural fit for converting to an arbitrary base), and consider |
|
| 30 | +how **sort(1)** and **uniq(1)** could help tidy up a list of bases. |
|
| 31 | + |
|
| 32 | +## REFERENCE |
|
| 33 | + |
|
| 34 | +For additional information on the **printf(1)** tool recommended for use |
|
| 35 | +in this project, please check out this paper: |
|
| 36 | + |
|
| 37 | + * https://lab46.g7n.org/downloads/printf.pdf |
|
| 38 | + |
|
| 39 | +NOTE that while it focuses on the C and Perl variants of printf, the |
|
| 40 | +conceptual underpinnings are the same, and many of the examples are |
|
| 41 | +likely portable to the UNIX variant of the tool. |
|
| 42 | + |
|
| 43 | +## OBJECTIVE |
|
| 44 | + |
|
| 45 | +To complete the script begun in **pwn0**: a script that can, with or without |
|
| 46 | +information provided by the user, display useful reference data in various |
|
| 47 | +number bases, skipping through values, adding bases, removing bases, and |
|
| 48 | +standing up to bad input. |
|
| 49 | + |
|
| 50 | +Your finished pwn1.sh does **everything** described in this document **and** |
|
| 51 | +in pwn0. Begin from your own pwn0.sh. If your pwn0 had gaps, this is your |
|
| 52 | +chance to close them: pwn1 is evaluated against the whole script. |
|
| 53 | + |
|
| 54 | +## BACKGROUND |
|
| 55 | + |
|
| 56 | +In **pwn0** you built the foundation: a table of values in bases 2, 8, 10, and |
|
| 57 | +16, with a starting and ending value, forward or backward, bounds checking, |
|
| 58 | +and online help. The four bases were fixed, and so was the step of 1. |
|
| 59 | + |
|
| 60 | +For **pwn1**, the table becomes flexible. **Everything about it is decided at |
|
| 61 | +run time**: |
|
| 62 | + |
|
| 63 | + * how far apart consecutive values are (**by#**) |
|
| 64 | + * which bases appear (**with#** to add, **sans#** to remove, even the defaults) |
|
| 65 | + * how gracefully the script copes with arguments that make no sense |
|
| 66 | + |
|
| 67 | +Where pwn0 had four columns written out in your logic, pwn1 has a *list of |
|
| 68 | +bases* that your script assembles, and that the header, the divider, and every |
|
| 69 | +row are built from. That shift (from "four things" to "a list of things") is the |
|
| 70 | +heart of this project. |
|
| 71 | + |
|
| 72 | +## PROCESS |
|
| 73 | + |
|
| 74 | +Your script does everything pwn0 did. As a reminder, with no arguments: |
|
| 75 | + |
|
| 76 | +``` |
|
| 77 | +lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh |
|
| 78 | + base 2 | base 8 | base10 | base16 | |
|
| 79 | +----------+----------+----------+----------+ |
|
| 80 | + 0 | 0 | 0 | 0 | |
|
| 81 | + 1 | 1 | 1 | 1 | |
|
| 82 | + 10 | 2 | 2 | 2 | |
|
| 83 | + 11 | 3 | 3 | 3 | |
|
| 84 | + 100 | 4 | 4 | 4 | |
|
| 85 | + 101 | 5 | 5 | 5 | |
|
| 86 | + 110 | 6 | 6 | 6 | |
|
| 87 | + 111 | 7 | 7 | 7 | |
|
| 88 | + 1000 | 10 | 8 | 8 | |
|
| 89 | + 1001 | 11 | 9 | 9 | |
|
| 90 | + 1010 | 12 | 10 | A | |
|
| 91 | + 1011 | 13 | 11 | B | |
|
| 92 | + 1100 | 14 | 12 | C | |
|
| 93 | + 1101 | 15 | 13 | D | |
|
| 94 | + 1110 | 16 | 14 | E | |
|
| 95 | + 1111 | 17 | 15 | F | |
|
| 96 | +lab46:~/src/SEMESTER/unix/pwn1$ |
|
| 97 | +``` |
|
| 98 | + |
|
| 99 | +The full set of arguments your script should take: |
|
| 100 | + |
|
| 101 | + * **$1**- starting value (a whole number, in decimal) |
|
| 102 | + * **$2**- ending value (a whole number, in decimal) |
|
| 103 | + |
|
| 104 | +Numerical arguments are to be given in decimal. |
|
| 105 | + |
|
| 106 | +Additional arguments your script should support: |
|
| 107 | + |
|
| 108 | + * **by#** - iterate through values by # (default: 1) |
|
| 109 | + * **with#** - include base # in the list of bases to display |
|
| 110 | + * **sans#** - remove base # in the list of bases to display |
|
| 111 | + * **help** - display script usage and exit |
|
| 112 | + |
|
| 113 | +With any of these arguments validly provided, they should adjust the |
|
| 114 | +script's processing and output accordingly. Any of them may be combined with |
|
| 115 | +any other, in any order. |
|
| 116 | + |
|
| 117 | +Some additional constraints/assumptions you can make: |
|
| 118 | + |
|
| 119 | + * the minimum lower limit your script should process for is **0**. If an input goes negative, cap it to 0. |
|
| 120 | + * the maximum upper limit you can implement for is **255** (base 10). If an input goes in excess of this, cap it to 255. |
|
| 121 | + * valid bases are 2 through 16, inclusive. The default bases are 2, 8, 10, and 16. |
|
| 122 | + |
|
| 123 | +Examples of the pwn0 behaviors (start-only, start/end, going backward, and |
|
| 124 | +exceeding bounds) are in the pwn0 project document; they all still apply. |
|
| 125 | + |
|
| 126 | +### SKIPPING VALUES |
|
| 127 | + |
|
| 128 | +With the 'by#' argument, we can cause numbers to iterate by more than 1. |
|
| 129 | +For example, if we wanted to go from 3 to 81 skipping 3 values each turn: |
|
| 130 | + |
|
| 131 | +``` |
|
| 132 | +lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 3 81 by3 |
|
| 133 | + base 2 | base 8 | base10 | base16 | |
|
| 134 | +----------+----------+----------+----------+ |
|
| 135 | + 11 | 3 | 3 | 3 | |
|
| 136 | + 110 | 6 | 6 | 6 | |
|
| 137 | + 1001 | 11 | 9 | 9 | |
|
| 138 | + 1100 | 14 | 12 | C | |
|
| 139 | + 1111 | 17 | 15 | F | |
|
| 140 | + 10010 | 22 | 18 | 12 | |
|
| 141 | + 10101 | 25 | 21 | 15 | |
|
| 142 | + 11000 | 30 | 24 | 18 | |
|
| 143 | + 11011 | 33 | 27 | 1B | |
|
| 144 | + 11110 | 36 | 30 | 1E | |
|
| 145 | + 100001 | 41 | 33 | 21 | |
|
| 146 | + 100100 | 44 | 36 | 24 | |
|
| 147 | + 100111 | 47 | 39 | 27 | |
|
| 148 | + 101010 | 52 | 42 | 2A | |
|
| 149 | + 101101 | 55 | 45 | 2D | |
|
| 150 | + 110000 | 60 | 48 | 30 | |
|
| 151 | + 110011 | 63 | 51 | 33 | |
|
| 152 | + 110110 | 66 | 54 | 36 | |
|
| 153 | + 111001 | 71 | 57 | 39 | |
|
| 154 | + 111100 | 74 | 60 | 3C | |
|
| 155 | + 111111 | 77 | 63 | 3F | |
|
| 156 | + 1000010 | 102 | 66 | 42 | |
|
| 157 | + 1000101 | 105 | 69 | 45 | |
|
| 158 | + 1001000 | 110 | 72 | 48 | |
|
| 159 | + 1001011 | 113 | 75 | 4B | |
|
| 160 | + 1001110 | 116 | 78 | 4E | |
|
| 161 | + 1010001 | 121 | 81 | 51 | |
|
| 162 | +lab46:~/src/SEMESTER/unix/pwn1$ |
|
| 163 | +``` |
|
| 164 | + |
|
| 165 | +This should be flexible whether going forward or backward in count: |
|
| 166 | + |
|
| 167 | +``` |
|
| 168 | +lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 32 2 by4 |
|
| 169 | + base 2 | base 8 | base10 | base16 | |
|
| 170 | +----------+----------+----------+----------+ |
|
| 171 | + 100000 | 40 | 32 | 20 | |
|
| 172 | + 11100 | 34 | 28 | 1C | |
|
| 173 | + 11000 | 30 | 24 | 18 | |
|
| 174 | + 10100 | 24 | 20 | 14 | |
|
| 175 | + 10000 | 20 | 16 | 10 | |
|
| 176 | + 1100 | 14 | 12 | C | |
|
| 177 | + 1000 | 10 | 8 | 8 | |
|
| 178 | + 100 | 4 | 4 | 4 | |
|
| 179 | +lab46:~/src/SEMESTER/unix/pwn1$ |
|
| 180 | +``` |
|
| 181 | + |
|
| 182 | +### ADDITIONAL BASES |
|
| 183 | + |
|
| 184 | +Your script should also support the inclusion of additional bases (valid |
|
| 185 | +bases are any base between 2 and 16, inclusive). The default bases |
|
| 186 | +assumed included are 2, 8, 10, and 16, but additional ones may be |
|
| 187 | +specified with a **with#** argument. |
|
| 188 | + |
|
| 189 | +For instance, let's say we wanted to include base 7: |
|
| 190 | + |
|
| 191 | +``` |
|
| 192 | +lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh with7 |
|
| 193 | + base 2 | base 7 | base 8 | base10 | base16 | |
|
| 194 | +----------+----------+----------+----------+----------+ |
|
| 195 | + 0 | 0 | 0 | 0 | 0 | |
|
| 196 | + 1 | 1 | 1 | 1 | 1 | |
|
| 197 | + 10 | 2 | 2 | 2 | 2 | |
|
| 198 | + 11 | 3 | 3 | 3 | 3 | |
|
| 199 | + 100 | 4 | 4 | 4 | 4 | |
|
| 200 | + 101 | 5 | 5 | 5 | 5 | |
|
| 201 | + 110 | 6 | 6 | 6 | 6 | |
|
| 202 | + 111 | 10 | 7 | 7 | 7 | |
|
| 203 | + 1000 | 11 | 10 | 8 | 8 | |
|
| 204 | + 1001 | 12 | 11 | 9 | 9 | |
|
| 205 | + 1010 | 13 | 12 | 10 | A | |
|
| 206 | + 1011 | 14 | 13 | 11 | B | |
|
| 207 | + 1100 | 15 | 14 | 12 | C | |
|
| 208 | + 1101 | 16 | 15 | 13 | D | |
|
| 209 | + 1110 | 20 | 16 | 14 | E | |
|
| 210 | + 1111 | 21 | 17 | 15 | F | |
|
| 211 | +lab46:~/src/SEMESTER/unix/pwn1$ |
|
| 212 | +``` |
|
| 213 | + |
|
| 214 | +And this should work even with the potential inclusion of starting, |
|
| 215 | +ending, or a by# option (forward or backward): |
|
| 216 | + |
|
| 217 | +``` |
|
| 218 | +lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 13 255 by13 with7 |
|
| 219 | + base 2 | base 7 | base 8 | base10 | base16 | |
|
| 220 | +----------+----------+----------+----------+----------+ |
|
| 221 | + 1101 | 16 | 15 | 13 | D | |
|
| 222 | + 11010 | 35 | 32 | 26 | 1A | |
|
| 223 | + 100111 | 54 | 47 | 39 | 27 | |
|
| 224 | + 110100 | 103 | 64 | 52 | 34 | |
|
| 225 | + 1000001 | 122 | 101 | 65 | 41 | |
|
| 226 | + 1001110 | 141 | 116 | 78 | 4E | |
|
| 227 | + 1011011 | 160 | 133 | 91 | 5B | |
|
| 228 | + 1101000 | 206 | 150 | 104 | 68 | |
|
| 229 | + 1110101 | 225 | 165 | 117 | 75 | |
|
| 230 | + 10000010 | 244 | 202 | 130 | 82 | |
|
| 231 | + 10001111 | 263 | 217 | 143 | 8F | |
|
| 232 | + 10011100 | 312 | 234 | 156 | 9C | |
|
| 233 | + 10101001 | 331 | 251 | 169 | A9 | |
|
| 234 | + 10110110 | 350 | 266 | 182 | B6 | |
|
| 235 | + 11000011 | 366 | 303 | 195 | C3 | |
|
| 236 | + 11010000 | 415 | 320 | 208 | D0 | |
|
| 237 | + 11011101 | 434 | 335 | 221 | DD | |
|
| 238 | + 11101010 | 453 | 352 | 234 | EA | |
|
| 239 | + 11110111 | 502 | 367 | 247 | F7 | |
|
| 240 | +lab46:~/src/SEMESTER/unix/pwn1$ |
|
| 241 | +``` |
|
| 242 | + |
|
| 243 | +Multiple additional bases can be included... you merely append additional |
|
| 244 | +**with#** arguments: |
|
| 245 | + |
|
| 246 | +``` |
|
| 247 | +lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 196 2 with3 by14 with12 |
|
| 248 | + base 2 | base 3 | base 8 | base10 | base12 | base16 | |
|
| 249 | +----------+----------+----------+----------+----------+----------+ |
|
| 250 | + 11000100 | 21021 | 304 | 196 | 144 | C4 | |
|
| 251 | + 10110110 | 20202 | 266 | 182 | 132 | B6 | |
|
| 252 | + 10101000 | 20020 | 250 | 168 | 120 | A8 | |
|
| 253 | + 10011010 | 12201 | 232 | 154 | 10A | 9A | |
|
| 254 | + 10001100 | 12012 | 214 | 140 | B8 | 8C | |
|
| 255 | + 1111110 | 11200 | 176 | 126 | A6 | 7E | |
|
| 256 | + 1110000 | 11011 | 160 | 112 | 94 | 70 | |
|
| 257 | + 1100010 | 10122 | 142 | 98 | 82 | 62 | |
|
| 258 | + 1010100 | 10010 | 124 | 84 | 70 | 54 | |
|
| 259 | + 1000110 | 2121 | 106 | 70 | 5A | 46 | |
|
| 260 | + 111000 | 2002 | 70 | 56 | 48 | 38 | |
|
| 261 | + 101010 | 1120 | 52 | 42 | 36 | 2A | |
|
| 262 | + 11100 | 1001 | 34 | 28 | 24 | 1C | |
|
| 263 | + 1110 | 112 | 16 | 14 | 12 | E | |
|
| 264 | +lab46:~/src/SEMESTER/unix/pwn1$ |
|
| 265 | +``` |
|
| 266 | + |
|
| 267 | +### OMITTING BASES |
|
| 268 | + |
|
| 269 | +With the **sans#** option, we can leave out specified bases (useful for |
|
| 270 | +excluding any of the default 2, 8, 10, or 16). |
|
| 271 | + |
|
| 272 | +Here we will omit base 8 from a default run: |
|
| 273 | + |
|
| 274 | +``` |
|
| 275 | +lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh sans8 |
|
| 276 | + base 2 | base10 | base16 | |
|
| 277 | +----------+----------+----------+ |
|
| 278 | + 0 | 0 | 0 | |
|
| 279 | + 1 | 1 | 1 | |
|
| 280 | + 10 | 2 | 2 | |
|
| 281 | + 11 | 3 | 3 | |
|
| 282 | + 100 | 4 | 4 | |
|
| 283 | + 101 | 5 | 5 | |
|
| 284 | + 110 | 6 | 6 | |
|
| 285 | + 111 | 7 | 7 | |
|
| 286 | + 1000 | 8 | 8 | |
|
| 287 | + 1001 | 9 | 9 | |
|
| 288 | + 1010 | 10 | A | |
|
| 289 | + 1011 | 11 | B | |
|
| 290 | + 1100 | 12 | C | |
|
| 291 | + 1101 | 13 | D | |
|
| 292 | + 1110 | 14 | E | |
|
| 293 | + 1111 | 15 | F | |
|
| 294 | +lab46:~/src/SEMESTER/unix/pwn1$ |
|
| 295 | +``` |
|
| 296 | + |
|
| 297 | +Of course, this option can be validly mixed with any of the other valid |
|
| 298 | +options, and needs to work as appropriate (here you'll see a run we did |
|
| 299 | +prior, with the only difference being the omission of base 8): |
|
| 300 | + |
|
| 301 | +``` |
|
| 302 | +lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 196 2 with3 by14 with12 sans8 |
|
| 303 | + base 2 | base 3 | base10 | base12 | base16 | |
|
| 304 | +----------+----------+----------+----------+----------+ |
|
| 305 | + 11000100 | 21021 | 196 | 144 | C4 | |
|
| 306 | + 10110110 | 20202 | 182 | 132 | B6 | |
|
| 307 | + 10101000 | 20020 | 168 | 120 | A8 | |
|
| 308 | + 10011010 | 12201 | 154 | 10A | 9A | |
|
| 309 | + 10001100 | 12012 | 140 | B8 | 8C | |
|
| 310 | + 1111110 | 11200 | 126 | A6 | 7E | |
|
| 311 | + 1110000 | 11011 | 112 | 94 | 70 | |
|
| 312 | + 1100010 | 10122 | 98 | 82 | 62 | |
|
| 313 | + 1010100 | 10010 | 84 | 70 | 54 | |
|
| 314 | + 1000110 | 2121 | 70 | 5A | 46 | |
|
| 315 | + 111000 | 2002 | 56 | 48 | 38 | |
|
| 316 | + 101010 | 1120 | 42 | 36 | 2A | |
|
| 317 | + 11100 | 1001 | 28 | 24 | 1C | |
|
| 318 | + 1110 | 112 | 14 | 12 | E | |
|
| 319 | +lab46:~/src/SEMESTER/unix/pwn1$ |
|
| 320 | +``` |
|
| 321 | + |
|
| 322 | +Multiple **sans#** options can be given, and will cancel out any present |
|
| 323 | +base (including those specified with a **with#** option). A **sans#** |
|
| 324 | +option for a non-existent base should be silently ignored. |
|
| 325 | + |
|
| 326 | +### INVALID ARGUMENTS AND EMPTY TABLES |
|
| 327 | + |
|
| 328 | +Arguments that make no sense are silently dropped, as if they were never |
|
| 329 | +given (no error messages, and the script runs on with whatever IS valid). |
|
| 330 | +Here, `by0`, `with1`, `sans99`, and `foo` are all nonsense: |
|
| 331 | + |
|
| 332 | +``` |
|
| 333 | +lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 5 8 by0 with1 sans99 foo |
|
| 334 | + base 2 | base 8 | base10 | base16 | |
|
| 335 | +----------+----------+----------+----------+ |
|
| 336 | + 101 | 5 | 5 | 5 | |
|
| 337 | + 110 | 6 | 6 | 6 | |
|
| 338 | + 111 | 7 | 7 | 7 | |
|
| 339 | + 1000 | 10 | 8 | 8 | |
|
| 340 | +lab46:~/src/SEMESTER/unix/pwn1$ |
|
| 341 | +``` |
|
| 342 | + |
|
| 343 | +Order of the **with#** and **sans#** options does not matter: a **sans#** |
|
| 344 | +always wins. Below, base 3 is requested and then removed, so it never appears |
|
| 345 | +(and the step of 2 takes us through 5 and 7): |
|
| 346 | + |
|
| 347 | +``` |
|
| 348 | +lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh 5 8 with3 by2 with3 sans3 |
|
| 349 | + base 2 | base 8 | base10 | base16 | |
|
| 350 | +----------+----------+----------+----------+ |
|
| 351 | + 101 | 5 | 5 | 5 | |
|
| 352 | + 111 | 7 | 7 | 7 | |
|
| 353 | +lab46:~/src/SEMESTER/unix/pwn1$ |
|
| 354 | +``` |
|
| 355 | + |
|
| 356 | +And if every base is removed, there is nothing to display, so the script |
|
| 357 | +quietly exits (not even the header is printed, and the exit status is 0): |
|
| 358 | + |
|
| 359 | +``` |
|
| 360 | +lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh sans2 sans8 sans10 sans16 |
|
| 361 | +lab46:~/src/SEMESTER/unix/pwn1$ |
|
| 362 | +``` |
|
| 363 | + |
|
| 364 | +Notice the next prompt immediately follows the command: nothing was displayed. |
|
| 365 | + |
|
| 366 | +### ONLINE HELP |
|
| 367 | + |
|
| 368 | +Your script should also, when prompted, display usage information with |
|
| 369 | +the **help** option. The pwn1 help text covers the complete set of arguments: |
|
| 370 | + |
|
| 371 | +``` |
|
| 372 | +lab46:~/src/SEMESTER/unix/pwn1$ ./pwn1.sh help |
|
| 373 | + |
|
| 374 | + pwn1.sh - render a number table in the specified bases, |
|
| 375 | + displaying from starting value to ending value. |
|
| 376 | + |
|
| 377 | + behavior: by default, bases 2, 8, 10, and 16 will be |
|
| 378 | + displayed, in a range of 0 to 15 (inclusive). |
|
| 379 | + |
|
| 380 | + note: valid bases range from 2-16, and values should |
|
| 381 | + not go negative nor exceed 255. If a starting |
|
| 382 | + value but no ending value is given, assume an |
|
| 383 | + ending value +15 away (or capped by 255). |
|
| 384 | + |
|
| 385 | + usage: pwn1.sh [start#] [end#] [OPTION]... |
|
| 386 | + |
|
| 387 | + options: |
|
| 388 | + $1 - if a non-negative decimal value, override the |
|
| 389 | + starting value (0) |
|
| 390 | + $2 - if a non-negative decimal value, override the |
|
| 391 | + ending value (15) |
|
| 392 | + |
|
| 393 | + other options: |
|
| 394 | + by# - iterate through values by # (default: 1) |
|
| 395 | + with# - include base # in the list of bases to display |
|
| 396 | + sans# - remove base # in the list of bases to display |
|
| 397 | + help - display script usage and exit |
|
| 398 | + |
|
| 399 | +lab46:~/src/SEMESTER/unix/pwn1$ |
|
| 400 | +``` |
|
| 401 | + |
|
| 402 | +(The complete online help is provided in the starter script.) |
|
| 403 | + |
|
| 404 | +### ARGUMENT RULES (CLARIFICATIONS) |
|
| 405 | + |
|
| 406 | +To remove ambiguity, here is exactly how arguments are to be treated: |
|
| 407 | + |
|
| 408 | + * **help** anywhere on the command line wins: display usage and exit (even |
|
| 409 | + if other arguments are present). |
|
| 410 | + * Arguments may appear in **any order** relative to one another. The first |
|
| 411 | + whole number encountered is the starting value, the second is the ending |
|
| 412 | + value. Any further whole numbers are silently ignored. |
|
| 413 | + * A "whole number" is an optional leading `-` followed by one or more digits. |
|
| 414 | + Things like `12.5`, `abc`, or `0x1F` are not whole numbers, and are |
|
| 415 | + silently dropped (as if never given). |
|
| 416 | + * Values below 0 become 0; values above 255 become 255 (this includes |
|
| 417 | + ridiculously long numbers). This applies to the start and the end value. |
|
| 418 | + * **by#** requires a whole number of at least 1. `by0`, `by`, `byx`, and |
|
| 419 | + `by-3` are invalid and silently dropped. If **by#** is given more than once, |
|
| 420 | + the last valid one wins. The step is always a *size*: when counting |
|
| 421 | + backward, a step of 4 subtracts 4. The final value displayed is the last |
|
| 422 | + one reached without passing the ending value (so `32 2 by4` ends at 4). |
|
| 423 | + * **with#** and **sans#** require a base from 2 to 16 (inclusive). Anything |
|
| 424 | + else (`with1`, `with17`, `withx`, `with`) is silently dropped. |
|
| 425 | + * The displayed bases are: (the defaults 2, 8, 10, 16, plus any valid |
|
| 426 | + **with#**) minus any **sans#**, in ascending order, with no duplicates. |
|
| 427 | + A **sans#** wins regardless of where it appears (`sans3 with3` and |
|
| 428 | + `with3 sans3` both result in no base 3). |
|
| 429 | + * If **no bases remain**, exit quietly with a status of 0, printing nothing |
|
| 430 | + at all (not even the header). |
|
| 431 | + * If only a starting value is given (or none at all), the ending value is |
|
| 432 | + the starting value + 15, capped at 255. |
|
| 433 | + * Nothing goes to STDERR, ever: this script has no error messages. The exit |
|
| 434 | + status is always 0. |
|
| 435 | + |
|
| 436 | +## SPECIFICATIONS |
|
| 437 | + |
|
| 438 | +Evaluation will be based on correctness of values as well as on |
|
| 439 | +formatting/spacing. |
|
| 440 | + |
|
| 441 | +You'll notice that everything lines up and is positioned similarly: |
|
| 442 | + |
|
| 443 | + * each column exists within 10 characters of on-screen real estate: |
|
| 444 | + * 8 characters for actual value display, |
|
| 445 | + * with one space padding either side |
|
| 446 | + * columns are separated with a `|` symbol, appended to the right edge of the column (effectively making each column 11 characters wide). |
|
| 447 | + * note that the rightmost column is ended with this `|`. |
|
| 448 | + * 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 |
|
| 449 | + * The dashes and vertical bars set up an ASCII art-like table pattern that helps make the data more readable. |
|
| 450 | + * The values are right justified with each column |
|
| 451 | + * justification is essential. Everything should line up on its respective right margin. |
|
| 452 | + * base headings are right justified; the word "base" is followed by the base number in a field 2 characters wide: |
|
| 453 | + * you'll see "base 2" vs. "base16"; your script needs to accommodate this. |
|
| 454 | + * 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). |
|
| 455 | + * You need to check your arguments to ensure they are present and valid. Some examples: |
|
| 456 | + * starting value is a valid (whole) number |
|
| 457 | + * if less than 0, or greater than 255, needs to be capped to whichever extreme it exceeds |
|
| 458 | + * if -4, cap to 0 |
|
| 459 | + * if 300, cap to 255 |
|
| 460 | + * ending value is a valid (whole) number |
|
| 461 | + * if less than 0, or greater than 255, needs to be capped to whichever extreme it exceeds |
|
| 462 | + * if -8, cap to 0 |
|
| 463 | + * if 420, cap to 255 |
|
| 464 | + * any invalid arguments (nonsensical value in place of starting value, invalid base specification, etc.) should be silently dropped/ignored. |
|
| 465 | + * 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. |
|
| 466 | + * if starting and ending values are the same, the script will display just one line of number output (in addition to the header). |
|
| 467 | + * if lacking any bases to display, silently exit (print nothing at all, not even the header, and exit with a status of 0) |
|
| 468 | + * your script needs to commence with a proper **shabang** to bash; your script needs to end with an "**exit 0**" at the very end |
|
| 469 | + * comments and indentation are required and necessary |
|
| 470 | + * comments should explain how or why you are doing something |
|
| 471 | + * indentation should be consistent throughout the script |
|
| 472 | + * indentation is to be no less than 3 on-screen spaces (I recommend tabstops of 4). |
|
| 473 | + * continuing with our shell scripting, your script will need to employ in a core/central way: |
|
| 474 | + * variables |
|
| 475 | + * command expansions |
|
| 476 | + * regular expressions |
|
| 477 | + * if statements |
|
| 478 | + * loops |
|
| 479 | + * your logic needs to: |
|
| 480 | + * flow (one thing leads into the next, as best as possible) |
|
| 481 | + * make sense within the given context |
|
| 482 | + * avoid redundancy |
|
| 483 | + * be understood by you (no grabbing snippets that seem to "work" from the internet) |
|
| 484 | + * if you gain inspiration from some external resource, please cite it |
|
| 485 | + * 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) |
|
| 486 | + |
|
| 487 | +To be sure, I'll be checking to make sure your solution follows the spirit |
|
| 488 | +of what this project is about (that you implement functional, flowing |
|
| 489 | +logic utilizing the tools and concepts we've learned, in an application |
|
| 490 | +that helps demonstrate your comprehension). Don't try to weasel your way |
|
| 491 | +out of this or cut corners. This is an opportunity to further solidify |
|
| 492 | +your proficiency with everything. |
|
| 493 | + |
|
| 494 | +## SPIRIT OF PROJECT |
|
| 495 | + |
|
| 496 | +The spirit of the project embodies many aspects we've been focusing on |
|
| 497 | +throughout the semester: |
|
| 498 | + |
|
| 499 | + * recognizing patterns to employ effective solutions in problem solving |
|
| 500 | + * utilizing concepts and tools covered |
|
| 501 | + * demonstrating comprehension of concepts, tools, and problems |
|
| 502 | + * employing concepts in knowledgeable and thoughtful manner |
|
| 503 | + * following instructions |
|
| 504 | + * implementing to specifications |
|
| 505 | + * utilizing creativity |
|
| 506 | + * being able to control solution via consistent, clear, and organized presentation |
|
| 507 | + |
|
| 508 | +Basically: I want your solution to be the result of an honest, genuine |
|
| 509 | +brainstorming process where you have (on your own) figured out a path to |
|
| 510 | +solving the problem, you have dabbled and experimented and figured things |
|
| 511 | +out, and you can command the concepts and tools with a fluency enabling |
|
| 512 | +you to pull off such a feat. Your solution should demonstrate the real |
|
| 513 | +learning that took place and experience gained. |
|
| 514 | + |
|
| 515 | +Cutting corners, avoiding work, skimping on functionality, cheating |
|
| 516 | +through getting others to do work for you or finding pre-packaged |
|
| 517 | +"answers" on the internet violates the spirit of the project, for they |
|
| 518 | +betray your ability to pull off the task on your own. |
|
| 519 | + |
|
| 520 | +NOTE: some have instantiated controversy in the past by utilizing AI in a |
|
| 521 | +manner well beyond their abilities. In such cases, submitted work is not |
|
| 522 | +considered your own, and thereby inviting disciplinary action. Don't fall |
|
| 523 | +into that trap. |
|
| 524 | + |
|
| 525 | +### IDENTIFYING SHORTCOMINGS |
|
| 526 | + |
|
| 527 | +I would also like it if you provided an inventory of what functionality |
|
| 528 | +is lacking or out of spec when you submit the project. The better you can |
|
| 529 | +describe your deviations from stated requirements, the more forgiving I |
|
| 530 | +may be during evaluation (versus trying to hide the shortcomings and |
|
| 531 | +hoping I do not discover them). |
|
| 532 | + |
|
| 533 | +The more fluent you are in describing your shortcomings on accomplishing |
|
| 534 | +the project (ie "I didn't know how to do this" is far from fluent), the |
|
| 535 | +better I will be able to gauge your understanding on a particular aspect. |
|
| 536 | + |
|
| 537 | +This can be in the form of comments in your script, or even a separate |
|
| 538 | +file submitted at time of submission (if a file, be sure to make mention |
|
| 539 | +of it in your script so I can be sure to look for it). |
|
| 540 | + |
|
| 541 | +## CONVERTING BETWEEN BASES |
|
| 542 | + |
|
| 543 | +**printf(1)** can show a value in octal (`%o`) and hexadecimal (`%x`/`%X`), |
|
| 544 | +but there is no format specifier for binary, nor for base 7 or base 12. The |
|
| 545 | +**bc(1)** calculator, however, has an `obase` (output base) setting: |
|
| 546 | + |
|
| 547 | +``` |
|
| 548 | +lab46:~$ echo "obase=12; 196" | bc |
|
| 549 | +144 |
|
| 550 | +lab46:~$ echo "obase=2; 13" | bc |
|
| 551 | +1101 |
|
| 552 | +lab46:~$ echo "obase=16; 196" | bc |
|
| 553 | +C4 |
|
| 554 | +lab46:~$ |
|
| 555 | +``` |
|
| 556 | + |
|
| 557 | +(Note the digits above 9 come out as uppercase letters, just as the project |
|
| 558 | +requires. The `obase` line must come before the number it should affect.) |
|
| 559 | + |
|
| 560 | +You could also work out the conversion by hand with the repeated-division |
|
| 561 | +method: divide by the base, remember the remainder, repeat with the quotient |
|
| 562 | +until it reaches 0, and read the remainders in reverse. Either is fine, as long |
|
| 563 | +as you understand what you wrote. |
|
| 564 | + |
|
| 565 | +## A FEW MORE SCRIPTING TOOLS |
|
| 566 | + |
|
| 567 | +Handling a changing list of bases, and a growing set of options, is easier |
|
| 568 | +with a few additional bash features. All of them are worth a visit to the |
|
| 569 | +**bash(1)** manual page. |
|
| 570 | + |
|
| 571 | +### arrays |
|
| 572 | + |
|
| 573 | +An array holds a list of values under one name: |
|
| 574 | + |
|
| 575 | +``` |
|
| 576 | +bases=(2 8 10 16) |
|
| 577 | +bases+=(7) # append another element |
|
| 578 | +echo "${bases[@]}" # all elements |
|
| 579 | +echo "${#bases[@]}" # how many elements |
|
| 580 | +for b in "${bases[@]}"; do |
|
| 581 | + echo "base: ${b}" |
|
| 582 | +done |
|
| 583 | +``` |
|
| 584 | + |
|
| 585 | +Combine an array with other small tools to tidy it up; for instance, putting |
|
| 586 | +a list in order and discarding duplicates: |
|
| 587 | + |
|
| 588 | +``` |
|
| 589 | +lab46:~$ bases=(2 8 10 16 7 8) |
|
| 590 | +lab46:~$ printf "%s\n" "${bases[@]}" | sort -n | uniq |
|
| 591 | +2 |
|
| 592 | +7 |
|
| 593 | +8 |
|
| 594 | +10 |
|
| 595 | +16 |
|
| 596 | +lab46:~$ |
|
| 597 | +``` |
|
| 598 | + |
|
| 599 | +### functions |
|
| 600 | + |
|
| 601 | +A function packages a repeated task so you write it (and debug it) once: |
|
| 602 | + |
|
| 603 | +``` |
|
| 604 | +show_row() { |
|
| 605 | + local value="$1" # arguments arrive as $1, $2, ... |
|
| 606 | + printf "%s\n" "${value}" |
|
| 607 | +} |
|
| 608 | + |
|
| 609 | +show_row 42 |
|
| 610 | +``` |
|
| 611 | + |
|
| 612 | +Variables marked `local` exist only inside the function. Functions must be |
|
| 613 | +defined before the line that calls them. |
|
| 614 | + |
|
| 615 | +### case statements |
|
| 616 | + |
|
| 617 | +A **case** compares a value against a series of patterns: |
|
| 618 | + |
|
| 619 | +``` |
|
| 620 | +case "${arg}" in |
|
| 621 | + help) usage; exit 0 ;; |
|
| 622 | + by[0-9]*) echo "looks like a step" ;; |
|
| 623 | + *) ;; # anything else: silently ignored |
|
| 624 | +esac |
|
| 625 | +``` |
|
| 626 | + |
|
| 627 | +Be careful, though: those patterns are shell *globs*, not regular expressions. |
|
| 628 | +`by[0-9]*` also accepts `by5x`, because `*` means "anything at all" here. When |
|
| 629 | +exactness matters (and in this project it does), use a regular expression. |
|
| 630 | + |
|
| 631 | +## PATTERN MATCHING |
|
| 632 | + |
|
| 633 | +In pwn0 you used a regular expression to recognize whole numbers. In pwn1, you |
|
| 634 | +also have to recognize `by#`, `with#`, and `sans#` (and reject close-but-wrong |
|
| 635 | +things like `by`, `byx`, `by0`, `with17`, `wit8`, and `standby5`). |
|
| 636 | + |
|
| 637 | +When your pattern includes a *capture group* (parentheses), bash saves what it |
|
| 638 | +matched in the `BASH_REMATCH` array: |
|
| 639 | + |
|
| 640 | +``` |
|
| 641 | +lab46:~$ arg="by13" |
|
| 642 | +lab46:~$ if [[ "${arg}" =~ ^by([0-9]+)$ ]]; then echo "step is ${BASH_REMATCH[1]}"; fi |
|
| 643 | +step is 13 |
|
| 644 | +lab46:~$ |
|
| 645 | +``` |
|
| 646 | + |
|
| 647 | +Recognizing the *shape* of an argument is one task; deciding whether the number |
|
| 648 | +inside it is *acceptable* (a step of at least 1, a base from 2 to 16) is a |
|
| 649 | +separate task. Think about each as its own step. |
|
| 650 | + |
|
| 651 | +## SUBMISSION |
|
| 652 | + |
|
| 653 | +By successfully performing this project, you should have a fully |
|
| 654 | +functioning script by the name of **pwn1.sh**, which is all you need to |
|
| 655 | +submit for project completion (no steps file, as your "steps" file IS the |
|
| 656 | +script you wrote). |
|
| 657 | + |
|
| 658 | +This project continues your pwn0 work, so begin from your own pwn0.sh. A |
|
| 659 | +**starter script** is also available (it contains the identification block, the |
|
| 660 | +complete final **help** text, and notes on what is new): |
|
| 661 | + |
|
| 662 | +``` |
|
| 663 | +$ cp /var/public/fall2026/UNIX/pwn1/pwn1.sh ~/src/SEMESTER/unix/pwn1/pwn1.sh |
|
| 664 | +``` |
|
| 665 | + |
|
| 666 | +Your pwn1.sh must stand on its own (it may not depend on your pwn0.sh being |
|
| 667 | +present), and must satisfy everything in this document and in pwn0. |
|
| 668 | + |
|
| 669 | +To submit this project to me using the **submit** tool, run the following |
|
| 670 | +command at your lab46 prompt: |
|
| 671 | + |
|
| 672 | +``` |
|
| 673 | +$ submit unix pwn1 pwn1.sh |
|
| 674 | +Submitting unix project "pwn1": |
|
| 675 | + -> pwn1.sh(OK) |
|
| 676 | + |
|
| 677 | +SUCCESSFULLY SUBMITTED |
|
| 678 | +``` |
|
| 679 | + |
|
| 680 | +You should get some sort of confirmation indicating successful submission |
|
| 681 | +if all went according to plan. If not, check for typos and or locational |
|
| 682 | +mismatches. |
|
| 683 | + |
|
| 684 | +What I'm looking for: |
|
| 685 | + |
|
| 686 | +``` |
|
| 687 | +312:pwn1:final tally of results (312/312) |
|
| 688 | +*:pwn1:pwn1.sh is a proper bash script: shabang, clean exit 0, parses, no hard-coded paths [13/13] |
|
| 689 | +*:pwn1:pwn1.sh on help displays informative usage and exits [13/13] |
|
| 690 | +*:pwn1:pwn1.sh formats output with printf width specifiers (no >2 literal spaces) [13/13] |
|
| 691 | +*:pwn1:pwn1.sh accurately displays values in proper alignment [26/26] |
|
| 692 | +*:pwn1:pwn1.sh effectively utilizes variables in operations [13/13] |
|
| 693 | +*:pwn1:pwn1.sh effectively utilizes command expansions [13/13] |
|
| 694 | +*:pwn1:pwn1.sh effectively utilizes selection statements [13/13] |
|
| 695 | +*:pwn1:pwn1.sh effectively utilizes looping structures [13/13] |
|
| 696 | +*:pwn1:pwn1.sh accurately displays values across combinations of options [26/26] |
|
| 697 | +*:pwn1:pwn1.sh employs discrete single purpose utilities [13/13] |
|
| 698 | +*:pwn1:pwn1.sh links tools through pipelines / command output streams [13/13] |
|
| 699 | +*:pwn1:pwn1.sh uses regular expressions to validate numeric input [13/13] |
|
| 700 | +*:pwn1:pwn1.sh uses pattern matching to parse by#/with#/sans# options [13/13] |
|
| 701 | +*:pwn1:pwn1.sh range logic flexibly works forward and reverse [13/13] |
|
| 702 | +*:pwn1:pwn1.sh iterates by # as appropriate in given scenarios [13/13] |
|
| 703 | +*:pwn1:pwn1.sh includes (with#) and omits (sans#) bases as requested [13/13] |
|
| 704 | +*:pwn1:pwn1.sh caps starting/ending values to the 0 to 255 bounds [13/13] |
|
| 705 | +*:pwn1:pwn1.sh silently drops invalid arguments and still runs [13/13] |
|
| 706 | +*:pwn1:pwn1.sh silently exits (status 0) when no bases remain [13/13] |
|
| 707 | +*:pwn1:pwn1.sh comments explain how/why (header block, density, reasoning) [13/13] |
|
| 708 | +*:pwn1:pwn1.sh logic is organized: consistent indentation (>=3), lines within 90 chars [13/13] |
|
| 709 | +*:pwn1:pwn1.sh identifies shortcomings, deviations from specification [13/13] |
|
| 710 | +``` |
|
| 711 | + |
|
| 712 | +Additionally: |
|
| 713 | + |
|
| 714 | + * Solutions not abiding by the **SPIRIT** of the project (including |
|
| 715 | + hard-coded output) will be subject to a 25% overall deduction |
|
| 716 | + * Solutions not utilizing descriptive why and how **COMMENTS** will be subject to a 25% overall deduction |
|
| 717 | + * Solutions not utilizing **INDENTATION** to promote scope and clarity will be subject to a 25% overall deduction |
|
| 718 | + * Solutions lacking **ORGANIZATION** or that are not easy to read (within 90 char width) are subject to a 25% overall deduction |