]>
cvs.zerfleddert.de Git - micropolis/blob - src/tclx/src/tclxchmd.c
4 * Chmod, chown and chgrp Tcl commands.
5 *-----------------------------------------------------------------------------
6 * Copyright 1992 Karl Lehenbauer and Mark Diekhans.
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
14 *-----------------------------------------------------------------------------
15 * $Id: tclXchmod.c,v 2.0 1992/10/16 04:50:26 markd Rel $
16 *-----------------------------------------------------------------------------
22 * Prototypes of internal functions.
25 ConvSymMode
_ANSI_ARGS_((Tcl_Interp
*interp
,
31 *-----------------------------------------------------------------------------
34 * Parse and convert symbolic file permissions as specified by chmod(C).
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.
43 * The new permissions, or -1 if invalid permissions where supplied.
45 *-----------------------------------------------------------------------------
48 ConvSymMode (interp
, symMode
, modeVal
)
54 int user
, group
, other
;
55 char operator, *scanPtr
;
56 int rwxMask
, ugoMask
, setUID
, sticky
, locking
;
61 while (*scanPtr
!= '\0') {
62 user
= group
= other
= FALSE
;
67 while (! ((*scanPtr
== '+') ||
72 user
= group
= other
= TRUE
;
90 * If none where specified, that means all.
93 if (! (user
|| group
|| other
))
94 user
= group
= other
= TRUE
;
96 operator = *scanPtr
++;
99 * Decode the permissions
103 setUID
= sticky
= locking
= FALSE
;
106 * Scan permissions field
108 while (! ((*scanPtr
== ',') || (*scanPtr
== 0))) {
135 * Build mode map of specified values.
141 newMode
|= rwxMask
<< 6;
145 newMode
|= rwxMask
<< 3;
154 if ((setUID
|| locking
) && group
)
160 * Add to cumulative mode based on operator.
165 else if (operator == '-')
167 else if (operator == '=')
168 modeVal
|= (modeVal
& ugoMask
) | newMode
;
176 Tcl_AppendResult (interp
, "invalid file mode \"", symMode
, "\"",
182 *-----------------------------------------------------------------------------
185 * Implements the TCL chmod command:
186 * chmod mode filelist
189 * Standard TCL results, may return the UNIX system error message.
191 *-----------------------------------------------------------------------------
194 Tcl_ChmodCmd (clientData
, interp
, argc
, argv
)
195 ClientData clientData
;
200 int idx
, modeVal
, fileArgc
, absMode
;
202 struct stat fileStat
;
205 Tcl_AppendResult (interp
, tclXWrongArgs
, argv
[0],
206 " mode filelist", (char *) NULL
);
210 if (isdigit (argv
[1][0])) {
211 if (Tcl_GetInt (interp
, argv
[1], &modeVal
) != TCL_OK
)
217 if (Tcl_SplitList (interp
, argv
[2], &fileArgc
, &fileArgv
) != TCL_OK
)
220 for (idx
= 0; idx
< fileArgc
; idx
++) {
222 if (stat (fileArgv
[idx
], &fileStat
) != 0)
224 modeVal
= ConvSymMode (interp
, argv
[1], fileStat
.st_mode
& 07777);
228 if (chmod (fileArgv
[idx
], (unsigned short) modeVal
) < 0)
233 ckfree ((char *) fileArgv
);
238 * Error accessing file, assumes file name is fileArgv [idx].
240 Tcl_AppendResult (interp
, fileArgv
[idx
], ": ", Tcl_UnixError (interp
),
244 ckfree ((char *) fileArgv
);
249 *-----------------------------------------------------------------------------
252 * Implements the TCL chown command:
253 * chown owner filelist
254 * chown {owner group} filelist
257 * Standard TCL results, may return the UNIX system error message.
259 *-----------------------------------------------------------------------------
262 Tcl_ChownCmd (clientData
, interp
, argc
, argv
)
263 ClientData clientData
;
268 int idx
, ownArgc
, fileArgc
;
269 char **ownArgv
, **fileArgv
= NULL
;
270 struct stat fileStat
;
271 int useOwnerGrp
, chGroup
, ownerId
, groupId
;
272 struct passwd
*passwdPtr
;
273 struct group
*groupPtr
;
274 int result
= TCL_ERROR
;
277 Tcl_AppendResult (interp
, tclXWrongArgs
, argv
[0],
278 " owner|{owner group} filelist", (char *) NULL
);
282 if (Tcl_SplitList (interp
, argv
[1], &ownArgc
, &ownArgv
) != TCL_OK
)
284 if ((ownArgc
< 1) || (ownArgc
> 2)) {
285 interp
->result
= "owner arg should be: owner or {owner group}";
289 useOwnerGrp
= (ownArgv
[1][0] == '\0');
295 * Get the owner id, either convert the name or use it as an integer.
297 passwdPtr
= getpwnam (ownArgv
[0]);
298 if (passwdPtr
!= NULL
)
299 ownerId
= passwdPtr
->pw_uid
;
301 if (!Tcl_StrToInt (ownArgv
[0], 10, &ownerId
)) {
302 Tcl_AppendResult (interp
, "unknown user id: ", ownArgv
[0],
308 * Get the group id, this is either the specified id or name, or the
309 * if associated with the specified user.
313 if (passwdPtr
== NULL
) {
314 passwdPtr
= getpwuid (ownerId
);
315 if (passwdPtr
!= NULL
) {
316 Tcl_AppendResult (interp
, "unknown user id: ",
317 ownArgv
[0], (char *) NULL
);
321 groupId
= passwdPtr
->pw_gid
;
323 groupPtr
= getgrnam (ownArgv
[1]);
324 if (groupPtr
!= NULL
)
325 groupId
= groupPtr
->gr_gid
;
327 if (!Tcl_StrToInt (ownArgv
[1], 10, &groupId
)) {
328 Tcl_AppendResult (interp
, "unknown group id: ",
329 ownArgv
[1], (char *) NULL
);
335 if (Tcl_SplitList (interp
, argv
[2], &fileArgc
, &fileArgv
) != TCL_OK
)
338 for (idx
= 0; idx
< fileArgc
; idx
++) {
340 if (stat (fileArgv
[idx
], &fileStat
) != 0) {
341 Tcl_AppendResult (interp
, fileArgv
[idx
], ": ",
342 Tcl_UnixError (interp
), (char *) NULL
);
345 groupId
= fileStat
.st_gid
;
348 if (chown (fileArgv
[idx
], ownerId
, groupId
) < 0) {
349 Tcl_AppendResult (interp
, fileArgv
[idx
], ": ",
350 Tcl_UnixError (interp
), (char *) NULL
);
354 } /* Modify each file */
358 ckfree ((char *) ownArgv
);
359 if (fileArgv
!= NULL
)
360 ckfree ((char *) fileArgv
);
365 *-----------------------------------------------------------------------------
368 * Implements the TCL chgrp command:
369 * chgrp group filelist
372 * Standard TCL results, may return the UNIX system error message.
374 *-----------------------------------------------------------------------------
377 Tcl_ChgrpCmd (clientData
, interp
, argc
, argv
)
378 ClientData clientData
;
383 int idx
, fileArgc
, groupId
, result
= TCL_ERROR
;
385 struct stat fileStat
;
386 struct group
*groupPtr
;
389 Tcl_AppendResult (interp
, tclXWrongArgs
, argv
[0],
390 " group filelist", (char *) NULL
);
394 groupPtr
= getgrnam (argv
[1]);
395 if (groupPtr
!= NULL
)
396 groupId
= groupPtr
->gr_gid
;
398 if (!Tcl_StrToInt (argv
[1], 10, &groupId
)) {
399 Tcl_AppendResult (interp
, "unknown group id: ", argv
[1],
404 if (Tcl_SplitList (interp
, argv
[2], &fileArgc
, &fileArgv
) != TCL_OK
)
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
);
414 } /* Modify each file */
418 ckfree ((char *) fileArgv
);