Esempio n. 1
0
static void push_timer_from_row(MYSQL_ROW row, int fields) 
{
	char *rng_duration, *rng_time;
	bool rng_sub;
	if( fields < 3 ) {
		wrn_print("fields(%d) < 3",fields);
		return;
	}
	
	rng_sub = !!atoi(row[4]);
	rng_duration = row[3];
	rng_time = row[2]; 
	
	struct sigevent se;
	se.sigev_notify = SIGEV_SIGNAL;
	se.sigev_signo = fit_default_durations(rng_duration);

	if(se.sigev_signo == -1 ) {				
		se.sigev_signo = SIG_RING_CUSTOM;				
		se.sigev_value.sival_int = duration(rng_duration);
	}

	
	if( push_timer_from_string(&se, rng_time, NULL,TIMER_ABSTIME,1) == -1 ) {
		wrn_print("push_timer_from_string %s", rng_time);
		return;			
	}
	
	dbg_print("    duration: (%ss) time: (%s)",rng_duration, rng_time);	
	
	if (rng_sub || sub_bell_conf.global_enable) {
	
		struct sigevent sub_se;		
		struct timespec exp;
		time_t tm, gap; 

		sub_se.sigev_value.sival_int = sub_bell_conf.ring_for;		
		sub_se.sigev_notify = SIGEV_SIGNAL;
		sub_se.sigev_signo = SIG_RING_CUSTOM;						
				
		gap = str_to_time(sub_bell_conf.ring_before, 0);
		gap -= timezone;              
                 /* ??? what ???*/
                 
		tm = str_to_time(rng_time, 1);	
		
		exp.tv_sec = tm - gap;
		exp.tv_nsec = 0;
		
		dbg_print("Sub duartion: (%ldns) time: (%s/%ld)", 
			(long) sub_bell_conf.ring_for,str_time("%H:%M:%S",&exp.tv_sec),
			(long)exp.tv_sec);
		
		if(push_timer(&sub_se, &exp, NULL,TIMER_ABSTIME,1) == -1) {
			wrn_print("push_timer");
			return;
		} 
	}
	
}
Esempio n. 2
0
DB_Computer *DB_get_comps(Database *db){
    PGconn      *conn;
    PGresult    *res;
    DB_Computer *comps;
    int nTuples, i;
    
    if(_DB_connect(db, &conn) != 0) return NULL;
    
    res = PQexec(conn, "SELECT id, domain_name, created_at "
                        "FROM "COMPUTERS_TABNAME" "
                        "WHERE deleted_at IS NULL AND "
                             "accepted_at IS NOT NULL;");
    if (PQresultStatus(res) != PGRES_TUPLES_OK){
        _DB_close_res(db, conn, res);
        return NULL;
    }
    
    nTuples = PQntuples(res);
    comps = (DB_Computer *) malloc(sizeof(DB_Computer) * nTuples);
    for(i = 0; i < nTuples; i++){
        //~ printf("%3d ", atoi(PQgetvalue(res, i, 0)));
        comps[i].id         = (unsigned int) atoi(PQgetvalue(res, i, 0));
        //~ printf("%s ", PQgetvalue(res, i, 1));
        strncpy(comps[i].domain,
                PQgetvalue(res, i, 1),
                COMPUTER_DOMAIN_NAME_SIZE);
        //~ printf("'%s':%d\n", PQgetvalue(res, i, 2), str_to_time(PQgetvalue(res, i, 2)));
        comps[i].created_at = str_to_time(PQgetvalue(res, i, 2));
    }
    PQclear(res);
    PQfinish(conn);
    return comps;
}
Esempio n. 3
0
static void penalty_parse_line(const char *line, struct penalty_line *line_r)
{
	const char *const *args = t_strsplit_tab(line);
	const char *ident = args[0];
	const char *penalty_str = args[1];
	const char *last_penalty_str = args[2];
	const char *last_update_str = args[3];

	memset(line_r, 0, sizeof(*line_r));

	(void)net_addr2ip(ident, &line_r->ip);
	if (str_to_uint(penalty_str, &line_r->penalty) < 0 ||
	    str_to_time(last_penalty_str, &line_r->last_penalty) < 0 ||
	    str_to_time(last_update_str, &line_r->last_update) < 0)
		i_fatal("Read invalid penalty line: %s", line);
}
Esempio n. 4
0
// YY-MM-DD, YYYY-MM-DD, YY-MM-DD HH:MM:SS
my_datetime::my_datetime(string dt_str)
{
	initDate();
	if (dt_str.length() > 0) {
		str_to_time(dt_str);
	}
}
Esempio n. 5
0
DB_Detail *DB_get_details(Database *db, unsigned int computer_id){
    PGconn      *conn;
    PGresult    *res;
    DB_Detail   *details;
    int nTuples, i;
    const char *paramValues[1];
    const int   paramFormats[1] = {BINARY_FRMT};
    const int   paramLengths[1] = {sizeof(uint32_t)};
    uint32_t tmp_id;
    
    if(_DB_connect(db, &conn) != 0) return NULL;
    
    paramValues[0] = order_int(computer_id, &tmp_id);
    
    res = PQexecParams(conn,
            "SELECT d.id, d.vendor_id, d.device_id, d.subsystem_id, "
                "d.serial, d.created_at "
                "FROM "CONFIGS_TABNAME" cd "
                "JOIN "DETAILS_TABNAME" d ON d.id = cd.detail_id "
                "WHERE "
                    "cd.computer_id = $1::int AND "
                    "cd.allow_del_at IS NULL;",
            1,              /* count of params */
            NULL,           /* let the backend deduce param type */
            paramValues,
            paramLengths,
            paramFormats,
            TEXT_FRMT);             /* text results */
    if (PQresultStatus(res) != PGRES_TUPLES_OK){
        _DB_close_res(db, conn, res);
        return NULL;
    }
    
    nTuples = PQntuples(res);
    details = (DB_Detail *) malloc(sizeof(DB_Detail) * nTuples);
    for(i = 0; i < nTuples; i++){
        details[i].id           = (unsigned int) atoi(PQgetvalue(res, i, 0));
        details[i].vendor_id    = (unsigned int) atoi(PQgetvalue(res, i, 1));
        details[i].device_id    = (unsigned int) atoi(PQgetvalue(res, i, 2));
        details[i].subsystem_id = (unsigned int) atoi(PQgetvalue(res, i, 3));
        strncpy(details[i].serial,
                PQgetvalue(res, i, 4),
                DETAIL_SERIAL_SIZE);
        details[i].created_at = str_to_time(PQgetvalue(res, i, 5));
        printf("Detail: %4d, %.4x, %.4x, %.8x, '%s', %d\n",
            details[i].id,
            details[i].vendor_id,
            details[i].device_id,
            details[i].subsystem_id,
            details[i].serial,
            (int) details[i].created_at
        );
    }
    PQclear(res);
    PQfinish(conn);
    return details;
}
Esempio n. 6
0
static void cmd_director_status(int argc, char *argv[])
{
	struct director_context *ctx;
	const char *line, *const *args;

	ctx = cmd_director_init(argc, argv, "a:t:", cmd_director_status);
	if (argv[optind] != NULL) {
		cmd_director_status_user(ctx, argv+optind);
		return;
	}

	doveadm_print_init(DOVEADM_PRINT_TYPE_TABLE);
	doveadm_print_header_simple("mail server ip");
	doveadm_print_header_simple("tag");
	doveadm_print_header_simple("vhosts");
	doveadm_print_header_simple("state");
	doveadm_print_header("state-changed", "state changed", 0);
	doveadm_print_header_simple("users");

	director_send(ctx, "HOST-LIST\n");
	while ((line = i_stream_read_next_line(ctx->input)) != NULL) {
		if (*line == '\0')
			break;
		T_BEGIN {
			unsigned int arg_count;
			time_t ts;

			args = t_strsplit_tab(line);
			arg_count = str_array_length(args);
			if (arg_count >= 6) {
				/* ip vhosts users tag updown updown-ts */
				doveadm_print(args[0]); 
				doveadm_print(args[3]);
				doveadm_print(args[1]);
				doveadm_print(args[4][0] == 'D' ? "down" : "up");
				if (str_to_time(args[5], &ts) < 0 ||
				    ts <= 0)
					doveadm_print("-");
				else
					doveadm_print(unixdate2str(ts));
				doveadm_print(args[2]);
			}
		} T_END;
	}
	if (line == NULL) {
		i_error("Director disconnected unexpectedly");
		doveadm_exit_code = EX_TEMPFAIL;
	}
	director_disconnect(ctx);
}
Esempio n. 7
0
/*
 * update entrants from a file
 */
