Tweak: Better supported syntax for URI on Linux
[einar-bin] / addfollowmeprint.sh
1 #!/bin/bash
2 # This script installs the FollowMe print queue at NTNU on Linux (and possibly Mac) systems.
3 # The targeted and tested distros are: Debian, Ubuntu (and derivates), Fedora, CentOS, OpenSUSE and Mint
4 # Copyright © 2017-2019 einar.haraldseid@ntnu.no
5
6 # Documentation
7 function usage {
8 echo "Usage: ./$(basename "${0}") [OPTIONS]"
9 echo "Options:"
10 echo " -m, --model {ricoh|generic} Printer model to install (default: generic)"
11 echo " -d, --driver {pcl,postscript} Printer driver to use (default: postscript)"
12 echo " -f, --force Force running script as if on Linux systems"
13 echo " -p, --plaintext Store credentials as plaintext in /etc/cups/printers.conf (Linux only)"
14 echo " -h, --help Display this help text"
15 }
16
17 # Print errors to STDERR
18 function printerror() {
19 echo "${*}" 1>&2
20 }
21
22 # Set default options that may be overridden by passed options below
23 Model="generic"
24 Driver="postscript"
25
26 # Set other default options
27 PrintServer="followprint.win.ntnu.no"
28 PrintFile="ntnuprint-ricoh"
29 Workgroup="WIN-NTNU-NO"
30 QueueName="FollowMe"
31
32 while [[ $# -gt 0 ]]; do
33 Key="${1}"
34
35 case ${Key} in
36 -m|--model)
37 Model=$(echo "${2}" | tr "[:upper:]" "[:lower:]")
38 if [ "${Model}" != "ricoh" ] && [ "${Model}" != "generic" ]; then
39 printerror "Unknown model ${Model}, please choose one of ricoh or generic"
40 exit 1
41 fi
42 shift # Jump to next argument
43 ;;
44 -f|--force)
45 Force="YES"
46 shift # Jump to next argument
47 ;;
48 -d|--driver)
49 Driver=$(echo "${2}" | tr "[:upper:]" "[:lower:]")
50 if [ "${Driver}" != "postscript" ] && [ "${Driver}" != "pcl" ]; then
51 printerror "Unknown driver ${Driver}, plase choose one of postscript or pcl"
52 exit 1
53 fi
54 shift # Jump to next argument
55 ;;
56 -p|--plaintext)
57 Plaintext="YES"
58 shift # Jump to next argument
59 ;;
60 -h|--help)
61 usage
62 exit 0
63 ;;
64 *)
65 # Unknown argument
66 echo "Unknown argument: ${Key}"
67 exit 1
68 ;;
69 esac
70
71 shift # past argument or value
72 done
73
74 # Make sure we have sudo powers when we need it
75 if ! sudo -k; then
76 printerror "This script requires sudo to function"
77 exit 1
78 fi
79
80 # But don't run as super user, otherwise we can't access the keyring
81 if [ ${UID} -eq 0 ]; then
82 if [ "${Plaintext}" != "YES" ]; then
83 printerror "Please run this script as your normal user, we will prompt you for your sudo password when needed. Or you can use the --plaintext option"
84 exit 1
85 fi
86 else
87 echo "Please provide sudo password, as some parts of this script requires it"
88 if ! sudo true; then
89 printerror "Sorry, this script requires working sudo privileges to function"
90 exit 1
91 fi
92 fi
93
94 # Test for supported OS
95 Uname=$(uname | tr "[:upper:]" "[:lower:]")
96 if [ "${Uname}" != "darwin" ] && [ "${Uname}" != "linux" ] && [ "${Force}" != "YES" ]; then
97 printerror "I don't think I can run on ${Uname}, but if you insist, please use -f to force Linux detection. This may not work, though."
98 exit 1
99 fi
100
101 # Set Uname to linux if we are forcing running the script
102 if [ "${Force}" = "YES" ]; then
103 Uname="linux"
104 fi
105
106 # Set printer driver path based on driver (we will override these if we're specific distros
107 if [ "${Driver}" = "postscript" ]; then
108 DriverPath="drv:///sample.drv/generic.ppd"
109 else
110 DriverPath="drv:///sample.drv/generpcl.ppd"
111 fi
112
113 # Test for CUPS
114 if ! sudo bash -c "command -v lpadmin" > /dev/null 2>&1; then
115 printerror "You must have CUPS installed to add printers. Please install CUPS."
116 exit 1
117 fi
118
119 # Tests for Linux systems
120 if [ "${Uname}" = "linux" ]; then
121 # Test if smbclient is installed
122 if ! command -v smbclient >/dev/null 2>&1; then
123 printerror "You must have smbclient installed to print to NTNU followprint. Please install smbclient."
124 exit 1
125 fi
126
127 # Test if secret-tool is installed
128 if ! command -v secret-tool >/dev/null 2>&1; then
129 printerror "You must have secret-tool installed for this script to work. Please install libsecret-tools (Debian-systems) or secret-tool (Fedora/CentOS)."
130 exit 1
131 fi
132
133 # Try to determine if the necessary printer drivers are installed, and set correct driver paths
134
135 # This should match OpenSUSE, and probably SUSE Enterprise, and other derivates that use zypper as the primary package manager
136 if command -v zypper >/dev/null 2>&1; then
137 if [ "${Driver}" = "postscript" ]; then
138 if [ "${Model}" = "ricoh" ]; then
139 if ! sudo rpm -q OpenPrintingPPDs-postscript >/dev/null 2>&1; then
140 printerror "You don't seem to have the correct printer drivers installed, please run:"
141 printerror " sudo zypper install OpenPrintingPPDs-postscript"
142 printerror "first, or use the generic driver instead."
143 exit 1
144 else
145 DriverPath="OpenPrintingPPDs/postscript/Ricoh-MP_C6003.Postscript-Ricoh.ppd.gz"
146 fi
147 else
148 DriverPath="Postscript.ppd.gz"
149 fi
150 else
151 if ! sudo rpm -q OpenPrintingPPDs-ghostscript >/dev/null 2>&1; then
152 printerror "You don't seem to have the correct printer drivers installed, please run:"
153 printerror " sudo zypper install OpenPrintingPPDs-ghostscript"
154 printerror "first, or use the generic driver instead."
155 exit 1
156 else
157 if [ "${Model}" = "ricoh" ]; then
158 DriverPath="OpenPrintingPPDs/ghostscript/Ricoh-MP_C6003.pxlcolor-Ricoh.ppd.gz"
159 else
160 DriverPath="OpenPrintingPPDs/ghostscript/Generic-PCL_6_PCL_XL_Printer.pxlcolor.ppd.gz"
161 fi
162 fi
163 fi
164 else
165 # The rest of the systems can use drv:/// paths for the generic drivers, but we need to detect various distros for advice on installing Ricoh drivers
166 if [ "${Model}" = "ricoh" ]; then
167 # This should match Fedora and other modern rpm based systems that have dnf as the primary package manager
168 if command -v dnf >/dev/null 2>&1; then
169 if ! sudo rpm -q foomatic-db-ppds 2>&1; then
170 printerror "You don't seem to have the correct printer drivers installed, please run:"
171 printerror " sudo dnf install foomatic-db-ppds"
172 printerror "first, or use the generic driver instead."
173 exit 1
174 else
175 if [ "${Driver}" = "postscript" ]; then
176 DriverPath="foomatic-db-ppds/Ricoh/PS/Ricoh-MP_C6003_PS.ppd.gz"
177 else
178 DriverPath="foomatic-db-ppds/Ricoh/PXL/Ricoh-MP_C6003_PXL.ppd.gz"
179 fi
180 fi
181 fi
182 # This should match CentOS, RHEL and other RHEL based distros that have yum as the primary package manager
183 if command -v yum >/dev/null 2>&1; then
184 if ! sudo rpm -q foomatic-db-ppds >/dev/null 2>&1; then
185 printerror "You don't seem to have the correct printer drivers installed, please run:"
186 printerror " sudo yum install foomatic-db-ppds"
187 printerror "first, or use the generic driver instead."
188 exit 1
189 else
190 if [ "${Driver}" = "postscript" ]; then
191 DriverPath="foomatic-db-ppds/Ricoh/PS/Ricoh-MP_C6003_PS.ppd.gz"
192 else
193 DriverPath="foomatic-db-ppds/Ricoh/PXL/Ricoh-MP_C6003_PXL.ppd.gz"
194 fi
195 fi
196 fi
197 # This should match Debian, Ubuntu and most if not all derivates that use dpkg as the primary package manager
198 if command -v dpkg >/dev/null 2>&1; then
199 if ! sudo dpkg -s openprinting-ppds > /dev/null 2>&1; then
200 printerror "You must have the correct printer drivers installed, please run:"
201 printerror " sudo apt-get install openprinting-ppds"
202 printerror "first, or use the generic driver instead."
203 exit 1
204 else
205 if [ "${Driver}" = "postscript" ]; then
206 DriverPath="openprinting-ppds:0/ppd/openprinting/Ricoh/PS/Ricoh-MP_C6003_PS.ppd"
207 else
208 DriverPath="openprinting-ppds:0/ppd/openprinting/Ricoh/PXL/Ricoh-MP_C6003_PXL.ppd"
209 fi
210 fi
211 fi
212 fi
213 fi
214 fi
215
216 echo "This script will add a new printer called ${QueueName}, connecting to the
217 print server ${PrintServer} using your user name and password from NTNU."
218
219 # Get username and password
220 printf "User name: "
221 read -r Username
222 printf "Password: "
223 Settings=$(stty -g)
224 stty -echo
225 read -r Password
226 stty "${Settings}"
227
228 echo ""
229
230 # Some further tests for Linux systems
231 if [ "${Uname}" = "linux" ]; then
232 # Test for valid username and password
233 # Bonus: find out if the print share is actually available
234 PrintServerIP=$(getent ahostsv4 ${PrintServer} | head -n 1 | cut -d " " -f 1)
235 if ! smbclient -U "${Workgroup}/${Username}%${Password}" -L "//${PrintServer}" -I "${PrintServerIP}" > /dev/null 2>&1; then
236 printerror "User name or password incorrect, or no contact with the print server ${PrintServer}."
237 exit 1
238 fi
239 ShareFound=$(smbclient -U "${Workgroup}/${Username}%${Password}" -L "//${PrintServer}" -I "${PrintServerIP}" -g 2>/dev/null | grep ${PrintFile} | cut -d "|" -f 1)
240 if [ "${ShareFound}" != "Printer" ]; then
241 printerror "Could not find printer share called ${PrintFile} on the server"
242 printerror "This script must be broken or outdated. Please contact orakel@ntnu.no for further assistance."
243 exit 1
244 fi
245 fi
246
247 # Similar tests for OSX
248 if [ "${Uname}" = "darwin" ]; then
249 if ! smbutil view -A "//${Workgroup};${Username}:${Password}@${PrintServer}" > /dev/null 2>&1; then
250 printerror "User name or password incorrect, or no contact with the print server ${PrintServer}."
251 exit 1
252 fi
253 ShareFound=$(smbutil view "//${Workgroup};${Username}:${Password}@${PrintServer}" 2>/dev/null | grep ${PrintFile} | cut -d " " -f 1)
254 if [ "${ShareFound}" != "${PrintFile}" ]; then
255 printerror "Could not find printer share called ${PrintFile} on the server"
256 printerror "This script must be broken or outdated. Please contact orakel@ntnu.no for further assistance."
257 exit 1
258 fi
259 fi
260
261 # Finally we can add the printer, let's remove any existing printer share with the same name first
262 sudo lpadmin -x ${QueueName} > /dev/null 2>&1
263
264 # The Linux way
265 if [ "${Uname}" = "linux" ]; then
266 if [ "${Plaintext}" = "YES" ]; then
267 PrinterShare="smb://${Workgroup}/${Username}:${Password}@${PrintServer}/${PrintFile}"
268 AuthInfo="none"
269 echo -e "\nNOTE: Your credentials will be stored in plaintext in /etc/cups/printers.conf.\nThis is usually only necessary on headless systems or on systems that don't run a dbus-daemon and/or a keyring that can provide the org.freedesktop.secrets service.\nNeedless to say, this is not a good idea on multi-user systems.\n"
270 else
271 PrinterShare="smb://${Workgroup}/${PrintServer}/${PrintFile}"
272 AuthInfo="username,password"
273 fi
274 if ! sudo lpadmin -p ${QueueName} \
275 -D "FollowMe print queue at NTNU" \
276 -L "Many locations" \
277 -v "${PrinterShare}" \
278 -m "${DriverPath}" \
279 -o auth-info-required="$AuthInfo" \
280 -u allow:all -E; then
281 printerror "Could not connect to printer share. See above error for details."
282 exit 1
283 fi
284 if [ "${Plaintext}" != "YES" ]; then
285 # Add credentials to the keyring
286 if ! echo -n "${Password}" | secret-tool store \
287 --label "ipp://localhost:631/printers/$QueueName" \
288 uri "ipp://localhost:631/printers/${QueueName}" \
289 user "${Username}"; then
290 printerror "Could not store credentials to the keyring, see above error for details. A workaround can be to use the option --plaintext"
291 fi
292 fi
293 fi
294
295 # The OSX way
296 if [ "${Uname}" = "darwin" ]; then
297 if ! sudo lpadmin -p ${QueueName} \
298 -D "FollowMe print queue at NTNU" \
299 -L "Many locations" \
300 -v "smb://${PrintServer}/${PrintFile}" \
301 -m "${DriverPath}" \
302 -o printer-is-shared=false -o printer-op-policy=authenticated \
303 -u allow:all -E; then
304 printerror "Could not connect to printer share. See above error for details."
305 exit 1
306 fi
307
308 sudo cupsenable "${QueueName}"
309 sudo cupsaccept "${QueueName}"
310
311 # Add credentials to the keychain if they are missing
312 # Shamelessly stolen^W^WBorrowed from https://github.com/Orakeltjenesten/scripts/blob/33abfb353524f449f0bbdee27adb2f1f0a9756a2/print/ntnuprint-mac.sh
313 # TODO: Since we should have a known-good username and password at this stage it's unwise to re-use the existing credentials, can we simply drop the test?
314 if ! security find-internet-password -s ${PrintServer} >/dev/null 2>&1; then
315 security -v add-internet-password -a "${Workgroup}\\${Username}" -s ${PrintServer} \
316 -w "${Password}" -D "Network Password" -r "smb " -l "${QueueName}" \
317 -T /System/Library/CoreServices/NetAuthAgent.app -T 'group://NetAuth' \
318 -T /System/Library/CoreServices/NetAuthAgent.app/Contents/MacOS/NetAuthSysAgent >/dev/null 2>&1
319 fi
320 fi
321
322 # Set correct paper size and enable the duplexer option
323 if ! sudo lpadmin -p ${QueueName} -o PageSize=A4 -o Option1=True; then
324 printerror "Could not set default options on the print queue ${QueueName}. See above error for details."
325 exit 1
326 fi
327
328 # Set as default
329 if ! sudo lpadmin -d ${QueueName}; then
330 printerror "Could not set the print queue ${QueueName} as default printer. See above error for details."
331 exit 1
332 fi
333
334 echo "Printer successfully installed. You may need to restart cups for the changes to take effect."