| #include <stdio.h> |
| #include <time.h> |
| #include <sys/time.h> |
| #include <unistd.h> |
| #include <sys/un.h> |
| #include <sys/socket.h> |
| #include <netinet/in.h> |
| #include <arpa/inet.h> |
| #include <errno.h> |
| #include <sys/ioctl.h> |
| #include <net/if.h> |
| #include <string.h> |
| #include <fcntl.h> |
| #include <signal.h> |
| #include <stdlib.h> |
| #include <sys/stat.h> |
| #include <sys/file.h> |
| #include <sys/types.h> |
| |
| #include "mbtk_type.h" |
| #include "mbtk_utils.h" |
| #ifdef LOG_TAG |
| #undef LOG_TAG |
| #endif |
| #define LOG_TAG "mbtk_utils" |
| #include "mbtk_log.h" |
| |
| #define MBTK_AT_BUF_SIZE 2048 |
| #define MBTK_AT_CLIENT_SOCKET "/data/sock_mbtk_at" |
| #define PROC_CMDLINE "/proc/cmdline" |
| #define TIME_FORMAT "%F %T" |
| |
| static int at_fd = -1; |
| static bool at_timeout = FALSE; |
| |
| static void |
| at_timer_alrm(int signo) |
| { |
| LOGW("AT Timeout.[%d]\n",signo); |
| at_timeout = TRUE; |
| } |
| |
| |
| /* |
| * Exec shell command. |
| */ |
| bool mbtk_cmd_line |
| ( |
| const char *cmd, |
| char *buf, |
| int buf_size |
| ) |
| { |
| FILE *fcmd; |
| bool result = FALSE; |
| fcmd = popen(cmd, "r"); |
| memset(buf, 0, buf_size); |
| if(fcmd) |
| { |
| int pos = 0; |
| int len = 0; |
| |
| while(!ferror(fcmd) && !feof(fcmd)) |
| { |
| if(buf_size - pos == 0) |
| { |
| break; |
| } |
| len = fread(buf + pos,1,buf_size - pos,fcmd); |
| if(len > 0) |
| pos += len; |
| } |
| |
| if(buf_size == pos) |
| buf[buf_size - 1] = '\0'; |
| |
| pclose(fcmd); |
| result = TRUE; |
| } |
| |
| LOGV("%s [result:%d]: %s",cmd,result,buf); |
| |
| return result; |
| } |
| |
| bool mbtk_cmd_line_ex |
| ( |
| const char *cmd, |
| mbtk_cmd_cb_func cb |
| ) |
| { |
| #define BUFF_SIZE 1024 |
| FILE *fcmd; |
| bool result = FALSE; |
| // Get stdout and stderr data. |
| // xxx 2>&1 |
| char buff[BUFF_SIZE + 1] = {0}; |
| snprintf(buff, BUFF_SIZE + 1, "%s 2>&1", cmd); |
| fcmd = popen(buff, "r"); |
| if(!cb) |
| { |
| return FALSE; |
| } |
| if(fcmd) |
| { |
| int len = 0; |
| if(setvbuf(fcmd, NULL, _IOLBF, BUFF_SIZE)) { |
| LOGE("setvbuf() fail:%d", errno); |
| } |
| errno = 0; |
| LOGI("ferror - %d,feof - %d",ferror(fcmd),feof(fcmd)); |
| while(!ferror(fcmd) && !feof(fcmd)) |
| { |
| memset(buff, 0, BUFF_SIZE + 1); |
| len = fread(buff,1,BUFF_SIZE,fcmd); |
| if(len > 0) |
| { |
| cb(buff,len); |
| } |
| else |
| { |
| LOGE("len - %d,errno - %d",len,errno); |
| } |
| } |
| |
| pclose(fcmd); |
| result = TRUE; |
| |
| cb(NULL,0); |
| } |
| else |
| { |
| LOGE("popen() fail.[errno=%d]",errno); |
| cb(NULL,0); |
| } |
| |
| return result; |
| } |
| |
| |
| |
| #if 1 |
| // Send msg to stanet_daemon |
| int mbtk_send_at(const void *at_req,void* at_rsp,int rsp_size,int timeout) |
| { |
| if(at_fd < 0) |
| { |
| struct sockaddr_un servaddr; |
| at_fd = socket(AF_LOCAL,SOCK_STREAM,0); |
| if(at_fd < 0) |
| { |
| LOGE("socket fail.(%d)\n",errno); |
| at_fd = -1; |
| return -1; |
| } |
| |
| // Set O_NONBLOCK |
| // int flags = fcntl(at_fd, F_GETFL, 0); |
| // if (flags < 0) { |
| // LOGE("Get flags error:%s\n", strerror(errno)); |
| // return -1; |
| // } |
| // flags |= O_NONBLOCK; |
| // if (fcntl(at_fd, F_SETFL, flags) < 0) { |
| // LOGE("Set flags error:%s\n", strerror(errno)); |
| // return -1; |
| // } |
| |
| memset(&servaddr,0x0,sizeof(servaddr)); |
| servaddr.sun_family = AF_LOCAL; |
| strcpy(servaddr.sun_path,MBTK_AT_CLIENT_SOCKET); |
| |
| if(connect(at_fd,(struct sockaddr*)&servaddr,sizeof(servaddr)) < 0) |
| { |
| LOGE("connect fail.(%d)\n",errno); |
| close(at_fd); |
| at_fd = -1; |
| return -1; |
| } |
| } |
| |
| at_timeout = FALSE; |
| int n = write(at_fd,at_req,strlen((char*)at_req)); |
| if(n == -1) |
| { |
| LOGE("write fail[%d].\n",errno); |
| close(at_fd); |
| at_fd = -1; |
| return -1; |
| } |
| |
| // Set timer |
| signal(SIGALRM, at_timer_alrm); |
| struct itimerval val; |
| // Only time |
| val.it_interval.tv_sec = 0; |
| val.it_interval.tv_usec = 0; |
| // Time |
| if(timeout >= 1000) |
| { |
| val.it_value.tv_sec = timeout/1000; |
| val.it_value.tv_usec = timeout%1000; |
| } |
| else |
| { |
| val.it_value.tv_sec = 0; |
| val.it_value.tv_usec = timeout; |
| } |
| if (setitimer(ITIMER_REAL, &val, NULL) == -1) |
| { |
| LOGE("setitimer fail.[%d]",errno); |
| return -1; |
| } |
| |
| memset(at_rsp,0x0,rsp_size); |
| while(!at_timeout) |
| { |
| n = read(at_fd,at_rsp,rsp_size); |
| if(n < 0) |
| { |
| if(errno == EWOULDBLOCK) |
| { |
| usleep(50000); |
| continue; |
| } |
| else |
| { |
| LOGW("read error.[%d]",errno); |
| break; |
| } |
| } |
| else if (n > 0) |
| { |
| LOGI("RSP:%s",(char*)at_rsp); |
| break; |
| } |
| else |
| { |
| LOGW("read error.[%d]",errno); |
| break; |
| } |
| } |
| |
| val.it_value.tv_sec = 0; |
| val.it_value.tv_usec = 0; |
| val.it_interval = val.it_value; |
| setitimer(ITIMER_REAL, &val, NULL); |
| |
| if(n > 0) |
| return 0; |
| |
| return -1; |
| } |
| #else |
| int mbtk_send_at(const void *at_req,void* at_rsp,int rsp_size,int timeout) |
| { |
| if(!at_req || !at_rsp || rsp_size <= 0) |
| { |
| LOGE("ARG error."); |
| return -1; |
| } |
| |
| // Return "ERROR" if AT fail. |
| const char* result = sendCmd(0,(const char*)at_req); |
| memset(at_rsp,0x0,rsp_size); |
| snprintf(at_rsp,rsp_size,"%s",result); |
| |
| return 0; |
| } |
| #endif |
| |
| /* |
| * Set timer as microseconds. |
| */ |
| int mbtk_timer_set(mbtk_timer_alrm_func func,uint32 timeout_ms) |
| { |
| signal(SIGALRM, func); |
| struct itimerval val; |
| // Only time |
| val.it_interval.tv_sec = 0; |
| val.it_interval.tv_usec = 0; |
| // Time |
| if(timeout_ms >= 1000) |
| { |
| val.it_value.tv_sec = timeout_ms/1000; |
| val.it_value.tv_usec = timeout_ms%1000; |
| } |
| else |
| { |
| val.it_value.tv_sec = 0; |
| val.it_value.tv_usec = timeout_ms; |
| } |
| if (setitimer(ITIMER_REAL, &val, NULL) == -1) |
| { |
| LOGE("setitimer fail.[errno - %d]",errno); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| /** |
| * Clear current timer. |
| */ |
| int mbtk_timer_clear() |
| { |
| struct itimerval value; |
| value.it_value.tv_sec = 0; |
| value.it_value.tv_usec = 0; |
| value.it_interval = value.it_value; |
| if (setitimer(ITIMER_REAL, &value, NULL) == -1) |
| { |
| LOGE("setitimer fail.[errno - %d]",errno); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| /* MRD still need to read /proc/cmdline after we drop root permission, |
| * so cache it in this function */ |
| int mbtk_get_kernel_cmdline(char *buf, int len) |
| { |
| static char cmdline[MBTK_CMDLINE_LEN]; |
| static int is_init = 0; |
| int ret = -1; |
| int fd; |
| |
| if(!buf || len <= 0) return -1; |
| |
| if(is_init) |
| goto INITED; |
| |
| fd = open(PROC_CMDLINE, O_RDONLY); |
| if (fd < 0) |
| goto ERR_RET; |
| |
| ret = read(fd, cmdline, MBTK_CMDLINE_LEN); |
| close(fd); |
| |
| if(ret <= 0 || ret > MBTK_CMDLINE_LEN) |
| goto ERR_RET; |
| cmdline[ret - 1] = '\0'; |
| |
| INITED: |
| ret = strlen(cmdline) + 1; |
| if(ret > len) |
| ret = len; |
| |
| strncpy(buf, cmdline, ret); |
| buf[ret - 1] = '\0'; |
| |
| is_init = 1; |
| |
| return ret; |
| |
| ERR_RET: |
| return -1; |
| } |
| |
| /** returns 1 if line starts with prefix, 0 if it does not */ |
| int strStartsWith(const char *line, const char *prefix) |
| { |
| if(prefix == NULL || strlen(prefix) == 0) { |
| return 1; |
| } |
| |
| for ( ; *line != '\0' && *prefix != '\0' ; line++, prefix++) { |
| if (*line != *prefix) { |
| return 0; |
| } |
| } |
| |
| return *prefix == '\0'; |
| } |
| |
| char* mbtk_time_text_get(char *buff, size_t buff_size) |
| { |
| long now_nsec = 0; |
| if(buff == NULL || buff_size <= 0) { |
| return NULL; |
| } |
| memset(buff, 0x0, buff_size); |
| #if 0 |
| time_t now; |
| now = time(&now); |
| if(now == -1) { |
| LOGE("time() fail."); |
| return NULL; |
| } |
| struct tm *now_tm = gmtime(&now); |
| #else |
| struct timespec now; |
| if(-1 == clock_gettime(CLOCK_REALTIME, &now)) { |
| LOGE("clock_gettime() fail."); |
| return NULL; |
| } |
| |
| struct tm *now_tm = gmtime((time_t*)(&(now.tv_sec))); |
| now_nsec = now.tv_nsec; |
| #endif |
| |
| if(now_tm == NULL) { |
| LOGE("gmtime() fail."); |
| return NULL; |
| } |
| |
| if(0 == strftime(buff, buff_size, TIME_FORMAT, now_tm)) { |
| LOGE("strftime() fail."); |
| return NULL; |
| } |
| |
| snprintf(buff + strlen(buff), buff_size - strlen(buff), |
| "-%03ld", now_nsec / 1000000); |
| |
| return buff; |
| } |
| |
| mbtk_byteorder_enum mbtk_byteorder_get() |
| { |
| union { |
| short a; |
| char c[sizeof(short)]; |
| } un; |
| un.a = 0x0102; |
| if(sizeof(short) == 2) { |
| if(un.c[0] == 1 && un.c[1] == 2) { |
| return MBTK_BYTEORDER_BIG; |
| } else if(un.c[0] == 2 && un.c[1] == 1) { |
| return MBTK_BYTEORDER_LITTLE; |
| } else { |
| return MBTK_BYTEORDER_UNKNOWN; |
| } |
| } else { |
| LOGE("Unknown byte order."); |
| return MBTK_BYTEORDER_UNKNOWN; |
| } |
| } |
| |
| uint16 byte_2_uint16(const void *buff, bool big_endian) |
| { |
| const uint8* ptr = (const uint8*)buff; |
| if(big_endian) { |
| return (uint16)((ptr[0] << 8) | ptr[1]); |
| } else { |
| return (uint16)((ptr[1] << 8) | ptr[0]); |
| } |
| } |
| |
| int uint16_2_byte(uint16 a, void *buff, bool big_endian) |
| { |
| uint8* ptr = (uint8*)buff; |
| if(big_endian) { |
| ptr[0] = (uint8)(a >> 8); |
| ptr[1] = (uint8)a; |
| } else { |
| ptr[1] = (uint8)(a >> 8); |
| ptr[0] = (uint8)a; |
| } |
| return sizeof(uint16); |
| } |
| |
| uint32 byte_2_uint32(const void *buff, bool big_endian) |
| { |
| const uint8* ptr = (const uint8*)buff; |
| if(big_endian) { |
| return (uint32)((ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3]); |
| } else { |
| return (uint32)((ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | ptr[0]); |
| } |
| } |
| |
| int uint32_2_byte(uint32 a, void *buff, bool big_endian) |
| { |
| uint8* ptr = (uint8*)buff; |
| if(big_endian) { |
| ptr[0] = (uint8)(a >> 24); |
| ptr[1] = (uint8)(a >> 16); |
| ptr[2] = (uint8)(a >> 8); |
| ptr[3] = (uint8)a; |
| } else { |
| ptr[3] = (uint8)(a >> 24); |
| ptr[2] = (uint8)(a >> 16); |
| ptr[1] = (uint8)(a >> 8); |
| ptr[0] = (uint8)a; |
| } |
| return sizeof(uint32); |
| } |
| |
| uint64 byte_2_uint64(const void *buff, bool big_endian) |
| { |
| const uint8* ptr = (const uint8*)buff; |
| if(big_endian) { |
| return (uint64)(((uint64)ptr[0] << 56) | ((uint64)ptr[1] << 48) | ((uint64)ptr[2] << 40) | ((uint64)ptr[3] << 32) | (ptr[4] << 24) | (ptr[5] << 16) | (ptr[6] << 8) | ptr[7]); |
| } else { |
| return (uint64)(uint64)(((uint64)ptr[7] << 56) | ((uint64)ptr[6] << 48) | ((uint64)ptr[5] << 40) | ((uint64)ptr[4] << 32) | (ptr[3] << 24) | (ptr[2] << 16) | (ptr[1] << 8) | ptr[0]); |
| } |
| } |
| |
| int uint64_2_byte(uint64 a, void *buff, bool big_endian) |
| { |
| uint8* ptr = (uint8*)buff; |
| if(big_endian) { |
| ptr[0] = (uint8)(a >> 56); |
| ptr[1] = (uint8)(a >> 48); |
| ptr[2] = (uint8)(a >> 40); |
| ptr[3] = (uint8)(a >> 32); |
| ptr[4] = (uint8)(a >> 24); |
| ptr[5] = (uint8)(a >> 16); |
| ptr[6] = (uint8)(a >> 8); |
| ptr[7] = (uint8)a; |
| } else { |
| ptr[7] = (uint8)(a >> 56); |
| ptr[6] = (uint8)(a >> 48); |
| ptr[5] = (uint8)(a >> 40); |
| ptr[4] = (uint8)(a >> 32); |
| ptr[3] = (uint8)(a >> 24); |
| ptr[2] = (uint8)(a >> 16); |
| ptr[1] = (uint8)(a >> 8); |
| ptr[0] = (uint8)a; |
| } |
| return sizeof(uint64); |
| } |
| |
| void* memdup(const void* data, int data_len) |
| { |
| if(data && data_len > 0) |
| { |
| uint8* result = (uint8*)malloc(data_len); |
| if(result == NULL) |
| { |
| return NULL; |
| } |
| memcpy(result, data, data_len); |
| return result; |
| } |
| else |
| { |
| return NULL; |
| } |
| } |
| |
| int app_already_running(const char *pid_file) |
| { |
| int fd; |
| char buff[16]; |
| |
| fd = open(pid_file, O_RDWR | O_CREAT, 0644); |
| if(fd < 0) { |
| LOGE("Open %s fail:%d", pid_file, errno); |
| exit(1); |
| } |
| |
| if(flock(fd, LOCK_EX | LOCK_NB)) { |
| if(EWOULDBLOCK == errno) { |
| LOGE("%s is running.", pid_file); |
| exit(1); |
| } else { |
| close(fd); |
| return 1; |
| } |
| } |
| |
| if(ftruncate(fd, 0)) { |
| LOGE("ftruncate(0) fail."); |
| return -1; |
| } |
| |
| sprintf(buff, "%ld", (long)getpid()); |
| if(write(fd, buff, strlen(buff) + 1) == strlen(buff) + 1) { |
| return 0; |
| } else { |
| return -1; |
| } |
| } |
| |
| void mbtk_system(const void* cmd) |
| { |
| if(cmd) { |
| int ret = system(cmd); |
| if(ret == -1 || ret == 127) { |
| LOGD("system(%s) fail.", cmd); |
| } |
| } |
| } |
| |
| void mbtk_write(int fd,const void *buf, size_t len) |
| { |
| if(fd >= 0 && buf) { |
| int ret = write(fd, buf, len); |
| if(ret < 0) { |
| LOGD("write() fail:%d", errno); |
| } |
| } |
| } |
| |
| void mbtk_read(int fd,void *buf, size_t len) |
| { |
| if(fd >= 0 && buf) { |
| int ret = read(fd, buf, len); |
| if(ret < 0) { |
| LOGD("read() fail:%d", errno); |
| } |
| } |
| } |
| |
| void mbtk_close(int fd) |
| { |
| if(fd >= 0) { |
| int ret = close(fd); |
| if(ret < 0) { |
| LOGD("close() fail:%d", errno); |
| } |
| } |
| } |
| |