Beispiel #1
0
char* logger::
format_header(const logger::msg& a_msg, char* a_buf, const char* a_end)
{
    // Message mormat: Timestamp|Level|Ident|Category|Message|File:Line FunName
    // Write everything up to Message to the m_data:
    char*  p = a_buf;

    // Write Timestamp
    if (timestamp_type() != stamp_type::NO_TIMESTAMP) {
        p   += timestamp::format(timestamp_type(), a_msg.m_timestamp, p, a_end - p);
        *p++ = '|';
    }
    // Write Level
    *p++ = logger::log_level_to_str(a_msg.m_level)[0];
    *p++ = '|';
    if (show_ident()) {
        p = stpncpy(p, ident().c_str(), ident().size());
        *p++ = '|';
    }
    if (show_thread()) {
        if (a_msg.m_thread_name[0] == '\0') {
            char* q = const_cast<char*>(a_msg.m_thread_name);
            itoa(a_msg.m_thread_id, q, 10);
        }
        p = stpcpy(p, a_msg.m_thread_name);
        *p++ = '|';
    }
    if (show_category()) {
        if (!a_msg.m_category.empty())
            p = stpncpy(p, a_msg.m_category.c_str(), a_msg.m_category.size());
        *p++ = '|';
    }

    return p;
}
int processArguments(int argc, char* argv[]) {

	int i;
	u_int temp;
	
	if(argc < 3) {
		printHelp(argv[0],true,"Faltan Argumentos\n");
		return false;
	}	

    if(strcmp(argv[1],"-r")==0){
		mode = SERVER;
	} else if(strcmp(argv[1],"-t")==0) {
		mode = CLIENT;
	} else {
		printHelp(argv[0],true,"Unkown Mode\n");
		return false;
	}
	
	for(i=2; i<(argc-1); i++) {
		if(strcmp(argv[i],"-h")==0) {
			printHelp(argv[0],false);
			return true;
		}	
		
		if(strcmp(argv[i],"-p")==0) {
			temp = strtoimax(argv[++i], NULL, 10);
			if(temp == 0 || temp < MINPORT || temp > MAXPORT) {
				printHelp(argv[0],true,"Port out of range\n");
				return false;
			}
			port = temp;
		} else if(strcmp(argv[i],"-d")==0) {
			stpncpy(ip_dst,argv[++i],18);
		} else if(strstr(argv[i],"-v")!=NULL) {
			debugLevel = strlen(argv[i])-1;
		} else if(strcmp(argv[i],"-i")==0) {
			stpncpy(ip_listen,argv[++i],18);	
		} else {
			printHelp(argv[0],true,"Unkown option\n");
			return false;
		}	
	}
	
	stpncpy(filename,argv[i],254);

	debug(2,"%s","\tConfiguraciones:");
	if(mode == SERVER) {
		debug(2,"\t\tModo:\t%s","Servidor");
		debug(2,"\t\tListen on:\t%s:%u",ip_listen,port);
	} else if (mode == CLIENT) {	
		debug(2,"\t\tModo:\t%s","Cliente");
		debug(2,"\t\tDestino:\t%s:%u",ip_dst,port);
	}
	debug(2,"\t\tFileName:\t%s",filename);
	
	return true;
}
Beispiel #3
0
/// Fills a buffer with a prefix string and multiple copies of another.
///
/// \param prefix Prefix for the output string.
/// \param rep String to be repeated until the output buffer is full.
/// \param buffer Output buffer.
/// \param bufsize Size of the output buffer.
static void
fill_buffer(const char* prefix, const char* rep, char* buffer,
            const size_t bufsize)
{
    char* ptr = stpncpy(buffer, prefix, bufsize);
    while (ptr < buffer + bufsize) {
        ptr = stpncpy(ptr, rep, bufsize - (ptr - buffer));
    }
    buffer[bufsize - 1] = '\0';
}
Beispiel #4
0
void assert_failed(const char* msg, const char* location, int line){
  char* p = buffer;
  p = stpncpy(p, msg, 32);
  p = stpcpy(p, (const char*)" in ");
  p = stpncpy(p, location, 32);
  p = stpcpy(p, (const char*)" line ");
  p = stpcpy(p, itoa(line, 10));
  getProgramVector()->message = buffer;
  if(getProgramVector()->programStatus != NULL)
    getProgramVector()->programStatus(AUDIO_ERROR_STATUS);
}
int main() {
  char test[100]="blubber";

  assert(mempcpy(test,"foo",3)==test+3 && !strcmp(test,"foobber"));
  assert(mempcpy(test,"foo",4)==test+4 && !strcmp(test,"foo"));

  assert(stpcpy(test,"foo")==test+3 && !strcmp(test,"foo"));

  stpncpy(test,"bar",2);
  assert(stpncpy(test,"bar",2)==test+2 && !strcmp(test,"bao"));
  assert(stpncpy(test,"xyz",6)==test+3 && !memcmp(test,"xyz\0\0\0",6));

  return 0;
}
char*
HttpHeaders::formatHeaders(char* buffer) const
{
  char* bufLastPos = buffer;

  for (const auto& header : m_headers) {
    bufLastPos = stpncpy(bufLastPos, header.m_key.c_str(), header.m_key.size());
    bufLastPos = stpncpy(bufLastPos, ": ", 2);
    bufLastPos = stpncpy(bufLastPos, header.m_value.c_str(), header.m_value.size());
    bufLastPos = stpncpy(bufLastPos, "\r\n", 2);
  }

  return bufLastPos;
}
void concatenation (char * destination, size_t taille_maxi, ...)
{
	va_list arguments;
	char *	source;
	char *	retour;
	size_t	taille_chaine;

	retour = destination;
	taille_chaine = 0;

	va_start(arguments, taille_maxi);

	while (1) {
		source = va_arg(arguments, char *);
		if (source == NULL)
			/* fin des arguments */
			break;
		retour = stpncpy(retour, source, taille_maxi - taille_chaine);
		taille_chaine = retour - destination;
		if (taille_chaine == taille_maxi) {
			/* Ecraser le dernier caractere par un zero */
			retour --; 
			* retour = '\0';
			break;
		}
	}
	va_end(arguments);
}
Beispiel #8
0
int main(void)
{
	char dst[8];
	char *src = "abcdef";

	if (stpncpy(dst, src, 5) != dst + 5)
		return 1;
	if (stpncpy(dst, src, 6) != dst + 6)
		return 1;
	if (stpncpy(dst, src, 7) != dst + 6)
		return 1;
	if (stpncpy(dst, src, 8) != dst + 6)
		return 1;
	
	return 0;
}
dl_status dl_start(dl_t self) {
  // Assume usbmuxd supports proto_version 1.  If not then we'd need to
  // send a binary listen request, check for failure, then retry this:
  plist_t dict = plist_new_dict();
  plist_dict_insert_item(dict, "ClientVersionString", plist_new_string(
        "device_listener"));
  plist_dict_insert_item(dict, "MessageType", plist_new_string("Listen"));
  plist_dict_insert_item(dict, "ProgName", plist_new_string("libusbmuxd"));
  char *xml = NULL;
  uint32_t xml_length = 0;
  plist_to_xml(dict, &xml, &xml_length);
  plist_free(dict);

  size_t length = 16 + xml_length;
  char *packet = (char *)calloc(length, sizeof(char));
  if (!packet) {
    return DL_ERROR;
  }
  char *tail = packet;
  tail = dl_sprintf_uint32(tail, length);
  tail = dl_sprintf_uint32(tail, 1); // version: 1
  tail = dl_sprintf_uint32(tail, TYPE_PLIST); // type: plist
  tail = dl_sprintf_uint32(tail, 1); // tag: 1
  tail = stpncpy(tail, xml, xml_length);
  free(xml);

  dl_status ret = self->send_packet(self, packet, length);
  free(packet);
  return ret;
}
Beispiel #10
0
void daemon_set_title (const char* fmt, ...)
{
	char title [64];
	int i, tlen;
	va_list ap;

	va_start(ap, fmt);
	vsnprintf (title, sizeof (title) - 1, fmt, ap);
	va_end (ap);

	tlen = strlen (title) + 1;
	if (arg_end - arg_start < tlen && env_start == arg_end) {
		char *env_end = env_start;
		for(i=0; environ[i]; i++) {
			if(env_end == environ[i]) {
				env_end = environ[i] + strlen (environ[i]) + 1;
				environ[i] = strdup(environ[i]);
			} else
				break;
		}
		arg_end = env_end;
		env_start = NULL;
	}

	i = arg_end - arg_start;
	if (tlen == i) {
		strcpy (arg_start, title);
	} else if (tlen < i) {
		strcpy (arg_start, title);
		memset (arg_start + tlen, 0, i - tlen);
	} else {
		stpncpy(arg_start, title, i - 1)[0] = '\0';
	}
}
Beispiel #11
0
static TACommandVerdict stpncpy_cmd(TAThread thread, TAInputStream stream)
{
    char* s1;
    char* s2;
    size_t n;
    char* res;

    // Prepare
    s1 = (char*)readPointer(&stream);
    s2 = (char*)readPointer(&stream);
    n = readSize(&stream);

    START_TARGET_OPERATION(thread);

    // Execute
    res = stpncpy(s1, s2, n);

    END_TARGET_OPERATION(thread);

    // Response
    writePointer(thread, res);
    sendResponse(thread);

    return taDefaultVerdict;
}
Beispiel #12
0
size_t
actlstr(char *buf, size_t n, char *ch, struct mixer *mx) {
	size_t ret;
	char *status;
	struct mixer_ctl *ctl;

	if (!(ctl = mixer_get_ctl_by_name(mx, ch))) {
		mixer_close(mx);
		die("couldn't find mixer ctl '%s'\n", ch);
	}

	switch (mixer_ctl_get_type(ctl)) {
	case MIXER_CTL_TYPE_INT:
		if ((ret = snprintf(buf, n, "%d%%",
				mixer_ctl_get_percent(ctl, 0))) > n)
			ret = n;
		break;
	case MIXER_CTL_TYPE_BOOL:
		status = mixer_ctl_get_value(ctl, 0) ? "On" : "Off";
		ret = stpncpy(buf, status, n) - buf;
		break;
	default:
		mixer_close(mx);
		die("unsupported ctl type '%s'\n",
			mixer_ctl_get_type_string(ctl));
	};

	return ret;
}
Beispiel #13
0
void debugMessage(const char* msg, float a){
  char* p = buffer;
  p = stpncpy(p, msg, 48);
  p = stpcpy(p, (const char*)" ");
  p = stpcpy(p, ftoa(a, 10));
  getProgramVector()->message = buffer;
}
Beispiel #14
0
/* Destructively modify PATH to contain no more than 8 non-`.'
   characters, optionally followed by a `.' and a filenname extension
   of 3 characters or fewer. */
