| /* SPDX-License-Identifier: MediaTekProprietary */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <errno.h> |
| #include <pthread.h> |
| #include <unistd.h> |
| #include <sys/types.h> |
| #include <sys/wait.h> |
| #include "list.h" |
| #include "prop_core.h" |
| #include <cutils/properties.h> |
| #include "prop_debug.h" |
| #include "prop_svc.h" |
| #include "utility.h" |
| #include "request.h" |
| |
| static pthread_t prop_pthread; |
| static struct list prop_queue_list; |
| static pthread_mutex_t prop_queue_mutex; |
| static pthread_cond_t prop_queue_condition; |
| static int prop_queue_inited=0; |
| |
| /** Signed 8-bit */ |
| typedef char s_8; |
| |
| /** Signed 16-bit */ |
| typedef short s_16; |
| |
| #if defined (__APPLE64__) |
| /** Signed 32-bit */ |
| typedef long s_32; |
| #else |
| /** Signed 32-bit */ |
| typedef int s_32; |
| #endif |
| |
| /** Signed 64-bit */ |
| typedef long s_64; |
| |
| /** Unsigned 8-bit */ |
| typedef unsigned char u_8; |
| |
| /** Unsigned 16-bit */ |
| typedef unsigned short u_16; |
| |
| #if defined (__APPLE64__) |
| /** Unsigned 32-bit */ |
| typedef unsigned long u_32; |
| #else |
| /** Unsigned 32-bit */ |
| typedef unsigned int u_32; |
| #endif |
| |
| /** Unsigned 64-bit */ |
| typedef unsigned long u_64; |
| |
| /** Boolean Definition */ |
| typedef int bool; |
| |
| /** True Definition */ |
| #define SC_TRUE 0x1 |
| |
| /** False Definition */ |
| #define SC_FALSE 0x0 |
| |
| /* for checking overflow*/ |
| #define SC_INT_MAX 2147483647 /* 0x7fffffff */ |
| #define SC_INT_MIN -2147483647 |
| #define SC_UINT_MAX 0xffffffff |
| #define SC_ULONG_MAX SC_UINT_MAX |
| #define SC_LONG_MAX SC_INT_MAX |
| |
| static s_32 util_isdigit(s_8 ch) |
| { |
| if (ch >= '0' && ch <= '9') |
| { |
| return SC_TRUE; |
| } |
| else |
| { |
| return SC_FALSE; |
| } |
| } |
| |
| static s_32 util_isspace(s_8 ch) |
| { |
| if (ch == ' ' || ch == '\t' || ch == '\r' || |
| ch == '\n' || ch == '\v' || ch == '\f') |
| { |
| return SC_TRUE; |
| } |
| else |
| { |
| return SC_FALSE; |
| } |
| } |
| |
| /* |
| ****************************************************************************** |
| * |
| * DESCRIPTION: |
| * This function converts the ascii string into the long int (32bit) |
| * |
| * INPUT PARAMS |
| * str: Pointer to the ascii string |
| * |
| * RETURN: |
| * Integer converted |
| * |
| ****************************************************************************** |
| */ |
| s_32 sc_str_to_long(const s_8 * str) |
| { |
| s_32 working; |
| s_32 neg; |
| s_8 *cursor; |
| |
| working = 0; |
| neg = 0; |
| cursor = (s_8 *)str; |
| |
| /* Create the number. Method: |
| * Multiply value by 10 (harmless on first pass: 0 * 10 == 0). |
| * Add offset value (character minus '0') to number. |
| */ |
| |
| /* Remove leading white spaces (space, tab, vertical tab, carriage return, |
| linefeed, formfeed) */ |
| while (util_isspace(*cursor)) |
| { |
| cursor++; |
| } |
| |
| if (*cursor == '-') |
| { |
| neg = 1; |
| cursor++; |
| } |
| |
| for(; *cursor; cursor++) |
| { |
| /* Validity check */ |
| if (!util_isdigit(*cursor)) |
| { |
| return working; |
| } |
| |
| if (working > SC_LONG_MAX/10) |
| { |
| // Overflow ( > 32 bit unsigned) |
| return SC_LONG_MAX; |
| } |
| |
| working *= 10; |
| working += *cursor - '0'; |
| |
| if (working > SC_LONG_MAX) |
| { |
| // Overflow ( > 32 bit unsigned) |
| return SC_LONG_MAX; |
| } |
| } |
| return neg ? (-1 * working) : working; |
| } |
| |
| /***************************************************************************** |
| * FUNCTION |
| * sc_util_atoi |
| * DESCRIPTION |
| * This function converts the ascii string into the long int (32bit) |
| * PARAMETERS |
| * str [IN] Pointer to the ascii string |
| * RETURNS |
| * Integer converted |
| *****************************************************************************/ |
| s_32 sc_util_atoi(const s_8 *str) |
| { |
| /*----------------------------------------------------------------*/ |
| /* Local Variables */ |
| /*----------------------------------------------------------------*/ |
| |
| /*----------------------------------------------------------------*/ |
| /* Code Body */ |
| /*----------------------------------------------------------------*/ |
| return (s_32)sc_str_to_long((const s_8*)str); |
| } |
| |
| int _prop_sncfg_request_handle(const int sock, struct sncfg_request *request) |
| { |
| int size; |
| unsigned int debug_level; |
| char value_buffer[PROPERTY_VALUE_MAX]; |
| |
| switch (request->type) { |
| case SNCFG_REQUEST_TYPE_PROP_GET: |
| request->status = prop_core_get(request->key, value_buffer); |
| request->value = value_buffer; |
| size = pack_request(request); |
| if (size < 0) { |
| request->status = -1; |
| request->value = NULL; |
| size = pack_request(request); |
| } |
| safe_write(sock, request, size); |
| break; |
| |
| case SNCFG_REQUEST_TYPE_PROP_SET: |
| request->status = prop_core_set(request->key, request->value); |
| size = pack_request(request); |
| safe_write(sock, request, size); |
| break; |
| |
| case SNCFG_REQUEST_TYPE_PROP_RELOAD: |
| request->status = prop_core_init(); |
| request->key = NULL; |
| request->value = NULL; |
| size = pack_request(request); |
| safe_write(sock, request, size); |
| break; |
| |
| case SNCFG_REQUEST_TYPE_PROP_DEBUG: |
| debug_level = (unsigned int)sc_util_atoi(request->key); |
| request->status = prop_debug_set(debug_level); |
| request->key = NULL; |
| request->value = NULL; |
| size = pack_request(request); |
| safe_write(sock, request, size); |
| break; |
| |
| case SNCFG_REQUEST_TYPE_PROP_TEST: |
| request->status = prop_test_func(request->key, request->value); |
| request->value = NULL; |
| size = pack_request(request); |
| safe_write(sock, request, size); |
| break; |
| |
| default: |
| break; |
| |
| } |
| |
| return 0; |
| } |
| |
| struct req *_prop_sncfg_dequeue(void) |
| { |
| struct list *p, *n; |
| struct req *temp_req; |
| |
| if (!prop_queue_inited) |
| return NULL; |
| |
| pthread_mutex_lock(&prop_queue_mutex); |
| |
| LIST_CHECK(&prop_queue_list); |
| if (list_empty(&prop_queue_list)) { |
| pthread_cond_wait(&prop_queue_condition, &prop_queue_mutex); |
| } |
| |
| LIST_FOR_EACH_SAFE(p, n, &prop_queue_list) { |
| LIST_CHECK(p); |
| list_del(p); |
| break; |
| } |
| |
| pthread_mutex_unlock(&prop_queue_mutex); |
| |
| temp_req = (struct req *)p; |
| |
| return temp_req; |
| } |
| |
| void *_prop_sncfg_thread(void *arg) |
| { |
| struct req *action_req; |
| |
| for (;;) { |
| action_req = _prop_sncfg_dequeue(); |
| if (NULL == action_req) { |
| continue; |
| } |
| |
| switch (action_req->request.type) { |
| case SNCFG_REQUEST_TYPE_PROP_GET: |
| case SNCFG_REQUEST_TYPE_PROP_SET: |
| case SNCFG_REQUEST_TYPE_PROP_RELOAD: |
| case SNCFG_REQUEST_TYPE_PROP_DEBUG: |
| case SNCFG_REQUEST_TYPE_PROP_TEST: |
| _prop_sncfg_request_handle(action_req->sock, &(action_req->request)); |
| safe_close(action_req->sock); |
| break; |
| case SNCFG_REQUEST_TYPE_PROP_CTRLSTOP_SIGNAL: |
| prop_core_notify_ctrl(action_req->child_pid); |
| break; |
| default: |
| break; |
| |
| } |
| |
| free(action_req); |
| } |
| |
| pthread_exit(NULL); |
| } |
| |
| int prop_sncfg_enqueue(struct req *req) |
| { |
| if (!req) |
| return -1; |
| |
| if (!prop_queue_inited) |
| return -1; |
| |
| pthread_mutex_lock(&prop_queue_mutex); |
| |
| LIST_CHECK(&prop_queue_list); |
| list_add_tail((struct list *)req, &prop_queue_list); |
| pthread_cond_signal(&prop_queue_condition); |
| |
| pthread_mutex_unlock(&prop_queue_mutex); |
| |
| return 0; |
| } |
| |
| void prop_sncfg_child_exit_handle(int sig) |
| { |
| pid_t pid; |
| int ret_val; |
| struct req *req; |
| int status; |
| |
| PROP_DEBUG_PRINT(PROP_DEBUG_TRACE, "Begin"); |
| |
| while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { |
| PROP_DEBUG_PRINT(PROP_DEBUG_TRACE, "Get the pid:%d ", pid); |
| |
| req = malloc(sizeof(struct req)); |
| if (!req) { |
| PROP_DEBUG_PRINT(PROP_DEBUG_ERROR, "Can't malloc!!"); |
| return; |
| } |
| |
| memset(req, 0x0, sizeof(struct req)); |
| req->child_pid = pid; |
| req->request.magic = SNCFG_REQUEST_MAGIC; |
| req->request.type = SNCFG_REQUEST_TYPE_PROP_CTRLSTOP_SIGNAL; |
| |
| ret_val = prop_sncfg_enqueue(req); |
| if (ret_val < 0) { |
| PROP_DEBUG_PRINT(PROP_DEBUG_ERROR, "Can't enque!!"); |
| free(req); |
| } |
| } |
| } |
| |
| int prop_sncfg_init(void) |
| { |
| /*Init the queue DBS*/ |
| INIT_LIST(&prop_queue_list); |
| pthread_mutex_init(&prop_queue_mutex, NULL); |
| pthread_cond_init(&prop_queue_condition, NULL); |
| prop_queue_inited = 1; |
| |
| /*Property handle thread*/ |
| if (pthread_create(&prop_pthread, NULL, _prop_sncfg_thread, (void *)NULL) != 0) { |
| PROP_DEBUG_PRINT(PROP_DEBUG_ERROR, "Can't create thread. %s !!", strerror(errno)); |
| return -1; |
| } |
| |
| /*Init the Property DB and load *.prop, *.rc, persist.* files.*/ |
| prop_core_init(); |
| |
| return 0; |
| } |