1/* vi: set sw=4 ts=4: */ 2/* 3 * Mini comm implementation for busybox 4 * 5 * Copyright (C) 2005 by Robert Sullivan <cogito.ergo.cogito@gmail.com> 6 * 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 */ 9 10//usage:#define comm_trivial_usage 11//usage: "[-123] FILE1 FILE2" 12//usage:#define comm_full_usage "\n\n" 13//usage: "Compare FILE1 with FILE2\n" 14//usage: "\n -1 Suppress lines unique to FILE1" 15//usage: "\n -2 Suppress lines unique to FILE2" 16//usage: "\n -3 Suppress lines common to both files" 17 18#include "libbb.h" 19 20#define COMM_OPT_1 (1 << 0) 21#define COMM_OPT_2 (1 << 1) 22#define COMM_OPT_3 (1 << 2) 23 24/* writeline outputs the input given, appropriately aligned according to class */ 25static void writeline(char *line, int class) 26{ 27 int flags = option_mask32; 28 if (class == 0) { 29 if (flags & COMM_OPT_1) 30 return; 31 } else if (class == 1) { 32 if (flags & COMM_OPT_2) 33 return; 34 if (!(flags & COMM_OPT_1)) 35 putchar('\t'); 36 } else /*if (class == 2)*/ { 37 if (flags & COMM_OPT_3) 38 return; 39 if (!(flags & COMM_OPT_1)) 40 putchar('\t'); 41 if (!(flags & COMM_OPT_2)) 42 putchar('\t'); 43 } 44 puts(line); 45} 46 47int comm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 48int comm_main(int argc UNUSED_PARAM, char **argv) 49{ 50 char *thisline[2]; 51 FILE *stream[2]; 52 int i; 53 int order; 54 55 opt_complementary = "=2"; 56 getopt32(argv, "123"); 57 argv += optind; 58 59 for (i = 0; i < 2; ++i) { 60 stream[i] = xfopen_stdin(argv[i]); 61 } 62 63 order = 0; 64 thisline[1] = thisline[0] = NULL; 65 while (1) { 66 if (order <= 0) { 67 free(thisline[0]); 68 thisline[0] = xmalloc_fgetline(stream[0]); 69 } 70 if (order >= 0) { 71 free(thisline[1]); 72 thisline[1] = xmalloc_fgetline(stream[1]); 73 } 74 75 i = !thisline[0] + (!thisline[1] << 1); 76 if (i) 77 break; 78 order = strcmp(thisline[0], thisline[1]); 79 80 if (order >= 0) 81 writeline(thisline[1], order ? 1 : 2); 82 else 83 writeline(thisline[0], 0); 84 } 85 86 /* EOF at least on one of the streams */ 87 i &= 1; 88 if (thisline[i]) { 89 /* stream[i] is not at EOF yet */ 90 /* we did not print thisline[i] yet */ 91 char *p = thisline[i]; 92 writeline(p, i); 93 while (1) { 94 free(p); 95 p = xmalloc_fgetline(stream[i]); 96 if (!p) 97 break; 98 writeline(p, i); 99 } 100 } 101 102 if (ENABLE_FEATURE_CLEAN_UP) { 103 fclose(stream[0]); 104 fclose(stream[1]); 105 } 106 107 return EXIT_SUCCESS; 108} 109