| 1 | /*************************************************************************** |
|---|
| 2 | * toolsOs.cc |
|---|
| 3 | * |
|---|
| 4 | * Sat Nov 19 2005 |
|---|
| 5 | * Copyright 2005 Dmytro Milinevskyy |
|---|
| 6 | * milinevskyy@gmail.com |
|---|
| 7 | ****************************************************************************/ |
|---|
| 8 | |
|---|
| 9 | /* |
|---|
| 10 | * This program is free software; you can redistribute it and/or modify |
|---|
| 11 | * it under the terms of the GNU Lesser General Public License version 2.1 as published by |
|---|
| 12 | * the Free Software Foundation; |
|---|
| 13 | * |
|---|
| 14 | * This program is distributed in the hope that it will be useful, |
|---|
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 17 | * GNU Library General Public License for more details. |
|---|
| 18 | * |
|---|
| 19 | * You should have received a copy of the GNU Lesser General Public License |
|---|
| 20 | * along with this program; if not, write to the Free Software |
|---|
| 21 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|---|
| 22 | */ |
|---|
| 23 | |
|---|
| 24 | /** |
|---|
| 25 | * vim indentation settings |
|---|
| 26 | * set tabstop=4 |
|---|
| 27 | * set shiftwidth=4 |
|---|
| 28 | */ |
|---|
| 29 | |
|---|
| 30 | #include <libdodo/directives.h> |
|---|
| 31 | |
|---|
| 32 | #include <signal.h> |
|---|
| 33 | #include <pwd.h> |
|---|
| 34 | #include <grp.h> |
|---|
| 35 | #include <unistd.h> |
|---|
| 36 | #include <sys/time.h> |
|---|
| 37 | #include <sys/types.h> |
|---|
| 38 | #include <sys/resource.h> |
|---|
| 39 | #include <sys/wait.h> |
|---|
| 40 | #include <stdlib.h> |
|---|
| 41 | #include <stdio.h> |
|---|
| 42 | #include <errno.h> |
|---|
| 43 | #include <string.h> |
|---|
| 44 | #ifdef PTHREAD_EXT |
|---|
| 45 | #include <pthread.h> |
|---|
| 46 | #endif |
|---|
| 47 | #ifdef DL_EXT |
|---|
| 48 | #include <dlfcn.h> |
|---|
| 49 | #endif |
|---|
| 50 | |
|---|
| 51 | #include <libdodo/pcSyncThread.h> |
|---|
| 52 | #include <libdodo/pcSyncStack.h> |
|---|
| 53 | #include <libdodo/toolsOs.h> |
|---|
| 54 | #include <libdodo/toolsOsEx.h> |
|---|
| 55 | #include <libdodo/types.h> |
|---|
| 56 | #include <libdodo/toolsMisc.h> |
|---|
| 57 | |
|---|
| 58 | using namespace dodo::tools; |
|---|
| 59 | |
|---|
| 60 | #ifdef DL_EXT |
|---|
| 61 | void *os::handlesSig[] = { |
|---|
| 62 | NULL, |
|---|
| 63 | NULL, |
|---|
| 64 | NULL, |
|---|
| 65 | NULL, |
|---|
| 66 | NULL, |
|---|
| 67 | NULL, |
|---|
| 68 | NULL, |
|---|
| 69 | NULL, |
|---|
| 70 | NULL, |
|---|
| 71 | NULL, |
|---|
| 72 | NULL, |
|---|
| 73 | NULL, |
|---|
| 74 | NULL, |
|---|
| 75 | NULL, |
|---|
| 76 | NULL, |
|---|
| 77 | NULL, |
|---|
| 78 | NULL, |
|---|
| 79 | NULL, |
|---|
| 80 | NULL |
|---|
| 81 | }; |
|---|
| 82 | |
|---|
| 83 | //------------------------------------------------------------------- |
|---|
| 84 | |
|---|
| 85 | bool os::handlesOpenedSig[] = { |
|---|
| 86 | false, |
|---|
| 87 | false, |
|---|
| 88 | false, |
|---|
| 89 | false, |
|---|
| 90 | false, |
|---|
| 91 | false, |
|---|
| 92 | false, |
|---|
| 93 | false, |
|---|
| 94 | false, |
|---|
| 95 | false, |
|---|
| 96 | false, |
|---|
| 97 | false, |
|---|
| 98 | false, |
|---|
| 99 | false, |
|---|
| 100 | false, |
|---|
| 101 | false, |
|---|
| 102 | false, |
|---|
| 103 | false, |
|---|
| 104 | false |
|---|
| 105 | }; |
|---|
| 106 | //------------------------------------------------------------------- |
|---|
| 107 | |
|---|
| 108 | char os::handlesCookiesSig[][32] = { |
|---|
| 109 | {'\0', }, |
|---|
| 110 | {'\0', }, |
|---|
| 111 | {'\0', }, |
|---|
| 112 | {'\0', }, |
|---|
| 113 | {'\0', }, |
|---|
| 114 | {'\0', }, |
|---|
| 115 | {'\0', }, |
|---|
| 116 | {'\0', }, |
|---|
| 117 | {'\0', }, |
|---|
| 118 | {'\0', }, |
|---|
| 119 | {'\0', }, |
|---|
| 120 | {'\0', }, |
|---|
| 121 | {'\0', }, |
|---|
| 122 | {'\0', }, |
|---|
| 123 | {'\0', }, |
|---|
| 124 | {'\0', }, |
|---|
| 125 | {'\0', }, |
|---|
| 126 | {'\0', }, |
|---|
| 127 | {'\0', } |
|---|
| 128 | }; |
|---|
| 129 | #endif |
|---|
| 130 | |
|---|
| 131 | //------------------------------------------------------------------- |
|---|
| 132 | |
|---|
| 133 | dodo::pc::sync::thread os::keeper; |
|---|
| 134 | |
|---|
| 135 | //------------------------------------------------------------------- |
|---|
| 136 | |
|---|
| 137 | dodo::string |
|---|
| 138 | os::workingDir() |
|---|
| 139 | { |
|---|
| 140 | char wd[PATH_MAXLEN]; |
|---|
| 141 | |
|---|
| 142 | if (getcwd(wd, PATH_MAXLEN) == NULL) |
|---|
| 143 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_WORKINGDIR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 144 | |
|---|
| 145 | return wd; |
|---|
| 146 | } |
|---|
| 147 | |
|---|
| 148 | //------------------------------------------------------------------- |
|---|
| 149 | |
|---|
| 150 | void |
|---|
| 151 | os::setWorkingDir(const dodo::string &path) |
|---|
| 152 | { |
|---|
| 153 | if (chdir(path.data()) == -1) |
|---|
| 154 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETWORKINGDIR, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 155 | } |
|---|
| 156 | |
|---|
| 157 | //------------------------------------------------------------------- |
|---|
| 158 | |
|---|
| 159 | os::__usage__ |
|---|
| 160 | os::usage() |
|---|
| 161 | { |
|---|
| 162 | rusage use; |
|---|
| 163 | if (getrusage(RUSAGE_SELF, &use) == -1) |
|---|
| 164 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_USAGE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 165 | |
|---|
| 166 | __usage__ info; |
|---|
| 167 | info.time = use.ru_utime.tv_sec * 100 + use.ru_utime.tv_usec; |
|---|
| 168 | info.mem = use.ru_maxrss * 1024; |
|---|
| 169 | |
|---|
| 170 | return info; |
|---|
| 171 | } |
|---|
| 172 | |
|---|
| 173 | //------------------------------------------------------------------- |
|---|
| 174 | |
|---|
| 175 | void |
|---|
| 176 | os::changeRoot(const dodo::string &path) |
|---|
| 177 | { |
|---|
| 178 | setWorkingDir(path); |
|---|
| 179 | |
|---|
| 180 | if (chroot(path.data()) == -1) |
|---|
| 181 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_CHANGEROOT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__, path); |
|---|
| 182 | } |
|---|
| 183 | |
|---|
| 184 | //------------------------------------------------------------------- |
|---|
| 185 | |
|---|
| 186 | os::__limit__ |
|---|
| 187 | os::limit(short type) |
|---|
| 188 | { |
|---|
| 189 | rlimit limit; |
|---|
| 190 | |
|---|
| 191 | int realRes(0); |
|---|
| 192 | |
|---|
| 193 | switch (type) { |
|---|
| 194 | case LIMIT_CPUTIME: |
|---|
| 195 | |
|---|
| 196 | realRes = RLIMIT_CPU; |
|---|
| 197 | |
|---|
| 198 | break; |
|---|
| 199 | |
|---|
| 200 | case LIMIT_MAXFILESIZE: |
|---|
| 201 | |
|---|
| 202 | realRes = RLIMIT_FSIZE; |
|---|
| 203 | |
|---|
| 204 | break; |
|---|
| 205 | |
|---|
| 206 | case LIMIT_MAXMEMUSAGE: |
|---|
| 207 | |
|---|
| 208 | realRes = RLIMIT_DATA; |
|---|
| 209 | |
|---|
| 210 | break; |
|---|
| 211 | |
|---|
| 212 | case LIMIT_MAXSTACK: |
|---|
| 213 | |
|---|
| 214 | realRes = RLIMIT_STACK; |
|---|
| 215 | |
|---|
| 216 | break; |
|---|
| 217 | |
|---|
| 218 | case LIMIT_MAXPROC: |
|---|
| 219 | |
|---|
| 220 | realRes = RLIMIT_NPROC; |
|---|
| 221 | |
|---|
| 222 | break; |
|---|
| 223 | |
|---|
| 224 | case LIMIT_MAXOPENFILES: |
|---|
| 225 | |
|---|
| 226 | #ifdef __FreeBSD__ |
|---|
| 227 | realRes = RLIMIT_NOFILE; |
|---|
| 228 | #else |
|---|
| 229 | realRes = RLIMIT_OFILE; |
|---|
| 230 | #endif |
|---|
| 231 | |
|---|
| 232 | break; |
|---|
| 233 | |
|---|
| 234 | default: |
|---|
| 235 | |
|---|
| 236 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_LIMIT, exception::ERRNO_LIBDODO, OSEX_WRONGPARAMETER, TOOLSOSEX_WRONGPARAMETER_STR, __LINE__, __FILE__); |
|---|
| 237 | } |
|---|
| 238 | |
|---|
| 239 | if (getrlimit(realRes, &limit) == -1) |
|---|
| 240 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_LIMIT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 241 | |
|---|
| 242 | __limit__ lim; |
|---|
| 243 | |
|---|
| 244 | lim.current = limit.rlim_cur; |
|---|
| 245 | lim.max = limit.rlim_max; |
|---|
| 246 | |
|---|
| 247 | return lim; |
|---|
| 248 | } |
|---|
| 249 | |
|---|
| 250 | //------------------------------------------------------------------- |
|---|
| 251 | |
|---|
| 252 | void |
|---|
| 253 | os::setLimit(short type, |
|---|
| 254 | const __limit__ &lim) |
|---|
| 255 | { |
|---|
| 256 | rlimit limit; |
|---|
| 257 | |
|---|
| 258 | int realRes(0); |
|---|
| 259 | |
|---|
| 260 | switch (type) { |
|---|
| 261 | case LIMIT_CPUTIME: |
|---|
| 262 | |
|---|
| 263 | realRes = RLIMIT_CPU; |
|---|
| 264 | |
|---|
| 265 | break; |
|---|
| 266 | |
|---|
| 267 | case LIMIT_MAXFILESIZE: |
|---|
| 268 | |
|---|
| 269 | realRes = RLIMIT_FSIZE; |
|---|
| 270 | |
|---|
| 271 | break; |
|---|
| 272 | |
|---|
| 273 | case LIMIT_MAXMEMUSAGE: |
|---|
| 274 | |
|---|
| 275 | realRes = RLIMIT_DATA; |
|---|
| 276 | |
|---|
| 277 | break; |
|---|
| 278 | |
|---|
| 279 | case LIMIT_MAXSTACK: |
|---|
| 280 | |
|---|
| 281 | realRes = RLIMIT_STACK; |
|---|
| 282 | |
|---|
| 283 | break; |
|---|
| 284 | |
|---|
| 285 | case LIMIT_MAXPROC: |
|---|
| 286 | |
|---|
| 287 | realRes = RLIMIT_NPROC; |
|---|
| 288 | |
|---|
| 289 | break; |
|---|
| 290 | |
|---|
| 291 | case LIMIT_MAXOPENFILES: |
|---|
| 292 | |
|---|
| 293 | #ifdef __FreeBSD__ |
|---|
| 294 | realRes = RLIMIT_NOFILE; |
|---|
| 295 | #else |
|---|
| 296 | realRes = RLIMIT_OFILE; |
|---|
| 297 | #endif |
|---|
| 298 | |
|---|
| 299 | break; |
|---|
| 300 | |
|---|
| 301 | default: |
|---|
| 302 | |
|---|
| 303 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETLIMIT, exception::ERRNO_LIBDODO, OSEX_WRONGPARAMETER, TOOLSOSEX_WRONGPARAMETER_STR, __LINE__, __FILE__); |
|---|
| 304 | } |
|---|
| 305 | |
|---|
| 306 | limit.rlim_cur = lim.current; |
|---|
| 307 | limit.rlim_max = lim.max; |
|---|
| 308 | |
|---|
| 309 | if (setrlimit(realRes, &limit) == -1) |
|---|
| 310 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETLIMIT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 311 | } |
|---|
| 312 | |
|---|
| 313 | //------------------------------------------------------------------- |
|---|
| 314 | |
|---|
| 315 | int |
|---|
| 316 | os::priority(short type) |
|---|
| 317 | { |
|---|
| 318 | int prio = getpriority(PRIO_PROCESS, UID(type)); |
|---|
| 319 | if (prio == -1) |
|---|
| 320 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_PRIORITY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 321 | |
|---|
| 322 | return prio; |
|---|
| 323 | } |
|---|
| 324 | |
|---|
| 325 | //------------------------------------------------------------------- |
|---|
| 326 | |
|---|
| 327 | void |
|---|
| 328 | os::setPriority(short type, |
|---|
| 329 | int prio) |
|---|
| 330 | { |
|---|
| 331 | if (setpriority(PRIO_PROCESS, UID(type), prio) == -1) |
|---|
| 332 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETPRIORITY, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 333 | } |
|---|
| 334 | |
|---|
| 335 | //------------------------------------------------------------------- |
|---|
| 336 | |
|---|
| 337 | int |
|---|
| 338 | os::UID(short type) |
|---|
| 339 | { |
|---|
| 340 | switch (type) { |
|---|
| 341 | case ID_UID: |
|---|
| 342 | |
|---|
| 343 | return getuid(); |
|---|
| 344 | |
|---|
| 345 | case ID_EUID: |
|---|
| 346 | |
|---|
| 347 | return geteuid(); |
|---|
| 348 | |
|---|
| 349 | default: |
|---|
| 350 | |
|---|
| 351 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_UID, exception::ERRNO_LIBDODO, OSEX_WRONGPARAMETER, TOOLSOSEX_WRONGPARAMETER_STR, __LINE__, __FILE__); |
|---|
| 352 | } |
|---|
| 353 | } |
|---|
| 354 | |
|---|
| 355 | //------------------------------------------------------------------- |
|---|
| 356 | |
|---|
| 357 | void |
|---|
| 358 | os::setUID(short type, |
|---|
| 359 | int uid) |
|---|
| 360 | { |
|---|
| 361 | int res(0); |
|---|
| 362 | |
|---|
| 363 | switch (type) { |
|---|
| 364 | case ID_UID: |
|---|
| 365 | |
|---|
| 366 | res = setuid(uid); |
|---|
| 367 | |
|---|
| 368 | break; |
|---|
| 369 | |
|---|
| 370 | case ID_EUID: |
|---|
| 371 | |
|---|
| 372 | res = seteuid(uid); |
|---|
| 373 | |
|---|
| 374 | break; |
|---|
| 375 | |
|---|
| 376 | default: |
|---|
| 377 | |
|---|
| 378 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETUID, exception::ERRNO_LIBDODO, OSEX_WRONGPARAMETER, TOOLSOSEX_WRONGPARAMETER_STR, __LINE__, __FILE__); |
|---|
| 379 | } |
|---|
| 380 | |
|---|
| 381 | if (res == -1) |
|---|
| 382 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETUID, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 383 | } |
|---|
| 384 | |
|---|
| 385 | //------------------------------------------------------------------- |
|---|
| 386 | |
|---|
| 387 | int |
|---|
| 388 | os::GID(short type) |
|---|
| 389 | { |
|---|
| 390 | switch (type) { |
|---|
| 391 | case ID_UID: |
|---|
| 392 | |
|---|
| 393 | return getgid(); |
|---|
| 394 | |
|---|
| 395 | case ID_EUID: |
|---|
| 396 | |
|---|
| 397 | return getegid(); |
|---|
| 398 | |
|---|
| 399 | default: |
|---|
| 400 | |
|---|
| 401 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_GID, exception::ERRNO_LIBDODO, OSEX_WRONGPARAMETER, TOOLSOSEX_WRONGPARAMETER_STR, __LINE__, __FILE__); |
|---|
| 402 | } |
|---|
| 403 | } |
|---|
| 404 | |
|---|
| 405 | //------------------------------------------------------------------- |
|---|
| 406 | |
|---|
| 407 | void |
|---|
| 408 | os::setGID(short type, |
|---|
| 409 | int uid) |
|---|
| 410 | { |
|---|
| 411 | int res(0); |
|---|
| 412 | |
|---|
| 413 | switch (type) { |
|---|
| 414 | case ID_UID: |
|---|
| 415 | |
|---|
| 416 | res = setgid(uid); |
|---|
| 417 | |
|---|
| 418 | break; |
|---|
| 419 | |
|---|
| 420 | case ID_EUID: |
|---|
| 421 | |
|---|
| 422 | res = setegid(uid); |
|---|
| 423 | |
|---|
| 424 | break; |
|---|
| 425 | |
|---|
| 426 | default: |
|---|
| 427 | |
|---|
| 428 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETGID, exception::ERRNO_LIBDODO, OSEX_WRONGPARAMETER, TOOLSOSEX_WRONGPARAMETER_STR, __LINE__, __FILE__); |
|---|
| 429 | } |
|---|
| 430 | |
|---|
| 431 | if (res == -1) |
|---|
| 432 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETGID, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 433 | } |
|---|
| 434 | |
|---|
| 435 | //------------------------------------------------------------------- |
|---|
| 436 | |
|---|
| 437 | os::__user__ |
|---|
| 438 | os::user(int uid) |
|---|
| 439 | { |
|---|
| 440 | passwd *in = getpwuid(uid); |
|---|
| 441 | if (in == NULL) |
|---|
| 442 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_USER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 443 | |
|---|
| 444 | __user__ info; |
|---|
| 445 | |
|---|
| 446 | return fillUser(info, in); |
|---|
| 447 | } |
|---|
| 448 | |
|---|
| 449 | //------------------------------------------------------------------- |
|---|
| 450 | |
|---|
| 451 | os::__user__ |
|---|
| 452 | os::user(const dodo::string &uid) |
|---|
| 453 | { |
|---|
| 454 | passwd *in = getpwnam(uid.data()); |
|---|
| 455 | if (in == NULL) |
|---|
| 456 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_USER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 457 | |
|---|
| 458 | __user__ info; |
|---|
| 459 | |
|---|
| 460 | return fillUser(info, in); |
|---|
| 461 | } |
|---|
| 462 | |
|---|
| 463 | //------------------------------------------------------------------- |
|---|
| 464 | |
|---|
| 465 | dodoArray<os::__user__> |
|---|
| 466 | os::users() |
|---|
| 467 | { |
|---|
| 468 | dodoArray<__user__> users; |
|---|
| 469 | |
|---|
| 470 | passwd *in; |
|---|
| 471 | |
|---|
| 472 | __user__ info; |
|---|
| 473 | |
|---|
| 474 | while ((in = getpwent()) != NULL) |
|---|
| 475 | users.push_back(fillUser(info, in)); |
|---|
| 476 | |
|---|
| 477 | switch (errno) { |
|---|
| 478 | case EIO: |
|---|
| 479 | case EMFILE: |
|---|
| 480 | case ENFILE: |
|---|
| 481 | case ENOMEM: |
|---|
| 482 | |
|---|
| 483 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_USERS, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 484 | } |
|---|
| 485 | |
|---|
| 486 | endpwent(); |
|---|
| 487 | |
|---|
| 488 | return users; |
|---|
| 489 | } |
|---|
| 490 | |
|---|
| 491 | //------------------------------------------------------------------- |
|---|
| 492 | |
|---|
| 493 | os::__user__ & |
|---|
| 494 | os::fillUser(__user__ &info, |
|---|
| 495 | void *in) |
|---|
| 496 | { |
|---|
| 497 | info.gid = ((passwd *)in)->pw_gid; |
|---|
| 498 | info.home = ((passwd *)in)->pw_dir; |
|---|
| 499 | info.name = ((passwd *)in)->pw_name; |
|---|
| 500 | info.pass = ((passwd *)in)->pw_passwd; |
|---|
| 501 | info.realName = ((passwd *)in)->pw_gecos; |
|---|
| 502 | info.shell = ((passwd *)in)->pw_shell; |
|---|
| 503 | info.uid = ((passwd *)in)->pw_uid; |
|---|
| 504 | |
|---|
| 505 | return info; |
|---|
| 506 | } |
|---|
| 507 | |
|---|
| 508 | //------------------------------------------------------------------- |
|---|
| 509 | |
|---|
| 510 | os::__group__ & |
|---|
| 511 | os::fillGroup(__group__ &info, |
|---|
| 512 | void *pw) |
|---|
| 513 | { |
|---|
| 514 | info.gid = ((::group *)pw)->gr_gid; |
|---|
| 515 | info.name = ((::group *)pw)->gr_name; |
|---|
| 516 | |
|---|
| 517 | info.members.clear(); |
|---|
| 518 | |
|---|
| 519 | int i(0); |
|---|
| 520 | |
|---|
| 521 | while (((::group *)pw)->gr_mem[i] != NULL) |
|---|
| 522 | info.members.push_back(((::group *)pw)->gr_mem[i++]); |
|---|
| 523 | |
|---|
| 524 | return info; |
|---|
| 525 | } |
|---|
| 526 | |
|---|
| 527 | //------------------------------------------------------------------- |
|---|
| 528 | |
|---|
| 529 | os::__group__ |
|---|
| 530 | os::group(int uid) |
|---|
| 531 | { |
|---|
| 532 | ::group *in = getgrgid(uid); |
|---|
| 533 | if (in == NULL) |
|---|
| 534 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_GROUP, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 535 | |
|---|
| 536 | __group__ info; |
|---|
| 537 | |
|---|
| 538 | return fillGroup(info, in); |
|---|
| 539 | } |
|---|
| 540 | |
|---|
| 541 | //------------------------------------------------------------------- |
|---|
| 542 | |
|---|
| 543 | os::__group__ |
|---|
| 544 | os::group(const dodo::string &uid) |
|---|
| 545 | { |
|---|
| 546 | ::group *in = getgrnam(uid.data()); |
|---|
| 547 | if (in == NULL) |
|---|
| 548 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_GROUP, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 549 | |
|---|
| 550 | __group__ info; |
|---|
| 551 | |
|---|
| 552 | return fillGroup(info, in); |
|---|
| 553 | } |
|---|
| 554 | |
|---|
| 555 | //------------------------------------------------------------------- |
|---|
| 556 | |
|---|
| 557 | dodoArray<os::__group__> |
|---|
| 558 | os::groups() |
|---|
| 559 | { |
|---|
| 560 | dodoArray<__group__> groups; |
|---|
| 561 | |
|---|
| 562 | ::group *in; |
|---|
| 563 | |
|---|
| 564 | __group__ info; |
|---|
| 565 | |
|---|
| 566 | while ((in = getgrent()) != NULL) |
|---|
| 567 | groups.push_back(fillGroup(info, in)); |
|---|
| 568 | |
|---|
| 569 | switch (errno) { |
|---|
| 570 | case EIO: |
|---|
| 571 | case EMFILE: |
|---|
| 572 | case ENFILE: |
|---|
| 573 | case EINTR: |
|---|
| 574 | case ENOMEM: |
|---|
| 575 | |
|---|
| 576 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_GROUPS, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 577 | } |
|---|
| 578 | |
|---|
| 579 | endgrent(); |
|---|
| 580 | |
|---|
| 581 | return groups; |
|---|
| 582 | } |
|---|
| 583 | |
|---|
| 584 | //------------------------------------------------------------------- |
|---|
| 585 | |
|---|
| 586 | void |
|---|
| 587 | os::die(const dodo::string &message, |
|---|
| 588 | int status) |
|---|
| 589 | { |
|---|
| 590 | unsigned short tries = DIE_MAXTRIES; |
|---|
| 591 | |
|---|
| 592 | while (tries-- > 0) |
|---|
| 593 | if (fwrite(message.data(), message.size(), 1, stderr) == 1) |
|---|
| 594 | break; |
|---|
| 595 | fflush(stderr); |
|---|
| 596 | |
|---|
| 597 | kill(0, SIGTERM); |
|---|
| 598 | |
|---|
| 599 | wait(NULL); |
|---|
| 600 | |
|---|
| 601 | exit(status); |
|---|
| 602 | } |
|---|
| 603 | |
|---|
| 604 | //------------------------------------------------------------------- |
|---|
| 605 | |
|---|
| 606 | void |
|---|
| 607 | os::sleepMs(unsigned long period) |
|---|
| 608 | { |
|---|
| 609 | timespec ts = {period/1000, (period%1000)*1000000}; |
|---|
| 610 | |
|---|
| 611 | nanosleep(&ts, NULL); |
|---|
| 612 | } |
|---|
| 613 | |
|---|
| 614 | //------------------------------------------------------------------- |
|---|
| 615 | |
|---|
| 616 | void |
|---|
| 617 | os::sleepUs(unsigned long period) |
|---|
| 618 | { |
|---|
| 619 | timespec ts = {period/1000000, (period%1000000)*1000}; |
|---|
| 620 | |
|---|
| 621 | nanosleep(&ts, NULL); |
|---|
| 622 | } |
|---|
| 623 | |
|---|
| 624 | //------------------------------------------------------------------- |
|---|
| 625 | |
|---|
| 626 | void |
|---|
| 627 | os::sleep(unsigned long period) |
|---|
| 628 | { |
|---|
| 629 | timespec ts = {period, 0}; |
|---|
| 630 | |
|---|
| 631 | nanosleep(&ts, NULL); |
|---|
| 632 | } |
|---|
| 633 | |
|---|
| 634 | //------------------------------------------------------------------- |
|---|
| 635 | |
|---|
| 636 | void |
|---|
| 637 | os::atExit(void (*func)()) |
|---|
| 638 | { |
|---|
| 639 | if (atexit(func) != 0) |
|---|
| 640 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_ATEXIT, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 641 | } |
|---|
| 642 | |
|---|
| 643 | //------------------------------------------------------------------- |
|---|
| 644 | |
|---|
| 645 | int |
|---|
| 646 | os::PID() |
|---|
| 647 | { |
|---|
| 648 | return getpid(); |
|---|
| 649 | } |
|---|
| 650 | |
|---|
| 651 | //------------------------------------------------------------------- |
|---|
| 652 | |
|---|
| 653 | int |
|---|
| 654 | os::PPID() |
|---|
| 655 | { |
|---|
| 656 | return getppid(); |
|---|
| 657 | } |
|---|
| 658 | |
|---|
| 659 | //------------------------------------------------------------------- |
|---|
| 660 | |
|---|
| 661 | int |
|---|
| 662 | os::GPID() |
|---|
| 663 | { |
|---|
| 664 | return getpgrp(); |
|---|
| 665 | } |
|---|
| 666 | |
|---|
| 667 | //------------------------------------------------------------------- |
|---|
| 668 | |
|---|
| 669 | int |
|---|
| 670 | os::GPID(int pid) |
|---|
| 671 | { |
|---|
| 672 | int pgid = getpgid(pid); |
|---|
| 673 | if (pgid == -1) |
|---|
| 674 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_GPID, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 675 | |
|---|
| 676 | return pgid; |
|---|
| 677 | } |
|---|
| 678 | |
|---|
| 679 | //------------------------------------------------------------------- |
|---|
| 680 | |
|---|
| 681 | void |
|---|
| 682 | os::setGPID(int gpid) |
|---|
| 683 | { |
|---|
| 684 | if (setpgid(0, gpid) == 1) |
|---|
| 685 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETGROUPPID, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 686 | } |
|---|
| 687 | |
|---|
| 688 | //------------------------------------------------------------------- |
|---|
| 689 | |
|---|
| 690 | void |
|---|
| 691 | os::setGPID(int pid, |
|---|
| 692 | int gpid) |
|---|
| 693 | { |
|---|
| 694 | if (setpgid(pid, gpid) == 1) |
|---|
| 695 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETGROUPPID, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 696 | } |
|---|
| 697 | |
|---|
| 698 | //------------------------------------------------------------------- |
|---|
| 699 | |
|---|
| 700 | void |
|---|
| 701 | os::sigMask(void *set, |
|---|
| 702 | long blockSignals) |
|---|
| 703 | { |
|---|
| 704 | if (blockSignals != -1) { |
|---|
| 705 | if (isSetFlag(blockSignals, SIGNAL_HANGUP)) |
|---|
| 706 | sigaddset((sigset_t *)set, SIGHUP); |
|---|
| 707 | |
|---|
| 708 | if (isSetFlag(blockSignals, SIGNAL_INTERRUPT)) |
|---|
| 709 | sigaddset((sigset_t *)set, SIGINT); |
|---|
| 710 | |
|---|
| 711 | if (isSetFlag(blockSignals, SIGNAL_QUIT)) |
|---|
| 712 | sigaddset((sigset_t *)set, SIGQUIT); |
|---|
| 713 | |
|---|
| 714 | if (isSetFlag(blockSignals, SIGNAL_ILLEGAL_INSTRUCTION)) |
|---|
| 715 | sigaddset((sigset_t *)set, SIGILL); |
|---|
| 716 | |
|---|
| 717 | if (isSetFlag(blockSignals, SIGNAL_ABORT)) |
|---|
| 718 | sigaddset((sigset_t *)set, SIGABRT); |
|---|
| 719 | |
|---|
| 720 | if (isSetFlag(blockSignals, SIGNAL_BUS_FAULT)) |
|---|
| 721 | sigaddset((sigset_t *)set, SIGBUS); |
|---|
| 722 | |
|---|
| 723 | if (isSetFlag(blockSignals, SIGNAL_FLOATINGPOINT_FAULT)) |
|---|
| 724 | sigaddset((sigset_t *)set, SIGFPE); |
|---|
| 725 | |
|---|
| 726 | if (isSetFlag(blockSignals, SIGNAL_USER_DEFINED1)) |
|---|
| 727 | sigaddset((sigset_t *)set, SIGUSR1); |
|---|
| 728 | |
|---|
| 729 | if (isSetFlag(blockSignals, SIGNAL_SEGMENTATION_FAULT)) |
|---|
| 730 | sigaddset((sigset_t *)set, SIGSEGV); |
|---|
| 731 | |
|---|
| 732 | if (isSetFlag(blockSignals, SIGNAL_USER_DEFINED2)) |
|---|
| 733 | sigaddset((sigset_t *)set, SIGUSR2); |
|---|
| 734 | |
|---|
| 735 | if (isSetFlag(blockSignals, SIGNAL_PIPE_FAULT)) |
|---|
| 736 | sigaddset((sigset_t *)set, SIGPIPE); |
|---|
| 737 | |
|---|
| 738 | if (isSetFlag(blockSignals, SIGNAL_ALARM)) |
|---|
| 739 | sigaddset((sigset_t *)set, SIGALRM); |
|---|
| 740 | |
|---|
| 741 | if (isSetFlag(blockSignals, SIGNAL_TERMINATION)) |
|---|
| 742 | sigaddset((sigset_t *)set, SIGTERM); |
|---|
| 743 | |
|---|
| 744 | if (isSetFlag(blockSignals, SIGNAL_CHILD_CHANGED)) |
|---|
| 745 | sigaddset((sigset_t *)set, SIGCHLD); |
|---|
| 746 | |
|---|
| 747 | if (isSetFlag(blockSignals, SIGNAL_CONTINUE)) |
|---|
| 748 | sigaddset((sigset_t *)set, SIGCONT); |
|---|
| 749 | |
|---|
| 750 | if (isSetFlag(blockSignals, SIGNAL_KEYBOARD_STOP)) |
|---|
| 751 | sigaddset((sigset_t *)set, SIGTSTP); |
|---|
| 752 | |
|---|
| 753 | if (isSetFlag(blockSignals, SIGNAL_CPULIMIT_EXCEEDED)) |
|---|
| 754 | sigaddset((sigset_t *)set, SIGXCPU); |
|---|
| 755 | |
|---|
| 756 | if (isSetFlag(blockSignals, SIGNAL_FILESIZE_EXCEEDED)) |
|---|
| 757 | sigaddset((sigset_t *)set, SIGXFSZ); |
|---|
| 758 | |
|---|
| 759 | if (isSetFlag(blockSignals, SIGNAL_BAD_SYSCALL)) |
|---|
| 760 | sigaddset((sigset_t *)set, SIGSYS); |
|---|
| 761 | } |
|---|
| 762 | } |
|---|
| 763 | |
|---|
| 764 | //------------------------------------------------------------------- |
|---|
| 765 | |
|---|
| 766 | void |
|---|
| 767 | os::setSignalHandler(long signal, |
|---|
| 768 | signalHandler handler, |
|---|
| 769 | int blockSignals) |
|---|
| 770 | { |
|---|
| 771 | pc::sync::stack tg(&keeper); |
|---|
| 772 | |
|---|
| 773 | #ifdef DL_EXT |
|---|
| 774 | deinitSignalModule deinit; |
|---|
| 775 | |
|---|
| 776 | int handleSignal = toSignalNumber(signal); |
|---|
| 777 | if (handleSignal > 0 && handlesOpenedSig[handleSignal]) { |
|---|
| 778 | deinit = (deinitSignalModule)dlsym(handlesSig[handleSignal], "deinitToolsOsSignalModule"); |
|---|
| 779 | if (deinit != NULL) |
|---|
| 780 | deinit(handlesCookiesSig[handleSignal]); |
|---|
| 781 | |
|---|
| 782 | #ifndef DL_FAST |
|---|
| 783 | dlclose(handlesSig[handleSignal]); |
|---|
| 784 | #endif |
|---|
| 785 | |
|---|
| 786 | handlesOpenedSig[handleSignal] = false; |
|---|
| 787 | handlesSig[handleSignal] = NULL; |
|---|
| 788 | } |
|---|
| 789 | #endif |
|---|
| 790 | |
|---|
| 791 | struct sigaction act; |
|---|
| 792 | act.sa_sigaction = (void(*) (int, siginfo_t *, void*))handler; |
|---|
| 793 | act.sa_flags = SA_SIGINFO | SA_RESTART; |
|---|
| 794 | |
|---|
| 795 | if (sigemptyset(&act.sa_mask) == -1) |
|---|
| 796 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 797 | |
|---|
| 798 | sigMask(&act.sa_mask, blockSignals); |
|---|
| 799 | |
|---|
| 800 | if (sigaction(os::toRealSignal(signal), &act, NULL) == -1) |
|---|
| 801 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 802 | } |
|---|
| 803 | |
|---|
| 804 | //------------------------------------------------------------------- |
|---|
| 805 | |
|---|
| 806 | void |
|---|
| 807 | os::setMicroTimer(unsigned long timeout, |
|---|
| 808 | signalHandler handler, |
|---|
| 809 | int blockSignals) |
|---|
| 810 | { |
|---|
| 811 | pc::sync::stack tg(&keeper); |
|---|
| 812 | |
|---|
| 813 | #ifdef DL_EXT |
|---|
| 814 | deinitSignalModule deinit; |
|---|
| 815 | |
|---|
| 816 | int handleSignal = toSignalNumber(SIGNAL_ALARM); |
|---|
| 817 | if (handleSignal > 0 && handlesOpenedSig[handleSignal]) { |
|---|
| 818 | deinit = (deinitSignalModule)dlsym(handlesSig[handleSignal], "deinitToolsOsSignalModule"); |
|---|
| 819 | if (deinit != NULL) |
|---|
| 820 | deinit(handlesCookiesSig[handleSignal]); |
|---|
| 821 | |
|---|
| 822 | #ifndef DL_FAST |
|---|
| 823 | dlclose(handlesSig[handleSignal]); |
|---|
| 824 | #endif |
|---|
| 825 | |
|---|
| 826 | handlesOpenedSig[handleSignal] = false; |
|---|
| 827 | handlesSig[handleSignal] = NULL; |
|---|
| 828 | } |
|---|
| 829 | #endif |
|---|
| 830 | |
|---|
| 831 | struct sigaction act; |
|---|
| 832 | act.sa_sigaction = (void(*) (int, siginfo_t *, void*))handler; |
|---|
| 833 | act.sa_flags = SA_SIGINFO | SA_RESTART; |
|---|
| 834 | |
|---|
| 835 | if (sigemptyset(&act.sa_mask) == -1) |
|---|
| 836 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETMICROTIMER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 837 | |
|---|
| 838 | sigMask(&act.sa_mask, blockSignals); |
|---|
| 839 | |
|---|
| 840 | long tSec = 0, tMicrosec = timeout; |
|---|
| 841 | |
|---|
| 842 | if (timeout > 1000000) { |
|---|
| 843 | tSec = timeout / 1000000; |
|---|
| 844 | tMicrosec = timeout % 1000000; |
|---|
| 845 | } |
|---|
| 846 | |
|---|
| 847 | itimerval value; |
|---|
| 848 | value.it_interval.tv_sec = tSec; |
|---|
| 849 | value.it_interval.tv_usec = tMicrosec; |
|---|
| 850 | value.it_value.tv_sec = tSec; |
|---|
| 851 | value.it_value.tv_usec = tMicrosec; |
|---|
| 852 | |
|---|
| 853 | if (sigaction(SIGALRM, &act, NULL) == -1) |
|---|
| 854 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETMICROTIMER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 855 | |
|---|
| 856 | if (setitimer(ITIMER_REAL, &value, NULL) != 0) |
|---|
| 857 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETMICROTIMER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 858 | } |
|---|
| 859 | |
|---|
| 860 | //------------------------------------------------------------------- |
|---|
| 861 | |
|---|
| 862 | void |
|---|
| 863 | os::setTimer(long timeout, |
|---|
| 864 | signalHandler handler, |
|---|
| 865 | int blockSignals) |
|---|
| 866 | { |
|---|
| 867 | pc::sync::stack tg(&keeper); |
|---|
| 868 | |
|---|
| 869 | #ifdef DL_EXT |
|---|
| 870 | deinitSignalModule deinit; |
|---|
| 871 | |
|---|
| 872 | int handleSignal = toSignalNumber(SIGNAL_ALARM); |
|---|
| 873 | if (handleSignal > 0 && handlesOpenedSig[handleSignal]) { |
|---|
| 874 | deinit = (deinitSignalModule)dlsym(handlesSig[handleSignal], "deinitToolsOsSignalModule"); |
|---|
| 875 | if (deinit != NULL) |
|---|
| 876 | deinit(handlesCookiesSig[handleSignal]); |
|---|
| 877 | |
|---|
| 878 | #ifndef DL_FAST |
|---|
| 879 | dlclose(handlesSig[handleSignal]); |
|---|
| 880 | #endif |
|---|
| 881 | |
|---|
| 882 | handlesOpenedSig[handleSignal] = false; |
|---|
| 883 | handlesSig[handleSignal] = NULL; |
|---|
| 884 | } |
|---|
| 885 | #endif |
|---|
| 886 | |
|---|
| 887 | struct sigaction act; |
|---|
| 888 | act.sa_sigaction = (void(*) (int, siginfo_t *, void*))handler; |
|---|
| 889 | act.sa_flags = SA_SIGINFO | SA_RESTART; |
|---|
| 890 | |
|---|
| 891 | if (sigemptyset(&act.sa_mask) == -1) |
|---|
| 892 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETTIMER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 893 | |
|---|
| 894 | sigMask(&act.sa_mask, blockSignals); |
|---|
| 895 | |
|---|
| 896 | itimerval value; |
|---|
| 897 | value.it_interval.tv_sec = timeout; |
|---|
| 898 | value.it_interval.tv_usec = 0; |
|---|
| 899 | value.it_value.tv_sec = timeout; |
|---|
| 900 | value.it_value.tv_usec = 0; |
|---|
| 901 | |
|---|
| 902 | if (sigaction(SIGALRM, &act, NULL) == -1) |
|---|
| 903 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETTIMER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 904 | |
|---|
| 905 | if (setitimer(ITIMER_REAL, &value, NULL) != 0) |
|---|
| 906 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETTIMER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 907 | } |
|---|
| 908 | |
|---|
| 909 | //------------------------------------------------------------------- |
|---|
| 910 | |
|---|
| 911 | bool |
|---|
| 912 | os::isSignalHandled(long signal) |
|---|
| 913 | { |
|---|
| 914 | struct sigaction act; |
|---|
| 915 | if (sigaction(os::toRealSignal(signal), NULL, &act) == 1) |
|---|
| 916 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 917 | |
|---|
| 918 | if (act.sa_sigaction != NULL || act.sa_handler != NULL) |
|---|
| 919 | return true; |
|---|
| 920 | else |
|---|
| 921 | return false; |
|---|
| 922 | } |
|---|
| 923 | |
|---|
| 924 | //------------------------------------------------------------------- |
|---|
| 925 | |
|---|
| 926 | void |
|---|
| 927 | os::sendSignal(int pid, |
|---|
| 928 | long signal) |
|---|
| 929 | { |
|---|
| 930 | if (kill(pid, os::toRealSignal(signal)) == -1) |
|---|
| 931 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SENDSIGNAL, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 932 | } |
|---|
| 933 | |
|---|
| 934 | //------------------------------------------------------------------- |
|---|
| 935 | |
|---|
| 936 | void |
|---|
| 937 | os::removeSignalHandler(long signal) |
|---|
| 938 | { |
|---|
| 939 | pc::sync::stack tg(&keeper); |
|---|
| 940 | |
|---|
| 941 | #ifdef DL_EXT |
|---|
| 942 | deinitSignalModule deinit; |
|---|
| 943 | |
|---|
| 944 | int handleSignal = toSignalNumber(signal); |
|---|
| 945 | if (handleSignal > 0 && handlesOpenedSig[handleSignal]) { |
|---|
| 946 | deinit = (deinitSignalModule)dlsym(handlesSig[handleSignal], "deinitToolsOsSignalModule"); |
|---|
| 947 | if (deinit != NULL) |
|---|
| 948 | deinit(handlesCookiesSig[handleSignal]); |
|---|
| 949 | |
|---|
| 950 | #ifndef DL_FAST |
|---|
| 951 | dlclose(handlesSig[handleSignal]); |
|---|
| 952 | #endif |
|---|
| 953 | |
|---|
| 954 | handlesOpenedSig[handleSignal] = false; |
|---|
| 955 | handlesSig[handleSignal] = NULL; |
|---|
| 956 | } |
|---|
| 957 | #endif |
|---|
| 958 | |
|---|
| 959 | struct sigaction act; |
|---|
| 960 | act.sa_sigaction = NULL; |
|---|
| 961 | |
|---|
| 962 | if (sigaction(os::toRealSignal(signal), &act, NULL) == 1) |
|---|
| 963 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_REMOVESIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 964 | } |
|---|
| 965 | |
|---|
| 966 | //------------------------------------------------------------------- |
|---|
| 967 | |
|---|
| 968 | #ifdef DL_EXT |
|---|
| 969 | os::__signal_module__ |
|---|
| 970 | os::module(const dodo::string &module, |
|---|
| 971 | void *toInit) |
|---|
| 972 | { |
|---|
| 973 | #ifdef DL_FAST |
|---|
| 974 | void *handle = dlopen(module.data(), RTLD_LAZY | RTLD_NODELETE); |
|---|
| 975 | #else |
|---|
| 976 | void *handle = dlopen(module.data(), RTLD_LAZY); |
|---|
| 977 | #endif |
|---|
| 978 | if (handle == NULL) |
|---|
| 979 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_MODULE, exception::ERRNO_DYNLOAD, 0, dlerror(), __LINE__, __FILE__); |
|---|
| 980 | |
|---|
| 981 | initSignalModule init = (initSignalModule)dlsym(handle, "initToolsOsSignalModule"); |
|---|
| 982 | if (init == NULL) |
|---|
| 983 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_MODULE, exception::ERRNO_DYNLOAD, 0, dlerror(), __LINE__, __FILE__); |
|---|
| 984 | |
|---|
| 985 | __signal_module__ mod = init(toInit); |
|---|
| 986 | |
|---|
| 987 | deinitSignalModule deinit = (deinitSignalModule)dlsym(handle, "deinitToolsOsSignalModule"); |
|---|
| 988 | if (init != NULL) |
|---|
| 989 | deinit(mod.cookie); |
|---|
| 990 | |
|---|
| 991 | |
|---|
| 992 | #ifndef DL_FAST |
|---|
| 993 | if (dlclose(handle) != 0) |
|---|
| 994 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_MODULE, exception::ERRNO_DYNLOAD, 0, dlerror(), __LINE__, __FILE__); |
|---|
| 995 | #endif |
|---|
| 996 | |
|---|
| 997 | return mod; |
|---|
| 998 | } |
|---|
| 999 | |
|---|
| 1000 | //------------------------------------------------------------------- |
|---|
| 1001 | |
|---|
| 1002 | void |
|---|
| 1003 | os::setSignalHandler(const dodo::string &path, |
|---|
| 1004 | void *toInit) |
|---|
| 1005 | { |
|---|
| 1006 | pc::sync::stack tg(&keeper); |
|---|
| 1007 | |
|---|
| 1008 | #ifdef DL_FAST |
|---|
| 1009 | void *handle = dlopen(path.data(), RTLD_LAZY | RTLD_NODELETE); |
|---|
| 1010 | #else |
|---|
| 1011 | void *handle = dlopen(path.data(), RTLD_LAZY); |
|---|
| 1012 | #endif |
|---|
| 1013 | if (handle == NULL) |
|---|
| 1014 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1015 | |
|---|
| 1016 | initSignalModule init = (initSignalModule)dlsym(handle, "initToolsOsSignalModule"); |
|---|
| 1017 | if (init == NULL) |
|---|
| 1018 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1019 | |
|---|
| 1020 | __signal_module__ mod = init(toInit); |
|---|
| 1021 | |
|---|
| 1022 | deinitSignalModule deinit; |
|---|
| 1023 | |
|---|
| 1024 | int handleSignal = toSignalNumber(mod.signal); |
|---|
| 1025 | if (handleSignal > 0 && handlesOpenedSig[handleSignal]) { |
|---|
| 1026 | deinit = (deinitSignalModule)dlsym(handlesSig[handleSignal], "deinitToolsOsSignalModule"); |
|---|
| 1027 | if (deinit != NULL) |
|---|
| 1028 | deinit(handlesCookiesSig[handleSignal]); |
|---|
| 1029 | |
|---|
| 1030 | #ifndef DL_FAST |
|---|
| 1031 | dlclose(handlesSig[handleSignal]); |
|---|
| 1032 | #endif |
|---|
| 1033 | |
|---|
| 1034 | handlesOpenedSig[handleSignal] = false; |
|---|
| 1035 | handlesSig[handleSignal] = NULL; |
|---|
| 1036 | } |
|---|
| 1037 | |
|---|
| 1038 | handlesSig[handleSignal] = handle; |
|---|
| 1039 | |
|---|
| 1040 | signalHandler in = (signalHandler)dlsym(handlesSig[mod.signal], mod.hook); |
|---|
| 1041 | if (in == NULL) |
|---|
| 1042 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1043 | |
|---|
| 1044 | struct sigaction act; |
|---|
| 1045 | act.sa_sigaction = (void(*) (int, siginfo_t *, void*))in; |
|---|
| 1046 | act.sa_flags = SA_SIGINFO | SA_RESTART; |
|---|
| 1047 | |
|---|
| 1048 | if (sigemptyset(&act.sa_mask) == -1) |
|---|
| 1049 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1050 | |
|---|
| 1051 | sigMask(&act.sa_mask, mod.blockSignals); |
|---|
| 1052 | |
|---|
| 1053 | if (sigaction(os::toRealSignal(mod.signal), &act, NULL) == 1) |
|---|
| 1054 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_SETSIGNALHANDLER, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1055 | |
|---|
| 1056 | handlesOpenedSig[handleSignal] = true; |
|---|
| 1057 | } |
|---|
| 1058 | #endif |
|---|
| 1059 | |
|---|
| 1060 | //------------------------------------------------------------------- |
|---|
| 1061 | |
|---|
| 1062 | int |
|---|
| 1063 | os::toSignalNumber(long signal) |
|---|
| 1064 | { |
|---|
| 1065 | switch (signal) { |
|---|
| 1066 | case SIGNAL_HANGUP: |
|---|
| 1067 | |
|---|
| 1068 | return 0; |
|---|
| 1069 | |
|---|
| 1070 | case SIGNAL_INTERRUPT: |
|---|
| 1071 | |
|---|
| 1072 | return 1; |
|---|
| 1073 | |
|---|
| 1074 | case SIGNAL_QUIT: |
|---|
| 1075 | |
|---|
| 1076 | return 2; |
|---|
| 1077 | |
|---|
| 1078 | case SIGNAL_ILLEGAL_INSTRUCTION: |
|---|
| 1079 | |
|---|
| 1080 | return 3; |
|---|
| 1081 | |
|---|
| 1082 | case SIGNAL_ABORT: |
|---|
| 1083 | |
|---|
| 1084 | return 4; |
|---|
| 1085 | |
|---|
| 1086 | case SIGNAL_BUS_FAULT: |
|---|
| 1087 | |
|---|
| 1088 | return 5; |
|---|
| 1089 | |
|---|
| 1090 | case SIGNAL_FLOATINGPOINT_FAULT: |
|---|
| 1091 | |
|---|
| 1092 | return 6; |
|---|
| 1093 | |
|---|
| 1094 | case SIGNAL_USER_DEFINED1: |
|---|
| 1095 | |
|---|
| 1096 | return 7; |
|---|
| 1097 | |
|---|
| 1098 | case SIGNAL_SEGMENTATION_FAULT: |
|---|
| 1099 | |
|---|
| 1100 | return 8; |
|---|
| 1101 | |
|---|
| 1102 | case SIGNAL_USER_DEFINED2: |
|---|
| 1103 | |
|---|
| 1104 | return 9; |
|---|
| 1105 | |
|---|
| 1106 | case SIGNAL_PIPE_FAULT: |
|---|
| 1107 | |
|---|
| 1108 | return 10; |
|---|
| 1109 | |
|---|
| 1110 | case SIGNAL_ALARM: |
|---|
| 1111 | |
|---|
| 1112 | return 11; |
|---|
| 1113 | |
|---|
| 1114 | case SIGNAL_TERMINATION: |
|---|
| 1115 | |
|---|
| 1116 | return 12; |
|---|
| 1117 | |
|---|
| 1118 | case SIGNAL_CHILD_CHANGED: |
|---|
| 1119 | |
|---|
| 1120 | return 13; |
|---|
| 1121 | |
|---|
| 1122 | case SIGNAL_CONTINUE: |
|---|
| 1123 | |
|---|
| 1124 | return 14; |
|---|
| 1125 | |
|---|
| 1126 | case SIGNAL_KEYBOARD_STOP: |
|---|
| 1127 | |
|---|
| 1128 | return 15; |
|---|
| 1129 | |
|---|
| 1130 | case SIGNAL_CPULIMIT_EXCEEDED: |
|---|
| 1131 | |
|---|
| 1132 | return 16; |
|---|
| 1133 | |
|---|
| 1134 | case SIGNAL_FILESIZE_EXCEEDED: |
|---|
| 1135 | |
|---|
| 1136 | return 17; |
|---|
| 1137 | |
|---|
| 1138 | case SIGNAL_BAD_SYSCALL: |
|---|
| 1139 | |
|---|
| 1140 | return 18; |
|---|
| 1141 | |
|---|
| 1142 | default: |
|---|
| 1143 | |
|---|
| 1144 | return -1; |
|---|
| 1145 | } |
|---|
| 1146 | } |
|---|
| 1147 | |
|---|
| 1148 | //------------------------------------------------------------------- |
|---|
| 1149 | |
|---|
| 1150 | int |
|---|
| 1151 | os::toRealSignal(long signal) |
|---|
| 1152 | { |
|---|
| 1153 | switch (signal) { |
|---|
| 1154 | case SIGNAL_HANGUP: |
|---|
| 1155 | |
|---|
| 1156 | return SIGHUP; |
|---|
| 1157 | |
|---|
| 1158 | case SIGNAL_INTERRUPT: |
|---|
| 1159 | |
|---|
| 1160 | return SIGINT; |
|---|
| 1161 | |
|---|
| 1162 | case SIGNAL_QUIT: |
|---|
| 1163 | |
|---|
| 1164 | return SIGQUIT; |
|---|
| 1165 | |
|---|
| 1166 | case SIGNAL_ILLEGAL_INSTRUCTION: |
|---|
| 1167 | |
|---|
| 1168 | return SIGILL; |
|---|
| 1169 | |
|---|
| 1170 | case SIGNAL_ABORT: |
|---|
| 1171 | |
|---|
| 1172 | return SIGABRT; |
|---|
| 1173 | |
|---|
| 1174 | case SIGNAL_BUS_FAULT: |
|---|
| 1175 | |
|---|
| 1176 | return SIGBUS; |
|---|
| 1177 | |
|---|
| 1178 | case SIGNAL_FLOATINGPOINT_FAULT: |
|---|
| 1179 | |
|---|
| 1180 | return SIGFPE; |
|---|
| 1181 | |
|---|
| 1182 | case SIGNAL_USER_DEFINED1: |
|---|
| 1183 | |
|---|
| 1184 | return SIGUSR1; |
|---|
| 1185 | |
|---|
| 1186 | case SIGNAL_SEGMENTATION_FAULT: |
|---|
| 1187 | |
|---|
| 1188 | return SIGSEGV; |
|---|
| 1189 | |
|---|
| 1190 | case SIGNAL_USER_DEFINED2: |
|---|
| 1191 | |
|---|
| 1192 | return SIGUSR2; |
|---|
| 1193 | |
|---|
| 1194 | case SIGNAL_PIPE_FAULT: |
|---|
| 1195 | |
|---|
| 1196 | return SIGPIPE; |
|---|
| 1197 | |
|---|
| 1198 | case SIGNAL_ALARM: |
|---|
| 1199 | |
|---|
| 1200 | return SIGALRM; |
|---|
| 1201 | |
|---|
| 1202 | case SIGNAL_TERMINATION: |
|---|
| 1203 | |
|---|
| 1204 | return SIGTERM; |
|---|
| 1205 | |
|---|
| 1206 | case SIGNAL_CHILD_CHANGED: |
|---|
| 1207 | |
|---|
| 1208 | return SIGCHLD; |
|---|
| 1209 | |
|---|
| 1210 | case SIGNAL_CONTINUE: |
|---|
| 1211 | |
|---|
| 1212 | return SIGCONT; |
|---|
| 1213 | |
|---|
| 1214 | case SIGNAL_KEYBOARD_STOP: |
|---|
| 1215 | |
|---|
| 1216 | return SIGTSTP; |
|---|
| 1217 | |
|---|
| 1218 | case SIGNAL_CPULIMIT_EXCEEDED: |
|---|
| 1219 | |
|---|
| 1220 | return SIGXCPU; |
|---|
| 1221 | |
|---|
| 1222 | case SIGNAL_FILESIZE_EXCEEDED: |
|---|
| 1223 | |
|---|
| 1224 | return SIGXFSZ; |
|---|
| 1225 | |
|---|
| 1226 | case SIGNAL_BAD_SYSCALL: |
|---|
| 1227 | |
|---|
| 1228 | return SIGSYS; |
|---|
| 1229 | |
|---|
| 1230 | default: |
|---|
| 1231 | |
|---|
| 1232 | return -1; |
|---|
| 1233 | } |
|---|
| 1234 | } |
|---|
| 1235 | |
|---|
| 1236 | //------------------------------------------------------------------- |
|---|
| 1237 | |
|---|
| 1238 | void |
|---|
| 1239 | os::blockSignal(long signals, |
|---|
| 1240 | bool block) |
|---|
| 1241 | { |
|---|
| 1242 | sigset_t signal_mask; |
|---|
| 1243 | sigemptyset(&signal_mask); |
|---|
| 1244 | |
|---|
| 1245 | os::sigMask(&signal_mask, signals); |
|---|
| 1246 | |
|---|
| 1247 | if (block) |
|---|
| 1248 | sigprocmask(SIG_BLOCK, &signal_mask, NULL); |
|---|
| 1249 | else |
|---|
| 1250 | sigprocmask(SIG_UNBLOCK, &signal_mask, NULL); |
|---|
| 1251 | } |
|---|
| 1252 | |
|---|
| 1253 | //------------------------------------------------------------------- |
|---|
| 1254 | |
|---|
| 1255 | void |
|---|
| 1256 | os::daemonize() |
|---|
| 1257 | { |
|---|
| 1258 | pid_t pid = fork(); |
|---|
| 1259 | |
|---|
| 1260 | if (pid == 0) { |
|---|
| 1261 | if (setsid() == -1) |
|---|
| 1262 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1263 | |
|---|
| 1264 | if (close(0) == -1) |
|---|
| 1265 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1266 | if (close(1) == -1) |
|---|
| 1267 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1268 | if (close(2) == -1) |
|---|
| 1269 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1270 | |
|---|
| 1271 | if (chdir("/") == -1) |
|---|
| 1272 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1273 | } else { |
|---|
| 1274 | if (pid == -1) |
|---|
| 1275 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1276 | else |
|---|
| 1277 | _exit(0); |
|---|
| 1278 | } |
|---|
| 1279 | } |
|---|
| 1280 | |
|---|
| 1281 | //------------------------------------------------------------------- |
|---|
| 1282 | |
|---|
| 1283 | void |
|---|
| 1284 | os::daemonize(daemon func, |
|---|
| 1285 | void *data) |
|---|
| 1286 | { |
|---|
| 1287 | pid_t pid = fork(); |
|---|
| 1288 | |
|---|
| 1289 | if (pid == 0) { |
|---|
| 1290 | if (setsid() == -1) |
|---|
| 1291 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1292 | |
|---|
| 1293 | if (close(0) == -1) |
|---|
| 1294 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1295 | if (close(1) == -1) |
|---|
| 1296 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1297 | if (close(2) == -1) |
|---|
| 1298 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1299 | |
|---|
| 1300 | if (chdir("/") == -1) |
|---|
| 1301 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1302 | |
|---|
| 1303 | func(data); |
|---|
| 1304 | |
|---|
| 1305 | exit(0); |
|---|
| 1306 | } else { |
|---|
| 1307 | if (pid == -1) |
|---|
| 1308 | dodo_throw exception::basic(exception::MODULE_TOOLSOS, OSEX_DAEMONIZE, exception::ERRNO_ERRNO, errno, strerror(errno), __LINE__, __FILE__); |
|---|
| 1309 | else |
|---|
| 1310 | _exit(0); |
|---|
| 1311 | } |
|---|
| 1312 | } |
|---|
| 1313 | |
|---|
| 1314 | //------------------------------------------------------------------- |
|---|