blob: 625ba5a47f65525fbd20ce3a9e00486157717f74 [file] [log] [blame]
/* 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;
}