… | |
… | |
38 | #include <X11/Xatom.h> |
38 | #include <X11/Xatom.h> |
39 | #include <X11/Xutil.h> |
39 | #include <X11/Xutil.h> |
40 | |
40 | |
41 | /* data structures */ |
41 | /* data structures */ |
42 | struct logfile_entry { |
42 | struct logfile_entry { |
43 | char *fname; /* name of file */ |
43 | char *fname; /* name of file */ |
44 | char *desc; /* alternative description */ |
44 | char *desc; /* alternative description */ |
|
|
45 | char *buf; /* text read but not yet displayed */ |
45 | FILE *fp; /* FILE struct associated with file */ |
46 | FILE *fp; /* FILE struct associated with file */ |
46 | ino_t inode; /* inode of the file opened */ |
47 | ino_t inode; /* inode of the file opened */ |
47 | off_t last_size; /* file size at the last check */ |
48 | off_t last_size; /* file size at the last check */ |
48 | unsigned long color; /* color to be used for printing */ |
49 | unsigned long color; /* color to be used for printing */ |
|
|
50 | int partial; /* true if the last line isn't complete */ |
|
|
51 | int lastpartial; /* true if the previous output wasn't complete */ |
|
|
52 | int index; /* index into linematrix of a partial line */ |
49 | struct logfile_entry *next; |
53 | struct logfile_entry *next; |
50 | }; |
54 | }; |
51 | |
55 | |
52 | struct linematrix { |
56 | struct linematrix { |
53 | char *line; |
57 | char *line; |
… | |
… | |
58 | /* global variables */ |
62 | /* global variables */ |
59 | int width = STD_WIDTH, listlen = STD_HEIGHT; |
63 | int width = STD_WIDTH, listlen = STD_HEIGHT; |
60 | int win_x = LOC_X, win_y = LOC_Y; |
64 | int win_x = LOC_X, win_y = LOC_Y; |
61 | int w = -1, h = -1, font_width, font_height, font_descent; |
65 | int w = -1, h = -1, font_width, font_height, font_descent; |
62 | int do_reopen; |
66 | int do_reopen; |
63 | struct timeval interval = { 2, 400000 }; /* see Knuth */ |
67 | struct timeval interval = { 3, 0 }; /* see Knuth */ |
64 | XFontSet fontset; |
68 | XFontSet fontset; |
65 | |
69 | |
66 | /* command line options */ |
70 | /* command line options */ |
67 | int opt_noinitial, opt_shade, opt_frame, opt_reverse, opt_nofilename, |
71 | int opt_noinitial, opt_shade, opt_frame, opt_reverse, opt_nofilename, |
68 | geom_mask, reload = 3600; |
72 | opt_whole, opt_update, geom_mask, reload = 0; |
69 | const char *command = NULL, |
73 | const char *command = NULL, |
70 | *fontname = USE_FONT, *dispname = NULL, *def_color = DEF_COLOR; |
74 | *fontname = USE_FONT, *dispname = NULL, *def_color = DEF_COLOR, |
|
|
75 | *continuation = "[+]"; |
71 | |
76 | |
72 | struct logfile_entry *loglist = NULL, *loglist_tail = NULL; |
77 | struct logfile_entry *loglist = NULL, *loglist_tail = NULL; |
73 | |
78 | |
74 | Display *disp; |
79 | Display *disp; |
75 | Window root; |
80 | Window root; |
… | |
… | |
95 | unsigned long GetColor(const char *); |
100 | unsigned long GetColor(const char *); |
96 | void redraw(void); |
101 | void redraw(void); |
97 | void refresh(struct linematrix *, int, int); |
102 | void refresh(struct linematrix *, int, int); |
98 | |
103 | |
99 | void transform_line(char *s); |
104 | void transform_line(char *s); |
100 | int lineinput(char *, int, FILE *); |
105 | int lineinput(struct logfile_entry *); |
101 | void reopen(void); |
106 | void reopen(void); |
102 | void check_open_files(void); |
107 | void check_open_files(void); |
103 | FILE *openlog(struct logfile_entry *); |
108 | FILE *openlog(struct logfile_entry *); |
104 | void main_loop(void); |
109 | void main_loop(void); |
105 | |
110 | |
… | |
… | |
373 | * we really want to read width + 1 characters if the last char is a '\n', |
378 | * we really want to read width + 1 characters if the last char is a '\n', |
374 | * which we should remove afterwards. So, read width+1 chars and ungetc |
379 | * which we should remove afterwards. So, read width+1 chars and ungetc |
375 | * the last character if it's not a newline. This means 'string' must be |
380 | * the last character if it's not a newline. This means 'string' must be |
376 | * width + 2 wide! |
381 | * width + 2 wide! |
377 | */ |
382 | */ |
378 | int lineinput(char *string, int slen, FILE *f) |
383 | int lineinput(struct logfile_entry *logfile) |
379 | { |
384 | { |
380 | int len; |
385 | char *string = logfile->buf; |
|
|
386 | int slen = width + 2; |
|
|
387 | FILE *f = logfile->fp; |
|
|
388 | |
|
|
389 | int len = strlen(string); |
|
|
390 | int partial = logfile->partial; |
381 | |
391 | |
382 | do { |
392 | do { |
383 | if (fgets(string, slen, f) == NULL) /* EOF or Error */ |
393 | if (fgets(string + len, slen - len, f) == NULL) /* EOF or Error */ |
384 | return 0; |
394 | return 0; |
385 | |
395 | |
386 | len = strlen(string); |
396 | len = strlen(string); |
387 | } while (len == 0); |
397 | } while (len == 0); |
388 | |
398 | |
|
|
399 | logfile->partial = 0; |
|
|
400 | |
|
|
401 | /* if the string ends in a newline, delete the newline */ |
389 | if (string[len - 1] == '\n') |
402 | if (string[len - 1] == '\n') |
390 | string[len - 1] = '\0'; /* erase newline */ |
403 | string[len - 1] = '\0'; /* erase newline */ |
|
|
404 | /* otherwise if we've read one too many characters, un-read the last one and delete it */ |
391 | else if (len >= slen - 1) { |
405 | else if (len >= slen - 1) { |
392 | ungetc(string[len - 1], f); |
406 | ungetc(string[len - 1], f); |
393 | string[len - 1] = '\0'; |
407 | string[len - 1] = '\0'; |
394 | } |
408 | } else if (opt_whole) |
|
|
409 | return 0; |
|
|
410 | else |
|
|
411 | logfile->partial = 1; |
395 | |
412 | |
396 | #if HAS_REGEX |
413 | #if HAS_REGEX |
397 | transform_line(string); |
414 | transform_line(string); |
398 | #endif |
415 | #endif |
|
|
416 | logfile->lastpartial = partial; |
399 | return len; |
417 | return len; |
400 | } |
418 | } |
401 | |
419 | |
402 | /* input: reads file->fname |
420 | /* input: reads file->fname |
403 | * output: fills file->fp, file->inode |
421 | * output: fills file->fp, file->inode |
… | |
… | |
423 | |
441 | |
424 | if (opt_noinitial) |
442 | if (opt_noinitial) |
425 | fseek (file->fp, 0, SEEK_END); |
443 | fseek (file->fp, 0, SEEK_END); |
426 | else if (stats.st_size > (listlen + 1) * width) |
444 | else if (stats.st_size > (listlen + 1) * width) |
427 | { |
445 | { |
428 | char dummy[255]; |
|
|
429 | |
|
|
430 | fseek(file->fp, -((listlen + 2) * width), SEEK_END); |
446 | fseek(file->fp, -((listlen + 2) * width), SEEK_END); |
431 | /* the pointer might point halfway some line. Let's |
|
|
432 | be nice and skip this damaged line */ |
|
|
433 | lineinput(dummy, sizeof(dummy), file->fp); |
|
|
434 | } |
447 | } |
435 | |
448 | |
436 | file->last_size = stats.st_size; |
449 | file->last_size = stats.st_size; |
437 | return file->fp; |
450 | return file->fp; |
438 | } |
451 | } |
… | |
… | |
486 | } |
499 | } |
487 | |
500 | |
488 | #define SCROLL_UP(lines, listlen) \ |
501 | #define SCROLL_UP(lines, listlen) \ |
489 | { \ |
502 | { \ |
490 | int cur_line; \ |
503 | int cur_line; \ |
|
|
504 | struct logfile_entry *current; \ |
491 | for (cur_line = 0; cur_line < (listlen - 1); cur_line++) { \ |
505 | for (cur_line = 0; cur_line < (listlen - 1); cur_line++) { \ |
492 | strcpy(lines[cur_line].line, lines[cur_line + 1].line); \ |
506 | strcpy(lines[cur_line].line, lines[cur_line + 1].line); \ |
493 | lines[cur_line].color = lines[cur_line + 1].color; \ |
507 | lines[cur_line].color = lines[cur_line + 1].color; \ |
494 | } \ |
508 | } \ |
|
|
509 | for (current = loglist; current; current = current->next) \ |
|
|
510 | if (current->partial && current->index) \ |
|
|
511 | current->index--; \ |
495 | } |
512 | } |
496 | |
513 | |
497 | void main_loop(void) |
514 | void main_loop(void) |
498 | { |
515 | { |
499 | struct linematrix *lines = xmalloc(sizeof(struct linematrix) * listlen); |
516 | struct linematrix *lines = xmalloc(sizeof(struct linematrix) * listlen); |
500 | int lin, miny, maxy, buflen; |
517 | int lin, miny, maxy; |
501 | char *buf; |
|
|
502 | time_t lastreload; |
518 | time_t lastreload; |
503 | Region region = XCreateRegion(); |
519 | Region region = XCreateRegion(); |
504 | XEvent xev; |
520 | XEvent xev; |
|
|
521 | struct logfile_entry *lastprinted = NULL; |
|
|
522 | struct logfile_entry *current; |
505 | |
523 | |
506 | maxy = 0; |
524 | maxy = 0; |
507 | miny = win_y + h; |
525 | miny = win_y + h; |
508 | buflen = width + 2; |
|
|
509 | buf = xmalloc(buflen); |
|
|
510 | lastreload = time(NULL); |
526 | lastreload = time(NULL); |
511 | |
527 | |
512 | /* Initialize linematrix */ |
528 | /* Initialize linematrix */ |
513 | for (lin = 0; lin < listlen; lin++) { |
529 | for (lin = 0; lin < listlen; lin++) { |
514 | lines[lin].line = xmalloc(buflen); |
530 | lines[lin].line = xmalloc(width + 2); |
515 | strcpy(lines[lin].line, "~"); |
531 | strcpy(lines[lin].line, "~"); |
516 | lines[lin].color = GetColor(def_color); |
532 | lines[lin].color = GetColor(def_color); |
517 | } |
533 | } |
518 | |
534 | |
519 | if (!opt_noinitial) |
|
|
520 | { |
|
|
521 | while (lineinput(buf, buflen, loglist->fp) != 0) { |
|
|
522 | SCROLL_UP(lines, listlen); |
|
|
523 | /* print the next line */ |
|
|
524 | strcpy(lines[listlen - 1].line, buf); |
|
|
525 | } |
|
|
526 | |
|
|
527 | redraw (); |
|
|
528 | } |
|
|
529 | |
|
|
530 | for (;;) { |
535 | for (;;) { |
531 | int need_update = 0; |
536 | int need_update = 0; |
532 | struct logfile_entry *current; |
|
|
533 | static struct logfile_entry *lastprinted = NULL; |
|
|
534 | |
537 | |
535 | /* read logs */ |
538 | /* read logs */ |
536 | for (current = loglist; current; current = current->next) { |
539 | for (current = loglist; current; current = current->next) { |
537 | if (!current->fp) |
540 | if (!current->fp) |
538 | continue; /* skip missing files */ |
541 | continue; /* skip missing files */ |
539 | |
542 | |
540 | clearerr(current->fp); |
543 | clearerr(current->fp); |
541 | |
544 | |
542 | while (lineinput(buf, buflen, current->fp) != 0) { |
545 | while (lineinput(current) != 0) { |
|
|
546 | |
|
|
547 | /* if we're trying to update old partial lines in |
|
|
548 | * place, and the last time this file was updated the |
|
|
549 | * output was partial, and that partial line is not |
|
|
550 | * too close to the top of the screen, then update |
|
|
551 | * that partial line */ |
|
|
552 | if (opt_update && current->lastpartial && current->index >= 3) { |
|
|
553 | int old_len = strlen(lines[current->index].line); |
|
|
554 | int new_len = strlen(current->buf); |
|
|
555 | int space_on_old_line = width - old_len; |
|
|
556 | strncat(lines[current->index].line, current->buf, width - old_len); |
|
|
557 | /* if we can't fit the whole update into the old |
|
|
558 | * partial line then we're going to have to print |
|
|
559 | * the rest of it at the bottom on the screen */ |
|
|
560 | if (new_len > space_on_old_line) { |
|
|
561 | /* strcpy() doesn't like the strings to |
|
|
562 | * overlap in memory, but memmove() doesn't |
|
|
563 | * care */ |
|
|
564 | memmove(current->buf, |
|
|
565 | current->buf + space_on_old_line, |
|
|
566 | new_len - space_on_old_line + 1); |
|
|
567 | } else { |
|
|
568 | need_update = 1; |
|
|
569 | strcpy(current->buf, ""); |
|
|
570 | continue; |
|
|
571 | } |
|
|
572 | } |
|
|
573 | |
543 | /* print filename if any, and if last line was from |
574 | /* print filename if any, and if last line was from |
544 | different file */ |
575 | * different file */ |
545 | if (!opt_nofilename && |
576 | if (!opt_nofilename && |
546 | !(lastprinted && lastprinted == current) && |
577 | lastprinted != current && |
547 | current->desc[0]) { |
578 | current->desc[0]) { |
548 | SCROLL_UP(lines, listlen); |
579 | SCROLL_UP(lines, listlen); |
549 | sprintf(lines[listlen - 1].line, "[%s]", current->desc); |
580 | sprintf(lines[listlen - 1].line, "[%s]", current->desc); |
550 | lines[listlen - 1].color = current->color; |
581 | lines[listlen - 1].color = current->color; |
551 | } |
582 | } |
552 | |
583 | |
|
|
584 | /* if this is the same file we showed last, and the |
|
|
585 | * last time we showed it, it wasn't finished, then |
|
|
586 | * append to the last line shown */ |
|
|
587 | if (lastprinted == current && current->lastpartial) { |
|
|
588 | int old_len = strlen(lines[listlen - 1].line); |
|
|
589 | int new_len = strlen(current->buf); |
|
|
590 | strncat(lines[listlen - 1].line, current->buf, width - old_len); |
|
|
591 | /* if it doesn't all fit, then put the part that |
|
|
592 | * doesn't fit on a new line */ |
|
|
593 | if (new_len > width - old_len) { |
553 | SCROLL_UP(lines, listlen); |
594 | SCROLL_UP(lines, listlen); |
|
|
595 | strcpy(lines[listlen - 1].line, current->buf + width - old_len); |
|
|
596 | } |
|
|
597 | /* show the 'continuation' string because we've got a |
|
|
598 | * continued partial line, but we weren't able to |
|
|
599 | * append it to the old displayed partial line */ |
|
|
600 | } else if (current->lastpartial) { |
|
|
601 | int old_len = strlen(continuation); |
|
|
602 | int new_len = strlen(current->buf); |
|
|
603 | SCROLL_UP(lines, listlen); |
|
|
604 | strcpy(lines[listlen - 1].line, continuation); |
|
|
605 | strncat(lines[listlen - 1].line, current->buf, width - old_len); |
|
|
606 | /* it might not fit, now that we've displayed the |
|
|
607 | * continuation string, so we may need to 'wrap' it */ |
|
|
608 | if (new_len > width - old_len) { |
|
|
609 | SCROLL_UP(lines, listlen); |
|
|
610 | strcpy(lines[listlen - 1].line, current->buf + width - old_len); |
|
|
611 | } |
|
|
612 | } else { |
|
|
613 | SCROLL_UP(lines, listlen); |
554 | strcpy(lines[listlen - 1].line, buf); |
614 | strcpy(lines[listlen - 1].line, current->buf); |
|
|
615 | } |
|
|
616 | |
|
|
617 | /* we've shown the line now. clear the buffer for the next line */ |
|
|
618 | strcpy(current->buf, ""); |
|
|
619 | current->index = listlen - 1; |
555 | lines[listlen - 1].color = current->color; |
620 | lines[listlen - 1].color = current->color; |
556 | |
621 | |
557 | lastprinted = current; |
622 | lastprinted = current; |
558 | need_update = 1; |
623 | need_update = 1; |
559 | } |
624 | } |
… | |
… | |
605 | } |
670 | } |
606 | } |
671 | } |
607 | |
672 | |
608 | /* reload if requested */ |
673 | /* reload if requested */ |
609 | if (reload && lastreload + reload < time(NULL)) { |
674 | if (reload && lastreload + reload < time(NULL)) { |
610 | if (command) |
675 | if (command && command[0]) |
611 | system(command); |
676 | system(command); |
612 | |
677 | |
613 | reopen(); |
678 | reopen(); |
614 | lastreload = time(NULL); |
679 | lastreload = time(NULL); |
615 | } |
680 | } |
… | |
… | |
628 | |
693 | |
629 | int main(int argc, char *argv[]) |
694 | int main(int argc, char *argv[]) |
630 | { |
695 | { |
631 | int i; |
696 | int i; |
632 | int opt_daemonize = 0; |
697 | int opt_daemonize = 0; |
|
|
698 | int opt_partial = 0, file_count = 0; |
633 | #if HAS_REGEX |
699 | #if HAS_REGEX |
634 | char *transform = NULL; |
700 | char *transform = NULL; |
635 | #endif |
701 | #endif |
636 | |
702 | |
637 | setlocale (LC_CTYPE, ""); /* try to initialize the locale. */ |
703 | setlocale (LC_CTYPE, ""); /* try to initialize the locale. */ |
… | |
… | |
656 | else if (!strcmp(arg, "-g") || !strcmp(arg, "-geometry")) |
722 | else if (!strcmp(arg, "-g") || !strcmp(arg, "-geometry")) |
657 | geom_mask = XParseGeometry(argv[++i], |
723 | geom_mask = XParseGeometry(argv[++i], |
658 | &win_x, &win_y, &width, &listlen); |
724 | &win_x, &win_y, &width, &listlen); |
659 | else if (!strcmp(arg, "-display")) |
725 | else if (!strcmp(arg, "-display")) |
660 | dispname = argv[++i]; |
726 | dispname = argv[++i]; |
|
|
727 | else if (!strcmp(arg, "-cont")) |
|
|
728 | continuation = argv[++i]; |
661 | else if (!strcmp(arg, "-font") || !strcmp(arg, "-fn")) |
729 | else if (!strcmp(arg, "-font") || !strcmp(arg, "-fn")) |
662 | fontname = argv[++i]; |
730 | fontname = argv[++i]; |
663 | #if HAS_REGEX |
731 | #if HAS_REGEX |
664 | else if (!strcmp(arg, "-t")) |
732 | else if (!strcmp(arg, "-t")) |
665 | transform = argv[++i]; |
733 | transform = argv[++i]; |
… | |
… | |
676 | opt_frame = 1; |
744 | opt_frame = 1; |
677 | else if (!strcmp(arg, "-no-filename")) |
745 | else if (!strcmp(arg, "-no-filename")) |
678 | opt_nofilename = 1; |
746 | opt_nofilename = 1; |
679 | else if (!strcmp(arg, "-reverse")) |
747 | else if (!strcmp(arg, "-reverse")) |
680 | opt_reverse = 1; |
748 | opt_reverse = 1; |
|
|
749 | else if (!strcmp(arg, "-whole")) |
|
|
750 | opt_whole = 1; |
|
|
751 | else if (!strcmp(arg, "-partial")) |
|
|
752 | opt_partial = 1; |
|
|
753 | else if (!strcmp(arg, "-update")) |
|
|
754 | opt_update = opt_partial = 1; |
681 | else if (!strcmp(arg, "-color")) |
755 | else if (!strcmp(arg, "-color")) |
682 | def_color = argv[++i]; |
756 | def_color = argv[++i]; |
683 | else if (!strcmp(arg, "-noinitial")) |
757 | else if (!strcmp(arg, "-noinitial")) |
684 | opt_noinitial = 1; |
758 | opt_noinitial = 1; |
685 | else if (!strcmp(arg, "-id")) |
759 | else if (!strcmp(arg, "-id")) |
… | |
… | |
697 | } else { /* it must be a filename */ |
771 | } else { /* it must be a filename */ |
698 | struct logfile_entry *e; |
772 | struct logfile_entry *e; |
699 | const char *fname, *desc, *fcolor = def_color; |
773 | const char *fname, *desc, *fcolor = def_color; |
700 | char *p; |
774 | char *p; |
701 | |
775 | |
|
|
776 | file_count++; |
|
|
777 | |
702 | /* this is not foolproof yet (',' in filenames are not allowed) */ |
778 | /* this is not foolproof yet (',' in filenames are not allowed) */ |
703 | fname = desc = arg; |
779 | fname = desc = arg; |
704 | if ((p = strchr(arg, ','))) { |
780 | if ((p = strchr(arg, ','))) { |
705 | *p = '\0'; |
781 | *p = '\0'; |
706 | fcolor = p + 1; |
782 | fcolor = p + 1; |
… | |
… | |
734 | memcpy(e->desc, desc, l); |
810 | memcpy(e->desc, desc, l); |
735 | *(e->desc + l) = '\0'; |
811 | *(e->desc + l) = '\0'; |
736 | } |
812 | } |
737 | |
813 | |
738 | e->color = GetColor(fcolor); |
814 | e->color = GetColor(fcolor); |
|
|
815 | e->buf = xmalloc(width + 2); |
|
|
816 | e->partial = 0; |
|
|
817 | e->buf[0] = '\0'; |
739 | e->next = NULL; |
818 | e->next = NULL; |
740 | |
819 | |
741 | if (!loglist) |
820 | if (!loglist) |
742 | loglist = e; |
821 | loglist = e; |
743 | if (loglist_tail) |
822 | if (loglist_tail) |
… | |
… | |
748 | |
827 | |
749 | if (!loglist) { |
828 | if (!loglist) { |
750 | fprintf(stderr, "You did not specify any files to tail\n" |
829 | fprintf(stderr, "You did not specify any files to tail\n" |
751 | "use %s --help for help\n", argv[0]); |
830 | "use %s --help for help\n", argv[0]); |
752 | exit(1); |
831 | exit(1); |
|
|
832 | } |
|
|
833 | |
|
|
834 | if (opt_partial && opt_whole) { |
|
|
835 | fprintf(stderr, "Specify at most one of -partial and -whole\n"); |
|
|
836 | exit(1); |
|
|
837 | } |
|
|
838 | |
|
|
839 | /* if we specifically requested to see partial lines then don't insist on whole lines */ |
|
|
840 | if (opt_partial) { |
|
|
841 | opt_whole = 0; |
|
|
842 | /* otherwise, if we've viewing multiple files, default to showing whole lines */ |
|
|
843 | } else if (file_count > 1) { |
|
|
844 | opt_whole = 1; |
753 | } |
845 | } |
754 | |
846 | |
755 | #if HAS_REGEX |
847 | #if HAS_REGEX |
756 | if (transform) { |
848 | if (transform) { |
757 | int i; |
849 | int i; |
… | |
… | |
822 | printf("Usage: %s [options] file1[,color[,desc]] " |
914 | printf("Usage: %s [options] file1[,color[,desc]] " |
823 | "[file2[,color[,desc]] ...]\n", myname); |
915 | "[file2[,color[,desc]] ...]\n", myname); |
824 | printf(" -g | -geometry geometry -g WIDTHxHEIGHT+X+Y\n" |
916 | printf(" -g | -geometry geometry -g WIDTHxHEIGHT+X+Y\n" |
825 | " -color color use color $color as default\n" |
917 | " -color color use color $color as default\n" |
826 | " -reload sec command reload after $sec and run command\n" |
918 | " -reload sec command reload after $sec and run command\n" |
827 | " by default -- 3 mins\n" |
|
|
828 | " -id id window id to use instead of the root window\n" |
919 | " -id id window id to use instead of the root window\n" |
829 | " -font FONTSPEC (-fn) font to use\n" |
920 | " -font FONTSPEC (-fn) font to use\n" |
830 | " -f | -fork fork into background\n" |
921 | " -f | -fork fork into background\n" |
831 | " -reverse print new lines at the top\n" |
922 | " -reverse print new lines at the top\n" |
|
|
923 | " -whole wait for \\n before showing a line\n" |
|
|
924 | " -partial show lines even if they don't end with a \\n\n" |
|
|
925 | " -update allow updates to old partial lines\n" |
|
|
926 | " -cont string to prefix continued partial lines with\n" |
|
|
927 | " defaults to \"[+]\"\n" |
832 | " -shade add shading to font\n" |
928 | " -shade add shading to font\n" |
833 | " -noinitial don't display the last file lines on\n" |
929 | " -noinitial don't display the last file lines on\n" |
834 | " startup\n" |
930 | " startup\n" |
835 | " -i | -interval seconds interval between checks (fractional\n" |
931 | " -i | -interval seconds interval between checks (fractional\n" |
836 | " values o.k.). Default 3\n" |
932 | " values o.k.). Default 3 seconds\n" |
837 | " -V display version information and exit\n" |
933 | " -V display version information and exit\n" |
838 | "\n"); |
934 | "\n"); |
839 | printf("Example:\n%s -g 80x25+100+50 -font fixed /var/log/messages,green " |
935 | printf("Example:\n%s -g 80x25+100+50 -font fixed /var/log/messages,green " |
840 | "/var/log/secure,red,'ALERT'\n", myname); |
936 | "/var/log/secure,red,'ALERT'\n", myname); |
841 | exit(0); |
937 | exit(0); |