Home | History | Annotate | Download | only in pec
      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 (at) 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  */
     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  */
     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  */
     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  */
    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  */
    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  */
    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  */
    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 
    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