Example #1
0
static void
process_utmp(void)
{
	struct utmpx *utx;

	while ((utx = getutxent()) != NULL) {
		if (((aflag || !bflag) && utx->ut_type == USER_PROCESS) ||
		    (bflag && utx->ut_type == BOOT_TIME))
			if (ttystat(utx->ut_line) == 0)
				row(utx);
	}
}
Example #2
0
static void
process_utmp(void)
{
	struct utmpx *utx;

	while ((utx = getutxent()) != NULL) {
		if (utx->ut_type != USER_PROCESS)
			continue;
		if (ttystat(utx->ut_line) != 0)
			continue;
		row(utx);
	}
}
Example #3
0
static void
process(struct entry *ep)
{
	struct stat *stp;
	time_t touched;
	int max;

	if ((max = strlen(ep->name)) > maxname)
		maxname = max;
	if ((max = strlen(ep->line)) > maxline)
		maxline = max;
	if ((max = strlen(ep->host)) > maxhost)
		maxhost = max;

	ep->tdev = 0;
	ep->idle = (time_t)-1;

	if (!(stp = ttystat(ep->line, maxline)))
		return;	/* corrupted record */

	ep->tdev = stp->st_rdev;
#ifdef CPU_CONSDEV
	/*
	 * If this is the console device, attempt to ascertain
	 * the true console device dev_t.
	 */
	if (ep->tdev == 0) {
		int mib[2];
		size_t size;

		mib[0] = CTL_MACHDEP;
		mib[1] = CPU_CONSDEV;
		size = sizeof(dev_t);
		(void)sysctl(mib, 2, &ep->tdev, &size, NULL, 0);
	}
#endif

	touched = stp->st_atime;
	if (touched < ep->tv.tv_sec) {
		/* tty untouched since before login */
		touched = ep->tv.tv_sec;
	}
	if ((ep->idle = now - touched) < 0)
		ep->idle = 0;
}
Example #4
0
File: w.c Project: UNGLinux/Obase
int
main(int argc, char *argv[])
{
	extern char *__progname;
	struct kinfo_proc *kp;
	struct hostent *hp;
	struct stat *stp;
	FILE *ut;
	struct in_addr addr;
	int ch, i, nentries, nusers, wcmd;
	char *memf, *nlistf, *p, *x;
	char buf[MAXHOSTNAMELEN], errbuf[_POSIX2_LINE_MAX];

	/* Are we w(1) or uptime(1)? */
	p = __progname;
	if (*p == '-')
		p++;
	if (p[0] == 'w' && p[1] == '\0') {
		wcmd = 1;
		p = "hiflM:N:asuw";
	} else if (!strcmp(p, "uptime")) {
		wcmd = 0;
		p = "";
	} else
		errx(1,
		 "this program should be invoked only as \"w\" or \"uptime\"");

	memf = nlistf = NULL;
	while ((ch = getopt(argc, argv, p)) != -1)
		switch (ch) {
		case 'h':
			header = 0;
			break;
		case 'i':
			sortidle = 1;
			break;
		case 'M':
			header = 0;
			memf = optarg;
			break;
		case 'N':
			nlistf = optarg;
			break;
		case 'a':
			nflag = 0;
			break;
		case 'f': case 'l': case 's': case 'u': case 'w':
			warnx("[-flsuw] no longer supported");
			/* FALLTHROUGH */
		case '?':
		default:
			usage(wcmd);
		}
	argc -= optind;
	argv += optind;

	if (nlistf == NULL && memf == NULL) {
		if ((kd = kvm_openfiles(nlistf, memf, NULL, KVM_NO_FILES,
		    errbuf)) == NULL)
			errx(1, "%s", errbuf);
	} else {
		if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == NULL)
			errx(1, "%s", errbuf);
	}

	(void)time(&now);
	if ((ut = fopen(_PATH_UTMP, "r")) == NULL)
		err(1, "%s", _PATH_UTMP);

	if (*argv)
		sel_user = *argv;

	for (nusers = 0; fread(&utmp, sizeof(utmp), 1, ut);) {
		if (utmp.ut_name[0] == '\0')
			continue;
		++nusers;
		if (wcmd == 0 || (sel_user &&
		    strncmp(utmp.ut_name, sel_user, UT_NAMESIZE) != 0))
			continue;
		if ((ep = calloc(1, sizeof(*ep))) == NULL)
			err(1, NULL);
		*nextp = ep;
		nextp = &(ep->next);
		memcpy(&(ep->utmp), &utmp, sizeof(utmp));
		if (!(stp = ttystat(ep->utmp.ut_line)))
			continue;
		ep->tdev = stp->st_rdev;

		/*
		 * If this is the console device, attempt to ascertain
		 * the true console device dev_t.
		 */
		if (ep->tdev == 0) {
			int mib[2];
			size_t size;

			mib[0] = CTL_KERN;
			mib[1] = KERN_CONSDEV;
			size = sizeof(dev_t);
			(void) sysctl(mib, 2, &ep->tdev, &size, NULL, 0);
		}

		if ((ep->idle = now - stp->st_atime) < 0)
			ep->idle = 0;
	}
	(void)fclose(ut);

	if (header || wcmd == 0) {
		pr_header(&now, nusers);
		if (wcmd == 0)
			exit (0);
	}

