예제 #1
0
void tchatbox::add_whisper_received(const std::string& sender, const std::string& message)
{
	bool can_go_to_active = !preferences::whisper_friends_only() || preferences::is_friend(sender);
	bool can_open_new = preferences::auto_open_whisper_windows() && can_go_to_active;

	lobby_info().get_whisper_log(sender).add_message(sender, message);

	if(whisper_window_open(sender, can_open_new)) {
		if(whisper_window_active(sender)) {
			add_active_window_message(sender, message);

			do_notify(NOTIFY_WHISPER, sender, message);
		} else {
			add_whisper_window_whisper(sender, message);
			increment_waiting_whsipers(sender);

			do_notify(NOTIFY_WHISPER_OTHER_WINDOW, sender, message);
		}
	} else if(can_go_to_active) {
		add_active_window_whisper(sender, message);
		do_notify(NOTIFY_WHISPER, sender, message);
	} else {
		LOG_LB << "Ignoring whisper from " << sender << "\n";
	}
}
예제 #2
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
/* handle all the notifications for a missing UPS in one place */
static void ups_is_gone(utype_t *ups)
{
    time_t	now;

    /* first time: clear the flag and throw the first notifier */
    if (ups->commstate != 0) {
        ups->commstate = 0;

        /* COMMBAD is the initial loss of communications */
        do_notify(ups, NOTIFY_COMMBAD);
        return;
    }

    time(&now);

    /* first only act if we're <nocommtime> seconds past the last poll */
    if ((now - ups->lastpoll) < nocommwarntime)
        return;

    /* now only complain if we haven't lately */
    if ((now - ups->lastncwarn) > nocommwarntime) {

        /* NOCOMM indicates a persistent condition */
        do_notify(ups, NOTIFY_NOCOMM);
        ups->lastncwarn = now;
    }
}
예제 #3
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
/* make sure the parent is still alive */
static void check_parent(void)
{
    int	ret;
    fd_set	rfds;
    struct	timeval	tv;
    time_t	now;
    static	time_t	lastwarn = 0;

    FD_ZERO(&rfds);
    FD_SET(pipefd[1], &rfds);

    tv.tv_sec = 0;
    tv.tv_usec = 0;

    ret = select(pipefd[1] + 1, &rfds, NULL, NULL, &tv);

    if (ret == 0)
        return;

    /* this should never happen, but we MUST KNOW if it ever does */

    time(&now);

    /* complain every 2 minutes */
    if ((now - lastwarn) < 120)
        return;

    lastwarn = now;
    do_notify(NULL, NOTIFY_NOPARENT);

    /* also do this in case the notifier isn't being effective */
    upslogx(LOG_ALERT, "Parent died - shutdown impossible");
}
예제 #4
0
void tchatbox::add_chat_room_message_received(const std::string& room,
	const std::string& speaker,
	const std::string& message)
{
	room_info* ri = lobby_info().get_room(room);
	if(!ri) {
		LOG_LB << "Discarding message to room " << room << " from " << speaker << " (room not open)\n";
		return;
	}

	t_notify_mode notify_mode = NOTIFY_NONE;
	ri->log().add_message(speaker, message);

	if(room_window_active(room)) {
		add_active_window_message(speaker, message);
		notify_mode = NOTIFY_MESSAGE;
	} else {
		add_room_window_message(room, speaker, message);
		increment_waiting_messages(room);
		notify_mode = NOTIFY_MESSAGE_OTHER_WINDOW;
	}

	if(speaker == "server") {
		notify_mode = NOTIFY_SERVER_MESSAGE;
	} else if (utils::word_match(message, preferences::login())) {
		notify_mode = NOTIFY_OWN_NICK;
	} else if (preferences::is_friend(speaker)) {
		notify_mode = NOTIFY_FRIEND_MESSAGE;
	}

	do_notify(notify_mode, speaker, message);
}
예제 #5
0
파일: io.c 프로젝트: pllopis/libxenvchan
static int do_recv(struct libvchan *ctrl, void *data, size_t size)
{
    int real_idx = rd_cons(ctrl) & (rd_ring_size(ctrl) - 1);
    int avail_contig = rd_ring_size(ctrl) - real_idx;
    if (avail_contig > size)
        avail_contig = size;
    barrier(); // data read must happen after rd_cons read
    memcpy(data, rd_ring(ctrl) + real_idx, avail_contig);
    if (avail_contig < size)
    {
        // we rolled across the end of the ring
        memcpy(data + avail_contig, rd_ring(ctrl), size - avail_contig);
    }
    rd_cons(ctrl) += size;
    if (VCHAN_DEBUG) {
        char metainfo[32];
        struct iovec iov[2];
        iov[0].iov_base = metainfo;
        iov[0].iov_len = snprintf(metainfo, 32, "vchan rd %d/%d", ctrl->other_domain_id, ctrl->device_number);
        iov[1].iov_base = data;
        iov[1].iov_len = size;
        writev(-1, iov, 2);
    }
    barrier(); // consumption must happen prior to notify of newly freed space
    if (do_notify(ctrl) < 0)
        return -1;
    return size;
}
예제 #6
0
파일: io.c 프로젝트: pllopis/libxenvchan
/**
 * returns -1 on error, or size on success
 */
