1621b6cf7SAndy Fiddaman /*
2621b6cf7SAndy Fiddaman * This file and its contents are supplied under the terms of the
3621b6cf7SAndy Fiddaman * Common Development and Distribution License ("CDDL"), version 1.0.
4621b6cf7SAndy Fiddaman * You may only use this file in accordance with the terms of version
5621b6cf7SAndy Fiddaman * 1.0 of the CDDL.
6621b6cf7SAndy Fiddaman *
7621b6cf7SAndy Fiddaman * A full copy of the text of the CDDL should have accompanied this
8621b6cf7SAndy Fiddaman * source. A copy of the CDDL is also available via the Internet at
9621b6cf7SAndy Fiddaman * http://www.illumos.org/license/CDDL.
10621b6cf7SAndy Fiddaman */
11621b6cf7SAndy Fiddaman
12621b6cf7SAndy Fiddaman /*
13621b6cf7SAndy Fiddaman * Copyright 2022 OmniOS Community Edition (OmniOSce) Association.
14621b6cf7SAndy Fiddaman */
15621b6cf7SAndy Fiddaman
16621b6cf7SAndy Fiddaman /*
17621b6cf7SAndy Fiddaman * This file exercises the various err(3C)/warn(3C) functions and produces
18621b6cf7SAndy Fiddaman * output that is checked by the corresponding err.ksh script.
19621b6cf7SAndy Fiddaman */
20621b6cf7SAndy Fiddaman
21621b6cf7SAndy Fiddaman #include <stdio.h>
22621b6cf7SAndy Fiddaman #include <stdlib.h>
23621b6cf7SAndy Fiddaman #include <stdbool.h>
24621b6cf7SAndy Fiddaman #include <errno.h>
25621b6cf7SAndy Fiddaman #include <err.h>
26621b6cf7SAndy Fiddaman #include <sys/debug.h>
27621b6cf7SAndy Fiddaman
28621b6cf7SAndy Fiddaman static FILE *stream = stderr;
29621b6cf7SAndy Fiddaman
30621b6cf7SAndy Fiddaman typedef enum variant {
31621b6cf7SAndy Fiddaman VARIANT_ = 0, /* warn(), err() */
32621b6cf7SAndy Fiddaman VARIANT_C, /* warnc(), errc() */
33621b6cf7SAndy Fiddaman VARIANT_X, /* warnx(), errx() */
34621b6cf7SAndy Fiddaman VARIANT_V, /* vwarn(), verr() */
35621b6cf7SAndy Fiddaman VARIANT_VC, /* vwarnc(), verrc() */
36621b6cf7SAndy Fiddaman VARIANT_VX, /* vwarnx(), verrx() */
37621b6cf7SAndy Fiddaman } variant_t;
38621b6cf7SAndy Fiddaman
39621b6cf7SAndy Fiddaman void
usage(void)40621b6cf7SAndy Fiddaman usage(void)
41621b6cf7SAndy Fiddaman {
42621b6cf7SAndy Fiddaman (void) fprintf(stderr,
43621b6cf7SAndy Fiddaman "usage: err [-e errno] [-x code] [-v variant]\n");
44621b6cf7SAndy Fiddaman exit(EXIT_FAILURE);
45621b6cf7SAndy Fiddaman }
46621b6cf7SAndy Fiddaman
47621b6cf7SAndy Fiddaman void
callback_func(int code)48621b6cf7SAndy Fiddaman callback_func(int code)
49621b6cf7SAndy Fiddaman {
50621b6cf7SAndy Fiddaman (void) fprintf(stream, "CALLBACK %d\n", code);
51621b6cf7SAndy Fiddaman }
52621b6cf7SAndy Fiddaman
53621b6cf7SAndy Fiddaman void
xtest(variant_t variant,int errcode,int exitcode,const char * fmt,...)54621b6cf7SAndy Fiddaman xtest(variant_t variant, int errcode, int exitcode, const char *fmt, ...)
55621b6cf7SAndy Fiddaman {
56621b6cf7SAndy Fiddaman va_list va;
57621b6cf7SAndy Fiddaman
58621b6cf7SAndy Fiddaman va_start(va, fmt);
59621b6cf7SAndy Fiddaman
60621b6cf7SAndy Fiddaman switch (variant) {
61621b6cf7SAndy Fiddaman case VARIANT_V:
62621b6cf7SAndy Fiddaman errno = errcode;
63621b6cf7SAndy Fiddaman if (exitcode != 0)
64621b6cf7SAndy Fiddaman verr(exitcode, fmt, va);
65621b6cf7SAndy Fiddaman else
66621b6cf7SAndy Fiddaman vwarn(fmt, va);
67621b6cf7SAndy Fiddaman break;
68621b6cf7SAndy Fiddaman case VARIANT_VC:
69621b6cf7SAndy Fiddaman errno = 0;
70621b6cf7SAndy Fiddaman if (exitcode != 0)
71621b6cf7SAndy Fiddaman verrc(exitcode, errcode, fmt, va);
72621b6cf7SAndy Fiddaman else
73621b6cf7SAndy Fiddaman vwarnc(errcode, fmt, va);
74621b6cf7SAndy Fiddaman break;
75621b6cf7SAndy Fiddaman case VARIANT_VX:
76621b6cf7SAndy Fiddaman if (exitcode != 0)
77621b6cf7SAndy Fiddaman verrx(exitcode, fmt, va);
78621b6cf7SAndy Fiddaman else
79621b6cf7SAndy Fiddaman vwarnx(fmt, va);
80621b6cf7SAndy Fiddaman break;
81621b6cf7SAndy Fiddaman default:
82621b6cf7SAndy Fiddaman errx(EXIT_FAILURE, "Unhandled variant in %s", __func__);
83621b6cf7SAndy Fiddaman }
84621b6cf7SAndy Fiddaman
85621b6cf7SAndy Fiddaman va_end(va);
86621b6cf7SAndy Fiddaman }
87621b6cf7SAndy Fiddaman
88621b6cf7SAndy Fiddaman int
main(int argc,char ** argv)89621b6cf7SAndy Fiddaman main(int argc, char **argv)
90621b6cf7SAndy Fiddaman {
91621b6cf7SAndy Fiddaman int errcode = 0;
92621b6cf7SAndy Fiddaman int exitcode = 0;
93621b6cf7SAndy Fiddaman variant_t variant = VARIANT_;
94621b6cf7SAndy Fiddaman const char *errstr;
95621b6cf7SAndy Fiddaman long long num;
96621b6cf7SAndy Fiddaman int ch;
97621b6cf7SAndy Fiddaman
98621b6cf7SAndy Fiddaman /*
99621b6cf7SAndy Fiddaman * -e specify errno for the test
100621b6cf7SAndy Fiddaman * -v select variant to test
101621b6cf7SAndy Fiddaman * -x specify exit code for the test
102621b6cf7SAndy Fiddaman */
103621b6cf7SAndy Fiddaman while ((ch = getopt(argc, argv, "e:v:x:")) != -1) {
104621b6cf7SAndy Fiddaman switch (ch) {
105621b6cf7SAndy Fiddaman case 'e':
106621b6cf7SAndy Fiddaman num = strtonum(optarg, 0, 127, &errstr);
107621b6cf7SAndy Fiddaman if (errstr != NULL)
108621b6cf7SAndy Fiddaman errx(EXIT_FAILURE, "-x: %s", errstr);
109621b6cf7SAndy Fiddaman errcode = (int)num;
110621b6cf7SAndy Fiddaman break;
111621b6cf7SAndy Fiddaman case 'v':
112621b6cf7SAndy Fiddaman num = strtonum(optarg, 0, VARIANT_VX, &errstr);
113621b6cf7SAndy Fiddaman if (errstr != NULL)
114621b6cf7SAndy Fiddaman errx(EXIT_FAILURE, "-v: %s", errstr);
115621b6cf7SAndy Fiddaman switch (num) {
116621b6cf7SAndy Fiddaman case VARIANT_:
117621b6cf7SAndy Fiddaman variant = VARIANT_;
118621b6cf7SAndy Fiddaman break;
119621b6cf7SAndy Fiddaman case VARIANT_C:
120621b6cf7SAndy Fiddaman variant = VARIANT_C;
121621b6cf7SAndy Fiddaman break;
122621b6cf7SAndy Fiddaman case VARIANT_X:
123621b6cf7SAndy Fiddaman variant = VARIANT_X;
124621b6cf7SAndy Fiddaman break;
125621b6cf7SAndy Fiddaman case VARIANT_V:
126621b6cf7SAndy Fiddaman variant = VARIANT_V;
127621b6cf7SAndy Fiddaman break;
128621b6cf7SAndy Fiddaman case VARIANT_VC:
129621b6cf7SAndy Fiddaman variant = VARIANT_VC;
130621b6cf7SAndy Fiddaman break;
131621b6cf7SAndy Fiddaman case VARIANT_VX:
132621b6cf7SAndy Fiddaman variant = VARIANT_VX;
133621b6cf7SAndy Fiddaman break;
134621b6cf7SAndy Fiddaman default:
135*6353250fSRobert Mustacchi errx(EXIT_FAILURE, "Unknown variant %lld", num);
136621b6cf7SAndy Fiddaman }
137621b6cf7SAndy Fiddaman break;
138621b6cf7SAndy Fiddaman case 'x':
139621b6cf7SAndy Fiddaman num = strtonum(optarg, 0, 127, &errstr);
140621b6cf7SAndy Fiddaman if (errstr != NULL)
141621b6cf7SAndy Fiddaman errx(EXIT_FAILURE, "-x: %s", errstr);
142621b6cf7SAndy Fiddaman exitcode = (int)num;
143621b6cf7SAndy Fiddaman break;
144621b6cf7SAndy Fiddaman default:
145621b6cf7SAndy Fiddaman usage();
146621b6cf7SAndy Fiddaman break;
147621b6cf7SAndy Fiddaman }
148621b6cf7SAndy Fiddaman }
149621b6cf7SAndy Fiddaman
150621b6cf7SAndy Fiddaman argc -= optind;
151621b6cf7SAndy Fiddaman argv += optind;
152621b6cf7SAndy Fiddaman
153621b6cf7SAndy Fiddaman if (argc > 0)
154621b6cf7SAndy Fiddaman errx(EXIT_FAILURE, "Unexpected argument '%s'.", argv[1]);
155621b6cf7SAndy Fiddaman
156621b6cf7SAndy Fiddaman switch (variant) {
157621b6cf7SAndy Fiddaman case VARIANT_:
158621b6cf7SAndy Fiddaman errno = errcode;
159621b6cf7SAndy Fiddaman if (exitcode != 0)
160621b6cf7SAndy Fiddaman err(exitcode, "E/%d/%d", variant, exitcode);
161621b6cf7SAndy Fiddaman else
162621b6cf7SAndy Fiddaman warn("W/%d", variant);
163621b6cf7SAndy Fiddaman break;
164621b6cf7SAndy Fiddaman case VARIANT_C:
165621b6cf7SAndy Fiddaman errno = 0;
166621b6cf7SAndy Fiddaman if (exitcode != 0)
167621b6cf7SAndy Fiddaman errc(exitcode, errcode, "E/%d/%d", variant, exitcode);
168621b6cf7SAndy Fiddaman else
169621b6cf7SAndy Fiddaman warnc(errcode, "W/%d", variant);
170621b6cf7SAndy Fiddaman break;
171621b6cf7SAndy Fiddaman case VARIANT_X:
172621b6cf7SAndy Fiddaman if (exitcode != 0)
173621b6cf7SAndy Fiddaman errx(exitcode, "E/%d/%d", variant, exitcode);
174621b6cf7SAndy Fiddaman else
175621b6cf7SAndy Fiddaman warnx("W/%d", variant);
176621b6cf7SAndy Fiddaman break;
177621b6cf7SAndy Fiddaman case VARIANT_V:
178621b6cf7SAndy Fiddaman case VARIANT_VC:
179621b6cf7SAndy Fiddaman case VARIANT_VX:
180621b6cf7SAndy Fiddaman if (exitcode != 0) {
181621b6cf7SAndy Fiddaman xtest(variant, errcode, exitcode, "E/%d/%d", variant,
182621b6cf7SAndy Fiddaman exitcode);
183621b6cf7SAndy Fiddaman } else {
184621b6cf7SAndy Fiddaman xtest(variant, errcode, exitcode, "W/%d", variant);
185621b6cf7SAndy Fiddaman }
186621b6cf7SAndy Fiddaman break;
187621b6cf7SAndy Fiddaman }
188621b6cf7SAndy Fiddaman
189621b6cf7SAndy Fiddaman return (0);
190621b6cf7SAndy Fiddaman }
191