2 * select.c - Provide select functions for gawk.
6 * Copyright (C) 2012 Andy Spencer
8 * GAWK is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * GAWK is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 int plugin_is_GPL_compatible;
28 * select(how, [timeout,] fd, ..)
29 * type = {to,from,error,any} */
30 static NODE *do_select(int nargs)
33 if (do_lint && get_curfunc_arg_count() < 2)
34 lintwarn("select: not enough arguments");
37 int read = 0, write = 0, except = 0;
38 NODE *node = get_scalar_argument(0, FALSE);
39 NODE *how = force_string(node);
40 if (!strcmp("to", how->stptr)) write = 1;
41 if (!strcmp("from", how->stptr)) read = 1;
42 if (!strcmp("error", how->stptr)) except = 1;
43 if (!strcmp("any", how->stptr)) read = write = except = 1;
44 if (!read && !write && !except) {
45 printf("select: invalid select type: %.*s\n",
46 how->stlen, how->stptr);
47 return make_number((AWKNUM) -EINVAL);
52 struct timeval _timeout = {.tv_sec = 1, .tv_usec = 0};
53 struct timeval *timeout = &_timeout;
54 NODE *next = get_scalar_argument(1, FALSE);
55 if (next->type == Node_val && next->flags & NUMBER) {
56 AWKNUM num = force_number(next);
60 _timeout.tv_sec = (int)num;
61 _timeout.tv_usec = (num - (int)num) * 1E6;
62 printf("timeout -> %lf %ld,%ld\n", num,
71 fd_set readfds, writefds, exceptfds;
77 for (int i = first; i < nargs; i++) {
78 NODE *node = get_scalar_argument(i, TRUE);
81 NODE *str = force_string(node);
82 struct redirect *redir =
83 getredirect(str->stptr, str->stlen);
86 int type = read && write ? redirect_twoway :
87 read ? redirect_input :
88 write ? redirect_output : 0 ;
89 redir = redirect(str, type, &err);
92 lintwarn("select: arg %d is not a redirect", i);
95 if ((read || except) && redir->iop->fd >= 0) {
96 int fd = redir->iop->fd;
97 if (read) FD_SET(fd, &readfds);
98 if (except) FD_SET(fd, &exceptfds);
99 if (fd > nfds) nfds = fd;
101 if ((write || except) && redir->fp) {
102 int fd = fileno(redir->fp);
103 if (write) FD_SET(fd, &writefds);
104 if (except) FD_SET(fd, &exceptfds);
105 if (fd > nfds) nfds = fd;
110 int rval = select(nfds+1, &readfds, &writefds, &exceptfds, timeout);
112 return make_number((AWKNUM) 0);
114 return make_number((AWKNUM) 0);
117 for (int i = first; i < nargs; i++) {
118 NODE *node = get_scalar_argument(i, TRUE);
121 NODE *str = force_string(node);
122 struct redirect *redir =
123 getredirect(str->stptr, str->stlen);
126 if ((read || except) && redir->iop->fd >= 0) {
127 int fd = redir->iop->fd;
128 if ((read && FD_ISSET(fd, &readfds)) ||
129 (except && FD_ISSET(fd, &writefds)))
132 if ((write || except) && redir->fp) {
133 int fd = fileno(redir->fp);
134 if ((write && FD_ISSET(fd, &writefds)) ||
135 (except && FD_ISSET(fd, &exceptfds)))
141 return make_number((AWKNUM) 0);
144 /* Load select function */
145 NODE *dlload(NODE *tree, void *dl)
147 make_builtin("select", do_select, 99);
148 return make_number((AWKNUM) 0);