static int do_send(struct libvchan *ctrl, const void *data, size_t size)
{
    int real_idx = wr_prod(ctrl) & (wr_ring_size(ctrl) - 1);
    int avail_contig = wr_ring_size(ctrl) - real_idx;
    if (VCHAN_DEBUG) {
        char metainfo[32];
        struct iovec iov[2];
        iov[0].iov_base = metainfo;
        iov[0].iov_len = snprintf(metainfo, 32, "vchan wr %d/%d", ctrl->other_domain_id, ctrl->device_number);
        iov[1].iov_base = (void *)data;
        iov[1].iov_len = size;
        writev(-1, iov, 2);
    }
    if (avail_contig > size)
        avail_contig = size;
    memcpy(wr_ring(ctrl) + real_idx, data, avail_contig);
    if (avail_contig < size)
    {
        // we rolled across the end of the ring
        memcpy(wr_ring(ctrl), data + avail_contig, size - avail_contig);
    }
    barrier(); // data must be in the ring prior to increment
    wr_prod(ctrl) += size;
    barrier(); // increment must happen prior to notify
    if (do_notify(ctrl) < 0)
        return -1;
    return size;
}
예제 #7
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
/* the actual shutdown procedure */
static void doshutdown(void)
{
    int	ret;

    /* this should probably go away at some point */
    upslogx(LOG_CRIT, "Executing automatic power-fail shutdown");
    wall("Executing automatic power-fail shutdown\n");

    do_notify(NULL, NOTIFY_SHUTDOWN);

    sleep(finaldelay);

    /* in the pipe model, we let the parent do this for us */
    if (use_pipe) {
        char	ch;

        ch = 1;
        ret = write(pipefd[1], &ch, 1);
    } else {
        /* one process model = we do all the work here */

        if (geteuid() != 0)
            upslogx(LOG_WARNING, "Not root, shutdown may fail");

        set_pdflag();

        ret = system(shutdowncmd);

        if (ret != 0)
            upslogx(LOG_ERR, "Unable to call shutdown command: %s",
                    shutdowncmd);
    }

    exit(EXIT_SUCCESS);
}
예제 #8
0
파일: notify.c 프로젝트: 559210/libpomelo
int main() {
  // create a client instance.
  pc_client_t *client = pc_client_new();

  struct sockaddr_in address;

  memset(&address, 0, sizeof(struct sockaddr_in));
  address.sin_family = AF_INET;
  address.sin_port = htons(port);
  address.sin_addr.s_addr = inet_addr(ip);

  // add some event callback.
  pc_add_listener(client, "onHey", on_hey);
  pc_add_listener(client, PC_EVENT_DISCONNECT, on_close);

  // try to connect to server.
  if(pc_client_connect(client, &address)) {
    printf("fail to connect server.\n");
    pc_client_destroy(client);
    return 1;
  }

  do_notify(client);

  // main thread has nothing to do and wait until child thread return.
  pc_client_join(client);

  // release the client
  pc_client_destroy(client);

  return 0;
}
예제 #9
0
파일: imc.c 프로젝트: bkero/Smaug
/* send a packet to a mud using the right version */
static void do_send_packet(imc_connect *c, const imc_packet *p)
{
  const char *output;
  int v;
#ifdef IMC_NOTIFY
  static time_t last_notify;

  if (last_notify + 3600*24 < imc_now)
  {
    last_notify = imc_now;
    do_notify();
  }
#endif

  v=c->version;
  if (v>IMC_VERSION)
    v=IMC_VERSION;

  output=(*imc_vinfo[v].generate)(p);

  if (output)
  {
    imc_stats.tx_pkts++;
    if (strlen(output) > imc_stats.max_pkt)
      imc_stats.max_pkt=strlen(output);
    do_send(c, output);
  }
}
예제 #10
0
파일: io.c 프로젝트: AndrewX192/qubes-core
/**
        Wait fot the writes to finish, then notify the peer of closing
        On server side, it waits for the peer to acknowledge
*/
int libvchan_close(struct libvchan *ctrl)
{
	while (*ctrl->wr_prod != *ctrl->wr_cons)
		if (libvchan_wait(ctrl) < 0)
			return -1;
	if (ctrl->is_server) {
		ctrl->ring->server_closed = 1;
		do_notify(ctrl);
		while (!ctrl->ring->client_closed
		       && libvchan_wait(ctrl) == 0);
	} else {
		ctrl->ring->client_closed = 1;
		do_notify(ctrl);
	}
	return 0;
}
예제 #11
0
void tlobby_main::process_gamelist_diff(const config& data)
{
	if(lobby_info_.process_gamelist_diff(data)) {
		DBG_LB << "Received gamelist diff\n";
		gamelist_dirty_ = true;
	} else {
		ERR_LB << "process_gamelist_diff failed!" << std::endl;
	}
	int joined = data.child_count("insert_child");
	int left = data.child_count("remove_child");
	if(joined > 0 || left > 0) {
		if(left > joined) {
			do_notify(NOTIFY_LOBBY_QUIT);
		} else {
			do_notify(NOTIFY_LOBBY_JOIN);
		}
	}
}
예제 #12
0
파일: lobby.cpp 프로젝트: doofus-01/wesnoth
void lobby_main::process_gamelist_diff(const config& data)
{
	if(lobby_info_.process_gamelist_diff(data)) {
		DBG_LB << "Received gamelist diff\n";
		gamelist_dirty_ = true;
	} else {
		ERR_LB << "process_gamelist_diff failed!" << std::endl;
		wesnothd_connection_.send_data(config("refresh_lobby"));
	}
	const int joined = data.child_count("insert_child");
	const int left = data.child_count("remove_child");
	if(joined > 0 || left > 0) {
		if(left > joined) {
			do_notify(mp::NOTIFY_LOBBY_QUIT);
		} else {
			do_notify(mp::NOTIFY_LOBBY_JOIN);
		}
	}
}
예제 #13
0
static void
notify_playing_entry (RBNotificationPlugin *plugin, gboolean requested)
{
	do_notify (plugin,
		   PLAYING_ENTRY_NOTIFY_TIME * 1000,
		   plugin->current_title,
		   plugin->current_album_and_artist,
		   plugin->notify_art_path,
		   TRUE);
}
예제 #14
0
static void
notify_custom (RBNotificationPlugin *plugin,
	       guint timeout,
	       const char *primary,
	       const char *secondary,
	       const char *image_uri,
	       gboolean requested)
{
	do_notify (plugin, timeout, primary, secondary, image_uri, FALSE);
}
예제 #15
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
static void upsreplbatt(utype_t *ups)
{
    time_t	now;

    time(&now);

    if ((now - ups->lastrbwarn) > rbwarntime) {
        do_notify(ups, NOTIFY_REPLBATT);
        ups->lastrbwarn = now;
    }
}
예제 #16
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
static void ups_fsd(utype_t *ups)
{
    if (flag_isset(ups->status, ST_FSD)) {		/* no change */
        upsdebugx(4, "%s: %s (no change)", __func__, ups->sys);
        return;
    }

    upsdebugx(3, "%s: %s (first time)", __func__, ups->sys);

    /* must have changed from !FSD to FSD, so notify */

    do_notify(ups, NOTIFY_FSD);
    setflag(&ups->status, ST_FSD);
}
예제 #17
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
static void ups_low_batt(utype_t *ups)
{
    if (flag_isset(ups->status, ST_LOWBATT)) { 	/* no change */
        upsdebugx(4, "%s: %s (no change)", __func__, ups->sys);
        return;
    }

    upsdebugx(3, "%s: %s (first time)", __func__, ups->sys);

    /* must have changed from !LB to LB, so notify */

    do_notify(ups, NOTIFY_LOWBATT);
    setflag(&ups->status, ST_LOWBATT);
}
예제 #18
0
파일: io.c 프로젝트: AndrewX192/qubes-core
/// returns nonzero if the peer has closed connection 
int libvchan_is_eof(struct libvchan *ctrl)
{
	if (ctrl->is_server) {
		if (ctrl->ring->client_closed)
			return -1;
	} else {
		if (ctrl->ring->server_closed) {
			ctrl->ring->client_closed = 1;
			do_notify(ctrl);
			return -1;
		}

	}
	return 0;
}
예제 #19
0
/*
 * Called when the mq_exclusive lock draws EOWNERDEAD or ENOTRECOVERABLE.
 * Wake up anyone waiting on mq_*send() or mq_*receive() and ensure that
 * they fail with errno == EBADMSG.  Trigger any registered notification.
 */
