@@ -22,6 +22,7 @@ use super::listener;
22
22
23
23
use listener:: Listen ;
24
24
use listener:: ReadWrite ;
25
+ use std:: os:: unix:: io:: FromRawFd ;
25
26
26
27
static SOCKET_PATH : & str = "/tmp/security-daemon-socket" ;
27
28
@@ -43,23 +44,35 @@ impl DomainSocketListener {
43
44
/// fails
44
45
/// - if binding to the socket path fails
45
46
fn init ( & mut self ) {
46
- let socket = Path :: new ( SOCKET_PATH ) ;
47
+ if cfg ! ( feature = "systemd-daemon" ) {
48
+ // The PARSEC service is socket activated (see parsec.socket file).
49
+ // systemd creates the PARSEC service giving it an initialised socket as the file
50
+ // descriptor number 3 (see sd_listen_fds(3) man page).
51
+ // If an instance of PARSEC compiled with the "systemd-daemon" feature is run directly
52
+ // instead of by systemd, this call will still work but the next accept call on the
53
+ // UnixListener will generate a Linux error 9 (Bad file number), as checked below.
54
+ unsafe {
55
+ self . listener = Some ( UnixListener :: from_raw_fd ( 3 ) ) ;
56
+ }
57
+ } else {
58
+ let socket = Path :: new ( SOCKET_PATH ) ;
47
59
48
- if socket. exists ( ) {
49
- fs:: remove_file ( & socket) . unwrap ( ) ;
50
- }
60
+ if socket. exists ( ) {
61
+ fs:: remove_file ( & socket) . unwrap ( ) ;
62
+ }
51
63
52
- let listener_val = match UnixListener :: bind ( SOCKET_PATH ) {
53
- Ok ( listener) => listener,
54
- Err ( err) => panic ! ( err) ,
55
- } ;
64
+ let listener_val = match UnixListener :: bind ( SOCKET_PATH ) {
65
+ Ok ( listener) => listener,
66
+ Err ( err) => panic ! ( err) ,
67
+ } ;
56
68
57
- // Set the socket as non-blocking.
58
- listener_val
59
- . set_nonblocking ( true )
60
- . expect ( "Could not set the socket as non-blocking" ) ;
69
+ // Set the socket as non-blocking.
70
+ listener_val
71
+ . set_nonblocking ( true )
72
+ . expect ( "Could not set the socket as non-blocking" ) ;
61
73
62
- self . listener = Some ( listener_val) ;
74
+ self . listener = Some ( listener_val) ;
75
+ }
63
76
}
64
77
}
65
78
@@ -84,6 +97,16 @@ impl Listen for DomainSocketListener {
84
97
}
85
98
}
86
99
Err ( err) => {
100
+ if cfg ! ( feature = "systemd-daemon" ) {
101
+ // When run as a systemd daemon, a file descriptor mapping to the Domain Socket
102
+ // should have been passed to this process.
103
+ if let Some ( os_error) = err. raw_os_error ( ) {
104
+ // On Linux, 9 is EBADF (Bad file number)
105
+ if os_error == 9 {
106
+ panic ! ( "The Unix Domain Socket file descriptor (number 3) should have been given to this process." ) ;
107
+ }
108
+ }
109
+ }
87
110
// Check if the error is because no connections are currently present.
88
111
if err. kind ( ) != ErrorKind :: WouldBlock {
89
112
// Only log the real errors.
0 commit comments