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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines