Path: utzoo!attcan!uunet!munnari!otc!metro!ipso!runx!brucee From: brucee@runx.ips.oz (Bruce Evans) Newsgroups: comp.os.minix Subject: Re: Bugs in 'strn' library functions Message-ID: <1531@runx.ips.oz> Date: 22 May 88 13:46:51 GMT Organization: RUNX Un*x Timeshare. Sydney, Australia. Lines: 127 Here are my versions of the 'strn' library functions, to fix the problems mentioned in my previous posting. I said I could 'easily' post corrected versions, but decided to test them carefully first and spent a long time on it when a bug showed up. To avoid unnecessary complications, I decided not to post the assembler versions. I said that the old 'strncat' sometimes does an incorrect null termination. This is wrong, since the null is effectively the one moved from the end of the initial target string. There is some confusion about what the type of the count arguments are. The functions here treat them as ints and not unsigneds, according to Unix Programmer's Manual 1983,1979 (V7) C A Reference Manual (Harbison and Steele, 1984) but for practical DOS compilers Turbo C V1.0: arguments are declared as int but act as unsigned (wrong) Microsoft C V4.0: arguments are declared and act as unsigned and Unofficial ANSI C standard: arguments are size_t (unsigned for Minix). So it looks like the new standard is that the count arguments are unsigned. This brings in a new set of problems, as lint will quite rightly complain about millions of old programs which pass int parameters. # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by brucee on Sun May 22 23:44:57 GMT+10:00 1988 # Contents: strncat.c strncmp.c strncpy.c echo x - strncat.c sed 's/^@//' > "strncat.c" <<'@//E*O*F strncat.c//' /* strncat.c - char *strncat( char *s1, char *s2, int n ) Strncat appends up to n characters from s2 to the end of s1. It returns s1. */ char *strncat( s1, s2, n ) char *s1; register char *s2; int n; { register char *rs1; rs1 = s1; if ( n > 0 ) { while ( *rs1++ != 0 ) ; --rs1; while ( (*rs1++ = *s2++) != 0 ) if ( --n == 0 ) { *rs1 = 0; break; } } return s1; } @//E*O*F strncat.c// chmod u=rw,g=,o= strncat.c echo x - strncmp.c sed 's/^@//' > "strncmp.c" <<'@//E*O*F strncmp.c//' /* strncmp.c - int strncmp( char *s1, char *s2, int n ) Strcmp compares s1 to s2, up to at most n characters (lexicographically with native character comparison). It returns positive if s1 > s2 zero if s1 = s2 negative if s1 < s2. */ int strncmp( s1, s2, n ) register char *s1; register char *s2; int n; { if ( n <= 0 ) return 0; while ( *s1++ == *s2++ ) if ( s1[-1] == 0 || --n == 0 ) return 0; return s1[-1] - s2[-1]; } @//E*O*F strncmp.c// chmod u=rw,g=,o= strncmp.c echo x - strncpy.c sed 's/^@//' > "strncpy.c" <<'@//E*O*F strncpy.c//' /* strncpy.c - char *strncpy( char *s1, char *s2, int n ) Strncpy writes exactly n (or 0 if n < 0) characters to s1. It copies up to n characters from s2, and null-pads the rest. The result is null terminated iff strlen( s2 ) < n. It returns the target string. */ char *strncpy( s1, s2, n ) char *s1; register char *s2; int n; { register char *rs1; rs1 = s1; if ( n > 0 ) { while ( (*rs1++ = *s2++) != 0 && --n != 0 ) ; if ( n != 0 ) while ( --n != 0 ) *rs1++ = 0; } return s1; } @//E*O*F strncpy.c// chmod u=rw,g=,o= strncpy.c exit 0 Bruce Evans Internet: brucee@runx.ips.oz.au UUCP: uunet!runx.ips.oz.au!brucee