aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
authorDavid M. Syzdek <syzdek@bindlebinaries.com>2017-06-14 20:26:23 -0800
committerDavid M. Syzdek <syzdek@bindlebinaries.com>2017-06-14 20:26:23 -0800
commit28de2ac47741ad7910725879b5db3f7c472a2cf6 (patch)
tree141c25b4598768258d248c607baf047d6dbcdb78 /src
parented7fd0e30cb1288e604707b6aa5a3d4791a21a14 (diff)
downloadsecurecoreutils-28de2ac47741ad7910725879b5db3f7c472a2cf6.tar.gz
securecoreutils-28de2ac47741ad7910725879b5db3f7c472a2cf6.tar.bz2
securecoreutils-28de2ac47741ad7910725879b5db3f7c472a2cf6.tar.xz
securecoreutils-28de2ac47741ad7910725879b5db3f7c472a2cf6.zip
Adding 'tail' widget.
Diffstat (limited to 'src')
-rw-r--r--src/securecoreutils.c9
-rw-r--r--src/securecoreutils.h11
-rw-r--r--src/widget-cat.c1
-rw-r--r--src/widget-pathcheck.c1
-rw-r--r--src/widget-tail.c483
-rw-r--r--src/widget-tail.h67
6 files changed, 571 insertions, 1 deletions
diff --git a/src/securecoreutils.c b/src/securecoreutils.c
index ef2e88b..2369f16 100644
--- a/src/securecoreutils.c
+++ b/src/securecoreutils.c
@@ -54,6 +54,7 @@
54 54
55#include "widget-cat.h" 55#include "widget-cat.h"
56#include "widget-pathcheck.h" 56#include "widget-pathcheck.h"
57#include "widget-tail.h"
57 58
58 59
59////////////////// 60//////////////////
@@ -93,6 +94,12 @@ const scu_widget scu_widget_map[] =
93 NULL, // widget alias 94 NULL, // widget alias
94 scu_widget_pathcheck, // widget function 95 scu_widget_pathcheck, // widget function
95 }, 96 },
97 {
98 "tail", // widget name
99 "Writes contents of file to standard out.", // widget description
100 "sectail", // widget alias
101 scu_widget_tail, // widget function
102 },
96 { NULL, NULL, NULL, NULL } 103 { NULL, NULL, NULL, NULL }
97}; 104};
98 105
@@ -280,6 +287,7 @@ void scu_usage(void)
280 printf(" widget [OPTIONS]\n"); 287 printf(" widget [OPTIONS]\n");
281 printf("\n"); 288 printf("\n");
282 scu_usage_options(); 289 scu_usage_options();
290 printf("\n");
283 scu_usage_widgets(); 291 scu_usage_widgets();
284 return; 292 return;
285} 293}
@@ -292,7 +300,6 @@ void scu_usage_options(void)
292 printf(" -q, --quiet, --silent do not print messages\n"); 300 printf(" -q, --quiet, --silent do not print messages\n");
293 printf(" -V, --version print version number and exit\n"); 301 printf(" -V, --version print version number and exit\n");
294 printf(" -v, --verbose print verbose messages\n"); 302 printf(" -v, --verbose print verbose messages\n");
295 printf("\n");
296 return; 303 return;
297} 304}
298 305
diff --git a/src/securecoreutils.h b/src/securecoreutils.h
index 342bee5..7cbc688 100644
--- a/src/securecoreutils.h
+++ b/src/securecoreutils.h
@@ -56,6 +56,7 @@
56 56
57#include <getopt.h> 57#include <getopt.h>
58#include <unistd.h> 58#include <unistd.h>
59#include <limits.h>
59 60
60 61
61/////////////////// 62///////////////////
@@ -84,6 +85,16 @@
84#endif 85#endif
85 86
86 87
88#ifdef LINE_MAX
89# define SCU_LINE_MAX LINE_MAX
90#elif defined _POSIX2_LINE_MAX
91# define SCU_LINE_MAX _POSIX2_LINE_MAX
92#else
93# define SCU_LINE_MAX 2048
94#endif
95#define SCU_BUFF_MAX (SCU_LINE_MAX*20)
96
97
87#define SCU_ESUCCESS 0 98#define SCU_ESUCCESS 0
88#define SCU_ERRNO 1 99#define SCU_ERRNO 1
89#define SCU_EPATH 2 100#define SCU_EPATH 2
diff --git a/src/widget-cat.c b/src/widget-cat.c
index c46ff25..b7424ae 100644
--- a/src/widget-cat.c
+++ b/src/widget-cat.c
@@ -208,6 +208,7 @@ void scu_widget_cat_usage(void)
208 printf(" seccat [OPTIONS] file\n"); 208 printf(" seccat [OPTIONS] file\n");
209 printf("\n"); 209 printf("\n");
210 scu_usage_options(); 210 scu_usage_options();
211 printf("\n");
211 return; 212 return;
212} 213}
213 214
diff --git a/src/widget-pathcheck.c b/src/widget-pathcheck.c
index 8789535..b1b56d7 100644
--- a/src/widget-pathcheck.c
+++ b/src/widget-pathcheck.c
@@ -152,6 +152,7 @@ void scu_widget_pathcheck_usage(void)
152 printf(" pathcheck [OPTIONS] file\n"); 152 printf(" pathcheck [OPTIONS] file\n");
153 printf("\n"); 153 printf("\n");
154 scu_usage_options(); 154 scu_usage_options();
155 printf("\n");
155 return; 156 return;
156} 157}
157 158
diff --git a/src/widget-tail.c b/src/widget-tail.c
new file mode 100644
index 0000000..68f274c
--- /dev/null
+++ b/src/widget-tail.c
@@ -0,0 +1,483 @@
1/*
2 * Secure Core Utilities
3 * Copyright (C) 2015 Bindle Binaries <syzdek@bindlebinaries.com>.
4 *
5 * @BINDLE_BINARIES_BSD_LICENSE_START@
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of Bindle Binaries nor the
17 * names of its contributors may be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BINDLE BINARIES BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @BINDLE_BINARIES_BSD_LICENSE_END@
33 */
34#include "widget-tail.h"
35
36///////////////
37// //
38// Headers //
39// //
40///////////////
41#ifdef __SECURECOREUTILS_PMARK
42#pragma mark - Headers
43#endif
44
45#include <inttypes.h>
46#include <assert.h>
47#include <errno.h>
48#include <stdio.h>
49#include <string.h>
50#include <fcntl.h>
51#include <sys/types.h>
52#include <sys/stat.h>
53#include <sys/uio.h>
54#include <unistd.h>
55#include <stdlib.h>
56#include <time.h>
57
58
59///////////////////
60// //
61// Definitions //
62// //
63///////////////////
64
65#define SCU_TAIL_OBOL 0x01
66#define SCU_TAIL_OBYTES 0x02
67#define SCU_TAIL_OFOLLOW 0x04
68
69
70//////////////////
71// //
72// Prototypes //
73// //
74//////////////////
75
76int scu_widget_tail_bytes(scu_config * cnf, int fd, struct stat * sb,
77 size_t opts, off_t optnum);
78int scu_widget_tail_follow(scu_config * cnf, int fd);
79int scu_widget_tail_lines(scu_config * cnf, int fd, struct stat * sb,
80 size_t opts, off_t optnum);
81
82
83/////////////////
84// //
85// Functions //
86// //
87/////////////////
88#ifdef __SECURECOREUTILS_PMARK
89#pragma mark - Functions
90#endif
91
92int scu_widget_tail(scu_config * cnf)
93{
94 int c;
95 int rc;
96 int opt_index;
97 int fd;
98 off_t optnum;
99 char * endptr;
100 size_t opts;
101 struct stat sb;
102
103 // getopt options
104 static char short_opt[] = "+c:fhn:qVv";
105 static struct option long_opt[] =
106 {
107 {"bytes", no_argument, NULL, 'c' },
108 {"follow", no_argument, NULL, 'f' },
109 {"help", no_argument, NULL, 'h' },
110 {"lines", no_argument, NULL, 'n' },
111 {"quiet", no_argument, NULL, 'q' },
112 {"silent", no_argument, NULL, 'q' },
113 {"version", no_argument, NULL, 'V' },
114 {"verbose", no_argument, NULL, 'v' },
115 { NULL, 0, NULL, 0 }
116 };
117
118 assert(cnf != NULL);
119
120 opts = 0;
121 optnum = 10;
122
123 while((c = getopt_long(cnf->argc, cnf->argv, short_opt, long_opt, &opt_index)) != -1)
124 {
125 switch(c)
126 {
127 case -1: /* no more arguments */
128 case 0: /* long options toggles */
129 break;
130
131
132 case 'h':
133 scu_widget_tail_usage();
134 return(0);
135
136
137 case 'c':
138 opts |= SCU_TAIL_OBYTES;
139 switch(optarg[0])
140 {
141 case '-':
142 optnum = strtoimax(&optarg[1], &endptr, 10);
143 break;
144
145 case '+':
146 opts |= SCU_TAIL_OBOL;
147 optnum = strtoimax(&optarg[1], &endptr, 10);
148 break;
149
150 default:
151 optnum = strtoimax(optarg, &endptr, 10);
152 break;
153 };
154 if ((endptr == optarg) || (endptr[0] != '\0'))
155 {
156 fprintf(stderr, "%s: %s: invalid value for `-c' -- %s\n", PROGRAM_NAME, cnf->widget->name, optarg);
157 return(1);
158 };
159 break;
160
161
162 case 'f':
163 opts |= SCU_TAIL_OFOLLOW;
164 break;
165
166
167 case 'n':
168 opts = (~SCU_TAIL_OBYTES) & opts;
169 switch(optarg[0])
170 {
171 case '-':
172 optnum = strtoimax(&optarg[1], &endptr, 10);
173 break;
174
175 case '+':
176 opts |= SCU_TAIL_OBOL;
177 optnum = strtoimax(&optarg[1], &endptr, 10);
178 break;
179
180 default:
181 optnum = strtoimax(optarg, &endptr, 10);
182 break;
183 };
184 if ((endptr == optarg) || (endptr[0] != '\0'))
185 {
186 fprintf(stderr, "%s: %s: invalid value for `-n' -- %s\n", PROGRAM_NAME, cnf->widget->name, optarg);
187 return(1);
188 };
189 break;
190
191
192 case 's':
193 cnf->quiet = 1;
194 if ((cnf->verbose))
195 {
196 fprintf(stderr, "%s: %s: incompatible options\n", PROGRAM_NAME, cnf->widget->name);
197 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
198 return(1);
199 };
200 break;
201
202
203 case 'V':
204 printf("%s widget\n", cnf->widget->name);
205 scu_version();
206 return(0);
207
208
209 case 'v':
210 cnf->verbose++;
211 if ((cnf->quiet))
212 {
213 fprintf(stderr, "%s: %s: incompatible options\n", PROGRAM_NAME, cnf->widget->name);
214 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->widget->name);
215 return(1);
216 };
217 break;
218
219
220 case '?':
221 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->widget->name);
222 return(1);
223
224
225 default:
226 fprintf(stderr, "%s: %s: unrecognized option `--%c'\n", PROGRAM_NAME, cnf->widget->name, c);
227 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->widget->name);
228 return(1);
229 };
230 };
231
232 if ((cnf->argc - optind) < 1)
233 {
234 fprintf(stderr, "%s: %s: missing required argument\n", PROGRAM_NAME, cnf->widget->name);
235 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->widget->name);
236 return(1);
237 };
238 if ((cnf->argc - optind) > 1)
239 {
240 fprintf(stderr, "%s: unrecognized argument `-- %s'\n", PROGRAM_NAME, cnf->argv[optind+1]);
241 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->widget->name);
242 return(1);
243 };
244
245 if ((rc = scu_pathcheck(cnf->argv[optind])) != 0)
246 {
247 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, cnf->widget->name, scu_strerror(rc));
248 return(1);
249 };
250
251 if ((fd = open(cnf->argv[optind], O_RDONLY)) == -1)
252 {
253 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, cnf->widget->name, strerror(errno));
254 return(1);
255 };
256
257 if ((rc = fstat(fd, &sb)) == -1)
258 {
259 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, cnf->widget->name, strerror(errno));
260 close(fd);
261 return(1);
262 };
263
264 if ((opts & SCU_TAIL_OBYTES) != 0)
265 {
266 if ((rc = scu_widget_tail_bytes(cnf, fd, &sb, opts, optnum)) == -1)
267 {
268 close(fd);
269 return(1);
270 };
271 };
272
273 if ((opts & SCU_TAIL_OBYTES) == 0)
274 {
275 if ((rc = scu_widget_tail_lines(cnf, fd, &sb, opts, optnum)) == -1)
276 {
277 close(fd);
278 return(1);
279 };
280 };
281
282 if ((opts & SCU_TAIL_OFOLLOW) != 0)
283 {
284 if (!(scu_widget_tail_follow(cnf, fd)))
285 {
286 close(fd);
287 return(1);
288 };
289 };
290
291 close(fd);
292
293 return(0);
294}
295
296
297int scu_widget_tail_bytes(scu_config * cnf, int fd, struct stat * sb,
298 size_t opts, off_t optnum)
299{
300 off_t rc;
301 off_t off;
302 char buff[SCU_BUFF_MAX];
303 ssize_t len;
304
305 if ((opts & SCU_TAIL_OBOL) == 0)
306 off = (sb->st_size < optnum) ? 0 : sb->st_size - optnum;
307 else
308 off = (sb->st_size < optnum) ? sb->st_size : optnum;
309
310 if ((rc = lseek(fd, off, SEEK_SET)) == -1)
311 {
312 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, cnf->widget->name, strerror(errno));
313 return(-1);
314 };
315
316 len = 1;
317 while ((len = read(fd, buff, sizeof(buff))) > 0)
318 {
319 if ((len = write(STDOUT_FILENO, buff, len)) == -1)
320 {
321 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, cnf->widget->name, strerror(errno));
322 return(-1);
323 };
324 };
325
326 return(0);
327}
328
329
330int scu_widget_tail_follow(scu_config * cnf, int fd)
331{
332 char buff[SCU_BUFF_MAX];
333 ssize_t len;
334 struct timespec ts;
335
336 ts.tv_sec = 0;
337 ts.tv_nsec = 10000000;
338
339 while (1)
340 {
341 switch (len = read(fd, buff, sizeof(buff)))
342 {
343 case -1:
344 fprintf(stderr, "%s: %s: read: %s\n", PROGRAM_NAME, cnf->widget->name, strerror(errno));
345 return(-1);
346
347 case 0:
348 nanosleep(&ts, NULL);
349 break;
350
351 default:
352 if ((len = write(STDOUT_FILENO, buff, len)) == -1)
353 {
354 fprintf(stderr, "%s: %s: write: %s\n", PROGRAM_NAME, cnf->widget->name, strerror(errno));
355 return(-1);
356 };
357 break;
358 };
359 };
360
361 return(0);
362}
363
364
365int scu_widget_tail_lines(scu_config * cnf, int fd, struct stat * sb,
366 size_t opts, off_t optnum)
367{
368 char buff[SCU_BUFF_MAX];
369 off_t rc;
370 ssize_t bufflen;
371 ssize_t len;
372 off_t linecount;
373 off_t seek;
374 ssize_t pos;
375 off_t found;
376
377 // start line count from beginning of file
378 if ((opts & SCU_TAIL_OBOL) != 0)
379 {
380 len = 1;
381 linecount = 1;
382 pos = 0;
383
384 while ((linecount < optnum) && (len > 0))
385 {
386 if ((len = read(fd, buff, sizeof(buff))) == -1)
387 {
388 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, cnf->widget->name, strerror(errno));
389 return(-1);
390 };
391
392 for (pos = 0; ((pos < len) && (linecount < optnum)); pos++)
393 {
394 if (buff[pos] == '\n')
395 linecount++;
396 if (linecount >= optnum)
397 {
398 if ((len = write(STDIN_FILENO, &buff[pos+1], (len-pos-1))) == -1)
399 {
400 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, cnf->widget->name, strerror(errno));
401 return(-1);
402 };
403 };
404 };
405 };
406 };
407
408 // start line count from end of file
409 if ((opts & SCU_TAIL_OBOL) == 0)
410 {
411 linecount = 0;
412 seek = sb->st_size;
413 found = 0;
414
415 while ((linecount <= optnum) && (seek > 0))
416 {
417 if (seek > (off_t)sizeof(buff))
418 {
419 bufflen = sizeof(buff);
420 seek -= bufflen;
421 } else {
422 bufflen = seek;
423 seek = 0;
424 };
425
426 if ((rc = lseek(fd, seek, SEEK_SET)) == -1)
427 {
428 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, cnf->widget->name, strerror(errno));
429 return(-1);
430 };
431
432 if ((len = read(fd, buff, bufflen)) == -1)
433 {
434 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, cnf->widget->name, strerror(errno));
435 return(-1);
436 };
437
438 for (pos = len; ((pos > 0) && (linecount <= optnum)); pos--)
439 {
440 if (buff[pos-1] == '\n')
441 linecount++;
442 if (linecount > optnum)
443 found = seek + pos;
444 };
445 };
446
447 if ((rc = lseek(fd, found, SEEK_SET)) == -1)
448 {
449 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, cnf->widget->name, strerror(errno));
450 return(-1);
451 };
452 };
453
454 len = 1;
455 while ((len = read(fd, buff, sizeof(buff))) > 0)
456 {
457 if ((len = write(STDOUT_FILENO, buff, len)) == -1)
458 {
459 fprintf(stderr, "%s: %s: %s\n", PROGRAM_NAME, cnf->widget->name, strerror(errno));
460 return(-1);
461 };
462 };
463
464 return(0);
465}
466
467
468void scu_widget_tail_usage(void)
469{
470 printf("Usage: %s tail [OPTIONS] file\n", PROGRAM_NAME);
471 printf(" tail [OPTIONS] file\n");
472 printf(" sectail [OPTIONS] file\n");
473 printf("\n");
474 scu_usage_options();
475 printf(" -c, --bytes=X output the last X bytes\n");
476 printf(" -f, --follow output appended data as the file grows\n");
477 printf(" -n, --lines=X output the last X lines\n");
478 printf("\n");
479 return;
480}
481
482
483/* end of source */
diff --git a/src/widget-tail.h b/src/widget-tail.h
new file mode 100644
index 0000000..493a1a9
--- /dev/null
+++ b/src/widget-tail.h
@@ -0,0 +1,67 @@
1/*
2 * Secure Core Utilities
3 * Copyright (C) 2015 Bindle Binaries <syzdek@bindlebinaries.com>.
4 *
5 * @BINDLE_BINARIES_BSD_LICENSE_START@
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of Bindle Binaries nor the
17 * names of its contributors may be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BINDLE BINARIES BE LIABLE FOR
24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @BINDLE_BINARIES_BSD_LICENSE_END@
33 */
34/**
35 * @file securecoreutils.c
36 * Secure Core Utils widget wrapper
37 */
38#ifndef __SRC_WIDGET_TAIL_H
39#define __SRC_WIDGET_TAIL_H 1
40
41
42///////////////
43// //
44// Headers //
45// //
46///////////////
47#ifdef __SECURECOREUTILS_PMARK
48#pragma mark - Headers
49#endif
50
51#include "securecoreutils.h"
52
53
54//////////////////
55// //
56// Prototypes //
57// //
58//////////////////
59#ifdef __TALLYMARK_PMARK
60#pragma mark -
61#endif
62
63int scu_widget_tail(scu_config * cnf);
64
65void scu_widget_tail_usage(void);
66
67#endif /* end of header */