lorun.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /**
  2. * Loco program runner core
  3. * Copyright (C) 2011 Lodevil(Du Jiong)
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include "lorun.h"
  19. #include "convert.h"
  20. #include "run.h"
  21. #include "diff.h"
  22. int initRun(struct Runobj *runobj, PyObject *args)
  23. {
  24. PyObject *config, *args_obj, *trace_obj, *time_obj, *memory_obj;
  25. PyObject *calls_obj, *runner_obj, *fd_obj;
  26. if (!PyArg_ParseTuple(args, "O", &config))
  27. RAISE1("initRun parseTuple failure");
  28. if(!PyDict_Check(config)) RAISE1("argument must be a dict");
  29. if((args_obj = PyDict_GetItemString(config, "args")) == NULL)
  30. RAISE1("must supply args");
  31. if((runobj->args = genRunArgs(args_obj)) == NULL) return -1;
  32. if((fd_obj = PyDict_GetItemString(config, "fd_in")) == NULL)
  33. runobj->fd_in = -1;
  34. else runobj->fd_in = PyLong_AsLong(fd_obj);
  35. if((fd_obj = PyDict_GetItemString(config, "fd_out")) == NULL)
  36. runobj->fd_out = -1;
  37. else runobj->fd_out = PyLong_AsLong(fd_obj);
  38. if((fd_obj = PyDict_GetItemString(config, "fd_err")) == NULL)
  39. runobj->fd_err = -1;
  40. else runobj->fd_err = PyLong_AsLong(fd_obj);
  41. if((time_obj = PyDict_GetItemString(config, "timelimit")) == NULL)
  42. RAISE1("must supply timelimit");
  43. runobj->time_limit = PyLong_AsLong(time_obj);
  44. if((memory_obj = PyDict_GetItemString(config, "memorylimit")) == NULL)
  45. RAISE1("must supply memorylimit");
  46. runobj->memory_limit = PyLong_AsLong(memory_obj);
  47. if((runner_obj = PyDict_GetItemString(config, "runner")) == NULL)
  48. runobj->runner = -1;
  49. else
  50. runobj->runner = PyLong_AsLong(runner_obj);
  51. if((trace_obj = PyDict_GetItemString(config, "trace")) != NULL){
  52. if(trace_obj == Py_True){
  53. runobj->trace = 1;
  54. //trace mode: supply calls and files to access.
  55. if((calls_obj = PyDict_GetItemString(config, "calls")) == NULL)
  56. RAISE1("trace == True, so you must specify calls.");
  57. if(!PyList_Check(calls_obj))
  58. RAISE1("calls must be a list.");
  59. if(initCalls(calls_obj, runobj->inttable)) return -1;
  60. if((runobj->files = PyDict_GetItemString(config, "files")) == NULL)
  61. RAISE1("trace == True, so you must specify files.");
  62. if(!PyDict_Check(runobj->files))
  63. RAISE1("files must be a dcit.");
  64. } else runobj->trace = 0;
  65. } else runobj->trace = 0;
  66. return 0;
  67. }
  68. PyObject *run(PyObject *self, PyObject *args)
  69. {
  70. struct Runobj runobj = {0};
  71. struct Result rst = {0};
  72. rst.re_call = -1;
  73. if(initRun(&runobj, args)){
  74. if(runobj.args)
  75. free((void*)runobj.args);
  76. return NULL;
  77. }
  78. if(runit(&runobj, &rst) == -1)
  79. return NULL;
  80. if(runobj.args)
  81. free((void*)runobj.args);
  82. return genResult(&rst);
  83. }
  84. PyObject* check(PyObject *self, PyObject *args)
  85. {
  86. int user_fd, right_fd, rst;
  87. if (!PyArg_ParseTuple(args, "ii", &right_fd, &user_fd))
  88. RAISE0("run parseTuple failure");
  89. if(checkDiff(right_fd, user_fd, &rst) == -1)
  90. return NULL;
  91. return Py_BuildValue("i", rst);
  92. }
  93. #define run_description "run(argv_dict):\n"\
  94. "\targv_dict contains:\n"\
  95. "\t@args : cmd to run\n"\
  96. "\t@fd_in, fd_out, fd_err : stdin,stdout,stderr fd\n"\
  97. "\t@timelimit : program time limit\n"\
  98. "\t@memorylimit : program memory limit\n"\
  99. "\t@runner : run user\n"\
  100. "\t@trace : trace?"
  101. #define check_description "check(right_fd, userout_fd)\n"
  102. static PyMethodDef lorun_methods[] = {
  103. {"run", run, METH_VARARGS, run_description},
  104. {"check", check, METH_VARARGS, check_description},
  105. {NULL, NULL, 0, NULL}
  106. };
  107. struct module_state {
  108. PyObject *error;
  109. };
  110. #ifdef IS_PY3
  111. #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
  112. static int lorun_ext_traverse(PyObject *m, visitproc visit, void *arg) {
  113. Py_VISIT(GETSTATE(m)->error);
  114. return 0;
  115. }
  116. static int lorun_ext_clear(PyObject *m) {
  117. Py_CLEAR(GETSTATE(m)->error);
  118. return 0;
  119. }
  120. static struct PyModuleDef moduledef = {
  121. PyModuleDef_HEAD_INIT,
  122. "_lorun_ext",
  123. NULL,
  124. sizeof(struct module_state),
  125. lorun_methods,
  126. NULL,
  127. lorun_ext_traverse,
  128. lorun_ext_clear,
  129. NULL
  130. };
  131. PyObject *PyInit__lorun_ext(void) {
  132. struct module_state *st;
  133. PyObject *module = PyModule_Create(&moduledef);
  134. if (module == NULL)
  135. return NULL;
  136. st = GETSTATE(module);
  137. st->error = PyErr_NewException("_lorun_ext.Error", NULL, NULL);
  138. if (st->error == NULL) {
  139. Py_DECREF(module);
  140. return NULL;
  141. }
  142. return module;
  143. }
  144. #else
  145. static struct module_state _state;
  146. void init_lorun_ext(void) {
  147. PyObject *module = Py_InitModule("_lorun_ext", lorun_methods);
  148. if (module == NULL) {
  149. return;
  150. }
  151. _state.error = PyErr_NewException("_lorun_ext.Error", NULL, NULL);
  152. if (_state.error == NULL) {
  153. Py_DECREF(module);
  154. return;
  155. }
  156. }
  157. #endif