顯示具有 c 標籤的文章。 顯示所有文章
顯示具有 c 標籤的文章。 顯示所有文章

2025/02/18

C Check that the pointer is in range of the memory.

It's hard to say. It's important to protect yourself.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Function to check if a pointer is within the process's mapped memory regions
int is_pointer_in_memory_range(void *ptr) {
    FILE *fp = fopen("/proc/self/maps", "r");
    if (!fp) {
        perror("fopen");
        return 0;
    }

    char line[256];
    uintptr_t addr = (uintptr_t)ptr;
    uintptr_t start, end;
    while (fgets(line, sizeof(line), fp)) {
        if (sscanf(line, "%lx-%lx", &start, &end) == 2) {
            if (addr >= start && addr < end) {
                fclose(fp);
                return 1; // Pointer is in a valid range
            }
        }
    }

    fclose(fp);
    return 0; // Pointer is not in the mapped memory range
}


2024/04/18

[C] chek cpu endian

1
2
3
4
5
6
7
8
#include <stdint.h>

static uint8_t is_little_endian(void)
{
    uint16_t value = 0x0001;
    uint8_t *byte_ptr = (uint8_t *)&value;
    return (*byte_ptr == 0x01); // If the system is little endian, the least significant byte is 0x01.
}


2024/04/09

[C] Create a folder even if the parent folder does not exist.

 

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
static int my_dirname(char *path) {
    char *p = strrchr(path, '/');
    if (p == NULL || p == path) {
        return -1;
    }
    *p = '\0';
    return 0;
}

static int my_mkdir(char *path) {
    struct  stat    st;
    char            p[128];
    char            l[128];

    mkdir(path, 0775);
    while ((stat(path, &st) != 0)) {
        memset(p, 0, 128);
        memcpy(p, path, strlen(path));
        if (0 != my_dirname(p)) {
            return (-1);
        }
        while ((stat(p, &st) != 0)) {
            memset(l, 0, 128);
            memcpy(l, p, strlen(p));  // save the last not exist parent path.
            if (0 != my_dirname(p)) {
                return (-1);
            }
        }
        mkdir(l, 0775);
        if (stat(l, &st) != 0) {
            return (-1);
        }
        mkdir(path, 0775);
    }
    return (0);
}

 

2023/04/21

[C] 16進制字串與 byte 陣列戶轉

 Convert between hex string and byte array.

以空間換取時間, 盡量減少計算跟比較.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
static uint8_t HEX_VALUE[256] = {
//  x0 x1 x2 x3 x4 x5 x6 x7   x8 x9 xA xB xC xD xE xF
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // 0x
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // 1x
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // 2x
     0, 1, 2, 3, 4, 5, 6, 7,   8, 9, 0, 0, 0, 0, 0, 0,  // 3x
     0,10,11,12,13,14,15, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // 4x
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // 5x
     0,10,11,12,13,14,15, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // 6x
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // 7x
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // 8x
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // 9x
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // Ax
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // Bx
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // Cx
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // Dx
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0,  // Ex
     0, 0, 0, 0, 0, 0, 0, 0,   0, 0, 0, 0, 0, 0, 0, 0   // Fx
};

static uint8_t HEX_CHAR[16] = {
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};

void bytes2hex(uint8_t* src, char* dest, uint8_t srcsize) {
    uint8_t flag;
    uint8_t pos;

    flag = 0;
    pos = 0;
    while (srcsize--) {
if (flag || src[srcsize]) {
dest[pos++] = HEX_CHAR[src[srcsize]>>4];
dest[pos++] = HEX_CHAR[src[srcsize]&0xf];
} } } void hex2bytes(char *src, uint8_t* dest, uint8_t destsize) { uint8_t len; uint8_t pos; uint8_t hilo; uint8_t byte; uint8_t lohi[2]; char *cptr; len = strlen(src); if (len > (destsize* 2)) {
return; } cptr = src + len; pos = 0; ++len; while (len) { memset(lohi, 0, 2); hilo = 2; while (hilo-- && --len) { lohi[hilo] = HEX_VALUE[*--cptr]; } dest[pos++] = lohi[1] | (lohi[0] << 4); } return; }




2020/06/09

[C] Simple state machine with pthread support


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

#if 1
#define DPRINTF(format, ...) do { \
	printf(format, ## __VA_ARGS__); \
	} while(0)
