ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/root-tail/root-tail.c
(Generate patch)

Comparing root-tail/root-tail.c (file contents):
Revision 1.31 by chris_moore, Tue Mar 30 23:23:46 2004 UTC vs.
Revision 1.47 by pcg, Thu Apr 1 13:37:30 2004 UTC

75struct displaymatrix 75struct displaymatrix
76{ 76{
77 char *line; 77 char *line;
78 int len; 78 int len;
79 int buffer_size; 79 int buffer_size;
80 unsigned long color;
80}; 81};
81 82
82/* global variables */ 83/* global variables */
83struct linematrix *lines; 84struct linematrix *lines;
84struct displaymatrix *display; 85struct displaymatrix *display;
404 /* if this line is a different than it was, then it 405 /* if this line is a different than it was, then it
405 * needs displaying */ 406 * needs displaying */
406 if (!opt_noflicker 407 if (!opt_noflicker
407 || refresh_all 408 || refresh_all
408 || display_line->len != line->len 409 || display_line->len != line->len
410 || display_line->color != line->color
409 || memcmp (display_line->line, line->line, line->len)) 411 || memcmp (display_line->line, line->line, line->len))
410 { 412 {
411 /* don't bother updating the record of what has been 413 /* don't bother updating the record of what has been
412 * displayed if -noflicker isn't in effect, since we redraw 414 * displayed if -noflicker isn't in effect, since we redraw
413 * the whole display every time anyway */ 415 * the whole display every time anyway */
414 if (opt_noflicker) 416 if (opt_noflicker)
415 { 417 {
416 /* update the record of what has been displayed; 418 /* update the record of what has been displayed;
417 * first make sure the buffer is big enough */ 419 * first make sure the buffer is big enough */
418 if (display_line->buffer_size <= line->len) 420 if (display_line->buffer_size < line->len)
419 { 421 {
420 display_line->buffer_size = line->len + 1; 422 display_line->buffer_size = line->len;
421 display_line->line = xrealloc (display_line->line, display_line->buffer_size); 423 display_line->line = xrealloc (display_line->line, display_line->buffer_size);
422 } 424 }
423 425
424 display_line->len = line->len; 426 display_line->len = line->len;
427 display_line->color = line->color;
425 memcpy (display_line->line, line->line, line->len); 428 memcpy (display_line->line, line->line, line->len);
426 429
427 if (clear) 430 if (clear)
428 XClearArea (disp, root, win_x, win_y + offset - font_ascent, 431 XClearArea (disp, root, win_x, win_y + offset - font_ascent,
429 width + effect_x_space, font_height + effect_y_space, False); 432 width + effect_x_space, font_height + effect_y_space, False);
432 if (opt_outline) 435 if (opt_outline)
433 { 436 {
434 int x, y; 437 int x, y;
435 XSetForeground (disp, WinGC, black_color); 438 XSetForeground (disp, WinGC, black_color);
436 439
437 for (x = -1; x < 2; x += 2) 440 for (x = -1; x <= 1; x += 2)
438 for (y = -1; y < 2; y += 2) 441 for (y = -1; y <= 1; y += 2)
439 XmbDrawString (disp, root, fontset, WinGC, 442 XmbDrawString (disp, root, fontset, WinGC,
440 win_x + effect_x_offset + x, 443 win_x + effect_x_offset + x,
441 win_y + y + offset, 444 win_y + y + offset,
442 line->line, line->len); 445 line->line, line->len);
443 } 446 }
488 if (i == 0) 491 if (i == 0)
489 { /* matched */ 492 { /* matched */
490 int match_start = matched[0].rm_so; 493 int match_start = matched[0].rm_so;
491 int match_end = matched[0].rm_eo; 494 int match_end = matched[0].rm_eo;
492 int old_len = match_end - match_start; 495 int old_len = match_end - match_start;
493 int new_len = strlen(transform_to); 496 int new_len = strlen (transform_to);
494 int old_whole_len = strlen(s); 497 int old_whole_len = strlen (s);
498
495 printf("regexp was matched by '%s' - replace with '%s'\n", s, transform_to); 499 printf ("regexp was matched by '%s' - replace with '%s'\n", s, transform_to);
496 printf("match is from %d to %d\n", 500 printf ("match is from %d to %d\n", match_start, match_end);
497 match_start, match_end);
498 if (new_len > old_len) { 501 if (new_len > old_len)
499 s = xrealloc(s, old_whole_len + new_len - old_len); 502 s = xrealloc(s, old_whole_len + new_len - old_len);
500 } 503
501 if (new_len != old_len) { 504 if (new_len != old_len)
505 {
502 memcpy(s + match_end + new_len - old_len, 506 memcpy(s + match_end + new_len - old_len,
503 s + match_end, 507 s + match_end,
504 old_whole_len - match_end); 508 old_whole_len - match_end);
505 s[old_whole_len + new_len - old_len] = '\0'; 509 s[old_whole_len + new_len - old_len] = '\0';
506 } 510 }
511
507 memcpy(s + match_start, 512 memcpy (s + match_start,
508 transform_to, 513 transform_to,
509 new_len); 514 new_len);
510 printf("transformed to '%s'\n", s); 515 printf ("transformed to '%s'\n", s);
511 } 516 }
512 else 517 else
513 { 518 {
514 printf("regexp was not matched by '%s'\n", s); 519 printf ("regexp was not matched by '%s'\n", s);
515 } 520 }
516 } 521 }
517} 522}
518#endif 523#endif
519 524
530 535
531 return r; 536 return r;
532} 537}
533 538
534/* 539/*
535 * This routine should read a single line, no matter how long. 540 * This routine can read a line of any length if it is called enough times.
536 */ 541 */
537int 542int
538lineinput (struct logfile_entry *logfile) 543lineinput (struct logfile_entry *logfile)
539{ 544{
540 char buff[1024], *p = buff; 545 char buff[1024], *p;
541 int ch; 546 int ch;
542 /* HACK this - to add on the length of any partial line which we will be appending to */ 547 /* HACK-2: add on the length of any partial line which we will be appending to */
543 int ofs = logfile->buf ? strlen (logfile->buf) : 0; 548 int ofs = logfile->buf ? strlen (logfile->buf) : 0;
544 549
550 /* this loop ensures that the whole line is read, even if it's
551 * longer than the buffer. we need to do this because when --whole
552 * is in effect we don't know whether to display the line or not
553 * until we've seen how (ie. whether) it ends */
545 do 554 do
546 { 555 {
556 p = buff;
557 do
558 {
547 ch = fgetc (logfile->fp); 559 ch = fgetc (logfile->fp);
548 560
549 if (ch == '\n' || ch == EOF) 561 if (ch == '\n' || ch == EOF)
550 break; 562 break;
551 else if (ch == '\r') 563 else if (ch == '\r')
552 continue; /* skip */ 564 continue; /* skip */
553 else if (ch == '\t') 565 else if (ch == '\t')
554 { 566 {
555 do 567 do
556 { 568 {
557 *p++ = ' '; 569 *p++ = ' ';
558 ofs++; 570 ofs++;
559 } 571 }
560 while (ofs & 7); 572 while (ofs & 7);
561 }
562 else
563 {
564 *p++ = ch;
565 ofs++;
566 }
567 } 573 }
574 else
575 {
576 *p++ = ch;
577 ofs++;
578 }
579 }
568 while (p < buff + (sizeof buff) - 8 - 1); 580 while (p < buff + (sizeof buff) - 8 - 1);
569 581
570 if (p == buff && ch == EOF) 582 if (p == buff && ch == EOF)
571 return 0; 583 return 0;
572 584
573 *p = 0; 585 *p = 0;
574 586
575 p = concat_line (logfile->buf, buff); 587 p = concat_line (logfile->buf, buff);
576 free (logfile->buf); logfile->buf = p; 588 free (logfile->buf); logfile->buf = p;
589 }
590 while (ch != '\n' && ch != EOF);
577 591
578 logfile->lastpartial = logfile->partial; 592 logfile->lastpartial = logfile->partial;
579 /* there are 3 ways we could have exited the loop: reading '\n', 593 /* there are 3 ways we could have exited the loop: reading '\n',
580 * reaching EOF, or filling the buffer; the 2nd and 3rd of these 594 * reaching EOF, or filling the buffer; the 2nd and 3rd of these
581 * both result in a partial line */ 595 * both result in a partial line */
660 sleep (1); 674 sleep (1);
661 if (e->fp) 675 if (e->fp)
662 fclose (e->fp); 676 fclose (e->fp);
663 if (openlog (e) == NULL) 677 if (openlog (e) == NULL)
664 continue; 678 continue;
679 if (fstat (fileno (e->fp), &stats) < 0)
680 continue;
665 } 681 }
666 682
667 /* HACK this - stats can be uninitialised here (if the file
668 * didn't exist when stat() was called, but was recreated during
669 * the sleep(1)) */
670 if (stats.st_ino != e->inode) 683 if (stats.st_ino != e->inode)
671 { /* file renamed? */ 684 { /* file renamed? */
672 if (e->fp) 685 if (e->fp)
673 fclose (e->fp); 686 fclose (e->fp);
674 if (openlog (e) == NULL) 687 if (openlog (e) == NULL)
688 continue;
689 if (fstat (fileno (e->fp), &stats) < 0)
675 continue; 690 continue;
676 } 691 }
677 692
678 if (stats.st_size < e->last_size) 693 if (stats.st_size < e->last_size)
679 { /* file truncated? */ 694 { /* file truncated? */
731 */ 746 */
732static void 747static void
733split_line (int idx, const char *str, unsigned long color) 748split_line (int idx, const char *str, unsigned long color)
734{ 749{
735 int l = strlen (str); 750 int l = strlen (str);
751 int last_wrapped = 0;
736 const char *p = str; 752 const char *p = str;
753 static int continuation_width = -1;
754 static int continuation_length;
755
756 /* only calculate the continuation's width once */
757 if (continuation_width == -1)
758 {
759 continuation_length = strlen (continuation);
760 continuation_width = XmbTextEscapement (fontset, continuation, continuation_length);
761 }
737 762
738 do 763 do
739 { 764 {
740 const char *beg = p; 765 const char *beg = p;
766 int w = last_wrapped ? continuation_width : 0;
741 int w = 0, wrapped = 0; 767 int wrapped = 0;
742 const char *break_p = NULL; 768 const char *break_p = NULL;
743 769
744 while (*p) 770 while (*p)
745 { 771 {
772 int cw, len;
773
746 /* find the length in bytes of the next multibyte character */ 774 /* find the length in bytes of the next multibyte character */
747 int len = mblen (p, l); 775 len = mblen (p, l);
748 if (len <= 0) 776 if (len <= 0)
749 len = 1; /* ignore (don't skip) illegal character sequences */ 777 len = 1; /* ignore (don't skip) illegal character sequences */
750 778
751 /* find the width in pixels of the next character */ 779 /* find the width in pixels of the next character */
752 int cw = XmbTextEscapement (fontset, p, len); 780 cw = XmbTextEscapement (fontset, p, len);
753 if (cw + w > width - effect_x_space) 781 if (cw + w > width - effect_x_space)
754 { 782 {
783 if (p == beg)
784 {
785 fprintf (stderr, "we can't even fit a single character onto the line\n");
786 if (len == 1) fprintf (stderr, "(the character we couldn't fit was '%c')\n", *p);
787 exit (1);
788 }
789
755 wrapped = 1; 790 wrapped = 1;
756 break; 791 break;
757 } 792 }
758 793
759 if (opt_wordwrap && len == 1 && p[0] == ' ') 794 if (opt_wordwrap && len == 1 && p[0] == ' ')
772 l += p - break_p; 807 l += p - break_p;
773 p = break_p; 808 p = break_p;
774 } 809 }
775 810
776 { 811 {
812 int len = p - beg + (last_wrapped ? continuation_length : 0);
777 char *s = xmalloc (p - beg + 1); 813 char *s = xmalloc (len + 1);
778 memcpy (s, beg, p - beg); 814 if (last_wrapped)
815 {
816 memcpy (s, continuation, continuation_length);
817 memcpy (s + continuation_length, beg, p - beg);
818 }
819 else
820 memcpy (s, beg, len);
821
779 s[p - beg] = 0; 822 s[len] = 0;
780 insert_line (idx); 823 insert_line (idx);
781 lines[idx].line = s; 824 lines[idx].line = s;
782 lines[idx].len = p - beg; 825 lines[idx].len = len;
783 lines[idx].color = color; 826 lines[idx].color = color;
784 } 827 }
785 828
786 /* if we wrapped at a space, don't display the space */ 829 /* if we wrapped at a space, don't display the space */
787 if (opt_wordwrap && wrapped && break_p && break_p != beg) 830 if (opt_wordwrap && wrapped && break_p && break_p != beg)
788 { 831 {
789 l--; 832 l--;
790 p++; 833 p++;
791 } 834 }
835
836 last_wrapped = wrapped;
792 } 837 }
793 while (l); 838 while (l);
794} 839}
795 840
796/* 841/*
812} 857}
813 858
814static void 859static void
815main_loop (void) 860main_loop (void)
816{ 861{
817 lines = xmalloc (sizeof (struct linematrix) * listlen);
818 display = xmalloc (sizeof (struct displaymatrix) * listlen);
819 int lin; 862 int lin;
820 time_t lastreload; 863 time_t lastreload;
821 Region region = XCreateRegion (); 864 Region region = XCreateRegion ();
822 XEvent xev; 865 XEvent xev;
823 struct logfile_entry *lastprinted = NULL; 866 struct logfile_entry *lastprinted = NULL;
824 struct logfile_entry *current; 867 struct logfile_entry *current;
825 int need_update = 1; 868 int need_update = 1;
826 869
870 lines = xmalloc (sizeof (struct linematrix) * listlen);
871 display = xmalloc (sizeof (struct displaymatrix) * listlen);
872
827 lastreload = time (NULL); 873 lastreload = time (NULL);
828 874
829 /* Initialize linematrix */ 875 /* Initialize linematrix */
830 for (lin = 0; lin < listlen; lin++) 876 for (lin = 0; lin < listlen; lin++)
831 { 877 {
832 lines[lin].line = xstrdup ("~"); 878 lines[lin].line = xstrdup ("~");
833 lines[lin].len = 1; 879 lines[lin].len = 1;
834 display[lin].line = xstrdup(""); 880 display[lin].line = xstrdup("");
835 display[lin].len = 0; 881 display[lin].len = 0;
836 display[lin].buffer_size = 1; 882 display[lin].buffer_size = 0;
837 lines[lin].color = GetColor (def_color); 883 lines[lin].color = GetColor (def_color);
838 } 884 }
839 885
840 for (;;) 886 for (;;)
841 { 887 {
866 912
867 /* print filename if any, and if last line was from 913 /* print filename if any, and if last line was from
868 * different file */ 914 * different file */
869 if (!opt_nofilename && lastprinted != current && current->desc[0]) 915 if (!opt_nofilename && lastprinted != current && current->desc[0])
870 { 916 {
871 char buf[1024]; /* HACK */
872 snprintf (buf, sizeof (buf), "[%s]", current->desc);
873 split_line (listlen - 1, buf, current->color); 917 split_line (listlen - 1, "[", current->color);
918 append_line (listlen - 1, current->desc);
919 append_line (listlen - 1, "]");
874 } 920 }
875 921
876 /* if we're dealing with partial lines, and the last 922 /* if we're dealing with partial lines, and the last
877 * time we showed the line it wasn't finished ... */ 923 * time we showed the line it wasn't finished ... */
878 if (!opt_whole && current->lastpartial) 924 if (!opt_whole && current->lastpartial)
1104 { 1150 {
1105 if ((e->fp = fdopen (0, "r")) == NULL) 1151 if ((e->fp = fdopen (0, "r")) == NULL)
1106 perror ("fdopen"), exit (1); 1152 perror ("fdopen"), exit (1);
1107 if (fcntl (0, F_SETFL, O_NONBLOCK) < 0) 1153 if (fcntl (0, F_SETFL, O_NONBLOCK) < 0)
1108 perror ("fcntl"), exit (1); 1154 perror ("fcntl"), exit (1);
1155
1109 e->fname = NULL; 1156 e->fname = NULL;
1110 e->inode = 0; 1157 e->inode = 0;
1111 e->desc = xstrdup ("stdin"); 1158 e->desc = xstrdup ("stdin");
1112 } 1159 }
1113 else 1160 else
1114 { 1161 {
1115 int l;
1116
1117 e->fname = xstrdup (fname); 1162 e->fname = xstrdup (fname);
1163
1118 if (openlog (e) == NULL) 1164 if (openlog (e) == NULL)
1119 perror (fname), exit (1); 1165 perror (fname), exit (1);
1120 1166
1121 l = strlen (desc); 1167 e->desc = xstrdup (desc);
1122 /* HACK on this - width is in pixels now */
1123 if (l > width - 2) /* must account for [ ] */
1124 l = width - 2;
1125 e->desc = xmalloc (l + 1);
1126 memcpy (e->desc, desc, l);
1127 *(e->desc + l) = '\0';
1128 } 1168 }
1129 1169
1130 e->color = GetColor (fcolor); 1170 e->color = GetColor (fcolor);
1131 e->partial = 0; 1171 e->partial = 0;
1132 e->next = NULL; 1172 e->next = NULL;
1133 1173
1134 if (!loglist) 1174 if (!loglist)
1135 loglist = e; 1175 loglist = e;
1136 if (loglist_tail) 1176 if (loglist_tail)
1137 loglist_tail->next = e; 1177 loglist_tail->next = e;
1178
1138 loglist_tail = e; 1179 loglist_tail = e;
1139 } 1180 }
1140 } 1181 }
1141 1182
1142 if (!loglist) 1183 if (!loglist)
1144 fprintf (stderr, "You did not specify any files to tail\n" 1185 fprintf (stderr, "You did not specify any files to tail\n"
1145 "use %s --help for help\n", argv[0]); 1186 "use %s --help for help\n", argv[0]);
1146 exit (1); 1187 exit (1);
1147 } 1188 }
1148 1189
1190 if (opt_update && opt_whole)
1191 {
1192 fprintf (stderr, "Specify at most one of -update and -whole\n");
1193 exit (1);
1194 }
1149 if (opt_partial && opt_whole) 1195 else if (opt_partial && opt_whole)
1150 { 1196 {
1151 fprintf (stderr, "Specify at most one of -partial and -whole\n"); 1197 fprintf (stderr, "Specify at most one of -partial and -whole\n");
1152 exit (1); 1198 exit (1);
1153 } 1199 }
1154 1200
1155 /* HACK this - do we want to allow both -shade and -outline? */ 1201 /* HACK-7: do we want to allow both -shade and -outline? */
1156 if (opt_shade && opt_outline) 1202 if (opt_shade && opt_outline)
1157 { 1203 {
1158 fprintf (stderr, "Specify at most one of -shade and -outline\n"); 1204 fprintf (stderr, "Specify at most one of -shade and -outline\n");
1159 exit (1); 1205 exit (1);
1160 } 1206 }
1223{ 1269{
1224 void *p; 1270 void *p;
1225 1271
1226 while ((p = strdup (string)) == NULL) 1272 while ((p = strdup (string)) == NULL)
1227 { 1273 {
1228 fprintf (stderr, "Memory exausted."); 1274 fprintf (stderr, "Memory exhausted in xstrdup().\n");
1229 sleep (10); 1275 sleep (10);
1230 } 1276 }
1231 1277
1232 return p; 1278 return p;
1233} 1279}
1237{ 1283{
1238 void *p; 1284 void *p;
1239 1285
1240 while ((p = malloc (size)) == NULL) 1286 while ((p = malloc (size)) == NULL)
1241 { 1287 {
1242 fprintf (stderr, "Memory exausted."); 1288 fprintf (stderr, "Memory exhausted in xmalloc().\n");
1243 sleep (10); 1289 sleep (10);
1244 } 1290 }
1245 1291
1246 return p; 1292 return p;
1247} 1293}
1251{ 1297{
1252 void *p; 1298 void *p;
1253 1299
1254 while ((p = realloc (ptr, size)) == NULL) 1300 while ((p = realloc (ptr, size)) == NULL)
1255 { 1301 {
1256 fprintf (stderr, "Memory exausted."); 1302 fprintf (stderr, "Memory exhausted in xrealloc().\n");
1257 sleep (10); 1303 sleep (10);
1258 } 1304 }
1259 1305
1260 return p; 1306 return p;
1261} 1307}
1283 " startup\n" 1329 " startup\n"
1284 " -i | -interval seconds interval between checks (fractional\n" 1330 " -i | -interval seconds interval between checks (fractional\n"
1285 " values o.k.). Default 2.4 seconds\n" 1331 " values o.k.). Default 2.4 seconds\n"
1286 " -V display version information and exit\n" 1332 " -V display version information and exit\n"
1287 "\n"); 1333 "\n");
1288 printf ("Example:\n%s -g 80x25+100+50 -font fixed /var/log/messages,green " 1334 printf ("Example:\n%s -g 800x250+100+50 -font fixed /var/log/messages,green "
1289 "/var/log/secure,red,'ALERT'\n", myname); 1335 "/var/log/secure,red,'ALERT'\n", myname);
1290 exit (0); 1336 exit (0);
1291} 1337}
1292 1338
1293void 1339void

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines