users: new applet.
[platform/upstream/busybox.git] / coreutils / comm.c
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 */
25 static 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
47 int comm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
48 int 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 }