]>
cvs.zerfleddert.de Git - micropolis/blob - src/tclx/src/tclxfctl.c
4 * Extended Tcl fcntl command.
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: tclXfcntl.c,v 2.0 1992/10/16 04:50:38 markd Rel $
16 *-----------------------------------------------------------------------------
22 * Macro to enable line buffering mode on a file. Macros assure that the
23 * resulting expression returns zero if the function call does not return
26 #ifdef TCL_HAVE_SETLINEBUF
27 # define SET_LINE_BUF(fp) (setlinebuf (fp),0)
29 # define SET_LINE_BUF(fp) setvbuf (fp, NULL, _IOLBF, BUFSIZ)
33 * If we don't have O_NONBLOCK, use O_NDELAY.
36 # define O_NONBLOCK O_NDELAY
40 * Attributes used by fcntl command and the maximum length of any attribute
43 #define ATTR_CLOEXEC 1
45 #define ATTR_LINEBUF 4
46 #define MAX_ATTR_NAME_LEN 20
49 * Prototypes of internal functions.
52 XlateFcntlAttr
_ANSI_ARGS_((Tcl_Interp
*interp
,
58 GetFcntlAttr
_ANSI_ARGS_((Tcl_Interp
*interp
,
63 SetFcntlAttr
_ANSI_ARGS_((Tcl_Interp
*interp
,
69 *-----------------------------------------------------------------------------
72 * Translate an fcntl attribute.
75 * o interp (I) - Tcl interpreter.
76 * o attrName (I) - The attrbute name to translate, maybe upper or lower
78 * o fcntlAttrPtr (O) - If the attr specified is one of the standard
79 * fcntl attrs, it is returned here, otherwise zero is returned.
80 * o otherAttrPtr (O) - If the attr specified is one of the additional
81 * attrs supported by the Tcl command, it is returned here, otherwise
84 * Returns TCL_OK if all is well, TCL_ERROR if there is an error.
85 *-----------------------------------------------------------------------------
88 XlateFcntlAttr (interp
, attrName
, fcntlAttrPtr
, otherAttrPtr
)
94 char attrNameUp
[MAX_ATTR_NAME_LEN
];
99 if (strlen (attrName
) >= MAX_ATTR_NAME_LEN
)
100 goto invalidAttrName
;
102 Tcl_UpShift (attrNameUp
, attrName
);
104 if (STREQU (attrNameUp
, "RDONLY")) {
105 *fcntlAttrPtr
= O_RDONLY
;
108 if (STREQU (attrNameUp
, "WRONLY")) {
109 *fcntlAttrPtr
= O_WRONLY
;
112 if (STREQU (attrNameUp
, "RDWR")) {
113 *fcntlAttrPtr
= O_RDWR
;
116 if (STREQU (attrNameUp
, "READ")) {
117 *fcntlAttrPtr
= O_RDONLY
| O_RDWR
;
120 if (STREQU (attrNameUp
, "WRITE")) {
121 *fcntlAttrPtr
= O_WRONLY
| O_RDWR
;
124 if (STREQU (attrNameUp
, "NONBLOCK")) {
125 *fcntlAttrPtr
= O_NONBLOCK
;
128 if (STREQU (attrNameUp
, "APPEND")) {
129 *fcntlAttrPtr
= O_APPEND
;
132 if (STREQU (attrNameUp
, "CLOEXEC")) {
133 *otherAttrPtr
= ATTR_CLOEXEC
;
136 if (STREQU (attrNameUp
, "NOBUF")) {
137 *otherAttrPtr
= ATTR_NOBUF
;
140 if (STREQU (attrNameUp
, "LINEBUF")) {
141 *otherAttrPtr
= ATTR_LINEBUF
;
149 Tcl_AppendResult (interp
, "unknown attribute name \"", attrName
,
150 "\", expected one of APPEND, CLOEXEC, LINEBUF, ",
151 "NONBLOCK, NOBUF, READ, RDONLY, RDWR, WRITE, WRONLY",
158 *-----------------------------------------------------------------------------
161 * Return the value of a specified fcntl attribute.
164 * o interp (I) - Tcl interpreter, value is returned in the result
165 * o filePtr (I) - Pointer to the file descriptor.
166 * o attrName (I) - The attrbute name to translate, maybe upper or lower
169 * Returns TCL_OK if all is well, TCL_ERROR if fcntl returns an error.
170 *-----------------------------------------------------------------------------
173 GetFcntlAttr (interp
, filePtr
, attrName
)
178 int fcntlAttr
, otherAttr
, current
;
180 if (XlateFcntlAttr (interp
, attrName
, &fcntlAttr
, &otherAttr
) != TCL_OK
)
183 if (fcntlAttr
!= 0) {
184 current
= fcntl (fileno (filePtr
->f
), F_GETFL
, 0);
187 interp
->result
= (current
& fcntlAttr
) ? "1" : "0";
191 if (otherAttr
& ATTR_CLOEXEC
) {
192 current
= fcntl (fileno (filePtr
->f
), F_GETFD
, 0);
195 interp
->result
= (current
& 1) ? "1" : "0";
200 * Poke the stdio FILE structure to determine the buffering status.
206 if (otherAttr
& ATTR_NOBUF
) {
207 interp
->result
= (filePtr
->f
->_flag
& _IONBF
) ? "1" : "0";
210 if (otherAttr
& ATTR_LINEBUF
) {
211 interp
->result
= (filePtr
->f
->_flag
& _IOLBF
) ? "1" : "0";
215 if (otherAttr
& ATTR_NOBUF
) {
216 interp
->result
= (filePtr
->f
->_flags
& _SNBF
) ? "1" : "0";
219 if (otherAttr
& ATTR_LINEBUF
) {
220 interp
->result
= (filePtr
->f
->_flags
& _SLBF
) ? "1" : "0";
228 interp
->result
= Tcl_UnixError (interp
);
233 *-----------------------------------------------------------------------------
236 * Set the specified fcntl attr to the given value.
239 * o interp (I) - Tcl interpreter, value is returned in the result
240 * o filePtr (I) - Pointer to the file descriptor.
241 * o attrName (I) - The attrbute name to translate, maybe upper or lower
243 * o valueStr (I) - The string value to set the attribiute to.
246 * Returns TCL_OK if all is well, TCL_ERROR if there is an error.
247 *-----------------------------------------------------------------------------
250 SetFcntlAttr (interp
, filePtr
, attrName
, valueStr
)
257 int fcntlAttr
, otherAttr
, current
, setValue
;
259 if (Tcl_GetBoolean (interp
, valueStr
, &setValue
) != TCL_OK
)
262 if (XlateFcntlAttr (interp
, attrName
, &fcntlAttr
, &otherAttr
) != TCL_OK
)
266 * Validate that this the attribute may be set (or cleared).
269 if (fcntlAttr
& (O_RDONLY
| O_WRONLY
| O_RDWR
)) {
270 Tcl_AppendResult (interp
, "Attribute \"", attrName
, "\" may not be ",
271 "altered after open", (char *) NULL
);
275 if ((otherAttr
& (ATTR_NOBUF
| ATTR_LINEBUF
)) && !setValue
) {
276 Tcl_AppendResult (interp
, "Attribute \"", attrName
, "\" may not be ",
277 "cleared once set", (char *) NULL
);
281 if (otherAttr
== ATTR_CLOEXEC
) {
282 if (fcntl (fileno (filePtr
->f
), F_SETFD
, setValue
) == -1)
287 if (otherAttr
== ATTR_NOBUF
) {
288 setbuf (filePtr
->f
, NULL
);
292 if (otherAttr
== ATTR_LINEBUF
) {
293 if (SET_LINE_BUF (filePtr
->f
) != 0)
299 * Handle standard fcntl attrs.
302 current
= fcntl (fileno (filePtr
->f
), F_GETFL
, 0);
305 current
&= ~fcntlAttr
;
307 current
|= fcntlAttr
;
308 if (fcntl (fileno (filePtr
->f
), F_SETFL
, current
) == -1)
314 interp
->result
= Tcl_UnixError (interp
);
320 *-----------------------------------------------------------------------------
323 * Implements the fcntl TCL command:
324 * fcntl handle [attribute value]
325 *-----------------------------------------------------------------------------
328 Tcl_FcntlCmd (clientData
, interp
, argc
, argv
)
329 ClientData clientData
;
336 if ((argc
< 3) || (argc
> 4)) {
337 Tcl_AppendResult (interp
, tclXWrongArgs
, argv
[0],
338 " handle attribute [value]", (char *) NULL
);
342 if (TclGetOpenFile (interp
, argv
[1], &filePtr
) != TCL_OK
)
345 if (GetFcntlAttr (interp
, filePtr
, argv
[2]) != TCL_OK
)
348 if (SetFcntlAttr (interp
, filePtr
, argv
[2], argv
[3]) != TCL_OK
)