1 /*
2  * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  *
6  * Functions specific to all POSIX compliant platforms.
7  */
8 
9 #include <Python.h>
10 #include <errno.h>
11 #include <stdlib.h>
12 #include <sys/resource.h>
13 #include <sys/types.h>
14 #include <signal.h>
15 #include <sys/socket.h>
16 #include <sys/ioctl.h>
17 #include <net/if.h>
18 #include <unistd.h>
19 
20 #ifdef PSUTIL_SUNOS10
21     #include "arch/solaris/v10/ifaddrs.h"
22 #elif PSUTIL_AIX
23     #include "arch/aix/ifaddrs.h"
24 #else
25     #include <ifaddrs.h>
26 #endif
27 
28 #if defined(PSUTIL_LINUX)
29     #include <netdb.h>
30     #include <linux/types.h>
31     #include <linux/if_packet.h>
32 #endif
33 #if defined(PSUTIL_BSD) || defined(PSUTIL_OSX)
34     #include <netdb.h>
35     #include <netinet/in.h>
36     #include <net/if_dl.h>
37     #include <sys/sockio.h>
38     #include <net/if_media.h>
39     #include <net/if.h>
40 #endif
41 #if defined(PSUTIL_SUNOS)
42     #include <netdb.h>
43     #include <sys/sockio.h>
44 #endif
45 #if defined(PSUTIL_AIX)
46     #include <netdb.h>
47 #endif
48 #if defined(PSUTIL_LINUX) || defined(PSUTIL_FREEBSD) || defined(PSUTIL_DRAGONFLY)
49     #include <sys/resource.h>
50 #endif
51 
52 #include "_psutil_common.h"
53 
54 
55 // ====================================================================
56 // --- Utils
57 // ====================================================================
58 
59 
60 /*
61  * From "man getpagesize" on Linux, https://linux.die.net/man/2/getpagesize:
62  *
63  * > In SUSv2 the getpagesize() call is labeled LEGACY, and in POSIX.1-2001
64  * > it has been dropped.
65  * > Portable applications should employ sysconf(_SC_PAGESIZE) instead
66  * > of getpagesize().
67  * > Most systems allow the synonym _SC_PAGE_SIZE for _SC_PAGESIZE.
68  * > Whether getpagesize() is present as a Linux system call depends on the
69  * > architecture.
70  */
71 long
psutil_getpagesize(void)72 psutil_getpagesize(void) {
73 #ifdef _SC_PAGESIZE
74     // recommended POSIX
75     return sysconf(_SC_PAGESIZE);
76 #elif _SC_PAGE_SIZE
77     // alias
78     return sysconf(_SC_PAGE_SIZE);
79 #else
80     // legacy
81     return (long) getpagesize();
82 #endif
83 }
84 
85 
86 /*
87  * Check if PID exists. Return values:
88  * 1: exists
89  * 0: does not exist
90  * -1: error (Python exception is set)
91  */
92 int
psutil_pid_exists(pid_t pid)93 psutil_pid_exists(pid_t pid) {
94     int ret;
95 
96     // No negative PID exists, plus -1 is an alias for sending signal
97     // too all processes except system ones. Not what we want.
98     if (pid < 0)
99         return 0;
100 
101     // As per "man 2 kill" PID 0 is an alias for sending the signal to
102     // every process in the process group of the calling process.
103     // Not what we want. Some platforms have PID 0, some do not.
104     // We decide that at runtime.
105     if (pid == 0) {
106 #if defined(PSUTIL_LINUX) || defined(PSUTIL_FREEBSD) || defined(PSUTIL_DRAGONFLY)
107         return 0;
108 #else
109         return 1;
110 #endif
111     }
112 
113     ret = kill(pid , 0);
114     if (ret == 0)
115         return 1;
116     else {
117         if (errno == ESRCH) {
118             // ESRCH == No such process
119             return 0;
120         }
121         else if (errno == EPERM) {
122             // EPERM clearly indicates there's a process to deny
123             // access to.
124             return 1;
125         }
126         else {
127             // According to "man 2 kill" possible error values are
128             // (EINVAL, EPERM, ESRCH) therefore we should never get
129             // here. If we do let's be explicit in considering this
130             // an error.
131             PyErr_SetFromErrno(PyExc_OSError);
132             return -1;
133         }
134     }
135 }
136 
137 
138 /*
139  * Utility used for those syscalls which do not return a meaningful
140  * error that we can translate into an exception which makes sense.
141  * As such, we'll have to guess.
142  * On UNIX, if errno is set, we return that one (OSError).
143  * Else, if PID does not exist we assume the syscall failed because
144  * of that so we raise NoSuchProcess.
145  * If none of this is true we giveup and raise RuntimeError(msg).
146  * This will always set a Python exception and return NULL.
147  */
148 void
psutil_raise_for_pid(long pid,char * syscall)149 psutil_raise_for_pid(long pid, char *syscall) {
150     if (errno != 0)  // unlikely
151         PyErr_SetFromOSErrnoWithSyscall(syscall);
152     else if (psutil_pid_exists(pid) == 0)
153         NoSuchProcess(syscall);
154     else
155         PyErr_Format(PyExc_RuntimeError, "%s syscall failed", syscall);
156 }
157 
158 
159 // ====================================================================
160 // --- Python wrappers
161 // ====================================================================
162 
163 
164 // Exposed so we can test it against Python's stdlib.
165 static PyObject *
psutil_getpagesize_pywrapper(PyObject * self,PyObject * args)166 psutil_getpagesize_pywrapper(PyObject *self, PyObject *args) {
167     return Py_BuildValue("l", psutil_getpagesize());
168 }
169 
170 
171 /*
172  * Given a PID return process priority as a Python integer.
173  */
174 static PyObject *
psutil_posix_getpriority(PyObject * self,PyObject * args)175 psutil_posix_getpriority(PyObject *self, PyObject *args) {
176     pid_t pid;
177     int priority;
178     errno = 0;
179 
180     if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
181         return NULL;
182 
183 #ifdef PSUTIL_OSX
184     priority = getpriority(PRIO_PROCESS, (id_t)pid);
185 #else
186     priority = getpriority(PRIO_PROCESS, pid);
187 #endif
188     if (errno != 0)
189         return PyErr_SetFromErrno(PyExc_OSError);
190     return Py_BuildValue("i", priority);
191 }
192 
193 
194 /*
195  * Given a PID and a value change process priority.
196  */
197 static PyObject *
psutil_posix_setpriority(PyObject * self,PyObject * args)198 psutil_posix_setpriority(PyObject *self, PyObject *args) {
199     pid_t pid;
200     int priority;
201     int retval;
202 
203     if (! PyArg_ParseTuple(args, _Py_PARSE_PID "i", &pid, &priority))
204         return NULL;
205 
206 #ifdef PSUTIL_OSX
207     retval = setpriority(PRIO_PROCESS, (id_t)pid, priority);
208 #else
209     retval = setpriority(PRIO_PROCESS, pid, priority);
210 #endif
211     if (retval == -1)
212         return PyErr_SetFromErrno(PyExc_OSError);
213     Py_RETURN_NONE;
214 }
215 
216 
217 /*
218  * Translate a sockaddr struct into a Python string.
219  * Return None if address family is not AF_INET* or AF_PACKET.
220  */
221 static PyObject *
psutil_convert_ipaddr(struct sockaddr * addr,int family)222 psutil_convert_ipaddr(struct sockaddr *addr, int family) {
223     char buf[NI_MAXHOST];
224     int err;
225     int addrlen;
226     size_t n;
227     size_t len;
228     const char *data;
229     char *ptr;
230 
231     if (addr == NULL) {
232         Py_INCREF(Py_None);
233         return Py_None;
234     }
235     else if (family == AF_INET || family == AF_INET6) {
236         if (family == AF_INET)
237             addrlen = sizeof(struct sockaddr_in);
238         else
239             addrlen = sizeof(struct sockaddr_in6);
240         err = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0,
241                           NI_NUMERICHOST);
242         if (err != 0) {
243             // XXX we get here on FreeBSD when processing 'lo' / AF_INET6
244             // broadcast. Not sure what to do other than returning None.
245             // ifconfig does not show anything BTW.
246             // PyErr_Format(PyExc_RuntimeError, gai_strerror(err));
247             // return NULL;
248             Py_INCREF(Py_None);
249             return Py_None;
250         }
251         else {
252             return Py_BuildValue("s", buf);
253         }
254     }
255 #ifdef PSUTIL_LINUX
256     else if (family == AF_PACKET) {
257         struct sockaddr_ll *lladdr = (struct sockaddr_ll *)addr;
258         len = lladdr->sll_halen;
259         data = (const char *)lladdr->sll_addr;
260     }
261 #elif defined(PSUTIL_BSD) || defined(PSUTIL_OSX) || defined(PSUTIL_DRAGONFLY)
262     else if (addr->sa_family == AF_LINK) {
263         // Note: prior to Python 3.4 socket module does not expose
264         // AF_LINK so we'll do.
265         struct sockaddr_dl *dladdr = (struct sockaddr_dl *)addr;
266         len = dladdr->sdl_alen;
267         data = LLADDR(dladdr);
268     }
269 #endif
270     else {
271         // unknown family
272         Py_INCREF(Py_None);
273         return Py_None;
274     }
275 
276     // AF_PACKET or AF_LINK
277     if (len > 0) {
278         ptr = buf;
279         for (n = 0; n < len; ++n) {
280             sprintf(ptr, "%02x:", data[n] & 0xff);
281             ptr += 3;
282         }
283         *--ptr = '\0';
284         return Py_BuildValue("s", buf);
285     }
286     else {
287         Py_INCREF(Py_None);
288         return Py_None;
289     }
290 }
291 
292 
293 /*
294  * Return NICs information a-la ifconfig as a list of tuples.
295  * TODO: on Solaris we won't get any MAC address.
296  */
297 static PyObject*
psutil_net_if_addrs(PyObject * self,PyObject * args)298 psutil_net_if_addrs(PyObject* self, PyObject* args) {
299     struct ifaddrs *ifaddr, *ifa;
300     int family;
301 
302     PyObject *py_retlist = PyList_New(0);
303     PyObject *py_tuple = NULL;
304     PyObject *py_address = NULL;
305     PyObject *py_netmask = NULL;
306     PyObject *py_broadcast = NULL;
307     PyObject *py_ptp = NULL;
308 
309     if (py_retlist == NULL)
310         return NULL;
311     if (getifaddrs(&ifaddr) == -1) {
312         PyErr_SetFromErrno(PyExc_OSError);
313         goto error;
314     }
315 
316     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
317         if (!ifa->ifa_addr)
318             continue;
319         family = ifa->ifa_addr->sa_family;
320         py_address = psutil_convert_ipaddr(ifa->ifa_addr, family);
321         // If the primary address can't be determined just skip it.
322         // I've never seen this happen on Linux but I did on FreeBSD.
323         if (py_address == Py_None)
324             continue;
325         if (py_address == NULL)
326             goto error;
327         py_netmask = psutil_convert_ipaddr(ifa->ifa_netmask, family);
328         if (py_netmask == NULL)
329             goto error;
330 
331         if (ifa->ifa_flags & IFF_BROADCAST) {
332             py_broadcast = psutil_convert_ipaddr(ifa->ifa_broadaddr, family);
333             Py_INCREF(Py_None);
334             py_ptp = Py_None;
335         }
336         else if (ifa->ifa_flags & IFF_POINTOPOINT) {
337             py_ptp = psutil_convert_ipaddr(ifa->ifa_dstaddr, family);
338             Py_INCREF(Py_None);
339             py_broadcast = Py_None;
340         }
341         else {
342             Py_INCREF(Py_None);
343             Py_INCREF(Py_None);
344             py_broadcast = Py_None;
345             py_ptp = Py_None;
346         }
347 
348         if ((py_broadcast == NULL) || (py_ptp == NULL))
349             goto error;
350         py_tuple = Py_BuildValue(
351             "(siOOOO)",
352             ifa->ifa_name,
353             family,
354             py_address,
355             py_netmask,
356             py_broadcast,
357             py_ptp
358         );
359 
360         if (! py_tuple)
361             goto error;
362         if (PyList_Append(py_retlist, py_tuple))
363             goto error;
364         Py_CLEAR(py_tuple);
365         Py_CLEAR(py_address);
366         Py_CLEAR(py_netmask);
367         Py_CLEAR(py_broadcast);
368         Py_CLEAR(py_ptp);
369     }
370 
371     freeifaddrs(ifaddr);
372     return py_retlist;
373 
374 error:
375     if (ifaddr != NULL)
376         freeifaddrs(ifaddr);
377     Py_DECREF(py_retlist);
378     Py_XDECREF(py_tuple);
379     Py_XDECREF(py_address);
380     Py_XDECREF(py_netmask);
381     Py_XDECREF(py_broadcast);
382     Py_XDECREF(py_ptp);
383     return NULL;
384 }
385 
386 
387 /*
388  * Return NIC MTU. References:
389  * http://www.i-scream.org/libstatgrab/
390  */
391 static PyObject *
psutil_net_if_mtu(PyObject * self,PyObject * args)392 psutil_net_if_mtu(PyObject *self, PyObject *args) {
393     char *nic_name;
394     int sock = -1;
395     int ret;
396 #ifdef PSUTIL_SUNOS10
397     struct lifreq lifr;
398 #else
399     struct ifreq ifr;
400 #endif
401 
402     if (! PyArg_ParseTuple(args, "s", &nic_name))
403         return NULL;
404 
405     sock = socket(AF_INET, SOCK_DGRAM, 0);
406     if (sock == -1)
407         goto error;
408 
409 #ifdef PSUTIL_SUNOS10
410     PSUTIL_STRNCPY(lifr.lifr_name, nic_name, sizeof(lifr.lifr_name));
411     ret = ioctl(sock, SIOCGIFMTU, &lifr);
412 #else
413     PSUTIL_STRNCPY(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name));
414     ret = ioctl(sock, SIOCGIFMTU, &ifr);
415 #endif
416     if (ret == -1)
417         goto error;
418     close(sock);
419 
420 #ifdef PSUTIL_SUNOS10
421     return Py_BuildValue("i", lifr.lifr_mtu);
422 #else
423     return Py_BuildValue("i", ifr.ifr_mtu);
424 #endif
425 
426 error:
427     if (sock != -1)
428         close(sock);
429     return PyErr_SetFromErrno(PyExc_OSError);
430 }
431 
432 
433 /*
434  * Inspect NIC flags, returns a bool indicating whether the NIC is
435  * running. References:
436  * http://www.i-scream.org/libstatgrab/
437  */
438 static PyObject *
psutil_net_if_is_running(PyObject * self,PyObject * args)439 psutil_net_if_is_running(PyObject *self, PyObject *args) {
440     char *nic_name;
441     int sock = -1;
442     int ret;
443     struct ifreq ifr;
444 
445     if (! PyArg_ParseTuple(args, "s", &nic_name))
446         return NULL;
447 
448     sock = socket(AF_INET, SOCK_DGRAM, 0);
449     if (sock == -1)
450         goto error;
451 
452     PSUTIL_STRNCPY(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name));
453     ret = ioctl(sock, SIOCGIFFLAGS, &ifr);
454     if (ret == -1)
455         goto error;
456 
457     close(sock);
458     if ((ifr.ifr_flags & IFF_RUNNING) != 0)
459         return Py_BuildValue("O", Py_True);
460     else
461         return Py_BuildValue("O", Py_False);
462 
463 error:
464     if (sock != -1)
465         close(sock);
466     return PyErr_SetFromErrno(PyExc_OSError);
467 }
468 
469 
470 /*
471  * net_if_stats() macOS/BSD implementation.
472  */
473 #if defined(PSUTIL_BSD) || defined(PSUTIL_OSX)
474 
psutil_get_nic_speed(int ifm_active)475 int psutil_get_nic_speed(int ifm_active) {
476     // Determine NIC speed. Taken from:
477     // http://www.i-scream.org/libstatgrab/
478     // Assuming only ETHER devices
479     switch(IFM_TYPE(ifm_active)) {
480         case IFM_ETHER:
481             switch(IFM_SUBTYPE(ifm_active)) {
482 #if defined(IFM_HPNA_1) && ((!defined(IFM_10G_LR)) \
483     || (IFM_10G_LR != IFM_HPNA_1))
484                 // HomePNA 1.0 (1Mb/s)
485                 case(IFM_HPNA_1):
486                     return 1;
487 #endif
488                 // 10 Mbit
489                 case(IFM_10_T):  // 10BaseT - RJ45
490                 case(IFM_10_2):  // 10Base2 - Thinnet
491                 case(IFM_10_5):  // 10Base5 - AUI
492                 case(IFM_10_STP):  // 10BaseT over shielded TP
493                 case(IFM_10_FL):  // 10baseFL - Fiber
494                     return 10;
495                 // 100 Mbit
496                 case(IFM_100_TX):  // 100BaseTX - RJ45
497                 case(IFM_100_FX):  // 100BaseFX - Fiber
498                 case(IFM_100_T4):  // 100BaseT4 - 4 pair cat 3
499                 case(IFM_100_VG):  // 100VG-AnyLAN
500                 case(IFM_100_T2):  // 100BaseT2
501                     return 100;
502                 // 1000 Mbit
503                 case(IFM_1000_SX):  // 1000BaseSX - multi-mode fiber
504                 case(IFM_1000_LX):  // 1000baseLX - single-mode fiber
505                 case(IFM_1000_CX):  // 1000baseCX - 150ohm STP
506 #if defined(IFM_1000_TX) && !defined(PSUTIL_OPENBSD)
507                 // FreeBSD 4 and others (but NOT OpenBSD) -> #define IFM_1000_T in net/if_media.h
508                 case(IFM_1000_TX):
509 #endif
510 #ifdef IFM_1000_FX
511                 case(IFM_1000_FX):
512 #endif
513 #ifdef IFM_1000_T
514                 case(IFM_1000_T):
515 #endif
516                     return 1000;
517 #if defined(IFM_10G_SR) || defined(IFM_10G_LR) || defined(IFM_10G_CX4) \
518          || defined(IFM_10G_T)
519 #ifdef IFM_10G_SR
520                 case(IFM_10G_SR):
521 #endif
522 #ifdef IFM_10G_LR
523                 case(IFM_10G_LR):
524 #endif
525 #ifdef IFM_10G_CX4
526                 case(IFM_10G_CX4):
527 #endif
528 #ifdef IFM_10G_TWINAX
529                 case(IFM_10G_TWINAX):
530 #endif
531 #ifdef IFM_10G_TWINAX_LONG
532                 case(IFM_10G_TWINAX_LONG):
533 #endif
534 #ifdef IFM_10G_T
535                 case(IFM_10G_T):
536 #endif
537                     return 10000;
538 #endif
539 #if defined(IFM_2500_SX)
540 #ifdef IFM_2500_SX
541                 case(IFM_2500_SX):
542 #endif
543                     return 2500;
544 #endif // any 2.5GBit stuff...
545                 // We don't know what it is
546                 default:
547                     return 0;
548             }
549             break;
550 
551 #ifdef IFM_TOKEN
552         case IFM_TOKEN:
553             switch(IFM_SUBTYPE(ifm_active)) {
554                 case IFM_TOK_STP4:  // Shielded twisted pair 4m - DB9
555                 case IFM_TOK_UTP4:  // Unshielded twisted pair 4m - RJ45
556                     return 4;
557                 case IFM_TOK_STP16:  // Shielded twisted pair 16m - DB9
558                 case IFM_TOK_UTP16:  // Unshielded twisted pair 16m - RJ45
559                     return 16;
560 #if defined(IFM_TOK_STP100) || defined(IFM_TOK_UTP100)
561 #ifdef IFM_TOK_STP100
562                 case IFM_TOK_STP100:  // Shielded twisted pair 100m - DB9
563 #endif
564 #ifdef IFM_TOK_UTP100
565                 case IFM_TOK_UTP100:  // Unshielded twisted pair 100m - RJ45
566 #endif
567                     return 100;
568 #endif
569                 // We don't know what it is
570                 default:
571                     return 0;
572             }
573             break;
574 #endif
575 
576 #ifdef IFM_FDDI
577         case IFM_FDDI:
578             switch(IFM_SUBTYPE(ifm_active)) {
579                 // We don't know what it is
580                 default:
581                     return 0;
582             }
583             break;
584 #endif
585         case IFM_IEEE80211:
586             switch(IFM_SUBTYPE(ifm_active)) {
587                 case IFM_IEEE80211_FH1:  // Frequency Hopping 1Mbps
588                 case IFM_IEEE80211_DS1:  // Direct Sequence 1Mbps
589                     return 1;
590                 case IFM_IEEE80211_FH2:  // Frequency Hopping 2Mbps
591                 case IFM_IEEE80211_DS2:  // Direct Sequence 2Mbps
592                     return 2;
593                 case IFM_IEEE80211_DS5:  // Direct Sequence 5Mbps
594                     return 5;
595                 case IFM_IEEE80211_DS11:  // Direct Sequence 11Mbps
596                     return 11;
597                 case IFM_IEEE80211_DS22:  // Direct Sequence 22Mbps
598                     return 22;
599                 // We don't know what it is
600                 default:
601                     return 0;
602             }
603             break;
604 
605         default:
606             return 0;
607     }
608 }
609 
610 
611 /*
612  * Return stats about a particular network interface.
613  * References:
614  * http://www.i-scream.org/libstatgrab/
615  */
616 static PyObject *
psutil_net_if_duplex_speed(PyObject * self,PyObject * args)617 psutil_net_if_duplex_speed(PyObject *self, PyObject *args) {
618     char *nic_name;
619     int sock = -1;
620     int ret;
621     int duplex;
622     int speed;
623     struct ifreq ifr;
624     struct ifmediareq ifmed;
625 
626     if (! PyArg_ParseTuple(args, "s", &nic_name))
627         return NULL;
628 
629     sock = socket(AF_INET, SOCK_DGRAM, 0);
630     if (sock == -1)
631         return PyErr_SetFromErrno(PyExc_OSError);
632     PSUTIL_STRNCPY(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name));
633 
634     // speed / duplex
635     memset(&ifmed, 0, sizeof(struct ifmediareq));
636     strlcpy(ifmed.ifm_name, nic_name, sizeof(ifmed.ifm_name));
637     ret = ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmed);
638     if (ret == -1) {
639         speed = 0;
640         duplex = 0;
641     }
642     else {
643         speed = psutil_get_nic_speed(ifmed.ifm_active);
644         if ((ifmed.ifm_active | IFM_FDX) == ifmed.ifm_active)
645             duplex = 2;
646         else if ((ifmed.ifm_active | IFM_HDX) == ifmed.ifm_active)
647             duplex = 1;
648         else
649             duplex = 0;
650     }
651 
652     close(sock);
653     return Py_BuildValue("[ii]", duplex, speed);
654 }
655 #endif  // net_if_stats() macOS/BSD implementation
656 
657 
658 #ifdef __cplusplus
659 extern "C" {
660 #endif
661 
662 
663 /*
664  * define the psutil C module methods and initialize the module.
665  */
666 static PyMethodDef mod_methods[] = {
667     {"getpriority", psutil_posix_getpriority, METH_VARARGS,
668      "Return process priority"},
669     {"setpriority", psutil_posix_setpriority, METH_VARARGS,
670      "Set process priority"},
671     {"net_if_addrs", psutil_net_if_addrs, METH_VARARGS,
672      "Retrieve NICs information"},
673     {"net_if_mtu", psutil_net_if_mtu, METH_VARARGS,
674      "Retrieve NIC MTU"},
675     {"net_if_is_running", psutil_net_if_is_running, METH_VARARGS,
676      "Return True if the NIC is running."},
677     {"getpagesize", psutil_getpagesize_pywrapper, METH_VARARGS,
678      "Return memory page size."},
679 #if defined(PSUTIL_BSD) || defined(PSUTIL_OSX)
680     {"net_if_duplex_speed", psutil_net_if_duplex_speed, METH_VARARGS,
681      "Return NIC stats."},
682 #endif
683     {NULL, NULL, 0, NULL}
684 };
685 
686 
687 #if PY_MAJOR_VERSION >= 3
688     #define INITERR return NULL
689 
690     static struct PyModuleDef moduledef = {
691         PyModuleDef_HEAD_INIT,
692         "_psutil_posix",
693         NULL,
694         -1,
695         mod_methods,
696         NULL,
697         NULL,
698         NULL,
699         NULL
700     };
701 
PyInit__psutil_posix(void)702     PyObject *PyInit__psutil_posix(void)
703 #else  /* PY_MAJOR_VERSION */
704     #define INITERR return
705 
706     void init_psutil_posix(void)
707 #endif  /* PY_MAJOR_VERSION */
708 {
709 #if PY_MAJOR_VERSION >= 3
710     PyObject *mod = PyModule_Create(&moduledef);
711 #else
712     PyObject *mod = Py_InitModule("_psutil_posix", mod_methods);
713 #endif
714     if (mod == NULL)
715         INITERR;
716 
717 #if defined(PSUTIL_BSD) || \
718         defined(PSUTIL_OSX) || \
719         defined(PSUTIL_SUNOS) || \
720         defined(PSUTIL_AIX)
721     if (PyModule_AddIntConstant(mod, "AF_LINK", AF_LINK)) INITERR;
722 #endif
723 
724 #if defined(PSUTIL_LINUX) || defined(PSUTIL_FREEBSD) || defined(PSUTIL_DRAGONFLY)
725     PyObject *v;
726 
727 #ifdef RLIMIT_AS
728     if (PyModule_AddIntConstant(mod, "RLIMIT_AS", RLIMIT_AS)) INITERR;
729 #endif
730 
731 #ifdef RLIMIT_CORE
732     if (PyModule_AddIntConstant(mod, "RLIMIT_CORE", RLIMIT_CORE)) INITERR;
733 #endif
734 
735 #ifdef RLIMIT_CPU
736     if (PyModule_AddIntConstant(mod, "RLIMIT_CPU", RLIMIT_CPU)) INITERR;
737 #endif
738 
739 #ifdef RLIMIT_DATA
740     if (PyModule_AddIntConstant(mod, "RLIMIT_DATA", RLIMIT_DATA)) INITERR;
741 #endif
742 
743 #ifdef RLIMIT_FSIZE
744     if (PyModule_AddIntConstant(mod, "RLIMIT_FSIZE", RLIMIT_FSIZE)) INITERR;
745 #endif
746 
747 #ifdef RLIMIT_MEMLOCK
748     if (PyModule_AddIntConstant(mod, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK)) INITERR;
749 #endif
750 
751 #ifdef RLIMIT_NOFILE
752     if (PyModule_AddIntConstant(mod, "RLIMIT_NOFILE", RLIMIT_NOFILE)) INITERR;
753 #endif
754 
755 #ifdef RLIMIT_NPROC
756     if (PyModule_AddIntConstant(mod, "RLIMIT_NPROC", RLIMIT_NPROC)) INITERR;
757 #endif
758 
759 #ifdef RLIMIT_RSS
760     if (PyModule_AddIntConstant(mod, "RLIMIT_RSS", RLIMIT_RSS)) INITERR;
761 #endif
762 
763 #ifdef RLIMIT_STACK
764     if (PyModule_AddIntConstant(mod, "RLIMIT_STACK", RLIMIT_STACK)) INITERR;
765 #endif
766 
767 // Linux specific
768 
769 #ifdef RLIMIT_LOCKS
770     if (PyModule_AddIntConstant(mod, "RLIMIT_LOCKS", RLIMIT_LOCKS)) INITERR;
771 #endif
772 
773 #ifdef RLIMIT_MSGQUEUE
774     if (PyModule_AddIntConstant(mod, "RLIMIT_MSGQUEUE", RLIMIT_MSGQUEUE)) INITERR;
775 #endif
776 
777 #ifdef RLIMIT_NICE
778     if (PyModule_AddIntConstant(mod, "RLIMIT_NICE", RLIMIT_NICE)) INITERR;
779 #endif
780 
781 #ifdef RLIMIT_RTPRIO
782     if (PyModule_AddIntConstant(mod, "RLIMIT_RTPRIO", RLIMIT_RTPRIO)) INITERR;
783 #endif
784 
785 #ifdef RLIMIT_RTTIME
786     if (PyModule_AddIntConstant(mod, "RLIMIT_RTTIME", RLIMIT_RTTIME)) INITERR;
787 #endif
788 
789 #ifdef RLIMIT_SIGPENDING
790     if (PyModule_AddIntConstant(mod, "RLIMIT_SIGPENDING", RLIMIT_SIGPENDING)) INITERR;
791 #endif
792 
793 // Free specific
794 
795 #ifdef RLIMIT_SWAP
796     if (PyModule_AddIntConstant(mod, "RLIMIT_SWAP", RLIMIT_SWAP)) INITERR;
797 #endif
798 
799 #ifdef RLIMIT_SBSIZE
800     if (PyModule_AddIntConstant(mod, "RLIMIT_SBSIZE", RLIMIT_SBSIZE)) INITERR;
801 #endif
802 
803 #ifdef RLIMIT_NPTS
804     if (PyModule_AddIntConstant(mod, "RLIMIT_NPTS", RLIMIT_NPTS)) INITERR;
805 #endif
806 
807 #if defined(HAVE_LONG_LONG)
808     if (sizeof(RLIM_INFINITY) > sizeof(long)) {
809         v = PyLong_FromLongLong((PY_LONG_LONG) RLIM_INFINITY);
810     } else
811 #endif
812     {
813         v = PyLong_FromLong((long) RLIM_INFINITY);
814     }
815     if (v) {
816         PyModule_AddObject(mod, "RLIM_INFINITY", v);
817     }
818 #endif  // defined(PSUTIL_LINUX) || defined(PSUTIL_FREEBSD)
819 
820     if (mod == NULL)
821         INITERR;
822 #if PY_MAJOR_VERSION >= 3
823     return mod;
824 #endif
825 }
826 
827 #ifdef __cplusplus
828 }
829 #endif
830