1 /* $OpenBSD: ident.c,v 1.25 2007/09/09 17:22:34 ray 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 <string.h> 32 #include <unistd.h> 33 34 #include "rcsprog.h" 35 36 #define KEYDELIM '$' /* keywords delimiter */ 37 #define VALDELIM ':' /* values delimiter */ 38 39 static int found = 0; 40 static int flags = 0; 41 42 static void ident_file(const char *, FILE *); 43 static void ident_line(FILE *); 44 45 int 46 ident_main(int argc, char **argv) 47 { 48 int i, ch, status; 49 FILE *fp; 50 51 status = 0; 52 53 while ((ch = rcs_getopt(argc, argv, "qV")) != -1) { 54 switch(ch) { 55 case 'q': 56 flags |= QUIET; 57 break; 58 case 'V': 59 printf("%s\n", rcs_version); 60 exit(0); 61 default: 62 (usage)(); 63 exit(1); 64 } 65 } 66 67 argc -= rcs_optind; 68 argv += rcs_optind; 69 70 if (argc == 0) 71 ident_file(NULL, stdin); 72 else { 73 for (i = 0; i < argc; i++) { 74 if ((fp = fopen(argv[i], "r")) == NULL) { 75 warn("%s", argv[i]); 76 status = 1; 77 continue; 78 } 79 80 ident_file(argv[i], fp); 81 (void)fclose(fp); 82 if (i != argc - 1) 83 printf("\n"); 84 } 85 } 86 87 return (status); 88 } 89 90 91 static void 92 ident_file(const char *filename, FILE *fp) 93 { 94 int c; 95 96 if (filename != NULL) 97 printf("%s:\n", filename); 98 else 99 filename = "standard output"; 100 101 for (c = 0; c != EOF; c = getc(fp)) { 102 if (feof(fp) || ferror(fp)) 103 break; 104 if (c == KEYDELIM) 105 ident_line(fp); 106 } 107 108 if (found == 0 && !(flags & QUIET)) 109 fprintf(stderr, "ident warning: no id keywords in %s\n", 110 filename); 111 112 found = 0; 113 } 114 115 static void 116 ident_line(FILE *fp) 117 { 118 int c; 119 BUF *bp; 120 size_t len; 121 122 bp = rcs_buf_alloc(512, BUF_AUTOEXT); 123 124 while ((c = getc(fp)) != VALDELIM) { 125 if (c == EOF) 126 goto out; 127 128 if (isalpha(c)) 129 rcs_buf_putc(bp, c); 130 else 131 goto out; 132 } 133 134 rcs_buf_putc(bp, VALDELIM); 135 136 while ((c = getc(fp)) != KEYDELIM) { 137 if (c == EOF) 138 goto out; 139 140 if (c == '\n') 141 goto out; 142 143 rcs_buf_putc(bp, c); 144 } 145 146 len = rcs_buf_len(bp); 147 if (rcs_buf_getc(bp, len - 1) != ' ') 148 goto out; 149 150 /* append trailing KEYDELIM */ 151 rcs_buf_putc(bp, c); 152 153 /* Append newline for printing. */ 154 rcs_buf_putc(bp, '\n'); 155 printf(" %c", KEYDELIM); 156 fflush(stdout); 157 rcs_buf_write_fd(bp, STDOUT_FILENO); 158 159 found++; 160 out: 161 if (bp != NULL) 162 rcs_buf_free(bp); 163 } 164 165 void 166 ident_usage(void) 167 { 168 fprintf(stderr, "usage: ident [-qV] file ...\n"); 169 } 170