#else
#define DPRINTF(format, ...) do {} while(0)
#endif

#define SM_CONTINUE	1
#define SM_STOP		0
#define MAX_THREAD	10

enum STATE {
	ST_NULL=0,
	ST_1,
	ST_2,
	ST_MAX,
};

struct STATE_INFO {
	int threadIndex;
	enum STATE state;
	char wait;
};

struct STATE_MACHINE {
	enum STATE state;
	int (*stFunc) (struct STATE_INFO *sInfo);
};

int st1 (struct STATE_INFO *sInfo);
int st2 (struct STATE_INFO *sInfo);

struct STATE_MACHINE statemachineList[ST_MAX] = {
	{ST_1,		st1},
	{ST_2,		st2},
};

pthread_t tid[MAX_THREAD]={0};

void threadWaitReady(struct STATE_INFO *sInfo) {
	while (sInfo->wait) {
		usleep(100);
	}
}

int statemachineFindIndexByState(enum STATE state)
{
	int i, index=-1;
	int stCount = sizeof(statemachineList)/sizeof(struct STATE_MACHINE);
	
	for(i=0; i<stCount; i++) {
		if (statemachineList[i].state == state) {
			index = i;
			i = stCount;
		}
	}
	return index;
}

void * statemachineMain(void *arg)
{
	struct STATE_INFO sInfo, *ssInfo;
	int stateIndex;
	char resume=SM_CONTINUE;

	pthread_detach(pthread_self());
	memcpy(&sInfo, arg, sizeof(sInfo));
	ssInfo = arg;
	ssInfo->wait = 0;
	DPRINTF("t[%d] [%s] start statemachine with state %d\n", sInfo.threadIndex, __func__, sInfo.state);
	while (resume != SM_STOP) {
		stateIndex = statemachineFindIndexByState(sInfo.state);
		if (-1 == stateIndex) {
			resume = SM_STOP;
		} else {
			if (statemachineList[stateIndex].stFunc)
			{
				resume = statemachineList[stateIndex].stFunc(&sInfo);
			} else {
				resume = SM_STOP;
				DPRINTF("t[%d] [%s] state %d without callback function\n", sInfo.threadIndex, __func__, sInfo.state);
			}
		}
	}
	tid[sInfo.threadIndex] = 0;
	pthread_exit(NULL);
}

int threadFindFree (void)
{
	int i, retval=-1;
	for (i=0; i<MAX_THREAD; i++) {
		if (0 == tid[i]) {
			retval = i;
			break;
		}
	}
	return retval;
}

int main(int argc, char *argv[])
{
	struct STATE_INFO sInfo;
	int i, tIndex;
	
	i=0;
	while(1) {
		bzero(&sInfo, sizeof(sInfo));
		sInfo.threadIndex = threadFindFree();
		if (-1 != sInfo.threadIndex) {
			++i;
			i %= ST_MAX;
			sInfo.state = i;
			sInfo.wait = 1;
			if(pthread_create(&tid[sInfo.threadIndex], NULL, statemachineMain, (void*) &sInfo) != 0 ) {
				tid[sInfo.threadIndex] = 0;
				DPRINTF("t[%d] [%s] Failed to create thread\n", sInfo.threadIndex , __func__);
			} else {
				threadWaitReady(&sInfo);
			}
		}
		usleep(1234567);
	}
}

int st1 (struct STATE_INFO *sInfo)
{
	DPRINTF("t[%d] [%s]\n", sInfo->threadIndex, __func__);
	sInfo->state = ST_2;
	usleep(1000000);
	return SM_CONTINUE;
}

int st2 (struct STATE_INFO *sInfo)
{
	DPRINTF("t[%d] [%s]\n", sInfo->threadIndex, __func__);
	sInfo->state = ST_1;
	usleep(2000000);
	return SM_CONTINUE;
}

2020/05/26

[C] Simple daemon example with multiple connections


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>

#define PORT 1539
#define MAX_CLIENT 32

// connection information
struct connectInfo {
	int socket;
	int index;
};

// pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_t tid[MAX_CLIENT]={0};

