diff options
| -rw-r--r-- | LICENSE | 6 | ||||
| -rw-r--r-- | Makefile.am | 11 | ||||
| -rw-r--r-- | NEWS | 5 | ||||
| -rw-r--r-- | configure.ac | 2 | ||||
| -rw-r--r-- | kasetkey/kasetkey.c | 221 | ||||
| -rw-r--r-- | portable/strlcat.c | 42 | ||||
| -rw-r--r-- | portable/strlcpy.c | 40 | ||||
| -rw-r--r-- | system.h | 6 | ||||
| -rw-r--r-- | tests/TESTS | 2 | ||||
| -rw-r--r-- | tests/portable/strlcat-t.c | 77 | ||||
| -rw-r--r-- | tests/portable/strlcat.c | 2 | ||||
| -rw-r--r-- | tests/portable/strlcpy-t.c | 72 | ||||
| -rw-r--r-- | tests/portable/strlcpy.c | 2 | 
13 files changed, 426 insertions, 62 deletions
| @@ -50,10 +50,12 @@ The file portable/snprintf.c is released under the following license:    It may be used for any purpose as long as this notice remains intact    on all source code distributions -The files portable/asprintf.c, portable/dummy.c and util/concat.c have -been placed in the public domain by their author. +The files portable/asprintf.c, portable/dummy.c, portable/strlcat.c, +portable/strlcpy.c, and util/concat.c have been placed in the public +domain by their author.  The files tests/libtest.c, tests/libtest.h, tests/portable/snprintf-t.c, +tests/portable/strlcat-t.c, tests/portable/strlcpy-t.c,  tests/util/concat-t.c, tests/util/messages-t.c, tests/util/xmalloc-t, and  tests/util/xmalloc.c are released under the following copyright and  license: diff --git a/Makefile.am b/Makefile.am index ba1ff21..fe0a812 100644 --- a/Makefile.am +++ b/Makefile.am @@ -121,7 +121,8 @@ clean-local:  # The bits below are for the test suite, not for the main package.  check_PROGRAMS = tests/runtests tests/portable/asprintf-t \ -	tests/portable/snprintf-t tests/util/concat-t tests/util/messages-t \ +	tests/portable/snprintf-t tests/portable/strlcat-t \ +	tests/portable/strlcpy-t tests/util/concat-t tests/util/messages-t \  	tests/util/xmalloc  check_LIBRARIES = tests/libtest.a  tests_libtest_a_SOURCES = tests/libtest.c tests/libtest.h @@ -135,6 +136,14 @@ tests_portable_snprintf_t_SOURCES = tests/portable/snprintf-t.c \          tests/portable/snprintf.c  tests_portable_snprintf_t_LDADD = tests/libtest.a util/libutil.a \  	portable/libportable.a +tests_portable_strlcat_t_SOURCES = tests/portable/strlcat-t.c \ +        tests/portable/strlcat.c +tests_portable_strlcat_t_LDADD = tests/libtest.a util/libutil.a \ +	portable/libportable.a +tests_portable_strlcpy_t_SOURCES = tests/portable/strlcpy-t.c \ +        tests/portable/strlcpy.c +tests_portable_strlcpy_t_LDADD = tests/libtest.a util/libutil.a \ +	portable/libportable.a  tests_util_concat_t_LDADD = tests/libtest.a util/libutil.a \  	portable/libportable.a  tests_util_messages_t_LDADD = tests/libtest.a util/libutil.a \ @@ -2,6 +2,11 @@  wallet 0.9 (unreleased) +    Add support for enabling and disabling principals (clearing or setting +    the NOTGS flag) and examining principals to kasetkey.  This +    functionality isn't used by wallet (and probably won't be) but is +    convenient for other users of kasetkey such as kadmin-remctl. +      Report the correct error message when addprinc fails while creating a      keytab object. diff --git a/configure.ac b/configure.ac index 7530691..4f722fc 100644 --- a/configure.ac +++ b/configure.ac @@ -26,7 +26,7 @@ RRA_C_GNU_VAMACROS  AC_CHECK_TYPES([long long])  RRA_FUNC_SNPRINTF  AC_CHECK_FUNCS([setrlimit]) -AC_REPLACE_FUNCS([asprintf]) +AC_REPLACE_FUNCS([asprintf strlcat strlcpy])  AC_ARG_WITH([wallet-server],      [AC_HELP_STRING([--with-wallet-server=HOST], [Default wallet server])], diff --git a/kasetkey/kasetkey.c b/kasetkey/kasetkey.c index 19c1ffd..8bcc950 100644 --- a/kasetkey/kasetkey.c +++ b/kasetkey/kasetkey.c @@ -1,19 +1,19 @@ -/*  $Id$ -** -**  Create or change a principal and/or generate a srvtab. -** -**  Written by Roland Schemers <schemers@stanford.edu> -**  Updated by Russ Allbery <rra@stanford.edu> -**  Updated again by AAU, Anton Ushakov  <antonu@stanford.edu> -**  Copyright 1994, 1998, 1999, 2000, 2006, 2007 -**      Board of Trustees, Leland Stanford Jr. University -** -**  See LICENSE for licensing terms. -** -**  Sets the key of a principal in the AFS kaserver given a srvtab.  This -**  program is now used for synchronization of K5 and K4 and nothing else. -**  It will no longer be used once K4 is retired. -*/ +/* $Id$ + * + * Create or change a principal and/or generate a srvtab. + * + * Sets the key of a principal in the AFS kaserver given a srvtab, enables or + * disables a principal, or displays information about a principal in an AFS + * kaserver. + * + * Written by Roland Schemers <schemers@stanford.edu> + * Updated by Russ Allbery <rra@stanford.edu> + * Updated again by Anton Ushakov  <antonu@stanford.edu> + * Copyright 1994, 1998, 1999, 2000, 2006, 2007, 2008 + *     Board of Trustees, Leland Stanford Jr. University + * + * See LICENSE for licensing terms. + */  #include <config.h> @@ -37,6 +37,8 @@  #include <afs/cellconfig.h>  #include <ubik.h> +#include <util/util.h> +  /* Normally set by the AFS libraries. */  #ifndef SNAME_SZ  # define SNAME_SZ       40 @@ -44,9 +46,11 @@  # define REALM_SZ       40  #endif -/* AFS currently doesn't prototype this function.  Cheat on the first argument -   since it actually takes a function with a completely variable argument -   list. */ +/* + * AFS currently doesn't prototype this function.  Cheat on the first argument + * since it actually takes a function with a completely variable argument + * list. + */  #if !HAVE_DECL_UBIK_CALL  afs_int32 ubik_Call(void *, struct ubik_client *, afs_int32, ...);  #endif @@ -60,12 +64,15 @@ struct config {      int debug;                  /* Whether to enable debugging. */      int init;                   /* Keyfile initialization. */      int random;                 /* Randomize the key. */ +    int tgs;                    /* Enable the principal. */ +    int notgs;                  /* Disable the princial. */      char *keyfile;              /* Name of srvtab to use. */      char *admin;                /* Name of ADMIN user to use. */      char *password;             /* Password to use. */      char *srvtab;               /* srvtab file to generate. */ -    char *service;              /* Service principal to create. */ -    char *delete;               /* Service principal to delete. */ +    char *service;              /* Principal to create/enable. */ +    char *delete;               /* Principal to delete. */ +    char *examine;              /* Principal to examine. */      char *k5srvtab;             /* K5 converted srvtab to read for key. */  }; @@ -75,14 +82,17 @@ Usage: %s [options]\n\    -a adminuser     Admin user\n\    -c k5srvtab      Use the key from the given srvtab (for sync w/ K5)\n\    -D service       Name of service to delete\n\ -  -d               turn on debugging\n\ +  -d               Turn on debugging\n\ +  -e principal     Examine the given principal\n\    -f srvtab        Name of srvtab file to create\n\    -h               This help\n\    -i               Initialize DES key file\n\    -k keyfile       File containing srvtab for admin user\n\ +  -n               Set the principal NOTGS\n\    -p password      Use given password to create key\n\    -r               Use random key\n\    -s service       Name of service to create\n\ +  -t               Set the principal TGS\n\    -v               Print version\n\  \n\  To create a srvtab for rcmd.slapshot and be prompted for the admin\n\ @@ -101,40 +111,6 @@ and then create a srvtab for rcmd.slapshot with:\n\  \n"; -/* Report a fatal error. */ -static void -die(const char *format, ...) -{ -    va_list args; - -    if (program != NULL) -        fprintf(stderr, "%s: ", program); -    va_start(args, format); -    vfprintf(stderr, format, args); -    va_end(args); -    fprintf(stderr, "\n"); -    exit(1); -} - - -/* Report a fatal error, including strerror information. */ -static void -sysdie(const char *format, ...) -{ -    int oerrno; -    va_list args; - -    oerrno = errno; -    if (program != NULL) -        fprintf(stderr, "%s: ", program); -    va_start(args, format); -    vfprintf(stderr, format, args); -    va_end(args); -    fprintf(stderr, ": %s\n", strerror(oerrno)); -    exit(1); -} - -  /*   * Print out the usage message and then exit with the status given as the only   * argument.  If status is zero, the message is printed to standard output; @@ -282,7 +258,9 @@ authenticate(struct config *config, struct ktc_token *token)  } -/* Delete a principal out of the AFS kaserver. */ +/* + * Delete a principal out of the AFS kaserver. + */  static void  delete_principal(struct config *config)  { @@ -314,6 +292,122 @@ delete_principal(struct config *config)  /* + * Format a date.  The output format expects ctime-style date formatting, so + * we use that.  Takes a buffer into which to put the date.  There will be a + * trailing newline. + */ +static void +format_date(char *buffer, size_t size, time_t date) +{ +    if (date == (time_t) NEVERDATE) +        strlcpy(buffer, "never\n", size); +    else +        strlcpy(buffer, ctime(&date), size); +} + + +/* + * Enable or disable a principal in the AFS kaserver (by setting or clearing + * the NOTGS flag).  The second argument says to enable if it's true, disable + * otherwise. + */ +static void +enable_principal(struct config *config, int enable) +{ +    struct ktc_token token; +    struct ubik_client *conn; +    struct kaentryinfo entry; +    char name[MAXKTCNAMELEN]; +    char inst[MAXKTCNAMELEN]; +    char cell[MAXKTCNAMELEN]; +    long code; + +    /* Make connection to AuthServer. */ +    authenticate(config, &token); +    parse_principal(config, config->delete, name, inst, cell); +    code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, &token, &conn); +    if (config->debug) +        printf("ka_AuthServerConn %s %ld\n", cell, code); +    if (code != 0) +        die("can't make connection to auth server"); + +    /* Retrieve the principal information. */ +    code = ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION, +                     &entry); +    if (config->debug) +        printf("ubik_Call KAM_GetEntry %ld\n", code); +    if (code != 0) { +        if (code == KANOENT) +            die("no such entry in the database"); +        else +            die("can't retrieve principal information"); +    } + +    /* Set the flags. */ +    if (enable) +        entry.flags &= ~KAFNOTGS; +    else +        entry.flags |= KAFNOTGS; +    code = ubik_Call(KAM_SetFields, conn, 0, name, inst, entry.flags, 0, 0, +                     -1, 0, 0); +    if (config->debug) +        printf("ubik_Call KAM_SetFields %ld\n", code); +    if (code != 0) +        die("can't %s principal", enable ? "enable" : "disable"); +    code = ubik_ClientDestroy(conn); +    exit(0); +} + + +/* + * Examine a principal.  The output format is compatible with the old Stanford + * Kerberos v4 kadmin, which may be compatible with Kerberos v4 kadmin in + * general (I haven't checked). + */ +static void +examine_principal(struct config *config) +{ +    struct ktc_token token; +    struct ubik_client *conn; +    struct kaentryinfo entry; +    char name[MAXKTCNAMELEN]; +    char inst[MAXKTCNAMELEN]; +    char cell[MAXKTCNAMELEN]; +    long code; +    char edate[64], cdate[64], mdate[64]; + +    /* Make connection to AuthServer. */ +    authenticate(config, &token); +    parse_principal(config, config->delete, name, inst, cell); +    code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, &token, &conn); +    if (config->debug) +        printf("ka_AuthServerConn %s %ld\n", cell, code); +    if (code != 0) +        die("can't make connection to auth server"); + +    /* Retrieve and format the entry. */ +    code = ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION, +                     &entry); +    if (config->debug) +        printf("ubik_Call KAM_GetEntry %ld\n", code); +    if (code != 0) +        die("can't retrieve current flags"); +    format_date(edate, sizeof(edate), entry.user_expiration); +    format_date(mdate, sizeof(cdate), entry.modification_time); +    format_date(cdate, sizeof(mdate), entry.change_password_time); +    printf("status: %s\n", (entry.flags & KAFNOTGS) ? "disabled" : "enabled"); +    printf("account expiration: %s", edate); +    printf("password last changed: %s", cdate); +    printf("modification time: %s", mdate); +    printf("modified by: %s%s%s\n", entry.modification_user.name, +           (entry.modification_user.instance[0] != '\0') ? "." : "", +           entry.modification_user.instance); +    code = ubik_ClientDestroy(conn); +    exit(0); +} + + +/*   * Create a new principal in the AFS kaserver (deleting it and recreating it   * if it already exists) with either the indicated key or with a random key,   * and then write out a srvtab for that principal.  Also supported is reading @@ -447,12 +541,15 @@ main(int argc, char *argv[])          case 'c': config.k5srvtab = optarg;     break;          case 'D': config.delete = optarg;       break;          case 'd': config.debug = 1;             break; +        case 'e': config.examine = optarg;      break;          case 'f': config.srvtab = optarg;       break;          case 'i': config.init = 1;              break;          case 'k': config.keyfile = optarg;      break; +        case 'n': config.notgs = 1;             break;          case 'p': config.password = optarg;     break;          case 'r': config.random = 1;            break;          case 's': config.service = optarg;      break; +        case 't': config.tgs = 1;               break;          /* Usage doesn't return. */          case 'h': @@ -468,10 +565,18 @@ main(int argc, char *argv[])      /* Take the right action. */      if (config.random && config.k5srvtab)          usage(1); +    if (config.notgs && config.tgs) +        die("cannot set principal both TGS and NOTGS at the same time"); +    if ((config.notgs || config.tgs) && config.service == NULL) +        die("must specify a principal with -s");      if (config.debug) -        fprintf(stdout,"cell: %s\n", config.local_cell); +        fprintf(stdout, "cell: %s\n", config.local_cell);      if (config.init)          initialize_admin_srvtab(&config); +    else if (config.tgs || config.notgs) +        enable_principal(&config, config.tgs); +    else if (config.examine != NULL) +        examine_principal(&config);      else if (config.service != NULL)          generate_srvtab(&config);      else if (config.delete != NULL) diff --git a/portable/strlcat.c b/portable/strlcat.c new file mode 100644 index 0000000..971a348 --- /dev/null +++ b/portable/strlcat.c @@ -0,0 +1,42 @@ +/* $Id$ + * + * Replacement for a missing strlcat. + * + * Provides the same functionality as the *BSD function strlcat, originally + * developed by Todd Miller and Theo de Raadt.  strlcat works similarly to + * strncat, except simpler.  The result is always nul-terminated even if the + * source string is longer than the space remaining in the destination string, + * and the total space required is returned.  The third argument is the total + * space available in the destination buffer, not just the amount of space + * remaining. + * + * Written by Russ Allbery <rra@stanford.edu> + * This work is hereby placed in the public domain by its author. + */ + +#include <config.h> +#include <system.h> + +/* + * If we're running the test suite, rename strlcat to avoid conflicts with + * the system version. + */ +#if TESTING +# define strlcat test_strlcat +size_t test_strlcat(char *, const char *, size_t); +#endif + +size_t +strlcat(char *dst, const char *src, size_t size) +{ +    size_t used, length, copy; + +    used = strlen(dst); +    length = strlen(src); +    if (size > 0 && used < size - 1) { +        copy = (length >= size - used) ? size - used - 1 : length; +        memcpy(dst + used, src, copy); +        dst[used + copy] = '\0'; +    } +    return used + length; +} diff --git a/portable/strlcpy.c b/portable/strlcpy.c new file mode 100644 index 0000000..1dd49a3 --- /dev/null +++ b/portable/strlcpy.c @@ -0,0 +1,40 @@ +/* $Id$ + * + * Replacement for a missing strlcpy. + * + * Provides the same functionality as the *BSD function strlcpy, originally + * developed by Todd Miller and Theo de Raadt.  strlcpy works similarly to + * strncpy, except saner and simpler.  The result is always nul-terminated + * even if the source string is longer than the destination string, and the + * total space required is returned.  The destination string is not nul-filled + * like strncpy does, just nul-terminated. + * + * Written by Russ Allbery <rra@stanford.edu> + * This work is hereby placed in the public domain by its author. + */ + +#include <config.h> +#include <system.h> + +/* + * If we're running the test suite, rename strlcpy to avoid conflicts with + * the system version. + */ +#if TESTING +# define strlcpy test_strlcpy +size_t test_strlcpy(char *, const char *, size_t); +#endif + +size_t +strlcpy(char *dst, const char *src, size_t size) +{ +    size_t length, copy; + +    length = strlen(src); +    if (size > 0) { +        copy = (length >= size) ? size - 1 : length; +        memcpy(dst, src, copy); +        dst[copy] = '\0'; +    } +    return length; +} @@ -73,6 +73,12 @@ extern int              snprintf(char *, size_t, const char *, ...)  #if !HAVE_DECL_VSNPRINTF  extern int              vsnprintf(char *, size_t, const char *, va_list);  #endif +#if !HAVE_STRLCAT +extern size_t           strlcat(char *, const char *, size_t); +#endif +#if !HAVE_STRLCPY +extern size_t           strlcpy(char *, const char *, size_t); +#endif  END_DECLS diff --git a/tests/TESTS b/tests/TESTS index 5bae099..4ff4a3b 100644 --- a/tests/TESTS +++ b/tests/TESTS @@ -3,6 +3,8 @@ client/full  client/pod  portable/asprintf  portable/snprintf +portable/strlcat +portable/strlcpy  server/admin  server/backend  server/keytab diff --git a/tests/portable/strlcat-t.c b/tests/portable/strlcat-t.c new file mode 100644 index 0000000..5ad8b6f --- /dev/null +++ b/tests/portable/strlcat-t.c @@ -0,0 +1,77 @@ +/* $Id$ + * + * strlcat test suite. + * + * Copyright (c) 2004, 2005, 2006 + *     by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, + *     2002, 2003 by The Internet Software Consortium and Rich Salz + * + * This code is derived from software contributed to the Internet Software + * Consortium by Rich Salz. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include <config.h> +#include <system.h> + +#include <tests/libtest.h> + +size_t test_strlcat(char *, const char *, size_t); + + +int +main(void) +{ +    char buffer[10] = ""; + +    test_init(27); + +    ok_int(1, 3, test_strlcat(buffer, "foo", sizeof(buffer))); +    ok_string(2, "foo", buffer); +    ok_int(3, 7, test_strlcat(buffer, " bar", sizeof(buffer))); +    ok_string(4, "foo bar", buffer); +    ok_int(5, 9, test_strlcat(buffer, "!!", sizeof(buffer))); +    ok_string(6, "foo bar!!", buffer); +    ok_int(7, 10, test_strlcat(buffer, "!", sizeof(buffer))); +    ok_string(8, "foo bar!!", buffer); +    ok(9, buffer[9] == '\0'); +    buffer[0] = '\0'; +    ok_int(10, 11, test_strlcat(buffer, "hello world", sizeof(buffer))); +    ok_string(11, "hello wor", buffer); +    ok(12, buffer[9] == '\0'); +    buffer[0] = '\0'; +    ok_int(13, 7, test_strlcat(buffer, "sausage", 5)); +    ok_string(14, "saus", buffer); +    ok_int(15, 14, test_strlcat(buffer, "bacon eggs", sizeof(buffer))); +    ok_string(16, "sausbacon", buffer); + +    /* Make sure that with a size of 0, the destination isn't changed. */ +    ok_int(17, 11, test_strlcat(buffer, "!!", 0)); +    ok_string(18, "sausbacon", buffer); + +    /* Now play with empty strings. */ +    ok_int(19, 9, test_strlcat(buffer, "", 0)); +    ok_string(20, "sausbacon", buffer); +    buffer[0] = '\0'; +    ok_int(21, 0, test_strlcat(buffer, "", sizeof(buffer))); +    ok_string(22, "", buffer); +    ok_int(23, 3, test_strlcat(buffer, "foo", 2)); +    ok_string(24, "f", buffer); +    ok(25, buffer[1] == '\0'); +    ok_int(26, 1, test_strlcat(buffer, "", sizeof(buffer))); +    ok(27, buffer[1] == '\0'); + +    return 0; +} diff --git a/tests/portable/strlcat.c b/tests/portable/strlcat.c new file mode 100644 index 0000000..8983bd8 --- /dev/null +++ b/tests/portable/strlcat.c @@ -0,0 +1,2 @@ +#define TESTING 1 +#include <portable/strlcat.c> diff --git a/tests/portable/strlcpy-t.c b/tests/portable/strlcpy-t.c new file mode 100644 index 0000000..6427374 --- /dev/null +++ b/tests/portable/strlcpy-t.c @@ -0,0 +1,72 @@ +/* $Id$ + * + * strlcpy test suite. + * + * Copyright (c) 2004, 2005, 2006 + *     by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1991, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, + *     2002, 2003 by The Internet Software Consortium and Rich Salz + * + * This code is derived from software contributed to the Internet Software + * Consortium by Rich Salz. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include <config.h> +#include <system.h> + +#include <tests/libtest.h> + +size_t test_strlcpy(char *, const char *, size_t); + + +int +main(void) +{ +    char buffer[10]; + +    test_init(23); + +    ok_int(1, 3, test_strlcpy(buffer, "foo", sizeof(buffer))); +    ok_string(2, "foo", buffer); +    ok_int(3, 9, test_strlcpy(buffer, "hello wor", sizeof(buffer))); +    ok_string(4, "hello wor", buffer); +    ok_int(5, 10, test_strlcpy(buffer, "world hell", sizeof(buffer))); +    ok_string(6, "world hel", buffer); +    ok(7, buffer[9] == '\0'); +    ok_int(8, 11, test_strlcpy(buffer, "hello world", sizeof(buffer))); +    ok_string(9, "hello wor", buffer); +    ok(10, buffer[9] == '\0'); + +    /* Make sure that with a size of 0, the destination isn't changed. */ +    ok_int(11, 3, test_strlcpy(buffer, "foo", 0)); +    ok_string(12, "hello wor", buffer); + +    /* Now play with empty strings. */ +    ok_int(13, 0, test_strlcpy(buffer, "", 0)); +    ok_string(14, "hello wor", buffer); +    ok_int(15, 0, test_strlcpy(buffer, "", sizeof(buffer))); +    ok_string(16, "", buffer); +    ok_int(17, 3, test_strlcpy(buffer, "foo", 2)); +    ok_string(18, "f", buffer); +    ok(19, buffer[1] == '\0'); +    ok_int(20, 0, test_strlcpy(buffer, "", 1)); +    ok(21, buffer[0] == '\0'); + +    /* Finally, check using strlcpy as strlen. */ +    ok_int(22, 3, test_strlcpy(NULL, "foo", 0)); +    ok_int(23, 11, test_strlcpy(NULL, "hello world", 0)); + +    return 0; +} diff --git a/tests/portable/strlcpy.c b/tests/portable/strlcpy.c new file mode 100644 index 0000000..d444595 --- /dev/null +++ b/tests/portable/strlcpy.c @@ -0,0 +1,2 @@ +#define TESTING 1 +#include <portable/strlcpy.c> | 
