2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Marcin Krzysztof Porwit 2005.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #define DBGC_CLASS DBGC_RPC_SRV
26 typedef struct eventlog_info
28 /* for use by the \PIPE\eventlog policy */
29 fstring source_log_file_name;
30 fstring source_server_name;
31 fstring handle_string;
38 static void free_eventlog_info(void *ptr)
40 struct eventlog_info *info = (struct eventlog_info *)ptr;
41 memset(info->source_log_file_name, '0', sizeof(*(info->source_log_file_name)));
42 memset(info->source_server_name, '0', sizeof(*(info->source_server_name)));
43 memset(info->handle_string, '0', sizeof(*(info->handle_string)));
44 memset(info, 0, sizeof(*(info)));
48 static Eventlog_info *find_eventlog_info_by_hnd(pipes_struct *p,
51 Eventlog_info *info = NULL;
53 if(!(find_policy_by_hnd(p,handle,(void **)&info)))
55 DEBUG(2,("find_eventlog_info_by_hnd: eventlog not found.\n"));
61 void policy_handle_to_string(POLICY_HND *handle, fstring *dest)
63 memset(dest, 0, sizeof(*dest));
64 snprintf((char *)dest, sizeof(*dest), "%08X-%08X-%04X-%04X-%02X%02X%02X%02X%02X",
77 * Callout to open the specified event log
79 * smbrun calling convention --
80 * INPUT: <open_cmd> <log name> <policy handle>
81 * OUTPUT: the string "SUCCESS" if the command succeeded
82 * no such string if there was a failure.
84 static BOOL _eventlog_open_eventlog_hook(Eventlog_info *info)
86 char *cmd = lp_eventlog_open_cmd();
93 if(cmd == NULL || strlen(cmd) == 0)
95 DEBUG(0, ("Must define an \"eventlog open command\" entry in the config.\n"));
99 memset(command, 0, sizeof(command));
100 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
102 info->source_log_file_name,
103 info->handle_string);
105 DEBUG(10, ("Running [%s]\n", command));
106 ret = smbrun(command, &fd);
107 DEBUGADD(10, ("returned [%d]\n", ret));
116 qlines = fd_lines_load(fd, &numlines);
117 DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
122 DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
123 if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS")))
125 DEBUGADD(10, ("Able to open [%s].\n", info->source_log_file_name));
126 file_lines_free(qlines);
131 file_lines_free(qlines);
135 WERROR _eventlog_open_eventlog(pipes_struct *p,
136 EVENTLOG_Q_OPEN_EVENTLOG *q_u,
137 EVENTLOG_R_OPEN_EVENTLOG *r_u)
139 Eventlog_info *info = NULL;
144 if((info = SMB_MALLOC_P(Eventlog_info)) == NULL)
149 if(q_u->servername_ptr != 0)
151 unistr2_to_ascii(info->source_server_name, &(q_u->servername), sizeof(info->source_server_name));
155 /* if servername == NULL, use the local computer */
156 fstrcpy(info->source_server_name, global_myname());
158 DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the server name.\n", info->source_server_name));
160 if(q_u->sourcename_ptr != 0)
162 unistr2_to_ascii(info->source_log_file_name, &(q_u->sourcename), sizeof(info->source_log_file_name));
166 /* if sourcename == NULL, default to "Application" log */
167 fstrcpy(info->source_log_file_name, "Application");
169 DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the source log file.\n", info->source_log_file_name));
171 if(!create_policy_hnd(p, &(r_u->handle), free_eventlog_info, (void *)info))
173 free_eventlog_info(info);
177 policy_handle_to_string(&r_u->handle, &info->handle_string);
179 if(!(_eventlog_open_eventlog_hook(info)))
181 close_policy_hnd(p, &r_u->handle);
188 * Callout to get the number of records in the specified event log
190 * smbrun calling convention --
191 * INPUT: <get_num_records_cmd> <log name> <policy handle>
192 * OUTPUT: A single line with a single integer containing the number of
193 * entries in the log. If there are no entries in the log, return 0.
195 static BOOL _eventlog_get_num_records_hook(Eventlog_info *info)
197 char *cmd = lp_eventlog_num_records_cmd();
204 if(cmd == NULL || strlen(cmd) == 0)
206 DEBUG(0, ("Must define an \"eventlog num records command\" entry in the config.\n"));
210 memset(command, 0, sizeof(command));
211 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
213 info->source_log_file_name,
214 info->handle_string);
216 DEBUG(10, ("Running [%s]\n", command));
217 ret = smbrun(command, &fd);
218 DEBUGADD(10, ("returned [%d]\n", ret));
227 qlines = fd_lines_load(fd, &numlines);
228 DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
233 DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
234 sscanf(qlines[0], "%d", &(info->num_records));
235 file_lines_free(qlines);
239 file_lines_free(qlines);
243 WERROR _eventlog_get_num_records(pipes_struct *p,
244 EVENTLOG_Q_GET_NUM_RECORDS *q_u,
245 EVENTLOG_R_GET_NUM_RECORDS *r_u)
247 Eventlog_info *info = NULL;
248 POLICY_HND *handle = NULL;
253 handle = &(q_u->handle);
254 info = find_eventlog_info_by_hnd(p, handle);
256 if(!(_eventlog_get_num_records_hook(info)))
259 r_u->num_records = info->num_records;
264 * Callout to find the oldest record in the log
266 * smbrun calling convention --
267 * INPUT: <oldest_entry_cmd> <log name> <policy handle>
268 * OUTPUT: If there are entries in the event log, the index of the
269 * oldest entry. Must be 1 or greater.
270 * If there are no entries in the log, returns a 0
272 static BOOL _eventlog_get_oldest_entry_hook(Eventlog_info *info)
274 char *cmd = lp_eventlog_oldest_record_cmd();
281 if(cmd == NULL || strlen(cmd) == 0)
283 DEBUG(0, ("Must define an \"eventlog oldest record command\" entry in the config.\n"));
287 memset(command, 0, sizeof(command));
288 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
290 info->source_log_file_name,
291 info->handle_string);
293 DEBUG(10, ("Running [%s]\n", command));
294 ret = smbrun(command, &fd);
295 DEBUGADD(10, ("returned [%d]\n", ret));
304 qlines = fd_lines_load(fd, &numlines);
305 DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
310 DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
311 sscanf(qlines[0], "%d", &(info->oldest_entry));
312 file_lines_free(qlines);
316 file_lines_free(qlines);
320 WERROR _eventlog_get_oldest_entry(pipes_struct *p,
321 EVENTLOG_Q_GET_OLDEST_ENTRY *q_u,
322 EVENTLOG_R_GET_OLDEST_ENTRY *r_u)
324 Eventlog_info *info = NULL;
325 POLICY_HND *handle = NULL;
330 handle = &(q_u->handle);
331 info = find_eventlog_info_by_hnd(p, handle);
333 if(!(_eventlog_get_oldest_entry_hook(info)))
336 r_u->oldest_entry = info->oldest_entry;
342 * Callout to close the specified event log
344 * smbrun calling convention --
345 * INPUT: <close_cmd> <log name> <policy handle>
346 * OUTPUT: the string "SUCCESS" if the command succeeded
347 * no such string if there was a failure.
349 static BOOL _eventlog_close_eventlog_hook(Eventlog_info *info)
351 char *cmd = lp_eventlog_close_cmd();
358 if(cmd == NULL || strlen(cmd) == 0)
360 DEBUG(0, ("Must define an \"eventlog close command\" entry in the config.\n"));
364 memset(command, 0, sizeof(command));
365 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
367 info->source_log_file_name,
368 info->handle_string);
370 DEBUG(10, ("Running [%s]\n", command));
371 ret = smbrun(command, &fd);
372 DEBUGADD(10, ("returned [%d]\n", ret));
381 qlines = fd_lines_load(fd, &numlines);
382 DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
387 DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
388 if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS")))
390 DEBUGADD(10, ("Able to close [%s].\n", info->source_log_file_name));
391 file_lines_free(qlines);
396 file_lines_free(qlines);
400 WERROR _eventlog_close_eventlog(pipes_struct *p,
401 EVENTLOG_Q_CLOSE_EVENTLOG *q_u,
402 EVENTLOG_R_CLOSE_EVENTLOG *r_u)
404 Eventlog_info *info = NULL;
410 handle = &(q_u->handle);
412 info = find_eventlog_info_by_hnd(p, handle);
413 if(!(_eventlog_close_eventlog_hook(info)))
416 if(!(close_policy_hnd(p, handle)))
418 /* WERR_NOMEM is probably not the correct error, but until I figure out a better
419 one it will have to do */
426 static BOOL _eventlog_read_parse_line(char *line, Eventlog_entry *entry, BOOL *eor)
428 char *start = NULL, *stop = NULL;
434 /* empty line signyfiying record delimeter, or we're at the end of the buffer */
435 if(start == NULL || strlen(start) == 0)
437 DEBUG(6, ("_eventlog_read_parse_line: found end-of-record indicator.\n"));
441 if(!(stop = strchr(line, ':')))
444 DEBUG(6, ("_eventlog_read_parse_line: trying to parse [%s].\n", line));
446 if(0 == strncmp(start, "LEN", stop - start))
448 /* This will get recomputed later anyway -- probably not necessary */
449 entry->record.length = atoi(stop + 1);
451 else if(0 == strncmp(start, "RS1", stop - start))
453 /* For now all these reserved entries seem to have the same value,
454 which can be hardcoded to int(1699505740) for now */
455 entry->record.reserved1 = atoi(stop + 1);
457 else if(0 == strncmp(start, "RCN", stop - start))
459 entry->record.record_number = atoi(stop + 1);
461 else if(0 == strncmp(start, "TMG", stop - start))
463 entry->record.time_generated = atoi(stop + 1);
465 else if(0 == strncmp(start, "TMW", stop - start))
467 entry->record.time_written = atoi(stop + 1);
469 else if(0 == strncmp(start, "EID", stop - start))
471 entry->record.event_id = atoi(stop + 1);
473 else if(0 == strncmp(start, "ETP", stop - start))
475 if(strstr(start, "ERROR"))
477 entry->record.event_type = EVENTLOG_ERROR_TYPE;
479 else if(strstr(start, "WARNING"))
481 entry->record.event_type = EVENTLOG_WARNING_TYPE;
483 else if(strstr(start, "INFO"))
485 entry->record.event_type = EVENTLOG_INFORMATION_TYPE;
487 else if(strstr(start, "AUDIT_SUCCESS"))
489 entry->record.event_type = EVENTLOG_AUDIT_SUCCESS;
491 else if(strstr(start, "AUDIT_FAILURE"))
493 entry->record.event_type = EVENTLOG_AUDIT_FAILURE;
495 else if(strstr(start, "SUCCESS"))
497 entry->record.event_type = EVENTLOG_SUCCESS;
501 /* some other eventlog type -- currently not defined in MSDN docs, so error out */
506 else if(0 == strncmp(start, "NST", stop - start))
508 entry->record.num_strings = atoi(stop + 1);
511 else if(0 == strncmp(start, "ECT", stop - start))
513 entry->record.event_category = atoi(stop + 1);
515 else if(0 == strncmp(start, "RS2", stop - start))
517 entry->record.reserved2 = atoi(stop + 1);
519 else if(0 == strncmp(start, "CRN", stop - start))
521 entry->record.closing_record_number = atoi(stop + 1);
523 else if(0 == strncmp(start, "USL", stop - start))
525 entry->record.user_sid_length = atoi(stop + 1);
527 else if(0 == strncmp(start, "SRC", stop - start))
529 memset(temp, 0, sizeof(temp));
531 while(isspace(stop[0]))
533 temp_len = strlen(stop);
534 strncpy(temp, stop, temp_len);
535 rpcstr_push((void *)(entry->data_record.source_name), temp,
536 sizeof(entry->data_record.source_name), STR_TERMINATE);
537 entry->data_record.source_name_len = (strlen_w(entry->data_record.source_name)* 2) + 2;
539 else if(0 == strncmp(start, "SRN", stop - start))
541 memset(temp, 0, sizeof(temp));
543 while(isspace(stop[0]))
545 temp_len = strlen(stop);
546 strncpy(temp, stop, temp_len);
547 rpcstr_push((void *)(entry->data_record.computer_name), temp,
548 sizeof(entry->data_record.computer_name), STR_TERMINATE);
549 entry->data_record.computer_name_len = (strlen_w(entry->data_record.computer_name)* 2) + 2;
551 else if(0 == strncmp(start, "SID", stop - start))
553 memset(temp, 0, sizeof(temp));
555 while(isspace(stop[0]))
557 temp_len = strlen(stop);
558 strncpy(temp, stop, temp_len);
559 rpcstr_push((void *)(entry->data_record.sid), temp,
560 sizeof(entry->data_record.sid), STR_TERMINATE);
561 entry->record.user_sid_length = (strlen_w(entry->data_record.sid) * 2) + 2;
563 else if(0 == strncmp(start, "STR", stop - start))
565 /* skip past initial ":" */
567 /* now skip any other leading whitespace */
568 while(isspace(stop[0]))
570 temp_len = strlen(stop);
571 memset(temp, 0, sizeof(temp));
572 strncpy(temp, stop, temp_len);
573 rpcstr_push((void *)(entry->data_record.strings + entry->data_record.strings_len),
575 sizeof(entry->data_record.strings) - entry->data_record.strings_len,
577 entry->data_record.strings_len += temp_len + 1;
578 fprintf(stderr, "Dumping strings:\n");
579 for(i = 0; i < entry->data_record.strings_len; i++)
581 fputc((char)entry->data_record.strings[i], stderr);
583 fprintf(stderr, "\nDone\n");
584 entry->record.num_strings++;
586 else if(0 == strncmp(start, "DAT", stop - start))
588 /* Now that we're done processing the STR data, adjust the length to account for
589 unicode, then proceed with the DAT data. */
590 entry->data_record.strings_len *= 2;
591 /* skip past initial ":" */
593 /* now skip any other leading whitespace */
594 while(isspace(stop[0]))
596 memset(temp, 0, sizeof(temp));
597 temp_len = strlen(stop);
598 strncpy(temp, stop, temp_len);
599 rpcstr_push((void *)(entry->data_record.user_data), temp,
600 sizeof(entry->data_record.user_data), STR_TERMINATE);
601 entry->data_record.user_data_len = (strlen_w((const smb_ucs2_t *)entry->data_record.user_data) * 2) + 2;
605 /* some other eventlog entry -- not implemented, so dropping on the floor */
606 DEBUG(10, ("Unknown entry [%s]. Ignoring.\n", line));
607 /* For now return true so that we can keep on parsing this mess. Eventually
608 we will return False here. */
614 * Callout to read entries from the specified event log
616 * smbrun calling convention --
617 * INPUT: <read_cmd> <log name> <direction> <starting record> <buffer size> <policy handle>
618 * where direction is either "forward" or "backward", the starting record is somewhere
619 * between the oldest_record and oldest_record+num_records, and the buffer size is the
620 * maximum size of the buffer that the client can accomodate.
621 * OUTPUT: A buffer containing a set of entries, one to a line, of the format:
622 * Multiple log entries can be contained in the buffer, delimited by an empty line
623 * line type:line data
624 * These are the allowed line types:
625 * RS1:(uint32) - reserved. All M$ entries seem to have int(1699505740) for now
626 * RCN:(uint32) - record number of the record, however it may be calculated by the script
627 * TMG:(uint32) - time generated, seconds since January 1, 1970, 0000 UTC
628 * TMW:(uint32) - time written, seconds since January 1, 1970, 0000 UTC
629 * EID:(uint32) - eventlog source defined event identifier. If there's a stringfile for the event, it is an index into that
630 * ETP:(uint16) - eventlog type - one of ERROR, WARNING, INFO, AUDIT_SUCCESS, AUDIT_FAILURE
631 * ECT:(uint16) - event category - depends on the eventlog generator...
632 * RS2:(uint16) - reserved, make it 0000
633 * CRN:(uint32) - reserved, make it 00000000 for now
634 * USL:(uint32) - user SID length. No sid? Make this 0. Must match SID below
635 * SRC:[(uint8)] - Name of the source, for example ccPwdSvc, in hex bytes. Can not be multiline.
636 * SRN:[(uint8)] - Name of the computer on which this is generated, the short hostname usually.
637 * SID:[(uint8)] - User sid if one exists. Must be present even if there is no SID.
638 * STR:[(uint8)] - String data. One string per line. Multiple strings can be specified using consecutive "STR" lines,
639 * up to a total aggregate string length of 1024 characters.
640 * DAT:[(uint8)] - The user-defined data portion of the event log. Can not be multiple lines.
641 * <empty line> - end-of-record indicator
643 static BOOL _eventlog_read_eventlog_hook(Eventlog_info *info,
644 Eventlog_entry *entry,
645 const char *direction,
652 char *cmd = lp_eventlog_read_cmd();
660 if(cmd == NULL || strlen(cmd) == 0)
662 DEBUG(0, ("Must define an \"eventlog read command\" entry in the config.\n"));
666 slprintf(command, sizeof(command)-1, "%s \"%s\" %s %d %d \"%s\"",
668 info->source_log_file_name,
672 info->handle_string);
676 DEBUG(10, ("Running [%s]\n", command));
677 ret = smbrun(command, &fd);
678 DEBUGADD(10, ("returned [%d]\n", ret));
687 *buffer = fd_lines_load(fd, numlines);
688 DEBUGADD(10, ("Lines returned = [%d]\n", *numlines));
694 for(i = 0; i < numlines; i++)
696 DEBUGADD(10, ("Line[%d] = %s\n", i, qlines[i]));
697 _eventlog_read_parse_line(qlines[i], entry);
699 file_lines_free(qlines);
706 /* file_lines_free(qlines);*/
710 static Eventlog_entry *_eventlog_read_package_entry(prs_struct *ps,
711 EVENTLOG_Q_READ_EVENTLOG *q_u,
712 EVENTLOG_R_READ_EVENTLOG *r_u,
713 Eventlog_entry *entry)
716 Eventlog_entry *new = NULL;
718 new = PRS_ALLOC_MEM(ps, Eventlog_entry, 1);
722 entry->data_record.sid_padding = ((4 - ((entry->data_record.source_name_len
723 + entry->data_record.computer_name_len) % 4)) %4);
724 entry->data_record.data_padding = (4 - ((entry->data_record.strings_len
725 + entry->data_record.user_data_len) % 4)) % 4;
726 entry->record.length = sizeof(Eventlog_record);
727 entry->record.length += entry->data_record.source_name_len;
728 entry->record.length += entry->data_record.computer_name_len;
729 if(entry->record.user_sid_length == 0)
731 /* Should not pad to a DWORD boundary for writing out the sid if there is
732 no SID, so just propagate the padding to pad the data */
733 entry->data_record.data_padding += entry->data_record.sid_padding;
734 entry->data_record.sid_padding = 0;
736 DEBUG(10, ("sid_padding is [%d].\n", entry->data_record.sid_padding));
737 DEBUG(10, ("data_padding is [%d].\n", entry->data_record.data_padding));
739 entry->record.length += entry->data_record.sid_padding;
740 entry->record.length += entry->record.user_sid_length;
741 entry->record.length += entry->data_record.strings_len;
742 entry->record.length += entry->data_record.user_data_len;
743 entry->record.length += entry->data_record.data_padding;
744 /* need another copy of length at the end of the data */
745 entry->record.length += sizeof(entry->record.length);
746 DEBUG(10, ("entry->record.length is [%d].\n", entry->record.length));
747 entry->data = PRS_ALLOC_MEM(ps, uint8, entry->record.length - sizeof(Eventlog_record) - sizeof(entry->record.length));
748 if(entry->data == NULL)
750 offset = entry->data;
751 memcpy(offset, &(entry->data_record.source_name), entry->data_record.source_name_len);
752 offset += entry->data_record.source_name_len;
753 memcpy(offset, &(entry->data_record.computer_name), entry->data_record.computer_name_len);
754 offset += entry->data_record.computer_name_len;
755 /* SID needs to be DWORD-aligned */
756 offset += entry->data_record.sid_padding;
757 entry->record.user_sid_offset = sizeof(Eventlog_record) + (offset - entry->data);
758 memcpy(offset, &(entry->data_record.sid), entry->record.user_sid_length);
759 offset += entry->record.user_sid_length;
760 /* Now do the strings */
761 entry->record.string_offset = sizeof(Eventlog_record) + (offset - entry->data);
762 memcpy(offset, &(entry->data_record.strings), entry->data_record.strings_len);
763 offset += entry->data_record.strings_len;
764 /* Now do the data */
765 entry->record.data_length = entry->data_record.user_data_len;
766 entry->record.data_offset = sizeof(Eventlog_record) + (offset - entry->data);
767 memcpy(offset, &(entry->data_record.user_data), entry->data_record.user_data_len);
768 offset += entry->data_record.user_data_len;
770 memcpy(&(new->record), &entry->record, sizeof(Eventlog_record));
771 memcpy(&(new->data_record), &entry->data_record, sizeof(Eventlog_data_record));
772 new->data = entry->data;
777 static BOOL _eventlog_add_record_to_resp(EVENTLOG_R_READ_EVENTLOG *r_u, Eventlog_entry *new)
779 Eventlog_entry *insert_point;
781 insert_point=r_u->entry;
783 if (NULL == insert_point)
790 while ((NULL != insert_point->next))
792 insert_point=insert_point->next;
795 insert_point->next = new;
798 r_u->num_bytes_in_resp += new->record.length;
803 WERROR _eventlog_read_eventlog(pipes_struct *p,
804 EVENTLOG_Q_READ_EVENTLOG *q_u,
805 EVENTLOG_R_READ_EVENTLOG *r_u)
807 Eventlog_info *info = NULL;
809 Eventlog_entry entry, *new;
810 BOOL eof = False, eor = False;
811 const char *direction = "";
812 uint32 num_records_read = 0;
820 handle = &(q_u->handle);
821 info = find_eventlog_info_by_hnd(p, handle);
822 info->flags = q_u->flags;
823 ps = &p->out_data.rdata;
824 /* if this is the first time we're reading on this handle */
825 if(info->active_entry == 0)
827 /* Rather than checking the EVENTLOG_SEQUENTIAL_READ/EVENTLOG_SEEK_READ flags,
828 we'll just go to the offset specified in the request, or the oldest entry
829 if no offset is specified */
831 info->active_entry = q_u->offset;
833 info->active_entry = info->oldest_entry;
837 if(q_u->flags & EVENTLOG_FORWARDS_READ)
838 direction = "forward";
839 else if(q_u->flags & EVENTLOG_BACKWARDS_READ)
840 direction = "backward";
842 if(!(_eventlog_read_eventlog_hook(info, &entry, direction, info->active_entry, q_u->max_read_size, &eof, &buffer, &numlines)))
850 for(i = 0; i < numlines; i++)
852 num_records_read = r_u->num_records;
853 DEBUGADD(10, ("Line[%d] = [%s]\n", i, buffer[i]));
854 _eventlog_read_parse_line(buffer[i], &entry, &eor);
857 /* package new entry */
858 if((new = _eventlog_read_package_entry(ps, q_u, r_u, &entry)) == NULL)
863 /* Now see if there is enough room to add */
864 if(r_u->num_bytes_in_resp + new->record.length > q_u->max_read_size)
866 r_u->bytes_in_next_record = new->record.length;
867 /* response would be too big to fit in client-size buffer */
870 _eventlog_add_record_to_resp(r_u, new);
873 num_records_read = r_u->num_records - num_records_read;
874 DEBUG(10, ("_eventlog_read_eventlog: read [%d] records for a total of [%d] records using [%d] bytes out of a max of [%d].\n",
877 r_u->num_bytes_in_resp,
878 q_u->max_read_size));
879 /* update the active record */
880 if(info->flags & EVENTLOG_FORWARDS_READ)
881 info->active_entry += num_records_read;
882 else if(info->flags & EVENTLOG_BACKWARDS_READ)
883 info->active_entry -= num_records_read;
892 * Callout to clear (and optionally backup) a specified event log
894 * smbrun calling convention --
895 * INPUT: <clear_eventlog_cmd> <log name> <policy handle>
896 * OUTPUT: A single line with the string "SUCCESS" if the command succeeded.
897 * Otherwise it is assumed to have failed
899 * INPUT: <clear_eventlog_cmd> <log name> <backup file> <policy handle>
900 * OUTPUT: A single line with the string "SUCCESS" if the command succeeded.
901 * Otherwise it is assumed to have failed
902 * The given log is copied to that location on the server. See comments for
903 * eventlog_io_q_clear_eventlog for info about odd file name behavior
905 static BOOL _eventlog_clear_eventlog_hook(Eventlog_info *info,
906 pstring backup_file_name)
908 char *cmd = lp_eventlog_clear_cmd();
915 if(cmd == NULL || strlen(cmd) == 0)
917 DEBUG(0, ("Must define an \"eventlog clear command\" entry in the config.\n"));
921 memset(command, 0, sizeof(command));
922 if(strlen(backup_file_name) > 0)
923 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\"",
925 info->source_log_file_name,
927 info->handle_string);
929 slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"",
931 info->source_log_file_name,
932 info->handle_string);
934 DEBUG(10, ("Running [%s]\n", command));
935 ret = smbrun(command, &fd);
936 DEBUGADD(10, ("returned [%d]\n", ret));
945 qlines = fd_lines_load(fd, &numlines);
946 DEBUGADD(10, ("Lines returned = [%d]\n", numlines));
951 DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0]));
952 if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS")))
954 DEBUGADD(10, ("Able to clear [%s].\n", info->source_log_file_name));
955 file_lines_free(qlines);
960 file_lines_free(qlines);
964 WERROR _eventlog_clear_eventlog(pipes_struct *p,
965 EVENTLOG_Q_CLEAR_EVENTLOG *q_u,
966 EVENTLOG_R_CLEAR_EVENTLOG *r_u)
968 Eventlog_info *info = NULL;
969 pstring backup_file_name;
970 POLICY_HND *handle = NULL;
975 handle = &(q_u->handle);
976 info = find_eventlog_info_by_hnd(p, handle);
977 memset(backup_file_name, 0, sizeof(backup_file_name));
979 if(q_u->backup_file_ptr != 0)
981 unistr2_to_ascii(backup_file_name, &(q_u->backup_file), sizeof(backup_file_name));
982 DEBUG(10, ("_eventlog_clear_eventlog: Using [%s] as the backup file name for log [%s].",
984 info->source_log_file_name));
988 /* if backup_file == NULL, do not back up the log before clearing it */
989 DEBUG(10, ("_eventlog_clear_eventlog: clearing [%s] log without making a backup.",
990 info->source_log_file_name));
993 if(!(_eventlog_clear_eventlog_hook(info, backup_file_name)))