xymon

Check-in [87c83232b4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:logfetch: Ensure multiple triggerline blocks get sent in low maxbyte situations (From Franco Gasperino) git-svn-id: http://svn.code.sf.net/p/xymon/code/branches/4.3.19@7604 44351d6e-118b-4698-b696-ce33095ecaa4
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | origin/4.3.19
Files: files | file ages | folders
SHA3-256: 87c83232b4e807c7cf7cf2ada7ac72c568b4794c066cb939720affc00d488609
User & Date: jccleaver@users.sf.net 2015-03-21 10:22:23
Context
2015-03-21
11:20
Add fgets() wrapper to safely skip NULLs embedded in log files (From Franco Gasperino) git-svn-id: http://svn.code.sf.net/p/xymon/code/branches/4.3.19@7605 44351d6e-118b-4698-b696-ce33095ecaa4 check-in: 2328238c24 user: jccleaver@users.sf.net tags: trunk, origin/4.3.19
10:22
logfetch: Ensure multiple triggerline blocks get sent in low maxbyte situations (From Franco Gasperino) git-svn-id: http://svn.code.sf.net/p/xymon/code/branches/4.3.19@7604 44351d6e-118b-4698-b696-ce33095ecaa4 check-in: 87c83232b4 user: jccleaver@users.sf.net tags: trunk, origin/4.3.19
09:58
Backport logfetch r6811 from trunk git-svn-id: http://svn.code.sf.net/p/xymon/code/branches/4.3.19@7603 44351d6e-118b-4698-b696-ce33095ecaa4 check-in: 8edb8f41d7 user: jccleaver@users.sf.net tags: trunk, origin/4.3.19
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to client/logfetch.c.

101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
...
116
117
118
119
120
121
122



123
124



125
126
127
128
129
130
131
...
255
256
257
258
259
260
261
























262
263
264
265
266
267
268
269
270
271
272
273






274
275
276
277







278
279
280
281
282
283
284
...
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323




























324
325
326
327
328
329
330
...
356
357
358
359
360
361
362


363
364
365
366
367
368
369

	return fd;
}


char *logdata(char *filename, logdef_t *logdef)
{
	static char *buf = NULL;
	char *startpos, *fillpos, *triggerstartpos, *triggerendpos;
	FILE *fd;
	struct stat st;
	size_t bytesread, bytesleft;
	int openerr, i, status, triggerlinecount, done;
	char *linepos[2*LINES_AROUND_TRIGGER+1];
	int lpidx;
................................................................................
	regex_t *ignexpr = NULL, *trigexpr = NULL;
#ifdef _LARGEFILE_SOURCE
	off_t bufsz;
#else
	long bufsz;
#endif




	if (buf) free(buf);
	buf = NULL;




	fd = fileopen(filename, &openerr);
	if (fd == NULL) {
		buf = (char *)malloc(1024 + strlen(filename));
		sprintf(buf, "Cannot open logfile %s : %s\n", filename, strerror(openerr));
		return buf;
	}
................................................................................
			if (match) {
				int sidx;
				
				sidx = lpidx - LINES_AROUND_TRIGGER; 
				if (sidx < 0) sidx += (2*LINES_AROUND_TRIGGER + 1);
				triggerstartpos = linepos[sidx]; if (!triggerstartpos) triggerstartpos = buf;
				triggerlinecount = LINES_AROUND_TRIGGER;
























			}
		}


		/* We want this line */
		lpidx = ((lpidx + 1) % (2*LINES_AROUND_TRIGGER+1));
		fillpos += strlen(fillpos);

		/* Save the current end-position if we had a trigger within the past LINES_AFTER_TRIGGER lines */
		if (triggerlinecount) {
			triggerlinecount--;
			triggerendpos = fillpos;






		}

		bytesleft = (bufsz - (fillpos - buf));
	}








	/* Was there an error reading the file? */
	if (ferror(fd)) {
		buf = (char *)malloc(1024 + strlen(filename));
		sprintf(buf, "Error while reading logfile %s : %s\n", filename, strerror(errno));
		startpos = buf;
		goto cleanup;
................................................................................

	bytesread = (fillpos - startpos);
	*(buf + bytesread) = '\0';

	if (bytesread > logdef->maxbytes) {
		char *skiptxt = "<...SKIPPED...>\n";

		/* FIXME: Must make sure to only pass complete lines back to the server */
		if (triggerstartpos) {
			/* Skip the beginning of the data up until the trigger was found */
			startpos = triggerstartpos;
			if ((startpos - strlen(skiptxt)) >= buf) {
				startpos -= strlen(skiptxt);
				memcpy(startpos, skiptxt, strlen(skiptxt));
			}
			bytesread = (fillpos - startpos);

			/*
			 * If it's still too big, show some lines after the trigger, and
			 * then skip until it will fit.
			 */
			if (bytesread > logdef->maxbytes) {
				size_t triggerbytesleft;

				triggerbytesleft = bytesread - (triggerendpos - startpos);
				if (triggerbytesleft > 0) {
					char *skipend;

					skipend = fillpos - triggerbytesleft;
					memmove(triggerendpos, skipend, triggerbytesleft);
					*(triggerendpos + triggerbytesleft) = '\0';

					if (triggerbytesleft >= strlen(skiptxt)) 
						memcpy(triggerendpos, skiptxt, strlen(skiptxt));
					bytesread = (triggerendpos - startpos) + triggerbytesleft;
				}
			}
		}




























		else {
			/* Just drop what is too much */
			startpos += (bytesread - logdef->maxbytes);
			memcpy(startpos, skiptxt, strlen(skiptxt));
			bytesread = logdef->maxbytes;
		}
	}
................................................................................

		if (logdef->triggercount) {
			for (i=0; (i < logdef->triggercount); i++) {
				if (logdef->trigger[i]) regfree(&trigexpr[i]);
			}
			xfree(trigexpr);
		}


	}

	return startpos;
}

