From eb8829af47869d4178a1378b729392bb9da53d26 Mon Sep 17 00:00:00 2001 From: Rod Wright Date: Tue, 24 Feb 2026 20:28:42 -0500 Subject: [PATCH] Incorporated changes for release 1.3.4 --- RPiSetup/ap-setup.sh | 42 +- RPiSetup/bookworm/ap-setup-nmcli.sh | 108 ++ .../apsetup/etc/webmin/custom/1630026603.cmd | 0 .../apsetup/etc/webmin/custom/1630026603.html | 0 .../apsetup/etc/webmin/custom/1630026756.cmd | 0 .../apsetup/etc/webmin/custom/1630026756.html | 0 .../apsetup/etc/webmin/custom/1630027149.edit | 0 .../apsetup/etc/webmin/custom/1630027149.html | 0 .../apsetup/etc/webmin/custom/config | 0 .../apsetup/usr/local/bin/wap-disable | 0 .../apsetup/usr/local/bin/wap-enable | 0 .../apsetup/usr/local/bin/wap-setpassphrase | 0 .../apsetup/usr/local/bin/wap-setssid | 0 .../brlaser-master/CMakeLists.txt | 0 .../{ => bookworm}/brlaser-master/COPYING | 0 .../{ => bookworm}/brlaser-master/ChangeLog | 0 .../{ => bookworm}/brlaser-master/README.md | 0 .../brlaser-master/brlaser.drv.in | 0 .../{ => bookworm}/brlaser-master/config.h.in | 0 .../{ => bookworm}/brlaser-master/src/block.h | 0 .../brlaser-master/src/brdecode.cc | 0 .../brlaser-master/src/debug.cc | 0 .../{ => bookworm}/brlaser-master/src/debug.h | 0 .../{ => bookworm}/brlaser-master/src/job.cc | 0 .../{ => bookworm}/brlaser-master/src/job.h | 0 .../{ => bookworm}/brlaser-master/src/line.cc | 0 .../{ => bookworm}/brlaser-master/src/line.h | 0 .../{ => bookworm}/brlaser-master/src/main.cc | 0 .../brlaser-master/test/lest.hpp | 0 .../brlaser-master/test/tempfile.h | 0 .../brlaser-master/test/test_block.cc | 0 .../brlaser-master/test/test_lest.cc | 0 .../brlaser-master/test/test_line.cc | 0 .../etc/apache2/conf-available/opendrs.conf | 0 .../etc/apache2/mods-available/alias.conf | 0 .../apache2/sites-available/000-default.conf | 0 RPiSetup/{ => bookworm}/etc/cups/cupsd.conf | 0 RPiSetup/{ => bookworm}/etc/drs.conf | 0 .../home/customer/.config/openbox/rc.xml | 0 .../{ => bookworm}/home/customer/.profile | 0 .../lib/systemd/system/getty@tty1.service | 0 .../{ => bookworm}/usr/local/bin/cloneuser | 0 .../{ => bookworm}/usr/local/bin/rpi-clone | 0 .../usr/local/bin/rpi-clone-setup | 0 .../{ => bookworm}/usr/local/bin/startdrs.sh | 0 RPiSetup/bullseye/ap-setup-hostapd.sh | 141 ++ .../apsetup/etc/webmin/custom/1630026603.cmd | 3 + .../apsetup/etc/webmin/custom/1630026603.html | 1 + .../apsetup/etc/webmin/custom/1630026756.cmd | 3 + .../apsetup/etc/webmin/custom/1630026756.html | 1 + .../apsetup/etc/webmin/custom/1630027149.edit | 11 + .../apsetup/etc/webmin/custom/1630027149.html | 1 + .../bullseye/apsetup/etc/webmin/custom/config | 8 + .../apsetup/usr/local/bin/wap-disable | 4 + .../bullseye/apsetup/usr/local/bin/wap-enable | 4 + .../apsetup/usr/local/bin/wap-setpassphrase | 16 + .../apsetup/usr/local/bin/wap-setssid | 15 + .../bullseye/brlaser-master/CMakeLists.txt | 126 ++ RPiSetup/bullseye/brlaser-master/COPYING | 339 ++++ RPiSetup/bullseye/brlaser-master/ChangeLog | 9 + RPiSetup/bullseye/brlaser-master/README.md | 85 + .../bullseye/brlaser-master/brlaser.drv.in | 143 ++ RPiSetup/bullseye/brlaser-master/config.h.in | 2 + RPiSetup/bullseye/brlaser-master/src/block.h | 68 + .../bullseye/brlaser-master/src/brdecode.cc | 225 +++ RPiSetup/bullseye/brlaser-master/src/debug.cc | 107 ++ RPiSetup/bullseye/brlaser-master/src/debug.h | 25 + RPiSetup/bullseye/brlaser-master/src/job.cc | 118 ++ RPiSetup/bullseye/brlaser-master/src/job.h | 68 + RPiSetup/bullseye/brlaser-master/src/line.cc | 191 ++ RPiSetup/bullseye/brlaser-master/src/line.h | 31 + RPiSetup/bullseye/brlaser-master/src/main.cc | 205 ++ .../bullseye/brlaser-master/test/lest.hpp | 199 ++ .../bullseye/brlaser-master/test/tempfile.h | 54 + .../brlaser-master/test/test_block.cc | 91 + .../bullseye/brlaser-master/test/test_lest.cc | 291 +++ .../bullseye/brlaser-master/test/test_line.cc | 150 ++ .../etc/apache2/conf-available/opendrs.conf | 10 + .../etc/apache2/mods-available/alias.conf | 24 + .../apache2/sites-available/000-default.conf | 31 + RPiSetup/bullseye/etc/cups/cupsd.conf | 146 ++ RPiSetup/bullseye/etc/drs.conf | 25 + .../home/customer/.config/openbox/rc.xml | 695 +++++++ RPiSetup/bullseye/home/customer/.profile | 23 + .../lib/systemd/system/getty@tty1.service | 53 + RPiSetup/bullseye/usr/local/bin/cloneuser | 28 + RPiSetup/bullseye/usr/local/bin/rpi-clone | 1642 +++++++++++++++++ .../bullseye/usr/local/bin/rpi-clone-setup | 144 ++ RPiSetup/bullseye/usr/local/bin/startdrs.sh | 40 + RPiSetup/common.sh | 36 + RPiSetup/etc/apt/sources.list.d/webmin.list | 1 - RPiSetup/server-setup.sh | 19 +- RPiSetup/terminal-setup.sh | 80 +- 93 files changed, 5860 insertions(+), 22 deletions(-) create mode 100644 RPiSetup/bookworm/ap-setup-nmcli.sh rename RPiSetup/{ => bookworm}/apsetup/etc/webmin/custom/1630026603.cmd (100%) rename RPiSetup/{ => bookworm}/apsetup/etc/webmin/custom/1630026603.html (100%) rename RPiSetup/{ => bookworm}/apsetup/etc/webmin/custom/1630026756.cmd (100%) rename RPiSetup/{ => bookworm}/apsetup/etc/webmin/custom/1630026756.html (100%) rename RPiSetup/{ => bookworm}/apsetup/etc/webmin/custom/1630027149.edit (100%) rename RPiSetup/{ => bookworm}/apsetup/etc/webmin/custom/1630027149.html (100%) rename RPiSetup/{ => bookworm}/apsetup/etc/webmin/custom/config (100%) rename RPiSetup/{ => bookworm}/apsetup/usr/local/bin/wap-disable (100%) rename RPiSetup/{ => bookworm}/apsetup/usr/local/bin/wap-enable (100%) rename RPiSetup/{ => bookworm}/apsetup/usr/local/bin/wap-setpassphrase (100%) rename RPiSetup/{ => bookworm}/apsetup/usr/local/bin/wap-setssid (100%) rename RPiSetup/{ => bookworm}/brlaser-master/CMakeLists.txt (100%) rename RPiSetup/{ => bookworm}/brlaser-master/COPYING (100%) rename RPiSetup/{ => bookworm}/brlaser-master/ChangeLog (100%) rename RPiSetup/{ => bookworm}/brlaser-master/README.md (100%) rename RPiSetup/{ => bookworm}/brlaser-master/brlaser.drv.in (100%) rename RPiSetup/{ => bookworm}/brlaser-master/config.h.in (100%) rename RPiSetup/{ => bookworm}/brlaser-master/src/block.h (100%) rename RPiSetup/{ => bookworm}/brlaser-master/src/brdecode.cc (100%) rename RPiSetup/{ => bookworm}/brlaser-master/src/debug.cc (100%) rename RPiSetup/{ => bookworm}/brlaser-master/src/debug.h (100%) rename RPiSetup/{ => bookworm}/brlaser-master/src/job.cc (100%) rename RPiSetup/{ => bookworm}/brlaser-master/src/job.h (100%) rename RPiSetup/{ => bookworm}/brlaser-master/src/line.cc (100%) rename RPiSetup/{ => bookworm}/brlaser-master/src/line.h (100%) rename RPiSetup/{ => bookworm}/brlaser-master/src/main.cc (100%) rename RPiSetup/{ => bookworm}/brlaser-master/test/lest.hpp (100%) rename RPiSetup/{ => bookworm}/brlaser-master/test/tempfile.h (100%) rename RPiSetup/{ => bookworm}/brlaser-master/test/test_block.cc (100%) rename RPiSetup/{ => bookworm}/brlaser-master/test/test_lest.cc (100%) rename RPiSetup/{ => bookworm}/brlaser-master/test/test_line.cc (100%) rename RPiSetup/{ => bookworm}/etc/apache2/conf-available/opendrs.conf (100%) rename RPiSetup/{ => bookworm}/etc/apache2/mods-available/alias.conf (100%) rename RPiSetup/{ => bookworm}/etc/apache2/sites-available/000-default.conf (100%) rename RPiSetup/{ => bookworm}/etc/cups/cupsd.conf (100%) rename RPiSetup/{ => bookworm}/etc/drs.conf (100%) rename RPiSetup/{ => bookworm}/home/customer/.config/openbox/rc.xml (100%) rename RPiSetup/{ => bookworm}/home/customer/.profile (100%) rename RPiSetup/{ => bookworm}/lib/systemd/system/getty@tty1.service (100%) rename RPiSetup/{ => bookworm}/usr/local/bin/cloneuser (100%) rename RPiSetup/{ => bookworm}/usr/local/bin/rpi-clone (100%) rename RPiSetup/{ => bookworm}/usr/local/bin/rpi-clone-setup (100%) rename RPiSetup/{ => bookworm}/usr/local/bin/startdrs.sh (100%) create mode 100644 RPiSetup/bullseye/ap-setup-hostapd.sh create mode 100644 RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026603.cmd create mode 100644 RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026603.html create mode 100644 RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026756.cmd create mode 100644 RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026756.html create mode 100644 RPiSetup/bullseye/apsetup/etc/webmin/custom/1630027149.edit create mode 100644 RPiSetup/bullseye/apsetup/etc/webmin/custom/1630027149.html create mode 100644 RPiSetup/bullseye/apsetup/etc/webmin/custom/config create mode 100644 RPiSetup/bullseye/apsetup/usr/local/bin/wap-disable create mode 100644 RPiSetup/bullseye/apsetup/usr/local/bin/wap-enable create mode 100644 RPiSetup/bullseye/apsetup/usr/local/bin/wap-setpassphrase create mode 100644 RPiSetup/bullseye/apsetup/usr/local/bin/wap-setssid create mode 100644 RPiSetup/bullseye/brlaser-master/CMakeLists.txt create mode 100644 RPiSetup/bullseye/brlaser-master/COPYING create mode 100644 RPiSetup/bullseye/brlaser-master/ChangeLog create mode 100644 RPiSetup/bullseye/brlaser-master/README.md create mode 100644 RPiSetup/bullseye/brlaser-master/brlaser.drv.in create mode 100644 RPiSetup/bullseye/brlaser-master/config.h.in create mode 100644 RPiSetup/bullseye/brlaser-master/src/block.h create mode 100644 RPiSetup/bullseye/brlaser-master/src/brdecode.cc create mode 100644 RPiSetup/bullseye/brlaser-master/src/debug.cc create mode 100644 RPiSetup/bullseye/brlaser-master/src/debug.h create mode 100644 RPiSetup/bullseye/brlaser-master/src/job.cc create mode 100644 RPiSetup/bullseye/brlaser-master/src/job.h create mode 100644 RPiSetup/bullseye/brlaser-master/src/line.cc create mode 100644 RPiSetup/bullseye/brlaser-master/src/line.h create mode 100644 RPiSetup/bullseye/brlaser-master/src/main.cc create mode 100644 RPiSetup/bullseye/brlaser-master/test/lest.hpp create mode 100644 RPiSetup/bullseye/brlaser-master/test/tempfile.h create mode 100644 RPiSetup/bullseye/brlaser-master/test/test_block.cc create mode 100644 RPiSetup/bullseye/brlaser-master/test/test_lest.cc create mode 100644 RPiSetup/bullseye/brlaser-master/test/test_line.cc create mode 100644 RPiSetup/bullseye/etc/apache2/conf-available/opendrs.conf create mode 100644 RPiSetup/bullseye/etc/apache2/mods-available/alias.conf create mode 100644 RPiSetup/bullseye/etc/apache2/sites-available/000-default.conf create mode 100644 RPiSetup/bullseye/etc/cups/cupsd.conf create mode 100644 RPiSetup/bullseye/etc/drs.conf create mode 100644 RPiSetup/bullseye/home/customer/.config/openbox/rc.xml create mode 100644 RPiSetup/bullseye/home/customer/.profile create mode 100644 RPiSetup/bullseye/lib/systemd/system/getty@tty1.service create mode 100644 RPiSetup/bullseye/usr/local/bin/cloneuser create mode 100644 RPiSetup/bullseye/usr/local/bin/rpi-clone create mode 100644 RPiSetup/bullseye/usr/local/bin/rpi-clone-setup create mode 100644 RPiSetup/bullseye/usr/local/bin/startdrs.sh create mode 100644 RPiSetup/common.sh delete mode 100644 RPiSetup/etc/apt/sources.list.d/webmin.list diff --git a/RPiSetup/ap-setup.sh b/RPiSetup/ap-setup.sh index e34af92..191fedf 100644 --- a/RPiSetup/ap-setup.sh +++ b/RPiSetup/ap-setup.sh @@ -15,6 +15,42 @@ then exit 1 fi echo "" +echo -n "Raspberry Pi model is: " +rpimodeltxt=$(tr -d '\0' < /proc/device-tree/model) +echo $rpimodeltxt +echo $rpimodeltxt|grep -q "Raspberry Pi 3" +if [ $? -eq 0 ] +then + ismodel3="true" +fi +echo "" +echo -n "OS Release version is: " +os_rel_ver=`grep VERSION_CODENAME /etc/os-release | cut -d "=" -f2` +echo $os_rel_ver +echo "" +echo -n "Architecture is: " +arch_32_64=`getconf LONG_BIT` +echo "$arch_32_64 bit" +echo "" +if [ $arch_32_64 -eq 64 -a "$ismodel3" = "true" ] +then + echo "Raspberry Pi 3 hardware is known to have problems with acting as a" + echo "wireless access point when 64 bit kernels are used. If you intend for" + echo "this terminal to act as a wireless access point, you should stop here," + echo "power off, remove the microsd card and re-image using a 32 bit version" + echo "of Raspberry Pi OS." + echo -n "Ignore and [c]ontinue or [A]bort? [c/A]: " + read archabort + if [ "$archabort" = "C" -o "$archabort" = "c" ] + then + echo "" + echo "Continuing with installation." + else + echo "" + echo "Aborting installation." + exit 0 + fi +fi echo "" echo "If this terminal connects to a network using ethernet, it can be configured" echo "as a wireless access point for other terminals. Would you like to configure" @@ -25,9 +61,9 @@ then echo "Configuring as wireless access point." echo "" echo "Copying files..." - chmod +x apsetup/usr/local/bin/* - cp apsetup/usr/local/bin/* /usr/local/bin - cp -R apsetup/etc/* /etc + chmod +x $os_rel_ver/apsetup/usr/local/bin/* + cp -v$os_rel_ver/apsetup/usr/local/bin/* /usr/local/bin + cp -Rv $os_rel_ver/apsetup/etc/* /etc echo "" wapssidok=0 while [ "$wapssidok" -ne 1 ] diff --git a/RPiSetup/bookworm/ap-setup-nmcli.sh b/RPiSetup/bookworm/ap-setup-nmcli.sh new file mode 100644 index 0000000..6ff9ed1 --- /dev/null +++ b/RPiSetup/bookworm/ap-setup-nmcli.sh @@ -0,0 +1,108 @@ +#!/bin/bash + +# ap-setup.sh +# OpenDRS Online Discrepancy Reporting System +# Copyright (C) 2022 Rod Wright + +# SPDX-License-Identifier: GPL-2.0 + +# Wireless Access Point Raspberry Pi Setup +current_user=`whoami` +if [ "$current_user" != "root" ] +then + echo "You must have root privileges to run this setup." + echo "Try 'sudo ./ap-setup-hostapd.sh'" + exit 1 +fi +source ../common.sh +echo "" +getmodel +echo "" +getosrelease +echo "" +getarch +echo "" +if [ $arch_32_64 -eq 64 -a "$ismodel3" = "true" ] +then + echo "Raspberry Pi 3 hardware is known to have problems with acting as a" + echo "wireless access point when 64 bit kernels are used. If you intend for" + echo "this terminal to act as a wireless access point, you should stop here," + echo "power off, remove the microsd card and re-image using a 32 bit version" + echo "of Raspberry Pi OS." + echo -n "Ignore and [c]ontinue or [A]bort? [c/A]: " + read archabort + if [ "$archabort" = "C" -o "$archabort" = "c" ] + then + echo "" + echo "Continuing with installation." + else + echo "" + echo "Aborting installation." + exit 0 + fi +fi +echo "" +echo "If this terminal connects to a network using ethernet, it can be configured" +echo "as a wireless access point for other terminals. Would you like to configure" +echo -n "this terminal as an access point? [y/N]: " +read wapconf +if [ "$wapconf" = "Y" -o "$wapconf" = "y" ] +then + echo "Configuring as wireless access point." + echo "" + echo "Copying files..." + chmod +x apsetup/usr/local/bin/* + cp -v apsetup/usr/local/bin/* /usr/local/bin + cp -Rv apsetup/etc/* /etc + echo "" + wapssidok=0 + while [ "$wapssidok" -ne 1 ] + do + echo "This access point will need an SSID. This is what will appear" + echo "as the name of this terminal when other devices connect." + echo -n "Please enter the desired SSID for this access point: " + read wapssid + if [ "$wapssid" = "" ] + then + echo "SSID cannot be blank. Try again." + else + wapssidok=1 + fi + done + wappassok=0 + while [ "$wappassok" -ne 1 ] + do + echo "You will need to set a passphrase for this access point. It should" + echo "be at least 8 characters in length and cannot be blank." + echo -n "Please enter the desired passphrase for this access point: " + read wappass + wappasslen=`echo -n $wappass | wc -m` + if [ "$wappass" = "" -o "$wappasslen" -lt 8 ] + then + echo "Passphrase doesn't satisfy requirements above. Try again." + else + wappassok=1 + fi + done + # Create network bridge interface + nmcli connection add type bridge con-name 'Bridge' ifname bridge0 + # Add ethernet connection to the bridge + nmcli connection add type ethernet slave-type bridge con-name 'Ethernet' ifname eth0 master bridge0 + # Create wireless interface and add it to the bridge + nmcli connection add con-name 'Hotspot' ifname wlan0 type wifi slave-type bridge master bridge0 \ + wifi.mode ap wifi.ssid $wapssid wifi-sec.key-mgmt wpa-psk \ + wifi-sec.proto rsn wifi-sec.pairwise ccmp \ + wifi-sec.psk $wappass + # Activate bridge + nmcli connection up Bridge + # Activate access point + nmcli connection up Hotspot + echo "" + echo "Wireless access point setup is complete." + echo "" + echo -n "Press enter key to continue..." + read cont +else + exit 2 +fi + diff --git a/RPiSetup/apsetup/etc/webmin/custom/1630026603.cmd b/RPiSetup/bookworm/apsetup/etc/webmin/custom/1630026603.cmd similarity index 100% rename from RPiSetup/apsetup/etc/webmin/custom/1630026603.cmd rename to RPiSetup/bookworm/apsetup/etc/webmin/custom/1630026603.cmd diff --git a/RPiSetup/apsetup/etc/webmin/custom/1630026603.html b/RPiSetup/bookworm/apsetup/etc/webmin/custom/1630026603.html similarity index 100% rename from RPiSetup/apsetup/etc/webmin/custom/1630026603.html rename to RPiSetup/bookworm/apsetup/etc/webmin/custom/1630026603.html diff --git a/RPiSetup/apsetup/etc/webmin/custom/1630026756.cmd b/RPiSetup/bookworm/apsetup/etc/webmin/custom/1630026756.cmd similarity index 100% rename from RPiSetup/apsetup/etc/webmin/custom/1630026756.cmd rename to RPiSetup/bookworm/apsetup/etc/webmin/custom/1630026756.cmd diff --git a/RPiSetup/apsetup/etc/webmin/custom/1630026756.html b/RPiSetup/bookworm/apsetup/etc/webmin/custom/1630026756.html similarity index 100% rename from RPiSetup/apsetup/etc/webmin/custom/1630026756.html rename to RPiSetup/bookworm/apsetup/etc/webmin/custom/1630026756.html diff --git a/RPiSetup/apsetup/etc/webmin/custom/1630027149.edit b/RPiSetup/bookworm/apsetup/etc/webmin/custom/1630027149.edit similarity index 100% rename from RPiSetup/apsetup/etc/webmin/custom/1630027149.edit rename to RPiSetup/bookworm/apsetup/etc/webmin/custom/1630027149.edit diff --git a/RPiSetup/apsetup/etc/webmin/custom/1630027149.html b/RPiSetup/bookworm/apsetup/etc/webmin/custom/1630027149.html similarity index 100% rename from RPiSetup/apsetup/etc/webmin/custom/1630027149.html rename to RPiSetup/bookworm/apsetup/etc/webmin/custom/1630027149.html diff --git a/RPiSetup/apsetup/etc/webmin/custom/config b/RPiSetup/bookworm/apsetup/etc/webmin/custom/config similarity index 100% rename from RPiSetup/apsetup/etc/webmin/custom/config rename to RPiSetup/bookworm/apsetup/etc/webmin/custom/config diff --git a/RPiSetup/apsetup/usr/local/bin/wap-disable b/RPiSetup/bookworm/apsetup/usr/local/bin/wap-disable similarity index 100% rename from RPiSetup/apsetup/usr/local/bin/wap-disable rename to RPiSetup/bookworm/apsetup/usr/local/bin/wap-disable diff --git a/RPiSetup/apsetup/usr/local/bin/wap-enable b/RPiSetup/bookworm/apsetup/usr/local/bin/wap-enable similarity index 100% rename from RPiSetup/apsetup/usr/local/bin/wap-enable rename to RPiSetup/bookworm/apsetup/usr/local/bin/wap-enable diff --git a/RPiSetup/apsetup/usr/local/bin/wap-setpassphrase b/RPiSetup/bookworm/apsetup/usr/local/bin/wap-setpassphrase similarity index 100% rename from RPiSetup/apsetup/usr/local/bin/wap-setpassphrase rename to RPiSetup/bookworm/apsetup/usr/local/bin/wap-setpassphrase diff --git a/RPiSetup/apsetup/usr/local/bin/wap-setssid b/RPiSetup/bookworm/apsetup/usr/local/bin/wap-setssid similarity index 100% rename from RPiSetup/apsetup/usr/local/bin/wap-setssid rename to RPiSetup/bookworm/apsetup/usr/local/bin/wap-setssid diff --git a/RPiSetup/brlaser-master/CMakeLists.txt b/RPiSetup/bookworm/brlaser-master/CMakeLists.txt similarity index 100% rename from RPiSetup/brlaser-master/CMakeLists.txt rename to RPiSetup/bookworm/brlaser-master/CMakeLists.txt diff --git a/RPiSetup/brlaser-master/COPYING b/RPiSetup/bookworm/brlaser-master/COPYING similarity index 100% rename from RPiSetup/brlaser-master/COPYING rename to RPiSetup/bookworm/brlaser-master/COPYING diff --git a/RPiSetup/brlaser-master/ChangeLog b/RPiSetup/bookworm/brlaser-master/ChangeLog similarity index 100% rename from RPiSetup/brlaser-master/ChangeLog rename to RPiSetup/bookworm/brlaser-master/ChangeLog diff --git a/RPiSetup/brlaser-master/README.md b/RPiSetup/bookworm/brlaser-master/README.md similarity index 100% rename from RPiSetup/brlaser-master/README.md rename to RPiSetup/bookworm/brlaser-master/README.md diff --git a/RPiSetup/brlaser-master/brlaser.drv.in b/RPiSetup/bookworm/brlaser-master/brlaser.drv.in similarity index 100% rename from RPiSetup/brlaser-master/brlaser.drv.in rename to RPiSetup/bookworm/brlaser-master/brlaser.drv.in diff --git a/RPiSetup/brlaser-master/config.h.in b/RPiSetup/bookworm/brlaser-master/config.h.in similarity index 100% rename from RPiSetup/brlaser-master/config.h.in rename to RPiSetup/bookworm/brlaser-master/config.h.in diff --git a/RPiSetup/brlaser-master/src/block.h b/RPiSetup/bookworm/brlaser-master/src/block.h similarity index 100% rename from RPiSetup/brlaser-master/src/block.h rename to RPiSetup/bookworm/brlaser-master/src/block.h diff --git a/RPiSetup/brlaser-master/src/brdecode.cc b/RPiSetup/bookworm/brlaser-master/src/brdecode.cc similarity index 100% rename from RPiSetup/brlaser-master/src/brdecode.cc rename to RPiSetup/bookworm/brlaser-master/src/brdecode.cc diff --git a/RPiSetup/brlaser-master/src/debug.cc b/RPiSetup/bookworm/brlaser-master/src/debug.cc similarity index 100% rename from RPiSetup/brlaser-master/src/debug.cc rename to RPiSetup/bookworm/brlaser-master/src/debug.cc diff --git a/RPiSetup/brlaser-master/src/debug.h b/RPiSetup/bookworm/brlaser-master/src/debug.h similarity index 100% rename from RPiSetup/brlaser-master/src/debug.h rename to RPiSetup/bookworm/brlaser-master/src/debug.h diff --git a/RPiSetup/brlaser-master/src/job.cc b/RPiSetup/bookworm/brlaser-master/src/job.cc similarity index 100% rename from RPiSetup/brlaser-master/src/job.cc rename to RPiSetup/bookworm/brlaser-master/src/job.cc diff --git a/RPiSetup/brlaser-master/src/job.h b/RPiSetup/bookworm/brlaser-master/src/job.h similarity index 100% rename from RPiSetup/brlaser-master/src/job.h rename to RPiSetup/bookworm/brlaser-master/src/job.h diff --git a/RPiSetup/brlaser-master/src/line.cc b/RPiSetup/bookworm/brlaser-master/src/line.cc similarity index 100% rename from RPiSetup/brlaser-master/src/line.cc rename to RPiSetup/bookworm/brlaser-master/src/line.cc diff --git a/RPiSetup/brlaser-master/src/line.h b/RPiSetup/bookworm/brlaser-master/src/line.h similarity index 100% rename from RPiSetup/brlaser-master/src/line.h rename to RPiSetup/bookworm/brlaser-master/src/line.h diff --git a/RPiSetup/brlaser-master/src/main.cc b/RPiSetup/bookworm/brlaser-master/src/main.cc similarity index 100% rename from RPiSetup/brlaser-master/src/main.cc rename to RPiSetup/bookworm/brlaser-master/src/main.cc diff --git a/RPiSetup/brlaser-master/test/lest.hpp b/RPiSetup/bookworm/brlaser-master/test/lest.hpp similarity index 100% rename from RPiSetup/brlaser-master/test/lest.hpp rename to RPiSetup/bookworm/brlaser-master/test/lest.hpp diff --git a/RPiSetup/brlaser-master/test/tempfile.h b/RPiSetup/bookworm/brlaser-master/test/tempfile.h similarity index 100% rename from RPiSetup/brlaser-master/test/tempfile.h rename to RPiSetup/bookworm/brlaser-master/test/tempfile.h diff --git a/RPiSetup/brlaser-master/test/test_block.cc b/RPiSetup/bookworm/brlaser-master/test/test_block.cc similarity index 100% rename from RPiSetup/brlaser-master/test/test_block.cc rename to RPiSetup/bookworm/brlaser-master/test/test_block.cc diff --git a/RPiSetup/brlaser-master/test/test_lest.cc b/RPiSetup/bookworm/brlaser-master/test/test_lest.cc similarity index 100% rename from RPiSetup/brlaser-master/test/test_lest.cc rename to RPiSetup/bookworm/brlaser-master/test/test_lest.cc diff --git a/RPiSetup/brlaser-master/test/test_line.cc b/RPiSetup/bookworm/brlaser-master/test/test_line.cc similarity index 100% rename from RPiSetup/brlaser-master/test/test_line.cc rename to RPiSetup/bookworm/brlaser-master/test/test_line.cc diff --git a/RPiSetup/etc/apache2/conf-available/opendrs.conf b/RPiSetup/bookworm/etc/apache2/conf-available/opendrs.conf similarity index 100% rename from RPiSetup/etc/apache2/conf-available/opendrs.conf rename to RPiSetup/bookworm/etc/apache2/conf-available/opendrs.conf diff --git a/RPiSetup/etc/apache2/mods-available/alias.conf b/RPiSetup/bookworm/etc/apache2/mods-available/alias.conf similarity index 100% rename from RPiSetup/etc/apache2/mods-available/alias.conf rename to RPiSetup/bookworm/etc/apache2/mods-available/alias.conf diff --git a/RPiSetup/etc/apache2/sites-available/000-default.conf b/RPiSetup/bookworm/etc/apache2/sites-available/000-default.conf similarity index 100% rename from RPiSetup/etc/apache2/sites-available/000-default.conf rename to RPiSetup/bookworm/etc/apache2/sites-available/000-default.conf diff --git a/RPiSetup/etc/cups/cupsd.conf b/RPiSetup/bookworm/etc/cups/cupsd.conf similarity index 100% rename from RPiSetup/etc/cups/cupsd.conf rename to RPiSetup/bookworm/etc/cups/cupsd.conf diff --git a/RPiSetup/etc/drs.conf b/RPiSetup/bookworm/etc/drs.conf similarity index 100% rename from RPiSetup/etc/drs.conf rename to RPiSetup/bookworm/etc/drs.conf diff --git a/RPiSetup/home/customer/.config/openbox/rc.xml b/RPiSetup/bookworm/home/customer/.config/openbox/rc.xml similarity index 100% rename from RPiSetup/home/customer/.config/openbox/rc.xml rename to RPiSetup/bookworm/home/customer/.config/openbox/rc.xml diff --git a/RPiSetup/home/customer/.profile b/RPiSetup/bookworm/home/customer/.profile similarity index 100% rename from RPiSetup/home/customer/.profile rename to RPiSetup/bookworm/home/customer/.profile diff --git a/RPiSetup/lib/systemd/system/getty@tty1.service b/RPiSetup/bookworm/lib/systemd/system/getty@tty1.service similarity index 100% rename from RPiSetup/lib/systemd/system/getty@tty1.service rename to RPiSetup/bookworm/lib/systemd/system/getty@tty1.service diff --git a/RPiSetup/usr/local/bin/cloneuser b/RPiSetup/bookworm/usr/local/bin/cloneuser similarity index 100% rename from RPiSetup/usr/local/bin/cloneuser rename to RPiSetup/bookworm/usr/local/bin/cloneuser diff --git a/RPiSetup/usr/local/bin/rpi-clone b/RPiSetup/bookworm/usr/local/bin/rpi-clone similarity index 100% rename from RPiSetup/usr/local/bin/rpi-clone rename to RPiSetup/bookworm/usr/local/bin/rpi-clone diff --git a/RPiSetup/usr/local/bin/rpi-clone-setup b/RPiSetup/bookworm/usr/local/bin/rpi-clone-setup similarity index 100% rename from RPiSetup/usr/local/bin/rpi-clone-setup rename to RPiSetup/bookworm/usr/local/bin/rpi-clone-setup diff --git a/RPiSetup/usr/local/bin/startdrs.sh b/RPiSetup/bookworm/usr/local/bin/startdrs.sh similarity index 100% rename from RPiSetup/usr/local/bin/startdrs.sh rename to RPiSetup/bookworm/usr/local/bin/startdrs.sh diff --git a/RPiSetup/bullseye/ap-setup-hostapd.sh b/RPiSetup/bullseye/ap-setup-hostapd.sh new file mode 100644 index 0000000..9a9b680 --- /dev/null +++ b/RPiSetup/bullseye/ap-setup-hostapd.sh @@ -0,0 +1,141 @@ +#!/bin/bash + +# ap-setup.sh +# OpenDRS Online Discrepancy Reporting System +# Copyright (C) 2022 Rod Wright + +# SPDX-License-Identifier: GPL-2.0 + +# Wireless Access Point Raspberry Pi Setup +current_user=`whoami` +if [ "$current_user" != "root" ] +then + echo "You must have root privileges to run this setup." + echo "Try 'sudo ./ap-setup-hostapd.sh'" + exit 1 +fi +source ../common.sh +echo "" +getmodel +echo "" +getosrelease +echo "" +getarch +echo "" +if [ $arch_32_64 -eq 64 -a "$ismodel3" = "true" ] +then + echo "Raspberry Pi 3 hardware is known to have problems with acting as a" + echo "wireless access point when 64 bit kernels are used. If you intend for" + echo "this terminal to act as a wireless access point, you should stop here," + echo "power off, remove the microsd card and re-image using a 32 bit version" + echo "of Raspberry Pi OS." + echo -n "Ignore and [c]ontinue or [A]bort? [c/A]: " + read archabort + if [ "$archabort" = "C" -o "$archabort" = "c" ] + then + echo "" + echo "Continuing with installation." + else + echo "" + echo "Aborting installation." + exit 0 + fi +fi +echo "" +echo "If this terminal connects to a network using ethernet, it can be configured" +echo "as a wireless access point for other terminals. Would you like to configure" +echo -n "this terminal as an access point? [y/N]: " +read wapconf +if [ "$wapconf" = "Y" -o "$wapconf" = "y" ] +then + echo "Configuring as wireless access point." + echo "" + echo "Copying files..." + chmod +x apsetup/usr/local/bin/* + cp -v apsetup/usr/local/bin/* /usr/local/bin + cp -Rv apsetup/etc/* /etc + echo "" + wapssidok=0 + while [ "$wapssidok" -ne 1 ] + do + echo "This access point will need an SSID. This is what will appear" + echo "as the name of this terminal when other devices connect." + echo -n "Please enter the desired SSID for this access point: " + read wapssid + if [ "$wapssid" = "" ] + then + echo "SSID cannot be blank. Try again." + else + wapssidok=1 + fi + done + wappassok=0 + while [ "$wappassok" -ne 1 ] + do + echo "You will need to set a passphrase for this access point. It should" + echo "be at least 8 characters in length and cannot be blank." + echo -n "Please enter the desired passphrase for this access point: " + read wappass + wappasslen=`echo -n $wappass | wc -m` + if [ "$wappass" = "" -o "$wappasslen" -lt 8 ] + then + echo "Passphrase doesn't satisfy requirements above. Try again." + else + wappassok=1 + fi + done + apt install hostapd + systemctl unmask hostapd + systemctl enable hostapd + echo "[NetDev]" >/etc/systemd/network/bridge-br0.netdev + echo "Name=br0" >>/etc/systemd/network/bridge-br0.netdev + echo "Kind=bridge" >>/etc/systemd/network/bridge-br0.netdev + echo "[Match]" >/etc/systemd/network/br0-member-eth0.network + echo "Name=eth0" >>/etc/systemd/network/br0-member-eth0.network + echo "" >>/etc/systemd/network/br0-member-eth0.network + echo "[Network]" >>/etc/systemd/network/br0-member-eth0.network + echo "Bridge=br0" >>/etc/systemd/network/br0-member-eth0.network + systemctl enable systemd-networkd + mv /etc/dhcpcd.conf /etc/dhcpcd.conf.old + echo "denyinterfaces wlan0 eth0" >/etc/dhcpcd.conf + cat /etc/dhcpcd.conf.old >>/etc/dhcpcd.conf + echo "interface br0" >>/etc/dhcpcd.conf + rfkill unblock wlan + echo "country_code=US" >/etc/hostapd/hostapd.conf + echo "interface=wlan0" >>/etc/hostapd/hostapd.conf + echo "bridge=br0" >>/etc/hostapd/hostapd.conf + echo "ssid=$wapssid" >>/etc/hostapd/hostapd.conf + echo "hw_mode=g" >>/etc/hostapd/hostapd.conf + echo "channel=7" >>/etc/hostapd/hostapd.conf + echo "macaddr_acl=0" >>/etc/hostapd/hostapd.conf + echo "auth_algs=1" >>/etc/hostapd/hostapd.conf + echo "ignore_broadcast_ssid=0" >>/etc/hostapd/hostapd.conf + echo "wpa=2" >>/etc/hostapd/hostapd.conf + echo "wpa_passphrase=$wappass" >>/etc/hostapd/hostapd.conf + echo "wpa_key_mgmt=WPA-PSK" >>/etc/hostapd/hostapd.conf + echo "wpa_pairwise=TKIP" >>/etc/hostapd/hostapd.conf + echo "rsn_pairwise=CCMP" >>/etc/hostapd/hostapd.conf + wget -c http://github.com/pjz/webmin-modules/releases/download/v1.0/hostap.wbm.gz + gzip -d hostap.wbm.gz + /usr/share/webmin/install-module.pl hostap.wbm + echo "" + echo "" + echo "Wireless access point setup is complete. It will be" + echo "automatically enabled after reboot. To change the SSID or" + echo "passphrase in the future, edit the file /etc/hostapd/hostapd.conf" + echo "or use the Host AP module in the Servers section of Webmin." + echo "" + echo "To disable the access point altogether in the future, run:" + echo " sudo wap-disable" + echo "at a command prompt and reboot the terminal. To re-enable it, run:" + echo " sudo wap-enable" + echo "at a command prompt and reboot the terminal." + echo "It can also be enabled or disabled via Custom Commands in the Tools" + echo "section of Webmin." + echo "" + echo -n "Press enter key to continue..." + read cont +else + exit 2 +fi + diff --git a/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026603.cmd b/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026603.cmd new file mode 100644 index 0000000..4abfe65 --- /dev/null +++ b/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026603.cmd @@ -0,0 +1,3 @@ +sudo wap-enable +Enable Wireless Access Point +* 0 1 0 0 0 0 0 - diff --git a/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026603.html b/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026603.html new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026603.html @@ -0,0 +1 @@ + diff --git a/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026756.cmd b/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026756.cmd new file mode 100644 index 0000000..bc5c3ea --- /dev/null +++ b/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026756.cmd @@ -0,0 +1,3 @@ +sudo wap-disable +Disable Wireless Access Point +* 0 1 0 0 0 0 0 - diff --git a/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026756.html b/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026756.html new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630026756.html @@ -0,0 +1 @@ + diff --git a/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630027149.edit b/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630027149.edit new file mode 100644 index 0000000..0c2e4aa --- /dev/null +++ b/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630027149.edit @@ -0,0 +1,11 @@ +/etc/hostapd/hostapd.conf +Edit Wireless Access Point Parameters + + + + +systemctl restart hostapd +0 +0 + + diff --git a/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630027149.html b/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630027149.html new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/RPiSetup/bullseye/apsetup/etc/webmin/custom/1630027149.html @@ -0,0 +1 @@ + diff --git a/RPiSetup/bullseye/apsetup/etc/webmin/custom/config b/RPiSetup/bullseye/apsetup/etc/webmin/custom/config new file mode 100644 index 0000000..7e7dd2a --- /dev/null +++ b/RPiSetup/bullseye/apsetup/etc/webmin/custom/config @@ -0,0 +1,8 @@ +display_mode=1 +params_file=0 +params_cmd=0 +columns=1 +height= +wrap= +width= +sort= diff --git a/RPiSetup/bullseye/apsetup/usr/local/bin/wap-disable b/RPiSetup/bullseye/apsetup/usr/local/bin/wap-disable new file mode 100644 index 0000000..a3fa126 --- /dev/null +++ b/RPiSetup/bullseye/apsetup/usr/local/bin/wap-disable @@ -0,0 +1,4 @@ +#!/bin/bash +systemctl stop hostapd +systemctl disable hostapd + diff --git a/RPiSetup/bullseye/apsetup/usr/local/bin/wap-enable b/RPiSetup/bullseye/apsetup/usr/local/bin/wap-enable new file mode 100644 index 0000000..b98c60d --- /dev/null +++ b/RPiSetup/bullseye/apsetup/usr/local/bin/wap-enable @@ -0,0 +1,4 @@ +#!/bin/bash +systemctl enable hostapd +systemctl start hostapd + diff --git a/RPiSetup/bullseye/apsetup/usr/local/bin/wap-setpassphrase b/RPiSetup/bullseye/apsetup/usr/local/bin/wap-setpassphrase new file mode 100644 index 0000000..9a010b8 --- /dev/null +++ b/RPiSetup/bullseye/apsetup/usr/local/bin/wap-setpassphrase @@ -0,0 +1,16 @@ +#!/bin/bash +newppok=0 +while [ "$newppok" -ne 1 ] +do + echo -n "New passphrase: " + read newpp + newpplen=`echo -n $newpp | wc -m` + if [ "$newpp" = "" -o "$newpplen" -lt 8 ] + then + echo "Passphrase didn't satisfy requirements. Try again or hit -c to abort." + else + newppok=1 + fi +done +sed -i "/wpa_passphrase=.*/c wpa_passphrase=$newpp" /etc/hostapd/hostapd.conf +systemctl restart hostapd diff --git a/RPiSetup/bullseye/apsetup/usr/local/bin/wap-setssid b/RPiSetup/bullseye/apsetup/usr/local/bin/wap-setssid new file mode 100644 index 0000000..694faa4 --- /dev/null +++ b/RPiSetup/bullseye/apsetup/usr/local/bin/wap-setssid @@ -0,0 +1,15 @@ +#!/bin/bash +newssidok=0 +while [ "$newssidok" -ne 1 ] +do + echo -n "New SSID: " + read newssid + if [ "$newssid" = "" ] + then + echo "SSID cannot be blank. Try again or hit -c to abort." + else + newssidok=1 + fi +done +sed -i "/ssid=.*/c ssid=$newssid" /etc/hostapd/hostapd.conf +systemctl restart hostapd diff --git a/RPiSetup/bullseye/brlaser-master/CMakeLists.txt b/RPiSetup/bullseye/brlaser-master/CMakeLists.txt new file mode 100644 index 0000000..15f430c --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/CMakeLists.txt @@ -0,0 +1,126 @@ +cmake_minimum_required(VERSION 3.1) +project(brlaser CXX) +set(BRLASER_VERSION "4") + +if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "No build type selected, default to RelWithDebInfo") + set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Build type (default RelWithDebInfo)" FORCE) +endif() + +include(CMakePushCheckState) +include(CheckCXXCompilerFlag) +include(CheckIncludeFileCXX) + + +## Enable assertions for all builds +## (cmake by default sets NDEBUG for release builds) + +foreach(var + CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS_MINSIZEREL) + string(REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" " " "${var}" "${${var}}") +endforeach() + + +## Configure the compiler + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +macro(extra_cxx_compiler_flag FLAG) + string(REGEX REPLACE "[^A-Za-z_0-9]" "_" SFLAG ${FLAG}) + check_cxx_compiler_flag(${FLAG} COMPILER_SUPPORT_${SFLAG}) + if(COMPILER_SUPPORT_${SFLAG}) + set(EXTRA_CXX_FLAGS "${EXTRA_CXX_FLAGS} ${FLAG}") + endif() +endmacro(extra_cxx_compiler_flag) + +# Compiler warnings +extra_cxx_compiler_flag("-Wall") +extra_cxx_compiler_flag("-Wno-missing-braces") +# Some security flags +extra_cxx_compiler_flag("-fstack-protector-strong") +extra_cxx_compiler_flag("-Wformat") +extra_cxx_compiler_flag("-Werror=format-security") +extra_cxx_compiler_flag("-D_FORTIFY_SOURCE=2") +# Enable the supported flags, but give priority to CXXFLAGS env var +set(CMAKE_CXX_FLAGS "${EXTRA_CXX_FLAGS} ${CMAKE_CXX_FLAGS}") + + +## Configure CUPS + +find_program(CUPS_CONFIG NAMES cups-config) +if(NOT CUPS_CONFIG) + message(FATAL_ERROR "cups-config command not found. Are the CUPS development packages installed?") +endif() +execute_process( + COMMAND "${CUPS_CONFIG}" --datadir + OUTPUT_VARIABLE CUPS_DATA_DIR + OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process( + COMMAND "${CUPS_CONFIG}" --serverbin + OUTPUT_VARIABLE CUPS_SERVER_BIN + OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process( + COMMAND "${CUPS_CONFIG}" --cflags + OUTPUT_VARIABLE CUPS_CFLAGS + OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process( + COMMAND "${CUPS_CONFIG}" --ldflags + OUTPUT_VARIABLE CUPS_LDFLAGS + OUTPUT_STRIP_TRAILING_WHITESPACE) +execute_process( + COMMAND "${CUPS_CONFIG}" --image --libs + OUTPUT_VARIABLE CUPS_LIBS + OUTPUT_STRIP_TRAILING_WHITESPACE) + +cmake_push_check_state() +set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${CUPS_CFLAGS}") +check_include_file_cxx(cups/raster.h HAVE_CUPS_RASTER_H) +cmake_pop_check_state() +if(NOT HAVE_CUPS_RASTER_H) + message(SEND_ERROR " header not found. Are the CUPS development packages installed?") +endif() + + +## Build instructions + +configure_file( + "${PROJECT_SOURCE_DIR}/brlaser.drv.in" + "${PROJECT_BINARY_DIR}/brlaser.drv") + +configure_file( + "${PROJECT_SOURCE_DIR}/config.h.in" + "${PROJECT_BINARY_DIR}/config.h") + +include_directories("${PROJECT_BINARY_DIR}") + +add_executable(rastertobrlaser src/main.cc src/job.cc src/line.cc src/debug.cc) +target_compile_options(rastertobrlaser PRIVATE ${CUPS_CFLAGS}) +target_link_libraries(rastertobrlaser ${CUPS_LIBS}) +target_link_libraries(rastertobrlaser ${CUPS_LDFLAGS}) + +add_executable(brdecode src/brdecode.cc) +add_executable(test_lest test/test_lest.cc) +add_executable(test_line test/test_line.cc src/line.cc) +add_executable(test_block test/test_block.cc) + +enable_testing() +add_test(test_lest test_lest) +add_test(test_line test_line) +add_test(test_block test_block) + +# Autotools-style "make check" command +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) +add_dependencies(check test_lest test_line test_block) + + +# Installation + +install( + TARGETS rastertobrlaser + DESTINATION "${CUPS_SERVER_BIN}/filter") +install( + FILES "${PROJECT_BINARY_DIR}/brlaser.drv" + DESTINATION "${CUPS_DATA_DIR}/drv") diff --git a/RPiSetup/bullseye/brlaser-master/COPYING b/RPiSetup/bullseye/brlaser-master/COPYING new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/RPiSetup/bullseye/brlaser-master/ChangeLog b/RPiSetup/bullseye/brlaser-master/ChangeLog new file mode 100644 index 0000000..4fbd9a2 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/ChangeLog @@ -0,0 +1,9 @@ +brlaser v3 (2014-07-07) + Added DCP-7065DN description. + +brlaser v2 (2014-06-29) + Suppport compilation with GCC 4.6. + Add a basic test suite. + +brlaser v1 (2013-12-30) + Initial release. diff --git a/RPiSetup/bullseye/brlaser-master/README.md b/RPiSetup/bullseye/brlaser-master/README.md new file mode 100644 index 0000000..7b79fea --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/README.md @@ -0,0 +1,85 @@ +brlaser: Brother laser printer driver +===================================== + +brlaser is a CUPS driver for Brother laser printers. + +Although most Brother printers support a standard printer language +such as PCL or PostScript, not all do. If you have a monochrome +Brother laser printer (or multi-function device) and the other open +source drivers don't work, this one might help. + +This driver is known to work with these printers: + +* Brother DCP-1510 +* Brother DCP-7030 +* Brother DCP-7040 +* Brother DCP-7055 +* Brother DCP-7055W +* Brother DCP-7065DN +* Brother HL-L2300D +* Brother MFC-7360N + + +Other printers +-------------- + +If your printer isn't included in the list above, just try selecting +any entry marked 'brlaser' and see if it works. + +If it does, please create a new issue here in Github and include the +output of this command: + + sudo lpinfo --include-schemes usb -l -v + +Then I'll be able to add a proper entry for your printer. + + +Installation +------------ + +Some operating systems already ship this driver. This is the case for +at least Debian, Ubuntu, Raspbian, openSUSE and Arch Linux. Look for a +package named `printer-driver-brlaser`. + +You'll also need Ghostscript, in case that's not installed +automatically. + +Once brlaser is installed, you can add your printer using the usual +CUPS interface. + + +Building from source +-------------------- + +To compile brlaser you'll need CMake and the CUPS development packages +(libcups2-dev, libcupsimage2-dev or similar). + +Get the code by cloning the git repo . Compile and install with these commands: + + cmake . + make + sudo make install + +It might be needed to restart CUPS after this. + +[latest release]: https://github.com/pdewacht/brlaser/releases/latest + + +Copyright +--------- + +Copyright © 2013 Peter De Wachter + +brlaser is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +brlaser is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with brlaser. If not, see . diff --git a/RPiSetup/bullseye/brlaser-master/brlaser.drv.in b/RPiSetup/bullseye/brlaser-master/brlaser.drv.in new file mode 100644 index 0000000..84542cc --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/brlaser.drv.in @@ -0,0 +1,143 @@ +// This file is part of the brlaser printer driver. +// +// Copyright 2013 Peter De Wachter +// +// brlaser is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// brlaser is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with brlaser. If not, see . + +#define USING "using @CMAKE_PROJECT_NAME@ v@BRLASER_VERSION@" + +// Include standard font and media definitions +#include +#include + +// List the fonts that are supported, in this case all standard fonts... +Font * + +// Manufacturer and driver version. +Manufacturer "Brother" +Version "@BRLASER_VERSION@" + +// Each filter provided by the driver... +Filter application/vnd.cups-raster 33 rastertobrlaser + +// Supported resolutions. +// The 1200dpi mode is weird: we need to send 1200x1200dpi raster +// data, but Brother only advertises 1200x600dpi. I wonder what +// is going on there. +// The 300dpi mode is reportedly not supported on all printers, so +// it's listed in individual printer blocks where we believe it works. +// Resolution k 1 0 0 0 "300dpi/300 DPI" +*Resolution k 1 0 0 0 "600dpi/600 DPI" +Resolution k 1 0 0 0 "1200dpi/1200HQ" + +// Supported page sizes. +HWMargins 8 8 8 16 +*MediaSize A4 +MediaSize A5 +MediaSize A6 +MediaSize B5 +MediaSize B6 +MediaSize EnvC5 +MediaSize EnvMonarch +MediaSize EnvDL +MediaSize Executive +MediaSize Legal +MediaSize Letter + +// Input trays. Numbers must match the filter source code. +*InputSlot 0 "Auto/Auto-select" +InputSlot 1 "Tray1/Tray 1" +InputSlot 2 "Tray2/Tray 2" +InputSlot 3 "Tray3/Tray 3" +InputSlot 4 "MPTray/MP Tray" +InputSlot 5 "Manual/Manual" + +// Media types. +*MediaType 0 "PLAIN/Plain paper" +MediaType 1 "THIN/Thin paper" +MediaType 2 "THICK/Thick paper" +MediaType 3 "THICKER/Thicker paper" +MediaType 4 "BOND/Bond paper" +MediaType 5 "TRANS/Transparencies" +MediaType 6 "ENV/Envelopes" +MediaType 7 "ENV-THICK/Thick envelopes" +MediaType 8 "ENV-THIN/Thin envelopes" + +Option "brlaserEconomode/Toner save mode" Boolean AnySetup 10 + *Choice False/Off "<>setpagedevice" + Choice True/On "<>setpagedevice" + + +{ + ModelName "DCP-1510" + Attribute "NickName" "" "Brother DCP-1510 series, $USING" + Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,XL2HB;MDL:DCP-1510 series;CLS:PRINTER;CID:Brother Laser Type1;" + Resolution k 1 0 0 0 "300dpi/300 DPI" + PCFileName "br1510.ppd" +} + +{ + ModelName "DCP-7030" + Attribute "NickName" "" "Brother DCP-7030, $USING" + Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7030;CLS:PRINTER;" + Resolution k 1 0 0 0 "300dpi/300 DPI" + PCFileName "br7030.ppd" +} + +{ + ModelName "DCP-7040" + Attribute "NickName" "" "Brother DCP-7040, $USING" + Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7040;CLS:PRINTER;" + Resolution k 1 0 0 0 "300dpi/300 DPI" + PCFileName "br7040.ppd" +} + +{ + ModelName "DCP-7055" + Attribute "NickName" "" "Brother DCP-7055, $USING" + Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7055;CLS:PRINTER;CID:Brother Laser Type1;" + Resolution k 1 0 0 0 "300dpi/300 DPI" + PCFileName "br7055.ppd" +} + +{ + ModelName "DCP-7055W" + Attribute "NickName" "" "Brother DCP-7055W, $USING" + Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7055W;CLS:PRINTER;CID:Brother Laser Type1;" + Resolution k 1 0 0 0 "300dpi/300 DPI" + PCFileName "br7055w.ppd" +} + +{ + ModelName "DCP-7065DN" + Attribute "NickName" "" "Brother DCP-7065DN, $USING" + Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:DCP-7065DN;CLS:PRINTER;CID:Brother Laser Type1;" + Duplex rotated + PCFileName "br7065dn.ppd" +} + +{ + ModelName "HL-L2300D" + Attribute "NickName" "" "Brother HL-L2300D, $USING" + Attribute "1284DeviceID" "" " MFG:Brother;CMD:PJL,HBP;MDL:HL-L2300D series;CLS:PRINTER;CID:Brother Laser Type1;" + Duplex rotated + PCFileName "brl2300d.ppd" +} + +{ + ModelName "MFC-7360N" + Attribute "NickName" "" "Brother MFC-7360N, $USING" + Attribute "1284DeviceID" "" "MFG:Brother;CMD:PJL,HBP;MDL:MFC-7360N;CLS:PRINTER;CID:Brother Laser Type1;" + PCFileName "br7360n.ppd" +} diff --git a/RPiSetup/bullseye/brlaser-master/config.h.in b/RPiSetup/bullseye/brlaser-master/config.h.in new file mode 100644 index 0000000..601ac5e --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/config.h.in @@ -0,0 +1,2 @@ +#define PACKAGE "@CMAKE_PROJECT_NAME@" +#define VERSION "@BRLASER_VERSION@" diff --git a/RPiSetup/bullseye/brlaser-master/src/block.h b/RPiSetup/bullseye/brlaser-master/src/block.h new file mode 100644 index 0000000..13daea1 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/src/block.h @@ -0,0 +1,68 @@ +// This file is part of the brlaser printer driver. +// +// Copyright 2013 Peter De Wachter +// +// brlaser is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// brlaser is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with brlaser. If not, see . + +#ifndef BLOCK_H +#define BLOCK_H + +#include +#include +#include + +class block { + public: + block(): line_bytes_(0) { + lines_.reserve(max_lines_per_block_); + } + + bool empty() const { + return line_bytes_ == 0; + } + + void add_line(std::vector &&line) { + assert(!line.empty()); + assert(line_fits(line.size())); + line_bytes_ += line.size(); + lines_.emplace_back(line); + } + + bool line_fits(unsigned size) { + return lines_.size() != max_lines_per_block_ + && line_bytes_ + size < max_block_size_; + } + + void flush(FILE *f) { + if (!empty()) { + fprintf(f, "%dw%c%c", + line_bytes_ + 2, 0, + static_cast(lines_.size())); + for (auto &line : lines_) { + fwrite(line.data(), 1, line.size(), f); + } + line_bytes_ = 0; + lines_.clear(); + } + } + + private: + static const unsigned max_block_size_ = 16350; + static const unsigned max_lines_per_block_ = 128; + + std::vector> lines_; + int line_bytes_; +}; + +#endif // BLOCK_H diff --git a/RPiSetup/bullseye/brlaser-master/src/brdecode.cc b/RPiSetup/bullseye/brlaser-master/src/brdecode.cc new file mode 100644 index 0000000..bcd3ec7 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/src/brdecode.cc @@ -0,0 +1,225 @@ +// A quick-and-dirty tool to convert print files back to pbm images. +// +// Copyright 2013 Peter De Wachter +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include +#include +#include + +namespace { + +const size_t MAX_LINE_SIZE = 2000; + +FILE *in_file; +std::vector> page; +std::vector line; +size_t line_offset; + + +class unexpected_eof: public std::exception { + public: + virtual const char *what() const noexcept { + return "Unexpected EOF"; + } +}; + +class line_overflow: public std::exception { + public: + virtual const char *what() const noexcept { + return "Unreasonable long line, aborting"; + } +}; + + +uint8_t get() { + int ch = getc(in_file); + if (ch < 0) + throw unexpected_eof(); + return ch; +} + +unsigned read_overflow() { + uint8_t ch; + unsigned sum = 0; + do { + ch = get(); + sum += ch; + } while (ch == 255); + return sum; +} + +void read_repeat(uint8_t cmd) { + uint16_t offset = (cmd >> 5) & 3; + if (offset == 3) + offset += read_overflow(); + uint16_t count = cmd & 31; + if (count == 31) + count += read_overflow(); + count += 2; + uint8_t data = get(); + + size_t end = line_offset + offset + count; + if (end > line.size()) { + if (end > MAX_LINE_SIZE) + throw line_overflow(); + line.resize(end); + } + line_offset += offset; + std::fill_n(line.begin() + line_offset, count, data); + line_offset += count; +} + +void read_substitute(uint8_t cmd) { + uint16_t offset = (cmd >> 3) & 15; + if (offset == 15) + offset += read_overflow(); + uint16_t count = cmd & 7; + if (count == 7) + count += read_overflow(); + count += 1; + + size_t end = line_offset + offset + count; + if (end > line.size()) { + if (end > MAX_LINE_SIZE) + throw line_overflow(); + line.resize(end); + } + line_offset += offset; + std::generate_n(line.begin() + line_offset, count, get); + line_offset += count; +} + +void read_edit() { + int8_t cmd = get(); + if (cmd < 0) { + read_repeat(cmd); + } else { + read_substitute(cmd); + } +} + +void read_line() { + uint8_t num_edits = get(); + if (num_edits == 255) { + line.clear(); + } else { + line_offset = 0; + for (int i = 0; i < num_edits; ++i) { + read_edit(); + } + } + page.push_back(line); +} + +void read_block() { + unsigned count = get(); + count = count * 256 + get(); + for (unsigned i = 0; i < count; ++i) { + read_line(); + } +} + +bool read_page() { + bool in_esc = false; + int ch; + + page.clear(); + line.clear(); + while ((ch = getc(in_file)) >= 0) { + if (ch == '\f') { + break; + } else if (ch == 033) { + in_esc = true; + } else if (in_esc && ch == 'w') { + read_block(); + } else if (in_esc && (ch >= 'A' && ch <= 'Z')) { + in_esc = false; + } + } + return !page.empty(); +} + +void write_pnm(FILE *f) { + size_t height = page.size(); + size_t width = 0; + for (auto &l : page) { + width = std::max(width, l.size()); + } + + fprintf(f, "P4 %zd %zd\n", width * 8, height); + std::vector empty(width); + for (auto &l : page) { + fwrite(l.data(), 1, l.size(), f); + fwrite(empty.data(), 1, width - l.size(), f); + } +} + +} // namespace + +int main(int argc, char *argv[]) { + const char *in_filename; + std::string out_prefix; + + if (argc > 2) { + in_filename = argv[1]; + out_prefix = argv[2]; + } else if (argc > 1) { + in_filename = argv[1]; + out_prefix = argv[1]; + } else { + in_filename = nullptr; + out_prefix = "page"; + } + + if (in_filename) { + in_file = fopen(in_filename, "rb"); + if (!in_file) { + fprintf(stderr, "Can't open file \"%s\"\n", in_filename); + return 1; + } + } else { + in_file = stdin; + if (isatty(0)) { + fprintf(stderr, "No filename given and no input on stdin\n"); + return 1; + } + } + + try { + int page_num = 1; + while (read_page()) { + std::string out_filename = out_prefix + + "-" + std::to_string(page_num) + ".pbm"; + FILE *out_file = fopen(out_filename.c_str(), "wb"); + if (!out_file) { + fprintf(stderr, "Can't write file \"%s\"\n", out_filename.c_str()); + return 1; + } + write_pnm(out_file); + fclose(out_file); + fprintf(stderr, "%s\n", out_filename.c_str()); + ++page_num; + } + } catch (std::exception &e) { + fprintf(stderr, "%s\n", e.what()); + return 1; + } + return 0; +} diff --git a/RPiSetup/bullseye/brlaser-master/src/debug.cc b/RPiSetup/bullseye/brlaser-master/src/debug.cc new file mode 100644 index 0000000..041b414 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/src/debug.cc @@ -0,0 +1,107 @@ +// This file is part of the brlaser printer driver. +// +// Copyright 2013 Peter De Wachter +// +// brlaser is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// brlaser is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with brlaser. If not, see . + +#include "config.h" +#include "debug.h" +#include +#include + +namespace { + +template +void dump(const char *name, const T &value) { + std::cerr << "DEBUG: " PACKAGE ": page header: " << name << " = " << value << '\n'; +} + +template +void dump(const char *name, const T (&value)[N]) { + std::cerr << "DEBUG: " PACKAGE ": page header: " << name << " ="; + for (int i = 0; i < N; ++i) { + std::cerr << ' ' << value[i]; + } + std::cerr << '\n'; +} + +void dump(const char *name, const char *value) { + std::cerr << "DEBUG: " PACKAGE ": page header: " << name << " = \"" << value << "\"\n"; +} + +template +void dump(const char *name, const char (&value)[N][M]) { + std::cerr << "DEBUG: " PACKAGE ": page header: " << name << " ="; + for (int i = 0; i < N; ++i) { + std::cerr << " \"" << value[i] << '"'; + } + std::cerr << '\n'; +} + +} // namespace + + +void dump_page_header(const cups_page_header2_t &h) { +#define d(f) dump(#f, h.f) + d(MediaClass); + d(MediaColor); + d(MediaType); + d(OutputType); + d(AdvanceDistance); + d(AdvanceMedia); + d(Collate); + d(CutMedia); + d(Duplex); + d(HWResolution); + d(ImagingBoundingBox); + d(InsertSheet); + d(Jog); + d(LeadingEdge); + d(Margins); + d(ManualFeed); + d(MediaPosition); + d(MediaWeight); + d(MirrorPrint); + d(NegativePrint); + d(NumCopies); + d(Orientation); + d(OutputFaceUp); + d(PageSize); + d(Separations); + d(TraySwitch); + d(Tumble); + d(cupsWidth); + d(cupsHeight); + d(cupsMediaType); + d(cupsBitsPerColor); + d(cupsBitsPerPixel); + d(cupsBytesPerLine); + d(cupsColorOrder); + d(cupsColorSpace); + d(cupsCompression); + d(cupsRowCount); + d(cupsRowFeed); + d(cupsRowStep); + d(cupsNumColors); + d(cupsBorderlessScalingFactor); + d(cupsPageSize); + d(cupsImagingBBox); + d(cupsInteger); + d(cupsReal); + d(cupsString); + d(cupsMarkerType); + d(cupsRenderingIntent); + d(cupsPageSizeName); +#undef d +} diff --git a/RPiSetup/bullseye/brlaser-master/src/debug.h b/RPiSetup/bullseye/brlaser-master/src/debug.h new file mode 100644 index 0000000..d1eff52 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/src/debug.h @@ -0,0 +1,25 @@ +// This file is part of the brlaser printer driver. +// +// Copyright 2013 Peter De Wachter +// +// brlaser is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// brlaser is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with brlaser. If not, see . + +#ifndef DEBUG_H +#define DEBUG_H + +#include + +void dump_page_header(const cups_page_header2_t &h); + +#endif diff --git a/RPiSetup/bullseye/brlaser-master/src/job.cc b/RPiSetup/bullseye/brlaser-master/src/job.cc new file mode 100644 index 0000000..440fc6d --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/src/job.cc @@ -0,0 +1,118 @@ +// This file is part of the brlaser printer driver. +// +// Copyright 2013 Peter De Wachter +// +// brlaser is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// brlaser is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with brlaser. If not, see . + +#include "job.h" +#include +#include +#include +#include "line.h" +#include "block.h" + + +job::job(FILE *out, const std::string &job_name) + : out_(out), + job_name_(job_name), + page_params_() { + // Delete dubious characters from job name + std::replace_if(job_name_.begin(), job_name_.end(), [](char c) { + return c < 32 || c >= 127 || c == '"' || c == '\\'; + }, ' '); + + begin_job(); +} + +job::~job() { + end_job(); +} + +void job::begin_job() { + for (int i = 0; i < 128; ++i) { + putc(0, out_); + } + fprintf(out_, "\033%%-12345X@PJL\n"); + fprintf(out_, "@PJL JOB NAME=\"%s\"\n", job_name_.c_str()); +} + +void job::end_job() { + fprintf(out_, "\033%%-12345X@PJL\n"); + fprintf(out_, "@PJL EOJ NAME=\"%s\"\n", job_name_.c_str()); + fprintf(out_, "\033%%-12345X\n"); +} + +void job::write_page_header() { + fprintf(out_, "\033%%-12345X@PJL\n"); + if (page_params_.resolution != 1200) { + fprintf(out_, "@PJL SET RAS1200MODE = FALSE\n"); + fprintf(out_, "@PJL SET RESOLUTION = %d\n", page_params_.resolution); + } else { + fprintf(out_, "@PJL SET RAS1200MODE = TRUE\n"); + fprintf(out_, "@PJL SET RESOLUTION = 600\n"); + } + fprintf(out_, "@PJL SET ECONOMODE = %s\n", + page_params_.economode ? "ON" : "OFF"); + fprintf(out_, "@PJL SET SOURCETRAY = %s\n", + page_params_.sourcetray.c_str()); + fprintf(out_, "@PJL SET MEDIATYPE = %s\n", + page_params_.mediatype.c_str()); + fprintf(out_, "@PJL SET PAPER = %s\n", + page_params_.papersize.c_str()); + fprintf(out_, "@PJL SET PAGEPROTECT = AUTO\n"); + fprintf(out_, "@PJL SET ORIENTATION = PORTRAIT\n"); + fprintf(out_, "@PJL ENTER LANGUAGE = PCL\n"); + + fputs("\033E", out_); + fprintf(out_, "\033&l%dX", std::max(1, page_params_.num_copies)); + + if (page_params_.duplex) { + fputs("\033&l2S", out_); + } +} + +void job::encode_page(const page_params &page_params, + int lines, + int linesize, + nextline_fn nextline) { + if (!(page_params_ == page_params)) { + page_params_ = page_params; + write_page_header(); + } + + std::vector line(linesize); + std::vector reference(linesize); + block block; + + if (!nextline(line)) { + return; + } + block.add_line(encode_line(line)); + std::swap(line, reference); + + fputs("\033*b1030m", out_); + + for (int i = 1; i < lines && nextline(line); ++i) { + std::vector encoded = encode_line(line, reference); + if (!block.line_fits(encoded.size())) { + block.flush(out_); + } + block.add_line(std::move(encoded)); + std::swap(line, reference); + } + + block.flush(out_); + fputs("1030M\f", out_); + fflush(out_); +} diff --git a/RPiSetup/bullseye/brlaser-master/src/job.h b/RPiSetup/bullseye/brlaser-master/src/job.h new file mode 100644 index 0000000..2ae7ea5 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/src/job.h @@ -0,0 +1,68 @@ +// This file is part of the brlaser printer driver. +// +// Copyright 2013 Peter De Wachter +// +// brlaser is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// brlaser is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with brlaser. If not, see . + +#ifndef JOB_H +#define JOB_H + +#include +#include +#include +#include + +struct page_params { + int num_copies; + int resolution; + bool duplex; + bool economode; + std::string sourcetray; + std::string mediatype; + std::string papersize; + + bool operator==(const page_params &o) const { + return num_copies == o.num_copies + && resolution == o.resolution + && duplex == o.duplex + && economode == o.economode + && sourcetray == o.sourcetray + && mediatype == o.mediatype + && papersize == o.papersize; + } +}; + +class job { + public: + typedef bool (*nextline_fn)(std::vector &buf); + + explicit job(FILE *out, const std::string &job_name); + ~job(); + + void encode_page(const page_params ¶ms, + int lines, + int linesize, + nextline_fn nextline); + + private: + void begin_job(); + void end_job(); + void write_page_header(); + + FILE *out_; + std::string job_name_; + page_params page_params_; +}; + +#endif // JOB_H diff --git a/RPiSetup/bullseye/brlaser-master/src/line.cc b/RPiSetup/bullseye/brlaser-master/src/line.cc new file mode 100644 index 0000000..6489118 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/src/line.cc @@ -0,0 +1,191 @@ +// This file is part of the brlaser printer driver. +// +// Copyright 2013 Peter De Wachter +// +// brlaser is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// brlaser is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with brlaser. If not, see . + +#include "line.h" +#include +#include +using std::vector; + +namespace { + +void write_overflow(int value, vector *out) { + if (value >= 0) { + if (value < 255) { + out->push_back(value); + } else { + out->insert(out->end(), value / 255, 255); + out->push_back(value % 255); + } + } +} + +template +void write_substitute(int offset, + Iterator first, + Iterator last, + vector *out) { + assert(offset >= 0); + assert(offset < 10000); + assert(first != last); + + const int offset_max = 15; + const int count_max = 7; + int count = std::distance(first, last) - 1; + + int offset_low = std::min(offset, offset_max); + int count_low = std::min(count, count_max); + out->push_back((offset_low << 3) | count_low); + write_overflow(offset - offset_max, out); + write_overflow(count - count_max, out); + out->insert(out->end(), first, last); +} + +void write_repeat(int offset, int count, int value, vector *out) { + assert(offset >= 0); + assert(offset < 10000); + assert(count >= 2); + assert(count < 10000); + + const int offset_max = 3; + const int count_max = 31; + count -= 2; + + int offset_low = std::min(offset, offset_max); + int count_low = std::min(count, count_max); + out->push_back(128 | (offset_low << 5) | count_low); + write_overflow(offset - offset_max, out); + write_overflow(count - count_max, out); + out->push_back(value); +} + + +bool all_zeros(const vector &buf) { + return std::none_of(buf.begin(), buf.end(), [](uint8_t b) { return b; }); +} + +template +int skip_to_next_mismatch(Iterator1 *first1, + Iterator1 last1, + Iterator2 *first2) { + auto mismatch_it = std::mismatch(*first1, last1, *first2); + int skipped = std::distance(*first1, mismatch_it.first); + *first1 = mismatch_it.first; + *first2 = mismatch_it.second; + return skipped; +} + +template +int repeat_length(Iterator first, Iterator last) { + if (first != last) { + auto k = *first; + auto mismatch = std::find_if(std::next(first), last, + [=](decltype(k) x) { return x != k; }); + return std::distance(first, mismatch); + } + return 0; +} + +template +int substitute_length(Iterator1 first1, Iterator1 last1, Iterator2 first2) { + if (first1 != last1) { + Iterator1 it1 = first1; + Iterator2 it2 = first2; + Iterator1 next1 = std::next(first1); + Iterator2 next2 = std::next(first2); + Iterator1 prev1 = first1; + while (next1 != last1) { + if ((*it1 == *it2 && *next1 == *next2)) { + return std::distance(first1, it1); + } + if (*it1 == *next1 && *it1 == *prev1) { + return std::distance(first1, prev1); + } + prev1 = it1; + it1 = next1; it2 = next2; + ++next1; ++next2; + } + } + return std::distance(first1, last1); +} + +size_t reserve_size(const vector &line) { + // Big enough to store the line uncompressed together with an Substitute + // command with many overflow bytes. + return line.size() + 16; +} + +} // namespace + +vector encode_line(const vector &line, + const vector &reference) { + assert(line.size() == reference.size()); + if (all_zeros(line)) { + return vector(1, 0xFF); + } + + vector output; + output.reserve(reserve_size(line)); + output.push_back(0); // first byte is the edit count + + const uint8_t max_edits = 254; + int num_edits = 0; + + auto line_it = line.begin(); + auto ref_it = reference.begin(); + while (1) { + int offset = skip_to_next_mismatch(&line_it, line.end(), &ref_it); + if (line_it == line.end()) { + // No more differences, we're done. + break; + } + + if (++num_edits == max_edits) { + // We've run out of edits. Just output the rest of the line in a big + // substitute command. + write_substitute(offset, line_it, line.end(), &output); + break; + } + + int s = substitute_length(line_it, line.end(), ref_it); + if (s > 0) { + write_substitute(offset, line_it, std::next(line_it, s), &output); + line_it += s; + ref_it += s; + } else { + int r = repeat_length(line_it, line.end()); + assert(r >= 2); + write_repeat(offset, r, *line_it, &output); + line_it += r; + ref_it += r; + } + } + + assert(num_edits <= max_edits); + output[0] = num_edits; + return output; +} + +vector encode_line(const vector &line) { + if (all_zeros(line)) { + return vector(1, 0xFF); + } + vector buf; + buf.reserve(reserve_size(line)); + buf.push_back(1); + write_substitute(0, line.begin(), line.end(), &buf); + return buf; +} diff --git a/RPiSetup/bullseye/brlaser-master/src/line.h b/RPiSetup/bullseye/brlaser-master/src/line.h new file mode 100644 index 0000000..d9d8716 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/src/line.h @@ -0,0 +1,31 @@ +// This file is part of the brlaser printer driver. +// +// Copyright 2013 Peter De Wachter +// +// brlaser is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// brlaser is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with brlaser. If not, see . + +#ifndef LINE_H +#define LINE_H + +#include +#include + +std::vector encode_line( + const std::vector &line, + const std::vector &reference); + +std::vector encode_line( + const std::vector &line); + +#endif // LINE_H diff --git a/RPiSetup/bullseye/brlaser-master/src/main.cc b/RPiSetup/bullseye/brlaser-master/src/main.cc new file mode 100644 index 0000000..6eafcdd --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/src/main.cc @@ -0,0 +1,205 @@ +// This file is part of the brlaser printer driver. +// +// Copyright 2013 Peter De Wachter +// +// brlaser is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// brlaser is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with brlaser. If not, see . + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "job.h" +#include "debug.h" + + +namespace { + +cups_raster_t *ras; +volatile sig_atomic_t interrupted = 0; + + +void sigterm_handler(int sig) { + interrupted = 1; +} + + +bool next_line(std::vector &buf) { + if (interrupted) { + return false; + } + return cupsRasterReadPixels(ras, buf.data(), buf.size()) == buf.size(); +} + + +bool plain_ascii_string(const char *str) { + bool result = true; + for (; result && *str; str++) { + result = *str >= 32 && *str <= 126; + } + return result; +} + +std::string ascii_job_name(const char *job_id, const char *job_user, const char *job_name) { + std::array parts = {{ + job_id, + job_user, + job_name + }}; + std::string result; + for (const char *part : parts) { + if (*part && plain_ascii_string(part)) { + if (!result.empty()) { + result += '/'; + } + result += part; + } + } + if (result.empty()) { + result = "brlaser"; + } + const int max_size = 79; + if (result.size() > max_size) { + result.resize(max_size); + } + return result; +} + +page_params build_page_params(const cups_page_header2_t &header) { + static const std::array sources = {{ + "AUTO", "T1", "T2", "T3", "MP", "MANUAL" + }}; + static const std::map sizes = { + { "A4", "A4" }, + { "A5", "A5" }, + { "A6", "A6" }, + { "B5", "B5" }, + { "B6", "B6" }, + { "EnvC5", "C5" }, + { "EnvMonarch", "MONARCH" }, + { "EnvPRC5", "DL" }, + { "EnvDL", "DL" }, + { "Executive", "EXECUTIVE" }, + { "Legal", "LEGAL" }, + { "Letter", "LETTER" } + }; + + page_params p = { }; + p.num_copies = header.NumCopies; + p.resolution = header.HWResolution[0]; + p.economode = header.cupsInteger[10]; + p.mediatype = header.MediaType; + p.duplex = header.Duplex; + + if (header.MediaPosition < sources.size()) + p.sourcetray = sources[header.MediaPosition]; + else + p.sourcetray = sources[0]; + + auto size_it = sizes.find(header.cupsPageSizeName); + if (size_it != sizes.end()) + p.papersize = size_it->second; + else + p.papersize = "A4"; + + return p; +} + +} // namespace + + +int main(int argc, char *argv[]) { + fprintf(stderr, "INFO: %s version %s\n", PACKAGE, VERSION); + + if (argc != 6 && argc != 7) { + fprintf(stderr, "ERROR: rastertobrlaser job-id user title copies options [file]\n"); + fprintf(stderr, "INFO: This program is a CUPS filter. It is not intended to be run manually.\n"); + return 1; + } + const char *job_id = argv[1]; + const char *job_user = argv[2]; + const char *job_name = argv[3]; + // const int job_copies = atoi(argv[4]); + // const char *job_options = argv[5]; + const char *job_filename = argv[6]; + // const char *job_charset = getenv("CHARSET"); + + signal(SIGTERM, sigterm_handler); + signal(SIGPIPE, SIG_IGN); + + int fd = STDIN_FILENO; + if (job_filename) { + fd = open(job_filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "ERROR: " PACKAGE ": Unable to open raster file\n"); + return 1; + } + } + +#ifdef __OpenBSD__ + if (pledge("stdio", nullptr) != 0) { + fprintf(stderr, "ERROR: " PACKAGE ": pledge failed\n"); + return 1; + } +#endif + + ras = cupsRasterOpen(fd, CUPS_RASTER_READ); + if (!ras) { + fprintf(stderr, "DEBUG: " PACKAGE ": Cannot read raster data. Most likely an earlier filter in the pipeline failed.\n"); + return 1; + } + + int pages = 0; + { + job job(stdout, ascii_job_name(job_id, job_user, job_name)); + cups_page_header2_t header; + while (!interrupted && cupsRasterReadHeader2(ras, &header)) { + if (header.cupsBitsPerPixel != 1 + || header.cupsBitsPerColor != 1 + || header.cupsNumColors != 1 + || header.cupsBytesPerLine > 10000) { + fprintf(stderr, "ERROR: " PACKAGE ": Page %d: Bogus raster data.\n", pages + 1); + dump_page_header(header); + return 1; + } + if (pages == 0) { + fprintf(stderr, "DEBUG: " PACKAGE ": Page header of first page\n"); + dump_page_header(header); + } + job.encode_page(build_page_params(header), + header.cupsHeight, + header.cupsBytesPerLine, + next_line); + fprintf(stderr, "PAGE: %d %d\n", ++pages, header.NumCopies); + } + } + + if (pages == 0) { + fprintf(stderr, "ERROR: " PACKAGE ": No pages were found.\n"); + return 1; + } + + fflush(stdout); + if (ferror(stdout)) { + fprintf(stderr, "DEBUG: " PACKAGE ": Could not write print data. Most likely the CUPS backend failed.\n"); + return 1; + } + return 0; +} diff --git a/RPiSetup/bullseye/brlaser-master/test/lest.hpp b/RPiSetup/bullseye/brlaser-master/test/lest.hpp new file mode 100644 index 0000000..efc9442 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/test/lest.hpp @@ -0,0 +1,199 @@ +// Copyright 2013 by Martin Moene +// +// lest is based on ideas by Kevlin Henney, see video at +// http://skillsmatter.com/podcast/agile-testing/kevlin-henney-rethinking-unit-testing-in-c-plus-plus +// +// Distributed under the Boost Software License, Version 1.0: +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#ifndef LEST_LEST_H_INCLUDED +#define LEST_LEST_H_INCLUDED + +#include +#include +#include +#include +#include + +#ifndef lest_NO_SHORT_ASSERTION_NAMES +# define EXPECT lest_EXPECT +# define EXPECT_THROWS lest_EXPECT_THROWS +# define EXPECT_THROWS_AS lest_EXPECT_THROWS_AS +#endif + +#define lest_EXPECT( expr ) \ + try \ + { \ + if ( ! (expr) ) \ + throw lest::failure{ lest_LOCATION, #expr }; \ + } \ + catch( lest::failure const & ) \ + { \ + throw ; \ + } \ + catch( std::exception const & e ) \ + { \ + throw lest::unexpected{ lest_LOCATION, #expr, lest::with_message( e.what() ) }; \ + } \ + catch(...) \ + { \ + throw lest::unexpected{ lest_LOCATION, #expr, "of unknown type" }; \ + } + +#define lest_EXPECT_THROWS( expr ) \ + for (;;) \ + { \ + try { lest::serum( expr ); } catch (...) { break; } \ + throw lest::expected{ lest_LOCATION, #expr }; \ + } + +#define lest_EXPECT_THROWS_AS( expr, excpt ) \ + for (;;) \ + { \ + try { lest::serum( expr ); } catch ( excpt & ) { break; } catch (...) {} \ + throw lest::expected{ lest_LOCATION, #expr, lest::of_type( #excpt ) }; \ + } + +#define lest_LOCATION lest::location{__FILE__, __LINE__} + +namespace lest { + +struct test +{ + const std::string name; + const std::function behaviour; +}; + +struct location +{ + const std::string file; + const int line; + + location( std::string file, int line ) + : file{ file }, line{ line } {} +}; + +struct comment +{ + const std::string text; + + comment( std::string text ) : text{ text } {} + explicit operator bool() { return ! text.empty(); } +}; + +struct message : std::runtime_error +{ + const std::string kind; + const location where; + const comment note; + + ~message() throw() {} // GCC 4.6 + + message( std::string kind, location where, std::string expr, std::string note = "" ) + : std::runtime_error{ expr }, kind{ kind }, where{ where }, note{ note } {} +}; + +struct failure : message +{ + failure( location where, std::string expr ) + : message{ "failed", where, expr } {} +}; + +struct expected : message +{ + expected( location where, std::string expr, std::string excpt = "" ) + : message{ "failed: didn't get exception", where, expr, excpt } {} +}; + +struct unexpected : message +{ + unexpected( location where, std::string expr, std::string note ) + : message{ "failed: got unexpected exception", where, expr, note } {} +}; + +inline bool serum( bool verum ) { return verum; } + +inline std::string with_message( std::string text ) +{ + return "with message \"" + text + "\""; +} + +inline std::string of_type( std::string text ) +{ + return "of type " + text; +} + +inline std::string pluralise( int n, std::string text ) +{ + return n == 1 ? text : text + "s"; +} + +inline std::ostream & operator<<( std::ostream & os, comment note ) +{ + return os << (note ? " " + note.text : "" ); +} + +inline std::ostream & operator<<( std::ostream & os, location where ) +{ +#ifdef __GNUG__ + return os << where.file << ":" << where.line; +#else + return os << where.file << "(" << where.line << ")"; +#endif +} + +inline void report( std::ostream & os, message const & e, std::string test ) +{ + os << e.where << ": " << e.kind << e.note << ": " << test << ": " << e.what() << std::endl; +} + +template +int run( test const (&specification)[N], std::ostream & os = std::cout ) +{ + int failures = 0; + + for ( auto & testing : specification ) + { + try + { + testing.behaviour(); + } + catch( message const & e ) + { + ++failures; + report( os, e, testing.name ); + } + } + + if ( failures > 0 ) + { + os << failures << " out of " << N << " " << pluralise(N, "test") << " failed." << std::endl; + } + + return failures; +} + +} // namespace lest + +#endif // LEST_LEST_H_INCLUDED diff --git a/RPiSetup/bullseye/brlaser-master/test/tempfile.h b/RPiSetup/bullseye/brlaser-master/test/tempfile.h new file mode 100644 index 0000000..f83e306 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/test/tempfile.h @@ -0,0 +1,54 @@ +// This file is part of the brlaser printer driver. +// +// Copyright 2014 Peter De Wachter +// +// brlaser is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// brlaser is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with brlaser. If not, see . + +#ifndef TEMPFILE_H +#define TEMPFILE_H + +#include +#include +#include + +class tempfile { + public: + explicit tempfile() + : ptr_(0), + size_(0), + file_(open_memstream(&ptr_, &size_)) { + } + + ~tempfile() { + fclose(file_); + free(ptr_); + } + + FILE *file() { + return file_; + } + + std::vector data() { + if (fflush(file_)) + return std::vector(); + return std::vector(ptr_, ptr_ + size_); + } + + private: + char *ptr_; + size_t size_; + FILE *file_; +}; + +#endif // TEMPFILE_H diff --git a/RPiSetup/bullseye/brlaser-master/test/test_block.cc b/RPiSetup/bullseye/brlaser-master/test/test_block.cc new file mode 100644 index 0000000..e5fd103 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/test/test_block.cc @@ -0,0 +1,91 @@ +// This file is part of the brlaser printer driver. +// +// Copyright 2014 Peter De Wachter +// +// brlaser is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// brlaser is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with brlaser. If not, see . + +#include "lest.hpp" +#include +#include +#include "tempfile.h" +#include "../src/block.h" + +typedef std::vector vec; + +const lest::test specification[] = { + "A block is created empty", + [] { + block b; + EXPECT(b.empty()); + }, + + "Adding a line makes a block no longer empty", + [] { + block b; + b.add_line(vec{1}); + EXPECT(!b.empty()); + }, + + "A block can contain 128 lines", + [] { + block b; + for (int i = 0; i < 128; ++i) { + EXPECT(b.line_fits(1)); + b.add_line(vec(1)); + } + EXPECT(!b.line_fits(1)); + }, + + "A block has a size limit of about 16 kilobyte", + [] { + block b; + for (int i = 0; i < 16; ++i) { + EXPECT(b.line_fits(1000)); + b.add_line(vec(1000)); + } + EXPECT(!b.line_fits(400)); + }, + + "Flushing an empty block does nothing", + [] { + block b; + tempfile f; + b.flush(f.file()); + EXPECT(f.data().empty()); + }, + + "Flush() writes the lines to a file with a proper header", + [] { + block b; + for (uint8_t n = 1; n < 6; ++n) { + b.add_line(vec{n, n}); + } + tempfile f; + b.flush(f.file()); + EXPECT(( f.data() == vec{'1','2','w',0,5,1,1,2,2,3,3,4,4,5,5} )); + }, + + "After flush() a block is empty again", + [] { + block b; + b.add_line(vec{1}); + tempfile f; + b.flush(f.file()); + EXPECT(b.empty()); + } +}; + +int main() { + return lest::run(specification); +} diff --git a/RPiSetup/bullseye/brlaser-master/test/test_lest.cc b/RPiSetup/bullseye/brlaser-master/test/test_lest.cc new file mode 100644 index 0000000..1eb7d6a --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/test/test_lest.cc @@ -0,0 +1,291 @@ +// Copyright 2013 by Martin Moene +// +// Distributed under the Boost Software License, Version 1.0: +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +#include "lest.hpp" +#include + +using namespace lest; + +const lest::test specification[] = +{ + "Function to suppress warning \"expression has no effect\" acts as identity function", [] + { + EXPECT( false == serum( false ) ); + EXPECT( true == serum( true ) ); + }, + + "Function with_message() returns correct string", [] + { + std::string msg = "Let writing tests become irresistibly easy and attractive."; + EXPECT( "with message \"" + msg + "\"" == with_message( msg ) ); + }, + + "Function of_type() returns correct string", [] + { + std::string msg = "this_type"; + EXPECT( "of type " + msg == of_type( msg ) ); + }, + + "Function pluralise() adds 's' except for 1 item", [] + { + std::string word = "hammer"; + EXPECT( word == pluralise( 1, word ) ); + for ( auto i : {0,2,3,4,5,6,7,8,9,10,11,12} ) + EXPECT( word + "s" == pluralise( i, word ) ); + }, + + "Location constructs properly", [] + { + char const * file = __FILE__; int line = __LINE__; + location where{ file, line }; + EXPECT( file == where.file ); + EXPECT( line == where.line ); + }, + + "Comment constructs properly", [] + { + std::string text = __FILE__; + comment note = text; + EXPECT( text == note.text ); + }, + + "Comment converted to bool indicates absence or presence of comment", [] + { + EXPECT( false == bool( comment( "") ) ); + EXPECT( true == bool( comment("x") ) ); + }, + + "Failure exception type constructs and prints properly", [] + { + std::string name = "test-name"; + failure msg( location{"filename.cpp", 765}, "expression" ); + + std::ostringstream os; + report( os, msg, name ); + +#ifndef __GNUG__ + EXPECT( os.str() == "filename.cpp(765): failed: test-name: expression\n" ); +#else + EXPECT( os.str() == "filename.cpp:765: failed: test-name: expression\n" ); +#endif + }, + + "Expected exception type constructs and prints properly", [] + { + std::string name = "test-name"; + expected msg( location{"filename.cpp", 765}, "expression" ); + + std::ostringstream os; + report( os, msg, name ); + +#ifndef __GNUG__ + EXPECT( os.str() == "filename.cpp(765): failed: didn't get exception: test-name: expression\n" ); +#else + EXPECT( os.str() == "filename.cpp:765: failed: didn't get exception: test-name: expression\n" ); +#endif + }, + + "Unexpected exception type constructs and prints properly", [] + { + std::string name = "test-name"; + unexpected msg( location{"filename.cpp", 765}, "expression", "exception-type" ); + + std::ostringstream os; + report( os, msg, name ); + +#ifndef __GNUG__ + EXPECT( os.str() == "filename.cpp(765): failed: got unexpected exception exception-type: test-name: expression\n" ); +#else + EXPECT( os.str() == "filename.cpp:765: failed: got unexpected exception exception-type: test-name: expression\n" ); +#endif + }, + + "Expect generates no message exception for a succeeding test", [] + { + test pass = { "P", [] { EXPECT( true ); } }; + + try { pass.behaviour(); } + catch(...) { throw failure(location{__FILE__,__LINE__}, "unexpected error generated"); } + }, + + "Expect generates a message exception for a failing test", [] + { + test fail = { "F", [] { EXPECT( false ); } }; + + for (;;) + { + try { fail.behaviour(); } catch ( message & ) { break; } + throw failure(location{__FILE__,__LINE__}, "no error generated"); + } + }, + + "Expect succeeds for success (true) and failure (false)", [] + { + test pass[] = {{ "P", [] { EXPECT( true ); } }}; + test fail[] = {{ "F", [] { EXPECT( false ); } }}; + + std::ostringstream os; + + EXPECT( 0 == run( pass, os ) ); + EXPECT( 1 == run( fail, os ) ); + }, + + "Expect succeeds for integer comparation", [] + { + test pass [] = {{ "P" , [] { EXPECT( 7 == 7 ); EXPECT( 7 != 8 ); + EXPECT( 7 >= 6 ); EXPECT( 7 <= 8 ); + EXPECT( 7 > 6 ); EXPECT( 7 < 8 ); } }}; + test fail_1[] = {{ "F1", [] { EXPECT( 7 == 8 ); } }}; + test fail_2[] = {{ "F2", [] { EXPECT( 7 != 7 ); } }}; + test fail_3[] = {{ "F3", [] { EXPECT( 7 <= 6 ); } }}; + test fail_4[] = {{ "F4", [] { EXPECT( 7 >= 8 ); } }}; + test fail_5[] = {{ "F5", [] { EXPECT( 7 < 6 ); } }}; + test fail_6[] = {{ "F6", [] { EXPECT( 7 > 8 ); } }}; + + std::ostringstream os; + + EXPECT( 0 == run( pass , os ) ); + EXPECT( 1 == run( fail_1, os ) ); + EXPECT( 1 == run( fail_2, os ) ); + EXPECT( 1 == run( fail_3, os ) ); + EXPECT( 1 == run( fail_4, os ) ); + EXPECT( 1 == run( fail_5, os ) ); + EXPECT( 1 == run( fail_6, os ) ); + }, + + "Expect succeeds for string comparation", [] + { + std::string a("a"); std::string b("b"); + test pass [] = {{ "P" , [=]() { EXPECT( a == a ); EXPECT( a != b ); + EXPECT( b >= a ); EXPECT( a <= b ); + EXPECT( b > a ); EXPECT( a < b ); } }}; + test fail_1[] = {{ "F1", [=]() { EXPECT( a == b ); } }}; + test fail_2[] = {{ "F2", [=]() { EXPECT( a != a ); } }}; + test fail_3[] = {{ "F3", [=]() { EXPECT( b <= a ); } }}; + test fail_4[] = {{ "F4", [=]() { EXPECT( a >= b ); } }}; + test fail_5[] = {{ "F5", [=]() { EXPECT( b < a ); } }}; + test fail_6[] = {{ "F6", [=]() { EXPECT( a > b ); } }}; + + std::ostringstream os; + + EXPECT( 0 == run( pass , os ) ); + EXPECT( 1 == run( fail_1, os ) ); + EXPECT( 1 == run( fail_2, os ) ); + EXPECT( 1 == run( fail_3, os ) ); + EXPECT( 1 == run( fail_4, os ) ); + EXPECT( 1 == run( fail_5, os ) ); + EXPECT( 1 == run( fail_6, os ) ); + }, + + "Function run() returns the right failure count", [] + { + test pass [] = {{ "P" , [] { EXPECT( 1==1 ); } }}; + test fail_1[] = {{ "F1", [] { EXPECT( 0==1 ); } }}; + test fail_3[] = {{ "F1", [] { EXPECT( 0==1 ); } }, + { "F2", [] { EXPECT( 0==1 ); } }, + { "F3", [] { EXPECT( 0==1 ); } },}; + + std::ostringstream os; + + EXPECT( 0 == run( pass , os ) ); + EXPECT( 1 == run( fail_1, os ) ); + EXPECT( 3 == run( fail_3, os ) ); + }, + + "Expect succeeds with an unexpected standard exception", [] + { + std::string text = "hello-world"; + test pass[] = {{ "P", [=]() { EXPECT( (throw std::runtime_error(text), true) ); } }}; + + std::ostringstream os; + + EXPECT( 1 == run( pass, os ) ); + EXPECT( std::string::npos != os.str().find(text) ); + }, + + "Expect succeeds with an unexpected non-standard exception", [] + { + test pass[] = {{ "P", [] { EXPECT( (throw 77, true) ); } }}; + + std::ostringstream os; + + EXPECT( 1 == run( pass, os ) ); + }, + + "Expect_throws succeeds with an expected standard exception", [] + { + std::string text = "hello-world"; + test pass[] = {{ "P", [=]() { EXPECT_THROWS( (throw std::runtime_error(text), true) ); } }}; + test fail[] = {{ "F", [ ]() { EXPECT_THROWS( true ); } }}; + + std::ostringstream os; + + EXPECT( 0 == run( pass, os ) ); + EXPECT( 1 == run( fail, os ) ); + }, + + "Expect_throws succeeds with an expected non-standard exception", [] + { + test pass[] = {{ "P", [] { EXPECT_THROWS( (throw 77, true) ); } }}; + test fail[] = {{ "F", [] { EXPECT_THROWS( true ); } }}; + + std::ostringstream os; + + EXPECT( 0 == run( pass, os ) ); + EXPECT( 1 == run( fail, os ) ); + }, + + "Expect_throws_as succeeds with a specific expected standard exception", [] + { + test pass[] = {{ "P", [] { EXPECT_THROWS_AS( (throw std::bad_alloc(), true), std::bad_alloc ); } }}; + test fail[] = {{ "F", [] { EXPECT_THROWS_AS( (throw std::bad_alloc(), true), std::runtime_error ); } }}; + + std::ostringstream os; + + EXPECT( 0 == run( pass, os ) ); + EXPECT( 1 == run( fail, os ) ); + }, + + "Expect_throws_as succeeds with a specific expected non-standard exception", [] + { + test pass[] = {{ "P", [] { EXPECT_THROWS_AS( (throw 77, true), int ); } }}; + test fail[] = {{ "F", [] { EXPECT_THROWS_AS( (throw 77, true), std::runtime_error ); } }}; + + std::ostringstream os; + + EXPECT( 0 == run( pass, os ) ); + EXPECT( 1 == run( fail, os ) ); + }, +}; + +int main() +{ + return lest::run( specification ); +} + +// cl -nologo -Wall -EHsc test_lest.cpp && test_lest +// g++ -Wall -Wextra -Weffc++ -std=c++11 -o test_lest.exe test_lest.cpp && test_lest + diff --git a/RPiSetup/bullseye/brlaser-master/test/test_line.cc b/RPiSetup/bullseye/brlaser-master/test/test_line.cc new file mode 100644 index 0000000..9ab12c6 --- /dev/null +++ b/RPiSetup/bullseye/brlaser-master/test/test_line.cc @@ -0,0 +1,150 @@ +// This file is part of the brlaser printer driver. +// +// Copyright 2014 Peter De Wachter +// +// brlaser is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// brlaser is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with brlaser. If not, see . + +#include "lest.hpp" +#include +#include +#include +#include "../src/line.h" + +typedef std::vector vec; + + +uint8_t sub(uint8_t offset, uint8_t count) { + assert(offset < 16); + assert(count < 8); + return (offset << 3) | count; +} + +uint8_t rep(uint8_t offset, uint8_t count) { + assert(offset < 4); + assert(count < 32); + return 128 | (offset << 5) | count; +} + + +const lest::test specification[] = { + "Don't crash on zero-length lines", + [] { + EXPECT(( encode_line(vec{}) == vec{0xFF} )); + EXPECT(( encode_line(vec{}, vec{}) == vec{0xFF} )); + }, + + "Encoding an initial blank line", + [] { + EXPECT(( encode_line(vec{0,0,0}) == vec{0xFF} )); + }, + + "Encoding an initial non-blank line", + [] { + EXPECT(( encode_line(vec{1,2,3}) == (vec{1,sub(0,2),1,2,3}) )); + }, + + "Encoding a (non-initial) blank line", + [] { + EXPECT(( encode_line(vec{0,0,0}, vec{1,2,3}) == vec{0xFF} )); + }, + + "Encoding a repeated line", + [] { + EXPECT(( encode_line(vec{1,2,3}, vec{1,2,3}) == vec{0} )); + }, + + "Using a subsitute command", + [] { + EXPECT(( encode_line(vec{0,0,1,2,3,0,0}, vec(7)) == vec{1,sub(2,2),1,2,3} )); + }, + + "Using a repeat command", + [] { + EXPECT(( encode_line(vec{0,0,1,1,0,0}, vec(6)) == vec{1,rep(2,0),1} )); + }, + + "Repeat command followed by substitute command", + [] { + EXPECT(( encode_line(vec{1,1,1,2,3}, vec(5)) == vec{2,rep(0,1),1,sub(0,1),2,3} )); + }, + + "Substitute comand followed by repeat command", + [] { + EXPECT(( encode_line(vec{3,2,1,1,1}, vec(5)) == vec{2,sub(0,1),3,2,rep(0,1),1} )); + }, + + "Substitute with an unmodified byte in the middle", + [] { + EXPECT(( encode_line(vec{1,2,3,0,1,2,3}, vec(7)) == vec{1,sub(0,6),1,2,3,0,1,2,3} )); + }, + + "Substitue with two unmodified bytes in the middle", + [] { + EXPECT(( encode_line(vec{1,2,3,0,0,1,2,3}, vec(8)) == vec{2,sub(0,2),1,2,3,sub(2,2),1,2,3} )); + }, + + "Repeat with an unmodified byte in the middle", + [] { + EXPECT(( encode_line(vec{1,1,1,0,1,1,1}, vec(7)) == vec{2,rep(0,1),1,rep(1,1),1} )); + }, + + "254 edits needed for a single line", + [] { + vec line, result; + for (int i = 0; i < 254; ++i) + line.insert(line.end(), {0,0,1}); + result.push_back(254); + for (int i = 0; i < 254; ++i) + result.insert(result.end(), {sub(2,0),1}); + EXPECT(( encode_line(line, vec(line.size())) == result )); + }, + + "Give up if more than 254 edits needed...", + [] { + vec line, result; + for (int i = 0; i < 255; ++i) + line.insert(line.end(), {0,0,1}); + result.push_back(254); + for (int i = 0; i < 253; ++i) + result.insert(result.end(), {sub(2,0),1}); + result.insert(result.end(), {sub(2,3),1,0,0,1}); + EXPECT(( encode_line(line, vec(line.size())) == result )); + }, + + "Repeat command with overflow bytes", + [] { + vec line(3, 0); + line.insert(line.end(), 512, 1); + vec ref(line.size(), 0); + vec expected{1,rep(3,31),0,255,224,1}; + EXPECT(encode_line(line, ref) == expected); + }, + + "Substitute command with overflow bytes", + [] { + vec expected{1,sub(15,7),255,0,255,237}; + vec line(270, 0); + for (int i = 0; i < 250; ++i) { + expected.insert(expected.end(), {1,2}); + line.insert(line.end(), {1,2}); + } + vec ref(line.size(), 0); + EXPECT(encode_line(line, ref) == expected); + }, +}; + + +int main() { + return lest::run(specification); +} diff --git a/RPiSetup/bullseye/etc/apache2/conf-available/opendrs.conf b/RPiSetup/bullseye/etc/apache2/conf-available/opendrs.conf new file mode 100644 index 0000000..91d3d92 --- /dev/null +++ b/RPiSetup/bullseye/etc/apache2/conf-available/opendrs.conf @@ -0,0 +1,10 @@ +# OpenMDRS configuration + +Alias /opendrs /var/www/opendrs + + + Options Indexes FollowSymLinks MultiViews + AllowOverride None + Order allow,deny + allow from all + diff --git a/RPiSetup/bullseye/etc/apache2/mods-available/alias.conf b/RPiSetup/bullseye/etc/apache2/mods-available/alias.conf new file mode 100644 index 0000000..e8341b8 --- /dev/null +++ b/RPiSetup/bullseye/etc/apache2/mods-available/alias.conf @@ -0,0 +1,24 @@ + + # Aliases: Add here as many aliases as you need (with no limit). The format is + # Alias fakename realname + # + # Note that if you include a trailing / on fakename then the server will + # require it to be present in the URL. So "/icons" isn't aliased in this + # example, only "/icons/". If the fakename is slash-terminated, then the + # realname must also be slash terminated, and if the fakename omits the + # trailing slash, the realname must also omit it. + # + # We include the /icons/ alias for FancyIndexed directory listings. If + # you do not use FancyIndexing, you may comment this out. + + #Alias /icons/ "/usr/share/apache2/icons/" + + + Options FollowSymlinks + AllowOverride None + Require all granted + + + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/RPiSetup/bullseye/etc/apache2/sites-available/000-default.conf b/RPiSetup/bullseye/etc/apache2/sites-available/000-default.conf new file mode 100644 index 0000000..bf8f25a --- /dev/null +++ b/RPiSetup/bullseye/etc/apache2/sites-available/000-default.conf @@ -0,0 +1,31 @@ + + # The ServerName directive sets the request scheme, hostname and port that + # the server uses to identify itself. This is used when creating + # redirection URLs. In the context of virtual hosts, the ServerName + # specifies what hostname must appear in the request's Host: header to + # match this virtual host. For the default virtual host (this file) this + # value is not decisive as it is used as a last resort host regardless. + # However, you must set it for any further virtual host explicitly. + #ServerName www.example.com + + ServerAdmin webmaster@localhost + DocumentRoot /var/www/opendrs + + # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, + # error, crit, alert, emerg. + # It is also possible to configure the loglevel for particular + # modules, e.g. + #LogLevel info ssl:warn + + ErrorLog ${APACHE_LOG_DIR}/error.log + CustomLog ${APACHE_LOG_DIR}/access.log combined + + # For most configuration files from conf-available/, which are + # enabled or disabled at a global level, it is possible to + # include a line for only one particular virtual host. For example the + # following line enables the CGI configuration for this host only + # after it has been globally disabled with "a2disconf". + #Include conf-available/serve-cgi-bin.conf + + +# vim: syntax=apache ts=4 sw=4 sts=4 sr noet diff --git a/RPiSetup/bullseye/etc/cups/cupsd.conf b/RPiSetup/bullseye/etc/cups/cupsd.conf new file mode 100644 index 0000000..524fdde --- /dev/null +++ b/RPiSetup/bullseye/etc/cups/cupsd.conf @@ -0,0 +1,146 @@ +# +# Configuration file for the CUPS scheduler. See "man cupsd.conf" for a +# complete description of this file. +# + +# Log general information in error_log - change "warn" to "debug" +# for troubleshooting... +LogLevel warn +PageLogFormat + +# Deactivate CUPS' internal logrotating, as we provide a better one, especially +# LogLevel debug2 gets usable now +MaxLogSize 0 + +# Only listen for connections from the local machine. +#Listen localhost:631 +Port 631 +Listen 0.0.0.0:631 +Listen /var/run/cups/cups.sock + +# Show shared printers on the local network. +Browsing On +BrowseLocalProtocols dnssd + +# Default authentication type, when authentication is required... +DefaultAuthType Basic + +# Web interface setting... +WebInterface Yes + +# Restrict access to the server... + + Order allow,deny + Allow from 192.168.100.* + + +# Restrict access to the admin pages... + + AuthType Basic + Require valid-user + Allow all + Order allow,deny + + +# Restrict access to configuration files... + + AuthType Default + Require user @SYSTEM + Order allow,deny + + +# Restrict access to log files... + + AuthType Default + Require user @SYSTEM + Order allow,deny + + +# Set the default printer/job policies... + + # Job/subscription privacy... + JobPrivateAccess default + JobPrivateValues default + SubscriptionPrivateAccess default + SubscriptionPrivateValues default + + # Job-related operations must be done by the owner or an administrator... + + Order deny,allow + + + + Require user @OWNER @SYSTEM + Order deny,allow + + + # All administration operations require an administrator to authenticate... + + AuthType Default + Require user @SYSTEM + Order deny,allow + + + # All printer operations require a printer operator to authenticate... + + AuthType Default + Require user @SYSTEM + Order deny,allow + + + # Only the owner or an administrator can cancel or authenticate a job... + + Require user @OWNER @SYSTEM + Order deny,allow + + + + Order deny,allow + + + +# Set the authenticated printer/job policies... + + # Job/subscription privacy... + JobPrivateAccess default + JobPrivateValues default + SubscriptionPrivateAccess default + SubscriptionPrivateValues default + + # Job-related operations must be done by the owner or an administrator... + + AuthType Default + Order deny,allow + + + + AuthType Default + Require user @OWNER @SYSTEM + Order deny,allow + + + # All administration operations require an administrator to authenticate... + + AuthType Default + Require user @SYSTEM + Order deny,allow + + + # All printer operations require a printer operator to authenticate... + + AuthType Default + Require user @SYSTEM + Order deny,allow + + + # Only the owner or an administrator can cancel or authenticate a job... + + AuthType Default + Require user @OWNER @SYSTEM + Order deny,allow + + + + Order deny,allow + + diff --git a/RPiSetup/bullseye/etc/drs.conf b/RPiSetup/bullseye/etc/drs.conf new file mode 100644 index 0000000..cc2e90d --- /dev/null +++ b/RPiSetup/bullseye/etc/drs.conf @@ -0,0 +1,25 @@ +# drs.conf + +# URL for OpenDRS +DRS_SERVER="http://localhost" + +# Set to "1" to prevent screen blanking on some monitors that go to sleep and won't wake up. +INHIBIT_BLANK="0" + +# For standard DRS functionality +APP_CMD="chromium-browser --test-type --ignore-certificate-errors --kiosk --no-first-run --check-for-update-interval=1 --simulate-upgrade --incognito $DRS_SERVER" +ALIVE_STRING="chromium-browse" +KILL_CMD="killall chromium-browser" +CLEANUP_CMD="rm -rf ~/.{config,cache}/chromium/" + +# Notes +# --test-type will ignore any warnings and +# --ignore-certificate-errors will allow you to kiosk any https-page without displaying certificate errors + +#----------------------------------------------------------------------- +# For test use +#APP_CMD="xterm" +#ALIVE_STRING="xterm" +#KILL_CMD="killall xterm" +#CLEANUP_CMD="sleep 1" + diff --git a/RPiSetup/bullseye/home/customer/.config/openbox/rc.xml b/RPiSetup/bullseye/home/customer/.config/openbox/rc.xml new file mode 100644 index 0000000..23d96da --- /dev/null +++ b/RPiSetup/bullseye/home/customer/.config/openbox/rc.xml @@ -0,0 +1,695 @@ + + + + + + 10 + 20 + + + + yes + + no + + yes + + no + + 200 + + no + + + + + Smart + +
yes
+ + Primary + + 1 + +
+ + + Clearlooks + NLIMC + + yes + yes + + sans + 8 + + bold + + normal + + + + sans + 8 + + bold + + normal + + + + sans + 9 + + normal + + normal + + + + sans + 9 + + normal + + normal + + + + sans + 9 + + bold + + normal + + + + sans + 9 + + bold + + normal + + + + + + + 1 + 1 + + + + 875 + + + + + yes + Nonpixel + + Center + + + + + 10 + + 10 + + + + + + + 0 + 0 + 0 + 0 + + + + TopLeft + + 0 + 0 + no + Above + + Vertical + + no + 300 + + 300 + + Middle + + + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + true + + + + + + shutdown -P now + + + C-g + + + + 1 + + 500 + + 400 + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + previous + + + next + + + previous + + + next + + + previous + + + next + + + + + + + + + + + + + + no + + + + + + + + + + + yes + + + + + + + + + + + + + + + + + + + + + + + + + client-menu + + + + + + top + + + + + + left + + + + + + right + + + + + + bottom + + + + + + client-menu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + client-menu + + + + + client-menu + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + vertical + + + horizontal + + + + + + + + + + + + + + + + + previous + + + next + + + + previous + + + next + + + previous + + + next + + + + + + + + + + + + + + + + + + + previous + + + next + + + previous + + + next + + + + + + + + + + + +
diff --git a/RPiSetup/bullseye/home/customer/.profile b/RPiSetup/bullseye/home/customer/.profile new file mode 100644 index 0000000..a0d10d7 --- /dev/null +++ b/RPiSetup/bullseye/home/customer/.profile @@ -0,0 +1,23 @@ +# ~/.profile: executed by the command interpreter for login shells. +# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login +# exists. +# see /usr/share/doc/bash/examples/startup-files for examples. +# the files are located in the bash-doc package. + +# the default umask is set in /etc/profile; for setting the umask +# for ssh logins, install and configure the libpam-umask package. +#umask 022 + +# if running bash +if [ -n "$BASH_VERSION" ]; then + # include .bashrc if it exists + if [ -f "$HOME/.bashrc" ]; then + . "$HOME/.bashrc" + fi +fi + +# set PATH so it includes user's private bin if it exists +if [ -d "$HOME/bin" ] ; then + PATH="$HOME/bin:$PATH" +fi +/usr/bin/startx /etc/X11/Xsession /usr/local/bin/startdrs.sh -- :0 diff --git a/RPiSetup/bullseye/lib/systemd/system/getty@tty1.service b/RPiSetup/bullseye/lib/systemd/system/getty@tty1.service new file mode 100644 index 0000000..5e77963 --- /dev/null +++ b/RPiSetup/bullseye/lib/systemd/system/getty@tty1.service @@ -0,0 +1,53 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Getty on %I +Documentation=man:agetty(8) man:systemd-getty-generator(8) +Documentation=http://0pointer.de/blog/projects/serial-console.html +After=systemd-user-sessions.service plymouth-quit-wait.service +After=rc-local.service + +# If additional gettys are spawned during boot then we should make +# sure that this is synchronized before getty.target, even though +# getty.target didn't actually pull it in. +Before=getty.target +IgnoreOnIsolate=yes + +# IgnoreOnIsolate causes issues with sulogin, if someone isolates +# rescue.target or starts rescue.service from multi-user.target or +# graphical.target. +Conflicts=rescue.service +Before=rescue.service + +# On systems without virtual consoles, don't start any getty. Note +# that serial gettys are covered by serial-getty@.service, not this +# unit. +ConditionPathExists=/dev/tty0 + +[Service] +# the VT is cleared by TTYVTDisallocate +ExecStart=-/sbin/agetty -a customer --noclear %I $TERM +Type=idle +Restart=always +RestartSec=0 +UtmpIdentifier=%I +TTYPath=/dev/%I +TTYReset=yes +TTYVHangup=yes +TTYVTDisallocate=yes +KillMode=process +IgnoreSIGPIPE=no +SendSIGHUP=yes + +# Unset locale for the console getty since the console has problems +# displaying some internationalized messages. +Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION= + +[Install] +WantedBy=getty.target +DefaultInstance=tty1 diff --git a/RPiSetup/bullseye/usr/local/bin/cloneuser b/RPiSetup/bullseye/usr/local/bin/cloneuser new file mode 100644 index 0000000..1466f31 --- /dev/null +++ b/RPiSetup/bullseye/usr/local/bin/cloneuser @@ -0,0 +1,28 @@ +#!/bin/bash +SRC=$1 +DEST=$2 + +if [ $# -ne 2 ]; then + echo "Usage: cloneuser source_user destination_user" + exit 1 +fi +if ! grep -q $SRC /etc/passwd ;then echo "Source user doesn't exist!"; exit 1; fi +if grep -q $DEST /etc/passwd ;then echo "Destination user already exists!"; exit 1; fi + +SRC_GROUPS=`id -Gn ${SRC}` +SRC_SHELL=$(awk -F : -v name=${SRC} '(name == $1) { print $7 }' /etc/passwd) +RAND_PW=`date +%s | sha256sum | base64 | head -c 32 ; echo` + +echo "Creating user $DEST with a random password" +useradd --shell ${SRC_SHELL} --password ${RAND_PW} --create-home ${DEST} +for grp in ${SRC_GROUPS};do + if [ "$grp" != "$SRC" ]; then + echo "Adding user $DEST to group $grp." + usermod -a -G $grp ${DEST} + fi +done +echo "Finished. Please set an actual password for $DEST if you want them to be able to log in." + + + + diff --git a/RPiSetup/bullseye/usr/local/bin/rpi-clone b/RPiSetup/bullseye/usr/local/bin/rpi-clone new file mode 100644 index 0000000..61842be --- /dev/null +++ b/RPiSetup/bullseye/usr/local/bin/rpi-clone @@ -0,0 +1,1642 @@ +#!/bin/bash + +version=2.0.20 + +# auto run grub-install if grub detected +grub_auto=1 + +PGM=`basename $0` +setup_command="$PGM-setup" + +rsync_options="--force -rltWDEHXAgoptx" + +if [ `id -u` != 0 ] +then + echo -e "$PGM needs to be run as root.\n" + exit 1 +fi + +confirm() + { + if ((unattended || (initialize && Unattended) )) + then + return 0 + fi + printf "\n%s (yes/no): " "$1" + read resp + if [ "$resp" = "y" ] || [ "$resp" = "yes" ] + then + return 0 + fi + if [ "$2" == "abort" ] + then + echo -e "Aborting!\n" + exit 0 + fi + return 1 + } + +commands="rsync parted fdisk findmnt column fsck.vfat" +packages="rsync parted util-linux mount bsdmainutils dosfstools" +need_packages="" + +idx=1 +for cmd in $commands +do + if ! command -v $cmd > /dev/null + then + pkg=$(echo "$packages" | cut -d " " -f $idx) + printf "%-30s %s\n" "Command not found: $cmd" "Package required: $pkg" + need_packages="$need_packages $pkg" + fi + ((++idx)) +done + +if [ "$need_packages" != "" ] +then + confirm "Do you want to apt-get install the packages?" "abort" + apt-get install -y --no-install-recommends $need_packages +fi + +clone=/mnt/clone +clone_src=/mnt/clone-src +clone_log=/var/log/$PGM.log + +HOSTNAME=`hostname` + + +usage() + { + echo $" +usage: $PGM sdN {-v|--verbose} {-f|--force-initialize} {-f2} + {-u|--unattended} {-U|--Unattended} {-q|--quiet} + {-s|--setup host} {-e|--edit-fstab sdX } {-m|--mountdir dir } + {-L|--label-partitions label} {-l|--leave-sd-usb-boot} + {-a|--all-sync} {-F|--Force-sync} {-x} {-V|--version} + {--convert-fstab-to-partuuid} + + -v - verbose rsync, list all files as they are copied. + -f - force initialize the destination disk by imaging the booted disk + partition structure. File systems are then synced or imaged. + -f2 - force initialize only the first 2 partitions to the destination. + So a multi partition USB boot can initialize clone back to + a 2 partition SD card. + -u - unattended clone if not initializing. No confirmations asked, + but abort if disk needs initializing or on error. + -U - unattended even if initializing. No confirmations asked, + but abort only on errors. + -q - quiet mode, no output unless errors or initializing. Implies -u. + -s host - add 'host' to args passed to script rpi-clone-setup and run it + after cloning but before unmounting partitions. For setting + clone disk hostname, but args can be what the script expects. + You can give multiple "-s arg" options. + -e sdX - edit destination fstab to change booted device names to new + device 'sdX'. This is Only for fstabs that use device names. + Used for setting up a USB bootable disk. + -m dir - Add dir to a custom list of mounted directories to sync. Then + the custom list will be synced instead of the default of all + mounted directories. The root directory is always synced. + Not for when initializing. + -L lbl - label for ext type partitions. If ends with '#', replace with + partition number and label all ext partitions. Otherwise, + apply label to root partition only. + -l - leave SD card to USB boot alone when cloning to SD card mmcblk0 + from a USB boot. This preserves a SD card to USB boot setup + by leaving the SD card cmdline.txt using the USB root. When + cloning to USB from SD card this option sets up the SD card + cmdline.txt to boot to the USB disk. + -a - Sync all partitions if types compatible, not just mounted ones. + -F - force file system sync even if errors. + If source used > destination space error, do the sync anyway. + If a source partition mount error, skip it and do other syncs. + -x - use set -x for very verbose bash shell script debugging + -V - print rpi-clone version. + + Clone a booted file system to a destination disk which is bootable. + + The destination disk is a SD card (USB card reader) or USB disk 'sdN' plugged + into a USB port. The 'sdN' name should be a full disk name like sda and not + a partition name like sda1. $PGM works on a Raspberry Pi and can work on + other systems. For a destination disk that shows up as sda, run: + + $ sudo rpi-clone sda + + Clones can be from a booted SD card or USB disk. For a description, example + clone runs and example usage of above options, see the README.md at: + + https://github.com/billw2/rpi-clone + + A line logging a $PGM run is written to $clone_log. + + Download: + git clone https://github.com/billw2/rpi-clone +" + exit 1 + } + +readable() + { + val=$1 + if [ "$val" == "" ] + then + result=" ??" + else + blk_size=$2 + val=$((val / 1000 * blk_size)) + + if ((val < 1000000)) + then + result=$(echo $val \ + | awk '{ byte =$1 /1000; printf "%.1f%s", byte, "MB" }') + elif ((val < 1000000000)) + then + result=$(echo $val \ + | awk '{ byte =$1 /1000/1000; printf "%.1f%s", byte, "GB" }') + else + result=$(echo $val \ + | awk '{ byte =$1 /1000/1000/1000; printf "%.1f%s", byte, "TB" }') + fi + fi + printf -v "${3}" "%s" "$result" + } + +qecho() + { + if ((!quiet)) + then + echo "$@" + fi + } + +qprintf() + { + if ((!quiet)) + then + printf "$@" + fi + } + +unmount_or_abort() + { + if [ "$1" == "" ] + then + return + fi + qprintf "\n $2\n The clone cannot proceed unless it is unmounted." + + if confirm "Do you want to unmount $1?" "abort" + then + if ! umount $1 + then + echo "$PGM could not unmount $1." + echo -e "Aborting!\n" + exit 0 + fi + fi + } + +unmount_list() + { + if [ "$1" == "" ] + then + return + fi + for dir in $1 + do + qecho " unmounting $dir" + if ! umount $dir + then + qecho " Failed to unmount: $dir" + fi + done + } + +mount_partition() + { + qecho " Mounting $1 on $2" + + if ! mount $1 $2 + then + echo " Mount failure of $1 on $2." + if [ "$3" != "" ] + then + unmount_list $3 + fi + echo "Aborting!" + exit 1 + fi + } + +rsync_file_system() + { + src_dir="$1" + dst_dir="$2" + + qprintf " => rsync $1 $2 $3 ..." + + if [ "$3" == "with-root-excludes" ] + then + rsync $rsync_options --delete \ + $exclude_swapfile \ + --exclude '.gvfs' \ + --exclude '/dev/*' \ + --exclude '/mnt/clone/*' \ + --exclude '/proc/*' \ + --exclude '/run/*' \ + --exclude '/sys/*' \ + --exclude '/tmp/*' \ + --exclude 'lost\+found/*' \ + $src_dir \ + $dst_dir + else + rsync $rsync_options --delete \ + --exclude '.gvfs' \ + --exclude 'lost\+found/*' \ + $src_dir \ + $dst_dir + fi + qecho "" + } + +print_partitions() + { + if ((quiet)) && ((!initialize)) + then + return + fi + n_parts=$(( (n_src_parts >= n_dst_parts) ? n_src_parts : n_dst_parts )) + + readable $src_disk_size "512" src_size_readable + readable $dst_disk_size "512" dst_size_readable + + printf "\n%-43s%s" "Booted disk: $src_disk $src_size_readable" \ + "Destination disk: $dst_disk $dst_size_readable" + echo $" +---------------------------------------------------------------------------" + out=$'Part, Size,FS,Label ,Part, Size,FS,Label\n' + for ((p = 1; p <= n_parts; p++)) + do + if ((p <= n_src_parts && src_exists[p])) + then + readable ${src_size_sectors[p]} "512" tmp + printf -v sectors_readable "%7s" $tmp + pname="$p ${src_name[p]}" + out=${out}$"$pname,$sectors_readable,${src_fs_type[p]},${src_label[p]}," + else + out=${out}$" , , , ," + fi + + if ((p <= n_dst_parts && dst_exists[p])) + then + readable ${dst_size_sectors[p]} "512" tmp + printf -v sectors_readable "%7s" $tmp + out=${out}$"$p,$sectors_readable,${dst_fs_type[p]},${dst_label[p]}," + else + out=${out}$" , , , ," + fi + out=${out}$'\n' + done + + echo $"$out" | column -t -s ',' + + if ((alt_root_part_num > 0)) + then + echo $" +** Assuming destination root partition for the clone is $dst_part_base$root_part_num + The root FS mount is not from booted $src_disk. It is ${src_root_dev#/dev/}" + + fi + echo $"---------------------------------------------------------------------------" + } + +print_sync_actions() + { + if ((quiet)) + then + return + fi + for ((p = 1; p <= n_src_parts; p++)) + do + if ((!src_exists[p])) + then + continue + fi + if ((p == root_part_num && alt_root_part_num > 0)) + then + part=${src_root_dev#/dev/} + flow="$part to $dst_part_base$p" + else + flow="to $dst_part_base$p" + fi + if ((src_sync_part[p])) + then + readable ${src_used_sectors[p]} "512" used + readable ${dst_size_sectors[p]} "512" size + printf "%-22s%-14s : SYNC %s\n" \ + "${src_mounted_dir[p]}" "(${used} used)" \ + "$flow (${size} size)" + fi + done + } + +print_image_actions() + { + for ((p = 1; p <= n_src_parts; p++)) + do + if ((!src_exists[p])) + then + continue + fi + pname="$p ${src_name[p]}" + fs_type=${src_fs_type[$p]} + + if ((p == root_part_num && alt_root_part_num > 0)) + then + part=${src_root_dev#/dev/} + flow="$part to $dst_part_base$p" + else + flow="to $dst_part_base$p" + fi + + action="" + if ((p <= n_image_parts)) + then + if [ "${src_mounted_dir[p]}" == "/boot" ] && ((p == 1)) + then + action="IMAGE $flow FSCK" + elif [ "$fs_type" == "swap" ] + then + action="MKSWAP" + elif ((p != ext_part_num)) + then + if [ "${src_mounted_dir[p]}" != "" ] || ((p == n_src_parts)) + then + if ((p < n_src_parts || last_part_space || force_sync)) + then + action="MKFS SYNC $flow" + else + action="MKFS **NO SYNC**" + fi + else + action="IMAGE $flow" + fi + fi + fi + + if ((p == n_image_parts)) + then + readable ${src_used_sectors[n_image_parts]} "512" used + printf "%-22s%-14s : RESIZE($image_space_readable) %s\n" \ + "$pname" "(${used} used)" "$action" + elif ((src_used_sectors[$p] > 0 && p < n_image_parts)) + then + readable ${src_used_sectors[p]} "512" used + printf "%-22s%-14s : $action\n" "$pname" "(${used} used)" + elif [ "$action" != "" ] + then + printf "%-36s : $action\n" "$pname" + fi + done + } + +print_options() + { + if ((quiet)) + then + return + fi + echo $"---------------------------------------------------------------------------" + + if ((force_2_parts)) + then + printf "%-22s : %s\n" "-f2" \ + "force initialize to first two partitions only" + fi + if [ "$edit_fstab_name" != "" ] + then + printf "%-22s : %s\n" "-e clone fstab edit" \ + "edit $src_part_base device entries to $edit_fstab_name" + fi + if [ "$ext_label" != "" ] + then + rep="${ext_label: -1}" + if [ "$rep" == "#" ] + then + msg="all ext partition types" + else + msg="root partition only" + fi + printf "%-22s : %s\n" "-L $ext_label" \ + "volume label for $msg." + fi + if ((leave_sd_usb_boot)) + then + if ((SD_slot_dst)) + then + msg="leave SD card cmdline.txt bootable to USB" + elif ((SD_slot_boot)) + then + msg="install boot to USB cmdline.txt on SD card" + else + msg="-l ignored. Src or dst is not a SD card slot." + fi + printf "%-22s : %s\n" "-l SD to USB boot mode" "$msg" + fi + if [ "$setup_args" != "" ] + then + printf "%-22s : %s\n" "Run setup script" "$setup_command $setup_args" + else + printf "%-22s : no\n" "Run setup script" + fi + if ((have_grub)) + then + printf "%-22s : %s\n" "Run grub" \ + "grub-install --root-directory=$clone /dev/$dst_disk" + fi + printf "%-22s : %s\n" "Verbose mode" "$verbose" + printf "%-23s:\n" "-----------------------" + } + +ext_label() + { + pnum=$1 + fs_type=$2 + flag=$3 + label_arg="" + + if [ "$ext_label" != "" ] && [[ "$fs_type" == *"ext"* ]] + then + rep="${ext_label: -1}" + if [ "$rep" == "#" ] + then + label_arg=${ext_label:: -1} + label_arg="$flag $label_arg$pnum" + elif ((pnum == root_part_num)) + then + label_arg="$flag $ext_label" + fi + fi + printf -v "${4}" "%s" "$label_arg" + } + +get_src_disk() + { + partition=${1#/dev/} + disk=${partition:: -1} + num="${partition: -1}" + if [[ $disk == *"mmcblk"* ]] + then + SD_slot_boot=1 + disk=${disk:0:7} + src_part_base=${disk}p + fi + printf -v "${2}" "%s" "$disk" + printf -v "${3}" "%s" "$num" + } + + +# ==== source (booted) disk info and default mount list +# +src_boot_dev=`findmnt /boot -o source -n` +src_root_dev=`findmnt / -o source -n` +SD_slot_boot=0 +SD_slot_dst=0 +src_part_base="" + +boot_part_num=0 +alt_root_part_num=0 + + +if [ "$src_boot_dev" == "" ] +then + get_src_disk "$src_root_dev" "src_disk" "unused" +else + get_src_disk "$src_boot_dev" "src_disk" "boot_part_num" +fi + +get_src_disk "$src_root_dev" "src_root_disk" "root_part_num" + +if [ "$src_disk" == "" ] +then + echo "Cannot find booted device." + exit 1 +fi + +if [ "$src_part_base" == "" ] +then + src_part_base=$src_disk +fi + +if [ "$src_disk" != "$src_root_disk" ] +then + if ((SD_slot_boot)) + then + # Handle SD card boots with root on different USB disk device. + # But will assume SD card has a root partition just above its root. + # + alt_root_part_num="$root_part_num" + root_part_num=$((boot_part_num + 1)) + else + echo $" +Boot and root are on different disks and it's not a SD card boot. +Don't know how to partition the destination disk!" + exit 1 + fi +fi + +# src_root_dev, if on device other than booted, is not in src_partition_table +# and src_fdisk_table, but is in src_df_table and src_mount_table +# +src_partition_table=$(parted -m "/dev/$src_disk" unit s print | tr -d ';') +src_fdisk_table=$(fdisk -l /dev/$src_disk | grep "^/dev/") + +tmp=$(df | grep -e "^/dev/$src_disk" -e "^/dev/root" -e "$src_root_dev" \ + | tr -s " ") +dev=${src_root_dev#/dev/} +src_df_table=$(echo "$tmp" | sed "s/root/$dev/") + +n_src_parts=$(echo "$src_partition_table" | tail -n 1 | cut -d ":" -f 1) +src_disk_size=$(echo "$src_partition_table" \ + | grep "^/dev/$src_disk" | cut -d ":" -f 2 | tr -d 's') + +line=$(fdisk -l /dev/$src_disk | grep "Disk identifier:") +src_disk_ID=${line#*x} + +src_mount_table=$(findmnt -o source,target -n -l \ + | grep -e "^/dev/$src_disk" -e "^$src_root_dev" | tr -s " ") +n_mounts=$(echo "$src_mount_table" | wc -l) + +if ((alt_root_part_num > 0 && n_src_parts < 2)) +then + echo $" +Booted disk has only one partition and the root is from another device. +Don't know how to partition the destination disk! +" + exit 1 +fi + + +line=$(echo "$src_fdisk_table" | grep "Extended") +if [ "$line" != "" ] +then + dev=$(echo "$line" | cut -d " " -f 1) + ext_part_num="${dev: -1}" +else + ext_part_num=0 +fi + + +for ((p = 1; p <= n_src_parts; p++)) +do + line=$(echo "$src_partition_table" | grep -e "^${p}:") + if [ "$line" == "" ] + then + src_exists[p]=0 + continue + fi + src_exists[p]=1 + + if ((p == root_part_num)) + then + src_partition[p]=${src_root_dev#/dev/} + src_device[p]=$src_root_dev + else + src_partition[p]="${src_part_base}${p}" + src_device[p]="/dev/${src_partition[p]}" + fi + + # parted sectors are 512 bytes + src_start_sector[p]=$(echo "$line" | cut -d ":" -f 2 | tr -d 's') + src_size_sectors[p]=$(echo "$line" | cut -d ":" -f 4 | tr -d 's') + + part_type=$(echo "$line" | cut -d ":" -f 5) + + src_mounted_dir[p]=$(echo "$src_mount_table" \ + | grep -m 1 -e "^${src_device[p]}" | cut -d " " -f 2) + if [ "${src_mounted_dir[p]}" != "" ] + then + src_sync_part[p]=1 + else + src_sync_part[p]=0 + fi + + src_name[p]="" + if [ "$part_type" != "" ] + then + src_fs_type[p]="$part_type" + else + src_fs_type[p]="--" + fi + src_label[p]="--" + + if [ "${src_mounted_dir[p]}" == "/" ] + then + src_name[p]="root" + # + # If root on device other than booted SD card, root_part_num assumed to be + # booted /boot part_num + 1 and alt_root_part_num is from root device. + # + elif ((p == root_part_num)) && ((alt_root_part_num > 0)) + then + src_name[p]="root**" + elif ((p == ext_part_num)) + then + src_fs_type[p]="EXT" + elif [[ "$part_type" == *"linux-swap"* ]] + then + src_fs_type[p]="swap" + elif [ "${src_mounted_dir[p]}" != "" ] + then + src_name[p]="${src_mounted_dir[p]}" + fi + + if [[ "$part_type" == *"ext"* ]] + then + label=`e2label ${src_device[p]} 2> /dev/null` + if [ "$label" != "" ] + then + src_label[p]="$label" + fi + fi +done + + +# command line +# +setup_args="" +edit_fstab_name="" +ext_label="" +verbose="no" + +force_initialize=0 +force_2_parts=0 +force_sync=0 +all_sync=0 +usage_error=0 +unattended=0 +Unattended=0 +quiet=0 +custom_sync=0 +leave_sd_usb_boot=0 +convert_to_partuuid=0 + +while [ "$1" ] +do + case "$1" in + -v|--verbose) + verbose="yes" + rsync_options=${rsync_options}v + ;; + -u|--unattended) + unattended=1 + ;; + -U|--Unattended-init) + unattended=1 + Unattended=1 + ;; + -q|--quiet) + unattended=1 + quiet=1 + rsync_options=${rsync_options}q + ;; + -s|--setup) + shift + if ! command -v $setup_command > /dev/null + then + echo "Cannot find script $setup_command for setup arg \"$1\"." + usage_error=1 + fi + if [ "$setup_args" == "" ] + then + setup_args="$1" + else + setup_args="$setup_args $1" + fi + ;; + -e|--edit-fstab) + shift + edit_fstab_name=$1 + ;; + -f|--force-initialize) + force_initialize=1 + ;; + -f2) + force_initialize=1 + force_2_parts=1 + ;; + -x) + set -x + ;; + -a|--all-sync) + all_sync=1 + ;; + -m|--mountdir) + shift + mount_ok=0 + for ((p = 1; p <= n_src_parts; p++)) + do + if ((!src_exists[p])) + then + continue + fi + if ((!custom_sync)) && ((p != root_part_num)) + then + src_sync_part[p]=0 + fi + if [ "${src_mounted_dir[p]}" == "$1" ] + then + src_sync_part[p]=1 + mount_ok=1 + fi + done + if ((!mount_ok)) + then + echo "Asking to clone directory \"$1\", but it is not mounted." + usage_error=1 + fi + custom_sync=1 + ;; + -L|--label_partitions) + shift + ext_label=$1 + ;; + -l|--leave-sd-usb-boot) + leave_sd_usb_boot=1 + ;; + -F|--Force-sync) + force_sync=1 + ;; + --convert-fstab-to-partuuid) + convert_to_partuuid=1 + ;; + -V|--version) + echo $PGM Version: $version + exit 0 + ;; + -h|--help) + usage + ;; + *) + if [ "$dst_disk" != "" ] + then + echo "Bad args" + usage + fi + dst_disk=$1 + dir=`expr substr $dst_disk 1 5` + if [ "$dir" == "/dev/" ] + then + dst_disk=${dst_disk#/dev/} + fi + ;; + esac + shift +done + +if ((custom_sync)) && ((all_sync)) +then + echo "-m and -a options at the same time conflict." + exit 1 +fi +if ((custom_sync)) && ((force_initialize)) +then + echo "-m and -f options at the same time conflict." + exit 1 +fi +if [[ "$verbose" == "yes" ]] && ((quiet)) +then + echo "-q and -v options at the same time conflict." + exit 1 +fi + +if ((usage_error)) +then + echo "" + exit 1 +fi + +if ((convert_to_partuuid)) +then + unattended=0 + Unattended=0 + + fstab=/etc/fstab + fstab_tmp=/tmp/fstab + fstab_save=${fstab}.${PGM}-save + confirm "This will change your $fstab, are you sure?" "abort" + + cp $fstab $fstab_tmp + printf "\nConverting $fstab from device names to PARTUUID\n" + count=0 + for ((p = 1; p <= n_src_parts; p++)) + do + if grep -q "^/dev/${src_partition[p]}" $fstab_tmp + then + partuuid=$(lsblk -n -o PARTUUID /dev/${src_partition[p]}) + sed -i "s/\/dev\/${src_partition[p]}/PARTUUID=$partuuid/" $fstab_tmp + printf " Editing $fstab, changing /dev/${src_partition[p]} to $partuuid\n" + ((++count)) + fi + done + if ((count)) + then + cp $fstab $fstab_save + cp $fstab_tmp $fstab + printf "Your original fstab is backed up to $fstab_save\n" + + cmdline_txt=/boot/cmdline.txt + cmdline_save=$cmdline_txt.${PGM}-save + if [ -f $cmdline_txt ] && grep -q "$src_root_dev" $cmdline_txt + then + root_part=${src_partition[root_part_num]} + partuuid=$(lsblk -n -o PARTUUID $src_root_dev) + if [ "$partuuid" != "" ] + then + cp $cmdline_txt $cmdline_save + sed -i "s/\/dev\/$root_part/PARTUUID=$partuuid/" $cmdline_txt + printf " Editing $cmdline_txt, changing root=$src_root_dev to root=PARTUUID=$partuuid\n" + printf "Your original cmdline.txt is backed up to $cmdline_save\n" + fi + fi + else + printf "Could not find any $src_disk partition names in $fstab, nothing changed.\n" + fi + rm $fstab_tmp + echo "" + exit 0 +fi + +# dst_mount_flag enumerations: +live=1 +temp=2 +fail=3 + +for ((p = 1; p <= n_src_parts; p++)) +do + if ((!src_exists[p])) + then + continue + fi + blocks=0 + dst_mount_flag[p]=0 + + if [ "${src_mounted_dir[p]}" != "" ] + then # df blocks are 1024 bytes + dst_mount_flag[p]=$live + blocks=$(echo "$src_df_table" \ + | grep -m 1 "^${src_device[p]}" | cut -d " " -f 3) + # in case intializing, get n_src_parts to compare to dest space + elif ((p == n_src_parts)) \ + || ((all_sync)) \ + && [ "${src_fs_type[p]}" != "EXT" ] \ + && [ "${src_fs_type[p]}" != "swap" ] \ + && [ "${src_fs_type[p]}" != "" ] + then + if mount ${src_device[p]} $clone + then + sleep 1 + blocks=$(df | grep "^${src_device[p]}" \ + | tr -s " " | cut -d " " -f 3) + umount $clone + dst_mount_flag[p]=$temp + if ((all_sync)) + then + src_sync_part[p]=1 + fi + else + dst_mount_flag[p]=$fail + fi + fi + src_used_sectors[p]=$((blocks * 2)) +done + +# ==== destination disk checks +# +if [ "$dst_disk" = "" ] +then + echo "No destination disk given." + usage +fi + +chk_disk=`cat /proc/partitions | grep -m 1 $dst_disk` + +if [ "$chk_disk" == "" ] +then + echo $" + Cannot find '$dst_disk' in the partition table. The partition table is:" + cat /proc/partitions + exit 1 +fi + +dst_part_base=$dst_disk + +if [[ ${chk_disk: -1} =~ ^[0-9]$ ]] +then + if [[ $dst_disk == *"mmcblk"* ]] + then + SD_slot_dst=1 + dst_part_base=${dst_disk}p + if [ "$edit_fstab_name" == "" ] \ + && ! grep -q "^PARTUUID=" /etc/fstab + then + edit_fstab_name=$dst_part_base + assumed_fstab_edit=1 + else + assumed_fstab_edit=0 + fi + else + qecho $" + Target disk $dst_disk ends with a digit so may be a partition. + $PGM requires disk names like 'sda' and not partition names like 'sda1'." + + confirm "Continue anyway?" "abort" + fi +fi + +if [ "$src_disk" == "$dst_disk" ] +then + echo "Destination disk $dst_disk is the booted disk. Cannot clone!" + exit 1 +fi + +dst_partition_table=$(parted -m "/dev/$dst_disk" unit s print | tr -d ';') +n_dst_parts=$(echo "$dst_partition_table" | tail -n 1 | cut -d ":" -f 1) +if [ "$n_dst_parts" == "/dev/$dst_disk" ] +then + n_dst_parts=0 +fi + +dst_disk_size=$(echo "$dst_partition_table" \ + | grep "^/dev/$dst_disk" | cut -d ":" -f 2 | tr -d 's') +dst_root_dev=/dev/${dst_part_base}${root_part_num} + +dst_mount_table=$(findmnt -o source,target -n -l \ + | grep "^/dev/$dst_disk" | tr -s " ") + +dst_fdisk_table=$(fdisk -l /dev/$dst_disk | grep "^/dev/") +line=$(echo "$dst_fdisk_table" | grep "Extended") +if [ "$line" != "" ] +then + dev=$(echo "$line" | cut -d " " -f 1) + ext_num="${dev: -1}" +else + ext_num=0 +fi + +for ((p = 1; p <= n_dst_parts; p++)) +do + line=$(echo "$dst_partition_table" | grep -e "^${p}:") + if [ "$line" == "" ] + then + dst_exists[p]=0 + continue + fi + dst_exists[p]=1 + + part="${dst_part_base}${p}" + dst_partition[p]="$part" + dst_device[p]="/dev/$part" + + dst_start_sector[p]=$(echo "$line" | cut -d ":" -f 2 | tr -d 's') + dst_size_sectors[p]=$(echo "$line" | cut -d ":" -f 4 | tr -d 's') + + part_type=$(echo "$line" | cut -d ":" -f 5) + if [ "$part_type" != "" ] + then + dst_fs_type[p]="$part_type" + else + dst_fs_type[p]="--" + fi + dst_label[p]="--" + + if [[ "$part_type" == *"linux-swap"* ]] + then + dst_fs_type[p]="swap" + elif [[ "$part_type" == *"ext"* ]] + then + label=`e2label ${dst_device[p]} 2> /dev/null` + if [ "$label" != "" ] + then + dst_label[p]="$label" + fi + elif ((p == ext_num)) + then + dst_fs_type[p]="EXT" + fi +done + +fs_match=1 +root_part_match=0 +first_part_mismatch=0 + +initialize=$((force_initialize)) + +for ((p = 1; p <= n_src_parts; p++)) +do + if ((!src_exists[p])) + then + continue + fi + stype=${src_fs_type[p]} + dtype=${dst_fs_type[p]} + if [ "$stype" != "$dtype" ] + then + tmp_match=0 + if [[ "$stype" == *"fat"* ]] && [[ "$dtype" == *"fat"* ]] + then + tmp_match=1 + elif [[ "$stype" == *"ext"* ]] && [[ "$dtype" == *"ext"* ]] + then + tmp_match=1 + fi + if ((tmp_match && p == root_part_num)) + then + root_part_match=1 + fi + if ((!tmp_match)) && ((src_sync_part[p])) + then + first_part_mismatch=$p + fs_match=0 + break + fi + fi +done + + +if ((!fs_match)) +then + initialize=1 + fs_match_string="do not match" +else + fs_match_string="OK, they match" +fi + +if ((initialize)) && ((quiet)) +then + echo "Quiet mode asked for but an initialize is required - can't clone!" + exit 1 +fi + +for ((p = n_dst_parts; p >= 1; --p)) +do + if ((!dst_exists[p])) + then + continue + fi + dir=$(echo "$dst_mount_table" \ + | grep -e "^${dst_device[p]}" | cut -d " " -f 2) + unmount_or_abort "$dir" \ +"Destination disk partition ${dst_device[p]} is mounted on $dir." +done + +mounted_dev=$(findmnt $clone -o source -n) +unmount_or_abort "$mounted_dev" \ + "Directory $clone is already mounted with $mounted_dev." + +mounted_dev=$(findmnt $clone_src -o source -n) +unmount_or_abort "$mounted_dev" \ + "Directory $clone_src is already mounted with $mounted_dev." + +mounted_dev=$(findmnt /mnt -o source -n) +unmount_or_abort "$mounted_dev" "$mounted_dev is currently mounted on /mnt." + + +if [ ! -d $clone ] +then + mkdir $clone +fi +if [ ! -d $clone_src ] +then + mkdir $clone_src +fi + +# Do not include a dhpys swapfile in rsync. It regenerates at boot. +# +if [ -f /etc/dphys-swapfile ] +then + swapfile=`cat /etc/dphys-swapfile | grep ^CONF_SWAPFILE | cut -f 2 -d=` + if [ "$swapfile" = "" ] + then + swapfile=/var/swap + fi + exclude_swapfile="--exclude $swapfile" +fi + +if ((grub_auto)) && [ -d /boot/grub ] && command -v grub-install +then + have_grub=1 +else + have_grub=0 +fi + +print_partitions + +if ((initialize)) +then + if ((unattended && !Unattended)) + then + echo $" +Unattended -u option not allowed when initializing. +Use -U for unattended even if initializing. +" + exit 1 + fi + + reason="FS types mismatch" + if ((force_initialize)) + then + reason="forced by option" + fi + + n_image_parts=$((force_2_parts ? 2 : n_src_parts)) + + start_sector=${src_start_sector[$n_image_parts]} + last_part_sectors=$((dst_disk_size - start_sector)) + last_part_used=${src_used_sectors[$n_image_parts]} + last_part_space=$(( (last_part_sectors > last_part_used) ? 1 : 0 )) + + if ((last_part_sectors < 7812)) + then + printf "%-22s : %s\n" "** FATAL **" \ + "Initialize required - $reason." + printf "%-22s : %s\n" "" \ + " But destination is too small. To image partition" + readable $((start_sector + 7812)) "512" min_size + printf "%-22s : %s\n" "" \ + " source sizes, minimum destination size is $min_size." + if ((n_src_parts > 2)) + then + printf "%-22s : %s\n" " " \ + " Options: try a two partition clone with -f2, or" + printf "%-22s : %s\n" " " \ + " manually create custom partitions that can work." + fi + printf "%-23s:\n" "-----------------------" + exit 1 + fi + + readable $((last_part_sectors + 7812)) "512" image_space_readable + + echo "== Initialize: IMAGE $src_disk partition table to $dst_disk - $reason ==" + print_image_actions + print_options + + printf "%-22s : %s\n" "** WARNING **" \ + "All destination disk $dst_disk data will be overwritten!" + printf "%-22s : %s\n" "" \ + " The partition structure will be imaged from $src_disk." + + abort=0 + if ((!last_part_space)) + then + readable $last_part_used "512" used_readable + printf "%-22s : %s\n" "** WARNING **" \ + "Destination last partition resize to $image_space_readable" + printf "%-22s : %s\n" "" \ + " is too small to hold source used $used_readable." + if [ "$n_image_parts" == "$root_part_num" ] && ((!force_sync)) + then + printf "%-22s : %s\n" "** FATAL **" \ + "This is the root partition, so aborting!" + printf "%-22s : %s\n" "" \ + " Use -F to override." + abort=1 + elif ((!force_sync)) + then + printf "%-22s : %s\n" "" \ + " The partition SYNC is skipped, use -F to override." + else + printf "%-22s : %s\n" "" \ + " ** Syncing anyway as you asked with -F. **" + fi + fi + printf "%-23s:\n" "-----------------------" + if ((abort)) + then + exit 1 + fi + confirm "Initialize and clone to the destination disk ${dst_disk}?" "abort" + + if ((!Unattended)) && [ "$ext_label" == "" ] + then + printf "Optional destination ext type file system label (16 chars max): " + read ext_label + fi + + start_time=`date '+%H:%M:%S'` + start_sec=$(date '+%s') + + if [ "${src_mounted_dir[1]}" == "/boot" ] + then + image_to_part=2 + msg="/boot" + else + image_to_part=1 + msg="first" + fi + image_to_sector=${src_start_sector[$image_to_part]} + count=$((image_to_sector / 2 / 1024 + 4)) # in MiB blocks for dd bs=1M + + printf "\nInitializing\n" + printf " Imaging past the start of $msg partition $image_to_part.\n" + sync + printf " => dd if=/dev/$src_disk of=/dev/$dst_disk bs=1M count=$count ..." + dd if=/dev/$src_disk of=/dev/$dst_disk bs=1M count=$count &> /tmp/$PGM-output + if [ "$?" != 0 ] + then + printf "\n dd failed. See /tmp/$PGM-output.\n" + printf " Try running $PGM again.\n\n" + exit 1 + fi + echo "" + sync + sleep 1 + sfd0=$(sfdisk -d /dev/$src_disk) + if ((force_2_parts && (n_src_parts > n_image_parts))) + then + remove_part_start=${src_partition[3]} + sfd0=$(echo "$sfd0" | sed -e "/\/dev\/$remove_part_start/,\$d") + fi + + part="${src_part_base}$n_image_parts" + sfd1=$(echo "$sfd0" | sed "\/dev\/$part/s/size=[^,]*,//") + + if ((ext_part_num > 0 && !force_2_parts)) + then + part="${src_part_base}$ext_part_num" + sfd1=$(echo "$sfd1" | sed "\/dev\/$part/s/size=[^,]*,//") + fi + + printf " Resizing last partition to end of disk ..." + for ((x = 0; x < 3; ++x)) + do + sleep $((x + 1)) + sfdisk --force /dev/$dst_disk &> /tmp/$PGM-output <<< "$sfd1" + if [ "$?" == 0 ] + then + break + fi + if ((x == 2)) + then + printf "\n====$PGM\n==orig:\n%s\n\n==edited:\n%s\n" \ + "$sfd0" "$sfd1" >> /tmp/$PGM-output + printf "\n Resize failed. See /tmp/$PGM-output.\n" + printf " Try running $PGM again.\n\n" + + # Don't let dst disk keep source disk ID. Can lead to remounts. + new_id=$(od -A n -t x -N 4 /dev/urandom | tr -d " ") + qprintf "x\ni\n0x$new_id\nr\nw\nq\n" | fdisk /dev/$dst_disk > /dev/null + exit 1 + fi + done + printf "\n Resize success.\n" + printf " Changing destination Disk ID ..." + sync + sleep 2 + + new_id=$(od -A n -t x -N 4 /dev/urandom | tr -d " ") + qprintf "x\ni\n0x$new_id\nr\nw\nq\n" | fdisk /dev/$dst_disk > /dev/null + printf "\n Delaying so partprobe can update /dev entries ..." + sync + sleep 2 + partprobe "/dev/$dst_disk" + sleep 2 + echo "" + + for ((p = n_image_parts + 1; p <= n_src_parts; p++)) + do + src_sync_part[p]=0 + done + + for ((p = 1; p <= n_image_parts; p++)) + do + if ((!src_exists[p])) + then + continue + fi + dst_dev=/dev/${dst_part_base}${p} + fs_type=${src_fs_type[$p]} + if ((p == ext_part_num)) \ + || [ "$fs_type" == "--" ] + then + continue + fi + + if [ "${src_mounted_dir[p]}" == "/boot" ] && ((p == 1)) + then + # Avoid "Volume not properly unmounted" warnings. + printf " => fsck -p $dst_dev ..." + fsck -p $dst_dev &>> /tmp/$PGM-log + echo "" + ext_label $p $fs_type "" label + if [ "$label" != "" ] + then + e2label $dst_dev $label + fi + else + if [ "$fs_type" == "swap" ] + then + printf " => mkswap $dst_dev\n" + mkswap $dst_dev &>> /tmp/$PGM-log + elif ((p != ext_part_num)) + then + if [ "${src_mounted_dir[p]}" != "" ] || ((p == n_image_parts)) + then + if [ "$fs_type" == "fat16" ] + then + fs_type="vfat" + elif [ "$fs_type" == "fat32" ] + then + fs_type="vfat -F 32" + fi + ext_label $p $fs_type "-L" label + printf " => mkfs -t $fs_type $label $dst_dev ..." + yes | mkfs -t "$fs_type" $label "$dst_dev" &>> /tmp/$PGM-output +# mkfs -t "$fs_type" "$dst_dev" &>> /tmp/$PGM-output <<< "yes" + echo "" + if ((p == n_image_parts)) + then + if ((!last_part_space)) + then + src_sync_part[p]=$force_sync + else + src_sync_part[p]=1 + fi + fi + else + printf " => dd if=${src_device[$p]} of=$dst_dev bs=1M ..." + dd if=${src_device[$p]} of=$dst_dev bs=1M &>> /tmp/$PGM-output + if [ "$?" != 0 ] + then + printf "\n dd failed. See /tmp/$PGM-output.\n" + else + echo "" + fi + ext_label $p $fs_type "" label + if [ "$label" != "" ] + then + echo " e2label $dst_dev $label" + e2label $dst_dev $label + fi + fi + fi + fi + done + ext_label="" +else + qecho "== SYNC $src_disk file systems to $dst_disk ==" + print_sync_actions + print_options + + informed=0 + space_ok=1 + all_sync_mount_ok=1 + if ((force_sync)) + then + err="WARNING" + else + err="FATAL" + fi + for ((p = 1; p <= n_src_parts; p++)) + do + if ((!src_exists[p] || !dst_exists[p])) + then + continue + fi + if ((${dst_size_sectors[p]} < ${src_used_sectors[p]})) \ + && ((src_sync_part[p])) + then + qprintf "%-22s : %s\n" "** $err **" \ + "Partition $p: source used > destination space." + space_ok=$force_sync + informed=1 + fi + if ((all_sync && dst_mount_flag[p] == fail)) + then + qprintf "%-22s : %s\n" "** $err **" \ + "Partition $p: mount failed, cannot sync." + all_sync_mount_ok=$force_sync + informed=1 + fi + done + if ((informed)) + then + qprintf "%-23s:\n" "-----------------------" + fi + + if ((!space_ok || !all_sync_mount_ok)) + then + printf "\nAborting!\n" + if ((!space_ok)) + then + printf " Use -F to override used > space fail or -m to select mounts to clone.\n" + fi + if ((!all_sync_mount_ok)) + then + printf " Use -a -F to sync all except failed mounts.\n" + fi + exit 1 + fi + + confirm "Ok to proceed with the clone?" "abort" + start_time=`date '+%H:%M:%S'` + start_sec=$(date '+%s') +fi + +line=$(fdisk -l /dev/$dst_disk | grep "Disk identifier:") +dst_disk_ID=${line#*x} +if [ "$dst_disk_ID" == "$src_disk_ID" ] +then + qecho "Destination disk has same Disk ID as source, changing it." + new_id=$(od -A n -t x -N 4 /dev/urandom | tr -d " ") + qprintf "x\ni\n0x$new_id\nr\nw\nq\n" | fdisk /dev/$dst_disk | grep changed + sync + sleep 2 + partprobe "/dev/$dst_disk" + sleep 2 + + line=$(fdisk -l /dev/$dst_disk | grep "Disk identifier:") + dst_disk_ID=${line#*x} + if [ "$dst_disk_ID" == "$src_disk_ID" ] + then + qecho " Failed to set a new Disk ID." + fi +fi + +sync +qprintf "\nSyncing file systems (can take a long time)\n" + +sync_msg_done=0 +for ((p = 1; p <= n_src_parts; p++)) +do + if ((!src_exists[p])) + then + continue + fi + if ((src_sync_part[p] && dst_mount_flag[p] == temp)) + then + if ((!sync_msg_done)) + then + qprintf "Syncing unmounted partitions:\n" + fi + sync_msg_done=1 + dst_dev=/dev/${dst_part_base}${p} + fs_type=${src_fs_type[$p]} + ext_label $p $fs_type "" label + if [ "$label" != "" ] + then + qecho " e2label $dst_dev $label" + e2label $dst_dev $label + fi + + mount_partition ${src_device[p]} $clone_src "" + mount_partition $dst_dev $clone "$clone_src" + unmount_list="$clone_src $clone" + rsync_file_system "${clone_src}/" "${clone}" "" + unmount_list "$unmount_list" + fi +done + +qprintf "Syncing mounted partitions:\n" + +fs_type=${src_fs_type[$root_part_num]} +ext_label $root_part_num $fs_type "" label +if [ "$label" != "" ] +then + qecho " e2label $dst_root_dev $label" + e2label $dst_root_dev $label +fi + +mount_partition $dst_root_dev $clone "" +unmount_list="$clone" + +rsync_file_system "//" "$clone" "with-root-excludes" + +for ((p = 1; p <= n_src_parts; p++)) +do + if ((!src_exists[p])) + then + continue + fi + if ((p != root_part_num && src_sync_part[p] && dst_mount_flag[p] == live)) + then + dst_dir=$clone${src_mounted_dir[p]} + if [ ! -d $dst_dir ] + then + mkdir -p $dst_dir + fi + + dst_dev=/dev/${dst_part_base}${p} + fs_type=${src_fs_type[$p]} + ext_label $p $fs_type "" label + if [ "$label" != "" ] + then + qecho " e2label $dst_dev $label" + e2label $dst_dev $label + fi + + mount_partition "$dst_dev" "$dst_dir" "$unmount_list" + rsync_file_system "${src_mounted_dir[p]}/" "${dst_dir}" "" + unmount_list="$dst_dir $unmount_list" + fi +done +qecho "" + +# Fix PARTUUID or device name references in cmdline.txt and fstab +# +fstab=${clone}/etc/fstab +cmdline_txt=${clone}/boot/cmdline.txt + +if [ -f $cmdline_txt ] +then + if ((leave_sd_usb_boot && SD_slot_dst)) + then + qecho "Leaving SD to USB boot alone." + cp $cmdline_txt ${clone}/boot/cmdline.boot + cmdline_txt=${clone}/boot/cmdline.boot + fi + if grep -q $src_disk_ID $cmdline_txt + then + qecho "Editing $cmdline_txt PARTUUID to use $dst_disk_ID" + sed -i "s/${src_disk_ID}/${dst_disk_ID}/" "$cmdline_txt" + elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} $cmdline_txt + then + qecho "Editing $cmdline_txt references from $src_part_base to $edit_fstab_name" + sed -i "s/${src_part_base}/$edit_fstab_name/" "$cmdline_txt" + fi + if ((leave_sd_usb_boot && SD_slot_boot)) + then + qecho "Copying USB cmdline.txt to SD card to set up USB boot." + cp /boot/cmdline.txt /boot/cmdline.boot + cp $cmdline_txt /boot/cmdline.txt + fi +fi + +if grep -q $src_disk_ID $fstab +then + qecho "Editing $fstab PARTUUID to use $dst_disk_ID" + sed -i "s/${src_disk_ID}/${dst_disk_ID}/g" "$fstab" +elif [ "$edit_fstab_name" != "" ] && grep -q ${src_part_base} $fstab +then + qecho "Editing $fstab references from $src_part_base to $edit_fstab_name" + sed -i "s/${src_part_base}/${edit_fstab_name}/" "$fstab" +fi + + +rm -f $clone/etc/udev/rules.d/70-persistent-net.rules + +dst_root_vol_name=`e2label $dst_root_dev` + +if [ "$dst_root_vol_name" = "" ] +then + dst_root_vol_name="no label" +fi + +if ((have_grub)) +then + qecho "grub-install --root-directory=$clone /dev/$dst_disk" + if ((quiet)) + then + grub-install --root-directory=$clone /dev/$dst_disk &> /dev/null + else + grub-install --root-directory=$clone /dev/$dst_disk + fi +fi + +if [ "$setup_args" != "" ] +then + qprintf "\nRunning setup script: $setup_command $setup_args\n" + $setup_command $setup_args +fi + +date=`date '+%F %H:%M'` +echo "$date $HOSTNAME $PGM : clone to $dst_disk ($dst_root_vol_name)" \ + >> $clone_log +echo "$date $HOSTNAME $PGM : clone to $dst_disk ($dst_root_vol_name)" \ + >> ${clone}${clone_log} + + +stop_sec=$(date '+%s') +clone_sec=$((stop_sec - start_sec)) + +stop_time=`date '+%H:%M:%S'` + +qecho "===============================" +qecho "Done with clone to /dev/$dst_disk" +qprintf " Start - %s End - %s Elapsed Time - %d:%02d\n" \ + "$start_time" "$stop_time" "$((clone_sec / 60))" "$((clone_sec % 60))" + +if ((!unattended)) +then + echo -n $" +Cloned partitions are mounted on $clone for inspection or customizing. + +Hit Enter when ready to unmount the /dev/$dst_disk partitions ..." + + read resp +fi + +unmount_list "$unmount_list" +qprintf "===============================\n\n" + +exit 0 diff --git a/RPiSetup/bullseye/usr/local/bin/rpi-clone-setup b/RPiSetup/bullseye/usr/local/bin/rpi-clone-setup new file mode 100644 index 0000000..5578c30 --- /dev/null +++ b/RPiSetup/bullseye/usr/local/bin/rpi-clone-setup @@ -0,0 +1,144 @@ +#!/bin/bash + +# Usage: rpi-clone-setup {-t|--test} hostname +# eg: sudo rpi-clone-setup bozo +# +# This script is automatically run by rpi-clone (when it is given -s options) +# to setup an alternate hostname. A cloned file system mounted on /mnt/clone +# is expected unless testing with the -t option. +# +# Or, this script can be run by hand at the end of a clone when rpi-clone +# pauses with the cloned file systems still mounted on /mnt/clone. +# +# Or, run this script by hand with -t to process files in test directories +# under /tmp/clone-test. Run -t and look at the files to see if the files +# have been edited OK. +# eg: sudo rpi-clone-setup -t bozo +# +# This is a starter script that handles only /etc/hosts and /etc/hostname. +# Make sure the script works correctly for your /etc/hosts file. +# +# If adding a customization for another file: +# Add the file to file_list. +# If needed, add a mkdir -p line to the "if ((testing))" part. +# Add the scripting necessary to customize the file. +# Test new scripting by running: rpi-clone-setup -t newhostname +# + +file_list="etc/hostname etc/hosts" + +clone=/mnt/clone +clone_test=/tmp/clone-test + +PGM=`basename $0` + +if [ `id -u` != 0 ] +then + echo "You must be root to run $PGM" + exit 0 +fi + +function usage + { + echo "Usage: $PGM hostname {-t|--test}" + echo " Eg: $PGM rpi1" + echo " Modify files appropriate to set up for a new host." + echo " Files handled are:" + for file in $file_list + do + echo " $file" + done + echo "" + echo "If testing (-t flag) files are copied and processed to $clone_test" + echo "" + exit 0 + } + +testing=0 +while [ "$1" ] +do + case "$1" in + -t|--test) + testing=1 + ;; + *) + if [ "$newhost" != "" ] + then + echo "Bad args" + usage + fi + newhost=$1 + ;; + esac + shift +done + +if [ "$newhost" = "" ] +then + echo -e "You must specify a target hostname\n" + usage +fi + +echo -e "\t$newhost\t- target hostname" + +if ((!testing)) && [ ! -d /mnt/clone/etc ] +then + echo "A destination clone file system is not mounted on /mnt/clone" + echo "Aborting!" + exit 0 +fi + +if ((testing)) +then + cd /tmp + rm -rf $clone_test + clone=$clone_test + + mkdir -p $clone/etc + + echo "**********************************************" + echo "Testing setup: copying files to $clone" + for file in $file_list + do + echo " cp /$file $clone/$file" + cp /$file $clone/$file + done + echo "This test run will modify those files." + echo "**********************************************" + echo "" +fi + + +## +# Set /etc/hostname +# +cd $clone/etc +echo $newhost > hostname +# +# Read it back to verify. +# +echo "$clone/etc/hostname - set new hostname: " +LINE=`cat hostname` +echo -e "$LINE\n" + + +## +# Edit /etc/hosts - edit the sed command if editing fails for your /etc/hosts. +# +cd $clone/etc +sed -i s/"$HOSTNAME"/"$newhost"/ hosts +# +# Read it back to verify. +# +echo "$clone/etc/hosts - set new hostname \"$newhost\" in lines: " +LINE=`grep $newhost hosts` +echo -e "$LINE\n" + + +## +# Add more customizations if needed. +# + + +exit 0 + diff --git a/RPiSetup/bullseye/usr/local/bin/startdrs.sh b/RPiSetup/bullseye/usr/local/bin/startdrs.sh new file mode 100644 index 0000000..275ef13 --- /dev/null +++ b/RPiSetup/bullseye/usr/local/bin/startdrs.sh @@ -0,0 +1,40 @@ +#!/bin/bash +# startdrs.sh + +source /etc/drs.conf + +openbox-session & + +if [ "$INHIBIT_BLANK" -eq "1" ] +then + xset s off + xset -dpms +else + xset s off + xset +dpms + xset dpms 0 600 1800 +fi + +while true +do + $KILL_CMD + $CLEANUP_CMD + + # start application + $APP_CMD & + + sleep 10 + + while true + do + pgrep $ALIVE_STRING + if [ "$?" -eq "1" ] + then + # relaunch application if it terminates + $APP_CMD & + fi + sleep 1 + done + + exit 0 +done diff --git a/RPiSetup/common.sh b/RPiSetup/common.sh new file mode 100644 index 0000000..946dbd6 --- /dev/null +++ b/RPiSetup/common.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# common.sh +# OpenDRS Online Discrepancy Reporting System +# Copyright (C) 2023 Rod Wright + +# SPDX-License-Identifier: GPL-2.0 + +function getmodel() { + # Determine the model of Raspberry Pi + # Takes no arguments. + echo -n "Raspberry Pi model is: " + rpimodeltxt=$(tr -d '\0' < /proc/device-tree/model) + echo $rpimodeltxt + echo $rpimodeltxt|grep -q "Raspberry Pi 3" + if [ $? -eq 0 ] + then + ismodel3="true" + fi +} + +function getarch() { + # Determine the architecture of Raspberry Pi OS + # Takes no arguments. + echo -n "Architecture is: " + arch_32_64=`getconf LONG_BIT` + echo "$arch_32_64 bit" +} + +function getosrelease() { + # Determine the Raspberry Pi OS release name + # Takes no arguments + echo -n "OS Release version is: " + os_rel_ver=`grep VERSION_CODENAME /etc/os-release | cut -d "=" -f2` + echo $os_rel_ver +} diff --git a/RPiSetup/etc/apt/sources.list.d/webmin.list b/RPiSetup/etc/apt/sources.list.d/webmin.list deleted file mode 100644 index 7b1f58d..0000000 --- a/RPiSetup/etc/apt/sources.list.d/webmin.list +++ /dev/null @@ -1 +0,0 @@ -deb http://download.webmin.com/download/repository sarge contrib diff --git a/RPiSetup/server-setup.sh b/RPiSetup/server-setup.sh index e46c05f..24f8143 100644 --- a/RPiSetup/server-setup.sh +++ b/RPiSetup/server-setup.sh @@ -36,6 +36,23 @@ then fi echo "It looks like you have. Continuing." echo "" +echo -n "Raspberry Pi model is: " +rpimodeltxt=$(tr -d '\0' < /proc/device-tree/model) +echo $rpimodeltxt +echo $rpimodeltxt|grep -q "Raspberry Pi 3" +if [ $? -eq 0 ] +then + ismodel3="true" +fi +echo "" +echo -n "OS Release version is: " +os_rel_ver=`grep VERSION_CODENAME /etc/os-release | cut -d "=" -f2` +echo $os_rel_ver +echo "" +echo -n "Architecture is: " +arch_32_64=`getconf LONG_BIT` +echo "$arch_32_64 bit" +echo "" echo "" echo "Updating Raspberry Pi OS..." sleep 10 @@ -72,7 +89,7 @@ echo "" echo "" apt install -y apache2 php mariadb-server phpmyadmin uuid-runtime apt install -y php-mysqli -cp etc/apache2/mods-available/alias.conf /etc/apache2/mods-available +cp -v $os_rel_ver/etc/apache2/mods-available/alias.conf /etc/apache2/mods-available service apache2 restart echo "...done." echo "" diff --git a/RPiSetup/terminal-setup.sh b/RPiSetup/terminal-setup.sh index e0482ab..a1a38c9 100644 --- a/RPiSetup/terminal-setup.sh +++ b/RPiSetup/terminal-setup.sh @@ -6,6 +6,7 @@ # SPDX-License-Identifier: GPL-2.0 +source common.sh current_user=`whoami` current_login=`who am i | awk '{print $1}'` if [ "$current_user" != "root" ] @@ -53,7 +54,31 @@ echo "If you have completed these steps, press enter to continue. If not," echo -n "press ctrl-c to quit." read continueok echo "" +getmodel echo "" +getosrelease +echo "" +getarch +echo "" +if [ $arch_32_64 -eq 64 -a "$ismodel3" = "true" ] +then + echo "Raspberry Pi 3 hardware is known to have problems with acting as a" + echo "wireless access point when 64 bit kernels are used. If you intend for" + echo "this terminal to act as a wireless access point, you should stop here," + echo "power off, remove the microsd card and re-image using a 32 bit version" + echo "of Raspberry Pi OS." + echo -n "Ignore and [c]ontinue or [A]bort? [c/A]: " + read archabort + if [ "$archabort" = "C" -o "$archabort" = "c" ] + then + echo "" + echo "Continuing with installation." + else + echo "" + echo "Aborting installation." + exit 0 + fi +fi echo "" echo "" echo "Updating Raspberry Pi OS..." @@ -70,13 +95,12 @@ echo "" echo "...done." sleep 10 echo "" -echo "" echo "Copying files..." -chmod +x usr/local/bin/* -cp usr/local/bin/* /usr/local/bin -cp etc/drs.conf /etc -cp etc/apt/sources.list.d/* /etc/apt/sources.list.d -cp lib/systemd/system/getty@tty1.service /lib/systemd/system +chmod +x $os_rel_ver/usr/local/bin/* +cp -v $os_rel_ver/usr/local/bin/* /usr/local/bin +cp -v $os_rel_ver/etc/drs.conf /etc +cp -v $os_rel_ver/etc/apt/sources.list.d/* /etc/apt/sources.list.d +cp -v $os_rel_ver/lib/systemd/system/getty@tty1.service /lib/systemd/system echo "" echo "" echo "" @@ -91,25 +115,47 @@ echo "" echo "" echo "" echo "" -echo "deb https://download.webmin.com/download/repository sarge contrib" >/etc/apt/sources.list.d/webmin.list -wget https://download.webmin.com/jcameron-key.asc -cat jcameron-key.asc | gpg --dearmor >/etc/apt/trusted.gpg.d/jcameron-key.gpg -rm jcameron-key.asc apt install apt-transport-https -apt update +skipwebmin="false" +curl -o setup-repos.sh https://raw.githubusercontent.com/webmin/webmin/master/setup-repos.sh +if [ $? -ne 0 ] +then + echo "Warning: failed to download Webmin repo setup script." + echo -n "Ignore and [c]ontinue or [A]bort? [c/A]: " + read wmfailchoice + if [ "$wmfailchoice" = "C" -o "$wmfailchoice" = "c" ] + then + skipwebmin="true" + echo "Continuing without installing Webmin. You should investigate the failure" + echo "and install Webmin manually after the terminal is set up, as the" + echo "Manage Terminal link in the OpenDRS menu depends on it." + echo -n "Press enter to continue." + read continueok + echo "" + apt update + else + echo "Aborting terminal setup." + exit 0 + fi +fi +if [ "$skipwebmin" = "false" ] +then + sh setup-repos.sh -f + apt update + apt install -y --install-recommends webmin +fi apt install -y --no-install-recommends xorg openbox chromium-browser apt install -y cups libcups2-dev cmake -apt install -y webmin addgroup lpadmin usermod -a -G lpadmin $current_login systemctl enable getty@tty1.service service cups-browsed stop systemctl disable cups-browsed.service -cp etc/cups/cupsd.conf /etc/cups/ +cp $os_rel_ver/etc/cups/cupsd.conf /etc/cups/ service cups restart -cd brlaser-master +cd $os_rel_ver/brlaser-master cmake . && make && make install -cd .. +cd ../.. myhn=`hostname` echo "" echo "" @@ -131,8 +177,8 @@ echo "" echo "" cloneuser $current_login customer mkdir -p /home/customer/.config/openbox -cp home/customer/.profile /home/customer -cp home/customer/.config/openbox/rc.xml /home/customer/.config/openbox +cp $os_rel_ver/home/customer/.profile /home/customer +cp $os_rel_ver/home/customer/.config/openbox/rc.xml /home/customer/.config/openbox chown -R customer:customer /home/customer/.config /home/customer/.profile echo "" echo ""