예제 #1
0
static int
_strcpy_cutoff(char *dest, const char *src, size_t cutoff, int ralign,
	       size_t buf_len)
{
	size_t len = strlen(src);
	if (buf_len <= 1) {
		if (buf_len == 0)
			dest[0] = 0;
		return 0;
	}

	if (cutoff == 0) {
		cutoff = len;
	}

	cutoff = QB_MIN(cutoff, buf_len - 1);
	len = QB_MIN(len, cutoff);
	if (ralign) {
		memset(dest, ' ', cutoff - len);
		memcpy(dest + cutoff - len, src, len);
	} else {
		memcpy(dest, src, len);
		memset(dest + len, ' ', cutoff - len);
	}

	dest[cutoff] = '\0';

	return cutoff;
}
예제 #2
0
파일: ipcs.c 프로젝트: ip1981/libqb
static ssize_t
_request_q_len_get(struct qb_ipcs_connection *c)
{
	ssize_t q_len;
	if (c->service->funcs.q_len_get) {
		q_len = c->service->funcs.q_len_get(&c->request);
		if (q_len <= 0) {
			return q_len;
		}
		if (c->service->poll_priority == QB_LOOP_MED) {
			q_len = QB_MIN(q_len, 5);
		} else if (c->service->poll_priority == QB_LOOP_LOW) {
			q_len = 1;
		} else {
			q_len = QB_MIN(q_len, MAX_RECV_MSGS);
		}
	} else {
		q_len = 1;
	}
	return q_len;
}
예제 #3
0
static st_query_result_t *
stonith_choose_peer(remote_fencing_op_t * op)
{
    const char *device = NULL;
    st_query_result_t *peer = NULL;
    uint32_t active = fencing_active_peers();

    do {
        if (op->devices) {
            device = op->devices->data;
            crm_trace("Checking for someone to fence %s with %s", op->target, device);
        } else {
            crm_trace("Checking for someone to fence %s", op->target);
        }

        peer = find_best_peer(device, op, FIND_PEER_SKIP_TARGET|FIND_PEER_VERIFIED_ONLY);
        if (peer) {
            crm_trace("Found verified peer %s for %s", peer->host, device?device:"<any>");
            return peer;
        }

        if(op->query_timer != 0 && op->replies < QB_MIN(op->replies_expected, active)) {
            crm_trace("Waiting before looking for unverified devices to fence %s", op->target);
            return NULL;
        }

        peer = find_best_peer(device, op, FIND_PEER_SKIP_TARGET);
        if (peer) {
            crm_trace("Found best unverified peer %s", peer->host);
            return peer;
        }

        peer = find_best_peer(device, op, FIND_PEER_TARGET_ONLY);
        if(peer) {
            crm_trace("%s will fence itself", peer->host);
            return peer;
        }

        /* Try the next fencing level if there is one */
    } while (is_set(op->call_options, st_opt_topology)
             && stonith_topology_next(op) == pcmk_ok);

    crm_notice("Couldn't find anyone to fence %s with %s", op->target, device?device:"<any>");
    return NULL;
}
예제 #4
0
파일: simplelog.c 프로젝트: ip1981/libqb
int32_t
main(int32_t argc, char *argv[])
{
	const char *options = "vhteobdf:";
	int32_t opt;
	int32_t tracer;
	int32_t do_stderr = QB_FALSE;
	int32_t do_stdout = QB_FALSE;
	int32_t do_dump_blackbox = QB_FALSE;
	char *logfile = NULL;
	int32_t log_fd = -1;

	while ((opt = getopt(argc, argv, options)) != -1) {
		switch (opt) {
		case 'd':
			do_dump_blackbox = QB_TRUE;
			break;
		case 't':
			do_threaded = QB_TRUE;
			break;
		case 'e':
			do_stderr = QB_TRUE;
			break;
		case 'o':
			do_stdout = QB_TRUE;
			break;
		case 'b':
			do_blackbox = QB_TRUE;
			break;
		case 'f':
			logfile = optarg;
			break;
		case 'v':
			_log_priority++;
			break;
		case 'h':
		default:
			show_usage(argv[0]);
			exit(0);
			break;
		}
	}

	if (do_dump_blackbox) {
		qb_log_blackbox_print_from_file("simple-log.fdata");
		exit(0);
	}

	signal(SIGSEGV, sigsegv_handler);

	qb_log_init("simple-log", LOG_USER, LOG_INFO);
	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, do_threaded);
	qb_log_tags_stringify_fn_set(my_tags_stringify);

	if (do_stderr) {
		qb_log_filter_fn_set(m_filter);
		qb_log_format_set(QB_LOG_STDERR, "[%p] %4g: %f:%l %b");
		qb_log_ctl(QB_LOG_STDERR, QB_LOG_CONF_ENABLED, QB_TRUE);

		tracer = qb_log_custom_open(trace_logger, NULL, NULL, NULL);
		qb_log_ctl(tracer, QB_LOG_CONF_ENABLED, QB_TRUE);
		qb_log_format_set(tracer, "%4g: %n() %b");
		qb_log_filter_ctl2(tracer, QB_LOG_FILTER_ADD,
				   QB_LOG_FILTER_FILE, __FILE__,
				   LOG_TRACE, 200);
	}
	if (do_stdout) {
		qb_log_filter_ctl2(QB_LOG_STDOUT, QB_LOG_FILTER_ADD,
				   QB_LOG_FILTER_FILE, __FILE__,
				   LOG_ALERT, QB_MIN(LOG_DEBUG, _log_priority));
		qb_log_format_set(QB_LOG_STDOUT, "[%p] %4g: %f:%l %b");
		qb_log_ctl(QB_LOG_STDOUT, QB_LOG_CONF_ENABLED, QB_TRUE);
	}
	if (do_blackbox) {
		qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
				  QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
		qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 4096);
		qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_THREADED, QB_FALSE);
		qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
	}
	if (logfile) {
		log_fd = qb_log_file_open(logfile);
		qb_log_filter_ctl(log_fd, QB_LOG_FILTER_ADD,
				  QB_LOG_FILTER_FILE, __FILE__, _log_priority);
		qb_log_format_set(log_fd, "[%N] %t %n() [%p] %b");
		qb_log_ctl(log_fd, QB_LOG_CONF_THREADED, do_threaded);
		qb_log_ctl(log_fd, QB_LOG_CONF_ENABLED, QB_TRUE);
	}
	if (do_threaded) {
		qb_log_thread_start();
	}
	qb_log(LOG_DEBUG, "hello");
	qb_log(LOG_INFO, "this is an info");
	qb_log(LOG_NOTICE, "hello - notice?");
	func_one();
	func_two();

	qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);

	qb_log(LOG_WARNING, "no syslog");
	qb_log(LOG_ERR, "no syslog");

