183 lines
5.1 KiB
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;
|
|
}
|