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 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 84 usage(void) 85 { 86 fprintf(stderr, "usage: asa [file ...]\n"); 87 exit(1); 88 } 89 90 static void 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