static void
owner_dead(mqdes_t *mqdp, int error)
{
	mqhdr_t *mqhp = mqdp->mqd_mq;

	mqdp->mqd_ownerdead = 1;
	(void) sem_post(&mqhp->mq_notfull);
	(void) sem_post(&mqhp->mq_notempty);
	if (error == EOWNERDEAD) {
		if (mqhp->mq_sigid.sn_pid != 0)
			do_notify(mqhp);
		(void) mutex_unlock(&mqhp->mq_exclusive);
	}
	errno = EBADMSG;
}
예제 #20
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
/* set flags and make announcements when a UPS has been checked successfully */
static void ups_is_alive(utype_t *ups)
{
    time_t	now;

    time(&now);
    ups->lastpoll = now;

    if (ups->commstate == 1)		/* already known */
        return;

    /* only notify for 0->1 transitions (to ignore the first connect) */
    if (ups->commstate == 0)
        do_notify(ups, NOTIFY_COMMOK);

    ups->commstate = 1;
}
예제 #21
0
    void on_read(boost::system::error_code const & error, std::size_t size)
    {
        if (error) {
            static_cast<Derived *>(this)->on_error(error);
            return;
        }

        char const * it = buffer_.data();
        char const * end = it + size;
        while(it < end) {
            auto * iev = reinterpret_cast<::inotify_event const *>(it);
            do_notify(iev);
            it += sizeof(*iev) + iev->len;
        }

        async_read();
    }