#define HEADER	"USER    TTY FROM              LOGIN@  IDLE WHAT"
#define WUSED	(sizeof(HEADER) - sizeof("WHAT"))
	(void)puts(HEADER);

	kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(*kp), &nentries);
	if (kp == NULL)
		errx(1, "%s", kvm_geterr(kd));
	for (i = 0; i < nentries; i++, kp++) {
		if (kp->p_stat == SIDL || kp->p_stat == SZOMB)
			continue;
		for (ep = ehead; ep != NULL; ep = ep->next) {
			/* ftp is a special case. */
			if (strncmp(ep->utmp.ut_line, "ftp", 3) == 0) {
				char pidstr[UT_LINESIZE-2];
				pid_t fp;

				(void)strncpy(pidstr, &ep->utmp.ut_line[3],
				    sizeof(pidstr) - 1);
				pidstr[sizeof(pidstr) - 1] = '\0';
				fp = (pid_t)strtol(pidstr, NULL, 10);
				if (kp->p_pid == fp) {
					ep->kp = kp;
					break;
				}
			} else if (ep->tdev == kp->p_tdev &&
			    kp->p__pgid == kp->p_tpgid) {
				/*
				 * Proc is in foreground of this terminal
				 */
				if (proc_compare(ep->kp, kp))
					ep->kp = kp;
				break;
			}
		}
	}
	if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 &&
	    ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 &&
	    ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0)
		ttywidth = 79;
	else
		ttywidth = ws.ws_col - 1;
	argwidth = ttywidth - WUSED;
	if (argwidth < 4)
		argwidth = 8;
	/* sort by idle time */
	if (sortidle && ehead != NULL) {
		struct entry *from = ehead, *save;

		ehead = NULL;
		while (from != NULL) {
			for (nextp = &ehead;
			    (*nextp) && from->idle >= (*nextp)->idle;
			    nextp = &(*nextp)->next)
				continue;
			save = from;
			from = from->next;
			save->next = *nextp;
			*nextp = save;
		}
	}

	if (!nflag) {
		if (gethostname(domain, sizeof(domain)) < 0 ||
		    (p = strchr(domain, '.')) == 0)
			domain[0] = '\0';
		else {
			domain[sizeof(domain) - 1] = '\0';
			memmove(domain, p, strlen(p) + 1);
		}
	}

	for (ep = ehead; ep != NULL; ep = ep->next) {
		p = *ep->utmp.ut_host ? ep->utmp.ut_host : "-";
		for (x = NULL, i = 0; p[i] != '\0' && i < UT_HOSTSIZE; i++)
			if (p[i] == ':') {
				x = &p[i];
				*x++ = '\0';
				break;
			}
		if (!nflag && inet_aton(p, &addr) &&
		    (hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET))) {
			if (domain[0] != '\0') {
				p = hp->h_name;
				p += strlen(hp->h_name);
				p -= strlen(domain);
				if (p > hp->h_name &&
				    strcasecmp(p, domain) == 0)
					*p = '\0';
			}
			p = hp->h_name;
		}
		if (x) {
			(void)snprintf(buf, sizeof(buf), "%s:%.*s", p,
			    (int)(ep->utmp.ut_host + UT_HOSTSIZE - x), x);
			p = buf;
		}
		(void)printf("%-*.*s %-2.2s %-*.*s ",
		    NAME_WIDTH, UT_NAMESIZE, ep->utmp.ut_name,
		    strncmp(ep->utmp.ut_line, "tty", 3) ?
		    ep->utmp.ut_line : ep->utmp.ut_line + 3,
		    HOST_WIDTH, HOST_WIDTH, *p ? p : "-");
		pr_attime(&ep->utmp.ut_time, &now);
		pr_idle(ep->idle);
		pr_args(ep->kp);
		printf("\n");
	}
	exit(0);
}
Example #5
0
int
main(int argc, char *argv[])
{
	struct kinfo_proc *kp;
	struct kinfo_proc *dkp;
	struct stat *stp;
	time_t touched;
	int ch, i, nentries, nusers, wcmd, longidle, longattime, dropgid;
	const char *memf, *nlistf, *p;
	char *x_suffix;
	char buf[MAXHOSTNAMELEN], errbuf[_POSIX2_LINE_MAX];
	char fn[MAXHOSTNAMELEN];
	char *dot;

	(void)setlocale(LC_ALL, "");
	use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0');
	use_comma = (*nl_langinfo(RADIXCHAR) != ',');

	/* Are we w(1) or uptime(1)? */
	if (this_is_uptime(argv[0]) == 0) {
		wcmd = 0;
		p = "";
	} else {
		wcmd = 1;
		p = "dhiflM:N:nsuw";
	}

	dropgid = 0;
	memf = _PATH_DEVNULL;
	nlistf = NULL;
	while ((ch = getopt(argc, argv, p)) != -1)
		switch (ch) {
		case 'd':
			dflag = 1;
			break;
		case 'h':
			header = 0;
			break;
		case 'i':
			sortidle = 1;
			break;
		case 'M':
			header = 0;
			memf = optarg;
			dropgid = 1;
			break;
		case 'N':
			nlistf = optarg;
			dropgid = 1;
			break;
		case 'n':
			nflag = 1;
			break;
		case 'f': case 'l': case 's': case 'u': case 'w':
			warnx("[-flsuw] no longer supported");
			/* FALLTHROUGH */
		case '?':
		default:
			usage(wcmd);
		}
	argc -= optind;
	argv += optind;

	if (!(_res.options & RES_INIT))
		res_init();
	_res.retrans = 2;	/* resolver timeout to 2 seconds per try */
	_res.retry = 1;		/* only try once.. */

	/*
	 * Discard setgid privileges if not the running kernel so that bad
	 * guys can't print interesting stuff from kernel memory.
	 */
	if (dropgid)
		setgid(getgid());

	if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == NULL)
		errx(1, "%s", errbuf);

	(void)time(&now);

	if (*argv)
		sel_users = argv;

	setutxent();
	for (nusers = 0; (utmp = getutxent()) != NULL;) {
		if (utmp->ut_type != USER_PROCESS)
			continue;
		if (!(stp = ttystat(utmp->ut_line)))
			continue;	/* corrupted record */
		++nusers;
		if (wcmd == 0)
			continue;
		if (sel_users) {
			int usermatch;
			char **user;

			usermatch = 0;
			for (user = sel_users; !usermatch && *user; user++)
				if (!strcmp(utmp->ut_user, *user))
					usermatch = 1;
			if (!usermatch)
				continue;
		}
		if ((ep = calloc(1, sizeof(struct entry))) == NULL)
			errx(1, "calloc");
		*nextp = ep;
		nextp = &ep->next;
		memmove(&ep->utmp, utmp, sizeof *utmp);
		ep->tdev = stp->st_rdev;
		/*
		 * If this is the console device, attempt to ascertain
		 * the true console device dev_t.
		 */
		if (ep->tdev == 0) {
			size_t size;

			size = sizeof(dev_t);
			(void)sysctlbyname("machdep.consdev", &ep->tdev, &size, NULL, 0);
		}
		touched = stp->st_atime;
		if (touched < ep->utmp.ut_tv.tv_sec) {
			/* tty untouched since before login */
			touched = ep->utmp.ut_tv.tv_sec;
		}
		if ((ep->idle = now - touched) < 0)
			ep->idle = 0;
	}
	endutxent();

	if (header || wcmd == 0) {
		pr_header(&now, nusers);
		if (wcmd == 0) {
			(void)kvm_close(kd);
			exit(0);
		}

#define HEADER_USER		"USER"
#define HEADER_TTY		"TTY"
#define HEADER_FROM		"FROM"
#define HEADER_LOGIN_IDLE	"LOGIN@  IDLE "
#define HEADER_WHAT		"WHAT\n"
#define WUSED  (W_DISPUSERSIZE + W_DISPLINESIZE + W_DISPHOSTSIZE + \
		sizeof(HEADER_LOGIN_IDLE) + 3)	/* header width incl. spaces */ 
		(void)printf("%-*.*s %-*.*s %-*.*s  %s", 
				W_DISPUSERSIZE, W_DISPUSERSIZE, HEADER_USER,
				W_DISPLINESIZE, W_DISPLINESIZE, HEADER_TTY,
				W_DISPHOSTSIZE, W_DISPHOSTSIZE, HEADER_FROM,
				HEADER_LOGIN_IDLE HEADER_WHAT);
	}

	if ((kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nentries)) == NULL)
		err(1, "%s", kvm_geterr(kd));
	for (i = 0; i < nentries; i++, kp++) {
		if (kp->ki_stat == SIDL || kp->ki_stat == SZOMB ||
		    kp->ki_tdev == NODEV)
			continue;
		for (ep = ehead; ep != NULL; ep = ep->next) {
			if (ep->tdev == kp->ki_tdev) {
				/*
				 * proc is associated with this terminal
				 */
				if (ep->kp == NULL && kp->ki_pgid == kp->ki_tpgid) {
					/*
					 * Proc is 'most interesting'
					 */
					if (proc_compare(ep->kp, kp))
						ep->kp = kp;
				}
				/*
				 * Proc debug option info; add to debug
				 * list using kinfo_proc ki_spare[0]
				 * as next pointer; ptr to ptr avoids the
				 * ptr = long assumption.
				 */
				dkp = ep->dkp;
				ep->dkp = kp;
				debugproc(kp) = dkp;
			}
		}
	}
	if ((ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1 &&
	     ioctl(STDERR_FILENO, TIOCGWINSZ, &ws) == -1 &&
	     ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) == -1) || ws.ws_col == 0)
	       ttywidth = 79;
        else
	       ttywidth = ws.ws_col - 1;
	argwidth = ttywidth - WUSED;
	if (argwidth < 4)
		argwidth = 8;
	for (ep = ehead; ep != NULL; ep = ep->next) {
		if (ep->kp == NULL) {
			ep->args = strdup("-");
			continue;
		}
		ep->args = fmt_argv(kvm_getargv(kd, ep->kp, argwidth),
		    ep->kp->ki_comm, NULL, MAXCOMLEN);
		if (ep->args == NULL)
			err(1, NULL);
	}
	/* sort by idle time */
	if (sortidle && ehead != NULL) {
		struct entry *from, *save;

		from = ehead;
		ehead = NULL;
		while (from != NULL) {
			for (nextp = &ehead;
			    (*nextp) && from->idle >= (*nextp)->idle;
			    nextp = &(*nextp)->next)
				continue;
			save = from;
			from = from->next;
			save->next = *nextp;
			*nextp = save;
		}
	}

	for (ep = ehead; ep != NULL; ep = ep->next) {
		struct addrinfo hints, *res;
		struct sockaddr_storage ss;
		struct sockaddr *sa = (struct sockaddr *)&ss;
		struct sockaddr_in *lsin = (struct sockaddr_in *)&ss;
		struct sockaddr_in6 *lsin6 = (struct sockaddr_in6 *)&ss;
		time_t t;
		int isaddr;

		p = *ep->utmp.ut_host ? ep->utmp.ut_host : "-";
		if ((x_suffix = strrchr(p, ':')) != NULL) {
			if ((dot = strchr(x_suffix, '.')) != NULL &&
			    strchr(dot+1, '.') == NULL)
				*x_suffix++ = '\0';
			else
				x_suffix = NULL;
		}

		isaddr = 0;
		memset(&ss, '\0', sizeof(ss));
		if (inet_pton(AF_INET6, p, &lsin6->sin6_addr) == 1) {
			lsin6->sin6_len = sizeof(*lsin6);
			lsin6->sin6_family = AF_INET6;
			isaddr = 1;
		} else if (inet_pton(AF_INET, p, &lsin->sin_addr) == 1) {
			lsin->sin_len = sizeof(*lsin);
			lsin->sin_family = AF_INET;
			isaddr = 1;
		}
		if (!nflag) {
			/* Attempt to change an IP address into a name */
			if (isaddr && realhostname_sa(fn, sizeof(fn), sa,
			    sa->sa_len) == HOSTNAME_FOUND)
				p = fn;
		} else if (!isaddr) {
			/*
			 * If a host has only one A/AAAA RR, change a
			 * name into an IP address
			 */
			memset(&hints, 0, sizeof(hints));
			hints.ai_flags = AI_PASSIVE;
			hints.ai_family = AF_UNSPEC;
			hints.ai_socktype = SOCK_STREAM;
			if (getaddrinfo(p, NULL, &hints, &res) == 0) {
				if (res->ai_next == NULL &&
				    getnameinfo(res->ai_addr, res->ai_addrlen,
					fn, sizeof(fn), NULL, 0,
					NI_NUMERICHOST) == 0)
					p = fn;
				freeaddrinfo(res);
			}
		}

		if (x_suffix) {
			(void)snprintf(buf, sizeof(buf), "%s:%s", p, x_suffix);
			p = buf;
		}
		if (dflag) {
			for (dkp = ep->dkp; dkp != NULL; dkp = debugproc(dkp)) {
				const char *ptr;

				ptr = fmt_argv(kvm_getargv(kd, dkp, argwidth),
				    dkp->ki_comm, NULL, MAXCOMLEN);
				if (ptr == NULL)
					ptr = "-";
				(void)printf("\t\t%-9d %s\n",
				    dkp->ki_pid, ptr);
			}
		}
		(void)printf("%-*.*s %-*.*s %-*.*s ",
		    W_DISPUSERSIZE, W_DISPUSERSIZE, ep->utmp.ut_user,
		    W_DISPLINESIZE, W_DISPLINESIZE,
		    *ep->utmp.ut_line ?
		    (strncmp(ep->utmp.ut_line, "tty", 3) &&
		    strncmp(ep->utmp.ut_line, "cua", 3) ?
		    ep->utmp.ut_line : ep->utmp.ut_line + 3) : "-",
		    W_DISPHOSTSIZE, W_DISPHOSTSIZE, *p ? p : "-");
		t = ep->utmp.ut_tv.tv_sec;
		longattime = pr_attime(&t, &now);
		longidle = pr_idle(ep->idle);
		(void)printf("%.*s\n", argwidth - longidle - longattime,
		    ep->args);
	}
	(void)kvm_close(kd);
	exit(0);
}
Example #6
0
int
main(int argc, char *argv[])
{
	struct iovec iov;
	struct utmpx *utmp;
	int ch;
	int ingroup;
	struct wallgroup *g;
	struct group *grp;
	char **np;
	const char *p;
	struct passwd *pw;

	(void)setlocale(LC_CTYPE, "");

	while ((ch = getopt(argc, argv, "g:n")) != -1)
		switch (ch) {
		case 'n':
			/* undoc option for shutdown: suppress banner */
			if (geteuid() == 0)
				nobanner = 1;
			break;
		case 'g':
			g = (struct wallgroup *)malloc(sizeof *g);
			g->next = grouplist;
			g->name = optarg;
			g->gid = -1;
			grouplist = g;
			break;
		case '?':
		default:
			usage();
		}
	argc -= optind;
	argv += optind;
	if (argc > 1)
		usage();

	for (g = grouplist; g; g = g->next) {
		grp = getgrnam(g->name);
		if (grp != NULL)
			g->gid = grp->gr_gid;
		else
			warnx("%s: no such group", g->name);
	}

	makemsg(*argv);

	iov.iov_base = mbuf;
	iov.iov_len = mbufsize;
	/* NOSTRICT */
	while ((utmp = getutxent()) != NULL) {
		if (utmp->ut_type != USER_PROCESS)
			continue;
		if (ttystat(utmp->ut_line) != 0)
			continue;
		if (grouplist) {
			ingroup = 0;
			pw = getpwnam(utmp->ut_user);
			if (!pw)
				continue;
			for (g = grouplist; g && ingroup == 0; g = g->next) {
				if (g->gid == (gid_t)-1)
					continue;
				if (g->gid == pw->pw_gid)
					ingroup = 1;
				else if ((grp = getgrgid(g->gid)) != NULL) {
					for (np = grp->gr_mem; *np; np++) {
						if (strcmp(*np, utmp->ut_user) == 0) {
							ingroup = 1;
							break;
						}
					}
				}
			}
			if (ingroup == 0)
				continue;
		}
		if ((p = ttymsg(&iov, 1, utmp->ut_line, 60*5)) != NULL)
			warnx("%s", p);
	}
	exit(0);
}
Example #7
0
int
main(int argc, char *argv[])
{
	struct iovec iov;
#ifdef __APPLE__
	// rdar://problem/4433603
	struct utmpx *u;
#else
	struct utmp utmp;
#endif
	int ch;
	int ingroup;
#ifndef __APPLE__
	FILE *fp;
#endif
	struct wallgroup *g;
	struct group *grp;
	char **np;
	const char *p;
	struct passwd *pw;
#ifdef __APPLE__
	char line[sizeof(u->ut_line) + 1];
	char username[sizeof(u->ut_user) + 1];
#else
	char line[sizeof(utmp.ut_line) + 1];
	char username[sizeof(utmp.ut_name) + 1];
#endif

	(void)setlocale(LC_CTYPE, "");

	while ((ch = getopt(argc, argv, "g:n")) != -1)
		switch (ch) {
		case 'n':
			/* undoc option for shutdown: suppress banner */
			if (geteuid() == 0)
				nobanner = 1;
			break;
		case 'g':
			g = (struct wallgroup *)malloc(sizeof *g);
			g->next = grouplist;
			g->name = optarg;
			g->gid = -1;
			grouplist = g;
			break;
		case '?':
		default:
			usage();
		}
	argc -= optind;
	argv += optind;
	if (argc > 1)
		usage();

	for (g = grouplist; g; g = g->next) {
		grp = getgrnam(g->name);
		if (grp != NULL)
			g->gid = grp->gr_gid;
		else
			warnx("%s: no such group", g->name);
	}

	makemsg(*argv);

#ifdef __APPLE__
	setutxent();
#else
	if (!(fp = fopen(_PATH_UTMP, "r")))
		err(1, "cannot read %s", _PATH_UTMP);
#endif
	iov.iov_base = mbuf;
	iov.iov_len = mbufsize;
	/* NOSTRICT */
#ifdef __APPLE__
	while ((u = getutxent()) != NULL) {
		if (!u->ut_user[0] || u->ut_type != USER_PROCESS)
			continue;
#else
	while (fread((char *)&utmp, sizeof(utmp), 1, fp) == 1) {
		if (!utmp.ut_name[0])
			continue;
		if (ttystat(utmp.ut_line, UT_LINESIZE) != 0)
			continue;
#endif
		if (grouplist) {
			ingroup = 0;
#ifdef __APPLE__
			strlcpy(username, u->ut_user, sizeof(username));
#else
			strlcpy(username, utmp.ut_name, sizeof(utmp.ut_name));
#endif
			pw = getpwnam(username);
			if (!pw)
				continue;
			for (g = grouplist; g && ingroup == 0; g = g->next) {
				if (g->gid == (gid_t)-1)
					continue;
				if (g->gid == pw->pw_gid)
					ingroup = 1;
				else if ((grp = getgrgid(g->gid)) != NULL) {
					for (np = grp->gr_mem; *np; np++) {
						if (strcmp(*np, username) == 0) {
							ingroup = 1;
							break;
						}
					}
				}
			}
			if (ingroup == 0)
				continue;
		}
#ifdef __APPLE__
		strlcpy(line, u->ut_line, sizeof(line));
#else
		strncpy(line, utmp.ut_line, sizeof(utmp.ut_line));
		line[sizeof(utmp.ut_line)] = '\0';
#endif
		if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL)
			warnx("%s", p);
	}
	exit(0);
}

static void
usage()
{
	(void)fprintf(stderr, "usage: wall [-g group] [file]\n");
	exit(1);
}