1
2
3
4
5
6 using System;
7 using System.Collections;
8 using System.IO;
9 using System.Os;
10
11 void PrintHelp()
12 {
13 Console.WriteLine("Usage: tail [options] [FILE]...");
14 Console.WriteLine("Print last 10 lines of each file to standard output.");
15 Console.WriteLine("Options:");
16 Console.WriteLine("--help | -h");
17 Console.WriteLine(" Print help and exit.");
18 Console.WriteLine("--lines=[+]NUM | -n=[+]NUM");
19 Console.WriteLine(" Print last NUM lines instead of first 10;");
20 Console.WriteLine(" with the leading '+' print lines starting with line number NUM.");
21 }
22
23 void PrintTail(const List<string>& files, int lineCount, bool startLine)
24 {
25 for (const string& file : files)
26 {
27 StreamReader reader(SharedPtr<Stream>());
28 if (!file.IsEmpty())
29 {
30 reader = File.OpenRead(file);
31 }
32 else
33 {
34 if (IsConsole(0))
35 {
36 reader = StreamReader(SharedPtr<Stream>(new FileStream(0)));
37 }
38 else
39 {
40 reader = StreamReader(SharedPtr<Stream>(new BufferedStream(SharedPtr<Stream>(new FileStream(0)))));
41 }
42 }
43 List<string> lines;
44 while (!reader.EndOfStream())
45 {
46 string line = reader.ReadLine();
47 lines.Add(line);
48 }
49 int n = cast<int>(lines.Count());
50 int start = Max(n - lineCount, 0);
51 if (startLine)
52 {
53 start = lineCount - 1;
54 }
55 for (int i = start; i < n; ++i;)
56 {
57 Console.WriteLine(lines[i]);
58 }
59 }
60 }
61
62 int main(int argc, const char** argv)
63 {
64 try
65 {
66 int lineCount = 10;
67 List<string> files;
68 bool startLine = false;
69 for (int i = 1; i < argc; ++i;)
70 {
71 string arg = argv[i];
72 if (arg.StartsWith("--"))
73 {
74 if (arg == "--help")
75 {
76 PrintHelp();
77 return 1;
78 }
79 else if (arg.Find('=') != -1)
80 {
81 List<string> components = arg.Split('=');
82 if (components.Count() == 2)
83 {
84 if (components[0] == "--lines")
85 {
86 if (components[1].StartsWith("+"))
87 {
88 startLine = true;
89 }
90 lineCount = ParseInt(components[1]);
91 }
92 else
93 {
94 throw Exception("unknown option '" + arg + "'");
95 }
96 }
97 else
98 {
99 throw Exception("unknown option '" + arg + "'");
100 }
101 }
102 else
103 {
104 throw Exception("unknown option '" + arg + "'");
105 }
106 }
107 else if (arg.StartsWith("-"))
108 {
109 if (arg.Find('=') != -1)
110 {
111 List<string> components = arg.Split('=');
112 if (components.Count() == 2)
113 {
114 if (components[0] == "-n")
115 {
116 if (components[1].StartsWith("+"))
117 {
118 startLine = true;
119 }
120 lineCount = ParseInt(components[1]);
121 }
122 else
123 {
124 throw Exception("unknown option '" + arg + "'");
125 }
126 }
127 else
128 {
129 throw Exception("unknown option '" + arg + "'");
130 }
131 }
132 else
133 {
134 string options = arg.Substring(1);
135 for (char o : options)
136 {
137 string uo;
138 bool unknown = false;
139 switch (o)
140 {
141 case 'h':
142 {
143 PrintHelp();
144 return 1;
145 }
146 default:
147 {
148 uo.Append(o);
149 unknown = true;
150 break;
151 }
152 }
153 if (unknown)
154 {
155 throw Exception("unknown option '-" + uo + "'");
156 }
157 }
158 }
159 }
160 else
161 {
162 files.Add(arg);
163 }
164 }
165 if (files.IsEmpty())
166 {
167 files.Add(string());
168 }
169 PrintTail(files, lineCount, startLine);
170 }
171 catch (const Exception& ex)
172 {
173 Console.Error() << ex.ToString() << endl();
174 return 1;
175 }
176 return 0;
177 }