summaryrefslogtreecommitdiff
path: root/regress/lib/libc
diff options
context:
space:
mode:
authorMarco S Hyman <marc@cvs.openbsd.org>2001-12-17 02:36:01 +0000
committerMarco S Hyman <marc@cvs.openbsd.org>2001-12-17 02:36:01 +0000
commitdb612c31eaea51b5134b19e147280173de6e12ab (patch)
treecdfab831261dfe8690860b3ee27e5f548530b694 /regress/lib/libc
parenteb940cb3b8cab72c5de6adfd3de13bcaa92491a6 (diff)
sigreturn test program
Diffstat (limited to 'regress/lib/libc')
-rw-r--r--regress/lib/libc/sigreturn/Makefile16
-rw-r--r--regress/lib/libc/sigreturn/sigret.c168
2 files changed, 184 insertions, 0 deletions
diff --git a/regress/lib/libc/sigreturn/Makefile b/regress/lib/libc/sigreturn/Makefile
new file mode 100644
index 00000000000..6a40c40fe0c
--- /dev/null
+++ b/regress/lib/libc/sigreturn/Makefile
@@ -0,0 +1,16 @@
+# $OpenBSD: Makefile,v 1.1 2001/12/17 02:36:00 marc Exp $
+
+PROG= sigret
+SRCS= sigret.c
+NOMAN= noman
+
+DEBUG+= -ggdb
+
+.PATH: ${.CURDIR}/../sigret
+
+install:
+
+regress: ${PROG}
+ ./${PROG}
+
+.include <bsd.prog.mk>
diff --git a/regress/lib/libc/sigreturn/sigret.c b/regress/lib/libc/sigreturn/sigret.c
new file mode 100644
index 00000000000..bd661a3649c
--- /dev/null
+++ b/regress/lib/libc/sigreturn/sigret.c
@@ -0,0 +1,168 @@
+/*
+ * Playing games with sigreturn. Check if calling sigreturn from a
+ * signal handler screws anything up.
+ *
+ * Run with:
+ * -a: use an alternate signal stack
+ *
+ * -b: call sigreturn from outside of a signal handler
+ * An error is OK
+ *
+ * -c: clobber the sigcontext before calling sigreturn
+ * the program should die
+ *
+ * -f: don't use sigreturn -- fall through the signal handler
+ * -c, and -i options ignored when used
+ *
+ * -i: call sigreturn from a function called by the signal handler
+ *
+ * Program should not exit until killed.
+ */
+
+#include <sys/time.h>
+
+#include <err.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+int altstack;
+int badcall;
+int clobbercall;
+int fallthru;
+int indirect;
+
+volatile int count;
+struct sigcontext gscp;
+int gscp_loaded;
+
+static void
+usage(const char * err, ...)
+{
+ extern const char * __progname;
+
+ if (err) {
+ va_list ap;
+ va_start(ap, err);
+ vwarnx(err, ap);
+ va_end(ap);
+ }
+ fprintf(stderr, "usage: %s [-abcfi]\n", __progname);
+ exit(1);
+}
+
+void
+indirect_return(struct sigcontext * scp)
+{
+ sigreturn(scp);
+}
+
+void
+sig_handler(int sig, siginfo_t *blah, void *x)
+{
+ struct sigcontext * scp = x;
+
+ count++;
+
+ if (!fallthru) {
+ if (clobbercall)
+ memset(scp, 0, sizeof *scp);
+ if (indirect)
+ indirect_return(scp);
+ else if (badcall) {
+ gscp = *scp;
+ gscp_loaded = 1;
+ } else
+ sigreturn(scp);
+ }
+}
+
+void
+test2(char *fmt)
+{
+ char *ofmt = fmt;
+
+ if (gscp_loaded) {
+ gscp_loaded = 0;
+ sigreturn(&gscp);
+ }
+
+ for (; *fmt; fmt++)
+ switch (*fmt) {
+ case 'i':
+ case 'c':
+ case 'l':
+ case 'p':
+ break;
+ default:
+ fprintf(stderr,
+ "unexpected character 0x%02x `%c' in %s: count %d\n",
+ *fmt, *fmt, ofmt, count);
+ }
+}
+
+int
+main(int argc, char * argv[])
+{
+ extern char *optarg;
+ extern int optind;
+
+ int opt;
+
+ struct sigaction act;
+ struct sigaltstack ss;
+
+ while ((opt = getopt(argc, argv, "abcfi")) != -1) {
+ switch (opt) {
+ case 'a':
+ /* use sigaltstack */
+ altstack = 1;
+ break;
+ case 'b':
+ /* call outside of sig_handler */
+ badcall = 1;
+ break;
+ case 'c':
+ /* force error by munging sigcontext */
+ clobbercall = 1;
+ break;
+ case 'f':
+ /* don't use sigreturn */
+ fallthru = 1;
+ break;
+ case 'i':
+ /* call sigreturn indirectly */
+ indirect = 1;
+ break;
+ }
+ }
+
+ /* make sure there is no other cruft left on the command line */
+ if (optind != argc)
+ usage("unknown arguement -- %s", argv[ optind ]);
+
+ if (altstack) {
+ if ((ss.ss_sp = malloc(SIGSTKSZ)) == NULL)
+ errx(1, "ss_sp malloc");
+
+ ss.ss_size = SIGSTKSZ;
+ ss.ss_flags = 0;
+ if (sigaltstack(&ss,0) == -1)
+ err(1, "sigaltstack");
+ }
+
+ sigfillset(&act.sa_mask);
+ act.sa_sigaction = sig_handler;
+ act.sa_flags = SA_RESTART;
+ if (altstack)
+ act.sa_flags |= SA_ONSTACK;
+ sigaction(SIGALRM, &act, NULL);
+
+ ualarm(10000, 10000);
+
+ while (1)
+ test2("iclp");
+}