Bug Summary

File:src/usr.sbin/wsmoused/wsmoused.c
Warning:line 416, column 4
Value stored to 'res' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name wsmoused.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -fno-rounding-math -mconstructor-aliases -munwind-tables -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/usr.sbin/wsmoused/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/wsmoused/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -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/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/wsmoused/wsmoused.c
1/* $OpenBSD: wsmoused.c,v 1.38 2021/10/24 21:24:19 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2001 Jean-Baptiste Marchand, Julien Montagne and Jerome Verdon
5 *
6 * Copyright (c) 1998 by Kazutaka Yokota
7 *
8 * Copyright (c) 1995 Michael Smith
9 *
10 * Copyright (c) 1993 by David Dawes <dawes@xfree86.org>
11 *
12 * Copyright (c) 1990,91 by Thomas Roell, Dinkelscherben, Germany.
13 *
14 * All rights reserved.
15 *
16 * Most of this code was taken from the FreeBSD moused daemon, written by
17 * Michael Smith. The FreeBSD moused daemon already contained code from the
18 * Xfree Project, written by David Dawes and Thomas Roell and Kazutaka Yokota.
19 *
20 * Adaptation to OpenBSD was done by Jean-Baptiste Marchand, Julien Montagne
21 * and Jerome Verdon.
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 * 1. Redistributions of source code must retain the above copyright
27 * notice, this list of conditions and the following disclaimer.
28 * 2. Redistributions in binary form must reproduce the above copyright
29 * notice, this list of conditions and the following disclaimer in the
30 * documentation and/or other materials provided with the distribution.
31 * 3. All advertising materials mentioning features or use of this software
32 * must display the following acknowledgement:
33 * This product includes software developed by
34 * David Dawes, Jean-Baptiste Marchand, Julien Montagne, Thomas Roell,
35 * Michael Smith, Jerome Verdon and Kazutaka Yokota.
36 * 4. The name authors may not be used to endorse or promote products
37 * derived from this software without specific prior written permission.
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
40 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
42 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
43 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
45 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
48 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 *
50 *
51 */
52
53#include <sys/ioctl.h>
54#include <sys/stat.h>
55#include <sys/types.h>
56#include <sys/time.h>
57#include <sys/tty.h>
58#include <dev/wscons/wsconsio.h>
59
60#include <ctype.h>
61#include <err.h>
62#include <errno(*__errno()).h>
63#include <fcntl.h>
64#include <unistd.h>
65#include <signal.h>
66#include <poll.h>
67#include <stdio.h>
68#include <string.h>
69#include <stdlib.h>
70#include <syslog.h>
71
72#include "mouse_protocols.h"
73#include "wsmoused.h"
74
75#define DEFAULT_TTY"/dev/ttyCcfg" "/dev/ttyCcfg"
76
77extern char *__progname;
78extern char *mouse_names[];
79
80int debug = 0;
81int background = FALSE0;
82int nodaemon = FALSE0;
83int identify = FALSE0;
84
85mouse_t mouse = {
86 .flags = 0,
87 .portname = NULL((void *)0),
88 .ttyname = NULL((void *)0),
89 .proto = P_UNKNOWN-2,
90 .rate = MOUSE_RATE_UNKNOWN255,
91 .resolution = MOUSE_RES_UNKNOWN255,
92 .mfd = -1,
93 .clickthreshold = 500, /* 0.5 sec */
94};
95
96/* identify the type of a wsmouse supported mouse */
97void
98wsmouse_identify(void)
99{
100 unsigned int type;
101
102 if (mouse.mfd != -1) {
103 if (ioctl(mouse.mfd, WSMOUSEIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((32)))
, &type) == -1)
104 err(1, "can't detect mouse type");
105
106 printf("wsmouse supported mouse: ");
107 switch (type) {
108 case WSMOUSE_TYPE_VSXXX1:
109 printf("DEC serial\n");
110 break;
111 case WSMOUSE_TYPE_PS22:
112 printf("PS/2 compatible\n");
113 break;
114 case WSMOUSE_TYPE_USB3:
115 printf("USB\n");
116 break;
117 case WSMOUSE_TYPE_LMS4:
118 printf("Logitech busmouse\n");
119 break;
120 case WSMOUSE_TYPE_MMS5:
121 printf("Microsoft InPort mouse\n");
122 break;
123 case WSMOUSE_TYPE_TPANEL6:
124 printf("Generic Touch Panel\n");
125 break;
126 case WSMOUSE_TYPE_NEXT7:
127 printf("NeXT\n");
128 break;
129 case WSMOUSE_TYPE_ARCHIMEDES8:
130 printf("Archimedes\n");
131 break;
132 case WSMOUSE_TYPE_ADB9:
133 printf("ADB\n");
134 break;
135 case WSMOUSE_TYPE_HIL10:
136 printf("HP-HIL\n");
137 break;
138 case WSMOUSE_TYPE_LUNA11:
139 printf("Omron Luna\n");
140 break;
141 case WSMOUSE_TYPE_DOMAIN12:
142 printf("Apollo Domain\n");
143 break;
144 case WSMOUSE_TYPE_SUN14:
145 printf("Sun\n");
146 break;
147 default:
148 printf("Unknown\n");
149 break;
150 }
151 } else
152 warnx("unable to open %s", mouse.portname);
153}
154
155/* wsmouse_init : init a wsmouse compatible mouse */
156void
157wsmouse_init(void)
158{
159 unsigned int res = WSMOUSE_RES_MIN0;
160
161 ioctl(mouse.mfd, WSMOUSEIO_SRES((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((33)))
, &res);
162}
163
164/*
165 * Buttons remapping
166 */
167
168/* physical to logical button mapping */
169static int p2l[MOUSE_MAXBUTTON16] = {
170 MOUSE_BUTTON10, MOUSE_BUTTON21, MOUSE_BUTTON32, MOUSE_BUTTON43,
171 MOUSE_BUTTON54, MOUSE_BUTTON65, MOUSE_BUTTON76, MOUSE_BUTTON87,
172};
173
174static char *
175skipspace(char *s)
176{
177 while (isspace((unsigned char)*s))
178 ++s;
179 return s;
180}
181
182/* mouse_installmap : install a map between physical and logical buttons */
183static int
184mouse_installmap(char *arg)
185{
186 int pbutton;
187 int lbutton;
188 char *s;
189
190 while (*arg) {
191 arg = skipspace(arg);
192 s = arg;
193 while (isdigit((unsigned char)*arg))
194 ++arg;
195 arg = skipspace(arg);
196 if ((arg <= s) || (*arg != '='))
197 return FALSE0;
198 lbutton = atoi(s);
199
200 arg = skipspace(++arg);
201 s = arg;
202 while (isdigit((unsigned char)*arg))
203 ++arg;
204 if (arg <= s || (!isspace((unsigned char)*arg) && *arg != '\0'))
205 return FALSE0;
206 pbutton = atoi(s);
207
208 if (lbutton <= 0 || lbutton > MOUSE_MAXBUTTON16)
209 return FALSE0;
210 if (pbutton <= 0 || pbutton > MOUSE_MAXBUTTON16)
211 return FALSE0;
212 p2l[pbutton - 1] = lbutton - 1;
213 }
214 return TRUE1;
215}
216
217/* terminate signals handler */
218static void
219terminate(int sig)
220{
221 struct wscons_event event;
222 unsigned int res;
223
224 if (mouse.mfd != -1) {
225 event.type = WSCONS_EVENT_WSMOUSED_OFF13;
226 ioctl(mouse.cfd, WSDISPLAYIO_WSMOUSED((unsigned long)0x80000000 | ((sizeof(struct wscons_event) &
0x1fff) << 16) | ((('W')) << 8) | ((88)))
, &event);
227 res = WSMOUSE_RES_DEFAULT75;
228 ioctl(mouse.mfd, WSMOUSEIO_SRES((unsigned long)0x80000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((33)))
, &res);
229 close(mouse.mfd);
230 mouse.mfd = -1;
231 }
232 _exit(0);
233}
234
235/* buttons status (for multiple click detection) */
236static struct {
237 int count; /* 0: up, 1: single click, 2: double click,... */
238 struct timeval tv; /* timestamp on the last `up' event */
239} buttonstate[MOUSE_MAXBUTTON16];
240
241/*
242 * handle button click
243 * Note that an ioctl is sent for each button
244 */
245static void
246mouse_click(struct wscons_event *event)
247{
248 struct timeval max_date;
249 struct timeval now;
250 struct timeval delay;
251 int i; /* button number */
252
253 i = event->value = p2l[event->value];
254
255 gettimeofday(&now, NULL((void *)0));
256 delay.tv_sec = mouse.clickthreshold / 1000;
257 delay.tv_usec = (mouse.clickthreshold % 1000) * 1000;
258 timersub(&now, &delay, &max_date)do { (&max_date)->tv_sec = (&now)->tv_sec - (&
delay)->tv_sec; (&max_date)->tv_usec = (&now)->
tv_usec - (&delay)->tv_usec; if ((&max_date)->tv_usec
< 0) { (&max_date)->tv_sec--; (&max_date)->
tv_usec += 1000000; } } while (0)
;
259
260 if (event->type == WSCONS_EVENT_MOUSE_DOWN5) {
261 if (timercmp(&max_date, &buttonstate[i].tv, >)(((&max_date)->tv_sec == (&buttonstate[i].tv)->
tv_sec) ? ((&max_date)->tv_usec > (&buttonstate
[i].tv)->tv_usec) : ((&max_date)->tv_sec > (&
buttonstate[i].tv)->tv_sec))
) {
262 timerclear(&buttonstate[i].tv)(&buttonstate[i].tv)->tv_sec = (&buttonstate[i].tv
)->tv_usec = 0
;
263 buttonstate[i].count = 1;
264 } else {
265 buttonstate[i].count++;
266 }
267 } else {
268 /* button is up */
269 buttonstate[i].tv.tv_sec = now.tv_sec;
270 buttonstate[i].tv.tv_usec = now.tv_usec;
271 }
272
273 /*
274 * we use the time field of wscons_event structure to put the number
275 * of multiple clicks
276 */
277 if (event->type == WSCONS_EVENT_MOUSE_DOWN5) {
278 event->time.tv_sec = buttonstate[i].count;
279 event->time.tv_nsec = 0;
280 } else {
281 /* button is up */
282 event->time.tv_sec = 0;
283 event->time.tv_nsec = 0;
284 }
285 ioctl(mouse.cfd, WSDISPLAYIO_WSMOUSED((unsigned long)0x80000000 | ((sizeof(struct wscons_event) &
0x1fff) << 16) | ((('W')) << 8) | ((88)))
, event);
286}
287
288/* workaround for cursor speed on serial mice */
289static void
290normalize_event(struct wscons_event *event)
291{
292 int dx, dy;
293 int two_power = 1;
294
295/* 2: normal speed, 3: slower cursor, 1: faster cursor */
296#define NORMALIZE_DIVISOR3 3
297
298 switch (event->type) {
299 case WSCONS_EVENT_MOUSE_DELTA_X6:
300 dx = abs(event->value);
301 while (dx > 2) {
302 two_power++;
303 dx = dx / 2;
304 }
305 event->value = event->value / (NORMALIZE_DIVISOR3 * two_power);
306 break;
307 case WSCONS_EVENT_MOUSE_DELTA_Y7:
308 two_power = 1;
309 dy = abs(event->value);
310 while (dy > 2) {
311 two_power++;
312 dy = dy / 2;
313 }
314 event->value = event->value / (NORMALIZE_DIVISOR3 * two_power);
315 break;
316 }
317}
318
319/* send a wscons_event to the kernel */
320static void
321treat_event(struct wscons_event *event)
322{
323 if (IS_MOTION_EVENT(event->type)(((event->type) == 6) || ((event->type) == 7) || ((event
->type) == 10) || ((event->type) == 16))
) {
324 ioctl(mouse.cfd, WSDISPLAYIO_WSMOUSED((unsigned long)0x80000000 | ((sizeof(struct wscons_event) &
0x1fff) << 16) | ((('W')) << 8) | ((88)))
, event);
325 } else if (IS_BUTTON_EVENT(event->type)(((event->type) == 4) || ((event->type) == 5)) &&
326 (uint)event->value < MOUSE_MAXBUTTON16) {
327 mouse_click(event);
328 }
329}
330
331/* split a full mouse event into multiples wscons events */
332static void
333split_event(mousestatus_t *act)
334{
335 struct wscons_event event;
336 int button, i, mask;
337
338 if (act->dx != 0) {
339 event.type = WSCONS_EVENT_MOUSE_DELTA_X6;
340 event.value = act->dx;
341 normalize_event(&event);
342 treat_event(&event);
343 }
344 if (act->dy != 0) {
345 event.type = WSCONS_EVENT_MOUSE_DELTA_Y7;
346 event.value = 0 - act->dy;
347 normalize_event(&event);
348 treat_event(&event);
349 }
350 if (act->dz != 0) {
351 event.type = WSCONS_EVENT_MOUSE_DELTA_Z10;
352 event.value = act->dz;
353 treat_event(&event);
354 }
355 if (act->dw != 0) {
356 event.type = WSCONS_EVENT_MOUSE_DELTA_W16;
357 event.value = act->dw;
358 treat_event(&event);
359 }
360
361 /* buttons state */
362 mask = act->flags & MOUSE_BUTTONS0x00FF;
363 if (mask == 0)
364 /* no button modified */
365 return;
366
367 button = MOUSE_BUTTON1DOWN0x0001;
368 for (i = 0; (i < MOUSE_MAXBUTTON16) && (mask != 0); i++) {
369 if (mask & 1) {
370 event.type = (act->button & button) ?
371 WSCONS_EVENT_MOUSE_DOWN5 : WSCONS_EVENT_MOUSE_UP4;
372 event.value = i;
373 treat_event(&event);
374 }
375 button <<= 1;
376 mask >>= 1;
377 }
378}
379
380/* main function */
381static void
382wsmoused(void)
383{
384 mousestatus_t action;
385 struct wscons_event event; /* original wscons_event */
386 struct pollfd pfd[1];
387 int res;
388 u_char b;
389
390 /* notify kernel the start of wsmoused */
391 event.type = WSCONS_EVENT_WSMOUSED_ON12;
392 res = ioctl(mouse.cfd, WSDISPLAYIO_WSMOUSED((unsigned long)0x80000000 | ((sizeof(struct wscons_event) &
0x1fff) << 16) | ((('W')) << 8) | ((88)))
, &event);
393 if (res != 0) {
394 /* the display driver has no getchar() method */
395 logerr(1, "this display driver has no support for wsmoused(8)")do { if (background) { syslog(3, "this display driver has no support for wsmoused(8)"
); exit(1); } else errx(1, "this display driver has no support for wsmoused(8)"
); } while (0)
;
396 }
397
398 bzero(&action, sizeof(action));
399 bzero(&event, sizeof(event));
400 bzero(&buttonstate, sizeof(buttonstate));
401
402 pfd[0].fd = mouse.mfd;
403 pfd[0].events = POLLIN0x0001;
404
405 /* process mouse data */
406 for (;;) {
407 if (poll(pfd, 1, INFTIM(-1)) <= 0)
408 logwarn("failed to read from mouse")do { if (background) syslog(4, "failed to read from mouse"); else
warnx("failed to read from mouse"); } while (0)
;
409
410 if (mouse.proto == P_WSCONS-1) {
411 /* wsmouse supported mouse */
412 read(mouse.mfd, &event, sizeof(event));
413 treat_event(&event);
414 } else {
415 /* serial mouse (not supported by wsmouse) */
416 res = read(mouse.mfd, &b, 1);
Value stored to 'res' is never read
417
418 /* if we have a full mouse event */
419 if (mouse_protocol(b, &action))
420 /* split it as multiple wscons_event */
421 split_event(&action);
422 }
423 }
424}
425
426
427static void
428usage(void)
429{
430 fprintf(stderr(&__sF[2]), "usage: %s [-2dfi] [-C thresh] [-D device]"
431 " [-M N=M]\n\t[-p device] [-t type]\n", __progname);
432 exit(1);
433}
434
435int
436main(int argc, char **argv)
437{
438 unsigned int type;
439 int opt;
440 int i;
441
442#define GETOPT_STRING"2dfhip:t:C:D:M:" "2dfhip:t:C:D:M:"
443 while ((opt = (getopt(argc, argv, GETOPT_STRING"2dfhip:t:C:D:M:"))) != -1) {
444 switch (opt) {
445 case '2':
446 /* on two button mice, right button pastes */
447 p2l[MOUSE_BUTTON32] = MOUSE_BUTTON21;
448 break;
449 case 'd':
450 ++debug;
451 break;
452 case 'f':
453 nodaemon = TRUE1;
454 break;
455 case 'h':
456 usage();
457 break;
458 case 'i':
459 identify = TRUE1;
460 nodaemon = TRUE1;
461 break;
462 case 'p':
463 if ((mouse.portname = strdup(optarg)) == NULL((void *)0))
464 logerr(1, "out of memory")do { if (background) { syslog(3, "out of memory"); exit(1); }
else errx(1, "out of memory"); } while (0)
;
465 break;
466 case 't':
467 if (strcmp(optarg, "auto") == 0) {
468 mouse.proto = P_UNKNOWN-2;
469 mouse.flags &= ~NoPnP0x0010;
470 break;
471 }
472 for (i = 0; mouse_names[i] != NULL((void *)0); i++)
473 if (strcmp(optarg,mouse_names[i]) == 0) {
474 mouse.proto = i;
475 mouse.flags |= NoPnP0x0010;
476 break;
477 }
478 if (mouse_names[i] != NULL((void *)0))
479 break;
480 warnx("no such mouse protocol `%s'", optarg);
481 usage();
482 break;
483 case 'C':
484#define MAX_CLICKTHRESHOLD2000 2000 /* max delay for double click */
485 mouse.clickthreshold = atoi(optarg);
486 if (mouse.clickthreshold < 0 ||
487 mouse.clickthreshold > MAX_CLICKTHRESHOLD2000) {
488 warnx("invalid threshold `%s': max value is %d",
489 optarg, MAX_CLICKTHRESHOLD2000);
490 usage();
491 }
492 break;
493 case 'D':
494 if ((mouse.ttyname = strdup(optarg)) == NULL((void *)0))
495 logerr(1, "out of memory")do { if (background) { syslog(3, "out of memory"); exit(1); }
else errx(1, "out of memory"); } while (0)
;
496 break;
497 case 'M':
498 if (!mouse_installmap(optarg)) {
499 warnx("invalid mapping `%s'", optarg);
500 usage();
501 }
502 break;
503 default:
504 usage();
505 }
506 }
507
508 /*
509 * Use defaults if unspecified
510 */
511 if (mouse.portname == NULL((void *)0))
512 mouse.portname = WSMOUSE_DEV"/dev/wsmouse";
513 if (mouse.ttyname == NULL((void *)0))
514 mouse.ttyname = DEFAULT_TTY"/dev/ttyCcfg";
515
516 if (identify == FALSE0) {
517 if ((mouse.cfd = open(mouse.ttyname, O_RDWR0x0002)) == -1)
518 logerr(1, "cannot open %s", mouse.ttyname)do { if (background) { syslog(3, "cannot open %s", mouse.ttyname
); exit(1); } else errx(1, "cannot open %s", mouse.ttyname); }
while (0)
;
519 }
520
521 if ((mouse.mfd = open(mouse.portname,
522 O_RDONLY0x0000 | O_NONBLOCK0x0004)) == -1)
523 logerr(1, "unable to open %s", mouse.portname)do { if (background) { syslog(3, "unable to open %s", mouse.portname
); exit(1); } else errx(1, "unable to open %s", mouse.portname
); } while (0)
;
524
525 /*
526 * Find out whether the mouse device is a wsmouse device
527 * or a serial device.
528 */
529 if (ioctl(mouse.mfd, WSMOUSEIO_GTYPE((unsigned long)0x40000000 | ((sizeof(u_int) & 0x1fff) <<
16) | ((('W')) << 8) | ((32)))
, &type) != -1)
530 mouse.proto = P_WSCONS-1;
531 else {
532 if (mouse_identify() == P_UNKNOWN-2) {
533 close(mouse.mfd);
534 logerr(1, "cannot determine mouse type on %s",do { if (background) { syslog(3, "cannot determine mouse type on %s"
, mouse.portname); exit(1); } else errx(1, "cannot determine mouse type on %s"
, mouse.portname); } while (0)
535 mouse.portname)do { if (background) { syslog(3, "cannot determine mouse type on %s"
, mouse.portname); exit(1); } else errx(1, "cannot determine mouse type on %s"
, mouse.portname); } while (0)
;
536 }
537 }
538
539 if (identify == TRUE1) {
540 if (mouse.proto == P_WSCONS-1)
541 wsmouse_identify();
542 else
543 printf("serial mouse: %s type\n",
544 mouse_name(mouse.proto));
545 exit(0);
546 }
547
548 signal(SIGINT2, terminate);
549 signal(SIGQUIT3, terminate);
550 signal(SIGTERM15, terminate);
551
552 if (mouse.proto == P_WSCONS-1)
553 wsmouse_init();
554 else
555 mouse_init();
556
557 if (!nodaemon) {
558 openlog(__progname, LOG_PID0x01, LOG_DAEMON(3<<3));
559 if (daemon(0, 0)) {
560 logerr(1, "failed to become a daemon")do { if (background) { syslog(3, "failed to become a daemon")
; exit(1); } else errx(1, "failed to become a daemon"); } while
(0)
;
561 } else {
562 background = TRUE1;
563 }
564 }
565
566 wsmoused();
567 exit(0);
568}