public inbox for ltp@lists.linux.it
 help / color / mirror / Atom feed
From: Subrata Modak <subrata@linux.vnet.ibm.com>
To: Wei Yongjun <yjwei@cn.fujitsu.com>
Cc: ltp-list@lists.sourceforge.net
Subject: Re: [LTP] [QUESTION] about test execve04 which testing for EMFILE
Date: Wed, 27 May 2009 19:53:20 +0530	[thread overview]
Message-ID: <1243434200.10447.16.camel@subratamodak.linux.ibm.com> (raw)
In-Reply-To: <4A1CB801.3080408@cn.fujitsu.com>

On Wed, 2009-05-27 at 11:48 +0800, Wei Yongjun wrote: 
> Subrata Modak wrote:
> > On Tue, 2009-05-26 at 17:44 +0800, Wei Yongjun wrote: 
> >   
> >> Subrata Modak wrote:
> >>     
> >>> On Fri, 2009-05-22 at 17:26 +0800, Wei Yongjun wrote: 
> >>>   
> >>>       
> >>>> recently kernel commit e7b9b550f53e81ea38e71d322d6f95730df058a2
> >>>> has removed the file get code. The execve syscall will never
> >>>> return EMFILE.
> >>>>
> >>>> Call to execve() will be suceess even if the the process has the
> >>>> maximum number of files open, because execve() never open any file.
> >>>>
> >>>> Can anyone tell me what does this test case test for? It be wrote
> >>>> base on which document? Just the man page?
> >>>>     
> >>>>         
> >>> * DESCRIPTION
> >>> *      Testcase to check execve(2) sets errno to EMFILE correctly
> >>> *
> >>> * ALGORITHM
> >>> *      Get the configured file descriptor table size. open(2) files to
> >>> fill
> >>> *      up the file descriptor table. Once file descriptor table is full,
> >>> *      an attempt to execve(2) any other executable fails with EMFILE.
> >>>
> >>> is what the source description says. Can you please execute the test
> >>> against that kernel commit and share the results with/without commits ?
> >>>   
> >>>       
> >> Test without that commit:
> >> # ./execve04 -F ./test3
> >> execve04 1 PASS : Expected failure - 24 : Too many open files
> >>
> >> Test with that commit:
> >> # ./execve04 -F ./test3
> >> <program name unknown>: error while loading shared libraries: libc.so.6:
> >> cannot open shared object file: Error 24
> >> execve04 1 FAIL :
> >> execve(/home/weiyj/ltp/testcases/kernel/syscalls/execve/./test3) failed:
> >> expected EMFILE(24), got 127 (Key has expired)
> >>
> >> Test with that commit but I compiled test3 with --static:
> >> # gcc test3.c -o test3 --static
> >> # ./execve04 -F ./test3
> >> Hello World
> >> execve04 1 FAIL :
> >> execve(/home/weiyj/ltp/testcases/kernel/syscalls/execve/./test3) failed:
> >> expected EMFILE(24), got 0 (Success)
> >>
> >> The latest kernel do execve(2) without get file descriptor, it only
> >> need one file struct. It seem that this test is obsoleted.
> >>     
> >
> > Lets remove then. Send a patch to do so.
> >   
> 
> Here is the patch.
> 
> -------------------------------------------------------
> 
> [PATCH] execve: remove obsoleted test case execve04
> 
> Since latest kernel do execve(2) without get file descriptor, it
> only use one file struct. This cause the case execve04 which test
> for set EMFILE errno obsoleted.
> 
> This patch removed test case execve04, and changed the index of
> the test cases after execve04.
> 
> Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>

Thanks.

Regards--
Subrata

