diff --git a/usr.bin/netstat/netisr.c b/usr.bin/netstat/netisr.c index bcb9351353c5..a3eb976d84bf 100644 --- a/usr.bin/netstat/netisr.c +++ b/usr.bin/netstat/netisr.c @@ -1,509 +1,506 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2010-2011 Juniper Networks, Inc. * All rights reserved. * * This software was developed by Robert N. M. Watson under contract * to Juniper Networks, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #include #include #include #include #define _WANT_NETISR_INTERNAL #include #include #include #include #include #include #include #include #include #include "netstat.h" #include "nl_defs.h" /* * Print statistics for the kernel netisr subsystem. */ static u_int bindthreads; static u_int maxthreads; static u_int numthreads; static u_int defaultqlimit; static u_int maxqlimit; static char dispatch_policy[20]; static struct sysctl_netisr_proto *proto_array; static u_int proto_array_len; static struct sysctl_netisr_workstream *workstream_array; static u_int workstream_array_len; static struct sysctl_netisr_work *work_array; static u_int work_array_len; static u_int *nws_array; static u_int maxprot; static void netisr_dispatch_policy_to_string(u_int policy, char *buf, size_t buflen) { const char *str; switch (policy) { case NETISR_DISPATCH_DEFAULT: str = "default"; break; case NETISR_DISPATCH_DEFERRED: str = "deferred"; break; case NETISR_DISPATCH_HYBRID: str = "hybrid"; break; case NETISR_DISPATCH_DIRECT: str = "direct"; break; default: str = "unknown"; break; } snprintf(buf, buflen, "%s", str); } /* * Load a nul-terminated string from KVM up to 'limit', guarantee that the * string in local memory is nul-terminated. */ static void netisr_load_kvm_string(uintptr_t addr, char *dest, u_int limit) { u_int i; for (i = 0; i < limit; i++) { if (kread(addr + i, &dest[i], sizeof(dest[i])) != 0) xo_errx(-1, "%s: kread()", __func__); if (dest[i] == '\0') break; } dest[limit - 1] = '\0'; } static const char * netisr_proto2name(u_int proto) { u_int i; for (i = 0; i < proto_array_len; i++) { if (proto_array[i].snp_proto == proto) return (proto_array[i].snp_name); } return ("unknown"); } static int netisr_protoispresent(u_int proto) { u_int i; for (i = 0; i < proto_array_len; i++) { if (proto_array[i].snp_proto == proto) return (1); } return (0); } static void netisr_load_kvm_config(void) { u_int tmp; kread(nl[N_NETISR_BINDTHREADS].n_value, &bindthreads, sizeof(u_int)); kread(nl[N_NETISR_MAXTHREADS].n_value, &maxthreads, sizeof(u_int)); kread(nl[N_NWS_COUNT].n_value, &numthreads, sizeof(u_int)); kread(nl[N_NETISR_DEFAULTQLIMIT].n_value, &defaultqlimit, sizeof(u_int)); kread(nl[N_NETISR_MAXQLIMIT].n_value, &maxqlimit, sizeof(u_int)); kread(nl[N_NETISR_DISPATCH_POLICY].n_value, &tmp, sizeof(u_int)); netisr_dispatch_policy_to_string(tmp, dispatch_policy, sizeof(dispatch_policy)); } static void netisr_load_sysctl_uint(const char *name, u_int *p) { size_t retlen; retlen = sizeof(u_int); if (sysctlbyname(name, p, &retlen, NULL, 0) < 0) xo_err(-1, "%s", name); if (retlen != sizeof(u_int)) xo_errx(-1, "%s: invalid len %ju", name, (uintmax_t)retlen); } static void netisr_load_sysctl_string(const char *name, char *p, size_t len) { size_t retlen; retlen = len; if (sysctlbyname(name, p, &retlen, NULL, 0) < 0) xo_err(-1, "%s", name); p[len - 1] = '\0'; } static void netisr_load_sysctl_config(void) { netisr_load_sysctl_uint("net.isr.bindthreads", &bindthreads); netisr_load_sysctl_uint("net.isr.maxthreads", &maxthreads); netisr_load_sysctl_uint("net.isr.numthreads", &numthreads); netisr_load_sysctl_uint("net.isr.defaultqlimit", &defaultqlimit); netisr_load_sysctl_uint("net.isr.maxqlimit", &maxqlimit); netisr_load_sysctl_string("net.isr.dispatch", dispatch_policy, sizeof(dispatch_policy)); } static void netisr_load_kvm_proto(void) { struct netisr_proto *np_array, *npp; u_int i, protocount; struct sysctl_netisr_proto *snpp; size_t len; /* * Kernel compile-time and user compile-time definitions of * NETISR_MAXPROT must match, as we use that to size work arrays. */ kread(nl[N_NETISR_MAXPROT].n_value, &maxprot, sizeof(u_int)); if (maxprot != NETISR_MAXPROT) xo_errx(-1, "%s: NETISR_MAXPROT mismatch", __func__); len = maxprot * sizeof(*np_array); np_array = malloc(len); if (np_array == NULL) xo_err(-1, "%s: malloc", __func__); if (kread(nl[N_NETISR_PROTO].n_value, np_array, len) != 0) xo_errx(-1, "%s: kread(_netisr_proto)", __func__); /* * Size and allocate memory to hold only live protocols. */ protocount = 0; for (i = 0; i < maxprot; i++) { if (np_array[i].np_name == NULL) continue; protocount++; } proto_array = calloc(protocount, sizeof(*proto_array)); if (proto_array == NULL) err(-1, "malloc"); protocount = 0; for (i = 0; i < maxprot; i++) { npp = &np_array[i]; if (npp->np_name == NULL) continue; snpp = &proto_array[protocount]; snpp->snp_version = sizeof(*snpp); netisr_load_kvm_string((uintptr_t)npp->np_name, snpp->snp_name, sizeof(snpp->snp_name)); snpp->snp_proto = i; snpp->snp_qlimit = npp->np_qlimit; snpp->snp_policy = npp->np_policy; snpp->snp_dispatch = npp->np_dispatch; if (npp->np_m2flow != NULL) snpp->snp_flags |= NETISR_SNP_FLAGS_M2FLOW; if (npp->np_m2cpuid != NULL) snpp->snp_flags |= NETISR_SNP_FLAGS_M2CPUID; if (npp->np_drainedcpu != NULL) snpp->snp_flags |= NETISR_SNP_FLAGS_DRAINEDCPU; protocount++; } proto_array_len = protocount; free(np_array); } static void netisr_load_sysctl_proto(void) { size_t len; if (sysctlbyname("net.isr.proto", NULL, &len, NULL, 0) < 0) xo_err(-1, "net.isr.proto: query len"); if (len % sizeof(*proto_array) != 0) xo_errx(-1, "net.isr.proto: invalid len"); proto_array = malloc(len); if (proto_array == NULL) xo_err(-1, "malloc"); if (sysctlbyname("net.isr.proto", proto_array, &len, NULL, 0) < 0) xo_err(-1, "net.isr.proto: query data"); if (len % sizeof(*proto_array) != 0) xo_errx(-1, "net.isr.proto: invalid len"); proto_array_len = len / sizeof(*proto_array); if (proto_array_len < 1) xo_errx(-1, "net.isr.proto: no data"); if (proto_array[0].snp_version != sizeof(proto_array[0])) xo_errx(-1, "net.isr.proto: invalid version"); } static void netisr_load_kvm_workstream(void) { struct netisr_workstream nws; struct sysctl_netisr_workstream *snwsp; struct sysctl_netisr_work *snwp; struct netisr_work *nwp; u_int counter, cpuid, proto, wsid; size_t len; len = numthreads * sizeof(*nws_array); nws_array = malloc(len); if (nws_array == NULL) xo_err(-1, "malloc"); if (kread(nl[N_NWS_ARRAY].n_value, nws_array, len) != 0) xo_errx(-1, "%s: kread(_nws_array)", __func__); workstream_array = calloc(numthreads, sizeof(*workstream_array)); if (workstream_array == NULL) xo_err(-1, "calloc"); workstream_array_len = numthreads; work_array = calloc(numthreads * proto_array_len, sizeof(*work_array)); if (work_array == NULL) xo_err(-1, "calloc"); counter = 0; for (wsid = 0; wsid < numthreads; wsid++) { cpuid = nws_array[wsid]; kset_dpcpu(cpuid); if (kread(nl[N_NWS].n_value, &nws, sizeof(nws)) != 0) xo_errx(-1, "%s: kread(nw)", __func__); snwsp = &workstream_array[wsid]; snwsp->snws_version = sizeof(*snwsp); snwsp->snws_wsid = cpuid; snwsp->snws_cpu = cpuid; if (nws.nws_intr_event != NULL) snwsp->snws_flags |= NETISR_SNWS_FLAGS_INTR; /* * Extract the CPU's per-protocol work information. */ xo_emit("counting to maxprot: {:maxprot/%u}\n", maxprot); for (proto = 0; proto < maxprot; proto++) { if (!netisr_protoispresent(proto)) continue; nwp = &nws.nws_work[proto]; snwp = &work_array[counter]; snwp->snw_version = sizeof(*snwp); snwp->snw_wsid = cpuid; snwp->snw_proto = proto; snwp->snw_len = nwp->nw_len; snwp->snw_watermark = nwp->nw_watermark; snwp->snw_dispatched = nwp->nw_dispatched; snwp->snw_hybrid_dispatched = nwp->nw_hybrid_dispatched; snwp->snw_qdrops = nwp->nw_qdrops; snwp->snw_queued = nwp->nw_queued; snwp->snw_handled = nwp->nw_handled; counter++; } } work_array_len = counter; } static void netisr_load_sysctl_workstream(void) { size_t len; if (sysctlbyname("net.isr.workstream", NULL, &len, NULL, 0) < 0) xo_err(-1, "net.isr.workstream: query len"); if (len % sizeof(*workstream_array) != 0) xo_errx(-1, "net.isr.workstream: invalid len"); workstream_array = malloc(len); if (workstream_array == NULL) xo_err(-1, "malloc"); if (sysctlbyname("net.isr.workstream", workstream_array, &len, NULL, 0) < 0) xo_err(-1, "net.isr.workstream: query data"); if (len % sizeof(*workstream_array) != 0) xo_errx(-1, "net.isr.workstream: invalid len"); workstream_array_len = len / sizeof(*workstream_array); if (workstream_array_len < 1) xo_errx(-1, "net.isr.workstream: no data"); if (workstream_array[0].snws_version != sizeof(workstream_array[0])) xo_errx(-1, "net.isr.workstream: invalid version"); } static void netisr_load_sysctl_work(void) { size_t len; if (sysctlbyname("net.isr.work", NULL, &len, NULL, 0) < 0) xo_err(-1, "net.isr.work: query len"); if (len % sizeof(*work_array) != 0) xo_errx(-1, "net.isr.work: invalid len"); work_array = malloc(len); if (work_array == NULL) xo_err(-1, "malloc"); if (sysctlbyname("net.isr.work", work_array, &len, NULL, 0) < 0) xo_err(-1, "net.isr.work: query data"); if (len % sizeof(*work_array) != 0) xo_errx(-1, "net.isr.work: invalid len"); work_array_len = len / sizeof(*work_array); if (work_array_len < 1) xo_errx(-1, "net.isr.work: no data"); if (work_array[0].snw_version != sizeof(work_array[0])) xo_errx(-1, "net.isr.work: invalid version"); } static void netisr_print_proto(struct sysctl_netisr_proto *snpp) { char tmp[20]; xo_emit("{[:-6}{k:name/%s}{]:}", snpp->snp_name); xo_emit(" {:protocol/%5u}", snpp->snp_proto); xo_emit(" {:queue-limit/%6u}", snpp->snp_qlimit); xo_emit(" {:policy-type/%6s}", (snpp->snp_policy == NETISR_POLICY_SOURCE) ? "source" : (snpp->snp_policy == NETISR_POLICY_FLOW) ? "flow" : (snpp->snp_policy == NETISR_POLICY_CPU) ? "cpu" : "-"); netisr_dispatch_policy_to_string(snpp->snp_dispatch, tmp, sizeof(tmp)); xo_emit(" {:policy/%8s}", tmp); xo_emit(" {:flags/%s%s%s}\n", (snpp->snp_flags & NETISR_SNP_FLAGS_M2CPUID) ? "C" : "-", (snpp->snp_flags & NETISR_SNP_FLAGS_DRAINEDCPU) ? "D" : "-", (snpp->snp_flags & NETISR_SNP_FLAGS_M2FLOW) ? "F" : "-"); } static void netisr_print_workstream(struct sysctl_netisr_workstream *snwsp) { struct sysctl_netisr_work *snwp; u_int i; xo_open_list("work"); for (i = 0; i < work_array_len; i++) { snwp = &work_array[i]; if (snwp->snw_wsid != snwsp->snws_wsid) continue; xo_open_instance("work"); xo_emit("{t:workstream/%4u} ", snwsp->snws_wsid); xo_emit("{t:cpu/%3u} ", snwsp->snws_cpu); xo_emit("{P: }"); xo_emit("{t:name/%-6s}", netisr_proto2name(snwp->snw_proto)); xo_emit(" {t:length/%5u}", snwp->snw_len); xo_emit(" {t:watermark/%5u}", snwp->snw_watermark); xo_emit(" {t:dispatched/%8ju}", snwp->snw_dispatched); xo_emit(" {t:hybrid-dispatched/%8ju}", snwp->snw_hybrid_dispatched); xo_emit(" {t:queue-drops/%8ju}", snwp->snw_qdrops); xo_emit(" {t:queued/%8ju}", snwp->snw_queued); xo_emit(" {t:handled/%8ju}", snwp->snw_handled); xo_emit("\n"); xo_close_instance("work"); } xo_close_list("work"); } void netisr_stats(void) { struct sysctl_netisr_workstream *snwsp; struct sysctl_netisr_proto *snpp; u_int i; if (live) { netisr_load_sysctl_config(); netisr_load_sysctl_proto(); netisr_load_sysctl_workstream(); netisr_load_sysctl_work(); } else { netisr_load_kvm_config(); netisr_load_kvm_proto(); netisr_load_kvm_workstream(); /* Also does work. */ } xo_open_container("netisr"); xo_emit("{T:Configuration}:\n"); xo_emit("{T:/%-25s} {T:/%12s} {T:/%12s}\n", "Setting", "Current", "Limit"); xo_emit("{T:/%-25s} {T:/%12u} {T:/%12u}\n", "Thread count", numthreads, maxthreads); xo_emit("{T:/%-25s} {T:/%12u} {T:/%12u}\n", "Default queue limit", defaultqlimit, maxqlimit); xo_emit("{T:/%-25s} {T:/%12s} {T:/%12s}\n", "Dispatch policy", dispatch_policy, "n/a"); xo_emit("{T:/%-25s} {T:/%12s} {T:/%12s}\n", "Threads bound to CPUs", bindthreads ? "enabled" : "disabled", "n/a"); xo_emit("\n"); xo_emit("{T:Protocols}:\n"); xo_emit("{T:/%-6s} {T:/%5s} {T:/%6s} {T:/%-6s} {T:/%-8s} {T:/%-5s}\n", "Name", "Proto", "QLimit", "Policy", "Dispatch", "Flags"); xo_open_list("protocol"); for (i = 0; i < proto_array_len; i++) { xo_open_instance("protocol"); snpp = &proto_array[i]; netisr_print_proto(snpp); xo_close_instance("protocol"); } xo_close_list("protocol"); xo_emit("\n"); xo_emit("{T:Workstreams}:\n"); xo_emit("{T:/%4s} {T:/%3s} ", "WSID", "CPU"); xo_emit("{P:/%2s}", ""); xo_emit("{T:/%-6s} {T:/%5s} {T:/%5s} {T:/%8s} {T:/%8s} {T:/%8s} " "{T:/%8s} {T:/%8s}\n", "Name", "Len", "WMark", "Disp'd", "HDisp'd", "QDrops", "Queued", "Handled"); xo_open_list("workstream"); for (i = 0; i < workstream_array_len; i++) { xo_open_instance("workstream"); snwsp = &workstream_array[i]; netisr_print_workstream(snwsp); xo_close_instance("workstream"); } xo_close_list("workstream"); xo_close_container("netisr"); } diff --git a/usr.bin/rup/rup.c b/usr.bin/rup/rup.c index aae3639b64d4..5f605f55b413 100644 --- a/usr.bin/rup/rup.c +++ b/usr.bin/rup/rup.c @@ -1,243 +1,240 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1993, John Brezak * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #include #include #include #include #undef FSHIFT /* Use protocol's shift and scale values */ #undef FSCALE #include #include #include #include #include #include #include #include #include #define HOST_WIDTH 15 static struct host_list { struct host_list *next; struct in_addr addr; } *hosts; static int search_host(struct in_addr addr) { struct host_list *hp; if (!hosts) return(0); for (hp = hosts; hp != NULL; hp = hp->next) { if (hp->addr.s_addr == addr.s_addr) return(1); } return(0); } static void remember_host(struct in_addr addr) { struct host_list *hp; if (!(hp = (struct host_list *)malloc(sizeof(struct host_list)))) errx(1, "no memory"); hp->addr.s_addr = addr.s_addr; hp->next = hosts; hosts = hp; } static bool_t rstat_reply(statstime *host_stat, struct sockaddr_in *raddrp) { struct tm *tmp_time; struct tm host_time; struct tm host_uptime; char days_buf[16]; char hours_buf[16]; struct hostent *hp; char *host; time_t tmp_time_t; if (search_host(raddrp->sin_addr)) return(0); hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr, sizeof(struct in_addr), AF_INET); if (hp) host = hp->h_name; else host = inet_ntoa(raddrp->sin_addr); /* truncate hostname to fit nicely into field */ if (strlen(host) > HOST_WIDTH) host[HOST_WIDTH] = '\0'; printf("%-*s\t", HOST_WIDTH, host); tmp_time_t = host_stat->curtime.tv_sec; tmp_time = localtime(&tmp_time_t); host_time = *tmp_time; host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec; tmp_time_t = host_stat->curtime.tv_sec; tmp_time = gmtime(&tmp_time_t); host_uptime = *tmp_time; #define updays (host_stat->curtime.tv_sec / 86400) if (host_uptime.tm_yday != 0) sprintf(days_buf, "%3d day%s, ", updays, (updays > 1) ? "s" : ""); else days_buf[0] = '\0'; if (host_uptime.tm_hour != 0) sprintf(hours_buf, "%2d:%02d, ", host_uptime.tm_hour, host_uptime.tm_min); else if (host_uptime.tm_min != 0) sprintf(hours_buf, "%2d mins, ", host_uptime.tm_min); else if (host_stat->curtime.tv_sec < 60) sprintf(hours_buf, "%2d secs, ", host_uptime.tm_sec); else hours_buf[0] = '\0'; printf(" %2d:%02d%cm up %9.9s%9.9s load average: %.2f %.2f %.2f\n", (host_time.tm_hour % 12) ? host_time.tm_hour % 12 : 12, host_time.tm_min, (host_time.tm_hour >= 12) ? 'p' : 'a', days_buf, hours_buf, (double)host_stat->avenrun[0]/FSCALE, (double)host_stat->avenrun[1]/FSCALE, (double)host_stat->avenrun[2]/FSCALE); remember_host(raddrp->sin_addr); return(0); } static int onehost(char *host) { CLIENT *rstat_clnt; statstime host_stat; struct sockaddr_in addr; struct hostent *hp; struct timeval tv; hp = gethostbyname(host); if (hp == NULL) { warnx("unknown host \"%s\"", host); return(-1); } rstat_clnt = clnt_create(host, RSTATPROG, RSTATVERS_TIME, "udp"); if (rstat_clnt == NULL) { warnx("%s %s", host, clnt_spcreateerror("")); return(-1); } bzero((char *)&host_stat, sizeof(host_stat)); tv.tv_sec = 15; /* XXX ??? */ tv.tv_usec = 0; if (clnt_call(rstat_clnt, RSTATPROC_STATS, (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_statstime, &host_stat, tv) != RPC_SUCCESS) { warnx("%s: %s", host, clnt_sperror(rstat_clnt, host)); clnt_destroy(rstat_clnt); return(-1); } memcpy(&addr.sin_addr.s_addr, hp->h_addr, sizeof(int)); rstat_reply(&host_stat, &addr); clnt_destroy(rstat_clnt); return (0); } static void allhosts(void) { statstime host_stat; enum clnt_stat clnt_stat; clnt_stat = clnt_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS, (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_statstime, &host_stat, (resultproc_t)rstat_reply); if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) errx(1, "%s", clnt_sperrno(clnt_stat)); } static void usage(void) { fprintf(stderr, "usage: rup [host ...]\n"); exit(1); } int main(int argc, char *argv[]) { int ch; while ((ch = getopt(argc, argv, "?")) != -1) switch (ch) { default: usage(); } setlinebuf(stdout); if (argc == optind) allhosts(); else { for (; optind < argc; optind++) (void) onehost(argv[optind]); } exit(0); } diff --git a/usr.bin/rusers/rusers.c b/usr.bin/rusers/rusers.c index 838e231ca02a..413de53c304b 100644 --- a/usr.bin/rusers/rusers.c +++ b/usr.bin/rusers/rusers.c @@ -1,253 +1,250 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1993, John Brezak * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAX_INT 0x7fffffff #define HOST_WIDTH 20 #define LINE_WIDTH 15 static int longopt; static int allopt; static struct host_list { struct host_list *next; struct in_addr addr; } *hosts; static int search_host(struct in_addr addr) { struct host_list *hp; if (hosts == NULL) return (0); for (hp = hosts; hp != NULL; hp = hp->next) { if (hp->addr.s_addr == addr.s_addr) return (1); } return (0); } static void remember_host(struct in_addr addr) { struct host_list *hp; if ((hp = (struct host_list *)malloc(sizeof(struct host_list))) == NULL) errx(1, "no memory"); hp->addr.s_addr = addr.s_addr; hp->next = hosts; hosts = hp; } static int rusers_reply(void *replyp, struct sockaddr_in *raddrp) { unsigned int x; int idle; char date[32], idle_time[64], remote[64]; struct hostent *hp; utmpidlearr *up, u; char *host; int days, hours, minutes, seconds; up = &u; memcpy(up, replyp, sizeof(*up)); if (search_host(raddrp->sin_addr)) return (0); if (!allopt && up->utmpidlearr_len == 0) return (0); hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr, sizeof(struct in_addr), AF_INET); if (hp != NULL) host = hp->h_name; else host = inet_ntoa(raddrp->sin_addr); if (!longopt) printf("%-*s ", HOST_WIDTH, host); for (x = 0; x < up->utmpidlearr_len; x++) { time_t t = _int_to_time(up->utmpidlearr_val[x].ui_utmp.ut_time); strncpy(date, &(ctime(&t)[4]), sizeof(date) - 1); idle = up->utmpidlearr_val[x].ui_idle; sprintf(idle_time, " :%02d", idle); if (idle == MAX_INT) strcpy(idle_time, "??"); else if (idle == 0) strcpy(idle_time, ""); else { seconds = idle; days = seconds / (60 * 60 * 24); seconds %= (60 * 60 * 24); hours = seconds / (60 * 60); seconds %= (60 * 60); minutes = seconds / 60; seconds %= 60; if (idle > 60) sprintf(idle_time, "%d:%02d", minutes, seconds); if (idle >= (60 * 60)) sprintf(idle_time, "%d:%02d:%02d", hours, minutes, seconds); if (idle >= (24 * 60 * 60)) sprintf(idle_time, "%d days, %d:%02d:%02d", days, hours, minutes, seconds); } strncpy(remote, up->utmpidlearr_val[x].ui_utmp.ut_host, sizeof(remote) - 1); if (strlen(remote) != 0) sprintf(remote, "(%.16s)", up->utmpidlearr_val[x].ui_utmp.ut_host); if (longopt) printf("%-8.8s %*s:%-*.*s %-12.12s %6s %.18s\n", up->utmpidlearr_val[x].ui_utmp.ut_name, HOST_WIDTH, host, LINE_WIDTH, LINE_WIDTH, up->utmpidlearr_val[x].ui_utmp.ut_line, date, idle_time, remote ); else printf("%s ", up->utmpidlearr_val[x].ui_utmp.ut_name); } if (!longopt) putchar('\n'); remember_host(raddrp->sin_addr); return (0); } static void onehost(char *host) { utmpidlearr up; CLIENT *rusers_clnt; struct sockaddr_in addr; struct hostent *hp; struct timeval tv; hp = gethostbyname(host); if (hp == NULL) errx(1, "unknown host \"%s\"", host); rusers_clnt = clnt_create(host, RUSERSPROG, RUSERSVERS_IDLE, "udp"); if (rusers_clnt == NULL) errx(1, "%s", clnt_spcreateerror("")); memset(&up, 0, sizeof(up)); tv.tv_sec = 15; /* XXX ?? */ tv.tv_usec = 0; if (clnt_call(rusers_clnt, RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_utmpidlearr, &up, tv) != RPC_SUCCESS) errx(1, "%s", clnt_sperror(rusers_clnt, "")); memcpy(&addr.sin_addr.s_addr, hp->h_addr, sizeof(addr.sin_addr.s_addr)); rusers_reply(&up, &addr); clnt_destroy(rusers_clnt); } static void allhosts(void) { utmpidlearr up; enum clnt_stat clnt_stat; memset(&up, 0, sizeof(up)); clnt_stat = clnt_broadcast(RUSERSPROG, RUSERSVERS_IDLE, RUSERSPROC_NAMES, (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_utmpidlearr, (char *)&up, (resultproc_t)rusers_reply); if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT) errx(1, "%s", clnt_sperrno(clnt_stat)); } static void usage(void) { fprintf(stderr, "usage: rusers [-al] [host ...]\n"); exit(1); } int main(int argc, char *argv[]) { int ch; while ((ch = getopt(argc, argv, "al")) != -1) switch (ch) { case 'a': allopt++; break; case 'l': longopt++; break; default: usage(); /* NOTREACHED */ } setlinebuf(stdout); if (argc == optind) allhosts(); else { for (; optind < argc; optind++) (void)onehost(argv[optind]); } exit(0); } diff --git a/usr.bin/systat/cmds.c b/usr.bin/systat/cmds.c index aa16167c96b5..5d20cd4175de 100644 --- a/usr.bin/systat/cmds.c +++ b/usr.bin/systat/cmds.c @@ -1,198 +1,195 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 4/29/95"; #endif #include #include #include #include #include #include #include "systat.h" #include "extern.h" void command(const char *cmd) { struct cmdtab *p; char *cp, *tmpstr, *tmpstr1; double t; tmpstr = tmpstr1 = strdup(cmd); for (cp = tmpstr1; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (*tmpstr1 == '\0') goto done; for (; *cp && isspace(*cp); cp++) ; if (strcmp(tmpstr1, "quit") == 0 || strcmp(tmpstr1, "q") == 0) die(0); if (strcmp(tmpstr1, "load") == 0) { load(); goto done; } if (strcmp(tmpstr1, "stop") == 0) { delay = 0; mvaddstr(CMDLINE, 0, "Refresh disabled."); clrtoeol(); goto done; } if (strcmp(tmpstr1, "help") == 0) { int _col, _len; move(CMDLINE, _col = 0); for (p = cmdtab; p->c_name; p++) { _len = strlen(p->c_name); if (_col + _len > COLS) break; addstr(p->c_name); _col += _len; if (_col + 1 < COLS) addch(' '); } clrtoeol(); goto done; } t = strtod(tmpstr1, NULL) * 1000000.0; if (t > 0 && t < (double)UINT_MAX) delay = (unsigned int)t; if ((t <= 0 || t > (double)UINT_MAX) && (strcmp(tmpstr1, "start") == 0 || strcmp(tmpstr1, "interval") == 0)) { if (*cp != '\0') { t = strtod(cp, NULL) * 1000000.0; if (t <= 0 || t >= (double)UINT_MAX) { error("%d: bad interval.", (int)t); goto done; } } } if (t > 0) { delay = (unsigned int)t; display(); status(); goto done; } p = lookup(tmpstr1); if (p == (struct cmdtab *)-1) { error("%s: Ambiguous command.", tmpstr1); goto done; } if (p) { if (curcmd == p) goto done; (*curcmd->c_close)(wnd); curcmd->c_flags &= ~CF_INIT; wnd = (*p->c_open)(); if (wnd == NULL) { error("Couldn't open new display"); wnd = (*curcmd->c_open)(); if (wnd == NULL) { error("Couldn't change back to previous cmd"); exit(1); } p = curcmd; } if ((p->c_flags & CF_INIT) == 0) { if ((*p->c_init)()) p->c_flags |= CF_INIT; else goto done; } curcmd = p; labels(); display(); status(); goto done; } if (curcmd->c_cmd == NULL || !(*curcmd->c_cmd)(tmpstr1, cp)) error("%s: Unknown command.", tmpstr1); done: free(tmpstr); } struct cmdtab * lookup(const char *name) { const char *p, *q; struct cmdtab *ct, *found; int nmatches, longest; longest = 0; nmatches = 0; found = (struct cmdtab *) 0; for (ct = cmdtab; (p = ct->c_name); ct++) { for (q = name; *q == *p++; q++) if (*q == 0) /* exact match? */ return (ct); if (!*q) { /* the name was a prefix */ if (q - name > longest) { longest = q - name; nmatches = 1; found = ct; } else if (q - name == longest) nmatches++; } } if (nmatches > 1) return ((struct cmdtab *)-1); return (found); } void status(void) { error("Showing %s, refresh every %d seconds.", curcmd->c_name, delay / 1000000); } int prefix(const char *s1, const char *s2) { while (*s1 == *s2) { if (*s1 == '\0') return (1); s1++, s2++; } return (*s1 == '\0'); } diff --git a/usr.bin/systat/cmdtab.c b/usr.bin/systat/cmdtab.c index 52329948748b..d14084f60269 100644 --- a/usr.bin/systat/cmdtab.c +++ b/usr.bin/systat/cmdtab.c @@ -1,88 +1,85 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93"; #endif #include "systat.h" #include "extern.h" #include "mode.h" struct cmdtab cmdtab[] = { { "pigs", showpigs, fetchpigs, labelpigs, initpigs, openpigs, closepigs, 0, 0, CF_LOADAV }, { "swap", showswap, fetchswap, labelswap, initswap, openswap, closeswap, 0, 0, CF_LOADAV }, { "iostat", showiostat, fetchiostat, labeliostat, initiostat, openiostat, closeiostat, cmdiostat, 0, CF_LOADAV }, { "vmstat", showkre, fetchkre, labelkre, initkre, openkre, closekre, cmdkre, 0, 0 }, { "netstat", shownetstat, fetchnetstat, labelnetstat, initnetstat, opennetstat, closenetstat, cmdnetstat, 0, CF_LOADAV }, { "icmp", showicmp, fetchicmp, labelicmp, initicmp, openicmp, closeicmp, cmdmode, reseticmp, CF_LOADAV }, { "ip", showip, fetchip, labelip, initip, openip, closeip, cmdmode, resetip, CF_LOADAV }, #ifdef INET6 { "icmp6", showicmp6, fetchicmp6, labelicmp6, initicmp6, openicmp6, closeicmp6, cmdmode, reseticmp6, CF_LOADAV }, { "ip6", showip6, fetchip6, labelip6, initip6, openip6, closeip6, cmdmode, resetip6, CF_LOADAV }, #endif { "sctp", showsctp, fetchsctp, labelsctp, initsctp, opensctp, closesctp, cmdmode, resetsctp, CF_LOADAV }, { "tcp", showtcp, fetchtcp, labeltcp, inittcp, opentcp, closetcp, cmdmode, resettcp, CF_LOADAV }, { "ifstat", showifstat, fetchifstat, labelifstat, initifstat, openifstat, closeifstat, cmdifstat, 0, CF_LOADAV }, { "zarc", showzarc, fetchzarc, labelzarc, initzarc, openzarc, closezarc, 0, resetzarc, CF_ZFSARC }, { NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0 } }; struct cmdtab *curcmd = &cmdtab[0]; diff --git a/usr.bin/systat/devs.c b/usr.bin/systat/devs.c index 87d04f989ea3..40a65708fe99 100644 --- a/usr.bin/systat/devs.c +++ b/usr.bin/systat/devs.c @@ -1,437 +1,434 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1998 Kenneth D. Merry. * 2015 Yoshihiro Ota * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /*- * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)disks.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include #include "systat.h" #include "extern.h" #include "devs.h" typedef enum { DS_MATCHTYPE_NONE, DS_MATCHTYPE_SPEC, DS_MATCHTYPE_PATTERN } last_match_type; struct statinfo cur_dev, last_dev, run_dev; last_match_type last_type; struct device_selection *dev_select; long generation; int num_devices, num_selected; int num_selections; long select_generation; struct devstat_match *matches = NULL; int num_matches = 0; char **specified_devices; int num_devices_specified = 0; static int dsmatchselect(const char *args, devstat_select_mode select_mode, int maxshowdevs, struct statinfo *s1); static int dsselect(const char *args, devstat_select_mode select_mode, int maxshowdevs, struct statinfo *s1); int dsinit(int maxshowdevs) { /* * Make sure that the userland devstat version matches the kernel * devstat version. If not, exit and print a message informing * the user of his mistake. */ if (devstat_checkversion(NULL) < 0) errx(1, "%s", devstat_errbuf); if( cur_dev.dinfo ) // init was alreay ran return(1); if ((num_devices = devstat_getnumdevs(NULL)) < 0) { warnx("%s", devstat_errbuf); return(0); } cur_dev.dinfo = calloc(1, sizeof(struct devinfo)); last_dev.dinfo = calloc(1, sizeof(struct devinfo)); run_dev.dinfo = calloc(1, sizeof(struct devinfo)); generation = 0; num_devices = 0; num_selected = 0; num_selections = 0; select_generation = 0; last_type = DS_MATCHTYPE_NONE; if (devstat_getdevs(NULL, &cur_dev) == -1) errx(1, "%s", devstat_errbuf); num_devices = cur_dev.dinfo->numdevs; generation = cur_dev.dinfo->generation; dev_select = NULL; /* * At this point, selectdevs will almost surely indicate that the * device list has changed, so we don't look for return values of 0 * or 1. If we get back -1, though, there is an error. */ if (devstat_selectdevs(&dev_select, &num_selected, &num_selections, &select_generation, generation, cur_dev.dinfo->devices, num_devices, NULL, 0, NULL, 0, DS_SELECT_ADD, maxshowdevs, 0) == -1) errx(1, "%d %s", __LINE__, devstat_errbuf); return(1); } void dsgetinfo(struct statinfo* dev) { switch (devstat_getdevs(NULL, dev)) { case -1: errx(1, "%s", devstat_errbuf); break; case 1: num_devices = dev->dinfo->numdevs; generation = dev->dinfo->generation; cmdkre("refresh", NULL); break; default: break; } } int dscmd(const char *cmd, const char *args, int maxshowdevs, struct statinfo *s1) { int retval; if (prefix(cmd, "display") || prefix(cmd, "add")) return(dsselect(args, DS_SELECT_ADDONLY, maxshowdevs, s1)); if (prefix(cmd, "ignore") || prefix(cmd, "delete")) return(dsselect(args, DS_SELECT_REMOVE, maxshowdevs, s1)); if (prefix(cmd, "show") || prefix(cmd, "only")) return(dsselect(args, DS_SELECT_ONLY, maxshowdevs, s1)); if (prefix(cmd, "type") || prefix(cmd, "match")) return(dsmatchselect(args, DS_SELECT_ONLY, maxshowdevs, s1)); if (prefix(cmd, "refresh")) { retval = devstat_selectdevs(&dev_select, &num_selected, &num_selections, &select_generation, generation, s1->dinfo->devices, num_devices, (last_type ==DS_MATCHTYPE_PATTERN) ? matches : NULL, (last_type ==DS_MATCHTYPE_PATTERN) ? num_matches : 0, (last_type == DS_MATCHTYPE_SPEC) ?specified_devices : NULL, (last_type == DS_MATCHTYPE_SPEC) ?num_devices_specified : 0, (last_type == DS_MATCHTYPE_NONE) ? DS_SELECT_ADD : DS_SELECT_ADDONLY, maxshowdevs, 0); if (retval == -1) { warnx("%s", devstat_errbuf); return(0); } else if (retval == 1) return(2); } if (prefix(cmd, "drives")) { int i; move(CMDLINE, 0); clrtoeol(); for (i = 0; i < num_devices; i++) { printw("%s%d ", s1->dinfo->devices[i].device_name, s1->dinfo->devices[i].unit_number); } return(1); } return(0); } static int dsmatchselect(const char *args, devstat_select_mode select_mode, int maxshowdevs, struct statinfo *s1) { char **tempstr, *tmpstr, *tmpstr1; char *tstr[100]; int num_args = 0; int i; int retval = 0; if (!args) { warnx("dsmatchselect: no arguments"); return(1); } /* * Break the (pipe delimited) input string out into separate * strings. */ tmpstr = tmpstr1 = strdup(args); for (tempstr = tstr, num_args = 0; (*tempstr = strsep(&tmpstr1, "|")) != NULL && (num_args < 100); num_args++) if (**tempstr != '\0') if (++tempstr >= &tstr[100]) break; free(tmpstr); if (num_args > 99) { warnx("dsmatchselect: too many match arguments"); return(0); } /* * If we've gone through the matching code before, clean out * previously used memory. */ if (num_matches > 0) { free(matches); matches = NULL; num_matches = 0; } for (i = 0; i < num_args; i++) { if (devstat_buildmatch(tstr[i], &matches, &num_matches) != 0) { warnx("%s", devstat_errbuf); return(0); } } if (num_args > 0) { last_type = DS_MATCHTYPE_PATTERN; retval = devstat_selectdevs(&dev_select, &num_selected, &num_selections, &select_generation, generation, s1->dinfo->devices, num_devices, matches, num_matches, NULL, 0, select_mode, maxshowdevs, 0); if (retval == -1) err(1, "device selection error"); else if (retval == 1) return(2); } return(1); } static int dsselect(const char *args, devstat_select_mode select_mode, int maxshowdevs, struct statinfo *s1) { char *cp, *tmpstr, *tmpstr1, *buffer; int i; int retval = 0; if (!args) { warnx("dsselect: no argument"); return(1); } /* * If we've gone through this code before, free previously * allocated resources. */ if (num_devices_specified > 0) { for (i = 0; i < num_devices_specified; i++) free(specified_devices[i]); free(specified_devices); specified_devices = NULL; num_devices_specified = 0; } /* do an initial malloc */ specified_devices = (char **)malloc(sizeof(char *)); tmpstr = tmpstr1 = strdup(args); cp = strchr(tmpstr1, '\n'); if (cp) *cp = '\0'; for (;;) { for (cp = tmpstr1; *cp && isspace(*cp); cp++) ; tmpstr1 = cp; for (; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (cp - tmpstr1 == 0) break; for (i = 0; i < num_devices; i++) { asprintf(&buffer, "%s%d", dev_select[i].device_name, dev_select[i].unit_number); if (strcmp(buffer, tmpstr1) == 0) { num_devices_specified++; specified_devices =(char **)realloc( specified_devices, sizeof(char *) * num_devices_specified); specified_devices[num_devices_specified -1]= strdup(tmpstr1); free(buffer); break; } else free(buffer); } if (i >= num_devices) error("%s: unknown drive", args); tmpstr1 = cp; } free(tmpstr); if (num_devices_specified > 0) { last_type = DS_MATCHTYPE_SPEC; retval = devstat_selectdevs(&dev_select, &num_selected, &num_selections, &select_generation, generation, s1->dinfo->devices, num_devices, NULL, 0, specified_devices, num_devices_specified, select_mode, maxshowdevs, 0); if (retval == -1) err(1, "%s", devstat_errbuf); else if (retval == 1) return(2); } return(1); } void dslabel(int maxdrives, int diskcol, int diskrow) { int i, j; mvprintw(diskrow, diskcol, "Disks"); mvprintw(diskrow + 1, diskcol, "KB/t"); mvprintw(diskrow + 2, diskcol, "tps"); mvprintw(diskrow + 3, diskcol, "MB/s"); mvprintw(diskrow + 4, diskcol, "%%busy"); /* * For now, we don't support a fourth disk statistic. So there's * no point in providing a label for it. If someone can think of a * fourth useful disk statistic, there is room to add it. */ /* mvprintw(diskrow + 4, diskcol, " msps"); */ j = 0; for (i = 0; i < num_devices && j < maxdrives; i++) if (dev_select[i].selected) { char tmpstr[80]; sprintf(tmpstr, "%s%d", dev_select[i].device_name, dev_select[i].unit_number); mvprintw(diskrow, diskcol + 5 + 6 * j, " %5.5s", tmpstr); j++; } } static void dsshow2(int diskcol, int diskrow, int dn, int lc, struct statinfo *now, struct statinfo *then) { long double transfers_per_second; long double kb_per_transfer, mb_per_second; long double elapsed_time, device_busy; int di; di = dev_select[dn].position; if (then != NULL) { /* Calculate relative to previous sample */ elapsed_time = now->snap_time - then->snap_time; } else { /* Calculate relative to device creation */ elapsed_time = now->snap_time - devstat_compute_etime( &now->dinfo->devices[di].creation_time, NULL); } if (devstat_compute_statistics(&now->dinfo->devices[di], then ? &then->dinfo->devices[di] : NULL, elapsed_time, DSM_KB_PER_TRANSFER, &kb_per_transfer, DSM_TRANSFERS_PER_SECOND, &transfers_per_second, DSM_MB_PER_SECOND, &mb_per_second, DSM_BUSY_PCT, &device_busy, DSM_NONE) != 0) errx(1, "%s", devstat_errbuf); lc = diskcol + lc * 6; putlongdouble(kb_per_transfer, diskrow + 1, lc, 5, 2, 0); putlongdouble(transfers_per_second, diskrow + 2, lc, 5, 0, 0); putlongdouble(mb_per_second, diskrow + 3, lc, 5, 2, 0); putlongdouble(device_busy, diskrow + 4, lc, 5, 0, 0); } void dsshow(int maxdrives, int diskcol, int diskrow, struct statinfo *now, struct statinfo *then) { int i, lc; for (i = 0, lc = 0; i < num_devices && lc < maxdrives; i++) if (dev_select[i].selected) dsshow2(diskcol, diskrow, i, ++lc, now, then); } diff --git a/usr.bin/systat/fetch.c b/usr.bin/systat/fetch.c index e24d0b8ee6ee..1b7a884159bd 100644 --- a/usr.bin/systat/fetch.c +++ b/usr.bin/systat/fetch.c @@ -1,141 +1,138 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)fetch.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include "systat.h" #include "extern.h" int kvm_ckread(void *a, void *b, int l) { if (kvm_read(kd, (u_long)a, b, l) != l) { if (verbose) error("error reading kmem at %p", a); return (0); } else return (1); } void getsysctl(const char *name, void *ptr, size_t len) { size_t nlen = len; if (sysctlbyname(name, ptr, &nlen, NULL, 0) != 0) { error("sysctl(%s...) failed: %s", name, strerror(errno)); } if (nlen != len) { error("sysctl(%s...) expected %zu, got %zu", name, len, nlen); } } /* * Read sysctl data with variable size. Try some times (with increasing * buffers), fail if still too small. * This is needed sysctls with possibly raplidly increasing data sizes, * but imposes little overhead in the case of constant sizes. * Returns NULL on error, or a pointer to freshly malloc()'ed memory that holds * the requested data. * If szp is not NULL, the size of the returned data will be written into *szp. */ /* Some defines: Number of tries. */ #define SD_NTRIES 10 /* Percent of over-allocation (initial) */ #define SD_MARGIN 10 /* * Factor for over-allocation in percent (the margin is increased by this on * any failed try). */ #define SD_FACTOR 50 /* Maximum supported MIB depth */ #define SD_MAXMIB 16 char * sysctl_dynread(const char *n, size_t *szp) { char *rv = NULL; int mib[SD_MAXMIB]; size_t mibsz = SD_MAXMIB; size_t mrg = SD_MARGIN; size_t sz; int i; /* cache the MIB */ if (sysctlnametomib(n, mib, &mibsz) == -1) { if (errno == ENOMEM) { error("XXX: SD_MAXMIB too small, please bump!"); } return NULL; } for (i = 0; i < SD_NTRIES; i++) { /* get needed buffer size */ if (sysctl(mib, mibsz, NULL, &sz, NULL, 0) == -1) break; sz += sz * mrg / 100; if ((rv = (char *)malloc(sz)) == NULL) { error("Out of memory!"); return NULL; } if (sysctl(mib, mibsz, rv, &sz, NULL, 0) == -1) { free(rv); rv = NULL; if (errno == ENOMEM) { mrg += mrg * SD_FACTOR / 100; } else break; } else { /* success */ if (szp != NULL) *szp = sz; break; } } return rv; } diff --git a/usr.bin/systat/icmp.c b/usr.bin/systat/icmp.c index 4b3a56640267..a1c25e37ed2a 100644 --- a/usr.bin/systat/icmp.c +++ b/usr.bin/systat/icmp.c @@ -1,281 +1,278 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static char sccsid[] = "@(#)mbufs.c 8.1 (Berkeley) 6/6/93"; #endif /* From: "Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp" */ #include #include #include #include #include #include #include #include #include #include #include #include #include "systat.h" #include "extern.h" #include "mode.h" static struct icmpstat icmpstat, initstat, oldstat; /*- --0 1 2 3 4 5 6 7 --0123456789012345678901234567890123456789012345678901234567890123456789012345 00 ICMP Input ICMP Output 01999999999 total messages 999999999 total messages 02999999999 with bad code 999999999 errors generated 03999999999 with bad length 999999999 suppressed - original too short 04999999999 with bad checksum 999999999 suppressed - original was ICMP 05999999999 with insufficient data 999999999 responses sent 06 999999999 suppressed - multicast echo 07 999999999 suppressed - multicast tstamp 08 09 Input Histogram Output Histogram 10999999999 echo response 999999999 echo response 11999999999 echo request 999999999 echo request 12999999999 destination unreachable 999999999 destination unreachable 13999999999 redirect 999999999 redirect 14999999999 time-to-live exceeded 999999999 time-to-line exceeded 15999999999 parameter problem 999999999 parameter problem 16999999999 router advertisement 999999999 router solicitation 17 18 --0123456789012345678901234567890123456789012345678901234567890123456789012345 --0 1 2 3 4 5 6 7 */ WINDOW * openicmp(void) { return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0)); } void closeicmp(WINDOW *w) { if (w == NULL) return; wclear(w); wrefresh(w); delwin(w); } void labelicmp(void) { wmove(wnd, 0, 0); wclrtoeol(wnd); #define L(row, str) mvwprintw(wnd, row, 10, str) #define R(row, str) mvwprintw(wnd, row, 45, str); L(0, "ICMP Input"); R(0, "ICMP Output"); L(1, "total messages"); R(1, "total messages"); L(2, "with bad code"); R(2, "errors generated"); L(3, "with bad length"); R(3, "suppressed - original too short"); L(4, "with bad checksum"); R(4, "suppressed - original was ICMP"); L(5, "with insufficient data"); R(5, "responses sent"); R(6, "suppressed - multicast echo"); R(7, "suppressed - multicast tstamp"); L(9, "Input Histogram"); R(9, "Output Histogram"); #define B(row, str) L(row, str); R(row, str) B(10, "echo response"); B(11, "echo request"); B(12, "destination unreachable"); B(13, "redirect"); B(14, "time-to-live exceeded"); B(15, "parameter problem"); L(16, "router advertisement"); R(16, "router solicitation"); #undef L #undef R #undef B } static void domode(struct icmpstat *ret) { const struct icmpstat *sub; int i, divisor = 1; switch(currentmode) { case display_RATE: sub = &oldstat; divisor = (delay > 1000000) ? delay / 1000000 : 1; break; case display_DELTA: sub = &oldstat; break; case display_SINCE: sub = &initstat; break; default: *ret = icmpstat; return; } #define DO(stat) ret->stat = (icmpstat.stat - sub->stat) / divisor DO(icps_error); DO(icps_oldshort); DO(icps_oldicmp); for (i = 0; i <= ICMP_MAXTYPE; i++) { DO(icps_outhist[i]); } DO(icps_badcode); DO(icps_tooshort); DO(icps_checksum); DO(icps_badlen); DO(icps_reflect); for (i = 0; i <= ICMP_MAXTYPE; i++) { DO(icps_inhist[i]); } DO(icps_bmcastecho); DO(icps_bmcasttstamp); #undef DO } void showicmp(void) { struct icmpstat stats; u_long totalin, totalout; int i; memset(&stats, 0, sizeof stats); domode(&stats); for (i = totalin = totalout = 0; i <= ICMP_MAXTYPE; i++) { totalin += stats.icps_inhist[i]; totalout += stats.icps_outhist[i]; } totalin += stats.icps_badcode + stats.icps_badlen + stats.icps_checksum + stats.icps_tooshort; mvwprintw(wnd, 1, 0, "%9lu", totalin); mvwprintw(wnd, 1, 35, "%9lu", totalout); #define DO(stat, row, col) \ mvwprintw(wnd, row, col, "%9lu", stats.stat) DO(icps_badcode, 2, 0); DO(icps_badlen, 3, 0); DO(icps_checksum, 4, 0); DO(icps_tooshort, 5, 0); DO(icps_error, 2, 35); DO(icps_oldshort, 3, 35); DO(icps_oldicmp, 4, 35); DO(icps_reflect, 5, 35); DO(icps_bmcastecho, 6, 35); DO(icps_bmcasttstamp, 7, 35); #define DO2(type, row) DO(icps_inhist[type], row, 0); DO(icps_outhist[type], \ row, 35) DO2(ICMP_ECHOREPLY, 10); DO2(ICMP_ECHO, 11); DO2(ICMP_UNREACH, 12); DO2(ICMP_REDIRECT, 13); DO2(ICMP_TIMXCEED, 14); DO2(ICMP_PARAMPROB, 15); DO(icps_inhist[ICMP_ROUTERADVERT], 16, 0); DO(icps_outhist[ICMP_ROUTERSOLICIT], 16, 35); #undef DO #undef DO2 } int initicmp(void) { size_t len; int name[4]; name[0] = CTL_NET; name[1] = PF_INET; name[2] = IPPROTO_ICMP; name[3] = ICMPCTL_STATS; len = 0; if (sysctl(name, 4, 0, &len, 0, 0) < 0) { error("sysctl getting icmpstat size failed"); return 0; } if (len > sizeof icmpstat) { error("icmpstat structure has grown--recompile systat!"); return 0; } if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) { error("sysctl getting icmpstat size failed"); return 0; } oldstat = initstat; return 1; } void reseticmp(void) { size_t len; int name[4]; name[0] = CTL_NET; name[1] = PF_INET; name[2] = IPPROTO_ICMP; name[3] = ICMPCTL_STATS; len = sizeof initstat; if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) { error("sysctl getting icmpstat size failed"); } oldstat = initstat; } void fetchicmp(void) { int name[4]; size_t len; oldstat = icmpstat; name[0] = CTL_NET; name[1] = PF_INET; name[2] = IPPROTO_ICMP; name[3] = ICMPCTL_STATS; len = sizeof icmpstat; if (sysctl(name, 4, &icmpstat, &len, 0, 0) < 0) return; } diff --git a/usr.bin/systat/icmp6.c b/usr.bin/systat/icmp6.c index 2853b90eff29..d7d612604475 100644 --- a/usr.bin/systat/icmp6.c +++ b/usr.bin/systat/icmp6.c @@ -1,281 +1,278 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static char sccsid[] = "@(#)mbufs.c 8.1 (Berkeley) 6/6/93"; #endif /* From: "Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp" */ #ifdef INET6 #include #include #include #include #include #include #include #include #include #include #include "systat.h" #include "extern.h" #include "mode.h" static struct icmp6stat icmp6stat, initstat, oldstat; /*- --0 1 2 3 4 5 6 7 --0123456789012345678901234567890123456789012345678901234567890123456789012345 00 ICMPv6 Input ICMPv6 Output 01999999999 total messages 999999999 total messages 02999999999 with bad code 999999999 errors generated 03999999999 with bad length 999999999 suppressed - original too short 04999999999 with bad checksum 999999999 suppressed - original was ICMP 05999999999 with insufficient data 999999999 responses sent 06 07 Input Histogram Output Histogram 08999999999 echo response 999999999 echo response 09999999999 echo request 999999999 echo request 10999999999 destination unreachable 999999999 destination unreachable 11999999999 redirect 999999999 redirect 12999999999 time-to-live exceeded 999999999 time-to-line exceeded 13999999999 parameter problem 999999999 parameter problem 14999999999 neighbor solicitation 999999999 neighbor solicitation 15999999999 neighbor advertisement 999999999 neighbor advertisement 16999999999 router advertisement 999999999 router solicitation 17 18 --0123456789012345678901234567890123456789012345678901234567890123456789012345 --0 1 2 3 4 5 6 7 */ WINDOW * openicmp6(void) { return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0)); } void closeicmp6(WINDOW *w) { if (w == NULL) return; wclear(w); wrefresh(w); delwin(w); } void labelicmp6(void) { wmove(wnd, 0, 0); wclrtoeol(wnd); #define L(row, str) mvwprintw(wnd, row, 10, str) #define R(row, str) mvwprintw(wnd, row, 45, str); L(0, "ICMPv6 Input"); R(0, "ICMPv6 Output"); L(1, "total messages"); R(1, "total messages"); L(2, "with bad code"); R(2, "errors generated"); L(3, "with bad length"); R(3, "suppressed - original too short"); L(4, "with bad checksum"); R(4, "suppressed - original was ICMP"); L(5, "with insufficient data"); R(5, "responses sent"); L(7, "Input Histogram"); R(7, "Output Histogram"); #define B(row, str) L(row, str); R(row, str) B(8, "echo response"); B(9, "echo request"); B(10, "destination unreachable"); B(11, "redirect"); B(12, "time-to-live exceeded"); B(13, "parameter problem"); B(14, "neighbor solicitation"); B(15, "neighbor advertisement"); L(16, "router advertisement"); R(16, "router solicitation"); #undef L #undef R #undef B } static void domode(struct icmp6stat *ret) { const struct icmp6stat *sub; int i, divisor = 1; switch(currentmode) { case display_RATE: sub = &oldstat; divisor = (delay > 1000000) ? delay / 1000000 : 1; break; case display_DELTA: sub = &oldstat; break; case display_SINCE: sub = &initstat; break; default: *ret = icmp6stat; return; } #define DO(stat) ret->stat = (icmp6stat.stat - sub->stat) / divisor DO(icp6s_error); DO(icp6s_tooshort); DO(icp6s_canterror); for (i = 0; i <= ICMP6_MAXTYPE; i++) { DO(icp6s_outhist[i]); } DO(icp6s_badcode); DO(icp6s_tooshort); DO(icp6s_checksum); DO(icp6s_badlen); DO(icp6s_reflect); for (i = 0; i <= ICMP6_MAXTYPE; i++) { DO(icp6s_inhist[i]); } #undef DO } void showicmp6(void) { struct icmp6stat stats; uint64_t totalin, totalout; int i; memset(&stats, 0, sizeof stats); domode(&stats); for (i = totalin = totalout = 0; i <= ICMP6_MAXTYPE; i++) { totalin += stats.icp6s_inhist[i]; totalout += stats.icp6s_outhist[i]; } totalin += stats.icp6s_badcode + stats.icp6s_badlen + stats.icp6s_checksum + stats.icp6s_tooshort; mvwprintw(wnd, 1, 0, "%9"PRIu64, totalin); mvwprintw(wnd, 1, 35, "%9"PRIu64, totalout); #define DO(stat, row, col) \ mvwprintw(wnd, row, col, "%9"PRIu64, stats.stat) DO(icp6s_badcode, 2, 0); DO(icp6s_badlen, 3, 0); DO(icp6s_checksum, 4, 0); DO(icp6s_tooshort, 5, 0); DO(icp6s_error, 2, 35); DO(icp6s_tooshort, 3, 35); DO(icp6s_canterror, 4, 35); DO(icp6s_reflect, 5, 35); #define DO2(type, row) DO(icp6s_inhist[type], row, 0); DO(icp6s_outhist[type], \ row, 35) DO2(ICMP6_ECHO_REPLY, 8); DO2(ICMP6_ECHO_REQUEST, 9); DO2(ICMP6_DST_UNREACH, 10); DO2(ND_REDIRECT, 11); DO2(ICMP6_TIME_EXCEEDED, 12); DO2(ICMP6_PARAM_PROB, 13); DO2(ND_NEIGHBOR_SOLICIT, 14); DO2(ND_NEIGHBOR_ADVERT, 15); DO(icp6s_inhist[ND_ROUTER_SOLICIT], 16, 0); DO(icp6s_outhist[ND_ROUTER_ADVERT], 16, 35); #undef DO #undef DO2 } int initicmp6(void) { size_t len; int name[4]; name[0] = CTL_NET; name[1] = PF_INET6; name[2] = IPPROTO_ICMPV6; name[3] = ICMPV6CTL_STATS; len = 0; if (sysctl(name, 4, 0, &len, 0, 0) < 0) { error("sysctl getting icmp6stat size failed"); return 0; } if (len > sizeof icmp6stat) { error("icmp6stat structure has grown--recompile systat!"); return 0; } if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) { error("sysctl getting icmp6stat size failed"); return 0; } oldstat = initstat; return 1; } void reseticmp6(void) { size_t len; int name[4]; name[0] = CTL_NET; name[1] = PF_INET6; name[2] = IPPROTO_ICMPV6; name[3] = ICMPV6CTL_STATS; len = sizeof initstat; if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) { error("sysctl getting icmp6stat size failed"); } oldstat = initstat; } void fetchicmp6(void) { int name[4]; size_t len; oldstat = icmp6stat; name[0] = CTL_NET; name[1] = PF_INET6; name[2] = IPPROTO_ICMPV6; name[3] = ICMPV6CTL_STATS; len = sizeof icmp6stat; if (sysctl(name, 4, &icmp6stat, &len, 0, 0) < 0) return; } #endif diff --git a/usr.bin/systat/iostat.c b/usr.bin/systat/iostat.c index 8767a046d81a..c6168b625c4e 100644 --- a/usr.bin/systat/iostat.c +++ b/usr.bin/systat/iostat.c @@ -1,389 +1,386 @@ /* * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1998 Kenneth D. Merry. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)iostat.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include #include #include #include "systat.h" #include "extern.h" #include "devs.h" static int linesperregion; static double etime; static int numbers = 0; /* default display bar graphs */ static int kbpt = 0; /* default ms/seek shown */ static int barlabels(int); static void histogram(long double, int, double); static int numlabels(int); static int devstats(int, int, int); static void stat1(int, int); WINDOW * openiostat(void) { return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0)); } void closeiostat(WINDOW *w) { if (w == NULL) return; wclear(w); wrefresh(w); delwin(w); } int initiostat(void) { /* * This value for maxshowdevs (100) is bogus. I'm not sure exactly * how to calculate it, though. */ if (dsinit(7) != 1) return(0); return(1); } void fetchiostat(void) { struct devinfo *tmp_dinfo; size_t len; len = sizeof(cur_dev.cp_time); if (sysctlbyname("kern.cp_time", &cur_dev.cp_time, &len, NULL, 0) || len != sizeof(cur_dev.cp_time)) { perror("kern.cp_time"); exit (1); } tmp_dinfo = last_dev.dinfo; last_dev.dinfo = cur_dev.dinfo; cur_dev.dinfo = tmp_dinfo; last_dev.snap_time = cur_dev.snap_time; /* * Here what we want to do is refresh our device stats. * getdevs() returns 1 when the device list has changed. * If the device list has changed, we want to go through * the selection process again, in case a device that we * were previously displaying has gone away. */ switch (devstat_getdevs(NULL, &cur_dev)) { case -1: errx(1, "%s", devstat_errbuf); break; case 1: cmdiostat("refresh", NULL); break; default: break; } num_devices = cur_dev.dinfo->numdevs; generation = cur_dev.dinfo->generation; } #define INSET 10 void labeliostat(void) { int row; row = 0; wmove(wnd, row, 0); wclrtobot(wnd); mvwaddstr(wnd, row++, INSET, "/0% /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); mvwaddstr(wnd, row++, 0, "cpu user|"); mvwaddstr(wnd, row++, 0, " nice|"); mvwaddstr(wnd, row++, 0, " system|"); mvwaddstr(wnd, row++, 0, "interrupt|"); mvwaddstr(wnd, row++, 0, " idle|"); if (numbers) row = numlabels(row + 1); else row = barlabels(row + 1); } static int numlabels(int row) { int i, _col, regions, ndrives; char tmpstr[10]; #define COLWIDTH 17 #define DRIVESPERLINE ((getmaxx(wnd) - 1 - INSET) / COLWIDTH) for (ndrives = 0, i = 0; i < num_devices; i++) if (dev_select[i].selected) ndrives++; regions = howmany(ndrives, DRIVESPERLINE); /* * Deduct -regions for blank line after each scrolling region. */ linesperregion = (getmaxy(wnd) - 1 - row - regions) / regions; /* * Minimum region contains space for two * label lines and one line of statistics. */ if (linesperregion < 3) linesperregion = 3; _col = INSET; for (i = 0; i < num_devices; i++) if (dev_select[i].selected) { if (_col + COLWIDTH >= getmaxx(wnd) - 1 - INSET) { _col = INSET, row += linesperregion + 1; if (row > getmaxy(wnd) - 1 - (linesperregion + 1)) break; } sprintf(tmpstr, "%s%d", dev_select[i].device_name, dev_select[i].unit_number); mvwaddstr(wnd, row, _col + 4, tmpstr); mvwaddstr(wnd, row + 1, _col, " KB/t tps MB/s "); _col += COLWIDTH; } if (_col) row += linesperregion + 1; return (row); } static int barlabels(int row) { int i; char tmpstr[10]; mvwaddstr(wnd, row++, INSET, "/0% /10 /20 /30 /40 /50 /60 /70 /80 /90 /100"); linesperregion = 2 + kbpt; for (i = 0; i < num_devices; i++) if (dev_select[i].selected) { if (row > getmaxy(wnd) - 1 - linesperregion) break; sprintf(tmpstr, "%s%d", dev_select[i].device_name, dev_select[i].unit_number); mvwprintw(wnd, row++, 0, "%-5.5s MB/s|", tmpstr); mvwaddstr(wnd, row++, 0, " tps|"); if (kbpt) mvwaddstr(wnd, row++, 0, " KB/t|"); } return (row); } void showiostat(void) { long t; int i, row, _col; #define X(fld) t = cur_dev.fld[i]; cur_dev.fld[i] -= last_dev.fld[i]; last_dev.fld[i] = t etime = 0; for(i = 0; i < CPUSTATES; i++) { X(cp_time); etime += cur_dev.cp_time[i]; } if (etime == 0.0) etime = 1.0; etime /= hertz; row = 1; for (i = 0; i < CPUSTATES; i++) stat1(row++, i); if (!numbers) { row += 2; for (i = 0; i < num_devices; i++) if (dev_select[i].selected) { if (row > getmaxy(wnd) - linesperregion) break; row = devstats(row, INSET, i); } return; } _col = INSET; wmove(wnd, row + linesperregion, 0); wdeleteln(wnd); wmove(wnd, row + 3, 0); winsertln(wnd); for (i = 0; i < num_devices; i++) if (dev_select[i].selected) { if (_col + COLWIDTH >= getmaxx(wnd) - 1 - INSET) { _col = INSET, row += linesperregion + 1; if (row > getmaxy(wnd) - 1 - (linesperregion + 1)) break; wmove(wnd, row + linesperregion, 0); wdeleteln(wnd); wmove(wnd, row + 3, 0); winsertln(wnd); } (void) devstats(row + 3, _col, i); _col += COLWIDTH; } } static int devstats(int row, int _col, int dn) { long double transfers_per_second; long double kb_per_transfer, mb_per_second; long double busy_seconds; int di; di = dev_select[dn].position; busy_seconds = cur_dev.snap_time - last_dev.snap_time; if (devstat_compute_statistics(&cur_dev.dinfo->devices[di], &last_dev.dinfo->devices[di], busy_seconds, DSM_KB_PER_TRANSFER, &kb_per_transfer, DSM_TRANSFERS_PER_SECOND, &transfers_per_second, DSM_MB_PER_SECOND, &mb_per_second, DSM_NONE) != 0) errx(1, "%s", devstat_errbuf); if (numbers) { mvwprintw(wnd, row, _col, " %5.2Lf %3.0Lf %5.2Lf ", kb_per_transfer, transfers_per_second, mb_per_second); return(row); } wmove(wnd, row++, _col); histogram(mb_per_second, 50, .5); wmove(wnd, row++, _col); histogram(transfers_per_second, 50, .5); if (kbpt) { wmove(wnd, row++, _col); histogram(kb_per_transfer, 50, .5); } return(row); } static void stat1(int row, int o) { int i; double dtime; dtime = 0.0; for (i = 0; i < CPUSTATES; i++) dtime += cur_dev.cp_time[i]; if (dtime == 0.0) dtime = 1.0; wmove(wnd, row, INSET); #define CPUSCALE 0.5 histogram(100.0 * cur_dev.cp_time[o] / dtime, 50, CPUSCALE); } static void histogram(long double val, int colwidth, double scale) { char buf[10]; int k; int v = (int)(val * scale) + 0.5; k = MIN(v, colwidth); if (v > colwidth) { snprintf(buf, sizeof(buf), "%5.2Lf", val); k -= strlen(buf); while (k--) waddch(wnd, 'X'); waddstr(wnd, buf); return; } while (k--) waddch(wnd, 'X'); wclrtoeol(wnd); } int cmdiostat(const char *cmd, const char *args) { if (prefix(cmd, "kbpt")) kbpt = !kbpt; else if (prefix(cmd, "numbers")) numbers = 1; else if (prefix(cmd, "bars")) numbers = 0; else if (!dscmd(cmd, args, 100, &cur_dev)) return (0); wclear(wnd); labeliostat(); refresh(); return (1); } diff --git a/usr.bin/systat/ip.c b/usr.bin/systat/ip.c index f177a6cd0ff8..bc90ff557e20 100644 --- a/usr.bin/systat/ip.c +++ b/usr.bin/systat/ip.c @@ -1,342 +1,339 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)mbufs.c 8.1 (Berkeley) 6/6/93"; #endif /* From: "Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp" */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "systat.h" #include "extern.h" #include "mode.h" struct stat { struct ipstat i; struct udpstat u; }; static struct stat curstat, initstat, oldstat; /*- --0 1 2 3 4 5 6 7 --0123456789012345678901234567890123456789012345678901234567890123456789012345 00 IP Input IP Output 01999999999 total packets received 999999999 total packets sent 02999999999 - with bad checksums 999999999 - generated locally 03999999999 - too short for header 999999999 - output drops 04999999999 - too short for data 999999999 output fragments generated 05999999999 - with invalid hlen 999999999 - fragmentation failed 06999999999 - with invalid length 999999999 destinations unreachable 07999999999 - with invalid version 999999999 packets output via raw IP 08999999999 - jumbograms 09999999999 total fragments received UDP Statistics 10999999999 - fragments dropped 999999999 total input packets 11999999999 - fragments timed out 999999999 - too short for header 12999999999 - packets reassembled ok 999999999 - invalid checksum 13999999999 packets forwarded 999999999 - no checksum 14999999999 - unreachable dests 999999999 - invalid length 15999999999 - redirects generated 999999999 - no socket for dest port 16999999999 option errors 999999999 - no socket for broadcast 17999999999 unwanted multicasts 999999999 - socket buffer full 18999999999 delivered to upper layer 999999999 total output packets --0123456789012345678901234567890123456789012345678901234567890123456789012345 --0 1 2 3 4 5 6 7 */ WINDOW * openip(void) { return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0)); } void closeip(WINDOW *w) { if (w == NULL) return; wclear(w); wrefresh(w); delwin(w); } void labelip(void) { wmove(wnd, 0, 0); wclrtoeol(wnd); #define L(row, str) mvwprintw(wnd, row, 10, str) #define R(row, str) mvwprintw(wnd, row, 45, str); L(0, "IP Input"); R(0, "IP Output"); L(1, "total packets received"); R(1, "total packets sent"); L(2, "- with bad checksums"); R(2, "- generated locally"); L(3, "- too short for header"); R(3, "- output drops"); L(4, "- too short for data"); R(4, "output fragments generated"); L(5, "- with invalid hlen"); R(5, "- fragmentation failed"); L(6, "- with invalid length"); R(6, "destinations unreachable"); L(7, "- with invalid version"); R(7, "packets output via raw IP"); L(8, "- jumbograms"); L(9, "total fragments received"); R(9, "UDP Statistics"); L(10, "- fragments dropped"); R(10, "total input packets"); L(11, "- fragments timed out"); R(11, "- too short for header"); L(12, "- packets reassembled ok"); R(12, "- invalid checksum"); L(13, "packets forwarded"); R(13, "- no checksum"); L(14, "- unreachable dests"); R(14, "- invalid length"); L(15, "- redirects generated"); R(15, "- no socket for dest port"); L(16, "option errors"); R(16, "- no socket for broadcast"); L(17, "unwanted multicasts"); R(17, "- socket buffer full"); L(18, "delivered to upper layer"); R(18, "total output packets"); #undef L #undef R } static void domode(struct stat *ret) { const struct stat *sub; int divisor = 1; switch(currentmode) { case display_RATE: sub = &oldstat; divisor = (delay > 1000000) ? delay / 1000000 : 1; break; case display_DELTA: sub = &oldstat; break; case display_SINCE: sub = &initstat; break; default: *ret = curstat; return; } #define DO(stat) ret->stat = (curstat.stat - sub->stat) / divisor DO(i.ips_total); DO(i.ips_badsum); DO(i.ips_tooshort); DO(i.ips_toosmall); DO(i.ips_badhlen); DO(i.ips_badlen); DO(i.ips_fragments); DO(i.ips_fragdropped); DO(i.ips_fragtimeout); DO(i.ips_forward); DO(i.ips_cantforward); DO(i.ips_redirectsent); DO(i.ips_noproto); DO(i.ips_delivered); DO(i.ips_localout); DO(i.ips_odropped); DO(i.ips_reassembled); DO(i.ips_fragmented); DO(i.ips_ofragments); DO(i.ips_cantfrag); DO(i.ips_badoptions); DO(i.ips_noroute); DO(i.ips_badvers); DO(i.ips_rawout); DO(i.ips_toolong); DO(i.ips_notmember); DO(u.udps_ipackets); DO(u.udps_hdrops); DO(u.udps_badsum); DO(u.udps_nosum); DO(u.udps_badlen); DO(u.udps_noport); DO(u.udps_noportbcast); DO(u.udps_fullsock); DO(u.udps_opackets); #undef DO } void showip(void) { struct stat stats; uint64_t totalout; domode(&stats); totalout = stats.i.ips_forward + stats.i.ips_localout; #define DO(stat, row, col) \ mvwprintw(wnd, row, col, "%9"PRIu64, stats.stat) DO(i.ips_total, 1, 0); mvwprintw(wnd, 1, 35, "%9"PRIu64, totalout); DO(i.ips_badsum, 2, 0); DO(i.ips_localout, 2, 35); DO(i.ips_tooshort, 3, 0); DO(i.ips_odropped, 3, 35); DO(i.ips_toosmall, 4, 0); DO(i.ips_ofragments, 4, 35); DO(i.ips_badhlen, 5, 0); DO(i.ips_cantfrag, 5, 35); DO(i.ips_badlen, 6, 0); DO(i.ips_noroute, 6, 35); DO(i.ips_badvers, 7, 0); DO(i.ips_rawout, 7, 35); DO(i.ips_toolong, 8, 0); DO(i.ips_fragments, 9, 0); DO(i.ips_fragdropped, 10, 0); DO(u.udps_ipackets, 10, 35); DO(i.ips_fragtimeout, 11, 0); DO(u.udps_hdrops, 11, 35); DO(i.ips_reassembled, 12, 0); DO(u.udps_badsum, 12, 35); DO(i.ips_forward, 13, 0); DO(u.udps_nosum, 13, 35); DO(i.ips_cantforward, 14, 0); DO(u.udps_badlen, 14, 35); DO(i.ips_redirectsent, 15, 0); DO(u.udps_noport, 15, 35); DO(i.ips_badoptions, 16, 0); DO(u.udps_noportbcast, 16, 35); DO(i.ips_notmember, 17, 0); DO(u.udps_fullsock, 17, 35); DO(i.ips_delivered, 18, 0); DO(u.udps_opackets, 18, 35); #undef DO } int initip(void) { size_t len; int name[4]; name[0] = CTL_NET; name[1] = PF_INET; name[2] = IPPROTO_IP; name[3] = IPCTL_STATS; len = 0; if (sysctl(name, 4, 0, &len, 0, 0) < 0) { error("sysctl getting ipstat size failed"); return 0; } if (len > sizeof curstat.i) { error("ipstat structure has grown--recompile systat!"); return 0; } if (sysctl(name, 4, &initstat.i, &len, 0, 0) < 0) { error("sysctl getting ipstat failed"); return 0; } name[2] = IPPROTO_UDP; name[3] = UDPCTL_STATS; len = 0; if (sysctl(name, 4, 0, &len, 0, 0) < 0) { error("sysctl getting udpstat size failed"); return 0; } if (len > sizeof curstat.u) { error("ipstat structure has grown--recompile systat!"); return 0; } if (sysctl(name, 4, &initstat.u, &len, 0, 0) < 0) { error("sysctl getting udpstat failed"); return 0; } oldstat = initstat; return 1; } void resetip(void) { size_t len; int name[4]; name[0] = CTL_NET; name[1] = PF_INET; name[2] = IPPROTO_IP; name[3] = IPCTL_STATS; len = sizeof initstat.i; if (sysctl(name, 4, &initstat.i, &len, 0, 0) < 0) { error("sysctl getting ipstat failed"); } name[2] = IPPROTO_UDP; name[3] = UDPCTL_STATS; len = sizeof initstat.u; if (sysctl(name, 4, &initstat.u, &len, 0, 0) < 0) { error("sysctl getting udpstat failed"); } oldstat = initstat; } void fetchip(void) { int name[4]; size_t len; oldstat = curstat; name[0] = CTL_NET; name[1] = PF_INET; name[2] = IPPROTO_IP; name[3] = IPCTL_STATS; len = sizeof curstat.i; if (sysctl(name, 4, &curstat.i, &len, 0, 0) < 0) return; name[2] = IPPROTO_UDP; name[3] = UDPCTL_STATS; len = sizeof curstat.u; if (sysctl(name, 4, &curstat.u, &len, 0, 0) < 0) return; } diff --git a/usr.bin/systat/ip6.c b/usr.bin/systat/ip6.c index ac9063f48fce..c7d9d477ada9 100644 --- a/usr.bin/systat/ip6.c +++ b/usr.bin/systat/ip6.c @@ -1,305 +1,302 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)mbufs.c 8.1 (Berkeley) 6/6/93"; #endif /* From: "Id: mbufs.c,v 1.5 1997/02/24 20:59:03 wollman Exp" */ #ifdef INET6 #include #include #include #include #include #include #include #include #include #include #include #include #include "systat.h" #include "extern.h" #include "mode.h" static struct ip6stat curstat, initstat, oldstat; /*- --0 1 2 3 4 5 6 7 --0123456789012345678901234567890123456789012345678901234567890123456789012345 00 IPv6 Input IPv6 Output 019999999 total packets received 999999999 total packets sent 029999999 - too short for header 999999999 - generated locally 039999999 - too short for data 999999999 - output drops 049999999 - with invalid version 999999999 output fragments generated 059999999 total fragments received 999999999 - fragmentation failed 069999999 - fragments dropped 999999999 destinations unreachable 079999999 - fragments timed out 999999999 packets output via raw IP 089999999 - fragments overflown 099999999 - packets reassembled ok Input next-header histogram 109999999 packets forwarded 999999999 - destination options 119999999 - unreachable dests 999999999 - hop-by-hop options 129999999 - redirects generated 999999999 - IPv4 139999999 option errors 999999999 - TCP 149999999 unwanted multicasts 999999999 - UDP 159999999 delivered to upper layer 999999999 - IPv6 169999999 bad scope packets 999999999 - routing header 179999999 address selection failed 999999999 - fragmentation header 18 999999999 - ICMP6 19 999999999 - none --0123456789012345678901234567890123456789012345678901234567890123456789012345 --0 1 2 3 4 5 6 7 */ WINDOW * openip6(void) { return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0)); } void closeip6(WINDOW *w) { if (w == NULL) return; wclear(w); wrefresh(w); delwin(w); } void labelip6(void) { wmove(wnd, 0, 0); wclrtoeol(wnd); #define L(row, str) mvwprintw(wnd, row, 10, str) #define R(row, str) mvwprintw(wnd, row, 45, str); L(0, "IPv6 Input"); R(0, "IPv6 Output"); L(1, "total packets received"); R(1, "total packets sent"); L(2, "- too short for header"); R(2, "- generated locally"); L(3, "- too short for data"); R(3, "- output drops"); L(4, "- with invalid version"); R(4, "output fragments generated"); L(5, "total fragments received"); R(5, "- fragmentation failed"); L(6, "- fragments dropped"); R(6, "destinations unreachable"); L(7, "- fragments timed out"); R(7, "packets output via raw IP"); L(8, "- fragments overflown"); L(9, "- atomic fragments"); R(9, "Input next-header histogram"); L(10, "- packets reassembled ok"); R(10, " - destination options"); L(11, "packets forwarded"); R(11, " - hop-by-hop options"); L(12, "- unreachable dests"); R(12, " - IPv4"); L(13, "- redirects generated"); R(13, " - TCP"); L(14, "option errors"); R(14, " - UDP"); L(15, "unwanted multicasts"); R(15, " - IPv6"); L(16, "delivered to upper layer"); R(16, " - routing header"); L(17, "bad scope packets"); R(17, " - fragmentation header"); L(18, "address selection failed");R(18, " - ICMP6"); R(19, " - none"); #undef L #undef R } static void domode(struct ip6stat *ret) { const struct ip6stat *sub; int divisor = 1, i; switch(currentmode) { case display_RATE: sub = &oldstat; divisor = (delay > 1000000) ? delay / 1000000 : 1; break; case display_DELTA: sub = &oldstat; break; case display_SINCE: sub = &initstat; break; default: *ret = curstat; return; } #define DO(stat) ret->stat = (curstat.stat - sub->stat) / divisor DO(ip6s_total); DO(ip6s_tooshort); DO(ip6s_toosmall); DO(ip6s_fragments); DO(ip6s_fragdropped); DO(ip6s_fragtimeout); DO(ip6s_fragoverflow); DO(ip6s_atomicfrags); DO(ip6s_forward); DO(ip6s_cantforward); DO(ip6s_redirectsent); DO(ip6s_delivered); DO(ip6s_localout); DO(ip6s_odropped); DO(ip6s_reassembled); DO(ip6s_fragmented); DO(ip6s_ofragments); DO(ip6s_cantfrag); DO(ip6s_badoptions); DO(ip6s_noroute); DO(ip6s_badvers); DO(ip6s_rawout); DO(ip6s_notmember); for (i = 0; i < 256; i++) DO(ip6s_nxthist[i]); DO(ip6s_badscope); DO(ip6s_sources_none); #undef DO } void showip6(void) { struct ip6stat stats; uint64_t totalout; domode(&stats); totalout = stats.ip6s_forward + stats.ip6s_localout; #define DO(stat, row, col) \ mvwprintw(wnd, row, col, "%9"PRIu64, stats.stat) DO(ip6s_total, 1, 0); mvwprintw(wnd, 1, 35, "%9"PRIu64, totalout); DO(ip6s_tooshort, 2, 0); DO(ip6s_localout, 2, 35); DO(ip6s_toosmall, 3, 0); DO(ip6s_odropped, 3, 35); DO(ip6s_badvers, 4, 0); DO(ip6s_ofragments, 4, 35); DO(ip6s_fragments, 5, 0); DO(ip6s_cantfrag, 5, 35); DO(ip6s_fragdropped, 6, 0); DO(ip6s_noroute, 6, 35); DO(ip6s_fragtimeout, 7, 0); DO(ip6s_rawout, 7, 35); DO(ip6s_fragoverflow, 8, 0); DO(ip6s_atomicfrags, 9, 0); DO(ip6s_reassembled, 10, 0); DO(ip6s_forward, 11, 0); DO(ip6s_nxthist[IPPROTO_DSTOPTS], 10, 35); DO(ip6s_cantforward, 12, 0); DO(ip6s_nxthist[IPPROTO_HOPOPTS], 11, 35); DO(ip6s_redirectsent, 13, 0); DO(ip6s_nxthist[IPPROTO_IPV4], 12, 35); DO(ip6s_badoptions, 14, 0); DO(ip6s_nxthist[IPPROTO_TCP], 13, 35); DO(ip6s_notmember, 15, 0); DO(ip6s_nxthist[IPPROTO_UDP], 14, 35); DO(ip6s_delivered, 16, 0); DO(ip6s_nxthist[IPPROTO_IPV6], 15, 35); DO(ip6s_badscope, 17, 0); DO(ip6s_nxthist[IPPROTO_ROUTING], 16, 35); DO(ip6s_sources_none, 18, 0); DO(ip6s_nxthist[IPPROTO_FRAGMENT], 17, 35); DO(ip6s_nxthist[IPPROTO_ICMPV6], 18, 35); DO(ip6s_nxthist[IPPROTO_NONE], 19, 35); #undef DO } int initip6(void) { size_t len; int name[4]; name[0] = CTL_NET; name[1] = PF_INET6; name[2] = IPPROTO_IPV6; name[3] = IPV6CTL_STATS; len = 0; if (sysctl(name, 4, 0, &len, 0, 0) < 0) { error("sysctl getting ip6stat size failed"); return 0; } if (len > sizeof curstat) { error("ip6stat structure has grown--recompile systat!"); return 0; } if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) { error("sysctl getting ip6stat failed"); return 0; } oldstat = initstat; return 1; } void resetip6(void) { size_t len; int name[4]; name[0] = CTL_NET; name[1] = PF_INET6; name[2] = IPPROTO_IPV6; name[3] = IPV6CTL_STATS; len = sizeof initstat; if (sysctl(name, 4, &initstat, &len, 0, 0) < 0) { error("sysctl getting ipstat failed"); } oldstat = initstat; } void fetchip6(void) { int name[4]; size_t len; oldstat = curstat; name[0] = CTL_NET; name[1] = PF_INET6; name[2] = IPPROTO_IPV6; name[3] = IPV6CTL_STATS; len = sizeof curstat; if (sysctl(name, 4, &curstat, &len, 0, 0) < 0) return; } #endif diff --git a/usr.bin/systat/keyboard.c b/usr.bin/systat/keyboard.c index a3401506c5ce..aac7d1a2bb79 100644 --- a/usr.bin/systat/keyboard.c +++ b/usr.bin/systat/keyboard.c @@ -1,182 +1,179 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)keyboard.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include #include "systat.h" #include "extern.h" static char line[80]; static int keyboard_dispatch(int ch); int keyboard(void) { int ch, n; struct timeval last, intvl, now, tm; fd_set rfds; /* Set initial timings */ gettimeofday(&last, NULL); intvl.tv_sec = delay / 1000000; intvl.tv_usec = delay % 1000000; for (;;) { col = 0; move(CMDLINE, 0); for (;;) { /* Determine interval to sleep */ (void)gettimeofday(&now, NULL); tm.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec; tm.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec; while (tm.tv_usec < 0) { tm.tv_usec += 1000000; tm.tv_sec--; } while (tm.tv_usec >= 1000000) { tm.tv_usec -= 1000000; tm.tv_sec++; } if (tm.tv_sec < 0) { /* We have to update screen immediately */ display(); gettimeofday(&last, NULL); continue; } /* Prepare select */ FD_ZERO(&rfds); FD_SET(STDIN_FILENO, &rfds); n = select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tm); if (n > 0) { /* Read event on stdin */ ch = getch(); if (keyboard_dispatch(ch) == 0) { refresh(); continue; } line[col] = '\0'; command(line + 1); /* Refresh delay */ intvl.tv_sec = delay / 1000000; intvl.tv_usec = delay % 1000000; refresh(); break; } if (n < 0 && errno != EINTR) exit(1); /* Timeout or signal. Call display another time */ display(); gettimeofday(&last, NULL); } } } static int keyboard_dispatch(int ch) { if (ch == ERR) { if (errno == EINTR) return 0; exit(1); } if (ch >= 'A' && ch <= 'Z') ch += 'a' - 'A'; if (col == 0) { if (ch == CTRL('l')) { wrefresh(curscr); return 0; } if (ch == CTRL('g')) { status(); return 0; } if (ch != ':') return 0; move(CMDLINE, 0); clrtoeol(); } if (ch == erasechar() && col > 0) { if (col == 1 && line[0] == ':') return 0; col--; goto doerase; } if (ch == CTRL('w') && col > 0) { while (--col >= 0 && isspace(line[col])) ; col++; while (--col >= 0 && !isspace(line[col])) if (col == 0 && line[0] == ':') return 1; col++; goto doerase; } if (ch == killchar() && col > 0) { col = 0; if (line[0] == ':') col++; doerase: move(CMDLINE, col); clrtoeol(); return 0; } if (isprint(ch) || ch == ' ') { line[col] = ch; mvaddch(CMDLINE, col, ch); col++; } if (col == 0 || (ch != '\r' && ch != '\n')) return 0; return 1; } diff --git a/usr.bin/systat/main.c b/usr.bin/systat/main.c index 7fdab312830e..e6fc79b7ba59 100644 --- a/usr.bin/systat/main.c +++ b/usr.bin/systat/main.c @@ -1,388 +1,385 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "systat.h" #include "extern.h" static int dellave; kvm_t *kd; sig_t sigtstpdfl; double avenrun[3]; int col; unsigned int delay = 5000000; /* in microseconds */ int verbose = 1; /* to report kvm read errs */ struct clockinfo clkinfo; double hertz; char c; char *namp; char hostname[MAXHOSTNAMELEN]; WINDOW *wnd; int CMDLINE; int use_kvm = 1; static WINDOW *wload; /* one line window for load average */ struct cmdentry { SLIST_ENTRY(cmdentry) link; char *cmd; /* Command name */ char *argv; /* Arguments vector for a command */ }; SLIST_HEAD(, cmdentry) commands; static void parse_cmd_args (int argc, char **argv) { int in_command = 0; struct cmdentry *cmd = NULL; double t; while (argc) { if (argv[0][0] == '-') { if (in_command) SLIST_INSERT_HEAD(&commands, cmd, link); if (memcmp(argv[0], "--", 3) == 0) { in_command = 0; /*-- ends a command explicitly*/ argc --, argv ++; continue; } cmd = calloc(1, sizeof(struct cmdentry)); if (cmd == NULL) errx(1, "memory allocating failure"); cmd->cmd = strdup(&argv[0][1]); if (cmd->cmd == NULL) errx(1, "memory allocating failure"); in_command = 1; } else if (!in_command) { t = strtod(argv[0], NULL) * 1000000.0; if (t > 0 && t < (double)UINT_MAX) delay = (unsigned int)t; } else if (cmd != NULL) { cmd->argv = strdup(argv[0]); if (cmd->argv == NULL) errx(1, "memory allocating failure"); in_command = 0; SLIST_INSERT_HEAD(&commands, cmd, link); } else errx(1, "invalid arguments list"); argc--, argv++; } if (in_command && cmd != NULL) SLIST_INSERT_HEAD(&commands, cmd, link); } static void resize(int signo __unused) { endwin(); refresh(); clear(); CMDLINE = LINES - 1; labels(); display(); status(); } int main(int argc, char **argv) { char errbuf[_POSIX2_LINE_MAX], dummy; size_t size; struct cmdentry *cmd = NULL; (void) setlocale(LC_ALL, ""); SLIST_INIT(&commands); argc--, argv++; if (argc > 0) { if (argv[0][0] == '-') { struct cmdtab *p; p = lookup(&argv[0][1]); if (p == (struct cmdtab *)-1) errx(1, "%s: ambiguous request", &argv[0][1]); if (p == (struct cmdtab *)0) errx(1, "%s: unknown request", &argv[0][1]); curcmd = p; argc--, argv++; } parse_cmd_args (argc, argv); } kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); if (kd != NULL) { /* * Try to actually read something, we may be in a jail, and * have /dev/null opened as /dev/mem. */ if (kvm_nlist(kd, namelist) != 0 || namelist[0].n_value == 0 || kvm_read(kd, namelist[0].n_value, &dummy, sizeof(dummy)) != sizeof(dummy)) { kvm_close(kd); kd = NULL; } } if (kd == NULL) { /* * Maybe we are lacking permissions? Retry, this time with bogus * devices. We can now use sysctl only. */ use_kvm = 0; kd = kvm_openfiles(_PATH_DEVNULL, _PATH_DEVNULL, _PATH_DEVNULL, O_RDONLY, errbuf); if (kd == NULL) { error("%s", errbuf); exit(1); } } signal(SIGHUP, die); signal(SIGINT, die); signal(SIGQUIT, die); signal(SIGTERM, die); signal(SIGWINCH, resize); /* * Initialize display. Load average appears in a one line * window of its own. Current command's display appears in * an overlapping sub-window of stdscr configured by the display * routines to minimize update work by curses. */ initscr(); CMDLINE = LINES - 1; wnd = (*curcmd->c_open)(); if (wnd == NULL) { warnx("couldn't initialize display"); die(0); } wload = newwin(1, 0, 1, 20); if (wload == NULL) { warnx("couldn't set up load average window"); die(0); } gethostname(hostname, sizeof (hostname)); size = sizeof(clkinfo); if (sysctlbyname("kern.clockrate", &clkinfo, &size, NULL, 0) || size != sizeof(clkinfo)) { error("kern.clockrate"); die(0); } hertz = clkinfo.stathz; (*curcmd->c_init)(); curcmd->c_flags |= CF_INIT; labels(); if (curcmd->c_cmd != NULL) SLIST_FOREACH (cmd, &commands, link) if (!curcmd->c_cmd(cmd->cmd, cmd->argv)) warnx("command is not understood"); dellave = 0.0; display(); noecho(); crmode(); keyboard(); /*NOTREACHED*/ return EXIT_SUCCESS; } void labels(void) { if (curcmd->c_flags & CF_LOADAV) { mvaddstr(0, 20, "/0 /1 /2 /3 /4 /5 /6 /7 /8 /9 /10"); mvaddstr(1, 5, "Load Average"); } if (curcmd->c_flags & CF_ZFSARC) { mvaddstr(0, 20, " Total MFU MRU Anon Hdr L2Hdr Other"); mvaddstr(1, 5, "ZFS ARC "); } (*curcmd->c_label)(); #ifdef notdef mvprintw(21, 25, "CPU usage on %s", hostname); #endif refresh(); } void display(void) { uint64_t arc_stat; int i, j; /* Get the load average over the last minute. */ (void) getloadavg(avenrun, nitems(avenrun)); (*curcmd->c_fetch)(); if (curcmd->c_flags & CF_LOADAV) { j = 5.0*avenrun[0] + 0.5; dellave -= avenrun[0]; if (dellave >= 0.0) c = '<'; else { c = '>'; dellave = -dellave; } if (dellave < 0.1) c = '|'; dellave = avenrun[0]; wmove(wload, 0, 0); wclrtoeol(wload); for (i = MIN(j, 50); i > 0; i--) waddch(wload, c); if (j > 50) wprintw(wload, " %4.1f", avenrun[0]); } if (curcmd->c_flags & CF_ZFSARC) { uint64_t arc[7] = {}; size_t size = sizeof(arc[0]); if (sysctlbyname("kstat.zfs.misc.arcstats.size", &arc[0], &size, NULL, 0) == 0 ) { GETSYSCTL("vfs.zfs.mfu_size", arc[1]); GETSYSCTL("vfs.zfs.mru_size", arc[2]); GETSYSCTL("vfs.zfs.anon_size", arc[3]); GETSYSCTL("kstat.zfs.misc.arcstats.hdr_size", arc[4]); GETSYSCTL("kstat.zfs.misc.arcstats.l2_hdr_size", arc[5]); GETSYSCTL("kstat.zfs.misc.arcstats.bonus_size", arc[6]); GETSYSCTL("kstat.zfs.misc.arcstats.dnode_size", arc_stat); arc[6] += arc_stat; GETSYSCTL("kstat.zfs.misc.arcstats.dbuf_size", arc_stat); arc[6] += arc_stat; wmove(wload, 0, 0); wclrtoeol(wload); for (i = 0 ; i < nitems(arc); i++) sysputuint64(wload, 0, i*8+2, 6, arc[i], 0); } } (*curcmd->c_refresh)(); if (curcmd->c_flags & (CF_LOADAV |CF_ZFSARC)) wrefresh(wload); wrefresh(wnd); move(CMDLINE, col); refresh(); } void load(void) { (void) getloadavg(avenrun, nitems(avenrun)); mvprintw(CMDLINE, 0, "%4.1f %4.1f %4.1f", avenrun[0], avenrun[1], avenrun[2]); clrtoeol(); } void die(int signo __unused) { move(CMDLINE, 0); clrtoeol(); refresh(); endwin(); exit(0); } #include void error(const char *fmt, ...) { va_list ap; char buf[255]; int oy, ox; va_start(ap, fmt); if (wnd) { getyx(stdscr, oy, ox); (void) vsnprintf(buf, sizeof(buf), fmt, ap); clrtoeol(); standout(); mvaddstr(CMDLINE, 0, buf); standend(); move(oy, ox); refresh(); } else { (void) vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); } va_end(ap); } void nlisterr(struct nlist n_list[]) { int i, n; n = 0; clear(); mvprintw(2, 10, "systat: nlist: can't find following symbols:"); for (i = 0; n_list[i].n_name != NULL && *n_list[i].n_name != '\0'; i++) if (n_list[i].n_value == 0) mvprintw(2 + ++n, 10, "%s", n_list[i].n_name); move(CMDLINE, 0); clrtoeol(); refresh(); endwin(); exit(1); } diff --git a/usr.bin/systat/mode.c b/usr.bin/systat/mode.c index a3fdf46c3b5d..28bc47a92351 100644 --- a/usr.bin/systat/mode.c +++ b/usr.bin/systat/mode.c @@ -1,99 +1,96 @@ /* * Copyright 1997 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that both the above copyright notice and this * permission notice appear in all copies, that both the above * copyright notice and this permission notice appear in all * supporting documentation, and that the name of M.I.T. not be used * in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. M.I.T. makes * no representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied * warranty. * * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * mode.c - mechanisms for dealing with SGI-style modal displays. * * There are four generally-understood useful modes for status displays * of the sort exemplified by the IRIX ``netstat -C'' and ``osview'' * programs. We try to follow their example, although the user interface * and terminology slightly differ. * * RATE - the default mode - displays the precise rate of change in * each statistic in units per second, regardless of the actual display * update interval. * * DELTA - displays the change in each statistic over the entire * display update interval (i.e., RATE * interval). * * SINCE - displays the total change in each statistic since the module * was last initialized or reset. * * ABSOLUTE - displays the current value of each statistic. * * In the SGI programs, these modes are selected by the single-character * commands D, W, N, and A. In systat, they are the slightly-harder-to-type * ``mode delta'', etc. The initial value for SINCE mode is initialized * when the module is first started and can be reset using the ``reset'' * command (as opposed to the SGI way where changing modes implicitly * resets). A ``mode'' command with no arguments displays the current * mode in the command line. */ -#include - -__FBSDID("$FreeBSD$"); #include #include "systat.h" #include "extern.h" #include "mode.h" enum mode currentmode = display_RATE; static const char *const modes[] = { "rate", "delta", "since", "absolute" }; int cmdmode(const char *cmd, const char *args) { if (prefix(cmd, "mode")) { if (args[0] == '\0') { move(CMDLINE, 0); clrtoeol(); printw("%s", modes[currentmode]); } else if (prefix(args, "rate")) { currentmode = display_RATE; } else if (prefix(args, "delta")) { currentmode = display_DELTA; } else if (prefix(args, "since")) { currentmode = display_SINCE; } else if (prefix(args, "absolute")) { currentmode = display_ABS; } else { printw("unknown mode `%s'", args); } return 1; } if(prefix(cmd, "reset")) { curcmd->c_reset(); return 1; } return 0; } diff --git a/usr.bin/systat/netcmds.c b/usr.bin/systat/netcmds.c index 8d5e48fdeb52..6320dd21562d 100644 --- a/usr.bin/systat/netcmds.c +++ b/usr.bin/systat/netcmds.c @@ -1,310 +1,307 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)netcmds.c 8.1 (Berkeley) 6/6/93"; #endif /* * Common network command support routines. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "systat.h" #include "extern.h" #define streq(a,b) (strcmp(a,b)==0) static struct hitem { struct in_addr addr; int onoff; } *hosts; int nports, nhosts, protos; static void changeitems(const char *, int); static int selectproto(const char *); static void showprotos(void); static int selectport(long, int); static void showports(void); static int selecthost(struct in_addr *, int); static void showhosts(void); int netcmd(const char *cmd, const char *args) { if (prefix(cmd, "proto")) { if (*args == '\0') { move(CMDLINE, 0); clrtoeol(); addstr("which proto?"); } else if (!selectproto(args)) { error("%s: Unknown protocol.", args); } return (1); } if (prefix(cmd, "ignore") || prefix(cmd, "display")) { changeitems(args, prefix(cmd, "display")); return (1); } if (prefix(cmd, "reset")) { selectproto(0); selecthost(0, 0); selectport(-1, 0); return (1); } if (prefix(cmd, "show")) { move(CMDLINE, 0); clrtoeol(); if (*args == '\0') { showprotos(); showhosts(); showports(); return (1); } if (prefix(args, "protos")) showprotos(); else if (prefix(args, "hosts")) showhosts(); else if (prefix(args, "ports")) showports(); else addstr("show what?"); return (1); } return (0); } static void changeitems(const char *args, int onoff) { char *cp, *tmpstr, *tmpstr1; struct servent *sp; struct hostent *hp; struct in_addr in; tmpstr = tmpstr1 = strdup(args); cp = strchr(tmpstr1, '\n'); if (cp) *cp = '\0'; for (;;tmpstr1 = cp) { for (cp = tmpstr1; *cp && isspace(*cp); cp++) ; tmpstr1 = cp; for (; *cp && !isspace(*cp); cp++) ; if (*cp) *cp++ = '\0'; if (cp - tmpstr1 == 0) break; sp = getservbyname(tmpstr1, protos == TCP ? "tcp" : protos == UDP ? "udp" : 0); if (sp) { selectport(sp->s_port, onoff); continue; } hp = gethostbyname(tmpstr1); if (hp == NULL) { in.s_addr = inet_addr(tmpstr1); if (in.s_addr == INADDR_NONE) { error("%s: unknown host or port", tmpstr1); continue; } } else in = *(struct in_addr *)hp->h_addr; selecthost(&in, onoff); } free(tmpstr); } static int selectproto(const char *proto) { if (proto == NULL || streq(proto, "all")) protos = TCP | UDP; else if (streq(proto, "tcp")) protos = TCP; else if (streq(proto, "udp")) protos = UDP; else return (0); return (protos); } static void showprotos(void) { if ((protos&TCP) == 0) addch('!'); addstr("tcp "); if ((protos&UDP) == 0) addch('!'); addstr("udp "); } static struct pitem { long port; int onoff; } *ports; static int selectport(long port, int onoff) { struct pitem *p; if (port == -1) { if (ports == NULL) return (0); free((char *)ports), ports = 0; nports = 0; return (1); } for (p = ports; p < ports + nports; p++) if (p->port == port) { p->onoff = onoff; return (0); } if (nports == 0) ports = (struct pitem *)malloc(sizeof (*p)); else ports = (struct pitem *)realloc(ports, (nports+1)*sizeof (*p)); p = &ports[nports++]; p->port = port; p->onoff = onoff; return (1); } int checkport(struct in_conninfo *inc) { struct pitem *p; if (ports) for (p = ports; p < ports+nports; p++) if (p->port == inc->inc_lport || p->port == inc->inc_fport) return (p->onoff); return (1); } static void showports(void) { struct pitem *p; struct servent *sp; for (p = ports; p < ports+nports; p++) { sp = getservbyport(p->port, protos == (TCP|UDP) ? 0 : protos == TCP ? "tcp" : "udp"); if (!p->onoff) addch('!'); if (sp) printw("%s ", sp->s_name); else printw("%d ", p->port); } } static int selecthost(struct in_addr *in, int onoff) { struct hitem *p; if (in == NULL) { if (hosts == NULL) return (0); free((char *)hosts), hosts = 0; nhosts = 0; return (1); } for (p = hosts; p < hosts+nhosts; p++) if (p->addr.s_addr == in->s_addr) { p->onoff = onoff; return (0); } if (nhosts == 0) hosts = (struct hitem *)malloc(sizeof (*p)); else hosts = (struct hitem *)realloc(hosts, (nhosts+1)*sizeof (*p)); p = &hosts[nhosts++]; p->addr = *in; p->onoff = onoff; return (1); } int checkhost(struct in_conninfo *inc) { struct hitem *p; if (hosts) for (p = hosts; p < hosts+nhosts; p++) if (p->addr.s_addr == inc->inc_laddr.s_addr || p->addr.s_addr == inc->inc_faddr.s_addr) return (p->onoff); return (1); } static void showhosts(void) { struct hitem *p; struct hostent *hp; for (p = hosts; p < hosts+nhosts; p++) { hp = gethostbyaddr((char *)&p->addr, sizeof (p->addr), AF_INET); if (!p->onoff) addch('!'); printw("%s ", hp ? hp->h_name : (char *)inet_ntoa(p->addr)); } } diff --git a/usr.bin/systat/netstat.c b/usr.bin/systat/netstat.c index a9487c4dcc9d..fc8e05a6b107 100644 --- a/usr.bin/systat/netstat.c +++ b/usr.bin/systat/netstat.c @@ -1,649 +1,646 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)netstat.c 8.1 (Berkeley) 6/6/93"; #endif /* * netstat */ #include #include #include #define _WANT_SOCKET #include #include #include #include #include #include #include #ifdef INET6 #include #endif #define _WANT_INPCB #include #include #include #include #include #include #include #define TCPSTATES #include #include #define _WANT_TCPCB #include #include #include #include #include #include #include #include #include #include "systat.h" #include "extern.h" static struct netinfo *enter(struct in_conninfo *, uint8_t, int, const char *); static void enter_kvm(struct inpcb *, struct socket *, int, const char *); static void enter_sysctl(struct xinpcb *, struct xsocket *, int, const char *); static void fetchnetstat_kvm(void); static void fetchnetstat_sysctl(void); static char *inetname(struct sockaddr *); static void inetprint(struct sockaddr *, const char *); #define streq(a,b) (strcmp(a,b)==0) #define YMAX(w) (getmaxy(w)-2) WINDOW * opennetstat(void) { sethostent(1); setnetent(1); return (subwin(stdscr, LINES-3-1, 0, MAINWIN_ROW, 0)); } struct netinfo { TAILQ_ENTRY(netinfo) chain; short ni_line; /* line on screen */ short ni_seen; /* 0 when not present in list */ short ni_flags; #define NIF_LACHG 0x1 /* local address changed */ #define NIF_FACHG 0x2 /* foreign address changed */ short ni_state; /* tcp state */ const char *ni_proto; /* protocol */ struct sockaddr_storage ni_lsa; /* local address */ struct sockaddr_storage ni_fsa; /* foreign address */ u_int ni_rcvcc; /* rcv buffer character count */ u_int ni_sndcc; /* snd buffer character count */ }; TAILQ_HEAD(netinfohead, netinfo) netcb = TAILQ_HEAD_INITIALIZER(netcb); static int aflag = 0; static int nflag = 0; static int lastrow = 1; void closenetstat(WINDOW *w) { struct netinfo *p; endhostent(); endnetent(); TAILQ_FOREACH(p, &netcb, chain) { if (p->ni_line != -1) lastrow--; p->ni_line = -1; } if (w != NULL) { wclear(w); wrefresh(w); delwin(w); } } static const char *miblist[] = { "net.inet.tcp.pcblist", "net.inet.udp.pcblist" }; static char tcb[] = "tcb", udb[] = "udb"; struct nlist namelist[] = { #define X_TCB 0 { .n_name = tcb }, #define X_UDB 1 { .n_name = udb }, { .n_name = NULL }, }; int initnetstat(void) { protos = TCP|UDP; return(1); } void fetchnetstat(void) { if (use_kvm) fetchnetstat_kvm(); else fetchnetstat_sysctl(); } static void fetchnetstat_kvm(void) { struct inpcb *next; struct netinfo *p; struct inpcbhead head; struct inpcb inpcb; struct socket sockb; struct tcpcb tcpcb; void *off; int istcp; if (namelist[X_TCB].n_value == 0) return; TAILQ_FOREACH(p, &netcb, chain) p->ni_seen = 0; if (protos&TCP) { off = NPTR(X_TCB); istcp = 1; } else if (protos&UDP) { off = NPTR(X_UDB); istcp = 0; } else { error("No protocols to display"); return; } again: KREAD(off, &head, sizeof (struct inpcbhead)); LIST_FOREACH(next, &head, inp_list) { KREAD(next, &inpcb, sizeof (inpcb)); next = &inpcb; if (!aflag) { if (inpcb.inp_vflag & INP_IPV4) { if (inpcb.inp_laddr.s_addr == INADDR_ANY) continue; } #ifdef INET6 else if (inpcb.inp_vflag & INP_IPV6) { if (memcmp(&inpcb.in6p_laddr, &in6addr_any, sizeof(in6addr_any)) == 0) continue; } #endif } if (nhosts && !checkhost(&inpcb.inp_inc)) continue; if (nports && !checkport(&inpcb.inp_inc)) continue; if (istcp) { if (inpcb.inp_flags & INP_TIMEWAIT) { bzero(&sockb, sizeof(sockb)); enter_kvm(&inpcb, &sockb, TCPS_TIME_WAIT, "tcp"); } else { KREAD(inpcb.inp_socket, &sockb, sizeof (sockb)); KREAD(inpcb.inp_ppcb, &tcpcb, sizeof (tcpcb)); enter_kvm(&inpcb, &sockb, tcpcb.t_state, "tcp"); } } else enter_kvm(&inpcb, &sockb, 0, "udp"); } if (istcp && (protos&UDP)) { istcp = 0; off = NPTR(X_UDB); goto again; } } static void fetchnetstat_sysctl(void) { struct netinfo *p; int idx; struct xinpgen *inpg; char *cur, *end; struct xinpcb *xip = NULL; struct xtcpcb *xtp = NULL; int plen; size_t lsz; TAILQ_FOREACH(p, &netcb, chain) p->ni_seen = 0; if (protos&TCP) { idx = 0; } else if (protos&UDP) { idx = 1; } else { error("No protocols to display"); return; } for (;idx < 2; idx++) { if (idx == 1 && !(protos&UDP)) break; inpg = (struct xinpgen *)sysctl_dynread(miblist[idx], &lsz); if (inpg == NULL) { error("sysctl(%s...) failed", miblist[idx]); continue; } /* * We currently do no require a consistent pcb list. * Try to be robust in case of struct size changes */ cur = ((char *)inpg) + inpg->xig_len; /* There is also a trailing struct xinpgen */ end = ((char *)inpg) + lsz - inpg->xig_len; if (end <= cur) { free(inpg); continue; } if (idx == 0) { /* TCP */ xtp = (struct xtcpcb *)cur; plen = xtp->xt_len; } else { xip = (struct xinpcb *)cur; plen = xip->xi_len; } while (cur + plen <= end) { if (idx == 0) { /* TCP */ xtp = (struct xtcpcb *)cur; xip = &xtp->xt_inp; } else { xip = (struct xinpcb *)cur; } cur += plen; if (!aflag) { if (xip->inp_vflag & INP_IPV4) { if (xip->inp_laddr.s_addr == INADDR_ANY) continue; } #ifdef INET6 else if (xip->inp_vflag & INP_IPV6) { if (memcmp(&xip->in6p_laddr, &in6addr_any, sizeof(in6addr_any)) == 0) continue; } #endif } if (nhosts && !checkhost(&xip->inp_inc)) continue; if (nports && !checkport(&xip->inp_inc)) continue; if (idx == 0) enter_sysctl(xip, &xip->xi_socket, xtp->t_state, "tcp"); else enter_sysctl(xip, &xip->xi_socket, 0, "udp"); } free(inpg); } } static void enter_kvm(struct inpcb *inp, struct socket *so, int state, const char *proto) { struct netinfo *p; if ((p = enter(&inp->inp_inc, inp->inp_vflag, state, proto)) != NULL) { p->ni_rcvcc = so->so_rcv.sb_ccc; p->ni_sndcc = so->so_snd.sb_ccc; } } static void enter_sysctl(struct xinpcb *xip, struct xsocket *so, int state, const char *proto) { struct netinfo *p; if ((p = enter(&xip->inp_inc, xip->inp_vflag, state, proto)) != NULL) { p->ni_rcvcc = so->so_rcv.sb_cc; p->ni_sndcc = so->so_snd.sb_cc; } } static struct netinfo * enter(struct in_conninfo *inc, uint8_t vflag, int state, const char *proto) { struct netinfo *p; struct sockaddr_storage lsa, fsa; struct sockaddr_in *sa4; #ifdef INET6 struct sockaddr_in6 *sa6; #endif memset(&lsa, 0, sizeof(lsa)); memset(&fsa, 0, sizeof(fsa)); if (vflag & INP_IPV4) { sa4 = (struct sockaddr_in *)&lsa; sa4->sin_addr = inc->inc_laddr; sa4->sin_port = inc->inc_lport; sa4->sin_family = AF_INET; sa4->sin_len = sizeof(struct sockaddr_in); sa4 = (struct sockaddr_in *)&fsa; sa4->sin_addr = inc->inc_faddr; sa4->sin_port = inc->inc_fport; sa4->sin_family = AF_INET; sa4->sin_len = sizeof(struct sockaddr_in); } #ifdef INET6 else if (vflag & INP_IPV6) { sa6 = (struct sockaddr_in6 *)&lsa; memcpy(&sa6->sin6_addr, &inc->inc6_laddr, sizeof(struct in6_addr)); sa6->sin6_port = inc->inc_lport; sa6->sin6_family = AF_INET6; sa6->sin6_len = sizeof(struct sockaddr_in6); sa6 = (struct sockaddr_in6 *)&fsa; memcpy(&sa6->sin6_addr, &inc->inc6_faddr, sizeof(struct in6_addr)); sa6->sin6_port = inc->inc_fport; sa6->sin6_family = AF_INET6; sa6->sin6_len = sizeof(struct sockaddr_in6); } #endif else return NULL; /* * Only take exact matches, any sockets with * previously unbound addresses will be deleted * below in the display routine because they * will appear as ``not seen'' in the kernel * data structures. */ TAILQ_FOREACH(p, &netcb, chain) { if (!streq(proto, p->ni_proto)) continue; if (p->ni_lsa.ss_family != lsa.ss_family || memcmp(&p->ni_lsa, &lsa, lsa.ss_len) != 0) continue; if (p->ni_fsa.ss_family == fsa.ss_family && memcmp(&p->ni_fsa, &fsa, fsa.ss_len) == 0) break; } if (p == NULL) { if ((p = malloc(sizeof(*p))) == NULL) { error("Out of memory"); return NULL; } TAILQ_INSERT_HEAD(&netcb, p, chain); p->ni_line = -1; memcpy(&p->ni_lsa, &lsa, lsa.ss_len); memcpy(&p->ni_fsa, &fsa, fsa.ss_len); p->ni_proto = strdup(proto); p->ni_flags = NIF_LACHG|NIF_FACHG; } p->ni_state = state; p->ni_seen = 1; return p; } /* column locations */ #define LADDR 0 #define FADDR LADDR+23 #define PROTO FADDR+23 #define RCVCC PROTO+6 #define SNDCC RCVCC+7 #define STATE SNDCC+7 void labelnetstat(void) { if (use_kvm && namelist[X_TCB].n_type == 0) return; wmove(wnd, 0, 0); wclrtobot(wnd); mvwaddstr(wnd, 0, LADDR, "Local Address"); mvwaddstr(wnd, 0, FADDR, "Foreign Address"); mvwaddstr(wnd, 0, PROTO, "Proto"); mvwaddstr(wnd, 0, RCVCC, "Recv-Q"); mvwaddstr(wnd, 0, SNDCC, "Send-Q"); mvwaddstr(wnd, 0, STATE, "(state)"); } void shownetstat(void) { struct netinfo *p, *q; char proto[6]; const char *family = ""; /* * First, delete any connections that have gone * away and adjust the position of connections * below to reflect the deleted line. */ p = TAILQ_FIRST(&netcb); while (p != NULL) { if (p->ni_line == -1 || p->ni_seen) { p = TAILQ_NEXT(p, chain); continue; } wmove(wnd, p->ni_line, 0); wdeleteln(wnd); TAILQ_FOREACH(q, &netcb, chain) if (q != p && q->ni_line > p->ni_line) { q->ni_line--; /* this shouldn't be necessary */ q->ni_flags |= NIF_LACHG|NIF_FACHG; } lastrow--; q = TAILQ_NEXT(p, chain); TAILQ_REMOVE(&netcb, p, chain); free(p); p = q; } /* * Update existing connections and add new ones. */ TAILQ_FOREACH(p, &netcb, chain) { if (p->ni_line == -1) { /* * Add a new entry if possible. */ if (lastrow > YMAX(wnd)) continue; p->ni_line = lastrow++; p->ni_flags |= NIF_LACHG|NIF_FACHG; } if (p->ni_flags & NIF_LACHG) { wmove(wnd, p->ni_line, LADDR); inetprint((struct sockaddr *)&p->ni_lsa, p->ni_proto); p->ni_flags &= ~NIF_LACHG; } if (p->ni_flags & NIF_FACHG) { wmove(wnd, p->ni_line, FADDR); inetprint((struct sockaddr *)&p->ni_fsa, p->ni_proto); p->ni_flags &= ~NIF_FACHG; } #ifdef INET6 family = (p->ni_lsa.ss_family == AF_INET) ? "4" : "6"; #endif snprintf(proto, sizeof(proto), "%s%s", p->ni_proto, family); mvwaddstr(wnd, p->ni_line, PROTO, proto); mvwprintw(wnd, p->ni_line, RCVCC, "%6u", p->ni_rcvcc); mvwprintw(wnd, p->ni_line, SNDCC, "%6u", p->ni_sndcc); if (streq(p->ni_proto, "tcp")) { if (p->ni_state < 0 || p->ni_state >= TCP_NSTATES) mvwprintw(wnd, p->ni_line, STATE, "%d", p->ni_state); else mvwaddstr(wnd, p->ni_line, STATE, tcpstates[p->ni_state]); } wclrtoeol(wnd); } if (lastrow < YMAX(wnd)) { wmove(wnd, lastrow, 0); wclrtobot(wnd); wmove(wnd, YMAX(wnd), 0); wdeleteln(wnd); /* XXX */ } } /* * Pretty print an Internet address (net address + port). * If the nflag was specified, use numbers instead of names. */ static void inetprint(struct sockaddr *sa, const char *proto) { struct servent *sp = 0; char line[80], *cp; int port; switch (sa->sa_family) { case AF_INET: port = ((struct sockaddr_in *)sa)->sin_port; break; #ifdef INET6 case AF_INET6: port = ((struct sockaddr_in6 *)sa)->sin6_port; break; #endif default: port = 0; break; } snprintf(line, sizeof(line), "%.*s.", 16, inetname(sa)); cp = strchr(line, '\0'); if (!nflag && port) sp = getservbyport(port, proto); if (sp || port == 0) snprintf(cp, sizeof(line) - (cp - line), "%.8s", sp ? sp->s_name : "*"); else snprintf(cp, sizeof(line) - (cp - line), "%d", ntohs((u_short)port)); /* pad to full column to clear any garbage */ cp = strchr(line, '\0'); while (cp - line < 22) *cp++ = ' '; line[22] = '\0'; waddstr(wnd, line); } /* * Construct an Internet address representation. * If the nflag has been supplied, give * numeric value, otherwise try for symbolic name. */ static char * inetname(struct sockaddr *sa) { char *cp = 0; static char line[NI_MAXHOST]; struct hostent *hp; struct in_addr in; #ifdef INET6 if (sa->sa_family == AF_INET6) { if (memcmp(&((struct sockaddr_in6 *)sa)->sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0) strcpy(line, "*"); else getnameinfo(sa, sa->sa_len, line, sizeof(line), NULL, 0, nflag ? NI_NUMERICHOST : 0); return (line); } #endif in = ((struct sockaddr_in *)sa)->sin_addr; if (!nflag && in.s_addr != INADDR_ANY) { hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET); if (hp) cp = hp->h_name; } if (in.s_addr == INADDR_ANY) strcpy(line, "*"); else if (cp) snprintf(line, sizeof(line), "%s", cp); else { in.s_addr = ntohl(in.s_addr); #define C(x) ((x) & 0xff) snprintf(line, sizeof(line), "%u.%u.%u.%u", C(in.s_addr >> 24), C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); } return (line); } int cmdnetstat(const char *cmd, const char *args) { if (prefix(cmd, "all")) { aflag = !aflag; goto fixup; } if (prefix(cmd, "numbers") || prefix(cmd, "names")) { struct netinfo *p; int new; new = prefix(cmd, "numbers"); if (new == nflag) return (1); TAILQ_FOREACH(p, &netcb, chain) { if (p->ni_line == -1) continue; p->ni_flags |= NIF_LACHG|NIF_FACHG; } nflag = new; goto redisplay; } if (!netcmd(cmd, args)) return (0); fixup: fetchnetstat(); redisplay: shownetstat(); refresh(); return (1); } diff --git a/usr.bin/systat/swap.c b/usr.bin/systat/swap.c index 19374918ff68..5aa9e3fe0363 100644 --- a/usr.bin/systat/swap.c +++ b/usr.bin/systat/swap.c @@ -1,183 +1,180 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1992, 1993 * The Regents of the University of California. All rights reserved. * Copyright (c) 2017, 2020 Yoshihiro Ota * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)swap.c 8.3 (Berkeley) 4/29/95"; #endif /* * swapinfo - based on a program of the same name by Kevin Lahey */ #include #include #include #include #include #include #include #include #include #include #include "systat.h" #include "extern.h" #include "devs.h" static int pathlen; WINDOW * openswap(void) { return (subwin(stdscr, LINES - 3 - 1, 0, MAINWIN_ROW, 0)); } void closeswap(WINDOW *w) { if (w == NULL) return; wclear(w); wrefresh(w); delwin(w); } /* * The meat of all the swap stuff is stolen from pstat(8)'s * swapmode(), which is based on a program called swapinfo written by * Kevin Lahey . */ #define NSWAP 16 static struct kvm_swap kvmsw[NSWAP]; static int kvnsw, okvnsw; int initswap(void) { static int once = 0; if (once) return (1); if ((kvnsw = kvm_getswapinfo(kd, kvmsw, NSWAP, 0)) < 0) { error("systat: kvm_getswapinfo failed"); return (0); } pathlen = 80 - 50 /* % */ - 5 /* Used */ - 5 /* Size */ - 3 /* space */; dsinit(12); procinit(); once = 1; return (1); } void fetchswap(void) { okvnsw = kvnsw; if ((kvnsw = kvm_getswapinfo(kd, kvmsw, NSWAP, 0)) < 0) { error("systat: kvm_getswapinfo failed"); return; } struct devinfo *tmp_dinfo; tmp_dinfo = last_dev.dinfo; last_dev.dinfo = cur_dev.dinfo; cur_dev.dinfo = tmp_dinfo; last_dev.snap_time = cur_dev.snap_time; dsgetinfo(&cur_dev); procgetinfo(); } void labelswap(void) { werase(wnd); dslabel(12, 0, LINES - DISKHIGHT - 1); if (kvnsw <= 0) { mvwprintw(wnd, 0, 0, "(swap not configured)"); return; } mvwprintw(wnd, 0, 0, "%*s%5s %5s %s", -pathlen, "Device/Path", "Size", "Used", "|0% /10 /20 /30 /40 / 60\\ 70\\ 80\\ 90\\ 100|"); } void showswap(void) { const char *name; int count, i; if (kvnsw != okvnsw) labelswap(); dsshow(12, 0, LINES - DISKHIGHT - 1, &cur_dev, &last_dev); if (kvnsw <= 0) return; for (i = (kvnsw == 1 ? 0 : kvnsw); i >= 0; i--) { name = i == kvnsw ? "Total" : kvmsw[i].ksw_devname; mvwprintw(wnd, 1 + i, 0, "%-*.*s", pathlen, pathlen - 1, name); sysputpage(wnd, i + 1, pathlen, 5, kvmsw[i].ksw_total, 0); sysputpage(wnd, i + 1, pathlen + 5 + 1, 5, kvmsw[i].ksw_used, 0); if (kvmsw[i].ksw_used > 0) { count = 50 * kvmsw[i].ksw_used / kvmsw[i].ksw_total; sysputXs(wnd, i + 1, pathlen + 5 + 1 + 5 + 1, count); } wclrtoeol(wnd); } count = kvnsw == 1 ? 2 : 3; proclabel(kvnsw + count); procshow(kvnsw + count, LINES - 5 - kvnsw + 3 - DISKHIGHT + 1, kvmsw[kvnsw].ksw_total); } diff --git a/usr.bin/systat/vmstat.c b/usr.bin/systat/vmstat.c index cfc88f83a5bd..9bdb27291529 100644 --- a/usr.bin/systat/vmstat.c +++ b/usr.bin/systat/vmstat.c @@ -1,831 +1,828 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1989, 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifdef lint static const char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 1/12/94"; #endif /* * Cursed vmstat -- from Robert Elz. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "systat.h" #include "extern.h" #include "devs.h" static struct Info { long time[CPUSTATES]; uint64_t v_swtch; /* context switches */ uint64_t v_trap; /* calls to trap */ uint64_t v_syscall; /* calls to syscall() */ uint64_t v_intr; /* device interrupts */ uint64_t v_soft; /* software interrupts */ /* * Virtual memory activity. */ uint64_t v_vm_faults; /* number of address memory faults */ uint64_t v_io_faults; /* page faults requiring I/O */ uint64_t v_cow_faults; /* number of copy-on-writes */ uint64_t v_zfod; /* pages zero filled on demand */ uint64_t v_ozfod; /* optimized zero fill pages */ uint64_t v_swapin; /* swap pager pageins */ uint64_t v_swapout; /* swap pager pageouts */ uint64_t v_swappgsin; /* swap pager pages paged in */ uint64_t v_swappgsout; /* swap pager pages paged out */ uint64_t v_vnodein; /* vnode pager pageins */ uint64_t v_vnodeout; /* vnode pager pageouts */ uint64_t v_vnodepgsin; /* vnode_pager pages paged in */ uint64_t v_vnodepgsout; /* vnode pager pages paged out */ uint64_t v_intrans; /* intransit blocking page faults */ uint64_t v_reactivated; /* number of pages reactivated by pagedaemon */ uint64_t v_pdwakeups; /* number of times daemon has awaken from sleep */ uint64_t v_pdpages; /* number of pages analyzed by daemon */ uint64_t v_dfree; /* pages freed by daemon */ uint64_t v_pfree; /* pages freed by exiting processes */ uint64_t v_tfree; /* total pages freed */ /* * Distribution of page usages. */ u_int v_free_count; /* number of pages free */ u_int v_wire_count; /* number of pages wired down */ u_int v_active_count; /* number of pages active */ u_int v_inactive_count; /* number of pages inactive */ u_int v_laundry_count; /* number of pages in laundry queue */ u_long v_kmem_map_size; /* Current kmem allocation size */ struct vmtotal Total; struct nchstats nchstats; long nchcount; long *intrcnt; long bufspace; u_long maxvnodes; long numvnodes; long freevnodes; int numdirtybuffers; } s, s1, s2, z; static u_long kmem_size; static u_int v_page_count; #define total s.Total #define nchtotal s.nchstats #define oldnchtotal s1.nchstats static enum state { BOOT, TIME, RUN } state = TIME; enum divisor { IEC = 0, SI = HN_DIVISOR_1000 }; static void allocinfo(struct Info *); static void copyinfo(struct Info *, struct Info *); static float cputime(int); static void do_putuint64(uint64_t, int, int, int, int); static void getinfo(struct Info *); static void putuint64(uint64_t, int, int, int); static int ucount(void); static int ncpu; static char buf[26]; static time_t t; static double etime; static int nintr; static long *intrloc; static char **intrname; static int nextintsrow; WINDOW * openkre(void) { return (stdscr); } void closekre(WINDOW *w) { if (w == NULL) return; wclear(w); wrefresh(w); } /* * These constants define where the major pieces are laid out */ #define STATROW 0 /* uses 1 row and 67 cols */ #define STATCOL 0 #define MEMROW 2 /* uses 4 rows and 45 cols */ #define MEMCOL 0 #define PAGEROW 1 /* uses 4 rows and 30 cols */ #define PAGECOL 47 #define INTSROW 5 /* uses all rows to bottom and 16 cols */ #define INTSCOL 64 #define PROCSROW 6 /* uses 3 rows and 20 cols */ #define PROCSCOL 0 #define GENSTATROW 7 /* uses 2 rows and 29 cols */ #define GENSTATCOL 22 #define VMSTATROW 5 /* uses 17 rows and 12-14 cols */ #define VMSTATCOL 52 #define GRAPHROW 10 /* uses 3 rows and 49-51 cols */ #define GRAPHCOL 0 #define VNSTATROW 13 /* uses 4 rows and 13 columns */ #define VNSTATCOL 35 #define NAMEIROW 14 /* uses 3 rows and 32 cols */ #define NAMEICOL 0 #define DISKROW 18 /* uses 5 rows and 47 cols (for 7 drives) */ #define DISKCOL 0 #define DRIVESPACE 7 /* max # for space */ #define MAXDRIVES DRIVESPACE /* max # to display */ int initkre(void) { char *cp, *cp1, *cp2, *intrnamebuf, *nextcp; int i; size_t sz; if (dsinit(MAXDRIVES) != 1) return(0); if (nintr == 0) { if (sysctlbyname("hw.intrcnt", NULL, &sz, NULL, 0) == -1) { error("sysctl(hw.intrcnt...) failed: %s", strerror(errno)); return (0); } nintr = sz / sizeof(u_long); intrloc = calloc(nintr, sizeof (long)); intrname = calloc(nintr, sizeof (char *)); intrnamebuf = sysctl_dynread("hw.intrnames", NULL); if (intrnamebuf == NULL || intrname == NULL || intrloc == NULL) { error("Out of memory"); if (intrnamebuf) free(intrnamebuf); if (intrname) free(intrname); if (intrloc) free(intrloc); nintr = 0; return(0); } for (cp = intrnamebuf, i = 0; i < nintr; i++) { nextcp = cp + strlen(cp) + 1; /* Discard trailing spaces. */ for (cp1 = nextcp - 1; cp1 > cp && *(cp1 - 1) == ' '; ) *--cp1 = '\0'; /* Convert "irqN: name" to "name irqN". */ if (strncmp(cp, "irq", 3) == 0) { cp1 = cp + 3; while (isdigit((u_char)*cp1)) cp1++; if (cp1 != cp && *cp1 == ':' && *(cp1 + 1) == ' ') { sz = strlen(cp); *cp1 = '\0'; cp1 = cp1 + 2; cp2 = strdup(cp); bcopy(cp1, cp, sz - (cp1 - cp) + 1); if (sz <= 10 + 4) { strcat(cp, " "); strcat(cp, cp2 + 3); } free(cp2); } } /* * Convert "name irqN" to "name N" if the former is * longer than the field width. */ if ((cp1 = strstr(cp, "irq")) != NULL && strlen(cp) > 10) bcopy(cp1 + 3, cp1, strlen(cp1 + 3) + 1); intrname[i] = cp; cp = nextcp; } nextintsrow = INTSROW + 2; allocinfo(&s); allocinfo(&s1); allocinfo(&s2); allocinfo(&z); } GETSYSCTL("vm.kmem_size", kmem_size); GETSYSCTL("vm.stats.vm.v_page_count", v_page_count); getinfo(&s2); copyinfo(&s2, &s1); return(1); } void fetchkre(void) { time_t now; struct tm *tp; static int d_first = -1; if (d_first < 0) d_first = (*nl_langinfo(D_MD_ORDER) == 'd'); time(&now); tp = localtime(&now); (void) strftime(buf, sizeof(buf), d_first ? "%e %b %T" : "%b %e %T", tp); getinfo(&s); } void labelkre(void) { int i, j; clear(); mvprintw(STATROW, STATCOL + 6, "users Load"); mvprintw(STATROW + 1, STATCOL + 3, "Mem usage: %%Phy %%Kmem"); mvprintw(MEMROW, MEMCOL, "Mem: REAL VIRTUAL"); mvprintw(MEMROW + 1, MEMCOL, " Tot Share Tot Share"); mvprintw(MEMROW + 2, MEMCOL, "Act"); mvprintw(MEMROW + 3, MEMCOL, "All"); mvprintw(MEMROW + 1, MEMCOL + 40, "Free"); mvprintw(PAGEROW, PAGECOL, " VN PAGER SWAP PAGER"); mvprintw(PAGEROW + 1, PAGECOL, " in out in out"); mvprintw(PAGEROW + 2, PAGECOL, "count"); mvprintw(PAGEROW + 3, PAGECOL, "pages"); mvprintw(INTSROW, INTSCOL + 1, "Interrupts"); mvprintw(INTSROW + 1, INTSCOL + 6, "total"); mvprintw(VMSTATROW, VMSTATCOL + 6, "ioflt"); mvprintw(VMSTATROW + 1, VMSTATCOL + 6, "cow"); mvprintw(VMSTATROW + 2, VMSTATCOL + 6, "zfod"); mvprintw(VMSTATROW + 3, VMSTATCOL + 6, "ozfod"); mvprintw(VMSTATROW + 4, VMSTATCOL + 6 - 1, "%%ozfod"); mvprintw(VMSTATROW + 5, VMSTATCOL + 6, "daefr"); mvprintw(VMSTATROW + 6, VMSTATCOL + 6, "prcfr"); mvprintw(VMSTATROW + 7, VMSTATCOL + 6, "totfr"); mvprintw(VMSTATROW + 8, VMSTATCOL + 6, "react"); mvprintw(VMSTATROW + 9, VMSTATCOL + 6, "pdwak"); mvprintw(VMSTATROW + 10, VMSTATCOL + 6, "pdpgs"); mvprintw(VMSTATROW + 11, VMSTATCOL + 6, "intrn"); mvprintw(VMSTATROW + 12, VMSTATCOL + 6, "wire"); mvprintw(VMSTATROW + 13, VMSTATCOL + 6, "act"); mvprintw(VMSTATROW + 14, VMSTATCOL + 6, "inact"); mvprintw(VMSTATROW + 15, VMSTATCOL + 6, "laund"); mvprintw(VMSTATROW + 16, VMSTATCOL + 6, "free"); if (LINES - 1 > VMSTATROW + 17) mvprintw(VMSTATROW + 17, VMSTATCOL + 6, "buf"); mvprintw(GENSTATROW, GENSTATCOL, " Csw Trp Sys Int Sof Flt"); mvprintw(GRAPHROW, GRAPHCOL, " . %%Sys . %%Intr . %%User . %%Nice . %%Idle"); mvprintw(PROCSROW, PROCSCOL, "Proc:"); mvprintw(PROCSROW + 1, PROCSCOL, " r p d s w"); mvprintw(GRAPHROW + 1, GRAPHCOL, "| | | | | | | | | | |"); mvprintw(VNSTATROW, VNSTATCOL + 8, "dtbuf"); mvprintw(VNSTATROW + 1, VNSTATCOL + 8, "maxvn"); mvprintw(VNSTATROW + 2, VNSTATCOL + 8, "numvn"); mvprintw(VNSTATROW + 3, VNSTATCOL + 8, "frevn"); mvprintw(NAMEIROW, NAMEICOL, "Namei Name-cache Dir-cache"); mvprintw(NAMEIROW + 1, NAMEICOL, " Calls hits %% hits %%"); dslabel(MAXDRIVES, DISKCOL, DISKROW); for (i = 0; i < nintr; i++) { if (intrloc[i] == 0) continue; mvprintw(intrloc[i], INTSCOL + 6, "%-10.10s", intrname[i]); } } #define X(fld) {t=s.fld[i]; s.fld[i]-=s1.fld[i]; if(state==TIME) s1.fld[i]=t;} #define Q(fld) {t=cur_dev.fld[i]; cur_dev.fld[i]-=last_dev.fld[i]; if(state==TIME) last_dev.fld[i]=t;} #define Y(fld) {t = s.fld; s.fld -= s1.fld; if(state == TIME) s1.fld = t;} #define Z(fld) {t = s.nchstats.fld; s.nchstats.fld -= s1.nchstats.fld; \ if(state == TIME) s1.nchstats.fld = t;} #define PUTRATE(fld, l, c, w) \ do { \ Y(fld); \ sysputwuint64(wnd, l, c, w, (s.fld/etime + 0.5), 0); \ } while (0) #define MAXFAIL 5 static char cpuchar[CPUSTATES] = { '=' , '+', '>', '-', ' ' }; static char cpuorder[CPUSTATES] = { CP_SYS, CP_INTR, CP_USER, CP_NICE, CP_IDLE }; void showkre(void) { float f1, f2; int psiz, inttotal; int i, l, lc; static int failcnt = 0; etime = 0; for(i = 0; i < CPUSTATES; i++) { X(time); Q(cp_time); etime += s.time[i]; } if (etime < 5.0) { /* < 5 ticks - ignore this trash */ if (failcnt++ >= MAXFAIL) { clear(); mvprintw(2, 10, "The alternate system clock has died!"); mvprintw(3, 10, "Reverting to ``pigs'' display."); move(CMDLINE, 0); refresh(); failcnt = 0; sleep(5); command("pigs"); } return; } failcnt = 0; etime /= hertz; etime /= ncpu; inttotal = 0; for (i = 0; i < nintr; i++) { if (s.intrcnt[i] == 0) continue; X(intrcnt); l = (int)((float)s.intrcnt[i]/etime + 0.5); inttotal += l; if (intrloc[i] == 0) { if (nextintsrow == LINES) continue; intrloc[i] = nextintsrow++; mvprintw(intrloc[i], INTSCOL + 6, "%-10.10s", intrname[i]); } putint(l, intrloc[i], INTSCOL, 5); } putint(inttotal, INTSROW + 1, INTSCOL, 5); Z(ncs_goodhits); Z(ncs_badhits); Z(ncs_miss); Z(ncs_long); Z(ncs_pass2); Z(ncs_2passes); Z(ncs_neghits); s.nchcount = nchtotal.ncs_goodhits + nchtotal.ncs_badhits + nchtotal.ncs_miss + nchtotal.ncs_long + nchtotal.ncs_neghits; if (state == TIME) s1.nchcount = s.nchcount; psiz = 0; f2 = 0.0; for (lc = 0; lc < CPUSTATES; lc++) { i = cpuorder[lc]; f1 = cputime(i); f2 += f1; l = (int) ((f2 + 1.0) / 2.0) - psiz; putfloat(f1, GRAPHROW, GRAPHCOL + 10 * lc, 4, 1, 0); move(GRAPHROW + 2, psiz); psiz += l; while (l-- > 0) addch(cpuchar[lc]); } putint(ucount(), STATROW, STATCOL, 5); putfloat(avenrun[0], STATROW, STATCOL + 20, 5, 2, 0); putfloat(avenrun[1], STATROW, STATCOL + 26, 5, 2, 0); putfloat(avenrun[2], STATROW, STATCOL + 32, 5, 2, 0); mvaddstr(STATROW, STATCOL + 55, buf); putfloat(100.0 * (v_page_count - total.t_free) / v_page_count, STATROW + 1, STATCOL + 15, 2, 0, 1); putfloat(100.0 * s.v_kmem_map_size / kmem_size, STATROW + 1, STATCOL + 22, 2, 0, 1); sysputpage(wnd, MEMROW + 2, MEMCOL + 4, 6, total.t_arm, 0); sysputpage(wnd, MEMROW + 2, MEMCOL + 12, 6, total.t_armshr, 0); sysputpage(wnd, MEMROW + 2, MEMCOL + 20, 6, total.t_avm, 0); sysputpage(wnd, MEMROW + 2, MEMCOL + 29, 6, total.t_avmshr, 0); sysputpage(wnd, MEMROW + 3, MEMCOL + 4, 6, total.t_rm, 0); sysputpage(wnd, MEMROW + 3, MEMCOL + 12, 6, total.t_rmshr, 0); sysputpage(wnd, MEMROW + 3, MEMCOL + 20, 6, total.t_vm, 0); sysputpage(wnd, MEMROW + 3, MEMCOL + 29, 6, total.t_vmshr, 0); sysputpage(wnd, MEMROW + 2, MEMCOL + 38, 6, total.t_free, 0); putint(total.t_rq - 1, PROCSROW + 2, PROCSCOL, 3); putint(total.t_pw, PROCSROW + 2, PROCSCOL + 4, 3); putint(total.t_dw, PROCSROW + 2, PROCSCOL + 8, 3); putint(total.t_sl, PROCSROW + 2, PROCSCOL + 12, 4); putint(total.t_sw, PROCSROW + 2, PROCSCOL + 17, 3); PUTRATE(v_io_faults, VMSTATROW, VMSTATCOL, 5); PUTRATE(v_cow_faults, VMSTATROW + 1, VMSTATCOL, 5); PUTRATE(v_zfod, VMSTATROW + 2, VMSTATCOL, 5); PUTRATE(v_ozfod, VMSTATROW + 3, VMSTATCOL, 5); putint(s.v_zfod != 0 ? (int)(s.v_ozfod * 100.0 / s.v_zfod) : 0, VMSTATROW + 4, VMSTATCOL, 5); PUTRATE(v_dfree, VMSTATROW + 5, VMSTATCOL, 5); PUTRATE(v_pfree, VMSTATROW + 6, VMSTATCOL, 5); PUTRATE(v_tfree, VMSTATROW + 7, VMSTATCOL, 5); PUTRATE(v_reactivated, VMSTATROW + 8, VMSTATCOL, 5); PUTRATE(v_pdwakeups, VMSTATROW + 9, VMSTATCOL, 5); PUTRATE(v_pdpages, VMSTATROW + 10, VMSTATCOL, 5); PUTRATE(v_intrans, VMSTATROW + 11, VMSTATCOL, 5); sysputpage(wnd, VMSTATROW + 12, VMSTATCOL, 5, s.v_wire_count, 0); sysputpage(wnd, VMSTATROW + 13, VMSTATCOL, 5, s.v_active_count, 0); sysputpage(wnd, VMSTATROW + 14, VMSTATCOL, 5, s.v_inactive_count, 0); sysputpage(wnd, VMSTATROW + 15, VMSTATCOL, 5, s.v_laundry_count, 0); sysputpage(wnd, VMSTATROW + 16, VMSTATCOL, 5, s.v_free_count, 0); if (LINES - 1 > VMSTATROW + 17) sysputuint64(wnd, VMSTATROW + 17, VMSTATCOL, 5, s.bufspace, 0); PUTRATE(v_vnodein, PAGEROW + 2, PAGECOL + 6, 5); PUTRATE(v_vnodeout, PAGEROW + 2, PAGECOL + 12, 5); PUTRATE(v_swapin, PAGEROW + 2, PAGECOL + 19, 5); PUTRATE(v_swapout, PAGEROW + 2, PAGECOL + 25, 5); PUTRATE(v_vnodepgsin, PAGEROW + 3, PAGECOL + 6, 5); PUTRATE(v_vnodepgsout, PAGEROW + 3, PAGECOL + 12, 5); PUTRATE(v_swappgsin, PAGEROW + 3, PAGECOL + 19, 5); PUTRATE(v_swappgsout, PAGEROW + 3, PAGECOL + 25, 5); PUTRATE(v_swtch, GENSTATROW + 1, GENSTATCOL, 4); PUTRATE(v_trap, GENSTATROW + 1, GENSTATCOL + 5, 4); PUTRATE(v_syscall, GENSTATROW + 1, GENSTATCOL + 10, 4); PUTRATE(v_intr, GENSTATROW + 1, GENSTATCOL + 15, 4); PUTRATE(v_soft, GENSTATROW + 1, GENSTATCOL + 20, 4); PUTRATE(v_vm_faults, GENSTATROW + 1, GENSTATCOL + 25, 4); switch(state) { case TIME: dsshow(MAXDRIVES, DISKCOL, DISKROW, &cur_dev, &last_dev); break; case RUN: dsshow(MAXDRIVES, DISKCOL, DISKROW, &cur_dev, &run_dev); break; case BOOT: dsshow(MAXDRIVES, DISKCOL, DISKROW, &cur_dev, NULL); break; } putint(s.numdirtybuffers, VNSTATROW, VNSTATCOL, 7); putint(s.maxvnodes, VNSTATROW + 1, VNSTATCOL, 7); putint(s.numvnodes, VNSTATROW + 2, VNSTATCOL, 7); putint(s.freevnodes, VNSTATROW + 3, VNSTATCOL, 7); putint(s.nchcount, NAMEIROW + 2, NAMEICOL, 8); putint((nchtotal.ncs_goodhits + nchtotal.ncs_neghits), NAMEIROW + 2, NAMEICOL + 9, 7); #define nz(x) ((x) ? (x) : 1) putfloat((nchtotal.ncs_goodhits+nchtotal.ncs_neghits) * 100.0 / nz(s.nchcount), NAMEIROW + 2, NAMEICOL + 17, 3, 0, 1); putint(nchtotal.ncs_pass2, NAMEIROW + 2, NAMEICOL + 21, 7); putfloat(nchtotal.ncs_pass2 * 100.0 / nz(s.nchcount), NAMEIROW + 2, NAMEICOL + 29, 3, 0, 1); #undef nz } int cmdkre(const char *cmd, const char *args) { int retval; if (prefix(cmd, "run")) { retval = 1; copyinfo(&s2, &s1); switch (devstat_getdevs(NULL, &run_dev)) { case -1: errx(1, "%s", devstat_errbuf); break; case 1: num_devices = run_dev.dinfo->numdevs; generation = run_dev.dinfo->generation; retval = dscmd("refresh", NULL, MAXDRIVES, &cur_dev); if (retval == 2) labelkre(); break; default: break; } state = RUN; return (retval); } if (prefix(cmd, "boot")) { state = BOOT; copyinfo(&z, &s1); return (1); } if (prefix(cmd, "time")) { state = TIME; return (1); } if (prefix(cmd, "zero")) { retval = 1; if (state == RUN) { getinfo(&s1); switch (devstat_getdevs(NULL, &run_dev)) { case -1: errx(1, "%s", devstat_errbuf); break; case 1: num_devices = run_dev.dinfo->numdevs; generation = run_dev.dinfo->generation; retval = dscmd("refresh",NULL, MAXDRIVES, &cur_dev); if (retval == 2) labelkre(); break; default: break; } } return (retval); } retval = dscmd(cmd, args, MAXDRIVES, &cur_dev); if (retval == 2) labelkre(); return(retval); } /* calculate number of users on the system */ static int ucount(void) { int nusers = 0; struct utmpx *ut; setutxent(); while ((ut = getutxent()) != NULL) if (ut->ut_type == USER_PROCESS) nusers++; endutxent(); return (nusers); } static float cputime(int indx) { double lt; int i; lt = 0; for (i = 0; i < CPUSTATES; i++) lt += s.time[i]; if (lt == 0.0) lt = 1.0; return (s.time[indx] * 100.0 / lt); } void putint(int n, int l, int lc, int w) { do_putuint64(n, l, lc, w, SI); } static void putuint64(uint64_t n, int l, int lc, int w) { do_putuint64(n, l, lc, w, IEC); } static void do_putuint64(uint64_t n, int l, int lc, int w, int div) { int snr; char b[128]; char buf[128]; move(l, lc); #ifdef DEBUG while (w-- > 0) addch('*'); return; #endif if (n == 0) { while (w-- > 0) addch(' '); return; } snr = snprintf(b, sizeof(b), "%*ju", w, (uintmax_t)n); if (snr != w) { humanize_number(buf, w, n, "", HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL | div); snr = snprintf(b, sizeof(b), "%*s", w, buf); } if (snr != w) { while (w-- > 0) addch('*'); return; } addstr(b); } void putfloat(double f, int l, int lc, int w, int d, int nz) { int snr; char b[128]; move(l, lc); #ifdef DEBUG while (--w >= 0) addch('*'); return; #endif if (nz && f == 0.0) { while (--w >= 0) addch(' '); return; } snr = snprintf(b, sizeof(b), "%*.*f", w, d, f); if (snr != w) snr = snprintf(b, sizeof(b), "%*.0f", w, f); if (snr != w) snr = snprintf(b, sizeof(b), "%*.0fk", w - 1, f / 1000); if (snr != w) snr = snprintf(b, sizeof(b), "%*.0fM", w - 1, f / 1000000); if (snr != w) { while (--w >= 0) addch('*'); return; } addstr(b); } void putlongdouble(long double f, int l, int lc, int w, int d, int nz) { int snr; char b[128]; move(l, lc); #ifdef DEBUG while (--w >= 0) addch('*'); return; #endif if (nz && f == 0.0) { while (--w >= 0) addch(' '); return; } snr = snprintf(b, sizeof(b), "%*.*Lf", w, d, f); if (snr != w) snr = snprintf(b, sizeof(b), "%*.0Lf", w, f); if (snr != w) snr = snprintf(b, sizeof(b), "%*.0Lfk", w - 1, f / 1000); if (snr != w) snr = snprintf(b, sizeof(b), "%*.0LfM", w - 1, f / 1000000); if (snr != w) { while (--w >= 0) addch('*'); return; } addstr(b); } static void getinfo(struct Info *ls) { struct devinfo *tmp_dinfo; size_t size; int mib[2]; GETSYSCTL("kern.cp_time", ls->time); GETSYSCTL("kern.cp_time", cur_dev.cp_time); GETSYSCTL("vm.stats.sys.v_swtch", ls->v_swtch); GETSYSCTL("vm.stats.sys.v_trap", ls->v_trap); GETSYSCTL("vm.stats.sys.v_syscall", ls->v_syscall); GETSYSCTL("vm.stats.sys.v_intr", ls->v_intr); GETSYSCTL("vm.stats.sys.v_soft", ls->v_soft); GETSYSCTL("vm.stats.vm.v_vm_faults", ls->v_vm_faults); GETSYSCTL("vm.stats.vm.v_io_faults", ls->v_io_faults); GETSYSCTL("vm.stats.vm.v_cow_faults", ls->v_cow_faults); GETSYSCTL("vm.stats.vm.v_zfod", ls->v_zfod); GETSYSCTL("vm.stats.vm.v_ozfod", ls->v_ozfod); GETSYSCTL("vm.stats.vm.v_swapin", ls->v_swapin); GETSYSCTL("vm.stats.vm.v_swapout", ls->v_swapout); GETSYSCTL("vm.stats.vm.v_swappgsin", ls->v_swappgsin); GETSYSCTL("vm.stats.vm.v_swappgsout", ls->v_swappgsout); GETSYSCTL("vm.stats.vm.v_vnodein", ls->v_vnodein); GETSYSCTL("vm.stats.vm.v_vnodeout", ls->v_vnodeout); GETSYSCTL("vm.stats.vm.v_vnodepgsin", ls->v_vnodepgsin); GETSYSCTL("vm.stats.vm.v_vnodepgsout", ls->v_vnodepgsout); GETSYSCTL("vm.stats.vm.v_intrans", ls->v_intrans); GETSYSCTL("vm.stats.vm.v_reactivated", ls->v_reactivated); GETSYSCTL("vm.stats.vm.v_pdwakeups", ls->v_pdwakeups); GETSYSCTL("vm.stats.vm.v_pdpages", ls->v_pdpages); GETSYSCTL("vm.stats.vm.v_dfree", ls->v_dfree); GETSYSCTL("vm.stats.vm.v_pfree", ls->v_pfree); GETSYSCTL("vm.stats.vm.v_tfree", ls->v_tfree); GETSYSCTL("vm.stats.vm.v_free_count", ls->v_free_count); GETSYSCTL("vm.stats.vm.v_wire_count", ls->v_wire_count); GETSYSCTL("vm.stats.vm.v_active_count", ls->v_active_count); GETSYSCTL("vm.stats.vm.v_inactive_count", ls->v_inactive_count); GETSYSCTL("vm.stats.vm.v_laundry_count", ls->v_laundry_count); GETSYSCTL("vfs.bufspace", ls->bufspace); GETSYSCTL("kern.maxvnodes", ls->maxvnodes); GETSYSCTL("vfs.numvnodes", ls->numvnodes); GETSYSCTL("vfs.freevnodes", ls->freevnodes); GETSYSCTL("vfs.cache.nchstats", ls->nchstats); GETSYSCTL("vfs.numdirtybuffers", ls->numdirtybuffers); GETSYSCTL("vm.kmem_map_size", ls->v_kmem_map_size); getsysctl("hw.intrcnt", ls->intrcnt, nintr * sizeof(u_long)); size = sizeof(ls->Total); mib[0] = CTL_VM; mib[1] = VM_TOTAL; if (sysctl(mib, 2, &ls->Total, &size, NULL, 0) < 0) { error("Can't get kernel info: %s\n", strerror(errno)); bzero(&ls->Total, sizeof(ls->Total)); } size = sizeof(ncpu); if (sysctlbyname("hw.ncpu", &ncpu, &size, NULL, 0) < 0 || size != sizeof(ncpu)) ncpu = 1; tmp_dinfo = last_dev.dinfo; last_dev.dinfo = cur_dev.dinfo; cur_dev.dinfo = tmp_dinfo; last_dev.snap_time = cur_dev.snap_time; dsgetinfo(&cur_dev); } static void allocinfo(struct Info *ls) { ls->intrcnt = (long *) calloc(nintr, sizeof(long)); if (ls->intrcnt == NULL) errx(2, "out of memory"); } static void copyinfo(struct Info *from, struct Info *to) { long *intrcnt; /* * time, wds, seek, and xfer are malloc'd so we have to * save the pointers before the structure copy and then * copy by hand. */ intrcnt = to->intrcnt; *to = *from; bcopy(from->intrcnt, to->intrcnt = intrcnt, nintr * sizeof (int)); } diff --git a/usr.bin/tail/forward.c b/usr.bin/tail/forward.c index 878cb5a4550b..48516a730a50 100644 --- a/usr.bin/tail/forward.c +++ b/usr.bin/tail/forward.c @@ -1,435 +1,432 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Edward Sze-Tyan Wang. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)forward.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "extern.h" static void rlines(FILE *, const char *fn, off_t, struct stat *); static int show(file_info_t *); static void set_events(file_info_t *files); /* defines for inner loop actions */ #define USE_SLEEP 0 #define USE_KQUEUE 1 #define ADD_EVENTS 2 static struct kevent *ev; static int action = USE_SLEEP; static int kq; static const file_info_t *last; /* * forward -- display the file, from an offset, forward. * * There are eight separate cases for this -- regular and non-regular * files, by bytes or lines and from the beginning or end of the file. * * FBYTES byte offset from the beginning of the file * REG seek * NOREG read, counting bytes * * FLINES line offset from the beginning of the file * REG read, counting lines * NOREG read, counting lines * * RBYTES byte offset from the end of the file * REG seek * NOREG cyclically read characters into a wrap-around buffer * * RLINES * REG mmap the file and step back until reach the correct offset. * NOREG cyclically read lines into a wrap-around array of buffers */ void forward(FILE *fp, const char *fn, enum STYLE style, off_t off, struct stat *sbp) { int ch; switch(style) { case FBYTES: if (off == 0) break; if (S_ISREG(sbp->st_mode)) { if (sbp->st_size < off) off = sbp->st_size; if (fseeko(fp, off, SEEK_SET) == -1) { ierr(fn); return; } } else while (off--) if ((ch = getc(fp)) == EOF) { if (ferror(fp)) { ierr(fn); return; } break; } break; case FLINES: if (off == 0) break; for (;;) { if ((ch = getc(fp)) == EOF) { if (ferror(fp)) { ierr(fn); return; } break; } if (ch == '\n' && !--off) break; } break; case RBYTES: if (S_ISREG(sbp->st_mode)) { if (sbp->st_size >= off && fseeko(fp, -off, SEEK_END) == -1) { ierr(fn); return; } } else if (off == 0) { while (getc(fp) != EOF); if (ferror(fp)) { ierr(fn); return; } } else if (bytes(fp, fn, off)) return; break; case RLINES: if (S_ISREG(sbp->st_mode)) if (!off) { if (fseeko(fp, (off_t)0, SEEK_END) == -1) { ierr(fn); return; } } else rlines(fp, fn, off, sbp); else if (off == 0) { while (getc(fp) != EOF); if (ferror(fp)) { ierr(fn); return; } } else if (lines(fp, fn, off)) return; break; default: break; } while ((ch = getc(fp)) != EOF) if (putchar(ch) == EOF) oerr(); if (ferror(fp)) { ierr(fn); return; } (void)fflush(stdout); } /* * rlines -- display the last offset lines of the file. */ static void rlines(FILE *fp, const char *fn, off_t off, struct stat *sbp) { struct mapinfo map; off_t curoff, size; int i; if (!(size = sbp->st_size)) return; map.start = NULL; map.fd = fileno(fp); map.mapoff = map.maxoff = size; /* * Last char is special, ignore whether newline or not. Note that * size == 0 is dealt with above, and size == 1 sets curoff to -1. */ curoff = size - 2; while (curoff >= 0) { if (curoff < map.mapoff && maparound(&map, curoff) != 0) { ierr(fn); return; } for (i = curoff - map.mapoff; i >= 0; i--) if (map.start[i] == '\n' && --off == 0) break; /* `i' is either the map offset of a '\n', or -1. */ curoff = map.mapoff + i; if (i >= 0) break; } curoff++; if (mapprint(&map, curoff, size - curoff) != 0) { ierr(fn); exit(1); } /* Set the file pointer to reflect the length displayed. */ if (fseeko(fp, sbp->st_size, SEEK_SET) == -1) { ierr(fn); return; } if (map.start != NULL && munmap(map.start, map.maplen)) { ierr(fn); return; } } static int show(file_info_t *file) { int ch; while ((ch = getc(file->fp)) != EOF) { if (last != file && no_files > 1) { if (!qflag) printfn(file->file_name, 1); last = file; } if (putchar(ch) == EOF) oerr(); } (void)fflush(stdout); if (ferror(file->fp)) { fclose(file->fp); file->fp = NULL; ierr(file->file_name); return 0; } clearerr(file->fp); return 1; } static void set_events(file_info_t *files) { int i, n = 0; file_info_t *file; struct timespec ts; struct statfs sf; ts.tv_sec = 0; ts.tv_nsec = 0; action = USE_KQUEUE; for (i = 0, file = files; i < no_files; i++, file++) { if (! file->fp) continue; if (fstatfs(fileno(file->fp), &sf) == 0 && (sf.f_flags & MNT_LOCAL) == 0) { action = USE_SLEEP; return; } if (Fflag && fileno(file->fp) != STDIN_FILENO) { EV_SET(&ev[n], fileno(file->fp), EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_DELETE | NOTE_RENAME, 0, 0); n++; } EV_SET(&ev[n], fileno(file->fp), EVFILT_READ, EV_ADD | EV_ENABLE | EV_CLEAR, 0, 0, 0); n++; } if (kevent(kq, ev, n, NULL, 0, &ts) < 0) { action = USE_SLEEP; } } /* * follow -- display the file, from an offset, forward. * */ void follow(file_info_t *files, enum STYLE style, off_t off) { int active, ev_change, i, n = -1; struct stat sb2; file_info_t *file; FILE *ftmp; struct timespec ts; /* Position each of the files */ file = files; active = 0; n = 0; for (i = 0; i < no_files; i++, file++) { if (file->fp) { active = 1; n++; if (no_files > 1 && !qflag) printfn(file->file_name, 1); forward(file->fp, file->file_name, style, off, &file->st); if (Fflag && fileno(file->fp) != STDIN_FILENO) n++; } } if (!Fflag && !active) return; last = --file; kq = kqueue(); if (kq < 0) err(1, "kqueue"); ev = malloc(n * sizeof(struct kevent)); if (! ev) err(1, "Couldn't allocate memory for kevents."); set_events(files); for (;;) { ev_change = 0; if (Fflag) { for (i = 0, file = files; i < no_files; i++, file++) { if (!file->fp) { file->fp = fileargs_fopen(fa, file->file_name, "r"); if (file->fp != NULL && fstat(fileno(file->fp), &file->st) == -1) { fclose(file->fp); file->fp = NULL; } if (file->fp != NULL) ev_change++; continue; } if (fileno(file->fp) == STDIN_FILENO) continue; ftmp = fileargs_fopen(fa, file->file_name, "r"); if (ftmp == NULL || fstat(fileno(ftmp), &sb2) == -1) { if (errno != ENOENT) ierr(file->file_name); show(file); if (file->fp != NULL) { fclose(file->fp); file->fp = NULL; } if (ftmp != NULL) { fclose(ftmp); } ev_change++; continue; } if (sb2.st_ino != file->st.st_ino || sb2.st_dev != file->st.st_dev || sb2.st_nlink == 0) { show(file); fclose(file->fp); file->fp = ftmp; memcpy(&file->st, &sb2, sizeof(struct stat)); ev_change++; } else { fclose(ftmp); } } } for (i = 0, file = files; i < no_files; i++, file++) if (file->fp && !show(file)) ev_change++; if (ev_change) set_events(files); switch (action) { case USE_KQUEUE: ts.tv_sec = 1; ts.tv_nsec = 0; /* * In the -F case we set a timeout to ensure that * we re-stat the file at least once every second. */ n = kevent(kq, NULL, 0, ev, 1, Fflag ? &ts : NULL); if (n < 0) err(1, "kevent"); if (n == 0) { /* timeout */ break; } else if (ev->filter == EVFILT_READ && ev->data < 0) { /* file shrank, reposition to end */ if (lseek(ev->ident, (off_t)0, SEEK_END) == -1) { ierr(file->file_name); continue; } } break; case USE_SLEEP: (void) usleep(250000); break; } } } diff --git a/usr.bin/tail/misc.c b/usr.bin/tail/misc.c index 537cf00ccfe3..21d0db8b5d40 100644 --- a/usr.bin/tail/misc.c +++ b/usr.bin/tail/misc.c @@ -1,134 +1,131 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Edward Sze-Tyan Wang. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include #include #include #include #include #include "extern.h" void ierr(const char *fname) { warn("%s", fname); rval = 1; } void oerr(void) { err(1, "stdout"); } /* * Print `len' bytes from the file associated with `mip', starting at * absolute file offset `startoff'. May move map window. */ int mapprint(struct mapinfo *mip, off_t startoff, off_t len) { int n; while (len > 0) { if (startoff < mip->mapoff || startoff >= mip->mapoff + (off_t)mip->maplen) { if (maparound(mip, startoff) != 0) return (1); } n = (mip->mapoff + mip->maplen) - startoff; if (n > len) n = len; WR(mip->start + (startoff - mip->mapoff), n); startoff += n; len -= n; } return (0); } /* * Move the map window so that it contains the byte at absolute file * offset `offset'. The start of the map window will be TAILMAPLEN * aligned. */ int maparound(struct mapinfo *mip, off_t offset) { if (mip->start != NULL && munmap(mip->start, mip->maplen) != 0) return (1); mip->mapoff = offset & ~((off_t)TAILMAPLEN - 1); mip->maplen = TAILMAPLEN; if ((off_t)mip->maplen > mip->maxoff - mip->mapoff) mip->maplen = mip->maxoff - mip->mapoff; if (mip->maplen <= 0) abort(); if ((mip->start = mmap(NULL, mip->maplen, PROT_READ, MAP_SHARED, mip->fd, mip->mapoff)) == MAP_FAILED) return (1); return (0); } /* * Print the file name without stdio buffering. */ void printfn(const char *fn, int print_nl) { if (print_nl) WR("\n", 1); WR("==> ", 4); WR(fn, strlen(fn)); WR(" <==\n", 5); } diff --git a/usr.bin/tail/read.c b/usr.bin/tail/read.c index 1e757c86195c..ff025b31d64c 100644 --- a/usr.bin/tail/read.c +++ b/usr.bin/tail/read.c @@ -1,214 +1,211 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Edward Sze-Tyan Wang. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include #include #include #include #include #include "extern.h" /* * bytes -- read bytes to an offset from the end and display. * * This is the function that reads to a byte offset from the end of the input, * storing the data in a wrap-around buffer which is then displayed. If the * rflag is set, the data is displayed in lines in reverse order, and this * routine has the usual nastiness of trying to find the newlines. Otherwise, * it is displayed from the character closest to the beginning of the input to * the end. */ int bytes(FILE *fp, const char *fn, off_t off) { int ch, len, tlen; char *ep, *p, *t; int wrap; char *sp; if ((sp = p = malloc(off)) == NULL) err(1, "malloc"); for (wrap = 0, ep = p + off; (ch = getc(fp)) != EOF;) { *p = ch; if (++p == ep) { wrap = 1; p = sp; } } if (ferror(fp)) { ierr(fn); free(sp); return 1; } if (rflag) { for (t = p - 1, len = 0; t >= sp; --t, ++len) if (*t == '\n' && len) { WR(t + 1, len); len = 0; } if (wrap) { tlen = len; for (t = ep - 1, len = 0; t >= p; --t, ++len) if (*t == '\n') { if (len) { WR(t + 1, len); len = 0; } if (tlen) { WR(sp, tlen); tlen = 0; } } if (len) WR(t + 1, len); if (tlen) WR(sp, tlen); } } else { if (wrap && (len = ep - p)) WR(p, len); len = p - sp; if (len) WR(sp, len); } free(sp); return 0; } /* * lines -- read lines to an offset from the end and display. * * This is the function that reads to a line offset from the end of the input, * storing the data in an array of buffers which is then displayed. If the * rflag is set, the data is displayed in lines in reverse order, and this * routine has the usual nastiness of trying to find the newlines. Otherwise, * it is displayed from the line closest to the beginning of the input to * the end. */ int lines(FILE *fp, const char *fn, off_t off) { struct { int blen; u_int len; char *l; } *llines; int ch, rc; char *p, *sp; int blen, cnt, recno, wrap; if ((llines = calloc(off, sizeof(*llines))) == NULL) err(1, "calloc"); p = sp = NULL; blen = cnt = recno = wrap = 0; rc = 0; while ((ch = getc(fp)) != EOF) { if (++cnt > blen) { if ((sp = realloc(sp, blen += 1024)) == NULL) err(1, "realloc"); p = sp + cnt - 1; } *p++ = ch; if (ch == '\n') { if ((int)llines[recno].blen < cnt) { llines[recno].blen = cnt + 256; if ((llines[recno].l = realloc(llines[recno].l, llines[recno].blen)) == NULL) err(1, "realloc"); } bcopy(sp, llines[recno].l, llines[recno].len = cnt); cnt = 0; p = sp; if (++recno == off) { wrap = 1; recno = 0; } } } if (ferror(fp)) { ierr(fn); rc = 1; goto done; } if (cnt) { llines[recno].l = sp; sp = NULL; llines[recno].len = cnt; if (++recno == off) { wrap = 1; recno = 0; } } if (rflag) { for (cnt = recno - 1; cnt >= 0; --cnt) WR(llines[cnt].l, llines[cnt].len); if (wrap) for (cnt = off - 1; cnt >= recno; --cnt) WR(llines[cnt].l, llines[cnt].len); } else { if (wrap) for (cnt = recno; cnt < off; ++cnt) WR(llines[cnt].l, llines[cnt].len); for (cnt = 0; cnt < recno; ++cnt) WR(llines[cnt].l, llines[cnt].len); } done: for (cnt = 0; cnt < off; cnt++) free(llines[cnt].l); free(sp); free(llines); return (rc); } diff --git a/usr.bin/tail/tail.c b/usr.bin/tail/tail.c index 8a65683bef7e..9e63353f9b40 100644 --- a/usr.bin/tail/tail.c +++ b/usr.bin/tail/tail.c @@ -1,371 +1,368 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Edward Sze-Tyan Wang. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1991, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)tail.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "extern.h" int Fflag, fflag, qflag, rflag, rval, no_files; fileargs_t *fa; static void obsolete(char **); static void usage(void); static const struct option long_opts[] = { {"blocks", required_argument, NULL, 'b'}, {"bytes", required_argument, NULL, 'c'}, {"lines", required_argument, NULL, 'n'}, {NULL, no_argument, NULL, 0} }; int main(int argc, char *argv[]) { struct stat sb; const char *fn; FILE *fp; off_t off; enum STYLE style; int ch, first; file_info_t file, *filep, *files; char *p; cap_rights_t rights; /* * Tail's options are weird. First, -n10 is the same as -n-10, not * -n+10. Second, the number options are 1 based and not offsets, * so -n+1 is the first line, and -c-1 is the last byte. Third, the * number options for the -r option specify the number of things that * get displayed, not the starting point in the file. The one major * incompatibility in this version as compared to historical versions * is that the 'r' option couldn't be modified by the -lbc options, * i.e. it was always done in lines. This version treats -rc as a * number of characters in reverse order. Finally, the default for * -r is the entire file, not 10 lines. */ #define ARG(units, forward, backward) { \ if (style) \ usage(); \ off = strtoll(optarg, &p, 10) * (units); \ if (*p) \ errx(1, "illegal offset -- %s", optarg); \ switch(optarg[0]) { \ case '+': \ if (off) \ off -= (units); \ style = (forward); \ break; \ case '-': \ off = -off; \ /* FALLTHROUGH */ \ default: \ style = (backward); \ break; \ } \ } obsolete(argv); style = NOTSET; off = 0; while ((ch = getopt_long(argc, argv, "+Fb:c:fn:qr", long_opts, NULL)) != -1) switch(ch) { case 'F': /* -F is superset of (and implies) -f */ Fflag = fflag = 1; break; case 'b': ARG(512, FBYTES, RBYTES); break; case 'c': ARG(1, FBYTES, RBYTES); break; case 'f': fflag = 1; break; case 'n': ARG(1, FLINES, RLINES); break; case 'q': qflag = 1; break; case 'r': rflag = 1; break; case '?': default: usage(); } argc -= optind; argv += optind; no_files = argc ? argc : 1; cap_rights_init(&rights, CAP_FSTAT, CAP_FSTATFS, CAP_FCNTL, CAP_MMAP_R); if (fflag) cap_rights_set(&rights, CAP_EVENT); if (caph_rights_limit(STDIN_FILENO, &rights) < 0 || caph_limit_stderr() < 0 || caph_limit_stdout() < 0) err(1, "can't limit stdio rights"); fa = fileargs_init(argc, argv, O_RDONLY, 0, &rights, FA_OPEN); if (fa == NULL) err(1, "unable to init casper"); caph_cache_catpages(); if (caph_enter_casper() < 0) err(1, "unable to enter capability mode"); /* * If displaying in reverse, don't permit follow option, and convert * style values. */ if (rflag) { if (fflag) usage(); if (style == FBYTES) style = RBYTES; else if (style == FLINES) style = RLINES; } /* * If style not specified, the default is the whole file for -r, and * the last 10 lines if not -r. */ if (style == NOTSET) { if (rflag) { off = 0; style = REVERSE; } else { off = 10; style = RLINES; } } if (*argv && fflag) { files = malloc(no_files * sizeof(struct file_info)); if (files == NULL) err(1, "Couldn't malloc space for file descriptors."); for (filep = files; (fn = *argv++); filep++) { filep->file_name = fn; filep->fp = fileargs_fopen(fa, filep->file_name, "r"); if (filep->fp == NULL || fstat(fileno(filep->fp), &filep->st)) { if (filep->fp != NULL) { fclose(filep->fp); filep->fp = NULL; } if (!Fflag || errno != ENOENT) ierr(filep->file_name); } } follow(files, style, off); free(files); } else if (*argv) { for (first = 1; (fn = *argv++);) { if ((fp = fileargs_fopen(fa, fn, "r")) == NULL || fstat(fileno(fp), &sb)) { ierr(fn); continue; } if (argc > 1 && !qflag) { printfn(fn, !first); first = 0; } if (rflag) reverse(fp, fn, style, off, &sb); else forward(fp, fn, style, off, &sb); } } else { fn = "stdin"; if (fstat(fileno(stdin), &sb)) { ierr(fn); exit(1); } /* * Determine if input is a pipe. 4.4BSD will set the SOCKET * bit in the st_mode field for pipes. Fix this then. */ if (lseek(fileno(stdin), (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) { errno = 0; fflag = 0; /* POSIX.2 requires this. */ } if (rflag) { reverse(stdin, fn, style, off, &sb); } else if (fflag) { file.file_name = fn; file.fp = stdin; file.st = sb; follow(&file, style, off); } else { forward(stdin, fn, style, off, &sb); } } fileargs_free(fa); exit(rval); } /* * Convert the obsolete argument form into something that getopt can handle. * This means that anything of the form [+-][0-9][0-9]*[lbc][Ffr] that isn't * the option argument for a -b, -c or -n option gets converted. */ static void obsolete(char *argv[]) { char *ap, *p, *t; size_t len; char *start; while ((ap = *++argv)) { /* Return if "--" or not an option of any form. */ if (ap[0] != '-') { if (ap[0] != '+') return; } else if (ap[1] == '-') return; switch(*++ap) { /* Old-style option. */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* Malloc space for dash, new option and argument. */ len = strlen(*argv); if ((start = p = malloc(len + 3)) == NULL) err(1, "malloc"); *p++ = '-'; /* * Go to the end of the option argument. Save off any * trailing options (-3lf) and translate any trailing * output style characters. */ t = *argv + len - 1; if (*t == 'F' || *t == 'f' || *t == 'r') { *p++ = *t; *t-- = '\0'; } switch(*t) { case 'b': *p++ = 'b'; *t = '\0'; break; case 'c': *p++ = 'c'; *t = '\0'; break; case 'l': *t = '\0'; /* FALLTHROUGH */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': *p++ = 'n'; break; default: errx(1, "illegal option -- %s", *argv); } *p++ = *argv[0]; (void)strcpy(p, ap); *argv = start; continue; /* * Options w/ arguments, skip the argument and continue * with the next option. */ case 'b': case 'c': case 'n': if (!ap[1]) ++argv; /* FALLTHROUGH */ /* Options w/o arguments, continue with the next option. */ case 'F': case 'f': case 'r': continue; /* Illegal option, return and let getopt handle it. */ default: return; } } } static void usage(void) { (void)fprintf(stderr, "usage: tail [-F | -f | -r] [-q] [-b # | -c # | -n #]" " [file ...]\n"); exit(1); } diff --git a/usr.bin/talk/ctl.c b/usr.bin/talk/ctl.c index abfd5e6b30ed..c9bd6f77fb81 100644 --- a/usr.bin/talk/ctl.c +++ b/usr.bin/talk/ctl.c @@ -1,124 +1,121 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)ctl.c 8.1 (Berkeley) 6/6/93"; #endif /* * This file handles haggling with the various talk daemons to * get a socket to talk to. sockt is opened and connected in * the progress */ #include #include #include #include "talk.h" #include "talk_ctl.h" struct sockaddr_in daemon_addr = { .sin_len = sizeof(daemon_addr), .sin_family = AF_INET }; struct sockaddr_in ctl_addr = { .sin_len = sizeof(ctl_addr), .sin_family = AF_INET }; struct sockaddr_in my_addr = { .sin_len = sizeof(my_addr), .sin_family = AF_INET }; /* inet addresses of the two machines */ struct in_addr my_machine_addr; struct in_addr his_machine_addr; u_short daemon_port; /* port number of the talk daemon */ int ctl_sockt; int sockt; int invitation_waiting = 0; CTL_MSG msg; void open_sockt(void) { socklen_t length; (void)memset(&my_addr, 0, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_len = sizeof(my_addr); my_addr.sin_addr = my_machine_addr; my_addr.sin_port = 0; sockt = socket(AF_INET, SOCK_STREAM, 0); if (sockt == -1) p_error("Bad socket"); if (bind(sockt, (struct sockaddr *)&my_addr, sizeof(my_addr)) != 0) p_error("Binding local socket"); length = sizeof(my_addr); if (getsockname(sockt, (struct sockaddr *)&my_addr, &length) == -1) p_error("Bad address for socket"); } /* open the ctl socket */ void open_ctl(void) { socklen_t length; (void)memset(&ctl_addr, 0, sizeof(ctl_addr)); ctl_addr.sin_family = AF_INET; ctl_addr.sin_len = sizeof(my_addr); ctl_addr.sin_port = 0; ctl_addr.sin_addr = my_machine_addr; ctl_sockt = socket(AF_INET, SOCK_DGRAM, 0); if (ctl_sockt == -1) p_error("Bad socket"); if (bind(ctl_sockt, (struct sockaddr *)&ctl_addr, sizeof(ctl_addr)) != 0) p_error("Couldn't bind to control socket"); length = sizeof(ctl_addr); if (getsockname(ctl_sockt, (struct sockaddr *)&ctl_addr, &length) == -1) p_error("Bad address for ctl socket"); } /* print_addr is a debug print routine */ void print_addr(struct sockaddr_in addr) { int i; printf("addr = %lx, port = %o, family = %o zero = ", (u_long)addr.sin_addr.s_addr, addr.sin_port, addr.sin_family); for (i = 0; i<8;i++) printf("%o ", (int)addr.sin_zero[i]); putchar('\n'); } diff --git a/usr.bin/talk/ctl_transact.c b/usr.bin/talk/ctl_transact.c index 650134da6ca6..c51bbed28437 100644 --- a/usr.bin/talk/ctl_transact.c +++ b/usr.bin/talk/ctl_transact.c @@ -1,107 +1,104 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)ctl_transact.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include "talk.h" #include "talk_ctl.h" #define CTL_WAIT 2 /* time to wait for a response, in seconds */ /* * SOCKDGRAM is unreliable, so we must repeat messages if we have * not received an acknowledgement within a reasonable amount * of time */ void ctl_transact(struct in_addr target, CTL_MSG lmsg, int type, CTL_RESPONSE *rp) { struct pollfd pfd[1]; int nready = 0, cc; lmsg.type = type; daemon_addr.sin_addr = target; daemon_addr.sin_port = daemon_port; pfd[0].fd = ctl_sockt; pfd[0].events = POLLIN; /* * Keep sending the message until a response of * the proper type is obtained. */ do { /* resend message until a response is obtained */ do { cc = sendto(ctl_sockt, (char *)&lmsg, sizeof (lmsg), 0, (struct sockaddr *)&daemon_addr, sizeof (daemon_addr)); if (cc != sizeof (lmsg)) { if (errno == EINTR) continue; p_error("Error on write to talk daemon"); } nready = poll(pfd, 1, CTL_WAIT * 1000); if (nready < 0) { if (errno == EINTR) continue; p_error("Error waiting for daemon response"); } } while (nready == 0); /* * Keep reading while there are queued messages * (this is not necessary, it just saves extra * request/acknowledgements being sent) */ do { cc = recv(ctl_sockt, (char *)rp, sizeof (*rp), 0); if (cc < 0) { if (errno == EINTR) continue; p_error("Error on read from talk daemon"); } nready = poll(pfd, 1, 0); } while (nready > 0 && (rp->vers != TALK_VERSION || rp->type != type)); } while (rp->vers != TALK_VERSION || rp->type != type); rp->id_num = ntohl(rp->id_num); rp->addr.sa_family = ntohs(rp->addr.sa_family); } diff --git a/usr.bin/talk/display.c b/usr.bin/talk/display.c index 9987194fcbb9..5f29cfd600d9 100644 --- a/usr.bin/talk/display.c +++ b/usr.bin/talk/display.c @@ -1,212 +1,209 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)display.c 8.1 (Berkeley) 6/6/93"; #endif /* * The window 'manager', initializes curses and handles the actual * displaying of text */ #include #include #include #define _XOPEN_SOURCE_EXTENDED #include #include "talk.h" void display(xwin_t *, wchar_t *); xwin_t my_win; xwin_t his_win; WINDOW *line_win; int curses_initialized = 0; /* * max HAS to be a function, it is called with * an argument of the form --foo at least once. */ int max(int a, int b) { return (a > b ? a : b); } static cchar_t * makecchar(wchar_t in) { static cchar_t cc; wchar_t wc[2]; wc[0] = in; wc[1] = L'\0'; if (setcchar(&cc, wc, A_NORMAL, 0, NULL) != OK) p_error("settchar(3) failure"); return (&cc); } /* * Display a symbol on somebody's window, processing some control * characters while we are at it. */ void display(xwin_t *win, wchar_t *wc) { /* * Alas, can't use variables in C switch statement. * Workaround these 3 cases with goto. */ if (*wc == win->kill) goto kill; else if (*wc == win->cerase) goto cerase; else if (*wc == win->werase) goto werase; switch (*wc) { case L'\n': case L'\r': wadd_wch(win->x_win, makecchar(L'\n')); getyx(win->x_win, win->x_line, win->x_col); wrefresh(win->x_win); return; case 004: if (win == &my_win) { /* Ctrl-D clears the screen. */ werase(my_win.x_win); getyx(my_win.x_win, my_win.x_line, my_win.x_col); wrefresh(my_win.x_win); werase(his_win.x_win); getyx(his_win.x_win, his_win.x_line, his_win.x_col); wrefresh(his_win.x_win); } return; /* Erase character. */ case 010: /* BS */ case 0177: /* DEL */ cerase: wmove(win->x_win, win->x_line, max(--win->x_col, 0)); getyx(win->x_win, win->x_line, win->x_col); waddch(win->x_win, ' '); wmove(win->x_win, win->x_line, win->x_col); getyx(win->x_win, win->x_line, win->x_col); wrefresh(win->x_win); return; case 027: /* ^W */ werase: { /* * On word erase search backwards until we find * the beginning of a word or the beginning of * the line. */ int endcol, xcol, c; endcol = win->x_col; xcol = endcol - 1; while (xcol >= 0) { c = readwin(win->x_win, win->x_line, xcol); if (c != ' ') break; xcol--; } while (xcol >= 0) { c = readwin(win->x_win, win->x_line, xcol); if (c == ' ') break; xcol--; } wmove(win->x_win, win->x_line, xcol + 1); for (int i = xcol + 1; i < endcol; i++) waddch(win->x_win, ' '); wmove(win->x_win, win->x_line, xcol + 1); getyx(win->x_win, win->x_line, win->x_col); wrefresh(win->x_win); return; } case 025: /* ^U */ kill: wmove(win->x_win, win->x_line, 0); wclrtoeol(win->x_win); getyx(win->x_win, win->x_line, win->x_col); wrefresh(win->x_win); return; case L'\f': if (win == &my_win) wrefresh(curscr); return; case L'\7': write(STDOUT_FILENO, wc, sizeof(*wc)); return; } if (iswprint(*wc) || *wc == L'\t') wadd_wch(win->x_win, makecchar(*wc)); else beep(); getyx(win->x_win, win->x_line, win->x_col); wrefresh(win->x_win); } /* * Read the character at the indicated position in win */ int readwin(WINDOW *win, int line, int col) { int oldline, oldcol; int c; getyx(win, oldline, oldcol); wmove(win, line, col); c = winch(win); wmove(win, oldline, oldcol); return (c); } diff --git a/usr.bin/talk/get_addrs.c b/usr.bin/talk/get_addrs.c index 53b841cee2ca..678fabce9aa2 100644 --- a/usr.bin/talk/get_addrs.c +++ b/usr.bin/talk/get_addrs.c @@ -1,67 +1,64 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)get_addrs.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include "talk.h" #include "talk_ctl.h" void get_addrs(const char *my_machine_name __unused, const char *his_machine_name) { struct hostent *hp; struct servent *sp; msg.pid = htonl(getpid()); hp = gethostbyname(his_machine_name); if (hp == NULL) errx(1, "%s: %s", his_machine_name, hstrerror(h_errno)); bcopy(hp->h_addr, (char *) &his_machine_addr, hp->h_length); if (get_iface(&his_machine_addr, &my_machine_addr) == -1) err(1, "failed to find my interface address"); /* find the server's port */ sp = getservbyname("ntalk", "udp"); if (sp == NULL) errx(1, "ntalk/udp: service is not registered"); daemon_port = sp->s_port; } diff --git a/usr.bin/talk/get_iface.c b/usr.bin/talk/get_iface.c index 96d3d6edabb5..5c69046c680e 100644 --- a/usr.bin/talk/get_iface.c +++ b/usr.bin/talk/get_iface.c @@ -1,100 +1,97 @@ /* * Copyright 1994, 1995 Massachusetts Institute of Technology * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby * granted, provided that both the above copyright notice and this * permission notice appear in all copies, that both the above * copyright notice and this permission notice appear in all * supporting documentation, and that the name of M.I.T. not be used * in advertising or publicity pertaining to distribution of the * software without specific, written prior permission. M.I.T. makes * no representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied * warranty. * * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); /* * From: * Id: find_interface.c,v 1.1 1995/08/14 16:08:39 wollman Exp */ #include #include #include #include "talk.h" /* * Try to find the interface address that is used to route an IP * packet to a remote peer. */ int get_iface(struct in_addr *dst, struct in_addr *iface) { static struct sockaddr_in local; struct sockaddr_in remote; socklen_t namelen; int s, rv; memcpy(&remote.sin_addr, dst, sizeof remote.sin_addr); remote.sin_port = htons(60000); remote.sin_family = AF_INET; remote.sin_len = sizeof remote; local.sin_addr.s_addr = htonl(INADDR_ANY); local.sin_port = htons(60000); local.sin_family = AF_INET; local.sin_len = sizeof local; s = socket(PF_INET, SOCK_DGRAM, 0); if (s < 0) return -1; do { rv = bind(s, (struct sockaddr *)&local, sizeof local); local.sin_port = htons(ntohs(local.sin_port) + 1); } while(rv < 0 && errno == EADDRINUSE); if (rv < 0) { close(s); return -1; } do { rv = connect(s, (struct sockaddr *)&remote, sizeof remote); remote.sin_port = htons(ntohs(remote.sin_port) + 1); } while(rv < 0 && errno == EADDRINUSE); if (rv < 0) { close(s); return -1; } namelen = sizeof local; rv = getsockname(s, (struct sockaddr *)&local, &namelen); close(s); if (rv < 0) return -1; memcpy(iface, &local.sin_addr, sizeof local.sin_addr); return 0; } diff --git a/usr.bin/talk/get_names.c b/usr.bin/talk/get_names.c index 3ca362ad9bff..78b025144328 100644 --- a/usr.bin/talk/get_names.c +++ b/usr.bin/talk/get_names.c @@ -1,117 +1,114 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)get_names.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include "talk.h" extern CTL_MSG msg; static void usage(void) { fprintf(stderr, "usage: talk person [ttyname]\n"); exit(1); } /* * Determine the local and remote user, tty, and machines */ void get_names(int argc, char *argv[]) { char hostname[MAXHOSTNAMELEN]; char *his_name, *my_name; const char *my_machine_name, *his_machine_name; const char *his_tty; char *cp; if (argc < 2 ) usage(); if (!isatty(0)) errx(1, "standard input must be a tty, not a pipe or a file"); if ((my_name = getlogin()) == NULL) { struct passwd *pw; if ((pw = getpwuid(getuid())) == NULL) errx(1, "you don't exist. Go away"); my_name = pw->pw_name; } gethostname(hostname, sizeof (hostname)); my_machine_name = hostname; /* check for, and strip out, the machine name of the target */ cp = argv[1] + strcspn(argv[1], "@:!"); if (*cp == '\0') { /* this is a local to local talk */ his_name = argv[1]; my_machine_name = his_machine_name = "localhost"; } else { if (*cp++ == '@') { /* user@host */ his_name = argv[1]; his_machine_name = cp; } else { /* host!user or host:user */ his_name = cp; his_machine_name = argv[1]; } *--cp = '\0'; } if (argc > 2) his_tty = argv[2]; /* tty name is arg 2 */ else his_tty = ""; get_addrs(my_machine_name, his_machine_name); /* * Initialize the message template. */ msg.vers = TALK_VERSION; msg.addr.sa_family = htons(AF_INET); msg.ctl_addr.sa_family = htons(AF_INET); msg.id_num = htonl(0); strlcpy(msg.l_name, my_name, NAME_SIZE); strlcpy(msg.r_name, his_name, NAME_SIZE); strlcpy(msg.r_tty, his_tty, TTY_SIZE); } diff --git a/usr.bin/talk/init_disp.c b/usr.bin/talk/init_disp.c index a3f125792254..936b9799a22c 100644 --- a/usr.bin/talk/init_disp.c +++ b/usr.bin/talk/init_disp.c @@ -1,235 +1,232 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)init_disp.c 8.2 (Berkeley) 2/16/94"; #endif /* * Initialization code for the display package, * as well as the signal handling routines. */ #include #include #include #include #include #include #include "talk.h" /* * Make sure the callee can write to the screen */ void check_writeable(void) { char *tty; struct stat sb; if ((tty = ttyname(STDERR_FILENO)) == NULL) err(1, "ttyname"); if (stat(tty, &sb) < 0) err(1, "%s", tty); if (!(sb.st_mode & S_IWGRP)) errx(1, "The callee cannot write to this terminal, use \"mesg y\"."); } /* * Set up curses, catch the appropriate signals, * and build the various windows. */ void init_display(void) { struct sigaction sa; if (initscr() == NULL) errx(1, "Terminal type unset or lacking necessary features."); (void) sigaction(SIGTSTP, (struct sigaction *)0, &sa); sigaddset(&sa.sa_mask, SIGALRM); (void) sigaction(SIGTSTP, &sa, (struct sigaction *)0); curses_initialized = 1; clear(); refresh(); noecho(); crmode(); signal(SIGINT, sig_sent); signal(SIGPIPE, sig_sent); signal(SIGWINCH, sig_winch); /* curses takes care of ^Z */ my_win.x_nlines = LINES / 2; my_win.x_ncols = COLS; my_win.x_win = newwin(my_win.x_nlines, my_win.x_ncols, 0, 0); idlok(my_win.x_win, TRUE); scrollok(my_win.x_win, TRUE); wclear(my_win.x_win); his_win.x_nlines = LINES / 2 - 1; his_win.x_ncols = COLS; his_win.x_win = newwin(his_win.x_nlines, his_win.x_ncols, my_win.x_nlines+1, 0); idlok(my_win.x_win, TRUE); scrollok(his_win.x_win, TRUE); wclear(his_win.x_win); line_win = newwin(1, COLS, my_win.x_nlines, 0); #if defined(hline) || defined(whline) || defined(NCURSES_VERSION) whline(line_win, 0, COLS); #else box(line_win, '-', '-'); #endif wrefresh(line_win); /* let them know we are working on it */ current_state = "No connection yet"; } /* * Trade edit characters with the other talk. By agreement * the first three characters each talk transmits after * connection are the three edit characters. */ void set_edit_chars(void) { char buf[3]; int cc; struct termios tio; tcgetattr(0, &tio); my_win.cerase = tio.c_cc[VERASE]; my_win.kill = tio.c_cc[VKILL]; my_win.werase = tio.c_cc[VWERASE]; if (my_win.cerase == (char)_POSIX_VDISABLE) my_win.kill = CERASE; if (my_win.kill == (char)_POSIX_VDISABLE) my_win.kill = CKILL; if (my_win.werase == (char)_POSIX_VDISABLE) my_win.werase = CWERASE; buf[0] = my_win.cerase; buf[1] = my_win.kill; buf[2] = my_win.werase; cc = write(sockt, buf, sizeof(buf)); if (cc != sizeof(buf) ) p_error("Lost the connection"); cc = read(sockt, buf, sizeof(buf)); if (cc != sizeof(buf) ) p_error("Lost the connection"); his_win.cerase = buf[0]; his_win.kill = buf[1]; his_win.werase = buf[2]; } /* ARGSUSED */ void sig_sent(int signo __unused) { message("Connection closing. Exiting"); quit(); } void sig_winch(int dummy __unused) { gotwinch = 1; } /* * All done talking...hang up the phone and reset terminal thingy's */ void quit(void) { if (curses_initialized) { wmove(his_win.x_win, his_win.x_nlines-1, 0); wclrtoeol(his_win.x_win); wrefresh(his_win.x_win); endwin(); } if (invitation_waiting) send_delete(); exit(0); } /* * If we get SIGWINCH, recompute both window sizes and refresh things. */ void resize_display(void) { struct winsize ws; if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0 || (ws.ws_row == LINES && ws.ws_col == COLS)) return; /* Update curses' internal state with new window size. */ resizeterm(ws.ws_row, ws.ws_col); /* * Resize each window but wait to refresh the screen until * everything has been drawn so the cursor is in the right spot. */ my_win.x_nlines = LINES / 2; my_win.x_ncols = COLS; wresize(my_win.x_win, my_win.x_nlines, my_win.x_ncols); mvwin(my_win.x_win, 0, 0); clearok(my_win.x_win, TRUE); his_win.x_nlines = LINES / 2 - 1; his_win.x_ncols = COLS; wresize(his_win.x_win, his_win.x_nlines, his_win.x_ncols); mvwin(his_win.x_win, my_win.x_nlines + 1, 0); clearok(his_win.x_win, TRUE); wresize(line_win, 1, COLS); mvwin(line_win, my_win.x_nlines, 0); #if defined(NCURSES_VERSION) || defined(whline) whline(line_win, '-', COLS); #else wmove(line_win, my_win.x_nlines, 0); box(line_win, '-', '-'); #endif /* Now redraw the screen. */ wrefresh(his_win.x_win); wrefresh(line_win); wrefresh(my_win.x_win); } diff --git a/usr.bin/talk/invite.c b/usr.bin/talk/invite.c index e000e54b0c35..78f92ed9cdbf 100644 --- a/usr.bin/talk/invite.c +++ b/usr.bin/talk/invite.c @@ -1,194 +1,191 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)invite.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include #include #include "talk_ctl.h" #include "talk.h" /* * There wasn't an invitation waiting, so send a request containing * our sockt address to the remote talk daemon so it can invite * him */ /* * The msg.id's for the invitations * on the local and remote machines. * These are used to delete the * invitations. */ static int local_id, remote_id; static jmp_buf invitebuf; void invite_remote(void) { int new_sockt; struct itimerval itimer; CTL_RESPONSE response; itimer.it_value.tv_sec = RING_WAIT; itimer.it_value.tv_usec = 0; itimer.it_interval = itimer.it_value; if (listen(sockt, 5) != 0) p_error("Error on attempt to listen for caller"); /* copy new style sockaddr to old, swap family (short in old) */ msg.addr = *(struct tsockaddr *)&my_addr; msg.addr.sa_family = htons(my_addr.sin_family); msg.id_num = htonl(-1); /* an impossible id_num */ invitation_waiting = 1; announce_invite(); /* * Shut off the automatic messages for a while, * so we can use the interrupt timer to resend the invitation */ end_msgs(); setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); message("Waiting for your party to respond"); signal(SIGALRM, re_invite); (void) setjmp(invitebuf); while ((new_sockt = accept(sockt, 0, 0)) < 0) { if (errno == EINTR) continue; p_error("Unable to connect with your party"); } close(sockt); sockt = new_sockt; /* * Have the daemons delete the invitations now that we * have connected. */ current_state = "Waiting for your party to respond"; start_msgs(); msg.id_num = htonl(local_id); ctl_transact(my_machine_addr, msg, DELETE, &response); msg.id_num = htonl(remote_id); ctl_transact(his_machine_addr, msg, DELETE, &response); invitation_waiting = 0; } /* * Routine called on interrupt to re-invite the callee */ /* ARGSUSED */ void re_invite(int signo __unused) { message("Ringing your party again"); waddch(my_win.x_win, '\n'); if (current_line < my_win.x_nlines - 1) current_line++; /* force a re-announce */ msg.id_num = htonl(remote_id + 1); announce_invite(); longjmp(invitebuf, 1); } static const char *answers[] = { "answer #0", /* SUCCESS */ "Your party is not logged on", /* NOT_HERE */ "Target machine is too confused to talk to us", /* FAILED */ "Target machine does not recognize us", /* MACHINE_UNKNOWN */ "Your party is refusing messages", /* PERMISSION_REFUSED */ "Target machine can not handle remote talk", /* UNKNOWN_REQUEST */ "Target machine indicates protocol mismatch", /* BADVERSION */ "Target machine indicates protocol botch (addr)",/* BADADDR */ "Target machine indicates protocol botch (ctl_addr)",/* BADCTLADDR */ }; #define NANSWERS (sizeof (answers) / sizeof (answers[0])) /* * Transmit the invitation and process the response */ void announce_invite(void) { CTL_RESPONSE response; current_state = "Trying to connect to your party's talk daemon"; ctl_transact(his_machine_addr, msg, ANNOUNCE, &response); remote_id = response.id_num; if (response.answer != SUCCESS) { if (response.answer < NANSWERS) message(answers[response.answer]); quit(); } /* leave the actual invitation on my talk daemon */ current_state = "Trying to connect to local talk daemon"; ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response); local_id = response.id_num; } /* * Tell the daemon to remove your invitation */ void send_delete(void) { msg.type = DELETE; /* * This is just an extra clean up, so just send it * and don't wait for an answer */ msg.id_num = htonl(remote_id); daemon_addr.sin_addr = his_machine_addr; if (sendto(ctl_sockt, &msg, sizeof (msg), 0, (struct sockaddr *)&daemon_addr, sizeof (daemon_addr)) != sizeof(msg)) warn("send_delete (remote)"); msg.id_num = htonl(local_id); daemon_addr.sin_addr = my_machine_addr; if (sendto(ctl_sockt, &msg, sizeof (msg), 0, (struct sockaddr *)&daemon_addr, sizeof (daemon_addr)) != sizeof (msg)) warn("send_delete (local)"); } diff --git a/usr.bin/talk/io.c b/usr.bin/talk/io.c index 9cf7ad8346eb..c47bf928712b 100644 --- a/usr.bin/talk/io.c +++ b/usr.bin/talk/io.c @@ -1,179 +1,176 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)io.c 8.1 (Berkeley) 6/6/93"; #endif /* * This file contains the I/O handling and the exchange of * edit characters. This connection itself is established in * ctl.c */ #include #include #include #include #include #include #include #include #include #define _XOPEN_SOURCE_EXTENDED #include #include "talk.h" #include "talk_ctl.h" extern void display(xwin_t *, wchar_t *); volatile sig_atomic_t gotwinch = 0; /* * The routine to do the actual talking */ void talk(void) { struct hostent *hp, *hp2; struct pollfd fds[2]; int nb; wchar_t buf[BUFSIZ]; char **addr, *his_machine_name; FILE *sockfp; his_machine_name = NULL; hp = gethostbyaddr((const char *)&his_machine_addr.s_addr, sizeof(his_machine_addr.s_addr), AF_INET); if (hp != NULL) { hp2 = gethostbyname(hp->h_name); if (hp2 != NULL && hp2->h_addrtype == AF_INET && hp2->h_length == sizeof(his_machine_addr)) for (addr = hp2->h_addr_list; *addr != NULL; addr++) if (memcmp(*addr, &his_machine_addr, sizeof(his_machine_addr)) == 0) { his_machine_name = strdup(hp->h_name); break; } } if (his_machine_name == NULL) his_machine_name = strdup(inet_ntoa(his_machine_addr)); snprintf((char *)buf, sizeof(buf), "Connection established with %s@%s.", msg.r_name, his_machine_name); free(his_machine_name); message((char *)buf); write(STDOUT_FILENO, "\007\007\007", 3); current_line = 0; if ((sockfp = fdopen(sockt, "w+")) == NULL) p_error("fdopen"); setvbuf(sockfp, NULL, _IONBF, 0); setvbuf(stdin, NULL, _IONBF, 0); /* * Wait on both the other process (sockt) and standard input. */ for (;;) { fds[0].fd = fileno(stdin); fds[0].events = POLLIN; fds[1].fd = sockt; fds[1].events = POLLIN; nb = poll(fds, 2, INFTIM); if (gotwinch) { resize_display(); gotwinch = 0; } if (nb <= 0) { if (errno == EINTR) continue; /* Panic, we don't know what happened. */ p_error("Unexpected error from poll"); quit(); } if (fds[1].revents & POLLIN) { wint_t w; /* There is data on sockt. */ w = fgetwc(sockfp); if (w == WEOF) { message("Connection closed. Exiting"); quit(); } display(&his_win, &w); } if (fds[0].revents & POLLIN) { wint_t w; if ((w = getwchar()) != WEOF) { display(&my_win, &w); (void )fputwc(w, sockfp); (void )fflush(sockfp); } } } } /* * p_error prints the system error message on the standard location * on the screen and then exits. (i.e. a curses version of perror) */ void p_error(const char *string) { wmove(my_win.x_win, current_line, 0); wprintw(my_win.x_win, "[%s : %s (%d)]\n", string, strerror(errno), errno); wrefresh(my_win.x_win); move(LINES-1, 0); refresh(); quit(); } /* * Display string in the standard location */ void message(const char *string) { wmove(my_win.x_win, current_line, 0); wprintw(my_win.x_win, "[%s]\n", string); if (current_line < my_win.x_nlines - 1) current_line++; wrefresh(my_win.x_win); } diff --git a/usr.bin/talk/look_up.c b/usr.bin/talk/look_up.c index 3c676b9c1ea2..3fb6cbb43037 100644 --- a/usr.bin/talk/look_up.c +++ b/usr.bin/talk/look_up.c @@ -1,119 +1,116 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)look_up.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include "talk_ctl.h" #include "talk.h" /* * See if the local daemon has an invitation for us. */ int check_local(void) { CTL_RESPONSE response; CTL_RESPONSE *rp = &response; struct sockaddr addr; /* the rest of msg was set up in get_names */ /* copy new style sockaddr to old, swap family (short in old) */ msg.ctl_addr = *(struct tsockaddr *)&ctl_addr; msg.ctl_addr.sa_family = htons(ctl_addr.sin_family); /* must be initiating a talk */ if (!look_for_invite(rp)) return (0); /* * There was an invitation waiting for us, * so connect with the other (hopefully waiting) party */ current_state = "Waiting to connect with caller"; do { if (rp->addr.sa_family != AF_INET) p_error("Response uses invalid network address"); (void)memcpy(&addr, &rp->addr.sa_family, sizeof(addr)); addr.sa_family = rp->addr.sa_family; addr.sa_len = sizeof(addr); errno = 0; if (connect(sockt, &addr, sizeof(addr)) != -1) return (1); } while (errno == EINTR); if (errno == ECONNREFUSED) { /* * The caller gave up, but his invitation somehow * was not cleared. Clear it and initiate an * invitation. (We know there are no newer invitations, * the talkd works LIFO.) */ ctl_transact(his_machine_addr, msg, DELETE, rp); close(sockt); open_sockt(); return (0); } p_error("Unable to connect with initiator"); /*NOTREACHED*/ return (0); } /* * Look for an invitation on 'machine' */ int look_for_invite(CTL_RESPONSE *rp) { current_state = "Checking for invitation on caller's machine"; ctl_transact(his_machine_addr, msg, LOOK_UP, rp); /* the switch is for later options, such as multiple invitations */ switch (rp->answer) { case SUCCESS: msg.id_num = htonl(rp->id_num); return (1); default: /* there wasn't an invitation waiting for us */ return (0); } } diff --git a/usr.bin/talk/msgs.c b/usr.bin/talk/msgs.c index e0886e9477f7..a40df7ff17e9 100644 --- a/usr.bin/talk/msgs.c +++ b/usr.bin/talk/msgs.c @@ -1,82 +1,79 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)msgs.c 8.1 (Berkeley) 6/6/93"; #endif /* * A package to display what is happening every MSG_INTERVAL seconds * if we are slow connecting. */ #include #include "talk.h" #define MSG_INTERVAL 4 const char *current_state; int current_line = 0; /* ARGSUSED */ void disp_msg(int signo __unused) { message(current_state); } void start_msgs(void) { struct itimerval itimer; message(current_state); signal(SIGALRM, disp_msg); itimer.it_value.tv_sec = itimer.it_interval.tv_sec = MSG_INTERVAL; itimer.it_value.tv_usec = itimer.it_interval.tv_usec = 0; setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); } void end_msgs(void) { struct itimerval itimer; timerclear(&itimer.it_value); timerclear(&itimer.it_interval); setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); signal(SIGALRM, SIG_DFL); } diff --git a/usr.bin/talk/talk.c b/usr.bin/talk/talk.c index 4b7e748e2f09..04c8572a04b4 100644 --- a/usr.bin/talk/talk.c +++ b/usr.bin/talk/talk.c @@ -1,84 +1,81 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)talk.c 8.1 (Berkeley) 6/6/93"; #endif #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #include #include #include "talk.h" /* * talk: A visual form of write. Using sockets, a two way * connection is set up between the two people talking. * With the aid of curses, the screen is split into two * windows, and each users text is added to the window, * one character at a time... * * Written by Kipp Hickman * * Modified to run under 4.1a by Clem Cole and Peter Moore * Modified to run between hosts by Peter Moore, 8/19/82 * Modified to run under 4.1c by Peter Moore 3/17/83 * Fixed to not run with unwriteable terminals MRVM 28/12/94 */ int main(int argc, char **argv) { (void) setlocale(LC_CTYPE, ""); get_names(argc, argv); setproctitle(" "); check_writeable(); init_display(); open_ctl(); open_sockt(); start_msgs(); if (!check_local()) invite_remote(); end_msgs(); set_edit_chars(); talk(); return 0; } diff --git a/usr.bin/tcopy/tcopy.c b/usr.bin/tcopy/tcopy.c index 24dcc969a9af..3db554fb1f49 100644 --- a/usr.bin/tcopy/tcopy.c +++ b/usr.bin/tcopy/tcopy.c @@ -1,340 +1,337 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1985, 1987, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1985, 1987, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)tcopy.c 8.2 (Berkeley) 4/17/94"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define MAXREC (64 * 1024) #define NOCOUNT (-2) static int filen, guesslen, maxblk = MAXREC; static uint64_t lastrec, record, size, tsize; static FILE *msg; static void *getspace(int); static void intr(int); static void usage(void) __dead2; static void verify(int, int, char *); static void writeop(int, int); static void rewind_tape(int); int main(int argc, char *argv[]) { int lastnread, nread, nw, inp, outp; enum {READ, VERIFY, COPY, COPYVERIFY} op = READ; sig_t oldsig; int ch, needeof; char *buff; const char *inf; msg = stdout; guesslen = 1; outp = -1; while ((ch = getopt(argc, argv, "cs:vx")) != -1) switch((char)ch) { case 'c': op = COPYVERIFY; break; case 's': maxblk = atoi(optarg); if (maxblk <= 0) { warnx("illegal block size"); usage(); } guesslen = 0; break; case 'v': op = VERIFY; break; case 'x': msg = stderr; break; case '?': default: usage(); } argc -= optind; argv += optind; switch(argc) { case 0: if (op != READ) usage(); inf = _PATH_DEFTAPE; break; case 1: if (op != READ) usage(); inf = argv[0]; break; case 2: if (op == READ) op = COPY; inf = argv[0]; if ((outp = open(argv[1], op == VERIFY ? O_RDONLY : op == COPY ? O_WRONLY : O_RDWR, DEFFILEMODE)) < 0) err(3, "%s", argv[1]); break; default: usage(); } if ((inp = open(inf, O_RDONLY, 0)) < 0) err(1, "%s", inf); buff = getspace(maxblk); if (op == VERIFY) { verify(inp, outp, buff); exit(0); } if ((oldsig = signal(SIGINT, SIG_IGN)) != SIG_IGN) (void) signal(SIGINT, intr); needeof = 0; for (lastnread = NOCOUNT;;) { if ((nread = read(inp, buff, maxblk)) == -1) { while (errno == EINVAL && (maxblk -= 1024)) { nread = read(inp, buff, maxblk); if (nread >= 0) goto r1; } err(1, "read error, file %d, record %ju", filen, (intmax_t)record); } else if (nread != lastnread) { if (lastnread != 0 && lastnread != NOCOUNT) { if (lastrec == 0 && nread == 0) fprintf(msg, "%ju records\n", (intmax_t)record); else if (record - lastrec > 1) fprintf(msg, "records %ju to %ju\n", (intmax_t)lastrec, (intmax_t)record); else fprintf(msg, "record %ju\n", (intmax_t)lastrec); } if (nread != 0) fprintf(msg, "file %d: block size %d: ", filen, nread); (void) fflush(stdout); lastrec = record; } r1: guesslen = 0; if (nread > 0) { if (op == COPY || op == COPYVERIFY) { if (needeof) { writeop(outp, MTWEOF); needeof = 0; } nw = write(outp, buff, nread); if (nw != nread) { if (nw == -1) { warn("write error, file %d, record %ju", filen, (intmax_t)record); } else { warnx("write error, file %d, record %ju", filen, (intmax_t)record); warnx("write (%d) != read (%d)", nw, nread); } errx(5, "copy aborted"); } } size += nread; record++; } else { if (lastnread <= 0 && lastnread != NOCOUNT) { fprintf(msg, "eot\n"); break; } fprintf(msg, "file %d: eof after %ju records: %ju bytes\n", filen, (intmax_t)record, (intmax_t)size); needeof = 1; filen++; tsize += size; size = record = lastrec = 0; lastnread = 0; } lastnread = nread; } fprintf(msg, "total length: %ju bytes\n", (intmax_t)tsize); (void)signal(SIGINT, oldsig); if (op == COPY || op == COPYVERIFY) { writeop(outp, MTWEOF); writeop(outp, MTWEOF); if (op == COPYVERIFY) { rewind_tape(outp); rewind_tape(inp); verify(inp, outp, buff); } } exit(0); } static void verify(int inp, int outp, char *outb) { int eot, inmaxblk, inn, outmaxblk, outn; char *inb; inb = getspace(maxblk); inmaxblk = outmaxblk = maxblk; for (eot = 0;; guesslen = 0) { if ((inn = read(inp, inb, inmaxblk)) == -1) { if (guesslen) while (errno == EINVAL && (inmaxblk -= 1024)) { inn = read(inp, inb, inmaxblk); if (inn >= 0) goto r1; } warn("read error"); break; } r1: if ((outn = read(outp, outb, outmaxblk)) == -1) { if (guesslen) while (errno == EINVAL && (outmaxblk -= 1024)) { outn = read(outp, outb, outmaxblk); if (outn >= 0) goto r2; } warn("read error"); break; } r2: if (inn != outn) { fprintf(msg, "%s: tapes have different block sizes; %d != %d.\n", "tcopy", inn, outn); break; } if (!inn) { if (eot++) { fprintf(msg, "tcopy: tapes are identical.\n"); free(inb); return; } } else { if (bcmp(inb, outb, inn)) { fprintf(msg, "tcopy: tapes have different data.\n"); break; } eot = 0; } } exit(1); } static void intr(int signo __unused) { if (record) { if (record - lastrec > 1) fprintf(msg, "records %ju to %ju\n", (intmax_t)lastrec, (intmax_t)record); else fprintf(msg, "record %ju\n", (intmax_t)lastrec); } fprintf(msg, "interrupt at file %d: record %ju\n", filen, (intmax_t)record); fprintf(msg, "total length: %ju bytes\n", (uintmax_t)(tsize + size)); exit(1); } static void * getspace(int blk) { void *bp; if ((bp = malloc((size_t)blk)) == NULL) errx(11, "no memory"); return (bp); } static void writeop(int fd, int type) { struct mtop op; op.mt_op = type; op.mt_count = (daddr_t)1; if (ioctl(fd, MTIOCTOP, (char *)&op) < 0) err(6, "tape op"); } static void usage(void) { fprintf(stderr, "usage: tcopy [-cvx] [-s maxblk] [src [dest]]\n"); exit(1); } static void rewind_tape(int fd) { struct stat sp; if(fstat(fd, &sp)) errx(12, "fstat in rewind"); /* * don't want to do tape ioctl on regular files: */ if( S_ISREG(sp.st_mode) ) { if( lseek(fd, 0, SEEK_SET) == -1 ) errx(13, "lseek"); } else /* assume its a tape */ writeop(fd, MTREW); } diff --git a/usr.bin/touch/touch.c b/usr.bin/touch/touch.c index 1594eacb67d0..91abcfd447ea 100644 --- a/usr.bin/touch/touch.c +++ b/usr.bin/touch/touch.c @@ -1,414 +1,411 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)touch.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include static void stime_arg1(const char *, struct timespec *); static void stime_arg2(const char *, int, struct timespec *); static void stime_darg(const char *, struct timespec *); static void stime_file(const char *, struct timespec *); static int timeoffset(const char *); static void usage(const char *); int main(int argc, char *argv[]) { struct stat sb; struct timespec ts[2]; int atflag; int Aflag, aflag, cflag, mflag, ch, fd, len, rval, timeset; char *p; char *myname; myname = basename(argv[0]); Aflag = aflag = cflag = mflag = timeset = 0; atflag = 0; ts[0].tv_sec = ts[1].tv_sec = 0; ts[0].tv_nsec = ts[1].tv_nsec = UTIME_NOW; while ((ch = getopt(argc, argv, "A:acd:fhmr:t:")) != -1) switch(ch) { case 'A': Aflag = timeoffset(optarg); break; case 'a': aflag = 1; break; case 'c': cflag = 1; break; case 'd': timeset = 1; stime_darg(optarg, ts); break; case 'f': /* No-op for compatibility. */ break; case 'h': cflag = 1; atflag = AT_SYMLINK_NOFOLLOW; break; case 'm': mflag = 1; break; case 'r': timeset = 1; stime_file(optarg, ts); break; case 't': timeset = 1; stime_arg1(optarg, ts); break; default: usage(myname); } argc -= optind; argv += optind; if (aflag == 0 && mflag == 0) aflag = mflag = 1; if (timeset) { if (Aflag) { /* * We're setting the time to an offset from a specified * time. God knows why, but it means that we can set * that time once and for all here. */ if (aflag) ts[0].tv_sec += Aflag; if (mflag) ts[1].tv_sec += Aflag; Aflag = 0; /* done our job */ } } else { /* * If no -r or -t flag, at least two operands, the first of * which is an 8 or 10 digit number, use the obsolete time * specification, otherwise use the current time. */ if (argc > 1) { strtol(argv[0], &p, 10); len = p - argv[0]; if (*p == '\0' && (len == 8 || len == 10)) { timeset = 1; stime_arg2(*argv++, len == 10, ts); } } /* Both times default to the same. */ ts[1] = ts[0]; } if (!aflag) ts[0].tv_nsec = UTIME_OMIT; if (!mflag) ts[1].tv_nsec = UTIME_OMIT; if (*argv == NULL) usage(myname); if (Aflag) cflag = 1; for (rval = 0; *argv; ++argv) { /* See if the file exists. */ if (fstatat(AT_FDCWD, *argv, &sb, atflag) != 0) { if (errno != ENOENT) { rval = 1; warn("%s", *argv); continue; } if (!cflag) { /* Create the file. */ fd = open(*argv, O_WRONLY | O_CREAT, DEFFILEMODE); if (fd == -1) { rval = 1; warn("%s", *argv); continue; } if (fstat(fd, &sb) < 0) { warn("%s", *argv); rval = 1; } if (close(fd) < 0) { warn("%s", *argv); rval = 1; } /* If using the current time, we're done. */ if (!timeset) continue; } else continue; } /* * We're adjusting the times based on the file times, not a * specified time (that gets handled above). */ if (Aflag) { if (aflag) { ts[0] = sb.st_atim; ts[0].tv_sec += Aflag; } if (mflag) { ts[1] = sb.st_mtim; ts[1].tv_sec += Aflag; } } if (!utimensat(AT_FDCWD, *argv, ts, atflag)) continue; rval = 1; warn("%s", *argv); } exit(rval); } #define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2; static void stime_arg1(const char *arg, struct timespec *tvp) { time_t now; struct tm *t; int yearset; char *p; now = time(NULL); if ((t = localtime(&now)) == NULL) err(1, "localtime"); /* [[CC]YY]MMDDhhmm[.SS] */ if ((p = strchr(arg, '.')) == NULL) t->tm_sec = 0; /* Seconds defaults to 0. */ else { if (strlen(p + 1) != 2) goto terr; *p++ = '\0'; t->tm_sec = ATOI2(p); } yearset = 0; switch(strlen(arg)) { case 12: /* CCYYMMDDhhmm */ t->tm_year = ATOI2(arg); t->tm_year *= 100; yearset = 1; /* FALLTHROUGH */ case 10: /* YYMMDDhhmm */ if (yearset) { yearset = ATOI2(arg); t->tm_year += yearset; } else { yearset = ATOI2(arg); if (yearset < 69) t->tm_year = yearset + 2000; else t->tm_year = yearset + 1900; } t->tm_year -= 1900; /* Convert to UNIX time. */ /* FALLTHROUGH */ case 8: /* MMDDhhmm */ t->tm_mon = ATOI2(arg); --t->tm_mon; /* Convert from 01-12 to 00-11 */ t->tm_mday = ATOI2(arg); t->tm_hour = ATOI2(arg); t->tm_min = ATOI2(arg); break; default: goto terr; } t->tm_isdst = -1; /* Figure out DST. */ tvp[0].tv_sec = tvp[1].tv_sec = mktime(t); if (tvp[0].tv_sec == -1) goto terr; tvp[0].tv_nsec = tvp[1].tv_nsec = 0; return; terr: errx(1, "out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]"); } static void stime_arg2(const char *arg, int year, struct timespec *tvp) { time_t now; struct tm *t; now = time(NULL); if ((t = localtime(&now)) == NULL) err(1, "localtime"); t->tm_mon = ATOI2(arg); /* MMDDhhmm[yy] */ --t->tm_mon; /* Convert from 01-12 to 00-11 */ t->tm_mday = ATOI2(arg); t->tm_hour = ATOI2(arg); t->tm_min = ATOI2(arg); if (year) { t->tm_year = ATOI2(arg); if (t->tm_year < 39) /* support 2000-2038 not 1902-1969 */ t->tm_year += 100; } t->tm_isdst = -1; /* Figure out DST. */ tvp[0].tv_sec = tvp[1].tv_sec = mktime(t); if (tvp[0].tv_sec == -1) errx(1, "out of range or illegal time specification: MMDDhhmm[yy]"); tvp[0].tv_nsec = tvp[1].tv_nsec = 0; } static void stime_darg(const char *arg, struct timespec *tvp) { struct tm t = { .tm_sec = 0 }; const char *fmt, *colon; char *p; int val, isutc = 0; tvp[0].tv_nsec = 0; t.tm_isdst = -1; colon = strchr(arg, ':'); if (colon == NULL || strchr(colon + 1, ':') == NULL) goto bad; fmt = strchr(arg, 'T') != NULL ? "%Y-%m-%dT%H:%M:%S" : "%Y-%m-%d %H:%M:%S"; p = strptime(arg, fmt, &t); if (p == NULL) goto bad; /* POSIX: must have at least one digit after dot */ if ((*p == '.' || *p == ',') && isdigit((unsigned char)p[1])) { p++; val = 100000000; while (isdigit((unsigned char)*p)) { tvp[0].tv_nsec += val * (*p - '0'); p++; val /= 10; } } if (*p == 'Z') { isutc = 1; p++; } if (*p != '\0') goto bad; tvp[0].tv_sec = isutc ? timegm(&t) : mktime(&t); tvp[1] = tvp[0]; return; bad: errx(1, "out of range or illegal time specification: YYYY-MM-DDThh:mm:SS[.frac][tz]"); } /* Calculate a time offset in seconds, given an arg of the format [-]HHMMSS. */ int timeoffset(const char *arg) { int offset; int isneg; offset = 0; isneg = *arg == '-'; if (isneg) arg++; switch (strlen(arg)) { default: /* invalid */ errx(1, "Invalid offset spec, must be [-][[HH]MM]SS"); case 6: /* HHMMSS */ offset = ATOI2(arg); /* FALLTHROUGH */ case 4: /* MMSS */ offset = offset * 60 + ATOI2(arg); /* FALLTHROUGH */ case 2: /* SS */ offset = offset * 60 + ATOI2(arg); } if (isneg) return (-offset); else return (offset); } static void stime_file(const char *fname, struct timespec *tsp) { struct stat sb; if (stat(fname, &sb)) err(1, "%s", fname); tsp[0] = sb.st_atim; tsp[1] = sb.st_mtim; } static void usage(const char *myname) { fprintf(stderr, "usage: %s [-A [-][[hh]mm]SS] [-achm] [-r file] " "[-t [[CC]YY]MMDDhhmm[.SS]]\n" " [-d YYYY-MM-DDThh:mm:SS[.frac][tz]] " "file ...\n", myname); exit(1); } diff --git a/usr.bin/tput/tput.c b/usr.bin/tput/tput.c index 8f678f61b1a0..c6308b4180df 100644 --- a/usr.bin/tput/tput.c +++ b/usr.bin/tput/tput.c @@ -1,214 +1,211 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)tput.c 8.2 (Berkeley) 3/19/94"; #endif #include #include #include #include #include #include #include #undef putchar #define outc putchar static void prlongname(char *); static void usage(void); static char **process(const char *, char *, char **); int main(int argc, char **argv) { int ch, exitval, n; char *cptr, *term, buf[1024], tbuf[1024]; const char *p; term = NULL; while ((ch = getopt(argc, argv, "T:")) != -1) switch(ch) { case 'T': term = optarg; break; case '?': default: usage(); } argc -= optind; argv += optind; if (argc < 1) usage(); if (!term && !(term = getenv("TERM"))) errx(2, "no terminal type specified and no TERM environmental variable."); if (tgetent(tbuf, term) != 1) err(3, "tgetent failure"); for (exitval = 0; (p = *argv) != NULL; ++argv) { switch (*p) { case 'c': if (!strcmp(p, "clear")) p = "cl"; break; case 'i': if (!strcmp(p, "init")) p = "is"; break; case 'l': if (!strcmp(p, "longname")) { prlongname(tbuf); continue; } break; case 'r': if (!strcmp(p, "reset")) p = "rs"; break; } cptr = buf; if (tgetstr(p, &cptr)) argv = process(p, buf, argv); else if ((n = tgetnum(p)) != -1) (void)printf("%d\n", n); else exitval = !tgetflag(p); } exit(exitval); } static void prlongname(char *buf) { int savech; char *p, *savep; for (p = buf; *p && *p != ':'; ++p); savech = *(savep = p); for (*p = '\0'; p >= buf && *p != '|'; --p); (void)printf("%s\n", p + 1); *savep = savech; } static char ** process(const char *cap, char *str, char **argv) { static const char errfew[] = "not enough arguments (%d) for capability `%s'"; static const char errmany[] = "too many arguments (%d) for capability `%s'"; static const char erresc[] = "unknown %% escape `%c' for capability `%s'"; char *cp; int arg_need, arg_rows, arg_cols; /* Count how many values we need for this capability. */ for (cp = str, arg_need = 0; *cp != '\0'; cp++) if (*cp == '%') switch (*++cp) { case 'd': case '2': case '3': case '.': case '+': arg_need++; break; case '%': case '>': case 'i': case 'r': case 'n': case 'B': case 'D': break; case 'p': if (cp[1]) { cp++; break; } default: /* * hpux has lot's of them, but we complain */ warnx(erresc, *cp, cap); } /* And print them. */ switch (arg_need) { case 0: (void)tputs(str, 1, outc); break; case 1: arg_cols = 0; if (*++argv == NULL || *argv[0] == '\0') errx(2, errfew, 1, cap); arg_rows = atoi(*argv); (void)tputs(tgoto(str, arg_cols, arg_rows), 1, outc); break; case 2: if (*++argv == NULL || *argv[0] == '\0') errx(2, errfew, 2, cap); arg_cols = atoi(*argv); if (*++argv == NULL || *argv[0] == '\0') errx(2, errfew, 2, cap); arg_rows = atoi(*argv); (void) tputs(tgoto(str, arg_cols, arg_rows), arg_rows, outc); break; default: errx(2, errmany, arg_need, cap); } return (argv); } static void usage(void) { (void)fprintf(stderr, "usage: tput [-T term] attribute ...\n"); exit(2); } diff --git a/usr.bin/tr/str.c b/usr.bin/tr/str.c index 2cd811ce5d6b..bd02eafbdff5 100644 --- a/usr.bin/tr/str.c +++ b/usr.bin/tr/str.c @@ -1,389 +1,386 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)str.c 8.2 (Berkeley) 4/28/95"; #endif #include #include #include #include #include #include #include #include #include #include #include "extern.h" static int backslash(STR *, int *); static int bracket(STR *); static void genclass(STR *); static void genequiv(STR *); static int genrange(STR *, int); static void genseq(STR *); wint_t next(STR *s) { int is_octal; wint_t ch; wchar_t wch; size_t clen; switch (s->state) { case EOS: return (0); case INFINITE: return (1); case NORMAL: switch (*s->str) { case '\0': s->state = EOS; return (0); case '\\': s->lastch = backslash(s, &is_octal); break; case '[': if (bracket(s)) return (next(s)); /* FALLTHROUGH */ default: clen = mbrtowc(&wch, s->str, MB_LEN_MAX, NULL); if (clen == (size_t)-1 || clen == (size_t)-2 || clen == 0) errc(1, EILSEQ, NULL); is_octal = 0; s->lastch = wch; s->str += clen; break; } /* We can start a range at any time. */ if (s->str[0] == '-' && genrange(s, is_octal)) return (next(s)); return (1); case RANGE: if (s->cnt-- == 0) { s->state = NORMAL; return (next(s)); } ++s->lastch; return (1); case SEQUENCE: if (s->cnt-- == 0) { s->state = NORMAL; return (next(s)); } return (1); case CCLASS: case CCLASS_UPPER: case CCLASS_LOWER: s->cnt++; ch = nextwctype(s->lastch, s->cclass); if (ch == -1) { s->state = NORMAL; return (next(s)); } s->lastch = ch; return (1); case SET: if ((ch = s->set[s->cnt++]) == OOBCH) { s->state = NORMAL; return (next(s)); } s->lastch = ch; return (1); default: return (0); } /* NOTREACHED */ } static int bracket(STR *s) { char *p; switch (s->str[1]) { case ':': /* "[:class:]" */ if ((p = strchr(s->str + 2, ']')) == NULL) return (0); if (*(p - 1) != ':' || p - s->str < 4) goto repeat; *(p - 1) = '\0'; s->str += 2; genclass(s); s->str = p + 1; return (1); case '=': /* "[=equiv=]" */ if (s->str[2] == '\0' || (p = strchr(s->str + 3, ']')) == NULL) return (0); if (*(p - 1) != '=' || p - s->str < 4) goto repeat; s->str += 2; genequiv(s); return (1); default: /* "[\###*n]" or "[#*n]" */ repeat: if ((p = strpbrk(s->str + 2, "*]")) == NULL) return (0); if (p[0] != '*' || strchr(p, ']') == NULL) return (0); s->str += 1; genseq(s); return (1); } /* NOTREACHED */ } static void genclass(STR *s) { if ((s->cclass = wctype(s->str)) == 0) errx(1, "unknown class %s", s->str); s->cnt = 0; s->lastch = -1; /* incremented before check in next() */ if (strcmp(s->str, "upper") == 0) s->state = CCLASS_UPPER; else if (strcmp(s->str, "lower") == 0) s->state = CCLASS_LOWER; else s->state = CCLASS; } static void genequiv(STR *s) { int i, p, pri; char src[2], dst[3]; size_t clen; wchar_t wc; if (*s->str == '\\') { s->equiv[0] = backslash(s, NULL); if (*s->str != '=') errx(1, "misplaced equivalence equals sign"); s->str += 2; } else { clen = mbrtowc(&wc, s->str, MB_LEN_MAX, NULL); if (clen == (size_t)-1 || clen == (size_t)-2 || clen == 0) errc(1, EILSEQ, NULL); s->equiv[0] = wc; if (s->str[clen] != '=') errx(1, "misplaced equivalence equals sign"); s->str += clen + 2; } /* * Calculate the set of all characters in the same equivalence class * as the specified character (they will have the same primary * collation weights). * XXX Knows too much about how strxfrm() is implemented. Assumes * it fills the string with primary collation weight bytes. Only one- * to-one mappings are supported. * XXX Equivalence classes not supported in multibyte locales. */ src[0] = (char)s->equiv[0]; src[1] = '\0'; if (MB_CUR_MAX == 1 && strxfrm(dst, src, sizeof(dst)) == 1) { pri = (unsigned char)*dst; for (p = 1, i = 1; i < NCHARS_SB; i++) { *src = i; if (strxfrm(dst, src, sizeof(dst)) == 1 && pri && pri == (unsigned char)*dst) s->equiv[p++] = i; } s->equiv[p] = OOBCH; } s->cnt = 0; s->state = SET; s->set = s->equiv; } static int genrange(STR *s, int was_octal) { int stopval, octal; char *savestart; int n, cnt, *p; size_t clen; wchar_t wc; octal = 0; savestart = s->str; if (*++s->str == '\\') stopval = backslash(s, &octal); else { clen = mbrtowc(&wc, s->str, MB_LEN_MAX, NULL); if (clen == (size_t)-1 || clen == (size_t)-2) errc(1, EILSEQ, NULL); stopval = wc; s->str += clen; } /* * XXX Characters are not ordered according to collating sequence in * multibyte locales. */ if (octal || was_octal || MB_CUR_MAX > 1) { if (stopval < s->lastch) { s->str = savestart; return (0); } s->cnt = stopval - s->lastch + 1; s->state = RANGE; --s->lastch; return (1); } if (charcoll((const void *)&stopval, (const void *)&(s->lastch)) < 0) { s->str = savestart; return (0); } if ((s->set = p = malloc((NCHARS_SB + 1) * sizeof(int))) == NULL) err(1, "genrange() malloc"); for (cnt = 0; cnt < NCHARS_SB; cnt++) if (charcoll((const void *)&cnt, (const void *)&(s->lastch)) >= 0 && charcoll((const void *)&cnt, (const void *)&stopval) <= 0) *p++ = cnt; *p = OOBCH; n = p - s->set; s->cnt = 0; s->state = SET; if (n > 1) mergesort(s->set, n, sizeof(*(s->set)), charcoll); return (1); } static void genseq(STR *s) { char *ep; wchar_t wc; size_t clen; if (s->which == STRING1) errx(1, "sequences only valid in string2"); if (*s->str == '\\') s->lastch = backslash(s, NULL); else { clen = mbrtowc(&wc, s->str, MB_LEN_MAX, NULL); if (clen == (size_t)-1 || clen == (size_t)-2) errc(1, EILSEQ, NULL); s->lastch = wc; s->str += clen; } if (*s->str != '*') errx(1, "misplaced sequence asterisk"); switch (*++s->str) { case '\\': s->cnt = backslash(s, NULL); break; case ']': s->cnt = 0; ++s->str; break; default: if (isdigit((u_char)*s->str)) { s->cnt = strtol(s->str, &ep, 0); if (*ep == ']') { s->str = ep + 1; break; } } errx(1, "illegal sequence count"); /* NOTREACHED */ } s->state = s->cnt ? SEQUENCE : INFINITE; } /* * Translate \??? into a character. Up to 3 octal digits, if no digits either * an escape code or a literal character. */ static int backslash(STR *s, int *is_octal) { int ch, cnt, val; if (is_octal != NULL) *is_octal = 0; for (cnt = val = 0;;) { ch = (u_char)*++s->str; if (!isdigit(ch) || ch > '7') break; val = val * 8 + ch - '0'; if (++cnt == 3) { ++s->str; break; } } if (cnt) { if (is_octal != NULL) *is_octal = 1; return (val); } if (ch != '\0') ++s->str; switch (ch) { case 'a': /* escape characters */ return ('\7'); case 'b': return ('\b'); case 'f': return ('\f'); case 'n': return ('\n'); case 'r': return ('\r'); case 't': return ('\t'); case 'v': return ('\13'); case '\0': /* \" -> \ */ s->state = EOS; return ('\\'); default: /* \x" -> x */ return (ch); } } diff --git a/usr.bin/tr/tr.c b/usr.bin/tr/tr.c index 2d1baad2ac09..4bd52fae1a08 100644 --- a/usr.bin/tr/tr.c +++ b/usr.bin/tr/tr.c @@ -1,384 +1,381 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)tr.c 8.2 (Berkeley) 5/4/95"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cmap.h" #include "cset.h" #include "extern.h" static STR s1 = { STRING1, NORMAL, 0, OOBCH, 0, { 0, OOBCH }, NULL, NULL }; static STR s2 = { STRING2, NORMAL, 0, OOBCH, 0, { 0, OOBCH }, NULL, NULL }; static struct cset *setup(char *, STR *, int, int); static void usage(void); int main(int argc, char **argv) { static int carray[NCHARS_SB]; struct cmap *map; struct cset *delete, *squeeze; int n, *p; int Cflag, cflag, dflag, sflag, isstring2; wint_t ch, cnt, lastch; (void)setlocale(LC_ALL, ""); if (caph_limit_stdio() == -1) err(1, "unable to limit stdio"); if (caph_enter() < 0) err(1, "unable to enter capability mode"); Cflag = cflag = dflag = sflag = 0; while ((ch = getopt(argc, argv, "Ccdsu")) != -1) switch((char)ch) { case 'C': Cflag = 1; cflag = 0; break; case 'c': cflag = 1; Cflag = 0; break; case 'd': dflag = 1; break; case 's': sflag = 1; break; case 'u': setbuf(stdout, (char *)NULL); break; case '?': default: usage(); } argc -= optind; argv += optind; switch(argc) { case 0: default: usage(); /* NOTREACHED */ case 1: isstring2 = 0; break; case 2: isstring2 = 1; break; } /* * tr -ds [-Cc] string1 string2 * Delete all characters (or complemented characters) in string1. * Squeeze all characters in string2. */ if (dflag && sflag) { if (!isstring2) usage(); delete = setup(argv[0], &s1, cflag, Cflag); squeeze = setup(argv[1], &s2, 0, 0); for (lastch = OOBCH; (ch = getwchar()) != WEOF;) if (!cset_in(delete, ch) && (lastch != ch || !cset_in(squeeze, ch))) { lastch = ch; (void)putwchar(ch); } if (ferror(stdin)) err(1, NULL); exit(0); } /* * tr -d [-Cc] string1 * Delete all characters (or complemented characters) in string1. */ if (dflag) { if (isstring2) usage(); delete = setup(argv[0], &s1, cflag, Cflag); while ((ch = getwchar()) != WEOF) if (!cset_in(delete, ch)) (void)putwchar(ch); if (ferror(stdin)) err(1, NULL); exit(0); } /* * tr -s [-Cc] string1 * Squeeze all characters (or complemented characters) in string1. */ if (sflag && !isstring2) { squeeze = setup(argv[0], &s1, cflag, Cflag); for (lastch = OOBCH; (ch = getwchar()) != WEOF;) if (lastch != ch || !cset_in(squeeze, ch)) { lastch = ch; (void)putwchar(ch); } if (ferror(stdin)) err(1, NULL); exit(0); } /* * tr [-Ccs] string1 string2 * Replace all characters (or complemented characters) in string1 with * the character in the same position in string2. If the -s option is * specified, squeeze all the characters in string2. */ if (!isstring2) usage(); map = cmap_alloc(); if (map == NULL) err(1, NULL); squeeze = cset_alloc(); if (squeeze == NULL) err(1, NULL); s1.str = argv[0]; if (Cflag || cflag) { cmap_default(map, OOBCH); if ((s2.str = strdup(argv[1])) == NULL) errx(1, "strdup(argv[1])"); } else s2.str = argv[1]; if (!next(&s2)) errx(1, "empty string2"); /* * For -s result will contain only those characters defined * as the second characters in each of the toupper or tolower * pairs. */ /* If string2 runs out of characters, use the last one specified. */ while (next(&s1)) { again: if (s1.state == CCLASS_LOWER && s2.state == CCLASS_UPPER && s1.cnt == 1 && s2.cnt == 1) { do { ch = towupper(s1.lastch); cmap_add(map, s1.lastch, ch); if (sflag && iswupper(ch)) cset_add(squeeze, ch); if (!next(&s1)) goto endloop; } while (s1.state == CCLASS_LOWER && s1.cnt > 1); /* skip upper set */ do { if (!next(&s2)) break; } while (s2.state == CCLASS_UPPER && s2.cnt > 1); goto again; } else if (s1.state == CCLASS_UPPER && s2.state == CCLASS_LOWER && s1.cnt == 1 && s2.cnt == 1) { do { ch = towlower(s1.lastch); cmap_add(map, s1.lastch, ch); if (sflag && iswlower(ch)) cset_add(squeeze, ch); if (!next(&s1)) goto endloop; } while (s1.state == CCLASS_UPPER && s1.cnt > 1); /* skip lower set */ do { if (!next(&s2)) break; } while (s2.state == CCLASS_LOWER && s2.cnt > 1); goto again; } else { cmap_add(map, s1.lastch, s2.lastch); if (sflag) cset_add(squeeze, s2.lastch); } (void)next(&s2); } endloop: if (cflag || (Cflag && MB_CUR_MAX > 1)) { /* * This is somewhat tricky: since the character set is * potentially huge, we need to avoid allocating a map * entry for every character. Our strategy is to set the * default mapping to the last character of string #2 * (= the one that gets automatically repeated), then to * add back identity mappings for characters that should * remain unchanged. We don't waste space on identity mappings * for non-characters with the -C option; those are simulated * in the I/O loop. */ s2.str = argv[1]; s2.state = NORMAL; for (cnt = 0; cnt < WINT_MAX; cnt++) { if (Cflag && !iswrune(cnt)) continue; if (cmap_lookup(map, cnt) == OOBCH) { if (next(&s2)) { cmap_add(map, cnt, s2.lastch); if (sflag) cset_add(squeeze, s2.lastch); } } else cmap_add(map, cnt, cnt); if ((s2.state == EOS || s2.state == INFINITE) && cnt >= cmap_max(map)) break; } cmap_default(map, s2.lastch); } else if (Cflag) { for (p = carray, cnt = 0; cnt < NCHARS_SB; cnt++) { if (cmap_lookup(map, cnt) == OOBCH && iswrune(cnt)) *p++ = cnt; else cmap_add(map, cnt, cnt); } n = p - carray; if (Cflag && n > 1) (void)mergesort(carray, n, sizeof(*carray), charcoll); s2.str = argv[1]; s2.state = NORMAL; for (cnt = 0; cnt < n; cnt++) { (void)next(&s2); cmap_add(map, carray[cnt], s2.lastch); /* * Chars taken from s2 can be different this time * due to lack of complex upper/lower processing, * so fill string2 again to not miss some. */ if (sflag) cset_add(squeeze, s2.lastch); } } cset_cache(squeeze); cmap_cache(map); if (sflag) for (lastch = OOBCH; (ch = getwchar()) != WEOF;) { if (!Cflag || iswrune(ch)) ch = cmap_lookup(map, ch); if (lastch != ch || !cset_in(squeeze, ch)) { lastch = ch; (void)putwchar(ch); } } else while ((ch = getwchar()) != WEOF) { if (!Cflag || iswrune(ch)) ch = cmap_lookup(map, ch); (void)putwchar(ch); } if (ferror(stdin)) err(1, NULL); exit (0); } static struct cset * setup(char *arg, STR *str, int cflag, int Cflag) { struct cset *cs; cs = cset_alloc(); if (cs == NULL) err(1, NULL); str->str = arg; while (next(str)) cset_add(cs, str->lastch); if (Cflag) cset_addclass(cs, wctype("rune"), true); if (cflag || Cflag) cset_invert(cs); cset_cache(cs); return (cs); } int charcoll(const void *a, const void *b) { static char sa[2], sb[2]; sa[0] = *(const int *)a; sb[0] = *(const int *)b; return (strcoll(sa, sb)); } static void usage(void) { (void)fprintf(stderr, "%s\n%s\n%s\n%s\n", "usage: tr [-Ccsu] string1 string2", " tr [-Ccu] -d string1", " tr [-Ccu] -s string1", " tr [-Ccu] -ds string1 string2"); exit(1); } diff --git a/usr.bin/tset/map.c b/usr.bin/tset/map.c index 4fa6d859f055..a546267397fa 100644 --- a/usr.bin/tset/map.c +++ b/usr.bin/tset/map.c @@ -1,254 +1,251 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)map.c 8.1 (Berkeley) 6/9/93"; #endif #include #include #include #include #include #include "extern.h" static speed_t tset_baudrate(char *); /* Baud rate conditionals for mapping. */ #define GT 0x01 #define EQ 0x02 #define LT 0x04 #define NOT 0x08 #define GE (GT | EQ) #define LE (LT | EQ) typedef struct map { struct map *next; /* Linked list of maps. */ char *porttype; /* Port type, or "" for any. */ char *type; /* Terminal type to select. */ int conditional; /* Baud rate conditionals bitmask. */ speed_t speed; /* Baud rate to compare against. */ } MAP; static MAP *cur, *maplist; /* * Syntax for -m: * [port-type][test baudrate]:terminal-type * The baud rate tests are: >, <, @, =, ! */ void add_mapping(const char *port, char *arg) { MAP *mapp; char *copy, *p, *termp; copy = strdup(arg); mapp = malloc(sizeof(MAP)); if (copy == NULL || mapp == NULL) errx(1, "malloc"); mapp->next = NULL; if (maplist == NULL) cur = maplist = mapp; else { cur->next = mapp; cur = mapp; } mapp->porttype = arg; mapp->conditional = 0; arg = strpbrk(arg, "><@=!:"); if (arg == NULL) { /* [?]term */ mapp->type = mapp->porttype; mapp->porttype = NULL; goto done; } if (arg == mapp->porttype) /* [><@=! baud]:term */ termp = mapp->porttype = NULL; else termp = arg; for (;; ++arg) /* Optional conditionals. */ switch(*arg) { case '<': if (mapp->conditional & GT) goto badmopt; mapp->conditional |= LT; break; case '>': if (mapp->conditional & LT) goto badmopt; mapp->conditional |= GT; break; case '@': case '=': /* Not documented. */ mapp->conditional |= EQ; break; case '!': mapp->conditional |= NOT; break; default: goto next; } next: if (*arg == ':') { if (mapp->conditional) goto badmopt; ++arg; } else { /* Optional baudrate. */ arg = strchr(p = arg, ':'); if (arg == NULL) goto badmopt; *arg++ = '\0'; mapp->speed = tset_baudrate(p); } if (*arg == '\0') /* Non-optional type. */ goto badmopt; mapp->type = arg; /* Terminate porttype, if specified. */ if (termp != NULL) *termp = '\0'; /* If a NOT conditional, reverse the test. */ if (mapp->conditional & NOT) mapp->conditional = ~mapp->conditional & (EQ | GT | LT); /* If user specified a port with an option flag, set it. */ done: if (port) { if (mapp->porttype) badmopt: errx(1, "illegal -m option format: %s", copy); mapp->porttype = strdup(port); } free(copy); #ifdef MAPDEBUG (void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY"); (void)printf("type: %s\n", mapp->type); (void)printf("conditional: "); p = ""; if (mapp->conditional & GT) { (void)printf("GT"); p = "/"; } if (mapp->conditional & EQ) { (void)printf("%sEQ", p); p = "/"; } if (mapp->conditional & LT) (void)printf("%sLT", p); (void)printf("\nspeed: %d\n", mapp->speed); #endif } /* * Return the type of terminal to use for a port of type 'type', as specified * by the first applicable mapping in 'map'. If no mappings apply, return * 'type'. */ const char * mapped(const char *type) { MAP *mapp; int match; match = 0; for (mapp = maplist; mapp; mapp = mapp->next) if (mapp->porttype == NULL || !strcmp(mapp->porttype, type)) { switch (mapp->conditional) { case 0: /* No test specified. */ match = 1; break; case EQ: match = (Ospeed == mapp->speed); break; case GE: match = (Ospeed >= mapp->speed); break; case GT: match = (Ospeed > mapp->speed); break; case LE: match = (Ospeed <= mapp->speed); break; case LT: match = (Ospeed < mapp->speed); break; } if (match) return (mapp->type); } /* No match found; return given type. */ return (type); } typedef struct speeds { const char *string; speed_t speed; } SPEEDS; static SPEEDS speeds[] = { { "0", B0 }, { "134.5", B134 }, { "exta", B19200 }, { "extb", B38400 }, { NULL, 0 } }; static speed_t tset_baudrate(char *rate) { SPEEDS *sp; speed_t speed; /* The baudrate number can be preceded by a 'B', which is ignored. */ if (*rate == 'B') ++rate; for (sp = speeds; sp->string; ++sp) if (!strcasecmp(rate, sp->string)) return (sp->speed); speed = atol(rate); if (speed == 0) errx(1, "unknown baud rate %s", rate); return speed; } diff --git a/usr.bin/tset/misc.c b/usr.bin/tset/misc.c index 737fde9dc130..8e7cde12e798 100644 --- a/usr.bin/tset/misc.c +++ b/usr.bin/tset/misc.c @@ -1,68 +1,65 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/9/93"; #endif #include #include #include #include #include "extern.h" void cat(char *file) { register int fd, nr, nw; char buf[1024]; if ((fd = open(file, O_RDONLY, 0)) < 0) err(1, "%s", file); while ((nr = read(fd, buf, sizeof(buf))) > 0) if ((nw = write(STDERR_FILENO, buf, nr)) == -1) err(1, "write to stderr"); if (nr != 0) err(1, "%s", file); (void)close(fd); } int outc(int c) { return putc(c, stderr); } diff --git a/usr.bin/tset/set.c b/usr.bin/tset/set.c index df204cebeebe..34bdc44431b0 100644 --- a/usr.bin/tset/set.c +++ b/usr.bin/tset/set.c @@ -1,324 +1,321 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)set.c 8.2 (Berkeley) 2/28/94"; #endif #include #include #include #include #include "extern.h" #define CHK(val, dft) (val <= 0 ? dft : val) int set_tabs(void); /* * Reset the terminal mode bits to a sensible state. Very useful after * a child program dies in raw mode. */ void reset_mode(void) { tcgetattr(STDERR_FILENO, &mode); #if defined(VDISCARD) && defined(CDISCARD) mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); #endif mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); #if defined(VFLUSH) && defined(CFLUSH) mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); #endif mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); #if defined(VLNEXT) && defined(CLNEXT) mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); #endif mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); #if defined(VREPRINT) && defined(CRPRNT) mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); #endif mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); #if defined(VWERASE) && defined(CWERASE) mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); #endif mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR #ifdef IUCLC | IUCLC #endif #ifdef IXANY | IXANY #endif | IXOFF); mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON #ifdef IMAXBEL | IMAXBEL #endif ); mode.c_oflag &= ~(0 #ifdef OLCUC | OLCUC #endif #ifdef OCRNL | OCRNL #endif #ifdef ONOCR | ONOCR #endif #ifdef ONLRET | ONLRET #endif #ifdef OFILL | OFILL #endif #ifdef OFDEL | OFDEL #endif #ifdef NLDLY | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY #endif ); mode.c_oflag |= (OPOST #ifdef ONLCR | ONLCR #endif ); mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL); mode.c_cflag |= (CS8 | CREAD); mode.c_lflag &= ~(ECHONL | NOFLSH | TOSTOP #ifdef ECHOPTR | ECHOPRT #endif #ifdef XCASE | XCASE #endif ); mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK #ifdef ECHOCTL | ECHOCTL #endif #ifdef ECHOKE | ECHOKE #endif ); tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); } /* * Determine the erase, interrupt, and kill characters from the termcap * entry and command line and update their values in 'mode'. */ void set_control_chars(void) { char *bp, *p, bs_char, buf[1024]; bp = buf; p = tgetstr("kb", &bp); if (p == NULL || p[1] != '\0') p = tgetstr("bc", &bp); if (p != NULL && p[1] == '\0') bs_char = p[0]; else if (tgetflag("bs")) bs_char = CTRL('h'); else bs_char = 0; if (erasech == 0 && bs_char != 0 && !tgetflag("os")) erasech = -1; if (erasech < 0) erasech = (bs_char != 0) ? bs_char : CTRL('h'); if (mode.c_cc[VERASE] == 0 || erasech != 0) mode.c_cc[VERASE] = erasech ? erasech : CERASE; if (mode.c_cc[VINTR] == 0 || intrchar != 0) mode.c_cc[VINTR] = intrchar ? intrchar : CINTR; if (mode.c_cc[VKILL] == 0 || killch != 0) mode.c_cc[VKILL] = killch ? killch : CKILL; } /* * Set up various conversions in 'mode', including parity, tabs, returns, * echo, and case, according to the termcap entry. If the program we're * running was named with a leading upper-case character, map external * uppercase to internal lowercase. */ void set_conversions(int usingupper) { if (tgetflag("UC") || usingupper) { #ifdef IUCLC mode.c_iflag |= IUCLC; mode.c_oflag |= OLCUC; #endif } else if (tgetflag("LC")) { #ifdef IUCLC mode.c_iflag &= ~IUCLC; mode.c_oflag &= ~OLCUC; #endif } mode.c_iflag &= ~(PARMRK | INPCK); mode.c_lflag |= ICANON; if (tgetflag("EP")) { mode.c_cflag |= PARENB; mode.c_cflag &= ~PARODD; } if (tgetflag("OP")) { mode.c_cflag |= PARENB; mode.c_cflag |= PARODD; } #ifdef ONLCR mode.c_oflag |= ONLCR; #endif mode.c_iflag |= ICRNL; mode.c_lflag |= ECHO; mode.c_oflag |= OXTABS; if (tgetflag("NL")) { /* Newline, not linefeed. */ #ifdef ONLCR mode.c_oflag &= ~ONLCR; #endif mode.c_iflag &= ~ICRNL; } if (tgetflag("HD")) /* Half duplex. */ mode.c_lflag &= ~ECHO; if (tgetflag("pt")) /* Print tabs. */ mode.c_oflag &= ~OXTABS; mode.c_lflag |= (ECHOE | ECHOK); } /* Output startup string. */ void set_init(void) { char *bp, buf[1024]; int settle; bp = buf; if (tgetstr("pc", &bp) != 0) /* Get/set pad character. */ PC = buf[0]; #ifdef TAB3 if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode); } #endif settle = set_tabs(); if (isreset) { bp = buf; if (tgetstr("rs", &bp) != 0 || tgetstr("is", &bp) != 0) { tputs(buf, 0, outc); settle = 1; } bp = buf; if (tgetstr("rf", &bp) != 0 || tgetstr("if", &bp) != 0) { cat(buf); settle = 1; } } if (settle) { (void)putc('\r', stderr); (void)fflush(stderr); (void)sleep(1); /* Settle the terminal. */ } } /* * Set the hardware tabs on the terminal, using the ct (clear all tabs), * st (set one tab) and ch (horizontal cursor addressing) capabilities. * This is done before if and is, so they can patch in case we blow this. * Return nonzero if we set any tab stops, zero if not. */ int set_tabs(void) { int c; char *capsp, *clear_tabs; char *set_column, *set_pos, *Set_tab; char caps[1024]; const char *tg_out; capsp = caps; Set_tab = tgetstr("st", &capsp); if (Set_tab && (clear_tabs = tgetstr("ct", &capsp))) { (void)putc('\r', stderr); /* Force to left margin. */ tputs(clear_tabs, 0, outc); } set_column = tgetstr("ch", &capsp); set_pos = set_column ? NULL : tgetstr("cm", &capsp); if (Set_tab) { for (c = 8; c < Columns; c += 8) { /* * Get to the right column. "OOPS" is returned by * tgoto() if it can't do the job. (*snarl*) */ tg_out = "OOPS"; if (set_column) tg_out = tgoto(set_column, 0, c); if (*tg_out == 'O' && set_pos) tg_out = tgoto(set_pos, c, Lines - 1); if (*tg_out != 'O') tputs(tg_out, 1, outc); else (void)fprintf(stderr, "%s", " "); /* Set the tab. */ tputs(Set_tab, 0, outc); } putc('\r', stderr); return (1); } return (0); } diff --git a/usr.bin/tset/term.c b/usr.bin/tset/term.c index 1c0196b1473c..08715fa268cd 100644 --- a/usr.bin/tset/term.c +++ b/usr.bin/tset/term.c @@ -1,158 +1,155 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)term.c 8.1 (Berkeley) 6/9/93"; #endif #include #include #include #include #include #include #include #include #include #include "extern.h" static char tbuf[1024]; /* Termcap entry. */ const char *askuser(const char *); char *ttys(char *); /* * Figure out what kind of terminal we're dealing with, and then read in * its termcap entry. */ const char * get_termcap_entry(char *userarg, char **tcapbufp) { struct ttyent *t; int rval; char *p, *ttypath; const char *ttype; if (userarg) { ttype = userarg; goto found; } /* Try the environment. */ if ((ttype = getenv("TERM"))) goto map; /* Try ttyname(3); check for dialup or other mapping. */ if ((ttypath = ttyname(STDERR_FILENO))) { if ((p = strrchr(ttypath, '/'))) ++p; else p = ttypath; if ((t = getttynam(p))) { ttype = t->ty_type; goto map; } } /* If still undefined, use "unknown". */ ttype = "unknown"; map: ttype = mapped(ttype); /* * If not a path, remove TERMCAP from the environment so we get a * real entry from /etc/termcap. This prevents us from being fooled * by out of date stuff in the environment. */ found: if ((p = getenv("TERMCAP")) != NULL && *p != '/') unsetenv("TERMCAP"); /* * ttype now contains a pointer to the type of the terminal. * If the first character is '?', ask the user. */ if (ttype[0] == '?') { if (ttype[1] != '\0') ttype = askuser(ttype + 1); else ttype = askuser(NULL); } /* Find the termcap entry. If it doesn't exist, ask the user. */ while ((rval = tgetent(tbuf, ttype)) == 0) { warnx("terminal type %s is unknown", ttype); ttype = askuser(NULL); } if (rval == -1) errx(1, "termcap: %s", strerror(errno ? errno : ENOENT)); *tcapbufp = tbuf; return (ttype); } /* Prompt the user for a terminal type. */ const char * askuser(const char *dflt) { static char answer[256]; char *p; /* We can get recalled; if so, don't continue uselessly. */ if (feof(stdin) || ferror(stdin)) { (void)fprintf(stderr, "\n"); exit(1); } for (;;) { if (dflt) (void)fprintf(stderr, "Terminal type? [%s] ", dflt); else (void)fprintf(stderr, "Terminal type? "); (void)fflush(stderr); if (fgets(answer, sizeof(answer), stdin) == NULL) { if (dflt == NULL) { (void)fprintf(stderr, "\n"); exit(1); } return (dflt); } if ((p = strchr(answer, '\n'))) *p = '\0'; if (answer[0]) return (answer); if (dflt != NULL) return (dflt); } } diff --git a/usr.bin/tset/tset.c b/usr.bin/tset/tset.c index be6fbf3abd2d..56cff3ca741b 100644 --- a/usr.bin/tset/tset.c +++ b/usr.bin/tset/tset.c @@ -1,299 +1,296 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1991, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)tset.c 8.1 (Berkeley) 6/9/93"; #endif #include #include #include #include #include #include #include #include #include #include #include "extern.h" void obsolete(char *[]); void report(const char *, int, u_int); void usage(void); struct termios mode, oldmode; int erasech; /* new erase character */ int intrchar; /* new interrupt character */ int isreset; /* invoked as reset */ int killch; /* new kill character */ int Lines, Columns; /* window size */ speed_t Ospeed; int main(int argc, char *argv[]) { #ifdef TIOCGWINSZ struct winsize win; #endif int ch, noinit, noset, quiet, Sflag, sflag, showterm, usingupper; char *p, *tcapbuf; const char *ttype; if (tcgetattr(STDERR_FILENO, &mode) < 0) err(1, "standard error"); oldmode = mode; Ospeed = cfgetospeed(&mode); if ((p = strrchr(*argv, '/'))) ++p; else p = *argv; usingupper = isupper(*p); if (!strcasecmp(p, "reset")) { isreset = 1; reset_mode(); } obsolete(argv); noinit = noset = quiet = Sflag = sflag = showterm = 0; while ((ch = getopt(argc, argv, "-a:d:e:Ii:k:m:np:QSrs")) != -1) { switch (ch) { case '-': /* display term only */ noset = 1; break; case 'a': /* OBSOLETE: map identifier to type */ add_mapping("arpanet", optarg); break; case 'd': /* OBSOLETE: map identifier to type */ add_mapping("dialup", optarg); break; case 'e': /* erase character */ erasech = optarg[0] == '^' && optarg[1] != '\0' ? optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : optarg[0]; break; case 'I': /* no initialization strings */ noinit = 1; break; case 'i': /* interrupt character */ intrchar = optarg[0] == '^' && optarg[1] != '\0' ? optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : optarg[0]; break; case 'k': /* kill character */ killch = optarg[0] == '^' && optarg[1] != '\0' ? optarg[1] == '?' ? '\177' : CTRL(optarg[1]) : optarg[0]; break; case 'm': /* map identifier to type */ add_mapping(NULL, optarg); break; case 'n': /* OBSOLETE: set new tty driver */ break; case 'p': /* OBSOLETE: map identifier to type */ add_mapping("plugboard", optarg); break; case 'Q': /* don't output control key settings */ quiet = 1; break; case 'S': /* output TERM/TERMCAP strings */ Sflag = 1; break; case 'r': /* display term on stderr */ showterm = 1; break; case 's': /* output TERM/TERMCAP strings */ sflag = 1; break; case '?': default: usage(); } } argc -= optind; argv += optind; if (argc > 1) usage(); ttype = get_termcap_entry(*argv, &tcapbuf); if (!noset) { Columns = tgetnum("co"); Lines = tgetnum("li"); #ifdef TIOCGWINSZ /* Set window size */ (void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win); if (win.ws_row == 0 && win.ws_col == 0 && Lines > 0 && Columns > 0) { win.ws_row = Lines; win.ws_col = Columns; (void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win); } #endif set_control_chars(); set_conversions(usingupper); if (!noinit) set_init(); /* Set the modes if they've changed. */ if (memcmp(&mode, &oldmode, sizeof(mode))) tcsetattr(STDERR_FILENO, TCSADRAIN, &mode); } if (noset) (void)printf("%s\n", ttype); else { if (showterm) (void)fprintf(stderr, "Terminal type is %s.\n", ttype); /* * If erase, kill and interrupt characters could have been * modified and not -Q, display the changes. */ if (!quiet) { report("Erase", VERASE, CERASE); report("Kill", VKILL, CKILL); report("Interrupt", VINTR, CINTR); } } if (Sflag) { (void)printf("%s ", ttype); if (strlen(tcapbuf) > 0) wrtermcap(tcapbuf); } if (sflag) { /* * Figure out what shell we're using. A hack, we look for an * environmental variable SHELL ending in "csh". */ if ((p = getenv("SHELL")) && !strcmp(p + strlen(p) - 3, "csh")) { printf("set noglob;\nsetenv TERM %s;\n", ttype); if (strlen(tcapbuf) > 0) { printf("setenv TERMCAP '"); wrtermcap(tcapbuf); printf("';\n"); } printf("unset noglob;\n"); } else { printf("TERM=%s;\n", ttype); if (strlen(tcapbuf) > 0) { printf("TERMCAP='"); wrtermcap(tcapbuf); printf("';\nexport TERMCAP;\n"); } printf("export TERM;\n"); } } exit(0); } /* * Tell the user if a control key has been changed from the default value. */ void report(const char *name, int which, u_int def) { u_int old, new; new = mode.c_cc[which]; old = oldmode.c_cc[which]; if (old == new && old == def) return; (void)fprintf(stderr, "%s %s ", name, old == new ? "is" : "set to"); if (new == 010) (void)fprintf(stderr, "backspace.\n"); else if (new == 0177) (void)fprintf(stderr, "delete.\n"); else if (new < 040) { new ^= 0100; (void)fprintf(stderr, "control-%c (^%c).\n", new, new); } else (void)fprintf(stderr, "%c.\n", new); } /* * Convert the obsolete argument form into something that getopt can handle. * This means that -e, -i and -k get default arguments supplied for them. */ void obsolete(char *argv[]) { for (; *argv; ++argv) { if (argv[0][0] != '-' || (argv[1] && argv[1][0] != '-') || (argv[0][1] != 'e' && argv[0][1] != 'i' && argv[0][1] != 'k') || argv[0][2] != '\0') continue; switch(argv[0][1]) { case 'e': argv[0] = strdup("-e^H"); break; case 'i': argv[0] = strdup("-i^C"); break; case 'k': argv[0] = strdup("-k^U"); break; } } } void usage(void) { (void)fprintf(stderr, "%s\n%s\n", "usage: tset [-IQrSs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]", " reset [-IQrSs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]"); exit(1); } diff --git a/usr.bin/tset/wrterm.c b/usr.bin/tset/wrterm.c index cd98558f20a9..44fd55dfd989 100644 --- a/usr.bin/tset/wrterm.c +++ b/usr.bin/tset/wrterm.c @@ -1,116 +1,113 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)wrterm.c 8.1 (Berkeley) 6/9/93"; #endif #include #include #include #include #include #include "extern.h" /* * Output termcap entry to stdout, quoting characters that would give the * shell problems and omitting empty fields. */ void wrtermcap(char *bp) { register int ch; register char *p; char *t, *sep; /* Find the end of the terminal names. */ if ((t = strchr(bp, ':')) == NULL) errx(1, "termcap names not colon terminated"); *t++ = '\0'; /* Output terminal names that don't have whitespace. */ sep = strdup(""); while ((p = strsep(&bp, "|")) != NULL) if (*p != '\0' && strpbrk(p, " \t") == NULL) { (void)printf("%s%s", sep, p); sep = strdup("|"); } (void)putchar(':'); /* * Output fields, transforming any dangerous characters. Skip * empty fields or fields containing only whitespace. */ while ((p = strsep(&t, ":")) != NULL) { while ((ch = *p) != '\0' && isspace(ch)) ++p; if (ch == '\0') continue; while ((ch = *p++) != '\0') switch(ch) { case '\033': (void)printf("\\E"); case ' ': /* No spaces. */ (void)printf("\\040"); break; case '!': /* No csh history chars. */ (void)printf("\\041"); break; case ',': /* No csh history chars. */ (void)printf("\\054"); break; case '"': /* No quotes. */ (void)printf("\\042"); break; case '\'': /* No quotes. */ (void)printf("\\047"); break; case '`': /* No quotes. */ (void)printf("\\140"); break; case '\\': /* Anything following is OK. */ case '^': (void)putchar(ch); if ((ch = *p++) == '\0') break; /* FALLTHROUGH */ default: (void)putchar(ch); } (void)putchar(':'); } } diff --git a/usr.bin/uname/uname.c b/usr.bin/uname/uname.c index 109505e4b9da..981d08a7a7c0 100644 --- a/usr.bin/uname/uname.c +++ b/usr.bin/uname/uname.c @@ -1,302 +1,299 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 2002 Juli Mallett. * Copyright (c) 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)uname.c 8.2 (Berkeley) 5/4/95"; #endif #include #include #include #include #include #include #include #define MFLAG 0x01 #define NFLAG 0x02 #define PFLAG 0x04 #define RFLAG 0x08 #define SFLAG 0x10 #define VFLAG 0x20 #define IFLAG 0x40 #define UFLAG 0x80 #define KFLAG 0x100 #define BFLAG 0x200 typedef void (*get_t)(void); static get_t get_buildid, get_ident, get_platform, get_hostname, get_arch, get_release, get_sysname, get_kernvers, get_uservers, get_version; static void native_ident(void); static void native_platform(void); static void native_hostname(void); static void native_arch(void); static void native_release(void); static void native_sysname(void); static void native_version(void); static void native_kernvers(void); static void native_uservers(void); static void native_buildid(void); static void print_uname(u_int); static void setup_get(void); static void usage(void); static char *buildid, *ident, *platform, *hostname, *arch, *release, *sysname, *version, *kernvers, *uservers; static int space; int main(int argc, char *argv[]) { u_int flags; int ch; setup_get(); flags = 0; while ((ch = getopt(argc, argv, "abiKmnoprsUv")) != -1) switch(ch) { case 'a': flags |= (MFLAG | NFLAG | RFLAG | SFLAG | VFLAG); break; case 'b': flags |= BFLAG; break; case 'i': flags |= IFLAG; break; case 'K': flags |= KFLAG; break; case 'm': flags |= MFLAG; break; case 'n': flags |= NFLAG; break; case 'p': flags |= PFLAG; break; case 'r': flags |= RFLAG; break; case 's': case 'o': flags |= SFLAG; break; case 'U': flags |= UFLAG; break; case 'v': flags |= VFLAG; break; case '?': default: usage(); } argc -= optind; argv += optind; if (argc) usage(); if (!flags) flags |= SFLAG; print_uname(flags); exit(0); } #define CHECK_ENV(opt,var) \ do { \ if ((var = getenv("UNAME_" opt)) == NULL) { \ get_##var = native_##var; \ } else { \ get_##var = (get_t)NULL; \ } \ } while (0) static void setup_get(void) { CHECK_ENV("s", sysname); CHECK_ENV("n", hostname); CHECK_ENV("r", release); CHECK_ENV("v", version); CHECK_ENV("m", platform); CHECK_ENV("p", arch); CHECK_ENV("i", ident); CHECK_ENV("K", kernvers); CHECK_ENV("U", uservers); CHECK_ENV("b", buildid); } #define PRINT_FLAG(flags,flag,var) \ if ((flags & flag) == flag) { \ if (space) \ printf(" "); \ else \ space++; \ if (get_##var != NULL) \ (*get_##var)(); \ printf("%s", var); \ } static void print_uname(u_int flags) { PRINT_FLAG(flags, SFLAG, sysname); PRINT_FLAG(flags, NFLAG, hostname); PRINT_FLAG(flags, RFLAG, release); PRINT_FLAG(flags, VFLAG, version); PRINT_FLAG(flags, MFLAG, platform); PRINT_FLAG(flags, PFLAG, arch); PRINT_FLAG(flags, IFLAG, ident); PRINT_FLAG(flags, KFLAG, kernvers); PRINT_FLAG(flags, UFLAG, uservers); PRINT_FLAG(flags, BFLAG, buildid); printf("\n"); } #define NATIVE_SYSCTL2_GET(var,mib0,mib1) \ static void \ native_##var(void) \ { \ int mib[] = { (mib0), (mib1) }; \ size_t len; \ static char buf[1024]; \ char **varp = &(var); \ \ len = sizeof buf; \ if (sysctl(mib, sizeof mib / sizeof mib[0], \ &buf, &len, NULL, 0) == -1) \ err(1, "sysctl"); #define NATIVE_SYSCTLNAME_GET(var,name) \ static void \ native_##var(void) \ { \ size_t len; \ static char buf[1024]; \ char **varp = &(var); \ \ len = sizeof buf; \ if (sysctlbyname(name, &buf, &len, NULL,\ 0) == -1) \ err(1, "sysctlbyname"); #define NATIVE_SET \ *varp = buf; \ return; \ } struct __hack #define NATIVE_BUFFER (buf) #define NATIVE_LENGTH (len) NATIVE_SYSCTL2_GET(sysname, CTL_KERN, KERN_OSTYPE) { } NATIVE_SET; NATIVE_SYSCTL2_GET(hostname, CTL_KERN, KERN_HOSTNAME) { } NATIVE_SET; NATIVE_SYSCTL2_GET(release, CTL_KERN, KERN_OSRELEASE) { } NATIVE_SET; NATIVE_SYSCTL2_GET(version, CTL_KERN, KERN_VERSION) { size_t n; char *p; p = NATIVE_BUFFER; n = NATIVE_LENGTH; for (; n--; ++p) if (*p == '\n' || *p == '\t') { if (n > 1) *p = ' '; else *p = '\0'; } } NATIVE_SET; NATIVE_SYSCTL2_GET(platform, CTL_HW, HW_MACHINE) { } NATIVE_SET; NATIVE_SYSCTL2_GET(arch, CTL_HW, HW_MACHINE_ARCH) { } NATIVE_SET; NATIVE_SYSCTLNAME_GET(ident, "kern.ident") { } NATIVE_SET; NATIVE_SYSCTLNAME_GET(buildid, "kern.build_id") { } NATIVE_SET; static void native_uservers(void) { static char buf[128]; snprintf(buf, sizeof(buf), "%d", __FreeBSD_version); uservers = buf; } static void native_kernvers(void) { static char buf[128]; snprintf(buf, sizeof(buf), "%d", getosreldate()); kernvers = buf; } static void usage(void) { fprintf(stderr, "usage: uname [-abiKmnoprsUv]\n"); exit(1); } diff --git a/usr.bin/unexpand/unexpand.c b/usr.bin/unexpand/unexpand.c index 08ba8ffe1dc4..116c4e02af4c 100644 --- a/usr.bin/unexpand/unexpand.c +++ b/usr.bin/unexpand/unexpand.c @@ -1,229 +1,226 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)unexpand.c 8.1 (Berkeley) 6/6/93"; #endif /* * unexpand - put tabs into a file replacing blanks */ #include #include #include #include #include #include #include #include #include #include static int all; static int nstops; static int tabstops[100]; static void getstops(const char *); static void usage(void); static int tabify(const char *); int main(int argc, char *argv[]) { int ch, failed; char *filename; setlocale(LC_CTYPE, ""); nstops = 1; tabstops[0] = 8; while ((ch = getopt(argc, argv, "at:")) != -1) { switch (ch) { case 'a': /* Un-expand all spaces, not just leading. */ all = 1; break; case 't': /* Specify tab list, implies -a. */ getstops(optarg); all = 1; break; default: usage(); /*NOTREACHED*/ } } argc -= optind; argv += optind; failed = 0; if (argc == 0) failed |= tabify("stdin"); else { while ((filename = *argv++) != NULL) { if (freopen(filename, "r", stdin) == NULL) { warn("%s", filename); failed = 1; } else failed |= tabify(filename); } } exit(failed != 0); } static void usage(void) { fprintf(stderr, "usage: unexpand [-a | -t tablist] [file ...]\n"); exit(1); } static int tabify(const char *curfile) { int dcol, doneline, limit, n, ocol, width; wint_t ch; limit = nstops == 1 ? INT_MAX : tabstops[nstops - 1] - 1; doneline = ocol = dcol = 0; while ((ch = getwchar()) != WEOF) { if (ch == ' ' && !doneline) { if (++dcol >= limit) doneline = 1; continue; } else if (ch == '\t') { if (nstops == 1) { dcol = (1 + dcol / tabstops[0]) * tabstops[0]; continue; } else { for (n = 0; n < nstops && tabstops[n] - 1 < dcol; n++) ; if (n < nstops - 1 && tabstops[n] - 1 < limit) { dcol = tabstops[n]; continue; } doneline = 1; } } /* Output maximal number of tabs. */ if (nstops == 1) { while (((ocol + tabstops[0]) / tabstops[0]) <= (dcol / tabstops[0])) { if (dcol - ocol < 2) break; putwchar('\t'); ocol = (1 + ocol / tabstops[0]) * tabstops[0]; } } else { for (n = 0; n < nstops && tabstops[n] - 1 < ocol; n++) ; while (ocol < dcol && n < nstops && ocol < limit) { putwchar('\t'); ocol = tabstops[n++]; } } /* Then spaces. */ while (ocol < dcol && ocol < limit) { putwchar(' '); ocol++; } if (ch == '\b') { putwchar('\b'); if (ocol > 0) ocol--, dcol--; } else if (ch == '\n') { putwchar('\n'); doneline = ocol = dcol = 0; continue; } else if (ch != ' ' || dcol > limit) { putwchar(ch); if ((width = wcwidth(ch)) > 0) ocol += width, dcol += width; } /* * Only processing leading blanks or we've gone past the * last tab stop. Emit remainder of this line unchanged. */ if (!all || dcol >= limit) { while ((ch = getwchar()) != '\n' && ch != WEOF) putwchar(ch); if (ch == '\n') putwchar('\n'); doneline = ocol = dcol = 0; } } if (ferror(stdin)) { warn("%s", curfile); return (1); } return (0); } static void getstops(const char *cp) { int i; nstops = 0; for (;;) { i = 0; while (*cp >= '0' && *cp <= '9') i = i * 10 + *cp++ - '0'; if (i <= 0) errx(1, "bad tab stop spec"); if (nstops > 0 && i <= tabstops[nstops-1]) errx(1, "bad tab stop spec"); if (nstops == sizeof(tabstops) / sizeof(*tabstops)) errx(1, "too many tab stops"); tabstops[nstops++] = i; if (*cp == 0) break; if (*cp != ',' && !isblank((unsigned char)*cp)) errx(1, "bad tab stop spec"); cp++; } } diff --git a/usr.bin/vgrind/regexp.c b/usr.bin/vgrind/regexp.c index 572f44d2aeed..97e5ef68cb9f 100644 --- a/usr.bin/vgrind/regexp.c +++ b/usr.bin/vgrind/regexp.c @@ -1,598 +1,595 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)regexp.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include "extern.h" static void expconv(void); bool _escaped; /* true if we are currently x_escaped */ char *s_start; /* start of string */ bool l_onecase; /* true if upper and lower equivalent */ #define makelower(c) (isupper((c)) ? tolower((c)) : (c)) /* STRNCMP - like strncmp except that we convert the * first string to lower case before comparing * if l_onecase is set. */ int STRNCMP(register char *s1, register char *s2, register int len) { if (l_onecase) { do if (*s2 - makelower(*s1)) return (*s2 - makelower(*s1)); else { s2++; s1++; } while (--len); } else { do if (*s2 - *s1) return (*s2 - *s1); else { s2++; s1++; } while (--len); } return(0); } /* The following routine converts an irregular expression to * internal format. * * Either meta symbols (\a \d or \p) or character strings or * operations ( alternation or parenthesizing ) can be * specified. Each starts with a descriptor byte. The descriptor * byte has STR set for strings, META set for meta symbols * and OPER set for operations. * The descriptor byte can also have the OPT bit set if the object * defined is optional. Also ALT can be set to indicate an alternation. * * For metasymbols the byte following the descriptor byte identities * the meta symbol (containing an ascii 'a', 'd', 'p', '|', or '('). For * strings the byte after the descriptor is a character count for * the string: * * meta symbols := descriptor * symbol * * strings := descriptor * character count * the string * * operations := descriptor * symbol * character count */ /* * handy macros for accessing parts of match blocks */ #define MSYM(A) (*(A+1)) /* symbol in a meta symbol block */ #define MNEXT(A) (A+2) /* character following a metasymbol block */ #define OSYM(A) (*(A+1)) /* symbol in an operation block */ #define OCNT(A) (*(A+2)) /* character count */ #define ONEXT(A) (A+3) /* next character after the operation */ #define OPTR(A) (A+*(A+2)) /* place pointed to by the operator */ #define SCNT(A) (*(A+1)) /* byte count of a string */ #define SSTR(A) (A+2) /* address of the string */ #define SNEXT(A) (A+2+*(A+1)) /* character following the string */ /* * bit flags in the descriptor */ #define OPT 1 #define STR 2 #define META 4 #define ALT 8 #define OPER 16 static char *ccre; /* pointer to current position in converted exp*/ static char *ure; /* pointer current position in unconverted exp */ /* re: unconverted irregular expression */ char * convexp(char *re) { register char *cre; /* pointer to converted regular expression */ /* allocate room for the converted expression */ if (re == NULL) return (NULL); if (*re == '\0') return (NULL); cre = malloc(4 * strlen(re) + 3); ccre = cre; ure = re; /* start the conversion with a \a */ *cre = META | OPT; MSYM(cre) = 'a'; ccre = MNEXT(cre); /* start the conversion (its recursive) */ expconv (); *ccre = 0; return (cre); } static void expconv() { register char *cs; /* pointer to current symbol in converted exp */ register char c; /* character being processed */ register char *acs; /* pinter to last alternate */ register int temp; /* let the conversion begin */ acs = NULL; cs = NULL; while (*ure) { switch (c = *ure++) { case '\\': switch (c = *ure++) { /* escaped characters are just characters */ default: if (cs == NULL || (*cs & STR) == 0) { cs = ccre; *cs = STR; SCNT(cs) = 1; ccre += 2; } else SCNT(cs)++; *ccre++ = c; break; /* normal(?) metacharacters */ case 'a': case 'd': case 'e': case 'p': if (acs != NULL && acs != cs) { do { temp = OCNT(acs); OCNT(acs) = ccre - acs; acs -= temp; } while (temp != 0); acs = NULL; } cs = ccre; *cs = META; MSYM(cs) = c; ccre = MNEXT(cs); break; } break; /* just put the symbol in */ case '^': case '$': if (acs != NULL && acs != cs) { do { temp = OCNT(acs); OCNT(acs) = ccre - acs; acs -= temp; } while (temp != 0); acs = NULL; } cs = ccre; *cs = META; MSYM(cs) = c; ccre = MNEXT(cs); break; /* mark the last match sequence as optional */ case '?': if (cs) *cs = *cs | OPT; break; /* recurse and define a subexpression */ case '(': if (acs != NULL && acs != cs) { do { temp = OCNT(acs); OCNT(acs) = ccre - acs; acs -= temp; } while (temp != 0); acs = NULL; } cs = ccre; *cs = OPER; OSYM(cs) = '('; ccre = ONEXT(cs); expconv(); OCNT(cs) = ccre - cs; /* offset to next symbol */ break; /* return from a recursion */ case ')': if (acs != NULL) { do { temp = OCNT(acs); OCNT(acs) = ccre - acs; acs -= temp; } while (temp != 0); acs = NULL; } cs = ccre; *cs = META; MSYM(cs) = c; ccre = MNEXT(cs); return; /* mark the last match sequence as having an alternate */ /* the third byte will contain an offset to jump over the */ /* alternate match in case the first did not fail */ case '|': if (acs != NULL && acs != cs) OCNT(ccre) = ccre - acs; /* make a back pointer */ else OCNT(ccre) = 0; *cs |= ALT; cs = ccre; *cs = OPER; OSYM(cs) = '|'; ccre = ONEXT(cs); acs = cs; /* remember that the pointer is to be filles */ break; /* if its not a metasymbol just build a scharacter string */ default: if (cs == NULL || (*cs & STR) == 0) { cs = ccre; *cs = STR; SCNT(cs) = 1; ccre = SSTR(cs); } else SCNT(cs)++; *ccre++ = c; break; } } if (acs != NULL) { do { temp = OCNT(acs); OCNT(acs) = ccre - acs; acs -= temp; } while (temp != 0); acs = NULL; } return; } /* end of convertre */ /* * The following routine recognises an irregular expression * with the following special characters: * * \? - means last match was optional * \a - matches any number of characters * \d - matches any number of spaces and tabs * \p - matches any number of alphanumeric * characters. The * characters matched will be copied into * the area pointed to by 'name'. * \| - alternation * \( \) - grouping used mostly for alternation and * optionality * * The irregular expression must be translated to internal form * prior to calling this routine * * The value returned is the pointer to the first non \a * character matched. */ /* * s: string to check for a match in * re: a converted irregular expression * mstring: where to put whatever matches a \p */ char * expmatch (register char *s, register char *re, register char *mstring) { register char *cs; /* the current symbol */ register char *ptr,*s1; /* temporary pointer */ bool matched; /* a temporary bool */ /* initial conditions */ if (re == NULL) return (NULL); cs = re; matched = false; /* loop till expression string is exhausted (or at least pretty tired) */ while (*cs) { switch (*cs & (OPER | STR | META)) { /* try to match a string */ case STR: matched = !STRNCMP (s, SSTR(cs), SCNT(cs)); if (matched) { /* hoorah it matches */ s += SCNT(cs); cs = SNEXT(cs); } else if (*cs & ALT) { /* alternation, skip to next expression */ cs = SNEXT(cs); } else if (*cs & OPT) { /* the match is optional */ cs = SNEXT(cs); matched = 1; /* indicate a successful match */ } else { /* no match, error return */ return (NULL); } break; /* an operator, do something fancy */ case OPER: switch (OSYM(cs)) { /* this is an alternation */ case '|': if (matched) /* last thing in the alternation was a match, skip ahead */ cs = OPTR(cs); else /* no match, keep trying */ cs = ONEXT(cs); break; /* this is a grouping, recurse */ case '(': ptr = expmatch(s, ONEXT(cs), mstring); if (ptr != NULL) { /* the subexpression matched */ matched = 1; s = ptr; } else if (*cs & ALT) { /* alternation, skip to next expression */ matched = 0; } else if (*cs & OPT) { /* the match is optional */ matched = 1; /* indicate a successful match */ } else { /* no match, error return */ return (NULL); } cs = OPTR(cs); break; } break; /* try to match a metasymbol */ case META: switch (MSYM(cs)) { /* try to match anything and remember what was matched */ case 'p': /* * This is really the same as trying the match the * remaining parts of the expression to any subset * of the string. */ s1 = s; do { ptr = expmatch(s1, MNEXT(cs), mstring); if (ptr != NULL && s1 != s) { /* we have a match, remember the match */ strncpy (mstring, s, s1 - s); mstring[s1 - s] = '\0'; return (ptr); } else if (ptr != NULL && (*cs & OPT)) { /* it was aoptional so no match is ok */ return (ptr); } else if (ptr != NULL) { /* not optional and we still matched */ return (NULL); } if (!(isalnum(*s1) || *s1 == '_' || /* C++ destructor */ *s1 == '~' || /* C++ scope operator */ (strlen(s1) > 1 && *s1 == ':' && s1[1] == ':' && (s1++, true)))) return (NULL); if (*s1 == '\\') _escaped = _escaped ? false : true; else _escaped = false; } while (*s1++); return (NULL); /* try to match anything */ case 'a': /* * This is really the same as trying the match the * remaining parts of the expression to any subset * of the string. */ s1 = s; do { ptr = expmatch(s1, MNEXT(cs), mstring); if (ptr != NULL && s1 != s) { /* we have a match */ return (ptr); } else if (ptr != NULL && (*cs & OPT)) { /* it was aoptional so no match is ok */ return (ptr); } else if (ptr != NULL) { /* not optional and we still matched */ return (NULL); } if (*s1 == '\\') _escaped = _escaped ? false : true; else _escaped = false; } while (*s1++); return (NULL); /* fail if we are currently _escaped */ case 'e': if (_escaped) return(NULL); cs = MNEXT(cs); break; /* match any number of tabs and spaces */ case 'd': ptr = s; while (*s == ' ' || *s == '\t') s++; if (s != ptr || s == s_start) { /* match, be happy */ matched = 1; cs = MNEXT(cs); } else if (*s == '\n' || *s == '\0') { /* match, be happy */ matched = 1; cs = MNEXT(cs); } else if (*cs & ALT) { /* try the next part */ matched = 0; cs = MNEXT(cs); } else if (*cs & OPT) { /* doesn't matter */ matched = 1; cs = MNEXT(cs); } else /* no match, error return */ return (NULL); break; /* check for end of line */ case '$': if (*s == '\0' || *s == '\n') { /* match, be happy */ s++; matched = 1; cs = MNEXT(cs); } else if (*cs & ALT) { /* try the next part */ matched = 0; cs = MNEXT(cs); } else if (*cs & OPT) { /* doesn't matter */ matched = 1; cs = MNEXT(cs); } else /* no match, error return */ return (NULL); break; /* check for start of line */ case '^': if (s == s_start) { /* match, be happy */ matched = 1; cs = MNEXT(cs); } else if (*cs & ALT) { /* try the next part */ matched = 0; cs = MNEXT(cs); } else if (*cs & OPT) { /* doesn't matter */ matched = 1; cs = MNEXT(cs); } else /* no match, error return */ return (NULL); break; /* end of a subexpression, return success */ case ')': return (s); } break; } } return (s); } diff --git a/usr.bin/vgrind/vfontedpr.c b/usr.bin/vgrind/vfontedpr.c index 235073094296..dab2a3699008 100644 --- a/usr.bin/vgrind/vfontedpr.c +++ b/usr.bin/vgrind/vfontedpr.c @@ -1,718 +1,715 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)vfontedpr.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include #include #include #include #include #include "pathnames.h" #include "extern.h" #define STANDARD 0 #define ALTERNATE 1 /* * Vfontedpr. * * Dave Presotto 1/12/81 (adapted from an earlier version by Bill Joy) * */ #define STRLEN 10 /* length of strings introducing things */ #define PNAMELEN 40 /* length of a function/procedure name */ #define PSMAX 20 /* size of procedure name stacking */ static int iskw(char *); static bool isproc(char *); static void putKcp(char *, char *, bool); static void putScp(char *); static void putcp(int); static int tabs(char *, char *); static int width(char *, char *); /* * The state variables */ static bool filter = false; /* act as a filter (like eqn) */ static bool inchr; /* in a string constant */ static bool incomm; /* in a comment of the primary type */ static bool idx = false; /* form an index */ static bool instr; /* in a string constant */ static bool nokeyw = false; /* no keywords being flagged */ static bool pass = false; /* * when acting as a filter, pass indicates * whether we are currently processing * input. */ static int blklevel; /* current nesting level */ static int comtype; /* type of comment */ static char * defsfile[2] = { _PATH_VGRINDEFS, 0 }; /* name of language definitions file */ static int margin; static int plstack[PSMAX]; /* the procedure nesting level stack */ static char pname[BUFSIZ+1]; static bool prccont; /* continue last procedure */ static int psptr; /* the stack index of the current procedure */ static char pstack[PSMAX][PNAMELEN+1]; /* the procedure name stack */ /* * The language specific globals */ char *l_acmbeg; /* string introducing a comment */ char *l_acmend; /* string ending a comment */ char *l_blkbeg; /* string beginning of a block */ char *l_blkend; /* string ending a block */ char *l_chrbeg; /* delimiter for character constant */ char *l_chrend; /* delimiter for character constant */ char *l_combeg; /* string introducing a comment */ char *l_comend; /* string ending a comment */ char l_escape; /* character used to escape characters */ char *l_keywds[BUFSIZ/2]; /* keyword table address */ char *l_nocom; /* regexp for non-comments */ char *l_prcbeg; /* regular expr for procedure begin */ char *l_strbeg; /* delimiter for string constant */ char *l_strend; /* delimiter for string constant */ bool l_toplex; /* procedures only defined at top lex level */ const char *language = "c"; /* the language indicator */ #define ps(x) printf("%s", x) static char minus[] = "-"; static char minusn[] = "-n"; int main(int argc, char **argv) { const char *fname = ""; struct stat stbuf; char buf[BUFSIZ]; char *defs; int needbp = 0; argc--, argv++; do { char *cp; int i; if (argc > 0) { if (!strcmp(argv[0], "-h")) { if (argc == 1) { printf("'ds =H\n"); argc = 0; goto rest; } printf("'ds =H %s\n", argv[1]); argc--, argv++; argc--, argv++; if (argc > 0) continue; goto rest; } /* act as a filter like eqn */ if (!strcmp(argv[0], "-f")) { filter = true; argv[0] = argv[argc-1]; argv[argc-1] = minus; continue; } /* take input from the standard place */ if (!strcmp(argv[0], "-")) { argc = 0; goto rest; } /* build an index */ if (!strcmp(argv[0], "-x")) { idx = true; argv[0] = minusn; } /* indicate no keywords */ if (!strcmp(argv[0], "-n")) { nokeyw = true; argc--, argv++; continue; } /* specify the font size */ if (!strncmp(argv[0], "-s", 2)) { i = 0; cp = argv[0] + 2; while (*cp) i = i * 10 + (*cp++ - '0'); printf("'ps %d\n'vs %d\n", i, i+1); argc--, argv++; continue; } /* specify the language */ if (!strncmp(argv[0], "-l", 2)) { language = argv[0]+2; argc--, argv++; continue; } /* specify the language description file */ if (!strncmp(argv[0], "-d", 2)) { defsfile[0] = argv[1]; argc--, argv++; argc--, argv++; continue; } /* open the file for input */ if (freopen(argv[0], "r", stdin) == NULL) err(1, "%s", argv[0]); if (idx) printf("'ta 4i 4.25i 5.5iR\n'in .5i\n"); fname = argv[0]; argc--, argv++; } rest: /* * get the language definition from the defs file */ i = cgetent(&defs, defsfile, language); if (i == -1) { fprintf (stderr, "no entry for language %s\n", language); exit(0); } else if (i == -2) { fprintf(stderr, "cannot find vgrindefs file %s\n", defsfile[0]); exit(0); } else if (i == -3) { fprintf(stderr, "potential reference loop detected in vgrindefs file %s\n", defsfile[0]); exit(0); } if (cgetustr(defs, "kw", &cp) == -1) nokeyw = true; else { char **cpp; cpp = l_keywds; while (*cp) { while (*cp == ' ' || *cp =='\t') *cp++ = '\0'; if (*cp) *cpp++ = cp; while (*cp != ' ' && *cp != '\t' && *cp) cp++; } *cpp = NULL; } cgetustr(defs, "pb", &cp); l_prcbeg = convexp(cp); cgetustr(defs, "cb", &cp); l_combeg = convexp(cp); cgetustr(defs, "ce", &cp); l_comend = convexp(cp); cgetustr(defs, "ab", &cp); l_acmbeg = convexp(cp); cgetustr(defs, "ae", &cp); l_acmend = convexp(cp); cgetustr(defs, "sb", &cp); l_strbeg = convexp(cp); cgetustr(defs, "se", &cp); l_strend = convexp(cp); cgetustr(defs, "bb", &cp); l_blkbeg = convexp(cp); cgetustr(defs, "be", &cp); l_blkend = convexp(cp); cgetustr(defs, "lb", &cp); l_chrbeg = convexp(cp); cgetustr(defs, "le", &cp); l_chrend = convexp(cp); if (cgetustr(defs, "nc", &cp) >= 0) l_nocom = convexp(cp); l_escape = '\\'; l_onecase = (cgetcap(defs, "oc", ':') != NULL); l_toplex = (cgetcap(defs, "tl", ':') != NULL); /* initialize the program */ incomm = false; instr = false; inchr = false; _escaped = false; blklevel = 0; for (psptr=0; psptr= 0)) { ps("'FC "); ps(pstack[psptr]); ps("\n"); } #ifdef DEBUG printf ("com %o str %o chr %o ptr %d\n", incomm, instr, inchr, psptr); #endif margin = 0; } needbp = 1; } while (argc > 0); exit(0); } #define isidchr(c) (isalnum(c) || (c) == '_') static void putScp(char *os) { register char *s = os; /* pointer to unmatched string */ char dummy[BUFSIZ]; /* dummy to be used by expmatch */ char *comptr; /* end of a comment delimiter */ char *acmptr; /* end of a comment delimiter */ char *strptr; /* end of a string delimiter */ char *chrptr; /* end of a character const delimiter */ char *blksptr; /* end of a lexical block start */ char *blkeptr; /* end of a lexical block end */ char *nocomptr; /* end of a non-comment delimiter */ s_start = os; /* remember the start for expmatch */ _escaped = false; if (nokeyw || incomm || instr) goto skip; if (isproc(s)) { ps("'FN "); ps(pname); ps("\n"); if (psptr < PSMAX) { ++psptr; strncpy (pstack[psptr], pname, PNAMELEN); pstack[psptr][PNAMELEN] = '\0'; plstack[psptr] = blklevel; } } skip: do { /* check for string, comment, blockstart, etc */ if (!incomm && !instr && !inchr) { blkeptr = expmatch(s, l_blkend, dummy); blksptr = expmatch(s, l_blkbeg, dummy); comptr = expmatch(s, l_combeg, dummy); acmptr = expmatch(s, l_acmbeg, dummy); strptr = expmatch(s, l_strbeg, dummy); chrptr = expmatch(s, l_chrbeg, dummy); nocomptr = expmatch (s, l_nocom, dummy); /* start of non-comment? */ if (nocomptr != NULL) if ((nocomptr <= comptr || comptr == NULL) && (nocomptr <= acmptr || acmptr == NULL)) { /* continue after non-comment */ putKcp (s, nocomptr-1, false); s = nocomptr; continue; } /* start of a comment? */ if (comptr != NULL) if ((comptr < strptr || strptr == NULL) && (comptr < acmptr || acmptr == NULL) && (comptr < chrptr || chrptr == NULL) && (comptr < blksptr || blksptr == NULL) && (comptr < blkeptr || blkeptr == NULL)) { putKcp(s, comptr-1, false); s = comptr; incomm = true; comtype = STANDARD; if (s != os) ps("\\c"); ps("\\c\n'+C\n"); continue; } /* start of a comment? */ if (acmptr != NULL) if ((acmptr < strptr || strptr == NULL) && (acmptr < chrptr || chrptr == NULL) && (acmptr < blksptr || blksptr == NULL) && (acmptr < blkeptr || blkeptr == NULL)) { putKcp(s, acmptr-1, false); s = acmptr; incomm = true; comtype = ALTERNATE; if (s != os) ps("\\c"); ps("\\c\n'+C\n"); continue; } /* start of a string? */ if (strptr != NULL) if ((strptr < chrptr || chrptr == NULL) && (strptr < blksptr || blksptr == NULL) && (strptr < blkeptr || blkeptr == NULL)) { putKcp(s, strptr-1, false); s = strptr; instr = true; continue; } /* start of a character string? */ if (chrptr != NULL) if ((chrptr < blksptr || blksptr == NULL) && (chrptr < blkeptr || blkeptr == NULL)) { putKcp(s, chrptr-1, false); s = chrptr; inchr = true; continue; } /* end of a lexical block */ if (blkeptr != NULL) { if (blkeptr < blksptr || blksptr == NULL) { putKcp(s, blkeptr - 1, false); s = blkeptr; if (blklevel > 0 /* sanity */) blklevel--; if (psptr >= 0 && plstack[psptr] >= blklevel) { /* end of current procedure */ if (s != os) ps("\\c"); ps("\\c\n'-F\n"); blklevel = plstack[psptr]; /* see if we should print the last proc name */ if (--psptr >= 0) prccont = true; else psptr = -1; } continue; } } /* start of a lexical block */ if (blksptr != NULL) { putKcp(s, blksptr - 1, false); s = blksptr; blklevel++; continue; } /* check for end of comment */ } else if (incomm) { comptr = expmatch(s, l_comend, dummy); acmptr = expmatch(s, l_acmend, dummy); if (((comtype == STANDARD) && (comptr != NULL)) || ((comtype == ALTERNATE) && (acmptr != NULL))) { if (comtype == STANDARD) { putKcp(s, comptr-1, true); s = comptr; } else { putKcp(s, acmptr-1, true); s = acmptr; } incomm = false; ps("\\c\n'-C\n"); continue; } else { putKcp(s, s + strlen(s) -1, true); s = s + strlen(s); continue; } /* check for end of string */ } else if (instr) { if ((strptr = expmatch(s, l_strend, dummy)) != NULL) { putKcp(s, strptr-1, true); s = strptr; instr = false; continue; } else { putKcp(s, s+strlen(s)-1, true); s = s + strlen(s); continue; } /* check for end of character string */ } else if (inchr) { if ((chrptr = expmatch(s, l_chrend, dummy)) != NULL) { putKcp(s, chrptr-1, true); s = chrptr; inchr = false; continue; } else { putKcp(s, s+strlen(s)-1, true); s = s + strlen(s); continue; } } /* print out the line */ putKcp(s, s + strlen(s) -1, false); s = s + strlen(s); } while (*s); } /* * start: start of string to write * end: end of string to write * force: true if we should force nokeyw */ static void putKcp(char *start, char *end, bool force) { int i; int xfld = 0; while (start <= end) { if (idx) { if (*start == ' ' || *start == '\t') { if (xfld == 0) printf("\001"); printf("\t"); xfld = 1; while (*start == ' ' || *start == '\t') start++; continue; } } /* take care of nice tab stops */ if (*start == '\t') { while (*start == '\t') start++; i = tabs(s_start, start) - margin / 8; printf("\\h'|%dn'", i * 10 + 1 - margin % 8); continue; } if (!nokeyw && !force) if ((*start == '#' || isidchr(*start)) && (start == s_start || !isidchr(start[-1]))) { i = iskw(start); if (i > 0) { ps("\\*(+K"); do putcp((unsigned char)*start++); while (--i > 0); ps("\\*(-K"); continue; } } putcp((unsigned char)*start++); } } static int tabs(char *s, char *os) { return (width(s, os) / 8); } static int width(register char *s, register char *os) { register int i = 0; while (s < os) { if (*s == '\t') { i = (i + 8) &~ 7; s++; continue; } if (*s < ' ') i += 2; else i++; s++; } return (i); } static void putcp(register int c) { switch(c) { case 0: break; case '\f': break; case '\r': break; case '{': ps("\\*(+K{\\*(-K"); break; case '}': ps("\\*(+K}\\*(-K"); break; case '\\': ps("\\e"); break; case '_': ps("\\*_"); break; case '-': ps("\\*-"); break; case '`': ps("\\`"); break; case '\'': ps("\\'"); break; case '.': ps("\\&."); break; case '*': ps("\\fI*\\fP"); break; case '/': ps("\\fI\\h'\\w' 'u-\\w'/'u'/\\fP"); break; default: if (c < 040) putchar('^'), c |= '@'; case '\t': case '\n': putchar(c); } } /* * look for a process beginning on this line */ static bool isproc(char *s) { pname[0] = '\0'; if (!l_toplex || blklevel == 0) if (expmatch(s, l_prcbeg, pname) != NULL) { return (true); } return (false); } /* iskw - check to see if the next word is a keyword */ static int iskw(register char *s) { register char **ss = l_keywds; register int i = 1; register char *cp = s; while (++cp, isidchr(*cp)) i++; while ((cp = *ss++)) if (!STRNCMP(s,cp,i) && !isidchr(cp[i])) return (i); return (0); } diff --git a/usr.bin/w/pr_time.c b/usr.bin/w/pr_time.c index 20b75704c309..7be11b777e79 100644 --- a/usr.bin/w/pr_time.c +++ b/usr.bin/w/pr_time.c @@ -1,132 +1,129 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1990, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)pr_time.c 8.2 (Berkeley) 4/4/94"; #endif #include #include #include #include #include #include #include "extern.h" /* * pr_attime -- * Print the time since the user logged in. */ int pr_attime(time_t *started, time_t *now) { static wchar_t buf[256]; struct tm tp, tm; time_t diff; const wchar_t *fmt; int len, width, offset = 0; tp = *localtime(started); tm = *localtime(now); diff = *now - *started; /* If more than a week, use day-month-year. */ if (diff > 86400 * 7) fmt = L"%d%b%y"; /* If not today, use day-hour-am/pm. */ else if (tm.tm_mday != tp.tm_mday || tm.tm_mon != tp.tm_mon || tm.tm_year != tp.tm_year) { /* The line below does not take DST into consideration */ /* else if (*now / 86400 != *started / 86400) { */ fmt = use_ampm ? L"%a%I%p" : L"%a%H"; } /* Default is hh:mm{am,pm}. */ else { fmt = use_ampm ? L"%l:%M%p" : L"%k:%M"; } (void)wcsftime(buf, sizeof(buf), fmt, &tp); len = wcslen(buf); width = wcswidth(buf, len); xo_attr("since", "%lu", (unsigned long) *started); xo_attr("delta", "%lu", (unsigned long) diff); if (len == width) xo_emit("{:login-time/%-7.7ls/%ls}", buf); else if (width < 7) xo_emit("{:login-time/%ls}%.*s", buf, 7 - width, " "); else { xo_emit("{:login-time/%ls}", buf); offset = width - 7; } return (offset); } /* * pr_idle -- * Display the idle time. * Returns number of excess characters that were used for long idle time. */ int pr_idle(time_t idle) { /* If idle more than 36 hours, print as a number of days. */ if (idle >= 36 * 3600) { int days = idle / 86400; xo_emit(" {:idle/%dday%s} ", days, days > 1 ? "s" : " " ); if (days >= 100) return (2); if (days >= 10) return (1); } /* If idle more than an hour, print as HH:MM. */ else if (idle >= 3600) xo_emit(" {:idle/%2d:%02d/} ", (int)(idle / 3600), (int)((idle % 3600) / 60)); else if (idle / 60 == 0) xo_emit(" - "); /* Else print the minutes idle. */ else xo_emit(" {:idle/%2d} ", (int)(idle / 60)); return (0); /* not idle longer than 9 days */ } diff --git a/usr.bin/w/w.c b/usr.bin/w/w.c index 5ba9f49cdd35..7c67a851ca99 100644 --- a/usr.bin/w/w.c +++ b/usr.bin/w/w.c @@ -1,588 +1,585 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1991, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)w.c 8.4 (Berkeley) 4/16/94"; #endif /* * w - print system status (who and what) * * This program is similar to the systat command on Tenex/Tops 10/20 * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "extern.h" static struct utmpx *utmp; static struct winsize ws; static kvm_t *kd; static time_t now; /* the current time of day */ static size_t ttywidth; /* width of tty */ static size_t fromwidth = 0; /* max width of "from" field */ static size_t argwidth; /* width of arguments */ static int header = 1; /* true if -h flag: don't print heading */ static int nflag; /* true if -n flag: don't convert addrs */ static int dflag; /* true if -d flag: output debug info */ static int sortidle; /* sort by idle time */ int use_ampm; /* use AM/PM time */ static int use_comma; /* use comma as floats separator */ static char **sel_users; /* login array of particular users selected */ /* * One of these per active utmp entry. */ static struct entry { struct entry *next; struct utmpx utmp; dev_t tdev; /* dev_t of terminal */ time_t idle; /* idle time of terminal in seconds */ struct kinfo_proc *kp; /* `most interesting' proc */ char *args; /* arg list of interesting process */ struct kinfo_proc *dkp; /* debug option proc list */ char *from; /* "from": name or addr */ char *save_from; /* original "from": name or addr */ } *ep, *ehead = NULL, **nextp = &ehead; #define debugproc(p) *(&((struct kinfo_proc *)p)->ki_udata) #define W_DISPUSERSIZE 10 #define W_DISPLINESIZE 8 #define W_MAXHOSTSIZE 40 static void pr_header(time_t *, int); static struct stat *ttystat(char *); static void usage(int); char *fmt_argv(char **, char *, char *, size_t); /* ../../bin/ps/fmt.c */ int main(int argc, char *argv[]) { struct kinfo_proc *kp; struct kinfo_proc *dkp; struct stat *stp; time_t touched; size_t width; int ch, i, nentries, nusers, wcmd, longidle, longattime; const char *memf, *nlistf, *p, *save_p; char *x_suffix; char errbuf[_POSIX2_LINE_MAX]; char buf[MAXHOSTNAMELEN], fn[MAXHOSTNAMELEN]; char *dot; (void)setlocale(LC_ALL, ""); use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0'); use_comma = (*nl_langinfo(RADIXCHAR) != ','); argc = xo_parse_args(argc, argv); if (argc < 0) exit(1); /* Are we w(1) or uptime(1)? */ if (strcmp(basename(argv[0]), "uptime") == 0) { wcmd = 0; p = ""; } else { wcmd = 1; p = "dhiflM:N:nsuw"; } 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; break; case 'N': nlistf = optarg; break; case 'n': nflag += 1; break; case 'f': case 'l': case 's': case 'u': case 'w': xo_warnx("-%c no longer supported", ch); /* 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.. */ if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf)) == NULL) xo_errx(1, "%s", errbuf); (void)time(&now); if (*argv) sel_users = argv; setutxent(); for (nusers = 0; (utmp = getutxent()) != NULL;) { 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; int isaddr; 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) xo_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; save_p = 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 == 0) { /* 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 && nflag > 1) { /* * 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; } ep->from = strdup(p); if ((width = strlen(p)) > fromwidth) fromwidth = width; if (save_p != p) ep->save_from = strdup(save_p); } endutxent(); #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 + fromwidth + \ sizeof(HEADER_LOGIN_IDLE) + 3) /* header width incl. spaces */ if (sizeof(HEADER_FROM) > fromwidth) fromwidth = sizeof(HEADER_FROM); fromwidth++; if (fromwidth > W_MAXHOSTSIZE) fromwidth = W_MAXHOSTSIZE; xo_open_container("uptime-information"); if (header || wcmd == 0) { pr_header(&now, nusers); if (wcmd == 0) { xo_close_container("uptime-information"); if (xo_finish() < 0) xo_err(1, "stdout"); (void)kvm_close(kd); exit(0); } xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%s}", W_DISPUSERSIZE, W_DISPUSERSIZE, HEADER_USER, W_DISPLINESIZE, W_DISPLINESIZE, HEADER_TTY, fromwidth, fromwidth, HEADER_FROM, HEADER_LOGIN_IDLE HEADER_WHAT); } if ((kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &nentries)) == NULL) xo_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) xo_err(1, "fmt_argv"); } /* 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; } } xo_open_container("user-table"); xo_open_list("user-entry"); for (ep = ehead; ep != NULL; ep = ep->next) { time_t t; xo_open_instance("user-entry"); if (dflag) { xo_open_container("process-table"); xo_open_list("process-entry"); 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 = "-"; xo_open_instance("process-entry"); xo_emit("\t\t{:process-id/%-9d/%d} " "{:command/%hs}\n", dkp->ki_pid, ptr); xo_close_instance("process-entry"); } xo_close_list("process-entry"); xo_close_container("process-table"); } xo_emit("{:user/%-*.*s/%@**@s} {:tty/%-*.*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) : "-"); if (ep->save_from) xo_attr("address", "%s", ep->save_from); xo_emit("{:from/%-*.*s/%@**@s} ", (int)fromwidth, (int)fromwidth, ep->from); t = ep->utmp.ut_tv.tv_sec; longattime = pr_attime(&t, &now); longidle = pr_idle(ep->idle); xo_emit("{:command/%.*hs/%@*@hs}\n", (int)argwidth - longidle - longattime, ep->args); xo_close_instance("user-entry"); } xo_close_list("user-entry"); xo_close_container("user-table"); xo_close_container("uptime-information"); if (xo_finish() < 0) xo_err(1, "stdout"); (void)kvm_close(kd); exit(0); } static void pr_header(time_t *nowp, int nusers) { char buf[64]; struct sbuf upbuf; double avenrun[3]; struct timespec tp; unsigned long days, hrs, mins, secs; unsigned int i; /* * Print time of day. */ if (strftime(buf, sizeof(buf), use_ampm ? "%l:%M%p" : "%k:%M", localtime(nowp)) != 0) xo_emit("{:time-of-day/%s} ", buf); /* * Print how long system has been up. */ (void)sbuf_new(&upbuf, buf, sizeof(buf), SBUF_FIXEDLEN); if (clock_gettime(CLOCK_UPTIME, &tp) != -1) { xo_emit(" up"); secs = tp.tv_sec; xo_emit("{e:uptime/%lu}", secs); mins = secs / 60; secs %= 60; hrs = mins / 60; mins %= 60; days = hrs / 24; hrs %= 24; xo_emit("{e:days/%ld}{e:hours/%ld}{e:minutes/%ld}{e:seconds/%ld}", days, hrs, mins, secs); /* If we've been up longer than 60 s, round to nearest min */ if (tp.tv_sec > 60) { secs = tp.tv_sec + 30; mins = secs / 60; secs = 0; hrs = mins / 60; mins %= 60; days = hrs / 24; hrs %= 24; } if (days > 0) sbuf_printf(&upbuf, " %ld day%s,", days, days > 1 ? "s" : ""); if (hrs > 0 && mins > 0) sbuf_printf(&upbuf, " %2ld:%02ld,", hrs, mins); else if (hrs > 0) sbuf_printf(&upbuf, " %ld hr%s,", hrs, hrs > 1 ? "s" : ""); else if (mins > 0) sbuf_printf(&upbuf, " %ld min%s,", mins, mins > 1 ? "s" : ""); else sbuf_printf(&upbuf, " %ld sec%s,", secs, secs > 1 ? "s" : ""); if (sbuf_finish(&upbuf) != 0) xo_err(1, "Could not generate output"); xo_emit("{:uptime-human/%s}", sbuf_data(&upbuf)); sbuf_delete(&upbuf); } /* Print number of users logged in to system */ xo_emit(" {:users/%d} {Np:user,users}", nusers); /* * Print 1, 5, and 15 minute load averages. */ if (getloadavg(avenrun, nitems(avenrun)) == -1) xo_emit(", no load average information available\n"); else { static const char *format[] = { " {:load-average-1/%.2f}", " {:load-average-5/%.2f}", " {:load-average-15/%.2f}", }; xo_emit(", load averages:"); for (i = 0; i < nitems(avenrun); i++) { if (use_comma && i > 0) xo_emit(","); xo_emit(format[i], avenrun[i]); } xo_emit("\n"); } } static struct stat * ttystat(char *line) { static struct stat sb; char ttybuf[MAXPATHLEN]; (void)snprintf(ttybuf, sizeof(ttybuf), "%s%s", _PATH_DEV, line); if (stat(ttybuf, &sb) == 0 && S_ISCHR(sb.st_mode)) return (&sb); return (NULL); } static void usage(int wcmd) { if (wcmd) xo_error("usage: w [-dhin] [-M core] [-N system] [user ...]\n"); else xo_error("usage: uptime\n"); xo_finish(); exit(1); } diff --git a/usr.bin/wall/ttymsg.c b/usr.bin/wall/ttymsg.c index beae788a9ba2..dc149db84885 100644 --- a/usr.bin/wall/ttymsg.c +++ b/usr.bin/wall/ttymsg.c @@ -1,169 +1,166 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char sccsid[] = "@(#)ttymsg.c 8.2 (Berkeley) 11/16/93"; #endif #include #include #include #include #include #include #include #include #include #include #include #include "ttymsg.h" /* * Display the contents of a uio structure on a terminal. Used by wall(1), * syslogd(8), and talkd(8). Forks and finishes in child if write would block, * waiting up to tmout seconds. Returns pointer to error string on unexpected * error; string is not newline-terminated. Various "normal" errors are * ignored (exclusive-use, lack of permission, etc.). */ const char * ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout) { struct iovec localiov[TTYMSG_IOV_MAX]; ssize_t left, wret; int cnt, fd; char device[MAXNAMLEN] = _PATH_DEV; static char errbuf[1024]; char *p; int forked; forked = 0; if (iovcnt > (int)(sizeof(localiov) / sizeof(localiov[0]))) return ("too many iov's (change code in wall/ttymsg.c)"); strlcat(device, line, sizeof(device)); p = device + sizeof(_PATH_DEV) - 1; if (strncmp(p, "pts/", 4) == 0) p += 4; if (strchr(p, '/') != NULL) { /* A slash is an attempt to break security... */ (void) snprintf(errbuf, sizeof(errbuf), "Too many '/' in \"%s\"", device); return (errbuf); } /* * open will fail on slip lines or exclusive-use lines * if not running as root; not an error. */ if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) { if (errno == EBUSY || errno == EACCES) return (NULL); (void) snprintf(errbuf, sizeof(errbuf), "%s: %s", device, strerror(errno)); return (errbuf); } for (cnt = 0, left = 0; cnt < iovcnt; ++cnt) left += iov[cnt].iov_len; for (;;) { wret = writev(fd, iov, iovcnt); if (wret >= left) break; if (wret >= 0) { left -= wret; if (iov != localiov) { bcopy(iov, localiov, iovcnt * sizeof(struct iovec)); iov = localiov; } for (cnt = 0; (size_t)wret >= iov->iov_len; ++cnt) { wret -= iov->iov_len; ++iov; --iovcnt; } if (wret) { iov->iov_base = (char *)iov->iov_base + wret; iov->iov_len -= wret; } continue; } if (errno == EWOULDBLOCK) { int cpid; if (forked) { (void) close(fd); _exit(1); } cpid = fork(); if (cpid < 0) { (void) snprintf(errbuf, sizeof(errbuf), "fork: %s", strerror(errno)); (void) close(fd); return (errbuf); } if (cpid) { /* parent */ (void) close(fd); return (NULL); } forked++; /* wait at most tmout seconds */ (void) signal(SIGALRM, SIG_DFL); (void) signal(SIGTERM, SIG_DFL); /* XXX */ (void) sigsetmask(0); (void) alarm((u_int)tmout); (void) fcntl(fd, F_SETFL, 0); /* clear O_NONBLOCK */ continue; } /* * We get ENODEV on a slip line if we're running as root, * and EIO if the line just went away. */ if (errno == ENODEV || errno == EIO) break; (void) close(fd); if (forked) _exit(1); (void) snprintf(errbuf, sizeof(errbuf), "%s: %s", device, strerror(errno)); return (errbuf); } (void) close(fd); if (forked) _exit(0); return (NULL); } diff --git a/usr.bin/wall/wall.c b/usr.bin/wall/wall.c index a02f103cb80f..992bc9f77b22 100644 --- a/usr.bin/wall/wall.c +++ b/usr.bin/wall/wall.c @@ -1,294 +1,291 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1988, 1990, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1988, 1990, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)wall.c 8.2 (Berkeley) 11/16/93"; #endif /* * This program is not related to David Wall, whose Stanford Ph.D. thesis * is entitled "Mechanisms for Broadcast and Selective Broadcast". */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ttymsg.h" static void makemsg(char *); static void usage(void); static struct wallgroup { struct wallgroup *next; char *name; gid_t gid; } *grouplist; static int nobanner; static int mbufsize; static char *mbuf; static int ttystat(char *line) { struct stat sb; char ttybuf[MAXPATHLEN]; (void)snprintf(ttybuf, sizeof(ttybuf), "%s%s", _PATH_DEV, line); if (stat(ttybuf, &sb) == 0) { return (0); } else return (-1); } 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); } static void usage(void) { (void)fprintf(stderr, "usage: wall [-g group] [file]\n"); exit(1); } void makemsg(char *fname) { int cnt; wchar_t ch; struct tm *lt; struct passwd *pw; struct stat sbuf; time_t now; FILE *fp; int fd; char hostname[MAXHOSTNAMELEN], tmpname[64]; wchar_t *p, *tmp, lbuf[256], codebuf[13]; const char *tty; const char *whom; gid_t egid; (void)snprintf(tmpname, sizeof(tmpname), "%s/wall.XXXXXX", _PATH_TMP); if ((fd = mkstemp(tmpname)) == -1 || !(fp = fdopen(fd, "r+"))) err(1, "can't open temporary file"); (void)unlink(tmpname); if (!nobanner) { tty = ttyname(STDERR_FILENO); if (tty == NULL) tty = "no tty"; if (!(whom = getlogin())) whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???"; (void)gethostname(hostname, sizeof(hostname)); (void)time(&now); lt = localtime(&now); /* * all this stuff is to blank out a square for the message; * we wrap message lines at column 79, not 80, because some * terminals wrap after 79, some do not, and we can't tell. * Which means that we may leave a non-blank character * in column 80, but that can't be helped. */ (void)fwprintf(fp, L"\r%79s\r\n", " "); (void)swprintf(lbuf, sizeof(lbuf)/sizeof(wchar_t), L"Broadcast Message from %s@%s", whom, hostname); (void)fwprintf(fp, L"%-79.79S\007\007\r\n", lbuf); (void)swprintf(lbuf, sizeof(lbuf)/sizeof(wchar_t), L" (%s) at %d:%02d %s...", tty, lt->tm_hour, lt->tm_min, lt->tm_zone); (void)fwprintf(fp, L"%-79.79S\r\n", lbuf); } (void)fwprintf(fp, L"%79s\r\n", " "); if (fname) { egid = getegid(); setegid(getgid()); if (freopen(fname, "r", stdin) == NULL) err(1, "can't read %s", fname); if (setegid(egid) != 0) err(1, "setegid failed"); } cnt = 0; while (fgetws(lbuf, sizeof(lbuf)/sizeof(wchar_t), stdin)) { for (p = lbuf; (ch = *p) != L'\0'; ++p, ++cnt) { if (ch == L'\r') { putwc(L'\r', fp); cnt = 0; continue; } else if (ch == L'\n') { for (; cnt < 79; ++cnt) putwc(L' ', fp); putwc(L'\r', fp); putwc(L'\n', fp); break; } if (cnt == 79) { putwc(L'\r', fp); putwc(L'\n', fp); cnt = 0; } if (iswprint(ch) || iswspace(ch) || ch == L'\a' || ch == L'\b') { putwc(ch, fp); } else { (void)swprintf(codebuf, sizeof(codebuf)/sizeof(wchar_t), L"<0x%X>", ch); for (tmp = codebuf; *tmp != L'\0'; ++tmp) { putwc(*tmp, fp); if (++cnt == 79) { putwc(L'\r', fp); putwc(L'\n', fp); cnt = 0; } } --cnt; } } } (void)fwprintf(fp, L"%79s\r\n", " "); rewind(fp); if (fstat(fd, &sbuf)) err(1, "can't stat temporary file"); mbufsize = sbuf.st_size; if (!(mbuf = malloc((u_int)mbufsize))) err(1, "out of memory"); if ((int)fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize) err(1, "can't read temporary file"); fclose(fp); } diff --git a/usr.bin/what/what.c b/usr.bin/what/what.c index 6d59f70cb589..5cd6a85f35bf 100644 --- a/usr.bin/what/what.c +++ b/usr.bin/what/what.c @@ -1,139 +1,136 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1988, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)what.c 8.1 (Berkeley) 6/6/93"; #endif #include #include #include #include #include static void usage(void); static bool search(bool, bool, FILE *); int main(int argc, char *argv[]) { const char *file; FILE *in; bool found, qflag, sflag; int c; qflag = sflag = false; while ((c = getopt(argc, argv, "qs")) != -1) { switch (c) { case 'q': qflag = true; break; case 's': sflag = true; break; default: usage(); } } argc -= optind; argv += optind; found = false; if (argc == 0) { if (search(sflag, qflag, stdin)) found = true; } else { while (argc--) { file = *argv++; in = fopen(file, "r"); if (in == NULL) { if (!qflag) warn("%s", file); continue; } if (!qflag) printf("%s:\n", file); if (search(sflag, qflag, in)) found = true; fclose(in); } } exit(found ? 0 : 1); } static void usage(void) { fprintf(stderr, "usage: what [-qs] [file ...]\n"); exit(1); } bool search(bool one, bool quiet, FILE *in) { bool found; int c; found = false; while ((c = getc(in)) != EOF) { loop: if (c != '@') continue; if ((c = getc(in)) != '(') goto loop; if ((c = getc(in)) != '#') goto loop; if ((c = getc(in)) != ')') goto loop; if (!quiet) putchar('\t'); while ((c = getc(in)) != EOF && c && c != '"' && c != '>' && c != '\\' && c != '\n') putchar(c); putchar('\n'); found = true; if (one) break; } return (found); } diff --git a/usr.bin/which/which.c b/usr.bin/which/which.c index abc23c876b2e..f6ee25f60cce 100644 --- a/usr.bin/which/which.c +++ b/usr.bin/which/which.c @@ -1,147 +1,144 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2000 Dan Papasian. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include static void usage(void); static int print_matches(char *, char *); static int silent; static int allpaths; int main(int argc, char **argv) { char *p, *path; ssize_t pathlen; int opt, status; status = EXIT_SUCCESS; while ((opt = getopt(argc, argv, "as")) != -1) { switch (opt) { case 'a': allpaths = 1; break; case 's': silent = 1; break; default: usage(); break; } } argv += optind; argc -= optind; if (argc == 0) usage(); if ((p = getenv("PATH")) == NULL) exit(EXIT_FAILURE); pathlen = strlen(p) + 1; path = malloc(pathlen); if (path == NULL) err(EXIT_FAILURE, NULL); while (argc > 0) { memcpy(path, p, pathlen); if (strlen(*argv) >= FILENAME_MAX || print_matches(path, *argv) == -1) status = EXIT_FAILURE; argv++; argc--; } exit(status); } static void usage(void) { (void)fprintf(stderr, "usage: which [-as] program ...\n"); exit(EXIT_FAILURE); } static int is_there(char *candidate) { struct stat fin; /* XXX work around access(2) false positives for superuser */ if (access(candidate, X_OK) == 0 && stat(candidate, &fin) == 0 && S_ISREG(fin.st_mode) && (getuid() != 0 || (fin.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0)) { if (!silent) printf("%s\n", candidate); return (1); } return (0); } static int print_matches(char *path, char *filename) { char candidate[PATH_MAX]; const char *d; int found; if (strchr(filename, '/') != NULL) return (is_there(filename) ? 0 : -1); found = 0; while ((d = strsep(&path, ":")) != NULL) { if (*d == '\0') d = "."; if (snprintf(candidate, sizeof(candidate), "%s/%s", d, filename) >= (int)sizeof(candidate)) continue; if (is_there(candidate)) { found = 1; if (!allpaths) break; } } return (found ? 0 : -1); } diff --git a/usr.bin/xstr/xstr.c b/usr.bin/xstr/xstr.c index da96581c3f2b..b1a5bf58ae01 100644 --- a/usr.bin/xstr/xstr.c +++ b/usr.bin/xstr/xstr.c @@ -1,493 +1,490 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)xstr.c 8.1 (Berkeley) 6/9/93"; #endif #include #include #include #include #include #include #include #include #include "pathnames.h" /* * xstr - extract and hash strings in a C program * * Bill Joy UCB * November, 1978 */ #define ignore(a) ((void) a) static off_t tellpt; static off_t mesgpt; static char cstrings[] = "strings"; static char *strings = cstrings; static int cflg; static int vflg; static int readstd; static char lastchr(char *); static int fgetNUL(char *, int, FILE *); static int istail(char *, char *); static int octdigit(char); static int xgetc(FILE *); static off_t hashit(char *, int); static off_t yankstr(char **); static void usage(void); static void flushsh(void); static void found(int, off_t, char *); static void inithash(void); static void onintr(int); static void process(const char *); static void prstr(char *); static void xsdotc(void); int main(int argc, char *argv[]) { int c; int fdesc; while ((c = getopt(argc, argv, "-cv")) != -1) switch (c) { case '-': readstd++; break; case 'c': cflg++; break; case 'v': vflg++; break; default: usage(); } argc -= optind; argv += optind; if (signal(SIGINT, SIG_IGN) == SIG_DFL) signal(SIGINT, onintr); if (cflg || (argc == 0 && !readstd)) inithash(); else { strings = strdup(_PATH_TMP); if (strings == NULL) err(1, "strdup() failed"); fdesc = mkstemp(strings); if (fdesc == -1) err(1, "Unable to create temporary file"); close(fdesc); } while (readstd || argc > 0) { if (freopen("x.c", "w", stdout) == NULL) err(1, "x.c"); if (!readstd && freopen(argv[0], "r", stdin) == NULL) err(2, "%s", argv[0]); process("x.c"); if (readstd == 0) argc--, argv++; else readstd = 0; } flushsh(); if (cflg == 0) xsdotc(); if (strings[0] == '/') ignore(unlink(strings)); exit(0); } static void usage(void) { fprintf(stderr, "usage: xstr [-cv] [-] [file ...]\n"); exit (1); } static char linebuf[BUFSIZ]; static void process(const char *name) { char *cp; int c; int incomm = 0; int ret; printf("extern char\txstr[];\n"); for (;;) { if (fgets(linebuf, sizeof linebuf, stdin) == NULL) { if (ferror(stdin)) err(3, "%s", name); break; } if (linebuf[0] == '#') { if (linebuf[1] == ' ' && isdigit(linebuf[2])) printf("#line%s", &linebuf[1]); else printf("%s", linebuf); continue; } for (cp = linebuf; (c = *cp++);) switch (c) { case '"': if (incomm) goto def; if ((ret = (int) yankstr(&cp)) == -1) goto out; printf("(&xstr[%d])", ret); break; case '\'': if (incomm) goto def; putchar(c); if (*cp) putchar(*cp++); break; case '/': if (incomm || *cp != '*') goto def; incomm = 1; cp++; printf("/*"); continue; case '*': if (incomm && *cp == '/') { incomm = 0; cp++; printf("*/"); continue; } goto def; def: default: putchar(c); break; } } out: if (ferror(stdout)) warn("x.c"), onintr(0); } static off_t yankstr(char **cpp) { char *cp = *cpp; int c, ch; char dbuf[BUFSIZ]; char *dp = dbuf; char *tp; static char tmp[] = "b\bt\tr\rn\nf\f\\\\\"\""; while ((c = *cp++)) { if (dp == dbuf + sizeof(dbuf) - 3) errx(1, "message too long"); switch (c) { case '"': cp++; goto out; case '\\': c = *cp++; if (c == 0) break; if (c == '\n') { if (fgets(linebuf, sizeof linebuf, stdin) == NULL) { if (ferror(stdin)) err(3, "x.c"); return(-1); } cp = linebuf; continue; } for (tp = tmp; (ch = *tp++); tp++) if (c == ch) { c = *tp; goto gotc; } if (!octdigit(c)) { *dp++ = '\\'; break; } c -= '0'; if (!octdigit(*cp)) break; c <<= 3, c += *cp++ - '0'; if (!octdigit(*cp)) break; c <<= 3, c += *cp++ - '0'; break; } gotc: *dp++ = c; } out: *cpp = --cp; *dp = 0; return (hashit(dbuf, 1)); } static int octdigit(char c) { return (isdigit(c) && c != '8' && c != '9'); } static void inithash(void) { char buf[BUFSIZ]; FILE *mesgread = fopen(strings, "r"); if (mesgread == NULL) return; for (;;) { mesgpt = tellpt; if (fgetNUL(buf, sizeof buf, mesgread) == 0) break; ignore(hashit(buf, 0)); } ignore(fclose(mesgread)); } static int fgetNUL(char *obuf, int rmdr, FILE *file) { int c; char *buf = obuf; while (--rmdr > 0 && (c = xgetc(file)) != 0 && c != EOF) *buf++ = c; *buf++ = 0; return ((feof(file) || ferror(file)) ? 0 : 1); } static int xgetc(FILE *file) { tellpt++; return (getc(file)); } #define BUCKETS 128 static struct hash { off_t hpt; char *hstr; struct hash *hnext; short hnew; } bucket[BUCKETS]; static off_t hashit(char *str, int new) { int i; struct hash *hp, *hp0; hp = hp0 = &bucket[lastchr(str) & 0177]; while (hp->hnext) { hp = hp->hnext; i = istail(str, hp->hstr); if (i >= 0) return (hp->hpt + i); } if ((hp = (struct hash *) calloc(1, sizeof (*hp))) == NULL) errx(8, "calloc"); hp->hpt = mesgpt; if (!(hp->hstr = strdup(str))) err(1, NULL); mesgpt += strlen(hp->hstr) + 1; hp->hnext = hp0->hnext; hp->hnew = new; hp0->hnext = hp; return (hp->hpt); } static void flushsh(void) { int i; struct hash *hp; FILE *mesgwrit; int old = 0, new = 0; for (i = 0; i < BUCKETS; i++) for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) if (hp->hnew) new++; else old++; if (new == 0 && old != 0) return; mesgwrit = fopen(strings, old ? "r+" : "w"); if (mesgwrit == NULL) err(4, "%s", strings); for (i = 0; i < BUCKETS; i++) for (hp = bucket[i].hnext; hp != NULL; hp = hp->hnext) { found(hp->hnew, hp->hpt, hp->hstr); if (hp->hnew) { fseek(mesgwrit, hp->hpt, 0); ignore(fwrite(hp->hstr, strlen(hp->hstr) + 1, 1, mesgwrit)); if (ferror(mesgwrit)) err(4, "%s", strings); } } if (fclose(mesgwrit) == EOF) err(4, "%s", strings); } static void found(int new, off_t off, char *str) { if (vflg == 0) return; if (!new) fprintf(stderr, "found at %d:", (int) off); else fprintf(stderr, "new at %d:", (int) off); prstr(str); fprintf(stderr, "\n"); } static void prstr(char *cp) { int c; while ((c = (*cp++ & 0377))) if (c < ' ') fprintf(stderr, "^%c", c + '`'); else if (c == 0177) fprintf(stderr, "^?"); else if (c > 0200) fprintf(stderr, "\\%03o", c); else fprintf(stderr, "%c", c); } static void xsdotc(void) { FILE *strf = fopen(strings, "r"); FILE *xdotcf; if (strf == NULL) err(5, "%s", strings); xdotcf = fopen("xs.c", "w"); if (xdotcf == NULL) err(6, "xs.c"); fprintf(xdotcf, "char\txstr[] = {\n"); for (;;) { int i, c; for (i = 0; i < 8; i++) { c = getc(strf); if (ferror(strf)) { warn("%s", strings); onintr(0); } if (feof(strf)) { fprintf(xdotcf, "\n"); goto out; } fprintf(xdotcf, "0x%02x,", c); } fprintf(xdotcf, "\n"); } out: fprintf(xdotcf, "};\n"); ignore(fclose(xdotcf)); ignore(fclose(strf)); } static char lastchr(char *cp) { while (cp[0] && cp[1]) cp++; return (*cp); } static int istail(char *str, char *of) { int d = strlen(of) - strlen(str); if (d < 0 || strcmp(&of[d], str) != 0) return (-1); return (d); } static void onintr(int dummy __unused) { ignore(signal(SIGINT, SIG_IGN)); if (strings[0] == '/') ignore(unlink(strings)); ignore(unlink("x.c")); ignore(unlink("xs.c")); exit(7); } diff --git a/usr.bin/ypcat/ypcat.c b/usr.bin/ypcat/ypcat.c index 3d927ba0e839..0b3b1c9879c8 100644 --- a/usr.bin/ypcat/ypcat.c +++ b/usr.bin/ypcat/ypcat.c @@ -1,144 +1,141 @@ /* $OpenBSD: ypcat.c,v 1.16 2015/02/08 23:40:35 deraadt Exp $ */ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 1992, 1993, 1996 Theo de Raadt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include static const struct ypalias { char *alias, *name; } ypaliases[] = { { "passwd", "passwd.byname" }, { "master.passwd", "master.passwd.byname" }, { "shadow", "shadow.byname" }, { "group", "group.byname" }, { "networks", "networks.byaddr" }, { "hosts", "hosts.byaddr" }, { "protocols", "protocols.bynumber" }, { "services", "services.byname" }, { "aliases", "mail.aliases" }, { "ethers", "ethers.byname" }, }; static int key; static void usage(void) { fprintf(stderr, "%s\n%s\n", "usage: ypcat [-kt] [-d domainname] mapname", " ypcat -x"); exit(1); } static int printit(u_long instatus, char *inkey, int inkeylen, char *inval, int invallen, void *indata) { if (instatus != YP_TRUE) return (instatus); if (key) printf("%*.*s ", inkeylen, inkeylen, inkey); printf("%*.*s\n", invallen, invallen, inval); return (0); } int main(int argc, char *argv[]) { char *domain = NULL, *inmap; struct ypall_callback ypcb; int c, notrans, r; u_int i; notrans = key = 0; while ((c = getopt(argc, argv, "xd:kt")) != -1) switch (c) { case 'x': for (i = 0; i < nitems(ypaliases); i++) printf("Use \"%s\" for \"%s\"\n", ypaliases[i].alias, ypaliases[i].name); exit(0); case 'd': domain = optarg; break; case 't': notrans = 1; break; case 'k': key = 1; break; default: usage(); } if (optind + 1 != argc) usage(); if (domain == NULL) yp_get_default_domain(&domain); inmap = argv[optind]; if (notrans == 0) { for (i = 0; i < nitems(ypaliases); i++) if (strcmp(inmap, ypaliases[i].alias) == 0) inmap = ypaliases[i].name; } ypcb.foreach = printit; ypcb.data = NULL; r = yp_all(domain, inmap, &ypcb); switch (r) { case 0: break; case YPERR_YPBIND: errx(1, "not running ypbind"); default: errx(1, "no such map %s. Reason: %s", inmap, yperr_string(r)); } exit(0); } diff --git a/usr.bin/ypmatch/ypmatch.c b/usr.bin/ypmatch/ypmatch.c index a110abaeafe5..24af4b8c8993 100644 --- a/usr.bin/ypmatch/ypmatch.c +++ b/usr.bin/ypmatch/ypmatch.c @@ -1,142 +1,139 @@ /* $OpenBSD: ypmatch.c,v 1.16 2015/02/08 23:40:35 deraadt Exp $ */ /* $NetBSD: ypmatch.c,v 1.8 1996/05/07 01:24:52 jtc Exp $ */ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 1992, 1993, 1996 Theo de Raadt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - -__FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include static const struct ypalias { char *alias, *name; } ypaliases[] = { { "passwd", "passwd.byname" }, { "master.passwd", "master.passwd.byname" }, { "shadow", "shadow.byname" }, { "group", "group.byname" }, { "networks", "networks.byaddr" }, { "hosts", "hosts.byname" }, { "protocols", "protocols.bynumber" }, { "services", "services.byname" }, { "aliases", "mail.aliases" }, { "ethers", "ethers.byname" }, }; static void usage(void) { fprintf(stderr, "%s\n%s\n", "usage: ypmatch [-kt] [-d domainname] key ... mapname", " ypmatch -x"); exit(1); } int main(int argc, char *argv[]) { char *domainname, *inkey, *inmap, *outbuf; int outbuflen, key, notrans, rval; int c, r; u_int i; domainname = NULL; notrans = key = 0; while ((c = getopt(argc, argv, "xd:kt")) != -1) switch (c) { case 'x': for (i = 0; i < nitems(ypaliases); i++) printf("Use \"%s\" for \"%s\"\n", ypaliases[i].alias, ypaliases[i].name); exit(0); case 'd': domainname = optarg; break; case 't': notrans = 1; break; case 'k': key = 1; break; default: usage(); } if (argc - optind < 2) usage(); if (domainname == NULL) yp_get_default_domain(&domainname); inmap = argv[argc-1]; if (notrans == 0) { for (i = 0; i < nitems(ypaliases); i++) if (strcmp(inmap, ypaliases[i].alias) == 0) inmap = ypaliases[i].name; } rval = 0; for (; optind < argc - 1; optind++) { inkey = argv[optind]; r = yp_match(domainname, inmap, inkey, strlen(inkey), &outbuf, &outbuflen); switch (r) { case 0: if (key) printf("%s: ", inkey); printf("%*.*s\n", outbuflen, outbuflen, outbuf); break; case YPERR_YPBIND: errx(1, "not running ypbind"); default: errx(1, "can't match key %s in map %s. reason: %s", inkey, inmap, yperr_string(r)); rval = 1; break; } } exit(rval); }