#include #include #include #include #include #include #include #include #define MAXFILES 40 #define MAXNAMELEN 64 #define MAX_CHILDREN 100 char *progname; char filenames[MAXFILES+1][MAXNAMELEN]; int numfiles, num_children, fds[MAXFILES]; pid_t child_pids[MAX_CHILDREN]; /************************************************************************ ******************** ERROUT ******************** ************************************************************************/ void errout(char *fmt, ...) { va_list ap; char temp[256]; int i; pid_t pid; sprintf(temp, "%s: ", progname); va_start(ap, fmt); vsprintf(temp+strlen(temp), fmt, ap); va_end(ap); if (errno) perror(temp); else fprintf(stderr, "%s\n", temp); for (i = 0; i < num_children; ++i) { if ((pid = child_pids[i]) != -1) kill(pid, SIGTERM); } exit(3); } /************************************************************************ ******************** USAGE ******************** ************************************************************************/ void usage() { fprintf(stderr, "usage: %s %s%s\n", progname, "-c num_children [-n num_iterations] ", "[-i interval_in_usecs] < FileNameList\n"); exit(1); } /************************************************************************ ******************** MAIN ******************** ************************************************************************/ main(int argc, char *argv[]) { int i, filenum, ch, iterations, count; useconds_t interval; pid_t pid; char *p, *line; struct timeval tv; unsigned int seed; struct flock lock; progname = argv[0]; for (i = strlen(progname) - 1; i >= 0 && progname[i] != '/'; --i); progname += (i + 1); interval = 0; num_children = -1; iterations = -1; while ((ch = getopt(argc, argv, "c:n:i:")) != EOF) { switch(ch) { case 'c': num_children = atoi(optarg); break; case 'i': interval = atoi(optarg); break; case 'n': iterations = atoi(optarg); break; default: usage(); } } if (num_children <= 0) usage(); if (num_children > MAX_CHILDREN) errout("Max number of processes is %d\n", MAX_CHILDREN); if (interval < 0) interval = 0; for (i = 0; i < MAX_CHILDREN; ++i) child_pids[i] = -1; numfiles = 0; line = filenames[0]; while (fgets(line, MAXNAMELEN-1, stdin) != NULL) { line[MAXNAMELEN-1] = '\0'; if ((p = strchr(line, '\n')) != NULL) *p = '\0'; line = filenames[++numfiles]; if (numfiles >= MAXFILES) break; } if (ferror(stdin)) errout("error reading filename list from stdin"); if (numfiles >= MAXFILES) fprintf(stderr, "%s: warning: only first %d filenames used\n", progname, MAXFILES); for (i = 0; i < num_children - 1; ++i) { if ((pid = fork()) < 0) errout("fork() failed on process # %d", i); if (pid > 0) child_pids[i] = pid; if (pid == 0) break; } for (i = 0; i < numfiles; ++i) { if ((fds[i] = open(filenames[i], O_RDWR)) < 0) errout("error opening %s for reading", filenames[i]); } if (gettimeofday(&tv, NULL) < 0) errout("gettimeofday() failed"); seed = ((tv.tv_sec & 0xFFF) << 20) | tv.tv_usec; srandom(seed); count = 0; for (;;) { filenum = random() % numfiles; memset(&lock, 0, sizeof(lock)); lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; if (fcntl(fds[filenum], F_SETLKW, &lock) < 0) errout("error locking %s, fd=%d", filenames[filenum], fds[filenum]); if (interval > 0) usleep(interval); lock.l_type = F_UNLCK; if (fcntl(fds[filenum], F_SETLKW, &lock) < 0) errout("error unlocking %s", filenames[filenum]); ++count; if (iterations > 0 && count >= iterations) break; } exit(0); }