Compare Pastes
Differences between the pastes
#273175 (11.03.2024 13:27)
and
#274603 (23.05.2024 02:13).
1 | #!/bin/sh | |
2 | # | |
3 | # pfetch - Simple POSIX sh fetch script. | |
4 | ||
5 | # Wrapper around all escape sequences used by pfetch to allow for | |
6 | # greater control over which sequences are used (if any at all). | |
7 | esc() { | |
8 | case $1 in | |
9 | CUU) e="${esc_c}[${2}A" ;; # cursor up | |
10 | CUD) e="${esc_c}[${2}B" ;; # cursor down | |
11 | CUF) e="${esc_c}[${2}C" ;; # cursor right | |
12 | CUB) e="${esc_c}[${2}D" ;; # cursor left | |
13 | ||
14 | # text formatting | |
15 | SGR) | |
16 | case ${PF_COLOR:=1} in | |
17 | (1) | |
18 | e="${esc_c}[${2}m" | |
19 | ;; | |
20 | ||
21 | (0) | |
22 | # colors disabled | |
23 | e= | |
24 | ;; | |
25 | esac | |
26 | ;; | |
27 | ||
28 | # line wrap | |
29 | DECAWM) | |
30 | case $TERM in | |
31 | (dumb | minix | cons25) | |
32 | # not supported | |
33 | e= | |
34 | ;; | |
35 | ||
36 | (*) | |
37 | e="${esc_c}[?7${2}" | |
38 | ;; | |
39 | esac | |
40 | ;; | |
41 | esac | |
42 | } | |
43 | ||
44 | # Print a sequence to the terminal. | |
45 | esc_p() { | |
46 | esc "$@" | |
47 | printf '%s' "$e" | |
48 | } | |
49 | ||
50 | # This is just a simple wrapper around 'command -v' to avoid | |
51 | # spamming '>/dev/null' throughout this function. This also guards | |
52 | # against aliases and functions. | |
53 | has() { | |
54 | _cmd=$(command -v "$1") 2>/dev/null || return 1 | |
55 | [ -x "$_cmd" ] || return 1 | |
56 | } | |
57 | ||
58 | log() { | |
59 | # The 'log()' function handles the printing of information. | |
60 | # In 'pfetch' (and 'neofetch'!) the printing of the ascii art and info | |
61 | # happen independently of each other. | |
62 | # | |
63 | # The size of the ascii art is stored and the ascii is printed first. | |
64 | # Once the ascii is printed, the cursor is located right below the art | |
65 | # (See marker $[1]). | |
66 | # | |
67 | # Using the stored ascii size, the cursor is then moved to marker $[2]. | |
68 | # This is simply a cursor up escape sequence using the "height" of the | |
69 | # ascii art. | |
70 | # | |
71 | # 'log()' then moves the cursor to the right the "width" of the ascii art | |
72 | # with an additional amount of padding to add a gap between the art and | |
73 | # the information (See marker $[3]). | |
74 | # | |
75 | # When 'log()' has executed, the cursor is then located at marker $[4]. | |
76 | # When 'log()' is run a second time, the next line of information is | |
77 | # printed, moving the cursor to marker $[5]. | |
78 | # | |
79 | # Markers $[4] and $[5] repeat all the way down through the ascii art | |
80 | # until there is no more information left to print. | |
81 | # | |
82 | # Every time 'log()' is called the script keeps track of how many lines | |
83 | # were printed. When printing is complete the cursor is then manually | |
84 | # placed below the information and the art according to the "heights" | |
85 | # of both. | |
86 | # | |
87 | # The math is simple: move cursor down $((ascii_height - info_height)). | |
88 | # If the aim is to move the cursor from marker $[5] to marker $[6], | |
89 | # plus the ascii height is 8 while the info height is 2 it'd be a move | |
90 | # of 6 lines downwards. | |
91 | # | |
92 | # However, if the information printed is "taller" (takes up more lines) | |
93 | # than the ascii art, the cursor isn't moved at all! | |
94 | # | |
95 | # Once the cursor is at marker $[6], the script exits. This is the gist | |
96 | # of how this "dynamic" printing and layout works. | |
97 | # | |
98 | # This method allows ascii art to be stored without markers for info | |
99 | # and it allows for easy swapping of info order and amount. | |
100 | # | |
101 | # $[2] ___ $[3] goldie@KISS | |
102 | # $[4](.· | $[5] os KISS Linux | |
103 | # (<> | | |
104 | # / __ \ | |
105 | # ( / \ /| | |
106 | # _/\ __)/_) | |
107 | # \/-____\/ | |
108 | # $[1] | |
109 | # | |
110 | # $[6] /home/goldie $ | |
111 | ||
112 | # End here if no data was found. | |
113 | [ "$2" ] || return | |
114 | ||
115 | # Store the values of '$1' and '$3' as we reset the argument list below. | |
116 | name=$1 | |
117 | use_seperator=$3 | |
118 | ||
119 | # Use 'set --' as a means of stripping all leading and trailing | |
120 | # white-space from the info string. This also normalizes all | |
121 | # white-space inside of the string. | |
122 | # | |
123 | # Disable the shellcheck warning for word-splitting | |
124 | # as it's safe and intended ('set -f' disables globbing). | |
125 | # shellcheck disable=2046,2086 | |
126 | { | |
127 | set -f | |
128 | set +f -- $2 | |
129 | info=$* | |
130 | } | |
131 | ||
132 | # Move the cursor to the right, the width of the ascii art with an | |
133 | # additional gap for text spacing. | |
134 | esc_p CUF "$ascii_width" | |
135 | ||
136 | # Print the info name and color the text. | |
137 | esc_p SGR "3${PF_COL1-4}"; | |
138 | esc_p SGR 1 | |
139 | printf '%s' "$name" | |
140 | esc_p SGR 0 | |
141 | ||
142 | # Print the info name and info data separator, if applicable. | |
143 | [ "$use_seperator" ] || printf %s "$PF_SEP" | |
144 | ||
145 | # Move the cursor backward the length of the *current* info name and | |
146 | # then move it forwards the length of the *longest* info name. This | |
147 | # aligns each info data line. | |
148 | esc_p CUB "${#name}" | |
149 | esc_p CUF "${PF_ALIGN:-$info_length}" | |
150 | ||
151 | # Print the info data, color it and strip all leading whitespace | |
152 | # from the string. | |
153 | esc_p SGR "3${PF_COL2-9}" | |
154 | printf '%s' "$info" | |
155 | esc_p SGR 0 | |
156 | printf '\n' | |
157 | ||
158 | # Keep track of the number of times 'log()' has been run. | |
159 | info_height=$((${info_height:-0} + 1)) | |
160 | } | |
161 | ||
162 | get_title() { | |
163 | # Username is retrieved by first checking '$USER' with a fallback | |
164 | # to the 'id -un' command. | |
165 | user=${USER:-$(id -un)} | |
166 | ||
167 | # Hostname is retrieved by first checking '$HOSTNAME' with a fallback | |
168 | # to the 'hostname' command. | |
169 | # | |
170 | # Disable the warning about '$HOSTNAME' being undefined in POSIX sh as | |
171 | # the intention for using it is allowing the user to overwrite the | |
172 | # value on invocation. | |
173 | # shellcheck disable=3028,2039 | |
174 | hostname=${HOSTNAME:-${hostname:-$(hostname)}} | |
175 | ||
176 | # If the hostname is still not found, fallback to the contents of the | |
177 | # /etc/hostname file. | |
178 | [ "$hostname" ] || read -r hostname < /etc/hostname | |
179 | ||
180 | # Add escape sequences for coloring to user and host name. As we embed | |
181 | # them directly in the arguments passed to log(), we cannot use esc_p(). | |
182 | esc SGR 1 | |
183 | user=$e$user | |
184 | esc SGR "3${PF_COL3:-1}" | |
185 | user=$e$user | |
186 | esc SGR 1 | |
187 | user=$user$e | |
188 | esc SGR 1 | |
189 | hostname=$e$hostname | |
190 | esc SGR "3${PF_COL3:-1}" | |
191 | hostname=$e$hostname | |
192 | ||
193 | log "${user}@${hostname}" " " " " >&6 | |
194 | } | |
195 | ||
196 | get_os() { | |
197 | # This function is called twice, once to detect the distribution name | |
198 | # for the purposes of picking an ascii art early and secondly to display | |
199 | # the distribution name in the info output (if enabled). | |
200 | # | |
201 | # On first run, this function displays _nothing_, only on the second | |
202 | # invocation is 'log()' called. | |
203 | [ "$distro" ] && { | |
204 | log os "$distro" >&6 | |
205 | return | |
206 | } | |
207 | ||
208 | case $os in | |
209 | (Linux*) | |
210 | # Some Linux distributions (which are based on others) | |
211 | # fail to identify as they **do not** change the upstream | |
212 | # distribution's identification packages or files. | |
213 | # | |
214 | # It is senseless to add a special case in the code for | |
215 | # each and every distribution (which _is_ technically no | |
216 | # different from what it is based on) as they're either too | |
217 | # lazy to modify upstream's identification files or they | |
218 | # don't have the know-how (or means) to ship their own | |
219 | # lsb-release package. | |
220 | # | |
221 | # This causes users to think there's a bug in system detection | |
222 | # tools like neofetch or pfetch when they technically *do* | |
223 | # function correctly. | |
224 | # | |
225 | # Exceptions are made for distributions which are independent, | |
226 | # not based on another distribution or follow different | |
227 | # standards. | |
228 | # | |
229 | # This applies only to distributions which follow the standard | |
230 | # by shipping unmodified identification files and packages | |
231 | # from their respective upstreams. | |
232 | if has lsb_release; then | |
233 | distro=$(lsb_release -sd) | |
234 | ||
235 | # Android detection works by checking for the existence of | |
236 | # the follow two directories. I don't think there's a simpler | |
237 | # method than this. | |
238 | elif [ -d /system/app ] && [ -d /system/priv-app ]; then | |
239 | distro="Android $(getprop ro.build.version.release)" | |
240 | ||
241 | elif [ -f /etc/os-release ]; then | |
242 | # This used to be a simple '. /etc/os-release' but I believe | |
243 | # this is insecure as we blindly executed whatever was in the | |
244 | # file. This parser instead simply handles 'key=val', treating | |
245 | # the file contents as plain-text. | |
246 | while IFS='=' read -r key val; do | |
247 | case $key in | |
248 | (PRETTY_NAME) | |
249 | distro=$val | |
250 | ;; | |
251 | esac | |
252 | done < /etc/os-release | |
253 | ||
254 | else | |
255 | # Special cases for (independent) distributions which | |
256 | # don't follow any os-release/lsb standards whatsoever. | |
257 | has crux && distro=$(crux) | |
258 | has guix && distro='Guix System' | |
259 | fi | |
260 | ||
261 | # 'os-release' and 'lsb_release' sometimes add quotes | |
262 | # around the distribution name, strip them. | |
263 | distro=${distro##[\"\']} | |
264 | distro=${distro%%[\"\']} | |
265 | ||
266 | # Check to see if we're running Bedrock Linux which is | |
267 | # very unique. This simply checks to see if the user's | |
268 | # PATH contains a Bedrock specific value. | |
269 | case $PATH in | |
270 | (*/bedrock/cross/*) | |
271 | distro='Bedrock Linux' | |
272 | ;; | |
273 | esac | |
274 | ||
275 | # Check to see if Linux is running in Windows 10 under | |
276 | # WSL1 (Windows subsystem for Linux [version 1]) and | |
277 | # append a string accordingly. | |
278 | # | |
279 | # If the kernel version string ends in "-Microsoft", | |
280 | # we're very likely running under Windows 10 in WSL1. | |
281 | if [ "$WSLENV" ]; then | |
282 | distro="${distro}${WSLENV+ on Windows 10 [WSL2]}" | |
283 | ||
284 | # Check to see if Linux is running in Windows 10 under | |
285 | # WSL2 (Windows subsystem for Linux [version 2]) and | |
286 | # append a string accordingly. | |
287 | # | |
288 | # This checks to see if '$WSLENV' is defined. This | |
289 | # appends the Windows 10 string even if '$WSLENV' is | |
290 | # empty. We only need to check that is has been _exported_. | |
291 | elif [ -z "${kernel%%*-Microsoft}" ]; then | |
292 | distro="$distro on Windows 10 [WSL1]" | |
293 | fi | |
294 | ;; | |
295 | ||
296 | (Darwin*) | |
297 | # Parse the SystemVersion.plist file to grab the macOS | |
298 | # version. The file is in the following format: | |
299 | # | |
300 | # | |
301 | # | |
302 | # | |
303 | # 'IFS' is set to '<>' to enable splitting between the | |
304 | # keys and a second 'read' is used to operate on the | |
305 | # next line directly after a match. | |
306 | # | |
307 | # '_' is used to nullify a field. '_ _ line _' basically | |
308 | # says "populate $line with the third field's contents". | |
309 | while IFS='<>' read -r _ _ line _; do | |
310 | case $line in | |
311 | # Match 'ProductVersion' and read the next line | |
312 | # directly as it contains the key's value. | |
313 | ProductVersion) | |
314 | IFS='<>' read -r _ _ mac_version _ | |
315 | continue | |
316 | ;; | |
317 | ||
318 | ProductName) | |
319 | IFS='<>' read -r _ _ mac_product _ | |
320 | continue | |
321 | ;; | |
322 | esac | |
323 | done < /System/Library/CoreServices/SystemVersion.plist | |
324 | ||
325 | # Use the ProductVersion to determine which macOS/OS X codename | |
326 | # the system has. As far as I'm aware there's no "dynamic" way | |
327 | # of grabbing this information. | |
328 | case $mac_version in | |
329 | (10.4*) distro='Mac OS X Tiger' ;; | |
330 | (10.5*) distro='Mac OS X Leopard' ;; | |
331 | (10.6*) distro='Mac OS X Snow Leopard' ;; | |
332 | (10.7*) distro='Mac OS X Lion' ;; | |
333 | (10.8*) distro='OS X Mountain Lion' ;; | |
334 | (10.9*) distro='OS X Mavericks' ;; | |
335 | (10.10*) distro='OS X Yosemite' ;; | |
336 | (10.11*) distro='OS X El Capitan' ;; | |
337 | (10.12*) distro='macOS Sierra' ;; | |
338 | (10.13*) distro='macOS High Sierra' ;; | |
339 | (10.14*) distro='macOS Mojave' ;; | |
340 | (10.15*) distro='macOS Catalina' ;; | |
341 | (11*) distro='macOS Big Sur' ;; | |
342 | (12*) distro='macOS Monterey' ;; | |
343 | (*) distro='macOS' ;; | |
344 | esac | |
345 | ||
346 | # Use the ProductName to determine if we're running in iOS. | |
347 | case $mac_product in | |
348 | (iP*) distro='iOS' ;; | |
349 | esac | |
350 | ||
351 | distro="$distro $mac_version" | |
352 | ;; | |
353 | ||
354 | (Haiku) | |
355 | # Haiku uses 'uname -v' for version information | |
356 | # instead of 'uname -r' which only prints '1'. | |
357 | distro=$(uname -sv) | |
358 | ;; | |
359 | ||
360 | (Minix|DragonFly) | |
361 | distro="$os $kernel" | |
362 | ||
363 | # Minix and DragonFly don't support the escape | |
364 | # sequences used, clear the exit trap. | |
365 | trap '' EXIT | |
366 | ;; | |
367 | ||
368 | (SunOS) | |
369 | # Grab the first line of the '/etc/release' file | |
370 | # discarding everything after '('. | |
371 | IFS='(' read -r distro _ < /etc/release | |
372 | ;; | |
373 | ||
374 | (OpenBSD*) | |
375 | # Show the OpenBSD version type (current if present). | |
376 | # kern.version=OpenBSD 6.6-current (GENERIC.MP) ... | |
377 | IFS=' =' read -r _ distro openbsd_ver _ <<-EOF | |
378 | $(sysctl kern.version) | |
379 | EOF | |
380 | ||
381 | distro="$distro $openbsd_ver" | |
382 | ;; | |
383 | ||
384 | (FreeBSD) | |
385 | distro="$os $(freebsd-version)" | |
386 | ;; | |
387 | ||
388 | (*) | |
389 | # Catch all to ensure '$distro' is never blank. | |
390 | # This also handles the BSDs. | |
391 | distro="$os $kernel" | |
392 | ;; | |
393 | esac | |
394 | } | |
395 | ||
396 | get_kernel() { | |
397 | case $os in | |
398 | # Don't print kernel output on some systems as the | |
399 | # OS name includes it. | |
400 | (*BSD*|Haiku|Minix) | |
401 | return | |
402 | ;; | |
403 | esac | |
404 | ||
405 | # '$kernel' is the cached output of 'uname -r'. | |
406 | log kernel "$kernel" >&6 | |
407 | } | |
408 | ||
409 | get_host() { | |
410 | case $os in | |
411 | (Linux*) | |
412 | # Despite what these files are called, version doesn't | |
413 | # always contain the version nor does name always contain | |
414 | # the name. | |
415 | read -r name < /sys/devices/virtual/dmi/id/product_name | |
416 | read -r version < /sys/devices/virtual/dmi/id/product_version | |
417 | read -r model < /sys/firmware/devicetree/base/model | |
418 | ||
419 | host="$name $version $model" | |
420 | ;; | |
421 | ||
422 | (Darwin* | FreeBSD* | DragonFly*) | |
423 | host=$(sysctl -n hw.model) | |
424 | ;; | |
425 | ||
426 | (NetBSD*) | |
427 | host=$(sysctl -n machdep.dmi.system-vendor \ | |
428 | machdep.dmi.system-product) | |
429 | ;; | |
430 | ||
431 | (OpenBSD*) | |
432 | host=$(sysctl -n hw.version) | |
433 | ;; | |
434 | ||
435 | (*BSD* | Minix) | |
436 | host=$(sysctl -n hw.vendor hw.product) | |
437 | ;; | |
438 | esac | |
439 | ||
440 | # Turn the host string into an argument list so we can iterate | |
441 | # over it and remove OEM strings and other information which | |
442 | # shouldn't be displayed. | |
443 | # | |
444 | # Disable the shellcheck warning for word-splitting | |
445 | # as it's safe and intended ('set -f' disables globbing). | |
446 | # shellcheck disable=2046,2086 | |
447 | { | |
448 | set -f | |
449 | set +f -- $host | |
450 | host= | |
451 | } | |
452 | ||
453 | # Iterate over the host string word by word as a means of stripping | |
454 | # unwanted and OEM information from the string as a whole. | |
455 | # | |
456 | # This could have been implemented using a long 'sed' command with | |
457 | # a list of word replacements, however I want to show that something | |
458 | # like this is possible in pure sh. | |
459 | # | |
460 | # This string reconstruction is needed as some OEMs either leave the | |
461 | # identification information as "To be filled by OEM", "Default", | |
462 | # "undefined" etc and we shouldn't print this to the screen. | |
463 | for word do | |
464 | # This works by reconstructing the string by excluding words | |
465 | # found in the "blacklist" below. Only non-matches are appended | |
466 | # to the final host string. | |
467 | case $word in | |
468 | (To | [Bb]e | [Ff]illed | [Bb]y | O.E.M. | OEM |\ | |
469 | Not | Applicable | Specified | System | Product | Name |\ | |
470 | Version | Undefined | Default | string | INVALID | � | os |\ | |
471 | Type1ProductConfigId ) | |
472 | continue | |
473 | ;; | |
474 | esac | |
475 | ||
476 | host="$host$word " | |
477 | done | |
478 | ||
479 | # '$arch' is the cached output from 'uname -m'. | |
480 | log host "${host:-$arch}" >&6 | |
481 | } | |
482 | ||
483 | get_uptime() { | |
484 | # Uptime works by retrieving the data in total seconds and then | |
485 | # converting that data into days, hours and minutes using simple | |
486 | # math. | |
487 | case $os in | |
488 | (Linux* | Minix* | SerenityOS*) | |
489 | IFS=. read -r s _ < /proc/uptime | |
490 | ;; | |
491 | ||
492 | (Darwin* | *BSD* | DragonFly*) | |
493 | s=$(sysctl -n kern.boottime) | |
494 | ||
495 | # Extract the uptime in seconds from the following output: | |
496 | # [...] { sec = 1271934886, usec = 667779 } Thu Apr 22 12:14:46 2010 | |
497 | s=${s#*=} | |
498 | s=${s%,*} | |
499 | ||
500 | # The uptime format from 'sysctl' needs to be subtracted from | |
501 | # the current time in seconds. | |
502 | s=$(($(date +%s) - s)) | |
503 | ;; | |
504 | ||
505 | (Haiku) | |
506 | # The boot time is returned in microseconds, convert it to | |
507 | # regular seconds. | |
508 | s=$(($(system_time) / 1000000)) | |
509 | ;; | |
510 | ||
511 | (SunOS) | |
512 | # Split the output of 'kstat' on '.' and any white-space | |
513 | # which exists in the command output. | |
514 | # | |
515 | # The output is as follows: | |
516 | # unix:0:system_misc:snaptime 14809.906993005 | |
517 | # | |
518 | # The parser extracts: ^^^^^ | |
519 | IFS=' .' read -r _ s _ <<-EOF | |
520 | $(kstat -p unix:0:system_misc:snaptime) | |
521 | EOF | |
522 | ;; | |
523 | ||
524 | (IRIX) | |
525 | # Grab the uptime in a pretty format. Usually, | |
526 | # 00:00:00 from the 'ps' command. | |
527 | t=$(LC_ALL=POSIX ps -o etime= -p 1) | |
528 | ||
529 | # Split the pretty output into days or hours | |
530 | # based on the uptime. | |
531 | case $t in | |
532 | (*-*) d=${t%%-*} t=${t#*-} ;; | |
533 | (*:*:*) h=${t%%:*} t=${t#*:} ;; | |
534 | esac | |
535 | ||
536 | h=${h#0} t=${t#0} | |
537 | ||
538 | # Convert the split pretty fields back into | |
539 | # seconds so we may re-convert them to our format. | |
540 | s=$((${d:-0}*86400 + ${h:-0}*3600 + ${t%%:*}*60 + ${t#*:})) | |
541 | ;; | |
542 | esac | |
543 | ||
544 | # Convert the uptime from seconds into days, hours and minutes. | |
545 | d=$((s / 60 / 60 / 24)) | |
546 | h=$((s / 60 / 60 % 24)) | |
547 | m=$((s / 60 % 60)) | |
548 | ||
549 | # Only append days, hours and minutes if they're non-zero. | |
550 | case "$d" in ([!0]*) uptime="${uptime}${d}d "; esac | |
551 | case "$h" in ([!0]*) uptime="${uptime}${h}h "; esac | |
552 | case "$m" in ([!0]*) uptime="${uptime}${m}m "; esac | |
553 | ||
554 | log uptime "${uptime:-0m}" >&6 | |
555 | } | |
556 | ||
557 | get_pkgs() { | |
558 | # This works by first checking for which package managers are | |
559 | # installed and finally by printing each package manager's | |
560 | # package list with each package one per line. | |
561 | # | |
562 | # The output from this is then piped to 'wc -l' to count each | |
563 | # line, giving us the total package count of whatever package | |
564 | # managers are installed. | |
565 | packages=$( | |
566 | case $os in | |
567 | (Linux*) | |
568 | # Commands which print packages one per line. | |
569 | has bonsai && bonsai list | |
570 | has crux && pkginfo -i | |
571 | has pacman-key && pacman -Qq | |
572 | has dpkg && dpkg-query -f '.\n' -W | |
573 | has rpm && rpm -qa | |
574 | has xbps-query && xbps-query -l | |
575 | has apk && apk info | |
576 | has guix && guix package --list-installed | |
577 | has opkg && opkg list-installed | |
578 | ||
579 | # Directories containing packages. | |
580 | has kiss && printf '%s\n' /var/db/kiss/installed/*/ | |
581 | has cpt-list && printf '%s\n' /var/db/cpt/installed/*/ | |
582 | has brew && printf '%s\n' "$(brew --cellar)/"* | |
583 | has emerge && printf '%s\n' /var/db/pkg/*/*/ | |
584 | has pkgtool && printf '%s\n' /var/log/packages/* | |
585 | has eopkg && printf '%s\n' /var/lib/eopkg/package/* | |
586 | ||
587 | # 'nix' requires two commands. | |
588 | has nix-store && { | |
589 | nix-store -q --requisites /run/current-system/sw | |
590 | nix-store -q --requisites ~/.nix-profile | |
591 | } | |
592 | ;; | |
593 | ||
594 | (Darwin*) | |
595 | # Commands which print packages one per line. | |
596 | has pkgin && pkgin list | |
597 | has dpkg && dpkg-query -f '.\n' -W | |
598 | ||
599 | # Directories containing packages. | |
600 | has brew && printf '%s\n' /usr/local/Cellar/* | |
601 | ||
602 | # 'port' prints a single line of output to 'stdout' | |
603 | # when no packages are installed and exits with | |
604 | # success causing a false-positive of 1 package | |
605 | # installed. | |
606 | # | |
607 | # 'port' should really exit with a non-zero code | |
608 | # in this case to allow scripts to cleanly handle | |
609 | # this behavior. | |
610 | has port && { | |
611 | pkg_list=$(port installed) | |
612 | ||
613 | case "$pkg_list" in | |
614 | ("No ports are installed.") | |
615 | # do nothing | |
616 | ;; | |
617 | ||
618 | (*) | |
619 | printf '%s\n' "$pkg_list" | |
620 | ;; | |
621 | esac | |
622 | } | |
623 | ;; | |
624 | ||
625 | (FreeBSD*|DragonFly*) | |
626 | pkg info | |
627 | ;; | |
628 | ||
629 | (OpenBSD*) | |
630 | printf '%s\n' /var/db/pkg/*/ | |
631 | ;; | |
632 | ||
633 | (NetBSD*) | |
634 | pkg_info | |
635 | ;; | |
636 | ||
637 | (Haiku) | |
638 | printf '%s\n' /boot/system/package-links/* | |
639 | ;; | |
640 | ||
641 | (Minix) | |
642 | printf '%s\n' /usr/pkg/var/db/pkg/*/ | |
643 | ;; | |
644 | ||
645 | (SunOS) | |
646 | has pkginfo && pkginfo -i | |
647 | has pkg && pkg list | |
648 | ;; | |
649 | ||
650 | (IRIX) | |
651 | versions -b | |
652 | ;; | |
653 | ||
654 | (SerenityOS) | |
655 | while IFS=" " read -r type _; do | |
656 | [ "$type" != dependency ] && | |
657 | printf "\n" | |
658 | done < /usr/Ports/packages.db | |
659 | ;; | |
660 | esac | wc -l | |
661 | ) | |
662 | ||
663 | # 'wc -l' can have leading and/or trailing whitespace | |
664 | # depending on the implementation, so strip them. | |
665 | # Procedure explained at https://github.com/dylanaraps/pure-sh-bible | |
666 | # (trim-leading-and-trailing-white-space-from-string) | |
667 | packages=${packages#"${packages%%[![:space:]]*}"} | |
668 | packages=${packages%"${packages##*[![:space:]]}"} | |
669 | ||
670 | case $os in | |
671 | # IRIX's package manager adds 3 lines of extra | |
672 | # output which we must account for here. | |
673 | (IRIX) | |
674 | packages=$((packages - 3)) | |
675 | ;; | |
676 | ||
677 | # OpenBSD's wc prints whitespace before the output | |
678 | # which needs to be stripped. | |
679 | (OpenBSD) | |
680 | packages=$((packages)) | |
681 | ;; | |
682 | esac | |
683 | ||
684 | case $packages in | |
685 | (1?*|[2-9]*) | |
686 | log pkgs "$packages" >&6 | |
687 | ;; | |
688 | esac | |
689 | } | |
690 | ||
691 | get_memory() { | |
692 | case $os in | |
693 | # Used memory is calculated using the following "formula": | |
694 | # MemUsed = MemTotal + Shmem - MemFree - Buffers - Cached - SReclaimable | |
695 | # Source: https://github.com/KittyKatt/screenFetch/issues/386 | |
696 | (Linux*) | |
697 | # Parse the '/proc/meminfo' file splitting on ':' and 'k'. | |
698 | # The format of the file is 'key: 000kB' and an additional | |
699 | # split is used on 'k' to filter out 'kB'. | |
700 | while IFS=':k ' read -r key val _; do | |
701 | case $key in | |
702 | (MemTotal) | |
703 | mem_used=$((mem_used + val)) | |
704 | mem_full=$val | |
705 | ;; | |
706 | ||
707 | (Shmem) | |
708 | mem_used=$((mem_used + val)) | |
709 | ;; | |
710 | ||
711 | (MemFree | Buffers | Cached | SReclaimable) | |
712 | mem_used=$((mem_used - val)) | |
713 | ;; | |
714 | ||
715 | # If detected this will be used over the above calculation | |
716 | # for mem_used. Available since Linux 3.14rc. | |
717 | # See kernel commit 34e431b0ae398fc54ea69ff85ec700722c9da773 | |
718 | (MemAvailable) | |
719 | mem_avail=$val | |
720 | ;; | |
721 | esac | |
722 | done < /proc/meminfo | |
723 | ||
724 | case $mem_avail in | |
725 | (*[0-9]*) | |
726 | mem_used=$(((mem_full - mem_avail) / 1024)) | |
727 | ;; | |
728 | ||
729 | *) | |
730 | mem_used=$((mem_used / 1024)) | |
731 | ;; | |
732 | esac | |
733 | ||
734 | mem_full=$((mem_full / 1024)) | |
735 | ;; | |
736 | ||
737 | # Used memory is calculated using the following "formula": | |
738 | # (wired + active + occupied) * 4 / 1024 | |
739 | (Darwin*) | |
740 | mem_full=$(($(sysctl -n hw.memsize) / 1024 / 1024)) | |
741 | ||
742 | # Parse the 'vmstat' file splitting on ':' and '.'. | |
743 | # The format of the file is 'key: 000.' and an additional | |
744 | # split is used on '.' to filter it out. | |
745 | while IFS=:. read -r key val; do | |
746 | case $key in | |
747 | (*' wired'*|*' active'*|*' occupied'*) | |
748 | mem_used=$((mem_used + ${val:-0})) | |
749 | ;; | |
750 | esac | |
751 | ||
752 | # Using '<<-EOF' is the only way to loop over a command's | |
753 | # output without the use of a pipe ('|'). | |
754 | # This ensures that any variables defined in the while loop | |
755 | # are still accessible in the script. | |
756 | done <<-EOF | |
757 | $(vm_stat) | |
758 | EOF | |
759 | ||
760 | mem_used=$((mem_used * 4 / 1024)) | |
761 | ;; | |
762 | ||
763 | (OpenBSD*) | |
764 | mem_full=$(($(sysctl -n hw.physmem) / 1024 / 1024)) | |
765 | ||
766 | # This is a really simpler parser for 'vmstat' which grabs | |
767 | # the used memory amount in a lazy way. 'vmstat' prints 3 | |
768 | # lines of output with the needed value being stored in the | |
769 | # final line. | |
770 | # | |
771 | # This loop simply grabs the 3rd element of each line until | |
772 | # the EOF is reached. Each line overwrites the value of the | |
773 | # previous one so we're left with what we wanted. This isn't | |
774 | # slow as only 3 lines are parsed. | |
775 | while read -r _ _ line _; do | |
776 | mem_used=${line%%M} | |
777 | ||
778 | # Using '<<-EOF' is the only way to loop over a command's | |
779 | # output without the use of a pipe ('|'). | |
780 | # This ensures that any variables defined in the while loop | |
781 | # are still accessible in the script. | |
782 | done <<-EOF | |
783 | $(vmstat) | |
784 | EOF | |
785 | ;; | |
786 | ||
787 | # Used memory is calculated using the following "formula": | |
788 | # mem_full - ((inactive + free + cache) * page_size / 1024) | |
789 | (FreeBSD*|DragonFly*) | |
790 | mem_full=$(($(sysctl -n hw.physmem) / 1024 / 1024)) | |
791 | ||
792 | # Use 'set --' to store the output of the command in the | |
793 | # argument list. POSIX sh has no arrays but this is close enough. | |
794 | # | |
795 | # Disable the shellcheck warning for word-splitting | |
796 | # as it's safe and intended ('set -f' disables globbing). | |
797 | # shellcheck disable=2046 | |
798 | { | |
799 | set -f | |
800 | set +f -- $(sysctl -n hw.pagesize \ | |
801 | vm.stats.vm.v_inactive_count \ | |
802 | vm.stats.vm.v_free_count \ | |
803 | vm.stats.vm.v_cache_count) | |
804 | } | |
805 | ||
806 | # Calculate the amount of used memory. | |
807 | # $1: hw.pagesize | |
808 | # $2: vm.stats.vm.v_inactive_count | |
809 | # $3: vm.stats.vm.v_free_count | |
810 | # $4: vm.stats.vm.v_cache_count | |
811 | mem_used=$((mem_full - (($2 + $3 + $4) * $1 / 1024 / 1024))) | |
812 | ;; | |
813 | ||
814 | (NetBSD*) | |
815 | mem_full=$(($(sysctl -n hw.physmem64) / 1024 / 1024)) | |
816 | ||
817 | # NetBSD implements a lot of the Linux '/proc' filesystem, | |
818 | # this uses the same parser as the Linux memory detection. | |
819 | while IFS=':k ' read -r key val _; do | |
820 | case $key in | |
821 | (MemFree) | |
822 | mem_free=$((val / 1024)) | |
823 | break | |
824 | ;; | |
825 | esac | |
826 | done < /proc/meminfo | |
827 | ||
828 | mem_used=$((mem_full - mem_free)) | |
829 | ;; | |
830 | ||
831 | (Haiku) | |
832 | # Read the first line of 'sysinfo -mem' splitting on | |
833 | # '(', ' ', and ')'. The needed information is then | |
834 | # stored in the 5th and 7th elements. Using '_' "consumes" | |
835 | # an element allowing us to proceed to the next one. | |
836 | # | |
837 | # The parsed format is as follows: | |
838 | # 3501142016 bytes free (used/max 792645632 / 4293787648) | |
839 | IFS='( )' read -r _ _ _ _ mem_used _ mem_full <<-EOF | |
840 | $(sysinfo -mem) | |
841 | EOF | |
842 | ||
843 | mem_used=$((mem_used / 1024 / 1024)) | |
844 | mem_full=$((mem_full / 1024 / 1024)) | |
845 | ;; | |
846 | ||
847 | (Minix) | |
848 | # Minix includes the '/proc' filesystem though the format | |
849 | # differs from Linux. The '/proc/meminfo' file is only a | |
850 | # single line with space separated elements and elements | |
851 | # 2 and 3 contain the total and free memory numbers. | |
852 | read -r _ mem_full mem_free _ < /proc/meminfo | |
853 | ||
854 | mem_used=$(((mem_full - mem_free) / 1024)) | |
855 | mem_full=$(( mem_full / 1024)) | |
856 | ;; | |
857 | ||
858 | (SunOS) | |
859 | hw_pagesize=$(pagesize) | |
860 | ||
861 | # 'kstat' outputs memory in the following format: | |
862 | # unix:0:system_pages:pagestotal 1046397 | |
863 | # unix:0:system_pages:pagesfree 885018 | |
864 | # | |
865 | # This simply uses the first "element" (white-space | |
866 | # separated) as the key and the second element as the | |
867 | # value. | |
868 | # | |
869 | # A variable is then assigned based on the key. | |
870 | while read -r key val; do | |
871 | case $key in | |
872 | (*total) | |
873 | pages_full=$val | |
874 | ;; | |
875 | ||
876 | (*free) | |
877 | pages_free=$val | |
878 | ;; | |
879 | esac | |
880 | done <<-EOF | |
881 | $(kstat -p unix:0:system_pages:pagestotal \ | |
882 | unix:0:system_pages:pagesfree) | |
883 | EOF | |
884 | ||
885 | mem_full=$((pages_full * hw_pagesize / 1024 / 1024)) | |
886 | mem_free=$((pages_free * hw_pagesize / 1024 / 1024)) | |
887 | mem_used=$((mem_full - mem_free)) | |
888 | ;; | |
889 | ||
890 | (IRIX) | |
891 | # Read the memory information from the 'top' command. Parse | |
892 | # and split each line until we reach the line starting with | |
893 | # "Memory". | |
894 | # | |
895 | # Example output: Memory: 160M max, 147M avail, ..... | |
896 | while IFS=' :' read -r label mem_full _ mem_free _; do | |
897 | case $label in | |
898 | (Memory) | |
899 | mem_full=${mem_full%M} | |
900 | mem_free=${mem_free%M} | |
901 | break | |
902 | ;; | |
903 | esac | |
904 | done <<-EOF | |
905 | $(top -n) | |
906 | EOF | |
907 | ||
908 | mem_used=$((mem_full - mem_free)) | |
909 | ;; | |
910 | ||
911 | (SerenityOS) | |
912 | IFS='{}' read -r _ memstat _ < /proc/memstat | |
913 | ||
914 | set -f -- "$IFS" | |
915 | IFS=, | |
916 | ||
917 | for pair in $memstat; do | |
918 | case $pair in | |
919 | (*user_physical_allocated*) | |
920 | mem_used=${pair##*:} | |
921 | ;; | |
922 | ||
923 | (*user_physical_available*) | |
924 | mem_free=${pair##*:} | |
925 | ;; | |
926 | esac | |
927 | done | |
928 | ||
929 | IFS=$1 | |
930 | set +f -- | |
931 | ||
932 | mem_used=$((mem_used * 4096 / 1024 / 1024)) | |
933 | mem_free=$((mem_free * 4096 / 1024 / 1024)) | |
934 | ||
935 | mem_full=$((mem_used + mem_free)) | |
936 | ;; | |
937 | esac | |
938 | ||
939 | log memory "${mem_used:-?}M / ${mem_full:-?}M" >&6 | |
940 | } | |
941 | ||
942 | get_wm() { | |
943 | case $os in | |
944 | (Darwin*) | |
945 | # Don't display window manager on macOS. | |
946 | ;; | |
947 | ||
948 | (*) | |
949 | # xprop can be used to grab the window manager's properties | |
950 | # which contains the window manager's name under '_NET_WM_NAME'. | |
951 | # | |
952 | # The upside to using 'xprop' is that you don't need to hardcode | |
953 | # a list of known window manager names. The downside is that | |
954 | # not all window managers conform to setting the '_NET_WM_NAME' | |
955 | # atom.. | |
956 | # | |
957 | # List of window managers which fail to set the name atom: | |
958 | # catwm, fvwm, dwm, 2bwm, monster, wmaker and sowm [mine! ;)]. | |
959 | # | |
960 | # The final downside to this approach is that it does _not_ | |
961 | # support Wayland environments. The only solution which supports | |
962 | # Wayland is the 'ps' parsing mentioned below. | |
963 | # | |
964 | # A more naive implementation is to parse the last line of | |
965 | # '~/.xinitrc' to extract the second white-space separated | |
966 | # element. | |
967 | # | |
968 | # The issue with an approach like this is that this line data | |
969 | # does not always equate to the name of the window manager and | |
970 | # could in theory be _anything_. | |
971 | # | |
972 | # This also fails when the user launches xorg through a display | |
973 | # manager or other means. | |
974 | # | |
975 | # | |
976 | # Another naive solution is to parse 'ps' with a hardcoded list | |
977 | # of window managers to detect the current window manager (based | |
978 | # on what is running). | |
979 | # | |
980 | # The issue with this approach is the need to hardcode and | |
981 | # maintain a list of known window managers. | |
982 | # | |
983 | # Another issue is that process names do not always equate to | |
984 | # the name of the window manager. False-positives can happen too. | |
985 | # | |
986 | # This is the only solution which supports Wayland based | |
987 | # environments sadly. It'd be nice if some kind of standard were | |
988 | # established to identify Wayland environments. | |
989 | # | |
990 | # pfetch's goal is to remain _simple_, if you'd like a "full" | |
991 | # implementation of window manager detection use 'neofetch'. | |
992 | # | |
993 | # Neofetch use a combination of 'xprop' and 'ps' parsing to | |
994 | # support all window managers (including non-conforming and | |
995 | # Wayland) though it's a lot more complicated! | |
996 | ||
997 | # Don't display window manager if X isn't running. | |
998 | [ "$DISPLAY" ] || return | |
999 | ||
1000 | # This is a two pass call to xprop. One call to get the window | |
1001 | # manager's ID and another to print its properties. | |
1002 | has xprop && { | |
1003 | # The output of the ID command is as follows: | |
1004 | # _NET_SUPPORTING_WM_CHECK: window id # 0x400000 | |
1005 | # | |
1006 | # To extract the ID, everything before the last space | |
1007 | # is removed. | |
1008 | id=$(xprop -root -notype _NET_SUPPORTING_WM_CHECK) | |
1009 | id=${id##* } | |
1010 | ||
1011 | # The output of the property command is as follows: | |
1012 | # _NAME 8t | |
1013 | # _NET_WM_PID = 252 | |
1014 | # _NET_WM_NAME = "bspwm" | |
1015 | # _NET_SUPPORTING_WM_CHECK: window id # 0x400000 | |
1016 | # WM_CLASS = "wm", "Bspwm" | |
1017 | # | |
1018 | # To extract the name, everything before '_NET_WM_NAME = \"' | |
1019 | # is removed and everything after the next '"' is removed. | |
1020 | wm=$(xprop -id "$id" -notype -len 25 -f _NET_WM_NAME 8t) | |
1021 | } | |
1022 | ||
1023 | # Handle cases of a window manager _not_ populating the | |
1024 | # '_NET_WM_NAME' atom. Display nothing in this case. | |
1025 | case $wm in | |
1026 | (*'_NET_WM_NAME = '*) | |
1027 | wm=${wm##*_NET_WM_NAME = \"} | |
1028 | wm=${wm%%\"*} | |
1029 | ;; | |
1030 | ||
1031 | (*) | |
1032 | # Fallback to checking the process list | |
1033 | # for the select few window managers which | |
1034 | # don't set '_NET_WM_NAME'. | |
1035 | while read -r ps_line; do | |
1036 | case $ps_line in | |
1037 | (*catwm*) wm=catwm ;; | |
1038 | (*fvwm*) wm=fvwm ;; | |
1039 | (*dwm*) wm=dwm ;; | |
1040 | (*2bwm*) wm=2bwm ;; | |
1041 | (*monsterwm*) wm=monsterwm ;; | |
1042 | (*wmaker*) wm='Window Maker' ;; | |
1043 | (*sowm*) wm=sowm ;; | |
1044 | (*penrose*) wm=penrose ;; | |
1045 | esac | |
1046 | done <<-EOF | |
1047 | $(ps x) | |
1048 | EOF | |
1049 | ;; | |
1050 | esac | |
1051 | ;; | |
1052 | esac | |
1053 | ||
1054 | log wm "$wm" >&6 | |
1055 | } | |
1056 | ||
1057 | ||
1058 | get_de() { | |
1059 | # This only supports Xorg related desktop environments though | |
1060 | # this is fine as knowing the desktop environment on Windows, | |
1061 | # macOS etc is useless (they'll always report the same value). | |
1062 | # | |
1063 | # Display the value of '$XDG_CURRENT_DESKTOP', if it's empty, | |
1064 | # display the value of '$DESKTOP_SESSION'. | |
1065 | log de "${XDG_CURRENT_DESKTOP:-$DESKTOP_SESSION}" >&6 | |
1066 | } | |
1067 | ||
1068 | get_shell() { | |
1069 | # Display the basename of the '$SHELL' environment variable. | |
1070 | log shell "${SHELL##*/}" >&6 | |
1071 | } | |
1072 | ||
1073 | get_editor() { | |
1074 | # Display the value of '$VISUAL', if it's empty, display the | |
1075 | # value of '$EDITOR'. | |
1076 | editor=${VISUAL:-"$EDITOR"} | |
1077 | ||
1078 | log editor "${editor##*/}" >&6 | |
1079 | } | |
1080 | ||
1081 | get_palette() { | |
1082 | # Print the first 8 terminal colors. This uses the existing | |
1083 | # sequences to change text color with a sequence prepended | |
1084 | # to reverse the foreground and background colors. | |
1085 | # | |
1086 | # This allows us to save hardcoding a second set of sequences | |
1087 | # for background colors. | |
1088 | # | |
1089 | # False positive. | |
1090 | # shellcheck disable=2154 | |
1091 | { | |
1092 | esc SGR 7 | |
1093 | palette="$e$c1 $c1 $c2 $c2 $c3 $c3 $c4 $c4 $c5 $c5 $c6 $c6 " | |
1094 | esc SGR 0 | |
1095 | palette="$palette$e" | |
1096 | } | |
1097 | ||
1098 | # Print the palette with a new-line before and afterwards but no seperator. | |
1099 | printf '\n' >&6 | |
1100 | log "$palette | |
1101 | " " " " " >&6 | |
1102 | } | |
1103 | ||
1104 | get_ascii() { | |
1105 | # This is a simple function to read the contents of | |
1106 | # an ascii file from 'stdin'. It allows for the use | |
1107 | # of '<<-EOF' to prevent the break in indentation in | |
1108 | # this source code. | |
1109 | # | |
1110 | # This function also sets the text colors according | |
1111 | # to the ascii color. | |
1112 | read_ascii() { | |
1113 | # 'PF_COL1': Set the info name color according to ascii color. | |
1114 | # 'PF_COL3': Set the title color to some other color. ¯\_(ツ)_/¯ | |
1115 | PF_COL1=${PF_COL1:-${1:-7}} | |
1116 | PF_COL3=${PF_COL3:-$((${1:-7}%8+1))} | |
1117 | ||
1118 | # POSIX sh has no 'var+=' so 'var=${var}append' is used. What's | |
1119 | # interesting is that 'var+=' _is_ supported inside '$(())' | |
1120 | # (arithmetic) though there's no support for 'var++/var--'. | |
1121 | # | |
1122 | # There is also no $'\n' to add a "literal"(?) newline to the | |
1123 | # string. The simplest workaround being to break the line inside | |
1124 | # the string (though this has the caveat of breaking indentation). | |
1125 | while IFS= read -r line; do | |
1126 | ascii="$ascii$line | |
1127 | " | |
1128 | done | |
1129 | } | |
1130 | ||
1131 | # This checks for ascii art in the following order: | |
1132 | # '$1': Argument given to 'get_ascii()' directly. | |
1133 | # '$PF_ASCII': Environment variable set by user. | |
1134 | # '$distro': The detected distribution name. | |
1135 | # '$os': The name of the operating system/kernel. | |
1136 | # | |
1137 | # NOTE: Each ascii art below is indented using tabs, this | |
1138 | # allows indentation to continue naturally despite | |
1139 | # the use of '<<-EOF'. | |
1140 | # | |
1141 | # False positive. | |
1142 | # shellcheck disable=2154 | |
1143 | case ${1:-${PF_ASCII:-${distro:-$os}}} in | |
1144 | ([Aa]lpine*) | |
1145 | read_ascii 4 <<-EOF | |
1146 | ${c4} /\\ /\\ | |
1147 | /${c7}/ ${c4}\\ \\ | |
1148 | /${c7}/ ${c4}\\ \\ | |
1149 | /${c7}// ${c4}\\ \\ | |
1150 | ${c7}// ${c4}\\ \\ | |
1151 | ${c4}\\ | |
1152 | EOF | |
1153 | ;; | |
1154 | ||
1155 | ([Aa]ndroid*) | |
1156 | read_ascii 2 <<-EOF | |
1157 | ${c2} ;, ,; | |
1158 | ${c2} ';,.-----.,;' | |
1159 | ${c2} ,' ', | |
1160 | ${c2} / O O \\ | |
1161 | ${c2}| | | |
1162 | ${c2}'-----------------' | |
1163 | EOF | |
1164 | ;; | |
1165 | ||
1166 | ([Aa]rch*) | |
1167 | read_ascii 4 <<-EOF | |
1168 | ${c6} /\\ | |
1169 | ${c6} / \\ | |
1170 | ${c6} /\\ \\ | |
1171 | ${c4} / \\ | |
1172 | ${c4} / ,, \\ | |
1173 | ${c4} / | | -\\ | |
1174 | ${c4} /_-'' ''-_\\ | |
1175 | EOF | |
1176 | ;; | |
1177 | ||
1178 | ([Aa]rco*) | |
1179 | read_ascii 4 <<-EOF | |
1180 | ${c4} /\\ | |
1181 | ${c4} / \\ | |
1182 | ${c4} / /\\ \\ | |
1183 | ${c4} / / \\ \\ | |
1184 | ${c4} / / \\ \\ | |
1185 | ${c4} / / _____\\ \\ | |
1186 | ${c4}/_/ \`----.\\_\\ | |
1187 | EOF | |
1188 | ;; | |
1189 | ||
1190 | ([Aa]rtix*) | |
1191 | read_ascii 6 <<-EOF | |
1192 | ${c4} /\\ | |
1193 | ${c4} / \\ | |
1194 | ${c4} /\`'.,\\ | |
1195 | ${c4} / ', | |
1196 | ${c4} / ,\`\\ | |
1197 | ${c4} / ,.'\`. \\ | |
1198 | ${c4}/.,'\` \`'.\\ | |
1199 | EOF | |
1200 | ;; | |
1201 | ||
1202 | ([Bb]edrock*) | |
1203 | read_ascii 4 <<-EOF | |
1204 | ${c7}__ | |
1205 | ${c7}\\ \\___ | |
1206 | ${c7} \\ _ \\ | |
1207 | ${c7} \\___/ | |
1208 | EOF | |
1209 | ;; | |
1210 | ||
1211 | ([Bb]uildroot*) | |
1212 | read_ascii 3 <<-EOF | |
1213 | ${c3} ___ | |
1214 | ${c3} / \` \\ | |
1215 | ${c3}| : :| | |
1216 | ${c3}-. _:__.- | |
1217 | ${c3} \` ---- \` | |
1218 | EOF | |
1219 | ;; | |
1220 | ||
1221 | ([Cc]el[Oo][Ss]*) | |
1222 | read_ascii 5 0 <<-EOF | |
1223 | ${c5} .////\\\\\//\\. | |
1224 | ${c5} //_ \\\\ | |
1225 | ${c5} /_ ${c7}############## | |
1226 | ${c5} // *\\ | |
1227 | ${c7}############### ${c5}|# | |
1228 | ${c5} \/ */ | |
1229 | ${c5} \* ${c7}############## | |
1230 | ${c5} */, .// | |
1231 | ${c5} '_///\\\\\//_' | |
1232 | EOF | |
1233 | ;; | |
1234 | ||
1235 | ([Cc]ent[Oo][Ss]*) | |
1236 | read_ascii 5 <<-EOF | |
1237 | ${c2} ____${c3}^${c5}____ | |
1238 | ${c2} |\\ ${c3}|${c5} /| | |
1239 | ${c2} | \\ ${c3}|${c5} / | | |
1240 | ${c5}<---- ${c4}----> | |
1241 | ${c4} | / ${c2}|${c3} \\ | | |
1242 | ${c4} |/__${c2}|${c3}__\\| | |
1243 | ${c2} v | |
1244 | EOF | |
1245 | ;; | |
1246 | ||
1247 | ([Cc]rystal*[Ll]inux) | |
1248 | read_ascii 5 5 <<-EOF | |
1249 | ${c5} -//. | |
1250 | ${c5} -//. | |
1251 | ${c5} -//. . | |
1252 | ${c5} -//. '//- | |
1253 | ${c5} /+: :+/ | |
1254 | ${c5} .//' .//. | |
1255 | ${c5} . .//. | |
1256 | ${c5} .//. | |
1257 | ${c5} .//. | |
1258 | EOF | |
1259 | ;; | |
1260 | ||
1261 | ([Dd]ahlia*) | |
1262 | read_ascii 1 <<-EOF | |
1263 | ${c1} _ | |
1264 | ${c1} ___/ \\___ | |
1265 | ${c1} | _-_ | | |
1266 | ${c1} | / \ | | |
1267 | ${c1}/ | | \\ | |
1268 | ${c1}\\ | | / | |
1269 | ${c1} | \ _ _ / | | |
1270 | ${c1} |___ - ___| | |
1271 | ${c1} \\_/ | |
1272 | EOF | |
1273 | ;; | |
1274 | ||
1275 | ([Dd]ebian*) | |
1276 | read_ascii 1 <<-EOF | |
1277 | ${c1} _____ | |
1278 | ${c1} / __ \\ | |
1279 | ${c1}| / | | |
1280 | ${c1}| \\___- | |
1281 | ${c1}-_ | |
1282 | ${c1} --_ | |
1283 | EOF | |
1284 | ;; | |
1285 | ||
1286 | ([Dd]evuan*) | |
1287 | read_ascii 6 <<-EOF | |
1288 | ${c4} ..:::. | |
1289 | ${c4} ..-==- | |
1290 | ${c4} .+#: | |
1291 | ${c4} =@@ | |
1292 | ${c4} :+%@#: | |
1293 | ${c4}.:=+#@@%*: | |
1294 | ${c4}#@@@#=: | |
1295 | EOF | |
1296 | ;; | |
1297 | ||
1298 | ([Dd]ragon[Ff]ly*) | |
1299 | read_ascii 1 <<-EOF | |
1300 | ,${c1}_${c7}, | |
1301 | ('-_${c1}|${c7}_-') | |
1302 | >--${c1}|${c7}--< | |
1303 | (_-'${c1}|${c7}'-_) | |
1304 | ${c1}| | |
1305 | ${c1}| | |
1306 | ${c1}| | |
1307 | EOF | |
1308 | ;; | |
1309 | ||
1310 | ([Ee]lementary*) | |
1311 | read_ascii <<-EOF | |
1312 | ${c7} _______ | |
1313 | ${c7} / ____ \\ | |
1314 | ${c7}/ | / /\\ | |
1315 | ${c7}|__\\ / / | | |
1316 | ${c7}\\ /__/ / | |
1317 | ${c7}\\_______/ | |
1318 | EOF | |
1319 | ;; | |
1320 | ||
1321 | ([Ee]ndeavour*) | |
1322 | read_ascii 4 <<-EOF | |
1323 | ${c1}/${c4}\\ | |
1324 | ${c1}/${c4}/ \\${c6}\\ | |
1325 | ${c1}/${c4}/ \\ ${c6}\\ | |
1326 | ${c1}/ ${c4}/ _) ${c6}) | |
1327 | ${c1}/_${c4}/___-- ${c6}__- | |
1328 | ${c6}/____-- | |
1329 | EOF | |
1330 | ;; | |
1331 | ||
1332 | ([Ff]edora*) | |
1333 | read_ascii 4 <<-EOF | |
1334 | ${c4},'''''. | |
1335 | ${c4}| ,. | | |
1336 | ${c4}| | '_' | |
1337 | ${c4} ,....| |.. | |
1338 | ${c4}.' ,_;| ..' | |
1339 | ${c4}| | | | | |
1340 | ${c4}| ',_,' | | |
1341 | ${c4} '. ,' | |
1342 | ${c4}''''' | |
1343 | EOF | |
1344 | ;; | |
1345 | ||
1346 | ([Ff]ree[Bb][Ss][Dd]*) | |
1347 | read_ascii 1 <<-EOF | |
1348 | ${c1}/\\,-'''''-,/\\ | |
1349 | ${c1}\\_) (_/ | |
1350 | ${c1}| | | |
1351 | ${c1}| | | |
1352 | ${c1}; ; | |
1353 | ${c1}'-_____-' | |
1354 | EOF | |
1355 | ;; | |
1356 | ||
1357 | ([Gg]aruda*) | |
1358 | read_ascii 4 <<-EOF | |
1359 | ${c3} _______ | |
1360 | ${c3} __/ \\_ | |
1361 | ${c3} _/ / \\_ | |
1362 | ${c7} _/ /_________\\ | |
1363 | ${c7}_/ | | |
1364 | ${c2}\\ ____________ | |
1365 | ${c2} \\_ __/ | |
1366 | ${c2} \\__________/ | |
1367 | EOF | |
1368 | ;; | |
1369 | ||
1370 | ([Gg]entoo*) | |
1371 | read_ascii 5 <<-EOF | |
1372 | ${c5} _-----_ | |
1373 | ${c5}( \\ | |
1374 | ${c5}\\ 0 \\ | |
1375 | ${c7} \\ ) | |
1376 | ${c7} / _/ | |
1377 | ${c7}( _- | |
1378 | ${c7}\\____- | |
1379 | EOF | |
1380 | ;; | |
1381 | ||
1382 | ([Gg][Nn][Uu]*) | |
1383 | read_ascii 3 <<-EOF | |
1384 | ${c2} _-\`\`-, ,-\`\`-_ | |
1385 | ${c2} .' _-_| |_-_ '. | |
1386 | ${c2}./ /_._ _._\\ \\. | |
1387 | ${c2}: _/_._\`:'_._\\_ : | |
1388 | ${c2}\\:._/ ,\` \\ \\ \\_.:/ | |
1389 | ${c2} ,-';'.@) \\ @) \\ | |
1390 | ${c2} ,'/' ..- .\\,-.| | |
1391 | ${c2} /'/' \\(( \\\` ./ ) | |
1392 | ${c2} '/'' \\_,----' | |
1393 | ${c2} '/'' ,;/'' | |
1394 | ${c2} \`\`;' | |
1395 | EOF | |
1396 | ;; | |
1397 | ||
1398 | ([Gg]uix[Ss][Dd]*|[Gg]uix*) | |
1399 | read_ascii 3 <<-EOF | |
1400 | ${c3}|.__ __.| | |
1401 | ${c3}|__ \\ / __| | |
1402 | ${c3}\\ \\ / / | |
1403 | ${c3}\\ \\ / / | |
1404 | ${c3}\\ \\ / / | |
1405 | ${c3}\\ \\/ / | |
1406 | ${c3}\\__/ | |
1407 | EOF | |
1408 | ;; | |
1409 | ||
1410 | ([Hh]aiku*) | |
1411 | read_ascii 3 <<-EOF | |
1412 | ${c3} ,^, | |
1413 | ${c3} / \\ | |
1414 | ${c3}*--_ ; ; _--* | |
1415 | ${c3}\\ '" "' / | |
1416 | ${c3}'. .' | |
1417 | ${c3}.-'" "'-. | |
1418 | ${c3}'-.__. .__.-' | |
1419 | ${c3}|_| | |
1420 | EOF | |
1421 | ;; | |
1422 | ||
1423 | ([Hh]ydroOS*) | |
1424 | read_ascii 4 <<-EOF | |
1425 | ${c1}╔╗╔╗──╔╗───╔═╦══╗ | |
1426 | ${c1}║╚╝╠╦╦╝╠╦╦═╣║║══╣ | |
1427 | ${c1}║╔╗║║║╬║╔╣╬║║╠══║ | |
1428 | ${c1}╚╝╚╬╗╠═╩╝╚═╩═╩══╝ | |
1429 | ${c1}───╚═╝ | |
1430 | EOF | |
1431 | ;; | |
1432 | ||
1433 | ([Hh]yperbola*) | |
1434 | read_ascii <<-EOF | |
1435 | ${c7} |\`__.\`/ | |
1436 | ${c7} \____/ | |
1437 | ${c7} .--. | |
1438 | ${c7} / \\ | |
1439 | ${c7} / ___ \\ | |
1440 | ${c7}/ .\` \`.\\ | |
1441 | ${c7}/.\` \`.\\ | |
1442 | EOF | |
1443 | ;; | |
1444 | ||
1445 | ([Ii]glunix*) | |
1446 | read_ascii <<-EOF | |
1447 | ${c0} | | |
1448 | ${c0} | | | |
1449 | ${c0} | | |
1450 | ${c0} | ________ | |
1451 | ${c0} | /\\ | \\ | |
1452 | ${c0} / \\ | \\ | | |
1453 | ${c0} / \\ \\ | | |
1454 | ${c0} / \\________\\ | |
1455 | ${c0} \\ / / | |
1456 | ${c0} \\ / / | |
1457 | ${c0} \\ / / | |
1458 | ${c0} \\/________/ | |
1459 | EOF | |
1460 | ;; | |
1461 | ||
1462 | ([Ii]nstant[Oo][Ss]*) | |
1463 | read_ascii <<-EOF | |
1464 | ${c0} ,-''-, | |
1465 | ${c0}: .''. : | |
1466 | ${c0}: ',,' : | |
1467 | ${c0} '-____:__ | |
1468 | ${c0} : \`. | |
1469 | ${c0} \`._.' | |
1470 | EOF | |
1471 | ;; | |
1472 | ||
1473 | ([Ii][Rr][Ii][Xx]*) | |
1474 | read_ascii 1 <<-EOF | |
1475 | ${c1} __ | |
1476 | ${c1} \\ \\ __ | |
1477 | ${c1} \\ \\ / / | |
1478 | ${c1} \\ v / | |
1479 | ${c1} / . \\ | |
1480 | ${c1} /_/ \\ \\ | |
1481 | ${c1} \\_\\ | |
1482 | EOF | |
1483 | ;; | |
1484 | ||
1485 | ([Kk][Dd][Ee]*[Nn]eon*) | |
1486 | read_ascii 6 <<-EOF | |
1487 | ${c7} .${c6}__${c7}.${c6}__${c7}. | |
1488 | ${c6} / _${c7}.${c6}_ \\ | |
1489 | ${c6} / / \\ \\ | |
1490 | ${c7} . ${c6}| ${c7}O${c6} | ${c7}. | |
1491 | ${c6} \\ \\_${c7}.${c6}_/ / | |
1492 | ${c6} \\${c7}.${c6}__${c7}.${c6}__${c7}.${c6}/ | |
1493 | EOF | |
1494 | ;; | |
1495 | ||
1496 | ([Ll]inux*[Ll]ite*|[Ll]ite*) | |
1497 | read_ascii 3 <<-EOF | |
1498 | ${c3} /\\ | |
1499 | ${c3} / \\ | |
1500 | ${c3} / ${c7}/ ${c3}/ | |
1501 | ${c3}> ${c7}/ ${c3}/ | |
1502 | ${c3}\\ ${c7}\\ ${c3}\\ | |
1503 | ${c3}\\_${c7}\\${c3}_\\ | |
1504 | ${c7} \\ | |
1505 | EOF | |
1506 | ;; | |
1507 | ||
1508 | ([Ll]inux*[Mm]int*|[Mm]int) | |
1509 | read_ascii 2 <<-EOF | |
1510 | ${c2} ___________ | |
1511 | ${c2}|_ \\ | |
1512 | ${c2}| ${c7}| _____ ${c2}| | |
1513 | ${c2}| ${c7}| | | | ${c2}| | |
1514 | ${c2}| ${c7}| | | | ${c2}| | |
1515 | ${c2}| ${c7}\\__${c7}___/ ${c2}| | |
1516 | ${c2}\\_________/ | |
1517 | EOF | |
1518 | ;; | |
1519 | ||
1520 | ||
1521 | ([Ll]inux*) | |
1522 | read_ascii 4 <<-EOF | |
1523 | ${c4} ___ | |
1524 | ${c4}(${c7}.. ${c4}| | |
1525 | ${c4}(${c5}<> ${c4}| | |
1526 | ${c4}/ ${c7}__ ${c4}\\ | |
1527 | ${c4}( ${c7}/ \\ ${c4}/| | |
1528 | ${c5}_${c4}/\\ ${c7}__)${c4}/${c5}_${c4}) | |
1529 | ${c5}\/${c4}-____${c5}\/ | |
1530 | EOF | |
1531 | ;; | |
1532 | ||
1533 | ([Mm]ac[Oo][Ss]*|[Dd]arwin*) | |
1534 | read_ascii 1 <<-EOF | |
1535 | ${c2} .:' | |
1536 | ${c2} _ :'_ | |
1537 | ${c3} .'\`_\`-'_\`\`. | |
1538 | ${c1}:________.-' | |
1539 | ${c1}:_______: | |
1540 | ${c4} :_______\`-; | |
1541 | ${c5} \`._.-._.' | |
1542 | EOF | |
1543 | ;; | |
1544 | ||
1545 | ([Mm]ageia*) | |
1546 | read_ascii 2 <<-EOF | |
1547 | ${c6} * | |
1548 | ${c6} * | |
1549 | ${c6} ** | |
1550 | ${c7} /\\__/\\ | |
1551 | ${c7}/ \\ | |
1552 | ${c7}\\ / | |
1553 | ${c7} \\____/ | |
1554 | EOF | |
1555 | ;; | |
1556 | ||
1557 | ([Mm]anjaro*) | |
1558 | read_ascii 2 <<-EOF | |
1559 | ${c2}||||||||| |||| | |
1560 | ${c2}||||||||| |||| | |
1561 | ${c2}|||| |||| | |
1562 | ${c2}|||| |||| |||| | |
1563 | ${c2}|||| |||| |||| | |
1564 | ${c2}|||| |||| |||| | |
1565 | ${c2}|||| |||| |||| | |
1566 | EOF | |
1567 | ;; | |
1568 | ||
1569 | ([Mm]inix*) | |
1570 | read_ascii 4 <<-EOF | |
1571 | ${c4} ,, ,, | |
1572 | ${c4};${c7},${c4} ', ,' ${c7},${c4}; | |
1573 | ${c4}; ${c7}',${c4} ',,' ${c7},'${c4} ; | |
1574 | ${c4}; ${c7}',${c4} ${c7},'${c4} ; | |
1575 | ${c4}; ${c7};, '' ,;${c4} ; | |
1576 | ${c4}; ${c7};${c4};${c7}',,'${c4};${c7};${c4} ; | |
1577 | ${c4}', ${c7};${c4};; ;;${c7};${c4} ,' | |
1578 | ${c4} '${c7};${c4}' '${c7};${c4}' | |
1579 | EOF | |
1580 | ;; | |
1581 | ||
1582 | ([Mm][Xx]*) | |
1583 | read_ascii <<-EOF | |
1584 | ${c7} \\\\ / | |
1585 | ${c7} \\\\/ | |
1586 | ${c7} \\\\ | |
1587 | ${c7} /\\/ \\\\ | |
1588 | ${c7} / \\ /\\ | |
1589 | ${c7} / \\/ \\ | |
1590 | ${c7}/__________\\ | |
1591 | EOF | |
1592 | ;; | |
1593 | ||
1594 | ([Nn]et[Bb][Ss][Dd]*) | |
1595 | read_ascii 3 <<-EOF | |
1596 | ${c7}\\\\${c3}\`-______,----__ | |
1597 | ${c7} \\\\ ${c3}__,---\`_ | |
1598 | ${c7} \\\\ ${c3}\`.____ | |
1599 | ${c7} \\\\${c3}-______,----\`- | |
1600 | ${c7} \\\\ | |
1601 | ${c7} \\\\ | |
1602 | ${c7} \\\\ | |
1603 | EOF | |
1604 | ;; | |
1605 | ||
1606 | ([Nn]ix[Oo][Ss]*) | |
1607 | read_ascii 4 <<-EOF | |
1608 | ${c4} \\\\ \\\\ // | |
1609 | ${c4} ==\\\\__\\\\/ // | |
1610 | ${c4} // \\\\// | |
1611 | ${c4}==// //== | |
1612 | ${c4} //\\\\___// | |
1613 | ${c4}// /\\\\ \\\\== | |
1614 | ${c4} // \\\\ \\\\ | |
1615 | EOF | |
1616 | ;; | |
1617 | ||
1618 | ([Oo]pen[Bb][Ss][Dd]*) | |
1619 | read_ascii 3 <<-EOF | |
1620 | ${c3} _____ | |
1621 | ${c3} \\- -/ | |
1622 | ${c3} \\_/ \\ | |
1623 | ${c3} | ${c7}O O${c3} | | |
1624 | ${c3} |_ < ) 3 ) | |
1625 | ${c3} / \\ / | |
1626 | ${c3} /-_____-\\ | |
1627 | EOF | |
1628 | ;; | |
1629 | ||
1630 | ([Oo]pen[Ss][Uu][Ss][Ee]*[Tt]umbleweed*) | |
1631 | read_ascii 2 <<-EOF | |
1632 | ${c2} _____ ______ | |
1633 | ${c2} / ____\\ / ____ \\ | |
1634 | ${c2}/ / \`/ / \\ \\ | |
1635 | ${c2}\\ \\____/ /,____/ / | |
1636 | ${c2} \\______/ \\_____/ | |
1637 | EOF | |
1638 | ;; | |
1639 | ||
1640 | ([Oo]pen[Ss][Uu][Ss][Ee]*|[Oo]pen*SUSE*|SUSE*|suse*) | |
1641 | read_ascii 2 <<-EOF | |
1642 | ${c2} _______ | |
1643 | ${c2}__| __ \\ | |
1644 | ${c2} / .\\ \\ | |
1645 | ${c2} \\__/ | | |
1646 | ${c2} _______| | |
1647 | ${c2} \\_______ | |
1648 | ${c2}__________/ | |
1649 | EOF | |
1650 | ;; | |
1651 | ||
1652 | ([Oo]pen[Ww]rt*) | |
1653 | read_ascii 1 <<-EOF | |
1654 | ${c1} _______ | |
1655 | ${c1}| |.-----.-----.-----. | |
1656 | ${c1}| - || _ | -__| | | |
1657 | ${c1}|_______|| __|_____|__|__| | |
1658 | ${c1} ________|__| __ | |
1659 | ${c1}| | | |.----.| |_ | |
1660 | ${c1}| | | || _|| _| | |
1661 | ${c1}|________||__| |____| | |
1662 | EOF | |
1663 | ;; | |
1664 | ||
1665 | ([Pp]arabola*) | |
1666 | read_ascii 5 <<-EOF | |
1667 | ${c5} __ __ __ _ | |
1668 | ${c5}.\`_//_//_/ / \`. | |
1669 | ${c5} / .\` | |
1670 | ${c5} / .\` | |
1671 | ${c5} /.\` | |
1672 | ${c5} /\` | |
1673 | EOF | |
1674 | ;; | |
1675 | ||
1676 | ([Pp]op!_[Oo][Ss]*) | |
1677 | read_ascii 6 <<-EOF | |
1678 | ${c6}______ | |
1679 | ${c6}\\ _ \\ __ | |
1680 | ${c6}\\ \\ \\ \\ / / | |
1681 | ${c6}\\ \\_\\ \\ / / | |
1682 | ${c6}\\ ___\\ /_/ | |
1683 | ${c6} \\ \\ _ | |
1684 | ${c6} __\\_\\__(_)_ | |
1685 | ${c6}(___________) | |
1686 | EOF | |
1687 | ;; | |
1688 | ||
1689 | ([Pp]ure[Oo][Ss]*) | |
1690 | read_ascii <<-EOF | |
1691 | ${c7} _____________ | |
1692 | ${c7}| _________ | | |
1693 | ${c7}| | | | | |
1694 | ${c7}| | | | | |
1695 | ${c7}| |_________| | | |
1696 | ${c7}|_____________| | |
1697 | EOF | |
1698 | ;; | |
1699 | ||
1700 | ([Rr]aspbian*) | |
1701 | read_ascii 1 <<-EOF | |
1702 | ${c2} __ __ | |
1703 | ${c2} (_\\)(/_) | |
1704 | ${c1} (_(__)_) | |
1705 | ${c1}(_(_)(_)_) | |
1706 | ${c1} (_(__)_) | |
1707 | ${c1} (__) | |
1708 | EOF | |
1709 | ;; | |
1710 | ||
1711 | ([Ss]erenity[Oo][Ss]*) | |
1712 | read_ascii 4 <<-EOF | |
1713 | ${c7} _____ | |
1714 | ${c1} ,-${c7} -, | |
1715 | ${c1} ;${c7} ( ; | |
1716 | ${c1}| ${c7}. \_${c1}.,${c7} | | |
1717 | ${c1}| ${c7}o _${c1} ',${c7} | | |
1718 | ${c1} ; ${c7}(_)${c1} )${c7} ; | |
1719 | ${c1} '-_____-${c7}' | |
1720 | EOF | |
1721 | ;; | |
1722 | ||
1723 | ([Ss]lackware*) | |
1724 | read_ascii 4 <<-EOF | |
1725 | ${c4} ________ | |
1726 | ${c4} / ______| | |
1727 | ${c4} | |______ | |
1728 | ${c4} \\______ \\ | |
1729 | ${c4} ______| | | |
1730 | ${c4}| |________/ | |
1731 | ${c4}|____________ | |
1732 | EOF | |
1733 | ;; | |
1734 | ||
1735 | ([Ss]olus*) | |
1736 | read_ascii 4 <<-EOF | |
1737 | ${c6} | |
1738 | ${c6} /| | |
1739 | ${c6} / |\\ | |
1740 | ${c6} / | \\ _ | |
1741 | ${c6} /___|__\\_\\ | |
1742 | ${c6} \\ / | |
1743 | ${c6} \`-------´ | |
1744 | EOF | |
1745 | ;; | |
1746 | ||
1747 | ([Ss]un[Oo][Ss]|[Ss]olaris*) | |
1748 | read_ascii 3 <<-EOF | |
1749 | ${c3} . .; . | |
1750 | ${c3} . :; :: ;: . | |
1751 | ${c3} .;. .. .. .;. | |
1752 | ${c3}.. .. .. .. | |
1753 | ${c3} .;, ,;. | |
1754 | EOF | |
1755 | ;; | |
1756 | ||
1757 | ([Uu]buntu*) | |
1758 | read_ascii 3 <<-EOF | |
1759 | ${c3} _ | |
1760 | ${c3} ---(_) | |
1761 | ${c3} _/ --- \\ | |
1762 | ${c3}(_) | | | |
1763 | ${c3} \\ --- _/ | |
1764 | ${c3} ---(_) | |
1765 | EOF | |
1766 | ;; | |
1767 | ||
1768 | ([Vv]oid*) | |
1769 | read_ascii 2 <<-EOF | |
1770 | ${c2} _______ | |
1771 | ${c2} _ \\______ - | |
1772 | ${c2}| \\ ___ \\ | | |
1773 | ${c2}| | / \ | | | |
1774 | ${c2}| | \___/ | | | |
1775 | ${c2}| \\______ \\_| | |
1776 | ${c2} -_______\\ | |
1777 | EOF | |
1778 | ;; | |
1779 | ||
1780 | ([Xx]eonix*) | |
1781 | read_ascii 2 <<-EOF | |
1782 | ${c2} ___ ___ | |
1783 | ${c2}___ \ \/ / ___ | |
1784 | ${c2}\ \ \ / / / | |
1785 | ${c2} \ \/ \/ / | |
1786 | ${c2} \ /\ / | |
1787 | ${c2} \__/ \__/ | |
1788 | EOF | |
1789 | ;; | |
1790 | ||
1791 | (*) | |
1792 | # On no match of a distribution ascii art, this function calls | |
1793 | # itself again, this time to look for a more generic OS related | |
1794 | # ascii art (KISS Linux -> Linux). | |
1795 | [ "$1" ] || { | |
1796 | get_ascii "$os" | |
1797 | return | |
1798 | } | |
1799 | ||
1800 | printf 'error: %s is not currently supported.\n' "$os" >&6 | |
1801 | printf 'error: Open an issue for support to be added.\n' >&6 | |
1802 | exit 1 | |
1803 | ;; | |
1804 | esac | |
1805 | ||
1806 | # Store the "width" (longest line) and "height" (number of lines) | |
1807 | # of the ascii art for positioning. This script prints to the screen | |
1808 | # *almost* like a TUI does. It uses escape sequences to allow dynamic | |
1809 | # printing of the information through user configuration. | |
1810 | # | |
1811 | # Iterate over each line of the ascii art to retrieve the above | |
1812 | # information. The 'sed' is used to strip '\033[3Xm' color codes from | |
1813 | # the ascii art so they don't affect the width variable. | |
1814 | while read -r line; do | |
1815 | ascii_height=$((${ascii_height:-0} + 1)) | |
1816 | ||
1817 | # This was a ternary operation but they aren't supported in | |
1818 | # Minix's shell. | |
1819 | [ "${#line}" -gt "${ascii_width:-0}" ] && | |
1820 | ascii_width=${#line} | |
1821 | ||
1822 | # Using '<<-EOF' is the only way to loop over a command's | |
1823 | # output without the use of a pipe ('|'). | |
1824 | # This ensures that any variables defined in the while loop | |
1825 | # are still accessible in the script. | |
1826 | done <<-EOF | |
1827 | $(printf %s "$ascii" | sed 's/\[3.m//g') | |
1828 | EOF | |
1829 | ||
1830 | # Add a gap between the ascii art and the information. | |
1831 | ascii_width=$((ascii_width + 4)) | |
1832 | ||
1833 | # Print the ascii art and position the cursor back where we | |
1834 | # started prior to printing it. | |
1835 | { | |
1836 | esc_p SGR 1 | |
1837 | printf '%s' "$ascii" | |
1838 | esc_p SGR 0 | |
1839 | esc_p CUU "$ascii_height" | |
1840 | } >&6 | |
1841 | } | |
1842 | ||
1843 | main() { | |
1844 | case $* in | |
1845 | -v) | |
1846 | printf '%s 0.7.0\n' "${0##*/}" | |
1847 | return 0 | |
1848 | ;; | |
1849 | ||
1850 | -d) | |
1851 | # Below exec is not run, stderr is shown. | |
1852 | ;; | |
1853 | ||
1854 | '') | |
1855 | exec 2>/dev/null | |
1856 | ;; | |
1857 | ||
1858 | *) | |
1859 | cat < | |
1860 | ${0##*/} show system information | |
1861 | ${0##*/} -d show stderr (debug mode) | |
1862 | ${0##*/} -v show version information | |
1863 | EOF | |
1864 | return 0 | |
1865 | ;; | |
1866 | esac | |
1867 | ||
1868 | # Hide 'stdout' and selectively print to it using '>&6'. | |
1869 | # This gives full control over what it displayed on the screen. | |
1870 | exec 6>&1 >/dev/null | |
1871 | ||
1872 | # Store raw escape sequence character for later reuse. | |
1873 | esc_c=$(printf '\033') | |
1874 | ||
1875 | # Allow the user to execute their own script and modify or | |
1876 | # extend pfetch's behavior. | |
1877 | # shellcheck source=/dev/null | |
1878 | ! [ -f "$PF_SOURCE" ] || . "$PF_SOURCE" | |
1879 | ||
1880 | # Ensure that the 'TMPDIR' is writable as heredocs use it and | |
1881 | # fail without the write permission. This was found to be the | |
1882 | # case on Android where the temporary directory requires root. | |
1883 | [ -w "${TMPDIR:-/tmp}" ] || export TMPDIR=~ | |
1884 | ||
1885 | # Generic color list. | |
1886 | # Disable warning about unused variables. | |
1887 | # shellcheck disable=2034 | |
1888 | for _c in c1 c2 c3 c4 c5 c6 c7 c8; do | |
1889 | esc SGR "3${_c#?}" 0 | |
1890 | export "$_c=$e" | |
1891 | done | |
1892 | ||
1893 | # Disable line wrapping and catch the EXIT signal to enable it again | |
1894 | # on exit. Ideally you'd somehow query the current value and retain | |
1895 | # it but I'm yet to see this irk anyone. | |
1896 | esc_p DECAWM l >&6 | |
1897 | trap 'esc_p DECAWM h >&6' EXIT | |
1898 | ||
1899 | # Store the output of 'uname' to avoid calling it multiple times | |
1900 | # throughout the script. 'read < | |
1901 | # a command into a list of variables. | |
1902 | read -r os kernel arch <<-EOF | |
1903 | $(uname -srm) | |
1904 | EOF | |
1905 | ||
1906 | # Always run 'get_os' for the purposes of detecting which ascii | |
1907 | # art to display. | |
1908 | get_os | |
1909 | ||
1910 | # Allow the user to specify the order and inclusion of information | |
1911 | # functions through the 'PF_INFO' environment variable. | |
1912 | # shellcheck disable=2086 | |
1913 | { | |
1914 | # Disable globbing and set the positional parameters to the | |
1915 | # contents of 'PF_INFO'. | |
1916 | set -f | |
1917 | set +f -- ${PF_INFO-ascii title os host kernel uptime pkgs memory} | |
1918 | ||
1919 | # Iterate over the info functions to determine the lengths of the | |
1920 | # "info names" for output alignment. The option names and subtitles | |
1921 | # match 1:1 so this is thankfully simple. | |
1922 | for info do | |
1923 | command -v "get_$info" >/dev/null || continue | |
1924 | ||
1925 | # This was a ternary operation but they aren't supported in | |
1926 | # Minix's shell. | |
1927 | [ "${#info}" -gt "${info_length:-0}" ] && | |
1928 | info_length=${#info} | |
1929 | done | |
1930 | ||
1931 | # Add an additional space of length to act as a gap. | |
1932 | info_length=$((info_length + 1)) | |
1933 | ||
1934 | # Iterate over the above list and run any existing "get_" functions. | |
1935 | for info do | |
1936 | "get_$info" | |
1937 | done | |
1938 | } | |
1939 | ||
1940 | # Position the cursor below both the ascii art and information lines | |
1941 | # according to the height of both. If the information exceeds the ascii | |
1942 | # art in height, don't touch the cursor (0/unset), else move it down | |
1943 | # N lines. | |
1944 | # | |
1945 | # This was a ternary operation but they aren't supported in Minix's shell. | |
1946 | [ "${info_height:-0}" -lt "${ascii_height:-0}" ] && | |
1947 | cursor_pos=$((ascii_height - info_height)) | |
1948 | ||
1949 | # Print '$cursor_pos' amount of newlines to correctly position the | |
1950 | # cursor. This used to be a 'printf $(seq X X)' however 'seq' is only | |
1951 | # typically available (by default) on GNU based systems! | |
1952 | while [ "${i:=0}" -le "${cursor_pos:-0}" ]; do | |
1953 | printf '\n' | |
1954 | i=$((i + 1)) | |
1955 | done >&6 | |
1956 | } | |
1957 |