2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
33 /* $Id: zoolib.c,v 1.8 2009/06/09 17:59:46 subrata_modak Exp $ */
37 * A Zoo is a file used to record what test tags are running at the moment.
38 * If the system crashes, we should be able to look at the zoo file to find out
39 * what was currently running. This is especially helpful when running multiple
40 * tests at the same time.
42 * The zoo file is meant to be a text file that fits on a standard console.
43 * You should be able to watch it with `cat zoofile`
46 * 80 characters per line, ending with a \n
47 * available lines start with '#'
48 * expected line fromat: pid_t,tag,cmdline
52 #include <stdlib.h> /* for getenv */
56 char zoo_error
[ZELEN
];
59 /* glibc2.2 definition needs -D_XOPEN_SOURCE, which breaks other things. */
60 extern int sighold (int __sig
);
61 extern int sigrelse (int __sig
);
64 /* zoo_mark(): private function to make an entry to the zoo
65 * returns 0 on success, -1 on error */
66 static int zoo_mark(zoo_t z
, char *entry
);
67 static int zoo_lock(zoo_t z
);
68 static int zoo_unlock(zoo_t z
);
69 /* cat_args(): helper function to make cmdline from argc, argv */
70 char *cat_args(int argc
, char **argv
);
73 /* zoo_getname(): create a filename to use for the zoo */
80 zoo
= getenv( "ZOO" );
82 snprintf(buf
, 1024, "%s/%s", zoo
, "active");
85 /* if there is no environment variable, we don't know where to put it */
91 /* zoo_open(): open a zoo for use */
93 zoo_open(char *zooname
)
97 new_zoo
= (zoo_t
)fopen(zooname
, "r+");
99 if (errno
== ENOENT
) {
100 /* file doesn't exist, try fopen(xxx, "a+") */
101 new_zoo
= (zoo_t
)fopen(zooname
, "a+");
104 snprintf(zoo_error
, ZELEN
,
105 "Could not open zoo as \"%s\", errno:%d %s",
106 zooname
, errno
, strerror(errno
));
110 new_zoo
= fopen(zooname
, "r+");
112 snprintf(zoo_error
, ZELEN
,
113 "Could not open zoo as \"%s\", errno:%d %s",
114 zooname
, errno
, strerror(errno
));
127 snprintf(zoo_error
, ZELEN
,
128 "closing zoo caused error, errno:%d %s",
129 errno
, strerror(errno
));
136 zoo_mark(zoo_t z
, char *entry
)
138 FILE *fp
= (FILE *)z
;
155 if (fgets(buf
, BUFLEN
, fp
) == NULL
)
160 if (fseek(fp
, pos
, SEEK_SET
)) {
162 snprintf(zoo_error
, ZELEN
,
163 "seek error while writing to zoo file, errno:%d %s",
164 errno
, strerror(errno
));
167 /* write the entry, left justified, and padded/truncated to the
168 * same size as the previous entry */
169 fprintf(fp
, "%-*.*s\n", (int)strlen(buf
)-1, (int)strlen(buf
)-1, entry
);
176 if (fseek(fp
, 0, SEEK_END
)) {
177 snprintf(zoo_error
, ZELEN
,
178 "error seeking to end of zoo file, errno:%d %s",
179 errno
, strerror(errno
));
182 fprintf(fp
, "%-*.*s\n", 79, 79, entry
);
192 zoo_mark_cmdline(zoo_t z
, pid_t p
, char *tag
, char *cmdline
)
194 char new_entry
[BUFLEN
];
196 snprintf(new_entry
, 80, "%d,%s,%s", p
, tag
, cmdline
);
197 return zoo_mark(z
, new_entry
);
201 zoo_mark_args(zoo_t z
, pid_t p
, char *tag
, int ac
, char **av
)
206 cmdline
= cat_args(ac
, av
);
207 ret
= zoo_mark_cmdline(z
, p
, tag
, cmdline
);
214 zoo_clear(zoo_t z
, pid_t p
)
216 FILE *fp
= (FILE *)z
;
233 if (fgets(buf
, BUFLEN
, fp
) == NULL
)
239 that_pid
= atoi(buf
);
241 if (fseek(fp
, pos
, SEEK_SET
)) {
243 snprintf(zoo_error
, ZELEN
,
244 "seek error while writing to zoo file, errno:%d %s",
245 errno
, strerror(errno
));
248 if (ftell(fp
) != pos
) {
249 printf("fseek failed\n");
259 /* FIXME: unlock zoo file */
264 snprintf(zoo_error
, ZELEN
,
265 "zoo_clear() did not find pid(%d)",
274 zoo_getpid(zoo_t z
, char *tag
)
276 FILE *fp
= (FILE *)z
;
277 char buf
[BUFLEN
], *s
;
289 if (fgets(buf
, BUFLEN
, fp
) == NULL
)
293 continue; /* recycled line */
295 if ((s
= strchr(buf
, ',')) == NULL
)
296 continue; /* line was not expected format */
298 if (strncmp(s
+1, tag
, strlen(tag
)))
299 continue; /* tag does not match */
301 this_pid
= atoi(buf
);
313 FILE *fp
= (FILE *)z
;
315 sigset_t block_these
;
321 zlock
.l_whence
= zlock
.l_start
= zlock
.l_len
= 0;
322 zlock
.l_type
= F_WRLCK
;
324 sigemptyset(&block_these
);
325 sigaddset(&block_these
, SIGINT
);
326 sigaddset(&block_these
, SIGTERM
);
327 sigaddset(&block_these
, SIGHUP
);
328 sigaddset(&block_these
, SIGUSR1
);
329 sigaddset(&block_these
, SIGUSR2
);
330 sigprocmask(SIG_BLOCK
, &block_these
, NULL
);
333 ret
= fcntl(fileno(fp
), F_SETLKW
, &zlock
);
334 } while (ret
== -1 && errno
== EINTR
);
336 sigprocmask(SIG_UNBLOCK
, &block_these
, NULL
);
338 snprintf(zoo_error
, ZELEN
,
339 "failed to unlock zoo file, errno:%d %s",
340 errno
, strerror(errno
));
350 FILE *fp
= (FILE *)z
;
352 sigset_t block_these
;
358 zlock
.l_whence
= zlock
.l_start
= zlock
.l_len
= 0;
359 zlock
.l_type
= F_UNLCK
;
361 sigemptyset(&block_these
);
362 sigaddset(&block_these
, SIGINT
);
363 sigaddset(&block_these
, SIGTERM
);
364 sigaddset(&block_these
, SIGHUP
);
365 sigaddset(&block_these
, SIGUSR1
);
366 sigaddset(&block_these
, SIGUSR2
);
367 sigprocmask(SIG_BLOCK
, &block_these
, NULL
);
370 ret
= fcntl(fileno(fp
), F_SETLKW
, &zlock
);
371 } while (ret
== -1 && errno
== EINTR
);
373 sigprocmask(SIG_UNBLOCK
, &block_these
, NULL
);
376 snprintf(zoo_error
, ZELEN
,
377 "failed to lock zoo file, errno:%d %s",
378 errno
, strerror(errno
));
385 cat_args(int argc
, char **argv
)
390 for( size
= a
= 0; a
< argc
; a
++) {
391 size
+= strlen(argv
[a
]);
395 if( (cmd
= (char *)malloc(size
)) == NULL
) {
396 snprintf(zoo_error
, ZELEN
,
397 "Malloc Error, %s/%d",
403 for(a
= 0; a
< argc
; a
++) {
406 strcat(cmd
, argv
[a
]);
412 #if defined(UNIT_TEST)
416 zt_add(zoo_t z
, int n
)
421 snprintf(tag
, 10, "%s%d", "test", n
);
422 snprintf(cmdline
, 200, "%s%d %s %s %s", "runtest", n
, "one", "two", "three");
424 zoo_mark_cmdline(z
, n
, tag
, cmdline
);
428 main(int argc
, char *argv
[])
433 char *test_tag
= "unittest";
437 zooname
= zoo_getname();
440 zooname
= strdup("test_zoo");
442 printf("Test zoo filename is %s\n", zooname
);
444 if ((test_zoo
= zoo_open(zooname
)) == NULL
) {
445 printf("Error opennning zoo\n");
450 zoo_mark_args(test_zoo
, getpid(), test_tag
, argc
, argv
);
453 for(j
= 0; j
< 5; j
++) {
454 for(i
= 0; i
< 20; i
++) {
459 zoo_clear(test_zoo
, i
);
463 zoo_clear(test_zoo
, getpid());