static char *
path_truncate (char *path)
{
  char *p, *beg = path;			/* following final '/' */
  for (p = path; *p != '\0'; ++p)
    {
      if (ISSLASH (*p))
        beg = 1+ p;
    }

  char *end = strchr (beg, '.');	/* first period */
  char *ext = strrchr (beg, '.');	/* last period */

  size_t len = (size_t) (end - beg);	/* length of filename element */
  if (len > 8)
    end = beg + 8;

  if (ext == NULL)
    {
      *end = '\0';
    }
  else if (ext != end)
    {
      stpncpy (end, ext, 4);
    }

  return path;
}
Beispiel #15
0
void debugMessage(const char* msg, int a, int b){
  char* p = buffer;
  p = stpncpy(p, msg, 32);
  p = stpcpy(p, (const char*)" ");
  p = stpcpy(p, itoa(a, 10));
  p = stpcpy(p, (const char*)" ");
  p = stpcpy(p, itoa(b, 10));
  getProgramVector()->message = buffer;
}
Beispiel #16
0
static char *format_token(char *outbuf, size_t outbuf_len, tfs_token_t *token) {
    char *p = outbuf;
    char *match = tfs_match_token(posix_tokens, sizeof(posix_tokens)/sizeof(posix_tokens[0]), token);
    if (match) {
        p = stpncpy(p, match, outbuf_len);
    } else {
        p = NULL;
    }
    return p;
}
Beispiel #17
0
int main(int argc, char* argv[]) {
    const char* benchmarks = "tst/benchmarks/";
    putchar('\n');
    DIR* d = opendir(benchmarks);
    if (d == NULL) {
        perror(benchmarks);
        exit(errno);
    }
    struct dirent* ent = readdir(d);
    while (ent) {
        char full_path[300];
        char* start = stpncpy(full_path, benchmarks, 50);
        char* name = ent->d_name;
        start = stpncpy(start, name, 250);
        run_benchmark(full_path, name);
        ent = readdir(d);
    }
    closedir(d);
    return 0;
}
// try to extract dir information
static int gridftp_readdir_parser(const std::string& line, struct dirent* entry)
{
    memset(entry->d_name, 0, sizeof(entry->d_name));
    g_strlcpy(entry->d_name, line.c_str(), sizeof(entry->d_name));
    char *p = stpncpy(entry->d_name, line.c_str(), sizeof(entry->d_name));
    // clear new line madness
    do {
        *p = '\0';
        --p;
    } while (p >= entry->d_name && isspace(*p));
    return 0;
}
Beispiel #19
0
static char *renamed_filename(struct afb_arg argfile)
{
    char *result;
    const char *e = strrchr(argfile.path, '/');
    if (e == NULL)
        result = strdup(argfile.value);
    else {
        result = malloc((++e - argfile.path) + strlen(argfile.value) + 1);
        if (result != NULL)
            strcpy(stpncpy(result, argfile.path, e - argfile.path), argfile.value);
    }
    return result;
}
Beispiel #20
0
 void setAddress(const char* addr){
   if(getPrefixLength() > 0 && types != address){
     // save old types
     int len = getPrefixLength();
     char saved[len];
     stpncpy(saved, (char*)types, len);
     types = address + writeOscString(address, addr);
     data = types + writeOscString(types, saved);
   }else{
     types = address + writeOscString(address, addr);
     data = types;
   }
 }
