Esempio n. 1
0
static int walk_tree(const char* path, watch_node* parent, array* ignores) {
  if (is_ignored(path, ignores)) {
    return ERR_IGNORE;
  }

  DIR* dir = opendir(path);
  if (dir == NULL) {
    if (errno == EACCES) {
      return ERR_IGNORE;
    }
    else if (errno == ENOTDIR) {  // flat root
      return add_watch(path, parent);
    }
    userlog(LOG_ERR, "opendir(%s): %s", path, strerror(errno));
    return ERR_CONTINUE;
  }

  int id = add_watch(path, parent);
  if (id < 0) {
    closedir(dir);
    return id;
  }

  struct dirent* entry;
  char subdir[PATH_MAX];
  strcpy(subdir, path);
  if (subdir[strlen(subdir) - 1] != '/') {
    strcat(subdir, "/");
  }
  char* p = subdir + strlen(subdir);

  while ((entry = readdir(dir)) != NULL) {
    if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
      continue;
    }

    strcpy(p, entry->d_name);
    if (!is_directory(entry, subdir)) {
      continue;
    }

    int subdir_id = walk_tree(subdir, table_get(watches, id), ignores);
    if (subdir_id < 0 && subdir_id != ERR_IGNORE) {
      rm_watch(id, true);
      id = subdir_id;
      break;
    }
  }

  closedir(dir);
  return id;
}
Esempio n. 2
0
static void watch_toggled(DBusWatch *watch, void *data)
{
	if (dbus_watch_get_enabled(watch))
		add_watch(watch, data);
	else
		remove_watch(watch, data);
}
Esempio n. 3
0
/**
 * The callback for when the main thread has issued a command to the run loop
 * thread. Reads all the pending commands and executes them
 */
static void command_callback(
    CFFileDescriptorRef fdref,
    CFOptionFlags callBackTypes,
    void *context) {
  int fd = CFFileDescriptorGetNativeDescriptor(fdref);
  struct thread_env *thread_env = (struct thread_env *)context;
  struct command *to_do = NULL;
  struct command *to_free = NULL;
  clear_pipe(fd);
  do {
    to_do = *(thread_env->commands);
  } while (OSAtomicCompareAndSwapPtr(to_do, NULL, (void *)(thread_env->commands)) == false);
  while (to_do != NULL) {
    switch (to_do->type) {
      case ADD_WATCH:
        add_watch(to_do->arg, thread_env);
        break;
      case RM_WATCH:
        // hh_server doesn't need this at the moment. Shouldn't be too hard to
        // do...just need to map of paths to FSEvent streams.
        fprintf(stderr, "fsevents impl doesn't support removing watches yet\n");
        break;
    }
    to_free = to_do;
    to_do = to_do->next;
    free(to_free->arg);
    free(to_free);
  }
  // For some reason you have to re-enable this callback every bloody time
  CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack);
}
Esempio n. 4
0
  bool kqueue_monitor::scan(const string& path, bool is_root_path)
  {
    struct stat fd_stat;
    if (!lstat_path(path, fd_stat)) return false;

    if (follow_symlinks && S_ISLNK(fd_stat.st_mode))
    {
      string link_path;
      if (read_link_path(path, link_path))
        return scan(link_path);

      return false;
    }

    bool is_dir = S_ISDIR(fd_stat.st_mode);

    if (!is_dir && !is_root_path && directory_only) return true;
    if (!is_dir && !accept_path(path)) return true;
    if (!add_watch(path, fd_stat)) return false;
    if (!recursive) return true;
    if (!is_dir) return true;

    vector<string> children = get_directory_children(path);

    for (string& child : children)
    {
      if (child.compare(".") == 0 || child.compare("..") == 0) continue;

      scan(path + "/" + child, false);
    }

    return true;
  }
