1 /*
2 * R : A Computer Language for Statistical Data Analysis
3 * Copyright (C) 2011--2018 The R Core Team.
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 2 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, a copy is available at
17 * https://www.R-project.org/Licenses/
18 */
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include "tools.h"
25 #include <signal.h> // C99
26
27 #ifdef _WIN32
28 #define WIN32_LEAN_AND_MEAN
29 #include <windows.h>
30 #endif
31
ps_kill(SEXP spid,SEXP ssignal)32 SEXP ps_kill(SEXP spid, SEXP ssignal)
33 {
34 SEXP sspid, sres;
35 int *pid, *res, signal = asInteger(ssignal);
36 PROTECT(sspid = coerceVector(spid, INTSXP));
37 unsigned int ns = LENGTH(sspid);
38 PROTECT(sres = allocVector(LGLSXP, ns));
39 pid = INTEGER(sspid);
40 res = INTEGER(sres);
41 #if !defined(_WIN32) && !defined(HAVE_KILL)
42 warning(_("pskill() is not supported on this platform"));
43 #endif
44 for (int i = 0; i < ns; i++) {
45 res[i] = FALSE;
46 if(signal != NA_INTEGER) {
47 #ifdef _WIN32
48 HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, pid[i]);
49 if (hProc) {
50 if (TerminateProcess(hProc, 1) != 0) res[i] = TRUE;
51 CloseHandle(hProc);
52 }
53 #elif defined(HAVE_KILL)
54 if (pid[i] > 0 && pid[i] != NA_INTEGER &&
55 kill(pid[i], signal) == 0) res[i] = TRUE;
56 #endif
57 }
58 }
59 UNPROTECT(2);
60 return sres;
61 }
62
63 #if defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_GETPRIORITY)
64 /* on macOS it seems sys/resource.h needed sys/time.h first at one time */
65 #include <sys/time.h>
66 #include <sys/resource.h>
67 #include <errno.h>
ps_priority(SEXP spid,SEXP svalue)68 SEXP ps_priority(SEXP spid, SEXP svalue)
69 {
70 SEXP sspid, sres;
71 int *pid, *res, val;
72 val = asInteger(svalue);
73 PROTECT(sspid = coerceVector(spid, INTSXP));
74 unsigned int ns = LENGTH(sspid);
75 PROTECT(sres = allocVector(INTSXP, ns));
76 pid = INTEGER(sspid);
77 res = INTEGER(sres);
78 for (int i = 0; i < ns; i++) {
79 if (pid[i] <= 0) {
80 res[i] = NA_INTEGER;
81 continue;
82 }
83 if (pid[i] != NA_INTEGER) {
84 /* return value -1 is both an error value
85 and a legitimate niceness */
86 errno = 0;
87 res[i] = getpriority(PRIO_PROCESS, pid[i]);
88 if(errno) res[i] = NA_INTEGER;
89 if(val != NA_INTEGER) setpriority(PRIO_PROCESS, pid[i], val);
90 } else res[i] = NA_INTEGER;
91 }
92 UNPROTECT(2);
93 return sres;
94 }
95 #elif defined(_WIN32)
ps_priority(SEXP spid,SEXP svalue)96 SEXP ps_priority(SEXP spid, SEXP svalue)
97 {
98 SEXP sspid, sres;
99 int *pid, *res, val;
100 val = asInteger(svalue);
101 PROTECT(sspid = coerceVector(spid, INTSXP));
102 unsigned int ns = LENGTH(sspid);
103 PROTECT(sres = allocVector(INTSXP, ns));
104 pid = INTEGER(sspid);
105 res = INTEGER(sres);
106 for (int i = 0; i < ns; i++) {
107 HANDLE hProc = OpenProcess(val != NA_INTEGER ?
108 PROCESS_SET_INFORMATION
109 : PROCESS_QUERY_INFORMATION,
110 FALSE, pid[i]);
111 if (hProc && pid[i] != NA_INTEGER) {
112 DWORD tmp = GetPriorityClass(hProc);
113 switch(tmp) {
114 case ABOVE_NORMAL_PRIORITY_CLASS: res[i] = -5; break;
115 case BELOW_NORMAL_PRIORITY_CLASS: res[i] = 15; break;
116 case HIGH_PRIORITY_CLASS: res[i] = -10; break;
117 case IDLE_PRIORITY_CLASS: res[i] = 19; break;
118 case NORMAL_PRIORITY_CLASS: res[i] = 0; break;
119 case REALTIME_PRIORITY_CLASS: res[i] = -20; break;
120 }
121 if(val != NA_INTEGER) {
122 switch(val) {
123 case 19: tmp = IDLE_PRIORITY_CLASS; break;
124 case 15: tmp = BELOW_NORMAL_PRIORITY_CLASS; break;
125 case 0: tmp = NORMAL_PRIORITY_CLASS; break;
126 case -5: tmp = ABOVE_NORMAL_PRIORITY_CLASS; break;
127 case -10: tmp = HIGH_PRIORITY_CLASS; break;
128 }
129 SetPriorityClass(hProc, tmp);
130 }
131 CloseHandle(hProc);
132 } else res[i] = NA_INTEGER;
133 }
134 UNPROTECT(2);
135 return sres;
136 }
137 #else
ps_priority(SEXP spid,SEXP svalue)138 SEXP ps_priority(SEXP spid, SEXP svalue)
139 {
140 error(_("psnice() is not supported on this platform"));
141 return R_NilValue; /* -Wall */
142 }
143 #endif
144
ps_sigs(SEXP signo)145 SEXP ps_sigs(SEXP signo)
146 {
147 int res = NA_INTEGER;
148 switch(asInteger(signo)) {
149 /* only SIGINT and SIGTERM are in C99 */
150 #ifdef SIGHUP
151 case 1: res = SIGHUP; break;
152 #endif
153 #ifdef SIGINT
154 case 2: res = SIGINT; break;
155 #endif
156 #ifdef SIGQUIT
157 case 3: res = SIGQUIT; break;
158 #endif
159 #ifdef SIGKILL
160 case 9: res = SIGKILL; break;
161 #endif
162 #ifdef SIGTERM
163 case 15: res = SIGTERM; break;
164 #endif
165 #ifdef SIGSTOP
166 case 17: res = SIGSTOP; break;
167 #endif
168 #ifdef SIGTSTP
169 case 18: res = SIGTSTP; break;
170 #endif
171 #ifdef SIGCONT
172 case 19: res = SIGCONT; break;
173 #endif
174 #ifdef SIGCHLD
175 case 20: res = SIGCHLD; break;
176 #endif
177 #ifdef SIGUSR1
178 case 30: res = SIGUSR1; break;
179 #endif
180 #ifdef SIGUSR2
181 case 31: res = SIGUSR2; break;
182 #endif
183 default: break;
184 }
185 return ScalarInteger(res);
186 }
187