1 /* $OpenBSD: ident.c,v 1.29 2011/04/20 19:34:16 nicm 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 exit(1); 63 } 64 } 65 66 argc -= rcs_optind; 67 argv += rcs_optind; 68 69 if (argc == 0) 70 ident_file(NULL, stdin); 71 else { 72 for (i = 0; i < argc; i++) { 73 if ((fp = fopen(argv[i], "r")) == NULL) { 74 warn("%s", argv[i]); 75 status = 1; 76 continue; 77 } 78 79 ident_file(argv[i], fp); 80 (void)fclose(fp); 81 if (i != argc - 1) 82 printf("\n"); 83 } 84 } 85 86 return (status); 87 } 88 89 90 static void 91 ident_file(const char *filename, FILE *fp) 92 { 93 int c; 94 95 if (filename != NULL) 96 printf("%s:\n", filename); 97 else 98 filename = "standard input"; 99 100 for (c = 0; c != EOF; c = getc(fp)) { 101 if (feof(fp) || ferror(fp)) 102 break; 103 if (c == KEYDELIM) 104 ident_line(fp); 105 } 106 107 if (found == 0 && !(flags & QUIET)) 108 fprintf(stderr, "ident warning: no id keywords in %s\n", 109 filename); 110 111 found = 0; 112 } 113 114 static void 115 ident_line(FILE *fp) 116 { 117 int c; 118 BUF *bp; 119 size_t len; 120 121 bp = buf_alloc(512); 122 123 while ((c = getc(fp)) != VALDELIM) { 124 if (c == EOF) 125 goto out; 126 127 if (isalpha(c)) 128 buf_putc(bp, c); 129 else 130 goto out; 131 } 132 133 buf_putc(bp, VALDELIM); 134 135 while ((c = getc(fp)) != KEYDELIM) { 136 if (c == EOF) 137 goto out; 138 139 if (c == '\n') 140 goto out; 141 142 buf_putc(bp, c); 143 } 144 145 len = buf_len(bp); 146 if (buf_getc(bp, len - 1) != ' ') 147 goto out; 148 149 /* append trailing KEYDELIM */ 150 buf_putc(bp, c); 151 152 /* Append newline for printing. */ 153 buf_putc(bp, '\n'); 154 printf(" %c", KEYDELIM); 155 fflush(stdout); 156 buf_write_fd(bp, STDOUT_FILENO); 157 158 found++; 159 out: 160 if (bp != NULL) 161 buf_free(bp); 162 } 163 164 void 165 ident_usage(void) 166 { 167 fprintf(stderr, "usage: ident [-qV] [file ...]\n"); 168 } 169