1
0
Fork 0
src/Wip/sysexits/sysexits.c

183 lines
5.1 KiB
C

#include <stdio.h>
#include <unistd.h>
#include "arraylen.h"
/* Thanks to u/smcameron on Reddit. */
#define TAB_WIDTH 8
/* Changing ENUM to DEFINE will make this output the traditional BSD header
* verbatim, without copyright notice. I don't have any idea if that's a
* copyright violation, but let's keep this as ENUM to skirt by that little
* technicality.
* I implemented sysexits(3) in the enum method before reading the BSD 4.0
* source to see how they did it. */
#define ENUM 1
static char *program_name = "sysexits";
static const char comment_prefix[] = "/* ";
static const char comment_prefix_ongoing[] = " * ";
static const char comment_suffix[] = " */\n";
static const char header_prefix[] =
"#ifndef _SYSEXITS_H\n"
"#\tdefine _SYSEXITS_H\n"
"enum{\n"
;
/* ASSUMPTIONS:
* - This array is always organized.
* - All characters in descriptions are one space wide.
* - The only whitespace in descriptions is ASCII_SP. */
static const struct {
char *desc;
char *name;
int status;
}sysexits[] = {
/* sysexit descriptions copied from FreeBSD's sysexits(3). */
{ "All is well.", /* except this one */
"EX_OK", 0 },
{ "The command was used incorrectly, e.g., with the wrong number of"
" arguments, a bad flag, a bad syntax in a parameter, or whatever.",
"EX_USAGE", 64 },
{ "The input data was incorrect in some way. This should only be used"
" for user's data and not system files.",
"EX_DATAERR", 65 },
{ "An input file (not a system file) did not exist or was not readable."
" This could also include errors like \"No message\" to a mailer (if it"
" cared to catch it).",
"EX_NOINPUT", 66 },
{ "The user specified did not exist. This might be used for mail"
" addresses or remote logins.",
"EX_NOUSER", 67 },
{ "The host specified did not exist. This is used in mail addresses or"
" network requests.",
"EX_NOHOST", 68 },
{ "A service is unavailable. This can occur if a support program or"
" file does not exist. This can also be used as a catchall message"
" when something you wanted to do does not work, but you do not know"
" why.",
"EX_UNAVAILABLE", 69 },
{ "An internal software error has been detected. This should be limited"
" to non-operating system related errors as possible.",
"EX_SOFTWARE", 70 },
{ "An operating system error has been detected. This is intended to be"
" used for such things as \"cannot fork\", \"cannot create pipe\", or"
" the like. It includes things like getuid returning a user that does"
" not exist in the passwd file.",
"EX_OSERR", 71 },
{ "Some system file (e.g., /etc/passwd, /var/run/utx.active, etc.) does"
" not exist, cannot be opened, or has some sort of error (e.g., syntax"
" error).",
"EX_OSFILE", 72 },
{ "A (user specified) output file cannot be created.",
"EX_CANTCREAT", 73 },
{ "An error occurred while doing I/O on some file.",
"EX_IOERR", 74 },
{ "Temporary failure, indicating something that is not really an error."
" In sendmail, this means that a mailer (e.g.) could not create a"
" connection, and the request should be reattempted later.",
"EX_TEMPFAIL", 75 },
{ "The remote system returned something that was \"not possible\" during a"
" protocol exchange.",
"EX_PROTOCOL", 76 },
{ "You did not have sufficient permission to perform the operation."
" This is not intended for file system problems, which should use"
" EX_NOINPUT or EX_CANTCREAT, but rather for higher level"
" permissions.",
"EX_NOPERM", 77 },
{ "Something was found in an unconfigured or misconfigured state.",
"EX_CONFIG", 78 }
};
static const char header_suffix[] =
"};\n"
"#endif /* ifndef _SYSEXITS_H */\n"
;
static size_t i;
static int findbyint(int status){
for(i = 0; i < ARRAYLEN(sysexits); ++i)
if(sysexits[i].status == status)
return i;
return -1;
}
static void output_comment(int fd, int indentation, int width, char *comment){
size_t word_start;
size_t line_start;
for(i = 0, line_start = 0, word_start = 0; ; ++i)
switch(comment[i]){
case '\0':
while( i - line_start
+ ARRAYLEN(comment_suffix)
+ indentation * TAB_WIDTH
> width){
i = word_start - 2; /* - current char, - space */
write(
fd, comment_prefix_ongoing,
ARRAYLEN(comment_prefix_ongoing)
);
write(fd, comment + line_start, i - line_start);
i += 2; /* + space, + next word char */
write(fd, "\n", 1);
}
write(fd, comment + line_start, i - line_start);
write(fd, comment_suffix, ARRAYLEN(comment_suffix));
break;
}
return;
}
static void output_header(void){
write(1, header_prefix, ARRAYLEN(header_prefix) - 1);
for(i = 0; i < ARRAYLEN(sysexits); ++i){
//output_comment(1, 1 * TAB_WIDTH, 80, sysexits[i].desc);
#ifdef ENUM
fprintf(stdout, "\t%s = %d%s",
sysexits[i].name,
sysexits[i].status,
i < ARRAYLEN(sysexits) - 1 ? ",\n" : "\n"
);
#endif /* ifdef ENUM */
#ifdef DEFINE
fprintf(stdout, "#\tdefine %s %d\n",
sysexits[i].name,
sysexits[i].status
);
#endif /* ifdef DEFINE */
}
fflush(stdout);
write(1, header_suffix, ARRAYLEN(header_suffix) - 1);
}
int main(int argc, char *argv[]){
if(argv[0] == NULL){
argv[0] = program_name;
++argc;
}
output_header();
return 0;
}