Esempio n. 5
0
void listen_primary_changed_signal(GDBusSignalCallback handler, gpointer data,
                                   GDestroyNotify data_free_func)
{
    GError* err = NULL;
    static GDBusConnection* conn = NULL;
    if (conn == NULL ) {
        conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &err);
    }
    if (err != NULL) {
        g_warning("[%s] get dbus failed: %s\n", __func__, err->message);
        g_clear_error(&err);
        return;
    }
    add_watch(conn, DISPLAY_PATH, DISPLAY_INTERFACE, PRIMARY_CHANGED_SIGNAL);
    g_dbus_connection_signal_subscribe(conn,
                                       DISPLAY_NAME,
                                       DISPLAY_INTERFACE,
                                       PRIMARY_CHANGED_SIGNAL,
                                       DISPLAY_PATH,
                                       NULL,
                                       G_DBUS_SIGNAL_FLAGS_NONE,
                                       handler,
                                       data,
                                       data_free_func);
}
Esempio n. 6
0
static void toggle_watch(DBusWatch *w, void *data)
{
    show_debug(__FILE__,__FUNCTION__,__LINE__,"toggling dbus watch watch=%p\n", w);
    if (dbus_watch_get_enabled(w))
        add_watch(w, data);
    else
        remove_watch(w, data);
}
Esempio n. 7
0
static int
handle_add_repo (SeafWTMonitor *monitor, const char *repo_id, const char *worktree)
{
    FSEventStreamRef stream = add_watch (monitor, repo_id, worktree);
    if (!stream)
        return -1;
    return 0;
}
Esempio n. 8
0
static void toggle_watch(DBusWatch *w, void *data)
{
    printf(" WATCH:    toggle dbus watch watch=%p\n", w);
    if (dbus_watch_get_enabled(w))
        add_watch(w, data);
    else
        remove_watch(w, data);
}
Esempio n. 9
0
static int handle_add_repo (SeafWTMonitorPriv *priv, const char *repo_id, long *handle)
{
    g_assert (handle);
    FSEventStreamRef stream = add_watch (priv, repo_id);
    if (!stream)
        return -1;
    *handle = (long)stream;
    return 0;
}
Esempio n. 10
0
static void watch_toggled(DBusWatch *watch, void *data)
{
	/* Because we just exit on OOM, enable/disable is
	 * no different from add/remove */
	if (dbus_watch_get_enabled(watch))
		add_watch(watch, data);
	else
		remove_watch(watch, data);
}
Esempio n. 11
0
static int walk_tree(int path_len, watch_node* parent, bool recursive, array* mounts) {
  for (int j=0; j<array_size(mounts); j++) {
    char* mount = array_get(mounts, j);
    if (strncmp(path_buf, mount, strlen(mount)) == 0) {
      userlog(LOG_DEBUG, "watch path '%s' crossed mount point '%s' - skipping", path_buf, mount);
      return ERR_IGNORE;
    }
  }

  DIR* dir = NULL;
  if (recursive) {
    if ((dir = opendir(path_buf)) == NULL) {
      if (errno == EACCES || errno == ENOENT || errno == ENOTDIR) {
        userlog(LOG_DEBUG, "opendir(%s): %d", path_buf, errno);
        return ERR_IGNORE;
      }
      else {
        userlog(LOG_ERR, "opendir(%s): %s", path_buf, strerror(errno));
        return ERR_CONTINUE;
      }
    }
  }

  int id = add_watch(path_len, parent);

  if (dir == NULL) {
    return id;
  }
  else if (id < 0) {
    closedir(dir);
    return id;
  }

  path_buf[path_len] = '/';

  struct dirent* entry;
  while ((entry = readdir(dir)) != NULL) {
    if (entry->d_type != DT_DIR ||
        strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
      continue;
    }

    int name_len = strlen(entry->d_name);
    memcpy(path_buf + path_len + 1, entry->d_name, name_len + 1);

    int subdir_id = walk_tree(path_len + 1 + name_len, table_get(watches, id), recursive, mounts);
    if (subdir_id < 0 && subdir_id != ERR_IGNORE) {
      rm_watch(id, true);
      id = subdir_id;
      break;
    }
  }

  closedir(dir);
  return id;
}
Esempio n. 12
0
static int handle_add_repo (SeafWTMonitor *monitor,
                            const char *repo_id,
                            const char *worktree)
{
    HANDLE handle;

    handle = add_watch (monitor->priv, repo_id, worktree);
    if (handle == NULL ||
        !add_handle_to_iocp(monitor, handle)) {
        return -1;
    }

    return 0;
}
Esempio n. 13
0
static int handle_add_repo (SeafWTMonitorPriv *priv, const char *repo_id, long *handle) 
{
    int inotify_fd;
    g_assert (handle != NULL);
    inotify_fd = add_watch (repo_id);

    if (inotify_fd < 0)
        return -1;

    FD_SET (inotify_fd, &priv->read_fds);
    priv->maxfd = MAX (inotify_fd, priv->maxfd);
    *handle = (long)inotify_fd;
    return 0;
}
Esempio n. 14
0
File: vnode.c Progetto: hajuuk/R7000
int
evfilt_vnode_knote_create(struct filter *filt, struct knote *kn)
{
    struct stat sb;

    if (fstat(kn->kev.ident, &sb) < 0) {
        dbg_puts("fstat failed");
        return (-1);
    }
    kn->data.vnode.nlink = sb.st_nlink;
    kn->data.vnode.size = sb.st_size;
    kn->kev.data = -1;

    return (add_watch(filt, kn));
}
Esempio n. 15
0
static int add_watch(int fd, char *indir, unsigned int mask)
{
	int wd = inotify_add_watch(fd, indir, mask);
	if (wd == -1)
	{
		LOG(vfs_sig_log, LOG_ERROR, "add %s to inotify watch err %m\n", indir);
		return -1;
	}
	if (wd >= MAX_WATCH)
	{
		LOG(vfs_sig_log, LOG_ERROR, "too many wd %d add to inotify!\n", wd);
		return -1;
	}
	snprintf(watch_dirs[wd], sizeof(watch_dirs[wd]), "%s", indir);
	DIR *dp;
	struct dirent *dirp;
	if ((dp = opendir(indir)) == NULL) 
	{
		LOG(vfs_sig_log, LOG_ERROR, "add inotify watch opendir %s err %m\n", indir);
		return -1;
	}

	char file[256] = {0x0};
	struct stat filestat;
	while((dirp = readdir(dp)) != NULL)
	{
		if (dirp->d_name[0] == '.')
			continue;
		snprintf(file, sizeof(file), "%s/%s", indir, dirp->d_name);
		if (stat(file, &filestat))
		{
			LOG(vfs_sig_log, LOG_ERROR, "add inotify watch get file stat %s err %m\n", file);
			continue;
		}

		if (S_ISDIR(filestat.st_mode))
		{
			if (add_watch(fd, file, mask))
				return -1;
		}
	}
	closedir(dp);
	LOG(vfs_sig_log, LOG_TRACE, "add inotify watch %s ok\n", indir);
	return 0;
}  
Esempio n. 16
0
  void inotify_monitor::scan(const string &path, const bool accept_non_dirs)
  {
    struct stat fd_stat;
    if (!stat_path(path, fd_stat)) return;

    /*
     * When watching a directory the inotify API will return change events of
     * first-level children.  Therefore, we do not need to manually add a watch
     * for a child unless it is a directory.  By default, accept_non_dirs is
     * true to allow watching a file when first invoked on a node.
     */
    if (!accept_non_dirs && !S_ISDIR(fd_stat.st_mode)) return;
    else if (follow_symlinks && S_ISLNK(fd_stat.st_mode))
    {
      string link_path;
      if (read_link_path(path, link_path))
        scan(link_path/*, fn */, accept_non_dirs);

      return;
    }

    if (!S_ISDIR(fd_stat.st_mode) && !accept_path(path)) return;
    if (!add_watch(path, fd_stat /*, fn */)) return;
    if (!recursive || !S_ISDIR(fd_stat.st_mode)) return;

    vector<string> children;
    get_directory_children(path, children);

    for (const string &child : children)
    {
      if (child.compare(".") == 0 || child.compare("..") == 0) continue;

      /*
       * Scan children but only watch directories.
       */
      scan(path + "/" + child /*, fn */, false);
    }
  }
