ibmi.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. /* Copyright libuv project contributors. All rights reserved.
  2. *
  3. * Permission is hereby granted, free of charge, to any person obtaining a copy
  4. * of this software and associated documentation files (the "Software"), to
  5. * deal in the Software without restriction, including without limitation the
  6. * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7. * sell copies of the Software, and to permit persons to whom the Software is
  8. * furnished to do so, subject to the following conditions:
  9. *
  10. * The above copyright notice and this permission notice shall be included in
  11. * all copies or substantial portions of the Software.
  12. *
  13. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19. * IN THE SOFTWARE.
  20. */
  21. #include "uv.h"
  22. #include "internal.h"
  23. #include <stdio.h>
  24. #include <stdint.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include <assert.h>
  28. #include <errno.h>
  29. #include <sys/types.h>
  30. #include <sys/socket.h>
  31. #include <sys/ioctl.h>
  32. #include <net/if.h>
  33. #include <netinet/in.h>
  34. #include <arpa/inet.h>
  35. #include <sys/time.h>
  36. #include <unistd.h>
  37. #include <fcntl.h>
  38. #include <utmp.h>
  39. #include <libgen.h>
  40. #include <sys/protosw.h>
  41. #include <procinfo.h>
  42. #include <sys/proc.h>
  43. #include <sys/procfs.h>
  44. #include <ctype.h>
  45. #include <sys/mntctl.h>
  46. #include <sys/vmount.h>
  47. #include <limits.h>
  48. #include <strings.h>
  49. #include <sys/vnode.h>
  50. #include <as400_protos.h>
  51. #include <as400_types.h>
  52. char* original_exepath = NULL;
  53. uv_mutex_t process_title_mutex;
  54. uv_once_t process_title_mutex_once = UV_ONCE_INIT;
  55. typedef struct {
  56. int bytes_available;
  57. int bytes_returned;
  58. char current_date_and_time[8];
  59. char system_name[8];
  60. char elapsed_time[6];
  61. char restricted_state_flag;
  62. char reserved;
  63. int percent_processing_unit_used;
  64. int jobs_in_system;
  65. int percent_permanent_addresses;
  66. int percent_temporary_addresses;
  67. int system_asp;
  68. int percent_system_asp_used;
  69. int total_auxiliary_storage;
  70. int current_unprotected_storage_used;
  71. int maximum_unprotected_storage_used;
  72. int percent_db_capability;
  73. int main_storage_size;
  74. int number_of_partitions;
  75. int partition_identifier;
  76. int reserved1;
  77. int current_processing_capacity;
  78. char processor_sharing_attribute;
  79. char reserved2[3];
  80. int number_of_processors;
  81. int active_jobs_in_system;
  82. int active_threads_in_system;
  83. int maximum_jobs_in_system;
  84. int percent_temporary_256mb_segments_used;
  85. int percent_temporary_4gb_segments_used;
  86. int percent_permanent_256mb_segments_used;
  87. int percent_permanent_4gb_segments_used;
  88. int percent_current_interactive_performance;
  89. int percent_uncapped_cpu_capacity_used;
  90. int percent_shared_processor_pool_used;
  91. long main_storage_size_long;
  92. } SSTS0200;
  93. typedef struct {
  94. char header[208];
  95. unsigned char loca_adapter_address[12];
  96. } LIND0500;
  97. typedef struct {
  98. int bytes_provided;
  99. int bytes_available;
  100. char msgid[7];
  101. } errcode_s;
  102. static const unsigned char e2a[256] = {
  103. 0, 1, 2, 3, 156, 9, 134, 127, 151, 141, 142, 11, 12, 13, 14, 15,
  104. 16, 17, 18, 19, 157, 133, 8, 135, 24, 25, 146, 143, 28, 29, 30, 31,
  105. 128, 129, 130, 131, 132, 10, 23, 27, 136, 137, 138, 139, 140, 5, 6, 7,
  106. 144, 145, 22, 147, 148, 149, 150, 4, 152, 153, 154, 155, 20, 21, 158, 26,
  107. 32, 160, 161, 162, 163, 164, 165, 166, 167, 168, 91, 46, 60, 40, 43, 33,
  108. 38, 169, 170, 171, 172, 173, 174, 175, 176, 177, 93, 36, 42, 41, 59, 94,
  109. 45, 47, 178, 179, 180, 181, 182, 183, 184, 185, 124, 44, 37, 95, 62, 63,
  110. 186, 187, 188, 189, 190, 191, 192, 193, 194, 96, 58, 35, 64, 39, 61, 34,
  111. 195, 97, 98, 99, 100, 101, 102, 103, 104, 105, 196, 197, 198, 199, 200, 201,
  112. 202, 106, 107, 108, 109, 110, 111, 112, 113, 114, 203, 204, 205, 206, 207, 208,
  113. 209, 126, 115, 116, 117, 118, 119, 120, 121, 122, 210, 211, 212, 213, 214, 215,
  114. 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
  115. 123, 65, 66, 67, 68, 69, 70, 71, 72, 73, 232, 233, 234, 235, 236, 237,
  116. 125, 74, 75, 76, 77, 78, 79, 80, 81, 82, 238, 239, 240, 241, 242, 243,
  117. 92, 159, 83, 84, 85, 86, 87, 88, 89, 90, 244, 245, 246, 247, 248, 249,
  118. 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 250, 251, 252, 253, 254, 255};
  119. static const unsigned char a2e[256] = {
  120. 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15,
  121. 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31,
  122. 64, 79, 127, 123, 91, 108, 80, 125, 77, 93, 92, 78, 107, 96, 75, 97,
  123. 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 122, 94, 76, 126, 110, 111,
  124. 124, 193, 194, 195, 196, 197, 198, 199, 200, 201, 209, 210, 211, 212, 213, 214,
  125. 215, 216, 217, 226, 227, 228, 229, 230, 231, 232, 233, 74, 224, 90, 95, 109,
  126. 121, 129, 130, 131, 132, 133, 134, 135, 136, 137, 145, 146, 147, 148, 149, 150,
  127. 151, 152, 153, 162, 163, 164, 165, 166, 167, 168, 169, 192, 106, 208, 161, 7,
  128. 32, 33, 34, 35, 36, 21, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27,
  129. 48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62, 225,
  130. 65, 66, 67, 68, 69, 70, 71, 72, 73, 81, 82, 83, 84, 85, 86, 87,
  131. 88, 89, 98, 99, 100, 101, 102, 103, 104, 105, 112, 113, 114, 115, 116, 117,
  132. 118, 119, 120, 128, 138, 139, 140, 141, 142, 143, 144, 154, 155, 156, 157, 158,
  133. 159, 160, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
  134. 184, 185, 186, 187, 188, 189, 190, 191, 202, 203, 204, 205, 206, 207, 218, 219,
  135. 220, 221, 222, 223, 234, 235, 236, 237, 238, 239, 250, 251, 252, 253, 254, 255};
  136. static void iconv_e2a(unsigned char src[], unsigned char dst[], size_t length) {
  137. size_t i;
  138. for (i = 0; i < length; i++)
  139. dst[i] = e2a[src[i]];
  140. }
  141. static void iconv_a2e(const char* src, unsigned char dst[], size_t length) {
  142. size_t srclen;
  143. size_t i;
  144. srclen = strlen(src);
  145. if (srclen > length)
  146. abort();
  147. for (i = 0; i < srclen; i++)
  148. dst[i] = a2e[src[i]];
  149. /* padding the remaining part with spaces */
  150. for (; i < length; i++)
  151. dst[i] = a2e[' '];
  152. }
  153. void init_process_title_mutex_once(void) {
  154. uv_mutex_init(&process_title_mutex);
  155. }
  156. static int get_ibmi_system_status(SSTS0200* rcvr) {
  157. /* rcvrlen is input parameter 2 to QWCRSSTS */
  158. unsigned int rcvrlen = sizeof(*rcvr);
  159. unsigned char format[8], reset_status[10];
  160. /* format is input parameter 3 to QWCRSSTS */
  161. iconv_a2e("SSTS0200", format, sizeof(format));
  162. /* reset_status is input parameter 4 */
  163. iconv_a2e("*NO", reset_status, sizeof(reset_status));
  164. /* errcode is input parameter 5 to QWCRSSTS */
  165. errcode_s errcode;
  166. /* qwcrssts_pointer is the 16-byte tagged system pointer to QWCRSSTS */
  167. ILEpointer __attribute__((aligned(16))) qwcrssts_pointer;
  168. /* qwcrssts_argv is the array of argument pointers to QWCRSSTS */
  169. void* qwcrssts_argv[6];
  170. /* Set the IBM i pointer to the QSYS/QWCRSSTS *PGM object */
  171. int rc = _RSLOBJ2(&qwcrssts_pointer, RSLOBJ_TS_PGM, "QWCRSSTS", "QSYS");
  172. if (rc != 0)
  173. return rc;
  174. /* initialize the QWCRSSTS returned info structure */
  175. memset(rcvr, 0, sizeof(*rcvr));
  176. /* initialize the QWCRSSTS error code structure */
  177. memset(&errcode, 0, sizeof(errcode));
  178. errcode.bytes_provided = sizeof(errcode);
  179. /* initialize the array of argument pointers for the QWCRSSTS API */
  180. qwcrssts_argv[0] = rcvr;
  181. qwcrssts_argv[1] = &rcvrlen;
  182. qwcrssts_argv[2] = &format;
  183. qwcrssts_argv[3] = &reset_status;
  184. qwcrssts_argv[4] = &errcode;
  185. qwcrssts_argv[5] = NULL;
  186. /* Call the IBM i QWCRSSTS API from PASE */
  187. rc = _PGMCALL(&qwcrssts_pointer, qwcrssts_argv, 0);
  188. return rc;
  189. }
  190. uint64_t uv_get_free_memory(void) {
  191. SSTS0200 rcvr;
  192. if (get_ibmi_system_status(&rcvr))
  193. return 0;
  194. return (uint64_t)rcvr.main_storage_size * 1024ULL;
  195. }
  196. uint64_t uv_get_total_memory(void) {
  197. SSTS0200 rcvr;
  198. if (get_ibmi_system_status(&rcvr))
  199. return 0;
  200. return (uint64_t)rcvr.main_storage_size * 1024ULL;
  201. }
  202. uint64_t uv_get_constrained_memory(void) {
  203. return 0; /* Memory constraints are unknown. */
  204. }
  205. void uv_loadavg(double avg[3]) {
  206. SSTS0200 rcvr;
  207. if (get_ibmi_system_status(&rcvr)) {
  208. avg[0] = avg[1] = avg[2] = 0;
  209. return;
  210. }
  211. /* The average (in tenths) of the elapsed time during which the processing
  212. * units were in use. For example, a value of 411 in binary would be 41.1%.
  213. * This percentage could be greater than 100% for an uncapped partition.
  214. */
  215. double processing_unit_used_percent =
  216. rcvr.percent_processing_unit_used / 1000.0;
  217. avg[0] = avg[1] = avg[2] = processing_unit_used_percent;
  218. }
  219. int uv_resident_set_memory(size_t* rss) {
  220. *rss = 0;
  221. return 0;
  222. }
  223. int uv_uptime(double* uptime) {
  224. return UV_ENOSYS;
  225. }
  226. int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) {
  227. unsigned int numcpus, idx = 0;
  228. uv_cpu_info_t* cpu_info;
  229. *cpu_infos = NULL;
  230. *count = 0;
  231. numcpus = sysconf(_SC_NPROCESSORS_ONLN);
  232. *cpu_infos = uv__malloc(numcpus * sizeof(uv_cpu_info_t));
  233. if (!*cpu_infos) {
  234. return UV_ENOMEM;
  235. }
  236. cpu_info = *cpu_infos;
  237. for (idx = 0; idx < numcpus; idx++) {
  238. cpu_info->speed = 0;
  239. cpu_info->model = uv__strdup("unknown");
  240. cpu_info->cpu_times.user = 0;
  241. cpu_info->cpu_times.sys = 0;
  242. cpu_info->cpu_times.idle = 0;
  243. cpu_info->cpu_times.irq = 0;
  244. cpu_info->cpu_times.nice = 0;
  245. cpu_info++;
  246. }
  247. *count = numcpus;
  248. return 0;
  249. }
  250. static int get_ibmi_physical_address(const char* line, char (*phys_addr)[6]) {
  251. LIND0500 rcvr;
  252. /* rcvrlen is input parameter 2 to QDCRLIND */
  253. unsigned int rcvrlen = sizeof(rcvr);
  254. unsigned char format[8], line_name[10];
  255. unsigned char mac_addr[sizeof(rcvr.loca_adapter_address)];
  256. int c[6];
  257. /* format is input parameter 3 to QDCRLIND */
  258. iconv_a2e("LIND0500", format, sizeof(format));
  259. /* line_name is input parameter 4 to QDCRLIND */
  260. iconv_a2e(line, line_name, sizeof(line_name));
  261. /* err is input parameter 5 to QDCRLIND */
  262. errcode_s err;
  263. /* qwcrssts_pointer is the 16-byte tagged system pointer to QDCRLIND */
  264. ILEpointer __attribute__((aligned(16))) qdcrlind_pointer;
  265. /* qwcrssts_argv is the array of argument pointers to QDCRLIND */
  266. void* qdcrlind_argv[6];
  267. /* Set the IBM i pointer to the QSYS/QDCRLIND *PGM object */
  268. int rc = _RSLOBJ2(&qdcrlind_pointer, RSLOBJ_TS_PGM, "QDCRLIND", "QSYS");
  269. if (rc != 0)
  270. return rc;
  271. /* initialize the QDCRLIND returned info structure */
  272. memset(&rcvr, 0, sizeof(rcvr));
  273. /* initialize the QDCRLIND error code structure */
  274. memset(&err, 0, sizeof(err));
  275. err.bytes_provided = sizeof(err);
  276. /* initialize the array of argument pointers for the QDCRLIND API */
  277. qdcrlind_argv[0] = &rcvr;
  278. qdcrlind_argv[1] = &rcvrlen;
  279. qdcrlind_argv[2] = &format;
  280. qdcrlind_argv[3] = &line_name;
  281. qdcrlind_argv[4] = &err;
  282. qdcrlind_argv[5] = NULL;
  283. /* Call the IBM i QDCRLIND API from PASE */
  284. rc = _PGMCALL(&qdcrlind_pointer, qdcrlind_argv, 0);
  285. if (rc != 0)
  286. return rc;
  287. /* convert ebcdic loca_adapter_address to ascii first */
  288. iconv_e2a(rcvr.loca_adapter_address, mac_addr,
  289. sizeof(rcvr.loca_adapter_address));
  290. /* convert loca_adapter_address(char[12]) to phys_addr(char[6]) */
  291. int r = sscanf(mac_addr, "%02x%02x%02x%02x%02x%02x",
  292. &c[0], &c[1], &c[2], &c[3], &c[4], &c[5]);
  293. if (r == ARRAY_SIZE(c)) {
  294. (*phys_addr)[0] = c[0];
  295. (*phys_addr)[1] = c[1];
  296. (*phys_addr)[2] = c[2];
  297. (*phys_addr)[3] = c[3];
  298. (*phys_addr)[4] = c[4];
  299. (*phys_addr)[5] = c[5];
  300. } else {
  301. memset(*phys_addr, 0, sizeof(*phys_addr));
  302. rc = -1;
  303. }
  304. return rc;
  305. }
  306. int uv_interface_addresses(uv_interface_address_t** addresses, int* count) {
  307. uv_interface_address_t* address;
  308. struct ifaddrs_pase *ifap = NULL, *cur;
  309. int inet6, r = 0;
  310. *count = 0;
  311. *addresses = NULL;
  312. if (Qp2getifaddrs(&ifap))
  313. return UV_ENOSYS;
  314. /* The first loop to get the size of the array to be allocated */
  315. for (cur = ifap; cur; cur = cur->ifa_next) {
  316. if (!(cur->ifa_addr->sa_family == AF_INET6 ||
  317. cur->ifa_addr->sa_family == AF_INET))
  318. continue;
  319. if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
  320. continue;
  321. (*count)++;
  322. }
  323. if (*count == 0) {
  324. Qp2freeifaddrs(ifap);
  325. return 0;
  326. }
  327. /* Alloc the return interface structs */
  328. *addresses = uv__calloc(*count, sizeof(**addresses));
  329. if (*addresses == NULL) {
  330. Qp2freeifaddrs(ifap);
  331. return UV_ENOMEM;
  332. }
  333. address = *addresses;
  334. /* The second loop to fill in the array */
  335. for (cur = ifap; cur; cur = cur->ifa_next) {
  336. if (!(cur->ifa_addr->sa_family == AF_INET6 ||
  337. cur->ifa_addr->sa_family == AF_INET))
  338. continue;
  339. if (!(cur->ifa_flags & IFF_UP && cur->ifa_flags & IFF_RUNNING))
  340. continue;
  341. address->name = uv__strdup(cur->ifa_name);
  342. inet6 = (cur->ifa_addr->sa_family == AF_INET6);
  343. if (inet6) {
  344. address->address.address6 = *((struct sockaddr_in6*)cur->ifa_addr);
  345. address->netmask.netmask6 = *((struct sockaddr_in6*)cur->ifa_netmask);
  346. address->netmask.netmask6.sin6_family = AF_INET6;
  347. } else {
  348. address->address.address4 = *((struct sockaddr_in*)cur->ifa_addr);
  349. address->netmask.netmask4 = *((struct sockaddr_in*)cur->ifa_netmask);
  350. address->netmask.netmask4.sin_family = AF_INET;
  351. }
  352. address->is_internal = cur->ifa_flags & IFF_LOOPBACK ? 1 : 0;
  353. if (!address->is_internal) {
  354. int rc = get_ibmi_physical_address(address->name, &address->phys_addr);
  355. if (rc != 0)
  356. r = rc;
  357. }
  358. address++;
  359. }
  360. Qp2freeifaddrs(ifap);
  361. return r;
  362. }
  363. void uv_free_interface_addresses(uv_interface_address_t* addresses, int count) {
  364. int i;
  365. for (i = 0; i < count; ++i) {
  366. uv__free(addresses[i].name);
  367. }
  368. uv__free(addresses);
  369. }
  370. char** uv_setup_args(int argc, char** argv) {
  371. char exepath[UV__PATH_MAX];
  372. char* s;
  373. size_t size;
  374. if (argc > 0) {
  375. /* Use argv[0] to determine value for uv_exepath(). */
  376. size = sizeof(exepath);
  377. if (uv__search_path(argv[0], exepath, &size) == 0) {
  378. uv_once(&process_title_mutex_once, init_process_title_mutex_once);
  379. uv_mutex_lock(&process_title_mutex);
  380. original_exepath = uv__strdup(exepath);
  381. uv_mutex_unlock(&process_title_mutex);
  382. }
  383. }
  384. return argv;
  385. }
  386. int uv_set_process_title(const char* title) {
  387. return 0;
  388. }
  389. int uv_get_process_title(char* buffer, size_t size) {
  390. if (buffer == NULL || size == 0)
  391. return UV_EINVAL;
  392. buffer[0] = '\0';
  393. return 0;
  394. }
  395. void uv__process_title_cleanup(void) {
  396. }