tazpanel view hardware.cgi @ rev 613

dot command may not search current directory first
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Jul 23 13:53:37 2017 +0200 (2017-07-23)
parents feae80a2b2f4
children 424eec4e4b44
line source
1 #!/bin/sh
2 #
3 # Hardware part of TazPanel - Devices, drivers, printing
4 #
5 # Copyright (C) 2011-2015 SliTaz GNU/Linux - BSD License
6 #
8 # Common functions from libtazpanel
9 . ./lib/libtazpanel
10 get_config
11 header
13 TITLE=$(_ 'Hardware')
15 # Call an optional module
16 lib() {
17 module=lib/$1
18 shift
19 [ -s $module ] && . $module "$@"
20 }
22 disk_info() {
23 fdisk -l | fgrep Disk | while read a b c; do
24 d=${b#/dev/}
25 d="/sys/block/${d%:}/device"
26 [ -d $d ] && echo "$a $b $c, $(cat $d/vendor) $(cat $d/model)"
27 smartctl -a ${b%:} | sed '/^Model/,/^Firmware/!d'
28 done 2> /dev/null | sed 's/ */ /g'
29 }
31 lsusb_vd() {
32 if lsusb --help 2>&1 | grep -qi busybox ; then
33 for i in /sys/class/usb_device/*/device ; do
34 grep -qs ${1%:*} $i/idVendor || continue
35 grep -qs ${1#*:} $i/idProduct || continue
36 ( cd $i ; for j in * ; do
37 [ -f $j -a -r $j ] || continue
38 case "$j" in
39 descriptors|remove) continue
40 esac
41 awk -vn=$j '{printf "%-20s %s\n",n,$0;n=""}' <$j
42 done )
43 break
44 done
45 else
46 lsusb -vd $1 | syntax_highlighter lsusb
47 fi
48 }
50 lsusb_table() {
51 cat <<EOT
52 <table class="wide zebra">
53 <thead>
54 <tr>
55 <td>$(_ 'Bus')</td>
56 <td>$(_ 'Device')</td>
57 <td>$(_ 'ID')</td>
58 <td>$(_ 'Name')</td>
59 </tr>
60 </thead>
61 <tbody>
62 EOT
63 lsusb | while read x b y d z id name ; do
64 echo "<tr><td>$b</td><td>${d%:}</td><td><a href=\"?lsusb=$id"
65 p=$(printf "class/usb_device/usbdev%d.%d" $b ${d%:})
66 grep -qs 0 /sys/$p/device/authorized && id="<del>$id</del>"
67 echo "\">$id</td><td>${name:-$(sed 's/ .*//' /sys/$p/device/manufacturer) $(cat /sys/$p/device/product)}</td></tr>"
68 done
69 echo "</tbody></table>"
70 }
73 lspci_table() {
74 cat <<EOT
75 <table class="wide zebra">
76 <thead><tr>
77 <td>$(_ 'Slot')</td>
78 <td>$(_ 'Device')</td>
79 <td>$(_ 'Name')</td>
80 </tr></thead>
81 <tbody>
82 EOT
83 lspci | while read a b c id ; do
84 if [ $b != "Class" ] || [ ! -s /usr/share/misc/pci.ids.gz ]; then
85 echo "X$a $b $c $id"
86 continue
87 fi
88 echo -n "$a "
89 zcat /usr/share/misc/pci.ids.gz | \
90 awk -va=${c:0:2} -vb=${c:2:2} -vh=${id:0:4} -vl=${id:5:4} '{
91 if ($1 == "C" && $2 == a) class=substr($0,5)
92 if (class != "" && $1 == b) { class=substr($0,5); exit }
93 if (substr($0,1,4) == h) m=substr($0,7)
94 else if (m == "") next
95 else if (substr($0,2,4) == l) { name=m substr($0,7); m="" }
96 else if ($1 == h && $2 == l) { name=m substr($0,14); m="" }
97 } END { print "[" a b "] " class ": [" h "/" l "] " name }'
98 done | sed 's| |</td><td>|;
99 s|: |</td><td>|;
100 s|^X\([^<]*\)|<a href="?lspci=\1">\1</a>|;
101 s|^.*$|<tr><td>\0</td></tr>|'
102 echo "</tbody></table>"
103 }
106 #
107 # Commands
108 #
110 case " $(GET) " in
111 *\ print\ *)
112 xhtml_header
113 echo "<h2>TODO</h2>"
114 ;;
117 *\ tazx\ *)
118 xhtml_header
119 cat <<EOT
120 <pre>$(tazx auto)</pre>
121 EOT
122 ;;
125 *\ detect\ *)
126 # Front end for Tazhw
127 # TODO: Add button to detect webcam, etc. Like in tazhw box.
128 xhtml_header "$(_ 'Detect hardware')"
129 cat <<EOT
130 <p>$(_ 'Detect PCI and USB hardware')</p>
131 EOT
132 tazhw detect-pci | htmlize
133 tazhw detect-usb | htmlize | filter_taztools_msgs
134 ;;
137 *\ modules\ *|*\ modinfo\ *)
138 xhtml_header "$(_ 'Kernel modules')"
140 search="$(GET search)"
141 cat <<EOT
142 <p>$(_ 'Manage, search or get information about the Linux kernel modules')</p>
144 <form class="search">
145 <input type="hidden" name="modules"/>
146 <input type="search" name="search" value="$search" placeholder="$(_ 'Modules search')" results="5" autosave="modsearch" autocomplete="on"/>
147 <button type="submit">$(_n 'Search')</button>
148 </form>
149 EOT
150 # Request may be modinfo output that we want in the page itself
151 get_modinfo="$(GET modinfo)"
152 if [ -n "$get_modinfo" ]; then
153 cat <<EOT
154 <section>
155 <header>$(_ 'Detailed information for module: %s' $get_modinfo)</header>
156 <div class="scroll">
158 EOT
159 modinfo $get_modinfo | awk 'BEGIN{print "<table class=\"wide zebra\">"}
160 {
161 printf("<tr><td><b>%s</b></td>", $1)
162 $1=""; printf("<td>%s</td></tr>", $0)
163 }
164 END{print "</table></div></section>"}'
165 fi
167 if [ -n "$(GET modprobe)" ]; then
168 echo "<pre>$(modprobe -v $(GET modprobe))</pre>"
169 fi
170 if [ -n "$(GET rmmod)" ]; then
171 echo "Removing"
172 rmmod -w $(GET rmmod)
173 fi
175 # Module search
176 if [ -n "$search" ]; then
177 cat <<EOT
178 <section>
179 <header>$(_ 'Matching result(s) for: %s' $search)</header>
180 <pre class="scroll">
181 EOT
182 busybox modprobe -l | grep "$search" | while read line
183 do
184 name=$(basename $line)
185 mod=${name%.ko.xz}
186 echo "<span data-icon=\"@modules@\">$(_ 'Module:')</span> <a href='?modinfo=$mod'>$mod</a>"
187 done
188 echo '</pre></section>'
189 fi
191 cat <<EOT
192 <section>
193 <table class="zebra">
194 <thead>
195 <tr>
196 <td>$(_ 'Module')</td>
197 <td>$(_ 'Description')</td>
198 <td>$(_ 'Size')</td>
199 <td>$(_ 'Used')</td>
200 <td>$(_ 'by')</td>
201 </tr>
202 <thead>
203 <tbody>
204 EOT
205 # Get the list of modules and link to modinfo
206 lsmod | tail -n+2 | awk '{
207 gsub(",", " ", $4);
208 printf("<tr><td><a href=\"?modinfo=%s\">%s</a></td><td>", $1, $1);
209 system("modinfo -d " $1);
210 printf("</td><td>%s</td><td>%s</td><td>%s</td></tr>", $2, $3, $4);
211 }'
212 cat <<EOT
213 </thead>
214 </table>
215 </section>
216 EOT
217 ;;
220 *\ lsusb\ *)
221 xhtml_header
222 vidpid="$(GET lsusb)"
223 cat <<EOT
224 <h2>$(_ 'Information for USB Device %s' $vidpid)</h2>
226 <p>$(_ 'Detailed information about specified device.')</p>
228 <section>$(lsusb_table)</section>
229 EOT
230 [ "$vidpid" != 'lsusb' ] && cat <<EOT
231 <section>
232 <pre style="white-space: pre-wrap">$(lsusb_vd $vidpid)</pre>
233 </section>
234 EOT
235 ;;
238 *\ lspci\ *)
239 xhtml_header
240 slot="$(GET lspci)"
241 cat <<EOT
242 <h2>$(_ 'Information for PCI Device %s' $slot)</h2>
244 <p>$(_ 'Detailed information about specified device.')</p>
246 <section>$(lspci_table)</section>
247 EOT
248 [ "$slot" != 'lspci' ] && cat <<EOT
249 <section>
250 <pre style="white-space: pre-wrap">$(lspci -vs $slot | syntax_highlighter lspci)</pre>
251 </section>
252 EOT
253 ;;
256 *)
257 [ -n "$(GET brightness)" ] &&
258 echo -n $(GET brightness) > /sys/devices/virtual/backlight/$(GET dev)/brightness
260 #
261 # Default to summary with mounted filesystem, loaded modules
262 #
263 xhtml_header "$(_ 'Drivers &amp; Devices')"
264 cat <<EOT
265 <p>$(_ 'Manage your computer hardware')</p>
267 <form><!--
268 --><button name="modules" data-icon="@modules@">$(_ 'Kernel modules')</button><!--
269 --><button name="detect" data-icon="@detect@" data-root>$(_ 'Detect PCI/USB')</button><!--
270 --><button name="tazx" data-icon="@tazx@" data-root>$(_ 'Auto-install Xorg video driver')</button><!--
271 --></form>
273 EOT
276 # Battery state
277 if [ -n "$(ls /proc/acpi/battery/*/info 2>/dev/null)" ]; then
278 cat <<EOT
279 <section>
280 <header>$(_ 'Battery')</header>
281 <div>
282 <table class="wide">
283 EOT
284 for dev in /proc/acpi/battery/*; do
285 grep ^present $dev/info | grep -q yes || continue
286 design=$(sed '/design capacity:/!d; s/[^0-9]*\([0-9]*\).*/\1/' < $dev/info)
287 remain=$(sed '/remaining capacity/!d; s/[^0-9]*\([0-9]*\).*/\1/' < $dev/state)
288 rate=$(sed '/present rate/!d; s/[^0-9]*\([0-9]*\).*/\1/' < $dev/state)
289 full=$(sed '/last full capacity/!d; s/[^0-9]*\([0-9]*\).*/\1/' < $dev/info)
290 warning=$(sed '/design capacity warning/!d;s/[^0-9]*\([0-9]*\).*/\1/' < $dev/info)
291 low=$(sed '/design capacity low/!d; s/[^0-9]*\([0-9]*\).*/\1/' < $dev/info)
292 state=$(sed '/charging state/!d; s/\([^:]*:[ ]\+\)\([a-z]\+\)/\2/' < $dev/state)
294 rempct=$(( $remain * 100 / $full ))
295 cat <<EOT
296 <tr>
297 <td><span data-icon="@battery@">$(_ 'Battery')</span>
298 $(grep "^battery type" $dev/info | sed 's/.*: *//')
299 $(grep "^design capacity:" $dev/info | sed 's/.*: *//') </td>
300 <td>$(_ 'health') $(( (100*$full)/$design))%</td>
301 <td class="meter"><meter min="0" max="$full" value="$remain" low="$low"
302 high="$warning" optimum="$full"></meter>
303 <span>
304 EOT
305 case "$state" in
306 "discharging")
307 remtime=$(( $remain * 60 / $rate ))
308 remtimef=$(printf "%d:%02d" $(($remtime/60)) $(($remtime%60)))
309 _ 'Discharging %d%% - %s' $rempct $remtimef ;;
310 "charging")
311 remtime=$(( ($full - $remain) * 60 / $rate ))
312 remtimef=$(printf "%d:%02d" $(($remtime/60)) $(($remtime%60)))
313 _ 'Charging %d%% - %s' $rempct $remtimef ;;
314 "charged")
315 _ 'Charged 100%%' ;;
316 esac
317 cat <<EOT
319 </span>
320 </td>
321 </tr>
322 EOT
323 done
324 cat <<EOT
325 </table>
326 </div>
327 </section>
328 EOT
329 fi
332 # Thermal sensors
333 if [ -n "$(ls /sys/devices/virtual/thermal/*/temp 2>/dev/null)" ]; then
334 echo "<p><span data-icon=\"@temperature@\">$(_ 'Temperature:')</span>"
335 for temp in /sys/devices/virtual/thermal/*/temp; do
336 awk '{ print $1/1000 "℃" }' < $temp
337 done
338 echo '</p>'
339 fi
342 # Brightness
343 if [ -n "$(ls /sys/devices/virtual/backlight/*/brightness 2>/dev/null)" ]; then
344 echo '<form>'
345 for dev in /sys/devices/virtual/backlight/*/brightness; do
346 name=$(echo $dev | sed 's|.*/backlight/\([^/]*\).*|\1|')
347 cat <<EOT
348 <input type="hidden" name="dev" value="$name"/>
349 <span data-icon="@brightness@">$(_ 'Brightness')</span> \
350 $(sed 's/.*\.//;s/_*$//' < /sys/devices/virtual/backlight/$name/device/path):
351 <select name="brightness" onchange="submit();">
352 EOT
353 max=$(cat /sys/devices/virtual/backlight/$name/max_brightness)
354 for i in $(seq 0 $max); do
355 echo -n "<option value=\"$i\""
356 [ $i -eq $(cat /sys/devices/virtual/backlight/$name/actual_brightness) ] &&
357 echo -n " selected=\"selected\""
358 echo "> $(( (($i + 1) * 100) / ($max + 1) ))% </option>"
359 done
360 echo '</select>'
361 done
362 echo '</form>'
363 fi
366 cat <<EOT
367 <section>
368 <form action="#mount" class="wide">
369 <header id="disk">$(_ 'Filesystem usage statistics')</header>
370 <div>
371 <pre>$(disk_info)</pre>
372 </div>
373 EOT
376 #
377 # Loop device management actions
378 #
379 device=$(GET loopdev)
380 lib crypto $device
381 case "$device" in
382 /dev/*loop*)
383 set -- $(losetup | grep ^$device:)
384 [ -n "$3" ] && losetup -d $device
385 ro=""
386 [ -n "$(GET readonly)" ] && ro="-r"
387 file="$(GET backingfile)"
388 [ -n "$file" ] && losetup -o $(GET offset) $ro $device $file
389 esac
392 #
393 # Disk stats and management (mount, umount, check)
394 #
395 device=$(GET device)
396 lib crypto $device
397 case "$device" in
398 *[\;\`\&\|\$]*) ;;
399 mount\ *)
400 ro=""
401 [ -n "$(GET readonly)" ] && ro="-r"
402 mntdir="$(GET mountpoint)"
403 [ -d "$mntdir" ] || mkdir -p "$mntdir"
404 $device $ro "$mntdir";;
405 umount\ *|swapon\ *|swapoff\ *)
406 $device ;;
407 esac
408 cat <<EOT
409 <table id="mount" class="zebra wide center">
410 EOT
411 df_thead
412 echo '<tbody>'
413 for fs in $(blkid | sort | sed 's/:.*//'); do
414 set -- $(df -h | grep "^$fs ")
415 size=$2
416 used=$3
417 av=$4
418 grep "^$fs " /proc/mounts | grep -q "[, ]ro[, ]" &&
419 av="<del>$av</del>"
420 pct=$5
421 mp=$6
423 # action
424 action="mount"
425 [ -n "$mp" ] && action="umount"
426 type=$(blkid $fs | sed '/ TYPE=/!d;s/.* TYPE="\([^"]*\).*/\1/')
427 [ -n "$type" ] || continue
428 [ "$type" == "swap" ] && action="swapon"
429 if grep -q "^$fs " /proc/swaps; then
430 action="swapoff"
431 set -- $(grep "^$fs " /proc/swaps)
432 size=$(blk2h $(($3*2)))
433 used=$(blk2h $(($4*2)))
434 av=$(blk2h $((2*($3-$4))))
435 pct=$(((100*$4)/$3))%
436 mp=swap
437 fi
439 # size
440 [ -z "$size" ] &&
441 size="$(blk2h $(cat /sys/block/${fs#/dev/}/size /sys/block/*/${fs#/dev/}/size))"
443 # image
444 disktype="@hdd@"
445 case "$(cat /sys/block/${fs#/dev/}/removable 2>/dev/null ||
446 cat /sys/block/${fs:5:3}/removable 2>/dev/null)" in
447 1) disktype="@removable@" ;;
448 esac
449 case "$(cat /sys/block/${fs#/dev/}/ro 2>/dev/null ||
450 cat /sys/block/${fs:5:3}/ro 2>/dev/null)" in
451 1) disktype="@cd@" ;;
452 esac
454 radio="<input type=\"radio\" name=\"device\" value=\"$action $fs\" id=\"${fs#/dev/}\"/>"
455 [ "$REMOTE_USER" == "root" ] || radio=""
456 cat <<EOT
457 <tr>
458 <td>$radio<!--
459 --><label for="${fs#/dev/}" data-icon="$disktype">&thinsp;${fs#/dev/}</label></td>
460 <td>$(blkid $fs | sed '/LABEL=/!d;s/.*LABEL="\([^"]*\).*/\1/')</td>
461 <td>$type</td>
462 <td>$size</td>
463 <td>$av</td>
464 EOT
465 if [ -n "$pct" ]; then
466 cat <<EOT
467 <td class="meter"><meter min="0" max="100" value="${pct%%%}" low="70"
468 high="90" optimum="10"></meter>
469 <span>$used - $pct</span>
470 </td>
471 EOT
472 else
473 cat <<EOT
474 <td> </td>
475 EOT
476 fi
477 cat <<EOT
478 <td>$mp</td>
479 <td>$(blkid $fs | sed '/UUID=/!d;s/.*UUID="\([^"]*\).*/\1/')</td>
480 </tr>
481 EOT
482 done
483 cat <<EOT
484 </tbody>
485 </table>
486 EOT
487 [ "$REMOTE_USER" == "root" ] && cat <<EOT
488 $(lib crypto input)
490 <footer>
491 <button type="submit">mount / umount</button> -
492 $(_ 'new mount point:') <input type="text" name="mountpoint" value="/media/usbdisk"/> -
493 <input type="checkbox" name="readonly" id="ro"><label for="ro">&thinsp;$(_ 'read-only')</label>
494 </footer>
495 EOT
496 cat <<EOT
497 </form>
498 </section>
499 EOT
502 #
503 # /etc/fstab
504 #
505 cat <<EOT
506 <section>
507 <header>
508 $(_ 'Filesystems table')
509 $(edit_button /etc/fstab)
510 </header>
511 <table class="wide zebra center">
512 <thead>
513 <tr>
514 <td>$(_ 'Disk')</td>
515 <td>$(_ 'Mount point')</td>
516 <td>$(_ 'Type')</td>
517 <td>$(_ 'Options')</td>
518 <td>$(_ 'Freq')</td>
519 <td>$(_ 'Pass')</td>
520 </tr>
521 </thead>
522 <tbody>
523 EOT
525 grep -v '^#' /etc/fstab | awk '{
526 print "<tr><td>" $1 "</td><td>" $2 "</td><td>" $3 "</td><td>" $4
527 print "</td><td>" $5 "</td><td>" $6 "</td></tr>"
528 }
529 END{print "</tbody></table>"}'
531 cat <<EOT
532 </section>
533 EOT
536 #
537 # Loop device management GUI
538 #
539 cat <<EOT
540 <section>
541 <header>$(_ 'Loop devices')</header>
543 <form action="#loop" class="wide">
544 <div class="scroll">
545 <table id="loop" class="wide zebra scroll">
546 <thead>
547 <tr>
548 <td>$(_ 'Device')</td>
549 <td>$(_ 'Backing file')</td>
550 <td>$(_ 'Size')</td>
551 <td>$(_ 'Access')</td>
552 <td>$(_ 'Offset')</td>
553 </tr>
554 </thead>
555 <tbody>
556 EOT
557 for devloop in $(ls /dev/*loop[0-9]*); do
558 loop="${devloop#/dev/}"
559 dir=/sys/block/$loop
560 case "$(cat $dir/ro 2>/dev/null)" in
561 0) ro="$(_ "read/write")" ;;
562 1) ro="$(_ "read only")" ;;
563 *) ro="" ;;
564 esac
565 size=$(blk2h $(cat $dir/size))
566 [ "$size" == "0.0K" ] && size="" && ro=""
567 set -- $(losetup $devloop)
568 set -- "${3:-$(cat $dir/loop/backing_file)}" "${2:-$(cat $dir/loop/offset)}" ${ro// /&nbsp;}
569 cat <<EOT
570 <tr><td><input type="radio" name="loopdev" value="$devloop" id="$loop"/><!--
571 --><label for="$loop" data-icon="@loopback@">$loop</label></td>
572 <td>$1</td><td>$size</td><td align="center">$3</td><td align="right">$2</td>
573 </tr>
574 EOT
575 done
576 cat <<EOT
577 </tbody>
578 </table>
579 </div>
581 $(lib crypto input)
583 <footer>
584 <button type="submit" data-icon="@ok@">$(_ 'Setup')</button> -
585 $(_ 'new backing file:') <input type="text" name="backingfile"/> -
586 $(_ 'offset in bytes:') <input type="text" name="offset" value="0" size="8"/> -
587 <input type="checkbox" name="readonly" id="ro"/><label for="ro">$(_ 'read only')</label>
588 </footer>
589 </form>
590 </section>
591 EOT
594 #
595 # System memory
596 #
597 mem_total=$(free -m | awk '$1 ~ "M" {print $2}')
598 mem_used=$((100 * $(free -m | awk '$1 ~ "+" {print $3}') / mem_total))
599 mem_buff=$((100 * $(free -m | awk '$1 ~ "M" {print $6}') / mem_total))
600 mem_free=$((100 - mem_used - mem_buff))
602 cat <<EOT
603 <section>
604 <header>$(_ 'System memory')</header>
606 <div class="sysmem"><!--
607 --><span class="sysmem_used" style="width: ${mem_used}%" title="$(_ 'Used')" ><span>${mem_used}%</span></span><!--
608 EOT
609 [ $mem_buff != 0 ] && cat <<EOT
610 --><span class="sysmem_buff" style="width: ${mem_buff}%" title="$(_ 'Buffers')"><span>${mem_buff}%</span></span><!--
611 EOT
612 cat <<EOT
613 --><span class="sysmem_free" style="width: ${mem_free}%" title="$(_ 'Free')" ><span>${mem_free}%</span></span><!--
614 --></div>
616 <table class="wide zebra center">
617 <thead>
618 <tr>
619 <td>&nbsp;</td>
620 <td>total</td>
621 <td>used</td>
622 <td>free</td>
623 <td>shared</td>
624 <td>buffers</td>
625 </tr>
626 </thead>
627 <tbody>
628 EOT
630 free -m | awk '
631 $1 ~ "M" {print "<tr><td>"$1"</td><td>"$2"</td><td>"$3"</td><td>"$4"</td><td>"$5"</td><td>"$6"</td></tr>"}
632 $1 ~ "+" {print "<tr><td>"$1 $2"</td><td></td><td>"$3"</td><td>"$4"</td><td></td><td></td></tr>"}
633 $1 ~ "S" {print "<tr><td>"$1"</td><td>"$2"</td><td>"$3"</td><td>"$4"</td><td></td><td></td></tr>"}'
635 cat <<EOT
636 </tbody>
637 </table>
638 </section>
639 EOT
642 #
643 # lspci and lsusb summary tables
644 #
645 cat <<EOT
646 <section>
647 <header>lspci</header>
648 $(lspci_table)
649 </section>
652 <section>
653 <header>lsusb</header>
654 $(lsusb_table)
655 </section>
656 EOT
657 ;;
658 esac
660 xhtml_footer
661 exit 0