New additions:
- tst_ library code.
- new quickhit tests
- more general code cleanup
diff --git a/INSTALL b/INSTALL
index f9b02a6..c6cdac2 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,4 +1,4 @@
-$Id: INSTALL,v 1.2 2000/05/08 20:31:30 alaffin Exp $
+$Id: INSTALL,v 1.3 2000/07/27 17:13:18 alaffin Exp $
Building and Installation of Test Tools.
@@ -8,9 +8,6 @@
were not necessary. Instead, a minimal approach was taken and the
build process reflects that. Simply:
-cd <tool>
make
-At the time of release, <tool> is doio. The build process builds the
-tools in question and leaves them among the sources. There are no
-install routines, yet.
+This does two things, builds the test libraries and then the tests.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..926df0b
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,15 @@
+
+CFLAGS+=
+LDFLAGS+=
+
+all: libltp.a
+ @$(MAKE) -C doio $@
+ @$(MAKE) -C tests $@
+
+libltp.a:
+ @$(MAKE) -C lib $@
+
+clean:
+ @$(MAKE) -C lib $@
+ @$(MAKE) -C doio $@
+ @$(MAKE) -C tests $@
diff --git a/doio/Makefile b/doio/Makefile
index 18f7fb8..27240eb 100644
--- a/doio/Makefile
+++ b/doio/Makefile
@@ -1,23 +1,21 @@
-CFLAGS+=
-LDFLAGS+=
-TARGETS=doio iogen rwtest growfiles
+CFLAGS+= -I../include
+LDFLAGS+= -L../lib -lltp
+TARGETS=doio growfiles rwtest iogen
SRCS=$(wildcard *.c)
OBJS=$(patsubst %.c,%.o,$(SRCS))
all: $(TARGETS)
-doio: doio.o random_range.o string_to_tokens.o pattern.o write_log.o
- $(CC) -o $@ $^ $(LDFLAGS)
+doio: doio.o
+ $(CC) -o $@ $^ -I. $(CFLAGS) $(LDFLAGS)
-growfiles: growfiles.o dataascii.o open_flags.o tlibio.o random_range.o \
- file_lock.o datapid.o databin.o forker.o string_to_tokens.o
- $(CC) -o $@ $^ $(LDFLAGS)
+growfiles: growfiles.o
+ $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS)
-iogen: iogen.o str_to_bytes.o string_to_tokens.o random_range.o \
- open_flags.o
- $(CC) -o $@ $^ $(LDFLAGS)
+iogen: iogen.o
+ $(CC) -o $@ $^ $(CFLAGS) $(LDFLAGS)
rwtest: rwtest.ks doio iogen
cp rwtest.ks rwtest
diff --git a/doio/growfiles.c b/doio/growfiles.c
index 1911fe7..f61091b 100644
--- a/doio/growfiles.c
+++ b/doio/growfiles.c
@@ -81,6 +81,7 @@
#include <string.h>
#include "dataascii.h"
#include "random_range.h"
+#include "databin.h"
#ifdef CRAY
#include <sys/panic.h>
diff --git a/include/databin.h b/include/databin.h
new file mode 100644
index 0000000..b71fbc0
--- /dev/null
+++ b/include/databin.h
@@ -0,0 +1,44 @@
+#ifndef _DATABIN_H_
+#define _DATABIN_H_
+
+/*******************************************************************************
+* NAME
+* databingen - fill a buffer with a data pattern
+*
+* SYNOPSIS
+* (void) databingen(mode, buffer, bsize, offset)
+* int mode;
+* char *buffer;
+* int bsize;
+* int offset;
+*
+* DESCRIPTION
+* datagen fills the buffer pointed to by 'buffer' with 'bsize' bytes
+* of data of the form indicated by 'mode'.
+* All modes (expect r -random) are file offset based.
+* This allows more than process to do writing to the file without
+* corrupting it if the same modes were used.
+* They data modes to choose from, these are:
+*
+* 'a' - writes an alternating bit pattern (i.e. 0x5555555...)
+*
+* 'c' - writes a checkerboard pattern (i.e. 0xff00ff00ff00...)
+*
+* 'C' - writes counting pattern (i.e. 0 - 07, 0 - 07, ...);
+*
+* 'o' - writes all bits set (i.e. 0xffffffffffffff...)
+*
+* 'z' - writes all bits cleared (i.e. 0x000000000...);
+*
+* 'r' - writes random integers
+*
+* RETURN VALUE
+* None
+*
+*******************************************************************************/
+
+void databingen( int mode, unsigned char *buffer, int bsize, int offset );
+
+void databinchedk( int mode, unsigned char *buffer, int bsize, int offset, char **errmsg);
+
+#endif
diff --git a/include/file_lock.h b/include/file_lock.h
new file mode 100644
index 0000000..8c9a948
--- /dev/null
+++ b/include/file_lock.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
+ */
+#ifndef _FILE_LOCK_H_
+#define _FILE_LOCK_H_
+
+extern char Fl_syscall_str[128];
+
+int file_lock( int , int, char ** );
+int record_lock( int , int , int , int , char ** );
+
+#endif /* _FILE_LOCK_H_ */
diff --git a/include/forker.h b/include/forker.h
new file mode 100644
index 0000000..eb0acae
--- /dev/null
+++ b/include/forker.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
+ */
+#ifndef _FORKER_H_
+#define _FORKER_H_
+
+#define MAX_PIDS 4098
+
+extern int Forker_pids[MAX_PIDS]; /* holds pids of forked processes */
+extern int Forker_npids; /* number of entries in Forker_pids */
+
+/*
+ * This function will fork and the parent will exit zero and
+ * the child will return. This will orphan the returning process
+ * putting it in the background.
+ */
+int background( char * );
+
+/*
+ * Forker will fork ncopies-1 copies of self.
+ *
+ * arg 1: Number of copies of the process to be running after return.
+ * This value minus one is the number of forks performed.
+ * arg 2: mode: 0 - all children are first generation descendents.
+ * 1 - each subsequent child is a descendent of another
+ * descendent, resulting in only one direct descendent of the
+ * parent and each other child is a child of another child in
+ * relation to the parent.
+ * arg 3: prefix: string to preceed any error messages. A value of NULL
+ * results in no error messages on failure.
+ * returns: returns to parent the number of children forked.
+ */
+int forker( int , int , char * );
+
+#endif /* _FORKER_H_ */
diff --git a/include/mc_getopt.h b/include/mc_getopt.h
new file mode 100644
index 0000000..d574fb5
--- /dev/null
+++ b/include/mc_getopt.h
@@ -0,0 +1,40 @@
+
+/* $Header: /cvsroot/ltp/ltp/include/Attic/mc_getopt.h,v 1.1 2000/07/27 17:13:18 alaffin Exp $ */
+
+/*
+ * (C) COPYRIGHT CRAY RESEARCH, INC.
+ * UNPUBLISHED PROPRIETARY INFORMATION.
+ * ALL RIGHTS RESERVED.
+ */
+
+#ifndef __MC_GETOPT_H__
+#define __MC_GETOPT_H__ 1
+
+/*
+ * Possible return value of mc_getopt
+ */
+
+#define MC_UNKNOWN_OPTION "UNKNOWN_OPTION"
+#define MC_AMBIGUOUS_OPTION "AMBIGUOUS_OPTION"
+#define MC_MISSING_OPTARG "MISSING_OPTARG"
+#define MC_DONE NULL
+
+/*
+ * Mc_getopt flags argument bits
+ */
+#define MC_FULL_TOKEN_MATCH 01
+#define MC_CASE_INSENSITIVE 02
+
+extern int mc_optind;
+extern char *mc_optarg;
+extern char *mc_optopt;
+
+/*
+ * Prototypes
+ */
+
+extern char *mc_getopt(int argc, char * const argv[], int flags, const char *optstring);
+extern char *mc_getoptv(int argc, char * const argv[], int flags, int nopts, char * const opt_arr[]);
+
+#endif /* __MC_GETOPT_H__ */
+
diff --git a/include/pattern.h b/include/pattern.h
new file mode 100644
index 0000000..74f841c
--- /dev/null
+++ b/include/pattern.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
+ */
+#ifndef _PATTERN_H_
+#define _PATTERN_H_
+
+/*
+ * pattern_check(buf, buflen, pat, patlen, patshift)
+ *
+ * Check a buffer of length buflen against repeated occurrances of
+ * a pattern whose length is patlen. Patshift can be used to rotate
+ * the pattern by patshift bytes to the left.
+ *
+ * Patshift may be greater than patlen, the pattern will be rotated by
+ * (patshift % patshift) bytes.
+ *
+ * pattern_check returns -1 if the buffer does not contain repeated
+ * occurrances of the indicated pattern (shifted by patshift).
+ *
+ * The algorithm used to check the buffer relies on the fact that buf is
+ * supposed to be repeated copies of pattern. The basic algorithm is
+ * to validate the first patlen bytes of buf against the pat argument
+ * passed in - then validate the next patlen bytes against the 1st patlen
+ * bytes - the next (2*patlen) bytes against the 1st (2*pathen) bytes, and
+ * so on. This algorithm only works when the assumption of a buffer full
+ * of repeated copies of a pattern holds, and gives MUCH better results
+ * then walking the buffer byte by byte.
+ *
+ * Performance wise, It appears to be about 5% slower than doing a straight
+ * memcmp of 2 buffers, but the big win is that it does not require a
+ * 2nd comparison buffer, only the pattern.
+ */
+int pattern_check( char * , int , char * , int , int );
+
+/*
+ * pattern_fill(buf, buflen, pat, patlen, patshift)
+ *
+ * Fill a buffer of length buflen with repeated occurrances of
+ * a pattern whose length is patlen. Patshift can be used to rotate
+ * the pattern by patshift bytes to the left.
+ *
+ * Patshift may be greater than patlen, the pattern will be rotated by
+ * (patshift % patlen) bytes.
+ *
+ * If buflen is not a multiple of patlen, a partial pattern will be written
+ * in the last part of the buffer. This implies that a buffer which is
+ * shorter than the pattern length will receive only a partial pattern ...
+ *
+ * pattern_fill always returns 0 - no validation of arguments is done.
+ *
+ * The algorithm used to fill the buffer relies on the fact that buf is
+ * supposed to be repeated copies of pattern. The basic algorithm is
+ * to fill the first patlen bytes of buf with the pat argument
+ * passed in - then copy the next patlen bytes with the 1st patlen
+ * bytes - the next (2*patlen) bytes with the 1st (2*pathen) bytes, and
+ * so on. This algorithm only works when the assumption of a buffer full
+ * of repeated copies of a pattern holds, and gives MUCH better results
+ * then filling the buffer 1 byte at a time.
+ */
+int pattern_fill( char * , int , char * , int , int );
+
+#endif
diff --git a/include/rmobj.h b/include/rmobj.h
new file mode 100644
index 0000000..4808ca2
--- /dev/null
+++ b/include/rmobj.h
@@ -0,0 +1,12 @@
+#ifndef _RMOBJ_H_
+#define _RMOBJ_H_
+
+/*
+ * rmobj() - Remove the specified object. If the specified object is a
+ * directory, recursively remove everything inside of it. If
+ * there are any problems, set errmsg (if it is not NULL) and
+ * return -1. Otherwise return 0.
+ */
+int rmobj( char *object , char **errmesg );
+
+#endif
diff --git a/include/test.h b/include/test.h
new file mode 100644
index 0000000..c7872fb
--- /dev/null
+++ b/include/test.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
+ */
+
+/* $Id: test.h,v 1.1 2000/07/27 17:13:18 alaffin Exp $ */
+
+#ifndef __TEST_H__
+#define __TEST_H__
+
+#include <stdio.h>
+#include <signal.h>
+#include <unistd.h>
+
+#define TPASS 0 /* Test passed flag */
+#define TFAIL 1 /* Test failed flag */
+#define TBROK 2 /* Test broken flag */
+#define TWARN 4 /* Test warning flag */
+#define TRETR 8 /* Test retire flag */
+#define TINFO 16 /* Test information flag */
+#define TCONF 32 /* Test not appropriate for configuration flag */
+
+/*
+ * To determine if you are on a Umk or Unicos system,
+ * use sysconf(_SC_CRAY_SYSTEM). But since _SC_CRAY_SYSTEM
+ * is not defined until 90, it will be define here if not already
+ * defined.
+ * if ( sysconf(_SC_CRAY_SYSTEM) == 1 )
+ * on UMK
+ * else # returned 0 or -1
+ * on Unicos
+ * This is only being done on CRAY systems.
+ */
+#ifdef CRAY
+#ifndef _SC_CRAY_SYSTEM
+#define _SC_CRAY_SYSTEM 140
+#endif /* ! _SC_CRAY_SYSTEM */
+#endif /* CRAY */
+
+/*
+ * Ensure that NUMSIGS is defined.
+ * It should be defined in signal.h or sys/signal.h on
+ * UNICOS/mk and IRIX systems. On UNICOS systems,
+ * it is not defined, thus it is being set to UNICOS's NSIG.
+ * Note: IRIX's NSIG (signals are 1-(NSIG-1))
+ * is not same meaning as UNICOS/UMK's NSIG (signals 1-NSIG)
+ */
+#ifndef NUMSIGS
+#define NUMSIGS NSIG
+#endif
+
+
+/* defines for unexpected signal setup routine (set_usig.c) */
+#define FORK 1 /* SIGCLD is to be ignored */
+#define NOFORK 0 /* SIGCLD is to be caught */
+#define DEF_HANDLER 0 /* tells set_usig() to use default signal handler */
+
+/*
+ * The following defines are used to control tst_res and t_result reporting.
+ */
+
+#define TOUTPUT "TOUTPUT" /* The name of the environment variable */
+ /* that can be set to one of the following */
+ /* strings to control tst_res output */
+ /* If not set, TOUT_VERBOSE_S is assumed */
+
+#define TOUT_VERBOSE_S "VERBOSE" /* All test cases reported */
+#define TOUT_CONDENSE_S "CONDENSE" /* ranges are used where identical messages*/
+ /* occur for sequential test cases */
+#define TOUT_NOPASS_S "NOPASS" /* No pass test cases are reported */
+#define TOUT_DISCARD_S "DISCARD" /* No output is reported */
+
+#define TST_NOBUF "TST_NOBUF" /* The name of the environment variable */
+ /* that can be set to control whether or not */
+ /* tst_res will buffer output into 4096 byte */
+ /* blocks of output */
+ /* If not set, buffer is done. If set, no */
+ /* internal buffering will be done in tst_res */
+ /* t_result does not have internal buffering */
+
+/*
+ * The following defines are used to control tst_tmpdir, tst_wildcard and t_mkchdir
+ */
+
+#define TDIRECTORY "TDIRECTORY" /* The name of the environment variable */
+ /* that if is set, the value (directory) */
+ /* is used by all tests as their working */
+ /* directory. tst_rmdir and t_rmdir will */
+ /* not attempt to clean up. */
+ /* This environment variable should only */
+ /* be set when doing system testing since */
+ /* tests will collide and break and fail */
+ /* because of setting it. */
+
+#define TEMPDIR "/tmp" /* This is the default temporary directory. */
+ /* The environment variable TMPDIR is */
+ /* used prior to this valid by tempnam(3). */
+ /* To control the base location of the */
+ /* temporary directory, set the TMPDIR */
+ /* environment variable to desired path */
+
+/*
+ * The following contains support for error message passing.
+ * See test_error.c for details.
+ */
+#define TST_ERR_MESG_SIZE 1023 /* max size of error message */
+#define TST_ERR_FILE_SIZE 511 /* max size of module name used by compiler */
+#define TST_ERR_FUNC_SIZE 127 /* max size of func name */
+
+typedef struct {
+ int te_line; /* line where last error was reported. Use */
+ /* "__LINE__" and let compiler do the rest */
+ int te_level; /* If set, will prevent current stored */
+ /* error to not be overwritten */
+ char te_func[TST_ERR_FUNC_SIZE+1]; /* name of function of last error */
+ /* Name of function or NULL */
+ char te_file[TST_ERR_FILE_SIZE+1]; /* module of last error. Use */
+ /* "__FILE__" and let compiler do the rest */
+ char te_mesg[TST_ERR_MESG_SIZE+1]; /* string of last error */
+
+} _TST_ERROR;
+
+extern _TST_ERROR Tst_error; /* defined in test_error.c */
+#if __STDC__
+extern void tst_set_error(char *file, int line, char *func, char *fmt, ...);
+#else
+extern void tst_set_error();
+#endif
+extern void tst_clear_error();
+
+
+/*
+ * The following define contains the name of an environmental variable
+ * that can be used to specify the number of iterations.
+ * It is supported in parse_opts.c and USC_setup.c.
+ */
+#define USC_ITERATION_ENV "USC_ITERATIONS"
+
+/*
+ * The following define contains the name of an environmental variable
+ * that can be used to specify to iteration until desired time
+ * in floating point seconds has gone by.
+ * Supported in USC_setup.c.
+ */
+#define USC_LOOP_WALLTIME "USC_LOOP_WALLTIME"
+
+/*
+ * The following define contains the name of an environmental variable
+ * that can be used to specify that no functional checks are wanted.
+ * It is supported in parse_opts.c and USC_setup.c.
+ */
+#define USC_NO_FUNC_CHECK "USC_NO_FUNC_CHECK"
+
+/*
+ * The following define contains the name of an environmental variable
+ * that can be used to specify the delay between each loop iteration.
+ * The value is in seconds (fractional numbers are allowed).
+ * It is supported in parse_opts.c.
+ */
+#define USC_LOOP_DELAY "USC_LOOP_DELAY"
+
+
+#ifndef CRAY
+/*
+ * The following prototypes are needed to remove compile errors
+ * on IRIX systems when compiled with -n32 and -64.
+ */
+extern void tst_res(int ttype, char *fname, char *arg_fmt, ...);
+extern void tst_resm(int ttype, char *arg_fmt, ...);
+extern void tst_brk(int ttype, char *fname, void (*func)(),
+ char *arg_fmt, ...);
+extern void tst_brkloop(int ttype, char *fname, void (*func)(),
+ char *arg_fmt, ...);
+extern void tst_brkm(int ttype, void (*func)(), char *arg_fmt, ...);
+extern void tst_brkloopm(int ttype, void (*func)(), char *arg_fmt, ...);
+
+extern int tst_environ();
+extern void tst_exit();
+extern void tst_flush();
+
+/* prototypes for the t_res.c functions */
+extern void t_result(char *tcid, int tnum, int ttype, char *tmesg);
+extern void tt_exit();
+extern int t_environ();
+extern void t_breakum(char *tcid, int total, int typ, char *msg, void (*fnc)());
+
+#endif /* ! CRAY */
+
+#endif /* end of __TEST_H__ */
diff --git a/include/usctest.h b/include/usctest.h
new file mode 100644
index 0000000..1d57920
--- /dev/null
+++ b/include/usctest.h
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
+ */
+
+/* $Id: usctest.h,v 1.1 2000/07/27 17:13:18 alaffin Exp $ */
+
+/**********************************************************
+ *
+ * IRIX/Linux Feature Test and Evaluation - Silicon Graphics, Inc.
+ *
+ * FUNCTION NAME : usctest.h
+ *
+ * FUNCTION TITLE : System Call Test Macros
+ *
+ * SYNOPSIS:
+ * See DESCRIPTION below.
+ *
+ * AUTHOR : William Roske
+ *
+ * INITIAL RELEASE : UNICOS 7.0
+ *
+ * DESCRIPTION
+ * TEST(SCALL) - calls a system call
+ * TEST_VOID(SCALL) - same as TEST() but for syscalls with no return value.
+ * TEST_CLEANUP - print the log of errno return counts if STD_ERRNO_LOG
+ * is set.
+ * TEST_PAUSEF(HAND) - Pause for SIGUSR1 if the pause flag is set.
+ * Use "hand" as the interrupt handling function
+ * TEST_PAUSE - Pause for SIGUSR1 if the pause flag is set.
+ * Use internal function to do nothing on signal and go on.
+ * TEST_LOOPING(COUNTER) - Conditional to check if test should
+ * loop. Evaluates to TRUE (1) or FALSE (0).
+ * TEST_ERROR_LOG(eno) - log that this errno was received,
+ * if STD_ERRNO_LOG is set.
+ * TEST_EXP_ENOS(array) - set the bits in TEST_VALID_ENO array at
+ * positions specified in integer "array"
+ *
+ * RETURN VALUE
+ * TEST(SCALL) - Global Variables set:
+ * int TEST_RETURN=return code from SCALL
+ * int TEST_ERRNO=value of errno at return from SCALL
+ * TEST_VOID(SCALL) - Global Variables set:
+ * int TEST_ERRNO=value of errno at return from SCALL
+ * TEST_CLEANUP - None.
+ * TEST_PAUSEF(HAND) - None.
+ * TEST_PAUSE - None.
+ * TEST_LOOPING(COUNTER) - True if COUNTER < STD_LOOP_COUNT or
+ * STD_INFINITE is set.
+ * TEST_ERROR_LOG(eno) - None
+ * TEST_EXP_ENOS(array) - None
+ *
+ * KNOWN BUGS
+ * If you use the TEST_PAUSE or TEST_LOOPING macros, you must
+ * link in parse_opts.o, which contains the code for those functions.
+ *
+ *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
+
+#ifndef __USCTEST_H__
+#define __USCTEST_H__ 1
+
+#ifndef _SC_CLK_TCK
+#include <unistd.h>
+#endif
+
+#include <sys/param.h>
+
+/*
+ * Ensure that PATH_MAX is defined
+ */
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
+#ifndef CRAY
+#ifndef BSIZE
+#define BSIZE BBSIZE
+#endif
+#endif
+
+/*
+ * Define standard options.
+ * These value should match the values in USC_common.h.
+ */
+
+#define NOFUNC "nofunc" /* no func check flag */
+#define ITERATIONS "iterations:" /* # iterations */
+#define DURATION "duration:" /* walltime floating point */
+#define DELAY "delay:" /* delay each iteration */
+#define TIMING "timing" /* sys call timing flag */
+#define ERRNO_LOGGING "errno_logging" /* errno logging flag */
+#define SETUP_PAUSE "pause_for_sigusr1" /* wait sigusr1 signal in setup */
+#define COPIES "copies:" /* number copies */
+#define USC_HELP "Help" /* basic help */
+
+#define ITERATIONS_HELP \
+" -iterations cnt : Execute test \"cnt\" times (Default is 1).\n\
+ A value of 0 will cause the test to run indefinitely.\n"
+
+#define DELAY_HELP \
+" -delay secs : Delay for \"secs\" seconds each iteration (def 0.0)\n"
+
+#define DURATION_HELP \
+" -duration secs : Iterate for elapsed time of \"secs\" (def 0.0)\n"
+
+#define NOFUNC_HELP \
+" -nofunc : Turn OFF Functional testing. Just exercise the system call.\n"
+
+#define SETUP_PAUSE_HELP \
+" -pause_for_sigusr1 : Pause for SIGUSR1 before entering testing loop.\n"
+
+#define TIMING_HELP \
+" -timing : Turn ON timing statistics (min, max and avg time in system call).\n"
+
+#define ERRNO_LOGGING_HELP \
+" -errno_logging : Turn ON errno logging.\n"
+
+#define COPIES_HELP \
+" -copies num : fork so there num copies (def 1)\n"
+
+#define USC_HELP_HELP \
+" -Help : parse_opts standard help and exit.\n"
+
+/*
+ * Defines used for genating usage
+ */
+#define NOFUNC_USE "[-nofunc]"
+#define ITERATIONS_USE "[-iterations cnt]"
+#define DURATION_USE "[-duration secs]"
+#define DELAY_USE "[-delay secs]"
+#define TIMING_USE "[-timing]"
+#define ERRNO_LOGGING_USE "[-errno_logging]"
+#define SETUP_PAUSE_USE "[-pause_for_sigusr1]"
+#define COPIES_USE "[-copies num]"
+#define HELP_USE "[-Help]"
+
+/***********************************************************************
+ * Define option_t structure type.
+ * Entries in this struct are used by the parse_opts routine
+ * to indicate valid options and return option arguments
+ ***********************************************************************/
+typedef struct {
+ char *option; /* Valid option string (one option only) like "a:" */
+ int *flag; /* pointer to location to set true if option given */
+ char **arg; /* pointer to location to place argument, if needed */
+} option_t;
+
+/***********************************************************************
+ * The following globals are defined in parse_opts.c but must be
+ * externed here because they are used in the macros defined below.
+ ***********************************************************************/
+extern int STD_FUNCTIONAL_TEST, /* turned off by -f to not do functional test */
+ STD_TIMING_ON, /* turned on by -t to print timing stats */
+ STD_PAUSE, /* turned on by -p to pause before loop */
+ STD_INFINITE, /* turned on by -c0 to loop forever */
+ STD_LOOP_COUNT, /* changed by -cn to set loop count to n */
+ STD_ERRNO_LOG, /* turned on by -e to log errnos returned */
+ STD_ERRNO_LIST[], /* counts of errnos returned. indexed by errno */
+ STD_COPIES,
+ STD_argind;
+
+extern float STD_LOOP_DURATION, /* wall clock time to iterate */
+ STD_LOOP_DELAY; /* delay time after each iteration */
+
+#define USC_MAX_ERRNO 2000
+
+/**********************************************************************
+ * Prototype for parse_opts routine
+ **********************************************************************/
+extern char *parse_opts();
+
+/*
+ * define a structure
+ */
+struct usc_errno_t {
+ int flag;
+};
+
+/***********************************************************************
+ ****
+ ****
+ ****
+ **********************************************************************/
+#ifdef _USC_LIB_
+
+extern int TEST_RETURN;
+extern int TEST_ERRNO;
+
+#else
+/***********************************************************************
+ * Global array of bit masks to indicate errnos that are expected.
+ * Bits set by TEST_EXP_ENOS() macro and used by TEST_CLEANUP() macro.
+ ***********************************************************************/
+struct usc_errno_t TEST_VALID_ENO[USC_MAX_ERRNO];
+
+/***********************************************************************
+ * Globals for returning the return code and errno from the system call
+ * test macros.
+ ***********************************************************************/
+int TEST_RETURN;
+int TEST_ERRNO;
+
+/***********************************************************************
+ * temporary variables for determining max and min times in TEST macro
+ ***********************************************************************/
+long btime, etime, tmptime;
+
+#endif /* _USC_LIB_ */
+
+/***********************************************************************
+ * structure for timing accumulator and counters
+ ***********************************************************************/
+struct tblock {
+ long tb_max;
+ long tb_min;
+ long tb_total;
+ long tb_count;
+};
+
+/***********************************************************************
+ * The following globals are externed here so that they are accessable
+ * in the macros that follow.
+ ***********************************************************************/
+extern struct tblock tblock;
+extern void STD_go();
+extern int (*_TMP_FUNC)(void);
+extern char *STD_opts_help();
+extern char *STD_opts();
+
+
+/***********************************************************************
+ * TEST: calls a system call
+ *
+ * parameters:
+ * SCALL = system call and parameters to execute
+ *
+ ***********************************************************************/
+#define TEST(SCALL) TEST_RETURN = (unsigned) SCALL; TEST_ERRNO=errno;
+
+/***********************************************************************
+ * TEST_VOID: calls a system call
+ *
+ * parameters:
+ * SCALL = system call and parameters to execute
+ *
+ * Note: This is IDENTICAL to the TEST() macro except that it is intended
+ * for use with syscalls returning no values (void syscall()). The
+ * Typecasting nothing (void) into an unsigned integer causes compilation
+ * errors.
+ *
+ ***********************************************************************/
+#define TEST_VOID(SCALL) SCALL; TEST_ERRNO=errno;
+
+/***********************************************************************
+ * TEST_CLEANUP: print system call timing stats and errno log entries
+ * to stdout if STD_TIMING_ON and STD_ERRNO_LOG are set, respectively.
+ * Do NOT print ANY information if no system calls logged.
+ *
+ * parameters:
+ * none
+ *
+ ***********************************************************************/
+#define TEST_CLEANUP \
+if ( STD_ERRNO_LOG ) { \
+ for (tmptime=0; tmptime<USC_MAX_ERRNO; tmptime++) { \
+ if ( STD_ERRNO_LIST[tmptime] ) { \
+ if ( TEST_VALID_ENO[tmptime].flag ) \
+ tst_resm(TINFO, "ERRNO %d:\tReceived %d Times", \
+ tmptime, STD_ERRNO_LIST[tmptime]); \
+ else \
+ tst_resm(TINFO, \
+ "ERRNO %d:\tReceived %d Times ** UNEXPECTED **", \
+ tmptime, STD_ERRNO_LIST[tmptime]); \
+ } \
+ } \
+}
+
+/***********************************************************************
+ * TEST_PAUSEF: Pause for SIGUSR1 if the pause flag is set.
+ * Set the user specified function as the interrupt
+ * handler instead of "STD_go"
+ *
+ * parameters:
+ * none
+ *
+ ***********************************************************************/
+#define TEST_PAUSEF(HANDLER) \
+if ( STD_PAUSE ) { \
+ _TMP_FUNC = (int (*)())signal(SIGUSR1, HANDLER); \
+ pause(); \
+ signal(SIGUSR1, (void (*)())_TMP_FUNC); \
+}
+
+/***********************************************************************
+ * TEST_PAUSE: Pause for SIGUSR1 if the pause flag is set.
+ * Just continue when signal comes in.
+ *
+ * parameters:
+ * none
+ *
+ ***********************************************************************/
+#define TEST_PAUSE usc_global_setup_hook();
+
+/***********************************************************************
+ * TEST_LOOPING now call the usc_test_looping function.
+ * The function will return 1 if the test should continue
+ * iterating.
+ *
+ ***********************************************************************/
+#define TEST_LOOPING usc_test_looping
+
+/***********************************************************************
+ * TEST_ERROR_LOG(eno): log this errno if STD_ERRNO_LOG flag set
+ *
+ * parameters:
+ * int eno: the errno location in STD_ERRNO_LIST to log.
+ *
+ ***********************************************************************/
+#define TEST_ERROR_LOG(eno) \
+ if ( STD_ERRNO_LOG ) \
+ if ( eno < USC_MAX_ERRNO ) \
+ STD_ERRNO_LIST[eno]++; \
+
+
+/***********************************************************************
+ * TEST_EXP_ENOS(array): set the bits associated with the nput errnos
+ * in the TEST_VALID_ENO array.
+ *
+ * parameters:
+ * int array[]: a zero terminated array of errnos expected.
+ *
+ ***********************************************************************/
+#define TEST_EXP_ENOS(array) \
+ tmptime=0; \
+ while (array[tmptime] != 0) { \
+ if (array[tmptime] < USC_MAX_ERRNO) \
+ TEST_VALID_ENO[array[tmptime]].flag=1; \
+ tmptime++; \
+ }
+
+
+#endif /* end of __USCTEST_H__ */
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 0000000..5cda105
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,12 @@
+
+CFLAGS+= -I../include
+LDFLAGS+=
+TARGET=libltp.a
+SRCS=$(wildcard *.c)
+OBJS=$(patsubst %.c,%.o,$(SRCS))
+
+$(TARGET): $(OBJS)
+ $(AR) -cr $@ $^
+
+clean:
+ rm -f $(TARGET) $(OBJS)
diff --git a/lib/databin.c b/lib/databin.c
index d11aa68..f09c2c8 100644
--- a/lib/databin.c
+++ b/lib/databin.c
@@ -33,6 +33,7 @@
#include <sys/param.h>
#include <string.h> /* memset */
#include <stdlib.h> /* rand */
+#include "databin.h"
#if UNIT_TEST
#include <malloc.h>
@@ -40,42 +41,6 @@
static char Errmsg[80];
-/*******************************************************************************
-* NAME
-* databingen - fill a buffer with a data pattern
-*
-* SYNOPSIS
-* (void) databingen(mode, buffer, bsize, offset)
-* int mode;
-* char *buffer;
-* int bsize;
-* int offset;
-*
-* DESCRIPTION
-* datagen fills the buffer pointed to by 'buffer' with 'bsize' bytes
-* of data of the form indicated by 'mode'.
-* All modes (expect r -random) are file offset based.
-* This allows more than process to do writing to the file without
-* corrupting it if the same modes were used.
-* They data modes to choose from, these are:
-*
-* 'a' - writes an alternating bit pattern (i.e. 0x5555555...)
-*
-* 'c' - writes a checkerboard pattern (i.e. 0xff00ff00ff00...)
-*
-* 'C' - writes counting pattern (i.e. 0 - 07, 0 - 07, ...);
-*
-* 'o' - writes all bits set (i.e. 0xffffffffffffff...)
-*
-* 'z' - writes all bits cleared (i.e. 0x000000000...);
-*
-* 'r' - writes random integers
-*
-* RETURN VALUE
-* None
-*
-*******************************************************************************/
-
void
databingen (mode, buffer, bsize, offset)
int mode; /* either a, c, r, o, z or C */
diff --git a/lib/file_lock.c b/lib/file_lock.c
index 00eb582..a67cdc3 100644
--- a/lib/file_lock.c
+++ b/lib/file_lock.c
@@ -39,6 +39,7 @@
#include <errno.h>
#include <sys/sysmacros.h>
#include <string.h> /* memset, strerror */
+#include "file_lock.h"
extern int errno;
diff --git a/lib/forker.c b/lib/forker.c
index cc849a2..e1e6b74 100644
--- a/lib/forker.c
+++ b/lib/forker.c
@@ -31,7 +31,7 @@
*/
/**************************************************************
*
- * OS Testing - Cray Research, Inc.
+ * OS Testing - Silicon Graphics, Inc.
*
* FUNCTION NAME : forker
* background
@@ -114,19 +114,18 @@
#include <errno.h>
#include <unistd.h> /* fork, getpid, sleep */
#include <string.h>
+#include "forker.h"
extern int errno;
-#define MAX_PIDS 4098
-
-int Forker_pids[MAX_PIDS]; /* holds pids of forked processes */
-int Forker_npids=0; /* number of entries in Forker_pids */
+int Forker_pids[MAX_PIDS]; /* holds pids of forked processes */
+int Forker_npids=0; /* number of entries in Forker_pids */
/***********************************************************************
*
* This function will fork and the parent will exit zero and
* the child will return. This will orphan the returning process
- * putting you in the background.
+ * putting it in the background.
*
* Return Value
* 0 : if fork did not fail
diff --git a/lib/mc_getopt.c b/lib/mc_getopt.c
new file mode 100644
index 0000000..07a9b9f
--- /dev/null
+++ b/lib/mc_getopt.c
@@ -0,0 +1,601 @@
+/* $Header: /cvsroot/ltp/ltp/lib/Attic/mc_getopt.c,v 1.1 2000/07/27 17:13:18 alaffin Exp $ */
+
+/*
+ * (C) COPYRIGHT CRAY RESEARCH, INC.
+ * UNPUBLISHED PROPRIETARY INFORMATION.
+ * ALL RIGHTS RESERVED.
+ */
+/**********************************************************
+ *
+ * OS Testing - Cray Research, Inc.
+ *
+ * FUNCTION NAME : mc_getopt and mc_getoptv
+ *
+ * FUNCTION TITLE : multiple character option parsing like getopt(3)
+ *
+ * SYNOPSIS:
+ * char *
+ * mc_getopt(argc, argv, flags, optstring)
+ * int argc;
+ * char *argv[];
+ * int flags;
+ * char *optstring;
+ *
+ * mc_getoptv(argc, argv, flags, nopts, opt_arr)
+ * int argc;
+ * char *argv[];
+ * int flags;
+ * int nopts;
+ * char *opt_arr[];
+ *
+ * extern int mc_optind;
+ * extern char *mc_optarg;
+ * extern char *mc_optopt;
+ *
+ *
+ * AUTHOR : Richard Logan
+ *
+ * DATE : 01/96
+ *
+ * DESCRIPTION
+ *
+ * The mc_getopt() and mc_getoptv() functions are command line parsers.
+ * The argc parameter specifies the argument count and the argv parameter
+ * specifies the argument array. The optstring argument contains a string
+ * of recognized option strings; if an option string is followed by a
+ * colon, the option takes an argument. Options are whitespace seperated.
+ * A option string can be a single character or a word.
+ *
+ * The opt_arr array contains nopts elements. Each option element in
+ * opt_arr must be NULL terminated string; if an option string is followed
+ * by a colon, the option takes an argument. A option string can be a
+ * single character or a word. opt_arr must be at least nopts elements
+ * in size.
+ *
+ * The variable mc_optind specifies the index of the next element of the
+ * argv parameter to be processed. It is initialized to 1, and the
+ * mc_getopt() function updates it as each element of argv is processed.
+ *
+ * The mc_getopt() function returns the optstring string that
+ * uniquely matches the next element of the argv parameter.
+ * If the option string takes an argument, the mc_getopt()
+ * function sets the mc_optarg variable to point to the option string
+ * argument according to the following rules:
+ *
+ * o If the argv's option was the last option string in the string,
+ * mc_optarg contains
+ * the next element of the argv array, and the mc_optind variable is
+ * incremented by 2. If the resulting value of mc_optind is greater than
+ * or equal to argc, the mc_getopt() function returns an MC_MISSING_OPTARG
+ *
+ * o Otherwise, mc_optarg points to the string following the option
+ * character in that element of the argv parameter, and the mc_optind
+ * variable is incremented by 1.
+ *
+ * If any of the following conditions are true when the mc_getopt()
+ * function is called, the mc_getopt() function returns MC_DONE without
+ * changing the mc_optind variable:
+ *
+ * o argv[mc_optind] is a null pointer
+ *
+ * o *argv[mc_optind] is not the character '-'
+ *
+ * o argv[mc_optind] points to the string "-"
+ *
+ * If the argv[mc_optind] parameter points to the "--" string, the mc_getopt
+ * function returns MC_DONE after incrementing the mc_optind variable.
+ *
+ * The flags argument can be used to change how an argv option string
+ * is compared to optstring. The flags argument is a bitmask.
+ * The only two bits defined thus far are:
+ *
+ * o MC_FULL_TOKEN_MATCH
+ * o MC_CASE_INSENSITIVE
+ *
+ * How flags bits can be used to affect mc_getopt()'s actions:
+ *
+ * o Without the MC_FULL_TOKEN_MATCH bit set, if the argv string exactly
+ * matches one optstring option, that option will be returned.
+ * Otherwise, if the argv string matches the beginning of only one
+ * optstring option, that optstring option is returned.
+ *
+ * o With the MC_FULL_TOKEN_MATCH bit set, the argv string must exactly
+ * match the optstring, excluding the colon ":". When word options are
+ * being used, the exact word option string must be in argv to be
+ * reconized as a match.
+ *
+ * o Without the MC_CASE_INSENSITIVE bit set, case comparisons are used.
+ * The -I option is different than the -i option.
+ *
+ * o With the MC_CASE_INSENSITIVE bit set, all strings are converted to
+ * lower case before comparisons are made. This means the -I and -i
+ * option are the same. The returned option string will be all lowercase.
+ * The mc_getoptv() function assumes the option string in the opt_arr
+ * is already converted to lowercase.
+ *
+ * If the mc_getopt(v) function encounters an option string that is not
+ * contained in the optstring parameter, it returns MC_UNKNOWN_OPTION
+ * string. If it detects a missing option argument, it returns
+ * MC_MISSING_OPTARG string. Unlike getopt, mc_getopt() will NOT print
+ * message if an argv option string is not found in optstring.
+ *
+ * If the argv option string matches more than one optstring strings,
+ * MC_AMBIGUOUS_OPTION string is returned.
+ *
+ * mc_getopt(v) will not modify argv or optstring. It will strdup optstring
+ * and update some character pointers. The optstring is parsed only
+ * once whenever a mc_optind is set to one or once a MC_DONE was returned.
+ * The strdup space is freed before a MC_DONE is returned. This means that
+ * optstring is ignored on all subquent calls.
+ *
+ *
+ * RETURN VALUES
+ * The mc_getopt(v) function returns the next option string specified on
+ * the command line. The string will be the string as listed in optstring.
+ *
+ * MC_MISSING_OPTARG is returned if the mc_getopt(v) function detects a
+ * missing argument.
+ *
+ * MC_UNKNOWN_OPTION is returned if the mc_getopt(v) function encounters an
+ * option string not in the optstring argument.
+ *
+ * MC_AMBIGUOUS_OPTION is returned if the mc_getopt(v) function encounters
+ * option string that matches two or more optstring argument and there
+ * is not a single exact match. This condition could occur if
+ * flags argument does not have the MC_FULL_TOKEN_MATCH bit set and
+ * the option string is not a unique string as defined in optstring.
+ * (i.e. -it, when optsting contains " iterations: italic") It
+ * could also occur if an optstring option is duplicated
+ * (i.e. -iterations, when optsting contains " iterations: iterations").
+ *
+ * Otherwise, the mc_getopt(v) function returns MC_DONE when all command
+ * line options are parsed.
+ *
+ * LIMITATIONS
+ * mc_getopt() has an internal limit of 256 options
+ * allowed in optstring.
+ *
+ *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/param.h>
+
+#include "mc_getopt.h"
+
+#ifndef DEBUG
+#define DEBUG 0 /* used for debugging */
+#endif
+
+/*
+ * Externally accessable variables.
+ */
+int mc_optind = 1; /* index to next argv token */
+char *mc_optarg; /* pointer to option argument string */
+
+char *mc_optopt; /* pointer to argv or opt_arg option string */
+
+/*
+ * Ensure PATH_MAX is defined.
+ */
+#ifndef PATH_MAX
+#define PATH_MAX 1023
+#endif
+
+/*
+ * Define the max number of option strings that can exist in optstring.
+ */
+#define MAX_OPTIONS 256
+
+/*******************************************************************************
+ *
+ *******************************************************************************/
+#if __STDC__
+char *
+mc_getopt(int argc, char * const argv[], int flags, const char *optstring)
+#else
+char *
+mc_getopt(argc, argv, flags, optstring)
+int argc;
+char * const argv[];
+int flags;
+const char *optstring;
+#endif /* __STDC__ */
+{
+
+ static char *opt_arr[MAX_OPTIONS]; /* array of pointers to option strings */
+
+ static char *optstr=NULL; /* strdup'ed optstring, ! NULL, means */
+ /* space allocated */
+ static int nopts; /* number of opt_arr elements */
+
+ char *token; /* used in optstring parsing and string comparision */
+ char *cc; /* used in optstring parsing and converting to lower case */
+ int optarr_ind=0; /* index into opt_arr */
+
+
+#if DEBUG > 0
+printf(" Entering mc_getopt, argc = %d, mc_optind = %d, flags = %#o, optstring = '%s'\n",
+ argc, mc_optind, flags, optstring);
+#endif
+
+ if ( mc_optind >= argc || argv[mc_optind] == NULL ||
+ argv[mc_optind][0] != '-' || argv[mc_optind][1] == '\0' ) {
+
+#if DEBUG > 1
+printf(" no more options to process\n");
+#endif
+ if ( optstr != NULL )
+ free(optstr);
+ return MC_DONE;
+
+ } else if ( strcmp(argv[mc_optind], "--") == 0 ) {
+#if DEBUG > 1
+printf(" option --, no more options to process\n");
+#endif
+ mc_optind++;
+ if ( optstr != NULL )
+ free(optstr);
+ return MC_DONE; /* we are done */
+ }
+
+ /*
+ * We have new argv - reset info for optstr.
+ * Otherwise old optstr is used.
+ */
+ if ( optstr == NULL || mc_optind == 1 ) {
+
+ /*
+ * copy string so that we don't modify user given string
+ */
+ if ( optstr != NULL )
+ free(optstr); /* free old strdup'ed space */
+
+ optstr=strdup(optstring); /* copy string */
+ nopts=0;
+ optarr_ind=0;
+
+ token=optstr;
+ /*
+ * walk through optstr option string (whitespace separated).
+ */
+ for (;;) {
+
+ /* skip preceeding separator chars */
+ for (; *token && isspace(*token); token++);
+
+ if ( ! *token ) /* no more tokens */
+ break;
+
+ cc = token; /* start of option string */
+
+ /*
+ * find first separator character after token
+ */
+ for (; *cc && !isspace(*cc); cc++) {
+ /*
+ * If doing case insensitive comparisons, make all
+ * optstr characters lowercase.
+ */
+ if ( flags & MC_CASE_INSENSITIVE && isupper(*cc) )
+ *cc = tolower(*cc);
+ }
+
+ opt_arr[optarr_ind++] = token;
+
+ if ( ! *cc) /* no more tokens */
+ break;
+
+ *cc = '\0'; /* null terminate */
+
+ token = ++cc;
+
+ } /* end of for loop */
+
+ nopts=optarr_ind;
+#if DEBUG > 1
+ printf("nopts = %d\n", nopts);
+
+ for(optarr_ind=0; optarr_ind<nopts; optarr_ind++)
+ printf(" optstring option (index %2d) : %14s\n",
+ optarr_ind, opt_arr[optarr_ind]);
+#endif
+ } /* end of processs optstring */
+
+ /*
+ * Call mc_getoptv with the optstring in opt_arr array format
+ */
+
+ cc=mc_getoptv(argc, argv, flags, nopts, opt_arr);
+
+ if ( optstr != NULL && strcmp(cc, MC_DONE) == 0 )
+ free(optstr);
+
+ return cc;
+}
+
+/***********************************************************************
+ *
+ ***********************************************************************/
+#if __STDC__
+char *
+mc_getoptv(int argc, char * const argv[], int flags, int nopts,
+ char * const opt_arr[])
+#else
+char *
+mc_getoptv(argc, argv, flags, nopts, opt_arr)
+int argc;
+char * const argv[];
+int flags;
+int nopts;
+char * const opt_arr[];
+#endif /* __STDC__ */
+{
+ char *token; /* used in string comparision */
+ char *cc; /* used in converting to lower case */
+ char *cptr;
+ int optarr_ind=0; /* index into opt_arr */
+
+ int found; /* count of argv option partical matches to optstr options */
+ int exact; /* count of argv option exact matches */
+ int cnt; /* counter */
+ int ind; /* index into opt_arr for matched option */
+ int reqarg; /* if opt_arr[ind] requires an arg */
+
+#if DEBUG > 1
+printf(" In mc_getoptv: argv[%d] = %s\n", mc_optind, argv[mc_optind]);
+#endif
+
+ if ( mc_optind >= argc || argv[mc_optind] == NULL ||
+ argv[mc_optind][0] != '-' || argv[mc_optind][1] == '\0' ) {
+
+#if DEBUG > 1
+printf(" no more options to process\n");
+#endif
+ return MC_DONE;
+
+ } else if ( strcmp(argv[mc_optind], "--") == 0 ) {
+#if DEBUG > 1
+printf(" option --, no more options to process\n");
+#endif
+ mc_optind++;
+ return MC_DONE; /* we are done */
+ }
+
+ if ( flags & MC_CASE_INSENSITIVE ) {
+ mc_optopt = &argv[mc_optind][1];
+
+ /*
+ * If doing case insensitive comparison,
+ * copy argv token and make it all lowercase.
+ */
+ cc = token = strdup(&argv[mc_optind++][1]);
+ for( ; *cc; cc++)
+ if ( isupper(*cc) )
+ *cc = tolower(*cc);
+
+ } else {
+ token = &argv[mc_optind++][1];
+ mc_optopt = token;
+ }
+
+ found=0;
+ exact=0;
+ reqarg=0;
+
+ /*
+ * Compare token to each option string.
+ * Do not stop once a match is found. There maybe multiple matches.
+ */
+ for(optarr_ind=0; optarr_ind<nopts; optarr_ind++) {
+
+ /*
+ * compare opt_arr[optarr_ind] to token
+ * character by character.
+ */
+
+ cc=token;
+ cptr=opt_arr[optarr_ind];
+ cnt=0; /* count of match characters */
+
+ while ( *cc && *cptr && *cc++ == *cptr++ ) {
+ cnt++;
+ }
+
+ /*
+ * Determine if argv option partially matched opstring option.
+ */
+ if ( cnt && *cc == '\0' ) {
+ /*
+ * Determine if argv option fully matched opstring option.
+ * Remember that opt_arr[optarr_ind] can have optional ":".
+ */
+ if ( *cptr == ':' || *cptr == '\0' ) {
+ exact++;
+ found++;
+ ind=optarr_ind;
+ if ( *cptr == ':' ) {
+ reqarg=1;
+ } else {
+ reqarg=0;
+ }
+
+ /*
+ * If not doing full token matches, count this partial match.
+ */
+ } else if ( ! (flags & MC_FULL_TOKEN_MATCH) ) {
+ found++;
+ if ( ! exact ) { /* exact matches are used over partial */
+ ind=optarr_ind;
+
+ /*
+ * Determine if this option string ends with ":",
+ * requiring an argument.
+ * Find the end of the string first, this
+ * would allow a colon in the string.
+ */
+ while ( *cptr )
+ cptr++;
+
+ if ( *(cptr-1) == ':' ) {
+ reqarg=1;
+ } else {
+ reqarg=0;
+ }
+ }
+ }
+ } /* end partial match */
+ } /* end option loop */
+
+#if DEBUG > 2
+printf("optarr_ind = %d, ind = %d, found = %d, exact = %d\n",
+ optarr_ind, ind, found, exact);
+#endif
+
+ /* if doing case insensitive comparison, free space */
+ if ( flags & MC_CASE_INSENSITIVE ) {
+ free(token);
+ }
+
+ if ( found == 0 ) {
+#if DEBUG > 1
+printf("argv option string not found in optstr returning MC_UNKNOWN_OPTION :%s\n",
+MC_UNKNOWN_OPTION);
+#endif
+ /* argv option string not found in optstr */
+ return MC_UNKNOWN_OPTION;
+
+ } else if ( exact == 1 || found == 1 ) {
+ /* option is uniquely matched */
+#if DEBUG > 1
+printf("argv option found a string match\n");
+#endif
+
+
+ if ( reqarg ) { /* option requires argument */
+
+ /* If option argument is missing, return MC_MISSING_OPTARG */
+ if ( mc_optind >= argc ) {
+#if DEBUG > 2
+printf("returning MC_MISSING_OPTARG: %s\n", MC_MISSING_OPTARG);
+#endif
+ return MC_MISSING_OPTARG;
+ }
+
+ mc_optarg = argv[mc_optind++];
+
+ }
+
+#if DEBUG > 2
+printf("returning the option (index %d) %s\n", ind, opt_arr[ind]);
+#endif
+ /* return the full mc_getopt option string */
+ return opt_arr[ind];
+
+ } else {
+
+ /*
+ * This condition will be encountered if
+ * argv option string matches more than optstr option string.
+ * The user could not have entered a unique option string or
+ * the optstr has a duplicate option entered.
+ */
+#if DEBUG > 1
+printf("argv option string not unique\n");
+#endif
+ return MC_AMBIGUOUS_OPTION;
+ }
+}
+
+
+
+#ifdef UNIT_TEST
+
+/****
+ **** The following code is provided as a basic unit test.
+ **** Compile this code with UNIT_TEST set and a executable
+ **** command will be generated. The optstring is hardcoded,
+ **** but the programs argc and argv are given to mc_getopt.
+ ****/
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+
+#define OPTSTR1 " iterate: Testpause I: i "
+ extern int mc_optind;
+ extern char *mc_optarg;
+
+ char *ret;
+ int ind=0;
+
+ mc_optind=1;
+ mc_optarg=NULL;
+ printf("*********** flags = 0, optstr = %s\n", OPTSTR1);
+ while ( (ret=mc_getopt(argc, argv, 0, OPTSTR1)) != MC_DONE ) {
+ if ( mc_optarg != NULL )
+ printf("mc_getopt returned %16s, mc_optopt = %8s, mc_optind = %d, mc_optarg = %s\n",
+ ret, mc_optopt, mc_optind, mc_optarg);
+ else
+ printf("mc_getopt returned %16s, mc_optopt = %8s, mc_optind = %d, mc_optarg = NULL\n",
+ ret, mc_optopt, mc_optind);
+ ind++;
+ mc_optarg=NULL;
+ }
+ if ( mc_optind < argc )
+ printf("mc_getopt is done, mc_optind = %d (argv[%d] = %s)\n",
+ mc_optind, mc_optind, argv[mc_optind]);
+ else
+ printf("mc_getopt is done, mc_optind = %d (no arguments)\n", mc_optind);
+
+ printf("******************************************************\n");
+
+
+ mc_optind=1;
+ mc_optarg=NULL;
+ printf("*********** flags = MC_FULL_TOKEN_MATCH, optstr = %s\n", OPTSTR1);
+ while ( (ret=mc_getopt(argc, argv, MC_FULL_TOKEN_MATCH, OPTSTR1)) != MC_DONE ) {
+ if ( mc_optarg != NULL )
+ printf("mc_getopt returned %16s, mc_optopt = %8s, mc_optind = %d, mc_optarg = %s\n",
+ ret, mc_optopt, mc_optind, mc_optarg);
+ else
+ printf("mc_getopt returned %16s, mc_optopt = %8s, mc_optind = %d, mc_optarg = NULL\n",
+ ret, mc_optopt, mc_optind);
+ mc_optarg=NULL;
+ }
+ if ( mc_optind < argc )
+ printf("mc_getopt is done, mc_optind = %d (argv[%d] = %s)\n",
+ mc_optind, mc_optind, argv[mc_optind]);
+ else
+ printf("mc_getopt is done, mc_optind = %d (no arguments)\n", mc_optind);
+
+ mc_optind=1;
+ mc_optarg=NULL;
+ printf("*********** flags = MC_CASE_INSENSITIVE, optstr = %s\n", OPTSTR1);
+ while ( (ret=mc_getopt(argc, argv, MC_CASE_INSENSITIVE, OPTSTR1)) != MC_DONE ) {
+ if ( mc_optarg != NULL )
+ printf("mc_getopt returned %16s, mc_optopt = %8s, mc_optind = %d, mc_optarg = %s\n",
+ ret, mc_optopt, mc_optind, mc_optarg);
+ else
+ printf("mc_getopt returned %16s, mc_optopt = %8s, mc_optind = %d, mc_optarg = NULL\n",
+ ret, mc_optopt, mc_optind);
+ mc_optarg=NULL;
+ }
+ if ( mc_optind < argc )
+ printf("mc_getopt is done, mc_optind = %d (argv[%d] = %s)\n",
+ mc_optind, mc_optind, argv[mc_optind]);
+ else
+ printf("mc_getopt is done, mc_optind = %d (no arguments)\n", mc_optind);
+
+ return 0;
+}
+
+/**
+Use the following unit test cmd line arguments:
+ -i -itera -4 -I -5 -i -IteRate -6 arg
+
+ ***/
+
+#endif /* UNIT_TEST */
diff --git a/lib/open_flags.c b/lib/open_flags.c
index 0fa76e9..eed39ee 100644
--- a/lib/open_flags.c
+++ b/lib/open_flags.c
@@ -31,7 +31,7 @@
*/
/**************************************************************
*
- * OS Testing - Cray Research, Inc.
+ * OS Testing - Silicon Graphics, Inc.
*
* FUNCTION NAME : parse_open_flags
* openflags2symbols
diff --git a/lib/parse_opts.c b/lib/parse_opts.c
new file mode 100644
index 0000000..af5e6dd
--- /dev/null
+++ b/lib/parse_opts.c
@@ -0,0 +1,1206 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
+ */
+
+/* $Id: parse_opts.c,v 1.1 2000/07/27 17:13:18 alaffin Exp $ */
+
+/**********************************************************
+ *
+ * OS Testing - Silicon Graphics, Inc.
+ *
+ * FUNCTION NAME : parse_opts
+ *
+ * FUNCTION TITLE : parse standard & user options for system call tests
+ *
+ * SYNOPSIS:
+ * #include "usctest.h"
+ *
+ * char *parse_opts(ac, av, user_optarr)
+ * int ac;
+ * char **av;
+ * option_t user_optarr[];
+ *
+ * AUTHOR : William Roske/Richard Logan
+ *
+ * INITIAL RELEASE : UNICOS 7.0
+ *
+ * DESCRIPTION
+ * The parse_opts library routine takes that argc and argv parameters
+ * recevied by main() and an array of structures defining user options.
+ * It parses the command line setting flag and argument locations
+ * associated with the options. It uses mc_getoptv to do the actual
+ * cmd line parsing.
+ *
+ * This module contains the functions usc_global_setup_hook and
+ * usc_test_looping, which are called by marcos defined in usctest.h.
+ *
+ * RETURN VALUE
+ * parse_opts returns a pointer to an error message if an error occurs.
+ * This pointer is (char *)NULL if parsing is successful.
+ *
+ *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/signal.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+
+#ifdef _CRAYMPP
+#include <mpp/shmem.h>
+#endif /* _CRAYMPP */
+
+#if UNIT_TEST
+#include <time.h>
+#endif /* UNIT_TEST */
+
+#include "test.h"
+#define _USC_LIB_ 1 /* indicates we are the library to the usctest.h include */
+#include "usctest.h"
+#include "mc_getopt.h"
+
+#ifndef USC_COPIES
+#define USC_COPIES "USC_COPIES"
+#endif
+
+#ifndef UNIT_TEST
+#define UNIT_TEST 0
+#endif
+
+#ifndef DEBUG
+#define DEBUG 0
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+extern int errno;
+
+/* The timing information block. */
+struct tblock tblock={0,((long) -1)>>1,0,0};
+
+/* temp variable to store old signal action to be restored after pause */
+int (*_TMP_FUNC)(void);
+
+/* Define flags and args for standard options */
+int STD_FUNCTIONAL_TEST=1, /* flag indicating to do functional testing code */
+ STD_TIMING_ON=0, /* flag indicating to print timing stats */
+ STD_PAUSE=0, /* flag indicating to pause before actual start, */
+ /* for contention mode */
+ STD_INFINITE=0, /* flag indciating to loop forever */
+ STD_LOOP_COUNT=1, /* number of iterations */
+ STD_COPIES=1, /* number of copies */
+ STD_ERRNO_LOG=0; /* flag indicating to do errno logging */
+
+float STD_LOOP_DURATION=0.0, /* duration value in fractional seconds */
+ STD_LOOP_DELAY=0.0; /* loop delay value in fractional seconds */
+
+
+char **STD_opt_arr = NULL; /* array of option strings */
+int STD_nopts=0, /* number of elements in STD_opt_arr */
+ STD_argind=1; /* argv index to next argv element */
+ /* (first argument) */
+ /* To getopt users, it is like optind */
+
+/*
+ * The following variables are to support system testing additions.
+ */
+static int STD_TP_barrier=0; /* flag to do barrier in TEST_PAUSE */
+ /* 2 - wait_barrier(), 3 - set_barrier(), * - barrier() */
+static int STD_LP_barrier=0; /* flag to do barrier in TEST_LOOPING */
+ /* 2 - wait_barrier(), 3 - set_barrier(), * - barrier() */
+static int STD_TP_shmem_sz=0; /* shmalloc this many words per pe in TEST_PAUSE */
+static int STD_LD_shmem=0; /* flag to do shmem_puts and shmem_gets during delay */
+static int STD_LP_shmem=0; /* flag to do shmem_puts and gets during TEST_LOOPING */
+static int STD_LD_recfun=0; /* do recressive function calls in loop delay */
+static int STD_LP_recfun=0; /* do recressive function calls in TEST_LOOPING */
+static int STD_TP_sbrk=0; /* do sbrk in TEST_PAUSE */
+static int STD_LP_sbrk=0; /* do sbrk in TEST_LOOPING */
+static char *STD_start_break=0; /* original sbrk size */
+#ifdef _CRAYMPP
+static long *STD_shmem=NULL; /* array of shmalloc space */
+static int MyPE=-1, Npe=-1; /* */
+#endif
+static int Debug=0;
+
+/*
+ * Structure for usc_recressive_func argument
+ */
+struct usc_bigstack_t {
+ char space[4096];
+};
+
+static struct usc_bigstack_t *STD_bigstack=NULL;
+
+static int add_option(char *option, char **opt_arr[], int *nopts);
+static int rm_option(char *option, char **opt_arr[], int *nopts);
+
+
+/*
+ * Counter of errnos returned (-e option). Indexed by errno.
+ * Make the array USC_MAX_ERRNO long. That is the first Fortran
+ * Lib errno. No syscall should return an errno that high.
+ */
+int STD_ERRNO_LIST[USC_MAX_ERRNO];
+
+/* define the string length for Mesg and Mesg2 strings */
+#define STRLEN 2048
+
+static char Mesg[STRLEN]; /* holds possible return string */
+static char Mesg2[STRLEN]; /* holds possible return string */
+static void usc_recressive_func();
+
+/*
+ * Define bits for options that might have env variable default
+ */
+#define OPT_iteration 01
+#define OPT_nofunccheck 02
+#define OPT_duration 04
+#define OPT_delay 010
+#define OPT_copies 020
+
+
+/**********************************************************************
+ * parse_opts:
+ **********************************************************************/
+char *
+parse_opts(int ac, char **av, option_t *user_optarr)
+{
+ int found; /* flag to indicate that an option specified was */
+ /* found in the user's list */
+ char chr; /* used in converting option arguments */
+ int k; /* scratch integer for returns and short time usage */
+ float ftmp; /* tmp float for parsing env variables */
+ char *ptr; /* used in getting env variables */
+ int options=0; /* no options specified */
+ int ind; /* index */
+ int cnt; /* counter */
+ int num; /* size of a string */
+ char *opt; /* return of mc_getoptv */
+
+ /*
+ * If not the first time this function is called, release the old STD_opt_arr
+ * vector.
+ */
+
+ if ( STD_opt_arr != NULL ) {
+ free(STD_opt_arr);
+ STD_opt_arr=NULL;
+ }
+
+ /*
+ * Define standard options known to the parse_opts package.
+ * Each option is added to the end of the STD_opt_arr array.
+ */
+ if ( add_option(ITERATIONS, &STD_opt_arr, &STD_nopts) == -1)
+ return Mesg2;
+ if ( add_option(DELAY, &STD_opt_arr, &STD_nopts) == -1 )
+ return Mesg2;
+ if ( add_option(DURATION, &STD_opt_arr, &STD_nopts) == -1 )
+ return Mesg2;
+ if ( add_option(NOFUNC, &STD_opt_arr, &STD_nopts) == -1 )
+ return Mesg2;
+ if ( add_option(SETUP_PAUSE, &STD_opt_arr, &STD_nopts) == -1 )
+ return Mesg2;
+ if ( add_option(COPIES, &STD_opt_arr, &STD_nopts) == -1 )
+ return Mesg2;
+ if ( add_option(USC_HELP, &STD_opt_arr, &STD_nopts) == -1 )
+ return Mesg2;
+ if ( add_option(TIMING, &STD_opt_arr, &STD_nopts) == -1 )
+ return Mesg2;
+ if ( add_option(ERRNO_LOGGING, &STD_opt_arr, &STD_nopts) == -1 )
+ return Mesg2;
+
+ /* validate input array of options and build STD_opt_arr */
+
+ if ( user_optarr != (option_t *) NULL ) {
+ for(cnt=0; user_optarr[cnt].option != (char *) NULL; cnt++ ) {
+ /*
+ * Determine if user option already in STD_opt_arr.
+ * If the option is listed twice (in even numbers), it is disabled.
+ * To disable the option, remove it from the option from STD_opt_arr.
+ */
+ for(ind=0; ind<STD_nopts; ind++) {
+ if (strcmp(user_optarr[cnt].option, STD_opt_arr[ind]) == 0 ) {
+ /*
+ * user option already in STD_opt_arry, which means to
+ * disable that option. Remove that option from STD_opt_arr.
+ */
+ rm_option(user_optarr[cnt].option, &STD_opt_arr, &STD_nopts);
+ break;
+ }
+ }
+
+ /*
+ * User's option is not already in STD_opt_arr so it needs to be
+ * added.
+ */
+ if ( ind >= STD_nopts ) {
+ num=strlen(user_optarr[cnt].option);
+
+ /*
+ * If the last character is ":", make sure arg pointer
+ * is not NULL.
+ */
+ if ( user_optarr[cnt].option[num-1] == ':' ) {
+
+ if ( user_optarr[cnt].arg == NULL ) {
+ sprintf(Mesg2,
+ "parse_opts: ERROR - option:\"%s\" expecting argument, NO POINTER GIVEN",
+ user_optarr[cnt].option);
+ return(Mesg2);
+ }
+
+ } else {
+ /*
+ * The option does not require an argument, make sure
+ * user_optarr[cnt].flag is pointing to something.
+ * The flag is optional when argument is required.
+ */
+ if ( user_optarr[cnt].flag == NULL ) {
+ sprintf(Mesg2,
+ "parse_opts: ERROR - option:\"%s\" NO FLAG LOCATION GIVEN",
+ user_optarr[cnt].option);
+ return(Mesg2);
+
+ }
+ }
+
+ /*
+ * Add the users option to the STD_opt_arr array.
+ */
+ if ( add_option(user_optarr[cnt].option, &STD_opt_arr, &STD_nopts) == -1 )
+ return Mesg2;
+
+ } /* new option */
+ } /* end of options loop */
+ } /* end of user options */
+
+#if DEBUG > 1
+ printf("STD_nopts = %d\n", STD_nopts);
+#endif
+
+
+ /*
+ * Loop through av parsing options.
+ */
+ while ( (opt=mc_getoptv(ac, av, 0, STD_nopts, STD_opt_arr)) != MC_DONE ) {
+
+ STD_argind = mc_optind;
+
+#if DEBUG > 0
+ printf("parse_opts: mc_getoptv returned '%s'\n", opt);
+#endif
+ if ( strcmp(opt, MC_UNKNOWN_OPTION) == 0 ) {
+ sprintf(Mesg2,
+ "parse_opts: ERROR - Unknown option: \"-%s\"",
+ mc_optopt);
+ return Mesg2;
+
+ } else if ( strcmp(opt, MC_AMBIGUOUS_OPTION) == 0 ) {
+ sprintf(Mesg2,
+ "parse_opts: ERROR - option \"-%s\" is not unique, be more specific",
+ mc_optopt);
+ return Mesg2;
+
+ } else if ( strcmp(opt, MC_MISSING_OPTARG) == 0 ) {
+ sprintf(Mesg2,
+ "parse_opts: ERROR - option \"-%s\" is missing its argument",
+ mc_optopt);
+ return Mesg2;
+
+ } else if ( strcmp(opt, ITERATIONS) == 0 ) {
+ options |= OPT_iteration;
+ if ( sscanf(mc_optarg, "%i%c", &STD_LOOP_COUNT, &chr) != 1) {
+ sprintf(Mesg2,
+ "parse_opts: ERROR - Argument for -%s option MUST be NUMERIC",
+ mc_optopt);
+ return(Mesg2);
+ }
+
+ if ( STD_LOOP_COUNT == 0 ) /* if arg is 0, set infinite loop flag */
+ STD_INFINITE=1;
+
+ } else if ( strcmp(opt, DELAY) == 0 ) {
+ options |= OPT_delay;
+ if ( sscanf(mc_optarg, "%f%c", &STD_LOOP_DELAY, &chr) != 1 ) {
+ sprintf(Mesg2,
+ "parse_opts: ERROR - Argument for -%s option MUST be NUMERIC",
+ mc_optopt);
+ return(Mesg2);
+ }
+
+ } else if ( strcmp(opt, DURATION) == 0 ) {
+ options |= OPT_duration;
+ if ( sscanf(mc_optarg, "%f%c", &STD_LOOP_DURATION, &chr) != 1 ) {
+ sprintf(Mesg2,
+ "parse_opts: ERROR - Argument for -%s option MUST be NUMERIC",
+ mc_optopt);
+ return(Mesg2);
+ }
+
+ if ( STD_LOOP_DURATION == 0.0 ) {
+ STD_INFINITE=1;
+ }
+
+ } else if ( strcmp(opt, COPIES) == 0 ) {
+ options |= OPT_copies;
+ if ( sscanf(mc_optarg, "%i%c", &STD_COPIES, &chr) != 1 ) {
+ sprintf(Mesg2,
+ "parse_opts: ERROR - Argument for -%s option MUST be NUMERIC",
+ mc_optopt);
+ return(Mesg2);
+ }
+
+ } else if ( strcmp(opt, NOFUNC) == 0 ) {
+ STD_FUNCTIONAL_TEST=0;
+ } else if ( strcmp(opt, SETUP_PAUSE) == 0 ) {
+ STD_PAUSE=1;
+ } else if ( strcmp(opt, TIMING) == 0 ) {
+ STD_TIMING_ON=1;
+ } else if ( strcmp(opt, ERRNO_LOGGING) == 0 ) {
+ STD_ERRNO_LOG=1;
+ } else if ( strcmp(opt, USC_HELP) == 0 ) {
+ printf(STD_opts_help());
+ exit(0);
+ } else {
+ /* Check all the user specified options */
+ found=0;
+ for(ind=0; user_optarr[ind].option != (char *) NULL; ind++) {
+
+ if ( strcmp(opt, user_optarr[ind].option) == 0 ) {
+ /* Yup, This is a user option, set the flag and look for argument */
+ if ( user_optarr[ind].flag != NULL ) {
+ *user_optarr[ind].flag=1;
+ }
+ found++;
+
+ /* If option requires arg, save pointer */
+ num=strlen(user_optarr[ind].option);
+ /* save the argument at the user's location */
+ if ( user_optarr[ind].option[num-1] == ':' ) {
+ *user_optarr[ind].arg=mc_optarg;
+ }
+ break; /* option found - break out of the for loop */
+ }
+ }
+ /* This condition "should never happen". SO CHECK FOR IT!!!! */
+ if ( ! found ) {
+ sprintf(Mesg2,
+ "parse_opts: ERROR - option:\"%s\" NOT FOUND... INTERNAL ERROR", opt);
+ return(Mesg2);
+ }
+ }
+
+ } /* end of while */
+
+ STD_argind = mc_optind;
+
+ /*
+ * Turn on debug
+ */
+ if ( (ptr=getenv("USC_DEBUG")) != NULL ) {
+ Debug=1;
+ printf("env USC_DEBUG is defined, turning on debug\n");
+ }
+ if ( (ptr=getenv("USC_VERBOSE")) != NULL ) {
+ Debug=1;
+ printf("env USC_VERBOSE is defined, turning on debug\n");
+ }
+
+ /*
+ * If the USC_ITERATION_ENV environmental variable is set to
+ * a number, use that number as iteration count (same as -c option).
+ * The -c option with arg will be used even if this env var is set.
+ */
+ if ( !(options & OPT_iteration) && (ptr=getenv(USC_ITERATION_ENV)) != NULL ) {
+ if ( sscanf(ptr, "%i", &k) == 1) {
+ if ( k == 0 ) { /* if arg is 0, set infinite loop flag */
+ STD_INFINITE=1;
+ if ( Debug )
+ printf("Using env %s, set STD_INFINITE to 1\n",
+ USC_ITERATION_ENV);
+ } else { /* else, set the loop count to the arguement */
+ STD_LOOP_COUNT=k;
+ if ( Debug )
+ printf("Using env %s, set STD_LOOP_COUNT to %d\n",
+ USC_ITERATION_ENV, k);
+ }
+ }
+ }
+
+ /*
+ * If the USC_NO_FUNC_CHECK environmental variable is set, we'll
+ * unset the STD_FUNCTIONAL_TEST variable.
+ */
+ if ( !(options & OPT_nofunccheck) && (ptr=getenv(USC_NO_FUNC_CHECK)) != NULL ) {
+ STD_FUNCTIONAL_TEST=0; /* Turn off functional testing */
+ if ( Debug )
+ printf("Using env %s, set STD_FUNCTIONAL_TEST to 0\n",
+ USC_NO_FUNC_CHECK);
+ }
+
+ /*
+ * If the USC_LOOP_WALLTIME environmental variable is set,
+ * use that number as duration (same as -I option).
+ * The -I option with arg will be used even if this env var is set.
+ */
+
+ if ( !(options & OPT_duration) && (ptr=getenv(USC_LOOP_WALLTIME)) != NULL ) {
+ if ( sscanf(ptr, "%f", &ftmp) == 1 && ftmp >= 0.0 ) {
+ STD_LOOP_DURATION=ftmp;
+ if ( Debug )
+ printf("Using env %s, set STD_LOOP_DURATION to %f\n",
+ USC_LOOP_WALLTIME, ftmp);
+ if ( STD_LOOP_DURATION == 0.0 ) { /* if arg is 0, set infinite loop flag */
+ STD_INFINITE=1;
+ if ( Debug )
+ printf("Using env %s, set STD_INFINITE to 1\n", USC_LOOP_WALLTIME);
+ }
+ }
+ }
+ if ( !(options & OPT_duration) && (ptr=getenv("USC_DURATION")) != NULL ) {
+ if ( sscanf(ptr, "%f", &ftmp) == 1 && ftmp >= 0.0 ) {
+ STD_LOOP_DURATION=ftmp;
+ if ( Debug )
+ printf("Using env USC_DURATION, set STD_LOOP_DURATION to %f\n", ftmp);
+ if ( STD_LOOP_DURATION == 0.0 ) { /* if arg is 0, set infinite loop flag */
+ STD_INFINITE=1;
+ if ( Debug )
+ printf("Using env USC_DURATION, set STD_INFINITE to 1\n");
+ }
+ }
+ }
+ /*
+ * If the USC_LOOP_DELAY environmental variable is set,
+ * use that number as delay in factional seconds (same as -P option).
+ * The -P option with arg will be used even if this env var is set.
+ */
+ if ( !(options & OPT_delay) && (ptr=getenv(USC_LOOP_DELAY)) != NULL ) {
+ if ( sscanf(ptr, "%f", &ftmp) == 1 && ftmp >= 0.0 ) {
+ STD_LOOP_DELAY=ftmp;
+ if ( Debug )
+ printf("Using env %s, set STD_LOOP_DELAY = %f\n",
+ USC_LOOP_DELAY, ftmp);
+ }
+ }
+
+ /*
+ * If the USC_COPIES environmental variable is set,
+ * use that number as copies (same as -c option).
+ * The -c option with arg will be used even if this env var is set.
+ */
+ if ( !(options & OPT_copies) && (ptr=getenv(USC_COPIES)) != NULL ) {
+ if ( sscanf(ptr, "%d", &STD_COPIES) == 1 && STD_COPIES >= 0 ) {
+ if ( Debug )
+ printf("Using env %s, set STD_COPIES = %d\n",
+ USC_COPIES, STD_COPIES);
+ }
+ }
+
+ /*
+ * The following are special system testing envs to turn on special
+ * hooks in the code.
+ */
+ if ( (ptr=getenv("USC_TP_BARRIER")) != NULL ) {
+ if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) {
+ STD_TP_barrier=k;
+ }
+ else
+ STD_TP_barrier=1;
+ if ( Debug )
+ printf("using env USC_TP_BARRIER, Set STD_TP_barrier to %d\n",
+ STD_TP_barrier);
+ }
+
+ if ( (ptr=getenv("USC_LP_BARRIER")) != NULL ) {
+ if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) {
+ STD_LP_barrier=k;
+ }
+ else
+ STD_LP_barrier=1;
+ if ( Debug )
+ printf("using env USC_LP_BARRIER, Set STD_LP_barrier to %d\n",
+ STD_LP_barrier);
+ }
+
+ if ( (ptr=getenv("USC_TP_SHMEM")) != NULL ) {
+ if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) {
+ STD_TP_shmem_sz=k;
+ if ( Debug )
+ printf("Using env USC_TP_SHMEM, Set STD_TP_shmem_sz to %d\n",
+ STD_TP_shmem_sz);
+ }
+ }
+
+ if ( (ptr=getenv("USC_LP_SHMEM")) != NULL ) {
+ if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) {
+ STD_LP_shmem=k;
+ if ( Debug )
+ printf("Using env USC_LP_SHMEM, Set STD_LP_shmem to %d\n",
+ STD_LP_shmem);
+ }
+ }
+
+ if ( (ptr=getenv("USC_LD_SHMEM")) != NULL ) {
+ if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) {
+ STD_LD_shmem=k;
+ if ( Debug )
+ printf("Using env USC_LD_SHMEM, Set STD_LD_shmem to %d\n",
+ STD_LD_shmem);
+ }
+ }
+
+ if ( (ptr=getenv("USC_TP_SBRK")) != NULL ) {
+ if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) {
+ STD_TP_sbrk=k;
+ if ( Debug )
+ printf("Using env USC_TP_SBRK, Set STD_TP_sbrk to %d\n",
+ STD_TP_sbrk);
+ }
+ }
+
+ if ( (ptr=getenv("USC_LP_SBRK")) != NULL ) {
+ if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) {
+ STD_LP_sbrk=k;
+ if ( Debug )
+ printf("Using env USC_LP_SBRK, Set STD_LP_sbrk to %d\n",
+ STD_LP_sbrk);
+ }
+ }
+
+ if ( (ptr=getenv("USC_LP_RECFUN")) != NULL ) {
+ if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) {
+ STD_LP_recfun=k;
+ if ( STD_bigstack != (struct usc_bigstack_t *)NULL )
+ STD_bigstack=(struct usc_bigstack_t *)
+ malloc(sizeof(struct usc_bigstack_t));
+ if ( Debug )
+ printf("Using env USC_LP_RECFUN, Set STD_LP_recfun to %d\n",
+ STD_LP_recfun);
+ }
+ }
+
+ if ( (ptr=getenv("USC_LD_RECFUN")) != NULL ) {
+ if ( sscanf(ptr, "%i", &k) == 1 && k >= 0 ) {
+ STD_LD_recfun=k;
+ if ( STD_bigstack != (struct usc_bigstack_t *)NULL )
+ STD_bigstack=(struct usc_bigstack_t *)
+ malloc(sizeof(struct usc_bigstack_t));
+ if ( Debug )
+ printf("Using env USC_LD_RECFUN, Set STD_LD_recfun to %d\n",
+ STD_LD_recfun);
+ }
+ }
+
+#if UNIT_TEST
+ printf("The following variables after option and env parsing:\n");
+ printf("STD_FUNCTIONAL_TEST = %d\n", STD_FUNCTIONAL_TEST);
+ printf("STD_LOOP_DURATION = %f\n", STD_LOOP_DURATION);
+ printf("STD_LOOP_DELAY = %f\n", STD_LOOP_DELAY);
+ printf("STD_COPIES = %d\n", STD_COPIES);
+ printf("STD_LOOP_COUNT = %d\n", STD_LOOP_COUNT);
+ printf("STD_INFINITE = %d\n", STD_INFINITE);
+ printf("STD_TIMING_ON = %d\n", STD_TIMING_ON);
+ printf("STD_ERRNO_LOG = %d\n", STD_ERRNO_LOG);
+ printf("STD_PAUSE = %d\n", STD_PAUSE);
+#endif
+
+ return((char *) NULL);
+
+} /* end of parse_opts */
+
+/***********************************************************************
+ * This function will remove option from the opt_arr array and
+ * decrement the value of nopts. If option is not at the end
+ * of the opt_arr, the remaining elements are moved up in the array.
+ *
+ ***********************************************************************/
+static int
+rm_option(char *option, char **opt_arr[], int *nopts)
+{
+ int ind;
+ int found=0;
+
+ for (ind=0; ind<*nopts; ind++) {
+ if ( found ) {
+ /*
+ * Move all opt_arr elements down in the array
+ */
+ if ( ind == (*nopts) ) {
+ (*opt_arr)[ind] = NULL;
+ } else {
+ (*opt_arr)[ind-1] = (*opt_arr)[ind];
+ }
+
+ } else if ( strcmp(option, (*opt_arr)[ind]) == 0 ) {
+ found=ind+1;
+ }
+ }
+ if ( found ) {
+ (*nopts)--;
+#if DEBUG > 1
+ printf("removed %s option from opt_arr, opt_arr[%d] = %s\n",
+option, found-1, (*opt_arr)[found-1]);
+#endif
+ }
+
+ return 0;
+}
+
+/***********************************************************************
+ * This function will add option to the end of opt_arr array and
+ * increment the value of nopts. The array space will be realloc'ed
+ * to make space for the element.
+ *
+ ***********************************************************************/
+static int
+add_option(char *option, char **opt_arr[], int *nopts)
+{
+
+ if ( (*opt_arr=(char **)realloc(*opt_arr, sizeof(char * ) * (*nopts+1))) ==
+ (char **)NULL ) {
+ sprintf(Mesg2, "parse_opts: ERROR: realloc(arr, %ld) failed, errno:%d %s",
+ (long)sizeof(char * ) * (*nopts+1), errno, strerror(errno));
+ return -1;
+ }
+
+ (*opt_arr)[*nopts] = option;
+
+#if DEBUG > 1
+ printf("adding opt_arr[%d] = %s\n", *nopts, (*opt_arr)[*nopts]);
+#endif
+ (*nopts)++;
+
+ return 0;
+}
+
+/*********************************************************************
+ * STD_opts() - return a usage string for the STD_OPTIONS.
+ *********************************************************************/
+char *
+STD_opts()
+{
+ int ind;
+
+ Mesg2[0] = '\0';
+
+ /*
+ * generate usage string from the standard options in STD_opt_arr
+ */
+ for(ind=0; ind<STD_nopts; ind++) {
+ if ( strcmp(ITERATIONS, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg2, ITERATIONS_USE);
+ }else if ( strcmp(DELAY, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg2, DELAY_USE);
+ }else if ( strcmp(DURATION, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg2, DURATION_USE);
+ }else if ( strcmp(COPIES, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg2, COPIES_USE);
+ }else if ( strcmp(NOFUNC, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg2, NOFUNC_USE);
+ }else if ( strcmp(SETUP_PAUSE, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg2, SETUP_PAUSE_USE);
+ }else if ( strcmp(TIMING, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg2, TIMING_USE);
+ }else if ( strcmp(ERRNO_LOGGING, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg2, ERRNO_LOGGING_USE);
+ }else if ( strcmp(USC_HELP, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg2, HELP_USE);
+ }
+ }
+
+ return Mesg2;
+}
+
+/*********************************************************************
+ * STD_opts_help() - return a help string for the STD_OPTIONS.
+ *********************************************************************/
+char *
+STD_opts_help()
+{
+ int ind;
+
+ sprintf(Mesg, " Options and option args can NOT be concatenated.\n\
+ You can use smallest unique string that identifies an option\n");
+
+ /*
+ * generate usage string from the standard options in STD_opt_arr
+ */
+ for(ind=0; ind<STD_nopts; ind++) {
+ if ( strcmp(ITERATIONS, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg, ITERATIONS_HELP);
+ }else if ( strcmp(DELAY, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg, DELAY_HELP);
+ }else if ( strcmp(DURATION, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg, DURATION_HELP);
+ }else if ( strcmp(COPIES, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg, COPIES_HELP);
+ }else if ( strcmp(NOFUNC, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg, NOFUNC_HELP);
+ }else if ( strcmp(SETUP_PAUSE, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg, SETUP_PAUSE_HELP);
+ }else if ( strcmp(TIMING, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg, TIMING_HELP);
+ }else if ( strcmp(ERRNO_LOGGING, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg, ERRNO_LOGGING_HELP);
+ }else if ( strcmp(USC_HELP, STD_opt_arr[ind]) == 0 ) {
+ strcat(Mesg, USC_HELP_HELP);
+ }
+ }
+
+ return Mesg;
+}
+
+/*
+ * routine to goto when we get the SIGUSR1 for STD_PAUSE
+ */
+void STD_go(int sig)
+{
+ return;
+}
+
+/***********************************************************************
+ * This function will do desired end of global setup test
+ * hooks.
+ * Currently it will only do a pause waiting for sigusr1 if
+ * STD_PAUSE is set.
+ *
+ ***********************************************************************/
+int
+usc_global_setup_hook()
+{
+ int cnt;
+
+ /*
+ * Fork STD_COPIES-1 copies.
+ */
+ for(cnt=1;cnt<STD_COPIES;cnt++) {
+ switch(fork() ) {
+ case -1:
+ fprintf(stderr, "%s: fork() failed, errno:%d %s\n",
+ __FILE__, errno, strerror(errno));
+ break;
+ case 0: /* child */
+ cnt=STD_COPIES; /* to stop the forking */
+ break;
+
+ default: /* parent */
+ break;
+ }
+ }
+
+
+
+#ifdef _CRAYMPP
+ MyPE = sysconf(_SC_CRAY_VPE);
+ Npe = sysconf(_SC_CRAY_NPES);
+#endif
+
+ /*
+ * pause waiting for sigusr1.
+ */
+ if ( STD_PAUSE ) {
+ _TMP_FUNC = (int (*)())signal(SIGUSR1, STD_go);
+ pause();
+ signal(SIGUSR1, (void (*)())_TMP_FUNC);
+ }
+
+#ifdef _CRAYMPP
+ if ( STD_TP_shmem_sz ) {
+ if ( (STD_shmem=(long *)shmalloc(STD_TP_shmem_sz*sizeof(long)*Npe)) == NULL ) {
+ STD_TP_shmem_sz=0;
+ }
+ else {
+ bzero(STD_shmem, STD_TP_shmem_sz*sizeof(long)*Npe);
+ if ( Debug )
+ printf("shmalloc(%d*%d*%d=%d) successful, pid:%d\n",
+ STD_TP_shmem_sz, sizeof(long), Npe,
+ STD_TP_shmem_sz*sizeof(long)*Npe, getpid());
+ }
+ }
+
+ if ( STD_TP_barrier ) {
+ switch (STD_TP_barrier) {
+ case 2:
+ wait_barrier();
+ if ( Debug )
+ printf("after wait_barrier, pid : %d\n", getpid());
+ break;
+
+ case 3:
+ set_barrier();
+ if ( Debug )
+ printf("after set_barrier, pid : %d\n", getpid());
+ break;
+
+ default:
+ barrier();
+ if ( Debug )
+ printf("after barrier, pid : %d\n", getpid());
+ }
+ }
+
+#endif /* _CRAYMPP */
+
+ if ( STD_TP_sbrk || STD_LP_sbrk) {
+ STD_start_break=sbrk(0); /* get original sbreak size */
+ }
+
+ if ( STD_TP_sbrk ) {
+ sbrk(STD_TP_sbrk);
+ if ( Debug )
+ printf("after sbrk(%d)\n", STD_TP_sbrk);
+ }
+ return 0;
+}
+
+#define USECS_PER_SEC 1000000 /* microseconds per second */
+
+/***********************************************************************
+ * This function returns the number of get_current_time()'s return
+ * per second.
+ ***********************************************************************/
+
+static int
+get_timepersec()
+{
+#if CRAY
+ return sysconf(_SC_CLK_TCK); /* clocks per second */
+#else
+ return USECS_PER_SEC; /* microseconds per second */
+#endif /* CRAY */
+
+}
+
+/***********************************************************************
+ * this function will get current time in clocks if on a CRAY system
+ * or in microseconds since 1970.
+ ***********************************************************************/
+static int
+get_current_time()
+{
+ struct timeval curtime;
+#if CRAY
+ return _rtc(); /* clocks since last boot */
+#else
+
+ gettimeofday(&curtime, NULL);
+
+ /* microseconds since 1970 */
+ return (curtime.tv_sec*USECS_PER_SEC) + curtime.tv_usec;
+
+#endif
+
+}
+
+/***********************************************************************
+ *
+ * This function will determine if test should continue iterating
+ * If the STD_INFINITE flag is set, return 1.
+ * If the STD_LOOP_COUNT variable is set, compare it against
+ * the counter.
+ * If the STD_LOOP_DURATION variable is set, compare current time against
+ * calculated stop_time.
+ * This function will return 1 until all desired looping methods
+ * have been met.
+ *
+ * counter integer is supplied by the user program.
+ ***********************************************************************/
+int
+usc_test_looping(counter)
+int counter;
+{
+ static int first_time = 1;
+ static int stop_time = 0; /* stop time in rtc or usecs */
+ static int delay; /* delay in clocks or usecs */
+ int hz=0; /* clocks per second or usecs per second */
+ int ct, end; /* current time, end delay time */
+ int keepgoing=0; /* used to determine return value */
+#ifdef _CRAYMPP
+ long word;
+ int pe;
+#endif
+
+ /*
+ * If this is the first iteration and we are looping for
+ * duration of STD_LOOP_DURATION seconds (fractional) or
+ * doing loop delays, get the clocks per second.
+ */
+ if ( first_time ) {
+
+ first_time=0;
+ if ( STD_LOOP_DELAY || STD_LOOP_DURATION ) {
+ hz = get_timepersec();
+ }
+
+ /*
+ * If looping for duration, calculate stop time in
+ * clocks.
+ */
+
+ if ( STD_LOOP_DURATION) {
+ ct=get_current_time();
+ stop_time=(int)((float)hz * STD_LOOP_DURATION) + ct;
+ }
+
+ /*
+ * If doing delay each iteration, calcuate the number
+ * of clocks for each delay.
+ */
+ if ( STD_LOOP_DELAY ) {
+ delay=(int)((float)hz * STD_LOOP_DELAY);
+ }
+
+ }
+
+ /*
+ * if delay each iteration, loop for delay clocks.
+ * This will not be done on first iteration.
+ * The delay will happen before determining if
+ * there will be another iteration.
+ */
+ else if ( STD_LOOP_DELAY ) {
+ ct=get_current_time();
+ end=ct+delay;
+ while ( ct < end ) {
+ /*
+ * The following are special test hooks in the delay loop.
+ */
+ if ( STD_LD_recfun ) {
+ if ( Debug )
+ printf("calling usc_recressive_func(0, %d, &STD_bigstack)\n",
+ STD_LD_recfun);
+ usc_recressive_func(0, STD_LD_recfun, &STD_bigstack);
+ }
+
+ ct=get_current_time();
+ }
+ }
+
+ if ( STD_INFINITE ) {
+ keepgoing++;
+ }
+
+ if ( STD_LOOP_COUNT && counter < STD_LOOP_COUNT ) {
+ keepgoing++;
+ }
+
+ if ( STD_LOOP_DURATION != 0.0 && get_current_time() < stop_time ) {
+ keepgoing++;
+ }
+
+ if ( keepgoing == 0 )
+ return 0;
+
+ /*
+ * The following code allows special system testing hooks.
+ */
+
+ if ( STD_LP_recfun ) {
+ if ( Debug )
+ printf("calling usc_recressive_func(0, %d, &STD_bigstack)\n",
+ STD_LP_recfun);
+ usc_recressive_func(0, STD_LP_recfun, &STD_bigstack);
+ }
+
+ if ( STD_LP_sbrk ) {
+ if ( Debug )
+ printf("about to do sbrk(%d)\n", STD_LP_sbrk);
+ sbrk(STD_LP_sbrk);
+ }
+
+#ifdef _CRAYMPP
+ if ( STD_LP_shmem ) {
+ if ( (pe=MyPE-1) < 0 ) /* put to be lower pe #*/
+ pe=Npe;
+ word=MyPE;
+
+ if ( Debug )
+ printf("about to do shmem_put\n");
+ shmem_put(&STD_shmem[pe], &STD_shmem[MyPE], STD_TP_shmem_sz, pe);
+
+
+ }
+ if ( STD_TP_barrier ) {
+ switch (STD_TP_barrier) {
+ case 2:
+ wait_barrier();
+ if ( Debug )
+ printf("after wait_barrier, pid : %d\n", getpid());
+ break;
+
+ case 3:
+ set_barrier();
+ if ( Debug )
+ printf("after set_barrier, pid : %d\n", getpid());
+ break;
+
+ default:
+ barrier();
+ if ( Debug )
+ printf("after barrier, pid : %d\n", getpid());
+ }
+ }
+ if ( STD_LP_shmem > 1) {
+ if ( (pe=MyPE+1) > Npe ) /* get from higher pe # */
+ pe=0;
+ word=MyPE;
+
+ if ( Debug )
+ printf("about to do shmem_get\n");
+ shmem_get(&STD_shmem[MyPE], &STD_shmem[pe], STD_TP_shmem_sz, pe);
+ }
+
+
+#endif /* _CRAYMPP */
+
+
+ if ( keepgoing )
+ return 1;
+ else
+ return 0; /* done - stop iterating */
+}
+
+
+/*
+ * This function recressively calls itself max times.
+ */
+static void
+usc_recressive_func(cnt, max, bstack)
+int cnt;
+int max;
+struct usc_bigstack_t bstack;
+{
+ if ( cnt < max )
+ usc_recressive_func(cnt+1, max, bstack);
+
+}
+
+#if UNIT_TEST
+/******************************************************************************
+ * UNIT TEST CODE
+ * UNIT TEST CODE
+ *
+ * this following code is provide so that unit testing can
+ * be done fairly easily.
+ ******************************************************************************/
+
+int Help = 0;
+int Help2 = 0;
+char *ptr;
+
+/*
+ * Code from usctest.h that not part of this file since we are the library.
+ */
+
+struct usc_errno_t TEST_VALID_ENO[USC_MAX_ERRNO];
+
+ /***********************************************************************
+ * Globals for returning the return code and errno from the system call
+ * test macros.
+ ***********************************************************************/
+int TEST_RETURN;
+int TEST_ERRNO;
+
+ /***********************************************************************
+ * temporary variables for determining max and min times in TEST macro
+ ***********************************************************************/
+long btime, etime, tmptime;
+
+
+
+/* for test specific parse_opts options */
+option_t Options[] = {
+ { "help", &Help2, NULL }, /* -help option */
+ { "h", &Help, NULL }, /* -h option */
+ { TIMING, NULL, NULL}, /* disable -timing option */
+
+#if INVALID_TEST_CASES
+ { "missingflag", NULL, &ptr }, /* error */
+ { "missingarg:", &Help, NULL }, /* error */
+#endif /* INVALID_TEST_CASES */
+
+ { NULL, NULL, NULL }
+};
+
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ int lc;
+ char *msg;
+ struct timeval t;
+ int cnt;
+
+ if ( (msg=parse_opts(argc, argv,
+ (option_t *) Options)) != (char *) NULL ) {
+ printf("ERROR : %s\n", msg);
+ exit(1);
+ }
+
+ if ( Help ) {
+ printf("****** -h option *****\n");
+ printf("Usage %s %s[-help]\n", argv[0], STD_opts());
+ printf("%s -help : print this help message and exit\n",
+ STD_opts_help());
+ exit(0);
+ }
+
+ if ( Help2 ) {
+ printf("****** -help option *****\n");
+ printf("Usage %s %s[-help]\n", argv[0], STD_opts());
+ printf("%s -help : print this help message and exit\n",
+ STD_opts_help());
+ exit(0);
+ }
+
+ TEST_PAUSE;
+
+ for (lc=0; TEST_LOOPING(lc); lc++) {
+
+ TEST( gettimeofday(&t, NULL) );
+ printf("iter=%d: sec:%d, usec:%6.6d %s", lc+1, t.tv_sec,
+ t.tv_usec, ctime(&t.tv_sec));
+ }
+
+
+ TEST_CLEANUP;
+
+ exit(0);
+}
+
+#endif /* UNIT_TEST */
diff --git a/lib/pattern.c b/lib/pattern.c
index 43528ae..7f4d587 100644
--- a/lib/pattern.c
+++ b/lib/pattern.c
@@ -29,40 +29,14 @@
*
* http://oss.sgi.com/projects/GenInfo/NoticeExplan/
*/
+#include <string.h>
+#include "pattern.h"
+
/*
* The routines in this module are used to fill/check a data buffer
* with/against a known pattern.
*/
-/*
- * pattern_check(buf, buflen, pat, patlen, patshift)
- *
- * Check a buffer of length buflen against repeated occurrances of
- * a pattern whose length is patlen. Patshift can be used to rotate
- * the pattern by patshift bytes to the left.
- *
- * Patshift may be greater than patlen, the pattern will be rotated by
- * (patshift % patshift) bytes.
- *
- * pattern_check returns -1 if the buffer does not contain repeated
- * occurrances of the indicated pattern (shifted by patshift).
- *
- * The algorithm used to check the buffer relies on the fact that buf is
- * supposed to be repeated copies of pattern. The basic algorithm is
- * to validate the first patlen bytes of buf against the pat argument
- * passed in - then validate the next patlen bytes against the 1st patlen
- * bytes - the next (2*patlen) bytes against the 1st (2*pathen) bytes, and
- * so on. This algorithm only works when the assumption of a buffer full
- * of repeated copies of a pattern holds, and gives MUCH better results
- * then walking the buffer byte by byte.
- *
- * Performance wise, It appears to be about 5% slower than doing a straight
- * memcmp of 2 buffers, but the big win is that it does not require a
- * 2nd comparison buffer, only the pattern.
- */
-
-#include <string.h>
-
int
pattern_check(buf, buflen, pat, patlen, patshift)
char *buf;
@@ -130,32 +104,6 @@
return 0;
}
-/*
- * pattern_fill(buf, buflen, pat, patlen, patshift)
- *
- * Fill a buffer of length buflen with repeated occurrances of
- * a pattern whose length is patlen. Patshift can be used to rotate
- * the pattern by patshift bytes to the left.
- *
- * Patshift may be greater than patlen, the pattern will be rotated by
- * (patshift % patlen) bytes.
- *
- * If buflen is not a multiple of patlen, a partial pattern will be written
- * in the last part of the buffer. This implies that a buffer which is
- * shorter than the pattern length will receive only a partial pattern ...
- *
- * pattern_fill always returns 0 - no validation of arguments is done.
- *
- * The algorithm used to fill the buffer relies on the fact that buf is
- * supposed to be repeated copies of pattern. The basic algorithm is
- * to fill the first patlen bytes of buf with the pat argument
- * passed in - then copy the next patlen bytes with the 1st patlen
- * bytes - the next (2*patlen) bytes with the 1st (2*pathen) bytes, and
- * so on. This algorithm only works when the assumption of a buffer full
- * of repeated copies of a pattern holds, and gives MUCH better results
- * then filling the buffer 1 byte at a time.
- */
-
int
pattern_fill(buf, buflen, pat, patlen, patshift)
char *buf;
diff --git a/lib/rmobj.c b/lib/rmobj.c
new file mode 100644
index 0000000..1fc77a7
--- /dev/null
+++ b/lib/rmobj.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
+ */
+
+/* $Id: rmobj.c,v 1.1 2000/07/27 17:13:18 alaffin Exp $ */
+
+/**********************************************************
+ *
+ * OS Testing - Silicon Graphics, Inc.
+ *
+ * FUNCTION NAME : rmobj()
+ *
+ * FUNCTION TITLE : Remove an object
+ *
+ * SYNOPSIS:
+ * int rmobj(char *obj, char **errmsg)
+ *
+ * AUTHOR : Kent Rogers
+ *
+ * INITIAL RELEASE : UNICOS 7.0
+ *
+ * USER DESCRIPTION
+ * This routine will remove the specified object. If the specified
+ * object is a directory, it will recursively remove the directory
+ * and everything underneath it. It assumes that it has privilege
+ * to remove everything that it tries to remove. If rmobj() encounters
+ * any problems, and errmsg is not NULL, errmsg is set to point to a
+ * string explaining the error.
+ *
+ * DETAILED DESCRIPTION
+ * Allocate space for the directory and its contents
+ * Open the directory to get access to what is in it
+ * Loop through the objects in the directory:
+ * If the object is not "." or "..":
+ * Determine the file type by calling lstat()
+ * If the object is not a directory:
+ * Remove the object with unlink()
+ * Else:
+ * Call rmobj(object) to remove the object's contents
+ * Determine the link count on object by calling lstat()
+ * If the link count >= 3:
+ * Remove the directory with unlink()
+ * Else
+ * Remove the directory with rmdir()
+ * Close the directory and free the pointers
+ *
+ * RETURN VALUE
+ * If there are any problems, rmobj() will set errmsg (if it was not
+ * NULL) and return -1. Otherwise it will return 0.
+ *
+ ************************************************************/
+#include <errno.h> /* for errno */
+#include <stdio.h> /* for NULL */
+#include <stdlib.h> /* for malloc() */
+#include <string.h> /* for string function */
+#include <limits.h> /* for PATH_MAX */
+#include <sys/types.h> /* for opendir(), readdir(), closedir(), stat() */
+#include <sys/stat.h> /* for [l]stat() */
+#include <dirent.h> /* for opendir(), readdir(), closedir() */
+#include "rmobj.h"
+
+#define SYSERR strerror(errno)
+
+int
+rmobj(char *obj, char **errmsg)
+{
+ int ret_val = 0; /* return value from this routine */
+ DIR *dir; /* pointer to a directory */
+ struct dirent *dir_ent; /* pointer to directory entries */
+ char dirobj[PATH_MAX]; /* object inside directory to modify */
+ struct stat statbuf; /* used to hold stat information */
+ static char err_msg[1024]; /* error message */
+
+ /* Determine the file type */
+ if ( lstat(obj, &statbuf) < 0 ) {
+ if ( errmsg != NULL ) {
+ sprintf(err_msg, "lstat(%s) failed; errno=%d: %s",
+ obj, errno, SYSERR);
+ *errmsg = err_msg;
+ }
+ return -1;
+ }
+
+ /* Take appropriate action, depending on the file type */
+ if ( (statbuf.st_mode & S_IFMT) == S_IFDIR ) {
+ /* object is a directory */
+
+ /* Do NOT perform the request if the directory is "/" */
+ if ( !strcmp(obj, "/") ) {
+ if ( errmsg != NULL ) {
+ sprintf(err_msg, "Cannot remove /");
+ *errmsg = err_msg;
+ }
+ return -1;
+ }
+
+ /* Open the directory to get access to what is in it */
+ if ( (dir = opendir(obj)) == NULL ) {
+ if ( rmdir(obj) != 0 ) {
+ if ( errmsg != NULL ) {
+ sprintf(err_msg, "rmdir(%s) failed; errno=%d: %s",
+ obj, errno, SYSERR);
+ *errmsg = err_msg;
+ }
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
+ /* Loop through the entries in the directory, removing each one */
+ for ( dir_ent = (struct dirent *)readdir(dir);
+ dir_ent != NULL;
+ dir_ent = (struct dirent *)readdir(dir)) {
+
+ /* Don't remove "." or ".." */
+ if ( !strcmp(dir_ent->d_name, ".") || !strcmp(dir_ent->d_name, "..") )
+ continue;
+
+ /* Recursively call this routine to remove the current entry */
+ sprintf(dirobj, "%s/%s", obj, dir_ent->d_name);
+ if ( rmobj(dirobj, errmsg) != 0 )
+ ret_val = -1;
+ }
+
+ /* Close the directory */
+ closedir(dir);
+
+ /* If there were problems removing an entry, don't attempt to
+ remove the directory itself */
+ if ( ret_val == -1 )
+ return -1;
+
+ /* Get the link count, now that all the entries have been removed */
+ if ( lstat(obj, &statbuf) < 0 ) {
+ if ( errmsg != NULL ) {
+ sprintf(err_msg, "lstat(%s) failed; errno=%d: %s",
+ obj, errno, SYSERR);
+ *errmsg = err_msg;
+ }
+ return -1;
+ }
+
+ /* Remove the directory itself */
+ if ( statbuf.st_nlink >= 3 ) {
+ /* The directory is linked; unlink() must be used */
+ if ( unlink(obj) < 0 ) {
+ if ( errmsg != NULL ) {
+ sprintf(err_msg, "unlink(%s) failed; errno=%d: %s",
+ obj, errno, SYSERR);
+ *errmsg = err_msg;
+ }
+ return -1;
+ }
+ } else {
+ /* The directory is not linked; rmdir() can be used */
+ if ( rmdir(obj) < 0 ) {
+ if ( errmsg != NULL ) {
+ sprintf(err_msg, "rmdir(%s) failed; errno=%d: %s",
+ obj, errno, SYSERR);
+ *errmsg = err_msg;
+ }
+ return -1;
+ }
+ }
+ } else {
+ /* object is not a directory; just use unlink() */
+ if ( unlink(obj) < 0 ) {
+ if ( errmsg != NULL ) {
+ sprintf(err_msg, "unlink(%s) failed; errno=%d: %s",
+ obj, errno, SYSERR);
+ *errmsg = err_msg;
+ }
+ return -1;
+ }
+ } /* if obj is a directory */
+
+ /*
+ * Everything must have went ok.
+ */
+ return 0;
+} /* rmobj() */
diff --git a/lib/string_to_tokens.c b/lib/string_to_tokens.c
index 5200aec..6f0d775 100644
--- a/lib/string_to_tokens.c
+++ b/lib/string_to_tokens.c
@@ -31,7 +31,7 @@
*/
/**********************************************************
*
- * UNICOS Testing - Cray Research, Inc.
+ * OS Testing - Silicon Graphics, Inc.
*
* FUNCTION NAME : string_to_tokens
*
diff --git a/lib/tlibio.c b/lib/tlibio.c
index a73aa39..ef75d8e 100644
--- a/lib/tlibio.c
+++ b/lib/tlibio.c
@@ -81,11 +81,7 @@
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
-#ifdef CRAY
-#include <sys/unistd.h>
-#else
#include <unistd.h>
-#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
diff --git a/lib/tst_res.c b/lib/tst_res.c
new file mode 100644
index 0000000..1c9534c
--- /dev/null
+++ b/lib/tst_res.c
@@ -0,0 +1,964 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
+ */
+
+
+/* $Id: tst_res.c,v 1.1 2000/07/27 17:13:19 alaffin Exp $ */
+
+/**********************************************************
+ *
+ * OS Testing - Silicon Graphics, Inc.
+ *
+ * FUNCTION NAME :
+ * tst_res() - Print result message (include file contents)
+ * tst_resm() - Print result message
+ * tst_brk() - Print result message (include file contents)
+ * and break remaining test cases
+ * tst_brkm() - Print result message and break remaining test
+ * cases
+ * tst_brkloop() - Print result message (include file contents)
+ * and break test cases remaining in current loop
+ * tst_brkloopm() - Print result message and break test case
+ * remaining in current loop
+ * tst_flush() - Print any messages pending because of
+ * CONDENSE mode, and flush output stream
+ * tst_exit() - Exit test with a meaningful exit value.
+ * tst_environ() - Keep results coming to original stdout
+ *
+ * FUNCTION TITLE : Standard automated test result reporting mechanism
+ *
+ * SYNOPSIS:
+ * #include "test.h"
+ *
+ * void tst_res(ttype, fname, tmesg [,arg]...)
+ * int ttype;
+ * char *fname;
+ * char *tmesg;
+ *
+ * void tst_resm(ttype, tmesg [,arg]...)
+ * int ttype;
+ * char *tmesg;
+ *
+ * void tst_brk(ttype, fname, cleanup, tmesg, [,argv]...)
+ * int ttype;
+ * char *fname;
+ * void (*cleanup)();
+ * char *tmesg;
+ *
+ * void tst_brkm(ttype, cleanup, tmesg [,arg]...)
+ * int ttype;
+ * void (*cleanup)();
+ * char *tmesg;
+ *
+ * void tst_brkloop(ttype, fname, cleanup, char *tmesg, [,argv]...)
+ * int ttype;
+ * char *fname;
+ * void (*cleanup)();
+ * char *tmesg;
+ *
+ * void tst_brkloopm(ttype, cleanup, tmesg [,arg]...)
+ * int ttype;
+ * void (*cleanup)();
+ * char *tmesg;
+ *
+ * void tst_flush()
+ *
+ * void tst_exit()
+ *
+ * int tst_environ()
+ *
+ * AUTHOR : Kent Rogers (from Dave Fenner's original)
+ *
+ * CO-PILOT : Rich Logan
+ *
+ * DATE STARTED : 05/01/90 (rewritten 1/96)
+ *
+ * DESCRIPTION
+ * See the man page(s).
+ *
+ *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
+#include <errno.h>
+#include <string.h>
+#include <stdio.h> /* for I/O functions, BUFSIZ */
+#include <stdlib.h> /* for getenv() */
+#include <stdarg.h> /* for varargs stuff */
+#include <unistd.h> /* for access() */
+#include "test.h" /* for output display mode & result type */
+ /* defines */
+
+/*
+ * Define some useful macros.
+ */
+#define VERBOSE 1 /* flag values for the T_mode variable */
+#define CONDENSE 2
+#define NOPASS 3
+#define DISCARD 4
+
+#define MAXMESG 80 /* max length of internal messages */
+#define USERMESG 2048 /* max length of user message */
+#define TRUE 1
+#define FALSE 0
+
+/*
+ * EXPAND_VAR_ARGS - Expand the variable portion (arg_fmt) of a result
+ * message into the specified string.
+ */
+#define EXPAND_VAR_ARGS(arg_fmt, str) { \
+ va_list ap; /* varargs mechanism */ \
+ \
+ if ( arg_fmt != NULL ) { \
+ if ( Expand_varargs == TRUE ) { \
+ va_start(ap, arg_fmt); \
+ vsprintf(str, arg_fmt, ap); \
+ va_end(ap); \
+ Expand_varargs = FALSE; \
+ } else { \
+ strcpy(str, arg_fmt); \
+ } \
+ } else { \
+ str[0] = '\0'; \
+ } \
+} /* EXPAND_VAR_ARGS() */
+
+/*
+ * Define local function prototypes.
+ */
+static void check_env();
+static void tst_condense(int tnum, int ttype, char *tmesg);
+static void tst_print(char *tcid, int tnum, int trange, int ttype, char *tmesg);
+static void cat_file(char *filename);
+
+
+/*
+ * Define some static/global variables.
+ */
+static FILE *T_out = NULL; /* tst_res() output file descriptor */
+static char *File; /* file whose contents is part of result */
+static int T_exitval = 0; /* exit value used by tst_exit() */
+static int T_mode = VERBOSE; /* flag indicating print mode: VERBOSE, */
+ /* CONDENSE, NOPASS, DISCARD */
+
+static int Expand_varargs = TRUE; /* if TRUE, expand varargs stuff */
+static char Warn_mesg[MAXMESG]; /* holds warning messages */
+
+/*
+ * These are used for condensing output when NOT in verbose mode.
+ */
+static int Buffered = FALSE; /* TRUE if condensed output is currently */
+ /* buffered (i.e. not yet printed) */
+static char *Last_tcid; /* previous test case id */
+static int Last_num; /* previous test case number */
+static int Last_type; /* previous test result type */
+static char *Last_mesg; /* previous test result message */
+
+
+/*
+ * These globals may be externed by the test.
+ */
+int Tst_count = 0; /* current count of test cases executed; NOTE: */
+ /* Tst_count may be externed by other programs */
+int Tst_lptotal = 0; /* tst_brkloop() external */
+int Tst_lpstart = 0; /* tst_brkloop() external */
+int Tst_range = 1; /* for specifying multiple results */
+int Tst_nobuf = 1; /* this is a no-op; buffering is never done, but */
+ /* this will stay for compatibility reasons */
+
+/*
+ * These globals must be defined in the test.
+ */
+extern char *TCID; /* Test case identifier from the test source */
+extern int TST_TOTAL; /* Total number of test cases from the test */
+ /* source */
+
+/*
+ * This global is used by the temp. dir. maintenance functions,
+ * tst_tmpdir()/tst_rmdir(), tst_wildcard()/tst_tr_rmdir(). It is the
+ * name of the directory created (if any). It is defined here, so that
+ * it only has to be declared once and can then be referenced from more
+ * than one module. Also, since the temp. dir. maintenance functions
+ * rely on the tst_res.c package this seemed like a reasonable place.
+ */
+char *TESTDIR = NULL;
+
+/*
+ * tst_res() - Main result reporting function. Handle test information
+ * appropriately depending on output display mode. Call
+ * tst_condense() or tst_print() to actually print results.
+ * All result functions (tst_resm(), tst_brk(), etc.)
+ * eventually get here to print the results.
+ */
+void
+tst_res(int ttype, char *fname, char *arg_fmt, ...)
+{
+ int i;
+ char tmesg[USERMESG]; /* expanded message */
+
+#if DEBUG
+ printf("IN tst_res; Tst_count = %d; Tst_range = %d\n",
+ Tst_count, Tst_range); fflush(stdout);
+#endif
+
+ /*
+ * Expand the arg_fmt string into tmesg, if necessary.
+ */
+ EXPAND_VAR_ARGS(arg_fmt, tmesg);
+
+ /*
+ * Save the test result type by ORing ttype into the current exit
+ * value (used by tst_exit()).
+ */
+ T_exitval |= ttype;
+
+ /*
+ * Unless T_out has already been set by tst_environ(), make tst_res()
+ * output go to standard output.
+ */
+ if ( T_out == NULL )
+ T_out = stdout;
+
+ /*
+ * Check TOUTPUT environment variable (if first time) and set T_mode
+ * flag.
+ */
+ check_env();
+
+ /*
+ * A negative or NULL range is invalid.
+ */
+ if ( Tst_range <= 0 ) {
+ Tst_range = 1;
+ tst_print(TCID, 0, 1, TWARN,
+ "tst_res(): Tst_range must be positive");
+ }
+
+ /*
+ * If a filename was specified, set 'File' if it exists.
+ */
+ if ( fname != NULL && access(fname, F_OK) == 0 )
+ File = fname;
+
+ /*
+ * Set the test case number and print the results, depending on the
+ * display type.
+ */
+ if ( ttype == TWARN || ttype == TINFO ) {
+ /*
+ * Handle WARN and INFO results (test case number is 0).
+ */
+ if ( Tst_range > 1 ) {
+ tst_print(TCID, 0, 1, TWARN,
+ "tst_res(): Range not valid for TINFO or TWARN types");
+ }
+ tst_print(TCID, 0, 1, ttype, tmesg);
+ } else {
+ /*
+ * Handle all other types of results other than WARN and INFO.
+ */
+ if ( Tst_count < 0 )
+ tst_print(TCID, 0, 1, TWARN,
+ "tst_res(): Tst_count < 0 is not valid");
+
+ /*
+ * Process each display type.
+ */
+ switch ( T_mode ) {
+ case DISCARD:
+ /* do not print any results */
+ break;
+
+ case NOPASS: /* passing result types are filtered by tst_print() */
+ case CONDENSE:
+ tst_condense(Tst_count + 1, ttype, tmesg);
+ break;
+
+ default: /* VERBOSE */
+ for ( i = 1 ; i <= Tst_range ; i++ )
+ tst_print(TCID, Tst_count + i, Tst_range, ttype, tmesg);
+ break;
+ } /* end switch() */
+
+ /*
+ * Increment Tst_count.
+ */
+ Tst_count += Tst_range;
+ } /* if ( ttype == TWARN || ttype == TINFO ) */
+
+ /*
+ * Reset some values.
+ */
+ Tst_range = 1;
+ Expand_varargs = TRUE;
+} /* tst_res() */
+
+
+/*
+ * tst_condense() - Handle test cases in CONDENSE or NOPASS mode (i.e.
+ * buffer the current result and print the last result
+ * if different than the current). If a file was
+ * specified, print the current result and do not
+ * buffer it.
+ */
+static void
+tst_condense(int tnum, int ttype, char *tmesg)
+{
+ char *file;
+
+#if DEBUG
+ printf("IN tst_condense: tcid = %s, tnum = %d, ttype = %d, tmesg = %s\n",
+ TCID, tnum, ttype, tmesg);
+ fflush(stdout);
+#endif
+
+ /*
+ * If this result is the same as the previous result, return.
+ */
+ if ( Buffered == TRUE ) {
+ if ( strcmp(Last_tcid, TCID) == 0 && Last_type == ttype &&
+ strcmp(Last_mesg, tmesg) == 0 && File == NULL )
+ return;
+
+ /*
+ * This result is different from the previous result. First,
+ * print the previous result.
+ */
+ file = File;
+ File = NULL;
+ tst_print(Last_tcid, Last_num, tnum - Last_num, Last_type,
+ Last_mesg);
+ free(Last_tcid);
+ free(Last_mesg);
+ File = file;
+ } /* if ( Buffered == TRUE ) */
+
+ /*
+ * If a file was specified, print the current result since we have no
+ * way of retaining the file contents for comparing with future
+ * results. Otherwise, buffer the current result info for next time.
+ */
+ if ( File != NULL ) {
+ tst_print(TCID, tnum, Tst_range, ttype, tmesg);
+ Buffered = FALSE;
+ } else {
+ Last_tcid = (char *)malloc(strlen(TCID) + 1);
+ strcpy(Last_tcid, TCID);
+ Last_num = tnum;
+ Last_type = ttype;
+ Last_mesg = (char *)malloc(strlen(tmesg) + 1);
+ strcpy(Last_mesg, tmesg);
+ Buffered = TRUE;
+ }
+} /* tst_condense() */
+
+
+/*
+ * tst_flush() - Print any messages pending because of CONDENSE mode,
+ * and flush T_out.
+ */
+void
+tst_flush()
+{
+#if DEBUG
+ printf("IN tst_flush\n");
+ fflush(stdout);
+#endif
+
+ /*
+ * Print out last line if in CONDENSE or NOPASS mode.
+ */
+ if ( Buffered == TRUE && (T_mode == CONDENSE || T_mode == NOPASS) ) {
+ tst_print(Last_tcid, Last_num, Tst_count - Last_num + 1,
+ Last_type, Last_mesg);
+ Buffered = FALSE;
+ }
+ fflush(T_out);
+} /* tst_flush() */
+
+
+/*
+ * tst_print() - Actually print a line or range of lines to the output
+ * stream.
+ */
+static void
+tst_print(char *tcid, int tnum, int trange, int ttype, char *tmesg)
+{
+ char type[5];
+
+#if DEBUG
+ printf("IN tst_print: tnum = %d, trange = %d, ttype = %d, tmesg = %s\n",
+ tnum, trange, ttype, tmesg);
+ fflush(stdout);
+#endif
+
+ /*
+ * Save the test result type by ORing ttype into the current exit
+ * value (used by tst_exit()). This is already done in tst_res(), but
+ * is also done here to catch internal warnings. For internal warnings,
+ * tst_print() is called directly with a case of TWARN.
+ */
+ T_exitval |= ttype;
+
+ /*
+ * If output mode is DISCARD, or if the output mode is NOPASS and
+ * this result is not one of FAIL, BROK, or WARN, just return. This
+ * check is necessary even though we check for DISCARD mode inside of
+ * tst_res(), since occasionally we get to this point without going
+ * through tst_res() (e.g. internal TWARN messages).
+ */
+ if ( T_mode == DISCARD || (T_mode == NOPASS && ttype != TFAIL &&
+ ttype != TBROK && ttype != TWARN) )
+ return;
+
+ /*
+ * Fill in the type string according to ttype.
+ */
+ switch ( ttype ) {
+ case TPASS:
+ strcpy(type, "PASS");
+ break;
+ case TFAIL:
+ strcpy(type, "FAIL");
+ break;
+ case TBROK:
+ strcpy(type, "BROK");
+ break;
+ case TRETR:
+ strcpy(type, "RETR");
+ break;
+ case TCONF:
+ strcpy(type, "CONF");
+ break;
+ case TWARN:
+ strcpy(type, "WARN");
+ break;
+ case TINFO:
+ strcpy(type, "INFO");
+ break;
+ default:
+ strcpy(type, "????");
+ break;
+ } /* switch ( ttype ) */
+
+ /*
+ * Build the result line and print it.
+ */
+ if ( T_mode == VERBOSE ) {
+ fprintf(T_out, "%-8s %4d %s : %s\n", tcid, tnum, type, tmesg);
+ } else {
+ /* condense results if a range is specified */
+ if ( trange > 1 )
+ fprintf(T_out, "%-8s %4d-%-4d %s : %s\n",
+ tcid, tnum, tnum + trange - 1, type, tmesg);
+ else
+ fprintf(T_out, "%-8s %4d %s : %s\n",
+ tcid, tnum, type, tmesg);
+ }
+
+ /*
+ * If tst_res() was called with a file, append file contents to the
+ * end of last printed result.
+ */
+ if ( File != NULL )
+ cat_file(File);
+ File = NULL;
+} /* tst_print() */
+
+
+/*
+ * check_env() - Check the value of the environment variable TOUTPUT and
+ * set the global variable T_mode. The TOUTPUT environment
+ * variable should be set to "VERBOSE", "CONDENSE",
+ * "NOPASS", or "DISCARD". If TOUTPUT does not exist or
+ * is not set to a valid value, the default is "VERBOSE".
+ */
+static void
+check_env()
+{
+ static int first_time = 1;
+ char *value; /* value of TOUTPUT environment variable */
+
+#if DEBUG
+ printf("IN check_env\n");
+ fflush(stdout);
+#endif
+
+ if ( !first_time )
+ return;
+
+ first_time = 0;
+
+ if ( (value = getenv(TOUTPUT)) == NULL ) {
+ /* TOUTPUT not defined, use default */
+ T_mode = VERBOSE;
+ } else if ( strcmp(value, TOUT_CONDENSE_S) == 0 ) {
+ T_mode = CONDENSE;
+ } else if ( strcmp(value, TOUT_NOPASS_S) == 0 ) {
+ T_mode = NOPASS;
+ } else if ( strcmp(value, TOUT_DISCARD_S) == 0 ) {
+ T_mode = DISCARD;
+ } else {
+ /* default */
+ T_mode = VERBOSE;
+ }
+
+ return;
+} /* check_env() */
+
+
+/*
+ * tst_exit() - Call exit() with the value T_exitval, set up by
+ * tst_res(). T_exitval has a bit set for most of the
+ * result types that were seen (including TPASS, TFAIL,
+ * TBROK, TWARN, TCONF). Also, print the last result (if
+ * necessary) before exiting.
+ */
+void
+tst_exit()
+{
+#if DEBUG
+ printf("IN tst_exit\n"); fflush(stdout);
+ fflush(stdout);
+#endif
+
+ /*
+ * Call tst_flush() flush any ouput in the buffer or the last
+ * result not printed because of CONDENSE mode.
+ */
+ tst_flush();
+
+ /*
+ * Mask out TRETR, TINFO, and TCONF results from the exit status.
+ */
+ exit(T_exitval & ~(TRETR | TINFO | TCONF));
+} /* tst_exit() */
+
+
+/*
+ * tst_environ() - Preserve the tst_res() output location, despite any
+ * changes to stdout.
+ */
+int
+tst_environ()
+{
+ FILE *fdopen();
+
+ if ( (T_out = fdopen(dup(fileno(stdout)), "w")) == NULL )
+ return(-1);
+ else
+ return(0);
+} /* tst_environ() */
+
+
+/*
+ * tst_brk() - Fail or break current test case, and break the remaining
+ * tests cases.
+ */
+void
+tst_brk(int ttype, char *fname, void (*func)(), char *arg_fmt, ...)
+{
+ char tmesg[USERMESG]; /* expanded message */
+
+#if DEBUG
+ printf("IN tst_brk\n"); fflush(stdout);
+ fflush(stdout);
+#endif
+
+ /*
+ * Expand the arg_fmt string into tmesg, if necessary.
+ */
+ EXPAND_VAR_ARGS(arg_fmt, tmesg);
+
+ /*
+ * Only FAIL, BROK, CONF, and RETR are supported by tst_brk().
+ */
+ if ( ttype != TFAIL && ttype != TBROK && ttype != TCONF &&
+ ttype != TRETR ) {
+ sprintf(Warn_mesg, "tst_brk(): Invalid Type: %d. Using TBROK",
+ ttype);
+ tst_print(TCID, 0, 1, TWARN, Warn_mesg);
+ ttype = TBROK;
+ }
+
+ /*
+ * Print the first result, if necessary.
+ */
+ if ( Tst_count < TST_TOTAL )
+ tst_res(ttype, fname, tmesg);
+
+ /*
+ * Determine the number of results left to report.
+ */
+ Tst_range = TST_TOTAL - Tst_count;
+
+ /*
+ * Print the rest of the results, if necessary.
+ */
+ if ( Tst_range > 0 ) {
+ if ( ttype == TCONF )
+ tst_res(ttype, NULL,
+ "Remaining cases not appropriate for configuration");
+ else if ( ttype == TRETR )
+ tst_res(ttype, NULL, "Remaining cases retired");
+ else
+ tst_res(TBROK, NULL, "Remaining cases broken");
+ } else {
+ Tst_range = 1;
+ Expand_varargs = TRUE;
+ } /* if ( Tst_range > 0 ) */
+
+ /*
+ * If no cleanup function was specified, just return to the caller.
+ * Otherwise call the specified function. If specified function
+ * returns, call tst_exit().
+ */
+ if ( func != NULL ) {
+ (*func)();
+ tst_exit();
+ }
+
+ return;
+} /* tst_brk() */
+
+
+/*
+ * tst_brkloop() - Fail or break current test case, and break the
+ * remaining test cases within test case loop.
+ */
+void
+tst_brkloop(int ttype, char *fname, void (*func)(), char *arg_fmt, ...)
+{
+ char tmesg[USERMESG]; /* expanded message */
+
+#if DEBUG
+ printf("IN tst_brkloop\n"); fflush(stdout);
+ fflush(stdout);
+#endif
+
+ /*
+ * Expand the arg_fmt string into tmesg.
+ */
+ EXPAND_VAR_ARGS(arg_fmt, tmesg);
+
+ /*
+ * Verify that Tst_lpstart & Tst_lptotal are valid.
+ */
+ if ( Tst_lpstart < 0 || Tst_lptotal < 0 ) {
+ tst_print(TCID, 0, 1, TWARN,
+ "tst_brkloop(): Tst_lpstart & Tst_lptotal must both be assigned non-negative values");
+ Expand_varargs = TRUE;
+ return;
+ }
+
+ /*
+ * Only FAIL, BROK, CONF, and RETR are supported by tst_brkloop().
+ */
+ if ( ttype != TFAIL && ttype != TBROK && ttype != TCONF &&
+ ttype != TRETR ) {
+ sprintf(Warn_mesg,
+ "tst_brkloop(): Invalid Type: %d. Using TBROK",
+ ttype);
+ tst_print(TCID, 0, 1, TWARN, Warn_mesg);
+ ttype = TBROK;
+ }
+
+ /*
+ * Print the first result, if necessary.
+ */
+ if ( Tst_count < Tst_lpstart + Tst_lptotal )
+ tst_res(ttype, fname, tmesg);
+
+ /*
+ * Determine the number of results left to report.
+ */
+ Tst_range = Tst_lptotal + Tst_lpstart - Tst_count;
+
+ /*
+ * Print the rest of the results, if necessary.
+ */
+ if ( Tst_range > 0 ) {
+ if ( ttype == TCONF )
+ tst_res(ttype, NULL,
+ "Remaining cases in loop not appropriate for configuration");
+ else if ( ttype == TRETR )
+ tst_res(ttype, NULL, "Remaining cases in loop retired");
+ else
+ tst_res(TBROK, NULL, "Remaining cases in loop broken");
+ } else {
+ Tst_range = 1;
+ Expand_varargs = TRUE;
+ } /* if ( Tst_range > 0 ) */
+
+ /*
+ * If a cleanup function was specified, call it.
+ */
+ if ( func != NULL )
+ (*func)();
+} /* tst_brkloop() */
+
+
+/*
+ * tst_resm() - Interface to tst_res(), with no filename.
+ */
+void
+tst_resm(int ttype, char *arg_fmt, ...)
+{
+ char tmesg[USERMESG]; /* expanded message */
+
+#if DEBUG
+ printf("IN tst_resm\n"); fflush(stdout);
+ fflush(stdout);
+#endif
+
+ /*
+ * Expand the arg_fmt string into tmesg.
+ */
+ EXPAND_VAR_ARGS(arg_fmt, tmesg);
+
+ /*
+ * Call tst_res with a null filename argument.
+ */
+ tst_res(ttype, NULL, tmesg);
+} /* tst_resm() */
+
+
+/*
+ * tst_brkm() - Interface to tst_brk(), with no filename.
+ */
+void
+tst_brkm(int ttype, void (*func)(), char *arg_fmt, ...)
+{
+ char tmesg[USERMESG]; /* expanded message */
+
+#if DEBUG
+ printf("IN tst_brkm\n"); fflush(stdout);
+ fflush(stdout);
+#endif
+
+ /*
+ * Expand the arg_fmt string into tmesg.
+ */
+ EXPAND_VAR_ARGS(arg_fmt, tmesg);
+
+ /*
+ * Call tst_brk with a null filename argument.
+ */
+ tst_brk(ttype, NULL, func, tmesg);
+} /* tst_brkm() */
+
+
+/*
+ * tst_brkloopm() - Interface to tst_brkloop(), with no filename.
+ */
+void
+tst_brkloopm(int ttype, void (*func)(), char *arg_fmt, ...)
+{
+ char tmesg[USERMESG]; /* expanded message */
+
+#if DEBUG
+ printf("IN tst_brkloopm\n");
+ fflush(stdout);
+#endif
+
+ /*
+ * Expand the arg_fmt string into tmesg.
+ */
+ EXPAND_VAR_ARGS(arg_fmt, tmesg);
+
+ /*
+ * Call tst_brkloop with a null filename argument.
+ */
+ tst_brkloop(ttype, NULL, func, tmesg);
+} /* tst_brkloopm() */
+
+
+/*
+ * cat_file() - Print the contents of a file to standard out.
+ */
+static void
+cat_file(char *filename)
+{
+ FILE *fp; /* file pointer */
+ int b_read; /* number of bytes read with read() */
+ int b_written; /* number of bytes written with write() */
+ char buffer[BUFSIZ]; /* read/write buffer; BUFSIZ defined in */
+ /* stdio.h */
+
+#if DEBUG
+ printf("IN cat_file\n"); fflush(stdout);
+#endif
+
+ /*
+ * Open the file for reading.
+ */
+ if ( (fp = fopen(filename, "r")) == NULL ) {
+ sprintf(Warn_mesg,
+ "tst_res(): fopen(%s, \"r\") failed; errno = %d: %s",
+ filename, errno, strerror(errno));
+ tst_print(TCID, 0, 1, TWARN, Warn_mesg);
+ return;
+ } /* if ( fopen(filename, "r") == -1 ) */
+
+ /*
+ * While something to read, continue to read blocks.
+ * From fread(3) man page:
+ * If an error occurs, or the end-of-file is reached, the return
+ * value is zero.
+ */
+ errno = 0;
+ while ( (b_read = fread((void *)buffer, 1, BUFSIZ, fp)) != (size_t)0 ) {
+ /*
+ * Write what was read to the result output stream.
+ */
+ if ( (b_written = fwrite((void *)buffer, 1, b_read, T_out)) !=
+ b_read ) {
+ sprintf(Warn_mesg,
+ "tst_res(): While trying to cat \"%s\", fwrite() wrote only %d of %d bytes",
+ filename, b_written, b_read);
+ tst_print(TCID, 0, 1, TWARN, Warn_mesg);
+ break;
+ } /* if ( b_written != b_read ) */
+ } /* while ( fread() != 0 ) */
+
+ /*
+ * Check for an fread() error.
+ */
+ if ( !feof(fp) ) {
+ sprintf(Warn_mesg,
+ "tst_res(): While trying to cat \"%s\", fread() failed, errno = %d: %s",
+ filename, errno, strerror(errno));
+ tst_print(TCID, 0, 1, TWARN, Warn_mesg);
+ } /* if ( !feof() ) */
+
+ /*
+ * Close the file.
+ */
+ if ( fclose(fp) == EOF ) {
+ sprintf(Warn_mesg,
+ "tst_res(): While trying to cat \"%s\", fclose() failed, errno = %d: %s",
+ filename, errno, strerror(errno));
+ tst_print(TCID, 0, 1, TWARN, Warn_mesg);
+ } /* if ( fclose(fp) == EOF ) */
+} /* cat_file() */
+
+
+
+#ifdef UNIT_TEST
+/****************************************************************************
+ * Unit test code: Takes input from stdin and can make the following
+ * calls: tst_res(), tst_resm(), tst_brk(), tst_brkm(),
+ * tst_flush_buf(), tst_exit().
+ ****************************************************************************/
+int TST_TOTAL = 10;
+char *TCID = "TESTTCID";
+
+#define RES "tst_res.c UNIT TEST message; ttype = %d; contents of \"%s\":"
+#define RESM "tst_res.c UNIT TEST message; ttype = %d"
+
+main()
+{
+ int ttype;
+ int range;
+ char *chrptr;
+ char chr;
+ char fname[MAXMESG];
+
+ printf("UNIT TEST of tst_res.c. Options for ttype:\n\
+ -1 : call tst_exit()\n\
+ -2 : call tst_flush()\n\
+ -3 : call tst_brk()\n\
+ -4 : call tst_brkloop()\n\
+ -5 : call tst_res() with a range\n\
+ 0 : call tst_res(TPASS, ...)\n\
+ 1 : call tst_res(TFAIL, ...)\n\
+ 2 : call tst_res(TBROK, ...)\n\
+ 4 : call tst_res(TWARN, ...)\n\
+ 8 : call tst_res(TRETR, ...)\n\
+ 16 : call tst_res(TINFO, ...)\n\
+ 32 : call tst_res(TCONF, ...)\n\n");
+
+ while ( 1 ) {
+ printf("Enter ttype (-5,-4,-3,-2,-1,0,1,2,4,8,16,32): ");
+ (void) scanf("%d%c", &ttype, &chr);
+
+
+ switch ( ttype ) {
+ case -1:
+ tst_exit();
+ break;
+
+ case -2:
+ tst_flush();
+ break;
+
+ case -3:
+ printf("Enter the current type (1=FAIL, 2=BROK, 8=RETR, 32=CONF): ");
+ (void) scanf("%d%c", &ttype, &chr);
+ printf("Enter file name (<cr> for none): ");
+ gets(fname);
+ if ( strcmp(fname, "") == 0 )
+ tst_brkm(ttype, tst_exit, RESM, ttype);
+ else
+ tst_brk(ttype, fname, tst_exit, RES, ttype, fname);
+ break;
+
+ case -4:
+ printf("Enter the size of the loop: ");
+ (void) scanf("%d%c", &range, &chr);
+ Tst_lpstart = Tst_count;
+ Tst_lptotal = range;
+ printf("Enter the current type (1=FAIL, 2=BROK, 8=RETR, 32=CONF): ");
+ (void) scanf("%d%c", &ttype, &chr);
+ printf("Enter file name (<cr> for none): ");
+ gets(fname);
+ if ( strcmp(fname, "") == 0 )
+ tst_brkloopm(ttype, NULL, RESM, ttype);
+ else
+ tst_brkloop(ttype, fname, NULL, RES, ttype, fname);
+ break;
+
+ case -5:
+ printf("Enter the size of the range: ");
+ (void) scanf("%d%c", &Tst_range, &chr);
+ printf("Enter the current type (0,1,2,4,8,16,32): ");
+ (void) scanf("%d%c", &ttype, &chr);
+ /* fall through to tst_res() call */
+
+ default:
+ printf("Enter file name (<cr> for none): ");
+ gets(fname);
+ if ( strcmp(fname, "") == 0 )
+ tst_resm(ttype, RESM, ttype);
+ else
+ tst_res(ttype, fname, RES, ttype, fname);
+ break;
+ } /* switch() */
+ } /* while() */
+}
+#endif /* UNIT_TEST */
diff --git a/lib/tst_sig.c b/lib/tst_sig.c
new file mode 100644
index 0000000..090a946
--- /dev/null
+++ b/lib/tst_sig.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
+ */
+
+/* $Id: tst_sig.c,v 1.1 2000/07/27 17:13:19 alaffin Exp $ */
+
+/*****************************************************************************
+ OS Testing - Silicon Graphics, Inc.
+
+ FUNCTION IDENTIFIER : tst_sig Set up for unexpected signals.
+
+ AUTHOR : David D. Fenner
+
+ CO-PILOT : Bill Roske
+
+ DATE STARTED : 06/06/90
+
+ This module may be linked with c-modules requiring unexpected
+ signal handling. The parameters to tst_sig are as follows:
+
+ fork_flag - set to FORK or NOFORK depending upon whether the
+ calling program executes a fork() system call. It
+ is normally the case that the calling program treats
+ SIGCLD as an expected signal if fork() is being used.
+
+ handler - a pointer to the unexpected signal handler to
+ be executed after an unexpected signal has been
+ detected. If handler is set to DEF_HANDLER, a
+ default handler is used. This routine should be
+ declared as function returning an int.
+
+ cleanup - a pointer to a cleanup routine to be executed
+ by the unexpected signal handler before tst_exit is
+ called. This parameter is set to NULL if no cleanup
+ routine is required. An external variable, T_cleanup
+ is set so that other user-defined handlers have
+ access to the cleanup routine. This routine should be
+ declared as returning type void.
+
+***************************************************************************/
+
+#ifndef CRAY
+#define _BSD_SIGNALS 1 /* Specify that we are using BSD signal interface */
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include "test.h"
+
+#define MAXMESG 150 /* size of mesg string sent to tst_res */
+
+void (*T_cleanup)(); /* pointer to cleanup function */
+
+extern int errno;
+static void def_handler(); /* default signal handler */
+
+/****************************************************************************
+ * tst_sig() : set-up to catch unexpected signals. fork_flag is set to NOFORK
+ * if SIGCLD is to be an "unexpected signal", otherwise it is set to
+ * FORK. cleanup points to a cleanup routine to be executed before
+ * tst_exit is called (cleanup is set to NULL if no cleanup is desired).
+ * handler is a pointer to the signal handling routine (if handler is
+ * set to NULL, a default handler is used).
+ ***************************************************************************/
+
+void
+tst_sig(fork_flag, handler, cleanup)
+int fork_flag; /* FORK if SIGCLD is expected, NOFORK if unexpected */
+void (*handler)(); /* pointer to signal handler routine or DEF_HANDLER */
+void (*cleanup)(); /* pointer to cleanup routine or NULL */
+{
+ extern char *TCID; /* test case id string (in calling prog) */
+
+ char mesg[MAXMESG]; /* message buffer for tst_res */
+ int sig;
+
+ /*
+ * save T_cleanup and handler function pointers
+ */
+ T_cleanup = cleanup; /* used by default handler */
+
+ if (handler == DEF_HANDLER) {
+ /* use default handler */
+ handler = def_handler;
+ }
+
+ /*
+ * now loop through all signals and set the handlers
+ */
+
+ for (sig = 1; sig < NSIG; sig++) {
+ /*
+ * SIGKILL is never unexpected.
+ * SIGCLD is only unexpected when
+ * no forking is being done.
+ * SIGINFO is used for file quotas and should be expected
+ */
+
+ switch (sig) {
+ case SIGKILL:
+ case SIGSTOP:
+ case SIGCONT:
+#ifdef CRAY
+ case SIGINFO:
+ case SIGRECOVERY: /* allow chkpnt/restart */
+#endif /* CRAY */
+
+#ifdef SIGSWAP
+ case SIGSWAP:
+#endif /* SIGSWAP */
+
+#ifdef SIGCKPT
+ case SIGCKPT:
+#endif
+#ifdef SIGRESTART
+ case SIGRESTART:
+#endif
+ /*
+ * pthread-private signals SIGPTINTR and SIGPTRESCHED.
+ * Setting a handler for these signals is disallowed when
+ * the binary is linked against libpthread.
+ */
+#ifdef SIGPTINTR
+ case SIGPTINTR:
+#endif /* SIGPTINTR */
+#ifdef SIGPTRESCHED
+ case SIGPTRESCHED:
+#endif /* SIGPTRESCHED */
+
+ break;
+
+ case SIGCLD:
+ if ( fork_flag == FORK )
+ continue;
+
+ default:
+ if (signal(sig, handler) == SIG_ERR) {
+ (void) sprintf(mesg,
+ "signal() failed for signal %d. error:%d %s.",
+ sig, errno, strerror(errno));
+ tst_resm(TWARN, mesg);
+ }
+ break;
+ }
+#ifdef __sgi
+ /* On irix (07/96), signal() fails when signo is 33 or higher */
+ if ( sig+1 >= 33 )
+ break;
+#endif /* __sgi */
+
+ } /* endfor */
+}
+
+
+
+/****************************************************************************
+ * def_handler() : default signal handler that is invoked when
+ * an unexpected signal is caught.
+ ***************************************************************************/
+
+static void
+def_handler(sig)
+int sig; /* signal that caused the interrupt */
+{
+ extern int Tst_count; /* number of items completed (in tst_res.c) */
+ extern int TST_TOTAL; /* total number of test items (in calling prog) */
+ char mesg[MAXMESG]; /* holds tst_res message */
+
+ /* first reset trap for this signal (except SIGCLD - its weird) */
+ if ((sig != SIGCLD) && (sig != SIGSTOP) && (sig != SIGCONT)) {
+ if (signal(sig, def_handler) == SIG_ERR) {
+ (void) sprintf(mesg,
+ "def_handler: signal() failed for signal %d. error:%d %s.",
+ sig, errno, strerror(errno));
+ tst_resm(TWARN, mesg);
+ }
+ }
+
+ (void) sprintf(mesg, "Unexpected signal %d received.", sig);
+
+ /*
+ * Break remaining test cases, do any cleanup, then exit
+ */
+ tst_brkm(TBROK, 0, mesg);
+
+ /* now cleanup and exit */
+ if (T_cleanup) {
+ (*T_cleanup)();
+ }
+
+ tst_exit();
+}
diff --git a/lib/tst_tmpdir.c b/lib/tst_tmpdir.c
new file mode 100644
index 0000000..e036609
--- /dev/null
+++ b/lib/tst_tmpdir.c
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it would be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Further, this software is distributed without any warranty that it is
+ * free of the rightful claim of any third person regarding infringement
+ * or the like. Any license provided herein, whether implied or
+ * otherwise, applies only to this software file. Patent licenses, if
+ * any, provided herein do not apply to combinations of this program with
+ * other software, or any other product whatsoever.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
+ * Mountain View, CA 94043, or:
+ *
+ * http://www.sgi.com
+ *
+ * For further information regarding this notice, see:
+ *
+ * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
+ */
+
+/* $Id: tst_tmpdir.c,v 1.1 2000/07/27 17:13:19 alaffin Exp $ */
+
+/**********************************************************
+ *
+ * OS Testing - Silicon Graphics, Inc.
+ *
+ * FUNCTION NAME : tst_tmpdir, tst_rmdir
+ *
+ * FUNCTION TITLE : Create/remove a testing temp dir
+ *
+ * SYNOPSIS:
+ * void tst_tmpdir();
+ * void tst_rmdir();
+ *
+ * AUTHOR : Dave Fenner
+ *
+ * INITIAL RELEASE : UNICOS 8.0
+ *
+ * DESCRIPTION
+ * tst_tmpdir() is used to create a unique, temporary testing
+ * directory, and make it the current working directory.
+ * tst_rmdir() is used to remove the directory created by
+ * tst_tmpdir().
+ *
+ * Setting the env variable "TDIRECTORY" will override the creation
+ * of a new temp dir. The directory specified by TDIRECTORY will
+ * be used as the temporary directory, and no removal will be done
+ * in tst_rmdir().
+ *
+ * RETURN VALUE
+ * Neither tst_tmpdir() or tst_rmdir() has a return value.
+ *
+ *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h> /* for getenv() */
+#include <string.h> /* for string functions */
+#include <unistd.h> /* for sysconf(), getcwd(), rmdir() */
+#include <sys/types.h> /* for mkdir() */
+#include <sys/stat.h> /* for mkdir() */
+#include "test.h"
+#include "rmobj.h"
+
+/*
+ * Define some useful macros.
+ */
+#define PREFIX_SIZE 4
+#define STRING_SIZE 256
+#define DIR_MODE 0777 /* mode of tmp dir that will be created */
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
+/*
+ * Define function prototypes.
+ */
+static void tmpdir_cleanup();
+
+/*
+ * Define global variables.
+ */
+extern char *TCID; /* defined/initialized in main() */
+extern int TST_TOTAL; /* defined/initialized in main() */
+extern char *TESTDIR; /* the directory created; defined in */
+ /* tst_res.c */
+
+/*
+ * tst_tmpdir() - Create a unique temporary directory and chdir() to it.
+ * It expects the caller to have defined/initialized the
+ * TCID/TST_TOTAL global variables. The TESTDIR global
+ * variable will be set to the directory that gets used
+ * as the testing directory.
+ *
+ * NOTE: This function must be called BEFORE any activity
+ * that would require CLEANUP. If tst_tmpdir() fails, it
+ * cleans up afer itself and calls tst_exit() (i.e. does
+ * not return).
+ */
+#undef FN_NAME
+#define FN_NAME "tst_tmpdir()"
+
+void
+tst_tmpdir()
+{
+ char prefix[PREFIX_SIZE]; /* first three characters from TCID */
+ int no_cleanup = 0; /* !0 means TDIRECTORY env var was set */
+
+ /*
+ * If the TDIRECTORY env variable is not set, a temp dir will be
+ * created.
+ */
+ if ( (TESTDIR = getenv(TDIRECTORY)) == NULL ) {
+ /*
+ * Create a unique name based on the first three characters of the
+ * TCID. The last byte in "prefix" is for the null.
+ */
+ strncpy(prefix, TCID, PREFIX_SIZE - 1);
+ prefix[PREFIX_SIZE-1] = '\0';
+ if ( (TESTDIR = tempnam(TEMPDIR, prefix)) == NULL )
+ tst_brkm(TBROK, tmpdir_cleanup, "%s: tempnam(%s, %s) failed",
+ FN_NAME, TEMPDIR, prefix);
+
+ /*
+ * Create the temporary directory.
+ */
+ if ( mkdir(TESTDIR, DIR_MODE) == -1 )
+ tst_brkm(TBROK, tmpdir_cleanup,
+ "%s: mkdir(%s, %#o) failed; errno = %d: %s",
+ FN_NAME, TESTDIR, DIR_MODE, errno, strerror(errno));
+
+ /*
+ * Change the group on this temporary directory to be that of the
+ * gid of the person running the tests.
+ */
+ if ( chown(TESTDIR, -1, getgid()) == -1 )
+ tst_brkm(TBROK, tmpdir_cleanup,
+ "chown(%s, -1, %d) failed; errno = %d: %s",
+ TESTDIR, getgid(), errno, strerror(errno));
+ } else {
+ /*
+ * The TDIRECTORY env. variable is set, so no temp dir is created.
+ * Also, no clean up will be done via tst_rmdir().
+ */
+ no_cleanup++;
+#if UNIT_TEST
+ printf("TDIRECTORY env var is set\n");
+#endif
+ }
+
+#if UNIT_TEST
+ printf("TESTDIR = %s\n", TESTDIR);
+#endif
+
+ /*
+ * Change to the temporary directory. If the chdir() fails, issue
+ * TBROK messages for all test cases, attempt to remove the
+ * directory (if it was created), and exit. If the removal also
+ * fails, also issue a TWARN message.
+ */
+ if ( chdir(TESTDIR) == -1 ) {
+ tst_brkm(TBROK, NULL, "%s: chdir(%s) failed; errno = %d: %s",
+ FN_NAME, TESTDIR, errno, strerror(errno) );
+
+ /* Try to remove the directory */
+ if ( !no_cleanup && rmdir(TESTDIR) == -1 )
+ tst_resm(TWARN, "%s: rmdir(%s) failed; errno = %d: %s",
+ FN_NAME, TESTDIR, errno, strerror(errno) );
+
+ tmpdir_cleanup();
+ }
+
+#if UNIT_TEST
+ printf("CWD is %s\n", getcwd((char *)NULL, PATH_MAX));
+#endif
+
+ /*
+ * If we made through all this stuff, return.
+ */
+ return;
+} /* tst_tmpdir() */
+
+
+/*
+ *
+ * tst_rmdir() - Recursively remove the temporary directory created by
+ * tst_tmpdir(). This function is intended ONLY as a
+ * companion to tst_tmpdir(). If the TDIRECTORY
+ * environment variable is set, no cleanup will be
+ * attempted.
+ */
+#undef FN_NAME
+#define FN_NAME "tst_rmdir()"
+
+void
+tst_rmdir()
+{
+ char *errmsg;
+ char *tdirectory;
+ char current_dir[PATH_MAX]; /* current working directory */
+ char parent_dir[PATH_MAX]; /* directory above TESTDIR */
+ char *basename; /* basename of the TESTDIR */
+
+ /*
+ * If the TDIRECTORY env variable is set, this indicates that no
+ * temp dir was created by tst_tmpdir(). Thus no cleanup will be
+ * necessary.
+ */
+ if ( (tdirectory = getenv(TDIRECTORY)) != NULL ) {
+#if UNIT_TEST
+ printf("\"TDIRECORY\" env variable is set; no cleanup was performed\n");
+#endif
+ return;
+ }
+
+ /*
+ * Check that TESTDIR is not NULL.
+ */
+ if ( TESTDIR == NULL ) {
+ tst_resm(TWARN, "%s: TESTDIR was NULL; no removal attempted",
+ FN_NAME);
+ return;
+ }
+
+ /*
+ * Check that the value of TESTDIR is not "*" or "/". These could
+ * have disastrous effects in a test run by root.
+ */
+ if ( strcmp(TESTDIR, "/") == 0 ) {
+ tst_resm(TWARN,
+ "%s: Recursive remove of root directory not attempted",
+ FN_NAME);
+ return;
+ }
+
+ if ( strchr(TESTDIR, '*') != NULL ) {
+ tst_resm(TWARN, "%s: Recursive remove of '*' not attempted",
+ FN_NAME);
+ return;
+ }
+
+ /*
+ * Get the directory name of TESTDIR. If TESTDIR is a relative path,
+ * get full path.
+ */
+ if ( TESTDIR[0] != '/' ) {
+ if ( getcwd(current_dir,PATH_MAX) == NULL )
+ strcpy(parent_dir, TESTDIR);
+ else
+ sprintf(parent_dir, "%s/%s", current_dir, TESTDIR);
+ } else {
+ strcpy(parent_dir, TESTDIR);
+ }
+ if ( (basename = strrchr(parent_dir, '/')) != NULL ) {
+ *basename='\0'; /* terminate at end of parent_dir */
+ }
+
+ /*
+ * Change directory to parent_dir (The dir above TESTDIR).
+ */
+ if ( chdir(parent_dir) != 0 )
+ tst_resm(TWARN,
+ "%s: chdir(%s) failed; errno = %d: %s\nAttempting to remove temp dir anyway",
+ FN_NAME, parent_dir, errno, strerror(errno));
+
+ /*
+ * Attempt to remove the "TESTDIR" directory, using rmobj().
+ */
+ if ( rmobj(TESTDIR, &errmsg) == -1 )
+ tst_resm(TWARN, "%s: rmobj(%s) failed: %s",
+ FN_NAME, TESTDIR, errmsg);
+
+ return;
+} /* tst_rmdir() */
+
+
+/*
+ * tmpdir_cleanup() - This function is used when tst_tmpdir()
+ * encounters an error, and must cleanup and exit.
+ * It prints a warning message via tst_resm(), and
+ * then calls tst_exit().
+ */
+#undef FN_NAME
+#define FN_NAME "tst_tmpdir()"
+
+static void
+tmpdir_cleanup()
+{
+ /*
+ * Print a warning message and call tst_exit() to exit the test.
+ */
+ tst_resm(TWARN, "%s: No user cleanup function called before exiting",
+ FN_NAME);
+ tst_exit();
+} /* tmpdir_cleanup() */
+
+
+#ifdef UNIT_TEST
+/****************************************************************************
+ * Unit test code: Takes input from stdin and can make the following
+ * calls: tst_tmpdir(), tst_rmdir().
+ ****************************************************************************/
+int TST_TOTAL = 10;
+char *TCID = "TESTTCID";
+
+main()
+{
+ int option;
+ char *chrptr;
+
+ printf("UNIT TEST of tst_tmpdir.c. Options to try:\n\
+ -1 : call tst_exit()\n\
+ 0 : call tst_tmpdir()\n\
+ 1 : call tst_rmdir()\n\n");
+
+ while ( 1 ) {
+ printf("Enter options (-1, 0, 1): ");
+ (void) scanf("%d%c", &option, &chrptr);
+
+ switch ( option ) {
+ case -1:
+ tst_exit();
+ break;
+
+ case 0:
+ tst_tmpdir();
+ break;
+
+ case 1:
+ tst_rmdir();
+ break;
+ } /* switch() */
+ } /* while() */
+}
+#endif /* UNIT_TEST */