Bug Summary

File:src/sbin/shutdown/shutdown.c
Warning:line 369, column 10
Although the value stored to 'wpid' is used in the enclosing expression, the value is never actually read from 'wpid'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name shutdown.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/shutdown/obj -resource-dir /usr/local/llvm16/lib/clang/16 -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/shutdown/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/sbin/shutdown/shutdown.c
1/* $OpenBSD: shutdown.c,v 1.55 2023/04/19 12:58:15 jsg Exp $ */
2/* $NetBSD: shutdown.c,v 1.9 1995/03/18 15:01:09 cgd Exp $ */
3
4/*
5 * Copyright (c) 1988, 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/types.h>
34#include <sys/resource.h>
35#include <sys/syslog.h>
36#include <sys/wait.h>
37
38#include <ctype.h>
39#include <fcntl.h>
40#include <sys/termios.h>
41#include <pwd.h>
42#include <signal.h>
43#include <stdio.h>
44#include <stdlib.h>
45#include <string.h>
46#include <time.h>
47#include <unistd.h>
48#include <limits.h>
49#include <errno(*__errno()).h>
50#include <err.h>
51
52#include "pathnames.h"
53
54#ifdef DEBUG
55#undef _PATH_NOLOGIN"/etc/nologin"
56#define _PATH_NOLOGIN"/etc/nologin" "./nologin"
57#undef _PATH_FASTBOOT"/fastboot"
58#define _PATH_FASTBOOT"/fastboot" "./fastboot"
59#endif
60
61#define H *60*60LL
62#define M *60LL
63#define S *1LL
64#define TEN_HOURS(10*60*60) (10*60*60)
65#define NOLOG_TIME(5*60) (5*60)
66struct interval {
67 time_t timeleft;
68 time_t timetowait;
69} tlist[] = {
70 { 0, 0 },
71 { 10 H, 5 H },
72 { 5 H, 3 H },
73 { 2 H, 1 H },
74 { 1 H, 30 M },
75 { 30 M, 10 M },
76 { 20 M, 10 M },
77 { 10 M, 5 M },
78 { 5 M, 3 M },
79 { 2 M, 1 M },
80 { 1 M, 30 S },
81 { 30 S, 30 S },
82 { 0, 0 }
83};
84const int tlistlen = sizeof(tlist) / sizeof(tlist[0]);
85#undef H
86#undef M
87#undef S
88
89static time_t offset, shuttime;
90static int dofast, dohalt, doreboot, dopower, dodump, mbuflen, nosync;
91static volatile sig_atomic_t killflg, timed_out;
92static char *whom, mbuf[BUFSIZ1024];
93
94void badtime(void);
95void __dead__attribute__((__noreturn__)) die_you_gravy_sucking_pig_dog(void);
96void doitfast(void);
97void __dead__attribute__((__noreturn__)) finish(int);
98void getoffset(char *);
99void __dead__attribute__((__noreturn__)) loop(void);
100void nolog(time_t);
101void timeout(int);
102void timewarn(time_t);
103void usage(void);
104
105int
106main(int argc, char *argv[])
107{
108 char when[64];
109 char *p, *endp;
110 struct passwd *pw;
111 struct tm *lt;
112 int arglen, ch, len, readstdin = 0;
113 pid_t forkpid;
114
115#ifndef DEBUG
116 if (geteuid())
117 errx(1, "NOT super-user");
118#endif
119 while ((ch = getopt(argc, argv, "dfhknpr-")) != -1)
120 switch (ch) {
121 case '-':
122 readstdin = 1;
123 break;
124 case 'd':
125 dodump = 1;
126 break;
127 case 'f':
128 dofast = 1;
129 break;
130 case 'h':
131 dohalt = 1;
132 break;
133 case 'k':
134 killflg = 1;
135 break;
136 case 'n':
137 nosync = 1;
138 break;
139 case 'p':
140 dopower = 1;
141 break;
142 case 'r':
143 doreboot = 1;
144 break;
145 default:
146 usage();
147 }
148 argc -= optind;
149 argv += optind;
150
151 if (argc < 1)
152 usage();
153
154 if (dofast && nosync) {
155 warnx("incompatible switches -f and -n.");
156 usage();
157 }
158 if (doreboot && dohalt) {
159 warnx("incompatible switches -h and -r.");
160 usage();
161 }
162 if (doreboot && dopower) {
163 warnx("incompatible switches -p and -r.");
164 usage();
165 }
166
167 if (unveil(_PATH_CONSOLE"/dev/console", "rw") == -1)
168 err(1, "unveil %s", _PATH_CONSOLE"/dev/console");
169 if (unveil(_PATH_RC"/etc/rc", "r") == -1)
170 err(1, "unveil %s", _PATH_RC"/etc/rc");
171 if (unveil(_PATH_WALL"/usr/bin/wall", "x") == -1)
172 err(1, "unveil %s", _PATH_WALL"/usr/bin/wall");
173 if (unveil(_PATH_FASTBOOT"/fastboot", "wc") == -1)
174 err(1, "unveil %s", _PATH_FASTBOOT"/fastboot");
175 if (unveil(_PATH_NOLOGIN"/etc/nologin", "wc") == -1)
176 err(1, "unveil %s", _PATH_NOLOGIN"/etc/nologin");
177 if (dohalt || dopower) {
178 if (unveil(_PATH_HALT"/sbin/halt", "x") == -1)
179 err(1, "unveil %s", _PATH_HALT"/sbin/halt");
180 } else if (doreboot) {
181 if (unveil(_PATH_REBOOT"/sbin/reboot", "x") == -1)
182 err(1, "unveil %s", _PATH_REBOOT"/sbin/reboot");
183 } else {
184 if (unveil(_PATH_BSHELL"/bin/sh", "x") == -1)
185 err(1, "unveil %s", _PATH_BSHELL"/bin/sh");
186 }
187 if (pledge("stdio rpath wpath cpath getpw tty id proc exec", NULL((void *)0)) == -1)
188 err(1, "pledge");
189
190 getoffset(*argv++);
191
192 if (*argv) {
193 for (p = mbuf, len = sizeof(mbuf); *argv; ++argv) {
194 arglen = strlen(*argv);
195 if ((len -= arglen) <= 2)
196 break;
197 if (p != mbuf)
198 *p++ = ' ';
199 memcpy(p, *argv, arglen);
200 p += arglen;
201 }
202 *p = '\n';
203 *++p = '\0';
204 }
205
206 if (readstdin) {
207 p = mbuf;
208 endp = mbuf + sizeof(mbuf) - 2;
209 for (;;) {
210 if (!fgets(p, endp - p + 1, stdin(&__sF[0])))
211 break;
212 for (; *p && p < endp; ++p)
213 ;
214 if (p == endp) {
215 *p = '\n';
216 *++p = '\0';
217 break;
218 }
219 }
220 }
221 mbuflen = strlen(mbuf);
222
223 if (offset > 0) {
224 shuttime = time(NULL((void *)0)) + offset;
225 lt = localtime(&shuttime);
226 if (lt != NULL((void *)0)) {
227 strftime(when, sizeof(when), "%a %b %e %T %Z %Y", lt);
228 printf("Shutdown at %s.\n", when);
229 } else
230 printf("Shutdown soon.\n");
231 } else
232 printf("Shutdown NOW!\n");
233
234 if (!(whom = getlogin()))
235 whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???";
236
237#ifdef DEBUG
238 (void)putc('\n', stdout)(!__isthreaded ? __sputc('\n', (&__sF[1])) : (putc)('\n',
(&__sF[1])))
;
239#else
240 (void)setpriority(PRIO_PROCESS0, 0, PRIO_MIN(-20));
241
242 forkpid = fork();
243 if (forkpid == -1)
244 err(1, "fork");
245 if (forkpid) {
246 (void)printf("shutdown: [pid %ld]\n", (long)forkpid);
247 exit(0);
248 }
249 setsid();
250#endif
251 openlog("shutdown", LOG_CONS0x02, LOG_AUTH(4<<3));
252 loop();
253 /* NOTREACHED */
254}
255
256void
257loop(void)
258{
259 struct timespec timeout;
260 int broadcast, i, logged;
261
262 broadcast = 1;
263
264 for (i = 0; i < tlistlen - 1; i++) {
265 if (offset > tlist[i + 1].timeleft) {
266 tlist[i].timeleft = offset;
267 tlist[i].timetowait = offset - tlist[i + 1].timeleft;
268 break;
269 }
270 }
271
272 /*
273 * Don't spam the users: skip our offset's warning broadcast if
274 * there's a broadcast scheduled after ours and it's relatively
275 * imminent.
276 */
277 if (offset > TEN_HOURS(10*60*60) ||
278 (offset > 0 && tlist[i].timetowait < tlist[i+1].timetowait / 5))
279 broadcast = 0;
280
281 for (logged = 0; i < tlistlen; i++) {
282 if (broadcast)
283 timewarn(tlist[i].timeleft);
284 broadcast = 1;
285 if (!logged && tlist[i].timeleft <= NOLOG_TIME(5*60)) {
286 logged = 1;
287 nolog(tlist[i].timeleft);
288 }
289 timeout.tv_sec = tlist[i].timetowait;
290 timeout.tv_nsec = 0;
291 nanosleep(&timeout, NULL((void *)0));
292 }
293 die_you_gravy_sucking_pig_dog();
294}
295
296static char *restricted_environ[] = {
297 "PATH=" _PATH_STDPATH"/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin",
298 NULL((void *)0)
299};
300
301void
302timewarn(time_t timeleft)
303{
304 static char hostname[HOST_NAME_MAX255+1];
305 char when[64];
306 struct tm *lt;
307 static int first;
308 int fd[2];
309 pid_t pid, wpid;
310
311 if (!first++)
312 (void)gethostname(hostname, sizeof(hostname));
313
314 if (pipe(fd) == -1) {
315 syslog(LOG_ERR3, "pipe: %m");
316 return;
317 }
318 switch (pid = fork()) {
319 case -1:
320 syslog(LOG_ERR3, "fork: %m");
321 close(fd[0]);
322 close(fd[1]);
323 return;
324 case 0:
325 if (dup2(fd[0], STDIN_FILENO0) == -1) {
326 syslog(LOG_ERR3, "dup2: %m");
327 _exit(1);
328 }
329 if (fd[0] != STDIN_FILENO0)
330 close(fd[0]);
331 close(fd[1]);
332 /* wall(1)'s undocumented '-n' flag suppresses its banner. */
333 execle(_PATH_WALL"/usr/bin/wall", _PATH_WALL"/usr/bin/wall", "-n", (char *)NULL((void *)0),
334 restricted_environ);
335 syslog(LOG_ERR3, "%s: %m", _PATH_WALL"/usr/bin/wall");
336 _exit(1);
337 default:
338 close(fd[0]);
339 }
340
341 dprintf(fd[1],
342 "\007*** %sSystem shutdown message from %s@%s ***\007\n",
343 timeleft ? "": "FINAL ", whom, hostname);
344
345 if (timeleft > 10 * 60) {
346 shuttime = time(NULL((void *)0)) + timeleft;
347 lt = localtime(&shuttime);
348 strftime(when, sizeof(when), "%H:%M %Z", lt);
349 dprintf(fd[1], "System going down at %s\n\n", when);
350 } else if (timeleft > 59) {
351 dprintf(fd[1], "System going down in %lld minute%s\n\n",
352 (long long)(timeleft / 60), (timeleft > 60) ? "s" : "");
353 } else if (timeleft)
354 dprintf(fd[1], "System going down in 30 seconds\n\n");
355 else
356 dprintf(fd[1], "System going down IMMEDIATELY\n\n");
357
358 if (mbuflen)
359 (void)write(fd[1], mbuf, mbuflen);
360 close(fd[1]);
361
362 /*
363 * If we wait longer than 30 seconds for wall(1) to exit we'll
364 * throw off our schedule.
365 */
366 signal(SIGALRM14, timeout);
367 siginterrupt(SIGALRM14, 1);
368 alarm(30);
369 while ((wpid = wait(NULL((void *)0))) != pid && !timed_out)
Although the value stored to 'wpid' is used in the enclosing expression, the value is never actually read from 'wpid'
370 continue;
371 alarm(0);
372 signal(SIGALRM14, SIG_DFL(void (*)(int))0);
373 if (timed_out) {
374 syslog(LOG_NOTICE5,
375 "wall[%ld] is taking too long to exit; continuing",
376 (long)pid);
377 timed_out = 0;
378 }
379}
380
381void
382timeout(int signo)
383{
384 timed_out = 1;
385}
386
387void
388die_you_gravy_sucking_pig_dog(void)
389{
390
391 syslog(LOG_NOTICE5, "%s by %s: %s",
392 doreboot ? "reboot" : dopower ? "power-down" : dohalt ? "halt" :
393 "shutdown", whom, mbuf);
394 (void)sleep(2);
395
396 (void)printf("\r\nSystem shutdown time has arrived\007\007\r\n");
397 if (killflg) {
398 (void)printf("\rbut you'll have to do it yourself\r\n");
399 finish(0);
400 }
401 if (dofast)
402 doitfast();
403
404 if (pledge("stdio rpath wpath cpath tty id proc exec", NULL((void *)0)) == -1)
405 err(1, "pledge");
406
407#ifdef DEBUG
408 if (doreboot)
409 (void)printf("reboot");
410 else if (dopower)
411 (void)printf("power-down");
412 else if (dohalt)
413 (void)printf("halt");
414 if (nosync)
415 (void)printf(" no sync");
416 if (dofast)
417 (void)printf(" no fsck");
418 if (dodump)
419 (void)printf(" with dump");
420 (void)printf("\nkill -HUP 1\n");
421#else
422 if (dohalt || dopower || doreboot) {
423 char *args[10];
424 char **arg, *path;
425
426 if (pledge("stdio exec", NULL((void *)0)) == -1)
427 err(1, "pledge");
428
429 arg = &args[0];
430 if (doreboot) {
431 path = _PATH_REBOOT"/sbin/reboot";
432 *arg++ = "reboot";
433 } else {
434 path = _PATH_HALT"/sbin/halt";
435 *arg++ = "halt";
436 }
437 *arg++ = "-l";
438 if (dopower)
439 *arg++ = "-p";
440 if (nosync)
441 *arg++ = "-n";
442 if (dodump)
443 *arg++ = "-d";
444 *arg++ = NULL((void *)0);
445 execve(path, args, NULL((void *)0));
446 syslog(LOG_ERR3, "shutdown: can't exec %s: %m.", path);
447 warn("%s", path);
448 }
449 if (access(_PATH_RC"/etc/rc", R_OK0x04) != -1) {
450 pid_t pid;
451 struct termios t;
452 int fd;
453
454 switch ((pid = fork())) {
455 case -1:
456 break;
457 case 0:
458 if (revoke(_PATH_CONSOLE"/dev/console") == -1)
459 perror("revoke");
460 if (setsid() == -1)
461 perror("setsid");
462 fd = open(_PATH_CONSOLE"/dev/console", O_RDWR0x0002);
463 if (fd == -1)
464 perror("open");
465 dup2(fd, 0);
466 dup2(fd, 1);
467 dup2(fd, 2);
468 if (fd > 2)
469 close(fd);
470
471 /* At a minimum... */
472 tcgetattr(0, &t);
473 t.c_oflag |= (ONLCR0x00000002 | OPOST0x00000001);
474 tcsetattr(0, TCSANOW0, &t);
475
476 execl(_PATH_BSHELL"/bin/sh", "sh", _PATH_RC"/etc/rc", "shutdown", (char *)NULL((void *)0));
477 _exit(1);
478 default:
479 waitpid(pid, NULL((void *)0), 0);
480 }
481 }
482 (void)kill(1, SIGTERM15); /* to single user */
483#endif
484 finish(0);
485}
486
487#define ATOI2(p)(p[0] - '0') * 10 + (p[1] - '0'); p += 2; (p[0] - '0') * 10 + (p[1] - '0'); p += 2;
488
489void
490getoffset(char *timearg)
491{
492 char when[64];
493 const char *errstr;
494 struct tm *lt;
495 int this_year;
496 time_t minutes, now;
497 char *p;
498
499 if (!strcasecmp(timearg, "now")) { /* now */
500 offset = 0;
501 return;
502 }
503
504 if (timearg[0] == '+') { /* +minutes */
505 minutes = strtonum(timearg, 0, INT_MAX0x7fffffff, &errstr);
506 if (errstr)
507 errx(1, "relative offset is %s: %s", errstr, timearg);
508 offset = minutes * 60;
509 return;
510 }
511
512 /* handle hh:mm by getting rid of the colon */
513 for (p = timearg; *p; ++p) {
514 if (!isascii((unsigned char)*p) || !isdigit((unsigned char)*p)) {
515 if (*p == ':' && strlen(p) == 3) {
516 p[0] = p[1];
517 p[1] = p[2];
518 p[2] = '\0';
519 } else
520 badtime();
521 }
522 }
523
524 unsetenv("TZ"); /* OUR timezone */
525 time(&now);
526 lt = localtime(&now); /* current time val */
527
528 switch (strlen(timearg)) {
529 case 10:
530 this_year = lt->tm_year;
531 lt->tm_year = ATOI2(timearg)(timearg[0] - '0') * 10 + (timearg[1] - '0'); timearg += 2;;
532 /*
533 * check if the specified year is in the next century.
534 * allow for one year of user error as many people will
535 * enter n - 1 at the start of year n.
536 */
537 if (lt->tm_year < (this_year % 100) - 1)
538 lt->tm_year += 100;
539 /* adjust for the year 2000 and beyond */
540 lt->tm_year += (this_year - (this_year % 100));
541 /* FALLTHROUGH */
542 case 8:
543 lt->tm_mon = ATOI2(timearg)(timearg[0] - '0') * 10 + (timearg[1] - '0'); timearg += 2;;
544 if (--lt->tm_mon < 0 || lt->tm_mon > 11)
545 badtime();
546 /* FALLTHROUGH */
547 case 6:
548 lt->tm_mday = ATOI2(timearg)(timearg[0] - '0') * 10 + (timearg[1] - '0'); timearg += 2;;
549 if (lt->tm_mday < 1 || lt->tm_mday > 31)
550 badtime();
551 /* FALLTHROUGH */
552 case 4:
553 lt->tm_hour = ATOI2(timearg)(timearg[0] - '0') * 10 + (timearg[1] - '0'); timearg += 2;;
554 if (lt->tm_hour < 0 || lt->tm_hour > 23)
555 badtime();
556 lt->tm_min = ATOI2(timearg)(timearg[0] - '0') * 10 + (timearg[1] - '0'); timearg += 2;;
557 if (lt->tm_min < 0 || lt->tm_min > 59)
558 badtime();
559 lt->tm_sec = 0;
560 if ((shuttime = mktime(lt)) == -1)
561 badtime();
562 if ((offset = shuttime - now) < 0) {
563 strftime(when, sizeof(when), "%a %b %e %T %Z %Y", lt);
564 errx(1, "time is already past: %s", when);
565 }
566 break;
567 default:
568 badtime();
569 }
570}
571
572void
573doitfast(void)
574{
575 int fastfd;
576
577 if ((fastfd = open(_PATH_FASTBOOT"/fastboot", O_WRONLY0x0001|O_CREAT0x0200|O_TRUNC0x0400,
578 0664)) >= 0) {
579 dprintf(fastfd, "fastboot file for fsck\n");
580 close(fastfd);
581 }
582}
583
584void
585nolog(time_t timeleft)
586{
587 char when[64];
588 struct tm *tm;
589 int logfd;
590
591 (void)unlink(_PATH_NOLOGIN"/etc/nologin"); /* in case linked to another file */
592 (void)signal(SIGINT2, finish);
593 (void)signal(SIGHUP1, finish);
594 (void)signal(SIGQUIT3, finish);
595 (void)signal(SIGTERM15, finish);
596 shuttime = time(NULL((void *)0)) + timeleft;
597 tm = localtime(&shuttime);
598 if (tm && (logfd = open(_PATH_NOLOGIN"/etc/nologin", O_WRONLY0x0001|O_CREAT0x0200|O_TRUNC0x0400,
599 0664)) >= 0) {
600 strftime(when, sizeof(when), "at %H:%M %Z", tm);
601 dprintf(logfd, "\n\nNO LOGINS: System going down %s\n\n", when);
602 close(logfd);
603 }
604}
605
606void
607finish(int signo)
608{
609 if (!killflg)
610 (void)unlink(_PATH_NOLOGIN"/etc/nologin");
611 if (signo == 0)
612 exit(0);
613 else
614 _exit(0);
615}
616
617void
618badtime(void)
619{
620 errx(1, "bad time format.");
621}
622
623void
624usage(void)
625{
626 fprintf(stderr(&__sF[2]),
627 "usage: shutdown [-] [-dfhknpr] time [warning-message ...]\n");
628 exit(1);
629}