1 #define PY_SSIZE_T_CLEAN 2 #include "Python.h" 3 #include "structmember.h" 4 5 #define PY_STRING_LENGTH_MAX PY_SSIZE_T_MAX 6 7 #include <sys/ipc.h> 8 #include <sys/shm.h> 9 #include <sys/sem.h> 10 #include <sys/msg.h> 11 12 #include "probe_results.h" 13 14 /* Struct to contain a key which can be None */ 15 typedef struct { 16 int is_none; 17 key_t value; 18 } NoneableKey; 19 20 21 /* These identifiers are prefixed with SVIFP_ which stands for SysV Ipc 22 For Python. It's really just a random string of letters to prevent clashes 23 with other constants (as happens with SHM_SIZE on AIX). 24 */ 25 enum GET_SET_IDENTIFIERS { 26 SVIFP_IPC_PERM_UID = 1, 27 SVIFP_IPC_PERM_GID, 28 SVIFP_IPC_PERM_CUID, 29 SVIFP_IPC_PERM_CGID, 30 SVIFP_IPC_PERM_MODE, 31 SVIFP_SEM_OTIME, 32 SVIFP_SHM_SIZE, 33 SVIFP_SHM_LAST_ATTACH_TIME, 34 SVIFP_SHM_LAST_DETACH_TIME, 35 SVIFP_SHM_LAST_CHANGE_TIME, 36 SVIFP_SHM_CREATOR_PID, 37 SVIFP_SHM_LAST_AT_DT_PID, 38 SVIFP_SHM_NUMBER_ATTACHED, 39 SVIFP_MQ_LAST_SEND_TIME, 40 SVIFP_MQ_LAST_RECEIVE_TIME, 41 SVIFP_MQ_LAST_CHANGE_TIME, 42 SVIFP_MQ_CURRENT_MESSAGES, 43 SVIFP_MQ_QUEUE_BYTES_MAX, 44 SVIFP_MQ_LAST_SEND_PID, 45 SVIFP_MQ_LAST_RECEIVE_PID 46 }; 47 48 // Shorthand for lazy typists like me 49 #define IPC_CREX (IPC_CREAT | IPC_EXCL) 50 51 #ifdef SYSV_IPC_DEBUG 52 #define DPRINTF(fmt, args...) fprintf(stderr, "+++ " fmt, ## args) 53 #else 54 #define DPRINTF(fmt, args...) 55 #endif 56 57 /* ************************************************************************** 58 I have to do some guessing about types, mostly with regard to key_t. Since I 59 schlep these values back and forth between C and Python, I need to know 60 approximately what types these represent so that I can call the appropriate 61 Python function to convert them to Python values (e.g. PyInt_FromLong(), 62 PyFloat_FromDouble(), etc.) 63 64 For most of these types the SUSv3 specification states that they're 65 integer-ish which means I can stuff them into a long and not worry. The macros 66 below safely convert each type and above each macro I document why my type 67 assumptions are safe. 68 69 Unfortunately, key_t is an exception. The SUSv3 specification doesn't get more 70 detailed than saying it is "arithmetic", which includes signed and unsigned 71 short, int, long, long long, float and double (but thankfully excludes 72 pointers). I feel I can safely ignore long long since support for it is far 73 from ubiquitous. 74 75 Ideally I would cast key_t to double and call PyWhatever_FromDouble() when 76 sending values to Python. Representing it as a double would ensure no data 77 loss regardless of whether it is typedef-ed as int, long, float, etc. 78 79 In practice, this would be awkward. I have yet to see a platform where 80 key_t is not integer-ish, so most or all users of this library would be 81 surprised if it returned keys as floats. 82 83 So I store keys as key_t types and cast them to long when Python forces 84 me to be specific. The two disadvantages to this are, (1) if any platforms 85 typedef key_t as a float or double, this code will break, and (2) KEY_MIN 86 and KEY_MAX don't represent the real min and max of keys. 87 88 Point #1 is mitigated somewhat because if any OS typedefs key_t as float or 89 double, this code should complain loudly during compilation. 90 91 Typedefs of key_t (for 32 bit systems): 92 OpenSolaris 2008.11 - int 93 OS X 10.5.8 - __int32_t (int) 94 Ubuntu 9.04 - int 95 Freebsd - l_int (int) 96 ************************************************************************** */ 97 98 99 // key_t is guaranteed to be an arithmetic type. Some earlier versions 100 // of the standard didn't guarantee that it was arithmetic; the standard was 101 // changed to guarantee that it *is* arithmetic. 102 // ref: http://pubs.opengroup.org/onlinepubs/009696899/functions/xsh_chap02_12.html 103 // I assume it is a long; see comment above. 104 // Some functions return (key_t)-1, so I guess this has to be a signed type. 105 // ref: http://www.opengroup.org/austin/interps/doc.tpl?gdid=6226 106 #define KEY_T_TO_PY(key) PyLong_FromLong(key) 107 108 // SUSv3 guarantees a uid_t to be an integer type. Some functions return 109 // (uid_t)-1, so I guess this has to be a signed type. 110 // ref: http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html 111 // ref: http://www.opengroup.org/onlinepubs/9699919799/functions/chown.html 112 #define UID_T_TO_PY(uid) PyLong_FromLong(uid) 113 114 // SUSv3 guarantees a gid_t to be an integer type. Some functions return 115 // (gid_t)-1, so I guess this has to be a signed type. 116 // ref: http://www.opengroup.org/onlinepubs/009695399/basedefs/sys/types.h.html 117 #define GID_T_TO_PY(gid) PyLong_FromLong(gid) 118 119 // I'm not sure what guarantees SUSv3 makes about a mode_t, but param 3 of 120 // shmget() is an int that contains flags in addition to the mode, so 121 // mode must be able to fit into an int. 122 // ref: http://www.opengroup.org/onlinepubs/009695399/functions/shmget.html 123 #define MODE_T_TO_PY(mode) PyLong_FromLong(mode) 124 125 // I'm not sure what guarantees SUSv3 makes about a time_t, but the times 126 // I deal with here are all guaranteed to be after 1 Jan 1970 which means 127 // they'll always be positive numbers. A ulong sounds appropriate to me, 128 // and Python agrees in posixmodule.c. 129 #define TIME_T_TO_PY(time) PyLong_FromUnsignedLong(time) 130 131 // C89 guarantees a size_t to be unsigned and fit into a ulong or smaller. 132 #define SIZE_T_TO_PY(size) PyLong_FromUnsignedLong(size) 133 134 // SUSv3 guarantees a pid_t to be a signed integer type. Some functions 135 // return (pid_t)-1 so I guess this has to be signed. 136 // ref: http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/types.h.html#tag_13_67 137 #define PID_T_TO_PY(pid) PyLong_FromLong(pid) 138 139 // The SUS guarantees a msglen_t to be an unsigned integer type. 140 // Ditto: msgqnum_t. 141 // ref: http://www.opengroup.org/onlinepubs/000095399/basedefs/sys/msg.h.html 142 #define MSGLEN_T_TO_PY(msglen) PyLong_FromUnsignedLong(msglen) 143 #define MSGQNUM_T_TO_PY(msgqnum) PyLong_FromUnsignedLong(msgqnum) 144 145 /* Utility functions */ 146 key_t get_random_key(void); 147 int convert_key_param(PyObject *, void *); 148 149 /* Custom Exceptions/Errors */ 150 extern PyObject *pBaseException; 151 extern PyObject *pInternalException; 152 extern PyObject *pPermissionsException; 153 extern PyObject *pExistentialException; 154 extern PyObject *pBusyException; 155 extern PyObject *pNotAttachedException; 156