// create directory for lock files and set appropriate access rights void createLockDirectory(const char* pathname) { do { if (access(pathname, R_OK | W_OK | X_OK) == 0) { struct STAT st; if (os_utils::stat(pathname, &st) != 0) system_call_failed::raise("stat"); if (S_ISDIR(st.st_mode)) return; // not exactly original meaning, but very close to it system_call_failed::raise("access", ENOTDIR); } } while (SYSCALL_INTERRUPTED(errno)); while (mkdir(pathname, 0700) != 0) // anyway need chmod to avoid umask effects { if (SYSCALL_INTERRUPTED(errno)) { continue; } (Arg::Gds(isc_lock_dir_access) << pathname).raise(); } changeFileRights(pathname, 0770); }
int UTIL_shutdown_child(pid_t child_pid, unsigned timeout_term, unsigned timeout_kill) { /************************************** * * U T I L _ s h u t d o w n _ c h i l d * ************************************** * * Functional description * * Terminates child using TERM signal, then KILL if it does not finish * within specified timeout * * Return code: * 0 Child finished cleanly (TERM) * 1 Child killed (KILL) * 2 Child not killed by KILL * -1 Syscall failed * **************************************/ int r = kill(child_pid, SIGTERM); if (r < 0) return ((errno == ESRCH) ? 0 : -1); if (UTIL_set_handler(SIGALRM, alrm_handler, false) < 0) return -1; alarm(timeout_term); int child_status; r = waitpid(child_pid, &child_status, 0); if ((r < 0) && !SYSCALL_INTERRUPTED(errno)) return -1; if (r == child_pid) return 0; r = kill(child_pid, SIGKILL); if (r < 0) return ((errno == ESRCH) ? 0 : -1); alarm(timeout_kill); r = waitpid(child_pid, &child_status, 0); if ((r < 0) && !SYSCALL_INTERRUPTED(errno)) return -1; if (r == child_pid) return 1; return 2; }
// open (or create if missing) and set appropriate access rights int openCreateSharedFile(const char* pathname, int flags) { int fd = os_utils::open(pathname, flags | O_RDWR | O_CREAT, S_IREAD | S_IWRITE); if (fd < 0) raiseError(fd, pathname); // Security check - avoid symbolic links in /tmp. // Malicious user can create a symlink with this name pointing to say // security2.fdb and when the lock file is created the file will be damaged. struct stat st; int rc; do { rc = fstat(fd, &st); } while (fd != 0 && SYSCALL_INTERRUPTED(errno)); if (rc != 0) { int e = errno; close(fd); raiseError(e, pathname); } if (S_ISLNK(st.st_mode)) { close(fd); raiseError(ELOOP, pathname); } changeFileRights(pathname, 0660); return fd; }
// force file descriptor to have O_CLOEXEC set int open(const char* pathname, int flags, mode_t mode) { int fd; do { fd = ::open(pathname, flags | O_CLOEXEC, mode); } while (fd < 0 && SYSCALL_INTERRUPTED(errno)); if (fd < 0 && errno == EINVAL) // probably O_CLOEXEC not accepted { do { fd = ::open(pathname, flags | O_CLOEXEC, mode); } while (fd < 0 && SYSCALL_INTERRUPTED(errno)); } setCloseOnExec(fd); return fd; }
// setting flag is not absolutely required, therefore ignore errors here void setCloseOnExec(int fd) { if (fd >= 0) { while (fcntl(fd, F_SETFD, O_CLOEXEC) < 0 && SYSCALL_INTERRUPTED(errno)) ; } }
// set file's last access and modification time to current time bool touchFile(const char* pathname) { #ifdef HAVE_UTIME_H while (utime(pathname, NULL) < 0) { if (SYSCALL_INTERRUPTED(errno)) { continue; } return false; } return true; #else return false; #endif }
FILE* fopen(const char* pathname, const char* mode) { FILE* f = NULL; do { #ifdef LSB_BUILD // TODO: use open + fdopen to avoid races f = fopen64(pathname, mode); #else f = ::fopen(pathname, mode); #endif } while (f == NULL && SYSCALL_INTERRUPTED(errno)); if (f) setCloseOnExec(fileno(f)); return f; }
int UTIL_wait_for_child(pid_t child_pid, const volatile sig_atomic_t& shutting_down) { /************************************** * * U T I L _ w a i t _ f o r _ c h i l d * ************************************** * * Functional description * * This function is used to wait for the child specified by child_pid * * Return code: * 0 Normal exit * -1 Abnormal exit - unknown reason. * -2 TERM signal caught * Other Abnormal exit - process error code returned. * **************************************/ int child_exit_status; fb_assert(child_pid != 0); // wait for the child process with child_pid to exit while (waitpid(child_pid, &child_exit_status, 0) == -1) { if (SYSCALL_INTERRUPTED(errno)) { if (shutting_down) return -2; continue; } return (errno); } if (WIFEXITED(child_exit_status)) return WEXITSTATUS(child_exit_status); return -1; }
static bool get_line( int *argc, SCHAR** argv, TEXT* stuff) { /************************************** * * g e t _ l i n e * ************************************** * * Functional description * Read the current line and put its pieces into an argc/argv * structure. Reads a max of MAXARGS - 1 pieces (argv [0] is * unused), and a max of MAXSTUFF characters, at which point * **************************************/ TEXT msg[MSG_LEN]; SRVRMGR_msg_get(MSG_PROMPT, msg); printf("%s ", msg); // "FBMGR> " //if (sw_service_gsec) // putc ('\001', stdout); fflush(stdout); *argc = 1; TEXT* cursor = stuff; USHORT count = MAXSTUFF - 1; bool first = true; // for each input character, if it's white space (or any non-printable, // non-newline for that matter), ignore it; if it's a newline, we're // done; otherwise, put it in the current argument while (*argc < MAXARGS && count > 0) { TEXT c = getc(stdin); if (c > ' ' && c <= '~') { // note that the first argument gets a '-' appended to the front to fool // the switch checker into thinking it came from the command line for (argv[(*argc)++] = cursor; count > 0; count--) { if (first) { first = false; if (c != '?') { *cursor++ = '-'; count--; } } *cursor++ = c; c = getc(stdin); if (c <= ' ' || c > '~') break; } *cursor++ = '\0'; count--; } if (c == '\n') break; if (c == EOF) { if (SYSCALL_INTERRUPTED(errno)) { errno = 0; continue; } return true; } } *cursor = '\0'; return false; }
static int nextchar() { /************************************** * * n e x t c h a r * ************************************** * * Functional description * Get the next character from the input stream. * **************************************/ SSHORT c; /* mark the end of the buffer */ const char* const end = DDL_buffer + sizeof(DDL_buffer); /* If there isn't anything floating around, get a new line */ while (!(c = *DDL_char++)) { DDL_char = DDL_buffer; if (dudleyGlob.DDL_interactive) { printf("%s", dudleyGlob.DDL_prompt); if (dudleyGlob.DDL_service) putc('\001', stdout); fflush(stdout); } while (c = getc(input_file)) { if (c == EOF && SYSCALL_INTERRUPTED(errno)) { errno = 0; continue; } if (c == EOF) break; if (DDL_char < end) *DDL_char++ = c; else DDL_err(279); /* msg 279: line too SLONG */ if (c == '\n') break; } *DDL_char = 0; if (c == EOF && DDL_char == DDL_buffer) { #ifdef UNIX if (dudleyGlob.DDL_interactive) printf("\n"); #endif dudleyGlob.DDL_eof = true; return EOF; } DDL_char = DDL_buffer; fputs(DDL_buffer, trace_file); } dudleyGlob.DDL_token.tok_position++; if (c == '\n') { ++dudleyGlob.DDL_line; #if (defined WIN_NT) /* need to account for extra linefeed on newline */ dudleyGlob.DDL_token.tok_position++; #endif } return c; }