xref: /freebsd/usr.bin/asa/asa.c (revision c2356a440db91c106867d45c94b3d6d7bc0e50f0)
1  /*	$NetBSD: asa.c,v 1.17 2016/09/05 00:40:28 sevan Exp $	*/
2  
3  /*-
4   * SPDX-License-Identifier: BSD-4-Clause
5   *
6   * Copyright (c) 1993,94 Winning Strategies, Inc.
7   * All rights reserved.
8   *
9   * Redistribution and use in source and binary forms, with or without
10   * modification, are permitted provided that the following conditions
11   * are met:
12   * 1. Redistributions of source code must retain the above copyright
13   *    notice, this list of conditions and the following disclaimer.
14   * 2. Redistributions in binary form must reproduce the above copyright
15   *    notice, this list of conditions and the following disclaimer in the
16   *    documentation and/or other materials provided with the distribution.
17   * 3. All advertising materials mentioning features or use of this software
18   *    must display the following acknowledgement:
19   *      This product includes software developed by Winning Strategies, Inc.
20   * 4. The name of the author may not be used to endorse or promote products
21   *    derived from this software without specific prior written permission
22   *
23   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26   * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   */
34  
35  #include <err.h>
36  #include <stdbool.h>
37  #include <stdio.h>
38  #include <stdlib.h>
39  #include <string.h>
40  #include <unistd.h>
41  
42  static void asa(FILE *);
43  static void usage(void) __dead2;
44  
45  int
main(int argc,char * argv[])46  main(int argc, char *argv[])
47  {
48  	FILE *fp;
49  	int ch, exval;
50  
51  	while ((ch = getopt(argc, argv, "")) != -1) {
52  		switch (ch) {
53  		default:
54  			usage();
55  		}
56  	}
57  	argc -= optind;
58  	argv += optind;
59  
60  	exval = 0;
61  	if (*argv == NULL) {
62  		asa(stdin);
63  	} else {
64  		do {
65  			if (strcmp(*argv, "-") == 0) {
66  				asa(stdin);
67  			} else if ((fp = fopen(*argv, "r")) == NULL) {
68  				warn("%s", *argv);
69  				exval = 1;
70  			} else {
71  				asa(fp);
72  				fclose(fp);
73  			}
74  		} while (*++argv != NULL);
75  	}
76  
77  	if (fflush(stdout) != 0)
78  		err(1, "stdout");
79  
80  	exit(exval);
81  }
82  
83  static void
usage(void)84  usage(void)
85  {
86  	fprintf(stderr, "usage: asa [file ...]\n");
87  	exit(1);
88  }
89  
90  static void
asa(FILE * f)91  asa(FILE *f)
92  {
93  	char *buf;
94  	size_t len;
95  	bool eol = false;
96  
97  	while ((buf = fgetln(f, &len)) != NULL) {
98  		/* in all cases but '+', terminate previous line, if any */
99  		if (buf[0] != '+' && eol)
100  			putchar('\n');
101  		/* examine and translate the control character */
102  		switch (buf[0]) {
103  		default:
104  			/*
105  			 * “It is suggested that implementations treat
106  			 * characters other than 0, 1, and '+' as <space>
107  			 * in the absence of any compelling reason to do
108  			 * otherwise” (POSIX.1-2017)
109  			 */
110  		case ' ':
111  			/* nothing */
112  			break;
113  		case '0':
114  			putchar('\n');
115  			break;
116  		case '1':
117  			putchar('\f');
118  			break;
119  		case '+':
120  			/*
121  			 * “If the '+' is the first character in the
122  			 * input, it shall be equivalent to <space>.”
123  			 * (POSIX.1-2017)
124  			 */
125  			if (eol)
126  				putchar('\r');
127  			break;
128  		}
129  		/* trim newline if there is one */
130  		if ((eol = (buf[len - 1] == '\n')))
131  			--len;
132  		/* print the rest of the input line */
133  		if (len > 1 && buf[0] && buf[1])
134  			fwrite(buf + 1, 1, len - 1, stdout);
135  	}
136  	/* terminate the last line, if any */
137  	if (eol)
138  		putchar('\n');
139  	/* check for output errors */
140  	if (ferror(stdout) != 0)
141  		err(1, "stdout");
142  }
143