1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2022 OmniOS Community Edition (OmniOSce) Association. 14 */ 15 16 /* 17 * This file exercises the various err(3C)/warn(3C) functions and produces 18 * output that is checked by the corresponding err.ksh script. 19 */ 20 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <stdbool.h> 24 #include <errno.h> 25 #include <err.h> 26 #include <sys/debug.h> 27 28 static FILE *stream = stderr; 29 30 typedef enum variant { 31 VARIANT_ = 0, /* warn(), err() */ 32 VARIANT_C, /* warnc(), errc() */ 33 VARIANT_X, /* warnx(), errx() */ 34 VARIANT_V, /* vwarn(), verr() */ 35 VARIANT_VC, /* vwarnc(), verrc() */ 36 VARIANT_VX, /* vwarnx(), verrx() */ 37 } variant_t; 38 39 void 40 usage(void) 41 { 42 (void) fprintf(stderr, 43 "usage: err [-e errno] [-x code] [-v variant]\n"); 44 exit(EXIT_FAILURE); 45 } 46 47 void 48 callback_func(int code) 49 { 50 (void) fprintf(stream, "CALLBACK %d\n", code); 51 } 52 53 void 54 xtest(variant_t variant, int errcode, int exitcode, const char *fmt, ...) 55 { 56 va_list va; 57 58 va_start(va, fmt); 59 60 switch (variant) { 61 case VARIANT_V: 62 errno = errcode; 63 if (exitcode != 0) 64 verr(exitcode, fmt, va); 65 else 66 vwarn(fmt, va); 67 break; 68 case VARIANT_VC: 69 errno = 0; 70 if (exitcode != 0) 71 verrc(exitcode, errcode, fmt, va); 72 else 73 vwarnc(errcode, fmt, va); 74 break; 75 case VARIANT_VX: 76 if (exitcode != 0) 77 verrx(exitcode, fmt, va); 78 else 79 vwarnx(fmt, va); 80 break; 81 default: 82 errx(EXIT_FAILURE, "Unhandled variant in %s", __func__); 83 } 84 85 va_end(va); 86 } 87 88 int 89 main(int argc, char **argv) 90 { 91 int errcode = 0; 92 int exitcode = 0; 93 variant_t variant = VARIANT_; 94 const char *errstr; 95 long long num; 96 int ch; 97 98 /* 99 * -e specify errno for the test 100 * -v select variant to test 101 * -x specify exit code for the test 102 */ 103 while ((ch = getopt(argc, argv, "e:v:x:")) != -1) { 104 switch (ch) { 105 case 'e': 106 num = strtonum(optarg, 0, 127, &errstr); 107 if (errstr != NULL) 108 errx(EXIT_FAILURE, "-x: %s", errstr); 109 errcode = (int)num; 110 break; 111 case 'v': 112 num = strtonum(optarg, 0, VARIANT_VX, &errstr); 113 if (errstr != NULL) 114 errx(EXIT_FAILURE, "-v: %s", errstr); 115 switch (num) { 116 case VARIANT_: 117 variant = VARIANT_; 118 break; 119 case VARIANT_C: 120 variant = VARIANT_C; 121 break; 122 case VARIANT_X: 123 variant = VARIANT_X; 124 break; 125 case VARIANT_V: 126 variant = VARIANT_V; 127 break; 128 case VARIANT_VC: 129 variant = VARIANT_VC; 130 break; 131 case VARIANT_VX: 132 variant = VARIANT_VX; 133 break; 134 default: 135 errx(EXIT_FAILURE, "Unknown variant %lld", num); 136 } 137 break; 138 case 'x': 139 num = strtonum(optarg, 0, 127, &errstr); 140 if (errstr != NULL) 141 errx(EXIT_FAILURE, "-x: %s", errstr); 142 exitcode = (int)num; 143 break; 144 default: 145 usage(); 146 break; 147 } 148 } 149 150 argc -= optind; 151 argv += optind; 152 153 if (argc > 0) 154 errx(EXIT_FAILURE, "Unexpected argument '%s'.", argv[1]); 155 156 switch (variant) { 157 case VARIANT_: 158 errno = errcode; 159 if (exitcode != 0) 160 err(exitcode, "E/%d/%d", variant, exitcode); 161 else 162 warn("W/%d", variant); 163 break; 164 case VARIANT_C: 165 errno = 0; 166 if (exitcode != 0) 167 errc(exitcode, errcode, "E/%d/%d", variant, exitcode); 168 else 169 warnc(errcode, "W/%d", variant); 170 break; 171 case VARIANT_X: 172 if (exitcode != 0) 173 errx(exitcode, "E/%d/%d", variant, exitcode); 174 else 175 warnx("W/%d", variant); 176 break; 177 case VARIANT_V: 178 case VARIANT_VC: 179 case VARIANT_VX: 180 if (exitcode != 0) { 181 xtest(variant, errcode, exitcode, "E/%d/%d", variant, 182 exitcode); 183 } else { 184 xtest(variant, errcode, exitcode, "W/%d", variant); 185 } 186 break; 187 } 188 189 return (0); 190 } 191