Deleted Added
full compact
progressbar.c (223308) progressbar.c (223328)
1/* $NetBSD: progressbar.c,v 1.7 2005/04/11 01:49:31 lukem Exp $ */
1/* $NetBSD: progressbar.c,v 1.14 2009/05/20 12:53:47 lukem Exp $ */
2/* from NetBSD: progressbar.c,v 1.21 2009/04/12 10:18:52 lukem Exp */
2
3/*-
3
4/*-
4 * Copyright (c) 1997-2003 The NetBSD Foundation, Inc.
5 * Copyright (c) 1997-2009 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Luke Mewburn.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Luke Mewburn.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include "tnftp.h"
34
35#if 0 /* tnftp */
36
39#include <sys/cdefs.h>
40#ifndef lint
37#include <sys/cdefs.h>
38#ifndef lint
41__RCSID("$NetBSD: progressbar.c,v 1.7 2005/04/11 01:49:31 lukem Exp $");
39__RCSID(" NetBSD: progressbar.c,v 1.21 2009/04/12 10:18:52 lukem Exp ");
42#endif /* not lint */
43
44/*
45 * FTP User Program -- Misc support routines
46 */
47#include <sys/types.h>
48#include <sys/param.h>
40#endif /* not lint */
41
42/*
43 * FTP User Program -- Misc support routines
44 */
45#include <sys/types.h>
46#include <sys/param.h>
49#include <sys/time.h>
50
51#include <err.h>
52#include <errno.h>
53#include <signal.h>
54#include <stdio.h>
55#include <stdlib.h>
56#include <string.h>
57#include <time.h>
47
48#include <err.h>
49#include <errno.h>
50#include <signal.h>
51#include <stdio.h>
52#include <stdlib.h>
53#include <string.h>
54#include <time.h>
55#include <tzfile.h>
58#include <unistd.h>
59
56#include <unistd.h>
57
58#endif /* tnftp */
59
60#include "progressbar.h"
61
60#include "progressbar.h"
61
62#define SECSPERHOUR (60 * 60)
63#define SECSPERDAY ((long)60 * 60 * 24)
64
65#if !defined(NO_PROGRESS)
66/*
67 * return non-zero if we're the current foreground process
68 */
69int
70foregroundproc(void)
71{
72 static pid_t pgrp = -1;
73
74 if (pgrp == -1)
62#if !defined(NO_PROGRESS)
63/*
64 * return non-zero if we're the current foreground process
65 */
66int
67foregroundproc(void)
68{
69 static pid_t pgrp = -1;
70
71 if (pgrp == -1)
72#if GETPGRP_VOID
75 pgrp = getpgrp();
73 pgrp = getpgrp();
74#else /* ! GETPGRP_VOID */
75 pgrp = getpgrp(0);
76#endif /* ! GETPGRP_VOID */
76
77 return (tcgetpgrp(fileno(ttyout)) == pgrp);
78}
79#endif /* !defined(NO_PROGRESS) */
80
81
82static void updateprogressmeter(int);
83

--- 5 unchanged lines hidden (view full) ---

89{
90 int oerrno = errno;
91
92 progressmeter(0);
93 errno = oerrno;
94}
95
96/*
77
78 return (tcgetpgrp(fileno(ttyout)) == pgrp);
79}
80#endif /* !defined(NO_PROGRESS) */
81
82
83static void updateprogressmeter(int);
84

--- 5 unchanged lines hidden (view full) ---

90{
91 int oerrno = errno;
92
93 progressmeter(0);
94 errno = oerrno;
95}
96
97/*
97 * List of order of magnitude prefixes.
98 * The last is `P', as 2^64 = 16384 Petabytes
98 * List of order of magnitude suffixes, per IEC 60027-2.
99 */
99 */
100static const char prefixes[] = " KMGTP";
100static const char * const suffixes[] = {
101 "", /* 2^0 (byte) */
102 "KiB", /* 2^10 Kibibyte */
103 "MiB", /* 2^20 Mebibyte */
104 "GiB", /* 2^30 Gibibyte */
105 "TiB", /* 2^40 Tebibyte */
106 "PiB", /* 2^50 Pebibyte */
107 "EiB", /* 2^60 Exbibyte */
108#if 0
109 /* The following are not necessary for signed 64-bit off_t */
110 "ZiB", /* 2^70 Zebibyte */
111 "YiB", /* 2^80 Yobibyte */
112#endif
113};
114#define NSUFFIXES (int)(sizeof(suffixes) / sizeof(suffixes[0]))
101
102/*
103 * Display a transfer progress bar if progress is non-zero.
104 * SIGALRM is hijacked for use by this function.
105 * - Before the transfer, set filesize to size of file (or -1 if unknown),
106 * and call with flag = -1. This starts the once per second timer,
107 * and a call to updateprogressmeter() upon SIGALRM.
108 * - During the transfer, updateprogressmeter will call progressmeter

--- 10 unchanged lines hidden (view full) ---

119{
120 static off_t lastsize;
121 off_t cursize;
122 struct timeval now, wait;
123#ifndef NO_PROGRESS
124 struct timeval td;
125 off_t abbrevsize, bytespersec;
126 double elapsed;
115
116/*
117 * Display a transfer progress bar if progress is non-zero.
118 * SIGALRM is hijacked for use by this function.
119 * - Before the transfer, set filesize to size of file (or -1 if unknown),
120 * and call with flag = -1. This starts the once per second timer,
121 * and a call to updateprogressmeter() upon SIGALRM.
122 * - During the transfer, updateprogressmeter will call progressmeter

--- 10 unchanged lines hidden (view full) ---

133{
134 static off_t lastsize;
135 off_t cursize;
136 struct timeval now, wait;
137#ifndef NO_PROGRESS
138 struct timeval td;
139 off_t abbrevsize, bytespersec;
140 double elapsed;
127 int ratio, barlength, i, remaining;
141 int ratio, i, remaining, barlength;
128
129 /*
130 * Work variables for progress bar.
131 *
132 * XXX: if the format of the progress bar changes
133 * (especially the number of characters in the
134 * `static' portion of it), be sure to update
135 * these appropriately.
136 */
137#endif
142
143 /*
144 * Work variables for progress bar.
145 *
146 * XXX: if the format of the progress bar changes
147 * (especially the number of characters in the
148 * `static' portion of it), be sure to update
149 * these appropriately.
150 */
151#endif
138 int len;
152 size_t len;
139 char buf[256]; /* workspace for progress bar */
140#ifndef NO_PROGRESS
153 char buf[256]; /* workspace for progress bar */
154#ifndef NO_PROGRESS
141#define BAROVERHEAD 43 /* non `*' portion of progress bar */
155#define BAROVERHEAD 45 /* non `*' portion of progress bar */
142 /*
143 * stars should contain at least
144 * sizeof(buf) - BAROVERHEAD entries
145 */
146 static const char stars[] =
147"*****************************************************************************"
148"*****************************************************************************"
149"*****************************************************************************";

--- 15 unchanged lines hidden (view full) ---

165 wait.tv_sec = 0;
166 } else {
167#ifndef STANDALONE_PROGRESS
168 if (quit_time > 0 && wait.tv_sec > quit_time) {
169 len = snprintf(buf, sizeof(buf), "\r\n%s: "
170 "transfer aborted because stalled for %lu sec.\r\n",
171 getprogname(), (unsigned long)wait.tv_sec);
172 (void)write(fileno(ttyout), buf, len);
156 /*
157 * stars should contain at least
158 * sizeof(buf) - BAROVERHEAD entries
159 */
160 static const char stars[] =
161"*****************************************************************************"
162"*****************************************************************************"
163"*****************************************************************************";

--- 15 unchanged lines hidden (view full) ---

179 wait.tv_sec = 0;
180 } else {
181#ifndef STANDALONE_PROGRESS
182 if (quit_time > 0 && wait.tv_sec > quit_time) {
183 len = snprintf(buf, sizeof(buf), "\r\n%s: "
184 "transfer aborted because stalled for %lu sec.\r\n",
185 getprogname(), (unsigned long)wait.tv_sec);
186 (void)write(fileno(ttyout), buf, len);
173 (void)xsignal(SIGALRM, SIG_DFL);
174 alarmtimer(0);
187 alarmtimer(0);
188 (void)xsignal(SIGALRM, SIG_DFL);
175 siglongjmp(toplevel, 1);
176 }
177#endif /* !STANDALONE_PROGRESS */
178 }
179 /*
180 * Always set the handler even if we are not the foreground process.
181 */
182#ifdef STANDALONE_PROGRESS
183 if (progress) {
184#else
185 if (quit_time > 0 || progress) {
186#endif /* !STANDALONE_PROGRESS */
187 if (flag == -1) {
188 (void)xsignal_restart(SIGALRM, updateprogressmeter, 1);
189 alarmtimer(1); /* set alarm timer for 1 Hz */
190 } else if (flag == 1) {
189 siglongjmp(toplevel, 1);
190 }
191#endif /* !STANDALONE_PROGRESS */
192 }
193 /*
194 * Always set the handler even if we are not the foreground process.
195 */
196#ifdef STANDALONE_PROGRESS
197 if (progress) {
198#else
199 if (quit_time > 0 || progress) {
200#endif /* !STANDALONE_PROGRESS */
201 if (flag == -1) {
202 (void)xsignal_restart(SIGALRM, updateprogressmeter, 1);
203 alarmtimer(1); /* set alarm timer for 1 Hz */
204 } else if (flag == 1) {
191 (void)xsignal(SIGALRM, SIG_DFL);
192 alarmtimer(0);
205 alarmtimer(0);
206 (void)xsignal(SIGALRM, SIG_DFL);
193 }
194 }
195#ifndef NO_PROGRESS
196 if (!progress)
197 return;
198 len = 0;
199
200 /*

--- 10 unchanged lines hidden (view full) ---

211 ratio = MAX(ratio, 0);
212 ratio = MIN(ratio, 100);
213 len += snprintf(buf + len, BUFLEFT, "%3d%% ", ratio);
214
215 /*
216 * calculate the length of the `*' bar, ensuring that
217 * the number of stars won't exceed the buffer size
218 */
207 }
208 }
209#ifndef NO_PROGRESS
210 if (!progress)
211 return;
212 len = 0;
213
214 /*

--- 10 unchanged lines hidden (view full) ---

225 ratio = MAX(ratio, 0);
226 ratio = MIN(ratio, 100);
227 len += snprintf(buf + len, BUFLEFT, "%3d%% ", ratio);
228
229 /*
230 * calculate the length of the `*' bar, ensuring that
231 * the number of stars won't exceed the buffer size
232 */
219 barlength = MIN(sizeof(buf) - 1, ttywidth) - BAROVERHEAD;
233 barlength = MIN((int)(sizeof(buf) - 1), ttywidth) - BAROVERHEAD;
220 if (prefix)
234 if (prefix)
221 barlength -= strlen(prefix);
235 barlength -= (int)strlen(prefix);
222 if (barlength > 0) {
223 i = barlength * ratio / 100;
224 len += snprintf(buf + len, BUFLEFT,
236 if (barlength > 0) {
237 i = barlength * ratio / 100;
238 len += snprintf(buf + len, BUFLEFT,
225 "|%.*s%*s|", i, stars, barlength - i, "");
239 "|%.*s%*s|", i, stars, (int)(barlength - i), "");
226 }
227 }
228
229 abbrevsize = cursize;
240 }
241 }
242
243 abbrevsize = cursize;
230 for (i = 0; abbrevsize >= 100000 && i < sizeof(prefixes); i++)
244 for (i = 0; abbrevsize >= 100000 && i < NSUFFIXES; i++)
231 abbrevsize >>= 10;
245 abbrevsize >>= 10;
232 len += snprintf(buf + len, BUFLEFT, " " LLFP("5") " %c%c ",
246 if (i == NSUFFIXES)
247 i--;
248 len += snprintf(buf + len, BUFLEFT, " " LLFP("5") " %-3s ",
233 (LLT)abbrevsize,
249 (LLT)abbrevsize,
234 prefixes[i],
235 i == 0 ? ' ' : 'B');
250 suffixes[i]);
236
237 timersub(&now, &start, &td);
238 elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
239
240 bytespersec = 0;
241 if (bytes > 0) {
242 bytespersec = bytes;
243 if (elapsed > 0.0)
244 bytespersec /= elapsed;
245 }
251
252 timersub(&now, &start, &td);
253 elapsed = td.tv_sec + (td.tv_usec / 1000000.0);
254
255 bytespersec = 0;
256 if (bytes > 0) {
257 bytespersec = bytes;
258 if (elapsed > 0.0)
259 bytespersec /= elapsed;
260 }
246 for (i = 1; bytespersec >= 1024000 && i < sizeof(prefixes); i++)
261 for (i = 1; bytespersec >= 1024000 && i < NSUFFIXES; i++)
247 bytespersec >>= 10;
248 len += snprintf(buf + len, BUFLEFT,
262 bytespersec >>= 10;
263 len += snprintf(buf + len, BUFLEFT,
249 " " LLFP("3") ".%02d %cB/s ",
264 " " LLFP("3") ".%02d %.2sB/s ",
250 (LLT)(bytespersec / 1024),
251 (int)((bytespersec % 1024) * 100 / 1024),
265 (LLT)(bytespersec / 1024),
266 (int)((bytespersec % 1024) * 100 / 1024),
252 prefixes[i]);
267 suffixes[i]);
253
254 if (filesize > 0) {
255 if (bytes <= 0 || elapsed <= 0.0 || cursize > filesize) {
256 len += snprintf(buf + len, BUFLEFT, " --:-- ETA");
257 } else if (wait.tv_sec >= STALLTIME) {
258 len += snprintf(buf + len, BUFLEFT, " - stalled -");
259 } else {
260 remaining = (int)

--- 33 unchanged lines hidden (view full) ---

294 * instead of ttyout.
295 */
296void
297ptransfer(int siginfo)
298{
299 struct timeval now, td, wait;
300 double elapsed;
301 off_t bytespersec;
268
269 if (filesize > 0) {
270 if (bytes <= 0 || elapsed <= 0.0 || cursize > filesize) {
271 len += snprintf(buf + len, BUFLEFT, " --:-- ETA");
272 } else if (wait.tv_sec >= STALLTIME) {
273 len += snprintf(buf + len, BUFLEFT, " - stalled -");
274 } else {
275 remaining = (int)

--- 33 unchanged lines hidden (view full) ---

309 * instead of ttyout.
310 */
311void
312ptransfer(int siginfo)
313{
314 struct timeval now, td, wait;
315 double elapsed;
316 off_t bytespersec;
302 int remaining, hh, i, len;
317 int remaining, hh, i;
318 size_t len;
303
304 char buf[256]; /* Work variable for transfer status. */
305
306 if (!verbose && !progress && !siginfo)
307 return;
308
309 (void)gettimeofday(&now, NULL);
310 timersub(&now, &start, &td);

--- 18 unchanged lines hidden (view full) ---

329 }
330 hh = remaining / SECSPERHOUR;
331 remaining %= SECSPERHOUR;
332 if (hh)
333 len += snprintf(buf + len, BUFLEFT, "%2d:", hh);
334 len += snprintf(buf + len, BUFLEFT,
335 "%02d:%02d ", remaining / 60, remaining % 60);
336
319
320 char buf[256]; /* Work variable for transfer status. */
321
322 if (!verbose && !progress && !siginfo)
323 return;
324
325 (void)gettimeofday(&now, NULL);
326 timersub(&now, &start, &td);

--- 18 unchanged lines hidden (view full) ---

345 }
346 hh = remaining / SECSPERHOUR;
347 remaining %= SECSPERHOUR;
348 if (hh)
349 len += snprintf(buf + len, BUFLEFT, "%2d:", hh);
350 len += snprintf(buf + len, BUFLEFT,
351 "%02d:%02d ", remaining / 60, remaining % 60);
352
337 for (i = 1; bytespersec >= 1024000 && i < sizeof(prefixes); i++)
353 for (i = 1; bytespersec >= 1024000 && i < NSUFFIXES; i++)
338 bytespersec >>= 10;
354 bytespersec >>= 10;
339 len += snprintf(buf + len, BUFLEFT, "(" LLF ".%02d %cB/s)",
355 if (i == NSUFFIXES)
356 i--;
357 len += snprintf(buf + len, BUFLEFT, "(" LLF ".%02d %.2sB/s)",
340 (LLT)(bytespersec / 1024),
341 (int)((bytespersec % 1024) * 100 / 1024),
358 (LLT)(bytespersec / 1024),
359 (int)((bytespersec % 1024) * 100 / 1024),
342 prefixes[i]);
360 suffixes[i]);
343
344 if (siginfo && bytes > 0 && elapsed > 0.0 && filesize >= 0
345 && bytes + restart_point <= filesize) {
346 remaining = (int)((filesize - restart_point) /
347 (bytes / elapsed) - elapsed);
348 hh = remaining / SECSPERHOUR;
349 remaining %= SECSPERHOUR;
350 len += snprintf(buf + len, BUFLEFT, " ETA: ");

--- 44 unchanged lines hidden (view full) ---

395
396/*
397 * Install a POSIX signal handler, allowing the invoker to set whether
398 * the signal should be restartable or not
399 */
400sigfunc
401xsignal_restart(int sig, sigfunc func, int restartable)
402{
361
362 if (siginfo && bytes > 0 && elapsed > 0.0 && filesize >= 0
363 && bytes + restart_point <= filesize) {
364 remaining = (int)((filesize - restart_point) /
365 (bytes / elapsed) - elapsed);
366 hh = remaining / SECSPERHOUR;
367 remaining %= SECSPERHOUR;
368 len += snprintf(buf + len, BUFLEFT, " ETA: ");

--- 44 unchanged lines hidden (view full) ---

413
414/*
415 * Install a POSIX signal handler, allowing the invoker to set whether
416 * the signal should be restartable or not
417 */
418sigfunc
419xsignal_restart(int sig, sigfunc func, int restartable)
420{
421#ifdef ultrix /* XXX: this is lame - how do we test sigvec vs. sigaction? */
422 struct sigvec vec, ovec;
423
424 vec.sv_handler = func;
425 sigemptyset(&vec.sv_mask);
426 vec.sv_flags = 0;
427 if (sigvec(sig, &vec, &ovec) < 0)
428 return (SIG_ERR);
429 return (ovec.sv_handler);
430#else /* ! ultrix */
403 struct sigaction act, oact;
404 act.sa_handler = func;
405
406 sigemptyset(&act.sa_mask);
407#if defined(SA_RESTART) /* 4.4BSD, Posix(?), SVR4 */
408 act.sa_flags = restartable ? SA_RESTART : 0;
409#elif defined(SA_INTERRUPT) /* SunOS 4.x */
410 act.sa_flags = restartable ? 0 : SA_INTERRUPT;
411#else
412#error "system must have SA_RESTART or SA_INTERRUPT"
413#endif
414 if (sigaction(sig, &act, &oact) < 0)
415 return (SIG_ERR);
416 return (oact.sa_handler);
431 struct sigaction act, oact;
432 act.sa_handler = func;
433
434 sigemptyset(&act.sa_mask);
435#if defined(SA_RESTART) /* 4.4BSD, Posix(?), SVR4 */
436 act.sa_flags = restartable ? SA_RESTART : 0;
437#elif defined(SA_INTERRUPT) /* SunOS 4.x */
438 act.sa_flags = restartable ? 0 : SA_INTERRUPT;
439#else
440#error "system must have SA_RESTART or SA_INTERRUPT"
441#endif
442 if (sigaction(sig, &act, &oact) < 0)
443 return (SIG_ERR);
444 return (oact.sa_handler);
445#endif /* ! ultrix */
417}
418
419/*
420 * Install a signal handler with the `restartable' flag set dependent upon
421 * which signal is being set. (This is a wrapper to xsignal_restart())
422 */
423sigfunc
424xsignal(int sig, sigfunc func)

--- 27 unchanged lines hidden (view full) ---

452 restartable = 0;
453 break;
454
455 default:
456 /*
457 * This is unpleasant, but I don't know what would be better.
458 * Right now, this "can't happen"
459 */
446}
447
448/*
449 * Install a signal handler with the `restartable' flag set dependent upon
450 * which signal is being set. (This is a wrapper to xsignal_restart())
451 */
452sigfunc
453xsignal(int sig, sigfunc func)

--- 27 unchanged lines hidden (view full) ---

481 restartable = 0;
482 break;
483
484 default:
485 /*
486 * This is unpleasant, but I don't know what would be better.
487 * Right now, this "can't happen"
488 */
460 errx(1, "xsignal_restart called with signal %d", sig);
489 errx(1, "xsignal_restart: called with signal %d", sig);
461 }
462
463 return(xsignal_restart(sig, func, restartable));
464}
490 }
491
492 return(xsignal_restart(sig, func, restartable));
493}