int refresh(Event* event, char* filename, int t_index) {
  Vector* lines = read_file(filename);
  char* line;
  char* token;
  char type;
  int node_id;
  int entrant_id;
  Time* time;
  int i;

  for (i = t_index; i < Vector_size(lines); i++) {
    Vector_get(lines, i, &line);

    /* type */
    token = strtok(line, " ");
    type = token[0];

    /* node id */
    token = strtok(NULL, " ");
    node_id = atoi(token);

    /* entrant id */
    token = strtok(NULL, " ");
    entrant_id = atoi(token);

    /* time */
    token = strtok(NULL, "\n");
    time = str_to_time(token);

    update_time(event, time, entrant_id);
    entrant_update_location(event, type, entrant_id, node_id);
  }

  Vector_dispose(lines);
	return i;
}
Esempio n. 8
0
///////////////////////////////////////////////////////////////////////////////
/// @fn int num_days(string start, string end)
/// @brief gets the number of days between the start string and the end string
/// @param string start is the start date
/// @param string end is the end date
/// @ret int that is the number of days between the 2 dates
///////////////////////////////////////////////////////////////////////////////
int validate::num_days(string start, string end) {

  // Just convert to time_t, because it's easier that way.
  return num_days( str_to_time( start ), str_to_time( end ) );

}
Esempio n. 9
0
static GESTimeline *
create_timeline (int nbargs, gchar ** argv, gchar * audio, gchar * video)
{
  GESTimelineLayer *layer;
  GESTrack *tracka = NULL, *trackv = NULL;
  GESTimeline *timeline;
  guint i;

  timeline = ges_timeline_new ();

  if (audio)
    tracka = ges_track_audio_raw_new ();
  if (video)
    trackv = ges_track_video_raw_new ();

  /* We are only going to be doing one layer of timeline objects */
  layer = (GESTimelineLayer *) ges_simple_timeline_layer_new ();

  /* Add the tracks and the layer to the timeline */
  if (!ges_timeline_add_layer (timeline, layer) ||
      !(!audio || ges_timeline_add_track (timeline, tracka)) ||
      !(!video || ges_timeline_add_track (timeline, trackv)))
    goto build_failure;

  /* Here we've finished initializing our timeline, we're 
   * ready to start using it... by solely working with the layer !*/

  for (i = 0; i < nbargs / 3; i++) {
    GESTimelineObject *obj;

    char *source = argv[i * 3];
    char *arg0 = argv[(i * 3) + 1];
    guint64 duration = str_to_time (argv[(i * 3) + 2]);

    if (!g_strcmp0 ("+pattern", source)) {
      obj = GES_TIMELINE_OBJECT (ges_timeline_test_source_new_for_nick (arg0));
      if (!obj) {
        g_error ("%s is an invalid pattern name!\n", arg0);
        goto build_failure;
      }

      g_object_set (G_OBJECT (obj), "duration", duration, NULL);

      g_printf ("Adding <pattern:%s> duration %" GST_TIME_FORMAT "\n", arg0,
          GST_TIME_ARGS (duration));
    }

    else if (!g_strcmp0 ("+transition", source)) {
      if (duration <= 0) {
        g_error ("durations must be greater than 0");
        goto build_failure;
      }

      obj =
          GES_TIMELINE_OBJECT (ges_timeline_standard_transition_new_for_nick
          (arg0));

      if (!obj) {
        g_error ("invalid transition type\n");
        goto build_failure;
      }

      g_object_set (G_OBJECT (obj), "duration", duration, NULL);

      g_printf ("Adding <transition:%s> duration %" GST_TIME_FORMAT "\n", arg0,
          GST_TIME_ARGS (duration));

    }

    else if (!g_strcmp0 ("+title", source)) {
      obj = GES_TIMELINE_OBJECT (ges_timeline_title_source_new ());

      g_object_set (obj, "duration", duration, "text", arg0, NULL);

      g_printf ("Adding <title:%s> duration %" GST_TIME_FORMAT "\n", arg0,
          GST_TIME_ARGS (duration));
    }

    else {
      gchar *uri;
      guint64 inpoint;

      if (!(uri = ensure_uri (source))) {
        GST_ERROR ("couldn't create uri for '%s'", source);
        goto build_failure;
      }

      inpoint = str_to_time (argv[i * 3 + 1]);
      obj = GES_TIMELINE_OBJECT (ges_timeline_filesource_new (uri));
      g_object_set (obj,
          "in-point", (guint64) inpoint, "duration", (guint64) duration, NULL);

      g_printf ("Adding clip %s inpoint:%" GST_TIME_FORMAT " duration:%"
          GST_TIME_FORMAT "\n", uri, GST_TIME_ARGS (inpoint),
          GST_TIME_ARGS (duration));

      g_free (uri);
    }

    /* Since we're using a GESSimpleTimelineLayer, objects will be automatically
     * appended to the end of the layer */
    ges_timeline_layer_add_object (layer, obj);
  }

  return timeline;

build_failure:
  {
    g_object_unref (timeline);
    return NULL;
  }
}
Esempio n. 10
0
static int
imap_master_client_parse_input(const char *const *args, pool_t pool,
			       struct mail_storage_service_input *input_r,
			       struct imap_master_input *master_input_r,
			       const char **error_r)
{
	const char *key, *value;
	unsigned int peer_dev_major = 0, peer_dev_minor = 0;

	i_zero(input_r);
	i_zero(master_input_r);
	master_input_r->client_input = buffer_create_dynamic(pool, 64);
	master_input_r->client_output = buffer_create_dynamic(pool, 16);
	master_input_r->state = buffer_create_dynamic(pool, 512);

	input_r->module = input_r->service = "imap";
	/* we never want to do userdb lookup again when restoring the client.
	   we have the userdb_fields cached already. */
	input_r->flags_override_remove = MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP;

	if (args[0] == NULL) {
		*error_r = "Missing username in input";
		return -1;
	}
	input_r->username = args[0];

	for (args++; *args != NULL; args++) {
		value = strchr(*args, '=');
		if (value != NULL)
			key = t_strdup_until(*args, value++);
		else {
			key = *args;
			value = "";
		}
		if (strcmp(key, "lip") == 0) {
			if (net_addr2ip(value, &input_r->local_ip) < 0) {
				*error_r = t_strdup_printf(
					"Invalid lip value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "rip") == 0) {
			if (net_addr2ip(value, &input_r->remote_ip) < 0) {
				*error_r = t_strdup_printf(
					"Invalid rip value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "peer_dev_major") == 0) {
			if (str_to_uint(value, &peer_dev_major) < 0) {
				*error_r = t_strdup_printf(
					"Invalid peer_dev_major value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "peer_dev_minor") == 0) {
			if (str_to_uint(value, &peer_dev_minor) < 0) {
				*error_r = t_strdup_printf(
					"Invalid peer_dev_minor value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "peer_ino") == 0) {
			if (str_to_ino(value, &master_input_r->peer_ino) < 0) {
				*error_r = t_strdup_printf(
					"Invalid peer_ino value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "session") == 0) {
			input_r->session_id = value;
		} else if (strcmp(key, "session_created") == 0) {
			if (str_to_time(value, &input_r->session_create_time) < 0) {
				*error_r = t_strdup_printf(
					"Invalid session_created value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "userdb_fields") == 0) {
			input_r->userdb_fields =
				t_strsplit_tabescaped(value);
		} else if (strcmp(key, "client_input") == 0) {
			if (base64_decode(value, strlen(value), NULL,
					  master_input_r->client_input) < 0) {
				*error_r = t_strdup_printf(
					"Invalid client_input base64 value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "client_output") == 0) {
			if (base64_decode(value, strlen(value), NULL,
					  master_input_r->client_output) < 0) {
				*error_r = t_strdup_printf(
					"Invalid client_output base64 value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "state") == 0) {
			if (base64_decode(value, strlen(value), NULL,
					  master_input_r->state) < 0) {
				*error_r = t_strdup_printf(
					"Invalid state base64 value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "tag") == 0) {
			master_input_r->tag = t_strdup(value);
		} else if (strcmp(key, "bad-done") == 0) {
			master_input_r->state_import_bad_idle_done = TRUE;
		} else if (strcmp(key, "idle-continue") == 0) {
			master_input_r->state_import_idle_continue = TRUE;
		}
	}
	if (peer_dev_major != 0 || peer_dev_minor != 0) {
		master_input_r->peer_dev =
			makedev(peer_dev_major, peer_dev_minor);
	}
	return 0;
}
Esempio n. 11
0
int main(int argc, char *argv[]) {
    int c, index;
    double dist = 0.0;
    int finish = -1, pace = -1;
    double finishd = -1.0, paced = -1.0;
    int mode = MODE_NONE;

    while ((c = getopt_long(argc, argv, "hd:f:p:", options, &index)) != -1) {
        switch (c) {
            case 'h':
                print_help();
                return 0;

            case 'd':
                if (strcmp("h", optarg) == 0)
                    dist = DIST_HALF;
                else if (strcmp("f", optarg) == 0)
                    dist = DIST_FULL;
                else
                    dist = atof(optarg);
                break;

            case 'f':
                finish = str_to_time(optarg);
                mode = mode | MODE_FTOP;
                break;

            case 'p':
                pace = str_to_time(optarg);
                mode = mode | MODE_PTOF;
                break;

            default:
                break;
        }
    }

    /* main proc */
    /* more than 1 mode are on */
    if (1 < countbits(mode))
        exit_with_error("Selected more than 1 mode.");

    /* calc and prepare result */
    char finish_str[128], pace_str[128];
    if (mode == MODE_FTOP) {
        paced = (double)finish / dist;
        dtime_to_str(paced, pace_str);
        time_to_str(finish, finish_str);
    } else if (mode == MODE_PTOF) {
        finishd = (double)pace * dist;
        time_to_str(pace, pace_str);
        dtime_to_str(finishd, finish_str);
    }

    /* disp results */
    cout << "Results:" << endl;
    cout << "  mode        " << mode_str[mode] << endl;
    cout << "  dist        " << dist << " km" << endl;
    cout << "  finish-time " << finish_str << endl;
    cout << "  pace-time   " << pace_str << " /km" << endl;

    return 0;
}
Esempio n. 12
0
my_bool
str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
                ulonglong flags, MYSQL_TIME_STATUS *status)
{
  const char *end=str+length, *pos;
  uint number_of_fields= 0, digits, year_length, not_zero_date;
  DBUG_ENTER("str_to_datetime");
  bzero(l_time, sizeof(*l_time));

  if (flags & TIME_TIME_ONLY)
  {
    my_bool ret= str_to_time(str, length, l_time, flags, status);
    DBUG_RETURN(ret);
  }

  my_time_status_init(status);

  /* Skip space at start */
  for (; str != end && my_isspace(&my_charset_latin1, *str) ; str++)
    ;
  if (str == end || ! my_isdigit(&my_charset_latin1, *str))
  {
    status->warnings= MYSQL_TIME_WARN_TRUNCATED;
    l_time->time_type= MYSQL_TIMESTAMP_NONE;
    DBUG_RETURN(1);
  }

  /*
    Calculate number of digits in first part.
    If length= 8 or >= 14 then year is of format YYYY.
    (YYYY-MM-DD,  YYYYMMDD, YYYYYMMDDHHMMSS)
  */
  pos= str;
  digits= skip_digits(&pos, end);

  if (pos < end && *pos == 'T') /* YYYYYMMDDHHMMSSThhmmss is supported too */
  {
    pos++;
    digits+= skip_digits(&pos, end);
  }
  if (pos < end && *pos == '.' && digits >= 12) /* YYYYYMMDDHHMMSShhmmss.uuuuuu is supported too */
  {
    pos++;
    skip_digits(&pos, end); // ignore the return value
  }

  if (pos == end)
  {
    /*
      Found date in internal format
      (only numbers like [YY]YYMMDD[T][hhmmss[.uuuuuu]])
    */
    year_length= (digits == 4 || digits == 8 || digits >= 14) ? 4 : 2;
    if (get_digits(&l_time->year, &number_of_fields, &str, end, year_length) 
        || get_digits(&l_time->month, &number_of_fields, &str, end, 2)
        || get_digits(&l_time->day, &number_of_fields, &str, end, 2)
        || get_maybe_T(&str, end)
        || get_digits(&l_time->hour, &number_of_fields, &str, end, 2)
        || get_digits(&l_time->minute, &number_of_fields, &str, end, 2)
        || get_digits(&l_time->second, &number_of_fields, &str, end, 2))
     status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
  }
  else
  {
    const char *start= str;
    if (get_number(&l_time->year, &number_of_fields, &str, end))
      status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
    year_length= str - start;

    if (!status->warnings &&
        (get_punct(&str, end)
         || get_number(&l_time->month, &number_of_fields, &str, end)
         || get_punct(&str, end)
         || get_number(&l_time->day, &number_of_fields, &str, end)
         || get_date_time_separator(&number_of_fields, flags, &str, end)
         || get_number(&l_time->hour, &number_of_fields, &str, end)
         || get_punct(&str, end)
         || get_number(&l_time->minute, &number_of_fields, &str, end)
         || get_punct(&str, end)
         || get_number(&l_time->second, &number_of_fields, &str, end)))
      status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
  }

  /* we're ok if date part is correct. even if the rest is truncated */
  if (number_of_fields < 3)
  {
    l_time->time_type= MYSQL_TIMESTAMP_NONE;
    status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
    DBUG_RETURN(TRUE);
  }

  if (!status->warnings && str < end && *str == '.')
  {
    str++;
    get_microseconds(&l_time->second_part, status,
                     &number_of_fields, &str, end);
  }

  not_zero_date = l_time->year || l_time->month || l_time->day ||
                  l_time->hour || l_time->minute || l_time->second ||
                  l_time->second_part;

  if (year_length == 2 && not_zero_date)
    l_time->year+= (l_time->year < YY_PART_YEAR ? 2000 : 1900);

  if (l_time->year > 9999 || l_time->month > 12 || l_time->day > 31 ||
      l_time->hour > 23 || l_time->minute > 59 || l_time->second > 59)
  {
    status->warnings|= MYSQL_TIME_WARN_TRUNCATED;
    goto err;
  }

  if (check_date(l_time, not_zero_date, flags, &status->warnings))
    goto err;

  l_time->time_type= (number_of_fields <= 3 ?
                      MYSQL_TIMESTAMP_DATE : MYSQL_TIMESTAMP_DATETIME);

  for (; str != end ; str++)
  {
    if (!my_isspace(&my_charset_latin1,*str))
    {
      status->warnings= MYSQL_TIME_WARN_TRUNCATED;
      break;
    }
  }

  DBUG_RETURN(FALSE);

err:
  bzero((char*) l_time, sizeof(*l_time));
  l_time->time_type= MYSQL_TIMESTAMP_ERROR;
  DBUG_RETURN(TRUE);
}
Esempio n. 13
0
static int
imap_hibernate_client_parse_input(const char *const *args, pool_t pool,
				  struct imap_client_state *state_r,
				  const char **error_r)
{
	const char *key, *value;
	unsigned int peer_dev_major = 0, peer_dev_minor = 0;

	memset(state_r, 0, sizeof(*state_r));
	if (args[0] == NULL) {
		*error_r = "Missing username in input";
		return -1;
	}
	state_r->username = args[0]; args++;
	if (args[0] == NULL) {
		*error_r = "Missing mail_log_prefix in input";
		return -1;
	}
	state_r->mail_log_prefix = args[0]; args++;

	for (; *args != NULL; args++) {
		value = strchr(*args, '=');
		if (value != NULL)
			key = t_strdup_until(*args, value++);
		else {
			key = *args;
			value = "";
		}
		if (strcmp(key, "lip") == 0) {
			if (net_addr2ip(value, &state_r->local_ip) < 0) {
				*error_r = t_strdup_printf(
					"Invalid lip value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "rip") == 0) {
			if (net_addr2ip(value, &state_r->remote_ip) < 0) {
				*error_r = t_strdup_printf(
					"Invalid rip value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "peer_dev_major") == 0) {
			if (str_to_uint(value, &peer_dev_major) < 0) {
				*error_r = t_strdup_printf(
					"Invalid peer_dev_major value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "peer_dev_minor") == 0) {
			if (str_to_uint(value, &peer_dev_minor) < 0) {
				*error_r = t_strdup_printf(
					"Invalid peer_dev_minor value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "peer_ino") == 0) {
			if (str_to_ino(value, &state_r->peer_ino) < 0) {
				*error_r = t_strdup_printf(
					"Invalid peer_ino value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "uid") == 0) {
			if (str_to_uid(value, &state_r->uid) < 0) {
				*error_r = t_strdup_printf(
					"Invalid uid value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "gid") == 0) {
			if (str_to_gid(value, &state_r->gid) < 0) {
				*error_r = t_strdup_printf(
					"Invalid gid value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "stats") == 0) {
			state_r->stats = value;
		} else if (strcmp(key, "idle-cmd") == 0) {
			state_r->idle_cmd = TRUE;
		} else if (strcmp(key, "session") == 0) {
			state_r->session_id = value;
		} else if (strcmp(key, "session_created") == 0) {
			if (str_to_time(value, &state_r->session_created) < 0) {
				*error_r = t_strdup_printf(
					"Invalid session_created value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "userdb_fields") == 0) {
			state_r->userdb_fields = value;
		} else if (strcmp(key, "notify_fd") == 0) {
			state_r->have_notify_fd = TRUE;
		} else if (strcmp(key, "idle_notify_interval") == 0) {
			if (str_to_uint(value, &state_r->imap_idle_notify_interval) < 0) {
				*error_r = t_strdup_printf(
					"Invalid idle_notify_interval value: %s", value);
				return -1;
			}
		} else if (strcmp(key, "tag") == 0) {
			state_r->tag = i_strdup(value);
		} else if (strcmp(key, "state") == 0) {
			buffer_t *state_buf;

			state_buf = buffer_create_dynamic(pool, 1024);
			if (base64_decode(value, strlen(value), NULL,
					  state_buf) < 0) {
				*error_r = t_strdup_printf(
					"Invalid state base64 value: %s", value);
				return -1;
			}
			state_r->state = state_buf->data;
			state_r->state_size = state_buf->used;
		}
	}
	if (state_r->tag == NULL) {
		*error_r = "Missing tag";
		return -1;
	}
	if (peer_dev_major != 0 || peer_dev_minor != 0)
		state_r->peer_dev = makedev(peer_dev_major, peer_dev_minor);
	return 0;
}