Esempio n. 17
0
static void inotify_event_handler(struct inotify_event *event)  
{
	int wd = event->wd;
	char *filename = event->name;

	if(filename == NULL )
	{
		LOG(vfs_sig_log, LOG_DEBUG, "inotify event has no filename, go next!\n");
		return;
	}
	LOG(vfs_sig_log, LOG_DEBUG, "inotify event filename [%s]!\n", filename);

	if(filename[0] == '.')
	{
		LOG(vfs_sig_log, LOG_TRACE, "tmpfile [%s] , i dont care!\n", filename);
		return;
	}

	char path[256] = {0x0};
	strcpy(path, watch_dirs[wd]);
	strcat(path, "/");
	strcat(path, filename);
	if (event->mask & IN_CREATE)
	{
		struct stat filestat;
		if (stat(path, &filestat))
		{
			LOG(vfs_sig_log, LOG_ERROR, "get file stat %s err %m\n", path);
			return;
		}

		if (S_ISDIR(filestat.st_mode))
		{
			LOG(vfs_sig_log, LOG_NORMAL, "new dir %s\n", path);
			add_watch(inotify_fd, path, mask);
		}
		else
			LOG(vfs_sig_log, LOG_NORMAL, "file %s be create, ignore it\n", path);
		return;
	}

    t_task_base task;
	memset(&task, 0, sizeof(task));

	snprintf(task.filename, sizeof(task.filename), "%s", path);
	if((event->mask & IN_CLOSE_WRITE) || (event->mask & IN_MOVED_TO)) 
	{
		if (get_localfile_stat(&task) != LOCALFILE_OK)
		{
			LOG(vfs_sig_log, LOG_ERROR, "get_localfile_stat err %s %m\n", task.filename);
			return;
		}
		task.type = TASK_ADDFILE;
    }
	
	if((event->mask & IN_DELETE) || (event->mask & IN_MOVED_FROM)) 
	{
		LOG(vfs_sig_log, LOG_DEBUG, "inotify file delete or move away %s\n", path);
		task.type = TASK_DELFILE;
	}
 	   
	t_vfs_tasklist *vfs_task;
	int ret = vfs_get_task(&vfs_task, TASK_HOME);
	if(ret != GET_TASK_OK) 
	{
		LOG(vfs_sig_log, LOG_ERROR, "inotify get task_home error %s:%d:%d\n", ID, FUNC, LN);
		return;
	}
	memset(&(vfs_task->task), 0, sizeof(t_vfs_taskinfo));
	memcpy(&(vfs_task->task.base), &task, sizeof(task));
	vfs_set_task(vfs_task, TASK_WAIT);	
	
	LOG(vfs_sig_log, LOG_DEBUG, "inotify add task to task_wait filepath %s, task type %d\n", task.filename, task.type);
	
	return;
}   
Esempio n. 18
0
static void start_inotify_thread(void * arg)
{

#ifndef PR_SET_NAME
#define PR_SET_NAME 15
#endif
	memset(watch_dirs, 0, sizeof(watch_dirs));
	prctl(PR_SET_NAME, "fcs_inotify", 0, 0, 0);
	pthread_detach(pthread_self());

	inotify_fd = inotify_init();
	if(inotify_fd < 0)
	{
		stop = 1;
		LOG(vfs_sig_log, LOG_ERROR, "inotify thread init error!\n");
		return ;
	}

	char *flvdir = myconfig_get_value("vfs_src_datadir");
	if(!flvdir)
	{
		flvdir = "/flvdata";
	}

	FD_ZERO(&fds);
	FD_SET(inotify_fd, &fds);
	int ret = add_watch(inotify_fd, flvdir, mask);
	if(ret != 0)
	{
		stop = 1;
		LOG(vfs_sig_log, LOG_ERROR, "inotify add watch dir error!\n");
		return ;
	}

	LOG(vfs_sig_log, LOG_DEBUG, "start to inotify watch dir\n");

	struct timeval tv;
	//Ñ­»·¼ì²éʼþ
	while(1) 
	{
		tv.tv_sec = 20;
		tv.tv_usec = 0;
		if (select(inotify_fd + 1, &fds, NULL, NULL, &tv) > 0)
		{
			while (1)
			{
				int len, index = 0;
				unsigned char buf[1024] = {0};
				len = read(inotify_fd, &buf, sizeof(buf));
				if (len <= 0)
					break;
				while (index < len)
				{
					struct inotify_event *event = (struct inotify_event *)(buf + index);
					inotify_event_handler(event);
					index += sizeof(struct inotify_event) + event->len;
				}
			}
		}
		FD_ZERO(&fds);
		FD_SET(inotify_fd, &fds);
	}
}
Esempio n. 19
0
int
handle_monitor (int argc, gchar *argv[], gboolean do_help)
{
  GOptionContext *context;
  gchar *param;
  GError *error = NULL;
  GFileMonitorFlags flags;
  guint total = 0;
  guint i;

  g_set_prgname ("gio monitor");

  /* Translators: commandline placeholder */
  param = g_strdup_printf ("[%s...]", _("LOCATION"));
  context = g_option_context_new (param);
  g_free (param);
  g_option_context_set_help_enabled (context, FALSE);
  g_option_context_set_summary (context,
    _("Monitor files or directories for changes."));
  g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);

  if (do_help)
    {
      show_help (context, NULL);
      return 0;
    }

  if (!g_option_context_parse (context, &argc, &argv, &error))
    {
      show_help (context, error->message);
      g_error_free (error);
      return 1;
    }

  g_option_context_free (context);

  flags = (no_moves ? 0 : G_FILE_MONITOR_WATCH_MOVES) |
          (mounts ? G_FILE_MONITOR_WATCH_MOUNTS : 0);

  if (watch_dirs)
    {
      for (i = 0; watch_dirs[i]; i++)
        if (!add_watch (watch_dirs[i], WATCH_DIR, flags, TRUE))
          return 1;
      total++;
    }

  if (watch_files)
    {
      for (i = 0; watch_files[i]; i++)
        if (!add_watch (watch_files[i], WATCH_FILE, flags, TRUE))
          return 1;
      total++;
    }

  if (watch_direct)
    {
      for (i = 0; watch_direct[i]; i++)
        if (!add_watch (watch_direct[i], WATCH_FILE, flags | G_FILE_MONITOR_WATCH_HARD_LINKS, TRUE))
          return 1;
      total++;
    }

  if (watch_silent)
    {
      for (i = 0; watch_silent[i]; i++)
        if (!add_watch (watch_silent[i], WATCH_FILE, flags | G_FILE_MONITOR_WATCH_HARD_LINKS, FALSE))
          return 1;
      total++;
    }

  if (watch_default)
    {
      for (i = 0; watch_default[i]; i++)
        if (!add_watch (watch_default[i], WATCH_AUTO, flags, TRUE))
          return 1;
      total++;
    }

  if (!total)
    {
      g_printerr ("gio: Must give at least one file to monitor\n");
      return 1;
    }

  while (TRUE)
    g_main_context_iteration (NULL, TRUE);

  return 0;
}
Esempio n. 20
0
int main(int argc, char *argv[])
{
    struct itimerspec its;
    sigset_t mask;
    std::unordered_map<int, std::string> inotify_watch_map;
    std::unordered_map<int, fd::socket> conn_map;
    struct epoll_event events[MAX_EVENTS];
    
    /* setup inotify */
    
    auto inotify = fd::inotify();
    
    for (int i = 0; i < argc; ++i) {
        int wd = inotify.add_watch(argv[i], IN_OPEN | IN_MODIFY | IN_ACCESS);
        inotify_watch_map[wd] = std::string(argv[i]);
    }
    
    /* setup timerfd */

    its.it_value.tv_sec = 1;
    its.it_value.tv_nsec = 0;
    its.it_interval.tv_sec = 10;
    its.it_interval.tv_nsec = 0;

    auto timerfd = fd::timerfd();
    timerfd.settime(its);
    
    /* setup signalfd */
    
    sigfillset(&mask);
    
    int err = sigprocmask(SIG_BLOCK, &mask, nullptr);
    if (err < 0)
        throw std::system_error(errno, std::system_category(), "sigprocmask()");
    
    auto sfd = fd::signalfd(mask);
    
    /* setup socket */
    unlink("/tmp/.epoll_test.sock");
    auto server = fd::easy::unix_socket::server("/tmp/.epoll_test.sock");
        
    /* setup epoll */
    
    auto epoll = fd::epoll();
    epoll.add(inotify, EPOLLIN, inotify);
    epoll.add(timerfd, EPOLLIN, timerfd);
    epoll.add(sfd, EPOLLIN, sfd);
    epoll.add(server, EPOLLIN, server);

    
    std::cout << "Use: \"Hello, World!\" | ncat -U /tmp/.epoll_test.sock\n"
              << "Press CTRL + c to exit\n";
              
    bool loop = true;
    
    while (loop) {
        auto nfds = epoll.wait(events, MAX_EVENTS);
        
        for (int i = 0; i < nfds; ++i) {
            if (events[i].data.fd == inotify) {
                struct inotify_event *event;
                char buffer[4096];
                
                std::cout << "**INOTIFY: ";
                
                auto n = inotify.read(buffer, sizeof(buffer));
                
                FOR_EACH_INOTIFY_EVENT(buffer, n, event) {
                    if (event->len > 0)
                        std::cout << event->name << " ";
                    else
                        std::cout << inotify_watch_map[event->wd] << " ";
                    
                    if (event->mask & IN_ACCESS)
                        std::cout << "IN_ACCESS ";
                    if (event->mask & IN_MODIFY)
                        std::cout << "IN_MODIFY ";
                    if (event->mask & IN_OPEN)
                        std::cout << "IN_OPEN ";
                    
                    std::cout << '\n';
                }
            } else if (events[i].data.fd == timerfd) {
                /* 
                 * Clear data on file descriptor, otherwise epoll will 
                 * trigger again.
                 */
                (void) timerfd.read();
                
                std::cout << "**TIMERFD: timeout\n";
            } else if (events[i].data.fd == sfd) {
                struct signalfd_siginfo info;
                
                sfd.read(info);
                
                std::cout << "**SIGNALFD: received " 
                          << strsignal(info.ssi_signo) << '\n';
                
                if (info.ssi_signo == SIGTERM || info.ssi_signo == SIGINT)
                    loop = false;
                
            } else if (events[i].data.fd == server) {
                auto sock = server.accept();

                epoll.add(sock, EPOLLIN, sock);
                
                /* 
                 * Notice how std::make_pair() can't make use of the cast 
                 * operator, therefore we can use the socket::fd() function
                 */
                conn_map.insert(std::make_pair(sock.fd(), std::move(sock)));
                std::cout << "**SERVER SOCKET: new connection\n";
            } else {
                char buf[128];
                auto it = conn_map.find(events[i].data.fd);
                
                std::cout << "**UNIX_CONNECTION: received: ";
                
                while (1) {
                    auto n = it->second.recv(buf, sizeof(buf), MSG_NOSIGNAL);
                    if (n == 0)
                        break;
                    
                    std::cout << std::string(buf, n);
                }
                conn_map.erase(it);
            }
        }
    }
Esempio n. 21
0
File: vnode.c Progetto: hajuuk/R7000
int
evfilt_vnode_knote_enable(struct filter *filt, struct knote *kn)
{
    return add_watch(filt, kn);
}
Esempio n. 22
0
	CmdResult Handle (const std::vector<std::string> &parameters, User *user)
	{
		if (parameters.empty())
		{
			watchlist* wl = ext.get(user);
			if (wl)
			{
				for (watchlist::iterator q = wl->begin(); q != wl->end(); q++)
				{
					if (!q->second.empty())
						user->WriteNumeric(604, "%s %s :is online", q->first.c_str(), q->second.c_str());
				}
			}
			user->WriteNumeric(607, ":End of WATCH list");
		}
		else if (parameters.size() > 0)
		{
			for (int x = 0; x < (int)parameters.size(); x++)
			{
				const char *nick = parameters[x].c_str();
				if (!strcasecmp(nick,"C"))
				{
					// watch clear
					watchlist* wl = ext.get(user);
					if (wl)
					{
						for (watchlist::iterator i = wl->begin(); i != wl->end(); i++)
						{
							watchentries::iterator i2 = whos_watching_me->find(i->first);
							if (i2 != whos_watching_me->end())
							{
								/* People are watching this user, am i one of them? */
								std::deque<User*>::iterator n = std::find(i2->second.begin(), i2->second.end(), user);
								if (n != i2->second.end())
									/* I'm no longer watching you... */
									i2->second.erase(n);

								if (i2->second.empty())
									/* nobody else is, either. */
									whos_watching_me->erase(i2);
							}
						}

						ext.unset(user);
					}
				}
				else if (!strcasecmp(nick,"L"))
				{
					watchlist* wl = ext.get(user);
					if (wl)
					{
						for (watchlist::iterator q = wl->begin(); q != wl->end(); q++)
						{
							if (!q->second.empty())
							{
								user->WriteNumeric(604, "%s %s :is online", q->first.c_str(), q->second.c_str());
								User *targ = ServerInstance->FindNick(q->first.c_str());
								if (targ->IsAway())
								{
									user->WriteNumeric(609, "%s %s %s %lu :is away", targ->nick.c_str(), targ->ident.c_str(), targ->dhost.c_str(), (unsigned long) targ->awaytime);
								}
							}
							else
								user->WriteNumeric(605, "%s * * 0 :is offline", q->first.c_str());
						}
					}
					user->WriteNumeric(607, ":End of WATCH list");
				}
				else if (!strcasecmp(nick,"S"))
				{
					watchlist* wl = ext.get(user);
					int you_have = 0;
					int youre_on = 0;
					std::string list;

					if (wl)
					{
						for (watchlist::iterator q = wl->begin(); q != wl->end(); q++)
							list.append(q->first.c_str()).append(" ");
						you_have = wl->size();
					}

					watchentries::iterator i2 = whos_watching_me->find(user->nick.c_str());
					if (i2 != whos_watching_me->end())
						youre_on = i2->second.size();

					user->WriteNumeric(603, ":You have %d and are on %d WATCH entries", you_have, youre_on);
					user->WriteNumeric(606, ":%s", list.c_str());
					user->WriteNumeric(607, ":End of WATCH S");
				}
				else if (nick[0] == '-')
				{
					nick++;
					remove_watch(user, nick);
				}
				else if (nick[0] == '+')
				{
					nick++;
					add_watch(user, nick);
				}
			}
		}
		return CMD_SUCCESS;
	}
Esempio n. 23
0
axa_json_res_t
axa_body_to_json(axa_emsg_t *emsg, nmsg_input_t nmsg_input, axa_p_hdr_t *hdr, axa_p_body_t *body, size_t body_len, char **out)
{
	struct axa_strbuf *sb = NULL, *sb_tmp = NULL;
	axa_json_res_t res;
	yajl_gen g = NULL;
	int yajl_rc;
	char op_str[AXA_P_OP_STRLEN];
	char addr_str[INET6_ADDRSTRLEN];
	axa_p_direction_t dir;
	uint8_t *p, *q;
	uint16_t user_objs_cnt, an_objs_cnt;
	_axa_p_stats_sys_t *sys;
	char time_buf[30];
	struct tm *tm_info;
	time_t t;
	runits_t ru;
	_axa_p_stats_user_t *user_obj;
	_axa_p_stats_user_rad_an_t *an_obj;

	switch(AXA_P2H16(hdr->op)) {
	case AXA_P_OP_MISSED_RAD:
	case AXA_P_OP_AHIT:
	case AXA_P_OP_ALIST:
		dir = AXA_P_FROM_RAD;
		break;
	case AXA_P_OP_USER:
	case AXA_P_OP_JOIN:
	case AXA_P_OP_PAUSE:
	case AXA_P_OP_GO:
	case AXA_P_OP_WATCH:
	case AXA_P_OP_WGET:
	case AXA_P_OP_STOP:
	case AXA_P_OP_ALL_STOP:
	case AXA_P_OP_CHANNEL:
	case AXA_P_OP_CGET:
	case AXA_P_OP_ACCT:
	case _AXA_P_OP_KILL_REQ:
	case _AXA_P_OP_STATS_REQ:
		dir = AXA_P_TO_SRA;
		break;
	case AXA_P_OP_ANOM:
	case AXA_P_OP_AGET:
	case AXA_P_OP_RADU:
		dir = AXA_P_TO_RAD;
		break;
	default:
		dir = AXA_P_FROM_SRA;
		break;
	} /* switch */

	if (axa_ck_hdr(emsg, hdr, "json", dir) == false)
		return (AXA_JSON_RES_FAILURE);

	if (AXA_P2H32(hdr->len) - sizeof(axa_p_hdr_t) != body_len) {
		axa_pemsg(emsg, "body length mismatch %zu != %zu",
				AXA_P2H32(hdr->len) - sizeof(axa_p_hdr_t),
				body_len);
		return (AXA_JSON_RES_FAILURE);
	}

	if (axa_ck_body(emsg, hdr->op, body, body_len) == false)
		return (AXA_JSON_RES_FAILURE);

	sb = axa_strbuf_init();
	if (sb == NULL) {
		axa_pemsg(emsg, "could not allocate axa_strbuf");
		return (AXA_JSON_RES_MEMFAIL);
	}

	sb_tmp = axa_strbuf_init();
	if (sb_tmp == NULL) {
		axa_pemsg(emsg, "could not allocate axa_strbuf");
		axa_strbuf_destroy(&sb);
		res = AXA_JSON_RES_MEMFAIL;
		goto err;
	}

	g = yajl_gen_alloc(NULL);
	AXA_ASSERT (g != NULL);

	yajl_rc = yajl_gen_config(g,
				  yajl_gen_print_callback,
				  _callback_print_yajl_axa_strbuf,
				  sb);
	AXA_ASSERT(yajl_rc != 0);

	add_yajl_map(g);

	add_yajl_string(g, "tag");
	if (AXA_P2H16(hdr->tag) == AXA_TAG_NONE)
		add_yajl_string(g, "*");
	else
		add_yajl_integer(g, AXA_P2H16(hdr->tag));


	add_yajl_string(g, "op");
	axa_op_to_str(op_str, sizeof(op_str), hdr->op);
	add_yajl_string(g, op_str);

	switch ((axa_p_op_t)hdr->op) {
	case AXA_P_OP_NOP:
		break;

	case AXA_P_OP_HELLO:
		add_yajl_string(g, "id");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->hello.id));

		add_yajl_string(g, "pvers_min");
		add_yajl_integer(g, body->hello.pvers_min);

		add_yajl_string(g, "pvers_max");
		add_yajl_integer(g, body->hello.pvers_max);

		add_yajl_string(g, "str");
		add_yajl_string(g, body->hello.str);
		break;

	case AXA_P_OP_OK:
	case AXA_P_OP_ERROR:
		add_yajl_string(g, "orig_op");
		axa_op_to_str(op_str, sizeof(op_str), body->result.orig_op);
		add_yajl_string(g, op_str);

		add_yajl_string(g, "str");
		add_yajl_string(g, body->result.str);
		break;

	case AXA_P_OP_MISSED:
		add_yajl_string(g, "missed");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed.missed));

		add_yajl_string(g, "dropped");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed.dropped));

		add_yajl_string(g, "rlimit");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed.rlimit));

		add_yajl_string(g, "filtered");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed.filtered));

		add_yajl_string(g, "last_report");
		add_yajl_integer(g, AXA_P2H32(body->missed.last_report));
		break;

	case AXA_P_OP_MISSED_RAD:
		add_yajl_string(g, "sra_missed");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.sra_missed));

		add_yajl_string(g, "sra_dropped");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.sra_dropped));

		add_yajl_string(g, "sra_rlimit");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.sra_rlimit));

		add_yajl_string(g, "sra_filtered");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.sra_filtered));

		add_yajl_string(g, "dropped");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.dropped));

		add_yajl_string(g, "rlimit");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.rlimit));

		add_yajl_string(g, "filtered");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->missed_rad.filtered));

		add_yajl_string(g, "last_report");
		add_yajl_integer(g, AXA_P2H32(body->missed_rad.last_report));
		break;

	case AXA_P_OP_WHIT:
		res = add_whit(emsg, g, sb, nmsg_input, &(body->whit), body_len);
		if (res != AXA_JSON_RES_SUCCESS)
			goto err;
		break;

	case AXA_P_OP_WATCH:
		add_watch(g, &(body->watch), body_len);
		break;

	case AXA_P_OP_ANOM: {
		bool print_parms;
		print_parms = body_len > offsetof(axa_p_anom_t, parms) && body->anom.parms[0] != '\0';
		add_anom(g, body->anom, print_parms);
		break;
	}

	case AXA_P_OP_CHANNEL:
		res = add_channel(emsg, g, body->channel.ch);
		if (res != AXA_JSON_RES_SUCCESS)
			goto err;

		add_yajl_string(g, "on");
		add_yajl_bool(g, body->channel.on != 0);
		break;

	case AXA_P_OP_WLIST:
		add_yajl_string(g, "cur_tag");
		add_yajl_integer(g, AXA_P2H16(body->wlist.cur_tag));

		add_watch(g, &(body->wlist.w), body_len - offsetof(axa_p_wlist_t, w));
		break;

	case AXA_P_OP_AHIT:
		add_yajl_string(g, "an");
		add_yajl_string(g, body->ahit.an.c);

		res = add_whit(emsg, g, sb, nmsg_input, &(body->ahit.whit), body_len - offsetof(axa_p_ahit_t, whit));
		if (res != AXA_JSON_RES_SUCCESS)
			goto err;
		break;

	case AXA_P_OP_ALIST: {
		bool print_parms;
		add_yajl_string(g, "cur_tag");
		add_yajl_integer(g, AXA_P2H16(body->alist.cur_tag));

		print_parms = body_len > offsetof(axa_p_alist_t, anom) + offsetof(axa_p_anom_t, parms) && body->alist.anom.parms[0] != '\0';
		add_anom(g, body->alist.anom, print_parms);
		break;
	}

	case AXA_P_OP_CLIST:
		res = add_channel(emsg, g, body->clist.ch);
		if (res != AXA_JSON_RES_SUCCESS)
			goto err;

		add_yajl_string(g, "on");
		add_yajl_bool(g, body->clist.on != 0);

		add_yajl_string(g, "spec");
		add_yajl_string(g, body->clist.spec.c);
		break;

	case AXA_P_OP_USER:
		add_yajl_string(g, "name");
		add_yajl_string(g, body->user.name);
		break;

	case AXA_P_OP_OPT: {
		char buf[AXA_P_OP_STRLEN];

		add_yajl_string(g, "type");
		add_yajl_string(g, axa_opt_to_str(buf, sizeof(buf), AXA_P2H64(body->opt.type)));

		switch((axa_p_opt_type_t)body->opt.type) {
			case AXA_P_OPT_TRACE: {
				add_yajl_string(g, "trace");
				if (AXA_P2H64(body->opt.u.trace) != AXA_P_OPT_TRACE_REQ) {
					add_yajl_number(g, sb_tmp, AXA_P2H64(body->opt.u.trace));
				} else {
					add_yajl_string(g, "REQUEST TRACE VALUE");
				}
				break;
			}

			case AXA_P_OPT_RLIMIT:
				add_yajl_string(g, "max_pkts_per_sec");
				res = add_rlimit_count(emsg, g, body->opt.u.rlimit.max_pkts_per_sec);
				if (res != AXA_JSON_RES_SUCCESS)
					goto err;

				add_yajl_string(g, "cur_pkts_per_sec");
				add_yajl_number(g, sb_tmp, AXA_P2H64(body->opt.u.rlimit.cur_pkts_per_sec));

				add_yajl_string(g, "report_secs");
				res = add_rlimit_count(emsg, g, body->opt.u.rlimit.report_secs);
				if (res != AXA_JSON_RES_SUCCESS)
					goto err;
				break;

			case AXA_P_OPT_SAMPLE:
				add_yajl_string(g, "sample");
				if (AXA_P2H64(body->opt.u.sample) == 0) {
					add_yajl_string(g, "requested");
				} else {
					axa_strbuf_reset(sb_tmp);
					axa_strbuf_append(sb_tmp, "%0.6f", ((double)AXA_P2H64(body->opt.u.sample)) / AXA_P_OPT_SAMPLE_MAX);
					add_yajl_number_sb(g, sb_tmp);
				}
				break;

			case AXA_P_OPT_SNDBUF:
				add_yajl_string(g, "bufsize");
				add_yajl_number(g, sb_tmp, AXA_P2H64(body->opt.u.bufsize));
				break;
		} /* switch */
		break;
	}

	case AXA_P_OP_JOIN:
		add_yajl_string(g, "id");
		add_yajl_number(g, sb_tmp, AXA_P2H64(body->join.id));
		break;

	case _AXA_P_OP_STATS_REQ:
		if (body->stats_req.version != _AXA_STATS_VERSION_ONE) {
			res = AXA_JSON_RES_FAILURE;
			goto err;
		}
		add_yajl_string(g, "version");
		add_yajl_integer(g, body->stats_req.version);

		add_yajl_string(g, "type");
		switch (body->stats_req.type) {
			case AXA_P_STATS_M_M_SUM:
				add_yajl_string(g, "summary");
				break;
			case AXA_P_STATS_M_M_ALL:
				add_yajl_string(g, "all");
				break;
			case AXA_P_STATS_M_M_SN:
				add_yajl_string(g, "serial number");
				break;
			case AXA_P_STATS_M_M_U:
				add_yajl_string(g, "user name");
				break;
			default:
				add_yajl_string(g, "unknown");
		}

		if (body->stats_req.type == AXA_P_STATS_M_M_SN) {
			add_yajl_string(g, "serial number");
			add_yajl_integer(g, body->stats_req.sn);
		}

		if (body->stats_req.type == AXA_P_STATS_M_M_U) {
			add_yajl_string(g, "user name");
			add_yajl_string(g, body->stats_req.user.name);
		}

		break;

	case _AXA_P_OP_STATS_RSP:
		if (body->stats_rsp.version != _AXA_STATS_VERSION_ONE) {
			res = AXA_JSON_RES_FAILURE;
			goto err;
		}
		add_yajl_string(g, "version");
		add_yajl_integer(g, body->stats_rsp.version);

		if (body->stats_rsp.sys_objs_cnt > 1) {
			res = AXA_JSON_RES_FAILURE;
			goto err;
		}

		add_yajl_string(g, "result");
		switch (body->stats_rsp.result) {
			case AXA_P_STATS_R_SUCCESS:
				add_yajl_string(g, "success");
				break;
			case AXA_P_STATS_R_FAIL_NF:
				add_yajl_string(g, "failed: user not found");
				break;
			case AXA_P_STATS_R_FAIL_UNK:
			default:
				add_yajl_string(g, "failed: unknown reason");
		}

		if (body->stats_rsp.sys_objs_cnt == 1) {
			p = (uint8_t *)&body->stats_rsp;
			sys = (_axa_p_stats_sys_t *)(p +
					sizeof (_axa_p_stats_rsp_t));

			if (sys->type != _AXA_P_STATS_TYPE_SYS) {
				res = AXA_JSON_RES_FAILURE;
				goto err;
			}

			add_yajl_string(g, "load");
			add_yajl_array(g);
			add_yajl_integer(g, AXA_P2H32(sys->load[0]));
			add_yajl_integer(g, AXA_P2H32(sys->load[1]));
			add_yajl_integer(g, AXA_P2H32(sys->load[2]));
			close_yajl_array(g);

			add_yajl_string(g, "cpu_usage");
			add_yajl_integer(g, AXA_P2H32(sys->cpu_usage));

			add_yajl_string(g, "uptime");
			add_yajl_integer(g, AXA_P2H32(sys->uptime));

			add_yajl_string(g, "starttime");
			add_yajl_integer(g, AXA_P2H32(sys->starttime));

			add_yajl_string(g, "vmsize");
			add_yajl_number(g, sb_tmp, AXA_P2H64(sys->vmsize));

			add_yajl_string(g, "vmrss");
			add_yajl_number(g, sb_tmp, AXA_P2H64(sys->vmrss));

			add_yajl_string(g, "thread_cnt");
			add_yajl_integer(g, AXA_P2H32(sys->thread_cnt));

			add_yajl_string(g, "user_cnt");
			add_yajl_integer(g, AXA_P2H32(sys->user_cnt));

			switch (sys->server_type) {
				case _AXA_STATS_SRVR_TYPE_SRA:
					add_yajl_string(g, "server_type");
					add_yajl_string(g, "sra");
					add_yajl_string(g, "fd_sockets");
					add_yajl_integer(g,
						AXA_P2H32(sys->fd_sockets));

					add_yajl_string(g, "fd_pipes");
					add_yajl_integer(g,
						AXA_P2H32(sys->fd_pipes));

					add_yajl_string(g, "fd_anon_inodes");
					add_yajl_integer(g,
						AXA_P2H32(sys->fd_anon_inodes));

					add_yajl_string(g, "fd_other");
					add_yajl_integer(g,
						AXA_P2H32(sys->fd_other));

					add_yajl_string(g, "rchar");
					add_yajl_number(g, sb_tmp,
						AXA_P2H64(sys->rchar));

					add_yajl_string(g, "wchar");
					add_yajl_number(g, sb_tmp,
						AXA_P2H64(sys->wchar));

					add_yajl_string(g,
							"sra_ipv4_watch_cnt");
					add_yajl_integer(g,
						AXA_P2H32(sys->srvr.sra.watches.ipv4_cnt));
					add_yajl_string(g,
							"sra_ipv6_watch_cnt");
					add_yajl_integer(g,
						AXA_P2H32(sys->srvr.sra.watches.ipv6_cnt));
					add_yajl_string(g,
							"sra_dns_watch_cnt");
					add_yajl_integer(g,
						AXA_P2H32(sys->srvr.sra.watches.dns_cnt));
					add_yajl_string(g,
							"sra_ch_watch_cnt");
					add_yajl_integer(g,
						AXA_P2H32(sys->srvr.sra.watches.ch_cnt));
					add_yajl_string(g,
							"sra_err_watch_cnt");
					add_yajl_integer(g,
						AXA_P2H32(sys->srvr.sra.watches.err_cnt));

					add_yajl_string(g, "sra_channels");
					add_yajl_array(g);
					for (int j = 0; j <= AXA_NMSG_CH_MAX; j++) {
						if (axa_get_bitwords(sys->srvr.sra.ch_mask.m, j)) {
							axa_strbuf_reset(sb_tmp);
							axa_strbuf_append(sb_tmp, "ch%d", (j));
							add_yajl_string(g, (const char*)sb_tmp->data);
						}
					}
					close_yajl_array(g);
					break;
				case _AXA_STATS_SRVR_TYPE_RAD:
					add_yajl_string(g, "server_type");
					add_yajl_string(g, "rad");
					add_yajl_string(g, "rad_anomaly_cnt");
					add_yajl_integer(g,
						AXA_P2H32(sys->srvr.rad.an_cnt));
					break;
				default:
					res = AXA_JSON_RES_FAILURE;
					goto err;
			}
		}

		user_objs_cnt = body->stats_rsp.user_objs_cnt;
		p = (uint8_t *)&body->stats_rsp +
			sizeof (_axa_p_stats_rsp_t) +
			body->stats_rsp.sys_objs_cnt *
			sizeof (_axa_p_stats_sys_t);
		if (user_objs_cnt > 0) {
			add_yajl_string(g, "users");
			add_yajl_array(g);
			user_obj = (_axa_p_stats_user_t *)p;
			for (; user_objs_cnt; user_objs_cnt--, user_obj++) {
				add_yajl_string(g, "user_obj");
				add_yajl_map(g);

				add_yajl_string(g, "server_type");
				switch (user_obj->server_type) {
					case _AXA_STATS_SRVR_TYPE_SRA:
						add_yajl_string(g, "sra");
						break;
					case _AXA_STATS_SRVR_TYPE_RAD:
						add_yajl_string(g, "rad");
						break;
					default:
						add_yajl_string(g,
								"unkwn");
						break;
				}
				add_yajl_string(g, "user");
				add_yajl_string(g, user_obj->user.name);
				add_yajl_string(g, "is_admin");
				add_yajl_bool(g, user_obj->is_admin == 1 ?
						true : false);

				add_yajl_string(g, "io_type");
				switch (user_obj->io_type) {
					case AXA_IO_TYPE_UNIX:
						add_yajl_string(g,
							AXA_IO_TYPE_UNIX_STR);
						break;
					case AXA_IO_TYPE_TCP:
						add_yajl_string(g,
							AXA_IO_TYPE_TCP_STR);
						break;
					case AXA_IO_TYPE_SSH:
						add_yajl_string(g,
							AXA_IO_TYPE_SSH_STR);
						break;
					case AXA_IO_TYPE_TLS:
						add_yajl_string(g,
							AXA_IO_TYPE_TLS_STR);
						break;
					case AXA_IO_TYPE_APIKEY:
						add_yajl_string(g,
							AXA_IO_TYPE_APIKEY_STR);
						break;
					case AXA_IO_TYPE_UNKN:
					default:
						add_yajl_string(g, "unknown");
						break;
				}
				add_yajl_string(g, "address");
				switch (user_obj->addr_type) {
					case AXA_AF_INET:
						inet_ntop(AF_INET, &user_obj->ip.ipv4,
							addr_str, sizeof(addr_str));
						break;
					case AXA_AF_INET6:
						inet_ntop(AF_INET6, &user_obj->ip.ipv6,
							addr_str, sizeof(addr_str));
						break;
					case AXA_AF_UNKNOWN:
						strlcpy(addr_str, "unknown",
							sizeof(addr_str));
						break;
				}
				add_yajl_string(g, addr_str);
				add_yajl_string(g, "sn");
				add_yajl_integer(g, user_obj->sn);
				add_yajl_string(g, "connected_since");
				t = AXA_P2H32(user_obj->connected_since.tv_sec);
				tm_info = gmtime(&t);
				strftime(time_buf, sizeof (time_buf),
						"%Y-%m-%dT%H:%M:%SZ",
						tm_info);
				add_yajl_string(g, time_buf);
				add_yajl_string(g, "ratelimit");
				if (AXA_P2H64(user_obj->ratelimit) == AXA_RLIMIT_OFF) {
					add_yajl_integer(g, 0);
				}
				else {
					add_yajl_integer(g,
						AXA_P2H64(user_obj->ratelimit));
				}
				add_yajl_string(g, "sample");
				axa_strbuf_reset(sb_tmp);
				axa_strbuf_append(sb_tmp, "%0.2f",
					((double)AXA_P2H64(user_obj->sample)));
				add_yajl_number_sb(g, sb_tmp);
				add_yajl_string(g, "last_count_update");
				t = AXA_P2H32(user_obj->last_cnt_update.tv_sec);
				tm_info = gmtime(&t);
				strftime(time_buf, sizeof (time_buf),
						"%Y-%m-%dT%H:%M:%SZ",
						tm_info);
				add_yajl_string(g, time_buf);
				add_yajl_string(g, "filtered");
				add_yajl_integer(g, user_obj->filtered);
				add_yajl_string(g, "missed");
				add_yajl_integer(g, user_obj->missed);
				add_yajl_string(g, "collected");
				add_yajl_integer(g, user_obj->collected);
				add_yajl_string(g, "sent");
				add_yajl_integer(g, user_obj->sent);
				add_yajl_string(g, "rlimit");
				add_yajl_integer(g, user_obj->rlimit);
				add_yajl_string(g, "congested");
				add_yajl_integer(g, user_obj->congested);
				switch (user_obj->server_type) {
					case _AXA_STATS_SRVR_TYPE_SRA:
						add_yajl_string(g,
								"ipv4_watch_cnt");
						add_yajl_integer(g,
								AXA_P2H32(user_obj->srvr.sra.watches.ipv4_cnt));
						add_yajl_string(g,
								"ipv6_watch_cnt");
						add_yajl_integer(g,
								AXA_P2H32(user_obj->srvr.sra.watches.ipv6_cnt));
						add_yajl_string(g,
								"dns_watch_cnt");
						add_yajl_integer(g,
								AXA_P2H32(user_obj->srvr.sra.watches.dns_cnt));
						add_yajl_string(g,
								"ch_watch_cnt");
						add_yajl_integer(g,
								AXA_P2H32(user_obj->srvr.sra.watches.ch_cnt));
						add_yajl_string(g,
								"err_watch_cnt");
						add_yajl_integer(g,
								AXA_P2H32(user_obj->srvr.sra.watches.err_cnt));

						add_yajl_string(g, "channels");
						add_yajl_array(g);
						for (int j = 0; j <= AXA_NMSG_CH_MAX; j++) {
							if (axa_get_bitwords(user_obj->srvr.sra.ch_mask.m, j)) {
								axa_strbuf_reset(sb_tmp);
								axa_strbuf_append(sb_tmp, "ch%d", (j));
								add_yajl_string(g, (const char*)sb_tmp->data);
							}
						}
						close_yajl_array(g);
						break;
					case _AXA_STATS_SRVR_TYPE_RAD:
						add_yajl_string(g, "anomaly_count_in_flight");
						add_yajl_integer(g,
							AXA_P2H32(user_obj->srvr.rad.an_obj_cnt));
						add_yajl_string(g, "anomaly_count_total");
						add_yajl_integer(g,
							AXA_P2H32(user_obj->srvr.rad.an_obj_cnt_total));
						an_objs_cnt = user_obj->srvr.rad.an_obj_cnt;
						q = (uint8_t *)&body->stats_rsp +
							sizeof (_axa_p_stats_rsp_t) +
							body->stats_rsp.sys_objs_cnt *
							sizeof (_axa_p_stats_sys_t) +
							sizeof (_axa_p_stats_user_t);
						if (an_objs_cnt > 0) {
							add_yajl_string(g,
								"anomalies");
							add_yajl_array(g);
							an_obj = (_axa_p_stats_user_rad_an_t *)q;
							for ( ; an_objs_cnt; an_objs_cnt--, an_obj++) {
								add_yajl_string(g, "an_obj");
								add_yajl_map(g);
								add_yajl_string(g, "name");
								add_yajl_string(g,
									an_obj->name);
								add_yajl_string(g, "options");
								add_yajl_string(g,
									an_obj->opt);
								add_yajl_string(g,
									"ru_original");
								ru = AXA_P2H32(an_obj->ru_original);
								if (ru == INT_MAX)
									add_yajl_string(g,
										"unlimited");
								else
									add_yajl_integer(g,
										AXA_P2H32(an_obj->ru_original));
								add_yajl_string(g,
									"ru_current");
								ru = AXA_P2H32(an_obj->ru_current);
								if (ru == INT_MAX)
									add_yajl_string(g,
										"unlimited");
								else
									add_yajl_integer(g,
										AXA_P2H32(an_obj->ru_current));
								add_yajl_string(g, "ru_cost");
								add_yajl_integer(g,
									AXA_P2H32(an_obj->ru_cost));
								add_yajl_string(g,
									"channels");
								add_yajl_array(g);
								for (int j = 0; j <= AXA_NMSG_CH_MAX; j++) {
									if (axa_get_bitwords(an_obj->ch_mask.m, j)) {
										axa_strbuf_reset(sb_tmp);
										axa_strbuf_append(sb_tmp, "ch%d", (j));
										add_yajl_string(g, (const char*)sb_tmp->data);
									}
								}
								close_yajl_array(g);
								close_yajl_map(g);
							}
							close_yajl_array(g);
						}
						break;
					default:
						res = AXA_JSON_RES_FAILURE;
						goto err;
				} /* switch (user_obj->server_type) */
				close_yajl_map(g);
			} /* for (; user_objs_cnt; user_objs_cnt--, ... */
			close_yajl_array(g);
		} /* if (user_objs_cnt > 0) */
		break;
	case _AXA_P_OP_KILL_REQ:
	case _AXA_P_OP_KILL_RSP:
		add_yajl_string(g, "mode");
		add_yajl_integer(g, body->kill.mode);
		add_yajl_string(g, "user");
		add_yajl_string(g, body->kill.user.name);
		add_yajl_string(g, "sn");
		add_yajl_integer(g, AXA_P2H32(body->kill.sn));
		add_yajl_string(g, "result");
		add_yajl_integer(g, body->kill.result);
		break;
	case AXA_P_OP_PAUSE:
	case AXA_P_OP_GO:
	case AXA_P_OP_WGET:
	case AXA_P_OP_AGET:
	case AXA_P_OP_STOP:
	case AXA_P_OP_ALL_STOP:
	case AXA_P_OP_CGET:
	case AXA_P_OP_ACCT:
	case AXA_P_OP_RADU:
		break;
	case AXA_P_OP_MGMT_GETRSP:
	case AXA_P_OP_MGMT_GET:
		add_yajl_string(g, "mgmt is deprecated; please upgrade and use \"stats\"");
		break;
	} /* switch */

	close_yajl_map(g);

	yajl_gen_reset(g, "");
	yajl_gen_free(g);

	*out = sb->data;
	free(sb);
	axa_strbuf_destroy(&sb_tmp);

	return (AXA_JSON_RES_SUCCESS);

err:
	if (g != NULL)
		yajl_gen_free(g);
	axa_strbuf_destroy(&sb);
	axa_strbuf_destroy(&sb_tmp);
	return (res);
}