#if 0
	// test blackbox
	logfile = NULL;
	logfile[5] = 'a';
#endif
	if (do_blackbox) {
		qb_log_blackbox_write_to_file("simple-log.fdata");
		qb_log_blackbox_print_from_file("simple-log.fdata");
		qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_FALSE);
	}
	qb_log_fini();
	return 0;
}
예제 #5
0
파일: cpg.c 프로젝트: oalbrigt/pacemaker
gboolean
cluster_connect_cpg(crm_cluster_t *cluster)
{
    int rc = -1;
    int fd = 0;
    int retries = 0;
    uint32_t id = 0;
    crm_node_t *peer = NULL;
    cpg_handle_t handle = 0;

    struct mainloop_fd_callbacks cpg_fd_callbacks = {
        .dispatch = pcmk_cpg_dispatch,
        .destroy = cluster->destroy,
    };

    cpg_callbacks_t cpg_callbacks = {
        .cpg_deliver_fn = cluster->cpg.cpg_deliver_fn,
        .cpg_confchg_fn = cluster->cpg.cpg_confchg_fn,
        /* .cpg_deliver_fn = pcmk_cpg_deliver, */
        /* .cpg_confchg_fn = pcmk_cpg_membership, */
    };

    cpg_evicted = FALSE;
    cluster->group.length = 0;
    cluster->group.value[0] = 0;

    /* group.value is char[128] */
    strncpy(cluster->group.value, crm_system_name?crm_system_name:"unknown", 127);
    cluster->group.value[127] = 0;
    cluster->group.length = 1 + QB_MIN(127, strlen(cluster->group.value));

    cs_repeat(retries, 30, rc = cpg_initialize(&handle, &cpg_callbacks));
    if (rc != CS_OK) {
        crm_err("Could not connect to the Cluster Process Group API: %d", rc);
        goto bail;
    }

    id = get_local_nodeid(handle);
    if (id == 0) {
        crm_err("Could not get local node id from the CPG API");
        goto bail;

    }
    cluster->nodeid = id;

    retries = 0;
    cs_repeat(retries, 30, rc = cpg_join(handle, &cluster->group));
    if (rc != CS_OK) {
        crm_err("Could not join the CPG group '%s': %d", crm_system_name, rc);
        goto bail;
    }

    rc = cpg_fd_get(handle, &fd);
    if (rc != CS_OK) {
        crm_err("Could not obtain the CPG API connection: %d", rc);
        goto bail;
    }

    pcmk_cpg_handle = handle;
    cluster->cpg_handle = handle;
    mainloop_add_fd("corosync-cpg", G_PRIORITY_MEDIUM, fd, cluster, &cpg_fd_callbacks);

  bail:
    if (rc != CS_OK) {
        cpg_finalize(handle);
        return FALSE;
    }

    peer = crm_get_peer(id, NULL);
    crm_update_peer_proc(__FUNCTION__, peer, crm_proc_cpg, ONLINESTATUS);
    return TRUE;
}

