1*0a6a1f1dSLionel Sambuc /* $NetBSD: w.c,v 1.82 2014/12/22 15:24:14 dennis Exp $ */
211eaad35SDavid van Moolenbroek
311eaad35SDavid van Moolenbroek /*-
411eaad35SDavid van Moolenbroek * Copyright (c) 1980, 1991, 1993, 1994
511eaad35SDavid van Moolenbroek * The Regents of the University of California. All rights reserved.
611eaad35SDavid van Moolenbroek *
711eaad35SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
811eaad35SDavid van Moolenbroek * modification, are permitted provided that the following conditions
911eaad35SDavid van Moolenbroek * are met:
1011eaad35SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
1111eaad35SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
1211eaad35SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
1311eaad35SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
1411eaad35SDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
1511eaad35SDavid van Moolenbroek * 3. Neither the name of the University nor the names of its contributors
1611eaad35SDavid van Moolenbroek * may be used to endorse or promote products derived from this software
1711eaad35SDavid van Moolenbroek * without specific prior written permission.
1811eaad35SDavid van Moolenbroek *
1911eaad35SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2011eaad35SDavid van Moolenbroek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2111eaad35SDavid van Moolenbroek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2211eaad35SDavid van Moolenbroek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2311eaad35SDavid van Moolenbroek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2411eaad35SDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2511eaad35SDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2611eaad35SDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2711eaad35SDavid van Moolenbroek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2811eaad35SDavid van Moolenbroek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2911eaad35SDavid van Moolenbroek * SUCH DAMAGE.
3011eaad35SDavid van Moolenbroek */
3111eaad35SDavid van Moolenbroek
3211eaad35SDavid van Moolenbroek #include <sys/cdefs.h>
3311eaad35SDavid van Moolenbroek #ifndef lint
3411eaad35SDavid van Moolenbroek __COPYRIGHT("@(#) Copyright (c) 1980, 1991, 1993, 1994\
3511eaad35SDavid van Moolenbroek The Regents of the University of California. All rights reserved.");
3611eaad35SDavid van Moolenbroek #endif /* not lint */
3711eaad35SDavid van Moolenbroek
3811eaad35SDavid van Moolenbroek #ifndef lint
3911eaad35SDavid van Moolenbroek #if 0
4011eaad35SDavid van Moolenbroek static char sccsid[] = "@(#)w.c 8.6 (Berkeley) 6/30/94";
4111eaad35SDavid van Moolenbroek #else
42*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: w.c,v 1.82 2014/12/22 15:24:14 dennis Exp $");
4311eaad35SDavid van Moolenbroek #endif
4411eaad35SDavid van Moolenbroek #endif /* not lint */
4511eaad35SDavid van Moolenbroek
4611eaad35SDavid van Moolenbroek /*
4711eaad35SDavid van Moolenbroek * w - print system status (who and what)
4811eaad35SDavid van Moolenbroek *
4911eaad35SDavid van Moolenbroek * This program is similar to the systat command on Tenex/Tops 10/20
5011eaad35SDavid van Moolenbroek *
5111eaad35SDavid van Moolenbroek */
5211eaad35SDavid van Moolenbroek #include <sys/param.h>
5311eaad35SDavid van Moolenbroek #include <sys/types.h>
5411eaad35SDavid van Moolenbroek #include <sys/time.h>
5511eaad35SDavid van Moolenbroek #include <sys/stat.h>
5611eaad35SDavid van Moolenbroek #include <sys/sysctl.h>
5711eaad35SDavid van Moolenbroek #include <sys/proc.h>
5811eaad35SDavid van Moolenbroek #include <sys/ioctl.h>
5911eaad35SDavid van Moolenbroek #include <sys/socket.h>
6011eaad35SDavid van Moolenbroek
6111eaad35SDavid van Moolenbroek #include <netinet/in.h>
6211eaad35SDavid van Moolenbroek #include <arpa/inet.h>
6311eaad35SDavid van Moolenbroek
6411eaad35SDavid van Moolenbroek #include <ctype.h>
6511eaad35SDavid van Moolenbroek #include <err.h>
6611eaad35SDavid van Moolenbroek #include <errno.h>
6711eaad35SDavid van Moolenbroek #include <fcntl.h>
6811eaad35SDavid van Moolenbroek #include <kvm.h>
6911eaad35SDavid van Moolenbroek #include <limits.h>
7011eaad35SDavid van Moolenbroek #include <netdb.h>
7111eaad35SDavid van Moolenbroek #include <nlist.h>
7211eaad35SDavid van Moolenbroek #include <paths.h>
7311eaad35SDavid van Moolenbroek #include <stdio.h>
7411eaad35SDavid van Moolenbroek #include <stdlib.h>
7511eaad35SDavid van Moolenbroek #include <string.h>
7611eaad35SDavid van Moolenbroek #include <time.h>
7711eaad35SDavid van Moolenbroek #include <tzfile.h>
7811eaad35SDavid van Moolenbroek #include <unistd.h>
7911eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMP
8011eaad35SDavid van Moolenbroek #include <utmp.h>
8111eaad35SDavid van Moolenbroek #endif
8211eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMPX
8311eaad35SDavid van Moolenbroek #include <utmpx.h>
8411eaad35SDavid van Moolenbroek #endif
8511eaad35SDavid van Moolenbroek #include <vis.h>
8611eaad35SDavid van Moolenbroek
8711eaad35SDavid van Moolenbroek #include "extern.h"
8811eaad35SDavid van Moolenbroek
8911eaad35SDavid van Moolenbroek struct timeval boottime;
9011eaad35SDavid van Moolenbroek struct winsize ws;
9111eaad35SDavid van Moolenbroek kvm_t *kd;
9211eaad35SDavid van Moolenbroek time_t now; /* the current time of day */
9311eaad35SDavid van Moolenbroek int ttywidth; /* width of tty */
9411eaad35SDavid van Moolenbroek int argwidth; /* width of tty left to print process args */
9511eaad35SDavid van Moolenbroek int header = 1; /* true if -h flag: don't print heading */
9611eaad35SDavid van Moolenbroek int nflag; /* true if -n flag: don't convert addrs */
9711eaad35SDavid van Moolenbroek int wflag; /* true if -w flag: wide printout */
9811eaad35SDavid van Moolenbroek int sortidle; /* sort bu idle time */
9911eaad35SDavid van Moolenbroek char *sel_user; /* login of particular user selected */
10011eaad35SDavid van Moolenbroek char domain[MAXHOSTNAMELEN + 1];
10111eaad35SDavid van Moolenbroek int maxname = 8, maxline = 3, maxhost = 16;
10211eaad35SDavid van Moolenbroek
10311eaad35SDavid van Moolenbroek /*
10411eaad35SDavid van Moolenbroek * One of these per active utmp entry.
10511eaad35SDavid van Moolenbroek */
10611eaad35SDavid van Moolenbroek struct entry {
10711eaad35SDavid van Moolenbroek struct entry *next;
10811eaad35SDavid van Moolenbroek char name[UTX_USERSIZE + 1];
10911eaad35SDavid van Moolenbroek char line[UTX_LINESIZE + 1];
11011eaad35SDavid van Moolenbroek char host[UTX_HOSTSIZE + 1];
11111eaad35SDavid van Moolenbroek char type[2];
11211eaad35SDavid van Moolenbroek struct timeval tv;
11311eaad35SDavid van Moolenbroek dev_t tdev; /* dev_t of terminal */
11411eaad35SDavid van Moolenbroek time_t idle; /* idle time of terminal in seconds */
11511eaad35SDavid van Moolenbroek struct kinfo_proc2 *tp; /* `most interesting' tty proc */
11611eaad35SDavid van Moolenbroek struct kinfo_proc2 *pp; /* pid proc */
11711eaad35SDavid van Moolenbroek pid_t pid; /* pid or ~0 if not known */
11811eaad35SDavid van Moolenbroek } *ehead = NULL, **nextp = &ehead;
11911eaad35SDavid van Moolenbroek
12011eaad35SDavid van Moolenbroek static void pr_args(struct kinfo_proc2 *);
12111eaad35SDavid van Moolenbroek static void pr_header(time_t *, int);
12211eaad35SDavid van Moolenbroek static int proc_compare_wrapper(const struct kinfo_proc2 *,
12311eaad35SDavid van Moolenbroek const struct kinfo_proc2 *);
12411eaad35SDavid van Moolenbroek #if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX)
12511eaad35SDavid van Moolenbroek static int ttystat(const char *, struct stat *);
12611eaad35SDavid van Moolenbroek static void process(struct entry *);
12711eaad35SDavid van Moolenbroek #endif
12811eaad35SDavid van Moolenbroek static void fixhost(struct entry *ep);
12911eaad35SDavid van Moolenbroek __dead static void usage(int);
13011eaad35SDavid van Moolenbroek
13111eaad35SDavid van Moolenbroek int
main(int argc,char ** argv)13211eaad35SDavid van Moolenbroek main(int argc, char **argv)
13311eaad35SDavid van Moolenbroek {
13411eaad35SDavid van Moolenbroek struct kinfo_proc2 *kp;
13511eaad35SDavid van Moolenbroek struct entry *ep;
13611eaad35SDavid van Moolenbroek int ch, i, nentries, nusers, wcmd, curtain, use_sysctl;
13711eaad35SDavid van Moolenbroek char *memf, *nlistf, *usrnp;
13811eaad35SDavid van Moolenbroek const char *options;
13911eaad35SDavid van Moolenbroek time_t then;
14011eaad35SDavid van Moolenbroek size_t len;
14111eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMP
14211eaad35SDavid van Moolenbroek struct utmp *ut;
14311eaad35SDavid van Moolenbroek #endif
14411eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMPX
14511eaad35SDavid van Moolenbroek struct utmpx *utx;
14611eaad35SDavid van Moolenbroek #endif
14711eaad35SDavid van Moolenbroek const char *progname;
14811eaad35SDavid van Moolenbroek char errbuf[_POSIX2_LINE_MAX];
14911eaad35SDavid van Moolenbroek
15011eaad35SDavid van Moolenbroek setprogname(argv[0]);
15111eaad35SDavid van Moolenbroek
15211eaad35SDavid van Moolenbroek /* Are we w(1) or uptime(1)? */
15311eaad35SDavid van Moolenbroek progname = getprogname();
15411eaad35SDavid van Moolenbroek if (*progname == '-')
15511eaad35SDavid van Moolenbroek progname++;
15611eaad35SDavid van Moolenbroek if (*progname == 'u') {
15711eaad35SDavid van Moolenbroek wcmd = 0;
15811eaad35SDavid van Moolenbroek options = "";
15911eaad35SDavid van Moolenbroek } else {
16011eaad35SDavid van Moolenbroek wcmd = 1;
16111eaad35SDavid van Moolenbroek options = "hiM:N:nw";
16211eaad35SDavid van Moolenbroek }
16311eaad35SDavid van Moolenbroek
16411eaad35SDavid van Moolenbroek memf = nlistf = NULL;
16511eaad35SDavid van Moolenbroek while ((ch = getopt(argc, argv, options)) != -1)
16611eaad35SDavid van Moolenbroek switch (ch) {
16711eaad35SDavid van Moolenbroek case 'h':
16811eaad35SDavid van Moolenbroek header = 0;
16911eaad35SDavid van Moolenbroek break;
17011eaad35SDavid van Moolenbroek case 'i':
17111eaad35SDavid van Moolenbroek sortidle = 1;
17211eaad35SDavid van Moolenbroek break;
17311eaad35SDavid van Moolenbroek case 'M':
17411eaad35SDavid van Moolenbroek header = 0;
17511eaad35SDavid van Moolenbroek memf = optarg;
17611eaad35SDavid van Moolenbroek break;
17711eaad35SDavid van Moolenbroek case 'N':
17811eaad35SDavid van Moolenbroek nlistf = optarg;
17911eaad35SDavid van Moolenbroek break;
18011eaad35SDavid van Moolenbroek case 'n':
18111eaad35SDavid van Moolenbroek nflag = 1;
18211eaad35SDavid van Moolenbroek break;
18311eaad35SDavid van Moolenbroek case 'w':
18411eaad35SDavid van Moolenbroek wflag = 1;
18511eaad35SDavid van Moolenbroek break;
18611eaad35SDavid van Moolenbroek case '?':
18711eaad35SDavid van Moolenbroek default:
18811eaad35SDavid van Moolenbroek usage(wcmd);
18911eaad35SDavid van Moolenbroek }
19011eaad35SDavid van Moolenbroek argc -= optind;
19111eaad35SDavid van Moolenbroek argv += optind;
19211eaad35SDavid van Moolenbroek
19311eaad35SDavid van Moolenbroek use_sysctl = (memf == NULL && nlistf == NULL);
19411eaad35SDavid van Moolenbroek
19511eaad35SDavid van Moolenbroek if ((kd = kvm_openfiles(nlistf, memf, NULL,
19611eaad35SDavid van Moolenbroek memf == NULL ? KVM_NO_FILES : O_RDONLY, errbuf)) == NULL)
19711eaad35SDavid van Moolenbroek errx(1, "%s", errbuf);
19811eaad35SDavid van Moolenbroek
19911eaad35SDavid van Moolenbroek (void)time(&now);
20011eaad35SDavid van Moolenbroek
20111eaad35SDavid van Moolenbroek if (use_sysctl) {
20211eaad35SDavid van Moolenbroek len = sizeof(curtain);
20311eaad35SDavid van Moolenbroek if (sysctlbyname("security.curtain", &curtain, &len,
20411eaad35SDavid van Moolenbroek NULL, 0) == -1)
20511eaad35SDavid van Moolenbroek curtain = 0;
20611eaad35SDavid van Moolenbroek }
20711eaad35SDavid van Moolenbroek
20811eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMPX
20911eaad35SDavid van Moolenbroek setutxent();
21011eaad35SDavid van Moolenbroek #endif
21111eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMP
21211eaad35SDavid van Moolenbroek setutent();
21311eaad35SDavid van Moolenbroek #endif
21411eaad35SDavid van Moolenbroek
21511eaad35SDavid van Moolenbroek if (*argv)
21611eaad35SDavid van Moolenbroek sel_user = *argv;
21711eaad35SDavid van Moolenbroek
21811eaad35SDavid van Moolenbroek nusers = 0;
21911eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMPX
22011eaad35SDavid van Moolenbroek while ((utx = getutxent()) != NULL) {
22111eaad35SDavid van Moolenbroek if (utx->ut_type != USER_PROCESS)
22211eaad35SDavid van Moolenbroek continue;
22311eaad35SDavid van Moolenbroek ++nusers;
224*0a6a1f1dSLionel Sambuc
225*0a6a1f1dSLionel Sambuc #ifndef SUPPORT_UTMP
226*0a6a1f1dSLionel Sambuc if (wcmd == 0)
227*0a6a1f1dSLionel Sambuc continue;
228*0a6a1f1dSLionel Sambuc #endif /* !SUPPORT_UTMP */
229*0a6a1f1dSLionel Sambuc
23011eaad35SDavid van Moolenbroek if (sel_user &&
23111eaad35SDavid van Moolenbroek strncmp(utx->ut_name, sel_user, sizeof(utx->ut_name)) != 0)
23211eaad35SDavid van Moolenbroek continue;
23311eaad35SDavid van Moolenbroek if ((ep = calloc(1, sizeof(struct entry))) == NULL)
23411eaad35SDavid van Moolenbroek err(1, NULL);
23511eaad35SDavid van Moolenbroek (void)memcpy(ep->line, utx->ut_line, sizeof(utx->ut_line));
23611eaad35SDavid van Moolenbroek ep->line[sizeof(utx->ut_line)] = '\0';
237*0a6a1f1dSLionel Sambuc *nextp = ep;
238*0a6a1f1dSLionel Sambuc nextp = &(ep->next);
239*0a6a1f1dSLionel Sambuc
240*0a6a1f1dSLionel Sambuc if (wcmd == 0)
241*0a6a1f1dSLionel Sambuc continue;
242*0a6a1f1dSLionel Sambuc
243*0a6a1f1dSLionel Sambuc (void)memcpy(ep->name, utx->ut_name, sizeof(utx->ut_name));
244*0a6a1f1dSLionel Sambuc ep->name[sizeof(utx->ut_name)] = '\0';
24511eaad35SDavid van Moolenbroek if (!nflag || getnameinfo((struct sockaddr *)&utx->ut_ss,
24611eaad35SDavid van Moolenbroek utx->ut_ss.ss_len, ep->host, sizeof(ep->host), NULL, 0,
24711eaad35SDavid van Moolenbroek NI_NUMERICHOST) != 0) {
24811eaad35SDavid van Moolenbroek (void)memcpy(ep->host, utx->ut_host,
24911eaad35SDavid van Moolenbroek sizeof(utx->ut_host));
25011eaad35SDavid van Moolenbroek ep->host[sizeof(utx->ut_host)] = '\0';
25111eaad35SDavid van Moolenbroek }
25211eaad35SDavid van Moolenbroek fixhost(ep);
25311eaad35SDavid van Moolenbroek ep->type[0] = 'x';
25411eaad35SDavid van Moolenbroek ep->tv = utx->ut_tv;
25511eaad35SDavid van Moolenbroek ep->pid = utx->ut_pid;
25611eaad35SDavid van Moolenbroek process(ep);
25711eaad35SDavid van Moolenbroek }
25811eaad35SDavid van Moolenbroek #endif
25911eaad35SDavid van Moolenbroek
26011eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMP
26111eaad35SDavid van Moolenbroek while ((ut = getutent()) != NULL) {
26211eaad35SDavid van Moolenbroek if (ut->ut_name[0] == '\0')
26311eaad35SDavid van Moolenbroek continue;
26411eaad35SDavid van Moolenbroek
26511eaad35SDavid van Moolenbroek if (sel_user &&
26611eaad35SDavid van Moolenbroek strncmp(ut->ut_name, sel_user, sizeof(ut->ut_name)) != 0)
26711eaad35SDavid van Moolenbroek continue;
26811eaad35SDavid van Moolenbroek
26911eaad35SDavid van Moolenbroek /* Don't process entries that we have utmpx for */
27011eaad35SDavid van Moolenbroek for (ep = ehead; ep != NULL; ep = ep->next) {
27111eaad35SDavid van Moolenbroek if (strncmp(ep->line, ut->ut_line,
27211eaad35SDavid van Moolenbroek sizeof(ut->ut_line)) == 0)
27311eaad35SDavid van Moolenbroek break;
27411eaad35SDavid van Moolenbroek }
27511eaad35SDavid van Moolenbroek if (ep != NULL)
27611eaad35SDavid van Moolenbroek continue;
27711eaad35SDavid van Moolenbroek
27811eaad35SDavid van Moolenbroek ++nusers;
279*0a6a1f1dSLionel Sambuc
280*0a6a1f1dSLionel Sambuc if (wcmd == 0)
281*0a6a1f1dSLionel Sambuc continue;
282*0a6a1f1dSLionel Sambuc
28311eaad35SDavid van Moolenbroek if ((ep = calloc(1, sizeof(struct entry))) == NULL)
28411eaad35SDavid van Moolenbroek err(1, NULL);
28511eaad35SDavid van Moolenbroek (void)memcpy(ep->name, ut->ut_name, sizeof(ut->ut_name));
28611eaad35SDavid van Moolenbroek (void)memcpy(ep->line, ut->ut_line, sizeof(ut->ut_line));
28711eaad35SDavid van Moolenbroek (void)memcpy(ep->host, ut->ut_host, sizeof(ut->ut_host));
28811eaad35SDavid van Moolenbroek ep->name[sizeof(ut->ut_name)] = '\0';
28911eaad35SDavid van Moolenbroek ep->line[sizeof(ut->ut_line)] = '\0';
29011eaad35SDavid van Moolenbroek ep->host[sizeof(ut->ut_host)] = '\0';
29111eaad35SDavid van Moolenbroek fixhost(ep);
29211eaad35SDavid van Moolenbroek ep->tv.tv_sec = ut->ut_time;
29311eaad35SDavid van Moolenbroek *nextp = ep;
29411eaad35SDavid van Moolenbroek nextp = &(ep->next);
29511eaad35SDavid van Moolenbroek process(ep);
29611eaad35SDavid van Moolenbroek }
29711eaad35SDavid van Moolenbroek #endif
29811eaad35SDavid van Moolenbroek
29911eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMPX
30011eaad35SDavid van Moolenbroek endutxent();
30111eaad35SDavid van Moolenbroek #endif
30211eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMP
30311eaad35SDavid van Moolenbroek endutent();
30411eaad35SDavid van Moolenbroek #endif
30511eaad35SDavid van Moolenbroek
30611eaad35SDavid van Moolenbroek if (header || wcmd == 0) {
30711eaad35SDavid van Moolenbroek pr_header(&now, nusers);
30811eaad35SDavid van Moolenbroek if (wcmd == 0)
30911eaad35SDavid van Moolenbroek exit (0);
31011eaad35SDavid van Moolenbroek }
31111eaad35SDavid van Moolenbroek
31211eaad35SDavid van Moolenbroek if ((kp = kvm_getproc2(kd, KERN_PROC_ALL, 0,
31311eaad35SDavid van Moolenbroek sizeof(struct kinfo_proc2), &nentries)) == NULL)
31411eaad35SDavid van Moolenbroek errx(1, "%s", kvm_geterr(kd));
31511eaad35SDavid van Moolenbroek
31611eaad35SDavid van Moolenbroek /* Include trailing space because TTY header starts one column early. */
31711eaad35SDavid van Moolenbroek for (i = 0; i < nentries; i++, kp++) {
31811eaad35SDavid van Moolenbroek
31911eaad35SDavid van Moolenbroek for (ep = ehead; ep != NULL; ep = ep->next) {
32011eaad35SDavid van Moolenbroek if (ep->tdev != 0 && ep->tdev == kp->p_tdev &&
32111eaad35SDavid van Moolenbroek kp->p__pgid == kp->p_tpgid) {
32211eaad35SDavid van Moolenbroek /*
32311eaad35SDavid van Moolenbroek * Proc is in foreground of this
32411eaad35SDavid van Moolenbroek * terminal
32511eaad35SDavid van Moolenbroek */
32611eaad35SDavid van Moolenbroek if (proc_compare_wrapper(ep->tp, kp))
32711eaad35SDavid van Moolenbroek ep->tp = kp;
32811eaad35SDavid van Moolenbroek break;
32911eaad35SDavid van Moolenbroek }
33011eaad35SDavid van Moolenbroek if (ep->pid != 0 && ep->pid == kp->p_pid) {
33111eaad35SDavid van Moolenbroek ep->pp = kp;
33211eaad35SDavid van Moolenbroek break;
33311eaad35SDavid van Moolenbroek }
33411eaad35SDavid van Moolenbroek }
33511eaad35SDavid van Moolenbroek }
33611eaad35SDavid van Moolenbroek
33711eaad35SDavid van Moolenbroek if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 &&
33811eaad35SDavid van Moolenbroek ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 &&
33911eaad35SDavid van Moolenbroek ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0)
34011eaad35SDavid van Moolenbroek ttywidth = 79;
34111eaad35SDavid van Moolenbroek else
34211eaad35SDavid van Moolenbroek ttywidth = ws.ws_col - 1;
34311eaad35SDavid van Moolenbroek
34411eaad35SDavid van Moolenbroek if (!wflag && maxhost > (ttywidth / 3))
34511eaad35SDavid van Moolenbroek maxhost = ttywidth / 3;
34611eaad35SDavid van Moolenbroek
34711eaad35SDavid van Moolenbroek argwidth = printf("%-*s TTY %-*s %*s IDLE WHAT\n",
34811eaad35SDavid van Moolenbroek maxname, "USER", maxhost, "FROM",
34911eaad35SDavid van Moolenbroek 7 /* "dddhhXm" */, "LOGIN@");
35011eaad35SDavid van Moolenbroek argwidth -= sizeof("WHAT\n") - 1 /* NUL */;
35111eaad35SDavid van Moolenbroek argwidth = ttywidth - argwidth;
35211eaad35SDavid van Moolenbroek if (argwidth < 4)
35311eaad35SDavid van Moolenbroek argwidth = 8;
35411eaad35SDavid van Moolenbroek if (wflag)
35511eaad35SDavid van Moolenbroek argwidth = -1;
35611eaad35SDavid van Moolenbroek
35711eaad35SDavid van Moolenbroek /* sort by idle time */
35811eaad35SDavid van Moolenbroek if (sortidle && ehead != NULL) {
35911eaad35SDavid van Moolenbroek struct entry *from = ehead, *save;
36011eaad35SDavid van Moolenbroek
36111eaad35SDavid van Moolenbroek ehead = NULL;
36211eaad35SDavid van Moolenbroek while (from != NULL) {
36311eaad35SDavid van Moolenbroek for (nextp = &ehead;
36411eaad35SDavid van Moolenbroek (*nextp) && from->idle >= (*nextp)->idle;
36511eaad35SDavid van Moolenbroek nextp = &(*nextp)->next)
36611eaad35SDavid van Moolenbroek continue;
36711eaad35SDavid van Moolenbroek save = from;
36811eaad35SDavid van Moolenbroek from = from->next;
36911eaad35SDavid van Moolenbroek save->next = *nextp;
37011eaad35SDavid van Moolenbroek *nextp = save;
37111eaad35SDavid van Moolenbroek }
37211eaad35SDavid van Moolenbroek }
37311eaad35SDavid van Moolenbroek #if defined(SUPPORT_UTMP) && defined(SUPPORT_UTMPX)
37411eaad35SDavid van Moolenbroek else if (ehead != NULL) {
37511eaad35SDavid van Moolenbroek struct entry *from = ehead, *save;
37611eaad35SDavid van Moolenbroek
37711eaad35SDavid van Moolenbroek ehead = NULL;
37811eaad35SDavid van Moolenbroek while (from != NULL) {
37911eaad35SDavid van Moolenbroek for (nextp = &ehead;
38011eaad35SDavid van Moolenbroek (*nextp) && strcmp(from->line, (*nextp)->line) > 0;
38111eaad35SDavid van Moolenbroek nextp = &(*nextp)->next)
38211eaad35SDavid van Moolenbroek continue;
38311eaad35SDavid van Moolenbroek save = from;
38411eaad35SDavid van Moolenbroek from = from->next;
38511eaad35SDavid van Moolenbroek save->next = *nextp;
38611eaad35SDavid van Moolenbroek *nextp = save;
38711eaad35SDavid van Moolenbroek }
38811eaad35SDavid van Moolenbroek }
38911eaad35SDavid van Moolenbroek #endif
39011eaad35SDavid van Moolenbroek
39111eaad35SDavid van Moolenbroek if (!nflag) {
39211eaad35SDavid van Moolenbroek int rv;
39311eaad35SDavid van Moolenbroek char *p;
39411eaad35SDavid van Moolenbroek
39511eaad35SDavid van Moolenbroek rv = gethostname(domain, sizeof(domain));
39611eaad35SDavid van Moolenbroek domain[sizeof(domain) - 1] = '\0';
39711eaad35SDavid van Moolenbroek if (rv < 0 || (p = strchr(domain, '.')) == 0)
39811eaad35SDavid van Moolenbroek domain[0] = '\0';
39911eaad35SDavid van Moolenbroek else
40011eaad35SDavid van Moolenbroek memmove(domain, p, strlen(p) + 1);
40111eaad35SDavid van Moolenbroek }
40211eaad35SDavid van Moolenbroek
40311eaad35SDavid van Moolenbroek for (ep = ehead; ep != NULL; ep = ep->next) {
40411eaad35SDavid van Moolenbroek if (ep->tp != NULL)
40511eaad35SDavid van Moolenbroek kp = ep->tp;
40611eaad35SDavid van Moolenbroek else if (ep->pp != NULL)
40711eaad35SDavid van Moolenbroek kp = ep->pp;
40811eaad35SDavid van Moolenbroek else if (ep->pid != 0) {
40911eaad35SDavid van Moolenbroek if (curtain)
41011eaad35SDavid van Moolenbroek kp = NULL;
41111eaad35SDavid van Moolenbroek else {
41211eaad35SDavid van Moolenbroek warnx("Stale utmp%s entry: %s %s %s",
41311eaad35SDavid van Moolenbroek ep->type, ep->name, ep->line, ep->host);
41411eaad35SDavid van Moolenbroek continue;
41511eaad35SDavid van Moolenbroek }
41611eaad35SDavid van Moolenbroek }
417*0a6a1f1dSLionel Sambuc #if !defined(__minix)
41811eaad35SDavid van Moolenbroek usrnp = (kp == NULL) ? ep->name : kp->p_login;
41911eaad35SDavid van Moolenbroek #else
42011eaad35SDavid van Moolenbroek usrnp = ep->name; /* TODO: implement getlogin/setlogin */
421*0a6a1f1dSLionel Sambuc #endif /* !defined(__minix) */
42211eaad35SDavid van Moolenbroek (void)printf("%-*s %-7.7s %-*.*s ",
42311eaad35SDavid van Moolenbroek maxname, usrnp, ep->line,
42411eaad35SDavid van Moolenbroek maxhost, maxhost, ep->host);
42511eaad35SDavid van Moolenbroek then = (time_t)ep->tv.tv_sec;
42611eaad35SDavid van Moolenbroek pr_attime(&then, &now);
42711eaad35SDavid van Moolenbroek pr_idle(ep->idle);
42811eaad35SDavid van Moolenbroek pr_args(kp);
42911eaad35SDavid van Moolenbroek (void)printf("\n");
43011eaad35SDavid van Moolenbroek }
43111eaad35SDavid van Moolenbroek exit(0);
43211eaad35SDavid van Moolenbroek }
43311eaad35SDavid van Moolenbroek
43411eaad35SDavid van Moolenbroek static void
pr_args(struct kinfo_proc2 * kp)43511eaad35SDavid van Moolenbroek pr_args(struct kinfo_proc2 *kp)
43611eaad35SDavid van Moolenbroek {
43711eaad35SDavid van Moolenbroek char **argv;
43811eaad35SDavid van Moolenbroek int left;
43911eaad35SDavid van Moolenbroek
44011eaad35SDavid van Moolenbroek if (kp == 0)
44111eaad35SDavid van Moolenbroek goto nothing;
44211eaad35SDavid van Moolenbroek left = argwidth;
44311eaad35SDavid van Moolenbroek argv = kvm_getargv2(kd, kp, (argwidth < 0) ? 0 : argwidth);
44411eaad35SDavid van Moolenbroek if (argv == 0) {
44511eaad35SDavid van Moolenbroek fmt_putc('(', &left);
44611eaad35SDavid van Moolenbroek fmt_puts((char *)kp->p_comm, &left);
44711eaad35SDavid van Moolenbroek fmt_putc(')', &left);
44811eaad35SDavid van Moolenbroek return;
44911eaad35SDavid van Moolenbroek }
45011eaad35SDavid van Moolenbroek while (*argv) {
45111eaad35SDavid van Moolenbroek fmt_puts(*argv, &left);
45211eaad35SDavid van Moolenbroek argv++;
45311eaad35SDavid van Moolenbroek fmt_putc(' ', &left);
45411eaad35SDavid van Moolenbroek }
45511eaad35SDavid van Moolenbroek return;
45611eaad35SDavid van Moolenbroek nothing:
45711eaad35SDavid van Moolenbroek putchar('-');
45811eaad35SDavid van Moolenbroek }
45911eaad35SDavid van Moolenbroek
46011eaad35SDavid van Moolenbroek static void
pr_header(time_t * nowp,int nusers)46111eaad35SDavid van Moolenbroek pr_header(time_t *nowp, int nusers)
46211eaad35SDavid van Moolenbroek {
46311eaad35SDavid van Moolenbroek double avenrun[3];
46411eaad35SDavid van Moolenbroek time_t uptime;
46511eaad35SDavid van Moolenbroek int days, hrs, mins;
46611eaad35SDavid van Moolenbroek int mib[2];
46711eaad35SDavid van Moolenbroek size_t size, i;
46811eaad35SDavid van Moolenbroek char buf[256];
46911eaad35SDavid van Moolenbroek
47011eaad35SDavid van Moolenbroek /*
47111eaad35SDavid van Moolenbroek * Print time of day.
47211eaad35SDavid van Moolenbroek *
47311eaad35SDavid van Moolenbroek * SCCS forces the string manipulation below, as it replaces
47411eaad35SDavid van Moolenbroek * %, M, and % in a character string with the file name.
47511eaad35SDavid van Moolenbroek */
47611eaad35SDavid van Moolenbroek (void)strftime(buf, sizeof(buf), "%l:%" "M%p", localtime(nowp));
47711eaad35SDavid van Moolenbroek buf[sizeof(buf) - 1] = '\0';
47811eaad35SDavid van Moolenbroek (void)printf("%s ", buf);
47911eaad35SDavid van Moolenbroek
48011eaad35SDavid van Moolenbroek /*
48111eaad35SDavid van Moolenbroek * Print how long system has been up.
48211eaad35SDavid van Moolenbroek * (Found by looking getting "boottime" from the kernel)
48311eaad35SDavid van Moolenbroek */
48411eaad35SDavid van Moolenbroek mib[0] = CTL_KERN;
48511eaad35SDavid van Moolenbroek mib[1] = KERN_BOOTTIME;
48611eaad35SDavid van Moolenbroek size = sizeof(boottime);
48711eaad35SDavid van Moolenbroek if (sysctl(mib, 2, &boottime, &size, NULL, 0) != -1 &&
48811eaad35SDavid van Moolenbroek boottime.tv_sec != 0) {
48911eaad35SDavid van Moolenbroek uptime = now - boottime.tv_sec;
49011eaad35SDavid van Moolenbroek uptime += 30;
49111eaad35SDavid van Moolenbroek if (uptime > SECSPERMIN) {
49211eaad35SDavid van Moolenbroek days = uptime / SECSPERDAY;
49311eaad35SDavid van Moolenbroek uptime %= SECSPERDAY;
49411eaad35SDavid van Moolenbroek hrs = uptime / SECSPERHOUR;
49511eaad35SDavid van Moolenbroek uptime %= SECSPERHOUR;
49611eaad35SDavid van Moolenbroek mins = uptime / SECSPERMIN;
49711eaad35SDavid van Moolenbroek (void)printf(" up");
49811eaad35SDavid van Moolenbroek if (days > 0)
49911eaad35SDavid van Moolenbroek (void)printf(" %d day%s,", days,
50011eaad35SDavid van Moolenbroek days > 1 ? "s" : "");
50111eaad35SDavid van Moolenbroek if (hrs > 0 && mins > 0)
50211eaad35SDavid van Moolenbroek (void)printf(" %2d:%02d,", hrs, mins);
50311eaad35SDavid van Moolenbroek else {
50411eaad35SDavid van Moolenbroek if (hrs > 0)
50511eaad35SDavid van Moolenbroek (void)printf(" %d hr%s,",
50611eaad35SDavid van Moolenbroek hrs, hrs > 1 ? "s" : "");
50711eaad35SDavid van Moolenbroek if (mins > 0)
50811eaad35SDavid van Moolenbroek (void)printf(" %d min%s,",
50911eaad35SDavid van Moolenbroek mins, mins > 1 ? "s" : "");
51011eaad35SDavid van Moolenbroek }
51111eaad35SDavid van Moolenbroek }
51211eaad35SDavid van Moolenbroek }
51311eaad35SDavid van Moolenbroek
51411eaad35SDavid van Moolenbroek /* Print number of users logged in to system */
51511eaad35SDavid van Moolenbroek (void)printf(" %d user%s", nusers, nusers != 1 ? "s" : "");
51611eaad35SDavid van Moolenbroek
51711eaad35SDavid van Moolenbroek /*
51811eaad35SDavid van Moolenbroek * Print 1, 5, and 15 minute load averages.
51911eaad35SDavid van Moolenbroek */
52011eaad35SDavid van Moolenbroek if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) == -1)
52111eaad35SDavid van Moolenbroek (void)printf(", no load average information available\n");
52211eaad35SDavid van Moolenbroek else {
52311eaad35SDavid van Moolenbroek (void)printf(", load averages:");
52411eaad35SDavid van Moolenbroek for (i = 0; i < (sizeof(avenrun) / sizeof(avenrun[0])); i++) {
52511eaad35SDavid van Moolenbroek if (i > 0)
52611eaad35SDavid van Moolenbroek (void)printf(",");
52711eaad35SDavid van Moolenbroek (void)printf(" %.2f", avenrun[i]);
52811eaad35SDavid van Moolenbroek }
52911eaad35SDavid van Moolenbroek (void)printf("\n");
53011eaad35SDavid van Moolenbroek }
53111eaad35SDavid van Moolenbroek }
53211eaad35SDavid van Moolenbroek
53311eaad35SDavid van Moolenbroek #if defined(SUPPORT_UTMP) || defined(SUPPORT_UTMPX)
53411eaad35SDavid van Moolenbroek static int
ttystat(const char * line,struct stat * st)53511eaad35SDavid van Moolenbroek ttystat(const char *line, struct stat *st)
53611eaad35SDavid van Moolenbroek {
53711eaad35SDavid van Moolenbroek char ttybuf[MAXPATHLEN];
53811eaad35SDavid van Moolenbroek
53911eaad35SDavid van Moolenbroek (void)snprintf(ttybuf, sizeof(ttybuf), "%s%s", _PATH_DEV, line);
54011eaad35SDavid van Moolenbroek return stat(ttybuf, st);
54111eaad35SDavid van Moolenbroek }
54211eaad35SDavid van Moolenbroek
54311eaad35SDavid van Moolenbroek static void
process(struct entry * ep)54411eaad35SDavid van Moolenbroek process(struct entry *ep)
54511eaad35SDavid van Moolenbroek {
54611eaad35SDavid van Moolenbroek struct stat st;
54711eaad35SDavid van Moolenbroek time_t touched;
54811eaad35SDavid van Moolenbroek int max;
54911eaad35SDavid van Moolenbroek
55011eaad35SDavid van Moolenbroek if ((max = strlen(ep->name)) > maxname)
55111eaad35SDavid van Moolenbroek maxname = max;
55211eaad35SDavid van Moolenbroek if ((max = strlen(ep->line)) > maxline)
55311eaad35SDavid van Moolenbroek maxline = max;
55411eaad35SDavid van Moolenbroek if ((max = strlen(ep->host)) > maxhost)
55511eaad35SDavid van Moolenbroek maxhost = max;
55611eaad35SDavid van Moolenbroek
55711eaad35SDavid van Moolenbroek ep->tdev = 0;
55811eaad35SDavid van Moolenbroek ep->idle = (time_t)-1;
55911eaad35SDavid van Moolenbroek
56011eaad35SDavid van Moolenbroek #ifdef SUPPORT_UTMP
56111eaad35SDavid van Moolenbroek /*
56211eaad35SDavid van Moolenbroek * Hack to recognize and correctly parse
56311eaad35SDavid van Moolenbroek * ut entry made by ftpd. The "tty" used
56411eaad35SDavid van Moolenbroek * by ftpd is not a real tty, just identifier in
56511eaad35SDavid van Moolenbroek * form ftpPID. Pid parsed from the "tty name"
56611eaad35SDavid van Moolenbroek * is used later to match corresponding process.
56711eaad35SDavid van Moolenbroek * NB: This is only used for utmp entries. For utmpx,
56811eaad35SDavid van Moolenbroek * we already have the pid.
56911eaad35SDavid van Moolenbroek */
57011eaad35SDavid van Moolenbroek if (ep->pid == 0 && strncmp(ep->line, "ftp", 3) == 0) {
57111eaad35SDavid van Moolenbroek ep->pid = strtol(ep->line + 3, NULL, 10);
57211eaad35SDavid van Moolenbroek return;
57311eaad35SDavid van Moolenbroek }
57411eaad35SDavid van Moolenbroek #endif
57511eaad35SDavid van Moolenbroek if (ttystat(ep->line, &st) == -1)
57611eaad35SDavid van Moolenbroek return;
57711eaad35SDavid van Moolenbroek
57811eaad35SDavid van Moolenbroek ep->tdev = st.st_rdev;
57911eaad35SDavid van Moolenbroek /*
58011eaad35SDavid van Moolenbroek * If this is the console device, attempt to ascertain
58111eaad35SDavid van Moolenbroek * the true console device dev_t.
58211eaad35SDavid van Moolenbroek */
58311eaad35SDavid van Moolenbroek if (ep->tdev == 0) {
58411eaad35SDavid van Moolenbroek int mib[2];
58511eaad35SDavid van Moolenbroek size_t size;
58611eaad35SDavid van Moolenbroek
58711eaad35SDavid van Moolenbroek mib[0] = CTL_KERN;
58811eaad35SDavid van Moolenbroek mib[1] = KERN_CONSDEV;
58911eaad35SDavid van Moolenbroek size = sizeof(dev_t);
59011eaad35SDavid van Moolenbroek (void) sysctl(mib, 2, &ep->tdev, &size, NULL, 0);
59111eaad35SDavid van Moolenbroek }
59211eaad35SDavid van Moolenbroek
59311eaad35SDavid van Moolenbroek touched = st.st_atime;
59411eaad35SDavid van Moolenbroek if (touched < ep->tv.tv_sec) {
59511eaad35SDavid van Moolenbroek /* tty untouched since before login */
59611eaad35SDavid van Moolenbroek touched = ep->tv.tv_sec;
59711eaad35SDavid van Moolenbroek }
59811eaad35SDavid van Moolenbroek if ((ep->idle = now - touched) < 0)
59911eaad35SDavid van Moolenbroek ep->idle = 0;
60011eaad35SDavid van Moolenbroek }
60111eaad35SDavid van Moolenbroek #endif
60211eaad35SDavid van Moolenbroek
60311eaad35SDavid van Moolenbroek static int
proc_compare_wrapper(const struct kinfo_proc2 * p1,const struct kinfo_proc2 * p2)60411eaad35SDavid van Moolenbroek proc_compare_wrapper(const struct kinfo_proc2 *p1,
60511eaad35SDavid van Moolenbroek const struct kinfo_proc2 *p2)
60611eaad35SDavid van Moolenbroek {
60711eaad35SDavid van Moolenbroek struct kinfo_lwp *l1, *l2;
60811eaad35SDavid van Moolenbroek int cnt;
60911eaad35SDavid van Moolenbroek
61011eaad35SDavid van Moolenbroek if (p1 == NULL)
61111eaad35SDavid van Moolenbroek return 1;
61211eaad35SDavid van Moolenbroek
61311eaad35SDavid van Moolenbroek l1 = kvm_getlwps(kd, p1->p_pid, 0, sizeof(*l1), &cnt);
61411eaad35SDavid van Moolenbroek if (l1 == NULL || cnt == 0)
61511eaad35SDavid van Moolenbroek return 1;
61611eaad35SDavid van Moolenbroek
61711eaad35SDavid van Moolenbroek l2 = kvm_getlwps(kd, p2->p_pid, 0, sizeof(*l1), &cnt);
61811eaad35SDavid van Moolenbroek if (l2 == NULL || cnt == 0)
61911eaad35SDavid van Moolenbroek return 0;
62011eaad35SDavid van Moolenbroek
62111eaad35SDavid van Moolenbroek return proc_compare(p1, l1, p2, l2);
62211eaad35SDavid van Moolenbroek }
62311eaad35SDavid van Moolenbroek
62411eaad35SDavid van Moolenbroek static void
fixhost(struct entry * ep)62511eaad35SDavid van Moolenbroek fixhost(struct entry *ep)
62611eaad35SDavid van Moolenbroek {
62711eaad35SDavid van Moolenbroek char host_buf[sizeof(ep->host)];
62811eaad35SDavid van Moolenbroek char *p, *x;
62911eaad35SDavid van Moolenbroek struct hostent *hp;
63011eaad35SDavid van Moolenbroek struct in_addr l;
63111eaad35SDavid van Moolenbroek
63211eaad35SDavid van Moolenbroek strlcpy(host_buf, *ep->host ? ep->host : "-", sizeof(host_buf));
63311eaad35SDavid van Moolenbroek p = host_buf;
63411eaad35SDavid van Moolenbroek
63511eaad35SDavid van Moolenbroek /*
63611eaad35SDavid van Moolenbroek * XXX: Historical behavior, ':' in hostname means X display number,
63711eaad35SDavid van Moolenbroek * IPv6 not handled.
63811eaad35SDavid van Moolenbroek */
63911eaad35SDavid van Moolenbroek for (x = p; x < &host_buf[sizeof(host_buf)]; x++)
64011eaad35SDavid van Moolenbroek if (*x == '\0' || *x == ':')
64111eaad35SDavid van Moolenbroek break;
64211eaad35SDavid van Moolenbroek if (x == p + sizeof(host_buf) || *x != ':')
64311eaad35SDavid van Moolenbroek x = NULL;
64411eaad35SDavid van Moolenbroek else
64511eaad35SDavid van Moolenbroek *x++ = '\0';
64611eaad35SDavid van Moolenbroek
64711eaad35SDavid van Moolenbroek if (!nflag && inet_aton(p, &l) &&
64811eaad35SDavid van Moolenbroek (hp = gethostbyaddr((char *)&l, sizeof(l), AF_INET))) {
64911eaad35SDavid van Moolenbroek if (domain[0] != '\0') {
65011eaad35SDavid van Moolenbroek p = hp->h_name;
65111eaad35SDavid van Moolenbroek p += strlen(hp->h_name);
65211eaad35SDavid van Moolenbroek p -= strlen(domain);
65311eaad35SDavid van Moolenbroek if (p > hp->h_name &&
65411eaad35SDavid van Moolenbroek strcasecmp(p, domain) == 0)
65511eaad35SDavid van Moolenbroek *p = '\0';
65611eaad35SDavid van Moolenbroek }
65711eaad35SDavid van Moolenbroek p = hp->h_name;
65811eaad35SDavid van Moolenbroek }
65911eaad35SDavid van Moolenbroek
66011eaad35SDavid van Moolenbroek if (x)
66111eaad35SDavid van Moolenbroek (void)snprintf(ep->host, sizeof(ep->host), "%s:%s", p, x);
66211eaad35SDavid van Moolenbroek else
66311eaad35SDavid van Moolenbroek
66411eaad35SDavid van Moolenbroek strlcpy(ep->host, p, sizeof(ep->host));
66511eaad35SDavid van Moolenbroek }
66611eaad35SDavid van Moolenbroek
66711eaad35SDavid van Moolenbroek static void
usage(int wcmd)66811eaad35SDavid van Moolenbroek usage(int wcmd)
66911eaad35SDavid van Moolenbroek {
67011eaad35SDavid van Moolenbroek
67111eaad35SDavid van Moolenbroek if (wcmd)
67211eaad35SDavid van Moolenbroek (void)fprintf(stderr,
67311eaad35SDavid van Moolenbroek "Usage: %s [-hinw] [-M core] [-N system] [user]\n",
67411eaad35SDavid van Moolenbroek getprogname());
67511eaad35SDavid van Moolenbroek else
67611eaad35SDavid van Moolenbroek (void)fprintf(stderr, "Usage: %s\n", getprogname());
67711eaad35SDavid van Moolenbroek exit(1);
67811eaad35SDavid van Moolenbroek }
679