1 /* $OpenBSD: ident.c,v 1.32 2016/08/26 09:02:54 guenther 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 <time.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 } 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 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