| /* SPDX-License-Identifier: MediaTekProprietary */ |
| |
| #include <stdio.h> |
| #include <string.h> |
| #include <signal.h> |
| #include <stdlib.h> |
| #include <errno.h> |
| #include <unistd.h> |
| #include <sched.h> |
| #include <sys/types.h> |
| #include <sys/wait.h> |
| #include <syslog.h> |
| #include "utility.h" |
| |
| /*******************************************************************************/ |
| /* UTILITY local definitions */ |
| /*******************************************************************************/ |
| |
| /*******************************************************************************/ |
| /* UTILITY local prototypes */ |
| /*******************************************************************************/ |
| |
| /*******************************************************************************/ |
| /* UTILITY local variables */ |
| /*******************************************************************************/ |
| int libsncfg_rw_block = 1; |
| |
| /*******************************************************************************/ |
| /* UTILITY local functions */ |
| /*******************************************************************************/ |
| |
| /*******************************************************************************/ |
| /* UTILITY functions */ |
| /*******************************************************************************/ |
| int safe_close(int fd) |
| { |
| int ret; |
| |
| do { |
| ret = close(fd); |
| } while (ret < 0 && errno == EINTR); |
| |
| if (ret < 0) { |
| int errnoTmp = errno; |
| |
| fprintf(stderr, "[LIBSNCFG][%d] close(%d) @ safe_close() failed : %s !!\n", getpid(), fd, strerror(errnoTmp)); |
| syslog(LOG_WARNING, "[LIBSNCFG][%d] close(%d) @ safe_close() failed : %s !!", getpid(), fd, strerror(errnoTmp)); |
| } |
| return ret; |
| } |
| |
| |
| ssize_t safe_read(int fd, void *buf, size_t count) |
| { |
| ssize_t n; |
| |
| again: |
| do { |
| n = read(fd, buf, count); |
| } while (n < 0 && errno == EINTR); |
| |
| if (n < 0) { |
| int errnoTmp = errno; |
| |
| fprintf(stderr, "[LIBSNCFG][%d] read(%d) @ safe_read() failed : %s !!\n", getpid(), fd, strerror(errnoTmp)); |
| syslog(LOG_WARNING, "[LIBSNCFG][%d] read(%d) @ safe_read() failed : %s !!", getpid(), fd, strerror(errnoTmp)); |
| if ((errnoTmp == EWOULDBLOCK || errnoTmp == EAGAIN) && libsncfg_rw_block) { |
| goto again; |
| } |
| } |
| return n; |
| } |
| |
| |
| ssize_t safe_write(int fd, const void *buf, size_t count) |
| { |
| ssize_t n; |
| |
| again: |
| do { |
| n = write(fd, buf, count); |
| if (n == 0) { |
| fprintf(stderr, "[LIBSNCFG][%d] write(%d) @ safe_write : write zero byte !!\n", getpid(), fd); |
| syslog(LOG_WARNING, "[LIBSNCFG][%d] write(%d) @ safe_write : write zero byte !!", getpid(), fd); |
| } |
| } while (n < 0 && errno == EINTR); |
| |
| if (n < 0) { |
| int errnoTmp = errno; |
| |
| fprintf(stderr, "[LIBSNCFG][%d] write(%d) @ safe_write() failed : %s !!\n", getpid(), fd, strerror(errnoTmp)); |
| syslog(LOG_WARNING, "[LIBSNCFG][%d] write(%d) @ safe_write() failed : %s !!", getpid(), fd, strerror(errnoTmp)); |
| if ((errno == EWOULDBLOCK || errno == EAGAIN) && libsncfg_rw_block) { |
| goto again; |
| } |
| } |
| return n; |
| } |
| |
| char *dupstr(char* s) |
| { |
| char *r; |
| |
| r = malloc (strlen (s) + 1); |
| if (r) |
| strcpy (r, s); |
| return (r); |
| } |
| |
| int nonrt_system(const char *cmd) |
| { |
| int wait_val, pid; |
| sig_t save_quit, save_int, save_chld; |
| struct sched_param sched; |
| |
| if (cmd == 0) { |
| return 1; |
| } |
| |
| save_quit = signal(SIGQUIT, SIG_IGN); |
| save_int = signal(SIGINT, SIG_IGN); |
| save_chld = signal(SIGCHLD, SIG_DFL); |
| |
| if ((pid = vfork()) < 0) { |
| signal(SIGQUIT, save_quit); |
| signal(SIGINT, save_int); |
| signal(SIGCHLD, save_chld); |
| return -1; |
| } |
| if (pid == 0) { |
| signal(SIGQUIT, SIG_DFL); |
| signal(SIGINT, SIG_DFL); |
| signal(SIGCHLD, SIG_DFL); |
| |
| /* child, can only call thread safe functions before exec ... */ |
| sched.sched_priority = 0; |
| if (sched_setscheduler(0, SCHED_OTHER, &sched) == -1) { |
| exit(127); |
| } |
| execl("/bin/sh", "sh", "-c", cmd, (char *) 0); |
| exit(127); |
| } |
| /* Signals are not absolutly guarenteed with vfork */ |
| signal(SIGQUIT, SIG_IGN); |
| signal(SIGINT, SIG_IGN); |
| |
| if (wait4(pid, &wait_val, 0, 0) == -1) { |
| wait_val = -1; |
| } |
| |
| signal(SIGQUIT, save_quit); |
| signal(SIGINT, save_int); |
| signal(SIGCHLD, save_chld); |
| return wait_val; |
| } |