/*
 *
 *   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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/*
 * NAME
 *	getcwd02
 *
 * DESCRIPTION
 *	Testcase to check the basic functionality of the getcwd(2) system call.
 *
 * ALGORITHM
 *	Get the path name of the current working directory from the current
 *	shell through a pipe, and compare it with what is returned by
 *	getcwd(2) system call.
 *
 *  Blocks 1-4 are with char[], #4 is special case where address is -1
 *
 *	Block 1: Call getcwd(2) with valid cwd[]:
 *              Should work fine
 *	Block 2: Call getcwd(2) with valid cwd[], size = 0:
 *              Should return NULL, errno = EINVAL
 *	Block 3: Call getcwd(2) with valid cwd[], size <= strlen(path):
 *              i.e. size = 1, Should return NULL, errno = ERANGE
 *      Block 4: Call getcwd(2) with cwd address = -1, size > strlen(path):
 *              Should return NULL, errno = EFAULT
 *
 *  Blocks 5-7 are with char*
 *
 *	Block 5: Call getcwd(2) with *buffer = NULL, size = 0:
 * 		Should allocate buffer, and work fine
 *	Block 6: Call getcwd(2) with *buffer = NULL, size <= strlen(path):
 * 		i.e. size = 1, Should return NULL, errno = ERANGE
 *      Block 7: Call getcwd(2) with *buffer = NULL, size > strlen(path):
 *              Should work fine and allocate buffer
 *
 * HISTORY
 *	07/2001 Ported by Wayne Boyer
 *      02/2002 Added more testcases, cleaned up by wjh
 *
 * RESTRICTIONS
 *	NONE
 */
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "test.h"
#define FAILED 1

char *pwd = "/bin/pwd";
int flag;
char *TCID = "getcwd02";
int TST_TOTAL = 7;

void cleanup(void);
void setup(void);
void do_block1(void);
void do_block2(void);
void do_block3(void);
void do_block4(void);
void do_block5(void);
void do_block6(void);
void do_block7(void);

char pwd_buf[BUFSIZ];		//holds results of pwd pipe
char cwd[BUFSIZ];		//used as our valid buffer
char *buffer = NULL;		//catches the return value from getcwd when passing NULL
char *cwd_ptr = NULL;		//catches the return value from getcwd() when passing cwd[]

int main(int ac, char **av)
{
	FILE *fin;
	char *cp;
	int lc;
	const char *msg;		/* parse_opts() return message */

	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL) {
		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
	}
	setup();

	/*
	 * The following loop checks looping state if -i option given
	 */
	for (lc = 0; TEST_LOOPING(lc); lc++) {
		tst_count = 0;

		if ((fin = popen(pwd, "r")) == NULL) {
			tst_resm(TINFO, "%s: can't run %s", TCID, pwd);
			tst_brkm(TBROK, cleanup, "%s FAILED", TCID);
		}
		while (fgets(pwd_buf, sizeof(pwd_buf), fin) != NULL) {
			if ((cp = strchr(pwd_buf, '\n')) == NULL) {
				tst_brkm(TBROK, cleanup, "pwd output too long");
			}
			*cp = 0;
		}
		pclose(fin);

		do_block1();
		do_block2();
		do_block3();
		do_block4();
		do_block5();
		do_block6();
		do_block7();
	}
	cleanup();
	tst_exit();
}

void do_block1(void)		//valid cwd[]: -> Should work fine
{
	int flag = 0;
	tst_resm(TINFO, "Enter Block 1");

	if ((cwd_ptr = getcwd(cwd, sizeof(cwd))) == NULL) {
		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly");
		flag = FAILED;
	}
	if ((flag != FAILED) && (strcmp(pwd_buf, cwd) != 0)) {
		tst_resm(TFAIL, "getcwd() returned unexpected working "
			 "directory: expected: %s, got: %s\n", pwd_buf, cwd);
		flag = FAILED;
	}
	tst_resm(TINFO, "Exit Block 1");
	if (flag == FAILED) {
		tst_resm(TFAIL, "Block 1 FAILED");
	} else {
		tst_resm(TPASS, "Block 1 PASSED");
	}
}

