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.35 by chris_moore, Wed Mar 31 00:48:12 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 * HACK-1: 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-2: 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-3: stats can be uninitialised here (if the file didn't
668 * exist when stat() was called, but was recreated during the
669 * 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? */
739 static int continuation_length; 754 static int continuation_length;
740 755
741 /* only calculate the continuation's width once */ 756 /* only calculate the continuation's width once */
742 if (continuation_width == -1) 757 if (continuation_width == -1)
743 { 758 {
744 continuation_length = strlen(continuation); 759 continuation_length = strlen (continuation);
745 continuation_width = XmbTextEscapement (fontset, continuation, continuation_length); 760 continuation_width = XmbTextEscapement (fontset, continuation, continuation_length);
746 } 761 }
747 762
748 do 763 do
749 { 764 {
752 int wrapped = 0; 767 int wrapped = 0;
753 const char *break_p = NULL; 768 const char *break_p = NULL;
754 769
755 while (*p) 770 while (*p)
756 { 771 {
772 int cw, len;
773
757 /* find the length in bytes of the next multibyte character */ 774 /* find the length in bytes of the next multibyte character */
758 int len = mblen (p, l); 775 len = mblen (p, l);
759 if (len <= 0) 776 if (len <= 0)
760 len = 1; /* ignore (don't skip) illegal character sequences */ 777 len = 1; /* ignore (don't skip) illegal character sequences */
761 778
762 /* find the width in pixels of the next character */ 779 /* find the width in pixels of the next character */
763 int cw = XmbTextEscapement (fontset, p, len); 780 cw = XmbTextEscapement (fontset, p, len);
764 if (cw + w > width - effect_x_space) 781 if (cw + w > width - effect_x_space)
765 { 782 {
766 if (p == beg) 783 if (p == beg)
767 { 784 {
768 fprintf(stderr, "we can't even fit a single character onto the line\n"); 785 fprintf (stderr, "we can't even fit a single character onto the line\n");
769 if (len == 1) fprintf(stderr, "(the character we couldn't fit was '%c')\n", *p); 786 if (len == 1) fprintf (stderr, "(the character we couldn't fit was '%c')\n", *p);
770 exit(1); 787 exit (1);
771 } 788 }
772 789
773 wrapped = 1; 790 wrapped = 1;
774 break; 791 break;
775 } 792 }
790 l += p - break_p; 807 l += p - break_p;
791 p = break_p; 808 p = break_p;
792 } 809 }
793 810
794 { 811 {
795 /* HACK-4 - consider inserting the 'continuation string'
796 * before the rest of the wrapped line */
797 int len = p - beg + (last_wrapped ? continuation_length : 0); 812 int len = p - beg + (last_wrapped ? continuation_length : 0);
798 char *s = xmalloc (len + 1); 813 char *s = xmalloc (len + 1);
799 if (last_wrapped) 814 if (last_wrapped)
800 { 815 {
801 memcpy (s, continuation, continuation_length); 816 memcpy (s, continuation, continuation_length);
802 memcpy (s + continuation_length, beg, p - beg); 817 memcpy (s + continuation_length, beg, p - beg);
803 } 818 }
804 else 819 else
805 memcpy (s, beg, len); 820 memcpy (s, beg, len);
806 821
807 s[len] = 0; 822 s[len] = 0;
808 insert_line (idx); 823 insert_line (idx);
809 lines[idx].line = s; 824 lines[idx].line = s;
810 lines[idx].len = len; 825 lines[idx].len = len;
842} 857}
843 858
844static void 859static void
845main_loop (void) 860main_loop (void)
846{ 861{
847 lines = xmalloc (sizeof (struct linematrix) * listlen);
848 display = xmalloc (sizeof (struct displaymatrix) * listlen);
849 int lin; 862 int lin;
850 time_t lastreload; 863 time_t lastreload;
851 Region region = XCreateRegion (); 864 Region region = XCreateRegion ();
852 XEvent xev; 865 XEvent xev;
853 struct logfile_entry *lastprinted = NULL; 866 struct logfile_entry *lastprinted = NULL;
854 struct logfile_entry *current; 867 struct logfile_entry *current;
855 int need_update = 1; 868 int need_update = 1;
856 869
870 lines = xmalloc (sizeof (struct linematrix) * listlen);
871 display = xmalloc (sizeof (struct displaymatrix) * listlen);
872
857 lastreload = time (NULL); 873 lastreload = time (NULL);
858 874
859 /* Initialize linematrix */ 875 /* Initialize linematrix */
860 for (lin = 0; lin < listlen; lin++) 876 for (lin = 0; lin < listlen; lin++)
861 { 877 {
862 lines[lin].line = xstrdup ("~"); 878 lines[lin].line = xstrdup ("~");
863 lines[lin].len = 1; 879 lines[lin].len = 1;
864 display[lin].line = xstrdup(""); 880 display[lin].line = xstrdup("");
865 display[lin].len = 0; 881 display[lin].len = 0;
866 display[lin].buffer_size = 1; 882 display[lin].buffer_size = 0;
867 lines[lin].color = GetColor (def_color); 883 lines[lin].color = GetColor (def_color);
868 } 884 }
869 885
870 for (;;) 886 for (;;)
871 { 887 {
896 912
897 /* print filename if any, and if last line was from 913 /* print filename if any, and if last line was from
898 * different file */ 914 * different file */
899 if (!opt_nofilename && lastprinted != current && current->desc[0]) 915 if (!opt_nofilename && lastprinted != current && current->desc[0])
900 { 916 {
901 char buf[1024]; /* HACK-5 */
902 snprintf (buf, sizeof (buf), "[%s]", current->desc);
903 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, "]");
904 } 920 }
905 921
906 /* if we're dealing with partial lines, and the last 922 /* if we're dealing with partial lines, and the last
907 * time we showed the line it wasn't finished ... */ 923 * time we showed the line it wasn't finished ... */
908 if (!opt_whole && current->lastpartial) 924 if (!opt_whole && current->lastpartial)
1134 { 1150 {
1135 if ((e->fp = fdopen (0, "r")) == NULL) 1151 if ((e->fp = fdopen (0, "r")) == NULL)
1136 perror ("fdopen"), exit (1); 1152 perror ("fdopen"), exit (1);
1137 if (fcntl (0, F_SETFL, O_NONBLOCK) < 0) 1153 if (fcntl (0, F_SETFL, O_NONBLOCK) < 0)
1138 perror ("fcntl"), exit (1); 1154 perror ("fcntl"), exit (1);
1155
1139 e->fname = NULL; 1156 e->fname = NULL;
1140 e->inode = 0; 1157 e->inode = 0;
1141 e->desc = xstrdup ("stdin"); 1158 e->desc = xstrdup ("stdin");
1142 } 1159 }
1143 else 1160 else
1144 { 1161 {
1145 int l;
1146
1147 e->fname = xstrdup (fname); 1162 e->fname = xstrdup (fname);
1163
1148 if (openlog (e) == NULL) 1164 if (openlog (e) == NULL)
1149 perror (fname), exit (1); 1165 perror (fname), exit (1);
1150 1166
1151 l = strlen (desc); 1167 e->desc = xstrdup (desc);
1152 /* HACK-6: width is in pixels now */
1153 if (l > width - 2) /* must account for [ ] */
1154 l = width - 2;
1155 e->desc = xmalloc (l + 1);
1156 memcpy (e->desc, desc, l);
1157 *(e->desc + l) = '\0';
1158 } 1168 }
1159 1169
1160 e->color = GetColor (fcolor); 1170 e->color = GetColor (fcolor);
1161 e->partial = 0; 1171 e->partial = 0;
1162 e->next = NULL; 1172 e->next = NULL;
1163 1173
1164 if (!loglist) 1174 if (!loglist)
1165 loglist = e; 1175 loglist = e;
1166 if (loglist_tail) 1176 if (loglist_tail)
1167 loglist_tail->next = e; 1177 loglist_tail->next = e;
1178
1168 loglist_tail = e; 1179 loglist_tail = e;
1169 } 1180 }
1170 } 1181 }
1171 1182
1172 if (!loglist) 1183 if (!loglist)
1174 fprintf (stderr, "You did not specify any files to tail\n" 1185 fprintf (stderr, "You did not specify any files to tail\n"
1175 "use %s --help for help\n", argv[0]); 1186 "use %s --help for help\n", argv[0]);
1176 exit (1); 1187 exit (1);
1177 } 1188 }
1178 1189
1190 if (opt_update && opt_whole)
1191 {
1192 fprintf (stderr, "Specify at most one of -update and -whole\n");
1193 exit (1);
1194 }
1179 if (opt_partial && opt_whole) 1195 else if (opt_partial && opt_whole)
1180 { 1196 {
1181 fprintf (stderr, "Specify at most one of -partial and -whole\n"); 1197 fprintf (stderr, "Specify at most one of -partial and -whole\n");
1182 exit (1); 1198 exit (1);
1183 } 1199 }
1184 1200
1253{ 1269{
1254 void *p; 1270 void *p;
1255 1271
1256 while ((p = strdup (string)) == NULL) 1272 while ((p = strdup (string)) == NULL)
1257 { 1273 {
1258 fprintf (stderr, "Memory exausted."); 1274 fprintf (stderr, "Memory exhausted in xstrdup().\n");
1259 sleep (10); 1275 sleep (10);
1260 } 1276 }
1261 1277
1262 return p; 1278 return p;
1263} 1279}
1267{ 1283{
1268 void *p; 1284 void *p;
1269 1285
1270 while ((p = malloc (size)) == NULL) 1286 while ((p = malloc (size)) == NULL)
1271 { 1287 {
1272 fprintf (stderr, "Memory exausted."); 1288 fprintf (stderr, "Memory exhausted in xmalloc().\n");
1273 sleep (10); 1289 sleep (10);
1274 } 1290 }
1275 1291
1276 return p; 1292 return p;
1277} 1293}
1281{ 1297{
1282 void *p; 1298 void *p;
1283 1299
1284 while ((p = realloc (ptr, size)) == NULL) 1300 while ((p = realloc (ptr, size)) == NULL)
1285 { 1301 {
1286 fprintf (stderr, "Memory exausted."); 1302 fprintf (stderr, "Memory exhausted in xrealloc().\n");
1287 sleep (10); 1303 sleep (10);
1288 } 1304 }
1289 1305
1290 return p; 1306 return p;
1291} 1307}
1313 " startup\n" 1329 " startup\n"
1314 " -i | -interval seconds interval between checks (fractional\n" 1330 " -i | -interval seconds interval between checks (fractional\n"
1315 " values o.k.). Default 2.4 seconds\n" 1331 " values o.k.). Default 2.4 seconds\n"
1316 " -V display version information and exit\n" 1332 " -V display version information and exit\n"
1317 "\n"); 1333 "\n");
1318 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 "
1319 "/var/log/secure,red,'ALERT'\n", myname); 1335 "/var/log/secure,red,'ALERT'\n", myname);
1320 exit (0); 1336 exit (0);
1321} 1337}
1322 1338
1323void 1339void

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines