ref: 8fa9d99424da17b8ac3e67fb6d5563bf71f51e56
dir: /src/seedbox/seedbox.c/
#include <u.h>
#include <libc.h>
typedef struct Seed Seed;
struct Seed {
int pid;
char *torrent;
int seen;
};
static Seed *seeds;
static int nseeds;
static char *ddir, *tdir;
static int tfd;
static void
spawn(Seed *s, char *t)
{
int p;
if(t != nil && (s->torrent = strdup(t)) == nil)
sysfatal("strdup: %r");
switch(p = fork()){
case -1:
sysfatal("fork: %r");
case 0:
if(chdir(ddir ? ddir : tdir) < 0)
sysfatal("chdir: %r");
execl("/bin/ip/torrent", "torrent", "-s", smprint("%s/%s", tdir, s->torrent), nil);
sysfatal("exec: %r");
default:
s->pid = p;
return;
}
}
static void
kill(Seed *s)
{
assert(s->pid != 0);
postnote(PNPROC, s->pid, "kill");
s->pid = 0;
free(s->torrent);
s->torrent = nil;
}
static void
scandir(void)
{
Dir *d;
char **new, *s;
int i, j, n, o, p;
for(j = 0; j < nseeds; j++)
seeds[j].seen = 0;
if(seek(tfd, 0, 0) != 0)
sysfatal("seek: %r");
n = dirreadall(tfd, &d);
if(n < 0)
sysfatal("dirreadall: %r");
new = mallocz(sizeof(char*)*n, 1);
if(new == nil)
sysfatal("malloc: %r");
o = 0;
for(i = 0; i < n; i++){
if((s = strstr(d[i].name, ".torrent")) == nil)
continue;
if(s[strlen(".torrent")] != '\0')
continue;
for(j = 0; j < nseeds; j++){
if(strcmp(seeds[j].torrent, d[i].name) != 0)
continue;
if(seeds[j].pid == 0)
spawn(seeds+j, nil);
seeds[j].seen = 1;
break;
}
if(j == nseeds)
new[o++] = d[i].name;
}
for(j = 0; o > 0 && j < nseeds; j++){
if(seeds[j].seen == 1)
continue;
kill(seeds+j);
spawn(seeds+j, new[--o]);
seeds[j].seen = 1;
}
if(o > 0){
seeds = realloc(seeds, sizeof(Seed) * (nseeds + o));
if(seeds == nil)
sysfatal("realloc: %r");
for(p = o, j = nseeds; j < nseeds + o; j++){
seeds[j].seen = 1;
spawn(seeds+j, new[--p]);
}
nseeds = nseeds + o;
}
for(j = 0; j < nseeds; j++)
if(seeds[j].seen == 0)
kill(seeds+j);
free(new);
free(d);
}
static int
catch(void*, char*)
{
int j;
for(j = 0; j < nseeds; j++)
kill(seeds+j);
return 0;
}
_Noreturn void
usage(void)
{
fprint(2, "%s: tdir <ddir>\n", argv0);
exits("usage");
}
void
main(int argc, char **argv)
{
int sec;
char *n, *r;
char buf[128];
sec = 30;
ARGBEGIN{
case 'w':
n = EARGF(usage());
sec = strtol(n, &r, 0);
if(n == r)
sysfatal("invalid number");
break;
default:
usage();
}ARGEND
switch(argc){
default:
usage();
case 2:
ddir = argv[1];
case 1:
tfd = open(argv[0], OREAD);
if(tfd < 0)
sysfatal("open: %r");
if(fd2path(tfd, buf, sizeof buf) != 0)
sysfatal("fd2path: %r");
tdir = strdup(buf);
if(tdir == nil)
sysfatal("tdir: %r");
}
switch(fork()){
case -1:
sysfatal("fork: %r");
case 0:
break;
default:
exits(0);
}
for(atnotify(catch, 1); ; sleep(sec * 1000))
scandir();
}