1 // SPDX-License-Identifier: GPL-2.0-or-later
2 // Copyright (c) 2010 Mohamed Naufal Basheer
3 // Author: Mohamed Naufal Basheer
4 
5 #include <sys/types.h>
6 #include <sys/mman.h>
7 #include <sys/stat.h>
8 #include <err.h>
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 
15 /*
16  * Named pipe to act as a communication channel between
17  * shell script & this process
18  */
19 #define STATUS_PIPE "status_pipe"
20 
21 int flag_exit;
22 int flag_allocated;
23 unsigned long memsize;
24 
25 /*
26  * process_options: process user specified options
27  */
process_options(int argc, char **argv)28 void process_options(int argc, char **argv)
29 {
30 	int c;
31 	char *end;
32 
33 	opterr = 0;
34 	while ((c = getopt(argc, argv, "pm:")) != -1) {
35 		switch (c) {
36 		case 'm':
37 			memsize = strtoul(optarg, &end, 10);
38 			if (*end != '\0')
39 				errx(2, "invalid -m usage");
40 			break;
41 		default:
42 			errx(2, "invalid option specified");
43 		}
44 	}
45 
46 	if (memsize <= 0)
47 		errx(3, "invalid usage");
48 }
49 
50 /*
51  * touch_memory: force physical memory allocation
52  */
touch_memory(char *p)53 void touch_memory(char *p)
54 {
55 	int i;
56 	int pagesize = getpagesize();
57 
58 	for (i = 0; i < (int)memsize; i += pagesize)
59 		p[i] = 0xef;
60 }
61 
mem_map(void)62 void mem_map(void)
63 {
64 	static char *p;
65 
66 	if (flag_allocated) {
67 		if (munmap(p, memsize) == -1)
68 			err(5, "munmap failed");
69 	} else {
70 		p = mmap(NULL, memsize, PROT_READ | PROT_WRITE,
71 			 MAP_SHARED | MAP_ANONYMOUS, 0, 0);
72 		if (p == MAP_FAILED)
73 			err(4, "mmap failed");
74 		touch_memory(p);
75 	}
76 	flag_allocated = !flag_allocated;
77 }
78 
79 /*
80  * done: retrieve instructions from the named pipe
81  */
action(int fd)82 char action(int fd)
83 {
84 	char ch;
85 
86 	if (read(fd, &ch, 1) == -1)
87 		err(7, "Error reading named pipe");
88 
89 	return ch;
90 }
91 
main(int argc, char **argv)92 int main(int argc, char **argv)
93 {
94 	int ret;
95 	int fd;
96 	char ch;
97 
98 	process_options(argc, argv);
99 
100 	ret = mkfifo(STATUS_PIPE, 0666);
101 
102 	if (ret == -1 && errno != EEXIST)
103 		errx(1, "Error creating named pipe");
104 
105 	if ((fd = open(STATUS_PIPE, O_RDONLY)) == -1)
106 		err(6, "Error opening named pipe");
107 
108 	do {
109 		ch = action(fd);
110 
111 		if (ch == 'm')
112 			mem_map();
113 	} while (ch != 'x');
114 
115 	close(fd);
116 
117 	remove(STATUS_PIPE);
118 
119 	return 0;
120 }
121