char *ftypestr(unsigned int mode, char *symlink)
{







|







 







>
>
>


>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>












>
>
>
>
>
>




>
>
>
>
>
>
>







 







|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442

	return fd;
}


char *logdata(char *filename, logdef_t *logdef)
{
	static char *buf, *replacement = NULL;
	char *startpos, *fillpos, *triggerstartpos, *triggerendpos;
	FILE *fd;
	struct stat st;
	size_t bytesread, bytesleft;
	int openerr, i, status, triggerlinecount, done;
	char *linepos[2*LINES_AROUND_TRIGGER+1];
	int lpidx;
................................................................................
	regex_t *ignexpr = NULL, *trigexpr = NULL;
#ifdef _LARGEFILE_SOURCE
	off_t bufsz;
#else
	long bufsz;
#endif

	char *(*triggerptrs)[2] = NULL;
	unsigned int triggerptrs_count = 0;

	if (buf) free(buf);
	buf = NULL;

	if (replacement) free(replacement);
	replacement = NULL;

	fd = fileopen(filename, &openerr);
	if (fd == NULL) {
		buf = (char *)malloc(1024 + strlen(filename));
		sprintf(buf, "Cannot open logfile %s : %s\n", filename, strerror(openerr));
		return buf;
	}
................................................................................
			if (match) {
				int sidx;
				
				sidx = lpidx - LINES_AROUND_TRIGGER; 
				if (sidx < 0) sidx += (2*LINES_AROUND_TRIGGER + 1);
				triggerstartpos = linepos[sidx]; if (!triggerstartpos) triggerstartpos = buf;
				triggerlinecount = LINES_AROUND_TRIGGER;

				if (triggerptrs == NULL || (triggerptrs_count > 0 && triggerptrs[triggerptrs_count - 1][1] != NULL)) {
					dbgprintf(" - %s trigger line encountered; preparing trigger START & END positioning store\n", ((triggerptrs_count == 0) ? "first" : "additional")); 

					/* Create or resize the trigger pointer array to contain another pair of anchors */
   					triggerptrs = realloc(triggerptrs, (sizeof(char *) * 2) * (++triggerptrs_count));
					if (triggerptrs == NULL) return "Out of memory";

					/* Save the current triggerstartpos as our first anchor in the pair */
					triggerptrs[triggerptrs_count - 1][0] = triggerstartpos;
					triggerptrs[triggerptrs_count - 1][1] = NULL;

					if (triggerptrs_count > 1 && (triggerstartpos <= triggerptrs[triggerptrs_count - 2][1])) {
						/* Whoops! This trigger's LINES_AROUND_TRIGGER bleeds into the prior's LINES_AROUND_TRIGGER */
						triggerptrs[triggerptrs_count - 1][0] = triggerptrs[triggerptrs_count - 2][1];
						dbgprintf("Current trigger START (w/ prepended LINES_AROUND_TRIGGER) would overlap with prior trigger's END. Adjusting.\n");
					}

					dbgprintf(" - new trigger anchor START position set\n");
		               } 
		               else {
					/* Do nothing. Merge the two trigger lines into a single start and end pair by extending the existing */
					dbgprintf("Additional trigger line encountered. Previous trigger START has no set END yet. Compressing anchors.\n");
				}
			}
		}


		/* We want this line */
		lpidx = ((lpidx + 1) % (2*LINES_AROUND_TRIGGER+1));
		fillpos += strlen(fillpos);

		/* Save the current end-position if we had a trigger within the past LINES_AFTER_TRIGGER lines */
		if (triggerlinecount) {
			triggerlinecount--;
			triggerendpos = fillpos;

			if (triggerlinecount == 0) {
				/* Terminate the current trigger anchor pair by aligning the end pointer */
				dbgprintf(" - trigger END position set\n");
				triggerptrs[triggerptrs_count - 1][1] = triggerendpos;
			}
		}

		bytesleft = (bufsz - (fillpos - buf));
	}

	if (triggerptrs != NULL) {
	        dbgprintf("Marked %i pairs of START and END anchors for consideration.\n", triggerptrs_count);

		/* Ensure that a premature EOF before the last trigger end postion doesn't blow up */
		if (triggerptrs[triggerptrs_count - 1][1] == NULL) triggerptrs[triggerptrs_count -1][1] = fillpos;
	}

	/* Was there an error reading the file? */
	if (ferror(fd)) {
		buf = (char *)malloc(1024 + strlen(filename));
		sprintf(buf, "Error while reading logfile %s : %s\n", filename, strerror(errno));
		startpos = buf;
		goto cleanup;
................................................................................

	bytesread = (fillpos - startpos);
	*(buf + bytesread) = '\0';

	if (bytesread > logdef->maxbytes) {
		char *skiptxt = "<...SKIPPED...>\n";

	        if (triggerptrs != NULL) {
		       size_t triggerbytes, nontriggerbytes, skiptxtbytes;
		       char *pos;
		       size_t size;

		       /* Sum the number of bytes required to hold all the trigger content (start -> end anchors) */
		       for (i = 0, triggerbytes = 0, skiptxtbytes = 0; i < triggerptrs_count; i++) {
		           triggerbytes += strlen(triggerptrs[i][0]) - strlen(triggerptrs[i][1]);
		           skiptxtbytes += strlen(skiptxt) * 2;
		       }
	  
		       /* Find the remaining bytes allowed for non-trigger content (and prevent size_t underflow wrap ) */
			nontriggerbytes = (logdef->maxbytes < triggerbytes) ? 0 : (logdef->maxbytes - triggerbytes);

		       dbgprintf("Found %zu bytes of trigger data, %zu bytes remaining of non-trigger data. Max allowed is %zu.\n", triggerbytes, nontriggerbytes, logdef->maxbytes);

		       /* Allocate a new buffer, reduced to what we actually can hold */
		       replacement = malloc(sizeof(char) * (triggerbytes + skiptxtbytes + nontriggerbytes));
		       if (replacement == NULL) return "Out of memory";

		       dbgprintf("Staging replacement buffer, %zu bytes.\n", (triggerbytes + skiptxtbytes + nontriggerbytes));

		       /* Iterate each trigger anchor pair, copying into the replacement */
		       for (i = 0, pos = replacement; i < triggerptrs_count; i++) {
		               dbgprintf("Copying buffer content for trigger %i.\n", (i + 1));

		               strncpy(pos, skiptxt, strlen(skiptxt));
		               pos += strlen(skiptxt);

		               size = strlen(triggerptrs[i][0]) - strlen(triggerptrs[i][1]);
		               strncpy(pos, triggerptrs[i][0], size);
		               pos += size;
		       }

		       /* At this point, all the required trigger lines are present */

		       if (nontriggerbytes > 0) {
		               /* Append non-trigger, up to the allowed byte size remaining, of remaining log content */
		               dbgprintf("Copying %zu bytes of non-trigger content.\n", nontriggerbytes);

		               /* Add the final skip for completeness */
		               strncpy(pos, skiptxt, strlen(skiptxt));
		               pos += strlen(skiptxt);

		               /* And copy the the rest of the original buffer content, starting at the last trigger END */
		               strncpy(pos, triggerptrs[triggerptrs_count - 1][1], nontriggerbytes);
		       }

		       /* Prune out the last line to prevent sending a partial */
		       if (*(pos = &replacement[strlen(replacement) - 1]) != '\n') {
		               while (*pos != '\n') {
		                       pos -= 1;
		               }
		               *(++pos) = '\0';
		       }

		       startpos = replacement;
		       bytesread = strlen(startpos);          
	        }
		else {
			/* Just drop what is too much */
			startpos += (bytesread - logdef->maxbytes);
			memcpy(startpos, skiptxt, strlen(skiptxt));
			bytesread = logdef->maxbytes;
		}
	}
................................................................................

		if (logdef->triggercount) {
			for (i=0; (i < logdef->triggercount); i++) {
				if (logdef->trigger[i]) regfree(&trigexpr[i]);
			}
			xfree(trigexpr);
		}

		if (triggerptrs) xfree(triggerptrs);
	}

	return startpos;
}

char *ftypestr(unsigned int mode, char *symlink)
{