1 /*
2 * fork.c - Provide fork and waitpid functions for gawk.
3 *
4 * Revised 6/2004
5 * Revised 5/2012 for new extension API.
6 */
7
8 /*
9 * Copyright (C) 2001, 2004, 2011, 2012, 2013, 2018
10 * the Free Software Foundation, Inc.
11 *
12 * This file is part of GAWK, the GNU implementation of the
13 * AWK Programming Language.
14 *
15 * GAWK is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 3 of the License, or
18 * (at your option) any later version.
19 *
20 * GAWK is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <stdio.h>
35 #include <assert.h>
36 #include <errno.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <sys/wait.h>
41
42 #include <sys/types.h>
43 #include <sys/stat.h>
44
45 #include "gawkapi.h"
46
47 #include "gettext.h"
48 #define _(msgid) gettext(msgid)
49 #define N_(msgid) msgid
50
51 static const gawk_api_t *api; /* for convenience macros to work */
52 static awk_ext_id_t ext_id;
53 static const char *ext_version = "fork extension: version 1.0";
54 static awk_bool_t (*init_func)(void) = NULL;
55
56 int plugin_is_GPL_compatible;
57
58
59 /* array_set --- set an array element */
60
61 static void
62 array_set_numeric(awk_array_t array, const char *sub, double num)
63 {
64 awk_value_t index, value;
65
66 set_array_element(array,
67 make_const_string(sub, strlen(sub), & index),
68 make_number(num, & value));
69
70 }
71
72 /* do_fork --- provide dynamically loaded fork() builtin for gawk */
73
74 static awk_value_t *
75 do_fork(int nargs, awk_value_t *result, struct awk_ext_func *unused)
76 {
77 int ret = -1;
78
79 assert(result != NULL);
80
81 ret = fork();
82
83 if (ret < 0)
84 update_ERRNO_int(errno);
85 else if (ret == 0) {
86 /* update PROCINFO in the child, if the array exists */
87 awk_value_t procinfo;
88
89 if (sym_lookup("PROCINFO", AWK_ARRAY, & procinfo)) {
90 if (procinfo.val_type != AWK_ARRAY) {
91 if (do_lint)
92 lintwarn(ext_id, _("fork: PROCINFO is not an array!"));
93 } else {
94 array_set_numeric(procinfo.array_cookie, "pid", getpid());
95 array_set_numeric(procinfo.array_cookie, "ppid", getppid());
96 }
97 }
98 }
99
100 /* Set the return value */
101 return make_number(ret, result);
102 }
103
104 /* do_waitpid --- provide dynamically loaded waitpid() builtin for gawk */
105
106 static awk_value_t *
107 do_waitpid(int nargs, awk_value_t *result, struct awk_ext_func *unused)
108 {
109 awk_value_t pid;
110 int ret = -1;
111 int options = 0;
112
113 assert(result != NULL);
114
115 if (get_argument(0, AWK_NUMBER, &pid)) {
116 options = WNOHANG|WUNTRACED;
117 ret = waitpid(pid.num_value, NULL, options);
118 if (ret < 0)
119 update_ERRNO_int(errno);
120 }
121
122 /* Set the return value */
123 return make_number(ret, result);
124 }
125
126
127 /* do_wait --- provide dynamically loaded wait() builtin for gawk */
128
129 static awk_value_t *
130 do_wait(int nargs, awk_value_t *result, struct awk_ext_func *unused)
131 {
132 int ret;
133
134 assert(result != NULL);
135
136 ret = wait(NULL);
137 if (ret < 0)
138 update_ERRNO_int(errno);
139
140 /* Set the return value */
141 return make_number(ret, result);
142 }
143
144 static awk_ext_func_t func_table[] = {
145 { "fork", do_fork, 0, 0, awk_false, NULL },
146 { "waitpid", do_waitpid, 1, 1, awk_false, NULL },
147 { "wait", do_wait, 0, 0, awk_false, NULL },
148 };
149
150 /* define the dl_load function using the boilerplate macro */
151
152 dl_load_func(func_table, fork, "")