예제 #22
0
파일: io.c 프로젝트: AndrewX192/qubes-core
/**
        may sleep (only if no data is available for reading);
        may return less data than requested;
        returns the amount of data processed, -1 on error or peer close
*/        
int libvchan_read(struct libvchan *ctrl, char *data, int size)
{
	int avail, avail_contig;
	int real_idx;
	while ((avail = libvchan_data_ready(ctrl)) == 0)
		if (libvchan_wait(ctrl) < 0)
			return -1;
	if (avail > size)
		avail = size;
	real_idx = (*ctrl->rd_cons) & (ctrl->rd_ring_size - 1);
	avail_contig = ctrl->rd_ring_size - real_idx;
	if (avail_contig < avail)
		avail = avail_contig;
	memcpy(data, ctrl->rd_ring + real_idx, avail);
	*ctrl->rd_cons += avail;
	if (do_notify(ctrl) < 0)
		return -1;
	return avail;
}
예제 #23
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
static void ups_on_batt(utype_t *ups)
{
    if (flag_isset(ups->status, ST_ONBATT)) { 	/* no change */
        upsdebugx(4, "%s: %s (no change)", __func__, ups->sys);
        return;
    }

    sleepval = pollfreqalert;	/* bump up polling frequency */

    ups->linestate = 0;

    upsdebugx(3, "%s: %s (first time)", __func__, ups->sys);

    /* must have changed from OL to OB, so notify */

    do_notify(ups, NOTIFY_ONBATT);
    setflag(&ups->status, ST_ONBATT);
    clearflag(&ups->status, ST_ONLINE);
}
예제 #24
0
파일: io.c 프로젝트: AndrewX192/qubes-core
/**
        may sleep (only if no buffer space available);
        may write less data than requested;
        returns the amount of data processed, -1 on error or peer close
*/        
int libvchan_write(struct libvchan *ctrl, const char *data, int size)
{
	int avail, avail_contig;
	int real_idx;
	while ((avail = libvchan_buffer_space(ctrl)) == 0)
		if (libvchan_wait(ctrl) < 0)
			return -1;
	if (avail > size)
		avail = size;
	real_idx = (*ctrl->wr_prod) & (ctrl->wr_ring_size - 1);
	avail_contig = ctrl->wr_ring_size - real_idx;
	if (avail_contig < avail)
		avail = avail_contig;
	memcpy(ctrl->wr_ring + real_idx, data, avail);
	*ctrl->wr_prod += avail;
	if (do_notify(ctrl) < 0)
		return -1;
	return avail;
}
예제 #25
0
파일: upsmon.c 프로젝트: ThomasKurz/nut
static void ups_on_line(utype_t *ups)
{
    if (flag_isset(ups->status, ST_ONLINE)) { 	/* no change */
        upsdebugx(4, "%s: %s (no change)", __func__, ups->sys);
        return;
    }

    sleepval = pollfreq;

    upsdebugx(3, "%s: %s (first time)", __func__, ups->sys);

    /* ignore the first OL at startup, otherwise send the notifier */
    if (ups->linestate != -1)
        do_notify(ups, NOTIFY_ONLINE);

    ups->linestate = 1;

    setflag(&ups->status, ST_ONLINE);
    clearflag(&ups->status, ST_ONBATT);
}
예제 #26
0
/* Kernel thread */
static int uh_thread(void *data)
{
	struct uh_data *uh = (struct uh_data *)data;
	
	while (!kthread_should_stop()) {
		do_wait(uh);

		if (kthread_should_stop())
			break;

		do_detect(uh);
		
		do_notify(uh);
		
		do_done(uh);
	}
	
	D("Exit.\n");

	return 0;
}
예제 #27
0
파일: io.c 프로젝트: pllopis/libxenvchan
void libvchan_close(struct libvchan *ctrl)
{
    if (!ctrl)
        return;
    if (ctrl->ring) {
        if (ctrl->is_server)
            ctrl->ring->srv_live = 0;
        else
            ctrl->ring->cli_live = 0;
        munmap(ctrl->ring, PAGE_SIZE);
    }
    if (ctrl->event_fd != -1) {
        if (ctrl->event_port > 0 && ctrl->ring)
            do_notify(ctrl);
        close(ctrl->event_fd);
    }
    if (ctrl->read.order >= PAGE_SHIFT)
        munmap(ctrl->read.buffer, 1 << ctrl->read.order);
    if (ctrl->write.order >= PAGE_SHIFT)
        munmap(ctrl->write.buffer, 1 << ctrl->write.order);
    free(ctrl);
}
예제 #28
0
파일: client.c 프로젝트: 559210/libpomelo
int main() {
  pc_client_t *client = pc_client_new();

  struct sockaddr_in address;

  memset(&address, 0, sizeof(struct sockaddr_in));
  address.sin_family = AF_INET;
  address.sin_port = htons(port);
  address.sin_addr.s_addr = inet_addr(ip);

  pc_add_listener(client, "onHey", on_hey);
  pc_add_listener(client, PC_EVENT_DISCONNECT, on_close);

  if(pc_client_connect(client, &address)) {
    printf("fail to connect server.\n");
    goto error;
  }

  int i;
  for(i=0; i<count; i++) {
    do_notify(client);
  }

  pc_client_join(client);

  //sleep(3);

  printf("before main return.\n");

  pc_client_destroy(client);

  return 0;

error:
  pc_client_destroy(client);
  return 1;
}
예제 #29
0
	void do_notify(t_notify_mode mode) { do_notify(mode, "", ""); }
