1 /* Loadable builtin to get and set file descriptor flags. */
3 /* See Makefile for compilation details. */
6 Copyright (C) 2017,2018,2019 Free Software Foundation, Inc.
8 This file is part of GNU Bush.
9 Bush is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Bush is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Bush. If not, see <http://www.gnu.org/licenses/>.
25 #if defined (HAVE_UNISTD_H)
33 #include "loadables.h"
46 { "append", O_APPEND
},
61 { "nonblock", O_NONBLOCK
},
81 { "altio", O_ALT_IO
},
86 { "direct", O_DIRECT
},
91 { "noatime", O_NOATIME
},
96 { "nosigpipe", O_NOSIGPIPE
},
98 # define O_NOSIGPIPE 0
102 # define ALLFLAGS (O_APPEND|O_ASYNC|O_SYNC|O_NONBLOCK|O_FSYNC|O_DSYNC|\
103 O_RSYNC|O_ALT_IO|O_DIRECT|O_NOATIME|O_NOSIGPIPE)
105 /* An unsed bit in the file status flags word we can use to pass around the
106 state of close-on-exec. */
107 # define O_CLOEXEC ((~ALLFLAGS) ^ ((~ALLFLAGS) & ((~ALLFLAGS) - 1)))
111 { "cloexec", O_CLOEXEC
},
115 #define N_FLAGS (sizeof (file_flags) / sizeof (file_flags[0]))
127 for (i
= allflags
= 0; i
< N_FLAGS
; i
++)
128 allflags
|= file_flags
[i
].value
;
133 getflags(int fd
, int p
)
138 if ((c
= fcntl(fd
, F_GETFD
)) == -1)
141 builtin_error("can't get status for fd %d: %s", fd
, strerror(errno
));
145 if ((f
= fcntl(fd
, F_GETFL
)) == -1)
148 builtin_error("Can't get flags for fd %d: %s", fd
, strerror(errno
));
155 return f
& getallflags();
159 printone(int fd
, int p
, int verbose
)
164 if ((f
= getflags(fd
, p
)) == -1)
169 for (i
= 0; i
< N_FLAGS
; i
++)
171 if (f
& file_flags
[i
].value
)
173 printf ("%s%s", verbose
? "+" : "", file_flags
[i
].name
);
174 f
&= ~file_flags
[i
].value
;
177 printf ( "-%s", file_flags
[i
].name
);
181 if (f
|| (verbose
&& i
!= N_FLAGS
- 1))
188 parseflags(char *s
, int *p
, int *n
)
196 for (s
= strtok(s
, ","); s
; s
= strtok(NULL
, ","))
213 for (i
= 0; i
< N_FLAGS
; i
++)
214 if (strcmp(s
, file_flags
[i
].name
) == 0)
216 *v
|= file_flags
[i
].value
;
220 builtin_error("invalid flag `%s'", s
);
227 setone(int fd
, char *v
, int verbose
)
229 int f
, n
, pos
, neg
, cloexec
;
235 parseflags(v
, &pos
, &neg
);
239 if ((pos
& O_CLOEXEC
) && (f
& O_CLOEXEC
) == 0)
240 cloexec
= FD_CLOEXEC
;
241 if ((neg
& O_CLOEXEC
) && (f
& O_CLOEXEC
))
244 if (cloexec
!= -1 && fcntl(fd
, F_SETFD
, cloexec
) == -1)
245 builtin_error("can't set status for fd %d: %s", fd
, strerror(errno
));
255 if (n
!= f
&& fcntl(fd
, F_SETFL
, n
) == -1)
256 builtin_error("can't set flags for fd %d: %s", fd
, strerror(errno
));
265 maxfd
= fcntl (0, F_MAXFD
);
270 maxfd
= getdtablesize ();
273 for (maxfd
--; maxfd
> 0; maxfd
--)
274 if (fcntl (maxfd
, F_GETFD
, &ignore
) != -1)
281 fdflags_builtin (WORD_LIST
*list
)
283 int opt
, maxfd
, i
, num
, verbose
, setflag
;
288 setflag
= verbose
= 0;
289 reset_internal_getopt ();
290 while ((opt
= internal_getopt (list
, "s:v")) != -1)
296 setspec
= list_optarg
;
310 /* Maybe we could provide some default here, but we don't yet. */
311 if (list
== 0 && setflag
)
312 return (EXECUTION_SUCCESS
);
319 builtin_error ("can't get max fd: %s", strerror (errno
));
320 return (EXECUTION_FAILURE
);
322 for (i
= 0; i
< maxfd
; i
++)
323 printone (i
, 0, verbose
);
324 return (EXECUTION_SUCCESS
);
327 opt
= EXECUTION_SUCCESS
;
328 for (l
= list
; l
; l
= l
->next
)
330 if (legal_number (l
->word
->word
, &inum
) == 0 || inum
< 0)
332 builtin_error ("%s: invalid file descriptor", l
->word
->word
);
333 opt
= EXECUTION_FAILURE
;
336 num
= inum
; /* truncate to int */
338 setone (num
, setspec
, verbose
);
340 printone (num
, 1, verbose
);
346 char *fdflags_doc
[] =
348 "Display and modify file descriptor flags.",
350 "Display or, if the -s option is supplied, set flags for each file",
351 "descriptor supplied as an argument. If the -v option is supplied,",
352 "the display is verbose, including each settable option name in the",
353 "form of a string such as that accepted by the -s option.",
355 "The -s option accepts a string with a list of flag names, each preceded",
356 "by a `+' (set) or `-' (unset). Those changes are applied to each file",
357 "descriptor supplied as an argument.",
359 "If no file descriptor arguments are supplied, the displayed information",
360 "consists of the status of flags for each of the shell's open files.",
364 /* The standard structure describing a builtin command. bush keeps an array
365 of these structures. The flags must include BUILTIN_ENABLED so the
366 builtin can be used. */
367 struct builtin fdflags_struct
= {
368 "fdflags", /* builtin name */
369 fdflags_builtin
, /* function implementing the builtin */
370 BUILTIN_ENABLED
, /* initial flags for builtin */
371 fdflags_doc
, /* array of long documentation strings. */
372 "fdflags [-v] [-s flags_string] [fd ...]", /* usage synopsis; becomes short_doc */
373 0 /* reserved for internal use */