Beispiel #21
0
int main(int argc, char* argv[])
{
    char **list_p;
    int list_size = argc;
    int str_len = 80;

    if ((list_p=malloc(sizeof(char *)*list_size))==NULL) { //10 string list
        //malloc failed
    } else {
        int ret = OK;
        int i = 0;

        for (; i<list_size; i++) {
            list_p[i] = malloc(sizeof(char)*str_len); //including \0
            if (list_p[i]==NULL) {
                //malloc failed
                break;
            }
        }
        
        if (i<list_size) {
            /* clean up */
            for (i-1; i>=0; i--) {
                free(list_p[i]);
            }
        } else {
            char *end_p = NULL;
            for (i=0; i<list_size; i++) {
                //end_p = strncpy(list_p[i], argv[i], str_len);
                end_p = stpncpy(list_p[i], argv[i], str_len);
                printf("end_p's int value is %d\n", *end_p);
                printf("strnlen list_p[i] is %ld\n", strnlen(list_p[i], str_len));
                list_p[i][str_len-1] = '\0';
            }

            for (i=0; i<list_size; i++) {
                printf("[%d]: %s, ", i, list_p[i]);
            }
            printf("\n");


            /* clean up */
            for (; i>0; i--) { 
                free(list_p[i-1]); 
            }
        }
        free(list_p);
    }
}
void chown_dir_contents(const char *dir_path, uid_t uid, gid_t gid) {
  DIR *dp;
  struct dirent *ep;

  char *path_tmp = malloc(strlen(dir_path) + NAME_MAX + 2);
  if (path_tmp == NULL) {
    return;
  }

  char *buf = stpncpy(path_tmp, dir_path, strlen(dir_path));
  *buf++ = '/';
     
  dp = opendir(dir_path);
  if (dp != NULL) {
    while (ep = readdir(dp)) {
      stpncpy(buf, ep->d_name, strlen(ep->d_name));
      buf[strlen(ep->d_name)] = '\0';
      change_owner(path_tmp, uid, gid);
    }
    closedir(dp);
  }

  free(path_tmp);
}
Beispiel #23
0
static int
udev_device_get_devid(struct udev_device *dev, char *bufptr, size_t buflen)
{
	struct udev_list_entry *entry;
	const char *bus;
	char devbyid[MAXPATHLEN];

	/* The bus based by-id path is preferred */
	bus = udev_device_get_property_value(dev, "ID_BUS");

	if (bus == NULL) {
		const char *dm_uuid;

		/*
		 * For multipath nodes use the persistent uuid based identifier
		 *
		 * Example: 'dm-uuid-mpath-35000c5006304de3f'
		 */
		dm_uuid = udev_device_get_property_value(dev, "DM_UUID");
		if (dm_uuid != NULL) {
			(void) snprintf(bufptr, buflen, "dm-uuid-%s", dm_uuid);
			return (0);
		}
		return (ENODATA);
	}

	/*
	 * locate the bus specific by-id link
	 *
	 * Example: 'scsi-MG03SCA300_350000494a8cb3d67-part1'
	 */
	(void) snprintf(devbyid, sizeof (devbyid), "%s%s-", DEV_BYID_PATH, bus);
	entry = udev_device_get_devlinks_list_entry(dev);
	while (entry != NULL) {
		const char *name;

		name = udev_list_entry_get_name(entry);
		if (strncmp(name, devbyid, strlen(devbyid)) == 0) {
			name += strlen(DEV_BYID_PATH);
			(void) stpncpy(bufptr, name, buflen);
			return (0);
		}
		entry = udev_list_entry_get_next(entry);
	}

	return (ENODATA);
}
char*
HttpResponse::formatResponse(char* buffer) const
{
  char* bufLastPos = buffer;

  bufLastPos = stpncpy(bufLastPos, "HTTP/", 5);
  bufLastPos = stpncpy(bufLastPos, m_version.c_str(), m_version.size());
  bufLastPos = stpncpy(bufLastPos, " ", 1);
  bufLastPos = stpncpy(bufLastPos, m_statusCode.c_str(), m_statusCode.size());
  bufLastPos = stpncpy(bufLastPos, " ", 1);
  bufLastPos = stpncpy(bufLastPos, m_statusMsg.c_str(), m_statusMsg.size());
  bufLastPos = stpncpy(bufLastPos, "\r\n", 2);

  bufLastPos = HttpHeaders::formatHeaders(bufLastPos);
  bufLastPos = stpncpy(bufLastPos, "\r\n", 2);

  return bufLastPos;
}
Beispiel #25
0
static int
get_ifconfig_info(struct net_desc *devs)
{
	char *buf_in;
	char *buf_tmp;
	const char **ignore;
	char *buf;
	char *tmp;
	int textsize;
	int i;

	/* Get ifconfig information */
	textsize = collect(T_OUTPUT, &buf_in, "/sbin/ifconfig -l 2>/dev/null");
	if (textsize < 0) {
		if (logfp)
			(void)fprintf(logfp,
			    "Aborting: Could not run ifconfig.\n");
		(void)fprintf(stderr, "Could not run ifconfig.");
		exit(1);
	}

	buf = malloc (STRSIZE * sizeof(char));
	for (i = 0, buf_tmp = buf_in; strlen(buf_tmp) > 0 && buf_tmp < buf_in +
	     strlen(buf_in);) {
		tmp = stpncpy(buf, buf_tmp, strcspn(buf_tmp," \n"));
		*tmp='\0';
		buf_tmp += (strcspn(buf_tmp, " \n") + 1) * sizeof(char);

		/* Skip ignored interfaces */
		for (ignore = ignored_if_names; *ignore != NULL; ignore++) {
			size_t len = strlen(*ignore);
			if (strncmp(buf, *ignore, len) == 0 &&
			    isdigit((unsigned char)buf[len]))
				break;
		}
		if (*ignore != NULL)
			continue;

		strlcpy (devs[i].if_dev, buf, STRSIZE);
		i++;
	}
	strcpy(devs[i].if_dev, "\0");

	free(buf);
	free(buf_in);
	return i;
}
Beispiel #26
0
int
main(int argc, char *argv[])
{
	char b[10];
	int len = atoi(argv[1]);
#if __GNUC_PREREQ__(4, 8)
	char *q = stpncpy(b, "1020202020202", len);

	if (q - b != len)
		abort();
#else
	// gcc-4.5 lacks __builtin___stpncpy_chk, lose.
	(void)strncpy(b, "1020202020202", len);
#endif

	(void)printf("%*.*s\n", len, len, b);
	return 0;
}
Beispiel #27
0
/**
 * Mount a cgroup controller at the requested mount point and create
 * a hierarchy for the Hadoop NodeManager to manage.
 * pair: a key-value pair of the form "controller=mount-path"
 * hierarchy: the top directory of the hierarchy for the NM
 */
