1223328Sgavin/* $NetBSD: progressbar.c,v 1.14 2009/05/20 12:53:47 lukem Exp $ */ 2223328Sgavin/* from NetBSD: progressbar.c,v 1.21 2009/04/12 10:18:52 lukem Exp */ 3116424Smikeh 4116424Smikeh/*- 5223328Sgavin * Copyright (c) 1997-2009 The NetBSD Foundation, Inc. 6116424Smikeh * All rights reserved. 7116424Smikeh * 8116424Smikeh * This code is derived from software contributed to The NetBSD Foundation 9116424Smikeh * by Luke Mewburn. 10116424Smikeh * 11116424Smikeh * Redistribution and use in source and binary forms, with or without 12116424Smikeh * modification, are permitted provided that the following conditions 13116424Smikeh * are met: 14116424Smikeh * 1. Redistributions of source code must retain the above copyright 15116424Smikeh * notice, this list of conditions and the following disclaimer. 16116424Smikeh * 2. Redistributions in binary form must reproduce the above copyright 17116424Smikeh * notice, this list of conditions and the following disclaimer in the 18116424Smikeh * documentation and/or other materials provided with the distribution. 19116424Smikeh * 20116424Smikeh * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21116424Smikeh * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22116424Smikeh * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23116424Smikeh * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24116424Smikeh * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25116424Smikeh * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26116424Smikeh * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27116424Smikeh * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28116424Smikeh * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29116424Smikeh * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30116424Smikeh * POSSIBILITY OF SUCH DAMAGE. 31116424Smikeh */ 32116424Smikeh 33223328Sgavin#include "tnftp.h" 34223328Sgavin 35223328Sgavin#if 0 /* tnftp */ 36223328Sgavin 37116424Smikeh#include <sys/cdefs.h> 38116424Smikeh#ifndef lint 39223328Sgavin__RCSID(" NetBSD: progressbar.c,v 1.21 2009/04/12 10:18:52 lukem Exp "); 40116424Smikeh#endif /* not lint */ 41116424Smikeh 42116424Smikeh/* 43116424Smikeh * FTP User Program -- Misc support routines 44116424Smikeh */ 45116424Smikeh#include <sys/types.h> 46116424Smikeh#include <sys/param.h> 47116424Smikeh 48116424Smikeh#include <err.h> 49116424Smikeh#include <errno.h> 50116424Smikeh#include <signal.h> 51116424Smikeh#include <stdio.h> 52116424Smikeh#include <stdlib.h> 53128671Smikeh#include <string.h> 54116424Smikeh#include <time.h> 55223328Sgavin#include <tzfile.h> 56116424Smikeh#include <unistd.h> 57116424Smikeh 58223328Sgavin#endif /* tnftp */ 59223328Sgavin 60116424Smikeh#include "progressbar.h" 61116424Smikeh 62116424Smikeh#if !defined(NO_PROGRESS) 63116424Smikeh/* 64116424Smikeh * return non-zero if we're the current foreground process 65116424Smikeh */ 66116424Smikehint 67116424Smikehforegroundproc(void) 68116424Smikeh{ 69116424Smikeh static pid_t pgrp = -1; 70116424Smikeh 71116424Smikeh if (pgrp == -1) 72223328Sgavin#if GETPGRP_VOID 73116424Smikeh pgrp = getpgrp(); 74223328Sgavin#else /* ! GETPGRP_VOID */ 75223328Sgavin pgrp = getpgrp(0); 76223328Sgavin#endif /* ! GETPGRP_VOID */ 77116424Smikeh 78116424Smikeh return (tcgetpgrp(fileno(ttyout)) == pgrp); 79116424Smikeh} 80116424Smikeh#endif /* !defined(NO_PROGRESS) */ 81116424Smikeh 82116424Smikeh 83116424Smikehstatic void updateprogressmeter(int); 84116424Smikeh 85116424Smikeh/* 86116424Smikeh * SIGALRM handler to update the progress meter 87116424Smikeh */ 88116424Smikehstatic void 89116424Smikehupdateprogressmeter(int dummy) 90116424Smikeh{ 91116424Smikeh int oerrno = errno; 92116424Smikeh 93116424Smikeh progressmeter(0); 94116424Smikeh errno = oerrno; 95116424Smikeh} 96116424Smikeh 97116424Smikeh/* 98223328Sgavin * List of order of magnitude suffixes, per IEC 60027-2. 99116424Smikeh */ 100223328Sgavinstatic const char * const suffixes[] = { 101223328Sgavin "", /* 2^0 (byte) */ 102223328Sgavin "KiB", /* 2^10 Kibibyte */ 103223328Sgavin "MiB", /* 2^20 Mebibyte */ 104223328Sgavin "GiB", /* 2^30 Gibibyte */ 105223328Sgavin "TiB", /* 2^40 Tebibyte */ 106223328Sgavin "PiB", /* 2^50 Pebibyte */ 107223328Sgavin "EiB", /* 2^60 Exbibyte */ 108223328Sgavin#if 0 109223328Sgavin /* The following are not necessary for signed 64-bit off_t */ 110223328Sgavin "ZiB", /* 2^70 Zebibyte */ 111223328Sgavin "YiB", /* 2^80 Yobibyte */ 112223328Sgavin#endif 113223328Sgavin}; 114223328Sgavin#define NSUFFIXES (int)(sizeof(suffixes) / sizeof(suffixes[0])) 115116424Smikeh 116116424Smikeh/* 117116424Smikeh * Display a transfer progress bar if progress is non-zero. 118116424Smikeh * SIGALRM is hijacked for use by this function. 119116424Smikeh * - Before the transfer, set filesize to size of file (or -1 if unknown), 120116424Smikeh * and call with flag = -1. This starts the once per second timer, 121116424Smikeh * and a call to updateprogressmeter() upon SIGALRM. 122116424Smikeh * - During the transfer, updateprogressmeter will call progressmeter 123116424Smikeh * with flag = 0 124116424Smikeh * - After the transfer, call with flag = 1 125116424Smikeh */ 126116424Smikehstatic struct timeval start; 127116424Smikehstatic struct timeval lastupdate; 128116424Smikeh 129116424Smikeh#define BUFLEFT (sizeof(buf) - len) 130116424Smikeh 131116424Smikehvoid 132116424Smikehprogressmeter(int flag) 133116424Smikeh{ 134116424Smikeh static off_t lastsize; 135116424Smikeh off_t cursize; 136116424Smikeh struct timeval now, wait; 137116424Smikeh#ifndef NO_PROGRESS 138116424Smikeh struct timeval td; 139116424Smikeh off_t abbrevsize, bytespersec; 140116424Smikeh double elapsed; 141223328Sgavin int ratio, i, remaining, barlength; 142116424Smikeh 143116424Smikeh /* 144116424Smikeh * Work variables for progress bar. 145116424Smikeh * 146116424Smikeh * XXX: if the format of the progress bar changes 147116424Smikeh * (especially the number of characters in the 148116424Smikeh * `static' portion of it), be sure to update 149116424Smikeh * these appropriately. 150116424Smikeh */ 151142129Smikeh#endif 152223328Sgavin size_t len; 153116424Smikeh char buf[256]; /* workspace for progress bar */ 154142129Smikeh#ifndef NO_PROGRESS 155223328Sgavin#define BAROVERHEAD 45 /* non `*' portion of progress bar */ 156116424Smikeh /* 157116424Smikeh * stars should contain at least 158116424Smikeh * sizeof(buf) - BAROVERHEAD entries 159116424Smikeh */ 160116424Smikeh static const char stars[] = 161116424Smikeh"*****************************************************************************" 162116424Smikeh"*****************************************************************************" 163116424Smikeh"*****************************************************************************"; 164116424Smikeh 165116424Smikeh#endif 166116424Smikeh 167116424Smikeh if (flag == -1) { 168116424Smikeh (void)gettimeofday(&start, NULL); 169116424Smikeh lastupdate = start; 170116424Smikeh lastsize = restart_point; 171116424Smikeh } 172116424Smikeh 173116424Smikeh (void)gettimeofday(&now, NULL); 174116424Smikeh cursize = bytes + restart_point; 175116424Smikeh timersub(&now, &lastupdate, &wait); 176116424Smikeh if (cursize > lastsize) { 177116424Smikeh lastupdate = now; 178116424Smikeh lastsize = cursize; 179116424Smikeh wait.tv_sec = 0; 180116424Smikeh } else { 181116424Smikeh#ifndef STANDALONE_PROGRESS 182116424Smikeh if (quit_time > 0 && wait.tv_sec > quit_time) { 183116424Smikeh len = snprintf(buf, sizeof(buf), "\r\n%s: " 184116424Smikeh "transfer aborted because stalled for %lu sec.\r\n", 185116424Smikeh getprogname(), (unsigned long)wait.tv_sec); 186116424Smikeh (void)write(fileno(ttyout), buf, len); 187223328Sgavin alarmtimer(0); 188116424Smikeh (void)xsignal(SIGALRM, SIG_DFL); 189116424Smikeh siglongjmp(toplevel, 1); 190116424Smikeh } 191116424Smikeh#endif /* !STANDALONE_PROGRESS */ 192116424Smikeh } 193116424Smikeh /* 194116424Smikeh * Always set the handler even if we are not the foreground process. 195116424Smikeh */ 196116424Smikeh#ifdef STANDALONE_PROGRESS 197116424Smikeh if (progress) { 198116424Smikeh#else 199116424Smikeh if (quit_time > 0 || progress) { 200116424Smikeh#endif /* !STANDALONE_PROGRESS */ 201116424Smikeh if (flag == -1) { 202116424Smikeh (void)xsignal_restart(SIGALRM, updateprogressmeter, 1); 203116424Smikeh alarmtimer(1); /* set alarm timer for 1 Hz */ 204116424Smikeh } else if (flag == 1) { 205223328Sgavin alarmtimer(0); 206116424Smikeh (void)xsignal(SIGALRM, SIG_DFL); 207116424Smikeh } 208116424Smikeh } 209116424Smikeh#ifndef NO_PROGRESS 210116424Smikeh if (!progress) 211116424Smikeh return; 212116424Smikeh len = 0; 213116424Smikeh 214116424Smikeh /* 215116424Smikeh * print progress bar only if we are foreground process. 216116424Smikeh */ 217116424Smikeh if (! foregroundproc()) 218116424Smikeh return; 219116424Smikeh 220116424Smikeh len += snprintf(buf + len, BUFLEFT, "\r"); 221128671Smikeh if (prefix) 222128671Smikeh len += snprintf(buf + len, BUFLEFT, "%s", prefix); 223116424Smikeh if (filesize > 0) { 224116424Smikeh ratio = (int)((double)cursize * 100.0 / (double)filesize); 225116424Smikeh ratio = MAX(ratio, 0); 226116424Smikeh ratio = MIN(ratio, 100); 227116424Smikeh len += snprintf(buf + len, BUFLEFT, "%3d%% ", ratio); 228116424Smikeh 229116424Smikeh /* 230116424Smikeh * calculate the length of the `*' bar, ensuring that 231146309Smikeh * the number of stars won't exceed the buffer size 232116424Smikeh */ 233223328Sgavin barlength = MIN((int)(sizeof(buf) - 1), ttywidth) - BAROVERHEAD; 234128671Smikeh if (prefix) 235223328Sgavin barlength -= (int)strlen(prefix); 236116424Smikeh if (barlength > 0) { 237116424Smikeh i = barlength * ratio / 100; 238116424Smikeh len += snprintf(buf + len, BUFLEFT, 239223328Sgavin "|%.*s%*s|", i, stars, (int)(barlength - i), ""); 240116424Smikeh } 241116424Smikeh } 242116424Smikeh 243116424Smikeh abbrevsize = cursize; 244223328Sgavin for (i = 0; abbrevsize >= 100000 && i < NSUFFIXES; i++) 245116424Smikeh abbrevsize >>= 10; 246223328Sgavin if (i == NSUFFIXES) 247223328Sgavin i--; 248223328Sgavin len += snprintf(buf + len, BUFLEFT, " " LLFP("5") " %-3s ", 249116424Smikeh (LLT)abbrevsize, 250223328Sgavin suffixes[i]); 251116424Smikeh 252116424Smikeh timersub(&now, &start, &td); 253116424Smikeh elapsed = td.tv_sec + (td.tv_usec / 1000000.0); 254116424Smikeh 255116424Smikeh bytespersec = 0; 256116424Smikeh if (bytes > 0) { 257116424Smikeh bytespersec = bytes; 258116424Smikeh if (elapsed > 0.0) 259116424Smikeh bytespersec /= elapsed; 260116424Smikeh } 261223328Sgavin for (i = 1; bytespersec >= 1024000 && i < NSUFFIXES; i++) 262116424Smikeh bytespersec >>= 10; 263116424Smikeh len += snprintf(buf + len, BUFLEFT, 264223328Sgavin " " LLFP("3") ".%02d %.2sB/s ", 265116424Smikeh (LLT)(bytespersec / 1024), 266116424Smikeh (int)((bytespersec % 1024) * 100 / 1024), 267223328Sgavin suffixes[i]); 268116424Smikeh 269116424Smikeh if (filesize > 0) { 270116424Smikeh if (bytes <= 0 || elapsed <= 0.0 || cursize > filesize) { 271116424Smikeh len += snprintf(buf + len, BUFLEFT, " --:-- ETA"); 272116424Smikeh } else if (wait.tv_sec >= STALLTIME) { 273116424Smikeh len += snprintf(buf + len, BUFLEFT, " - stalled -"); 274116424Smikeh } else { 275116424Smikeh remaining = (int) 276116424Smikeh ((filesize - restart_point) / (bytes / elapsed) - 277116424Smikeh elapsed); 278116424Smikeh if (remaining >= 100 * SECSPERHOUR) 279116424Smikeh len += snprintf(buf + len, BUFLEFT, 280116424Smikeh " --:-- ETA"); 281116424Smikeh else { 282116424Smikeh i = remaining / SECSPERHOUR; 283116424Smikeh if (i) 284116424Smikeh len += snprintf(buf + len, BUFLEFT, 285116424Smikeh "%2d:", i); 286116424Smikeh else 287116424Smikeh len += snprintf(buf + len, BUFLEFT, 288116424Smikeh " "); 289116424Smikeh i = remaining % SECSPERHOUR; 290116424Smikeh len += snprintf(buf + len, BUFLEFT, 291116424Smikeh "%02d:%02d ETA", i / 60, i % 60); 292116424Smikeh } 293116424Smikeh } 294116424Smikeh } 295116424Smikeh if (flag == 1) 296116424Smikeh len += snprintf(buf + len, BUFLEFT, "\n"); 297116424Smikeh (void)write(fileno(ttyout), buf, len); 298116424Smikeh 299116424Smikeh#endif /* !NO_PROGRESS */ 300116424Smikeh} 301116424Smikeh 302116424Smikeh#ifndef STANDALONE_PROGRESS 303116424Smikeh/* 304116424Smikeh * Display transfer statistics. 305116424Smikeh * Requires start to be initialised by progressmeter(-1), 306116424Smikeh * direction to be defined by xfer routines, and filesize and bytes 307116424Smikeh * to be updated by xfer routines 308116424Smikeh * If siginfo is nonzero, an ETA is displayed, and the output goes to stderr 309116424Smikeh * instead of ttyout. 310116424Smikeh */ 311116424Smikehvoid 312116424Smikehptransfer(int siginfo) 313116424Smikeh{ 314116424Smikeh struct timeval now, td, wait; 315116424Smikeh double elapsed; 316116424Smikeh off_t bytespersec; 317223328Sgavin int remaining, hh, i; 318223328Sgavin size_t len; 319116424Smikeh 320116424Smikeh char buf[256]; /* Work variable for transfer status. */ 321116424Smikeh 322116424Smikeh if (!verbose && !progress && !siginfo) 323116424Smikeh return; 324116424Smikeh 325116424Smikeh (void)gettimeofday(&now, NULL); 326116424Smikeh timersub(&now, &start, &td); 327116424Smikeh elapsed = td.tv_sec + (td.tv_usec / 1000000.0); 328116424Smikeh bytespersec = 0; 329116424Smikeh if (bytes > 0) { 330116424Smikeh bytespersec = bytes; 331116424Smikeh if (elapsed > 0.0) 332116424Smikeh bytespersec /= elapsed; 333116424Smikeh } 334116424Smikeh len = 0; 335116424Smikeh len += snprintf(buf + len, BUFLEFT, LLF " byte%s %s in ", 336116424Smikeh (LLT)bytes, bytes == 1 ? "" : "s", direction); 337116424Smikeh remaining = (int)elapsed; 338116424Smikeh if (remaining > SECSPERDAY) { 339116424Smikeh int days; 340116424Smikeh 341116424Smikeh days = remaining / SECSPERDAY; 342116424Smikeh remaining %= SECSPERDAY; 343116424Smikeh len += snprintf(buf + len, BUFLEFT, 344116424Smikeh "%d day%s ", days, days == 1 ? "" : "s"); 345116424Smikeh } 346116424Smikeh hh = remaining / SECSPERHOUR; 347116424Smikeh remaining %= SECSPERHOUR; 348116424Smikeh if (hh) 349116424Smikeh len += snprintf(buf + len, BUFLEFT, "%2d:", hh); 350116424Smikeh len += snprintf(buf + len, BUFLEFT, 351116424Smikeh "%02d:%02d ", remaining / 60, remaining % 60); 352116424Smikeh 353223328Sgavin for (i = 1; bytespersec >= 1024000 && i < NSUFFIXES; i++) 354116424Smikeh bytespersec >>= 10; 355223328Sgavin if (i == NSUFFIXES) 356223328Sgavin i--; 357223328Sgavin len += snprintf(buf + len, BUFLEFT, "(" LLF ".%02d %.2sB/s)", 358116424Smikeh (LLT)(bytespersec / 1024), 359116424Smikeh (int)((bytespersec % 1024) * 100 / 1024), 360223328Sgavin suffixes[i]); 361116424Smikeh 362116424Smikeh if (siginfo && bytes > 0 && elapsed > 0.0 && filesize >= 0 363116424Smikeh && bytes + restart_point <= filesize) { 364116424Smikeh remaining = (int)((filesize - restart_point) / 365116424Smikeh (bytes / elapsed) - elapsed); 366116424Smikeh hh = remaining / SECSPERHOUR; 367116424Smikeh remaining %= SECSPERHOUR; 368116424Smikeh len += snprintf(buf + len, BUFLEFT, " ETA: "); 369116424Smikeh if (hh) 370116424Smikeh len += snprintf(buf + len, BUFLEFT, "%2d:", hh); 371116424Smikeh len += snprintf(buf + len, BUFLEFT, "%02d:%02d", 372116424Smikeh remaining / 60, remaining % 60); 373116424Smikeh timersub(&now, &lastupdate, &wait); 374116424Smikeh if (wait.tv_sec >= STALLTIME) 375116424Smikeh len += snprintf(buf + len, BUFLEFT, " (stalled)"); 376116424Smikeh } 377116424Smikeh len += snprintf(buf + len, BUFLEFT, "\n"); 378116424Smikeh (void)write(siginfo ? STDERR_FILENO : fileno(ttyout), buf, len); 379116424Smikeh} 380116424Smikeh 381116424Smikeh/* 382116424Smikeh * SIG{INFO,QUIT} handler to print transfer stats if a transfer is in progress 383116424Smikeh */ 384116424Smikehvoid 385116424Smikehpsummary(int notused) 386116424Smikeh{ 387116424Smikeh int oerrno = errno; 388116424Smikeh 389116424Smikeh if (bytes > 0) { 390116424Smikeh if (fromatty) 391116424Smikeh write(fileno(ttyout), "\n", 1); 392116424Smikeh ptransfer(1); 393116424Smikeh } 394116424Smikeh errno = oerrno; 395116424Smikeh} 396116424Smikeh#endif /* !STANDALONE_PROGRESS */ 397116424Smikeh 398116424Smikeh 399116424Smikeh/* 400116424Smikeh * Set the SIGALRM interval timer for wait seconds, 0 to disable. 401116424Smikeh */ 402116424Smikehvoid 403116424Smikehalarmtimer(int wait) 404116424Smikeh{ 405116424Smikeh struct itimerval itv; 406116424Smikeh 407116424Smikeh itv.it_value.tv_sec = wait; 408116424Smikeh itv.it_value.tv_usec = 0; 409116424Smikeh itv.it_interval = itv.it_value; 410116424Smikeh setitimer(ITIMER_REAL, &itv, NULL); 411116424Smikeh} 412116424Smikeh 413116424Smikeh 414116424Smikeh/* 415116424Smikeh * Install a POSIX signal handler, allowing the invoker to set whether 416116424Smikeh * the signal should be restartable or not 417116424Smikeh */ 418116424Smikehsigfunc 419116424Smikehxsignal_restart(int sig, sigfunc func, int restartable) 420116424Smikeh{ 421223328Sgavin#ifdef ultrix /* XXX: this is lame - how do we test sigvec vs. sigaction? */ 422223328Sgavin struct sigvec vec, ovec; 423223328Sgavin 424223328Sgavin vec.sv_handler = func; 425223328Sgavin sigemptyset(&vec.sv_mask); 426223328Sgavin vec.sv_flags = 0; 427223328Sgavin if (sigvec(sig, &vec, &ovec) < 0) 428223328Sgavin return (SIG_ERR); 429223328Sgavin return (ovec.sv_handler); 430223328Sgavin#else /* ! ultrix */ 431116424Smikeh struct sigaction act, oact; 432116424Smikeh act.sa_handler = func; 433116424Smikeh 434116424Smikeh sigemptyset(&act.sa_mask); 435116424Smikeh#if defined(SA_RESTART) /* 4.4BSD, Posix(?), SVR4 */ 436116424Smikeh act.sa_flags = restartable ? SA_RESTART : 0; 437116424Smikeh#elif defined(SA_INTERRUPT) /* SunOS 4.x */ 438116424Smikeh act.sa_flags = restartable ? 0 : SA_INTERRUPT; 439116424Smikeh#else 440116424Smikeh#error "system must have SA_RESTART or SA_INTERRUPT" 441116424Smikeh#endif 442116424Smikeh if (sigaction(sig, &act, &oact) < 0) 443116424Smikeh return (SIG_ERR); 444116424Smikeh return (oact.sa_handler); 445223328Sgavin#endif /* ! ultrix */ 446116424Smikeh} 447116424Smikeh 448116424Smikeh/* 449116424Smikeh * Install a signal handler with the `restartable' flag set dependent upon 450116424Smikeh * which signal is being set. (This is a wrapper to xsignal_restart()) 451116424Smikeh */ 452116424Smikehsigfunc 453116424Smikehxsignal(int sig, sigfunc func) 454116424Smikeh{ 455116424Smikeh int restartable; 456116424Smikeh 457116424Smikeh /* 458116424Smikeh * Some signals print output or change the state of the process. 459116424Smikeh * There should be restartable, so that reads and writes are 460116424Smikeh * not affected. Some signals should cause program flow to change; 461116424Smikeh * these signals should not be restartable, so that the system call 462116424Smikeh * will return with EINTR, and the program will go do something 463116424Smikeh * different. If the signal handler calls longjmp() or siglongjmp(), 464116424Smikeh * it doesn't matter if it's restartable. 465116424Smikeh */ 466116424Smikeh 467116424Smikeh switch(sig) { 468116424Smikeh#ifdef SIGINFO 469116424Smikeh case SIGINFO: 470116424Smikeh#endif 471116424Smikeh case SIGQUIT: 472116424Smikeh case SIGUSR1: 473116424Smikeh case SIGUSR2: 474116424Smikeh case SIGWINCH: 475116424Smikeh restartable = 1; 476116424Smikeh break; 477116424Smikeh 478116424Smikeh case SIGALRM: 479116424Smikeh case SIGINT: 480116424Smikeh case SIGPIPE: 481116424Smikeh restartable = 0; 482116424Smikeh break; 483116424Smikeh 484116424Smikeh default: 485116424Smikeh /* 486116424Smikeh * This is unpleasant, but I don't know what would be better. 487116424Smikeh * Right now, this "can't happen" 488116424Smikeh */ 489223328Sgavin errx(1, "xsignal_restart: called with signal %d", sig); 490116424Smikeh } 491116424Smikeh 492116424Smikeh return(xsignal_restart(sig, func, restartable)); 493116424Smikeh} 494