void do_block2(void)		//valid cwd[], size = 0: -> Should return NULL, errno = EINVAL
{
	int flag = 0;
	tst_resm(TINFO, "Enter Block 2");

	if (((cwd_ptr = getcwd(cwd, 0)) == NULL)
	    && (errno != EINVAL)) {
		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly (wanted EINVAL)");
		flag = FAILED;
	}
	tst_resm(TINFO, "Exit Block 2");
	if (flag == FAILED) {
		tst_resm(TFAIL, "Block 2 FAILED");
	} else {
		tst_resm(TPASS, "Block 2 PASSED");
	}
}

void do_block3(void)		//valid cwd[], size = 1 -> Should return NULL, errno = ERANGE
{
	int flag = 0;
	tst_resm(TINFO, "Enter Block 3");

	if (((cwd_ptr = getcwd(cwd, 1)) != NULL)
	    || (errno != ERANGE)) {
		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly (wanted ERANGE)");
		flag = FAILED;
	}
	tst_resm(TINFO, "Exit Block 3");
	if (flag == FAILED) {
		tst_resm(TFAIL, "Block 3 FAILED");
	} else {
		tst_resm(TPASS, "Block 3 PASSED");
	}
}

void do_block4(void)		//invalid cwd[] = -1, size = BUFSIZ: -> return NULL, errno = FAULT
{
/* Skip since uClinux does not implement memory protection */
#ifndef UCLINUX
	int flag = 0;
	tst_resm(TINFO, "Enter Block 4");

	if (((cwd_ptr = getcwd((char *)-1, sizeof(cwd))) != NULL)
	    || (errno != EFAULT)) {
		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly (wanted EFAULT)");
		flag = FAILED;
	}
	tst_resm(TINFO, "Exit Block 4");
	if (flag == FAILED) {
		tst_resm(TFAIL, "Block 4 FAILED");
	} else {
		tst_resm(TPASS, "Block 4 PASSED");
	}
#else
	tst_resm(TINFO, "Skipping Block 4 on uClinux");
#endif
}

void do_block5(void)		//buffer = NULL, and size = 0, should succeed
{
	int flag = 0;
	tst_resm(TINFO, "Enter Block 5");

	if ((buffer = getcwd(NULL, 0)) == NULL) {
		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly");
		flag = FAILED;
	}
	if ((flag != FAILED) && (strcmp(pwd_buf, buffer) != 0)) {
		tst_resm(TFAIL, "getcwd() returned unexpected working "
			 "directory: expected: %s, got: %s\n", pwd_buf, buffer);
		flag = FAILED;
	}
	tst_resm(TINFO, "Exit Block 5");
	if (flag == FAILED) {
		tst_resm(TFAIL, "Block 5 FAILED");
	} else {
		tst_resm(TPASS, "Block 5 PASSED");
	}
	free(buffer);
	buffer = NULL;
}

void do_block6(void)		//buffer = NULL, size = 1: -> return NULL, errno = ERANGE
{
	int flag = 0;
	tst_resm(TINFO, "Enter Block 6");

	if (((buffer = getcwd(NULL, 1)) != NULL)
	    || (errno != ERANGE)) {
		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly (wanted ERANGE)");
		flag = FAILED;
	}
	tst_resm(TINFO, "Exit Block 6");
	if (flag == FAILED) {
		tst_resm(TFAIL, "Block 6 FAILED");
	} else {
		tst_resm(TPASS, "Block 6 PASSED");
	}
}

void do_block7(void)		//buffer = NULL, size = BUFSIZ: -> work fine, allocate buffer
{
	int flag = 0;
	tst_resm(TINFO, "Enter Block 7");

	if ((buffer = getcwd(NULL, sizeof(cwd))) == NULL) {
		tst_resm(TFAIL|TERRNO, "getcwd() failed unexpectedly");
		flag = FAILED;
	}
	if ((flag != FAILED) && (strcmp(pwd_buf, buffer) != 0)) {
		tst_resm(TFAIL, "getcwd() returned unexpected working "
			 "directory: expected: %s, got: %s\n", pwd_buf, buffer);
		flag = FAILED;
	}
	tst_resm(TINFO, "Exit Block 7");
	if (flag == FAILED) {
		tst_resm(TFAIL, "Block 7 FAILED");
	} else {
		tst_resm(TPASS, "Block 7 PASSED");
	}
	free(buffer);
	buffer = NULL;
}

void setup(void)
{
	/* FORK is set here because of the popen() call above */
	tst_sig(FORK, DEF_HANDLER, cleanup);

	TEST_PAUSE;

	/* create a test directory and cd into it */
	tst_tmpdir();
}

void cleanup(void)
{
	/* remove the test directory */
	tst_rmdir();
}
