1 /* $OpenBSD: ident.c,v 1.30 2014/10/02 06:23:15 otto Exp $ */ 2 /* 3 * Copyright (c) 2005 Xavier Santolaria <xsa@openbsd.org> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. The name of the author may not be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 16 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 17 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 18 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <ctype.h> 28 #include <err.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <unistd.h> 32 33 #include "rcsprog.h" 34 35 #define KEYDELIM '$' /* keywords delimiter */ 36 #define VALDELIM ':' /* values delimiter */ 37 38 static int found = 0; 39 static int flags = 0; 40 41 static void ident_file(const char *, FILE *); 42 static void ident_line(FILE *); 43 44 int 45 ident_main(int argc, char **argv) 46 { 47 int i, ch, status; 48 FILE *fp; 49 50 status = 0; 51 52 while ((ch = rcs_getopt(argc, argv, "qV")) != -1) { 53 switch(ch) { 54 case 'q': 55 flags |= QUIET; 56 break; 57 case 'V': 58 printf("%s\n", rcs_version); 59 exit(0); 60 default: 61 (usage)(); 62 } 63 } 64 65 argc -= rcs_optind; 66 argv += rcs_optind; 67 68 if (argc == 0) 69 ident_file(NULL, stdin); 70 else { 71 for (i = 0; i < argc; i++) { 72 if ((fp = fopen(argv[i], "r")) == NULL) { 73 warn("%s", argv[i]); 74 status = 1; 75 continue; 76 } 77 78 ident_file(argv[i], fp); 79 (void)fclose(fp); 80 if (i != argc - 1) 81 printf("\n"); 82 } 83 } 84 85 return (status); 86 } 87 88 89 static void 90 ident_file(const char *filename, FILE *fp) 91 { 92 int c; 93 94 if (filename != NULL) 95 printf("%s:\n", filename); 96 else 97 filename = "standard input"; 98 99 for (c = 0; c != EOF; c = getc(fp)) { 100 if (feof(fp) || ferror(fp)) 101 break; 102 if (c == KEYDELIM) 103 ident_line(fp); 104 } 105 106 if (found == 0 && !(flags & QUIET)) 107 fprintf(stderr, "ident warning: no id keywords in %s\n", 108 filename); 109 110 found = 0; 111 } 112 113 static void 114 ident_line(FILE *fp) 115 { 116 int c; 117 BUF *bp; 118 size_t len; 119 120 bp = buf_alloc(512); 121 122 while ((c = getc(fp)) != VALDELIM) { 123 if (c == EOF) 124 goto out; 125 126 if (isalpha(c)) 127 buf_putc(bp, c); 128 else 129 goto out; 130 } 131 132 buf_putc(bp, VALDELIM); 133 134 while ((c = getc(fp)) != KEYDELIM) { 135 if (c == EOF) 136 goto out; 137 138 if (c == '\n') 139 goto out; 140 141 buf_putc(bp, c); 142 } 143 144 len = buf_len(bp); 145 if (buf_getc(bp, len - 1) != ' ') 146 goto out; 147 148 /* append trailing KEYDELIM */ 149 buf_putc(bp, c); 150 151 /* Append newline for printing. */ 152 buf_putc(bp, '\n'); 153 printf(" %c", KEYDELIM); 154 fflush(stdout); 155 buf_write_fd(bp, STDOUT_FILENO); 156 157 found++; 158 out: 159 if (bp != NULL) 160 buf_free(bp); 161 } 162 163 __dead void 164 ident_usage(void) 165 { 166 fprintf(stderr, "usage: ident [-qV] [file ...]\n"); 167 168 exit(1); 169 } 170