예제 #30
0
/* The entrypoint for bytecode evaluation */
int sieve_eval_bc(sieve_execute_t *exe, int is_incl, sieve_interp_t *i,
		  void *sc, void *m,
		  strarray_t *imapflags, action_list_t *actions,
		  notify_list_t *notify_list, const char **errmsg) 
{
    const char *data;
    int res=0;
    int op;
    int version;
  
    sieve_bytecode_t *bc_cur = exe->bc_cur;
    bytecode_input_t *bc = (bytecode_input_t *) bc_cur->data;
    int ip = 0, ip_max = (bc_cur->len/sizeof(bytecode_input_t));

    if (bc_cur->is_executing) {
	*errmsg = "Recursive Include";
	return SIEVE_RUN_ERROR;
    }
    bc_cur->is_executing = 1;
    
    /* Check that we
     * a) have bytecode
     * b) it is atleast long enough for the magic number, the version
     *    and one opcode */
    if(!bc) return SIEVE_FAIL;
    if(bc_cur->len < (BYTECODE_MAGIC_LEN + 2*sizeof(bytecode_input_t)))
       return SIEVE_FAIL;

    if(memcmp(bc, BYTECODE_MAGIC, BYTECODE_MAGIC_LEN)) {
	*errmsg = "Not a bytecode file";
	return SIEVE_FAIL;
    }

    ip = BYTECODE_MAGIC_LEN / sizeof(bytecode_input_t);

    version= ntohl(bc[ip].op);

    /* this is because there was a time where integers were not network byte
       order.  all the scripts written then would have version 0x01 written
       in host byte order.*/

     if(version == (int)ntohl(1)) {
	if(errmsg) {
	    *errmsg =
		"Incorrect Bytecode Version, please recompile (use sievec)";
	    
	}
	return SIEVE_FAIL;
    }
    
    if((version < BYTECODE_MIN_VERSION) || (version > BYTECODE_VERSION)) {
	if(errmsg) {
	    *errmsg =
		"Incorrect Bytecode Version, please recompile (use sievec)";
	}
	return SIEVE_FAIL;
    }

#if VERBOSE
    printf("version number %d\n",version); 
#endif

    for(ip++; ip<ip_max; ) { 
	int copy = 0;

	op=ntohl(bc[ip].op);
	switch(op) {
	case B_STOP:/*0*/
	    res=1;
	    break;

	case B_KEEP:/*1*/
	    res = do_keep(actions, imapflags);
	    if (res == SIEVE_RUN_ERROR)
		*errmsg = "Keep can not be used with Reject";
	    ip++;
	    break;

	case B_DISCARD:/*2*/
	    res=do_discard(actions);
	    ip++;
	    break;

	case B_REJECT:/*3*/
	    ip = unwrap_string(bc, ip+1, &data, NULL);
	    
	    res = do_reject(actions, data);
	
	    if (res == SIEVE_RUN_ERROR)
		*errmsg = "Reject can not be used with any other action";  

	    break;

	case B_FILEINTO:/*19*/
	    copy = ntohl(bc[ip+1].value);
	    ip+=1;

	    /* fall through */
	case B_FILEINTO_ORIG:/*4*/
	{
	    ip = unwrap_string(bc, ip+1, &data, NULL);

	    res = do_fileinto(actions, data, !copy, imapflags);

	    if (res == SIEVE_RUN_ERROR)
		*errmsg = "Fileinto can not be used with Reject";

	    break;
	}

	case B_REDIRECT:/*20*/
	    copy = ntohl(bc[ip+1].value);
	    ip+=1;

	    /* fall through */
	case B_REDIRECT_ORIG:/*5*/
	{
	    ip = unwrap_string(bc, ip+1, &data, NULL);

	    res = do_redirect(actions, data, !copy);

	    if (res == SIEVE_RUN_ERROR)
		*errmsg = "Redirect can not be used with Reject";

	    break;
	}

	case B_IF:/*6*/
	{
	    int testend=ntohl(bc[ip+1].value);
	    int result;
	   
	    ip+=2;
	    result=eval_bc_test(i, m, bc, &ip);
	    
	    if (result<0) {
		*errmsg = "Invalid test";
		return SIEVE_FAIL;
	    } else if (result) {
	    	/*skip over jump instruction*/
		testend+=2;
	    }
	    ip=testend;
	    
	    break;
	}

	case B_MARK:/*8*/
	    res = do_mark(actions);
	    ip++;
	    break;

	case B_UNMARK:/*9*/
	    res = do_unmark(actions);
	    ip++;
	    break;

	case B_ADDFLAG:/*10*/ 
	{
	    int x;
	    int list_len=ntohl(bc[ip+1].len);

	    ip+=3; /* skip opcode, list_len, and list data len */

	    for (x=0; x<list_len; x++) {
		ip = unwrap_string(bc, ip, &data, NULL);
		
		res = do_addflag(actions, data);

		if (res == SIEVE_RUN_ERROR)
		    *errmsg = "addflag can not be used with Reject";
	    } 
	    break;
	}

	case B_SETFLAG:
	{
	    int x;
	    int list_len=ntohl(bc[ip+1].len);

	    ip+=3; /* skip opcode, list_len, and list data len */

	    ip = unwrap_string(bc, ip, &data, NULL);

	    res = do_setflag(actions, data);

	    if (res == SIEVE_RUN_ERROR) {
		*errmsg = "setflag can not be used with Reject";
	    } else {
		for (x=1; x<list_len; x++) {
		    ip = unwrap_string(bc, ip, &data, NULL);

		    res = do_addflag(actions, data);

		    if (res == SIEVE_RUN_ERROR)
			*errmsg = "setflag can not be used with Reject";
		} 
	    }
	    
	    break;
	}

	case B_REMOVEFLAG:
	{
	    int x;
	    int list_len=ntohl(bc[ip+1].len);

	    ip+=3; /* skip opcode, list_len, and list data len */

	    for (x=0; x<list_len; x++) {
		ip = unwrap_string(bc, ip, &data, NULL);

		res = do_removeflag(actions, data);

		if (res == SIEVE_RUN_ERROR)
		    *errmsg = "removeflag can not be used with Reject";
	    } 
	    break;
	}

	case B_NOTIFY:
	{
	    const char * id;
	    const char * method;
	    const char **options = NULL;
	    const char *priority = NULL;
	    const char * message;
	    int pri;
	    
	    ip++;

	    /* method */
	    ip = unwrap_string(bc, ip, &method, NULL);

	    /* id */
	    ip = unwrap_string(bc, ip, &id, NULL);

	    /*options*/
	    options=bc_makeArray(bc, &ip); 

	    /* priority */
	    pri=ntohl(bc[ip].value);
	    ip++;
	    
	    switch (pri)
	    {
	    case B_LOW:
		priority="low";
		break;
	    case B_NORMAL:
		priority="normal";
		break;
	    case B_HIGH: 
		priority="high";
		break; 
	    case B_ANY:
		priority="any";
		break;
	    default:
		res=SIEVE_RUN_ERROR;
	    }

	    /* message */
	    ip = unwrap_string(bc, ip, &message, NULL);
	  
	    res = do_notify(notify_list, id, method, options,
			    priority, message);

	    break;
	}
	case B_DENOTIFY:
	{
         /*
	  * i really have no idea what the count matchtype should do here.
	  * the sanest thing would be to use 1.
	  * however that would require passing on the match type to do_notify.
	  *  -jsmith2
	  */

	    comparator_t *comp = NULL;
	    
	    const char *pattern;
	    regex_t *reg;
	    
	    const char *priority = NULL;
	    void *comprock = NULL;
	    
	    int comparator;
	    int pri;
	    
	    ip++;
	    pri=ntohl(bc[ip].value);
	    ip++;
	    
	    switch (pri)
	    {
	    case B_LOW:
		priority="low";		
		break;
	    case B_NORMAL:
		priority="normal";
		break;
	    case B_HIGH: 
		priority="high";
		break; 
	    case B_ANY:
		priority="any";
		break;
	    default:
		res=SIEVE_RUN_ERROR;
	    }

	    if(res == SIEVE_RUN_ERROR)
		break;
	   
	    comparator =ntohl( bc[ip].value);
	    ip++;
	    
	    if (comparator == B_ANY)
	    { 
		ip++;/* skip placeholder this has no comparator function */
		comp=NULL;
	    } else {
		int x= ntohl(bc[ip].value);
		ip++;
		
		comp=lookup_comp(B_ASCIICASEMAP,comparator,
				 x, &comprock);
	    }
	    
	    ip = unwrap_string(bc, ip, &pattern, NULL);
	  
	    if (comparator == B_REGEX)
	    {	
		char errmsg[1024]; /* Basically unused */
		
		reg=bc_compile_regex(pattern,
				     REG_EXTENDED | REG_NOSUB | REG_ICASE,
				     errmsg, sizeof(errmsg));
		if (!reg) {
		    res = SIEVE_RUN_ERROR;
		} else {
		    res = do_denotify(notify_list, comp, reg,
				      comprock, priority);
		    free(reg);
		}
	    } else {
		res = do_denotify(notify_list, comp, pattern,
				  comprock, priority);
	    }
	    
	    break;
	}
	case B_VACATION_ORIG:
	case B_VACATION:
	{
	    int respond;
	    char *fromaddr = NULL; /* relative to message we send */
	    char *toaddr = NULL; /* relative to message we send */
	    const char *handle = NULL;
	    const char *message = NULL;
	    int seconds, mime;
	    char buf[128];
	    char subject[1024];
	    int x;

	    ip++;

	    x = ntohl(bc[ip].len);
	    
	    respond = shouldRespond(m, i, x, bc, ip+2,
				    &fromaddr, &toaddr);
	    
	    ip = ntohl(bc[ip+1].value) / 4;
	    if (respond==SIEVE_OK)
	    {
		ip = unwrap_string(bc, ip, &data, NULL);

		if (!data) 
		{
		    /* we have to generate a subject */
		    const char **s;	    
		    strlcpy(buf, "subject", sizeof(buf));
		    if (i->getheader(m, buf, &s) != SIEVE_OK ||
			s[0] == NULL) {
			strlcpy(subject, "Automated reply", sizeof(subject));
		    } else {
			/* s[0] contains the original subject */
			const char *origsubj = s[0];
			snprintf(subject, sizeof(subject), "Auto: %s", origsubj);
		    }
		} else {
		    /* user specified subject */
		    strlcpy(subject, data, sizeof(subject));
		}

		ip = unwrap_string(bc, ip, &message, NULL);

		seconds = ntohl(bc[ip].value);
		if (op == B_VACATION_ORIG) {
		    seconds *= DAY2SEC;
		}
		mime = ntohl(bc[ip+1].value);

		ip+=2;

		if (version >= 0x05) {
		    ip = unwrap_string(bc, ip, &data, NULL);

		    if (data) {
			/* user specified from address */
			free(fromaddr);
			fromaddr = xstrdup(data);
		    }

		    ip = unwrap_string(bc, ip, &data, NULL);

		    if (data) {
			/* user specified handle */
			handle = data;
		    }
		}

		res = do_vacation(actions, toaddr, fromaddr, xstrdup(subject),
				  message, seconds, mime, handle);

		if (res == SIEVE_RUN_ERROR)
		    *errmsg = "Vacation can not be used with Reject or Vacation";
	    } else if (respond == SIEVE_DONE) {
                /* skip subject and message */

		ip = unwrap_string(bc, ip, &data, NULL);
		ip = unwrap_string(bc, ip, &data, NULL);

		ip+=2;/*skip days and mime flag*/

		if (version >= 0x05) {
		    /* skip from and handle */
		    ip = unwrap_string(bc, ip, &data, NULL);
		    ip = unwrap_string(bc, ip, &data, NULL);
		}
	    } else {
		res = SIEVE_RUN_ERROR; /* something is bad */ 
	    }

	    break;
	}
	case B_NULL:/*15*/
	    ip++;
	    break;

	case B_JUMP:/*16*/
	    ip= ntohl(bc[ip+1].jump);
	    break;

	case B_INCLUDE:/*17*/
	{
	    int isglobal = (ntohl(bc[ip+1].value) & 63) == B_GLOBAL;
	    int once = ntohl(bc[ip+1].value) & 64 ? 1 : 0;
	    int isoptional = ntohl(bc[ip+1].value) & 128 ? 1 : 0;
	    char fpath[4096];

	    ip = unwrap_string(bc, ip+2, &data, NULL);

	    res = i->getinclude(sc, data, isglobal, fpath, sizeof(fpath));
	    if (res != SIEVE_OK) {
		if (isoptional == 0)
		    *errmsg = "Include can not find script";
		else
		    res = SIEVE_OK;
	        break;
	    }
	    res = sieve_script_load(fpath, &exe);
	    if (res == SIEVE_SCRIPT_RELOADED) {
		if (once == 1) {
		    res = SIEVE_OK;
		    break;
		}
	    } else if (res != SIEVE_OK) { /* SIEVE_FAIL */
		if (isoptional == 0)
		    *errmsg = "Include can not load script";
		else
		    res = SIEVE_OK;
		break;
	    }

	    res = sieve_eval_bc(exe, 1, i,
				sc, m, imapflags, actions,
				notify_list, errmsg);
	    break;
	}

	case B_RETURN:/*18*/
	    if (is_incl)
		goto done;
	    else
		res=1;
	    break;

	default:
	    if(errmsg) *errmsg = "Invalid sieve bytecode";
	    return SIEVE_FAIL;
	}
      
	if (res) /* we've either encountered an error or a stop */
	    break;
    }

  done:
    bc_cur->is_executing = 0;

    return res;
}