gboolean
send_cluster_message_cs(xmlNode * msg, gboolean local, crm_node_t * node, enum crm_ais_msg_types dest)
{
    gboolean rc = TRUE;
    char *data = NULL;

    data = dump_xml_unformatted(msg);
    rc = send_cluster_text(crm_class_cluster, data, local, node, dest);
    free(data);
    return rc;
}

gboolean
send_cluster_text(int class, const char *data,
              gboolean local, crm_node_t * node, enum crm_ais_msg_types dest)
{
    static int msg_id = 0;
    static int local_pid = 0;
    static int local_name_len = 0;
    static const char *local_name = NULL;

    char *target = NULL;
    struct iovec *iov;
    AIS_Message *msg = NULL;
    enum crm_ais_msg_types sender = text2msg_type(crm_system_name);

    /* There are only 6 handlers registered to crm_lib_service in plugin.c */
    CRM_CHECK(class < 6, crm_err("Invalid message class: %d", class);
              return FALSE);

#if !SUPPORT_PLUGIN
    CRM_CHECK(dest != crm_msg_ais, return FALSE);
#endif

    if(local_name == NULL) {
        local_name = get_local_node_name();
    }
    if(local_name_len == 0 && local_name) {
        local_name_len = strlen(local_name);
    }

    if (data == NULL) {
        data = "";
    }

    if (local_pid == 0) {
        local_pid = getpid();
    }

    if (sender == crm_msg_none) {
        sender = local_pid;
    }

    msg = calloc(1, sizeof(AIS_Message));

    msg_id++;
    msg->id = msg_id;
    msg->header.id = class;
    msg->header.error = CS_OK;

    msg->host.type = dest;
    msg->host.local = local;

    if (node) {
        if (node->uname) {
            target = strdup(node->uname);
            msg->host.size = strlen(node->uname);
            memset(msg->host.uname, 0, MAX_NAME);
            memcpy(msg->host.uname, node->uname, msg->host.size);
        } else {
            target = crm_strdup_printf("%u", node->id);
        }
        msg->host.id = node->id;
    } else {
        target = strdup("all");
    }

    msg->sender.id = 0;
    msg->sender.type = sender;
    msg->sender.pid = local_pid;
    msg->sender.size = local_name_len;
    memset(msg->sender.uname, 0, MAX_NAME);
    if(local_name && msg->sender.size) {
        memcpy(msg->sender.uname, local_name, msg->sender.size);
    }

    msg->size = 1 + strlen(data);
    msg->header.size = sizeof(AIS_Message) + msg->size;

    if (msg->size < CRM_BZ2_THRESHOLD) {
        msg = realloc_safe(msg, msg->header.size);
        memcpy(msg->data, data, msg->size);

    } else {
        char *compressed = NULL;
        unsigned int new_size = 0;
        char *uncompressed = strdup(data);

        if (crm_compress_string(uncompressed, msg->size, 0, &compressed, &new_size)) {

            msg->header.size = sizeof(AIS_Message) + new_size;
            msg = realloc_safe(msg, msg->header.size);
            memcpy(msg->data, compressed, new_size);

            msg->is_compressed = TRUE;
            msg->compressed_size = new_size;

        } else {
            msg = realloc_safe(msg, msg->header.size);
            memcpy(msg->data, data, msg->size);
        }

        free(uncompressed);
        free(compressed);
    }

    iov = calloc(1, sizeof(struct iovec));
    iov->iov_base = msg;
    iov->iov_len = msg->header.size;

    if (msg->compressed_size) {
        crm_trace("Queueing CPG message %u to %s (%llu bytes, %d bytes compressed payload): %.200s",
                  msg->id, target, (unsigned long long) iov->iov_len,
                  msg->compressed_size, data);
    } else {
        crm_trace("Queueing CPG message %u to %s (%llu bytes, %d bytes payload): %.200s",
                  msg->id, target, (unsigned long long) iov->iov_len,
                  msg->size, data);
    }
    free(target);

#if SUPPORT_PLUGIN
    /* The plugin is the only time we dont use CPG messaging */
    if(get_cluster_type() == pcmk_cluster_classic_ais) {
        return send_plugin_text(class, iov);
    }
#endif

    send_cpg_iov(iov);

    return TRUE;
}

