Software /
code /
prosody
Comparison
util-src/pposix.c @ 6621:352fa2cae1c9
Merge 0.10->trunk
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Fri, 03 Apr 2015 19:34:47 +0100 |
parent | 6620:50eaefeec013 |
child | 6642:113d321976b6 |
comparison
equal
deleted
inserted
replaced
6614:c78f8f8f4434 | 6621:352fa2cae1c9 |
---|---|
43 #if defined(__linux__) && defined(_GNU_SOURCE) | 43 #if defined(__linux__) && defined(_GNU_SOURCE) |
44 #include <linux/falloc.h> | 44 #include <linux/falloc.h> |
45 #endif | 45 #endif |
46 | 46 |
47 #if (defined(_SVID_SOURCE) && !defined(WITHOUT_MALLINFO)) | 47 #if (defined(_SVID_SOURCE) && !defined(WITHOUT_MALLINFO)) |
48 #include <malloc.h> | 48 #include <malloc.h> |
49 #define WITH_MALLINFO | 49 #define WITH_MALLINFO |
50 #endif | 50 #endif |
51 | 51 |
52 /* Daemonization support */ | 52 /* Daemonization support */ |
53 | 53 |
54 static int lc_daemonize(lua_State *L) | 54 static int lc_daemonize(lua_State* L) { |
55 { | |
56 | 55 |
57 pid_t pid; | 56 pid_t pid; |
58 | 57 |
59 if ( getppid() == 1 ) | 58 if(getppid() == 1) { |
60 { | |
61 lua_pushboolean(L, 0); | 59 lua_pushboolean(L, 0); |
62 lua_pushstring(L, "already-daemonized"); | 60 lua_pushstring(L, "already-daemonized"); |
63 return 2; | 61 return 2; |
64 } | 62 } |
65 | 63 |
66 /* Attempt initial fork */ | 64 /* Attempt initial fork */ |
67 if((pid = fork()) < 0) | 65 if((pid = fork()) < 0) { |
68 { | |
69 /* Forking failed */ | 66 /* Forking failed */ |
70 lua_pushboolean(L, 0); | 67 lua_pushboolean(L, 0); |
71 lua_pushstring(L, "fork-failed"); | 68 lua_pushstring(L, "fork-failed"); |
72 return 2; | 69 return 2; |
73 } | 70 } else if(pid != 0) { |
74 else if(pid != 0) | |
75 { | |
76 /* We are the parent process */ | 71 /* We are the parent process */ |
77 lua_pushboolean(L, 1); | 72 lua_pushboolean(L, 1); |
78 lua_pushnumber(L, pid); | 73 lua_pushnumber(L, pid); |
79 return 2; | 74 return 2; |
80 } | 75 } |
81 | 76 |
82 /* and we are the child process */ | 77 /* and we are the child process */ |
83 if(setsid() == -1) | 78 if(setsid() == -1) { |
84 { | |
85 /* We failed to become session leader */ | 79 /* We failed to become session leader */ |
86 /* (we probably already were) */ | 80 /* (we probably already were) */ |
87 lua_pushboolean(L, 0); | 81 lua_pushboolean(L, 0); |
88 lua_pushstring(L, "setsid-failed"); | 82 lua_pushstring(L, "setsid-failed"); |
89 return 2; | 83 return 2; |
97 open("/dev/null", O_RDONLY); | 91 open("/dev/null", O_RDONLY); |
98 open("/dev/null", O_WRONLY); | 92 open("/dev/null", O_WRONLY); |
99 open("/dev/null", O_WRONLY); | 93 open("/dev/null", O_WRONLY); |
100 | 94 |
101 /* Final fork, use it wisely */ | 95 /* Final fork, use it wisely */ |
102 if(fork()) | 96 if(fork()) { |
103 exit(0); | 97 exit(0); |
98 } | |
104 | 99 |
105 /* Show's over, let's continue */ | 100 /* Show's over, let's continue */ |
106 lua_pushboolean(L, 1); | 101 lua_pushboolean(L, 1); |
107 lua_pushnil(L); | 102 lua_pushnil(L); |
108 return 2; | 103 return 2; |
109 } | 104 } |
110 | 105 |
111 /* Syslog support */ | 106 /* Syslog support */ |
112 | 107 |
113 const char * const facility_strings[] = { | 108 const char* const facility_strings[] = { |
114 "auth", | 109 "auth", |
115 #if !(defined(sun) || defined(__sun)) | 110 #if !(defined(sun) || defined(__sun)) |
116 "authpriv", | 111 "authpriv", |
117 #endif | 112 #endif |
118 "cron", | 113 "cron", |
119 "daemon", | 114 "daemon", |
120 #if !(defined(sun) || defined(__sun)) | 115 #if !(defined(sun) || defined(__sun)) |
121 "ftp", | 116 "ftp", |
122 #endif | 117 #endif |
123 "kern", | 118 "kern", |
124 "local0", | 119 "local0", |
125 "local1", | 120 "local1", |
126 "local2", | 121 "local2", |
127 "local3", | 122 "local3", |
128 "local4", | 123 "local4", |
129 "local5", | 124 "local5", |
130 "local6", | 125 "local6", |
131 "local7", | 126 "local7", |
132 "lpr", | 127 "lpr", |
133 "mail", | 128 "mail", |
134 "syslog", | 129 "syslog", |
135 "user", | 130 "user", |
136 "uucp", | 131 "uucp", |
137 NULL | 132 NULL |
138 }; | 133 }; |
139 int facility_constants[] = { | 134 int facility_constants[] = { |
140 LOG_AUTH, | 135 LOG_AUTH, |
141 #if !(defined(sun) || defined(__sun)) | 136 #if !(defined(sun) || defined(__sun)) |
142 LOG_AUTHPRIV, | 137 LOG_AUTHPRIV, |
143 #endif | 138 #endif |
144 LOG_CRON, | 139 LOG_CRON, |
145 LOG_DAEMON, | 140 LOG_DAEMON, |
146 #if !(defined(sun) || defined(__sun)) | 141 #if !(defined(sun) || defined(__sun)) |
147 LOG_FTP, | 142 LOG_FTP, |
148 #endif | 143 #endif |
149 LOG_KERN, | 144 LOG_KERN, |
150 LOG_LOCAL0, | 145 LOG_LOCAL0, |
151 LOG_LOCAL1, | 146 LOG_LOCAL1, |
152 LOG_LOCAL2, | 147 LOG_LOCAL2, |
153 LOG_LOCAL3, | 148 LOG_LOCAL3, |
154 LOG_LOCAL4, | 149 LOG_LOCAL4, |
155 LOG_LOCAL5, | 150 LOG_LOCAL5, |
156 LOG_LOCAL6, | 151 LOG_LOCAL6, |
157 LOG_LOCAL7, | 152 LOG_LOCAL7, |
158 LOG_LPR, | 153 LOG_LPR, |
159 LOG_MAIL, | 154 LOG_MAIL, |
160 LOG_NEWS, | 155 LOG_NEWS, |
161 LOG_SYSLOG, | 156 LOG_SYSLOG, |
162 LOG_USER, | 157 LOG_USER, |
163 LOG_UUCP, | 158 LOG_UUCP, |
164 -1 | 159 -1 |
165 }; | 160 }; |
166 | 161 |
167 /* " | 162 /* " |
168 The parameter ident in the call of openlog() is probably stored as-is. | 163 The parameter ident in the call of openlog() is probably stored as-is. |
169 Thus, if the string it points to is changed, syslog() may start | 164 Thus, if the string it points to is changed, syslog() may start |
170 prepending the changed string, and if the string it points to ceases to | 165 prepending the changed string, and if the string it points to ceases to |
172 constant. | 167 constant. |
173 " -- syslog manpage | 168 " -- syslog manpage |
174 */ | 169 */ |
175 char* syslog_ident = NULL; | 170 char* syslog_ident = NULL; |
176 | 171 |
177 int lc_syslog_open(lua_State* L) | 172 int lc_syslog_open(lua_State* L) { |
178 { | |
179 int facility = luaL_checkoption(L, 2, "daemon", facility_strings); | 173 int facility = luaL_checkoption(L, 2, "daemon", facility_strings); |
180 facility = facility_constants[facility]; | 174 facility = facility_constants[facility]; |
181 | 175 |
182 luaL_checkstring(L, 1); | 176 luaL_checkstring(L, 1); |
183 | 177 |
184 if(syslog_ident) | 178 if(syslog_ident) { |
185 free(syslog_ident); | 179 free(syslog_ident); |
180 } | |
186 | 181 |
187 syslog_ident = strdup(lua_tostring(L, 1)); | 182 syslog_ident = strdup(lua_tostring(L, 1)); |
188 | 183 |
189 openlog(syslog_ident, LOG_PID, facility); | 184 openlog(syslog_ident, LOG_PID, facility); |
190 return 0; | 185 return 0; |
191 } | 186 } |
192 | 187 |
193 const char * const level_strings[] = { | 188 const char* const level_strings[] = { |
194 "debug", | 189 "debug", |
195 "info", | 190 "info", |
196 "notice", | 191 "notice", |
197 "warn", | 192 "warn", |
198 "error", | 193 "error", |
199 NULL | 194 NULL |
200 }; | 195 }; |
201 int level_constants[] = { | 196 int level_constants[] = { |
202 LOG_DEBUG, | 197 LOG_DEBUG, |
203 LOG_INFO, | 198 LOG_INFO, |
204 LOG_NOTICE, | 199 LOG_NOTICE, |
205 LOG_WARNING, | 200 LOG_WARNING, |
206 LOG_CRIT, | 201 LOG_CRIT, |
207 -1 | 202 -1 |
208 }; | 203 }; |
209 int lc_syslog_log(lua_State* L) | 204 int lc_syslog_log(lua_State* L) { |
210 { | |
211 int level = level_constants[luaL_checkoption(L, 1, "notice", level_strings)]; | 205 int level = level_constants[luaL_checkoption(L, 1, "notice", level_strings)]; |
212 | 206 |
213 if(lua_gettop(L) == 3) | 207 if(lua_gettop(L) == 3) { |
214 syslog(level, "%s: %s", luaL_checkstring(L, 2), luaL_checkstring(L, 3)); | 208 syslog(level, "%s: %s", luaL_checkstring(L, 2), luaL_checkstring(L, 3)); |
215 else | 209 } else { |
216 syslog(level, "%s", lua_tostring(L, 2)); | 210 syslog(level, "%s", lua_tostring(L, 2)); |
211 } | |
217 | 212 |
218 return 0; | 213 return 0; |
219 } | 214 } |
220 | 215 |
221 int lc_syslog_close(lua_State* L) | 216 int lc_syslog_close(lua_State* L) { |
222 { | |
223 closelog(); | 217 closelog(); |
224 if(syslog_ident) | 218 |
225 { | 219 if(syslog_ident) { |
226 free(syslog_ident); | 220 free(syslog_ident); |
227 syslog_ident = NULL; | 221 syslog_ident = NULL; |
228 } | 222 } |
223 | |
229 return 0; | 224 return 0; |
230 } | 225 } |
231 | 226 |
232 int lc_syslog_setmask(lua_State* L) | 227 int lc_syslog_setmask(lua_State* L) { |
233 { | |
234 int level_idx = luaL_checkoption(L, 1, "notice", level_strings); | 228 int level_idx = luaL_checkoption(L, 1, "notice", level_strings); |
235 int mask = 0; | 229 int mask = 0; |
236 do | 230 |
237 { | 231 do { |
238 mask |= LOG_MASK(level_constants[level_idx]); | 232 mask |= LOG_MASK(level_constants[level_idx]); |
239 } while (++level_idx<=4); | 233 } while(++level_idx <= 4); |
240 | 234 |
241 setlogmask(mask); | 235 setlogmask(mask); |
242 return 0; | 236 return 0; |
243 } | 237 } |
244 | 238 |
245 /* getpid */ | 239 /* getpid */ |
246 | 240 |
247 int lc_getpid(lua_State* L) | 241 int lc_getpid(lua_State* L) { |
248 { | |
249 lua_pushinteger(L, getpid()); | 242 lua_pushinteger(L, getpid()); |
250 return 1; | 243 return 1; |
251 } | 244 } |
252 | 245 |
253 /* UID/GID functions */ | 246 /* UID/GID functions */ |
254 | 247 |
255 int lc_getuid(lua_State* L) | 248 int lc_getuid(lua_State* L) { |
256 { | |
257 lua_pushinteger(L, getuid()); | 249 lua_pushinteger(L, getuid()); |
258 return 1; | 250 return 1; |
259 } | 251 } |
260 | 252 |
261 int lc_getgid(lua_State* L) | 253 int lc_getgid(lua_State* L) { |
262 { | |
263 lua_pushinteger(L, getgid()); | 254 lua_pushinteger(L, getgid()); |
264 return 1; | 255 return 1; |
265 } | 256 } |
266 | 257 |
267 int lc_setuid(lua_State* L) | 258 int lc_setuid(lua_State* L) { |
268 { | |
269 int uid = -1; | 259 int uid = -1; |
270 if(lua_gettop(L) < 1) | 260 |
261 if(lua_gettop(L) < 1) { | |
271 return 0; | 262 return 0; |
272 if(!lua_isnumber(L, 1) && lua_tostring(L, 1)) | 263 } |
273 { | 264 |
265 if(!lua_isnumber(L, 1) && lua_tostring(L, 1)) { | |
274 /* Passed UID is actually a string, so look up the UID */ | 266 /* Passed UID is actually a string, so look up the UID */ |
275 struct passwd *p; | 267 struct passwd* p; |
276 p = getpwnam(lua_tostring(L, 1)); | 268 p = getpwnam(lua_tostring(L, 1)); |
277 if(!p) | 269 |
278 { | 270 if(!p) { |
279 lua_pushboolean(L, 0); | 271 lua_pushboolean(L, 0); |
280 lua_pushstring(L, "no-such-user"); | 272 lua_pushstring(L, "no-such-user"); |
281 return 2; | 273 return 2; |
282 } | 274 } |
275 | |
283 uid = p->pw_uid; | 276 uid = p->pw_uid; |
284 } | 277 } else { |
285 else | |
286 { | |
287 uid = lua_tonumber(L, 1); | 278 uid = lua_tonumber(L, 1); |
288 } | 279 } |
289 | 280 |
290 if(uid>-1) | 281 if(uid > -1) { |
291 { | |
292 /* Ok, attempt setuid */ | 282 /* Ok, attempt setuid */ |
293 errno = 0; | 283 errno = 0; |
294 if(setuid(uid)) | 284 |
295 { | 285 if(setuid(uid)) { |
296 /* Fail */ | 286 /* Fail */ |
297 lua_pushboolean(L, 0); | 287 lua_pushboolean(L, 0); |
298 switch(errno) | 288 |
299 { | 289 switch(errno) { |
300 case EINVAL: | 290 case EINVAL: |
301 lua_pushstring(L, "invalid-uid"); | 291 lua_pushstring(L, "invalid-uid"); |
302 break; | 292 break; |
303 case EPERM: | 293 case EPERM: |
304 lua_pushstring(L, "permission-denied"); | 294 lua_pushstring(L, "permission-denied"); |
305 break; | 295 break; |
306 default: | 296 default: |
307 lua_pushstring(L, "unknown-error"); | 297 lua_pushstring(L, "unknown-error"); |
308 } | 298 } |
299 | |
309 return 2; | 300 return 2; |
310 } | 301 } else { |
311 else | |
312 { | |
313 /* Success! */ | 302 /* Success! */ |
314 lua_pushboolean(L, 1); | 303 lua_pushboolean(L, 1); |
315 return 1; | 304 return 1; |
316 } | 305 } |
317 } | 306 } |
320 lua_pushboolean(L, 0); | 309 lua_pushboolean(L, 0); |
321 lua_pushstring(L, "invalid-uid"); | 310 lua_pushstring(L, "invalid-uid"); |
322 return 2; | 311 return 2; |
323 } | 312 } |
324 | 313 |
325 int lc_setgid(lua_State* L) | 314 int lc_setgid(lua_State* L) { |
326 { | |
327 int gid = -1; | 315 int gid = -1; |
328 if(lua_gettop(L) < 1) | 316 |
317 if(lua_gettop(L) < 1) { | |
329 return 0; | 318 return 0; |
330 if(!lua_isnumber(L, 1) && lua_tostring(L, 1)) | 319 } |
331 { | 320 |
321 if(!lua_isnumber(L, 1) && lua_tostring(L, 1)) { | |
332 /* Passed GID is actually a string, so look up the GID */ | 322 /* Passed GID is actually a string, so look up the GID */ |
333 struct group *g; | 323 struct group* g; |
334 g = getgrnam(lua_tostring(L, 1)); | 324 g = getgrnam(lua_tostring(L, 1)); |
335 if(!g) | 325 |
336 { | 326 if(!g) { |
337 lua_pushboolean(L, 0); | 327 lua_pushboolean(L, 0); |
338 lua_pushstring(L, "no-such-group"); | 328 lua_pushstring(L, "no-such-group"); |
339 return 2; | 329 return 2; |
340 } | 330 } |
331 | |
341 gid = g->gr_gid; | 332 gid = g->gr_gid; |
342 } | 333 } else { |
343 else | |
344 { | |
345 gid = lua_tonumber(L, 1); | 334 gid = lua_tonumber(L, 1); |
346 } | 335 } |
347 | 336 |
348 if(gid>-1) | 337 if(gid > -1) { |
349 { | |
350 /* Ok, attempt setgid */ | 338 /* Ok, attempt setgid */ |
351 errno = 0; | 339 errno = 0; |
352 if(setgid(gid)) | 340 |
353 { | 341 if(setgid(gid)) { |
354 /* Fail */ | 342 /* Fail */ |
355 lua_pushboolean(L, 0); | 343 lua_pushboolean(L, 0); |
356 switch(errno) | 344 |
357 { | 345 switch(errno) { |
358 case EINVAL: | 346 case EINVAL: |
359 lua_pushstring(L, "invalid-gid"); | 347 lua_pushstring(L, "invalid-gid"); |
360 break; | 348 break; |
361 case EPERM: | 349 case EPERM: |
362 lua_pushstring(L, "permission-denied"); | 350 lua_pushstring(L, "permission-denied"); |
363 break; | 351 break; |
364 default: | 352 default: |
365 lua_pushstring(L, "unknown-error"); | 353 lua_pushstring(L, "unknown-error"); |
366 } | 354 } |
355 | |
367 return 2; | 356 return 2; |
368 } | 357 } else { |
369 else | |
370 { | |
371 /* Success! */ | 358 /* Success! */ |
372 lua_pushboolean(L, 1); | 359 lua_pushboolean(L, 1); |
373 return 1; | 360 return 1; |
374 } | 361 } |
375 } | 362 } |
378 lua_pushboolean(L, 0); | 365 lua_pushboolean(L, 0); |
379 lua_pushstring(L, "invalid-gid"); | 366 lua_pushstring(L, "invalid-gid"); |
380 return 2; | 367 return 2; |
381 } | 368 } |
382 | 369 |
383 int lc_initgroups(lua_State* L) | 370 int lc_initgroups(lua_State* L) { |
384 { | |
385 int ret; | 371 int ret; |
386 gid_t gid; | 372 gid_t gid; |
387 struct passwd *p; | 373 struct passwd* p; |
388 | 374 |
389 if(!lua_isstring(L, 1)) | 375 if(!lua_isstring(L, 1)) { |
390 { | |
391 lua_pushnil(L); | 376 lua_pushnil(L); |
392 lua_pushstring(L, "invalid-username"); | 377 lua_pushstring(L, "invalid-username"); |
393 return 2; | 378 return 2; |
394 } | 379 } |
380 | |
395 p = getpwnam(lua_tostring(L, 1)); | 381 p = getpwnam(lua_tostring(L, 1)); |
396 if(!p) | 382 |
397 { | 383 if(!p) { |
398 lua_pushnil(L); | 384 lua_pushnil(L); |
399 lua_pushstring(L, "no-such-user"); | 385 lua_pushstring(L, "no-such-user"); |
400 return 2; | 386 return 2; |
401 } | 387 } |
402 if(lua_gettop(L) < 2) | 388 |
389 if(lua_gettop(L) < 2) { | |
403 lua_pushnil(L); | 390 lua_pushnil(L); |
404 switch(lua_type(L, 2)) | 391 } |
405 { | 392 |
406 case LUA_TNIL: | 393 switch(lua_type(L, 2)) { |
407 gid = p->pw_gid; | 394 case LUA_TNIL: |
408 break; | 395 gid = p->pw_gid; |
409 case LUA_TNUMBER: | |
410 gid = lua_tointeger(L, 2); | |
411 break; | |
412 default: | |
413 lua_pushnil(L); | |
414 lua_pushstring(L, "invalid-gid"); | |
415 return 2; | |
416 } | |
417 ret = initgroups(lua_tostring(L, 1), gid); | |
418 if(ret) | |
419 { | |
420 switch(errno) | |
421 { | |
422 case ENOMEM: | |
423 lua_pushnil(L); | |
424 lua_pushstring(L, "no-memory"); | |
425 break; | 396 break; |
426 case EPERM: | 397 case LUA_TNUMBER: |
427 lua_pushnil(L); | 398 gid = lua_tointeger(L, 2); |
428 lua_pushstring(L, "permission-denied"); | |
429 break; | 399 break; |
430 default: | 400 default: |
431 lua_pushnil(L); | 401 lua_pushnil(L); |
432 lua_pushstring(L, "unknown-error"); | 402 lua_pushstring(L, "invalid-gid"); |
403 return 2; | |
404 } | |
405 | |
406 ret = initgroups(lua_tostring(L, 1), gid); | |
407 | |
408 if(ret) { | |
409 switch(errno) { | |
410 case ENOMEM: | |
411 lua_pushnil(L); | |
412 lua_pushstring(L, "no-memory"); | |
413 break; | |
414 case EPERM: | |
415 lua_pushnil(L); | |
416 lua_pushstring(L, "permission-denied"); | |
417 break; | |
418 default: | |
419 lua_pushnil(L); | |
420 lua_pushstring(L, "unknown-error"); | |
433 } | 421 } |
434 } | 422 } else { |
435 else | |
436 { | |
437 lua_pushboolean(L, 1); | 423 lua_pushboolean(L, 1); |
438 lua_pushnil(L); | 424 lua_pushnil(L); |
439 } | 425 } |
426 | |
440 return 2; | 427 return 2; |
441 } | 428 } |
442 | 429 |
443 int lc_umask(lua_State* L) | 430 int lc_umask(lua_State* L) { |
444 { | |
445 char old_mode_string[7]; | 431 char old_mode_string[7]; |
446 mode_t old_mode = umask(strtoul(luaL_checkstring(L, 1), NULL, 8)); | 432 mode_t old_mode = umask(strtoul(luaL_checkstring(L, 1), NULL, 8)); |
447 | 433 |
448 snprintf(old_mode_string, sizeof(old_mode_string), "%03o", old_mode); | 434 snprintf(old_mode_string, sizeof(old_mode_string), "%03o", old_mode); |
449 old_mode_string[sizeof(old_mode_string)-1] = 0; | 435 old_mode_string[sizeof(old_mode_string) - 1] = 0; |
450 lua_pushstring(L, old_mode_string); | 436 lua_pushstring(L, old_mode_string); |
451 | 437 |
452 return 1; | 438 return 1; |
453 } | 439 } |
454 | 440 |
455 int lc_mkdir(lua_State* L) | 441 int lc_mkdir(lua_State* L) { |
456 { | |
457 int ret = mkdir(luaL_checkstring(L, 1), S_IRUSR | S_IWUSR | S_IXUSR | 442 int ret = mkdir(luaL_checkstring(L, 1), S_IRUSR | S_IWUSR | S_IXUSR |
458 | S_IRGRP | S_IWGRP | S_IXGRP | 443 | S_IRGRP | S_IWGRP | S_IXGRP |
459 | S_IROTH | S_IXOTH); /* mode 775 */ | 444 | S_IROTH | S_IXOTH); /* mode 775 */ |
460 | 445 |
461 lua_pushboolean(L, ret==0); | 446 lua_pushboolean(L, ret == 0); |
462 if(ret) | 447 |
463 { | 448 if(ret) { |
464 lua_pushstring(L, strerror(errno)); | 449 lua_pushstring(L, strerror(errno)); |
465 return 2; | 450 return 2; |
466 } | 451 } |
452 | |
467 return 1; | 453 return 1; |
468 } | 454 } |
469 | 455 |
470 /* Like POSIX's setrlimit()/getrlimit() API functions. | 456 /* Like POSIX's setrlimit()/getrlimit() API functions. |
471 * | 457 * |
475 * Any negative limit will be replace with the current limit by an additional call of getrlimit(). | 461 * Any negative limit will be replace with the current limit by an additional call of getrlimit(). |
476 * | 462 * |
477 * Example usage: | 463 * Example usage: |
478 * pposix.setrlimit("NOFILE", 1000, 2000) | 464 * pposix.setrlimit("NOFILE", 1000, 2000) |
479 */ | 465 */ |
480 int string2resource(const char *s) { | 466 int string2resource(const char* s) { |
481 if (!strcmp(s, "CORE")) return RLIMIT_CORE; | 467 if(!strcmp(s, "CORE")) { |
482 if (!strcmp(s, "CPU")) return RLIMIT_CPU; | 468 return RLIMIT_CORE; |
483 if (!strcmp(s, "DATA")) return RLIMIT_DATA; | 469 } |
484 if (!strcmp(s, "FSIZE")) return RLIMIT_FSIZE; | 470 |
485 if (!strcmp(s, "NOFILE")) return RLIMIT_NOFILE; | 471 if(!strcmp(s, "CPU")) { |
486 if (!strcmp(s, "STACK")) return RLIMIT_STACK; | 472 return RLIMIT_CPU; |
473 } | |
474 | |
475 if(!strcmp(s, "DATA")) { | |
476 return RLIMIT_DATA; | |
477 } | |
478 | |
479 if(!strcmp(s, "FSIZE")) { | |
480 return RLIMIT_FSIZE; | |
481 } | |
482 | |
483 if(!strcmp(s, "NOFILE")) { | |
484 return RLIMIT_NOFILE; | |
485 } | |
486 | |
487 if(!strcmp(s, "STACK")) { | |
488 return RLIMIT_STACK; | |
489 } | |
490 | |
487 #if !(defined(sun) || defined(__sun)) | 491 #if !(defined(sun) || defined(__sun)) |
488 if (!strcmp(s, "MEMLOCK")) return RLIMIT_MEMLOCK; | 492 |
489 if (!strcmp(s, "NPROC")) return RLIMIT_NPROC; | 493 if(!strcmp(s, "MEMLOCK")) { |
490 if (!strcmp(s, "RSS")) return RLIMIT_RSS; | 494 return RLIMIT_MEMLOCK; |
495 } | |
496 | |
497 if(!strcmp(s, "NPROC")) { | |
498 return RLIMIT_NPROC; | |
499 } | |
500 | |
501 if(!strcmp(s, "RSS")) { | |
502 return RLIMIT_RSS; | |
503 } | |
504 | |
491 #endif | 505 #endif |
492 #ifdef RLIMIT_NICE | 506 #ifdef RLIMIT_NICE |
493 if (!strcmp(s, "NICE")) return RLIMIT_NICE; | 507 |
508 if(!strcmp(s, "NICE")) { | |
509 return RLIMIT_NICE; | |
510 } | |
511 | |
494 #endif | 512 #endif |
495 return -1; | 513 return -1; |
496 } | 514 } |
497 | 515 |
498 unsigned long int arg_to_rlimit(lua_State* L, int idx, rlim_t current) { | 516 unsigned long int arg_to_rlimit(lua_State* L, int idx, rlim_t current) { |
499 switch(lua_type(L, idx)) { | 517 switch(lua_type(L, idx)) { |
500 case LUA_TSTRING: | 518 case LUA_TSTRING: |
501 if(strcmp(lua_tostring(L, idx), "unlimited") == 0) | 519 |
502 return RLIM_INFINITY; | 520 if(strcmp(lua_tostring(L, idx), "unlimited") == 0) { |
503 case LUA_TNUMBER: | 521 return RLIM_INFINITY; |
504 return lua_tointeger(L, idx); | 522 } |
505 case LUA_TNONE: | 523 |
506 case LUA_TNIL: | 524 case LUA_TNUMBER: |
507 return current; | 525 return lua_tointeger(L, idx); |
508 default: | 526 case LUA_TNONE: |
509 return luaL_argerror(L, idx, "unexpected type"); | 527 case LUA_TNIL: |
510 } | 528 return current; |
511 } | 529 default: |
512 | 530 return luaL_argerror(L, idx, "unexpected type"); |
513 int lc_setrlimit(lua_State *L) { | 531 } |
532 } | |
533 | |
534 int lc_setrlimit(lua_State* L) { | |
514 struct rlimit lim; | 535 struct rlimit lim; |
515 int arguments = lua_gettop(L); | 536 int arguments = lua_gettop(L); |
516 int rid = -1; | 537 int rid = -1; |
538 | |
517 if(arguments < 1 || arguments > 3) { | 539 if(arguments < 1 || arguments > 3) { |
518 lua_pushboolean(L, 0); | 540 lua_pushboolean(L, 0); |
519 lua_pushstring(L, "incorrect-arguments"); | 541 lua_pushstring(L, "incorrect-arguments"); |
520 return 2; | 542 return 2; |
521 } | 543 } |
522 | 544 |
523 rid = string2resource(luaL_checkstring(L, 1)); | 545 rid = string2resource(luaL_checkstring(L, 1)); |
524 if (rid == -1) { | 546 |
547 if(rid == -1) { | |
525 lua_pushboolean(L, 0); | 548 lua_pushboolean(L, 0); |
526 lua_pushstring(L, "invalid-resource"); | 549 lua_pushstring(L, "invalid-resource"); |
527 return 2; | 550 return 2; |
528 } | 551 } |
529 | 552 |
530 /* Fetch current values to use as defaults */ | 553 /* Fetch current values to use as defaults */ |
531 if (getrlimit(rid, &lim)) { | 554 if(getrlimit(rid, &lim)) { |
532 lua_pushboolean(L, 0); | 555 lua_pushboolean(L, 0); |
533 lua_pushstring(L, "getrlimit-failed"); | 556 lua_pushstring(L, "getrlimit-failed"); |
534 return 2; | 557 return 2; |
535 } | 558 } |
536 | 559 |
537 lim.rlim_cur = arg_to_rlimit(L, 2, lim.rlim_cur); | 560 lim.rlim_cur = arg_to_rlimit(L, 2, lim.rlim_cur); |
538 lim.rlim_max = arg_to_rlimit(L, 3, lim.rlim_max); | 561 lim.rlim_max = arg_to_rlimit(L, 3, lim.rlim_max); |
539 | 562 |
540 if (setrlimit(rid, &lim)) { | 563 if(setrlimit(rid, &lim)) { |
541 lua_pushboolean(L, 0); | 564 lua_pushboolean(L, 0); |
542 lua_pushstring(L, "setrlimit-failed"); | 565 lua_pushstring(L, "setrlimit-failed"); |
543 return 2; | 566 return 2; |
544 } | 567 } |
568 | |
545 lua_pushboolean(L, 1); | 569 lua_pushboolean(L, 1); |
546 return 1; | 570 return 1; |
547 } | 571 } |
548 | 572 |
549 int lc_getrlimit(lua_State *L) { | 573 int lc_getrlimit(lua_State* L) { |
550 int arguments = lua_gettop(L); | 574 int arguments = lua_gettop(L); |
551 const char *resource = NULL; | 575 const char* resource = NULL; |
552 int rid = -1; | 576 int rid = -1; |
553 struct rlimit lim; | 577 struct rlimit lim; |
554 | 578 |
555 if (arguments != 1) { | 579 if(arguments != 1) { |
556 lua_pushboolean(L, 0); | 580 lua_pushboolean(L, 0); |
557 lua_pushstring(L, "invalid-arguments"); | 581 lua_pushstring(L, "invalid-arguments"); |
558 return 2; | 582 return 2; |
559 } | 583 } |
560 | 584 |
561 | 585 |
562 | 586 |
563 resource = luaL_checkstring(L, 1); | 587 resource = luaL_checkstring(L, 1); |
564 rid = string2resource(resource); | 588 rid = string2resource(resource); |
565 if (rid != -1) { | 589 |
566 if (getrlimit(rid, &lim)) { | 590 if(rid != -1) { |
591 if(getrlimit(rid, &lim)) { | |
567 lua_pushboolean(L, 0); | 592 lua_pushboolean(L, 0); |
568 lua_pushstring(L, "getrlimit-failed."); | 593 lua_pushstring(L, "getrlimit-failed."); |
569 return 2; | 594 return 2; |
570 } | 595 } |
571 } else { | 596 } else { |
572 /* Unsupported resoucrce. Sorry I'm pretty limited by POSIX standard. */ | 597 /* Unsupported resoucrce. Sorry I'm pretty limited by POSIX standard. */ |
573 lua_pushboolean(L, 0); | 598 lua_pushboolean(L, 0); |
574 lua_pushstring(L, "invalid-resource"); | 599 lua_pushstring(L, "invalid-resource"); |
575 return 2; | 600 return 2; |
576 } | 601 } |
602 | |
577 lua_pushboolean(L, 1); | 603 lua_pushboolean(L, 1); |
578 if(lim.rlim_cur == RLIM_INFINITY) | 604 |
605 if(lim.rlim_cur == RLIM_INFINITY) { | |
579 lua_pushstring(L, "unlimited"); | 606 lua_pushstring(L, "unlimited"); |
580 else | 607 } else { |
581 lua_pushnumber(L, lim.rlim_cur); | 608 lua_pushnumber(L, lim.rlim_cur); |
582 if(lim.rlim_max == RLIM_INFINITY) | 609 } |
610 | |
611 if(lim.rlim_max == RLIM_INFINITY) { | |
583 lua_pushstring(L, "unlimited"); | 612 lua_pushstring(L, "unlimited"); |
584 else | 613 } else { |
585 lua_pushnumber(L, lim.rlim_max); | 614 lua_pushnumber(L, lim.rlim_max); |
615 } | |
616 | |
586 return 3; | 617 return 3; |
587 } | 618 } |
588 | 619 |
589 int lc_abort(lua_State* L) | 620 int lc_abort(lua_State* L) { |
590 { | |
591 abort(); | 621 abort(); |
592 return 0; | 622 return 0; |
593 } | 623 } |
594 | 624 |
595 int lc_uname(lua_State* L) | 625 int lc_uname(lua_State* L) { |
596 { | |
597 struct utsname uname_info; | 626 struct utsname uname_info; |
598 if(uname(&uname_info) != 0) | 627 |
599 { | 628 if(uname(&uname_info) != 0) { |
600 lua_pushnil(L); | 629 lua_pushnil(L); |
601 lua_pushstring(L, strerror(errno)); | 630 lua_pushstring(L, strerror(errno)); |
602 return 2; | 631 return 2; |
603 } | 632 } |
633 | |
604 lua_newtable(L); | 634 lua_newtable(L); |
605 lua_pushstring(L, uname_info.sysname); | 635 lua_pushstring(L, uname_info.sysname); |
606 lua_setfield(L, -2, "sysname"); | 636 lua_setfield(L, -2, "sysname"); |
607 lua_pushstring(L, uname_info.nodename); | 637 lua_pushstring(L, uname_info.nodename); |
608 lua_setfield(L, -2, "nodename"); | 638 lua_setfield(L, -2, "nodename"); |
613 lua_pushstring(L, uname_info.machine); | 643 lua_pushstring(L, uname_info.machine); |
614 lua_setfield(L, -2, "machine"); | 644 lua_setfield(L, -2, "machine"); |
615 return 1; | 645 return 1; |
616 } | 646 } |
617 | 647 |
618 int lc_setenv(lua_State* L) | 648 int lc_setenv(lua_State* L) { |
619 { | 649 const char* var = luaL_checkstring(L, 1); |
620 const char *var = luaL_checkstring(L, 1); | 650 const char* value; |
621 const char *value; | |
622 | 651 |
623 /* If the second argument is nil or nothing, unset the var */ | 652 /* If the second argument is nil or nothing, unset the var */ |
624 if(lua_isnoneornil(L, 2)) | 653 if(lua_isnoneornil(L, 2)) { |
625 { | 654 if(unsetenv(var) != 0) { |
626 if(unsetenv(var) != 0) | |
627 { | |
628 lua_pushnil(L); | 655 lua_pushnil(L); |
629 lua_pushstring(L, strerror(errno)); | 656 lua_pushstring(L, strerror(errno)); |
630 return 2; | 657 return 2; |
631 } | 658 } |
659 | |
632 lua_pushboolean(L, 1); | 660 lua_pushboolean(L, 1); |
633 return 1; | 661 return 1; |
634 } | 662 } |
635 | 663 |
636 value = luaL_checkstring(L, 2); | 664 value = luaL_checkstring(L, 2); |
637 | 665 |
638 if(setenv(var, value, 1) != 0) | 666 if(setenv(var, value, 1) != 0) { |
639 { | |
640 lua_pushnil(L); | 667 lua_pushnil(L); |
641 lua_pushstring(L, strerror(errno)); | 668 lua_pushstring(L, strerror(errno)); |
642 return 2; | 669 return 2; |
643 } | 670 } |
644 | 671 |
645 lua_pushboolean(L, 1); | 672 lua_pushboolean(L, 1); |
646 return 1; | 673 return 1; |
647 } | 674 } |
648 | 675 |
649 #ifdef WITH_MALLINFO | 676 #ifdef WITH_MALLINFO |
650 int lc_meminfo(lua_State* L) | 677 int lc_meminfo(lua_State* L) { |
651 { | |
652 struct mallinfo info = mallinfo(); | 678 struct mallinfo info = mallinfo(); |
653 lua_newtable(L); | 679 lua_newtable(L); |
654 /* This is the total size of memory allocated with sbrk by malloc, in bytes. */ | 680 /* This is the total size of memory allocated with sbrk by malloc, in bytes. */ |
655 lua_pushinteger(L, info.arena); | 681 lua_pushinteger(L, info.arena); |
656 lua_setfield(L, -2, "allocated"); | 682 lua_setfield(L, -2, "allocated"); |
674 /* File handle extraction blatantly stolen from | 700 /* File handle extraction blatantly stolen from |
675 * https://github.com/rrthomas/luaposix/blob/master/lposix.c#L631 | 701 * https://github.com/rrthomas/luaposix/blob/master/lposix.c#L631 |
676 * */ | 702 * */ |
677 | 703 |
678 #if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L || defined(_GNU_SOURCE) | 704 #if _XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L || defined(_GNU_SOURCE) |
679 int lc_fallocate(lua_State* L) | 705 int lc_fallocate(lua_State* L) { |
680 { | |
681 int ret; | 706 int ret; |
682 off_t offset, len; | 707 off_t offset, len; |
683 FILE *f = *(FILE**) luaL_checkudata(L, 1, LUA_FILEHANDLE); | 708 FILE* f = *(FILE**) luaL_checkudata(L, 1, LUA_FILEHANDLE); |
684 if (f == NULL) | 709 |
685 luaL_error(L, "attempt to use a closed file"); | 710 if(f == NULL) { |
711 return luaL_error(L, "attempt to use a closed file"); | |
712 } | |
686 | 713 |
687 offset = luaL_checkinteger(L, 2); | 714 offset = luaL_checkinteger(L, 2); |
688 len = luaL_checkinteger(L, 3); | 715 len = luaL_checkinteger(L, 3); |
689 | 716 |
690 #if defined(__linux__) && defined(_GNU_SOURCE) | 717 #if defined(__linux__) && defined(_GNU_SOURCE) |
691 errno = 0; | 718 errno = 0; |
692 ret = fallocate(fileno(f), FALLOC_FL_KEEP_SIZE, offset, len); | 719 ret = fallocate(fileno(f), FALLOC_FL_KEEP_SIZE, offset, len); |
693 if(ret == 0) | 720 |
694 { | 721 if(ret == 0) { |
695 lua_pushboolean(L, 1); | 722 lua_pushboolean(L, 1); |
696 return 1; | 723 return 1; |
697 } | 724 } |
725 | |
698 /* Some old versions of Linux apparently use the return value instead of errno */ | 726 /* Some old versions of Linux apparently use the return value instead of errno */ |
699 if(errno == 0) errno = ret; | 727 if(errno == 0) { |
700 | 728 errno = ret; |
701 if(errno != ENOSYS && errno != EOPNOTSUPP) | 729 } |
702 { | 730 |
731 if(errno != ENOSYS && errno != EOPNOTSUPP) { | |
703 lua_pushnil(L); | 732 lua_pushnil(L); |
704 lua_pushstring(L, strerror(errno)); | 733 lua_pushstring(L, strerror(errno)); |
705 return 2; | 734 return 2; |
706 } | 735 } |
736 | |
707 #else | 737 #else |
708 #warning Only using posix_fallocate() fallback. | 738 #warning Only using posix_fallocate() fallback. |
709 #warning Linux fallocate() is strongly recommended if available: recompile with -D_GNU_SOURCE | 739 #warning Linux fallocate() is strongly recommended if available: recompile with -D_GNU_SOURCE |
710 #warning Note that posix_fallocate() will still be used on filesystems that dont support fallocate() | 740 #warning Note that posix_fallocate() will still be used on filesystems that dont support fallocate() |
711 #endif | 741 #endif |
712 | 742 |
713 ret = posix_fallocate(fileno(f), offset, len); | 743 ret = posix_fallocate(fileno(f), offset, len); |
714 if(ret == 0) | 744 |
715 { | 745 if(ret == 0) { |
716 lua_pushboolean(L, 1); | 746 lua_pushboolean(L, 1); |
717 return 1; | 747 return 1; |
718 } | 748 } else { |
719 else | |
720 { | |
721 lua_pushnil(L); | 749 lua_pushnil(L); |
722 lua_pushstring(L, strerror(ret)); | 750 lua_pushstring(L, strerror(ret)); |
723 /* posix_fallocate() can leave a bunch of NULs at the end, so we cut that | 751 /* posix_fallocate() can leave a bunch of NULs at the end, so we cut that |
724 * this assumes that offset == length of the file */ | 752 * this assumes that offset == length of the file */ |
725 ftruncate(fileno(f), offset); | 753 ftruncate(fileno(f), offset); |
728 } | 756 } |
729 #endif | 757 #endif |
730 | 758 |
731 /* Register functions */ | 759 /* Register functions */ |
732 | 760 |
733 int luaopen_util_pposix(lua_State *L) | 761 int luaopen_util_pposix(lua_State* L) { |
734 { | |
735 luaL_Reg exports[] = { | 762 luaL_Reg exports[] = { |
736 { "abort", lc_abort }, | 763 { "abort", lc_abort }, |
737 | 764 |
738 { "daemonize", lc_daemonize }, | 765 { "daemonize", lc_daemonize }, |
739 | 766 |