From 13d8a8696ac5b5b505be20f428fe64e22a134016 Mon Sep 17 00:00:00 2001 From: guowenxue <guowenxue@gmail.com> Date: Thu, 07 Sep 2023 09:59:30 +0800 Subject: [PATCH] Add socketd example project --- project/socketd/booster/proc.c | 432 ++++++++++++++++++ project/socketd/makefile | 67 ++ project/socketd/booster/ds18b20.h | 31 + project/socketd/sqlite/makefile | 7 project/socketd/sqlite/build.sh | 181 +++++++ project/socketd/booster/ds18b20.c | 119 ++++ project/socketd/booster/logger.h | 70 ++ project/socketd/client.c | 107 ++++ project/socketd/booster/makefile | 35 + project/socketd/booster/logger.c | 279 +++++++++++ project/socketd/booster/proc.h | 89 +++ 11 files changed, 1,417 insertions(+), 0 deletions(-) diff --git a/project/socketd/booster/ds18b20.c b/project/socketd/booster/ds18b20.c new file mode 100644 index 0000000..5f279fe --- /dev/null +++ b/project/socketd/booster/ds18b20.c @@ -0,0 +1,119 @@ +/********************************************************************************* + * Copyright: (C) 2023 LingYun IoT System Studio + * All rights reserved. + * + * Filename: ds18b20.c + * Description: This file is temperature sensor DS18B20 code + * + * Version: 1.0.0(2023/8/10) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "2023/8/10 12:13:26" + * + * Pin connection: + * + * DS18B20 Module Raspberry Pi Board + * VCC <-----> #Pin1(3.3V) + * DQ <-----> #Pin7(BCM GPIO4) + * GND <-----> GND + * + * /boot/config.txt: + * + * dtoverlay=w1-gpio-pullup,gpiopin=4 + * + ********************************************************************************/ + + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <dirent.h> +#include <string.h> +#include <time.h> +#include <errno.h> + +#include "logger.h" + +/* File Content: + pi@raspberrypi:~/guowenxue $ cat /sys/bus/w1/devices/28-041731f7c0ff/w1_slave + 3a 01 4b 46 7f ff 0c 10 a5 : crc=a5 YES + 3a 01 4b 46 7f ff 0c 10 a5 t=19625 + */ + +int ds18b20_get_temperature(float *temp) +{ + char w1_path[50] = "/sys/bus/w1/devices/"; + char chip[20]; + char buf[128]; + DIR *dirp; + struct dirent *direntp; + int fd =-1; + char *ptr; + float value; + int found = 0; + + if( !temp ) + { + return -1; + } + + /*+-------------------------------------------------------------------+ + *| open dierectory /sys/bus/w1/devices to get chipset Serial Number | + *+-------------------------------------------------------------------+*/ + if((dirp = opendir(w1_path)) == NULL) + { + log_error("opendir error: %s\n", strerror(errno)); + return -2; + } + + while((direntp = readdir(dirp)) != NULL) + { + if(strstr(direntp->d_name,"28-")) + { + /* find and get the chipset SN filename */ + strcpy(chip,direntp->d_name); + found = 1; + break; + } + } + closedir(dirp); + + if( !found ) + { + log_error("Can not find ds18b20 in %s\n", w1_path); + return -3; + } + + /* get DS18B20 sample file full path: /sys/bus/w1/devices/28-xxxx/w1_slave */ + strncat(w1_path, chip, sizeof(w1_path)-strlen(w1_path)); + strncat(w1_path, "/w1_slave", sizeof(w1_path)-strlen(w1_path)); + + /* open file /sys/bus/w1/devices/28-xxxx/w1_slave to get temperature */ + if( (fd=open(w1_path, O_RDONLY)) < 0 ) + { + log_error("open %s error: %s\n", w1_path, strerror(errno)); + return -4; + } + + if(read(fd, buf, sizeof(buf)) < 0) + { + log_error("read %s error: %s\n", w1_path, strerror(errno)); + return -5; + } + + ptr = strstr(buf, "t="); + if( !ptr ) + { + log_error("ERROR: Can not get temperature\n"); + return -6; + } + + ptr+=2; + + /* convert string value to float value */ + *temp = atof(ptr)/1000; + + close(fd); + + return 0; +} diff --git a/project/socketd/booster/ds18b20.h b/project/socketd/booster/ds18b20.h new file mode 100644 index 0000000..e756134 --- /dev/null +++ b/project/socketd/booster/ds18b20.h @@ -0,0 +1,31 @@ +/********************************************************************************* + * Copyright: (C) 2023 LingYun IoT System Studio + * All rights reserved. + * + * Filename: ds18b20.h + * Description: This file is temperature sensor DS18B20 code + * + * Version: 1.0.0(2023/8/10) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "2023/8/10 12:13:26" + * + * Pin connection: + * + * DS18B20 Module Raspberry Pi Board + * VCC <-----> #Pin1(3.3V) + * DQ <-----> #Pin7(BCM GPIO4) + * GND <-----> GND + * + * /boot/config.txt: + * + * dtoverlay=w1-gpio-pullup,gpiopin=4 + * + ********************************************************************************/ + +#ifndef _DS18B20_H_ +#define _DS18B20_H_ + +extern int ds18b20_get_temperature(float *temp); + +#endif /* ----- #ifndef _DS18B20_H_ ----- */ + diff --git a/project/socketd/booster/logger.c b/project/socketd/booster/logger.c new file mode 100644 index 0000000..217eb02 --- /dev/null +++ b/project/socketd/booster/logger.c @@ -0,0 +1,279 @@ +/********************************************************************************* + * Copyright: (C) 2023 LingYun IoT System Studio. + * All rights reserved. + * + * Filename: logger.c + * Description: This file is common logger API functions + * + * Version: 1.0.0(11/08/23) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "11/08/23 16:18:43" + * + ********************************************************************************/ + +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/time.h> +#include <pthread.h> + +#include "logger.h" + +typedef void (*log_LockFn)(void *udata, int lock); + +static struct { + char file[32]; /* logger file name */ + FILE *fp; /* logger file pointer */ + long size; /* logger file max size */ + int level; /* logger level */ + log_LockFn lockfn; /* lock function */ + void *udata; /* lock data */ +} L; + +static const char *level_names[] = { + "ERROR", + "WARN", + "INFO", + "DEBUG", + "TRACE" +}; + +static const char *level_colors[] = { + "\x1b[31m", + "\x1b[33m", + "\x1b[32m", + "\x1b[36m", + "\x1b[94m" +}; + +static inline void time_to_str(char *buf) +{ + struct timeval tv; + struct tm *tm; + int len; + + gettimeofday(&tv, NULL); + tm = localtime(&tv.tv_sec); + + len = sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%06d ", + tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec, (int)tv.tv_usec); + + buf[len] = '\0'; +} + +static void mutex_lock(void *udata, int lock) +{ + int err; + pthread_mutex_t *l = (pthread_mutex_t *) udata; + + if (lock) + { + if ( (err = pthread_mutex_lock(l)) != 0 ) + log_error("Unable to lock log lock: %s", strerror(err)); + } + else + { + if ( (err = pthread_mutex_unlock(l) != 0) ) + log_error("Unable to unlock log lock: %s", strerror(err)); + } +} + +int log_open(char *fname, int level, int size, int lock) +{ + FILE *fp; + + L.level = level; + L.size = size*1024; + + if( !fname || !strcmp(fname, "console") || !strcmp(fname, "stderr") ) + { + strcpy(L.file, "console"); + L.fp = stderr; + L.size = 0; /* console don't need rollback */ + } + else + { + if ( !(fp = fopen(fname, "a+")) ) + { + fprintf(stderr, "%s() failed: %s\n", __func__, strerror(errno)); + return -2; + } + L.fp = fp; + strncpy(L.file, fname, sizeof(L.file)); + } + + + if( lock ) + { + static pthread_mutex_t log_lock; + + pthread_mutex_init(&log_lock, NULL); + L.udata = (void *)&log_lock; + L.lockfn = mutex_lock; + } + + fprintf(L.fp, "\n"); + log_info("logger system(%s) start: file:\"%s\", level:%s, maxsize:%luKiB\n\n", + LOG_VERSION, L.file, level_names[level], size); + + return 0; +} + +void log_close(void) +{ + if( L.fp && L.fp!=stderr ) + fclose(L.fp); + + if (L.udata ) + pthread_mutex_destroy( L.udata); +} + +static void log_rollback(void) +{ + char cmd[128]={0}; + long fsize; + + /* don't need rollback */ + if(L.size <= 0 ) + return ; + + fsize = ftell(L.fp); + if( fsize < L.size ) + return ; + + /* backup current log file */ + snprintf(cmd, sizeof(cmd), "cp %s %s.bak", L.file, L.file); + system(cmd); + + /* rollback file */ + fseek(L.fp, 0, SEEK_SET); + truncate(L.file, 0); + + fprintf(L.fp, "\n"); + log_info("logger system(%s) rollback: file:\"%s\", level:%s, maxsize:%luKiB\n\n", + LOG_VERSION, L.file, level_names[L.level], L.size/1024); + + return ; +} + +void _log_write(int level, const char *file, int line, const char *fmt, ...) +{ + va_list args; + char time_string[100]; + + if ( !L.fp || level>L.level ) + return; + + /* Acquire lock */ + if ( L.lockfn ) + L.lockfn(L.udata, 1); + + log_rollback(); + + /* check and rollback file */ + time_to_str(time_string); + + /* Log to stderr */ + if ( L.fp == stderr ) + { + fprintf(L.fp, "%s %s %-5s\x1b[0m \x1b[90m%s:%03d:\x1b[0m ", + time_string, level_colors[level], level_names[level], file, line); + } + else /* Log to file */ + { + fprintf(L.fp, "%s %-5s %s:%03d: ", time_string, level_names[level], file, line); + } + + va_start(args, fmt); + vfprintf(L.fp, fmt, args); + va_end(args); + + fflush(L.fp); + + /* Release lock */ + if ( L.lockfn ) + L.lockfn(L.udata, 0); +} + +#define LINELEN 81 +#define CHARS_PER_LINE 16 +static char *print_char = +" " +" " +" !\"#$%&'()*+,-./" +"0123456789:;<=>?" +"@ABCDEFGHIJKLMNO" +"PQRSTUVWXYZ[\\]^_" +"`abcdefghijklmno" +"pqrstuvwxyz{|}~ " +" " +" " +" ???????????????" +"????????????????" +"????????????????" +"????????????????" +"????????????????" +"????????????????"; + +void log_dump(int level, const char *prompt, char *buf, size_t len) +{ + int rc; + int idx; + char prn[LINELEN]; + char lit[CHARS_PER_LINE + 2]; + char hc[4]; + short line_done = 1; + + if (!L.fp || level>L.level) + return; + + if( prompt ) + _log_write(level, __FILE__, __LINE__, "%s", prompt); + + rc = len; + idx = 0; + lit[CHARS_PER_LINE] = '\0'; + + while (rc > 0) + { + if (line_done) + snprintf(prn, LINELEN, "%08X: ", idx); + + do + { + unsigned char c = buf[idx]; + snprintf(hc, 4, "%02X ", c); + strncat(prn, hc, LINELEN); + + lit[idx % CHARS_PER_LINE] = print_char[c]; + } + while (--rc > 0 && (++idx % CHARS_PER_LINE != 0)); + + line_done = (idx % CHARS_PER_LINE) == 0; + if (line_done) + { + if (L.fp) + fprintf(L.fp, "%s %s\n", prn, lit); + } + } + + if (!line_done) + { + int ldx = idx % CHARS_PER_LINE; + lit[ldx++] = print_char[(int)buf[idx]]; + lit[ldx] = '\0'; + + while ((++idx % CHARS_PER_LINE) != 0) + strncat(prn, " ", sizeof(prn)-strlen(prn)); + + if (L.fp) + fprintf(L.fp, "%s %s\n", prn, lit); + + } +} diff --git a/project/socketd/booster/logger.h b/project/socketd/booster/logger.h new file mode 100644 index 0000000..484ac33 --- /dev/null +++ b/project/socketd/booster/logger.h @@ -0,0 +1,70 @@ +/********************************************************************************* + * Copyright: (C) 2023 LingYun IoT System Studio. + * All rights reserved. + * + * Filename: logger.h + * Description: This file is common logger API functions + * + * Version: 1.0.0(11/08/23) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "11/08/23 16:18:43" + * + ********************************************************************************/ + +#ifndef _LOGGER_H_ +#define _LOGGER_H_ + +#include <stdio.h> +#include <stdarg.h> + +#define LOG_VERSION "v0.1" + +/* log level */ +enum { + LOG_LEVEL_ERROR, + LOG_LEVEL_WARN, + LOG_LEVEL_INFO, + LOG_LEVEL_DEBUG, + LOG_LEVEL_TRACE, + LOG_LEVEL_MAX +}; + +enum { + LOG_LOCK_DISABLE, /* disable lock */ + LOG_LOCK_ENABLE, /* enable lock */ +}; + +#define ROLLBACK_NONE 0 + +/* description: Initial the logger system + * arguments : + * $fname: logger file name, NULL/"console"/"stderr" will log to console + * $level: logger level above; + * $size : logger file max size in KiB + * $lock : thread lock enable or not + * return : <0: Failed ==0: Sucessfully + */ +#define THREAD_LOCK_NONE 0 +#define THREAD_LOCK_EN 1 +int log_open(char *fname, int level, int size, int lock); + + +/* description: Terminate the logger system */ +void log_close(void); + + +/* description: log message into log file. Don't call this function directly. */ +void _log_write(int level, const char *file, int line, const char *fmt, ...); + + +/* description: dump a buffer in hex to logger file */ +void log_dump(int level, const char *prompt, char *buf, size_t len); + +/* function: log message into logger file with different log level */ +#define log_trace(...) _log_write(LOG_LEVEL_TRACE, __FILE__, __LINE__, __VA_ARGS__) +#define log_debug(...) _log_write(LOG_LEVEL_DEBUG, __FILE__, __LINE__, __VA_ARGS__) +#define log_info(...) _log_write(LOG_LEVEL_INFO, __FILE__, __LINE__, __VA_ARGS__) +#define log_warn(...) _log_write(LOG_LEVEL_WARN, __FILE__, __LINE__, __VA_ARGS__) +#define log_error(...) _log_write(LOG_LEVEL_ERROR, __FILE__, __LINE__, __VA_ARGS__) + +#endif diff --git a/project/socketd/booster/makefile b/project/socketd/booster/makefile new file mode 100644 index 0000000..b6ece0e --- /dev/null +++ b/project/socketd/booster/makefile @@ -0,0 +1,35 @@ +#******************************************************************************** +# Copyright: (C) 2023 LingYun IoT System Studio +# All rights reserved. +# +# Filename: Makefile +# Description: This file used compile all the source code to static library +# +# Version: 1.0.0(11/08/23) +# Author: Guo Wenxue <guowenxue@gmail.com> +# ChangeLog: 1, Release initial version on "11/08/23 16:18:43" +# +#******************************************************************************* + +PWD=$(shell pwd ) + +BUILD_ARCH=$(shell uname -m) +ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),) + CROSS_COMPILE?=arm-linux-gnueabihf- +endif + +LIBNAME=$(shell basename ${PWD} ) +TOPDIR=$(shell dirname ${PWD} ) +CFLAGS+=-D_GNU_SOURCE + +all: clean + @rm -f *.o + @${CROSS_COMPILE}gcc ${CFLAGS} -I${TOPDIR} -c *.c + ${CROSS_COMPILE}ar -rcs lib${LIBNAME}.a *.o + +clean: + @rm -f *.o + @rm -f *.a + +distclean: + @make clean diff --git a/project/socketd/booster/proc.c b/project/socketd/booster/proc.c new file mode 100644 index 0000000..d233d83 --- /dev/null +++ b/project/socketd/booster/proc.c @@ -0,0 +1,432 @@ +/********************************************************************************* + * Copyright: (C) 2020 LingYun IoT System Studio + * All rights reserved. + * + * Filename: proc.c + * Description: This file is the process API + * + * Version: 1.0.0(7/06/2020) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "7/06/2020 09:19:02 PM" + * + ********************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <libgen.h> +#include <pthread.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "proc.h" +#include "logger.h" + +proc_signal_t g_signal={0}; + +void proc_default_sighandler(int sig) +{ + switch(sig) + { + case SIGINT: + log_warn("SIGINT - stopping\n"); + g_signal.stop = 1; + break; + + case SIGTERM: + log_warn("SIGTERM - stopping\n"); + g_signal.stop = 1; + break; + + case SIGSEGV: + log_warn("SIGSEGV - stopping\n"); +#if 0 + if(g_signal.stop) + exit(0); + + g_signal.stop = 1; +#endif + break; + + case SIGPIPE: + log_warn("SIGPIPE - warnning\n"); + break; + + default: + break; + } +} + + +/* install default signal process functions */ +void install_default_signal(void) +{ + struct sigaction sigact, sigign; + + log_info("Install default signal handler.\n"); + + /* Initialize the catch signal structure. */ + sigemptyset(&sigact.sa_mask); + sigact.sa_flags = 0; + sigact.sa_handler = proc_default_sighandler; + + /* Setup the ignore signal. */ + sigemptyset(&sigign.sa_mask); + sigign.sa_flags = 0; + sigign.sa_handler = SIG_IGN; + + sigaction(SIGTERM, &sigact, 0); /* catch terminate signal "kill" command */ + sigaction(SIGINT, &sigact, 0); /* catch interrupt signal CTRL+C */ + //sigaction(SIGSEGV, &sigact, 0); /* catch segmentation faults */ + sigaction(SIGPIPE, &sigact, 0); /* catch broken pipe */ +#if 0 + sigaction(SIGCHLD, &sigact, 0); /* catch child process return */ + sigaction(SIGUSR2, &sigact, 0); /* catch USER signal */ +#endif +} + + +/* **************************************************************************** + * FunctionName: daemonize + * Description : Set the programe runs as daemon in background + * Inputs : nodir: DON'T change the work directory to / : 1:NoChange 0:Change + * noclose: close the opened file descrtipion or not 1:Noclose 0:Close + * Output : NONE + * Return : NONE + * *****************************************************************************/ +void daemonize(int nochdir, int noclose) +{ + int rv, fd; + int i; + + /* already a daemon */ + if (1 == getppid()) + return; + + /* fork error */ + rv = fork(); + if (rv < 0) exit(1); + + /* parent process exit */ + if (rv > 0) + exit(0); + + /* obtain a new process session group */ + setsid(); + + if (!noclose) + { + /* close all descriptors */ + for (i = getdtablesize(); i >= 0; --i) + { + //if (i != g_logPtr->fd) + close(i); + } + + /* Redirect Standard input [0] to /dev/null */ + fd = open("/dev/null", O_RDWR); + + /* Redirect Standard output [1] to /dev/null */ + dup(fd); + + /* Redirect Standard error [2] to /dev/null */ + dup(fd); + } + + umask(0); + + if (!nochdir) + chdir("/"); + + return; +} + +/* **************************************************************************** + * FunctionName: check_set_program_running + * Description : check program already running or not, if not then run it and + * record pid into $pidfile + * Inputs : daemon: set program running in daemon or not + * pid_file:The record PID file path + * Output : NONE + * Return : 0: Record successfully Else: Failure + * *****************************************************************************/ + +int check_set_program_running(int daemon, char *pidfile) +{ + if( !pidfile ) + return 0; + + if( check_daemon_running(pidfile) ) + { + log_error("Program already running, process exit now"); + return -1; + } + + if( daemon ) + { + if( set_daemon_running(pidfile) < 0 ) + { + log_error("set program running as daemon failure\n"); + return -2; + } + } + else + { + if( record_daemon_pid(pidfile) < 0 ) + { + log_error("record program running PID failure\n"); + return -3; + } + } + + return 0; +} + + + +/* **************************************************************************** + * FunctionName: record_daemon_pid + * Description : Record the running daemon program PID to the file "pid_file" + * Inputs : pid_file:The record PID file path + * Output : NONE + * Return : 0: Record successfully Else: Failure + * *****************************************************************************/ +int record_daemon_pid(const char *pid_file) +{ + struct stat fStatBuf; + int fd = -1; + int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU; + char ipc_dir[64] = { 0 }; + + strncpy(ipc_dir, pid_file, 64); + + /* dirname() will modify ipc_dir and save the result */ + dirname(ipc_dir); + + /* If folder pid_file PATH doesnot exist, then we will create it" */ + if (stat(ipc_dir, &fStatBuf) < 0) + { + if (mkdir(ipc_dir, mode) < 0) + { + log_error("cannot create %s: %s\n", ipc_dir, strerror(errno)); + return -1; + } + + (void)chmod(ipc_dir, mode); + } + + /* Create the process running PID file */ + mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; + if ((fd = open(pid_file, O_RDWR | O_CREAT | O_TRUNC, mode)) >= 0) + { + char pid[PID_ASCII_SIZE]; + snprintf(pid, sizeof(pid), "%u\n", (unsigned)getpid()); + write(fd, pid, strlen(pid)); + close(fd); + + log_debug("Record PID<%u> to file %s.\n", getpid(), pid_file); + } + else + { + log_error("cannot create %s: %s\n", pid_file, strerror(errno)); + return -1; + } + + return 0; +} + +/* **************************************************************************** + * FunctionName: get_daemon_pid + * Description : Get the daemon process PID from the PID record file "pid_file" + * Inputs : pid_file: the PID record file + * Output : NONE + * Return : pid_t: The daemon process PID number + * *****************************************************************************/ +pid_t get_daemon_pid(const char *pid_file) +{ + FILE *f; + pid_t pid; + + if ((f = fopen(pid_file, "rb")) != NULL) + { + char pid_ascii[PID_ASCII_SIZE]; + (void)fgets(pid_ascii, PID_ASCII_SIZE, f); + (void)fclose(f); + pid = atoi(pid_ascii); + } + else + { + log_error("Can't open PID record file %s: %s\n", pid_file, strerror(errno)); + return -1; + } + return pid; +} + +/* **************************************************************************** + * FunctionName: check_daemon_running + * Description : Check the daemon program already running or not + * Inputs : pid_file: The record running daemon program PID + * Output : NONE + * Return : 1: The daemon program alread running 0: Not running + * *****************************************************************************/ +int check_daemon_running(const char *pid_file) +{ + int rv = -1; + struct stat fStatBuf; + + rv = stat(pid_file, &fStatBuf); + if (0 == rv) + { + pid_t pid = -1; + printf("PID record file \"%s\" exist.\n", pid_file); + + pid = get_daemon_pid(pid_file); + if (pid > 0) /* Process pid exist */ + { + if ((rv = kill(pid, 0)) == 0) + { + printf("Program with PID[%d] seems running.\n", pid); + return 1; + } + else /* Send signal to the old process get no reply. */ + { + printf("Program with PID[%d] seems exit.\n", pid); + remove(pid_file); + return 0; + } + } + else if (0 == pid) + { + printf("Can not read program PID form record file.\n"); + remove(pid_file); + return 0; + } + else /* Read pid from file "pid_file" failure */ + { + printf("Read record file \"%s\" failure, maybe program still running.\n", pid_file); + return 1; + } + } + + return 0; +} + +/* **************************************************************************** + * FunctionName: stop_daemon_running + * Description : Stop the daemon program running + * Inputs : pid_file: The record running daemon program PID + * Output : NONE + * Return : 1: The daemon program alread running 0: Not running + * *****************************************************************************/ +int stop_daemon_running(const char *pid_file) +{ + pid_t pid = -1; + struct stat fStatBuf; + + if ( stat(pid_file, &fStatBuf) < 0) + return 0; + + printf("PID record file \"%s\" exist.\n", pid_file); + pid = get_daemon_pid(pid_file); + if (pid > 0) /* Process pid exist */ + { + while ( (kill(pid, 0) ) == 0) + { + kill(pid, SIGTERM); + sleep(1); + } + + remove(pid_file); + } + + return 0; +} + + + +/* **************************************************************************** + * FunctionName: set_daemon_running + * Description : Set the programe running as daemon if it's not running and record + * its PID to the pid_file. + * Inputs : pid_file: The record running daemon program PID + * Output : NONE + * Return : 0: Successfully. 1: Failure + * *****************************************************************************/ +int set_daemon_running(const char *pid_file) +{ + daemonize(0, 1); + log_info("Program running as daemon [PID:%d].\n", getpid()); + + if (record_daemon_pid(pid_file) < 0) + { + log_error("Record PID to file \"%s\" failure.\n", pid_file); + return -2; + } + + return 0; +} + +/* start a new thread to run $thread_workbody point function */ +int thread_start(pthread_t *thread_id, thread_body_t thread_workbody, void *thread_arg) +{ + int rv = 0; + pthread_t tid; + + pthread_attr_t thread_attr; + + /* Initialize the thread attribute */ + rv = pthread_attr_init(&thread_attr); + if(rv) + return -1; + + /* Set the stack size of the thread */ + rv = pthread_attr_setstacksize(&thread_attr, 120 * 1024); + if(rv) + goto CleanUp; + + /* Set thread to detached state:Don`t need pthread_join */ + rv = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + if(rv) + goto CleanUp; + + /* Create the thread */ + rv = pthread_create(&tid, &thread_attr, thread_workbody, thread_arg); + if(rv) + goto CleanUp; + +CleanUp: + + + if( thread_id ) + { + if( rv ) + *thread_id = 0; + else + *thread_id = tid; + } + + /* Destroy the attributes of thread */ + pthread_attr_destroy(&thread_attr); + return rv; +} + + +/* excute a linux command by system() */ +void exec_system_cmd(const char *format, ...) +{ + char cmd[256]; + va_list args; + + memset(cmd, 0, sizeof(cmd)); + + va_start(args, format); + vsnprintf(cmd, sizeof(cmd), format, args); + va_end(args); + + system(cmd); +} + + diff --git a/project/socketd/booster/proc.h b/project/socketd/booster/proc.h new file mode 100644 index 0000000..1a8a14e --- /dev/null +++ b/project/socketd/booster/proc.h @@ -0,0 +1,89 @@ +/******************************************************************************** + * Copyright: (C) 2020 LingYun IoT System Studio + * All rights reserved. + * + * Filename: proc.h + * Description: This head file is for Linux process/thread API + * + * Version: 1.0.0(7/06/2012~) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "7/06/2012 09:21:33 PM" + * + ********************************************************************************/ + +#ifndef __PROC_H_ +#define __PROC_H_ + +#include <signal.h> +#include <time.h> + +#define PID_ASCII_SIZE 11 + +typedef struct proc_signal_s +{ + int signal; + unsigned stop; /* 0: Not term 1: Stop */ +} proc_signal_t; + +typedef void *(* thread_body_t) (void *thread_arg); + +extern proc_signal_t g_signal; + +/* install default signal process functions */ +extern void install_default_signal(void); + +/* excute a linux command by system() */ +extern void exec_system_cmd(const char *format, ...); + +/* check program already running or not, if not then run it and record pid into $pidfile */ +extern int check_set_program_running(int daemon, char *pidfile); + +/* check program already running or not from $pid_file */ +extern int check_daemon_running(const char *pid_file); + +/* set program daemon running and record pid in $pid_file */ +extern int set_daemon_running(const char *pid_file); + +/* record proces ID into $pid_file */ +extern int record_daemon_pid(const char *pid_file); + +/* stop program running from $pid_file */ +extern int stop_daemon_running(const char *pid_file); + +/* my implementation for set program running in daemon */ +extern void daemonize(int nochdir, int noclose); + +/* start a new thread to run $thread_workbody point function */ +extern int thread_start(pthread_t *thread_id, thread_body_t thread_workbody, void *thread_arg); + +/* +---------------------+ + * | Low level API | + * +---------------------+*/ + +/* get daemon process ID from $pid_file */ +extern pid_t get_daemon_pid(const char *pid_file); + +/* +------------------------+ + * | inline functions API | + * +------------------------+*/ +static inline void msleep(unsigned long ms) +{ + struct timespec cSleep; + unsigned long ulTmp; + + cSleep.tv_sec = ms / 1000; + if (cSleep.tv_sec == 0) + { + ulTmp = ms * 10000; + cSleep.tv_nsec = ulTmp * 100; + } + else + { + cSleep.tv_nsec = 0; + } + + nanosleep(&cSleep, 0); + return ; +} + +#endif diff --git a/project/socketd/client.c b/project/socketd/client.c new file mode 100644 index 0000000..e350bef --- /dev/null +++ b/project/socketd/client.c @@ -0,0 +1,107 @@ +/********************************************************************************* + * Copyright: (C) 2019 LingYun IoT System Studio + * All rights reserved. + * + * Filename: main.c + * Description: This file + * + * Version: 1.0.0(29/01/19) + * Author: Guo Wenxue <guowenxue@gmail.com> + * ChangeLog: 1, Release initial version on "29/01/19 15:34:41" + * + ********************************************************************************/ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> +#include <getopt.h> +#include <libgen.h> +#include <string.h> +#include <errno.h> + +#include "logger.h" +#include "ds18b20.h" +#include "proc.h" + +#define PROG_VERSION "v1.0.0" +#define DAEMON_PIDFILE "/tmp/.socketd.pid" + +static void program_usage(char *progname) +{ + + printf("Usage: %s [OPTION]...\n", progname); + printf(" %s is LingYun studio temperature socket client program running on RaspberryPi\n", progname); + + printf("\nMandatory arguments to long options are mandatory for short options too:\n"); + printf(" -d[debug ] Running in debug mode\n"); + printf(" -h[help ] Display this help information\n"); + printf(" -v[version ] Display the program version\n"); + + printf("\n%s version %s\n", progname, PROG_VERSION); + return; +} + +int main (int argc, char **argv) +{ + int daemon = 1; + int opt; + char *progname=NULL; + char *logfile="client.log"; + int loglevel=LOG_LEVEL_INFO; + int logsize=10; /* logfile size max to 10K */ + + struct option long_options[] = { + {"debug", no_argument, NULL, 'd'}, + {"version", no_argument, NULL, 'v'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + progname = (char *)basename(argv[0]); + + /* Parser the command line parameters */ + while ((opt = getopt_long(argc, argv, "dvh", long_options, NULL)) != -1) + { + switch (opt) + { + case 'd': /* Set debug running */ + daemon = 0; + logfile="console"; + loglevel=LOG_LEVEL_DEBUG; + break; + + case 'v': /* Get software version */ + printf("%s version %s\n", progname, PROG_VERSION); + return 0; + + case 'h': /* Get help information */ + program_usage(progname); + return 0; + + default: + break; + } + + } + + if( log_open(logfile, loglevel, logsize, THREAD_LOCK_NONE) < 0 ) + { + fprintf(stderr, "Initial log system failed\n"); + return 1; + } + + install_default_signal(); + + if( check_set_program_running(daemon, DAEMON_PIDFILE) < 0 ) + goto cleanup; + + while( ! g_signal.stop ) + { + msleep(1000); + } + +cleanup: + log_close(); + + return 0; +} diff --git a/project/socketd/makefile b/project/socketd/makefile new file mode 100644 index 0000000..2c72631 --- /dev/null +++ b/project/socketd/makefile @@ -0,0 +1,67 @@ +#******************************************************************************** +# Copyright: (C) 2023 LingYun IoT System Studio +# All rights reserved. +# +# Filename: Makefile +# Description: This file is the project top Makefie +# +# Version: 1.0.0(11/08/23) +# Author: Guo Wenxue <guowenxue@gmail.com> +# ChangeLog: 1, Release initial version on "11/08/23 16:18:43" +# +#******************************************************************************* + +PRJ_PATH=$(shell pwd) +APP_NAME = client + +BUILD_ARCH=$(shell uname -m) +ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),) + CROSS_COMPILE=arm-linux-gnueabihf- +endif + +# C source files in top-level directory +SRCFILES = $(wildcard *.c) + +# common CFLAGS for our source code +CFLAGS = -Wall -Wshadow -Wundef -Wmaybe-uninitialized -D_GNU_SOURCE + +# sub-directory need to entry and compile +SUBDIR=booster sqlite + +# sub-directory compiled to a library and need to link +SRCS=booster +SRCS_PATH=$(patsubst %,${PRJ_PATH}/%,$(SRCS)) +CFLAGS+=$(patsubst %,-I%,$(SRCS_PATH)) +LDFLAGS+=$(patsubst %,-L%,$(SRCS_PATH)) +LIBS=$(patsubst %,-l%,$(SRCS)) +LDFLAGS+=${LIBS} + +# Open source libraries +CFLAGS+=-I ${PRJ_PATH}/sqlite/install/include +LDFLAGS+=-L ${PRJ_PATH}/sqlite/install/lib +LDFLAGS+=-lsqlite3 + +LDFLAGS+=-lpthread + +all: entry subdir + ${CROSS_COMPILE}gcc ${CFLAGS} client.c -o client ${LDFLAGS} + +entry: + @echo "Building ${APP_NAME} on ${BUILD_ARCH}" + +subdir: + @for dir in ${SUBDIR} ; do if [ ! -e $${dir} ] ; then ln -s ../$${dir}; fi; done + @for dir in ${SUBDIR} ; do make -C $${dir} ; done + +install: + cp ${APP_NAME} /tftp + +clean: + @for dir in ${SRCS} ; do if [ -e $${dir} ] ; then make clean -C $${dir}; fi; done + @rm -f ${APP_NAME} + +distclean: + @for dir in ${SUBDIR} ; do if [ -e $${dir} ] ; then make clean -C $${dir}; fi; done + @rm -f ${APP_NAME} + @rm -f cscope.* tags + diff --git a/project/socketd/sqlite/build.sh b/project/socketd/sqlite/build.sh new file mode 100755 index 0000000..53599b4 --- /dev/null +++ b/project/socketd/sqlite/build.sh @@ -0,0 +1,181 @@ +#!/bin/bash + +# library name and version +# Official: https://www.sqlite.org/index.html +LIB_NAME=sqlite-autoconf-3430000 +PACK_SUFIX=tar.gz + +# LingYun source code FTP server +LY_FTP=http://main.iot-yun.club:2211/src/ + +# library download URL address +LIB_URL=$LY_FTP + +# Cross compiler for cross compile on Linux server +CROSS_COMPILE=arm-linux-gnueabihf- + +# compile jobs +JOBS=`cat /proc/cpuinfo |grep "processor"|wc -l` + +# this project absolute path +PRJ_PATH=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd) + +# top project absolute path +TOP_PATH=$(realpath $PRJ_PATH/..) + +# binaries install path +PREFIX_PATH=$PRJ_PATH/install +BIN_PATH=$PREFIX_PATH/bin +LIB_PATH=$PREFIX_PATH/lib +INC_PATH=$PREFIX_PATH/include + +# check installed or not file +INST_FILE=$PREFIX_PATH/bin/sqlite3 + +# shell script will exit once get command error +set -e + +#+-------------------------+ +#| Shell script functions | +#+-------------------------+ + +function pr_error() { + echo -e "\033[40;31m $1 \033[0m" +} + +function pr_warn() { + echo -e "\033[40;33m $1 \033[0m" +} + +function pr_info() { + echo -e "\033[40;32m $1 \033[0m" +} + +function check_result() +{ + if [ $? != 0 ] ; then + pr_error $1 + fi +} +# decompress a packet to destination path +function do_unpack() +{ + tarball=$1 + dstpath=`pwd` + + if [[ $# == 2 ]] ; then + dstpath=$2 + fi + + pr_info "decompress $tarball => $dstpath" + + mkdir -p $dstpath + case $tarball in + *.tar.gz) + tar -xzf $tarball -C $dstpath + ;; + + *.tar.bz2) + tar -xjf $tarball -C $dstpath + ;; + + *.tar.xz) + tar -xJf $tarball -C $dstpath + ;; + + *.tar.zst) + tar -I zstd -xf $tarball -C $dstpath + ;; + + *.tar) + tar -xf $tarball -C $dstpath + ;; + + *.zip) + unzip -qo $tarball -d $dstpath + ;; + + *) + pr_error "decompress Unsupport packet: $tarball" + return 1; + ;; + esac +} + +function do_export() +{ + BUILD_ARCH=$(uname -m) + if [[ $BUILD_ARCH =~ "arm" ]] ; then + pr_warn "local($BUILD_ARCH) compile $LIB_NAME" + return ; + fi + + pr_warn "cross(${CROSS_COMPILE}) compile $LIB_NAME" + + # export cross toolchain + export CC=${CROSS_COMPILE}gcc + export CXX=${CROSS_COMPILE}g++ + export AS=${CROSS_COMPILE}as + export AR=${CROSS_COMPILE}ar + export LD=${CROSS_COMPILE}ld + export NM=${CROSS_COMPILE}nm + export RANLIB=${CROSS_COMPILE}ranlib + export OBJDUMP=${CROSS_COMPILE}objdump + export STRIP=${CROSS_COMPILE}strip + + # export cross configure + export CONFIG_CROSS=" --build=i686-pc-linux --host=arm-linux " + + # Clear LDFLAGS and CFLAGS + export LDFLAGS= + export CFLAGS= +} + +function do_fetch() +{ + if [ -e ${INST_FILE} ] ; then + pr_warn "$LIB_NAME compile and installed alredy" + exit ; + fi + + if [ -d $LIB_NAME ] ; then + pr_warn "$LIB_NAME fetch already" + return ; + fi + + if [ ! -f ${LIB_NAME}.${PACK_SUFIX} ] ; then + wget ${LIB_URL}/${LIB_NAME}.${PACK_SUFIX} + check_result "ERROR: download ${LIB_NAME} failure" + fi + + do_unpack ${LIB_NAME}.${PACK_SUFIX} +} + +function do_build() +{ + cd $LIB_NAME + + do_export + + ./configure --prefix=${PREFIX_PATH} ${CONFIG_CROSS} --enable-static --enable-static-shell + check_result "ERROR: configure ${LIB_NAME} failure" + + make && make install + check_result "ERROR: compile ${LIB_NAME} failure" +} + +function do_clean() +{ + rm -rf *${LIB_NAME}* +} + +if [[ $# == 1 && $1 == -c ]] ;then + pr_warn "start clean ${LIB_NAME}" + do_clean + exit; +fi + +do_fetch + +do_build + diff --git a/project/socketd/sqlite/makefile b/project/socketd/sqlite/makefile new file mode 100644 index 0000000..4572f9f --- /dev/null +++ b/project/socketd/sqlite/makefile @@ -0,0 +1,7 @@ + +all: + ./build.sh + +clean: + rm -rf install + ./build.sh -c -- Gitblit v1.9.1