|  | 
 | #include "Python.h" | 
 | #include "structseq.h" | 
 | #include <sys/resource.h> | 
 | #include <sys/time.h> | 
 | #include <string.h> | 
 | #include <errno.h> | 
 | /* for sysconf */ | 
 | #if defined(HAVE_UNISTD_H) | 
 | #include <unistd.h> | 
 | #endif | 
 |  | 
 | /* On some systems, these aren't in any header file. | 
 |    On others they are, with inconsistent prototypes. | 
 |    We declare the (default) return type, to shut up gcc -Wall; | 
 |    but we can't declare the prototype, to avoid errors | 
 |    when the header files declare it different. | 
 |    Worse, on some Linuxes, getpagesize() returns a size_t... */ | 
 |  | 
 | #define doubletime(TV) ((double)(TV).tv_sec + (TV).tv_usec * 0.000001) | 
 |  | 
 | static PyObject *ResourceError; | 
 |  | 
 | PyDoc_STRVAR(struct_rusage__doc__, | 
 | "struct_rusage: Result from getrusage.\n\n" | 
 | "This object may be accessed either as a tuple of\n" | 
 | "    (utime,stime,maxrss,ixrss,idrss,isrss,minflt,majflt,\n" | 
 | "    nswap,inblock,oublock,msgsnd,msgrcv,nsignals,nvcsw,nivcsw)\n" | 
 | "or via the attributes ru_utime, ru_stime, ru_maxrss, and so on."); | 
 |  | 
 | static PyStructSequence_Field struct_rusage_fields[] = { | 
 | 	{"ru_utime",	"user time used"}, | 
 | 	{"ru_stime",	"system time used"}, | 
 | 	{"ru_maxrss",	"max. resident set size"}, | 
 | 	{"ru_ixrss",	"shared memory size"}, | 
 | 	{"ru_idrss",	"unshared data size"}, | 
 | 	{"ru_isrss",	"unshared stack size"}, | 
 | 	{"ru_minflt",	"page faults not requiring I/O"}, | 
 | 	{"ru_majflt",	"page faults requiring I/O"}, | 
 | 	{"ru_nswap",	"number of swap outs"}, | 
 | 	{"ru_inblock",	"block input operations"}, | 
 | 	{"ru_oublock",	"block output operations"}, | 
 | 	{"ru_msgsnd",	"IPC messages sent"}, | 
 | 	{"ru_msgrcv",	"IPC messages received"}, | 
 | 	{"ru_nsignals",	"signals received"}, | 
 | 	{"ru_nvcsw",	"voluntary context switches"}, | 
 | 	{"ru_nivcsw",	"involuntary context switches"}, | 
 | 	{0} | 
 | }; | 
 |  | 
 | static PyStructSequence_Desc struct_rusage_desc = { | 
 | 	"resource.struct_rusage",	/* name */ | 
 | 	struct_rusage__doc__,	/* doc */ | 
 | 	struct_rusage_fields,	/* fields */ | 
 | 	16	/* n_in_sequence */ | 
 | }; | 
 |  | 
 | static int initialized; | 
 | static PyTypeObject StructRUsageType; | 
 |  | 
 | static PyObject * | 
 | resource_getrusage(PyObject *self, PyObject *args) | 
 | { | 
 | 	int who; | 
 | 	struct rusage ru; | 
 | 	PyObject *result; | 
 |  | 
 | 	if (!PyArg_ParseTuple(args, "i:getrusage", &who)) | 
 | 		return NULL; | 
 |  | 
 | 	if (getrusage(who, &ru) == -1) { | 
 | 		if (errno == EINVAL) { | 
 | 			PyErr_SetString(PyExc_ValueError, | 
 | 					"invalid who parameter"); | 
 | 			return NULL; | 
 | 		}  | 
 | 		PyErr_SetFromErrno(ResourceError); | 
 | 		return NULL; | 
 | 	} | 
 |  | 
 | 	result = PyStructSequence_New(&StructRUsageType); | 
 | 	if (!result) | 
 | 		return NULL; | 
 |  | 
 | 	PyStructSequence_SET_ITEM(result, 0, | 
 | 			PyFloat_FromDouble(doubletime(ru.ru_utime))); | 
 | 	PyStructSequence_SET_ITEM(result, 1, | 
 | 			PyFloat_FromDouble(doubletime(ru.ru_stime))); | 
 | 	PyStructSequence_SET_ITEM(result, 2, PyLong_FromLong(ru.ru_maxrss)); | 
 | 	PyStructSequence_SET_ITEM(result, 3, PyLong_FromLong(ru.ru_ixrss)); | 
 | 	PyStructSequence_SET_ITEM(result, 4, PyLong_FromLong(ru.ru_idrss)); | 
 | 	PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong(ru.ru_isrss)); | 
 | 	PyStructSequence_SET_ITEM(result, 6, PyLong_FromLong(ru.ru_minflt)); | 
 | 	PyStructSequence_SET_ITEM(result, 7, PyLong_FromLong(ru.ru_majflt)); | 
 | 	PyStructSequence_SET_ITEM(result, 8, PyLong_FromLong(ru.ru_nswap)); | 
 | 	PyStructSequence_SET_ITEM(result, 9, PyLong_FromLong(ru.ru_inblock)); | 
 | 	PyStructSequence_SET_ITEM(result, 10, PyLong_FromLong(ru.ru_oublock)); | 
 | 	PyStructSequence_SET_ITEM(result, 11, PyLong_FromLong(ru.ru_msgsnd)); | 
 | 	PyStructSequence_SET_ITEM(result, 12, PyLong_FromLong(ru.ru_msgrcv)); | 
 | 	PyStructSequence_SET_ITEM(result, 13, PyLong_FromLong(ru.ru_nsignals)); | 
 | 	PyStructSequence_SET_ITEM(result, 14, PyLong_FromLong(ru.ru_nvcsw)); | 
 | 	PyStructSequence_SET_ITEM(result, 15, PyLong_FromLong(ru.ru_nivcsw)); | 
 |  | 
 | 	if (PyErr_Occurred()) { | 
 | 		Py_DECREF(result); | 
 | 		return NULL; | 
 | 	} | 
 |  | 
 | 	return result; | 
 | } | 
 |  | 
 |  | 
 | static PyObject * | 
 | resource_getrlimit(PyObject *self, PyObject *args) | 
 | { | 
 | 	struct rlimit rl; | 
 | 	int resource; | 
 |  | 
 | 	if (!PyArg_ParseTuple(args, "i:getrlimit", &resource))  | 
 | 		return NULL; | 
 |  | 
 | 	if (resource < 0 || resource >= RLIM_NLIMITS) { | 
 | 		PyErr_SetString(PyExc_ValueError, | 
 | 				"invalid resource specified"); | 
 | 		return NULL; | 
 | 	} | 
 |  | 
 | 	if (getrlimit(resource, &rl) == -1) { | 
 | 		PyErr_SetFromErrno(ResourceError); | 
 | 		return NULL; | 
 | 	} | 
 |  | 
 | #if defined(HAVE_LONG_LONG) | 
 | 	if (sizeof(rl.rlim_cur) > sizeof(long)) { | 
 | 		return Py_BuildValue("LL", | 
 | 				     (PY_LONG_LONG) rl.rlim_cur, | 
 | 				     (PY_LONG_LONG) rl.rlim_max); | 
 | 	} | 
 | #endif | 
 | 	return Py_BuildValue("ll", (long) rl.rlim_cur, (long) rl.rlim_max); | 
 | } | 
 |  | 
 | static PyObject * | 
 | resource_setrlimit(PyObject *self, PyObject *args) | 
 | { | 
 | 	struct rlimit rl; | 
 | 	int resource; | 
 | 	PyObject *curobj, *maxobj; | 
 |  | 
 | 	if (!PyArg_ParseTuple(args, "i(OO):setrlimit", | 
 | 			      &resource, &curobj, &maxobj)) | 
 | 		return NULL; | 
 |  | 
 | 	if (resource < 0 || resource >= RLIM_NLIMITS) { | 
 | 		PyErr_SetString(PyExc_ValueError, | 
 | 				"invalid resource specified"); | 
 | 		return NULL; | 
 | 	} | 
 |  | 
 | #if !defined(HAVE_LARGEFILE_SUPPORT) | 
 | 	rl.rlim_cur = PyLong_AsLong(curobj); | 
 | 	if (rl.rlim_cur == (rlim_t)-1 && PyErr_Occurred()) | 
 | 	    return NULL; | 
 | 	rl.rlim_max = PyLong_AsLong(maxobj); | 
 | 	if (rl.rlim_max == (rlim_t)-1 && PyErr_Occurred()) | 
 | 	    return NULL; | 
 | #else | 
 | 	/* The limits are probably bigger than a long */ | 
 | 	rl.rlim_cur = PyLong_AsLongLong(curobj); | 
 | 	if (rl.rlim_cur == (rlim_t)-1 && PyErr_Occurred()) | 
 | 	    return NULL; | 
 | 	rl.rlim_max = PyLong_AsLongLong(maxobj); | 
 | 	if (rl.rlim_max == (rlim_t)-1 && PyErr_Occurred()) | 
 | 	    return NULL; | 
 | #endif | 
 |  | 
 | 	rl.rlim_cur = rl.rlim_cur & RLIM_INFINITY; | 
 | 	rl.rlim_max = rl.rlim_max & RLIM_INFINITY; | 
 | 	if (setrlimit(resource, &rl) == -1) { | 
 | 		if (errno == EINVAL) | 
 | 			PyErr_SetString(PyExc_ValueError, | 
 | 					"current limit exceeds maximum limit"); | 
 | 		else if (errno == EPERM) | 
 | 			PyErr_SetString(PyExc_ValueError, | 
 | 					"not allowed to raise maximum limit"); | 
 | 		else | 
 | 			PyErr_SetFromErrno(ResourceError); | 
 | 		return NULL; | 
 | 	} | 
 | 	Py_INCREF(Py_None); | 
 | 	return Py_None; | 
 | } | 
 |  | 
 | static PyObject * | 
 | resource_getpagesize(PyObject *self, PyObject *unused) | 
 | { | 
 | 	long pagesize = 0; | 
 | #if defined(HAVE_GETPAGESIZE) | 
 | 	pagesize = getpagesize(); | 
 | #elif defined(HAVE_SYSCONF) | 
 | #if defined(_SC_PAGE_SIZE) | 
 | 	pagesize = sysconf(_SC_PAGE_SIZE); | 
 | #else | 
 | 	/* Irix 5.3 has _SC_PAGESIZE, but not _SC_PAGE_SIZE */ | 
 | 	pagesize = sysconf(_SC_PAGESIZE); | 
 | #endif | 
 | #endif | 
 | 	return Py_BuildValue("i", pagesize); | 
 |  | 
 | } | 
 |  | 
 | /* List of functions */ | 
 |  | 
 | static struct PyMethodDef | 
 | resource_methods[] = { | 
 | 	{"getrusage",    resource_getrusage,   METH_VARARGS}, | 
 | 	{"getrlimit",    resource_getrlimit,   METH_VARARGS}, | 
 | 	{"setrlimit",    resource_setrlimit,   METH_VARARGS}, | 
 | 	{"getpagesize",  resource_getpagesize, METH_NOARGS}, | 
 | 	{NULL, NULL}			     /* sentinel */ | 
 | }; | 
 |  | 
 |  | 
 | /* Module initialization */ | 
 |  | 
 |  | 
 | static struct PyModuleDef resourcemodule = { | 
 | 	PyModuleDef_HEAD_INIT, | 
 | 	"resource", | 
 | 	NULL, | 
 | 	-1, | 
 | 	resource_methods, | 
 | 	NULL, | 
 | 	NULL, | 
 | 	NULL, | 
 | 	NULL | 
 | }; | 
 |  | 
 | PyMODINIT_FUNC | 
 | PyInit_resource(void) | 
 | { | 
 | 	PyObject *m, *v; | 
 |  | 
 | 	/* Create the module and add the functions */ | 
 | 	m = PyModule_Create(&resourcemodule); | 
 | 	if (m == NULL) | 
 | 		return NULL; | 
 |  | 
 | 	/* Add some symbolic constants to the module */ | 
 | 	if (ResourceError == NULL) { | 
 | 		ResourceError = PyErr_NewException("resource.error", | 
 | 						   NULL, NULL); | 
 | 	} | 
 | 	Py_INCREF(ResourceError); | 
 | 	PyModule_AddObject(m, "error", ResourceError); | 
 | 	if (!initialized) | 
 | 		PyStructSequence_InitType(&StructRUsageType,  | 
 | 					  &struct_rusage_desc); | 
 | 	Py_INCREF(&StructRUsageType); | 
 |  	PyModule_AddObject(m, "struct_rusage",  | 
 | 			   (PyObject*) &StructRUsageType); | 
 |  | 
 | 	/* insert constants */ | 
 | #ifdef RLIMIT_CPU | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_CPU", RLIMIT_CPU); | 
 | #endif | 
 |  | 
 | #ifdef RLIMIT_FSIZE | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_FSIZE", RLIMIT_FSIZE); | 
 | #endif | 
 |  | 
 | #ifdef RLIMIT_DATA | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_DATA", RLIMIT_DATA); | 
 | #endif | 
 |  | 
 | #ifdef RLIMIT_STACK | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_STACK", RLIMIT_STACK); | 
 | #endif | 
 |  | 
 | #ifdef RLIMIT_CORE | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_CORE", RLIMIT_CORE); | 
 | #endif | 
 |  | 
 | #ifdef RLIMIT_NOFILE | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_NOFILE", RLIMIT_NOFILE); | 
 | #endif | 
 |  | 
 | #ifdef RLIMIT_OFILE | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_OFILE", RLIMIT_OFILE); | 
 | #endif | 
 |  | 
 | #ifdef RLIMIT_VMEM | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_VMEM", RLIMIT_VMEM); | 
 | #endif | 
 |  | 
 | #ifdef RLIMIT_AS | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_AS", RLIMIT_AS); | 
 | #endif | 
 |  | 
 | #ifdef RLIMIT_RSS | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_RSS", RLIMIT_RSS); | 
 | #endif | 
 |  | 
 | #ifdef RLIMIT_NPROC | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_NPROC", RLIMIT_NPROC); | 
 | #endif | 
 |  | 
 | #ifdef RLIMIT_MEMLOCK | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK); | 
 | #endif | 
 |  | 
 | #ifdef RLIMIT_SBSIZE | 
 | 	PyModule_AddIntConstant(m, "RLIMIT_SBSIZE", RLIMIT_SBSIZE); | 
 | #endif | 
 |  | 
 | #ifdef RUSAGE_SELF | 
 | 	PyModule_AddIntConstant(m, "RUSAGE_SELF", RUSAGE_SELF); | 
 | #endif | 
 |  | 
 | #ifdef RUSAGE_CHILDREN | 
 | 	PyModule_AddIntConstant(m, "RUSAGE_CHILDREN", RUSAGE_CHILDREN); | 
 | #endif | 
 |  | 
 | #ifdef RUSAGE_BOTH | 
 | 	PyModule_AddIntConstant(m, "RUSAGE_BOTH", RUSAGE_BOTH); | 
 | #endif | 
 |  | 
 | #if defined(HAVE_LONG_LONG) | 
 | 	if (sizeof(RLIM_INFINITY) > sizeof(long)) { | 
 | 		v = PyLong_FromLongLong((PY_LONG_LONG) RLIM_INFINITY); | 
 | 	} else  | 
 | #endif | 
 | 	{ | 
 | 		v = PyLong_FromLong((long) RLIM_INFINITY); | 
 | 	} | 
 | 	if (v) { | 
 | 		PyModule_AddObject(m, "RLIM_INFINITY", v); | 
 | 	} | 
 | 	initialized = 1; | 
 | 	return m; | 
 | } |