• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************/
2 /*                                                                            */
3 /* Copyright (c) 2008 FUJITSU LIMITED                                         */
4 /*                                                                            */
5 /* This program is free software;  you can redistribute it and/or modify      */
6 /* it under the terms of the GNU General Public License as published by       */
7 /* the Free Software Foundation; either version 2 of the License, or          */
8 /* (at your option) any later version.                                        */
9 /*                                                                            */
10 /* This program is distributed in the hope that it will be useful,            */
11 /* but WITHOUT ANY WARRANTY;  without even the implied warranty of            */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                  */
13 /* the GNU General Public License for more details.                           */
14 /*                                                                            */
15 /* You should have received a copy of the GNU General Public License          */
16 /* along with this program;  if not, write to the Free Software               */
17 /* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA    */
18 /*                                                                            */
19 /* Author: Li Zefan <lizf@cn.fujitsu.com>                                     */
20 /*                                                                            */
21 /******************************************************************************/
22 
23 #include <unistd.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <pwd.h>
28 #include <sys/types.h>
29 #include <sys/wait.h>
30 
31 #include "test.h"
32 
33 #define DEFAULT_EVENT_NUM       1
34 
35 unsigned long nr_event = DEFAULT_EVENT_NUM;
36 
37 uid_t ltp_uid;
38 gid_t ltp_gid;
39 const char *ltp_user = "nobody";
40 
41 char **exec_argv;
42 
43 void (*gen_event) (void);
44 
45 /*
46  * Show the usage
47  *
48  * @status: the exit status
49  */
usage(int status)50 static void usage(int status)
51 {
52 	FILE *stream = (status ? stderr : stdout);
53 
54 	fprintf(stream,
55 		"Usage: event_generator -e fork|exit|exec|uid|gid [-n nr_event]\n");
56 
57 	exit(status);
58 }
59 
60 /*
61  * Generate exec event.
62  *
63  * We can't just exec nr_event times, because the current process image
64  * will be replaced with the new process image, so we use enviroment
65  * viriable as event counters, as it will be inherited after exec.
66  */
gen_exec(void)67 static void gen_exec(void)
68 {
69 	char *val;
70 	char buf[10];
71 	unsigned long nr_exec;
72 
73 	/* get the event counter */
74 	val = getenv("NR_EXEC");
75 	if (!val) {
76 		nr_exec = 0;
77 		setenv("NR_EXEC", "1", 1);
78 	} else {
79 		nr_exec = atoi(val);
80 		snprintf(buf, 10, "%lu", nr_exec + 1);
81 		setenv("NR_EXEC", buf, 1);
82 	}
83 
84 	/* stop generate exec event */
85 	if (nr_exec >= nr_event)
86 		return;
87 
88 	/* fflush is needed before exec */
89 	printf("exec pid: %d\n", getpid());
90 	fflush(stdout);
91 
92 	execv(exec_argv[0], exec_argv);
93 }
94 
95 /*
96  * Generate fork event.
97  */
gen_fork(void)98 static inline void gen_fork(void)
99 {
100 	pid_t pid;
101 	int status;
102 
103 	pid = fork();
104 	if (pid == 0) {
105 		printf("fork parent: %d, child: %d\n", getppid(), getpid());
106 		exit(0);
107 	} else if (pid < 0) {
108 		fprintf(stderr, "fork() failed\n");
109 		exit(1);
110 	} else {		/* Parent should wait for the child */
111 		wait(&status);
112 	}
113 }
114 
115 /**
116  * Generate exit event
117  */
gen_exit(void)118 static inline void gen_exit(void)
119 {
120 	pid_t pid;
121 
122 	pid = fork();
123 	if (pid == 0) {
124 		printf("exit pid: %d exit_code: %d\n", getpid(), 0);
125 		exit(0);
126 	} else if (pid < 0) {
127 		fprintf(stderr, "fork() failed\n");
128 		exit(1);
129 	}
130 }
131 
132 /*
133  * Generate uid event.
134  */
gen_uid(void)135 static inline void gen_uid(void)
136 {
137 	setuid(ltp_uid);
138 	printf("uid pid: %d euid: %d\n", getpid(), ltp_uid);
139 }
140 
141 /*
142  * Generate gid event.
143  */
gen_gid(void)144 static inline void gen_gid(void)
145 {
146 	setgid(ltp_gid);
147 	printf("gid pid: %d egid: %d\n", getpid(), ltp_gid);
148 }
149 
150 /*
151  * Read option from user input.
152  *
153  * @argc: number of arguments
154  * @argv: argument list
155  */
process_options(int argc,char ** argv)156 static void process_options(int argc, char **argv)
157 {
158 	int c;
159 	char *end;
160 
161 	while ((c = getopt(argc, argv, "e:n:h")) != -1) {
162 		switch (c) {
163 			/* which event to generate */
164 		case 'e':
165 			if (!strcmp(optarg, "exec"))
166 				gen_event = gen_exec;
167 			else if (!strcmp(optarg, "fork"))
168 				gen_event = gen_fork;
169 			else if (!strcmp(optarg, "exit"))
170 				gen_event = gen_exit;
171 			else if (!strcmp(optarg, "uid"))
172 				gen_event = gen_uid;
173 			else if (!strcmp(optarg, "gid"))
174 				gen_event = gen_gid;
175 			else {
176 				fprintf(stderr, "wrong -e argument!");
177 				exit(1);
178 			}
179 			break;
180 			/* number of event to generate */
181 		case 'n':
182 			nr_event = strtoul(optarg, &end, 10);
183 			if (*end != '\0' || nr_event == 0) {
184 				fprintf(stderr, "wrong -n argument!");
185 				exit(1);
186 			}
187 			break;
188 			/* help */
189 		case 'h':
190 			usage(0);
191 		default:
192 			fprintf(stderr, "unknown option!\n");
193 			usage(1);
194 		}
195 	}
196 
197 	if (!gen_event) {
198 		fprintf(stderr, "no event type specified!\n");
199 		usage(1);
200 	}
201 }
202 
main(int argc,char ** argv)203 int main(int argc, char **argv)
204 {
205 	unsigned long i;
206 	struct passwd *ent;
207 
208 	process_options(argc, argv);
209 
210 	ent = getpwnam(ltp_user);
211 	if (ent == NULL) {
212 		fprintf(stderr, "can't get password entry for %s", ltp_user);
213 		exit(1);
214 	}
215 	ltp_uid = ent->pw_uid;
216 	ltp_gid = ent->pw_gid;
217 
218 	signal(SIGCHLD, SIG_IGN);
219 
220 	/* special processing for gen_exec, see comments above gen_exec() */
221 	if (gen_event == gen_exec) {
222 		exec_argv = argv;
223 
224 		gen_exec();
225 
226 		/* won't reach here */
227 		return 0;
228 	}
229 
230 	/* other events */
231 	for (i = 0; i < nr_event; i++)
232 		gen_event();
233 
234 	return 0;
235 }
236