view watcher.c @ 158:9961a538c00e

rlgwebd.js: get rid of numerical game identifiers. Games will be indentified by gamename/username pairs. This will allow better interoperability with dgamelaunch. Polling clients are no longer supported; the code remnants need to be removed. The reaper() function will likely crash. Unexpectedly, the WebSocket client still works well enough to play. Watching and listing current games are probably broken.
author John "Elwin" Edwards
date Thu, 01 Jan 2015 15:56:22 -0500
parents 245a2959f504
children 66fef65c34e7
line wrap: on
line source

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/select.h>
#include <unistd.h>
#include <limits.h>
#include <dirent.h>

struct watchdir {
  int wd;
  char *name;
};

char ibuf[sizeof(struct inotify_event) + NAME_MAX + 1];

int startwatch(int ifd, char *dir, struct watchdir *w) {
  DIR *dstream;
  struct dirent *ent;

  w->name = dir;
  w->wd = inotify_add_watch(ifd, dir, IN_CREATE|IN_DELETE|IN_DELETE_SELF);
  if (w->wd < 0) {
    fprintf(stderr, "Could not watch %s\n", dir);
    return 1;
  }
  dstream = opendir(dir);
  if (dstream == NULL) {
    fprintf(stderr, "%s is not a readable directory\n", dir);
    inotify_rm_watch(ifd, w->wd);
    w->wd = -1;
    return 1;
  }
  ent = readdir(dstream);
  while (ent != NULL) {
    if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, ".."))
      printf("E %s/%s\n", dir, ent->d_name);
    ent = readdir(dstream);
  }
  closedir(dstream);
  fflush(stdout);
  return 0;
}

int main(int argc, char *argv[]) {
  int ifd, rsize, off, done, nwatchers, i;
  char typecode;
  struct inotify_event *iev;
  fd_set rfds;
  struct watchdir *watchers;

  done = 0;
  nwatchers = argc - 1;
  iev = (struct inotify_event *) ibuf;
  ifd = inotify_init();
  if (nwatchers == 0) {
    watchers = malloc(sizeof(struct watchdir));
    nwatchers = 1;
    startwatch(ifd, ".", watchers);
  }
  else {
    watchers = malloc(nwatchers * sizeof(struct watchdir));
    for (i = 0; i < nwatchers; i++) {
      startwatch(ifd, argv[i+1], watchers + i);
    }
  }

  while (!done) {
    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
    FD_SET(ifd, &rfds);
    select(ifd + 1, &rfds, NULL, NULL, NULL);
    if (FD_ISSET(ifd, &rfds)) {
      off = 0;
      rsize = read(ifd, ibuf, sizeof(struct inotify_event) + NAME_MAX + 1);
      while (off < rsize) {
        iev = (struct inotify_event *) (ibuf + off);
        if (iev->mask & IN_CREATE)
          typecode = 'C';
        else if (iev->mask & IN_DELETE)
          typecode = 'D';
        else
          typecode = '?';
        for (i = 0; i < nwatchers; i++) {
          if (watchers[i].wd == iev->wd)
            printf("%c %s/%s\n", typecode, watchers[i].name, iev->name);
        }
        off += sizeof(struct inotify_event) + iev->len;
      }
      fflush(stdout);
    }
    if (FD_ISSET(0, &rfds)) {
      read(0, &typecode, 1);
      if (typecode == '\n')
        done = 1;
    }
    
  }
  close(ifd);
  return 0;
}