1 /*
2  * The contents of this file are subject to the terms of the
3  * Common Development and Distribution License, Version 1.0 only
4  * (the "License").  You may not use this file except in compliance
5  * with the License.
6  *
7  * See the file CDDL.Schily.txt in this distribution for details.
8  *
9  * When distributing Covered Code, include this CDDL HEADER in each
10  * file and include the License file CDDL.Schily.txt from this distribution.
11  */
12 /*
13  * @(#)parsex.c	1.10 20/08/24 Copyright 2018-2020 J. Schilling
14  */
15 #if defined(sun)
16 #pragma ident "@(#)parsex.c	1.10 20/08/24 Copyright 2018-2020 J. Schilling"
17 #endif
18 
19 #if defined(sun)
20 #pragma ident	"@(#)parsex.c"
21 #pragma ident	"@(#)sccs:lib/comobj/parsex.c"
22 #endif
23 #include	<defines.h>
24 #include	<i18n.h>
25 
26 int
parseX(X)27 parseX(X)
28 	Xparms	*X;
29 {
30 	char	*opts = X->x_parm;
31 	char	*ep;
32 	char	*np;
33 	int	optlen;
34 	long	optflags = X->x_opts;
35 	unsigned flags = X->x_flags;
36 	BOOL	not = FALSE;
37 
38 	while (*opts) {
39 		/*
40 		 * If '=' appears in the string to the right of a ',', this
41 		 * would be a wrong match.
42 		 */
43 		np = strchr(opts, ',');
44 		if ((ep = strchr(opts, '=')) != NULL &&
45 		    (np == NULL || np > ep)) {
46 			Intptr_t	pdiff = ep - opts;
47 
48 			optlen = (int)pdiff;
49 			if (optlen != pdiff)	/* lint paranoia */
50 				return (FALSE);
51 			optlen++;
52 			if ((np = strchr(opts, ',')) == NULL) {
53 				np = &opts[strlen(opts)];
54 			} else {
55 				np++;
56 			}
57 		} else if ((ep = np) != NULL) {	/* pointer to ',' */
58 			Intptr_t	pdiff = ep - opts;
59 
60 			optlen = (int)pdiff;
61 			if (optlen != pdiff)	/* lint paranoia */
62 				return (FALSE);
63 			np = &ep[1];
64 		} else {
65 			optlen = strlen(opts);
66 			np = &opts[optlen];
67 		}
68 		if (opts[0] == '!') {
69 			opts++;
70 			optlen--;
71 			not = TRUE;
72 		}
73 		if (strncmp(opts, "not", optlen) == 0 ||
74 				strncmp(opts, "!", optlen) == 0) {
75 			not = TRUE;
76 		} else if ((flags & XO_INIT_PATH) &&
77 		    strncmp(opts, "Gp=", optlen) == 0) {
78 			size_t	l = np - &opts[3];
79 
80 			if (optlen != 3)
81 				goto bad;
82 			if (opts[3]) {
83 				if (*np == '\0')
84 					l++;
85 				X->x_init_path = xmalloc(l);
86 				strlcpy(X->x_init_path, &opts[3], l);
87 				optflags |= XO_INIT_PATH;
88 			}
89 
90 		} else if ((flags & XO_URAND) &&
91 		    strncmp(opts, "Gr=", optlen) == 0) {
92 			size_t	l = np - &opts[3];
93 			char	buf[33];
94 
95 			if (*np == '\0')
96 				l++;
97 			if (optlen != 3 || l > sizeof (buf))
98 				goto bad;
99 			if (opts[3]) {
100 				strlcpy(buf, &opts[3], l);
101 				if (*urand_ab(buf, &X->x_rand))
102 					goto bad;
103 				optflags |= XO_URAND;
104 			}
105 
106 		} else if ((flags & XO_G_PATH) &&
107 		    strncmp(opts, "gpath=", optlen) == 0) {
108 			size_t	l = np - &opts[6];
109 
110 			if (optlen != 6)
111 				goto bad;
112 			if (opts[6]) {
113 				if (*np == '\0')
114 					l++;
115 				X->x_gpath = xmalloc(l);
116 				strlcpy(X->x_gpath, &opts[6], l);
117 				optflags |= XO_G_PATH;
118 			}
119 
120 		} else if ((flags & XO_MAIL) &&
121 		    strncmp(opts, "mail=", optlen) == 0) {
122 			size_t	l = np - &opts[5];
123 
124 			if (optlen != 5)
125 				goto bad;
126 			if (opts[5]) {
127 				if (*np == '\0')
128 					l++;
129 				X->x_mail = xmalloc(l);
130 				strlcpy(X->x_mail, &opts[5], l);
131 				optflags |= XO_MAIL;
132 			}
133 
134 		} else if ((flags & XO_USER) &&
135 		    strncmp(opts, "user=", optlen) == 0) {
136 			size_t	l = np - &opts[5];
137 
138 			if (optlen != 5)
139 				goto bad;
140 			if (opts[5]) {
141 				if (*np == '\0')
142 					l++;
143 				X->x_user = xmalloc(l);
144 				strlcpy(X->x_user, &opts[5], l);
145 				optflags |= XO_USER;
146 			}
147 
148 		} else if ((flags & XO_DATE) &&
149 		    strncmp(opts, "date=", optlen) == 0) {
150 			if (optlen != 5)
151 				goto bad;
152 			if (opts[5]) {
153 				parse_datez(&opts[5], &X->x_dtime, PF_V6);
154 				optflags |= XO_DATE;
155 			}
156 		} else if ((flags & XO_PREPEND_FILE) &&
157 		    strncmp(opts, "prepend", optlen) == 0) {
158 			optflags |= XO_PREPEND_FILE;
159 		} else if ((flags & XO_UNLINK) &&
160 		    strncmp(opts, "unlink", optlen) == 0) {
161 			optflags |= XO_UNLINK;
162 		} else if ((flags & XO_NULLPATH) &&
163 		    strncmp(opts, "0", optlen) == 0) {
164 			optflags |= XO_NULLPATH;
165 		} else if ((flags & XO_NOBULK) &&
166 		    strncmp(opts, "nobulk", optlen) == 0) {
167 			optflags |= XO_NOBULK;
168 		} else if (strncmp(opts, "help", optlen) == 0) {
169 			sccshelp(stdout, "Xopts");
170 			exit(0);
171 		} else {
172 		bad:
173 			Fflags &= ~FTLEXIT;
174 			fatal(gettext("illegal Xopt (co41)"));
175 			sccshelp(stdout, "Xopts");
176 			exit(1);
177 		}
178 		opts = np;
179 	}
180 	if (not)
181 		optflags = ~optflags;
182 
183 	X->x_opts = optflags;
184 
185 	return (TRUE);
186 }
187