]> git.zerfleddert.de Git - micropolis/blob - src/tclx/src/tclxchmd.c
Fixes for compilation with gcc 15
[micropolis] / src / tclx / src / tclxchmd.c
1 /*
2 * tclXchmod.c --
3 *
4 * Chmod, chown and chgrp Tcl commands.
5 *-----------------------------------------------------------------------------
6 * Copyright 1992 Karl Lehenbauer and Mark Diekhans.
7 *
8 * Permission to use, copy, modify, and distribute this software and its
9 * documentation for any purpose and without fee is hereby granted, provided
10 * that the above copyright notice appear in all copies. Karl Lehenbauer and
11 * Mark Diekhans make no representations about the suitability of this
12 * software for any purpose. It is provided "as is" without express or
13 * implied warranty.
14 *-----------------------------------------------------------------------------
15 * $Id: tclXchmod.c,v 2.0 1992/10/16 04:50:26 markd Rel $
16 *-----------------------------------------------------------------------------
17 */
18
19 #include "tclxint.h"
20
21 /*
22 * Prototypes of internal functions.
23 */
24 static int
25 ConvSymMode _ANSI_ARGS_((Tcl_Interp *interp,
26 char *symMode,
27 int modeVal));
28
29 \f
30 /*
31 *-----------------------------------------------------------------------------
32 *
33 * ConvSymMode --
34 * Parse and convert symbolic file permissions as specified by chmod(C).
35 *
36 * Parameters:
37 * o interp - Pointer to the current interpreter, error messages will be
38 * returned in the result.
39 * o symMode - The symbolic permissions to parse.
40 * o modeVal - The existing permissions value on a file.
41 *
42 * Results:
43 * The new permissions, or -1 if invalid permissions where supplied.
44 *
45 *-----------------------------------------------------------------------------
46 */
47 static int
48 ConvSymMode (Tcl_Interp *interp, char *symMode, int modeVal)
49
50 {
51 int user, group, other;
52 char operator, *scanPtr;
53 int rwxMask, ugoMask, setUID, sticky, locking;
54 int newMode;
55
56 scanPtr = symMode;
57
58 while (*scanPtr != '\0') {
59 user = group = other = FALSE;
60
61 /*
62 * Scan who field.
63 */
64 while (! ((*scanPtr == '+') ||
65 (*scanPtr == '-') ||
66 (*scanPtr == '='))) {
67 switch (*scanPtr) {
68 case 'a':
69 user = group = other = TRUE;
70 break;
71 case 'u':
72 user = TRUE;
73 break;
74 case 'g':
75 group = TRUE;
76 break;
77 case 'o':
78 other = TRUE;
79 break;
80 default:
81 goto invalidMode;
82 }
83 scanPtr++;
84 }
85
86 /*
87 * If none where specified, that means all.
88 */
89
90 if (! (user || group || other))
91 user = group = other = TRUE;
92
93 operator = *scanPtr++;
94
95 /*
96 * Decode the permissions
97 */
98
99 rwxMask = 0;
100 setUID = sticky = locking = FALSE;
101
102 /*
103 * Scan permissions field
104 */
105 while (! ((*scanPtr == ',') || (*scanPtr == 0))) {
106 switch (*scanPtr) {
107 case 'r':
108 rwxMask |= 4;
109 break;
110 case 'w':
111 rwxMask |= 2;
112 break;
113 case 'x':
114 rwxMask |= 1;
115 break;
116 case 's':
117 setUID = TRUE;
118 break;
119 case 't':
120 sticky = TRUE;
121 break;
122 case 'l':
123 locking = TRUE;
124 break;
125 default:
126 goto invalidMode;
127 }
128 scanPtr++;
129 }
130
131 /*
132 * Build mode map of specified values.
133 */
134
135 newMode = 0;
136 ugoMask = 0;
137 if (user) {
138 newMode |= rwxMask << 6;
139 ugoMask |= 0700;
140 }
141 if (group) {
142 newMode |= rwxMask << 3;
143 ugoMask |= 0070;
144 }
145 if (other) {
146 newMode |= rwxMask;
147 ugoMask |= 0007;
148 }
149 if (setUID && user)
150 newMode |= 04000;
151 if ((setUID || locking) && group)
152 newMode |= 02000;
153 if (sticky)
154 newMode |= 01000;
155
156 /*
157 * Add to cumulative mode based on operator.
158 */
159
160 if (operator == '+')
161 modeVal |= newMode;
162 else if (operator == '-')
163 modeVal &= ~newMode;
164 else if (operator == '=')
165 modeVal |= (modeVal & ugoMask) | newMode;
166 if (*scanPtr == ',')
167 scanPtr++;
168 }
169
170 return modeVal;
171
172 invalidMode:
173 Tcl_AppendResult (interp, "invalid file mode \"", symMode, "\"",
174 (char *) NULL);
175 return -1;
176 }
177 \f
178 /*
179 *-----------------------------------------------------------------------------
180 *
181 * Tcl_ChmodCmd --
182 * Implements the TCL chmod command:
183 * chmod mode filelist
184 *
185 * Results:
186 * Standard TCL results, may return the UNIX system error message.
187 *
188 *-----------------------------------------------------------------------------
189 */
190 int
191 Tcl_ChmodCmd (
192 ClientData clientData,
193 Tcl_Interp *interp,
194 int argc,
195 char **argv
196 )
197 {
198 int idx, modeVal, fileArgc, absMode;
199 char **fileArgv;
200 struct stat fileStat;
201
202 if (argc != 3) {
203 Tcl_AppendResult (interp, tclXWrongArgs, argv [0],
204 " mode filelist", (char *) NULL);
205 return TCL_ERROR;
206 }
207
208 if (isdigit (argv [1][0])) {
209 if (Tcl_GetInt (interp, argv [1], &modeVal) != TCL_OK)
210 return TCL_ERROR;
211 absMode = TRUE;
212 } else
213 absMode = FALSE;
214
215 if (Tcl_SplitList (interp, argv [2], &fileArgc, &fileArgv) != TCL_OK)
216 return TCL_ERROR;
217
218 for (idx = 0; idx < fileArgc; idx++) {
219 if (!absMode) {
220 if (stat (fileArgv [idx], &fileStat) != 0)
221 goto fileError;
222 modeVal = ConvSymMode (interp, argv [1], fileStat.st_mode & 07777);
223 if (modeVal < 0)
224 goto errorExit;
225 }
226 if (chmod (fileArgv [idx], (unsigned short) modeVal) < 0)
227 goto fileError;
228 }
229
230 exitPoint:
231 ckfree ((char *) fileArgv);
232 return TCL_OK;
233
234 fileError:
235 /*
236 * Error accessing file, assumes file name is fileArgv [idx].
237 */
238 Tcl_AppendResult (interp, fileArgv [idx], ": ", Tcl_UnixError (interp),
239 (char *) NULL);
240
241 errorExit:
242 ckfree ((char *) fileArgv);
243 return TCL_ERROR;
244 }
245 \f
246 /*
247 *-----------------------------------------------------------------------------
248 *
249 * Tcl_ChownCmd --
250 * Implements the TCL chown command:
251 * chown owner filelist
252 * chown {owner group} filelist
253 *
254 * Results:
255 * Standard TCL results, may return the UNIX system error message.
256 *
257 *-----------------------------------------------------------------------------
258 */
259 int
260 Tcl_ChownCmd (
261 ClientData clientData,
262 Tcl_Interp *interp,
263 int argc,
264 char **argv
265 )
266 {
267 int idx, ownArgc, fileArgc;
268 char **ownArgv, **fileArgv = NULL;
269 struct stat fileStat;
270 int useOwnerGrp, chGroup, ownerId, groupId;
271 struct passwd *passwdPtr;
272 struct group *groupPtr;
273 int result = TCL_ERROR;
274
275 if (argc != 3) {
276 Tcl_AppendResult (interp, tclXWrongArgs, argv [0],
277 " owner|{owner group} filelist", (char *) NULL);
278 return TCL_ERROR;
279 }
280
281 if (Tcl_SplitList (interp, argv[1], &ownArgc, &ownArgv) != TCL_OK)
282 return TCL_ERROR;
283 if ((ownArgc < 1) || (ownArgc > 2)) {
284 interp->result = "owner arg should be: owner or {owner group}";
285 goto exitPoint;
286 }
287 if (ownArgc == 2) {
288 useOwnerGrp = (ownArgv [1][0] == '\0');
289 chGroup = TRUE;
290 } else
291 chGroup = FALSE;
292
293 /*
294 * Get the owner id, either convert the name or use it as an integer.
295 */
296 passwdPtr = getpwnam (ownArgv [0]);
297 if (passwdPtr != NULL)
298 ownerId = passwdPtr->pw_uid;
299 else {
300 if (!Tcl_StrToInt (ownArgv [0], 10, &ownerId)) {
301 Tcl_AppendResult (interp, "unknown user id: ", ownArgv [0],
302 (char *) NULL);
303 goto exitPoint;
304 }
305 }
306 /*
307 * Get the group id, this is either the specified id or name, or the
308 * if associated with the specified user.
309 */
310 if (chGroup) {
311 if (useOwnerGrp) {
312 if (passwdPtr == NULL) {
313 passwdPtr = getpwuid (ownerId);
314 if (passwdPtr != NULL) {
315 Tcl_AppendResult (interp, "unknown user id: ",
316 ownArgv [0], (char *) NULL);
317 goto exitPoint;
318 }
319 }
320 groupId = passwdPtr->pw_gid;
321 } else {
322 groupPtr = getgrnam (ownArgv [1]);
323 if (groupPtr != NULL)
324 groupId = groupPtr->gr_gid;
325 else {
326 if (!Tcl_StrToInt (ownArgv [1], 10, &groupId)) {
327 Tcl_AppendResult (interp, "unknown group id: ",
328 ownArgv [1], (char *) NULL);
329 goto exitPoint;
330 }
331 }
332 }
333 }
334 if (Tcl_SplitList (interp, argv [2], &fileArgc, &fileArgv) != TCL_OK)
335 goto exitPoint;
336
337 for (idx = 0; idx < fileArgc; idx++) {
338 if (!chGroup) {
339 if (stat (fileArgv [idx], &fileStat) != 0) {
340 Tcl_AppendResult (interp, fileArgv [idx], ": ",
341 Tcl_UnixError (interp), (char *) NULL);
342 goto exitPoint;
343 }
344 groupId = fileStat.st_gid;
345 }
346
347 if (chown (fileArgv[idx], ownerId, groupId) < 0) {
348 Tcl_AppendResult (interp, fileArgv [idx], ": ",
349 Tcl_UnixError (interp), (char *) NULL);
350 goto exitPoint;
351 }
352
353 } /* Modify each file */
354
355 result = TCL_OK;
356 exitPoint:
357 ckfree ((char *) ownArgv);
358 if (fileArgv != NULL)
359 ckfree ((char *) fileArgv);
360 return result;
361 }
362 \f
363 /*
364 *-----------------------------------------------------------------------------
365 *
366 * Tcl_ChgrpCmd --
367 * Implements the TCL chgrp command:
368 * chgrp group filelist
369 *
370 * Results:
371 * Standard TCL results, may return the UNIX system error message.
372 *
373 *-----------------------------------------------------------------------------
374 */
375 int
376 Tcl_ChgrpCmd (
377 ClientData clientData,
378 Tcl_Interp *interp,
379 int argc,
380 char **argv
381 )
382 {
383 int idx, fileArgc, groupId, result = TCL_ERROR;
384 char **fileArgv;
385 struct stat fileStat;
386 struct group *groupPtr;
387
388 if (argc < 3) {
389 Tcl_AppendResult (interp, tclXWrongArgs, argv [0],
390 " group filelist", (char *) NULL);
391 return TCL_ERROR;
392 }
393
394 groupPtr = getgrnam (argv [1]);
395 if (groupPtr != NULL)
396 groupId = groupPtr->gr_gid;
397 else {
398 if (!Tcl_StrToInt (argv [1], 10, &groupId)) {
399 Tcl_AppendResult (interp, "unknown group id: ", argv [1],
400 (char *) NULL);
401 return TCL_ERROR;
402 }
403 }
404 if (Tcl_SplitList (interp, argv [2], &fileArgc, &fileArgv) != TCL_OK)
405 return TCL_ERROR;
406
407 for (idx = 0; idx < fileArgc; idx++) {
408 if ((stat (fileArgv [idx], &fileStat) != 0) ||
409 (chown (fileArgv[idx], fileStat.st_uid, groupId) < 0)) {
410 Tcl_AppendResult (interp, fileArgv [idx], ": ",
411 Tcl_UnixError (interp), (char *) NULL);
412 goto exitPoint;
413 }
414 } /* Modify each file */
415
416 result = TCL_OK;
417 exitPoint:
418 ckfree ((char *) fileArgv);
419 return result;
420 }
Impressum, Datenschutz