1 /*
2 colortail -- output last part of file(s) in color.
3 Copyright (C) 2009 Joakim Andersson <ja@joakimandersson.se>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include <iostream>
21 #include <sstream>
22 #include <cstring>
23 #include <string.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 #include "OptionsParser.h"
28 #include "Info.h"
29 #include "Usage.h"
30
31 using namespace std;
32 // methods for class Options
33
Options()34 Options::Options()
35 {
36 // sets default values for attributes
37
38 // don't follow by default
39 follow = 0;
40 // color output by default
41 color = 1;
42 // 10 rows by default
43 rows = 10;
44 // verbose by default
45 verbose = 1;
46 // no cfg files by default
47 nr_cfg_files = 0;
48 for (int i = 0 ; i < MAX_FILES ; i++)
49 {
50 cfg_filenames[i] = NULL;
51 }
52 // individual cfg files as default
53 global_cfg_file = 0;
54
55 }
56
~Options()57 Options::~Options()
58 {
59 // destructor, frees memory allocated for filenames
60
61 for (int i = 0 ; i < MAX_FILES ; i++)
62 {
63 if (cfg_filenames[i])
64 {
65 delete[] cfg_filenames[i];
66 }
67 }
68 }
69
70 // methods for class OptionsParser
OptionsParser()71 OptionsParser::OptionsParser()
72 {
73 // constructor
74
75 // set default error msg
76 sprintf(m_error, "No error");
77 }
78
~OptionsParser()79 OptionsParser::~OptionsParser()
80 {
81 // destructor
82 }
83
parse(int argc,char ** argv)84 Options* OptionsParser::parse(int argc, char **argv)
85 {
86 // parses options and sets the attributes in the Options class
87 // which is then returned. Returns NULL on error and m_error is set
88
89 // make Options instance
90 Options *o = new Options();
91
92 // prevent error messages from getopt_long
93 opterr = 0;
94
95 int c;
96 Info info;
97 Usage usage;
98
99 while (1)
100 {
101 c = getopt_long(argc, argv, "qvn:fk:l", long_options, NULL);
102 if (c == -1)
103 {
104 break;
105 }
106
107 switch (c)
108 {
109 case 'v':
110 // version
111 info.print();
112 break;
113
114 case 'h':
115 // help
116 usage.print();
117 break;
118
119 case 'f':
120 // follow
121 o->follow = 1;
122 break;
123
124 case 'k':
125 // color config file
126
127 {
128
129 int pos = 0; // position in optarg
130 int loop = 1;
131 while (loop)
132 {
133 ostringstream filename;
134
135 while (1)
136 {
137 if (optarg[pos] == ',')
138 {
139 // found seperator
140 // set filename in options class
141 string str = filename.str();
142 char* cs = new char[str.length()+1];
143 std::strcpy(cs, str.c_str());
144
145 o->cfg_filenames[o->nr_cfg_files] = cs;
146
147 // increase the nr_cfg_files counter
148 (o->nr_cfg_files)++;
149
150 // increase the position
151 pos++;
152
153 // break the inner loop
154 break;
155 }
156
157 if (optarg[pos] == '\0')
158 {
159 // found end of string
160 // set filename in options class
161 string str = filename.str();
162 char* cs = new char[str.length()+1];
163 std::strcpy(cs, str.c_str());
164
165 o->cfg_filenames[o->nr_cfg_files] = cs;
166
167 // increase the nr_cfg_files counter
168 (o->nr_cfg_files)++;
169
170 // check if only one cfg file
171 if (o->nr_cfg_files == 1)
172 {
173 // only one cfg file
174 o->global_cfg_file = 1;
175 }
176
177 // stop the big loop
178 loop = 0;
179
180 // break the inner loop
181 break;
182 }
183
184 // insert the current character into the filename string
185 filename.put(optarg[pos]);
186
187 // increase the position
188 pos++;
189 }
190 }
191 }
192 break;
193
194 case 'l':
195 // no colors
196 o->color = 0;
197 break;
198
199 case 'n':
200 // numberg of lines
201
202 // check if only digits
203 if (check_digits(optarg) == 0)
204 {
205 o->rows = atoi(optarg);
206 }
207 else
208 {
209 sprintf(m_error,
210 "One or more non-digits were given as number of rows");
211 // free memory for options class
212 delete o;
213 // return NULL to show that an error occured
214 return NULL;
215 }
216 break;
217
218 case 'q':
219 // quiet mode
220 o->verbose = 0;
221 break;
222
223 case '?':
224 // unrecognized option
225
226 // TODO: fix to handle -45 that means -n 45
227
228 cout << "colortail: invalid option -- " << (char)c << endl;
229 cout << "Try 'colortail --help' for more information." << endl;
230
231 break;
232
233 default:
234
235 cout << "Unrecognized option " << (char)c << endl;
236
237 // print usage
238 usage.print();
239 break;
240 }
241 }
242
243 return o;
244 }
245
246
check_digits(char * str)247 int OptionsParser::check_digits(char *str)
248 {
249 // checks if str only contains digits
250
251 int i = 0, len = strlen(str);
252
253 for (i = 0 ; i < len ; i++)
254 {
255 if (str[i] < '0' || str[i] > '9')
256 {
257 // not a digit
258 return 1;
259 }
260 }
261 return 0;
262 }
263
get_error_msg()264 char* OptionsParser::get_error_msg()
265 {
266 // returns the current set error msg
267
268 return m_error;
269 }
270
271
272
273
274
275
276