Skip to content

Commit 0dae5a2

Browse files
committed
Added ipp-usb status command, for troubleshooting
The `ipp-usb status` command prints actual status of all attached 7/1/4 devices. It is designed with a purpose to add some visibility in a case of troubleshooting. See also #52
1 parent a1bad7c commit 0dae5a2

7 files changed

+213
-108
lines changed

flock_unix.go

+41-13
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,55 @@
1010

1111
package main
1212

13+
/*
14+
#include <errno.h>
15+
#include <unistd.h>
16+
17+
static inline int do_lockf (int fd, int cmd, off_t len) {
18+
int rc = lockf(fd, cmd, len);
19+
if (rc < 0) {
20+
rc = -errno;
21+
}
22+
return rc;
23+
}
24+
*/
25+
import "C"
26+
1327
import (
1428
"os"
1529
"syscall"
1630
)
1731

18-
// FileLock acquires file lock
19-
func FileLock(file *os.File, exclusive, wait bool) error {
20-
var how int
32+
// FileLockCmd represents set of possible values for the
33+
// FileLock argument
34+
type FileLockCmd C.int
2135

22-
if exclusive {
23-
how = syscall.LOCK_EX
24-
} else {
25-
how = syscall.LOCK_SH
26-
}
36+
const (
37+
// Lock the file; wait if it is busy
38+
FileLockWait = C.F_LOCK
39+
40+
// Lock the file; fail with ErrLockIsBusy if it is busy
41+
FileLockNoWait = C.F_TLOCK
42+
43+
// Test the lock. Return immediately with ErrLockIsBusy
44+
// if file is busy or with the nil error, if file is not
45+
// busy. File locking state is not affected in both cases
46+
FileLockTest = C.F_TEST
47+
48+
// Unlock the file
49+
FileLockUnlock = C.F_ULOCK
50+
)
2751

28-
if !wait {
29-
how |= syscall.LOCK_NB
52+
// FileLock manages file lock
53+
func FileLock(file *os.File, cmd FileLockCmd) error {
54+
rc := C.do_lockf(C.int(file.Fd()), C.int(cmd), 0)
55+
if rc == 0 {
56+
return nil
3057
}
3158

32-
err := syscall.Flock(int(file.Fd()), how)
33-
if err == syscall.Errno(syscall.EWOULDBLOCK) {
59+
var err error = syscall.Errno(-rc)
60+
switch err {
61+
case syscall.EACCES, syscall.EAGAIN:
3462
err = ErrLockIsBusy
3563
}
3664

@@ -39,5 +67,5 @@ func FileLock(file *os.File, exclusive, wait bool) error {
3967

4068
// FileUnlock releases file lock
4169
func FileUnlock(file *os.File) error {
42-
return syscall.Flock(int(file.Fd()), syscall.LOCK_UN)
70+
return FileLock(file, FileLockUnlock)
4371
}

flock_windows.go

-87
This file was deleted.

ipp-usb.8

+6-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ logs duplicated on console, \-bg option is ignored
2525
.TP
2626
\fBcheck\fR
2727
check configuration and exit\. It also prints a list of all connected devices
28+
.TP
29+
\fBstatus\fR
30+
print \fBipp\-usb\fR status
2831
.SS "Options are"
2932
.TP
3033
\fB\-bg\fR
@@ -228,6 +231,8 @@ If you found out about your device that it needs a quirk to work properly or it
228231
.IP "\[ci]" 4
229232
\fB/var/ipp\-usb/lock/ipp\-usb\.lock\fR: lock file, that helps to prevent multiple copies of daemon to run simultaneously
230233
.IP "\[ci]" 4
234+
\fB/var/ipp\-usb/status\fR: per\-device status in a form of a text file (printed by \fBipp\-usb status\fR)
235+
.IP "\[ci]" 4
231236
\fB/usr/share/ipp\-usb/quirks/*\.conf\fR: device\-specific quirks (see above)
232237
.IP "\[ci]" 4
233238
\fB/etc/ipp\-usb/quirks/*\.conf\fR: device\-specific quirks defined by sysadmin (see above)
@@ -239,4 +244,4 @@ All rights reserved\.
239244
.P
240245
This program is licensed under 2\-Clause BSD license\. See LICENSE file for details\.
241246
.SH "SEE ALSO"
242-
cups(1)
247+
\fBcups(1)\fR

ipp-usb.8.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ IPP printing, eSCL scanning and web console are fully supported.
3535
check configuration and exit. It also prints a list
3636
of all connected devices
3737

38+
* `status`:
39+
print `ipp-usb` status
40+
3841
### Options are
3942

4043
* `-bg`:
@@ -285,6 +288,9 @@ of such a device.
285288
* `/var/ipp-usb/lock/ipp-usb.lock`:
286289
lock file, that helps to prevent multiple copies of daemon to run simultaneously
287290

291+
* `/var/ipp-usb/status`:
292+
per-device status in a form of a text file (printed by `ipp-usb status`)
293+
288294
* `/usr/share/ipp-usb/quirks/*.conf`: device-specific quirks (see above)
289295

290296
* `/etc/ipp-usb/quirks/*.conf`: device-specific quirks defined by sysadmin (see above)
@@ -298,6 +304,6 @@ This program is licensed under 2-Clause BSD license. See LICENSE file for detail
298304

299305
## SEE ALSO
300306

301-
cups(1)
307+
**cups(1)**
302308

303309
# vim:ts=8:sw=4:et

main.go

+80-6
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package main
1111
import (
1212
"bytes"
1313
"fmt"
14+
"io/ioutil"
1415
"os"
1516
"sort"
1617
)
@@ -26,6 +27,7 @@ Modes are:
2627
debug - logs duplicated on console, -bg option is
2728
ignored
2829
check - check configuration and exit
30+
status - print ipp-usb status and exit
2931
3032
Options are
3133
-bg - run in background (ignored in debug mode)
@@ -40,6 +42,7 @@ const (
4042
RunUdev
4143
RunDebug
4244
RunCheck
45+
RunStatus
4346
)
4447

4548
// String returns RunMode name
@@ -55,6 +58,8 @@ func (m RunMode) String() string {
5558
return "debug"
5659
case RunCheck:
5760
return "check"
61+
case RunStatus:
62+
return "status"
5863
}
5964

6065
return fmt.Sprintf("unknown (%d)", int(m))
@@ -113,6 +118,9 @@ func parseArgv() (params RunParameters) {
113118
case "check":
114119
params.Mode = RunCheck
115120
modes++
121+
case "status":
122+
params.Mode = RunStatus
123+
modes++
116124
case "-bg":
117125
params.Background = true
118126
default:
@@ -131,6 +139,65 @@ func parseArgv() (params RunParameters) {
131139
return
132140
}
133141

142+
// printStatus prints status of running ipp-usb daemon, if any
143+
func printStatus() {
144+
running := false
145+
146+
// Check if ipp-usb is running
147+
lock, err := os.OpenFile(PathLockFile,
148+
os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
149+
if err == nil {
150+
err = FileLock(lock, FileLockTest)
151+
lock.Close()
152+
}
153+
154+
switch err {
155+
case nil:
156+
InitLog.Info(0, "ipp-usb is not running")
157+
case ErrLockIsBusy:
158+
InitLog.Info(0, "ipp-usb is running")
159+
running = true
160+
default:
161+
InitLog.Info(0, "%s", err)
162+
}
163+
164+
// Dump ipp-usb status file, if ipp-usb is running
165+
if running {
166+
var text []byte
167+
168+
status, err := os.OpenFile(PathStatusFile,
169+
os.O_RDWR, 0600)
170+
if err == nil {
171+
defer status.Close()
172+
err = FileLock(status, FileLockWait)
173+
}
174+
if err == nil {
175+
err = FileLock(status, FileLockWait)
176+
text, err = ioutil.ReadAll(status)
177+
}
178+
179+
if err == nil {
180+
text = bytes.Trim(text, "\n")
181+
lines := bytes.Split(text, []byte("\n"))
182+
183+
for len(lines) > 0 && len(lines[len(lines)-1]) == 0 {
184+
lines = lines[0 : len(lines)-1]
185+
}
186+
187+
if len(lines) == 0 {
188+
InitLog.Info(0, "per-device status: empty")
189+
} else {
190+
InitLog.Info(0, "per-device status:")
191+
for _, line := range lines {
192+
InitLog.Info(0, "%s", line)
193+
}
194+
}
195+
} else {
196+
InitLog.Info(0, "per-device status: %s", err)
197+
}
198+
}
199+
}
200+
134201
// The main function
135202
func main() {
136203
var err error
@@ -143,7 +210,9 @@ func main() {
143210
InitLog.Check(err)
144211

145212
// Setup logging
146-
if params.Mode != RunDebug && params.Mode != RunCheck {
213+
if params.Mode != RunDebug &&
214+
params.Mode != RunCheck &&
215+
params.Mode != RunStatus {
147216
Console.ToNowhere()
148217
} else if Conf.ColorConsole {
149218
Console.ToColorConsole()
@@ -200,8 +269,13 @@ func main() {
200269
InitLog.Exit(0, "This program requires root privileges")
201270
}
202271

203-
// If mode is "check", we are done
204-
if params.Mode == RunCheck {
272+
// In RunStatus mode, print ipp-usb status
273+
if params.Mode == RunStatus {
274+
printStatus()
275+
}
276+
277+
// If mode is "check" or "status", we are done
278+
if params.Mode == RunCheck || params.Mode == RunStatus {
205279
os.Exit(0)
206280
}
207281

@@ -220,7 +294,7 @@ func main() {
220294
InitLog.Check(err)
221295
defer lock.Close()
222296

223-
err = FileLock(lock, true, false)
297+
err = FileLock(lock, FileLockNoWait)
224298
if err == ErrLockIsBusy {
225299
if params.Mode == RunUdev {
226300
// It's not an error in udev mode
@@ -232,7 +306,7 @@ func main() {
232306
InitLog.Check(err)
233307

234308
// Write to log that we are here
235-
if params.Mode != RunCheck {
309+
if params.Mode != RunCheck && params.Mode != RunStatus {
236310
Log.Info(' ', "===============================")
237311
Log.Info(' ', "ipp-usb started in %q mode, pid=%d",
238312
params.Mode, os.Getpid())
@@ -269,7 +343,7 @@ func main() {
269343
Log.Check(err)
270344

271345
if UsbCheckIppOverUsbDevices() &&
272-
FileLock(lock, true, false) == nil {
346+
FileLock(lock, FileLockNoWait) == nil {
273347
Log.Info(' ', "New IPP-over-USB device found")
274348
continue
275349
}

paths.go

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ const (
2727
// PathLockFile defines path to lock file
2828
PathLockFile = PathLockDir + "/ipp-usb.lock"
2929

30+
// PathStatusFile defines path to the status file
31+
PathStatusFile = PathProgState + "/status"
32+
3033
// PathProgStateDev defines path to directory where per-device state
3134
// files are saved to
3235
PathProgStateDev = PathProgState + "/dev"

0 commit comments

Comments
 (0)