3232#include "pyutil.h"
3333#include "macro.h"
3434
35+ #if LIBSYSTEMD_VERSION >= 214
36+ # define HAVE_PID_NOTIFY
37+ # if LIBSYSTEMD_VERSION >= 219
38+ # define HAVE_PID_NOTIFY_WITH_FDS
39+ # endif
40+ #endif
41+
3542PyDoc_STRVAR (module__doc__ ,
3643 "Python interface to the libsystemd-daemon library.\n\n"
3744 "Provides _listen_fds, notify, booted, and is_* functions\n"
@@ -57,37 +64,99 @@ static PyObject* booted(PyObject *self, PyObject *args) {
5764 return PyBool_FromLong (r );
5865}
5966
67+ static inline void PyMem_Free_intp (int * * p ) {
68+ PyMem_Free (* p );
69+ }
70+
6071PyDoc_STRVAR (notify__doc__ ,
61- "notify(status, unset_environment=False) -> bool\n\n"
72+ "notify(status, unset_environment=False, pid=0, fds=None ) -> bool\n\n"
6273 "Send a message to the init system about a status change.\n"
6374 "Wraps sd_notify(3)." );
6475
6576static PyObject * notify (PyObject * self , PyObject * args , PyObject * keywds ) {
6677 int r ;
6778 const char * msg ;
68- int unset = false;
79+ int unset = false, n_fds ;
80+ int _pid = 0 ;
81+ pid_t pid ;
82+ PyObject * fds = NULL ;
83+ _cleanup_ (PyMem_Free_intp ) int * arr = NULL ;
6984
7085 static const char * const kwlist [] = {
7186 "status" ,
7287 "unset_environment" ,
88+ "pid" ,
89+ "fds" ,
7390 NULL ,
7491 };
7592#if PY_MAJOR_VERSION >=3 && PY_MINOR_VERSION >= 3
76- if (!PyArg_ParseTupleAndKeywords (args , keywds , "s|p :notify" ,
77- (char * * ) kwlist , & msg , & unset ))
93+ if (!PyArg_ParseTupleAndKeywords (args , keywds , "s|piO :notify" ,
94+ (char * * ) kwlist , & msg , & unset , & _pid , & fds ))
7895 return NULL ;
7996#else
8097 PyObject * obj = NULL ;
81- if (!PyArg_ParseTupleAndKeywords (args , keywds , "s|O :notify" ,
82- (char * * ) kwlist , & msg , & obj ))
98+ if (!PyArg_ParseTupleAndKeywords (args , keywds , "s|OiO :notify" ,
99+ (char * * ) kwlist , & msg , & obj , & _pid , & fds ))
83100 return NULL ;
84101 if (obj != NULL )
85102 unset = PyObject_IsTrue (obj );
86103 if (unset < 0 )
87104 return NULL ;
88105#endif
106+ pid = _pid ;
107+ if (pid < 0 || pid != _pid ) {
108+ PyErr_SetString (PyExc_OverflowError , "Bad pid_t" );
109+ return NULL ;
110+ }
111+
112+ if (fds != NULL ) {
113+ Py_ssize_t i , len ;
114+
115+ len = PySequence_Length (fds );
116+ if (len < 0 )
117+ return NULL ;
118+
119+ arr = PyMem_NEW (int , len );
120+ if (!fds )
121+ return NULL ;
122+
123+ for (i = 0 ; i < len ; i ++ ) {
124+ PyObject * item = PySequence_GetItem (fds , i );
125+ if (!item )
126+ return NULL ;
127+
128+ long value = PyLong_AsLong (item );
129+ if (PyErr_Occurred ())
130+ return NULL ;
131+
132+ arr [i ] = value ;
133+ if (arr [i ] != value ) {
134+ PyErr_SetString (PyExc_OverflowError , "Value to large for an integer" );
135+ return NULL ;
136+ }
137+ }
138+
139+ n_fds = len ;
140+ }
141+
142+ if (pid == 0 && fds == NULL )
143+ r = sd_notify (unset , msg );
144+ else if (fds == NULL ) {
145+ #ifdef HAVE_PID_NOTIFY
146+ r = sd_pid_notify (pid , unset , msg );
147+ #else
148+ PyErr_SetString (PyExc_NotImplementedError , "Compiled without support for sd_pid_notify" );
149+ return NULL ;
150+ #endif
151+ } else {
152+ #ifdef HAVE_PID_NOTIFY_WITH_FDS
153+ r = sd_pid_notify_with_fds (pid , unset , msg , arr , n_fds );
154+ #else
155+ PyErr_SetString (PyExc_NotImplementedError , "Compiled without support for sd_pid_notify_with_fds" );
156+ return NULL ;
157+ #endif
158+ }
89159
90- r = sd_notify (unset , msg );
91160 if (set_error (r , NULL , NULL ) < 0 )
92161 return NULL ;
93162
@@ -177,8 +246,8 @@ static PyObject* is_mq(PyObject *self, PyObject *args) {
177246 if (!PyArg_ParseTuple (args , "i|O&:_is_mq" ,
178247 & fd , Unicode_FSConverter , & _path ))
179248 return NULL ;
180- if (_path )
181- path = PyBytes_AsString (_path );
249+ if (_path )
250+ path = PyBytes_AsString (_path );
182251#else
183252 if (!PyArg_ParseTuple (args , "i|z:_is_mq" , & fd , & path ))
184253 return NULL ;
0 commit comments