What you're looking for i 'strlcpy()' (or on windows maybe 'strncpy_s()'). BSD has strlcpy(), I don't know why glibc (Linux) doesn't have it by default. Actually, I do sort of know: The glibc project leader doesn't like it: http://sources.redhat.com/ml/libc-alpha/2002-01/msg00002.html
Ulrich left it out because he either doesn't like the (BSD) people who came up with strlcpy() (http://www.gratisoft.us/todd/papers/strlcpy.html), or it is what he implies, that he is convinced it encourages lazy programming and causes unexpected failure modes if the programmer forgets that strlcpy() can truncate a string (well he literally says something else, but if he literally means what he says then he just plainly doesn't understand where source strings can come from in the real world).
Besides the fact that strlcpy() has a return value that indicates truncation, he (incorrectly) assumes that ignored truncation can only be bad. I say incorrectly, because there are plenty of cases where a string truncation by strlcpy() is no problem. One important one of them is when the source string is only too long for the buffer if it is either erroneous (and a truncated version of the string is not more problematic later on), or it is specially crafted to try to cause a buffer overflow.... Honestly, I think the missing strlcpy() in glibc is more about personalities than anything else. Oh well...
The irony is that, as a result, some (many?) programmers are now using strncpy() and assuming it does the same thing as strlcpy(), causing more problems than strlcpy() even could have caused in Ulrich's imagination.
The (in case of overflow) not NUL-terminating of strncpy() means the destination is not guaranteed a string. It clearly was not meant to have a string as destination, but just a buffer (that's what the man page says too btw). It's padding with zeros to prevent 'leakage' of previous data in the destination, in case later the destination buffer is forwarded/stored as a whole (not as a string).
I think the main problem with that funtion is its name, it does not do what the name implies. A better name would be memstrcpy(dst,src,count), because it really is a memcopy where the source is a string and the destination is a buffer (it will never read past the end of the source string but always write the entire destination buffer).
I wonder how many people don't have a clue about this. For example, even "{char buf[10]; strncpy(buf,something,9);}" is still not safe, because buf[9] is uninitialized and therefore not guaranteed to be NUL... If you want to use strncpy() and the destination buffer is later treated as a string, you really have to make sure yourself that the last char in your buffer is NUL. When you do use strncpy(), you can check afterwards if the string did fit (it's going to be NUL if it did, not NUL if it didn't), and take appropriate action... But that's a lot of code if you just want a string copy with length truncation, aka strlcpy()...