Line data Source code
1 : /********************************************************************\
2 :
3 : Name: ELOG.C
4 : Created by: Stefan Ritt
5 :
6 : Contents: MIDAS elog functions
7 :
8 : $Id$
9 :
10 : \********************************************************************/
11 :
12 : #include "midas.h"
13 : #include "msystem.h"
14 : #include "mstrlcpy.h"
15 : #include <assert.h>
16 :
17 : /** @defgroup elfunctioncode Midas Elog Functions (el_xxx)
18 : */
19 :
20 : /**dox***************************************************************/
21 : /** @addtogroup elfunctioncode
22 : *
23 : * @{ */
24 :
25 : /**dox***************************************************************/
26 : #ifndef DOXYGEN_SHOULD_SKIP_THIS
27 :
28 : /********************************************************************\
29 : * *
30 : * Electronic logbook functions *
31 : * *
32 : \********************************************************************/
33 :
34 : /********************************************************************/
35 0 : static void el_decode(const char *message, const char *key, char *result, int size)
36 : {
37 : int i;
38 : const char *pc;
39 :
40 0 : if (result == NULL)
41 0 : return;
42 :
43 0 : *result = 0;
44 :
45 0 : pc = strstr(message, key);
46 :
47 0 : if (!pc)
48 0 : return;
49 :
50 0 : pc += strlen(key);
51 :
52 0 : for (i=0; i<size; i++) {
53 0 : if (pc[i] == 0)
54 0 : break;
55 0 : if (pc[i] == '\n')
56 0 : break;
57 0 : result[i] = pc[i];
58 : }
59 :
60 0 : assert(i<=size); // ensure that code above did not overrun the "result" array
61 :
62 0 : if (i==size)
63 0 : result[size-1] = 0;
64 : else
65 0 : result[i] = 0;
66 : }
67 :
68 0 : static void xwrite(const char* filename, int fd, const void* data, int size)
69 : {
70 0 : int wr = write(fd, data, size);
71 0 : if (wr != size) {
72 0 : cm_msg(MERROR, "xwrite", "cannot write to \'%s\', write(%d) returned %d, errno %d (%s)", filename, size, wr, errno, strerror(errno));
73 : }
74 0 : }
75 :
76 0 : static int xread(const char* filename, int fd, void* data, int size)
77 : {
78 0 : int rd = read(fd, data, size);
79 0 : if (rd == 0) {
80 : // end of file
81 0 : } else if (rd < 0) {
82 0 : cm_msg(MERROR, "xread", "cannot read from \'%s\', read(%d) returned %d, errno %d (%s)", filename, size, rd, errno, strerror(errno));
83 0 : } else if (rd != size) {
84 0 : cm_msg(MERROR, "xread", "truncated read from \'%s\', read(%d) returned %d", filename, size, rd);
85 : }
86 0 : return rd;
87 : }
88 :
89 0 : static void xtruncate(const char* filename, int fd)
90 : {
91 0 : int tr = ftruncate(fd, TELL(fd));
92 0 : if (tr != 0) {
93 0 : cm_msg(MERROR, "xtruncate", "cannot truncate \'%s\', ftruncate() returned %d, errno %d (%s)", filename, tr, errno, strerror(errno));
94 : }
95 0 : }
96 :
97 : /**dox***************************************************************/
98 : #endif /* DOXYGEN_SHOULD_SKIP_THIS */
99 :
100 : /********************************************************************/
101 : /**
102 : Submit an ELog entry.
103 : @param run Run Number.
104 : @param author Message author.
105 : @param type Message type.
106 : @param syst Message system.
107 : @param subject Subject.
108 : @param text Message text.
109 : @param reply_to In reply to this message.
110 : @param encoding Text encoding, either HTML or plain.
111 : @param afilename1 File name of attachment.
112 : @param buffer1 File contents.
113 : @param buffer_size1 Size of buffer in bytes.
114 : @param afilename2 File name of attachment.
115 : @param buffer2 File contents.
116 : @param buffer_size2 Size of buffer in bytes.
117 : @param afilename3 File name of attachment.
118 : @param buffer3 File contents.
119 : @param buffer_size3 Size of buffer in bytes.
120 : @param tag If given, edit existing message.
121 : @param tag_size Maximum size of tag.
122 : @return EL_SUCCESS
123 : */
124 0 : INT el_submit(int run, const char *author, const char *type, const char *syst, const char *subject,
125 : const char *text, const char *reply_to, const char *encoding,
126 : const char *afilename1, const char *buffer1, INT buffer_size1,
127 : const char *afilename2, const char *buffer2, INT buffer_size2,
128 : const char *afilename3, const char *buffer3, INT buffer_size3, char *tag, INT tag_size)
129 : {
130 0 : if (rpc_is_remote())
131 0 : return rpc_call(RPC_EL_SUBMIT, run, author, type, syst, subject,
132 : text, reply_to, encoding,
133 : afilename1, buffer1, buffer_size1,
134 0 : afilename2, buffer2, buffer_size2, afilename3, buffer3, buffer_size3, tag, tag_size);
135 :
136 : #ifdef LOCAL_ROUTINES
137 : {
138 0 : INT size, fh, status, run_number, semaphore, idx, offset = 0, tail_size = 0;
139 : char file_name[256+256+100];
140 : char afile_name[3][256+256];
141 : char dir[256];
142 : char start_str[80], end_str[80], last[80], date[80], thread[80], attachment[256];
143 : HNDLE hDB;
144 : time_t now;
145 : char *p;
146 0 : char* message = NULL;
147 0 : size_t message_size = 0;
148 : BOOL bedit;
149 : struct tm tms;
150 :
151 0 : cm_get_experiment_database(&hDB, NULL);
152 :
153 0 : bedit = (tag[0] != 0);
154 :
155 : /* request semaphore */
156 0 : cm_get_experiment_semaphore(NULL, &semaphore, NULL, NULL);
157 0 : status = ss_semaphore_wait_for(semaphore, 5 * 60 * 1000);
158 0 : if (status != SS_SUCCESS) {
159 0 : cm_msg(MERROR, "el_submit", "Cannot lock experiment semaphore, ss_semaphore_wait_for() status %d", status);
160 0 : abort();
161 : }
162 :
163 : /* get run number from ODB if not given */
164 0 : if (run > 0)
165 0 : run_number = run;
166 : else {
167 : /* get run number */
168 0 : size = sizeof(run_number);
169 0 : status = db_get_value(hDB, 0, "/Runinfo/Run number", &run_number, &size, TID_INT, TRUE);
170 0 : assert(status == SUCCESS);
171 : }
172 :
173 0 : if (run_number < 0) {
174 0 : cm_msg(MERROR, "el_submit", "aborting on attempt to use invalid run number %d", run_number);
175 0 : abort();
176 : }
177 :
178 0 : for (idx = 0; idx < 3; idx++) {
179 : /* generate filename for attachment */
180 0 : afile_name[idx][0] = file_name[0] = 0;
181 :
182 : char afilename[256];
183 0 : const char* buffer = NULL;
184 0 : int buffer_size = 0;
185 :
186 0 : if (idx == 0) {
187 0 : mstrlcpy(afilename, afilename1, sizeof(afilename));
188 0 : buffer = buffer1;
189 0 : buffer_size = buffer_size1;
190 0 : } else if (idx == 1) {
191 0 : mstrlcpy(afilename, afilename2, sizeof(afilename));
192 0 : buffer = buffer2;
193 0 : buffer_size = buffer_size2;
194 0 : } else if (idx == 2) {
195 0 : mstrlcpy(afilename, afilename3, sizeof(afilename));
196 0 : buffer = buffer3;
197 0 : buffer_size = buffer_size3;
198 : }
199 :
200 0 : if (afilename[0]) {
201 0 : strcpy(file_name, afilename);
202 0 : p = file_name;
203 0 : while (strchr(p, ':'))
204 0 : p = strchr(p, ':') + 1;
205 0 : while (strchr(p, '\\'))
206 0 : p = strchr(p, '\\') + 1; /* NT */
207 0 : while (strchr(p, '/'))
208 0 : p = strchr(p, '/') + 1; /* Unix */
209 0 : while (strchr(p, ']'))
210 0 : p = strchr(p, ']') + 1; /* VMS */
211 :
212 : /* assemble ELog filename */
213 0 : if (p[0]) {
214 0 : dir[0] = 0;
215 0 : if (hDB > 0) {
216 0 : size = sizeof(dir);
217 0 : memset(dir, 0, size);
218 0 : status = db_get_value(hDB, 0, "/Logger/Elog dir", dir, &size, TID_STRING, FALSE);
219 0 : if (status != DB_SUCCESS)
220 0 : db_get_value(hDB, 0, "/Logger/Data dir", dir, &size, TID_STRING, TRUE);
221 :
222 0 : if (dir[0] != 0 && dir[strlen(dir) - 1] != DIR_SEPARATOR)
223 0 : strcat(dir, DIR_SEPARATOR_STR);
224 : }
225 :
226 0 : ss_tzset();
227 0 : time(&now);
228 0 : localtime_r(&now, &tms);
229 :
230 : char str[256];
231 0 : mstrlcpy(str, p, sizeof(str));
232 0 : sprintf(afile_name[idx], "%02d%02d%02d_%02d%02d%02d_%s",
233 0 : tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday,
234 : tms.tm_hour, tms.tm_min, tms.tm_sec, str);
235 0 : sprintf(file_name, "%s%02d%02d%02d_%02d%02d%02d_%s", dir,
236 0 : tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday,
237 : tms.tm_hour, tms.tm_min, tms.tm_sec, str);
238 :
239 : /* save attachment */
240 0 : fh = open(file_name, O_CREAT | O_RDWR | O_BINARY, 0644);
241 0 : if (fh < 0) {
242 0 : cm_msg(MERROR, "el_submit", "Cannot write attachment file \"%s\", open() returned %d, errno %d (%s)", file_name, fh, errno, strerror(errno));
243 : } else {
244 0 : xwrite(file_name, fh, buffer, buffer_size);
245 0 : close(fh);
246 : }
247 : }
248 : }
249 : } // loop over attachmnents
250 :
251 : /* generate new file name YYMMDD.log in data directory */
252 0 : cm_get_experiment_database(&hDB, NULL);
253 :
254 0 : size = sizeof(dir);
255 0 : memset(dir, 0, size);
256 0 : status = db_get_value(hDB, 0, "/Logger/Elog dir", dir, &size, TID_STRING, FALSE);
257 0 : if (status != DB_SUCCESS)
258 0 : db_get_value(hDB, 0, "/Logger/Data dir", dir, &size, TID_STRING, TRUE);
259 :
260 0 : if (dir[0] != 0 && dir[strlen(dir) - 1] != DIR_SEPARATOR)
261 0 : strcat(dir, DIR_SEPARATOR_STR);
262 :
263 0 : ss_tzset();
264 :
265 0 : char* buffer = NULL;
266 :
267 0 : if (bedit) {
268 : /* edit existing message */
269 : char str[256];
270 0 : mstrlcpy(str, tag, sizeof(str));
271 0 : if (strchr(str, '.')) {
272 0 : offset = atoi(strchr(str, '.') + 1);
273 0 : *strchr(str, '.') = 0;
274 : }
275 0 : sprintf(file_name, "%s%s.log", dir, str);
276 0 : fh = open(file_name, O_CREAT | O_RDWR | O_BINARY, 0644);
277 0 : if (fh < 0) {
278 0 : ss_semaphore_release(semaphore);
279 0 : return EL_FILE_ERROR;
280 : }
281 0 : lseek(fh, offset, SEEK_SET);
282 0 : xread(file_name, fh, str, 16);
283 :
284 0 : if (strncmp(str, "$Start$", 7) != 0) {
285 0 : cm_msg(MERROR, "el_submit", "cannot read from \'%s\', corrupted file: no $Start$ in \"%s\"", file_name, str);
286 0 : close(fh);
287 0 : return EL_FILE_ERROR;
288 : }
289 :
290 0 : size = atoi(str + 9);
291 :
292 0 : if (size < 1) {
293 0 : cm_msg(MERROR, "el_submit", "cannot read from \'%s\', corrupted file: bad size %d in \"%s\"", file_name, size, str);
294 0 : close(fh);
295 0 : return EL_FILE_ERROR;
296 : }
297 :
298 0 : message = (char*)malloc(size);
299 :
300 0 : if (!message) {
301 0 : cm_msg(MERROR, "el_submit", "cannot read from \'%s\', corrupted file: bad size %d in \"%s\", cannot malloc(%d): errno %d (%s)", file_name, size, str, size, errno, strerror(errno));
302 0 : close(fh);
303 0 : return EL_FILE_ERROR;
304 : }
305 :
306 0 : status = read(fh, message, size);
307 0 : if (status != size && status + 16 != size) {
308 0 : free(message);
309 0 : return EL_FILE_ERROR;
310 : }
311 :
312 0 : el_decode(message, "Date: ", date, sizeof(date));
313 0 : el_decode(message, "Thread: ", thread, sizeof(thread));
314 0 : el_decode(message, "Attachment: ", attachment, sizeof(attachment));
315 :
316 0 : free(message);
317 0 : message = NULL;
318 :
319 : /* buffer tail of logfile */
320 0 : lseek(fh, 0, SEEK_END);
321 0 : tail_size = TELL(fh) - (offset + size);
322 :
323 0 : if (tail_size > 0) {
324 : int n;
325 :
326 0 : buffer = (char *) M_MALLOC(tail_size);
327 0 : if (buffer == NULL) {
328 0 : close(fh);
329 0 : ss_semaphore_release(semaphore);
330 0 : return EL_FILE_ERROR;
331 : }
332 :
333 0 : lseek(fh, offset + size, SEEK_SET);
334 0 : n = xread(file_name, fh, buffer, tail_size);
335 0 : if (n != tail_size)
336 0 : return EL_FILE_ERROR;
337 : }
338 0 : lseek(fh, offset, SEEK_SET);
339 : } else {
340 : /* create new message */
341 0 : ss_tzset(); // required by localtime_r()
342 0 : time(&now);
343 0 : localtime_r(&now, &tms);
344 :
345 0 : sprintf(file_name, "%s%02d%02d%02d.log", dir, tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday);
346 :
347 0 : fh = open(file_name, O_CREAT | O_RDWR | O_BINARY, 0644);
348 0 : if (fh < 0) {
349 0 : ss_semaphore_release(semaphore);
350 0 : return EL_FILE_ERROR;
351 : }
352 :
353 : assert(sizeof(date) >= 32);
354 0 : ctime_r(&now, date);
355 0 : date[24] = 0;
356 :
357 0 : if (reply_to[0])
358 0 : sprintf(thread, "%16s %16s", reply_to, "0");
359 : else
360 0 : sprintf(thread, "%16s %16s", "0", "0");
361 :
362 0 : lseek(fh, 0, SEEK_END);
363 : }
364 :
365 0 : message_size = 1000;
366 0 : message_size += strlen(date);
367 0 : message_size += strlen(author);
368 0 : message_size += strlen(type);
369 0 : message_size += strlen(syst);
370 0 : message_size += strlen(subject);
371 0 : message_size += strlen(attachment);
372 0 : message_size += strlen(afile_name[0]);
373 0 : message_size += strlen(afile_name[1]);
374 0 : message_size += strlen(afile_name[2]);
375 0 : message_size += strlen(encoding);
376 0 : message_size += strlen(text);
377 :
378 : //printf("message_size %d, text %d\n", (int)message_size, (int)strlen(text));
379 :
380 0 : message = (char*)malloc(message_size);
381 :
382 0 : if (!message) {
383 0 : cm_msg(MERROR, "el_submit", "cannot malloc() %d bytes: errno %d (%s)", size, errno, strerror(errno));
384 0 : close(fh);
385 0 : return EL_FILE_ERROR;
386 : }
387 :
388 : /* compose message */
389 :
390 0 : sprintf(message, "Date: %s\n", date);
391 0 : sprintf(message + strlen(message), "Thread: %s\n", thread);
392 0 : sprintf(message + strlen(message), "Run: %d\n", run_number);
393 0 : sprintf(message + strlen(message), "Author: %s\n", author);
394 0 : sprintf(message + strlen(message), "Type: %s\n", type);
395 0 : sprintf(message + strlen(message), "System: %s\n", syst);
396 0 : sprintf(message + strlen(message), "Subject: %s\n", subject);
397 :
398 : /* keep original attachment if edit and no new attachment */
399 0 : if (bedit && afile_name[0][0] == 0 && afile_name[1][0] == 0 && afile_name[2][0] == 0)
400 0 : sprintf(message + strlen(message), "Attachment: %s", attachment);
401 : else {
402 0 : sprintf(message + strlen(message), "Attachment: %s", afile_name[0]);
403 0 : if (afile_name[1][0])
404 0 : sprintf(message + strlen(message), ",%s", afile_name[1]);
405 0 : if (afile_name[2][0])
406 0 : sprintf(message + strlen(message), ",%s", afile_name[2]);
407 : }
408 0 : sprintf(message + strlen(message), "\n");
409 :
410 0 : sprintf(message + strlen(message), "Encoding: %s\n", encoding);
411 0 : sprintf(message + strlen(message), "========================================\n");
412 0 : strcat(message, text);
413 :
414 0 : assert(strlen(message) < message_size); /* bomb out on array overrun. */
415 :
416 0 : size = 0;
417 0 : sprintf(start_str, "$Start$: %6d\n", size);
418 0 : sprintf(end_str, "$End$: %6d\n\f", size);
419 :
420 0 : size = strlen(message) + strlen(start_str) + strlen(end_str);
421 :
422 0 : if (tag != NULL && !bedit) {
423 0 : sprintf(tag, "%02d%02d%02d.%d", tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday, (int) TELL(fh));
424 : }
425 :
426 : /* size has to fit in 6 digits */
427 0 : assert(size < 999999);
428 :
429 0 : sprintf(start_str, "$Start$: %6d\n", size);
430 0 : sprintf(end_str, "$End$: %6d\n\f", size);
431 :
432 0 : xwrite(file_name, fh, start_str, strlen(start_str));
433 0 : xwrite(file_name, fh, message, strlen(message));
434 0 : xwrite(file_name, fh, end_str, strlen(end_str));
435 :
436 0 : free(message);
437 0 : message = NULL;
438 0 : message_size = 0;
439 :
440 0 : if (bedit) {
441 0 : if (tail_size > 0) {
442 0 : xwrite(file_name, fh, buffer, tail_size);
443 0 : M_FREE(buffer);
444 : }
445 :
446 : /* truncate file here */
447 : #ifdef OS_WINNT
448 : chsize(fh, TELL(fh));
449 : #else
450 0 : xtruncate(file_name, fh);
451 : #endif
452 : }
453 :
454 0 : close(fh);
455 :
456 : /* if reply, mark original message */
457 0 : if (reply_to[0] && !bedit) {
458 0 : strcpy(last, reply_to);
459 : do {
460 : char filename[256];
461 0 : status = el_search_message(last, &fh, FALSE, filename, sizeof(filename));
462 0 : if (status == EL_SUCCESS) {
463 : /* position to next thread location */
464 0 : lseek(fh, 72, SEEK_CUR);
465 : char str[256];
466 0 : memset(str, 0, sizeof(str));
467 0 : xread(filename, fh, str, 16);
468 0 : lseek(fh, -16, SEEK_CUR);
469 :
470 : /* if no reply yet, set it */
471 0 : if (atoi(str) == 0) {
472 0 : sprintf(str, "%16s", tag);
473 0 : xwrite(filename, fh, str, 16);
474 0 : close(fh);
475 0 : break;
476 : } else {
477 : /* if reply set, find last one in chain */
478 0 : strcpy(last, strtok(str, " "));
479 0 : close(fh);
480 : }
481 : } else
482 : /* stop on error */
483 0 : break;
484 :
485 0 : } while (TRUE);
486 : }
487 :
488 : /* release elog semaphore */
489 0 : ss_semaphore_release(semaphore);
490 : }
491 : #endif /* LOCAL_ROUTINES */
492 :
493 0 : return EL_SUCCESS;
494 : }
495 :
496 : /**dox***************************************************************/
497 : #ifndef DOXYGEN_SHOULD_SKIP_THIS
498 :
499 : /********************************************************************/
500 0 : INT el_search_message(char *tag, int *fh, BOOL walk, char *xfilename, int xfilename_size)
501 : {
502 : int i, size, offset, direction, status;
503 : struct tm tms;
504 0 : time_t lt, ltime=0, lact;
505 : char str[256];
506 : char dir[256];
507 : char file_name[256+100];
508 : HNDLE hDB;
509 :
510 0 : ss_tzset(); // required by localtime_r()
511 :
512 0 : if (xfilename && xfilename_size > 0)
513 0 : *xfilename = 0;
514 :
515 : /* open file */
516 0 : cm_get_experiment_database(&hDB, NULL);
517 :
518 0 : size = sizeof(dir);
519 0 : memset(dir, 0, size);
520 0 : status = db_get_value(hDB, 0, "/Logger/Elog dir", dir, &size, TID_STRING, FALSE);
521 0 : if (status != DB_SUCCESS)
522 0 : db_get_value(hDB, 0, "/Logger/Data dir", dir, &size, TID_STRING, TRUE);
523 :
524 0 : if (dir[0] != 0 && dir[strlen(dir) - 1] != DIR_SEPARATOR)
525 0 : strcat(dir, DIR_SEPARATOR_STR);
526 :
527 : /* check tag for direction */
528 0 : direction = 0;
529 0 : if (strpbrk(tag, "+-")) {
530 0 : direction = atoi(strpbrk(tag, "+-"));
531 0 : *strpbrk(tag, "+-") = 0;
532 : }
533 :
534 : /* if tag is given, open file directly */
535 0 : if (tag[0]) {
536 : /* extract time structure from tag */
537 0 : memset(&tms, 0, sizeof(struct tm));
538 0 : tms.tm_year = (tag[0] - '0') * 10 + (tag[1] - '0');
539 0 : tms.tm_mon = (tag[2] - '0') * 10 + (tag[3] - '0') - 1;
540 0 : tms.tm_mday = (tag[4] - '0') * 10 + (tag[5] - '0');
541 0 : tms.tm_hour = 12;
542 :
543 0 : if (tms.tm_year < 90)
544 0 : tms.tm_year += 100;
545 0 : ltime = lt = ss_mktime(&tms);
546 :
547 0 : strcpy(str, tag);
548 0 : if (strchr(str, '.')) {
549 0 : offset = atoi(strchr(str, '.') + 1);
550 0 : *strchr(str, '.') = 0;
551 : } else
552 0 : return EL_FILE_ERROR;
553 :
554 : do {
555 0 : localtime_r(<ime, &tms);
556 :
557 0 : sprintf(file_name, "%s%02d%02d%02d.log", dir, tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday);
558 :
559 0 : if (xfilename)
560 0 : mstrlcpy(xfilename, file_name, xfilename_size);
561 :
562 0 : *fh = open(file_name, O_RDWR | O_BINARY, 0644);
563 :
564 0 : if (*fh < 0) {
565 0 : if (!walk)
566 0 : return EL_FILE_ERROR;
567 :
568 0 : if (direction == -1)
569 0 : ltime -= 3600 * 24; /* one day back */
570 : else
571 0 : ltime += 3600 * 24; /* go forward one day */
572 :
573 : /* set new tag */
574 0 : localtime_r(<ime, &tms);
575 0 : sprintf(tag, "%02d%02d%02d.0", tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday);
576 : }
577 :
578 : /* in forward direction, stop today */
579 0 : if (direction != -1 && ltime > time(NULL) + 3600 * 24)
580 0 : break;
581 :
582 : /* in backward direction, go back 10 years */
583 0 : if (direction == -1 && abs((INT) lt - (INT) ltime) > 3600 * 24 * 365 * 10)
584 0 : break;
585 :
586 0 : } while (*fh < 0);
587 :
588 0 : if (*fh < 0)
589 0 : return EL_FILE_ERROR;
590 :
591 0 : lseek(*fh, offset, SEEK_SET);
592 :
593 : /* check if start of message */
594 0 : i = xread(file_name, *fh, str, 15);
595 0 : if (i <= 0) {
596 0 : close(*fh);
597 0 : return EL_FILE_ERROR;
598 : }
599 :
600 0 : if (strncmp(str, "$Start$: ", 9) != 0) {
601 0 : close(*fh);
602 0 : return EL_FILE_ERROR;
603 : }
604 :
605 0 : lseek(*fh, offset, SEEK_SET);
606 : }
607 :
608 : /* open most recent file if no tag given */
609 0 : if (tag[0] == 0) {
610 0 : time((time_t *) <);
611 0 : ltime = lt;
612 : do {
613 0 : localtime_r(<ime, &tms);
614 :
615 0 : sprintf(file_name, "%s%02d%02d%02d.log", dir, tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday);
616 :
617 0 : if (xfilename)
618 0 : mstrlcpy(xfilename, file_name, xfilename_size);
619 :
620 0 : *fh = open(file_name, O_RDWR | O_BINARY, 0644);
621 :
622 0 : if (*fh < 0)
623 0 : ltime -= 3600 * 24; /* one day back */
624 :
625 0 : } while (*fh < 0 && (INT) lt - (INT) ltime < 3600 * 24 * 365);
626 :
627 0 : if (*fh < 0)
628 0 : return EL_FILE_ERROR;
629 :
630 : /* remember tag */
631 0 : sprintf(tag, "%02d%02d%02d", tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday);
632 :
633 0 : lseek(*fh, 0, SEEK_END);
634 :
635 0 : sprintf(tag + strlen(tag), ".%d", (int) TELL(*fh));
636 : }
637 :
638 :
639 0 : if (direction == -1) {
640 : /* seek previous message */
641 :
642 0 : if (TELL(*fh) == 0) {
643 : /* go back one day */
644 0 : close(*fh);
645 :
646 0 : lt = ltime;
647 : do {
648 0 : lt -= 3600 * 24;
649 0 : localtime_r(<, &tms);
650 0 : sprintf(str, "%02d%02d%02d.0", tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday);
651 :
652 0 : status = el_search_message(str, fh, FALSE, file_name, sizeof(file_name));
653 :
654 0 : if (xfilename)
655 0 : mstrlcpy(xfilename, file_name, xfilename_size);
656 :
657 0 : } while (status != EL_SUCCESS && (INT) ltime - (INT) lt < 3600 * 24 * 365);
658 :
659 0 : if (status != EL_SUCCESS)
660 0 : return EL_FIRST_MSG;
661 :
662 : /* adjust tag */
663 0 : strcpy(tag, str);
664 :
665 : /* go to end of current file */
666 0 : lseek(*fh, 0, SEEK_END);
667 : }
668 :
669 : /* read previous message size */
670 0 : lseek(*fh, -17, SEEK_CUR);
671 0 : i = xread(file_name, *fh, str, 17);
672 0 : if (i <= 0) {
673 0 : close(*fh);
674 0 : return EL_FILE_ERROR;
675 : }
676 :
677 0 : if (strncmp(str, "$End$: ", 7) != 0) {
678 0 : close(*fh);
679 0 : return EL_FILE_ERROR;
680 : }
681 :
682 : /* make sure the input string to atoi() is zero-terminated:
683 : * $End$: 355garbage
684 : * 01234567890123456789 */
685 0 : str[15] = 0;
686 :
687 0 : size = atoi(str + 7);
688 0 : if (size <= 15) {
689 0 : close(*fh);
690 0 : return EL_FILE_ERROR;
691 : }
692 :
693 0 : lseek(*fh, -size, SEEK_CUR);
694 :
695 : /* adjust tag */
696 0 : sprintf(strchr(tag, '.') + 1, "%d", (int) TELL(*fh));
697 : }
698 :
699 0 : if (direction == 1) {
700 : /* seek next message */
701 :
702 : /* read current message size */
703 0 : TELL(*fh);
704 :
705 0 : i = xread(file_name, *fh, str, 15);
706 0 : if (i <= 0) {
707 0 : close(*fh);
708 0 : return EL_FILE_ERROR;
709 : }
710 0 : lseek(*fh, -15, SEEK_CUR);
711 :
712 0 : if (strncmp(str, "$Start$: ", 9) != 0) {
713 0 : close(*fh);
714 0 : return EL_FILE_ERROR;
715 : }
716 :
717 : /* make sure the input string to atoi() is zero-terminated
718 : * $Start$: 606garbage
719 : * 01234567890123456789 */
720 0 : str[15] = 0;
721 :
722 0 : size = atoi(str + 9);
723 :
724 0 : if (size <= 15) {
725 0 : close(*fh);
726 0 : return EL_FILE_ERROR;
727 : }
728 :
729 0 : lseek(*fh, size, SEEK_CUR);
730 :
731 : /* if EOF, goto next day */
732 0 : i = xread(file_name, *fh, str, 15);
733 0 : if (i < 15) {
734 0 : close(*fh);
735 0 : time((time_t *) &lact);
736 :
737 0 : lt = ltime;
738 : do {
739 0 : lt += 3600 * 24;
740 0 : localtime_r(<, &tms);
741 0 : sprintf(str, "%02d%02d%02d.0", tms.tm_year % 100, tms.tm_mon + 1, tms.tm_mday);
742 :
743 0 : status = el_search_message(str, fh, FALSE, file_name, sizeof(file_name));
744 :
745 0 : if (xfilename)
746 0 : mstrlcpy(xfilename, file_name, xfilename_size);
747 :
748 0 : } while (status != EL_SUCCESS && (INT) lt - (INT) lact < 3600 * 24);
749 :
750 0 : if (status != EL_SUCCESS)
751 0 : return EL_LAST_MSG;
752 :
753 : /* adjust tag */
754 0 : strcpy(tag, str);
755 :
756 : /* go to beginning of current file */
757 0 : lseek(*fh, 0, SEEK_SET);
758 : } else
759 0 : lseek(*fh, -15, SEEK_CUR);
760 :
761 : /* adjust tag */
762 0 : sprintf(strchr(tag, '.') + 1, "%d", (int) TELL(*fh));
763 : }
764 :
765 0 : return EL_SUCCESS;
766 : }
767 :
768 :
769 : /********************************************************************/
770 0 : INT el_retrieve(char *tag, char *date, int *run, char *author, char *type,
771 : char *syst, char *subject, char *text, int *textsize,
772 : char *orig_tag, char *reply_tag,
773 : char *attachment1, char *attachment2, char *attachment3, char *encoding)
774 : /********************************************************************\
775 :
776 : Routine: el_retrieve
777 :
778 : Purpose: Retrieve an ELog entry by its message tab
779 :
780 : Input:
781 : char *tag tag in the form YYMMDD.offset
782 : int *size Size of text buffer
783 :
784 : Output:
785 : char *tag tag of retrieved message
786 : char *date Date/time of message recording
787 : int *run Run number
788 : char *author Message author
789 : char *type Message type
790 : char *syst Message system
791 : char *subject Subject
792 : char *text Message text
793 : char *orig_tag Original message if this one is a reply
794 : char *reply_tag Reply for current message
795 : char *attachment1/2/3 File attachment
796 : char *encoding Encoding of message
797 : int *size Actual message text size
798 :
799 : Function value:
800 : EL_SUCCESS Successful completion
801 : EL_LAST_MSG Last message in log
802 :
803 : \********************************************************************/
804 : {
805 0 : int size, fh = 0, search_status, rd;
806 : char str[256], *p;
807 : char thread[256];
808 : char attachment_all[3*256+100]; /* size of attachement1/2/3 from show_elog_submit_query() */
809 0 : char *message = NULL;
810 0 : size_t message_size = 0;
811 : char filename[256];
812 :
813 0 : if (tag[0]) {
814 0 : search_status = el_search_message(tag, &fh, TRUE, filename, sizeof(filename));
815 0 : if (search_status != EL_SUCCESS)
816 0 : return search_status;
817 : } else {
818 : /* open most recent message */
819 0 : strcpy(tag, "-1");
820 0 : search_status = el_search_message(tag, &fh, TRUE, filename, sizeof(filename));
821 0 : if (search_status != EL_SUCCESS)
822 0 : return search_status;
823 : }
824 :
825 : //printf("el_retrieve: reading [%s]\n", filename);
826 :
827 : /* extract message size */
828 0 : TELL(fh);
829 0 : rd = xread(filename, fh, str, 15);
830 0 : if (rd != 15)
831 0 : return EL_FILE_ERROR;
832 :
833 : /* make sure the input string is zero-terminated before we call atoi() */
834 0 : str[15] = 0;
835 :
836 : /* get size */
837 0 : size = atoi(str + 9);
838 :
839 0 : if ((strncmp(str, "$Start$:", 8) != 0) || (size <= 15)) {
840 0 : cm_msg(MERROR, "el_retrieve", "cannot read from \'%s\', corrupted file: no $Start$ or bad size in \"%s\"", filename, str);
841 0 : close(fh);
842 0 : return EL_FILE_ERROR;
843 : }
844 :
845 0 : message_size = size + 1;
846 0 : message = (char*)malloc(message_size);
847 :
848 0 : if (!message) {
849 0 : cm_msg(MERROR, "el_retrieve", "cannot read from \'%s\', cannot malloc() %d bytes, errno %d (%s)", filename, (int)message_size, errno, strerror(errno));
850 0 : free(message);
851 0 : close(fh);
852 0 : return EL_FILE_ERROR;
853 : }
854 :
855 0 : memset(message, 0, message_size);
856 :
857 0 : rd = read(fh, message, size);
858 0 : if (rd <= 0 || !((rd + 15 == size) || (rd == size))) {
859 0 : cm_msg(MERROR, "el_retrieve", "cannot read from \'%s\', read(%d) returned %d, errno %d (%s)", filename, size, rd, errno, strerror(errno));
860 0 : free(message);
861 0 : close(fh);
862 0 : return EL_FILE_ERROR;
863 : }
864 :
865 0 : close(fh);
866 :
867 : /* decode message */
868 0 : if (strstr(message, "Run: ") && run)
869 0 : *run = atoi(strstr(message, "Run: ") + 5);
870 :
871 0 : el_decode(message, "Date: ", date, 80); /* size from show_elog_submit_query() */
872 0 : el_decode(message, "Thread: ", thread, sizeof(thread));
873 0 : el_decode(message, "Author: ", author, 80); /* size from show_elog_submit_query() */
874 0 : el_decode(message, "Type: ", type, 80); /* size from show_elog_submit_query() */
875 0 : el_decode(message, "System: ", syst, 80); /* size from show_elog_submit_query() */
876 0 : el_decode(message, "Subject: ", subject, 256); /* size from show_elog_submit_query() */
877 0 : el_decode(message, "Attachment: ", attachment_all, sizeof(attachment_all));
878 0 : el_decode(message, "Encoding: ", encoding, 80); /* size from show_elog_submit_query() */
879 :
880 : /* break apart attachements */
881 0 : if (attachment1 && attachment2 && attachment3) {
882 0 : attachment1[0] = attachment2[0] = attachment3[0] = 0;
883 0 : p = strtok(attachment_all, ",");
884 0 : if (p != NULL) {
885 0 : mstrlcpy(attachment1, p, 256); /* size from show_elog_submit_query() */
886 0 : p = strtok(NULL, ",");
887 0 : if (p != NULL) {
888 0 : mstrlcpy(attachment2, p, 256); /* size from show_elog_submit_query() */
889 0 : p = strtok(NULL, ",");
890 0 : if (p != NULL)
891 0 : mstrlcpy(attachment3, p, 256); /* size from show_elog_submit_query() */
892 : }
893 : }
894 : }
895 :
896 : /* conver thread in reply-to and reply-from */
897 0 : if (orig_tag != NULL && reply_tag != NULL) {
898 0 : p = strtok(thread, " \r");
899 0 : if (p != NULL)
900 0 : strcpy(orig_tag, p);
901 : else
902 0 : strcpy(orig_tag, "");
903 0 : p = strtok(NULL, " \r");
904 0 : if (p != NULL)
905 0 : strcpy(reply_tag, p);
906 : else
907 0 : strcpy(reply_tag, "");
908 0 : if (atoi(orig_tag) == 0)
909 0 : orig_tag[0] = 0;
910 0 : if (atoi(reply_tag) == 0)
911 0 : reply_tag[0] = 0;
912 : }
913 :
914 0 : p = strstr(message, "========================================\n");
915 :
916 0 : if (text != NULL) {
917 0 : if (p != NULL) {
918 0 : p += 41;
919 0 : if ((int) strlen(p) >= *textsize) {
920 0 : strncpy(text, p, *textsize - 1);
921 0 : text[*textsize - 1] = 0;
922 0 : free(message);
923 0 : return EL_TRUNCATED;
924 : } else {
925 0 : strcpy(text, p);
926 :
927 : /* strip end tag */
928 0 : if (strstr(text, "$End$"))
929 0 : *strstr(text, "$End$") = 0;
930 :
931 0 : *textsize = strlen(text);
932 : }
933 : } else {
934 0 : text[0] = 0;
935 0 : *textsize = 0;
936 : }
937 : }
938 :
939 0 : free(message);
940 0 : message = NULL;
941 :
942 0 : if (search_status == EL_LAST_MSG)
943 0 : return EL_LAST_MSG;
944 :
945 0 : return EL_SUCCESS;
946 : }
947 :
948 :
949 : /********************************************************************/
950 0 : INT el_search_run(int run, char *return_tag)
951 : /********************************************************************\
952 :
953 : Routine: el_search_run
954 :
955 : Purpose: Find first message belonging to a specific run
956 :
957 : Input:
958 : int run Run number
959 :
960 : Output:
961 : char *tag tag of retrieved message
962 :
963 : Function value:
964 : EL_SUCCESS Successful completion
965 : EL_LAST_MSG Last message in log
966 :
967 : \********************************************************************/
968 : {
969 0 : int actual_run=0, fh, status;
970 : char tag[256];
971 :
972 0 : tag[0] = return_tag[0] = 0;
973 :
974 : do {
975 : /* open first message in file */
976 0 : strcat(tag, "-1");
977 0 : status = el_search_message(tag, &fh, TRUE, NULL, 0);
978 0 : if (status == EL_FIRST_MSG)
979 0 : break;
980 0 : if (status != EL_SUCCESS)
981 0 : return status;
982 0 : close(fh);
983 :
984 0 : if (strchr(tag, '.') != NULL)
985 0 : strcpy(strchr(tag, '.'), ".0");
986 :
987 0 : el_retrieve(tag, NULL, &actual_run, NULL, NULL,
988 : NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
989 0 : } while (actual_run >= run);
990 :
991 0 : while (actual_run < run) {
992 0 : strcat(tag, "+1");
993 0 : status = el_search_message(tag, &fh, TRUE, NULL, 0);
994 0 : if (status == EL_LAST_MSG)
995 0 : break;
996 0 : if (status != EL_SUCCESS)
997 0 : return status;
998 0 : close(fh);
999 :
1000 0 : el_retrieve(tag, NULL, &actual_run, NULL, NULL,
1001 : NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
1002 : }
1003 :
1004 0 : strcpy(return_tag, tag);
1005 :
1006 0 : if (status == EL_LAST_MSG || status == EL_FIRST_MSG)
1007 0 : return status;
1008 :
1009 0 : return EL_SUCCESS;
1010 : }
1011 :
1012 :
1013 : /********************************************************************/
1014 0 : INT el_delete_message(const char *tag)
1015 : /********************************************************************\
1016 :
1017 : Routine: el_submit
1018 :
1019 : Purpose: Submit an ELog entry
1020 :
1021 : Input:
1022 : char *tag Message tage
1023 :
1024 : Output:
1025 : <none>
1026 :
1027 : Function value:
1028 : EL_SUCCESS Successful completion
1029 :
1030 : \********************************************************************/
1031 : {
1032 : #ifdef LOCAL_ROUTINES
1033 0 : INT size, fh, semaphore, offset = 0, tail_size, status;
1034 : char dir[256];
1035 : char str[256];
1036 : char file_name[256+256+10];
1037 : HNDLE hDB;
1038 0 : char *buffer = NULL;
1039 :
1040 0 : cm_get_experiment_database(&hDB, NULL);
1041 :
1042 : /* request semaphore */
1043 0 : cm_get_experiment_semaphore(NULL, &semaphore, NULL, NULL);
1044 0 : status = ss_semaphore_wait_for(semaphore, 5 * 60 * 1000);
1045 0 : if (status != SS_SUCCESS) {
1046 0 : cm_msg(MERROR, "el_delete_message",
1047 : "Cannot lock experiment semaphore, ss_semaphore_wait_for() status %d", status);
1048 0 : abort();
1049 : }
1050 :
1051 : /* generate file name YYMMDD.log in data directory */
1052 0 : cm_get_experiment_database(&hDB, NULL);
1053 :
1054 0 : size = sizeof(dir);
1055 0 : memset(dir, 0, size);
1056 0 : status = db_get_value(hDB, 0, "/Logger/Elog dir", dir, &size, TID_STRING, FALSE);
1057 0 : if (status != DB_SUCCESS)
1058 0 : db_get_value(hDB, 0, "/Logger/Data dir", dir, &size, TID_STRING, TRUE);
1059 :
1060 0 : if (dir[0] != 0 && dir[strlen(dir) - 1] != DIR_SEPARATOR)
1061 0 : strcat(dir, DIR_SEPARATOR_STR);
1062 :
1063 0 : strcpy(str, tag);
1064 0 : if (strchr(str, '.')) {
1065 0 : offset = atoi(strchr(str, '.') + 1);
1066 0 : *strchr(str, '.') = 0;
1067 : }
1068 0 : sprintf(file_name, "%s%s.log", dir, str);
1069 0 : fh = open(file_name, O_CREAT | O_RDWR | O_BINARY, 0644);
1070 0 : if (fh < 0) {
1071 0 : ss_semaphore_release(semaphore);
1072 0 : return EL_FILE_ERROR;
1073 : }
1074 0 : lseek(fh, offset, SEEK_SET);
1075 0 : xread(file_name, fh, str, 16);
1076 0 : size = atoi(str + 9);
1077 :
1078 : /* buffer tail of logfile */
1079 0 : lseek(fh, 0, SEEK_END);
1080 0 : tail_size = TELL(fh) - (offset + size);
1081 :
1082 0 : if (tail_size > 0) {
1083 0 : buffer = (char *) M_MALLOC(tail_size);
1084 0 : if (buffer == NULL) {
1085 0 : close(fh);
1086 0 : ss_semaphore_release(semaphore);
1087 0 : return EL_FILE_ERROR;
1088 : }
1089 :
1090 0 : lseek(fh, offset + size, SEEK_SET);
1091 0 : xread(file_name, fh, buffer, tail_size);
1092 : }
1093 0 : lseek(fh, offset, SEEK_SET);
1094 :
1095 0 : if (tail_size > 0) {
1096 0 : xwrite(file_name, fh, buffer, tail_size);
1097 0 : M_FREE(buffer);
1098 : }
1099 :
1100 : /* truncate file here */
1101 : #ifdef OS_WINNT
1102 : chsize(fh, TELL(fh));
1103 : #else
1104 0 : xtruncate(file_name, fh);
1105 : #endif
1106 :
1107 : /* if file length gets zero, delete file */
1108 0 : tail_size = lseek(fh, 0, SEEK_END);
1109 0 : close(fh);
1110 :
1111 0 : if (tail_size == 0)
1112 0 : remove(file_name);
1113 :
1114 : /* release elog semaphore */
1115 0 : ss_semaphore_release(semaphore);
1116 : #endif /* LOCAL_ROUTINES */
1117 :
1118 0 : return EL_SUCCESS;
1119 : }
1120 :
1121 : /**dox***************************************************************/
1122 : #endif /* DOXYGEN_SHOULD_SKIP_THIS */
1123 :
1124 : /**dox***************************************************************/
1125 : /** @} *//* end of elfunctioncode */
1126 :
1127 : /* emacs
1128 : * Local Variables:
1129 : * tab-width: 8
1130 : * c-basic-offset: 3
1131 : * indent-tabs-mode: nil
1132 : * End:
1133 : */
|