int mount_cgroup(const char *pair, const char *hierarchy) {
#ifndef __linux
  fprintf(LOGFILE, "Failed to mount cgroup controller, not supported\n");
  return -1;
#else
  char *controller = malloc(strlen(pair));
  char *mount_path = malloc(strlen(pair));
  char hier_path[PATH_MAX];
  int result = 0;

  if (get_kv_key(pair, controller, strlen(pair)) < 0 ||
      get_kv_value(pair, mount_path, strlen(pair)) < 0) {
    fprintf(LOGFILE, "Failed to mount cgroup controller; invalid option: %s\n",
              pair);
    result = -1; 
  } else {
    if (mount("none", mount_path, "cgroup", 0, controller) == 0) {
      char *buf = stpncpy(hier_path, mount_path, strlen(mount_path));
      *buf++ = '/';
      snprintf(buf, PATH_MAX - (buf - hier_path), "%s", hierarchy);

      // create hierarchy as 0750 and chown to Hadoop NM user
      const mode_t perms = S_IRWXU | S_IRGRP | S_IXGRP;
      if (mkdirs(hier_path, perms) == 0) {
        change_owner(hier_path, nm_uid, nm_gid);
        chown_dir_contents(hier_path, nm_uid, nm_gid);
      }
    } else {
      fprintf(LOGFILE, "Failed to mount cgroup controller %s at %s - %s\n",
                controller, mount_path, strerror(errno));
      // if controller is already mounted, don't stop trying to mount others
      if (errno != EBUSY) {
        result = -1;
      }
    }
  }

  free(controller);
  free(mount_path);

  return result;
#endif
}
Beispiel #28
0
void set_process_title(int argc,char* argv[],const char* fmt, ...)
{
    char *arg_start = argv[0];
    char *arg_end = argv[argc-1] + strlen(argv[argc-1])+1;

    char title [256] ={0};
    va_list ap;
    va_start(ap, fmt);
    vsnprintf (title, sizeof (title), fmt, ap);
    va_end (ap);

    int i=0;
    int tlen = strlen (title) + 1;
    if (arg_end - arg_start < tlen && environ[0] == arg_end)
    {
        char *env_next = environ[0];
        for(i=0; environ[i]!=NULL; i++)
        {
            if(env_next == environ[i])
            {
                env_next = environ[i] + strlen (environ[i]) + 1;
                environ[i] = strdup(environ[i]);
            }
            else
            {
                break;
            }
        }
        arg_end = env_next;

    }

    i = arg_end - arg_start;
    if (tlen <= i)
    {
        strcpy(arg_start, title);
        memset(arg_start + tlen, 0, i - tlen);
    }
    else
    {
        stpncpy(arg_start, title, i - 1)[0] = '\0';
    }
}
Beispiel #29
0
static char * canonDir(rpmstrPool pool, rpmsid dirNameId)
{
    const char * dirName = rpmstrPoolStr(pool, dirNameId);
    size_t cdnl = rpmstrPoolStrlen(pool, dirNameId);;
    char *cdnbuf = NULL;

    if (*dirName == '/') {
	cdnbuf = xstrdup(dirName);
	cdnbuf = rpmCleanPath(cdnbuf);
	/* leave my trailing slashes along you b**** */
	if (cdnl > 1)
	    cdnbuf = rstrcat(&cdnbuf, "/");
    } else {
	/* Using realpath on the arg isn't correct if the arg is a symlink,
	 * especially if the symlink is a dangling link.  What we 
	 * do instead is use realpath() on `.' and then append arg to
	 * the result.
	 */

	/* if the current directory doesn't exist, we might fail. 
	   oh well. likewise if it's too long.  */

	/* XXX we should let realpath() allocate if it can */
	cdnbuf = xmalloc(PATH_MAX);
	cdnbuf[0] = '\0';
	if (realpath(".", cdnbuf) != NULL) {
	    char *end = cdnbuf + strlen(cdnbuf);
	    if (end[-1] != '/')	*end++ = '/';
	    end = stpncpy(end, dirName, PATH_MAX - (end - cdnbuf));
	    *end = '\0';
	    (void)rpmCleanPath(cdnbuf); /* XXX possible /../ from concatenation */
	    end = cdnbuf + strlen(cdnbuf);
	    if (end[-1] != '/')	*end++ = '/';
	    *end = '\0';
	} else {
	    cdnbuf = _free(cdnbuf);
	}
    }
    return cdnbuf;
}
Beispiel #30
0
static void
test_stpncpy(const char *s)
{
	char *src, *dst;
	size_t size, len, bufsize, x;
	int i, j;

	size = strlen(s) + 1;
	for (i = 0; i <= 1; i++) {
		for (j = 0; j <= 1; j++) {
			for (bufsize = 0; bufsize <= size + 10; bufsize++) {
				src = makebuf(size, i);
				memcpy(src, s, size);
				dst = makebuf(bufsize, j);
				memset(dst, 'X', bufsize);
				len = (bufsize < size) ? bufsize : size - 1;
				assert(stpncpy(dst, src, bufsize) == dst+len);
				assert(memcmp(src, dst, len) == 0);
				for (x = len; x < bufsize; x++)
					assert(dst[x] == '\0');
			}
		}
	}
}