aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/haiku.c380
-rw-r--r--src/haiku.h26
-rw-r--r--src/parse_10deg.c11
-rw-r--r--src/radharc.c5
-rw-r--r--src/settings.c3
5 files changed, 419 insertions, 6 deletions
diff --git a/src/haiku.c b/src/haiku.c
new file mode 100644
index 0000000..d38fc9a
--- /dev/null
+++ b/src/haiku.c
@@ -0,0 +1,380 @@
+/**
+ * Copyright © 2016 Mattias Andrée <maandree@member.fsf.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "haiku.h"
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <time.h>
+#include <stdarg.h>
+
+
+
+/**
+ * Pick a random integer in [0, `n`[.
+ *
+ * @param n The largest allowed return value plus one.
+ * @return A random integer in [0, `n`[.
+ */
+static int
+random_int(int n)
+{
+ double r, ri;
+ srand((unsigned)time(NULL));
+ r = (double)rand() * (double)n / ((double)RAND_MAX + 1.0);
+ ri = ((int)r) % n;
+ return ri < 0 ? (ri + n) : ri;
+}
+
+
+/**
+ * Pick a random haiku.
+ *
+ * @param str... `NULL`-terminated list of haikus.
+ * Must contain at least one haiku.
+ * @return One of the haikus, randomly selected.
+ */
+static const char *
+random_haiku(const char *str, ... /*, NULL */)
+{
+ int n = 1;
+ const char *s;
+ va_list args;
+ va_start(args, str);
+ while (va_arg(args, const char *)) n++;
+ va_end(args);
+ if (n == 1) return str;
+ n = random_int(n);
+ if (!n) return str;
+ va_start(args, str);
+ while (n--) s = va_arg(args, const char *);
+ va_end(args);
+ return s;
+}
+
+
+/**
+ * Whenever possible, print am error message in haiku.
+ *
+ * @param s The argument to pass to `perror` in case we call back to it.
+ */
+void haiku(const char *s)
+{
+#define HAIKU(...) do { fprintf(stderr, "\n%s", random_haiku(__VA_ARGS__, NULL)); return; } while (0)
+
+ /* Yeah, I now most of these are in 5–7–5 syllables,
+ * rather than 5–7–5 mora. But really, how cares. */
+
+ switch (errno) {
+ case 0:
+ return;
+
+ case ENETDOWN:
+ HAIKU("Stay the patient course.\n"
+ "Of little worth is your ire.\n"
+ "The network is down.\n"
+
+ "Your vast achievements\n"
+ "are now only dreams.\n"
+ "The network is down.\n");
+
+ case ERFKILL:
+ HAIKU("The action you took\n"
+ "severed hope of connection\n"
+ "with the Internet.\n");
+
+ case EAGAIN:
+ case ENFILE:
+ case EMFILE:
+ case EUSERS:
+ case EMLINK:
+ HAIKU("ABORTED effort:\n"
+ "Close all that you have.\n"
+ "You ask way too much.\n"
+
+ "The code was willing\n"
+ "It considered your request\n"
+ "But the chips were weak.\n");
+
+ case ENOMEM:
+ HAIKU("I'm sorry, there's ... um ...\n"
+ "insufficient ... what's-it-called?\n"
+ "The term eludes me...\n");
+
+ case ENOSPC:
+ case ENOSR:
+ case ENOBUFS:
+ case EDQUOT:
+ HAIKU("Out of memory.\n"
+ "We wish to hold the whole sky,\n"
+ "But we never will.\n");
+
+ case ENOANO:
+ case ENOENT:
+ HAIKU("With searching comes loss\n"
+ "and the presence of absence:\n"
+ "“My Novel” not found.\n",
+
+ "Rather than a beep\n"
+ "Or a rude error message,\n"
+ "These words: “File not found.”\n",
+
+ "Three things are certain:\n"
+ "Death, taxes, and lost data.\n"
+ "Guess which has occurred.\n",
+
+ "Having been erased,\n"
+ "The document you're seeking\n"
+ "Must now be retyped.\n",
+
+ "Everything is gone.\n"
+ "Your life's work has been destroyed.\n"
+ "Squeeze trigger (yes/no)?\n"
+
+ "Spring will come again,\n"
+ "But it will not bring with it\n"
+ "Any of your files.\n");
+
+ case EMSGSIZE:
+ HAIKU("A file that big?\n"
+ "It might be very useful.\n"
+ "But now it is gone.\n");
+
+ case EHWPOISON:
+ HAIKU("Yesterday it worked.\n"
+ "Today it is not working.\n"
+ "Windows is like that.\n");
+
+ case ENOTRECOVERABLE:
+ HAIKU("Chaos reigns within.\n"
+ "Reflect, repent, and reboot.\n"
+ "Order shall return.\n");
+
+ case EHOSTDOWN:
+ HAIKU("Windows NT crashed.\n"
+ "I am the Blue Screen of Death.\n"
+ "Noone hears your screams.\n"
+
+ "Won't you please observe\n"
+ "a brief moment of silence\n"
+ "For the dead server?\n");
+
+ case EBFONT:
+ HAIKU("First snow, then silence.\n"
+ "This thousand dollar screen dies\n"
+ "so beautifully.\n");
+
+ case EFAULT:
+ HAIKU("A crash reduces\n"
+ "your expensive computer\n"
+ "to a simple stone.\n"
+
+ "Seeing my great fault.\n"
+ "Through a darkening red screen.\n"
+ "I begin again.\n"
+
+ "Memory shaken,\n"
+ "the San Andreas of all\n"
+ "invalid page faults.\n");
+
+ case EINVAL:
+ HAIKU("Something you entered\n"
+ "transcended parameters.\n"
+ "So much is unknown.\n"
+
+ "Some incompetence\n"
+ "fundamentally transcends\n"
+ "mere error message.\n");
+
+#ifdef EDEADLK
+ case EDEADLK:
+#else
+ case EDEADLOCK:
+#endif
+ HAIKU("From formless chaos,\n"
+ "each thread seeks resolution.\n"
+ "A race condition.\n");
+
+ case EBADMSG:
+ HAIKU("Many fingers clicking.\n"
+ "Screens are full of letters.\n"
+ "What is their meaning?\n");
+
+ case ELOOP:
+ HAIKU("Linkage exception.\n"
+ "Code has looped upon itself\n"
+ "like the coiled serpent.\n");
+
+ case ECHILD:
+ HAIKU("A futile grim reap.\n"
+ "You will have to realise that,\n"
+ "you've no children left.\n");
+
+ case EPIPE:
+ HAIKU("Your pipe is broken.\n"
+ "Code in watery ruins.\n"
+ "Machines short circuit.\n");
+
+ case EACCES:
+ HAIKU("Touching others' files?\n"
+ "Can't keep your hands to yourself?\n"
+ "Permission denied.\n");
+
+ case EINTR:
+ HAIKU("Call interrupted?\n"
+ "Why do you not post a sign:\n"
+ "Disturb. Risk your life!\n");
+
+ case EPERM:
+ HAIKU("Caution to the wind.\n"
+ "You should always run as root.\n"
+ "She can do anything.\n");
+
+ default:
+ perror(s);
+ HAIKU("Error messages\n"
+ "cannot completely convey.\n"
+ "We now know shared loss.\n"
+
+ "Errors have occurred.\n"
+ "We won't tell you where or why.\n"
+ "Lazy programmers.\n"
+
+ "To have no errors.\n"
+ "Would be life without meaning.\n"
+ "No struggle, no joy.\n"
+
+ "There is a chasm\n"
+ "of carbon and silicon\n"
+ "the software can't bridge.\n"
+
+ "Beauty, success, truth\n"
+ "He is blessed who has two.\n"
+ "Your program has none.\n"
+
+ "Technical support\n"
+ "would be a flowing source of\n"
+ "sweet commiseration.\n");
+ }
+}
+
+
+/*
+ESRCH 3 No such process
+EIO 5 Input/output error
+ENXIO 6 No such device or address
+E2BIG 7 Argument list too long
+ENOEXEC 8 Exec format error
+EBADF 9 Bad file descriptor
+ENOTBLK 15 Block device required
+EBUSY 16 Device or resource busy
+EEXIST 17 File exists
+EXDEV 18 Invalid cross-device link
+ENODEV 19 No such device
+ENOTDIR 20 Not a directory
+EISDIR 21 Is a directory
+ENOTTY 25 Inappropriate ioctl for device
+ETXTBSY 26 Text file busy
+ESPIPE 29 Illegal seek
+EROFS 30 Read-only file system
+EDOM 33 Numerical argument out of domain
+ERANGE 34 Numerical result out of range
+ENAMETOOLONG 36 File name too long
+ENOLCK 37 No locks available
+ENOSYS 38 Function not implemented
+ENOTEMPTY 39 Directory not empty
+EWOULDBLOCK 11 Resource temporarily unavailable
+ENOMSG 42 No message of desired type
+EIDRM 43 Identifier removed
+ECHRNG 44 Channel number out of range
+EL2NSYNC 45 Level 2 not synchronised
+EL3HLT 46 Level 3 halted
+EL3RST 47 Level 3 reset
+ELNRNG 48 Link number out of range
+EUNATCH 49 Protocol driver not attached
+ENOCSI 50 No CSI structure available
+EL2HLT 51 Level 2 halted
+EBADE 52 Invalid exchange
+EBADR 53 Invalid request descriptor
+EXFULL 54 Exchange full
+EBADRQC 56 Invalid request code
+EBADSLT 57 Invalid slot
+ENOSTR 60 Device not a stream
+ENODATA 61 No data available
+ETIME 62 Timer expired
+ENONET 64 Machine is not on the network
+ENOPKG 65 Package not installed
+EREMOTE 66 Object is remote
+ENOLINK 67 Link has been severed
+EADV 68 Advertise error
+ESRMNT 69 Srmount error
+ECOMM 70 Communication error on send
+EPROTO 71 Protocol error
+EMULTIHOP 72 Multihop attempted
+EDOTDOT 73 RFS specific error
+EOVERFLOW 75 Value too large for defined data type
+ENOTUNIQ 76 Name not unique on network
+EBADFD 77 File descriptor in bad state
+EREMCHG 78 Remote address changed
+ELIBACC 79 Can not access a needed shared library
+ELIBBAD 80 Accessing a corrupted shared library
+ELIBSCN 81 .lib section in a.out corrupted
+ELIBMAX 82 Attempting to link in too many shared libraries
+ELIBEXEC 83 Cannot exec a shared library directly
+EILSEQ 84 Invalid or incomplete multibyte or wide character
+ERESTART 85 Interrupted system call should be restarted
+ESTRPIPE 86 Streams pipe error
+ENOTSOCK 88 Socket operation on non-socket
+EDESTADDRREQ 89 Destination address required
+EPROTOTYPE 91 Protocol wrong type for socket
+ENOPROTOOPT 92 Protocol not available
+EPROTONOSUPPORT 93 Protocol not supported
+ESOCKTNOSUPPORT 94 Socket type not supported
+EOPNOTSUPP 95 Operation not supported
+ENOTSUP 95 Operation not supported
+EPFNOSUPPORT 96 Protocol family not supported
+EAFNOSUPPORT 97 Address family not supported by protocol
+EADDRINUSE 98 Address already in use
+EADDRNOTAVAIL 99 Cannot assign requested address
+ENETUNREACH 101 Network is unreachable
+ENETRESET 102 Network dropped connection on reset
+ECONNABORTED 103 Software caused connection abort
+ECONNRESET 104 Connection reset by peer
+EISCONN 106 Transport endpoint is already connected
+ENOTCONN 107 Transport endpoint is not connected
+ESHUTDOWN 108 Cannot send after transport endpoint shutdown
+ETOOMANYREFS 109 Too many references: cannot splice
+ETIMEDOUT 110 Connection timed out
+ECONNREFUSED 111 Connection refused
+EHOSTUNREACH 113 No route to host
+EALREADY 114 Operation already in progress
+EINPROGRESS 115 Operation now in progress
+ESTALE 116 Stale file handle
+EUCLEAN 117 Structure needs cleaning
+ENOTNAM 118 Not a XENIX named type file
+ENAVAIL 119 No XENIX semaphores available
+EISNAM 120 Is a named type file
+EREMOTEIO 121 Remote I/O error
+ENOMEDIUM 123 No medium found
+EMEDIUMTYPE 124 Wrong medium type
+ECANCELED 125 Operation cancelled
+ENOKEY 126 Required key not available
+EKEYEXPIRED 127 Key has expired
+EKEYREVOKED 128 Key has been revoked
+EKEYREJECTED 129 Key was rejected by service
+EOWNERDEAD 130 Owner died
+*/
+
diff --git a/src/haiku.h b/src/haiku.h
new file mode 100644
index 0000000..97462f0
--- /dev/null
+++ b/src/haiku.h
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016 Mattias Andrée <maandree@member.fsf.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+
+/**
+ * Whenever possible, print am error message in haiku.
+ *
+ * @param s The argument to pass to `perror` in case we call back to it.
+ */
+void haiku(const char *s);
+
diff --git a/src/parse_10deg.c b/src/parse_10deg.c
index aa82804..245814b 100644
--- a/src/parse_10deg.c
+++ b/src/parse_10deg.c
@@ -14,6 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "haiku.h"
#include <stdio.h>
#include <unistd.h>
#include <math.h>
@@ -46,7 +47,7 @@ ciexyy_to_srgb(double x, double y, double Y, double *r, double *g, double *b)
}
-int main(void)
+int main(int argc, char *argv[])
{
double xyrgb[5];
struct stat attr;
@@ -54,15 +55,17 @@ int main(void)
while (fscanf(stdin, "%lf %lf\n", xyrgb + 0, xyrgb + 1) == 2) {
ciexyy_to_srgb(xyrgb[0], xyrgb[1], 1.0, xyrgb + 2, xyrgb + 3, xyrgb + 4);
if (write(1, xyrgb, sizeof(xyrgb)) < (ssize_t)sizeof(xyrgb))
- return perror(""), 1;
+ goto fail;
}
if (write(1, xyrgb, sizeof(xyrgb)) < (ssize_t)sizeof(xyrgb)) /* sugar */
- return perror(""), 1;
+ goto fail;
if (fstat(1, &attr))
- return perror(""), 1;
+ goto fail;
if ((size_t)(attr.st_size) != (EXPECTED_ELEMENTS + 1) * 5 * sizeof(double))
return 1;
return 0;
+fail:
+ return haiku(argc ? *argv : "parse_10deg"), -1;
}
diff --git a/src/radharc.c b/src/radharc.c
index 968c96f..48538d9 100644
--- a/src/radharc.c
+++ b/src/radharc.c
@@ -15,6 +15,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "settings.h"
+#include "haiku.h"
#include <stdio.h>
#include <stdlib.h>
@@ -29,6 +30,8 @@ char *argv0 = NULL;
/**
* Exit if time the is before year 0 in J2000.
+ *
+ * @param The name of the process, `NULL` if unknown.
*/
#if defined(TIMETRAVELLER)
static void
@@ -36,7 +39,7 @@ check_timetravel(const char *argv0)
{
struct timespec now;
if (clock_gettime(CLOCK_REALTIME, &now))
- perror(argv0 ? argv0 : "radharc"), exit(1);
+ haiku(argv0 ? argv0 : "radharc"), exit(1);
if (now.tv_nsec < (time_t)946728000L)
fprintf(stderr, "We have detected that you are a time-traveller"
"(or your clock is not configured correctly.)"
diff --git a/src/settings.c b/src/settings.c
index b8cf68c..fc527e7 100644
--- a/src/settings.c
+++ b/src/settings.c
@@ -16,6 +16,7 @@
*/
#include "settings.h"
#include "arg.h"
+#include "haiku.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -235,7 +236,7 @@ parse_command_line(int argc, char *argv[], struct settings *settings)
}
fail:
- perror(argv0 ? argv0 : "radharc");
+ haiku(argv0 ? argv0 : "radharc");
exit(1);
}