932fdefd |
1 | /* |
6868f2f7 |
2 | * beep: make a beeping noise, by any means necessary |
932fdefd |
3 | */ |
4 | |
5 | #include <stdio.h> |
6 | #include <stdlib.h> |
7 | #include <string.h> |
8 | #include <errno.h> |
9 | #include <ctype.h> |
10 | |
11 | #ifndef NO_X11 |
12 | #include <X11/X.h> |
13 | #include <X11/Xlib.h> |
14 | #endif |
15 | |
16 | #include <unistd.h> |
17 | #include <fcntl.h> |
18 | |
19 | const char usagemsg[] = |
20 | "usage: beep [ -v ] [" |
21 | #ifndef NO_X11 |
22 | " -X |" |
23 | #endif |
24 | " -T | -S ]\n" |
25 | "where: " |
26 | #ifndef NO_X11 |
27 | "-X beep using the X display or not at all\n " |
28 | #endif |
29 | "-T beep using /dev/tty or not at all\n" |
30 | " -S beep using standard output or not at all\n" |
31 | " -v log failed and successful beep attempts\n" |
32 | " also: beep --version report version number\n" |
33 | " beep --help display this help text\n" |
34 | " beep --licence display the (MIT) licence text\n" |
35 | ; |
36 | |
37 | void usage(void) { |
38 | fputs(usagemsg, stdout); |
39 | } |
40 | |
41 | const char licencemsg[] = |
42 | "beep is copyright 2006 Simon Tatham.\n" |
43 | "\n" |
44 | "Permission is hereby granted, free of charge, to any person\n" |
45 | "obtaining a copy of this software and associated documentation files\n" |
46 | "(the \"Software\"), to deal in the Software without restriction,\n" |
47 | "including without limitation the rights to use, copy, modify, merge,\n" |
48 | "publish, distribute, sublicense, and/or sell copies of the Software,\n" |
49 | "and to permit persons to whom the Software is furnished to do so,\n" |
50 | "subject to the following conditions:\n" |
51 | "\n" |
52 | "The above copyright notice and this permission notice shall be\n" |
53 | "included in all copies or substantial portions of the Software.\n" |
54 | "\n" |
55 | "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n" |
56 | "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n" |
57 | "MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n" |
58 | "NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n" |
59 | "BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n" |
60 | "ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n" |
61 | "CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n" |
62 | "SOFTWARE.\n" |
63 | ; |
64 | |
65 | void licence(void) { |
66 | fputs(licencemsg, stdout); |
67 | } |
68 | |
69 | void version(void) { |
70 | #define SVN_REV "$Revision$" |
71 | char rev[sizeof(SVN_REV)]; |
72 | char *p, *q; |
73 | |
74 | strcpy(rev, SVN_REV); |
75 | |
76 | for (p = rev; *p && *p != ':'; p++); |
77 | if (*p) { |
78 | p++; |
79 | while (*p && isspace((unsigned char)*p)) p++; |
80 | for (q = p; *q && !isspace((unsigned char)*q) && *q != '$'; q++); |
81 | if (*q) *q = '\0'; |
82 | printf("beep revision %s", p); |
83 | } else { |
84 | printf("beep: unknown version"); |
85 | } |
86 | #ifdef NO_X11 |
87 | printf(", compiled without X11"); |
88 | #endif |
89 | putchar('\n'); |
90 | } |
91 | |
92 | int main(int argc, char **argv) { |
93 | #ifndef NO_X11 |
94 | char *display = NULL; |
95 | #endif |
96 | int verbose = 0; |
97 | enum { X11 = 1, TTY = 2, STDOUT = 4 } mode = X11 | TTY | STDOUT; |
98 | char errbuf[4096]; |
99 | int errlen = 0; |
100 | int done = 0; |
101 | char *pname = argv[0]; |
102 | |
103 | /* parse the command line arguments */ |
104 | while (--argc) { |
105 | char *p = *++argv; |
106 | |
107 | #ifndef NO_X11 |
108 | if (!strcmp(p, "-display") || !strcmp(p, "-disp")) { |
109 | if (!argv[1]) { |
110 | fprintf(stderr, "%s: option `%s' expects a parameter\n", |
111 | pname, p); |
112 | return 1; |
113 | } |
114 | display = *++argv, --argc; |
115 | } else if (!strcmp(p, "-X")) { |
116 | mode = X11; |
117 | } else |
118 | #endif |
119 | if (!strcmp(p, "-T")) { |
120 | mode = TTY; |
121 | } else if (!strcmp(p, "-S")) { |
122 | mode = STDOUT; |
123 | } else if (!strcmp(p, "-v")) { |
124 | verbose = 1; |
125 | } else if (!strcmp(p, "--help")) { |
126 | usage(); |
127 | return 0; |
128 | } else if (!strcmp(p, "--version")) { |
129 | version(); |
130 | return 0; |
131 | } else if (!strcmp(p, "--licence") || !strcmp(p, "--license")) { |
132 | licence(); |
133 | return 0; |
134 | } else if (*p=='-') { |
135 | fprintf(stderr, "%s: unrecognised option `%s'\n", pname, p); |
136 | return 1; |
137 | } else { |
138 | fprintf(stderr, "%s: parameter `%s' unexpected\n", pname, p); |
139 | return 1; |
140 | } |
141 | } |
142 | |
143 | #ifndef NO_X11 |
144 | if (!done && (mode & X11)) { |
145 | Display *disp = XOpenDisplay(display); |
146 | if (!disp) { |
147 | errlen += sprintf(errbuf+errlen, |
148 | "%s: unable to open X display\n", pname); |
149 | } else { |
150 | XBell(disp, 0); |
151 | XCloseDisplay(disp); |
152 | if (verbose) { |
153 | errlen += sprintf(errbuf+errlen, |
154 | "%s: successfully beeped via X11\n", pname); |
155 | } |
156 | done = 1; |
157 | } |
158 | } |
159 | #endif |
160 | |
161 | if (!done && (mode & TTY)) { |
162 | int fd = open("/dev/tty", O_WRONLY); |
163 | if (fd < 0) { |
164 | errlen += sprintf(errbuf+errlen, |
165 | "%s: unable to open /dev/tty: %s\n", |
166 | pname, strerror(errno)); |
167 | } else { |
168 | if (write(fd, "\007", 1) < 0) { |
169 | errlen += sprintf(errbuf+errlen, "%s: unable to write to" |
170 | " /dev/tty: %s\n", pname, strerror(errno)); |
171 | } else { |
172 | if (verbose) { |
173 | errlen += sprintf(errbuf+errlen, "%s: successfully beeped" |
174 | " via /dev/tty\n", pname); |
175 | } |
176 | done = 1; |
177 | } |
178 | close(fd); |
179 | } |
180 | } |
181 | |
182 | if (!done && (mode & STDOUT)) { |
183 | if (write(1, "\007", 1) < 0) { |
184 | errlen += sprintf(errbuf+errlen, "%s: unable to write to standard " |
185 | "output: %s\n", pname, strerror(errno)); |
186 | } else { |
187 | if (verbose) { |
188 | errlen += sprintf(errbuf+errlen, "%s: successfully beeped" |
189 | " via standard output\n", pname); |
190 | } |
191 | done = 1; |
192 | } |
193 | } |
194 | |
195 | if (verbose || !done) { |
196 | errbuf[errlen] = '\0'; |
197 | fputs(errbuf, stderr); |
198 | } |
199 | |
200 | return (done ? EXIT_SUCCESS : EXIT_FAILURE); |
201 | } |