--- /dev/null
+\cfg{man-identity}{beep}{1}{2006-02-15}{Simon Tatham}{Simon Tatham}
+
+\title Man page for \c{beep}
+
+\U NAME
+
+\c{beep} - produce a beeping noise, by any available method
+
+\U SYNOPSIS
+
+\c beep [ -v ] [ -X | -T | -S ]
+\e bbbb bb bb bb bb
+
+\U DESCRIPTION
+
+\c{beep} is a command-line utility for making a computer go beep.
+
+Under normal circumstances, you should be able to use it just by
+typing \cq{beep}, with no options.
+
+The traditional method of producing a beep in a shell script is to
+write an ASCII BEL (\cw{\\007}) character to standard output, by
+means of a shell command such as \cq{echo -ne '\\007'}. This only
+works if the calling shell's standard output is currently directed
+to a terminal device of some sort; if not, the beep will produce no
+sound and might even cause unwanted corruption in whatever file the
+output is directed to.
+
+There are other ways to cause a beeping noise. A slightly more
+reliable method is to open \cw{/dev/tty} and send your BEL character
+there. This is robust against I/O redirection, but still fails in
+the case where the shell script wishing to generate a beep does not
+\e{have} a controlling terminal, for example because it is run from
+an X window manager.
+
+A third approach is to connect to your X display and send it a bell
+command. This does not depend on a Unix terminal device, but does
+(of course) require an X display.
+
+The \c{beep} command supports all these methods of generating a
+beep, and will try them in order until one works. Its order of
+preference is to use the X server, then to fall back to
+\cw{/dev/tty}, and if all else fails it will simply write a BEL to
+its standard output.
+
+\U OPTIONS
+
+\dt \cw{-X}
+
+\dd Restricts \c{beep} to only using the X server to generate its
+beep. If there is no X server available, no beep will be generated
+and \c{beep} will return failure.
+
+\dt \cw{-T}
+
+\dd Restricts \c{beep} to only using \cw{/dev/tty} to generate its
+beep. If \cw{/dev/tty} cannot be opened or written to, no beep will
+be generated and \c{beep} will return failure.
+
+\dt \cw{-S}
+
+\dd Restricts \c{beep} to only using standard output to generate its
+beep. If its standard output cannot be written to, no beep will be
+generated and \c{beep} will return failure.
+
+\dt \cw{-v}
+
+\dd Causes \c{beep} to log everything it did even if it succeeds. By
+default, error messages will only be output if none of the available
+beep methods succeeded.
+
+\U EXIT STATUS
+
+\c{beep} will return a success (0) status if it thinks it
+successfully beeped, and failure (1) otherwise.
+
+\U BUGS
+
+None known at present.
+
+\U LICENCE
+
+\cw{xcopy} is free software, distributed under the MIT licence. Type
+\cw{xcopy --licence} to see the full licence text.
+
+\versionid $Id$
--- /dev/null
+/*
+ * beep: quickly pipe text data into, or out of, the primary X
+ * selection
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#ifndef NO_X11
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+
+const char usagemsg[] =
+ "usage: beep [ -v ] ["
+#ifndef NO_X11
+ " -X |"
+#endif
+ " -T | -S ]\n"
+ "where: "
+#ifndef NO_X11
+ "-X beep using the X display or not at all\n "
+#endif
+ "-T beep using /dev/tty or not at all\n"
+ " -S beep using standard output or not at all\n"
+ " -v log failed and successful beep attempts\n"
+ " also: beep --version report version number\n"
+ " beep --help display this help text\n"
+ " beep --licence display the (MIT) licence text\n"
+ ;
+
+void usage(void) {
+ fputs(usagemsg, stdout);
+}
+
+const char licencemsg[] =
+ "beep is copyright 2006 Simon Tatham.\n"
+ "\n"
+ "Permission is hereby granted, free of charge, to any person\n"
+ "obtaining a copy of this software and associated documentation files\n"
+ "(the \"Software\"), to deal in the Software without restriction,\n"
+ "including without limitation the rights to use, copy, modify, merge,\n"
+ "publish, distribute, sublicense, and/or sell copies of the Software,\n"
+ "and to permit persons to whom the Software is furnished to do so,\n"
+ "subject to the following conditions:\n"
+ "\n"
+ "The above copyright notice and this permission notice shall be\n"
+ "included in all copies or substantial portions of the Software.\n"
+ "\n"
+ "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n"
+ "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n"
+ "MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n"
+ "NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n"
+ "BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n"
+ "ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n"
+ "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n"
+ "SOFTWARE.\n"
+ ;
+
+void licence(void) {
+ fputs(licencemsg, stdout);
+}
+
+void version(void) {
+#define SVN_REV "$Revision$"
+ char rev[sizeof(SVN_REV)];
+ char *p, *q;
+
+ strcpy(rev, SVN_REV);
+
+ for (p = rev; *p && *p != ':'; p++);
+ if (*p) {
+ p++;
+ while (*p && isspace((unsigned char)*p)) p++;
+ for (q = p; *q && !isspace((unsigned char)*q) && *q != '$'; q++);
+ if (*q) *q = '\0';
+ printf("beep revision %s", p);
+ } else {
+ printf("beep: unknown version");
+ }
+#ifdef NO_X11
+ printf(", compiled without X11");
+#endif
+ putchar('\n');
+}
+
+int main(int argc, char **argv) {
+#ifndef NO_X11
+ char *display = NULL;
+#endif
+ int verbose = 0;
+ enum { X11 = 1, TTY = 2, STDOUT = 4 } mode = X11 | TTY | STDOUT;
+ char errbuf[4096];
+ int errlen = 0;
+ int done = 0;
+ char *pname = argv[0];
+
+ /* parse the command line arguments */
+ while (--argc) {
+ char *p = *++argv;
+
+#ifndef NO_X11
+ if (!strcmp(p, "-display") || !strcmp(p, "-disp")) {
+ if (!argv[1]) {
+ fprintf(stderr, "%s: option `%s' expects a parameter\n",
+ pname, p);
+ return 1;
+ }
+ display = *++argv, --argc;
+ } else if (!strcmp(p, "-X")) {
+ mode = X11;
+ } else
+#endif
+ if (!strcmp(p, "-T")) {
+ mode = TTY;
+ } else if (!strcmp(p, "-S")) {
+ mode = STDOUT;
+ } else if (!strcmp(p, "-v")) {
+ verbose = 1;
+ } else if (!strcmp(p, "--help")) {
+ usage();
+ return 0;
+ } else if (!strcmp(p, "--version")) {
+ version();
+ return 0;
+ } else if (!strcmp(p, "--licence") || !strcmp(p, "--license")) {
+ licence();
+ return 0;
+ } else if (*p=='-') {
+ fprintf(stderr, "%s: unrecognised option `%s'\n", pname, p);
+ return 1;
+ } else {
+ fprintf(stderr, "%s: parameter `%s' unexpected\n", pname, p);
+ return 1;
+ }
+ }
+
+#ifndef NO_X11
+ if (!done && (mode & X11)) {
+ Display *disp = XOpenDisplay(display);
+ if (!disp) {
+ errlen += sprintf(errbuf+errlen,
+ "%s: unable to open X display\n", pname);
+ } else {
+ XBell(disp, 0);
+ XCloseDisplay(disp);
+ if (verbose) {
+ errlen += sprintf(errbuf+errlen,
+ "%s: successfully beeped via X11\n", pname);
+ }
+ done = 1;
+ }
+ }
+#endif
+
+ if (!done && (mode & TTY)) {
+ int fd = open("/dev/tty", O_WRONLY);
+ if (fd < 0) {
+ errlen += sprintf(errbuf+errlen,
+ "%s: unable to open /dev/tty: %s\n",
+ pname, strerror(errno));
+ } else {
+ if (write(fd, "\007", 1) < 0) {
+ errlen += sprintf(errbuf+errlen, "%s: unable to write to"
+ " /dev/tty: %s\n", pname, strerror(errno));
+ } else {
+ if (verbose) {
+ errlen += sprintf(errbuf+errlen, "%s: successfully beeped"
+ " via /dev/tty\n", pname);
+ }
+ done = 1;
+ }
+ close(fd);
+ }
+ }
+
+ if (!done && (mode & STDOUT)) {
+ if (write(1, "\007", 1) < 0) {
+ errlen += sprintf(errbuf+errlen, "%s: unable to write to standard "
+ "output: %s\n", pname, strerror(errno));
+ } else {
+ if (verbose) {
+ errlen += sprintf(errbuf+errlen, "%s: successfully beeped"
+ " via standard output\n", pname);
+ }
+ done = 1;
+ }
+ }
+
+ if (verbose || !done) {
+ errbuf[errlen] = '\0';
+ fputs(errbuf, stderr);
+ }
+
+ return (done ? EXIT_SUCCESS : EXIT_FAILURE);
+}