1/* ***************************************************************************** 2 3libcsc: System Subsystem 4 5 ---------------------------------------------------------------- 6 7Copyright (c) 1999, 2001, 2002 Douglas R. Jerome, Peoria, AZ USA 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU Library General Public License as 11 published by the Free Software Foundation; either version 2 of the 12 License, or (at your option) any later version. 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 General Public License for more details. 18 19 You should have received a copy of the GNU Library General Public 20 License along with this program; if not, write to the Free Software 21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 23 ---------------------------------------------------------------- 24 25FILE NAME 26 27 $RCSfile: csc_sys.c,v $ 28 $Revision: 1.7 $ 29 $Date: 2002/05/11 04:56:05 $ 30 31PROGRAM INFORMATION 32 33 Developed by: libcsc project 34 Developer: Douglas R. Jerome, drj, <jerome@primenet.com> 35 36FILE DESCRIPTION 37 38<SUBSYSTEM NAME="csc_sys"> 39 40NAME 41 csc_sys 42 43DESCRIPTION 44 System Subsystem 45 46FUNCTIONS 47 CSCsysLimitsGet - find some system limits 48 CSCsysInstallSignal - fairly portable signal installer 49 CSCsysUsleep - sleep some microseconds 50</SUBSYSTEM> 51 52CHANGE LOG 53 54 10may02 drj Miscellaneous c-switching and header file changes. 55 56 02may02 drj Small changes to support Solaris. 57 58 20apr02 drj Small comments changes. 59 60 13apr02 drj Added CSCsysUsleep(). 61 62 25jun01 drj Converted to libcsc: renamed everything from rt to csc, 63 removed some debug message printing code. 64 65 29apr99 drj Rebaselined from librt version 0.3.1. 66 67***************************************************************************** */ 68 69 70/* ************************************************************************* */ 71/* */ 72/* F e a t u r e S w i t c h e s */ 73/* */ 74/* ************************************************************************* */ 75 76/* 77 * Select these feature by moving them from the `if UNDEF' into the `else' 78 * section. 79 */ 80#ifdef UNDEF 81# define _BSD_SOURCE 1 /* 4.3+bsd subsystems */ 82# define _POSIX_SOURCE 1 /* posix.1 */ 83# define _POSIX_C_SOURCE 199309L /* posix.1 and posix.4 */ 84#else 85# define _POSIX_C_SOURCE 199506L /* posix.1 and posix.4, and more */ 86# ifndef _REENTRANT 87# define _REENTRANT /* for glibc */ 88# endif 89#endif 90 91 92/* ************************************************************************* */ 93/* */ 94/* I n c l u d e d F i l e s */ 95/* */ 96/* ************************************************************************* */ 97 98/* 99 * OS Specific Header Files 100 */ 101/* (None.) */ 102 103/* 104 * Standard C (ANSI) Header Files 105 */ 106#include <errno.h> 107#include <string.h> 108#ifdef DEBUG 109# include <stdio.h> 110#endif 111 112/* 113 * Posix Header Files 114 */ 115#include <unistd.h> 116#include <signal.h> /* use POSIX signal API */ 117 118/* 119 * 4.3+BSD Header Files 120 */ 121#ifdef SOLARIS /* Use extensions because the use of POSIX */ 122# define __EXTENSIONS__ /* disables "struct timeval". */ 123#endif 124#include <sys/time.h> 125#ifdef SOLARIS 126# undef __EXTENSIONS__ 127#endif 128 129/* 130 * Project Specific Header Files 131 */ 132#include "libcsc_debug.h" 133#include "libcsc.h" 134 135 136/* ************************************************************************* */ 137/* */ 138/* M a n i f e s t C o n s t a n t s */ 139/* */ 140/* ************************************************************************* */ 141 142/* (None.) */ 143 144 145/* ************************************************************************* */ 146/* */ 147/* E x t e r n a l R e f e r e n c e s */ 148/* */ 149/* ************************************************************************* */ 150 151/* (None.) */ 152 153 154/* ************************************************************************* */ 155/* */ 156/* S c a l a r D a t a T y p e s */ 157/* */ 158/* ************************************************************************* */ 159 160/* (None.) */ 161 162 163/* ************************************************************************* */ 164/* */ 165/* N o n - S c a l a r D a t a S t r u c t u r e s */ 166/* */ 167/* ************************************************************************* */ 168 169/* (None.) */ 170 171 172/* ************************************************************************* */ 173/* */ 174/* P u b l i c G l o b a l V a r i a b l e s */ 175/* */ 176/* ************************************************************************* */ 177 178/* (None.) */ 179 180 181/* ************************************************************************* */ 182/* */ 183/* P r i v a t e G l o b a l V a r i a b l e s */ 184/* */ 185/* ************************************************************************* */ 186 187/* (None.) */ 188 189 190/* ************************************************************************* */ 191/* */ 192/* E x e c u t a b l e C o d e (Locally Used Functions) */ 193/* */ 194/* ************************************************************************* */ 195 196 197/************************************************************************** 198 * Private Function Prototypes 199 **************************************************************************/ 200 201/* (None.) */ 202 203 204/* ---------------------------------------------------------------------- */ 205 206 207/************************************************************************** 208 * Private Function 209 **************************************************************************/ 210 211/* (None.) */ 212 213 214/* ************************************************************************* */ 215/* */ 216/* E x e c u t a b l e C o d e (External Interface Functions) */ 217/* */ 218/* ************************************************************************* */ 219 220 221/*************************************************************************** 222 * Public Function rtusleep 223 *************************************************************************** 224 225<SUBROUTINE NAME="CSCsysUsleep"> 226 227NAME 228 CSCsysUsleep - sleep some microseconds (rounded to kernel capability) 229 230SYNOPSYS 231 #include "libcsc.h" 232 233 void CSCsysUsleep ( 234 const size_t microseconds 235 ); 236 237RETURN VALUE 238 CSCsysUsleep() has no return value. 239 240DESCRIPTION 241 The calling process/task will block for microseconds. The actual time 242 blocked will be descretized to the granularity implemented by the 243 kernel. 244 245SEE ALSO 246 CSCsysInstallSignal(3) 247 CSCsysLimitsGet(3) 248</SUBROUTINE> 249 250 ***************************************************************************/ 251 252PUBLIC void (CSCsysUsleep) ( 253 const size_t microseconds 254 ) 255 { 256 struct timeval timeout; 257 fd_set readfds; 258 fd_set writefds; 259 fd_set exceptfds; 260 261 FD_ZERO (&readfds); 262 FD_ZERO (&writefds); 263 FD_ZERO (&exceptfds); 264 265 timeout.tv_sec = microseconds / 1000000u; 266 timeout.tv_usec = microseconds % 1000000u; 267 268 select (1, &readfds, &writefds, &exceptfds, &timeout); 269 } 270 271 272/*************************************************************************** 273 * Public Function CSCsysLimitsGet 274 *************************************************************************** 275 276<SUBROUTINE NAME="CSCsysLimitsGet"> 277 278NAME 279 CSCsysLimitsGet - find some system limits 280 281SYNOPSYS 282 #include "libcsc.h" 283 284 int CSCsysLimitsGet ( 285 int* const fileOpenMaxPtr, 286 int* const fileNameLengthPtr, 287 int* const filePathLengthPtr 288 ); 289 290RETURN VALUE 291 RTS_OK ........ successful 292 293 CSC_BADARG .... fileOpenMaxPtr, or fileNameLengthPtr, or 294 filePathLengthPtr is NULL 295 296 CSC_ERROR ..... error getting limit from system call 297 298DESCRIPTION 299 CSCsysLimitsGet() makes some system calls and writes the integer 300 information to the addresses specified in the arguments. 301 302 `fileOpenMaxPtr' must be a non-NULL pointer to an integer. If the call 303 to CSCsysLimitsGet() is successful, the integer value will be the 304 maximum number of open files allowed per process. 305 306 `fileNameLenghtPtr' must be a non-NULL pointer to an integer. If the 307 call to CSCsysLimitsGet() is successful, the integer value will be the 308 maximum files name length allowed by the system. 309 310 `filePathLengthPtr' must be a non-NULL pointer to an integer. If the 311 call to CSCsysLimitsGet() is successful, the integer value will be the 312 maximum path length allowed by the system. 313 314SEE ALSO 315 CSCsysInstallSignal(3) 316 CSCsysUsleep(3) 317</SUBROUTINE> 318 319 ***************************************************************************/ 320 321PUBLIC int (CSCsysLimitsGet) ( 322 int* const fileOpenMaxPtr, 323 int* const fileNameLengthPtr, 324 int* const filePathLengthPtr 325 ) 326 { 327 int errCode = CSC_OK; 328 int configItem = 0; 329 330 ASSERT_RTN ( \ 331 fileOpenMaxPtr != NULL, \ 332 "CSCsysLimitsGet: NULL fileOpenMaxPtr", \ 333 CSC_BADARG \ 334 ); 335 ASSERT_RTN ( \ 336 fileNameLengthPtr != NULL, \ 337 "CSCsysLimitsGet: NULL fileNameLengthPtr", \ 338 CSC_BADARG \ 339 ); 340 ASSERT_RTN ( \ 341 filePathLengthPtr != NULL, \ 342 "CSCsysLimitsGet: NULL filePathLengthPtr", \ 343 CSC_BADARG \ 344 ); 345 346#define I_HAVE_A_BAD_ARGUMENT ((fileOpenMaxPtr == NULL) || \ 347 (fileNameLengthPtr == NULL) || \ 348 (filePathLengthPtr == NULL)) 349 if (I_HAVE_A_BAD_ARGUMENT) return (CSC_BADARG); 350#undef I_HAVE_A_BAD_ARGUMENT 351 352 /* 353 * Find the maximum number of open files allowed per process. Don't use 354 * the constant OPEN_MAX from the POSIX.1 header file `limits.h' because, 355 * as a portable constant, it is restrictive. Use the posix function 356 * `sysconf(_SC_OPEN_MAX)' to dynamically find the system's true 357 * capabilities. Don't use the constant _POSIX_OPEN_MAX because it seems to 358 * be even more restrictive than the constant OPEN_MAX. 359 */ 360 361 configItem = sysconf (_SC_OPEN_MAX); 362 if (configItem > 0) 363 { 364 *fileOpenMaxPtr = configItem; 365 } 366 else 367 { 368 if (errno == 0) 369 { 370 CSCioWarnPrint ( 371 "libcsc", 372 "CSCsysLimitsGet", 373 "guessing at maximum open file count (%d).\n", 374 255 375 ); 376 *fileOpenMaxPtr = 255; /* Guess at it. */ 377 } 378 else 379 { 380#ifdef DEBUG 381 perror ("error for sysconf(_SC_OPEN_MAX)"); 382#endif 383 errCode = CSC_ERROR; 384 } 385 } 386 387/* 388 * Find the maximum file name length. Don't use the constant NAME_MAX from the 389 * POSIX.1 header file `limits.h' because, as a portable constant, it is 390 * restrictive. Use the posix function `sysconf(_PC_NAME_MAX)' to dynamically 391 * find the system's true capabilities. Don't use the constant _POSIX_NAME_MAX 392 * because it seems to be even more restrictive than the constant NAME_MAX. 393 */ 394 395 configItem = pathconf ("/", _PC_NAME_MAX); 396 if (configItem > 0) 397 { 398 *fileNameLengthPtr = configItem; 399 } 400 else 401 { 402 if (errno == 0) 403 { 404 CSCioWarnPrint ( 405 "libcsc", 406 "CSCsysLimitsGet", 407 "guessing at maximum file name size (%d).\n", 408 255 409 ); 410 *fileNameLengthPtr = 255; /* Guess at it. */ 411 } 412 else 413 { 414#ifdef DEBUG 415 perror ("error for pathconf(\"/\",_PC_NAME_MAX)"); 416#endif 417 errCode = CSC_ERROR; 418 } 419 } 420 421/* 422 * Find the maximum path length. Don't use the constant PATH_MAX from the 423 * POSIX.1 header file `limits.h' because, as a portable constant, it is 424 * restrictive. Use the posix function `pathconf(_PC_PATH_MAX)' to dynamically 425 * find the system's true capabilities. Don't use the constant _POSIX_PATH_MAX 426 * because it seems to be even more restrictive than the constant PATH_MAX. 427 */ 428 429 configItem = pathconf ("/", _PC_PATH_MAX); 430 if (configItem > 0) 431 { 432 *filePathLengthPtr = configItem; 433 } 434 else 435 { 436 if (errno == 0) 437 { 438 CSCioWarnPrint ( 439 "libcsc", 440 "CSCsysLimitsGet", 441 "guessing at maximum path size (%d).\n", 442 255 443 ); 444 *filePathLengthPtr = 255; /* Guess at it. */ 445 } 446 else 447 { 448#ifdef DEBUG 449 perror ("error for pathconf(\"/\",_PC_PATH_MAX)"); 450#endif 451 errCode = CSC_ERROR; 452 } 453 } 454 455 return (errCode); 456 } 457 458 459/*************************************************************************** 460 * Public Function CSCsysInstallSignal 461 *************************************************************************** 462 463<SUBROUTINE NAME="CSCsysInstallSignal"> 464 465NAME 466 CSCsysInstallSignal - fairly portable signal installer 467 468SYNOPSYS 469 #include "libcsc.h" 470 471 CSCsigFnType CSCsysInstallSignal ( 472 const int signo, 473 const CSCsigFnType func, 474 const CSCsigModeType mode 475 ); 476 477RETURN VALUE 478 The return value from CSCsysInstallSignal() is a function pointer to a 479 signal handler. 480 481 If CSCsysInstallSignal() is NOT successful, then the return value is 482 SIG_ERR cast as a signal handler function. 483 484 If CSCsysInstallSignal() is successful, then the return value is a 485 function pointer to the previously installed handler cast as a 486 signal handler function; this might be NULL in the typical case that 487 there was no previous signal handler. 488 489DESCRIPTION 490 CSCsysInstallSignal() is a reliable version of signal() using POSIX 491 sigaction(). 492 493 `signo' is the signal number of the signal for which the signal handler 494 function `func' is installed. 495 496 `mode' is CSC_SIG_INTERRUPT or CSC_SIG_RESTART; it is used to control 497 behavior, specifically for slow system calls: 498 499 mode behavior 500 ---- -------- 501 CSC_SIG_INTERRUPT slow system calls are interrupted 502 503 CSC_SIG_RESTART slow system calls are not interrupted 504 505 An illustration of slow system call and signal interrupt is a program 506 that creates children and has a signal handler for SIGCHLD. If this 507 program blocks on something like an accept() on a TCP socket connection 508 and a child process terminates, then the registered SIGCHLD signal 509 handler runs; but, the process unblocks and returns from the accept() 510 with no connection (errno should be EINTR). This can be avoided by 511 using CSCsysInstallSignal() to install the SIGCHLD signal handler 512 function `func' and specifying CSC_SIG_RESTART for `mode'. 513 514SEE ALSO 515 CSCsysLimitsGet(3) 516 CSCsysUsleep(3) 517</SUBROUTINE> 518 519 *************************************************************************** 520 521 If you want to set, or possibly change, the return value or type of the 522 variable `installStat', then spend some time digging through the system 523 header files. Start with `signal.h'. You can really mess up things if you 524 don't completely understand SIG_ERR. 525 526 ***************************************************************************/ 527 528PUBLIC CSCsigFnType (CSCsysInstallSignal) ( 529 const int signo, 530 const CSCsigFnType func, 531 const CSCsigModeType mode 532 ) 533 { 534 CSCsigFnType installStat = SIG_ERR; 535 struct sigaction newAction; 536 struct sigaction oldAction; 537 538 newAction.sa_handler = func; 539 newAction.sa_flags = 0; 540 if (sigemptyset(&newAction.sa_mask) == 0) 541 { 542 switch (mode) 543 { 544 default: 545 ASSERT_RTN ( \ 546 CSC_FALSE, \ 547 "CSCsysInstallSignal: terrible excuse for a mode",\ 548 SIG_ERR \ 549 ); 550 break; 551 552 case CSC_SIG_INTERRUPT: 553#ifdef SA_INTERRUPT 554 newAction.sa_flags |= SA_INTERRUPT; /* SunOS 4.1.x */ 555#endif 556 break; 557 558 case CSC_SIG_RESTART: 559#ifdef SA_RESTART 560 newAction.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */ 561#endif 562 break; 563 } 564 if (sigaction(signo,&newAction,&oldAction) == 0) 565 { 566 installStat = oldAction.sa_handler; 567 } 568#ifdef DEBUG 569 else 570 { 571 perror ("sigaction() failed"); 572 CSCioErrorPrint ( 573 "libcsc", 574 "CSCsysInstallSignal", 575 "can't install signal %d handler (errno %d).\n\t", 576 signo, 577 errno 578 ); 579 } 580#endif 581 } 582#ifdef DEBUG 583 else 584 { 585 perror ("sigemptyset() failed"); 586 CSCioErrorPrint ( 587 "libcsc", 588 "CSCsysInstallSignal", 589 "can't create empty signal mask (errno %d).\n\t", 590 errno 591 ); 592 } 593#endif 594 595 return (installStat); 596 } 597 598 599/* End of file. */ 600