xref: /freebsd/usr.bin/colrm/colrm.c (revision 95498a5acc0888ed2e73237b82a1e90f109473f9)
10da30e9aSPeter Wemm /*-
28a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
38a16b7a1SPedro F. Giffuni  *
40da30e9aSPeter Wemm  * Copyright (c) 1991, 1993
50da30e9aSPeter Wemm  *	The Regents of the University of California.  All rights reserved.
60da30e9aSPeter Wemm  *
70da30e9aSPeter Wemm  * Redistribution and use in source and binary forms, with or without
80da30e9aSPeter Wemm  * modification, are permitted provided that the following conditions
90da30e9aSPeter Wemm  * are met:
100da30e9aSPeter Wemm  * 1. Redistributions of source code must retain the above copyright
110da30e9aSPeter Wemm  *    notice, this list of conditions and the following disclaimer.
120da30e9aSPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
130da30e9aSPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
140da30e9aSPeter Wemm  *    documentation and/or other materials provided with the distribution.
15fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
160da30e9aSPeter Wemm  *    may be used to endorse or promote products derived from this software
170da30e9aSPeter Wemm  *    without specific prior written permission.
180da30e9aSPeter Wemm  *
190da30e9aSPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
200da30e9aSPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
210da30e9aSPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
220da30e9aSPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
230da30e9aSPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
240da30e9aSPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
250da30e9aSPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
260da30e9aSPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
270da30e9aSPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
280da30e9aSPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
290da30e9aSPeter Wemm  * SUCH DAMAGE.
300da30e9aSPeter Wemm  */
310da30e9aSPeter Wemm 
320da30e9aSPeter Wemm #include <sys/types.h>
33c3920857SPhilippe Charnier #include <err.h>
34821df508SXin LI #include <errno.h>
35821df508SXin LI #include <limits.h>
36d10ab05eSTim J. Robbins #include <locale.h>
370da30e9aSPeter Wemm #include <stdio.h>
380da30e9aSPeter Wemm #include <stdlib.h>
39821df508SXin LI #include <string.h>
400da30e9aSPeter Wemm #include <unistd.h>
41d10ab05eSTim J. Robbins #include <wchar.h>
420da30e9aSPeter Wemm 
43*95498a5aSFaraz Vahedi #include <capsicum_helpers.h>
44*95498a5aSFaraz Vahedi 
450da30e9aSPeter Wemm #define	TAB	8
460da30e9aSPeter Wemm 
47f1bb2cd2SWarner Losh void check(FILE *);
48498a0a9cSAlfonso Gregory static void usage(void) __dead2;
490da30e9aSPeter Wemm 
500da30e9aSPeter Wemm int
main(int argc,char * argv[])516ed42fb9SDavid Malone main(int argc, char *argv[])
520da30e9aSPeter Wemm {
536e47870bSMark Murray 	u_long column, start, stop;
54d10ab05eSTim J. Robbins 	int ch, width;
550da30e9aSPeter Wemm 	char *p;
560da30e9aSPeter Wemm 
57d10ab05eSTim J. Robbins 	setlocale(LC_ALL, "");
58d10ab05eSTim J. Robbins 
59*95498a5aSFaraz Vahedi 	caph_cache_catpages();
60*95498a5aSFaraz Vahedi 	if (caph_limit_stdio() < 0 || caph_enter() < 0)
61*95498a5aSFaraz Vahedi 		err(EXIT_FAILURE, "capsicum");
62*95498a5aSFaraz Vahedi 
631c8af878SWarner Losh 	while ((ch = getopt(argc, argv, "")) != -1)
640da30e9aSPeter Wemm 		switch(ch) {
650da30e9aSPeter Wemm 		case '?':
660da30e9aSPeter Wemm 		default:
670da30e9aSPeter Wemm 			usage();
680da30e9aSPeter Wemm 		}
690da30e9aSPeter Wemm 	argc -= optind;
700da30e9aSPeter Wemm 	argv += optind;
710da30e9aSPeter Wemm 
720da30e9aSPeter Wemm 	start = stop = 0;
730da30e9aSPeter Wemm 	switch(argc) {
740da30e9aSPeter Wemm 	case 2:
750da30e9aSPeter Wemm 		stop = strtol(argv[1], &p, 10);
760da30e9aSPeter Wemm 		if (stop <= 0 || *p)
77fc26f24bSFaraz Vahedi 			errx(EXIT_FAILURE, "illegal column -- %s", argv[1]);
780da30e9aSPeter Wemm 		/* FALLTHROUGH */
790da30e9aSPeter Wemm 	case 1:
800da30e9aSPeter Wemm 		start = strtol(argv[0], &p, 10);
810da30e9aSPeter Wemm 		if (start <= 0 || *p)
82fc26f24bSFaraz Vahedi 			errx(EXIT_FAILURE, "illegal column -- %s", argv[0]);
830da30e9aSPeter Wemm 		break;
840da30e9aSPeter Wemm 	case 0:
850da30e9aSPeter Wemm 		break;
860da30e9aSPeter Wemm 	default:
870da30e9aSPeter Wemm 		usage();
880da30e9aSPeter Wemm 	}
890da30e9aSPeter Wemm 
900da30e9aSPeter Wemm 	if (stop && start > stop)
91fc26f24bSFaraz Vahedi 		errx(EXIT_FAILURE, "illegal start and stop columns");
920da30e9aSPeter Wemm 
930da30e9aSPeter Wemm 	for (column = 0;;) {
94d10ab05eSTim J. Robbins 		switch (ch = getwchar()) {
95d10ab05eSTim J. Robbins 		case WEOF:
960da30e9aSPeter Wemm 			check(stdin);
970da30e9aSPeter Wemm 			break;
980da30e9aSPeter Wemm 		case '\b':
990da30e9aSPeter Wemm 			if (column)
1000da30e9aSPeter Wemm 				--column;
1010da30e9aSPeter Wemm 			break;
1020da30e9aSPeter Wemm 		case '\n':
1030da30e9aSPeter Wemm 			column = 0;
1040da30e9aSPeter Wemm 			break;
1050da30e9aSPeter Wemm 		case '\t':
1060da30e9aSPeter Wemm 			column = (column + TAB) & ~(TAB - 1);
1070da30e9aSPeter Wemm 			break;
1080da30e9aSPeter Wemm 		default:
109d10ab05eSTim J. Robbins 			if ((width = wcwidth(ch)) > 0)
110d10ab05eSTim J. Robbins 				column += width;
1110da30e9aSPeter Wemm 			break;
1120da30e9aSPeter Wemm 		}
1130da30e9aSPeter Wemm 
114d7d10053SAlexander Langer 		if ((!start || column < start || (stop && column > stop)) &&
115d10ab05eSTim J. Robbins 		    putwchar(ch) == WEOF)
1160da30e9aSPeter Wemm 			check(stdout);
1170da30e9aSPeter Wemm 	}
1180da30e9aSPeter Wemm }
1190da30e9aSPeter Wemm 
1200da30e9aSPeter Wemm void
check(FILE * stream)1216ed42fb9SDavid Malone check(FILE *stream)
1220da30e9aSPeter Wemm {
1230da30e9aSPeter Wemm 	if (feof(stream))
124fc26f24bSFaraz Vahedi 		exit(EXIT_SUCCESS);
1250da30e9aSPeter Wemm 	if (ferror(stream))
126fc26f24bSFaraz Vahedi 		err(EXIT_FAILURE, "%s", stream == stdin ? "stdin" : "stdout");
1270da30e9aSPeter Wemm }
1280da30e9aSPeter Wemm 
1290da30e9aSPeter Wemm void
usage(void)1306ed42fb9SDavid Malone usage(void)
1310da30e9aSPeter Wemm {
1320da30e9aSPeter Wemm 	(void)fprintf(stderr, "usage: colrm [start [stop]]\n");
133fc26f24bSFaraz Vahedi 	exit(EXIT_FAILURE);
1340da30e9aSPeter Wemm }
135