Re: Variable-sized lines of text in linked list (long)



My web site server log seemed horribly cluttered and 'hits' from
one site were mixed with those from other sites, so I read the
log a line at a time and made lists (and lists of lists) so I
could produce a report in which requests would be grouped
chronologically by requestor. For example:

25 216.185.230.83
| 02-26 16:45 301 /DeSoto
| 02-26 16:45 200 /DeSoto/
| 02-26 20:17 200 /DeSoto/solar.html
| 02-26 20:17 200 /DeSoto/SC_Madison/
| 02-27 15:03 200 /DeSoto/SC_Types.html
| 02-27 15:26 200 /DeSoto/

for three visits, which is incredibly easier for me to read.

The main() function is fairly simple:

int main (int argc,char **argv)
{ char *line,*s,*z;
unsigned have_page,is_image,line_count = 0,len;
FILE *fp;
user_e *q;
evnt_e *e;
/*
* Check parameters and open the log file
*/
if (argc < 2)
{ puts("Usage: logan <log file>\n");
exit(EXIT_FAILURE);
}
if (!(fp = fopen(argv[1],"r")))
{ puts("Error: can't open log file\n");
exit(EXIT_FAILURE);
}
/*
* Eat the file
*/
while ((line = getsm(fp)))
{ ++line_count;
if (strlen(line) > 256) line[255] = '\0';
process(line);
free(line);
}
/*
* Output the list of requestors and files requested
*/
for (q=user_list.head; q; q=q->next)
{ printf("\n%7u %s\n",q->count,q->user);
have_page = 0;
for (e=q->head; e; e=e->next)
{ s = e->evnt->page->page;
len = strlen(s);
z = s + len;
if (len > 4) is_image = (!strcmp(z-4,".gif") ||
!strcmp(z-4,".ico") ||
!strcmp(z-4,".jpg") ||
!strcmp(z-4,".png"));
else is_image = 0;
if (have_page && is_image) continue;
printf(" | %s %03u %s\n",
ptime(e->evnt->when),e->evnt->code,s);
if (!have_page && !is_image) have_page = 1;
}
}
printf("\nLines: %u\n\n",line_count);
return 0;
}

The process() function, which breaks the line into its
constituant parts, is a bit messier, but still isn't really
complex:

/*
* Extract data from a log record to a log element
*/
log_e *process(char *line)
{ char *p, *s;
char bbuf[256], cbuf[256], fbuf[256], pbuf[256], tbuf[256],
ubuf[256];
log_e *q = NULL;
/*
* Extract the requestor
*/
for (p = line,s = ubuf; *p; ++p)
{ if (*p <= ' ') break;
*s++ = *p;
}
if (*p) ++p;
*s = '\0';

for ( ; *p; ++p) if (*p == '[') break;
if (*p) ++p;
/*
* Extract the access date/time
*/
for (s = tbuf; *p; ++p)
{ if (*p == ']') break;
else *s++ = *p;
}
if (*p) ++p;
*s = '\0';

for ( ; *p; ++p) if (*p == '"') break;
if (*p) ++p;
/*
* Extract the web page URL
*/
if (!strncmp(p,"GET ",4)) p += 4;
for (s = pbuf; *p; ++p)
{ if ((*p == '"') || (*p == ' ')) break;
else *s++ = *p;
}
if (*p == ' ') for (; *p; ++p) if (*p == '"') break;
if (*p) ++p;
*s = '\0';

for ( ; *p; ++p) if (*p != ' ') break;
/*
* Extract the return code
*/
for (s = cbuf; *p; ++p)
{ if ((*p < '0') || (*p > '9')) break;
else *s++ = *p;
}
if (*p) ++p;
*s = '\0';

for ( ; *p; ++p) if (*p != ' ') break;
/*
* Extract the byte count
*/
for (s = bbuf; *p; ++p)
{ if ((*p < '0') || (*p > '9')) break;
else *s++ = *p;
}
if (*p) ++p;
*s = '\0';

for ( ; *p; ++p) if (*p == '"') break;
if (*p) ++p;
/*
* Extract the referring URL
*/
for (s = fbuf; *p; ++p)
{ if (*p == '"') break;
else *s++ = *p;
}
if (*p) ++p;
*s = '\0';
/*
* Add the log record info to the list
*/
if (!(q = malloc(sizeof(log_e))))
{ puts("Allocation failure");
return NULL;
}
q->next = NULL;
q->user = add_user(q,ubuf);
q->when = gtime(tbuf);
q->page = add_page(q,pbuf);
q->code = atoi(cbuf);
q->bcnt = atoi(bbuf);
q->from = add_from(q,fbuf);
if (log_list.head) log_list.tail->next = q;
else log_list.head = q;
log_list.tail = q;
return q;
}

And the remainder is basic stuff to add elements to lists and
convert/format time.

--
Morris Dovey
DeSoto Solar
DeSoto, Iowa USA
http://www.iedu.com/DeSoto
.



Relevant Pages

  • Re: Difference between two ranges
    ... >Another frequent tasks involving lists is to create a ... >that you want to extract items. ... >> Extracting Values Common To Two Lists ... >> the following array formula in the first cell of the ...
    (microsoft.public.excel.misc)
  • Re: Cons cell archaic!?
    ... implementing the first Lisp on an IBM 704. ... when you think of lists as sequence of things as ... you will also have functions that extract arbitrary contiguous ... in any other lang), and you must also have functions that do delete ...
    (comp.lang.lisp)
  • Re: Family History Software
    ... primitive database program to list my ancestors in one view, ... Note that I didn't have to type in details of the census more than once. ... selection lists for further processing? ... In addition I want to add an extract ...
    (soc.genealogy.britain)
  • Re: PyCheck for a classes defined in python and user data in PyObject_HEAD
    ... in C I want to check if a given PyObject is a xml.dom.minidom.Node (or ... how do i extract a PyTypeObject for such a class? ... I'm in a situation when i don't really need to extend python with any ... object in a key with an obscure name while in lists this would change ...
    (comp.lang.python)
  • Re: updates...preventing changes to previously entered values
    ... would changing the data entry property from no to yes in the form properties ... include region, department, and requestor fields that are limited to choices ... another table that lists a requestor's name and the ... yesterday joe smith worked in the IT department and submitted a request. ...
    (microsoft.public.access.gettingstarted)