enum crm_ais_msg_types
text2msg_type(const char *text)
{
    int type = crm_msg_none;

    CRM_CHECK(text != NULL, return type);
    if (safe_str_eq(text, "ais")) {
        type = crm_msg_ais;
    } else if (safe_str_eq(text, "crm_plugin")) {
        type = crm_msg_ais;
    } else if (safe_str_eq(text, CRM_SYSTEM_CIB)) {
        type = crm_msg_cib;
    } else if (safe_str_eq(text, CRM_SYSTEM_CRMD)) {
        type = crm_msg_crmd;
    } else if (safe_str_eq(text, CRM_SYSTEM_DC)) {
        type = crm_msg_crmd;
    } else if (safe_str_eq(text, CRM_SYSTEM_TENGINE)) {
        type = crm_msg_te;
    } else if (safe_str_eq(text, CRM_SYSTEM_PENGINE)) {
        type = crm_msg_pe;
    } else if (safe_str_eq(text, CRM_SYSTEM_LRMD)) {
        type = crm_msg_lrmd;
    } else if (safe_str_eq(text, CRM_SYSTEM_STONITHD)) {
        type = crm_msg_stonithd;
    } else if (safe_str_eq(text, "stonith-ng")) {
        type = crm_msg_stonith_ng;
    } else if (safe_str_eq(text, "attrd")) {
        type = crm_msg_attrd;

    } else {
        /* This will normally be a transient client rather than
         * a cluster daemon.  Set the type to the pid of the client
         */
        int scan_rc = sscanf(text, "%d", &type);

        if (scan_rc != 1 || type <= crm_msg_stonith_ng) {
            /* Ensure it's sane */
            type = crm_msg_none;
        }
    }
    return type;
}
예제 #6
0
파일: cpg.c 프로젝트: oalbrigt/pacemaker
static ssize_t
crm_cs_flush(gpointer data)
{
    int sent = 0;
    ssize_t rc = 0;
    int queue_len = 0;
    static unsigned int last_sent = 0;
    cpg_handle_t *handle = (cpg_handle_t *)data;

    if (*handle == 0) {
        crm_trace("Connection is dead");
        return pcmk_ok;
    }

    queue_len = g_list_length(cs_message_queue);
    if ((queue_len % 1000) == 0 && queue_len > 1) {
        crm_err("CPG queue has grown to %d", queue_len);

    } else if (queue_len == CS_SEND_MAX) {
        crm_warn("CPG queue has grown to %d", queue_len);
    }

    if (cs_message_timer) {
        /* There is already a timer, wait until it goes off */
        crm_trace("Timer active %d", cs_message_timer);
        return pcmk_ok;
    }

    while (cs_message_queue && sent < CS_SEND_MAX) {
        struct iovec *iov = cs_message_queue->data;

        errno = 0;
        rc = cpg_mcast_joined(*handle, CPG_TYPE_AGREED, iov, 1);

        if (rc != CS_OK) {
            break;
        }

        sent++;
        last_sent++;
        crm_trace("CPG message sent, size=%llu",
                  (unsigned long long) iov->iov_len);

        cs_message_queue = g_list_remove(cs_message_queue, iov);
        free(iov->iov_base);
        free(iov);
    }

    queue_len -= sent;
    if (sent > 1 || cs_message_queue) {
        crm_info("Sent %d CPG messages  (%d remaining, last=%u): %s (%lld)",
                 sent, queue_len, last_sent, ais_error2text(rc),
                 (long long) rc);
    } else {
        crm_trace("Sent %d CPG messages  (%d remaining, last=%u): %s (%lld)",
                  sent, queue_len, last_sent, ais_error2text(rc),
                  (long long) rc);
    }

    if (cs_message_queue) {
        uint32_t delay_ms = 100;
        if(rc != CS_OK) {
            /* Proportionally more if sending failed but cap at 1s */
            delay_ms = QB_MIN(1000, CS_SEND_MAX + (10 * queue_len));
        }
        cs_message_timer = g_timeout_add(delay_ms, crm_cs_flush_cb, data);
    }

    return rc;
}
예제 #7
0
파일: unix.c 프로젝트: lkunemail/libqb
int32_t
qb_sys_mmap_file_open(char *path, const char *file, size_t bytes,
		       uint32_t file_flags)
{
	int32_t fd;
	int32_t i;
	int32_t res = 0;
	ssize_t written;
	char *buffer = NULL;
	char *is_absolute = strchr(file, '/');

	if (is_absolute) {
		(void)strlcpy(path, file, PATH_MAX);
	} else {
#if defined(QB_LINUX) || defined(QB_CYGWIN)
		snprintf(path, PATH_MAX, "/dev/shm/%s", file);
#else
		snprintf(path, PATH_MAX, LOCALSTATEDIR "/run/%s", file);
		is_absolute = path;
#endif
	}
	fd = open_mmap_file(path, file_flags);
	if (fd < 0 && !is_absolute) {
		qb_util_perror(LOG_ERR, "couldn't open file %s", path);

		snprintf(path, PATH_MAX, LOCALSTATEDIR "/run/%s", file);
		fd = open_mmap_file(path, file_flags);
		if (fd < 0) {
			res = -errno;
			qb_util_perror(LOG_ERR, "couldn't open file %s", path);
			return res;
		}
	} else if (fd < 0 && is_absolute) {
		res = -errno;
		qb_util_perror(LOG_ERR, "couldn't open file %s", path);
		return res;
	}

	if (ftruncate(fd, bytes) == -1) {
		res = -errno;
		qb_util_perror(LOG_ERR, "couldn't truncate file %s", path);
		goto unlink_exit;
	}

	if (file_flags & O_CREAT) {
		long page_size = sysconf(_SC_PAGESIZE);
		long write_size = QB_MIN(page_size, bytes);
		if (page_size < 0) {
			res = -errno;
			goto unlink_exit;
		}
		buffer = calloc(1, write_size);
		if (buffer == NULL) {
			res = -ENOMEM;
			goto unlink_exit;
		}
		for (i = 0; i < (bytes / write_size); i++) {
retry_write:
			written = write(fd, buffer, write_size);
			if (written == -1 && errno == EINTR) {
				goto retry_write;
			}
			if (written != write_size) {
				res = -ENOSPC;
				free(buffer);
				goto unlink_exit;
			}
		}
		free(buffer);
	}

	return fd;

unlink_exit:
	unlink(path);
	if (fd > 0) {
		close(fd);
	}
	return res;
}
예제 #8
0
파일: ipcs.c 프로젝트: ip1981/libqb
int32_t
qb_ipcs_dispatch_connection_request(int32_t fd, int32_t revents, void *data)
{
	struct qb_ipcs_connection *c = (struct qb_ipcs_connection *)data;
	char bytes[MAX_RECV_MSGS];
	int32_t res;
	int32_t res2;
	int32_t recvd = 0;
	ssize_t avail;

	if (revents & POLLNVAL) {
		qb_util_log(LOG_DEBUG, "NVAL conn:%p fd:%d", c, fd);
		return -EINVAL;
	}
	if (revents & POLLHUP) {
		qb_util_log(LOG_DEBUG, "HUP conn:%p fd:%d", c, fd);
		qb_ipcs_disconnect(c);
		return -ESHUTDOWN;
	}

	if (revents & POLLOUT) {
		res = resend_event_notifications(c);
		if (res < 0 && res != -EAGAIN) {
			errno = -res;
			qb_util_perror(LOG_WARNING, "resend_event_notifications");
		}
		if ((revents & POLLIN) == 0) {
			return 0;
		}
	}
	if (c->fc_enabled) {
		return 0;
	}
	avail = _request_q_len_get(c);

	if (c->service->needs_sock_for_poll && avail == 0) {
		res2 = qb_ipc_us_recv(&c->setup, bytes, 1, 0);
		qb_util_log(LOG_WARNING,
			    "conn:%p Nothing in q but got POLLIN on fd:%d (res2:%d)",
			    c, fd, res2);
		return 0;
	}

	do {
		res = _process_request_(c, IPC_REQUEST_TIMEOUT);
		if (res > 0 || res == -ENOBUFS || res == -EINVAL) {
			recvd++;
		}
		if (res > 0) {
			avail--;
		}
	} while (avail > 0 && res > 0 && !c->fc_enabled);

	if (c->service->needs_sock_for_poll && recvd > 0) {
		res2 = qb_ipc_us_recv(&c->setup, bytes, recvd, -1);
		if (res2 < 0) {
			errno = -res2;
			qb_util_perror(LOG_ERR, "error receiving from setup sock");
		}
	}

	res = QB_MIN(0, res);
	if (res == -EAGAIN || res == -ETIMEDOUT || res == -ENOBUFS) {
		res = 0;
	}
	if (res != 0) {
		errno = -res;
		qb_util_perror(LOG_ERR, "request returned error");
		qb_ipcs_connection_unref(c);
	}

	return res;
}
예제 #9
0
size_t
qb_vsnprintf_serialize(char *serialize, size_t max_len,
		       const char *fmt, va_list ap)
{
	char *format;
	char *p;
	int type_long = 0;
	int type_longlong = 0;
        int sformat_length = 0;
        int sformat_precision = 0;
	uint32_t location = strlcpy(serialize, fmt, max_len) + 1;

	format = (char *)fmt;
	for (;;) {
		type_long = 0;
		type_longlong = 0;
		p = strchrnul((const char *)format, '%');
		if (*p == '\0') {
			break;
		}
		format = p + 1;
reprocess:
		switch (format[0]) {
		case '#': /* alternate form conversion, ignore */
		case '-': /* left adjust, ignore */
		case ' ': /* a space, ignore */
		case '+': /* a sign should be used, ignore */
		case '\'': /* group in thousands, ignore */
		case 'I': /* glibc-ism locale alternative, ignore */
                    format++;
                    goto reprocess;
		case '.': /* precision, ignore */
                    format++;
                    sformat_precision = 1;
                    goto reprocess;
		case '0': /* field width, ignore */
		case '1': /* field width, ignore */
		case '2': /* field width, ignore */
		case '3': /* field width, ignore */
		case '4': /* field width, ignore */
		case '5': /* field width, ignore */
		case '6': /* field width, ignore */
		case '7': /* field width, ignore */
		case '8': /* field width, ignore */
		case '9': /* field width, ignore */
                        if(sformat_precision) {
                            sformat_length *= 10;
                            sformat_length += (format[0] - '0');
                        }
			format++;
			goto reprocess;
		case '*': /* variable field width, save */ {
			int arg_int = va_arg(ap, int);
			if (location + sizeof (int) > max_len) {
				return max_len;
			}
			memcpy(&serialize[location], &arg_int, sizeof (int));
			location += sizeof(int);
			format++;
			goto reprocess;
		}
		case 'l':
			format++;
			type_long = 1;
			if (*format == 'l') {
				type_long = 0;
				type_longlong = 1;
				format++;
			}
			goto reprocess;
		case 'd': /* int argument */
		case 'i': /* int argument */
		case 'o': /* unsigned int argument */
		case 'u':
		case 'x':
		case 'X':
			if (type_long) {
				long int arg_int;

				if (location + sizeof (long int) > max_len) {
					return max_len;
				}
				arg_int = va_arg(ap, long int);
				memcpy(&serialize[location], &arg_int,
				       sizeof(long int));
				location += sizeof(long int);
				format++;
				break;
			} else if (type_longlong) {
				long long int arg_int;

				if (location + sizeof (long long int) > max_len) {
					return max_len;
				}
				arg_int = va_arg(ap, long long int);
				memcpy(&serialize[location], &arg_int,
				       sizeof(long long int));
				location += sizeof(long long int);
				format++;
				break;
			} else {
				int arg_int;

				if (location + sizeof (int) > max_len) {
					return max_len;
				}
				arg_int = va_arg(ap, int);
				memcpy(&serialize[location], &arg_int,
				       sizeof(int));
				location += sizeof(int);
				format++;
				break;
			}
		case 'e':
		case 'E':
		case 'f':
		case 'F':
		case 'g':
		case 'G':
		case 'a':
		case 'A':
			{
			double arg_double;

			if (location + sizeof (double) > max_len) {
				return max_len;
			}
			arg_double = va_arg(ap, double);
			memcpy (&serialize[location], &arg_double, sizeof (double));
			location += sizeof(double);
			format++;
			break;
			}
		case 'c':
			{
			int arg_int;
			unsigned char arg_char;

			if (location + sizeof (unsigned int) > max_len) {
				return max_len;
			}
			arg_int = va_arg(ap, unsigned int);
			arg_char = (unsigned char)arg_int;
			memcpy (&serialize[location], &arg_char, sizeof (unsigned char));
			location += sizeof(unsigned char);
			break;
			}
		case 's':
			{
			char *arg_string;
			arg_string = va_arg(ap, char *);
			if (arg_string == NULL) {
				location += strlcpy(&serialize[location],
						   "(null)",
						   QB_MIN(strlen("(null)") + 1,
							  max_len - location));
			} else if (sformat_length) {
                                location += strlcpy(&serialize[location],
						   arg_string,
						   QB_MIN(sformat_length + 1,
						   (max_len - location)));
			} else {
				location += strlcpy(&serialize[location],
						   arg_string,
						   QB_MIN(strlen(arg_string) + 1,
							  max_len - location));
			}
			location++;
			break;
			}
		case 'p':
			{
			ptrdiff_t arg_pointer = va_arg(ap, ptrdiff_t);
			if (location + sizeof (ptrdiff_t) > max_len) {
				return max_len;
			}
			memcpy(&serialize[location], &arg_pointer, sizeof(ptrdiff_t));
			location += sizeof(ptrdiff_t);
			break;
			}
		case '%':
			if (location + 1 > max_len) {
				return max_len;
			}
			serialize[location++] = '%';
                        sformat_length = 0;
                        sformat_precision = 0;
			break;

		}