// Each connection creates a pthread to handle communication.
void * sThread(void *arg)
{
	char message[64], retmsg[64];
	struct connectInfo *cInfo = (struct connectInfo *)arg;
	int nSocket = cInfo->socket;

	pthread_detach(pthread_self());
	int resume=1, i;
	struct timeval timeout;
	fd_set fds;
	
	FD_ZERO(&fds);
	FD_SET(nSocket, &fds);
	
	while (resume) {
		// reset timer
		timeout.tv_sec = 300;
		timeout.tv_usec = 0;
		
		// receive message with timeout control.
		i = select(nSocket+1, &fds, NULL, NULL, &timeout);
		if (0 == i) {
			printf("[%d] timeout\n", nSocket);
			resume = 0;
		} else if (-1 == i) {
			printf("[%d] got error\n", nSocket);
			resume = 0;
		} else {
			// The message still needs to be retrieved by recv.
			recv(nSocket , message , sizeof(message) , 0);
			printf("[%d] got message %s\n", nSocket, message);
			//pthread_mutex_lock(&lock);
			/*                         */
			//pthread_mutex_unlock(&lock);
			if (strncmp (message, "exit" , 4) == 0 ) {
				sprintf(retmsg, "bye");
				resume = 0;
			} else {
				sprintf(retmsg, "I got %s", message);
			}
			// Reply message to the other side.
			send(nSocket, retmsg, sizeof(retmsg), 0);
		}
	}
	// close connection
	close(nSocket);
	// release tid
	tid[cInfo->index] = 0;
	// exit pthread
	pthread_exit(NULL);
}

int main(int argc, char *argv[])
{
	int sSocket, nSocket, i;
	struct sockaddr_in s_in;
	struct sockaddr_storage s_storage;
	socklen_t addr_size;
	struct connectInfo cInfo[MAX_CLIENT];
	
	sSocket = socket(PF_INET, SOCK_STREAM, 0);
	
	// Set daemon to listen on port 1539 to any address 
	s_in.sin_family = AF_INET;
	s_in.sin_port = htons(PORT);
	s_in.sin_addr.s_addr = htonl(INADDR_ANY);
	memset(s_in.sin_zero, '\0', sizeof s_in.sin_zero);
	bind(sSocket, (struct sockaddr *) &s_in, sizeof(s_in));

	// start listen.
	if(listen(sSocket, MAX_CLIENT)==0) {
		printf("Listening\n");
	} else {
		printf("Listen Fail\n");
		exit(-1);
	}

	i = 0;
	while (1) {
		addr_size = sizeof(s_storage);
		nSocket = accept(sSocket, (struct sockaddr *) &s_storage, &addr_size);
		if (-1 == nSocket) {	//accept return error
			continue;
		}

		// when got a new connection, find an empty tid to create a new pthread.
		for (i=0; i<MAX_CLIENT; i++) {
			if (0 == tid[i]) {
				cInfo.socket = nSocket;
				cInfo.index = i;
				if( pthread_create(&tid[i], NULL, sThread, (void*) &cInfo[i]) != 0 ) {
					printf("Failed to create thread\n");
				} else {
					i = MAX_CLIENT+1;
				}
			}
		}
		
		if (MAX_CLIENT == i) {
			printf("No more free thread.\n");
			close(nSocket);
		}
	}
}

2014/08/12

find_pid_by_cmdline

要寫一個送 kill 到指定程式的 code,所以先要弄出這個根據 command line 找到 pid 的 function
#include <dirent.h>

static int find_pid_by_cmdline(const char *cmdline)
{
DIR *dir;
struct dirent *entry;
char *name, *p;
char status[32];
char buf[1024];
FILE *fp;
int pid, i;

dir = opendir("/proc");
if (!dir)
return 0;

while (entry = readdir(dir)) {
name = entry->d_name;
if (!(*name >= '0' && *name <= '9'))
continue;

pid = atoi(name);
sprintf(status, "/proc/%d/cmdline", pid);
if ((fp = fopen(status, "r")) == NULL)
continue;

name = fgets(buf, sizeof(buf), fp);
fclose(fp);
if (name == NULL)
continue;

for (i=0; i<1024; i++) {
if (buf[i] == 0) {
if (buf[i+1] == 0) {
i = 1024;
} else {
buf[i] = ' ';
}
}
}

if (!strcmp(buf, cmdline)) {
closedir(dir);
return pid;
}
}
closedir(dir);

return 0;
}