> ---
>  doc/testcases/kernel.txt                    |    6 +-
>  runtest/ltplite                             |    5 +-
>  runtest/stress.part3                        |    5 +-
>  runtest/syscalls                            |    3 +-
>  testcases/kernel/syscalls/execve/execve04.c |  331 ++++++++++++++---------
>  testcases/kernel/syscalls/execve/execve05.c |  380 ++++++++++----------------
>  testcases/kernel/syscalls/execve/execve06.c |  236 -----------------
>  7 files changed, 357 insertions(+), 609 deletions(-)
>  delete mode 100644 testcases/kernel/syscalls/execve/execve06.c
> 
> diff --git a/doc/testcases/kernel.txt b/doc/testcases/kernel.txt
> index aa277e4..90afc9b 100644
> --- a/doc/testcases/kernel.txt
> +++ b/doc/testcases/kernel.txt
> @@ -803,14 +803,10 @@ syscalls
>    
>    execve04  
>    
> - 	Testcase to check execve(2) sets errno to EMFILE correctly
> - 
> -  execve05  
> -  
>   	Testcase to check execve sets the following errnos correctly:
>   	1.	ETXTBSY
> 
> -  execve06  
> +  execve05  
>    
>    	This testcase tests the basic functionality of the execve(2) system
>   	call.
> diff --git a/runtest/ltplite b/runtest/ltplite
> index 571763f..4717f1f 100644
> --- a/runtest/ltplite
> +++ b/runtest/ltplite
> @@ -167,9 +167,8 @@ execv01 execv01
>  execve01 execve01
>  execve02 execve02 -F $LTPROOT/testcases/bin/test3
>  execve03 execve03
> -execve04 cp -f $LTPROOT/testcases/bin/test3 $TMP; execve04 -F test3
> -execve05 execve05 -F $LTPROOT/testcases/bin/test3
> -execve06 execve06 20 $LTPROOT/testcases/bin/execve06 $LTPROOT/testcases/bin/execve06 4
> +execve04 execve04 -F $LTPROOT/testcases/bin/test3
> +execve05 execve05 20 $LTPROOT/testcases/bin/execve05 $LTPROOT/testcases/bin/execve05 4
>  execvp01 execvp01
> 
>  exit01 exit01
> diff --git a/runtest/stress.part3 b/runtest/stress.part3
> index b071625..88f5c04 100644
> --- a/runtest/stress.part3
> +++ b/runtest/stress.part3
> @@ -108,9 +108,8 @@ execv01 execv01
>  execve01 execve01
>  execve02 execve02 -F $LTPROOT/testcases/bin/test3
>  execve03 execve03
> -execve04 cp -f $LTPROOT/testcases/bin/test3 $TMP; execve04 -F test3
> -execve05 execve05 -F $LTPROOT/testcases/bin/test3
> -execve06 execve06 20 $LTPROOT/testcases/bin/execve06 $LTPROOT/testcases/bin/execve06 4
> +execve04 execve04 -F $LTPROOT/testcases/bin/test3
> +execve05 execve05 20 $LTPROOT/testcases/bin/execve05 $LTPROOT/testcases/bin/execve05 4
>  execvp01 execvp01
> 
>  exit01 exit01
> diff --git a/runtest/syscalls b/runtest/syscalls
> index 9b7b2ca..69e5e0b 100644
> --- a/runtest/syscalls
> +++ b/runtest/syscalls
> @@ -129,8 +129,7 @@ execve01 execve01
>  execve02 execve02 -F $LTPROOT/testcases/bin/test3
>  execve03 execve03
>  execve04 execve04 -F $LTPROOT/testcases/bin/test3
> -execve05 execve05 -F $LTPROOT/testcases/bin/test3
> -execve06 execve06 20 $LTPROOT/testcases/bin/execve06 $LTPROOT/testcases/bin/execve06 4
> +execve05 execve05 20 $LTPROOT/testcases/bin/execve05 $LTPROOT/testcases/bin/execve05 4
>  execvp01 execvp01
> 
>  exit01 exit01
> diff --git a/testcases/kernel/syscalls/execve/execve04.c b/testcases/kernel/syscalls/execve/execve04.c
> index 78c4bcb..b85fc32 100644
> --- a/testcases/kernel/syscalls/execve/execve04.c
> +++ b/testcases/kernel/syscalls/execve/execve04.c
> @@ -1,59 +1,64 @@
>  /*
>   *
> - *  Copyright (c) International Business Machines  Corp., 2001
> + *   Copyright (c) International Business Machines  Corp., 2001
>   *
> - *  This program is free software;  you can redistribute it and/or modify
> - *  it under the terms of the GNU General Public License as published by
> - *  the Free Software Foundation; either version 2 of the License, or
> - *  (at your option) any later version.
> + *   This program is free software;  you can redistribute it and/or modify
> + *   it under the terms of the GNU General Public License as published by
> + *   the Free Software Foundation; either version 2 of the License, or
> + *   (at your option) any later version.
>   *
> - *  This program is distributed in the hope that it will be useful,
> - *  but WITHOUT ANY WARRANTY;  without even the implied warranty of
> - *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> - *  the GNU General Public License for more details.
> + *   This program is distributed in the hope that it will be useful,
> + *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
> + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> + *   the GNU General Public License for more details.
>   *
> - *  You should have received a copy of the GNU General Public License
> - *  along with this program;  if not, write to the Free Software
> - *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> + *   You should have received a copy of the GNU General Public License
> + *   along with this program;  if not, write to the Free Software
> + *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
>   */
> 
>  /*
>   * NAME
> - *	execve04
> + *	execve04.c
>   *
>   * DESCRIPTION
> - *	Testcase to check execve(2) sets errno to EMFILE correctly
> + *	Testcase to check execve sets the following errnos correctly:
> + *	1.	ETXTBSY
>   *
>   * ALGORITHM
> - *	Get the configured file descriptor table size. open(2) files to fill
> - *	up the file descriptor table. Once file descriptor table is full,
> - *	an attempt to execve(2) any other executable fails with EMFILE.
> + *	1.	Attempt to execve(2) a file which is being opened by another
> + *		process for writing fails with ETXTBSY.
>   *
>   * USAGE:  <for command-line>
>   *  execve04 -F <test file> [-c n] [-e] [-i n] [-I x] [-P x] [-t]
> - *     where,	-c n : Run n copies concurrently.
> - *		-e   : Turn on errno logging.
> - *		-i n : Execute test n times.
> - *		-I x : Execute test for x seconds.
> - *		-P x : Pause for x seconds between iterations.
> - *		-t   : Turn on syscall timing.
> + *     where,  -c n : Run n copies concurrently.
> + *             -e   : Turn on errno logging.
> + *             -i n : Execute test n times.
> + *             -I x : Execute test for x seconds.
> + *             -P x : Pause for x seconds between iterations.
> + *             -t   : Turn on syscall timing.
>   *
>   * HISTORY
>   *	07/2001 Ported by Wayne Boyer
> + *	04/2008 Roy Lee <roylee@andestech.com>
> + *              - Fix a synchronization issue.
> + *                On a loaded system, the 'execving' child can get access
> + *                to the file before the 'opening' child does, hence results
> + *                in an unexpected opening fail.
>   *
>   * RESTRICTIONS
> - *	Must run test with the -F <test file> option.
> + *	must be run with -F <test file> option
>   */
> 
>  #include <stdio.h>
>  #include <errno.h>
> -#include <unistd.h>
> +#include <fcntl.h>
>  #include <sys/types.h>
> -#include <sys/stat.h>
>  #include <sys/wait.h>
> -#include <fcntl.h>
> -#include <test.h>
> -#include <usctest.h>
> +#include <libgen.h>
> +#include "test.h"
> +#include "usctest.h"
> +#include "libtestsuite.h"
> 
>  char *TCID = "execve04";
>  int TST_TOTAL = 1;
> @@ -62,20 +67,27 @@ extern int Tst_count;
>  void setup(void);
>  void cleanup(void);
>  void help(void);
> +void do_child_1(void);
> +void do_child_2(void);
> 
> -int mypid;
> -char fname[40] = "";
> -char test_name[PATH_MAX] = "";
> -int ifile, nfile, first;
> -
> -int exp_enos[] = { EMFILE, 0 };
> +int exp_enos[] = { ETXTBSY, 0 };
> +int start_sync_pipes[2];
> +int end_sync_pipes[2];
> 
>  int Fflag = 0;
> -char *fname1;
> +char *test_name;
> +
> +#ifdef UCLINUX
> +#define PIPE_NAME_START		"execve04_start"
> +#define PIPE_NAME_END		"execve04_end"
> +#else
> +#define PIPE_NAME_START		NULL
> +#define PIPE_NAME_END		NULL
> +#endif
> 
>  /* for test specific parse_opts options - in this case "-F" */
>  option_t options[] = {
> -	{"F:", &Fflag, &fname1},
> +	{"F:", &Fflag, &test_name},
>  	{NULL, NULL, NULL}
>  };
> 
> @@ -83,20 +95,23 @@ int main(int ac, char **av)
>  {
>  	int lc;			/* loop counter */
>  	char *msg;		/* message returned from parse_opts */
> -	int childpid;
> -	int err;
> +	pid_t pid, pid1;
> +	int e_code, status, retval = 3;
> +	char *argv[1], *env[1];
> 
>  	/* parse standard options */
>  	if ((msg = parse_opts(ac, av, options, &help)) != (char *)NULL) {
>  		tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
>  	}
> +#ifdef UCLINUX
> +	maybe_run_child(&do_child_1, "nS", 1, &test_name);
> +#endif
> 
>  	if (!Fflag) {
> -		tst_resm(TWARN,
> -			 "You must specify a test executable with"
> +		tst_resm(TWARN, "You must specify an executable file with "
>  			 "the -F option.");
>  		tst_resm(TWARN, "Run '%s -h' for option information.", TCID);
> -		tst_exit();
> +		cleanup();
>  	}
> 
>  	setup();
> @@ -109,119 +124,152 @@ int main(int ac, char **av)
>  		/* reset Tst_count in case we are looping */
>  		Tst_count = 0;
> 
> -		childpid = fork();
> -		if (childpid == -1) {
> -			tst_resm(TBROK, "fork() failed: %s", strerror(errno));
> -		} else if (childpid == 0) {
> -			TEST(execve(test_name, NULL, NULL));
> -			exit(TEST_ERRNO);
> -		} else {	/* parent */
> -			waitpid(childpid, &err, 0);
> -			err = WEXITSTATUS(err);
> -
> -			if (err != EMFILE) {
> -				tst_resm(TFAIL,
> -					 "execve(%s) failed: expected EMFILE(%d), got %d (%s)",
> -					 test_name, EMFILE, err, strerror(err));
> -				continue;
> +		if (sync_pipe_create(start_sync_pipes, PIPE_NAME_START) == -1)
> +			tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
> +		if (sync_pipe_create(end_sync_pipes, PIPE_NAME_END) == -1)
> +			tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
> +
> +		/*
> +		 * to test whether execve(2) sets ETXTBSY when a second
> +		 * child process attempts to execve the executable opened
> +		 * by the first child process
> +		 */
> +		if ((pid = FORK_OR_VFORK()) == -1) {
> +			tst_brkm(TBROK, cleanup, "fork #1 failed");
> +		}
> +
> +		if (pid == 0) {	/* first child */
> +#ifdef UCLINUX
> +			if (self_exec(av[0], "nS", 1, test_name) < 0) {
> +				tst_brkm(TBROK, cleanup, "self_exec failed");
>  			}
> +#else
> +			do_child_1();
> +#endif
> +		}
> 
> -			TEST_ERROR_LOG(err);
> +		if (sync_pipe_wait(start_sync_pipes) == -1)
> +			tst_brkm(TBROK, cleanup, "sync_pipe_wait failed");
> 
> -			tst_resm(TPASS, "Expected failure - %d : %s", err,
> -				 strerror(err));
> -		}
> +		if (sync_pipe_close(start_sync_pipes, PIPE_NAME_START) == -1)
> +			tst_brkm(TBROK, cleanup, "sync_pipe_close failed");
> +
> +		if ((pid1 = FORK_OR_VFORK()) == -1)
> +			tst_brkm(TBROK, cleanup, "fork #2 failed");
> +
> +		if (pid1 == 0) {	/* second child */
> +			argv[0] = 0;
> +			env[0] = 0;
> +
> +			/* do not interfere with end synchronization of first
> +			 * child */
> +			sync_pipe_close(end_sync_pipes, PIPE_NAME_END);
> 
> +			TEST(execve(test_name, argv, env));
> +
> +			TEST_ERROR_LOG(TEST_ERRNO);
> +
> +			if (TEST_ERRNO != ETXTBSY) {
> +				retval = 1;
> +				tst_resm(TFAIL, "expected ETXTBSY, received "
> +					 "%d : %s", TEST_ERRNO,
> +					 strerror(TEST_ERRNO));
> +			} else {
> +				tst_resm(TPASS, "call generated expected "
> +					 "ETXTBSY error");
> +			}
> +			exit(retval);
> +		} else {	/* parent */
> +			/* wait for the child to finish */
> +			waitpid(pid1, &status, 0);
> +			/* make sure the child returned a good exit status */
> +			e_code = status >> 8;
> +			/* If execve() succeeds, child cannot report the error */
> +			if (status == 0)
> +				tst_resm(TFAIL, "execve succeeded, "
> +					 "expected failure");
> +			if ((e_code != 3) || (retval != 3)) {
> +				tst_resm(TFAIL, "Failures reported above");
> +			}
> +
> +			/*  terminate first child */
> +			sync_pipe_notify(end_sync_pipes);
> +			waitpid(pid, NULL, 0);
> +			cleanup();
> +		}
>  	}
> -	cleanup();
> 
> -	/* NOTREACHED */
> -	return 0;
> +	 /*NOTREACHED*/ return 0;
>  }
> 
>  /*
> - * help
> - *	Prints out the help message for the -F option defined
> - *	by this test.
> + * help() - Prints out the help message for the -D option defined
> + *          by this test.
>   */
>  void help()
>  {
> -	puts("  -F <test file> : for example, 'execve04 -F test1'\n");
> +	printf("  -F <test name> : for example, 'execve04 -F test3'\n");
>  }
> 
>  /*
> - * setup
> - *	performs all ONE TIME setup for this test.
> + * setup() - performs all ONE TIME setup for this test.
>   */
>  void setup()
>  {
> -	int fd;
> -	char *pname = NULL;
> +	char *cmd, *dirc, *basec, *bname, *dname, *path, *pwd = NULL;
> +	int res;
> 
>  	/* capture signals */
>  	tst_sig(FORK, DEF_HANDLER, cleanup);
> 
> -	/* Pause if that option was specified */
> -	TEST_PAUSE;
> -
> -	/*
> -	 * Get the current working directory and append to it the name
> -	 * of the executable file specified with the -F option.
> -	 * This way when we issue the execve() call later, we get the
> -	 * correct path.  But only do this if user did not provide the
> -	 * full path to the executable file.
> +	/* Get file name of the passed test file and the absolute path to it.
> +	 * We will need these informations to copy the test file in the temp
> +	 * directory.
>  	 */
> -	if (*fname1 != '/') {
> -		if ((pname = getcwd(pname, 0)) == NULL) {
> +	dirc = strdup(test_name);
> +	basec = strdup(test_name);
> +	dname = dirname(dirc);
> +	bname = basename(basec);
> +
> +	if (dname[0] == '/')
> +		path = dname;
> +	else {
> +		if ((pwd = getcwd(NULL, 0)) == NULL) {
>  			tst_brkm(TBROK, tst_exit,
>  				 "Could not get current directory");
>  		}
> -		snprintf(test_name, sizeof(test_name) - 1, "%s/%s", pname,
> -			 fname1);
> -	} else {
> -		strncpy(test_name, fname1, sizeof(test_name) - 1);
> +		path = malloc(strlen(pwd) + strlen(dname) + 2);
> +		if (path == NULL) {
> +			tst_brkm(TBROK, tst_exit, "Cannot alloc path string");
> +		}
> +		sprintf(path, "%s/%s", pwd, dname);
>  	}
> 
> -	/* make temp dir and cd to it */
> +	/* make a temp dir and cd to it */
>  	tst_tmpdir();
> 
> -	nfile = getdtablesize();
> -	mypid = getpid();
> -
> -	sprintf(fname, "execve04.%d", mypid);
> -	unlink(fname);
> -
> -	if ((first = fd = creat(fname, 0666)) == -1) {
> -		tst_brkm(TBROK, cleanup, "Cannot open first file: %s",
> -			 strerror(errno));
> +	/* Copy the given test file to the private temp directory.
> +	 */
> +	cmd = malloc(strlen(path) + strlen(bname) + 15);
> +	if (cmd == NULL) {
> +		tst_brkm(TBROK, tst_exit, "Cannot alloc command string");
>  	}
> 
> -	close(fd);
> -	unlink(fname);
> -
> -	for (ifile = first; ifile <= nfile; ifile++) {
> -		sprintf(fname, "execve04.%d.%d", ifile, mypid);
> -		if ((fd = creat(fname, 0666)) == -1) {
> -			if (errno == EMFILE) {
> -				if (ifile != nfile)
> -					tst_resm(TINFO,
> -						 "couldn't creat file #%d, but this should be ok",
> -						 ifile + 1);
> -				break;
> -			}
> -			tst_resm(TBROK,
> -				 "couldn't creat file #%d, expected to "
> -				 "create %d files: %s", ifile + 1, nfile,
> -				 strerror(errno));
> -			cleanup();
> -		}
> +	sprintf(cmd, "cp -p %s/%s .", path, bname);
> +	res = system(cmd);
> +	free(cmd);
> +	if (res == -1) {
> +		tst_brkm(TBROK, tst_exit, "Cannot copy file %s", test_name);
>  	}
> +
> +	test_name = bname;
> +	/* Pause if that option was specified */
> +	TEST_PAUSE;
>  }
> 
>  /*
> - * cleanup
> - *	performs all ONE TIME cleanup for this test at completion or
> - *	premature exit
> + * cleanup() - performs all ONE TIME cleanup for this test at
> + *	       completion or premature exit.
>   */
>  void cleanup()
>  {
> @@ -229,17 +277,48 @@ void cleanup()
>  	 * print timing stats if that option was specified.
>  	 * print errno log if that option was specified.
>  	 */
> -	close(first);
> -
>  	TEST_CLEANUP;
> 
> -	/* Remove the tmp dir and all files it */
> -	for (ifile = first; ifile < nfile; ifile++) {
> -		sprintf(fname, "execve04.%d.%d", ifile, mypid);
> -		unlink(fname);
> -	}
> +	/* Remove the temporary directory */
>  	tst_rmdir();
> 
>  	/* exit with return code appropriate for results */
>  	tst_exit();
>  }
> +
> +/*
> + * do_child_1()
> + */
> +void do_child_1()
> +{
> +	int fildes;
> +
> +#ifdef UCLINUX
> +	if (sync_pipe_create(start_sync_pipes, PIPE_NAME_START) == -1)
> +		tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
> +	if (sync_pipe_create(end_sync_pipes, PIPE_NAME_END) == -1)
> +		tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
> +#endif
> +
> +	if ((fildes = open(test_name, O_WRONLY)) == -1) {
> +		tst_brkm(TBROK, NULL, "open(2) failed");
> +		exit(1);
> +	}
> +
> +	if (sync_pipe_notify(start_sync_pipes) == -1) {
> +		tst_brkm(TBROK, NULL, "sync_pipe_notify failed");
> +		exit(1);
> +	}
> +
> +	if (sync_pipe_close(start_sync_pipes, PIPE_NAME_START) == -1) {
> +		tst_brkm(TBROK, NULL, "sync_pipe_close failed");
> +		exit(1);
> +	}
> +
> +	/* let other child execve same file */
> +	if (sync_pipe_wait(end_sync_pipes) == -1) {
> +		tst_brkm(TBROK, NULL, "sync_pipe_wait failed");
> +		exit(1);
> +	}
> +	exit(0);
> +}
> diff --git a/testcases/kernel/syscalls/execve/execve05.c b/testcases/kernel/syscalls/execve/execve05.c
> index e232a03..ec2c99e 100644
> --- a/testcases/kernel/syscalls/execve/execve05.c
> +++ b/testcases/kernel/syscalls/execve/execve05.c
> @@ -19,104 +19,75 @@
> 
>  /*
>   * NAME
> - *	execve05.c
> + * 	execve05.c
>   *
>   * DESCRIPTION
> - *	Testcase to check execve sets the following errnos correctly:
> - *	1.	ETXTBSY
> + * 	This testcase tests the basic functionality of the execve(2) system
> + *	call.
>   *
>   * ALGORITHM
> - *	1.	Attempt to execve(2) a file which is being opened by another
> - *		process for writing fails with ETXTBSY.
> + *	This program also gets the names "test1", and "test2". This tests
> + *	the functionality of the execve(2) system call by spawning a few
> + *	children, each of which would execute "test1/test2" executables, and
> + *	finally the parent ensures that they terminated correctly.
>   *
> - * USAGE:  <for command-line>
> - *  execve05 -F <test file> [-c n] [-e] [-i n] [-I x] [-P x] [-t]
> - *     where,  -c n : Run n copies concurrently.
> - *             -e   : Turn on errno logging.
> - *             -i n : Execute test n times.
> - *             -I x : Execute test for x seconds.
> - *             -P x : Pause for x seconds between iterations.
> - *             -t   : Turn on syscall timing.
> - *
> - * HISTORY
> - *	07/2001 Ported by Wayne Boyer
> - *	04/2008 Roy Lee <roylee@andestech.com>
> - *              - Fix a synchronization issue.
> - *                On a loaded system, the 'execving' child can get access
> - *                to the file before the 'opening' child does, hence results
> - *                in an unexpected opening fail.
> + * USAGE
> + *	execve05 20 test1 test2 4
>   *
>   * RESTRICTIONS
> - *	must be run with -F <test file> option
> + * 	This program does not follow the LTP format - *PLEASE FIX*
>   */
> 
>  #include <stdio.h>
>  #include <errno.h>
> -#include <fcntl.h>
>  #include <sys/types.h>
> +#include <sys/stat.h>
>  #include <sys/wait.h>
> -#include <libgen.h>
>  #include "test.h"
>  #include "usctest.h"
> -#include "libtestsuite.h"
> 
> -char *TCID = "execve05";
> -int TST_TOTAL = 1;
> -extern int Tst_count;
> +#undef DEBUG			/* change this to #define if needed */
> 
>  void setup(void);
>  void cleanup(void);
> -void help(void);
> -void do_child_1(void);
> -void do_child_2(void);
> -
> -int exp_enos[] = { ETXTBSY, 0 };
> -int start_sync_pipes[2];
> -int end_sync_pipes[2];
> 
> -int Fflag = 0;
> -char *test_name;
> +char *TCID = "execve05";
> +int TST_TOTAL = 1;
> +extern int Tst_count;
> 
> -#ifdef UCLINUX
> -#define PIPE_NAME_START		"execve05_start"
> -#define PIPE_NAME_END		"execve05_end"
> -#else
> -#define PIPE_NAME_START		NULL
> -#define PIPE_NAME_END		NULL
> -#endif
> +int iterations;
> +char *fname1;
> +char *fname2;
> +char *prog;
> +char *av[6];
> +char *ev[1];
> 
> -/* for test specific parse_opts options - in this case "-F" */
> -option_t options[] = {
> -	{"F:", &Fflag, &test_name},
> -	{NULL, NULL, NULL}
> -};
> +void usage(void)
> +{
> +	tst_resm(TBROK, "usage: %s <iters> <fname1> <fname2> <count>", TCID);
> +	tst_resm(TINFO, "example: %s 20 test1 test2 4", TCID);
> +	tst_exit();
> +}
> 
>  int main(int ac, char **av)
>  {
> -	int lc;			/* loop counter */
> -	char *msg;		/* message returned from parse_opts */
> -	pid_t pid, pid1;
> -	int e_code, status, retval = 3;
> -	char *argv[1], *env[1];
> +	char iter[20];
> +	int pid, child, status, count;
> +	int nchild, i, fail = 0;
> +
> +	int lc;
> +	char *msg;
> 
>  	/* parse standard options */
> -	if ((msg = parse_opts(ac, av, options, &help)) != (char *)NULL) {
> +	if ((msg = parse_opts(ac, av, (option_t *) NULL, NULL)) != (char *)NULL) {
>  		tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
> -	}
> -#ifdef UCLINUX
> -	maybe_run_child(&do_child_1, "nS", 1, &test_name);
> -#endif
> -
> -	if (!Fflag) {
> -		tst_resm(TWARN, "You must specify an executable file with "
> -			 "the -F option.");
> -		tst_resm(TWARN, "Run '%s -h' for option information.", TCID);
> -		cleanup();
> -	}
> -
> +	 /*NOTREACHED*/}
>  	setup();
> 
> -	TEST_EXP_ENOS(exp_enos);
> +	if (ac != 5) {
> +		tst_resm(TINFO, "Wrong number of arguments");
> +		usage();
> +	 /*NOTREACHED*/}
> 
>  	/* check looping state if -i option given */
>  	for (lc = 0; TEST_LOOPING(lc); lc++) {
> @@ -124,201 +95,142 @@ int main(int ac, char **av)
>  		/* reset Tst_count in case we are looping */
>  		Tst_count = 0;
> 
> -		if (sync_pipe_create(start_sync_pipes, PIPE_NAME_START) == -1)
> -			tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
> -		if (sync_pipe_create(end_sync_pipes, PIPE_NAME_END) == -1)
> -			tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
> +		prog = av[0];
> +		iterations = atoi(av[1]);
> +		fname1 = av[2];
> +		fname2 = av[3];
> +		count = atoi(av[4]);
> +#ifdef DEBUG
> +		tst_resm(TINFO, "Entered %s %d %s %s %d -- pid = %d", prog,
> +			 iterations, fname1, fname2, count, getpid());
> +#endif
> 
> -		/*
> -		 * to test whether execve(2) sets ETXTBSY when a second
> -		 * child process attempts to execve the executable opened
> -		 * by the first child process
> -		 */
> -		if ((pid = FORK_OR_VFORK()) == -1) {
> -			tst_brkm(TBROK, cleanup, "fork #1 failed");
> +		if (iterations == 0) {
> +			tst_resm(TPASS, "Test DONE, pid %d, -- %s %d %s %s",
> +				 getpid(), prog, iterations, fname1, fname2);
> +			tst_exit();
>  		}
> 
> -		if (pid == 0) {	/* first child */
> -#ifdef UCLINUX
> -			if (self_exec(av[0], "nS", 1, test_name) < 0) {
> -				tst_brkm(TBROK, cleanup, "self_exec failed");
> -			}
> -#else
> -			do_child_1();
> +		if (!count) {
> +			sprintf(iter, "%d", iterations - 1);
> +			av[0] = fname1;
> +			av[1] = iter;
> +			av[2] = fname1;
> +			av[3] = fname2;
> +			av[4] = "0";
> +			av[5] = 0;
> +			ev[0] = 0;
> +#ifdef DEBUG
> +			tst_resm(TINFO, "Doing execve(%s, av, ev)", fname1);
> +			tst_resm(TINFO, "av[0,1,2,3,4] = %s, %s, %s, %s, %s",
> +				 av[0], av[1], av[2], av[3], av[4]);
>  #endif
> +			(void)execve(fname1, av, ev);
> +			tst_resm(TFAIL, "Execve fail, %s, errno=%d", fname1,
> +				 errno);
>  		}
> 
> -		if (sync_pipe_wait(start_sync_pipes) == -1)
> -			tst_brkm(TBROK, cleanup, "sync_pipe_wait failed");
> -
> -		if (sync_pipe_close(start_sync_pipes, PIPE_NAME_START) == -1)
> -			tst_brkm(TBROK, cleanup, "sync_pipe_close failed");
> -
> -		if ((pid1 = FORK_OR_VFORK()) == -1)
> -			tst_brkm(TBROK, cleanup, "fork #2 failed");
> -
> -		if (pid1 == 0) {	/* second child */
> -			argv[0] = 0;
> -			env[0] = 0;
> -
> -			/* do not interfere with end synchronization of first
> -			 * child */
> -			sync_pipe_close(end_sync_pipes, PIPE_NAME_END);
> -
> -			TEST(execve(test_name, argv, env));
> -
> -			TEST_ERROR_LOG(TEST_ERRNO);
> -
> -			if (TEST_ERRNO != ETXTBSY) {
> -				retval = 1;
> -				tst_resm(TFAIL, "expected ETXTBSY, received "
> -					 "%d : %s", TEST_ERRNO,
> -					 strerror(TEST_ERRNO));
> -			} else {
> -				tst_resm(TPASS, "call generated expected "
> -					 "ETXTBSY error");
> +		nchild = count * 2;
> +
> +		sprintf(iter, "%d", iterations);
> +		for (i = 0; i < count; i++) {
> +			pid = FORK_OR_VFORK();
> +			if (pid < 0) {
> +				perror("Fork failed");
> +				exit(1);
> +			} else if (pid == 0) {
> +				av[0] = fname1;
> +				av[1] = iter;
> +				av[2] = fname1;
> +				av[3] = fname2;
> +				av[4] = "0";
> +				av[5] = 0;
> +				ev[0] = 0;
> +				(void)execve(fname1, av, ev);
> +				tst_resm(TFAIL, "Execve fail, %s, errno = %d",
> +					 fname1, errno);
> +				exit(2);
> +			}
> +#ifdef DEBUG
> +			tst_resm(TINFO, "Main - started pid %d", pid);
> +#endif
> +			pid = FORK_OR_VFORK();
> +			if (pid < 0) {
> +				perror("Fork failed");
> +				exit(1);
> +			} else if (pid == 0) {
> +				av[0] = fname2;
> +				av[1] = iter;
> +				av[2] = fname2;
> +				av[3] = fname1;
> +				av[4] = "0";
> +				av[5] = 0;
> +				ev[0] = 0;
> +				execve(fname2, av, ev);
> +				tst_resm(TFAIL, "Execve fail, %s, errno = %d",
> +					 fname2, errno);
> +				exit(2);
>  			}
> -			exit(retval);
> -		} else {	/* parent */
> -			/* wait for the child to finish */
> -			waitpid(pid1, &status, 0);
> -			/* make sure the child returned a good exit status */
> -			e_code = status >> 8;
> -			/* If execve() succeeds, child cannot report the error */
> -			if (status == 0)
> -				tst_resm(TFAIL, "execve succeeded, "
> -					 "expected failure");
> -			if ((e_code != 3) || (retval != 3)) {
> -				tst_resm(TFAIL, "Failures reported above");
> +#ifdef DEBUG
> +			tst_resm(TINFO, "Main - started pid %d", pid);
> +#endif
> +		}
> +
> +		/*
> +		 * Wait for children to finish
> +		 */
> +		count = 0;
> +		while ((child = wait(&status)) > 0) {
> +#ifdef DEBUG
> +			tst_resm(TINFO, "Test [%d] exited status = 0x%x",
> +				 child, status);
> +#endif
> +			++count;
> +			if (status) {
> +				fail = 1;
>  			}
> +		}
> 
> -			/*  terminate first child */
> -			sync_pipe_notify(end_sync_pipes);
> -			waitpid(pid, NULL, 0);
> -			cleanup();
> +		/*
> +		 * Should have colledcted all children
> +		 */
> +		if (count != nchild) {
> +			tst_resm(TFAIL, "Wrong #children waited on, count = %d",
> +				 count);
> +			fail = 1;
> +		}
> +		if (fail) {
> +			tst_resm(TINFO, "Test FAILED");
> +		} else {
> +			tst_resm(TINFO, "Test PASSED");
>  		}
>  	}
> +	cleanup();
> 
>  	 /*NOTREACHED*/ return 0;
>  }
> 
>  /*
> - * help() - Prints out the help message for the -D option defined
> - *          by this test.
> - */
> -void help()
> -{
> -	printf("  -F <test name> : for example, 'execve05 -F test3'\n");
> -}
> -
> -/*
> - * setup() - performs all ONE TIME setup for this test.
> + * setup - performs all ONE TIME steup for this test
>   */
> -void setup()
> +void setup(void)
>  {
> -	char *cmd, *dirc, *basec, *bname, *dname, *path, *pwd = NULL;
> -	int res;
> -
>  	/* capture signals */
>  	tst_sig(FORK, DEF_HANDLER, cleanup);
> 
> -	/* Get file name of the passed test file and the absolute path to it.
> -	 * We will need these informations to copy the test file in the temp
> -	 * directory.
> -	 */
> -	dirc = strdup(test_name);
> -	basec = strdup(test_name);
> -	dname = dirname(dirc);
> -	bname = basename(basec);
> -
> -	if (dname[0] == '/')
> -		path = dname;
> -	else {
> -		if ((pwd = getcwd(NULL, 0)) == NULL) {
> -			tst_brkm(TBROK, tst_exit,
> -				 "Could not get current directory");
> -		}
> -		path = malloc(strlen(pwd) + strlen(dname) + 2);
> -		if (path == NULL) {
> -			tst_brkm(TBROK, tst_exit, "Cannot alloc path string");
> -		}
> -		sprintf(path, "%s/%s", pwd, dname);
> -	}
> -
> -	/* make a temp dir and cd to it */
> -	tst_tmpdir();
> -
> -	/* Copy the given test file to the private temp directory.
> -	 */
> -	cmd = malloc(strlen(path) + strlen(bname) + 15);
> -	if (cmd == NULL) {
> -		tst_brkm(TBROK, tst_exit, "Cannot alloc command string");
> -	}
> -
> -	sprintf(cmd, "cp -p %s/%s .", path, bname);
> -	res = system(cmd);
> -	free(cmd);
> -	if (res == -1) {
> -		tst_brkm(TBROK, tst_exit, "Cannot copy file %s", test_name);
> -	}
> -
> -	test_name = bname;
>  	/* Pause if that option was specified */
>  	TEST_PAUSE;
> +
> +	umask(0);
>  }
> 
>  /*
> - * cleanup() - performs all ONE TIME cleanup for this test at
> - *	       completion or premature exit.
> + * cleanup() - performs all the ONE TIME cleanup for this test at completion or
> + * 	       premature exit
>   */
> -void cleanup()
> +void cleanup(void)
>  {
> -	/*
> -	 * print timing stats if that option was specified.
> -	 * print errno log if that option was specified.
> -	 */
>  	TEST_CLEANUP;
> 
> -	/* Remove the temporary directory */
> -	tst_rmdir();
> -
> -	/* exit with return code appropriate for results */
>  	tst_exit();
>  }
> -
> -/*
> - * do_child_1()
> - */
> -void do_child_1()
> -{
> -	int fildes;
> -
> -#ifdef UCLINUX
> -	if (sync_pipe_create(start_sync_pipes, PIPE_NAME_START) == -1)
> -		tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
> -	if (sync_pipe_create(end_sync_pipes, PIPE_NAME_END) == -1)
> -		tst_brkm(TBROK, cleanup, "sync_pipe_create failed");
> -#endif
> -
> -	if ((fildes = open(test_name, O_WRONLY)) == -1) {
> -		tst_brkm(TBROK, NULL, "open(2) failed");
> -		exit(1);
> -	}
> -
> -	if (sync_pipe_notify(start_sync_pipes) == -1) {
> -		tst_brkm(TBROK, NULL, "sync_pipe_notify failed");
> -		exit(1);
> -	}
> -
> -	if (sync_pipe_close(start_sync_pipes, PIPE_NAME_START) == -1) {
> -		tst_brkm(TBROK, NULL, "sync_pipe_close failed");
> -		exit(1);
> -	}
> -
> -	/* let other child execve same file */
> -	if (sync_pipe_wait(end_sync_pipes) == -1) {
> -		tst_brkm(TBROK, NULL, "sync_pipe_wait failed");
> -		exit(1);
> -	}
> -	exit(0);
> -}
> diff --git a/testcases/kernel/syscalls/execve/execve06.c b/testcases/kernel/syscalls/execve/execve06.c
> deleted file mode 100644
> index 3146d45..0000000
> --- a/testcases/kernel/syscalls/execve/execve06.c
> +++ /dev/null
> @@ -1,236 +0,0 @@
> -/*
> - *
> - *   Copyright (c) International Business Machines  Corp., 2001
> - *
> - *   This program is free software;  you can redistribute it and/or modify
> - *   it under the terms of the GNU General Public License as published by
> - *   the Free Software Foundation; either version 2 of the License, or
> - *   (at your option) any later version.
> - *
> - *   This program is distributed in the hope that it will be useful,
> - *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
> - *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
> - *   the GNU General Public License for more details.
> - *
> - *   You should have received a copy of the GNU General Public License
> - *   along with this program;  if not, write to the Free Software
> - *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> - */
> -
> -/*
> - * NAME
> - * 	execve06.c
> - *
> - * DESCRIPTION
> - * 	This testcase tests the basic functionality of the execve(2) system
> - *	call.
> - *
> - * ALGORITHM
> - *	This program also gets the names "test1", and "test2". This tests
> - *	the functionality of the execve(2) system call by spawning a few
> - *	children, each of which would execute "test1/test2" executables, and
> - *	finally the parent ensures that they terminated correctly.
> - *
> - * USAGE
> - *	execve06 20 test1 test2 4
> - *
> - * RESTRICTIONS
> - * 	This program does not follow the LTP format - *PLEASE FIX*
> - */
> -
> -#include <stdio.h>
> -#include <errno.h>
> -#include <sys/types.h>
> -#include <sys/stat.h>
> -#include <sys/wait.h>
> -#include "test.h"
> -#include "usctest.h"
> -
> -#undef DEBUG			/* change this to #define if needed */
> -
> -void setup(void);
> -void cleanup(void);
> -
> -char *TCID = "execve06";
> -int TST_TOTAL = 1;
> -extern int Tst_count;
> -
> -int iterations;
> -char *fname1;
> -char *fname2;
> -char *prog;
> -char *av[6];
> -char *ev[1];
> -
> -void usage(void)
> -{
> -	tst_resm(TBROK, "usage: %s <iters> <fname1> <fname2> <count>", TCID);
> -	tst_resm(TINFO, "example: %s 20 test1 test2 4", TCID);
> -	tst_exit();
> -}
> -
> -int main(int ac, char **av)
> -{
> -	char iter[20];
> -	int pid, child, status, count;
> -	int nchild, i, fail = 0;
> -
> -	int lc;
> -	char *msg;
> -
> -	/* parse standard options */
> -	if ((msg = parse_opts(ac, av, (option_t *) NULL, NULL)) != (char *)NULL) {
> -		tst_brkm(TBROK, tst_exit, "OPTION PARSING ERROR - %s", msg);
> -	 /*NOTREACHED*/}
> -	setup();
> -
> -	if (ac != 5) {
> -		tst_resm(TINFO, "Wrong number of arguments");
> -		usage();
> -	 /*NOTREACHED*/}
> -
> -	/* check looping state if -i option given */
> -	for (lc = 0; TEST_LOOPING(lc); lc++) {
> -
> -		/* reset Tst_count in case we are looping */
> -		Tst_count = 0;
> -
> -		prog = av[0];
> -		iterations = atoi(av[1]);
> -		fname1 = av[2];
> -		fname2 = av[3];
> -		count = atoi(av[4]);
> -#ifdef DEBUG
> -		tst_resm(TINFO, "Entered %s %d %s %s %d -- pid = %d", prog,
> -			 iterations, fname1, fname2, count, getpid());
> -#endif
> -
> -		if (iterations == 0) {
> -			tst_resm(TPASS, "Test DONE, pid %d, -- %s %d %s %s",
> -				 getpid(), prog, iterations, fname1, fname2);
> -			tst_exit();
> -		}
> -
> -		if (!count) {
> -			sprintf(iter, "%d", iterations - 1);
> -			av[0] = fname1;
> -			av[1] = iter;
> -			av[2] = fname1;
> -			av[3] = fname2;
> -			av[4] = "0";
> -			av[5] = 0;
> -			ev[0] = 0;
> -#ifdef DEBUG
> -			tst_resm(TINFO, "Doing execve(%s, av, ev)", fname1);
> -			tst_resm(TINFO, "av[0,1,2,3,4] = %s, %s, %s, %s, %s",
> -				 av[0], av[1], av[2], av[3], av[4]);
> -#endif
> -			(void)execve(fname1, av, ev);
> -			tst_resm(TFAIL, "Execve fail, %s, errno=%d", fname1,
> -				 errno);
> -		}
> -
> -		nchild = count * 2;
> -
> -		sprintf(iter, "%d", iterations);
> -		for (i = 0; i < count; i++) {
> -			pid = FORK_OR_VFORK();
> -			if (pid < 0) {
> -				perror("Fork failed");
> -				exit(1);
> -			} else if (pid == 0) {
> -				av[0] = fname1;
> -				av[1] = iter;
> -				av[2] = fname1;
> -				av[3] = fname2;
> -				av[4] = "0";
> -				av[5] = 0;
> -				ev[0] = 0;
> -				(void)execve(fname1, av, ev);
> -				tst_resm(TFAIL, "Execve fail, %s, errno = %d",
> -					 fname1, errno);
> -				exit(2);
> -			}
> -#ifdef DEBUG
> -			tst_resm(TINFO, "Main - started pid %d", pid);
> -#endif
> -			pid = FORK_OR_VFORK();
> -			if (pid < 0) {
> -				perror("Fork failed");
> -				exit(1);
> -			} else if (pid == 0) {
> -				av[0] = fname2;
> -				av[1] = iter;
> -				av[2] = fname2;
> -				av[3] = fname1;
> -				av[4] = "0";
> -				av[5] = 0;
> -				ev[0] = 0;
> -				execve(fname2, av, ev);
> -				tst_resm(TFAIL, "Execve fail, %s, errno = %d",
> -					 fname2, errno);
> -				exit(2);
> -			}
> -#ifdef DEBUG
> -			tst_resm(TINFO, "Main - started pid %d", pid);
> -#endif
> -		}
> -
> -		/*
> -		 * Wait for children to finish
> -		 */
> -		count = 0;
> -		while ((child = wait(&status)) > 0) {
> -#ifdef DEBUG
> -			tst_resm(TINFO, "Test [%d] exited status = 0x%x",
> -				 child, status);
> -#endif
> -			++count;
> -			if (status) {
> -				fail = 1;
> -			}
> -		}
> -
> -		/*
> -		 * Should have colledcted all children
> -		 */
> -		if (count != nchild) {
> -			tst_resm(TFAIL, "Wrong #children waited on, count = %d",
> -				 count);
> -			fail = 1;
> -		}
> -		if (fail) {
> -			tst_resm(TINFO, "Test FAILED");
> -		} else {
> -			tst_resm(TINFO, "Test PASSED");
> -		}
> -	}
> -	cleanup();
> -
> -	 /*NOTREACHED*/ return 0;
> -}
> -
> -/*
> - * setup - performs all ONE TIME steup for this test
> - */
> -void setup(void)
> -{
> -	/* capture signals */
> -	tst_sig(FORK, DEF_HANDLER, cleanup);
> -
> -	/* Pause if that option was specified */
> -	TEST_PAUSE;
> -
> -	umask(0);
> -}
> -
> -/*
> - * cleanup() - performs all the ONE TIME cleanup for this test at completion or
> - * 	       premature exit
> - */
> -void cleanup(void)
> -{
> -	TEST_CLEANUP;
> -
> -	tst_exit();
> -}


------------------------------------------------------------------------------
Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT 
is a gathering of tech-side developers & brand creativity professionals. Meet
the minds behind Google Creative Lab, Visual Complexity, Processing, & 
iPhoneDevCamp as they present alongside digital heavyweights like Barbarian 
Group, R/GA, & Big Spaceship. http://p.sf.net/sfu/creativitycat-com 
_______________________________________________
Ltp-list mailing list
Ltp-list@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/ltp-list

      reply	other threads:[~2009-05-27 14:23 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-22  9:26 [LTP] [QUESTION] about test execve04 which testing for EMFILE Wei Yongjun
2009-05-25 16:14 ` Subrata Modak
2009-05-26  9:44   ` Wei Yongjun
2009-05-26 12:22     ` Subrata Modak
2009-05-27  3:48       ` Wei Yongjun
2009-05-27 14:23         ` Subrata Modak [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1243434200.10447.16.camel@subratamodak.linux.ibm.com \
    --to=subrata@linux.vnet.ibm.com \
    --cc=ltp-list@lists.sourceforge.net \
    --cc=yjwei@cn.fujitsu.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox