blob: 91f017753afb51b63a87a79e8c46345cc0976ee9 [file] [log] [blame]
Rob Landley2acfd7b2005-05-11 23:12:49 +00001/* 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 *
Rob Landleye104d5f2006-04-04 19:26:37 +00007 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Rob Landley2acfd7b2005-05-11 23:12:49 +00008 */
9
Rob Landley2acfd7b2005-05-11 23:12:49 +000010#include "busybox.h"
11
12#define COMM_OPT_1 0x01
13#define COMM_OPT_2 0x02
14#define COMM_OPT_3 0x04
15
16/* These three variables control behaviour if non-zero */
17
18static int only_file_1;
19static int only_file_2;
20static int both;
21
22/* writeline outputs the input given, appropriately aligned according to class */
Mike Frysingerb3a6ec32005-05-12 22:41:13 +000023static void writeline(char *line, int class)
Mike Frysinger0d605e92005-05-12 22:25:41 +000024{
Mike Frysinger867a6082005-05-13 00:57:30 +000025 if (class == 0) {
26 if (!only_file_1)
Mike Frysinger0fb397e2005-05-13 00:58:18 +000027 return;
Mike Frysinger867a6082005-05-13 00:57:30 +000028 } else if (class == 1) {
Mike Frysingerdad4cf72005-05-12 22:50:12 +000029 if (!only_file_2)
30 return;
31 if (only_file_1)
32 putchar('\t');
33 }
Mike Frysinger867a6082005-05-13 00:57:30 +000034 else /*if (class == 2)*/ {
Mike Frysingerdad4cf72005-05-12 22:50:12 +000035 if (!both)
36 return;
37 if (only_file_1)
38 putchar('\t');
39 if (only_file_2)
40 putchar('\t');
Rob Landley2acfd7b2005-05-11 23:12:49 +000041 }
Mike Frysinger0d605e92005-05-12 22:25:41 +000042 fputs(line, stdout);
Rob Landley2acfd7b2005-05-11 23:12:49 +000043}
44
45/* This is the real core of the program - lines are compared here */
Mike Frysinger867a6082005-05-13 00:57:30 +000046static void cmp_files(char **infiles)
Mike Frysinger0d605e92005-05-12 22:25:41 +000047{
Mike Frysinger867a6082005-05-13 00:57:30 +000048#define LINE_LEN 100
49#define BB_EOF_0 0x1
50#define BB_EOF_1 0x2
51 char thisline[2][LINE_LEN];
Rob Landley2acfd7b2005-05-11 23:12:49 +000052 FILE *streams[2];
Mike Frysinger867a6082005-05-13 00:57:30 +000053 int i;
Mike Frysinger0d605e92005-05-12 22:25:41 +000054
Mike Frysinger867a6082005-05-13 00:57:30 +000055 for (i = 0; i < 2; ++i) {
Rob Landleyd921b2e2006-08-03 15:41:12 +000056 streams[i] = ((infiles[i][0] == '=' && infiles[i][1]) ? stdin : xfopen(infiles[i], "r"));
Mike Frysinger867a6082005-05-13 00:57:30 +000057 fgets(thisline[i], LINE_LEN, streams[i]);
Rob Landley2acfd7b2005-05-11 23:12:49 +000058 }
59
Rob Landleye104d5f2006-04-04 19:26:37 +000060 while (*thisline[0] || *thisline[1]) {
Rob Landley2acfd7b2005-05-11 23:12:49 +000061 int order = 0;
Mike Frysinger867a6082005-05-13 00:57:30 +000062
63 i = 0;
64 if (feof(streams[0])) i |= BB_EOF_0;
65 if (feof(streams[1])) i |= BB_EOF_1;
Mike Frysinger0d605e92005-05-12 22:25:41 +000066
Rob Landleye104d5f2006-04-04 19:26:37 +000067 if (!*thisline[0])
Rob Landley2acfd7b2005-05-11 23:12:49 +000068 order = 1;
Rob Landleye104d5f2006-04-04 19:26:37 +000069 else if (!*thisline[1])
Rob Landley2acfd7b2005-05-11 23:12:49 +000070 order = -1;
71 else {
Mike Frysinger867a6082005-05-13 00:57:30 +000072 int tl0_len, tl1_len;
73 tl0_len = strlen(thisline[0]);
74 tl1_len = strlen(thisline[1]);
Rob Landley2acfd7b2005-05-11 23:12:49 +000075 order = memcmp(thisline[0], thisline[1], tl0_len < tl1_len ? tl0_len : tl1_len);
76 if (!order)
77 order = tl0_len < tl1_len ? -1 : tl0_len != tl1_len;
78 }
Mike Frysinger0d605e92005-05-12 22:25:41 +000079
Mike Frysinger867a6082005-05-13 00:57:30 +000080 if (order == 0 && !i)
Rob Landley2acfd7b2005-05-11 23:12:49 +000081 writeline(thisline[1], 2);
Mike Frysinger867a6082005-05-13 00:57:30 +000082 else if (order > 0 && !(i & BB_EOF_1))
83 writeline(thisline[1], 1);
84 else if (order < 0 && !(i & BB_EOF_0))
85 writeline(thisline[0], 0);
Mike Frysinger0d605e92005-05-12 22:25:41 +000086
Mike Frysinger867a6082005-05-13 00:57:30 +000087 if (i & BB_EOF_0 & BB_EOF_1) {
Rob Landley2acfd7b2005-05-11 23:12:49 +000088 break;
Mike Frysinger0d605e92005-05-12 22:25:41 +000089
Mike Frysinger867a6082005-05-13 00:57:30 +000090 } else if (i) {
91 i = (i & BB_EOF_0 ? 1 : 0);
92 while (!feof(streams[i])) {
93 if ((order < 0 && i) || (order > 0 && !i))
94 writeline(thisline[i], i);
95 fgets(thisline[i], LINE_LEN, streams[i]);
Rob Landley2acfd7b2005-05-11 23:12:49 +000096 }
Rob Landley2acfd7b2005-05-11 23:12:49 +000097 break;
Mike Frysinger0d605e92005-05-12 22:25:41 +000098
99 } else {
Rob Landley2acfd7b2005-05-11 23:12:49 +0000100 if (order >= 0)
Mike Frysinger867a6082005-05-13 00:57:30 +0000101 fgets(thisline[1], LINE_LEN, streams[1]);
Rob Landley2acfd7b2005-05-11 23:12:49 +0000102 if (order <= 0)
Mike Frysinger867a6082005-05-13 00:57:30 +0000103 fgets(thisline[0], LINE_LEN, streams[0]);
Rob Landley2acfd7b2005-05-11 23:12:49 +0000104 }
105 }
106
Mike Frysinger867a6082005-05-13 00:57:30 +0000107 fclose(streams[0]);
108 fclose(streams[1]);
Rob Landley2acfd7b2005-05-11 23:12:49 +0000109}
110
Mike Frysingerb3a6ec32005-05-12 22:41:13 +0000111int comm_main(int argc, char **argv)
Mike Frysinger0d605e92005-05-12 22:25:41 +0000112{
Mike Frysingerb3a6ec32005-05-12 22:41:13 +0000113 unsigned long flags;
Mike Frysinger0d605e92005-05-12 22:25:41 +0000114
Denis Vlasenko67b23e62006-10-03 21:00:06 +0000115 flags = getopt32(argc, argv, "123");
Mike Frysinger0d605e92005-05-12 22:25:41 +0000116
Mike Frysingerb3a6ec32005-05-12 22:41:13 +0000117 if (optind + 2 != argc)
Mike Frysinger0d605e92005-05-12 22:25:41 +0000118 bb_show_usage();
119
Mike Frysingerb3a6ec32005-05-12 22:41:13 +0000120 only_file_1 = !(flags & COMM_OPT_1);
121 only_file_2 = !(flags & COMM_OPT_2);
122 both = !(flags & COMM_OPT_3);
Rob Landley2acfd7b2005-05-11 23:12:49 +0000123
Mike Frysinger867a6082005-05-13 00:57:30 +0000124 cmp_files(argv + optind);
125 exit(EXIT_SUCCESS);
Rob Landley2acfd7b2005-05-11 23:12:49 +0000126}