1*6b734416SAndy Fiddaman /*
2*6b734416SAndy Fiddaman * CDDL HEADER START
3*6b734416SAndy Fiddaman *
4*6b734416SAndy Fiddaman * The contents of this file are subject to the terms of the
5*6b734416SAndy Fiddaman * Common Development and Distribution License (the "License").
6*6b734416SAndy Fiddaman * You may not use this file except in compliance with the License.
7*6b734416SAndy Fiddaman *
8*6b734416SAndy Fiddaman * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*6b734416SAndy Fiddaman * or http://www.opensolaris.org/os/licensing.
10*6b734416SAndy Fiddaman * See the License for the specific language governing permissions
11*6b734416SAndy Fiddaman * and limitations under the License.
12*6b734416SAndy Fiddaman *
13*6b734416SAndy Fiddaman * When distributing Covered Code, include this CDDL HEADER in each
14*6b734416SAndy Fiddaman * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*6b734416SAndy Fiddaman * If applicable, add the following below this CDDL HEADER, with the
16*6b734416SAndy Fiddaman * fields enclosed by brackets "[]" replaced with your own identifying
17*6b734416SAndy Fiddaman * information: Portions Copyright [yyyy] [name of copyright owner]
18*6b734416SAndy Fiddaman *
19*6b734416SAndy Fiddaman * CDDL HEADER END
20*6b734416SAndy Fiddaman */
21*6b734416SAndy Fiddaman
22*6b734416SAndy Fiddaman /*
23*6b734416SAndy Fiddaman * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*6b734416SAndy Fiddaman * Use is subject to license terms.
25*6b734416SAndy Fiddaman */
26*6b734416SAndy Fiddaman
27*6b734416SAndy Fiddaman /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*6b734416SAndy Fiddaman /* All Rights Reserved */
29*6b734416SAndy Fiddaman
30*6b734416SAndy Fiddaman /*
31*6b734416SAndy Fiddaman * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
32*6b734416SAndy Fiddaman */
33*6b734416SAndy Fiddaman
34*6b734416SAndy Fiddaman #include <stdio.h>
35*6b734416SAndy Fiddaman #include <err.h>
36*6b734416SAndy Fiddaman #include <sys/types.h>
37*6b734416SAndy Fiddaman #include <string.h>
38*6b734416SAndy Fiddaman #include <stdlib.h>
39*6b734416SAndy Fiddaman #include <ctype.h>
40*6b734416SAndy Fiddaman #include <assert.h>
41*6b734416SAndy Fiddaman #include <libcustr.h>
42*6b734416SAndy Fiddaman #include "cron.h"
43*6b734416SAndy Fiddaman
44*6b734416SAndy Fiddaman #ifdef PARSETEST
45*6b734416SAndy Fiddaman #define xstrdup(x) strdup((x))
46*6b734416SAndy Fiddaman #endif
47*6b734416SAndy Fiddaman
48*6b734416SAndy Fiddaman #define MAX_ELEMENTS 60
49*6b734416SAndy Fiddaman
50*6b734416SAndy Fiddaman #define READNUMBER(x) \
51*6b734416SAndy Fiddaman do { \
52*6b734416SAndy Fiddaman (x) = (x) * 10 + (line[cursor] - '0'); \
53*6b734416SAndy Fiddaman if ((x) > MAX_ELEMENTS) { \
54*6b734416SAndy Fiddaman err = CFOUTOFBOUND; \
55*6b734416SAndy Fiddaman goto out; \
56*6b734416SAndy Fiddaman } \
57*6b734416SAndy Fiddaman } while (isdigit(line[++cursor]))
58*6b734416SAndy Fiddaman
59*6b734416SAndy Fiddaman #define ADDELEMENT(x) \
60*6b734416SAndy Fiddaman do { \
61*6b734416SAndy Fiddaman if (eindex >= MAX_ELEMENTS) { \
62*6b734416SAndy Fiddaman err = CFEOVERFLOW; \
63*6b734416SAndy Fiddaman goto out; \
64*6b734416SAndy Fiddaman } \
65*6b734416SAndy Fiddaman elements[eindex++] = (x); \
66*6b734416SAndy Fiddaman } while (0)
67*6b734416SAndy Fiddaman
68*6b734416SAndy Fiddaman /* A more restrictive version of isspace(3C) that only looks for space/tab */
69*6b734416SAndy Fiddaman #define ISSPACE(x) \
70*6b734416SAndy Fiddaman ((x) == ' ' || (x) == '\t')
71*6b734416SAndy Fiddaman
72*6b734416SAndy Fiddaman cferror_t
next_field(uint_t lower,uint_t upper,char * line,int * cursorp,char ** ret)73*6b734416SAndy Fiddaman next_field(uint_t lower, uint_t upper, char *line, int *cursorp, char **ret)
74*6b734416SAndy Fiddaman {
75*6b734416SAndy Fiddaman uint_t elements[MAX_ELEMENTS];
76*6b734416SAndy Fiddaman uint_t eindex = 0, i;
77*6b734416SAndy Fiddaman int cursor = *cursorp;
78*6b734416SAndy Fiddaman cferror_t err = CFOK;
79*6b734416SAndy Fiddaman
80*6b734416SAndy Fiddaman assert(upper - lower <= MAX_ELEMENTS);
81*6b734416SAndy Fiddaman
82*6b734416SAndy Fiddaman if (ret != NULL)
83*6b734416SAndy Fiddaman *ret = NULL;
84*6b734416SAndy Fiddaman
85*6b734416SAndy Fiddaman while (ISSPACE(line[cursor]))
86*6b734416SAndy Fiddaman cursor++;
87*6b734416SAndy Fiddaman
88*6b734416SAndy Fiddaman if (line[cursor] == '\0') {
89*6b734416SAndy Fiddaman err = CFEOLN;
90*6b734416SAndy Fiddaman goto out;
91*6b734416SAndy Fiddaman }
92*6b734416SAndy Fiddaman
93*6b734416SAndy Fiddaman for (;;) {
94*6b734416SAndy Fiddaman uint_t num = 0, num2 = 0, step = 0;
95*6b734416SAndy Fiddaman
96*6b734416SAndy Fiddaman if (line[cursor] == '*') {
97*6b734416SAndy Fiddaman cursor++;
98*6b734416SAndy Fiddaman
99*6b734416SAndy Fiddaman /* Short circuit for plain '*' */
100*6b734416SAndy Fiddaman if (ISSPACE(line[cursor])) {
101*6b734416SAndy Fiddaman if (ret != NULL)
102*6b734416SAndy Fiddaman *ret = xstrdup("*");
103*6b734416SAndy Fiddaman goto out;
104*6b734416SAndy Fiddaman }
105*6b734416SAndy Fiddaman
106*6b734416SAndy Fiddaman /*
107*6b734416SAndy Fiddaman * '*' is only permitted alongside other elements if
108*6b734416SAndy Fiddaman * it has an associated step.
109*6b734416SAndy Fiddaman */
110*6b734416SAndy Fiddaman
111*6b734416SAndy Fiddaman if (line[cursor] != '/') {
112*6b734416SAndy Fiddaman err = CFUNEXPECT;
113*6b734416SAndy Fiddaman goto out;
114*6b734416SAndy Fiddaman }
115*6b734416SAndy Fiddaman
116*6b734416SAndy Fiddaman /* Treat it as a range covering all values */
117*6b734416SAndy Fiddaman num = lower;
118*6b734416SAndy Fiddaman num2 = upper;
119*6b734416SAndy Fiddaman } else {
120*6b734416SAndy Fiddaman if (!isdigit(line[cursor])) {
121*6b734416SAndy Fiddaman err = CFUNEXPECT;
122*6b734416SAndy Fiddaman goto out;
123*6b734416SAndy Fiddaman }
124*6b734416SAndy Fiddaman
125*6b734416SAndy Fiddaman READNUMBER(num);
126*6b734416SAndy Fiddaman
127*6b734416SAndy Fiddaman if (num < lower || num > upper) {
128*6b734416SAndy Fiddaman err = CFOUTOFBOUND;
129*6b734416SAndy Fiddaman goto out;
130*6b734416SAndy Fiddaman }
131*6b734416SAndy Fiddaman
132*6b734416SAndy Fiddaman if (line[cursor] == '-') {
133*6b734416SAndy Fiddaman cursor++;
134*6b734416SAndy Fiddaman if (!isdigit(line[cursor])) {
135*6b734416SAndy Fiddaman err = CFUNEXPECT;
136*6b734416SAndy Fiddaman goto out;
137*6b734416SAndy Fiddaman }
138*6b734416SAndy Fiddaman
139*6b734416SAndy Fiddaman READNUMBER(num2);
140*6b734416SAndy Fiddaman
141*6b734416SAndy Fiddaman if (num2 < lower || num2 > upper) {
142*6b734416SAndy Fiddaman err = CFOUTOFBOUND;
143*6b734416SAndy Fiddaman goto out;
144*6b734416SAndy Fiddaman }
145*6b734416SAndy Fiddaman } else {
146*6b734416SAndy Fiddaman ADDELEMENT(num);
147*6b734416SAndy Fiddaman goto next;
148*6b734416SAndy Fiddaman }
149*6b734416SAndy Fiddaman }
150*6b734416SAndy Fiddaman
151*6b734416SAndy Fiddaman /* Look for a step definition */
152*6b734416SAndy Fiddaman if (line[cursor] == '/') {
153*6b734416SAndy Fiddaman cursor++;
154*6b734416SAndy Fiddaman if (!isdigit(line[cursor])) {
155*6b734416SAndy Fiddaman err = CFUNEXPECT;
156*6b734416SAndy Fiddaman goto out;
157*6b734416SAndy Fiddaman }
158*6b734416SAndy Fiddaman
159*6b734416SAndy Fiddaman READNUMBER(step);
160*6b734416SAndy Fiddaman
161*6b734416SAndy Fiddaman if (step == 0) {
162*6b734416SAndy Fiddaman err = CFOUTOFBOUND;
163*6b734416SAndy Fiddaman goto out;
164*6b734416SAndy Fiddaman }
165*6b734416SAndy Fiddaman } else {
166*6b734416SAndy Fiddaman step = 1;
167*6b734416SAndy Fiddaman }
168*6b734416SAndy Fiddaman
169*6b734416SAndy Fiddaman if (num <= num2) {
170*6b734416SAndy Fiddaman for (i = num; i <= num2; i += step) {
171*6b734416SAndy Fiddaman ADDELEMENT(i);
172*6b734416SAndy Fiddaman }
173*6b734416SAndy Fiddaman } else {
174*6b734416SAndy Fiddaman /* Wrap-around range */
175*6b734416SAndy Fiddaman for (i = num; i <= upper; i += step) {
176*6b734416SAndy Fiddaman ADDELEMENT(i);
177*6b734416SAndy Fiddaman }
178*6b734416SAndy Fiddaman
179*6b734416SAndy Fiddaman i -= (upper - lower + 1);
180*6b734416SAndy Fiddaman for (; i <= num2; i += step) {
181*6b734416SAndy Fiddaman ADDELEMENT(i);
182*6b734416SAndy Fiddaman }
183*6b734416SAndy Fiddaman }
184*6b734416SAndy Fiddaman
185*6b734416SAndy Fiddaman next:
186*6b734416SAndy Fiddaman
187*6b734416SAndy Fiddaman if (line[cursor] != ',')
188*6b734416SAndy Fiddaman break;
189*6b734416SAndy Fiddaman
190*6b734416SAndy Fiddaman cursor++;
191*6b734416SAndy Fiddaman }
192*6b734416SAndy Fiddaman
193*6b734416SAndy Fiddaman if (line[cursor] == '\0') {
194*6b734416SAndy Fiddaman err = CFEOLN;
195*6b734416SAndy Fiddaman goto out;
196*6b734416SAndy Fiddaman }
197*6b734416SAndy Fiddaman
198*6b734416SAndy Fiddaman if (!ISSPACE(line[cursor])) {
199*6b734416SAndy Fiddaman err = CFUNEXPECT;
200*6b734416SAndy Fiddaman goto out;
201*6b734416SAndy Fiddaman }
202*6b734416SAndy Fiddaman
203*6b734416SAndy Fiddaman if (ret != NULL) {
204*6b734416SAndy Fiddaman custr_t *cs = NULL;
205*6b734416SAndy Fiddaman
206*6b734416SAndy Fiddaman if (custr_alloc(&cs) != 0) {
207*6b734416SAndy Fiddaman err = CFENOMEM;
208*6b734416SAndy Fiddaman goto out;
209*6b734416SAndy Fiddaman }
210*6b734416SAndy Fiddaman
211*6b734416SAndy Fiddaman for (i = 0; i < eindex; i++) {
212*6b734416SAndy Fiddaman if (custr_len(cs) > 0) {
213*6b734416SAndy Fiddaman if (custr_appendc(cs, ',') != 0) {
214*6b734416SAndy Fiddaman custr_free(cs);
215*6b734416SAndy Fiddaman err = CFENOMEM;
216*6b734416SAndy Fiddaman goto out;
217*6b734416SAndy Fiddaman }
218*6b734416SAndy Fiddaman }
219*6b734416SAndy Fiddaman if (custr_append_printf(cs, "%u", elements[i]) != 0) {
220*6b734416SAndy Fiddaman custr_free(cs);
221*6b734416SAndy Fiddaman err = CFENOMEM;
222*6b734416SAndy Fiddaman goto out;
223*6b734416SAndy Fiddaman }
224*6b734416SAndy Fiddaman }
225*6b734416SAndy Fiddaman
226*6b734416SAndy Fiddaman if (custr_len(cs) != 0)
227*6b734416SAndy Fiddaman *ret = xstrdup(custr_cstr(cs));
228*6b734416SAndy Fiddaman custr_free(cs);
229*6b734416SAndy Fiddaman }
230*6b734416SAndy Fiddaman
231*6b734416SAndy Fiddaman out:
232*6b734416SAndy Fiddaman
233*6b734416SAndy Fiddaman *cursorp = cursor;
234*6b734416SAndy Fiddaman
235*6b734416SAndy Fiddaman return (err);
236*6b734416SAndy Fiddaman }
237*6b734416SAndy Fiddaman
238*6b734416SAndy Fiddaman #ifdef PARSETEST
239*6b734416SAndy Fiddaman int
main(int argc,char ** argv)240*6b734416SAndy Fiddaman main(int argc, char **argv)
241*6b734416SAndy Fiddaman {
242*6b734416SAndy Fiddaman int lower, upper, cursor = 0;
243*6b734416SAndy Fiddaman char *ret;
244*6b734416SAndy Fiddaman
245*6b734416SAndy Fiddaman if (argc != 4)
246*6b734416SAndy Fiddaman errx(1, "<lower> <upper> <string>");
247*6b734416SAndy Fiddaman
248*6b734416SAndy Fiddaman lower = atoi(argv[1]);
249*6b734416SAndy Fiddaman upper = atoi(argv[2]);
250*6b734416SAndy Fiddaman
251*6b734416SAndy Fiddaman switch (next_field(lower, upper, argv[3], &cursor, &ret)) {
252*6b734416SAndy Fiddaman case CFOK:
253*6b734416SAndy Fiddaman (void) printf("%s\n", ret);
254*6b734416SAndy Fiddaman break;
255*6b734416SAndy Fiddaman case CFEOLN:
256*6b734416SAndy Fiddaman (void) printf("UnexpectedEOL\n");
257*6b734416SAndy Fiddaman break;
258*6b734416SAndy Fiddaman case CFUNEXPECT:
259*6b734416SAndy Fiddaman (void) printf("UnexpectedChar\n");
260*6b734416SAndy Fiddaman break;
261*6b734416SAndy Fiddaman case CFOUTOFBOUND:
262*6b734416SAndy Fiddaman (void) printf("OutOfBounds\n");
263*6b734416SAndy Fiddaman break;
264*6b734416SAndy Fiddaman case CFEOVERFLOW:
265*6b734416SAndy Fiddaman (void) printf("Overflow\n");
266*6b734416SAndy Fiddaman break;
267*6b734416SAndy Fiddaman case CFENOMEM:
268*6b734416SAndy Fiddaman (void) printf("OutOfMemory\n");
269*6b734416SAndy Fiddaman break;
270*6b734416SAndy Fiddaman default:
271*6b734416SAndy Fiddaman (void) printf("UnknownError\n");
272*6b734416SAndy Fiddaman break;
273*6b734416SAndy Fiddaman }
274*6b734416SAndy Fiddaman
275*6b734416SAndy Fiddaman return (0);
276*6b734416SAndy Fiddaman }
277*6b734416SAndy Fiddaman #endif
278