summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.bin/sendbug/Makefile7
-rw-r--r--usr.bin/sendbug/atomicio.c62
-rw-r--r--usr.bin/sendbug/atomicio.h39
-rw-r--r--usr.bin/sendbug/sendbug.147
-rw-r--r--usr.bin/sendbug/sendbug.c315
5 files changed, 470 insertions, 0 deletions
diff --git a/usr.bin/sendbug/Makefile b/usr.bin/sendbug/Makefile
new file mode 100644
index 00000000000..bfa4e82f116
--- /dev/null
+++ b/usr.bin/sendbug/Makefile
@@ -0,0 +1,7 @@
+# $OpenBSD: Makefile,v 1.1 2007/03/23 01:47:11 ray Exp $
+
+PROG=sendbug
+SRCS=atomicio.c sendbug.c
+COPTS+=-Wall -W
+
+.include <bsd.prog.mk>
diff --git a/usr.bin/sendbug/atomicio.c b/usr.bin/sendbug/atomicio.c
new file mode 100644
index 00000000000..8f2f2ee58c3
--- /dev/null
+++ b/usr.bin/sendbug/atomicio.c
@@ -0,0 +1,62 @@
+/* $OpenBSD: atomicio.c,v 1.1 2007/03/23 01:47:11 ray Exp $ */
+/*
+ * Copyright (c) 2006 Damien Miller. All rights reserved.
+ * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
+ * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <string.h>
+
+#include "atomicio.h"
+
+/*
+ * ensure all of data on socket comes through. f==read || f==vwrite
+ */
+size_t
+atomicio(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n)
+{
+ char *s = _s;
+ size_t pos = 0;
+ ssize_t res;
+
+ while (n > pos) {
+ res = (f) (fd, s + pos, n - pos);
+ switch (res) {
+ case -1:
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
+ return 0;
+ case 0:
+ errno = EPIPE;
+ return pos;
+ default:
+ pos += (size_t)res;
+ }
+ }
+ return (pos);
+}
diff --git a/usr.bin/sendbug/atomicio.h b/usr.bin/sendbug/atomicio.h
new file mode 100644
index 00000000000..72595dba99f
--- /dev/null
+++ b/usr.bin/sendbug/atomicio.h
@@ -0,0 +1,39 @@
+/* $OpenBSD: atomicio.h,v 1.1.1.1 2007/03/23 01:47:11 ray Exp $ */
+
+/*
+ * Copyright (c) 2006 Damien Miller. All rights reserved.
+ * Copyright (c) 1995,1999 Theo de Raadt. All rights reserved.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ATOMICIO_H
+#define _ATOMICIO_H
+
+/*
+ * Ensure all of data on socket comes through. f==read || f==vwrite
+ */
+size_t atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
+
+#define vwrite (ssize_t (*)(int, void *, size_t))write
+
+#endif /* _ATOMICIO_H */
diff --git a/usr.bin/sendbug/sendbug.1 b/usr.bin/sendbug/sendbug.1
new file mode 100644
index 00000000000..cea68d06f6c
--- /dev/null
+++ b/usr.bin/sendbug/sendbug.1
@@ -0,0 +1,47 @@
+.\" $OpenBSD: sendbug.1,v 1.1 2007/03/23 01:47:11 ray Exp $
+.\"
+.\" Written by Raymond Lai <ray@cyth.net>.
+.\" Public domain.
+.\"
+.Dd March 22, 2007
+.Dt SENDBUG 1
+.Os
+.Sh NAME
+.Nm sendbug
+.Nd report a bug in
+.Ox
+.Sh SYNOPSIS
+.Nm
+.Sh DESCRIPTION
+.Nm
+is used to send bug reports to
+.Ox .
+Some system information is filled out in a temporary file,
+which is then opened by an editor.
+See
+.Ev EDITOR
+below,
+for details of which editor, if any, is invoked.
+.Pp
+Once the bug report is filled out,
+it is e-mailed to the
+.Ox
+developers.
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev EDITOR
+Specifies an editor to use.
+If
+.Ev EDITOR
+is not set,
+the default is
+.Xr vi 1 .
+.It Ev TMPDIR
+Specifies a directory for temporary files to be created.
+The default is
+.Pa /tmp .
+.El
+.Sh AUTHORS
+.Nm
+was written from scratch for the public domain by
+.An Ray Lai Aq ray@cyth.net .
diff --git a/usr.bin/sendbug/sendbug.c b/usr.bin/sendbug/sendbug.c
new file mode 100644
index 00000000000..8a8e2850731
--- /dev/null
+++ b/usr.bin/sendbug/sendbug.c
@@ -0,0 +1,315 @@
+/* $OpenBSD: sendbug.c,v 1.1 2007/03/23 01:47:11 ray Exp $ */
+
+/*
+ * Written by Ray Lai <ray@cyth.net>.
+ * Public domain.
+ */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/wait.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "atomicio.h"
+
+int init(void);
+int prompt(void);
+int send_file(const char *, int dst);
+int sendmail(const char *);
+void template(FILE *);
+
+struct passwd *pw;
+const char *categories = "system user library documentation ports kernel "
+ "alpha amd64 arm i386 m68k m88k mips ppc sgi sparc sparc64 vax";
+char os[BUFSIZ], rel[BUFSIZ], mach[BUFSIZ];
+char *fullname;
+
+int
+main(int argc, char *argv[])
+{
+ struct stat sb;
+ FILE *fp;
+ const char *editor, *tmpdir;
+ char *tmppath = NULL;
+ time_t mtime;
+ int c, fd, ret = 1;
+
+ if ((tmpdir = getenv("TMPDIR")) == NULL || tmpdir[0] == '\0')
+ tmpdir = _PATH_TMP;
+ if (asprintf(&tmppath, "%s/p.XXXXXXXXXX", tmpdir) == -1) {
+ warn("asprintf");
+ goto quit;
+ }
+ if ((fd = mkstemp(tmppath)) == -1)
+ err(1, "mkstemp");
+ if ((fp = fdopen(fd, "w+")) == NULL) {
+ warn("fdopen");
+ goto cleanup;
+ }
+
+ if (init() == -1)
+ goto cleanup;
+
+ template(fp);
+
+ if (fflush(fp) == EOF || fstat(fd, &sb) == -1 || fclose(fp) == EOF) {
+ warn("error creating template");
+ goto cleanup;
+ }
+ mtime = sb.st_mtime;
+
+ edit:
+ if ((editor = getenv("EDITOR")) == NULL)
+ editor = "vi";
+ switch (fork()) {
+ case -1:
+ warn("fork");
+ goto cleanup;
+ case 0:
+ execlp(editor, editor, tmppath, NULL);
+ err(1, "execlp");
+ default:
+ wait(NULL);
+ break;
+ }
+
+ if (stat(tmppath, &sb) == -1) {
+ warn("stat");
+ goto cleanup;
+ }
+ if (mtime == sb.st_mtime) {
+ warnx("report unchanged, nothing sent");
+ goto cleanup;
+ }
+
+ prompt:
+ c = prompt();
+ switch (c) {
+ case 'a': case EOF:
+ warnx("unsent report in %s", tmppath);
+ goto quit;
+ case 'e':
+ goto edit;
+ case 's':
+ if (sendmail(tmppath) == -1)
+ goto quit;
+ break;
+ default:
+ goto prompt;
+ }
+
+ ret = 0;
+
+ cleanup:
+ if (tmppath && unlink(tmppath) == -1)
+ warn("unlink");
+
+ quit:
+ return (ret);
+}
+
+int
+prompt(void)
+{
+ int c, ret;
+
+ fpurge(stdin);
+ fprintf(stderr, "a)bort, e)dit, or s)end: ");
+ fflush(stderr);
+ ret = getchar();
+ if (ret == EOF || ret == '\n')
+ return (ret);
+ do {
+ c = getchar();
+ } while (c != EOF && c != '\n');
+ return (ret);
+}
+
+int
+sendmail(const char *tmppath)
+{
+ int filedes[2];
+
+ if (pipe(filedes) == -1) {
+ warn("pipe: unsent report in %s", tmppath);
+ return (-1);
+ }
+ switch (fork()) {
+ case -1:
+ warn("fork error: unsent report in %s",
+ tmppath);
+ return (-1);
+ case 0:
+ close(filedes[1]);
+ if (dup2(filedes[0], STDIN_FILENO) == -1) {
+ warn("dup2 error: unsent report in %s",
+ tmppath);
+ return (-1);
+ }
+ close(filedes[0]);
+ execl("/usr/sbin/sendmail", "sendmail",
+ "-oi", "-t", NULL);
+ warn("sendmail error: unsent report in %s",
+ tmppath);
+ return (-1);
+ default:
+ close(filedes[0]);
+ /* Pipe into sendmail. */
+ if (send_file(tmppath, filedes[1]) == -1) {
+ warn("send_file error: unsent report in %s",
+ tmppath);
+ return (-1);
+ }
+ close(filedes[1]);
+ wait(NULL);
+ break;
+ }
+ return (0);
+}
+
+int
+init(void)
+{
+ size_t len;
+ int sysname[2];
+
+ if ((pw = getpwuid(getuid())) == NULL) {
+ warn("getpwuid");
+ return (-1);
+ }
+
+ /* Get full name. */
+ len = strcspn(pw->pw_gecos, ",");
+ if ((fullname = malloc(len + 1)) == NULL) {
+ warn("malloc");
+ return (-1);
+ }
+ memcpy(fullname, pw->pw_gecos, len);
+ fullname[len] = '\0';
+
+ sysname[0] = CTL_KERN;
+ sysname[1] = KERN_OSTYPE;
+ len = sizeof(os) - 1;
+ if (sysctl(sysname, 2, &os, &len, NULL, 0) == -1) {
+ warn("sysctl");
+ return (-1);
+ }
+
+ sysname[0] = CTL_KERN;
+ sysname[1] = KERN_OSRELEASE;
+ len = sizeof(rel) - 1;
+ if (sysctl(sysname, 2, &rel, &len, NULL, 0) == -1) {
+ warn("sysctl");
+ return (-1);
+ }
+
+ sysname[0] = CTL_HW;
+ sysname[1] = HW_MACHINE;
+ len = sizeof(mach) - 1;
+ if (sysctl(sysname, 2, &mach, &len, NULL, 0) == -1) {
+ warn("sysctl");
+ return (-1);
+ }
+
+ return (0);
+}
+
+int
+send_file(const char *file, int dst)
+{
+ FILE *fp;
+ char *buf;
+ size_t len;
+ int blank = 0;
+
+ if ((fp = fopen(file, "r")) == NULL)
+ return (-1);
+ while ((buf = fgetln(fp, &len))) {
+ /* Skip lines starting with "SENDBUG". */
+ if (len >= sizeof("SENDBUG") - 1 &&
+ memcmp(buf, "SENDBUG", sizeof("SENDBUG") - 1) == 0)
+ continue;
+ if (len == 1 && buf[0] == '\n')
+ blank = 1;
+ /* Skip comments, but only if we encountered a blank line. */
+ while (len) {
+ char *sp, *ep = NULL;
+ size_t copylen;
+
+ if (blank && (sp = memchr(buf, '<', len)) != NULL)
+ ep = memchr(sp, '>', len - (sp - buf + 1));
+ /* Length of string before comment. */
+ copylen = ep ? sp - buf : len;
+ if (atomicio(vwrite, dst, buf, copylen) != copylen) {
+ int saved_errno = errno;
+
+ fclose(fp);
+ errno = saved_errno;
+ return (-1);
+ }
+ if (!ep)
+ break;
+ /* Skip comment. */
+ len -= ep - buf + 1;
+ buf = ep + 1;
+ }
+ }
+ fclose(fp);
+ return (0);
+}
+
+void
+template(FILE *fp)
+{
+ fprintf(fp, "SENDBUG: -*- sendbug -*-\n");
+ fprintf(fp, "SENDBUG: Lines starting with `SENDBUG' will be removed automatically, as\n");
+ fprintf(fp, "SENDBUG: will all comments (text enclosed in `<' and `>'). \n");
+ fprintf(fp, "SENDBUG:\n");
+ fprintf(fp, "SENDBUG: Choose from the following categories:\n");
+ fprintf(fp, "SENDBUG:\n");
+ fprintf(fp, "SENDBUG: %s\n", categories);
+ fprintf(fp, "SENDBUG:\n");
+ fprintf(fp, "SENDBUG:\n");
+ fprintf(fp, "To: %s\n", "gnats@openbsd.org");
+ fprintf(fp, "Subject: \n");
+ fprintf(fp, "From: %s\n", pw->pw_name);
+ fprintf(fp, "Cc: \n");
+ fprintf(fp, "Reply-To: %s\n", pw->pw_name);
+ fprintf(fp, "X-sendbug-version: 4.2\n");
+ fprintf(fp, "\n");
+ fprintf(fp, "\n");
+ fprintf(fp, ">Submitter-Id:\tnet\n");
+ fprintf(fp, ">Originator:\t%s\n", fullname);
+ fprintf(fp, ">Organization:\n");
+ fprintf(fp, "net\n");
+ fprintf(fp, ">Synopsis:\t<synopsis of the problem (one line)>\n");
+ fprintf(fp, ">Severity:\t<[ non-critical | serious | critical ] (one line)>\n");
+ fprintf(fp, ">Priority:\t<[ low | medium | high ] (one line)>\n");
+ fprintf(fp, ">Category:\t<PR category (one line)>\n");
+ fprintf(fp, ">Class:\t\t<[ sw-bug | doc-bug | change-request | support ] (one line)>\n");
+ fprintf(fp, ">Release:\t<release number or tag (one line)>\n");
+ fprintf(fp, ">Environment:\n");
+ fprintf(fp, "\t<machine, os, target, libraries (multiple lines)>\n");
+ fprintf(fp, "\tSystem : %s %s\n", os, rel);
+ fprintf(fp, "\tArchitecture: %s.%s\n", os, mach);
+ fprintf(fp, "\tMachine : %s\n", mach);
+ fprintf(fp, ">Description:\n");
+ fprintf(fp, "\t<precise description of the problem (multiple lines)>\n");
+ fprintf(fp, ">How-To-Repeat:\n");
+ fprintf(fp, "\t<code/input/activities to reproduce the problem (multiple lines)>\n");
+ fprintf(fp, ">Fix:\n");
+ fprintf(fp, "\t<how to correct or work around the problem, if known (multiple lines)>\n");
+}