diff --git a/usr.bin/script/script.c b/usr.bin/script/script.c index 1d3588c26d8b..72e639e413dd 100644 --- a/usr.bin/script/script.c +++ b/usr.bin/script/script.c @@ -1,615 +1,615 @@ /* * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2010, 2012 David E. O'Brien * 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$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1992, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)script.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 #include #define DEF_BUF 65536 struct stamp { uint64_t scr_len; /* amount of data */ uint64_t scr_sec; /* time it arrived in seconds... */ uint32_t scr_usec; /* ...and microseconds */ uint32_t scr_direction; /* 'i', 'o', etc (also indicates endianness) */ }; struct buf_elm { TAILQ_ENTRY(buf_elm) link; size_t rpos; size_t len; char ibuf[]; }; static FILE *fscript; static int master, slave; static int child; static const char *fname; static char *fmfname; static int fflg, qflg, ttyflg; static int usesleep, rawout, showexit; static TAILQ_HEAD(, buf_elm) obuf_list = TAILQ_HEAD_INITIALIZER(obuf_list); static struct termios tt; #ifndef TSTAMP_FMT /* useful for tool and human reading */ # define TSTAMP_FMT "%n@ %s [%Y-%m-%d %T]%n" #endif static const char *tstamp_fmt = TSTAMP_FMT; static int tflg; static void done(int) __dead2; static void doshell(char **); static void finish(void); static void record(FILE *, char *, size_t, int); static void consume(FILE *, off_t, char *, int); static void playback(FILE *) __dead2; -static void usage(void); +static void usage(void) __dead2; int main(int argc, char *argv[]) { struct termios rtt, stt; struct winsize win; struct timeval tv, *tvp; time_t tvec, start; char obuf[BUFSIZ]; char ibuf[BUFSIZ]; fd_set rfd, wfd; struct buf_elm *be; ssize_t cc; int aflg, Fflg, kflg, pflg, ch, k, n, fcm; int flushtime, readstdin; int fm_fd, fm_log; aflg = Fflg = kflg = pflg = 0; usesleep = 1; rawout = 0; flushtime = 30; fm_fd = -1; /* Shut up stupid "may be used uninitialized" GCC warning. (not needed w/clang) */ showexit = 0; while ((ch = getopt(argc, argv, "adeFfkpqrT:t:")) != -1) switch(ch) { case 'a': aflg = 1; break; case 'd': usesleep = 0; break; case 'e': /* Default behavior, accepted for linux compat */ break; case 'F': Fflg = 1; break; case 'f': fflg = 1; break; case 'k': kflg = 1; break; case 'p': pflg = 1; break; case 'q': qflg = 1; break; case 'r': rawout = 1; break; case 't': flushtime = atoi(optarg); if (flushtime < 0) err(1, "invalid flush time %d", flushtime); break; case 'T': tflg = pflg = 1; if (strchr(optarg, '%')) tstamp_fmt = optarg; break; case '?': default: usage(); } argc -= optind; argv += optind; if (argc > 0) { fname = argv[0]; argv++; argc--; } else fname = "typescript"; if ((fscript = fopen(fname, pflg ? "r" : aflg ? "a" : "w")) == NULL) err(1, "%s", fname); if (fflg) { asprintf(&fmfname, "%s.filemon", fname); if (!fmfname) err(1, "%s.filemon", fname); if ((fm_fd = open("/dev/filemon", O_RDWR | O_CLOEXEC)) == -1) err(1, "open(\"/dev/filemon\", O_RDWR)"); if ((fm_log = open(fmfname, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1) err(1, "open(%s)", fmfname); if (ioctl(fm_fd, FILEMON_SET_FD, &fm_log) < 0) err(1, "Cannot set filemon log file descriptor"); } if (pflg) playback(fscript); if (tcgetattr(STDIN_FILENO, &tt) == -1 || ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == -1) { if (errno != ENOTTY) /* For debugger. */ err(1, "tcgetattr/ioctl"); if (openpty(&master, &slave, NULL, NULL, NULL) == -1) err(1, "openpty"); } else { if (openpty(&master, &slave, NULL, &tt, &win) == -1) err(1, "openpty"); ttyflg = 1; } fcm = fcntl(master, F_GETFL); if (fcm == -1) err(1, "master F_GETFL"); fcm |= O_NONBLOCK; if (fcntl(master, F_SETFL, fcm) == -1) err(1, "master F_SETFL"); if (rawout) record(fscript, NULL, 0, 's'); if (!qflg) { tvec = time(NULL); (void)printf("Script started, output file is %s\n", fname); if (!rawout) { (void)fprintf(fscript, "Script started on %s", ctime(&tvec)); if (argv[0]) { showexit = 1; fprintf(fscript, "Command: "); for (k = 0 ; argv[k] ; ++k) fprintf(fscript, "%s%s", k ? " " : "", argv[k]); fprintf(fscript, "\n"); } } fflush(fscript); if (fflg) { (void)printf("Filemon started, output file is %s\n", fmfname); } } if (ttyflg) { rtt = tt; cfmakeraw(&rtt); rtt.c_lflag &= ~ECHO; (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt); } child = fork(); if (child < 0) { warn("fork"); done(1); } if (child == 0) { if (fflg) { int pid; pid = getpid(); if (ioctl(fm_fd, FILEMON_SET_PID, &pid) < 0) err(1, "Cannot set filemon PID"); } doshell(argv); } close(slave); start = tvec = time(0); readstdin = 1; for (;;) { FD_ZERO(&rfd); FD_ZERO(&wfd); FD_SET(master, &rfd); if (readstdin) FD_SET(STDIN_FILENO, &rfd); if (!TAILQ_EMPTY(&obuf_list)) FD_SET(master, &wfd); if (!readstdin && ttyflg) { tv.tv_sec = 1; tv.tv_usec = 0; tvp = &tv; readstdin = 1; } else if (flushtime > 0) { tv.tv_sec = flushtime - (tvec - start); tv.tv_usec = 0; tvp = &tv; } else { tvp = NULL; } n = select(master + 1, &rfd, &wfd, NULL, tvp); if (n < 0 && errno != EINTR) break; if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) { cc = read(STDIN_FILENO, ibuf, BUFSIZ); if (cc < 0) break; if (cc == 0) { if (tcgetattr(master, &stt) == 0 && (stt.c_lflag & ICANON) != 0) { (void)write(master, &stt.c_cc[VEOF], 1); } readstdin = 0; } if (cc > 0) { if (rawout) record(fscript, ibuf, cc, 'i'); be = malloc(sizeof(*be) + cc); be->rpos = 0; be->len = cc; memcpy(be->ibuf, ibuf, cc); TAILQ_INSERT_TAIL(&obuf_list, be, link); } } if (n > 0 && FD_ISSET(master, &wfd)) { while ((be = TAILQ_FIRST(&obuf_list)) != NULL) { cc = write(master, be->ibuf + be->rpos, be->len); if (cc == -1) { if (errno == EWOULDBLOCK || errno == EINTR) break; warn("write master"); done(1); } if (cc == 0) break; /* retry later ? */ if (kflg && tcgetattr(master, &stt) >= 0 && ((stt.c_lflag & ECHO) == 0)) { (void)fwrite(be->ibuf + be->rpos, 1, cc, fscript); } be->len -= cc; if (be->len == 0) { TAILQ_REMOVE(&obuf_list, be, link); free(be); } else { be->rpos += cc; } } } if (n > 0 && FD_ISSET(master, &rfd)) { cc = read(master, obuf, sizeof (obuf)); if (cc <= 0) break; (void)write(STDOUT_FILENO, obuf, cc); if (rawout) record(fscript, obuf, cc, 'o'); else (void)fwrite(obuf, 1, cc, fscript); } tvec = time(0); if (tvec - start >= flushtime) { fflush(fscript); start = tvec; } if (Fflg) fflush(fscript); } finish(); done(0); } static void usage(void) { (void)fprintf(stderr, "usage: script [-aeFfkpqr] [-t time] [file [command ...]]\n"); (void)fprintf(stderr, " script -p [-deq] [-T fmt] [file]\n"); exit(1); } static void finish(void) { int e, status; if (waitpid(child, &status, 0) == child) { if (WIFEXITED(status)) e = WEXITSTATUS(status); else if (WIFSIGNALED(status)) e = WTERMSIG(status); else /* can't happen */ e = 1; done(e); } } static void doshell(char **av) { const char *shell; shell = getenv("SHELL"); if (shell == NULL) shell = _PATH_BSHELL; (void)close(master); (void)fclose(fscript); free(fmfname); login_tty(slave); setenv("SCRIPT", fname, 1); if (av[0]) { execvp(av[0], av); warn("%s", av[0]); } else { execl(shell, shell, "-i", (char *)NULL); warn("%s", shell); } exit(1); } static void done(int eno) { time_t tvec; if (ttyflg) (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt); tvec = time(NULL); if (rawout) record(fscript, NULL, 0, 'e'); if (!qflg) { if (!rawout) { if (showexit) (void)fprintf(fscript, "\nCommand exit status:" " %d", eno); (void)fprintf(fscript,"\nScript done on %s", ctime(&tvec)); } (void)printf("\nScript done, output file is %s\n", fname); if (fflg) { (void)printf("Filemon done, output file is %s\n", fmfname); } } (void)fclose(fscript); (void)close(master); exit(eno); } static void record(FILE *fp, char *buf, size_t cc, int direction) { struct iovec iov[2]; struct stamp stamp; struct timeval tv; (void)gettimeofday(&tv, NULL); stamp.scr_len = cc; stamp.scr_sec = tv.tv_sec; stamp.scr_usec = tv.tv_usec; stamp.scr_direction = direction; iov[0].iov_len = sizeof(stamp); iov[0].iov_base = &stamp; iov[1].iov_len = cc; iov[1].iov_base = buf; if (writev(fileno(fp), &iov[0], 2) == -1) err(1, "writev"); } static void consume(FILE *fp, off_t len, char *buf, int reg) { size_t l; if (reg) { if (fseeko(fp, len, SEEK_CUR) == -1) err(1, NULL); } else { while (len > 0) { l = MIN(DEF_BUF, len); if (fread(buf, sizeof(char), l, fp) != l) err(1, "cannot read buffer"); len -= l; } } } #define swapstamp(stamp) do { \ if (stamp.scr_direction > 0xff) { \ stamp.scr_len = bswap64(stamp.scr_len); \ stamp.scr_sec = bswap64(stamp.scr_sec); \ stamp.scr_usec = bswap32(stamp.scr_usec); \ stamp.scr_direction = bswap32(stamp.scr_direction); \ } \ } while (0/*CONSTCOND*/) static void termset(void) { struct termios traw; if (tcgetattr(STDOUT_FILENO, &tt) == -1) { if (errno != ENOTTY) /* For debugger. */ err(1, "tcgetattr"); return; } ttyflg = 1; traw = tt; cfmakeraw(&traw); traw.c_lflag |= ISIG; (void)tcsetattr(STDOUT_FILENO, TCSANOW, &traw); } static void termreset(void) { if (ttyflg) { tcsetattr(STDOUT_FILENO, TCSADRAIN, &tt); ttyflg = 0; } } static void playback(FILE *fp) { struct timespec tsi, tso; struct stamp stamp; struct stat pst; char buf[DEF_BUF]; off_t nread, save_len; size_t l; time_t tclock; time_t lclock; int reg; if (fstat(fileno(fp), &pst) == -1) err(1, "fstat failed"); reg = S_ISREG(pst.st_mode); lclock = 0; for (nread = 0; !reg || nread < pst.st_size; nread += save_len) { if (fread(&stamp, sizeof(stamp), 1, fp) != 1) { if (reg) err(1, "reading playback header"); else break; } swapstamp(stamp); save_len = sizeof(stamp); if (reg && stamp.scr_len > (uint64_t)(pst.st_size - save_len) - nread) errx(1, "invalid stamp"); save_len += stamp.scr_len; tclock = stamp.scr_sec; tso.tv_sec = stamp.scr_sec; tso.tv_nsec = stamp.scr_usec * 1000; if (nread == 0) tsi = tso; switch (stamp.scr_direction) { case 's': if (!qflg) (void)printf("Script started on %s", ctime(&tclock)); tsi = tso; (void)consume(fp, stamp.scr_len, buf, reg); termset(); atexit(termreset); break; case 'e': termreset(); if (!qflg) (void)printf("\nScript done on %s", ctime(&tclock)); (void)consume(fp, stamp.scr_len, buf, reg); break; case 'i': /* throw input away */ (void)consume(fp, stamp.scr_len, buf, reg); break; case 'o': if (tflg) { if (stamp.scr_len == 0) continue; if (tclock - lclock > 0) { l = strftime(buf, sizeof buf, tstamp_fmt, localtime(&tclock)); (void)write(STDOUT_FILENO, buf, l); } lclock = tclock; } else { tsi.tv_sec = tso.tv_sec - tsi.tv_sec; tsi.tv_nsec = tso.tv_nsec - tsi.tv_nsec; if (tsi.tv_nsec < 0) { tsi.tv_sec -= 1; tsi.tv_nsec += 1000000000; } if (usesleep) (void)nanosleep(&tsi, NULL); tsi = tso; } while (stamp.scr_len > 0) { l = MIN(DEF_BUF, stamp.scr_len); if (fread(buf, sizeof(char), l, fp) != l) err(1, "cannot read buffer"); (void)write(STDOUT_FILENO, buf, l); stamp.scr_len -= l; } break; default: errx(1, "invalid direction"); } } (void)fclose(fp); exit(0); } diff --git a/usr.bin/sed/main.c b/usr.bin/sed/main.c index 44a274eb90e6..4139b69da2f8 100644 --- a/usr.bin/sed/main.c +++ b/usr.bin/sed/main.c @@ -1,557 +1,557 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2013 Johann 'Myrkraverk' Oskarsson. * Copyright (c) 1992 Diomidis Spinellis. * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Diomidis Spinellis of Imperial College, University of London. * * 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) 1992, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/3/94"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "defs.h" #include "extern.h" /* * Linked list of units (strings and files) to be compiled */ struct s_compunit { struct s_compunit *next; enum e_cut {CU_FILE, CU_STRING} type; char *s; /* Pointer to string or fname */ }; /* * Linked list pointer to compilation units and pointer to current * next pointer. */ static struct s_compunit *script, **cu_nextp = &script; /* * Linked list of files to be processed */ struct s_flist { char *fname; struct s_flist *next; }; /* * Linked list pointer to files and pointer to current * next pointer. */ static struct s_flist *files, **fl_nextp = &files; FILE *infile; /* Current input file */ FILE *outfile; /* Current output file */ int aflag, eflag, nflag; int rflags = 0; int quit = 0; static int rval; /* Exit status */ static int ispan; /* Whether inplace editing spans across files */ /* * Current file and line number; line numbers restart across compilation * units, but span across input files. The latter is optional if editing * in place. */ const char *fname; /* File name. */ const char *outfname; /* Output file name */ static char oldfname[PATH_MAX]; /* Old file name (for in-place editing) */ static char tmpfname[PATH_MAX]; /* Temporary file name (for in-place editing) */ const char *inplace; /* Inplace edit file extension. */ u_long linenum; static void add_compunit(enum e_cut, char *); static void add_file(char *); -static void usage(void); +static void usage(void) __dead2; int main(int argc, char *argv[]) { int c, fflag, fflagstdin; char *temp_arg; (void) setlocale(LC_ALL, ""); fflag = 0; fflagstdin = 0; inplace = NULL; while ((c = getopt(argc, argv, "EI:ae:f:i:lnru")) != -1) switch (c) { case 'r': /* Gnu sed compat */ case 'E': rflags = REG_EXTENDED; break; case 'I': inplace = optarg; ispan = 1; /* span across input files */ break; case 'a': aflag = 1; break; case 'e': eflag = 1; if ((temp_arg = malloc(strlen(optarg) + 2)) == NULL) err(1, "malloc"); strcpy(temp_arg, optarg); strcat(temp_arg, "\n"); add_compunit(CU_STRING, temp_arg); break; case 'f': fflag = 1; if (strcmp(optarg, "-") == 0) fflagstdin = 1; add_compunit(CU_FILE, optarg); break; case 'i': inplace = optarg; ispan = 0; /* don't span across input files */ break; case 'l': if(setvbuf(stdout, NULL, _IOLBF, 0) != 0) warnx("setting line buffered output failed"); break; case 'n': nflag = 1; break; case 'u': if(setvbuf(stdout, NULL, _IONBF, 0) != 0) warnx("setting unbuffered output failed"); break; default: case '?': usage(); } argc -= optind; argv += optind; /* First usage case; script is the first arg */ if (!eflag && !fflag && *argv) { add_compunit(CU_STRING, *argv); argv++; } compile(); /* Continue with first and start second usage */ if (*argv) for (; *argv; argv++) add_file(*argv); else if (fflagstdin) exit(rval); else add_file(NULL); process(); cfclose(prog, NULL); if (fclose(stdout)) err(1, "stdout"); exit(rval); } static void usage(void) { (void)fprintf(stderr, "usage: %s script [-Ealnru] [-i extension] [file ...]\n" "\t%s [-Ealnu] [-i extension] [-e script] ... [-f script_file]" " ... [file ...]\n", getprogname(), getprogname()); exit(1); } /* * Like fgets, but go through the chain of compilation units chaining them * together. Empty strings and files are ignored. */ char * cu_fgets(char *buf, int n, int *more) { static enum {ST_EOF, ST_FILE, ST_STRING} state = ST_EOF; static FILE *f; /* Current open file */ static char *s; /* Current pointer inside string */ static char string_ident[30]; char *p; again: switch (state) { case ST_EOF: if (script == NULL) { if (more != NULL) *more = 0; return (NULL); } linenum = 0; switch (script->type) { case CU_FILE: if (strcmp(script->s, "-") == 0) { f = stdin; fname = "stdin"; } else { if ((f = fopen(script->s, "r")) == NULL) err(1, "%s", script->s); fname = script->s; } state = ST_FILE; goto again; case CU_STRING: if (((size_t)snprintf(string_ident, sizeof(string_ident), "\"%s\"", script->s)) >= sizeof(string_ident) - 1) (void)strcpy(string_ident + sizeof(string_ident) - 6, " ...\""); fname = string_ident; s = script->s; state = ST_STRING; goto again; default: __unreachable(); } case ST_FILE: if ((p = fgets(buf, n, f)) != NULL) { linenum++; if (linenum == 1 && buf[0] == '#' && buf[1] == 'n') nflag = 1; if (more != NULL) *more = !feof(f); return (p); } script = script->next; (void)fclose(f); state = ST_EOF; goto again; case ST_STRING: if (linenum == 0 && s[0] == '#' && s[1] == 'n') nflag = 1; p = buf; for (;;) { if (n-- <= 1) { *p = '\0'; linenum++; if (more != NULL) *more = 1; return (buf); } switch (*s) { case '\0': state = ST_EOF; if (s == script->s) { script = script->next; goto again; } else { script = script->next; *p = '\0'; linenum++; if (more != NULL) *more = 0; return (buf); } case '\n': *p++ = '\n'; *p = '\0'; s++; linenum++; if (more != NULL) *more = 0; return (buf); default: *p++ = *s++; } } } /* NOTREACHED */ return (NULL); } /* * Like fgets, but go through the list of files chaining them together. * Set len to the length of the line. */ int mf_fgets(SPACE *sp, enum e_spflag spflag) { struct stat sb; ssize_t len; char *dirbuf, *basebuf; static char *p = NULL; static size_t plen = 0; int c; static int firstfile; if (infile == NULL) { /* stdin? */ if (files->fname == NULL) { if (inplace != NULL) errx(1, "-I or -i may not be used with stdin"); infile = stdin; fname = "stdin"; outfile = stdout; outfname = "stdout"; } firstfile = 1; } for (;;) { if (infile != NULL && (c = getc(infile)) != EOF && !quit) { (void)ungetc(c, infile); break; } /* If we are here then either eof or no files are open yet */ if (infile == stdin) { sp->len = 0; return (0); } if (infile != NULL) { fclose(infile); if (*oldfname != '\0') { /* if there was a backup file, remove it */ unlink(oldfname); /* * Backup the original. Note that hard links * are not supported on all filesystems. */ if ((link(fname, oldfname) != 0) && (rename(fname, oldfname) != 0)) { warn("rename()"); if (*tmpfname) unlink(tmpfname); exit(1); } *oldfname = '\0'; } if (*tmpfname != '\0') { if (outfile != NULL && outfile != stdout) if (fclose(outfile) != 0) { warn("fclose()"); unlink(tmpfname); exit(1); } outfile = NULL; if (rename(tmpfname, fname) != 0) { /* this should not happen really! */ warn("rename()"); unlink(tmpfname); exit(1); } *tmpfname = '\0'; } outfname = NULL; } if (firstfile == 0) files = files->next; else firstfile = 0; if (files == NULL) { sp->len = 0; return (0); } fname = files->fname; if (inplace != NULL) { if (lstat(fname, &sb) != 0) err(1, "%s", fname); if (!S_ISREG(sb.st_mode)) errx(1, "%s: %s %s", fname, "in-place editing only", "works for regular files"); if (*inplace != '\0') { strlcpy(oldfname, fname, sizeof(oldfname)); len = strlcat(oldfname, inplace, sizeof(oldfname)); if (len > (ssize_t)sizeof(oldfname)) errx(1, "%s: name too long", fname); } if ((dirbuf = strdup(fname)) == NULL || (basebuf = strdup(fname)) == NULL) err(1, "strdup"); len = snprintf(tmpfname, sizeof(tmpfname), "%s/.!%ld!%s", dirname(dirbuf), (long)getpid(), basename(basebuf)); free(dirbuf); free(basebuf); if (len >= (ssize_t)sizeof(tmpfname)) errx(1, "%s: name too long", fname); unlink(tmpfname); if (outfile != NULL && outfile != stdout) fclose(outfile); if ((outfile = fopen(tmpfname, "w")) == NULL) err(1, "%s", fname); fchown(fileno(outfile), sb.st_uid, sb.st_gid); fchmod(fileno(outfile), sb.st_mode & ALLPERMS); outfname = tmpfname; if (!ispan) { linenum = 0; resetstate(); } } else { outfile = stdout; outfname = "stdout"; } if ((infile = fopen(fname, "r")) == NULL) { warn("%s", fname); rval = 1; continue; } } /* * We are here only when infile is open and we still have something * to read from it. * * Use getline() so that we can handle essentially infinite input * data. The p and plen are static so each invocation gives * getline() the same buffer which is expanded as needed. */ len = getline(&p, &plen, infile); if (len == -1) err(1, "%s", fname); if (len != 0 && p[len - 1] == '\n') { sp->append_newline = 1; len--; } else if (!lastline()) { sp->append_newline = 1; } else { sp->append_newline = 0; } cspace(sp, p, len, spflag); linenum++; return (1); } /* * Add a compilation unit to the linked list */ static void add_compunit(enum e_cut type, char *s) { struct s_compunit *cu; if ((cu = malloc(sizeof(struct s_compunit))) == NULL) err(1, "malloc"); cu->type = type; cu->s = s; cu->next = NULL; *cu_nextp = cu; cu_nextp = &cu->next; } /* * Add a file to the linked list */ static void add_file(char *s) { struct s_flist *fp; if ((fp = malloc(sizeof(struct s_flist))) == NULL) err(1, "malloc"); fp->next = NULL; *fl_nextp = fp; fp->fname = s; fl_nextp = &fp->next; } static int next_files_have_lines(void) { struct s_flist *file; FILE *file_fd; int ch; file = files; while ((file = file->next) != NULL) { if ((file_fd = fopen(file->fname, "r")) == NULL) continue; if ((ch = getc(file_fd)) != EOF) { /* * This next file has content, therefore current * file doesn't contains the last line. */ ungetc(ch, file_fd); fclose(file_fd); return (1); } fclose(file_fd); } return (0); } int lastline(void) { int ch; if (feof(infile)) { return !( (inplace == NULL || ispan) && next_files_have_lines()); } if ((ch = getc(infile)) == EOF) { return !( (inplace == NULL || ispan) && next_files_have_lines()); } ungetc(ch, infile); return (0); } diff --git a/usr.bin/showmount/showmount.c b/usr.bin/showmount/showmount.c index fbd1c9bbbe3c..d2b9f46792ba 100644 --- a/usr.bin/showmount/showmount.c +++ b/usr.bin/showmount/showmount.c @@ -1,428 +1,428 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1989, 1993, 1995 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Rick Macklem at The University of Guelph. * * 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. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1989, 1993, 1995\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)showmount.c 8.3 (Berkeley) 3/29/95"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Constant defs */ #define ALL 1 #define DIRS 2 #define DODUMP 0x1 #define DOEXPORTS 0x2 #define DOPARSABLEEXPORTS 0x4 struct mountlist { struct mountlist *ml_left; struct mountlist *ml_right; char ml_host[MNTNAMLEN+1]; char ml_dirp[MNTPATHLEN+1]; }; struct grouplist { struct grouplist *gr_next; char gr_name[MNTNAMLEN+1]; }; struct exportslist { struct exportslist *ex_next; struct grouplist *ex_groups; char ex_dirp[MNTPATHLEN+1]; }; static struct mountlist *mntdump; static struct exportslist *exportslist; static int type = 0; void print_dump(struct mountlist *); -static void usage(void); +static void usage(void) __dead2; int xdr_mntdump(XDR *, struct mountlist **); int xdr_exportslist(XDR *, struct exportslist **); int tcp_callrpc(const char *host, int prognum, int versnum, int procnum, xdrproc_t inproc, char *in, xdrproc_t outproc, char *out); static const struct option long_opts[] = { { "all", no_argument, NULL, 'a' }, { "directories", no_argument, NULL, 'd' }, { "exports-script", no_argument, NULL, 'E' }, { "exports", no_argument, NULL, 'e' }, { NULL, 0, NULL, 0 }, }; /* * This command queries the NFS mount daemon for it's mount list and/or * it's exports list and prints them out. * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A" * and the "Network File System Protocol XXX.." * for detailed information on the protocol. */ int main(int argc, char **argv) { char strvised[MNTPATHLEN * 4 + 1]; register struct exportslist *exp; register struct grouplist *grp; register int rpcs = 0, mntvers = 3; const char *host; int ch, estat, nbytes; while ((ch = getopt_long(argc, argv, "+adEe13", long_opts, NULL)) != -1) switch (ch) { case 'a': if (type == 0) { type = ALL; rpcs |= DODUMP; } else usage(); break; case 'd': if (type == 0) { type = DIRS; rpcs |= DODUMP; } else usage(); break; case 'E': rpcs |= DOPARSABLEEXPORTS; break; case 'e': rpcs |= DOEXPORTS; break; case '1': mntvers = 1; break; case '3': mntvers = 3; break; case '?': default: usage(); } argc -= optind; argv += optind; if ((rpcs & DOPARSABLEEXPORTS) != 0) { if ((rpcs & DOEXPORTS) != 0) errx(1, "-E cannot be used with -e"); if ((rpcs & DODUMP) != 0) errx(1, "-E cannot be used with -a or -d"); } if (argc > 0) host = *argv; else host = "localhost"; if (rpcs == 0) rpcs = DODUMP; if (rpcs & DODUMP) if ((estat = tcp_callrpc(host, MOUNTPROG, mntvers, MOUNTPROC_DUMP, (xdrproc_t)xdr_void, (char *)0, (xdrproc_t)xdr_mntdump, (char *)&mntdump)) != 0) { clnt_perrno(estat); errx(1, "can't do mountdump rpc"); } if (rpcs & (DOEXPORTS | DOPARSABLEEXPORTS)) if ((estat = tcp_callrpc(host, MOUNTPROG, mntvers, MOUNTPROC_EXPORT, (xdrproc_t)xdr_void, (char *)0, (xdrproc_t)xdr_exportslist, (char *)&exportslist)) != 0) { clnt_perrno(estat); errx(1, "can't do exports rpc"); } /* Now just print out the results */ if (rpcs & DODUMP) { switch (type) { case ALL: printf("All mount points on %s:\n", host); break; case DIRS: printf("Directories on %s:\n", host); break; default: printf("Hosts on %s:\n", host); break; } print_dump(mntdump); } if (rpcs & DOEXPORTS) { printf("Exports list on %s:\n", host); exp = exportslist; while (exp) { printf("%-34s ", exp->ex_dirp); grp = exp->ex_groups; if (grp == NULL) { printf("Everyone\n"); } else { while (grp) { printf("%s ", grp->gr_name); grp = grp->gr_next; } printf("\n"); } exp = exp->ex_next; } } if (rpcs & DOPARSABLEEXPORTS) { exp = exportslist; while (exp) { nbytes = strsnvis(strvised, sizeof(strvised), exp->ex_dirp, VIS_GLOB | VIS_NL, "\"'$"); if (nbytes == -1) err(1, "strsnvis"); printf("%s\n", strvised); exp = exp->ex_next; } } exit(0); } /* * tcp_callrpc has the same interface as callrpc, but tries to * use tcp as transport method in order to handle large replies. */ int tcp_callrpc(const char *host, int prognum, int versnum, int procnum, xdrproc_t inproc, char *in, xdrproc_t outproc, char *out) { CLIENT *client; struct timeval timeout; int rval; if ((client = clnt_create(host, prognum, versnum, "tcp")) == NULL && (client = clnt_create(host, prognum, versnum, "udp")) == NULL) return ((int) rpc_createerr.cf_stat); timeout.tv_sec = 25; timeout.tv_usec = 0; rval = (int) clnt_call(client, procnum, inproc, in, outproc, out, timeout); clnt_destroy(client); return rval; } /* * Xdr routine for retrieving the mount dump list */ int xdr_mntdump(XDR *xdrsp, struct mountlist **mlp) { register struct mountlist *mp; register struct mountlist *tp; register struct mountlist **otp; int val, val2; int bool; char *strp; *mlp = (struct mountlist *)0; if (!xdr_bool(xdrsp, &bool)) return (0); while (bool) { mp = (struct mountlist *)malloc(sizeof(struct mountlist)); if (mp == NULL) return (0); mp->ml_left = mp->ml_right = (struct mountlist *)0; strp = mp->ml_host; if (!xdr_string(xdrsp, &strp, MNTNAMLEN)) { free(mp); return (0); } strp = mp->ml_dirp; if (!xdr_string(xdrsp, &strp, MNTPATHLEN)) { free(mp); return (0); } /* * Build a binary tree on sorted order of either host or dirp. * Drop any duplications. */ if (*mlp == NULL) { *mlp = mp; } else { tp = *mlp; while (tp) { val = strcmp(mp->ml_host, tp->ml_host); val2 = strcmp(mp->ml_dirp, tp->ml_dirp); switch (type) { case ALL: if (val == 0) { if (val2 == 0) { free((caddr_t)mp); goto next; } val = val2; } break; case DIRS: if (val2 == 0) { free((caddr_t)mp); goto next; } val = val2; break; default: if (val == 0) { free((caddr_t)mp); goto next; } break; } if (val < 0) { otp = &tp->ml_left; tp = tp->ml_left; } else { otp = &tp->ml_right; tp = tp->ml_right; } } *otp = mp; } next: if (!xdr_bool(xdrsp, &bool)) return (0); } return (1); } /* * Xdr routine to retrieve exports list */ int xdr_exportslist(XDR *xdrsp, struct exportslist **exp) { register struct exportslist *ep; register struct grouplist *gp; int bool, grpbool; char *strp; *exp = (struct exportslist *)0; if (!xdr_bool(xdrsp, &bool)) return (0); while (bool) { ep = (struct exportslist *)malloc(sizeof(struct exportslist)); if (ep == NULL) return (0); ep->ex_groups = (struct grouplist *)0; strp = ep->ex_dirp; if (!xdr_string(xdrsp, &strp, MNTPATHLEN)) return (0); if (!xdr_bool(xdrsp, &grpbool)) return (0); while (grpbool) { gp = (struct grouplist *)malloc(sizeof(struct grouplist)); if (gp == NULL) return (0); strp = gp->gr_name; if (!xdr_string(xdrsp, &strp, MNTNAMLEN)) return (0); gp->gr_next = ep->ex_groups; ep->ex_groups = gp; if (!xdr_bool(xdrsp, &grpbool)) return (0); } ep->ex_next = *exp; *exp = ep; if (!xdr_bool(xdrsp, &bool)) return (0); } return (1); } static void usage(void) { fprintf(stderr, "usage: showmount [-a | -d] [-e3] [host]\n"); exit(1); } /* * Print the binary tree in inorder so that output is sorted. */ void print_dump(struct mountlist *mp) { if (mp == NULL) return; if (mp->ml_left) print_dump(mp->ml_left); switch (type) { case ALL: printf("%s:%s\n", mp->ml_host, mp->ml_dirp); break; case DIRS: printf("%s\n", mp->ml_dirp); break; default: printf("%s\n", mp->ml_host); break; } if (mp->ml_right) print_dump(mp->ml_right); } diff --git a/usr.bin/split/split.c b/usr.bin/split/split.c index 91710899a9e9..cee3980ea291 100644 --- a/usr.bin/split/split.c +++ b/usr.bin/split/split.c @@ -1,446 +1,446 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1987, 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) 1987, 1993, 1994\n\ The Regents of the University of California. All rights reserved.\n"; #endif #ifndef lint static const char sccsid[] = "@(#)split.c 8.2 (Berkeley) 4/16/94"; #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEFLINE 1000 /* Default num lines per file. */ static off_t bytecnt; /* Byte count to split on. */ static off_t chunks = 0; /* Chunks count to split into. */ static bool clobber = true; /* Whether to overwrite existing output files. */ static long numlines; /* Line count to split on. */ static int file_open; /* If a file open. */ static int ifd = -1, ofd = -1; /* Input/output file descriptors. */ static char fname[MAXPATHLEN]; /* File name prefix. */ static regex_t rgx; static int pflag; static bool dflag; static long sufflen = 2; /* File name suffix length. */ static int autosfx = 1; /* Whether to auto-extend the suffix length. */ static void newfile(void); static void split1(void); static void split2(void); static void split3(void); -static void usage(void); +static void usage(void) __dead2; int main(int argc, char **argv) { int ch; int error; char *ep, *p; setlocale(LC_ALL, ""); dflag = false; while ((ch = getopt(argc, argv, "0123456789a:b:cdl:n:p:")) != -1) switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': /* * Undocumented kludge: split was originally designed * to take a number after a dash. */ if (numlines == 0) { p = argv[optind - 1]; if (p[0] == '-' && p[1] == ch && !p[2]) numlines = strtol(++p, &ep, 10); else numlines = strtol(argv[optind] + 1, &ep, 10); if (numlines <= 0 || *ep) errx(EX_USAGE, "%s: illegal line count", optarg); } break; case 'a': /* Suffix length */ if ((sufflen = strtol(optarg, &ep, 10)) <= 0 || *ep) errx(EX_USAGE, "%s: illegal suffix length", optarg); autosfx = 0; break; case 'b': /* Byte count. */ errno = 0; error = expand_number(optarg, &bytecnt); if (error == -1) errx(EX_USAGE, "%s: offset too large", optarg); break; case 'c': /* Continue, don't overwrite output files. */ clobber = false; break; case 'd': /* Decimal suffix */ dflag = true; break; case 'l': /* Line count. */ if (numlines != 0) usage(); if ((numlines = strtol(optarg, &ep, 10)) <= 0 || *ep) errx(EX_USAGE, "%s: illegal line count", optarg); break; case 'n': /* Chunks. */ if (!isdigit((unsigned char)optarg[0]) || (chunks = (size_t)strtoul(optarg, &ep, 10)) == 0 || *ep != '\0') { errx(EX_USAGE, "%s: illegal number of chunks", optarg); } break; case 'p': /* pattern matching. */ if (regcomp(&rgx, optarg, REG_EXTENDED|REG_NOSUB) != 0) errx(EX_USAGE, "%s: illegal regexp", optarg); pflag = 1; break; default: usage(); } argv += optind; argc -= optind; if (*argv != NULL) { /* Input file. */ if (strcmp(*argv, "-") == 0) ifd = STDIN_FILENO; else if ((ifd = open(*argv, O_RDONLY, 0)) < 0) err(EX_NOINPUT, "%s", *argv); ++argv; } if (*argv != NULL) /* File name prefix. */ if (strlcpy(fname, *argv++, sizeof(fname)) >= sizeof(fname)) errx(EX_USAGE, "file name prefix is too long"); if (*argv != NULL) usage(); if (strlen(fname) + (unsigned long)sufflen >= sizeof(fname)) errx(EX_USAGE, "suffix is too long"); if (pflag && (numlines != 0 || bytecnt != 0 || chunks != 0)) usage(); if (numlines == 0) numlines = DEFLINE; else if (bytecnt != 0 || chunks != 0) usage(); if (bytecnt && chunks) usage(); if (ifd == -1) /* Stdin by default. */ ifd = 0; if (bytecnt) { split1(); exit (0); } else if (chunks) { split3(); exit (0); } split2(); if (pflag) regfree(&rgx); exit(0); } /* * split1 -- * Split the input by bytes. */ static void split1(void) { static char bfr[MAXBSIZE]; off_t bcnt; char *C; ssize_t dist, len; int nfiles; nfiles = 0; for (bcnt = 0;;) switch ((len = read(ifd, bfr, sizeof(bfr)))) { case 0: exit(0); case -1: err(EX_IOERR, "read"); /* NOTREACHED */ default: if (!file_open) { if (!chunks || (nfiles < chunks)) { newfile(); nfiles++; } } if (bcnt + len >= bytecnt) { dist = bytecnt - bcnt; if (write(ofd, bfr, dist) != dist) err(EX_IOERR, "write"); len -= dist; for (C = bfr + dist; len >= bytecnt; len -= bytecnt, C += bytecnt) { if (!chunks || (nfiles < chunks)) { newfile(); nfiles++; } if (write(ofd, C, bytecnt) != bytecnt) err(EX_IOERR, "write"); } if (len != 0) { if (!chunks || (nfiles < chunks)) { newfile(); nfiles++; } if (write(ofd, C, len) != len) err(EX_IOERR, "write"); } else file_open = 0; bcnt = len; } else { bcnt += len; if (write(ofd, bfr, len) != len) err(EX_IOERR, "write"); } } } /* * split2 -- * Split the input by lines. */ static void split2(void) { char *buf; size_t bufsize; ssize_t len; long lcnt = 0; FILE *infp; buf = NULL; bufsize = 0; /* Stick a stream on top of input file descriptor */ if ((infp = fdopen(ifd, "r")) == NULL) err(EX_NOINPUT, "fdopen"); /* Process input one line at a time */ while ((errno = 0, len = getline(&buf, &bufsize, infp)) > 0) { /* Check if we need to start a new file */ if (pflag) { regmatch_t pmatch; pmatch.rm_so = 0; pmatch.rm_eo = len - 1; if (regexec(&rgx, buf, 0, &pmatch, REG_STARTEND) == 0) newfile(); } else if (lcnt++ == numlines) { newfile(); lcnt = 1; } /* Open output file if needed */ if (!file_open) newfile(); /* Write out line */ if (write(ofd, buf, len) != len) err(EX_IOERR, "write"); } /* EOF or error? */ if ((len == -1 && errno != 0) || ferror(infp)) err(EX_IOERR, "read"); else exit(0); } /* * split3 -- * Split the input into specified number of chunks */ static void split3(void) { struct stat sb; if (fstat(ifd, &sb) == -1) { err(1, "stat"); /* NOTREACHED */ } if (chunks > sb.st_size) { errx(1, "can't split into more than %d files", (int)sb.st_size); /* NOTREACHED */ } bytecnt = sb.st_size / chunks; split1(); } /* * newfile -- * Open a new output file. */ static void newfile(void) { long i, maxfiles, tfnum; static long fnum; static char *fpnt; char beg, end; int pattlen; int flags = O_WRONLY | O_CREAT | O_TRUNC; if (!clobber) flags |= O_EXCL; if (ofd == -1) { if (fname[0] == '\0') { fname[0] = 'x'; fpnt = fname + 1; } else { fpnt = fname + strlen(fname); } } else if (close(ofd) != 0) err(1, "%s", fname); again: if (dflag) { beg = '0'; end = '9'; } else { beg = 'a'; end = 'z'; } pattlen = end - beg + 1; /* * If '-a' is not specified, then we automatically expand the * suffix length to accomodate splitting all input. We do this * by moving the suffix pointer (fpnt) forward and incrementing * sufflen by one, thereby yielding an additional two characters * and allowing all output files to sort such that 'cat *' yields * the input in order. I.e., the order is '... xyy xyz xzaaa * xzaab ... xzyzy, xzyzz, xzzaaaa, xzzaaab' and so on. */ if (!dflag && autosfx && (fpnt[0] == 'y') && strspn(fpnt+1, "z") == strlen(fpnt+1)) { fpnt = fname + strlen(fname) - sufflen; fpnt[sufflen + 2] = '\0'; fpnt[0] = end; fpnt[1] = beg; /* Basename | Suffix * before: * x | yz * after: * xz | a.. */ fpnt++; sufflen++; /* Reset so we start back at all 'a's in our extended suffix. */ tfnum = 0; fnum = 0; } /* maxfiles = pattlen^sufflen, but don't use libm. */ for (maxfiles = 1, i = 0; i < sufflen; i++) if (LONG_MAX / pattlen < maxfiles) errx(EX_USAGE, "suffix is too long (max %ld)", i); else maxfiles *= pattlen; if (fnum == maxfiles) errx(EX_DATAERR, "too many files"); /* Generate suffix of sufflen letters */ tfnum = fnum; i = sufflen - 1; do { fpnt[i] = tfnum % pattlen + beg; tfnum /= pattlen; } while (i-- > 0); fpnt[sufflen] = '\0'; ++fnum; if ((ofd = open(fname, flags, DEFFILEMODE)) < 0) { if (!clobber && errno == EEXIST) goto again; err(EX_IOERR, "%s", fname); } file_open = 1; } static void usage(void) { (void)fprintf(stderr, "usage: split [-cd] [-l line_count] [-a suffix_length] [file [prefix]]\n" " split [-cd] -b byte_count[K|k|M|m|G|g] [-a suffix_length] [file [prefix]]\n" " split [-cd] -n chunk_count [-a suffix_length] [file [prefix]]\n" " split [-cd] -p pattern [-a suffix_length] [file [prefix]]\n"); exit(EX_USAGE); } diff --git a/usr.bin/tail/tail.c b/usr.bin/tail/tail.c index e0266515d749..a9841f2d4a8a 100644 --- a/usr.bin/tail/tail.c +++ b/usr.bin/tail/tail.c @@ -1,381 +1,381 @@ /*- * 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 #include "extern.h" int Fflag, fflag, qflag, rflag, rval, no_files, vflag; fileargs_t *fa; static void obsolete(char **); -static void usage(void); +static void usage(void) __dead2; static const struct option long_opts[] = { {"blocks", required_argument, NULL, 'b'}, {"bytes", required_argument, NULL, 'c'}, {"lines", required_argument, NULL, 'n'}, {"quiet", no_argument, NULL, 'q'}, {"silent", no_argument, NULL, 'q'}, {"verbose", no_argument, NULL, 'v'}, {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; 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(); \ if (expand_number(optarg, &off)) \ err(1, "illegal offset -- %s", optarg); \ if (off > INT64_MAX / units || off < INT64_MIN / units ) \ 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:qrv", 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; vflag = 0; break; case 'r': rflag = 1; break; case 'v': vflag = 1; qflag = 0; 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 (vflag || (qflag == 0 && argc > 1)) { 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/tee/tee.c b/usr.bin/tee/tee.c index bc338e14bd66..5646930a1c98 100644 --- a/usr.bin/tee/tee.c +++ b/usr.bin/tee/tee.c @@ -1,160 +1,160 @@ /*- * 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. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)tee.c 8.1 (Berkeley) 6/6/93"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include struct entry { int fd; const char *name; STAILQ_ENTRY(entry) entries; }; static STAILQ_HEAD(, entry) head = STAILQ_HEAD_INITIALIZER(head); static void add(int, const char *); -static void usage(void); +static void usage(void) __dead2; int main(int argc, char *argv[]) { struct entry *p; int n, fd, rval, wval; char *bp; int append, ch, exitval; char *buf; #define BSIZE (8 * 1024) append = 0; while ((ch = getopt(argc, argv, "ai")) != -1) switch((char)ch) { case 'a': append = 1; break; case 'i': (void)signal(SIGINT, SIG_IGN); break; case '?': default: usage(); } argv += optind; argc -= optind; if ((buf = malloc(BSIZE)) == NULL) err(1, "malloc"); if (caph_limit_stdin() == -1 || caph_limit_stderr() == -1) err(EXIT_FAILURE, "unable to limit stdio"); add(STDOUT_FILENO, "stdout"); for (exitval = 0; *argv; ++argv) if ((fd = open(*argv, append ? O_WRONLY|O_CREAT|O_APPEND : O_WRONLY|O_CREAT|O_TRUNC, DEFFILEMODE)) < 0) { warn("%s", *argv); exitval = 1; } else add(fd, *argv); if (caph_enter() < 0) err(EXIT_FAILURE, "unable to enter capability mode"); while ((rval = read(STDIN_FILENO, buf, BSIZE)) > 0) STAILQ_FOREACH(p, &head, entries) { n = rval; bp = buf; do { if ((wval = write(p->fd, bp, n)) == -1) { warn("%s", p->name); exitval = 1; break; } bp += wval; } while (n -= wval); } if (rval < 0) err(1, "read"); exit(exitval); } static void usage(void) { (void)fprintf(stderr, "usage: tee [-ai] [file ...]\n"); exit(1); } static void add(int fd, const char *name) { struct entry *p; cap_rights_t rights; if (fd == STDOUT_FILENO) { if (caph_limit_stdout() == -1) err(EXIT_FAILURE, "unable to limit stdout"); } else { cap_rights_init(&rights, CAP_WRITE, CAP_FSTAT); if (caph_rights_limit(fd, &rights) < 0) err(EXIT_FAILURE, "unable to limit rights"); } if ((p = malloc(sizeof(struct entry))) == NULL) err(1, "malloc"); p->fd = fd; p->name = name; STAILQ_INSERT_HEAD(&head, p, entries); } diff --git a/usr.bin/time/time.c b/usr.bin/time/time.c index 9121b1f14408..64063212170d 100644 --- a/usr.bin/time/time.c +++ b/usr.bin/time/time.c @@ -1,313 +1,313 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1987, 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. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1987, 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)time.c 8.1 (Berkeley) 6/6/93"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int getstathz(void); static void humantime(FILE *, long, long); static void showtime(FILE *, struct timespec *, struct timespec *, struct rusage *); static void siginfo(int); -static void usage(void); +static void usage(void) __dead2; static sig_atomic_t siginfo_recvd; static char decimal_point; static struct timespec before_ts; static int hflag, pflag; int main(int argc, char **argv) { int aflag, ch, lflag, status; int exitonsig; pid_t pid; struct rlimit rl; struct rusage ru; struct timespec after; char *ofn = NULL; FILE *out = stderr; (void) setlocale(LC_NUMERIC, ""); decimal_point = localeconv()->decimal_point[0]; aflag = hflag = lflag = pflag = 0; while ((ch = getopt(argc, argv, "ahlo:p")) != -1) switch((char)ch) { case 'a': aflag = 1; break; case 'h': hflag = 1; break; case 'l': lflag = 1; break; case 'o': ofn = optarg; break; case 'p': pflag = 1; break; case '?': default: usage(); } if (!(argc -= optind)) exit(0); argv += optind; if (ofn) { if ((out = fopen(ofn, aflag ? "ae" : "we")) == NULL) err(1, "%s", ofn); setvbuf(out, (char *)NULL, _IONBF, (size_t)0); } if (clock_gettime(CLOCK_MONOTONIC, &before_ts)) err(1, "clock_gettime"); switch(pid = fork()) { case -1: /* error */ err(1, "time"); /* NOTREACHED */ case 0: /* child */ execvp(*argv, argv); err(errno == ENOENT ? 127 : 126, "%s", *argv); /* NOTREACHED */ } /* parent */ (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); siginfo_recvd = 0; (void)signal(SIGINFO, siginfo); (void)siginterrupt(SIGINFO, 1); while (wait4(pid, &status, 0, &ru) != pid) { if (siginfo_recvd) { siginfo_recvd = 0; if (clock_gettime(CLOCK_MONOTONIC, &after)) err(1, "clock_gettime"); getrusage(RUSAGE_CHILDREN, &ru); showtime(stdout, &before_ts, &after, &ru); } } if (clock_gettime(CLOCK_MONOTONIC, &after)) err(1, "clock_gettime"); if ( ! WIFEXITED(status)) warnx("command terminated abnormally"); exitonsig = WIFSIGNALED(status) ? WTERMSIG(status) : 0; showtime(out, &before_ts, &after, &ru); if (lflag) { int hz = getstathz(); u_long ticks; ticks = hz * (ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) + hz * (ru.ru_utime.tv_usec + ru.ru_stime.tv_usec) / 1000000; /* * If our round-off on the tick calculation still puts us at 0, * then always assume at least one tick. */ if (ticks == 0) ticks = 1; fprintf(out, "%10ld %s\n", ru.ru_maxrss, "maximum resident set size"); fprintf(out, "%10ld %s\n", ru.ru_ixrss / ticks, "average shared memory size"); fprintf(out, "%10ld %s\n", ru.ru_idrss / ticks, "average unshared data size"); fprintf(out, "%10ld %s\n", ru.ru_isrss / ticks, "average unshared stack size"); fprintf(out, "%10ld %s\n", ru.ru_minflt, "page reclaims"); fprintf(out, "%10ld %s\n", ru.ru_majflt, "page faults"); fprintf(out, "%10ld %s\n", ru.ru_nswap, "swaps"); fprintf(out, "%10ld %s\n", ru.ru_inblock, "block input operations"); fprintf(out, "%10ld %s\n", ru.ru_oublock, "block output operations"); fprintf(out, "%10ld %s\n", ru.ru_msgsnd, "messages sent"); fprintf(out, "%10ld %s\n", ru.ru_msgrcv, "messages received"); fprintf(out, "%10ld %s\n", ru.ru_nsignals, "signals received"); fprintf(out, "%10ld %s\n", ru.ru_nvcsw, "voluntary context switches"); fprintf(out, "%10ld %s\n", ru.ru_nivcsw, "involuntary context switches"); } /* * If the child has exited on a signal, exit on the same * signal, too, in order to reproduce the child's exit status. * However, avoid actually dumping core from the current process. */ if (exitonsig) { if (signal(exitonsig, SIG_DFL) == SIG_ERR) warn("signal"); else { rl.rlim_max = rl.rlim_cur = 0; if (setrlimit(RLIMIT_CORE, &rl) == -1) warn("setrlimit"); kill(getpid(), exitonsig); } } exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE); } static void usage(void) { fprintf(stderr, "usage: time [-al] [-h | -p] [-o file] utility [argument ...]\n"); exit(1); } /* * Return the frequency of the kernel's statistics clock. */ static int getstathz(void) { int mib[2]; size_t size; struct clockinfo clockrate; mib[0] = CTL_KERN; mib[1] = KERN_CLOCKRATE; size = sizeof clockrate; if (sysctl(mib, 2, &clockrate, &size, NULL, 0) == -1) err(1, "sysctl kern.clockrate"); return clockrate.stathz; } static void humantime(FILE *out, long sec, long centisec) { long days, hrs, mins; days = sec / (60L * 60 * 24); sec %= (60L * 60 * 24); hrs = sec / (60L * 60); sec %= (60L * 60); mins = sec / 60; sec %= 60; fprintf(out, "\t"); if (days) fprintf(out, "%ldd", days); if (hrs) fprintf(out, "%ldh", hrs); if (mins) fprintf(out, "%ldm", mins); fprintf(out, "%ld%c%02lds", sec, decimal_point, centisec); } static void showtime(FILE *out, struct timespec *before, struct timespec *after, struct rusage *ru) { after->tv_sec -= before->tv_sec; after->tv_nsec -= before->tv_nsec; if (after->tv_nsec < 0) after->tv_sec--, after->tv_nsec += 1000000000; if (pflag) { /* POSIX wants output that must look like "real %f\nuser %f\nsys %f\n" and requires at least two digits after the radix. */ fprintf(out, "real %jd%c%02ld\n", (intmax_t)after->tv_sec, decimal_point, after->tv_nsec/10000000); fprintf(out, "user %jd%c%02ld\n", (intmax_t)ru->ru_utime.tv_sec, decimal_point, ru->ru_utime.tv_usec/10000); fprintf(out, "sys %jd%c%02ld\n", (intmax_t)ru->ru_stime.tv_sec, decimal_point, ru->ru_stime.tv_usec/10000); } else if (hflag) { humantime(out, after->tv_sec, after->tv_nsec/10000000); fprintf(out, " real\t"); humantime(out, ru->ru_utime.tv_sec, ru->ru_utime.tv_usec/10000); fprintf(out, " user\t"); humantime(out, ru->ru_stime.tv_sec, ru->ru_stime.tv_usec/10000); fprintf(out, " sys\n"); } else { fprintf(out, "%9jd%c%02ld real ", (intmax_t)after->tv_sec, decimal_point, after->tv_nsec/10000000); fprintf(out, "%9jd%c%02ld user ", (intmax_t)ru->ru_utime.tv_sec, decimal_point, ru->ru_utime.tv_usec/10000); fprintf(out, "%9jd%c%02ld sys\n", (intmax_t)ru->ru_stime.tv_sec, decimal_point, ru->ru_stime.tv_usec/10000); } } static void siginfo(int sig __unused) { siginfo_recvd = 1; } diff --git a/usr.bin/tr/tr.c b/usr.bin/tr/tr.c index 2d1baad2ac09..32f1858049ac 100644 --- a/usr.bin/tr/tr.c +++ b/usr.bin/tr/tr.c @@ -1,384 +1,384 @@ /*- * 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); +static void usage(void) __dead2; 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/tty/tty.c b/usr.bin/tty/tty.c index 02fc2fec1e28..4f9549eb67c5 100644 --- a/usr.bin/tty/tty.c +++ b/usr.bin/tty/tty.c @@ -1,82 +1,82 @@ /*- * 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. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1988, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)tty.c 8.1 (Berkeley) 6/6/93"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include #include #include -static void usage(void); +static void usage(void) __dead2; int main(int argc, char *argv[]) { int ch, sflag; char *t; sflag = 0; while ((ch = getopt(argc, argv, "s")) != -1) switch (ch) { case 's': sflag = 1; break; case '?': default: usage(); /* NOTREACHED */ } t = ttyname(STDIN_FILENO); if (!sflag) puts(t ? t : "not a tty"); exit(t ? EXIT_SUCCESS : EXIT_FAILURE); } static void usage(void) { fprintf(stderr, "usage: %s [-s]\n", getprogname()); exit(2); } diff --git a/usr.bin/ul/ul.c b/usr.bin/ul/ul.c index 14b1d87905d2..07a796ffd55b 100644 --- a/usr.bin/ul/ul.c +++ b/usr.bin/ul/ul.c @@ -1,588 +1,588 @@ /*- * 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. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)ul.c 8.1 (Berkeley) 6/6/93"; #endif static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #include #include #include #define IESC '\033' #define SO '\016' #define SI '\017' #define HFWD '9' #define HREV '8' #define FREV '7' #define MAXBUF 512 #define NORMAL 000 #define ALTSET 001 /* Reverse */ #define SUPERSC 002 /* Dim */ #define SUBSC 004 /* Dim | Ul */ #define UNDERL 010 /* Ul */ #define BOLD 020 /* Bold */ static int must_use_uc, must_overstrike; static const char *CURS_UP, *CURS_RIGHT, *CURS_LEFT, *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE, *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES; struct CHAR { char c_mode; wchar_t c_char; int c_width; /* width or -1 if multi-column char. filler */ } ; static struct CHAR sobuf[MAXBUF]; /* static output buffer */ static struct CHAR *obuf = sobuf; static int buflen = MAXBUF; static int col, maxcol; static int mode; static int halfpos; static int upln; static int iflag; -static void usage(void); +static void usage(void) __dead2; static void setnewmode(int); static void initcap(void); static void reverse(void); static int outchar(int); static void fwd(void); static void initbuf(void); static void iattr(void); static void overstrike(void); static void flushln(void); static void filter(FILE *); static void outc(wint_t, int); #define PRINT(s) if (s == NULL) /* void */; else tputs(s, 1, outchar) int main(int argc, char **argv) { int c; const char *termtype; FILE *f; char termcap[1024]; setlocale(LC_ALL, ""); termtype = getenv("TERM"); if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1))) termtype = "lpr"; while ((c = getopt(argc, argv, "it:T:")) != -1) switch (c) { case 't': case 'T': /* for nroff compatibility */ termtype = optarg; break; case 'i': iflag = 1; break; default: usage(); } switch (tgetent(termcap, termtype)) { case 1: break; default: warnx("trouble reading termcap"); /* FALLTHROUGH */ case 0: /* No such terminal type - assume dumb */ (void)strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:"); break; } initcap(); if ((tgetflag("os") && ENTER_BOLD == NULL ) || (tgetflag("ul") && ENTER_UNDERLINE == NULL && UNDER_CHAR == NULL)) must_overstrike = 1; initbuf(); if (optind == argc) filter(stdin); else for (; optind 0) col--; continue; case '\t': col = (col+8) & ~07; if (col > maxcol) maxcol = col; continue; case '\r': col = 0; continue; case SO: mode |= ALTSET; continue; case SI: mode &= ~ALTSET; continue; case IESC: switch (c = getwc(f)) { case HREV: if (halfpos == 0) { mode |= SUPERSC; halfpos--; } else if (halfpos > 0) { mode &= ~SUBSC; halfpos--; } else { halfpos = 0; reverse(); } continue; case HFWD: if (halfpos == 0) { mode |= SUBSC; halfpos++; } else if (halfpos < 0) { mode &= ~SUPERSC; halfpos++; } else { halfpos = 0; fwd(); } continue; case FREV: reverse(); continue; default: errx(1, "unknown escape sequence in input: %o, %o", IESC, c); } continue; case '_': if (obuf[col].c_char || obuf[col].c_width < 0) { while (col > 0 && obuf[col].c_width < 0) col--; w = obuf[col].c_width; for (i = 0; i < w; i++) obuf[col++].c_mode |= UNDERL | mode; if (col > maxcol) maxcol = col; continue; } obuf[col].c_char = '_'; obuf[col].c_width = 1; /* FALLTHROUGH */ case ' ': col++; if (col > maxcol) maxcol = col; continue; case '\n': flushln(); continue; case '\f': flushln(); putwchar('\f'); continue; default: if ((w = wcwidth(c)) <= 0) /* non printing */ continue; if (obuf[col].c_char == '\0') { obuf[col].c_char = c; for (i = 0; i < w; i++) obuf[col + i].c_mode = mode; obuf[col].c_width = w; for (i = 1; i < w; i++) obuf[col + i].c_width = -1; } else if (obuf[col].c_char == '_') { obuf[col].c_char = c; for (i = 0; i < w; i++) obuf[col + i].c_mode |= UNDERL|mode; obuf[col].c_width = w; for (i = 1; i < w; i++) obuf[col + i].c_width = -1; } else if ((wint_t)obuf[col].c_char == c) { for (i = 0; i < w; i++) obuf[col + i].c_mode |= BOLD|mode; } else { w = obuf[col].c_width; for (i = 0; i < w; i++) obuf[col + i].c_mode = mode; } col += w; if (col > maxcol) maxcol = col; continue; } } if (ferror(f)) err(1, NULL); if (maxcol) flushln(); } static void flushln(void) { int lastmode; int i; int hadmodes = 0; lastmode = NORMAL; for (i = 0; i < maxcol; i++) { if (obuf[i].c_mode != lastmode) { hadmodes++; setnewmode(obuf[i].c_mode); lastmode = obuf[i].c_mode; } if (obuf[i].c_char == '\0') { if (upln) PRINT(CURS_RIGHT); else outc(' ', 1); } else outc(obuf[i].c_char, obuf[i].c_width); if (obuf[i].c_width > 1) i += obuf[i].c_width - 1; } if (lastmode != NORMAL) { setnewmode(0); } if (must_overstrike && hadmodes) overstrike(); putwchar('\n'); if (iflag && hadmodes) iattr(); (void)fflush(stdout); if (upln) upln--; initbuf(); } /* * For terminals that can overstrike, overstrike underlines and bolds. * We don't do anything with halfline ups and downs, or Greek. */ static void overstrike(void) { int i; wchar_t lbuf[256]; wchar_t *cp = lbuf; int hadbold=0; /* Set up overstrike buffer */ for (i=0; i 1) i += obuf[i].c_width - 1; hadbold=1; break; } putwchar('\r'); for (*cp=' '; *cp==' '; cp--) *cp = 0; for (cp=lbuf; *cp; cp++) putwchar(*cp); if (hadbold) { putwchar('\r'); for (cp=lbuf; *cp; cp++) putwchar(*cp=='_' ? ' ' : *cp); putwchar('\r'); for (cp=lbuf; *cp; cp++) putwchar(*cp=='_' ? ' ' : *cp); } } static void iattr(void) { int i; wchar_t lbuf[256]; wchar_t *cp = lbuf; for (i=0; i __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 void usage(void) __dead2; 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..47a3b1f611ca 100644 --- a/usr.bin/unexpand/unexpand.c +++ b/usr.bin/unexpand/unexpand.c @@ -1,229 +1,229 @@ /*- * 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 void usage(void) __dead2; 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/usbhidctl/usbhid.c b/usr.bin/usbhidctl/usbhid.c index 984cdebc3289..b814aa3924d1 100644 --- a/usr.bin/usbhidctl/usbhid.c +++ b/usr.bin/usbhidctl/usbhid.c @@ -1,533 +1,533 @@ /* $NetBSD: usbhid.c,v 1.14 2000/07/03 02:51:37 matt Exp $ */ /* $FreeBSD$ */ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Lennart Augustsson (augustss@netbsd.org). * * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 #include #include #include #include #include #include #include #include #include #include static struct variable { char *name; int instance; int val; struct hid_item h; struct variable *next; } *vars; static int verbose = 0; static int noname = 0; static int hexdump = 0; static int wflag = 0; static int zflag = 0; -static void usage(void); +static void usage(void) __dead2; static void dumpitem(const char *label, struct hid_item *h); static void dumpitems(report_desc_t r); static void prdata(u_char *buf, struct hid_item *h); static void dumpdata(int f, report_desc_t r, int loop); static void writedata(int f, report_desc_t r); static void parceargs(report_desc_t r, int all, int nnames, char **names) { struct hid_data *d; struct hid_item h; char colls[1000]; char hname[1000], *tmp1, *tmp2; struct variable *var, **pnext; int i, instance, cp, t; pnext = &vars; if (all) { if (wflag) errx(1, "Must not specify -w to read variables"); cp = 0; for (d = hid_start_parse(r, 1<name, "%s%s%s:%s", colls, colls[0] != 0 ? "." : "", hid_usage_page(HID_PAGE(h.usage)), hid_usage_in_page(h.usage)); var->h = h; *pnext = var; pnext = &var->next; } hid_end_parse(d); return; } for (i = 0; i < nnames; i++) { var = malloc(sizeof(*var)); memset(var, 0, sizeof(*var)); tmp1 = tmp2 = strdup(names[i]); strsep(&tmp2, "="); var->name = strsep(&tmp1, "#"); if (tmp1 != NULL) var->instance = atoi(tmp1); if (tmp2 != NULL) { if (!wflag) errx(1, "Must specify -w to write variables"); var->val = atoi(tmp2); } else if (wflag) errx(1, "Must not specify -w to read variables"); *pnext = var; pnext = &var->next; instance = 0; cp = 0; for (d = hid_start_parse(r, 1<name); if (t > 0) { if (strcmp(hname + t, var->name) != 0) continue; if (hname[t - 1] != '.') continue; } else if (strcmp(hname, var->name) != 0) continue; if (var->instance != instance++) continue; var->h = h; break; } hid_end_parse(d); if (var->h.usage == 0) errx(1, "Unknown item '%s'", var->name); } } static void usage(void) { fprintf(stderr, "usage: %s -f device " "[-l] [-n] [-r] [-t tablefile] [-v] [-x] [-z] name ...\n", getprogname()); fprintf(stderr, " %s -f device " "[-l] [-n] [-r] [-t tablefile] [-v] [-x] [-z] -a\n", getprogname()); fprintf(stderr, " %s -f device " "[-t tablefile] [-v] [-z] -w name=value\n", getprogname()); exit(1); } static void dumpitem(const char *label, struct hid_item *h) { if ((h->flags & HIO_CONST) && !verbose) return; printf("%s rid=%d pos=%d size=%d count=%d page=%s usage=%s%s%s", label, h->report_ID, h->pos, h->report_size, h->report_count, hid_usage_page(HID_PAGE(h->usage)), hid_usage_in_page(h->usage), h->flags & HIO_CONST ? " Const" : "", h->flags & HIO_VARIABLE ? "" : " Array"); printf(", logical range %d..%d", h->logical_minimum, h->logical_maximum); if (h->physical_minimum != h->physical_maximum) printf(", physical range %d..%d", h->physical_minimum, h->physical_maximum); if (h->unit) printf(", unit=0x%02x exp=%d", h->unit, h->unit_exponent); printf("\n"); } static const char * hid_collection_type(int32_t type) { static char num[8]; switch (type) { case 0: return ("Physical"); case 1: return ("Application"); case 2: return ("Logical"); case 3: return ("Report"); case 4: return ("Named_Array"); case 5: return ("Usage_Switch"); case 6: return ("Usage_Modifier"); } snprintf(num, sizeof(num), "0x%02x", type); return (num); } static void dumpitems(report_desc_t r) { struct hid_data *d; struct hid_item h; int size; for (d = hid_start_parse(r, ~0, -1); hid_get_item(d, &h); ) { switch (h.kind) { case hid_collection: printf("Collection type=%s page=%s usage=%s\n", hid_collection_type(h.collection), hid_usage_page(HID_PAGE(h.usage)), hid_usage_in_page(h.usage)); break; case hid_endcollection: printf("End collection\n"); break; case hid_input: dumpitem("Input ", &h); break; case hid_output: dumpitem("Output ", &h); break; case hid_feature: dumpitem("Feature", &h); break; } } hid_end_parse(d); size = hid_report_size(r, hid_input, -1); printf("Total input size %d bytes\n", size); size = hid_report_size(r, hid_output, -1); printf("Total output size %d bytes\n", size); size = hid_report_size(r, hid_feature, -1); printf("Total feature size %d bytes\n", size); } static void prdata(u_char *buf, struct hid_item *h) { u_int data; int i, pos; pos = h->pos; for (i = 0; i < h->report_count; i++) { data = hid_get_data(buf, h); if (i > 0) printf(" "); if (h->logical_minimum < 0) printf("%d", (int)data); else printf("%u", data); if (hexdump) printf(" [0x%x]", data); h->pos += h->report_size; } h->pos = pos; } static void dumpdata(int f, report_desc_t rd, int loop) { struct variable *var; int dlen, havedata, i, match, r, rid, use_rid; u_char *dbuf; enum hid_kind kind; kind = zflag ? 3 : 0; rid = -1; use_rid = !!hid_get_report_id(f); do { if (kind < 3) { if (++rid >= 256) { rid = 0; kind++; } if (kind >= 3) rid = -1; for (var = vars; var; var = var->next) { if (rid == var->h.report_ID && kind == var->h.kind) break; } if (var == NULL) continue; } dlen = hid_report_size(rd, kind < 3 ? kind : hid_input, rid); if (dlen <= 0) continue; dbuf = malloc(dlen); memset(dbuf, 0, dlen); if (kind < 3) { dbuf[0] = rid; r = hid_get_report(f, kind, dbuf, dlen); if (r < 0) warn("hid_get_report(rid %d)", rid); havedata = !r && (rid == 0 || dbuf[0] == rid); if (rid != 0) dbuf[0] = rid; } else { r = read(f, dbuf, dlen); if (r < 1) err(1, "read error"); havedata = 1; } if (verbose) { printf("Got %s report %d (%d bytes):", kind == hid_output ? "output" : kind == hid_feature ? "feature" : "input", use_rid ? dbuf[0] : 0, dlen); if (havedata) { for (i = 0; i < dlen; i++) printf(" %02x", dbuf[i]); } printf("\n"); } match = 0; for (var = vars; var; var = var->next) { if ((kind < 3 ? kind : hid_input) != var->h.kind) continue; if (var->h.report_ID != 0 && dbuf[0] != var->h.report_ID) continue; match = 1; if (!noname) printf("%s=", var->name); if (havedata) prdata(dbuf, &var->h); printf("\n"); } if (match) printf("\n"); free(dbuf); } while (loop || kind < 3); } static void writedata(int f, report_desc_t rd) { struct variable *var; int dlen, i, r, rid; u_char *dbuf; enum hid_kind kind; kind = 0; rid = 0; for (kind = 0; kind < 3; kind ++) { for (rid = 0; rid < 256; rid ++) { for (var = vars; var; var = var->next) { if (rid == var->h.report_ID && kind == var->h.kind) break; } if (var == NULL) continue; dlen = hid_report_size(rd, kind, rid); if (dlen <= 0) continue; dbuf = malloc(dlen); memset(dbuf, 0, dlen); dbuf[0] = rid; if (!zflag && hid_get_report(f, kind, dbuf, dlen) == 0) { if (verbose) { printf("Got %s report %d (%d bytes):", kind == hid_input ? "input" : kind == hid_output ? "output" : "feature", rid, dlen); for (i = 0; i < dlen; i++) printf(" %02x", dbuf[i]); printf("\n"); } } else if (!zflag) { warn("hid_get_report(rid %d)", rid); if (verbose) { printf("Can't get %s report %d (%d bytes). " "Will be initialized with zeros.\n", kind == hid_input ? "input" : kind == hid_output ? "output" : "feature", rid, dlen); } } for (var = vars; var; var = var->next) { if (rid != var->h.report_ID || kind != var->h.kind) continue; hid_set_data(dbuf, &var->h, var->val); } if (verbose) { printf("Setting %s report %d (%d bytes):", kind == hid_output ? "output" : kind == hid_feature ? "feature" : "input", rid, dlen); for (i = 0; i < dlen; i++) printf(" %02x", dbuf[i]); printf("\n"); } r = hid_set_report(f, kind, dbuf, dlen); if (r != 0) warn("hid_set_report(rid %d)", rid); free(dbuf); } } } int main(int argc, char **argv) { report_desc_t r; char *table = 0; char devnam[100], *dev = NULL; int f; int all = 0; int ch; int repdump = 0; int loop = 0; while ((ch = getopt(argc, argv, "af:lnrt:vwxz")) != -1) { switch(ch) { case 'a': all++; break; case 'f': dev = optarg; break; case 'l': loop ^= 1; break; case 'n': noname++; break; case 'r': repdump++; break; case 't': table = optarg; break; case 'v': verbose++; break; case 'w': wflag = 1; break; case 'x': hexdump = 1; break; case 'z': zflag = 1; break; case '?': default: usage(); } } argc -= optind; argv += optind; if (dev == NULL) usage(); if (argc == 0 && !all && !repdump) usage(); if (dev[0] != '/') { if (isdigit(dev[0])) snprintf(devnam, sizeof(devnam), "/dev/uhid%s", dev); else snprintf(devnam, sizeof(devnam), "/dev/%s", dev); dev = devnam; } hid_init(table); f = open(dev, O_RDWR); if (f < 0) err(1, "%s", dev); r = hid_get_report_desc(f); if (r == 0) errx(1, "USB_GET_REPORT_DESC"); if (repdump) { printf("Report descriptor:\n"); dumpitems(r); } if (argc != 0 || all) { parceargs(r, all, argc, argv); if (wflag) writedata(f, r); else dumpdata(f, r, loop); } hid_dispose_report_desc(r); exit(0); } diff --git a/usr.bin/wall/wall.c b/usr.bin/wall/wall.c index a02f103cb80f..b1db354e6ec3 100644 --- a/usr.bin/wall/wall.c +++ b/usr.bin/wall/wall.c @@ -1,294 +1,294 @@ /*- * 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 void usage(void) __dead2; 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..5430a1fa0f35 100644 --- a/usr.bin/what/what.c +++ b/usr.bin/what/what.c @@ -1,139 +1,139 @@ /*- * 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 void usage(void) __dead2; 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/whois/whois.c b/usr.bin/whois/whois.c index d98120052b76..5dccb3c4a485 100644 --- a/usr.bin/whois/whois.c +++ b/usr.bin/whois/whois.c @@ -1,625 +1,625 @@ /*- * 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. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #if 0 #ifndef lint static char sccsid[] = "@(#)whois.c 8.1 (Berkeley) 6/6/93"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define ABUSEHOST "whois.abuse.net" #define ANICHOST "whois.arin.net" #define DENICHOST "whois.denic.de" #define DKNICHOST "whois.dk-hostmaster.dk" #define FNICHOST "whois.afrinic.net" #define GNICHOST "whois.nic.gov" #define IANAHOST "whois.iana.org" #define INICHOST "whois.internic.net" #define KNICHOST "whois.krnic.net" #define LNICHOST "whois.lacnic.net" #define MNICHOST "whois.ra.net" #define PDBHOST "whois.peeringdb.com" #define PNICHOST "whois.apnic.net" #define QNICHOST_TAIL ".whois-servers.net" #define RNICHOST "whois.ripe.net" #define VNICHOST "whois.verisign-grs.com" #define DEFAULT_PORT "whois" #define WHOIS_RECURSE 0x01 #define WHOIS_QUICK 0x02 #define WHOIS_SPAM_ME 0x04 #define CHOPSPAM ">>> Last update of WHOIS database:" #define ishost(h) (isalnum((unsigned char)h) || h == '.' || h == '-') #define SCAN(p, end, check) \ while ((p) < (end)) \ if (check) ++(p); \ else break static struct { const char *suffix, *server; } whoiswhere[] = { /* Various handles */ { "-ARIN", ANICHOST }, { "-NICAT", "at" QNICHOST_TAIL }, { "-NORID", "no" QNICHOST_TAIL }, { "-RIPE", RNICHOST }, /* Nominet's whois server doesn't return referrals to JANET */ { ".ac.uk", "ac.uk" QNICHOST_TAIL }, { ".gov.uk", "ac.uk" QNICHOST_TAIL }, { "", IANAHOST }, /* default */ { NULL, NULL } /* safety belt */ }; #define WHOIS_REFERRAL(s) { s, sizeof(s) - 1 } static struct { const char *prefix; size_t len; } whois_referral[] = { WHOIS_REFERRAL("whois:"), /* IANA */ WHOIS_REFERRAL("Whois Server:"), WHOIS_REFERRAL("Registrar WHOIS Server:"), /* corporatedomains.com */ WHOIS_REFERRAL("ReferralServer: whois://"), /* ARIN */ WHOIS_REFERRAL("ReferralServer: rwhois://"), /* ARIN */ WHOIS_REFERRAL("descr: region. Please query"), /* AfriNIC */ { NULL, 0 } }; /* * We have a list of patterns for RIRs that assert ignorance rather than * providing referrals. If that happens, we guess that ARIN will be more * helpful. But, before following a referral to an RIR, we check if we have * asked that RIR already, and if so we make another guess. */ static const char *actually_arin[] = { "netname: ERX-NETBLOCK\n", /* APNIC */ "netname: NON-RIPE-NCC-MANAGED-ADDRESS-BLOCK\n", NULL }; static struct { int loop; const char *host; } try_rir[] = { { 0, ANICHOST }, { 0, RNICHOST }, { 0, PNICHOST }, { 0, FNICHOST }, { 0, LNICHOST }, { 0, NULL } }; static void reset_rir(void) { int i; for (i = 0; try_rir[i].host != NULL; i++) try_rir[i].loop = 0; } static const char *port = DEFAULT_PORT; static const char *choose_server(char *); static struct addrinfo *gethostinfo(const char *, const char *, int); static void s_asprintf(char **ret, const char *format, ...) __printflike(2, 3); -static void usage(void); +static void usage(void) __dead2; static void whois(const char *, const char *, const char *, int); int main(int argc, char *argv[]) { const char *country, *host; int ch, flags; #ifdef SOCKS SOCKSinit(argv[0]); #endif country = host = NULL; flags = 0; while ((ch = getopt(argc, argv, "aAbc:fgh:iIklmp:PQrRS")) != -1) { switch (ch) { case 'a': host = ANICHOST; break; case 'A': host = PNICHOST; break; case 'b': host = ABUSEHOST; break; case 'c': country = optarg; break; case 'f': host = FNICHOST; break; case 'g': host = GNICHOST; break; case 'h': host = optarg; break; case 'i': host = INICHOST; break; case 'I': host = IANAHOST; break; case 'k': host = KNICHOST; break; case 'l': host = LNICHOST; break; case 'm': host = MNICHOST; break; case 'p': port = optarg; break; case 'P': host = PDBHOST; break; case 'Q': flags |= WHOIS_QUICK; break; case 'r': host = RNICHOST; break; case 'R': flags |= WHOIS_RECURSE; break; case 'S': flags |= WHOIS_SPAM_ME; break; case '?': default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (!argc || (country != NULL && host != NULL)) usage(); /* * If no host or country is specified, rely on referrals from IANA. */ if (host == NULL && country == NULL) { if ((host = getenv("WHOIS_SERVER")) == NULL && (host = getenv("RA_SERVER")) == NULL) { if (!(flags & WHOIS_QUICK)) flags |= WHOIS_RECURSE; } } while (argc-- > 0) { if (country != NULL) { char *qnichost; s_asprintf(&qnichost, "%s%s", country, QNICHOST_TAIL); whois(*argv, qnichost, port, flags); free(qnichost); } else whois(*argv, host != NULL ? host : choose_server(*argv), port, flags); reset_rir(); argv++; } exit(0); } static const char * choose_server(char *domain) { size_t len = strlen(domain); int i; for (i = 0; whoiswhere[i].suffix != NULL; i++) { size_t suffix_len = strlen(whoiswhere[i].suffix); if (len > suffix_len && strcasecmp(domain + len - suffix_len, whoiswhere[i].suffix) == 0) return (whoiswhere[i].server); } errx(EX_SOFTWARE, "no default whois server"); } static struct addrinfo * gethostinfo(const char *host, const char *hport, int exit_on_noname) { struct addrinfo hints, *res; int error; memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; res = NULL; error = getaddrinfo(host, hport, &hints, &res); if (error && (exit_on_noname || error != EAI_NONAME)) err(EX_NOHOST, "%s: %s", host, gai_strerror(error)); return (res); } /* * Wrapper for asprintf(3) that exits on error. */ static void s_asprintf(char **ret, const char *format, ...) { va_list ap; va_start(ap, format); if (vasprintf(ret, format, ap) == -1) { va_end(ap); err(EX_OSERR, "vasprintf()"); } va_end(ap); } static int connect_to_any_host(struct addrinfo *hostres) { struct addrinfo *res; nfds_t i, j; size_t count; struct pollfd *fds; int timeout = 180, s = -1; for (res = hostres, count = 0; res; res = res->ai_next) count++; fds = calloc(count, sizeof(*fds)); if (fds == NULL) err(EX_OSERR, "calloc()"); /* * Traverse the result list elements and make non-block * connection attempts. */ count = i = 0; for (res = hostres; res != NULL; res = res->ai_next) { s = socket(res->ai_family, res->ai_socktype | SOCK_NONBLOCK, res->ai_protocol); if (s < 0) continue; if (connect(s, res->ai_addr, res->ai_addrlen) < 0) { if (errno == EINPROGRESS) { /* Add the socket to poll list */ fds[i].fd = s; fds[i].events = POLLERR | POLLHUP | POLLIN | POLLOUT; /* * From here until a socket connects, the * socket fd is owned by the fds[] poll array. */ s = -1; count++; i++; } else { close(s); s = -1; /* * Poll only if we have something to poll, * otherwise just go ahead and try next * address */ if (count == 0) continue; } } else goto done; /* * If we are at the last address, poll until a connection is * established or we failed all connection attempts. */ if (res->ai_next == NULL) timeout = INFTIM; /* * Poll the watched descriptors for successful connections: * if we still have more untried resolved addresses, poll only * once; otherwise, poll until all descriptors have errors, * which will be considered as ETIMEDOUT later. */ do { int n; n = poll(fds, i, timeout); if (n == 0) { /* * No event reported in time. Try with a * smaller timeout (but cap at 2-3ms) * after a new host have been added. */ if (timeout >= 3) timeout >>= 1; break; } else if (n < 0) { /* * errno here can only be EINTR which we would * want to clean up and bail out. */ s = -1; goto done; } /* * Check for the event(s) we have seen. */ for (j = 0; j < i; j++) { if (fds[j].fd == -1 || fds[j].events == 0 || fds[j].revents == 0) continue; if (fds[j].revents & ~(POLLIN | POLLOUT)) { close(fds[j].fd); fds[j].fd = -1; fds[j].events = 0; count--; continue; } else if (fds[j].revents & (POLLIN | POLLOUT)) { /* Connect succeeded. */ s = fds[j].fd; fds[j].fd = -1; goto done; } } } while (timeout == INFTIM && count != 0); } /* All attempts were failed */ s = -1; if (count == 0) errno = ETIMEDOUT; done: /* Close all watched fds except the succeeded one */ for (j = 0; j < i; j++) if (fds[j].fd != -1) close(fds[j].fd); free(fds); return (s); } static void whois(const char *query, const char *hostname, const char *hostport, int flags) { FILE *fp; struct addrinfo *hostres; char *buf, *host, *nhost, *nport, *p; int comment, s, f; size_t len, i; hostres = gethostinfo(hostname, hostport, 1); s = connect_to_any_host(hostres); if (s == -1) err(EX_OSERR, "connect()"); /* Restore default blocking behavior. */ if ((f = fcntl(s, F_GETFL)) == -1) err(EX_OSERR, "fcntl()"); f &= ~O_NONBLOCK; if (fcntl(s, F_SETFL, f) == -1) err(EX_OSERR, "fcntl()"); fp = fdopen(s, "r+"); if (fp == NULL) err(EX_OSERR, "fdopen()"); if (!(flags & WHOIS_SPAM_ME) && (strcasecmp(hostname, DENICHOST) == 0 || strcasecmp(hostname, "de" QNICHOST_TAIL) == 0)) { const char *q; int idn = 0; for (q = query; *q != '\0'; q++) if (!isascii(*q)) idn = 1; fprintf(fp, "-T dn%s %s\r\n", idn ? "" : ",ace", query); } else if (!(flags & WHOIS_SPAM_ME) && (strcasecmp(hostname, DKNICHOST) == 0 || strcasecmp(hostname, "dk" QNICHOST_TAIL) == 0)) fprintf(fp, "--show-handles %s\r\n", query); else if ((flags & WHOIS_SPAM_ME) || strchr(query, ' ') != NULL) fprintf(fp, "%s\r\n", query); else if (strcasecmp(hostname, ANICHOST) == 0) { if (strncasecmp(query, "AS", 2) == 0 && strspn(query+2, "0123456789") == strlen(query+2)) fprintf(fp, "+ a %s\r\n", query+2); else fprintf(fp, "+ %s\r\n", query); } else if (strcasecmp(hostres->ai_canonname, VNICHOST) == 0) fprintf(fp, "domain %s\r\n", query); else fprintf(fp, "%s\r\n", query); fflush(fp); comment = 0; if (!(flags & WHOIS_SPAM_ME) && (strcasecmp(hostname, ANICHOST) == 0 || strcasecmp(hostname, RNICHOST) == 0)) { comment = 2; } nhost = NULL; while ((buf = fgetln(fp, &len)) != NULL) { /* Nominet */ if (!(flags & WHOIS_SPAM_ME) && len == 5 && strncmp(buf, "-- \r\n", 5) == 0) break; /* RIRs */ if (comment == 1 && buf[0] == '#') break; else if (comment == 2) { if (strchr("#%\r\n", buf[0]) != NULL) continue; else comment = 1; } printf("%.*s", (int)len, buf); if ((flags & WHOIS_RECURSE) && nhost == NULL) { for (i = 0; whois_referral[i].prefix != NULL; i++) { p = buf; SCAN(p, buf+len, *p == ' '); if (strncasecmp(p, whois_referral[i].prefix, whois_referral[i].len) != 0) continue; p += whois_referral[i].len; SCAN(p, buf+len, *p == ' '); host = p; SCAN(p, buf+len, ishost(*p)); if (p > host) { char *pstr; s_asprintf(&nhost, "%.*s", (int)(p - host), host); if (*p != ':') { s_asprintf(&nport, "%s", port); break; } pstr = ++p; SCAN(p, buf+len, isdigit(*p)); if (p > pstr && (p - pstr) < 6) { s_asprintf(&nport, "%.*s", (int)(p - pstr), pstr); break; } /* Invalid port; don't recurse */ free(nhost); nhost = NULL; } break; } for (i = 0; actually_arin[i] != NULL; i++) { if (strncmp(buf, actually_arin[i], len) == 0) { s_asprintf(&nhost, "%s", ANICHOST); s_asprintf(&nport, "%s", port); break; } } } /* Verisign etc. */ if (!(flags & WHOIS_SPAM_ME) && len >= sizeof(CHOPSPAM)-1 && (strncasecmp(buf, CHOPSPAM, sizeof(CHOPSPAM)-1) == 0 || strncasecmp(buf, CHOPSPAM+4, sizeof(CHOPSPAM)-5) == 0)) { printf("\n"); break; } } fclose(fp); freeaddrinfo(hostres); f = 0; for (i = 0; try_rir[i].host != NULL; i++) { /* Remember visits to RIRs */ if (try_rir[i].loop == 0 && strcasecmp(try_rir[i].host, hostname) == 0) try_rir[i].loop = 1; /* Do we need to find an alternative RIR? */ if (try_rir[i].loop != 0 && nhost != NULL && strcasecmp(try_rir[i].host, nhost) == 0) { free(nhost); nhost = NULL; free(nport); nport = NULL; f = 1; } } if (f) { /* Find a replacement RIR */ for (i = 0; try_rir[i].host != NULL; i++) { if (try_rir[i].loop == 0) { s_asprintf(&nhost, "%s", try_rir[i].host); s_asprintf(&nport, "%s", port); break; } } } if (nhost != NULL) { /* Ignore self-referrals */ if (strcasecmp(hostname, nhost) != 0) { printf("# %s\n\n", nhost); whois(query, nhost, nport, flags); } free(nhost); free(nport); } } static void usage(void) { fprintf(stderr, "usage: whois [-aAbfgiIklmPQrRS] [-c country-code | -h hostname] " "[-p port] name ...\n"); exit(EX_USAGE); } diff --git a/usr.bin/write/write.c b/usr.bin/write/write.c index 06cae97d9fc9..399373c5bc57 100644 --- a/usr.bin/write/write.c +++ b/usr.bin/write/write.c @@ -1,359 +1,359 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory. * * 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. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1989, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif #if 0 #ifndef lint static char sccsid[] = "@(#)write.c 8.1 (Berkeley) 6/6/93"; #endif #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void done(int); void do_write(int, char *, char *, const char *); -static void usage(void); +static void usage(void) __dead2; int term_chk(int, char *, int *, time_t *, int); void wr_fputs(wchar_t *s); void search_utmp(int, char *, char *, char *, uid_t); int utmp_chk(char *, char *); int main(int argc, char **argv) { unsigned long cmds[] = { TIOCGETA, TIOCGWINSZ, FIODGNAME }; cap_rights_t rights; struct passwd *pwd; time_t atime; uid_t myuid; int msgsok, myttyfd; char tty[MAXPATHLEN], *mytty; const char *login; int devfd; (void)setlocale(LC_CTYPE, ""); devfd = open(_PATH_DEV, O_RDONLY); if (devfd < 0) err(1, "open(/dev)"); cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_IOCTL, CAP_LOOKUP, CAP_PWRITE); if (caph_rights_limit(devfd, &rights) < 0) err(1, "can't limit devfd rights"); /* * Can't use capsicum helpers here because we need the additional * FIODGNAME ioctl. */ cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_IOCTL, CAP_READ, CAP_WRITE); if (caph_rights_limit(STDIN_FILENO, &rights) < 0 || caph_rights_limit(STDOUT_FILENO, &rights) < 0 || caph_rights_limit(STDERR_FILENO, &rights) < 0 || caph_ioctls_limit(STDIN_FILENO, cmds, nitems(cmds)) < 0 || caph_ioctls_limit(STDOUT_FILENO, cmds, nitems(cmds)) < 0 || caph_ioctls_limit(STDERR_FILENO, cmds, nitems(cmds)) < 0 || caph_fcntls_limit(STDIN_FILENO, CAP_FCNTL_GETFL) < 0 || caph_fcntls_limit(STDOUT_FILENO, CAP_FCNTL_GETFL) < 0 || caph_fcntls_limit(STDERR_FILENO, CAP_FCNTL_GETFL) < 0) err(1, "can't limit stdio rights"); caph_cache_catpages(); caph_cache_tzdata(); /* * Cache UTX database fds. */ setutxent(); /* * Determine our login name before we reopen() stdout * and before entering capability sandbox. */ myuid = getuid(); if ((login = getlogin()) == NULL) { if ((pwd = getpwuid(myuid))) login = pwd->pw_name; else login = "???"; } if (caph_enter() < 0) err(1, "cap_enter"); while (getopt(argc, argv, "") != -1) usage(); argc -= optind; argv += optind; /* check that sender has write enabled */ if (isatty(fileno(stdin))) myttyfd = fileno(stdin); else if (isatty(fileno(stdout))) myttyfd = fileno(stdout); else if (isatty(fileno(stderr))) myttyfd = fileno(stderr); else errx(1, "can't find your tty"); if (!(mytty = ttyname(myttyfd))) errx(1, "can't find your tty's name"); if (!strncmp(mytty, _PATH_DEV, strlen(_PATH_DEV))) mytty += strlen(_PATH_DEV); if (term_chk(devfd, mytty, &msgsok, &atime, 1)) exit(1); if (!msgsok) errx(1, "you have write permission turned off"); /* check args */ switch (argc) { case 1: search_utmp(devfd, argv[0], tty, mytty, myuid); do_write(devfd, tty, mytty, login); break; case 2: if (!strncmp(argv[1], _PATH_DEV, strlen(_PATH_DEV))) argv[1] += strlen(_PATH_DEV); if (utmp_chk(argv[0], argv[1])) errx(1, "%s is not logged in on %s", argv[0], argv[1]); if (term_chk(devfd, argv[1], &msgsok, &atime, 1)) exit(1); if (myuid && !msgsok) errx(1, "%s has messages disabled on %s", argv[0], argv[1]); do_write(devfd, argv[1], mytty, login); break; default: usage(); } done(0); return (0); } static void usage(void) { (void)fprintf(stderr, "usage: write user [tty]\n"); exit(1); } /* * utmp_chk - checks that the given user is actually logged in on * the given tty */ int utmp_chk(char *user, char *tty) { struct utmpx lu, *u; strncpy(lu.ut_line, tty, sizeof lu.ut_line); while ((u = getutxline(&lu)) != NULL) if (u->ut_type == USER_PROCESS && strcmp(user, u->ut_user) == 0) { endutxent(); return(0); } endutxent(); return(1); } /* * search_utmp - search utmp for the "best" terminal to write to * * Ignores terminals with messages disabled, and of the rest, returns * the one with the most recent access time. Returns as value the number * of the user's terminals with messages enabled, or -1 if the user is * not logged in at all. * * Special case for writing to yourself - ignore the terminal you're * writing from, unless that's the only terminal with messages enabled. */ void search_utmp(int devfd, char *user, char *tty, char *mytty, uid_t myuid) { struct utmpx *u; time_t bestatime, atime; int nloggedttys, nttys, msgsok, user_is_me; nloggedttys = nttys = 0; bestatime = 0; user_is_me = 0; while ((u = getutxent()) != NULL) if (u->ut_type == USER_PROCESS && strcmp(user, u->ut_user) == 0) { ++nloggedttys; if (term_chk(devfd, u->ut_line, &msgsok, &atime, 0)) continue; /* bad term? skip */ if (myuid && !msgsok) continue; /* skip ttys with msgs off */ if (strcmp(u->ut_line, mytty) == 0) { user_is_me = 1; continue; /* don't write to yourself */ } ++nttys; if (atime > bestatime) { bestatime = atime; (void)strlcpy(tty, u->ut_line, MAXPATHLEN); } } endutxent(); if (nloggedttys == 0) errx(1, "%s is not logged in", user); if (nttys == 0) { if (user_is_me) { /* ok, so write to yourself! */ (void)strlcpy(tty, mytty, MAXPATHLEN); return; } errx(1, "%s has messages disabled", user); } else if (nttys > 1) { warnx("%s is logged in more than once; writing to %s", user, tty); } } /* * term_chk - check that a terminal exists, and get the message bit * and the access time */ int term_chk(int devfd, char *tty, int *msgsokP, time_t *atimeP, int showerror) { struct stat s; if (fstatat(devfd, tty, &s, 0) < 0) { if (showerror) warn("%s%s", _PATH_DEV, tty); return(1); } *msgsokP = (s.st_mode & (S_IWRITE >> 3)) != 0; /* group write bit */ *atimeP = s.st_atime; return(0); } /* * do_write - actually make the connection */ void do_write(int devfd, char *tty, char *mytty, const char *login) { char *nows; time_t now; char host[MAXHOSTNAMELEN]; wchar_t line[512]; int fd; fd = openat(devfd, tty, O_WRONLY); if (fd < 0) err(1, "openat(%s%s)", _PATH_DEV, tty); fclose(stdout); stdout = fdopen(fd, "w"); if (stdout == NULL) err(1, "%s%s", _PATH_DEV, tty); (void)signal(SIGINT, done); (void)signal(SIGHUP, done); /* print greeting */ if (gethostname(host, sizeof(host)) < 0) (void)strcpy(host, "???"); now = time((time_t *)NULL); nows = ctime(&now); nows[16] = '\0'; (void)printf("\r\n\007\007\007Message from %s@%s on %s at %s ...\r\n", login, host, mytty, nows + 11); while (fgetws(line, sizeof(line)/sizeof(wchar_t), stdin) != NULL) wr_fputs(line); } /* * done - cleanup and exit */ void done(int n __unused) { (void)printf("EOF\r\n"); exit(0); } /* * wr_fputs - like fputs(), but makes control characters visible and * turns \n into \r\n */ void wr_fputs(wchar_t *s) { #define PUTC(c) if (putwchar(c) == WEOF) err(1, NULL); for (; *s != L'\0'; ++s) { if (*s == L'\n') { PUTC(L'\r'); PUTC(L'\n'); } else if (iswprint(*s) || iswspace(*s)) { PUTC(*s); } else { wprintf(L"<0x%X>", *s); } } return; #undef PUTC } diff --git a/usr.bin/xstr/xstr.c b/usr.bin/xstr/xstr.c index da96581c3f2b..af9f0d2893bb 100644 --- a/usr.bin/xstr/xstr.c +++ b/usr.bin/xstr/xstr.c @@ -1,493 +1,493 @@ /*- * 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 usage(void) __dead2; 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); }