source: mainline/uspace/lib/posix/source/string.c@ 820104d

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 820104d was fdf97f6, checked in by Vojtech Horky <vojtechhorky@…>, 12 years ago

Libposix functions are without posix_ prefix

Prior this commit, libposix headers declared all functions as posix_*
and used macros to rename e.g. strncpy to posix_strncpy in all (ported)
sources.

After this change, libposix headers look as normal POSIX compliant headers
(well, almost) and no renaming is done in the source codei (of the ported
applications). Instead, the renaming is done at object files level to
bypass weird problems that are bound to happen if you use macros.

The scheme is following. libposix headers use special macro to declare
the names. When included from outside, the functions have their normal
(standard) names. When included from the libposix sources, posix_ prefix
is added. Thus, when libposix is compiled and linked, it contains the
posix_* naming while compiling of ported software uses the normal
non-prefixed versions. This way the posix_* can use HelenOS libc without
any problem. Before linking, the posix_* prefix is removed from all
symbols and special prefix helenos_libc_ is added to all functions
that exists in our (HelenOS) libc and its name clashes with the POSIX
one.

The following happens, for example, to the open() function that exists in
both libposix and in libc.

  • Headers and sources of libc are left intact.
  • Copy of libc.a is made and to all clashing functions is added the helenos_libc prefix. This library is called libc4posix.a.
  • POSIX_DEF(open)(const char *) is used in libposix headers. This macro expands to plain open when included from the "outside world". But it expands to posix_open when included from libposix sources.
  • Libposix is compiled and linked, containing posix_open() that internally calls open() [the original one from libc].
  • Libposix is transformed - all open() are replaced with prefix variant: helenos_libc_open() and all posix_open() are replaced with open(). The transformed library is stored as libposixaslibc.a

Binutils and PCC are then linked with libc4posix and libposixaslibc
libraries instead of libc and libposix as was done previously.

WARNING: it looks that binutils, PCC and MSIM still works but not all
architectures were tested.

  • Property mode set to 100644
File size: 19.9 KB
Line 
1/*
2 * Copyright (c) 2011 Petr Koupy
3 * Copyright (c) 2011 Jiri Zarevucky
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libposix
31 * @{
32 */
33/** @file String manipulation.
34 */
35
36#define LIBPOSIX_INTERNAL
37#define __POSIX_DEF__(x) posix_##x
38
39#include "internal/common.h"
40#include "posix/string.h"
41
42#include "posix/assert.h"
43#include "posix/errno.h"
44#include "posix/limits.h"
45#include "posix/stdlib.h"
46#include "posix/signal.h"
47
48#include "libc/str_error.h"
49
50/**
51 * The same as strpbrk, except it returns pointer to the nul terminator
52 * if no occurence is found.
53 *
54 * @param s1 String in which to look for the bytes.
55 * @param s2 String of bytes to look for.
56 * @return Pointer to the found byte on success, pointer to the
57 * string terminator otherwise.
58 */
59static char *strpbrk_null(const char *s1, const char *s2)
60{
61 while (!posix_strchr(s2, *s1)) {
62 ++s1;
63 }
64
65 return (char *) s1;
66}
67
68/**
69 * Copy a string.
70 *
71 * @param dest Destination pre-allocated buffer.
72 * @param src Source string to be copied.
73 * @return Pointer to the destination buffer.
74 */
75char *posix_strcpy(char *restrict dest, const char *restrict src)
76{
77 posix_stpcpy(dest, src);
78 return dest;
79}
80
81/**
82 * Copy fixed length string.
83 *
84 * @param dest Destination pre-allocated buffer.
85 * @param src Source string to be copied.
86 * @param n Number of bytes to be stored into destination buffer.
87 * @return Pointer to the destination buffer.
88 */
89char *posix_strncpy(char *restrict dest, const char *restrict src, size_t n)
90{
91 posix_stpncpy(dest, src, n);
92 return dest;
93}
94
95/**
96 * Copy a string.
97 *
98 * @param dest Destination pre-allocated buffer.
99 * @param src Source string to be copied.
100 * @return Pointer to the nul character in the destination string.
101 */
102char *posix_stpcpy(char *restrict dest, const char *restrict src)
103{
104 assert(dest != NULL);
105 assert(src != NULL);
106
107 for (size_t i = 0; ; ++i) {
108 dest[i] = src[i];
109
110 if (src[i] == '\0') {
111 /* pointer to the terminating nul character */
112 return &dest[i];
113 }
114 }
115
116 /* unreachable */
117 return NULL;
118}
119
120/**
121 * Copy fixed length string.
122 *
123 * @param dest Destination pre-allocated buffer.
124 * @param src Source string to be copied.
125 * @param n Number of bytes to be stored into destination buffer.
126 * @return Pointer to the first written nul character or &dest[n].
127 */
128char *posix_stpncpy(char *restrict dest, const char *restrict src, size_t n)
129{
130 assert(dest != NULL);
131 assert(src != NULL);
132
133 for (size_t i = 0; i < n; ++i) {
134 dest[i] = src[i];
135
136 /* the standard requires that nul characters
137 * are appended to the length of n, in case src is shorter
138 */
139 if (src[i] == '\0') {
140 char *result = &dest[i];
141 for (++i; i < n; ++i) {
142 dest[i] = '\0';
143 }
144 return result;
145 }
146 }
147
148 return &dest[n];
149}
150
151/**
152 * Concatenate two strings.
153 *
154 * @param dest String to which src shall be appended.
155 * @param src String to be appended after dest.
156 * @return Pointer to destination buffer.
157 */
158char *posix_strcat(char *restrict dest, const char *restrict src)
159{
160 assert(dest != NULL);
161 assert(src != NULL);
162
163 posix_strcpy(posix_strchr(dest, '\0'), src);
164 return dest;
165}
166
167/**
168 * Concatenate a string with part of another.
169 *
170 * @param dest String to which part of src shall be appended.
171 * @param src String whose part shall be appended after dest.
172 * @param n Number of bytes to append after dest.
173 * @return Pointer to destination buffer.
174 */
175char *posix_strncat(char *restrict dest, const char *restrict src, size_t n)
176{
177 assert(dest != NULL);
178 assert(src != NULL);
179
180 char *zeroptr = posix_strncpy(posix_strchr(dest, '\0'), src, n);
181 /* strncpy doesn't append the nul terminator, so we do it here */
182 zeroptr[n] = '\0';
183 return dest;
184}
185
186/**
187 * Copy limited number of bytes in memory.
188 *
189 * @param dest Destination buffer.
190 * @param src Source buffer.
191 * @param c Character after which the copying shall stop.
192 * @param n Number of bytes that shall be copied if not stopped earlier by c.
193 * @return Pointer to the first byte after c in dest if found, NULL otherwise.
194 */
195void *posix_memccpy(void *restrict dest, const void *restrict src, int c, size_t n)
196{
197 assert(dest != NULL);
198 assert(src != NULL);
199
200 unsigned char* bdest = dest;
201 const unsigned char* bsrc = src;
202
203 for (size_t i = 0; i < n; ++i) {
204 bdest[i] = bsrc[i];
205
206 if (bsrc[i] == (unsigned char) c) {
207 /* pointer to the next byte */
208 return &bdest[i + 1];
209 }
210 }
211
212 return NULL;
213}
214
215/**
216 * Duplicate a string.
217 *
218 * @param s String to be duplicated.
219 * @return Newly allocated copy of the string.
220 */
221char *posix_strdup(const char *s)
222{
223 return posix_strndup(s, SIZE_MAX);
224}
225
226/**
227 * Duplicate a specific number of bytes from a string.
228 *
229 * @param s String to be duplicated.
230 * @param n Maximum length of the resulting string..
231 * @return Newly allocated string copy of length at most n.
232 */
233char *posix_strndup(const char *s, size_t n)
234{
235 assert(s != NULL);
236
237 size_t len = posix_strnlen(s, n);
238 char *dup = malloc(len + 1);
239 if (dup == NULL) {
240 return NULL;
241 }
242
243 memcpy(dup, s, len);
244 dup[len] = '\0';
245
246 return dup;
247}
248
249/**
250 * Compare bytes in memory.
251 *
252 * @param mem1 First area of memory to be compared.
253 * @param mem2 Second area of memory to be compared.
254 * @param n Maximum number of bytes to be compared.
255 * @return Difference of the first pair of inequal bytes,
256 * or 0 if areas have the same content.
257 */
258int posix_memcmp(const void *mem1, const void *mem2, size_t n)
259{
260 assert(mem1 != NULL);
261 assert(mem2 != NULL);
262
263 const unsigned char *s1 = mem1;
264 const unsigned char *s2 = mem2;
265
266 for (size_t i = 0; i < n; ++i) {
267 if (s1[i] != s2[i]) {
268 return s1[i] - s2[i];
269 }
270 }
271
272 return 0;
273}
274
275/**
276 * Compare two strings.
277 *
278 * @param s1 First string to be compared.
279 * @param s2 Second string to be compared.
280 * @return Difference of the first pair of inequal characters,
281 * or 0 if strings have the same content.
282 */
283int posix_strcmp(const char *s1, const char *s2)
284{
285 assert(s1 != NULL);
286 assert(s2 != NULL);
287
288 return posix_strncmp(s1, s2, STR_NO_LIMIT);
289}
290
291/**
292 * Compare part of two strings.
293 *
294 * @param s1 First string to be compared.
295 * @param s2 Second string to be compared.
296 * @param n Maximum number of characters to be compared.
297 * @return Difference of the first pair of inequal characters,
298 * or 0 if strings have the same content.
299 */
300int posix_strncmp(const char *s1, const char *s2, size_t n)
301{
302 assert(s1 != NULL);
303 assert(s2 != NULL);
304
305 for (size_t i = 0; i < n; ++i) {
306 if (s1[i] != s2[i]) {
307 return s1[i] - s2[i];
308 }
309 if (s1[i] == '\0') {
310 break;
311 }
312 }
313
314 return 0;
315}
316
317/**
318 * Find byte in memory.
319 *
320 * @param mem Memory area in which to look for the byte.
321 * @param c Byte to look for.
322 * @param n Maximum number of bytes to be inspected.
323 * @return Pointer to the specified byte on success,
324 * NULL pointer otherwise.
325 */
326void *posix_memchr(const void *mem, int c, size_t n)
327{
328 assert(mem != NULL);
329
330 const unsigned char *s = mem;
331
332 for (size_t i = 0; i < n; ++i) {
333 if (s[i] == (unsigned char) c) {
334 return (void *) &s[i];
335 }
336 }
337 return NULL;
338}
339
340/**
341 * Scan string for a first occurence of a character.
342 *
343 * @param s String in which to look for the character.
344 * @param c Character to look for.
345 * @return Pointer to the specified character on success,
346 * NULL pointer otherwise.
347 */
348char *posix_strchr(const char *s, int c)
349{
350 assert(s != NULL);
351
352 char *res = gnu_strchrnul(s, c);
353 return (*res == c) ? res : NULL;
354}
355
356/**
357 * Scan string for a last occurence of a character.
358 *
359 * @param s String in which to look for the character.
360 * @param c Character to look for.
361 * @return Pointer to the specified character on success,
362 * NULL pointer otherwise.
363 */
364char *posix_strrchr(const char *s, int c)
365{
366 assert(s != NULL);
367
368 const char *ptr = posix_strchr(s, '\0');
369
370 /* the same as in strchr, except it loops in reverse direction */
371 while (*ptr != (char) c) {
372 if (ptr == s) {
373 return NULL;
374 }
375
376 ptr--;
377 }
378
379 return (char *) ptr;
380}
381
382/**
383 * Scan string for a first occurence of a character.
384 *
385 * @param s String in which to look for the character.
386 * @param c Character to look for.
387 * @return Pointer to the specified character on success, pointer to the
388 * string terminator otherwise.
389 */
390char *gnu_strchrnul(const char *s, int c)
391{
392 assert(s != NULL);
393
394 while (*s != c && *s != '\0') {
395 s++;
396 }
397
398 return (char *) s;
399}
400
401/**
402 * Scan a string for a first occurence of one of provided bytes.
403 *
404 * @param s1 String in which to look for the bytes.
405 * @param s2 String of bytes to look for.
406 * @return Pointer to the found byte on success,
407 * NULL pointer otherwise.
408 */
409char *posix_strpbrk(const char *s1, const char *s2)
410{
411 assert(s1 != NULL);
412 assert(s2 != NULL);
413
414 char *ptr = strpbrk_null(s1, s2);
415 return (*ptr == '\0') ? NULL : ptr;
416}
417
418/**
419 * Get the length of a complementary substring.
420 *
421 * @param s1 String that shall be searched for complementary prefix.
422 * @param s2 String of bytes that shall not occur in the prefix.
423 * @return Length of the prefix.
424 */
425size_t posix_strcspn(const char *s1, const char *s2)
426{
427 assert(s1 != NULL);
428 assert(s2 != NULL);
429
430 char *ptr = strpbrk_null(s1, s2);
431 return (size_t) (ptr - s1);
432}
433
434/**
435 * Get length of a substring.
436 *
437 * @param s1 String that shall be searched for prefix.
438 * @param s2 String of bytes that the prefix must consist of.
439 * @return Length of the prefix.
440 */
441size_t posix_strspn(const char *s1, const char *s2)
442{
443 assert(s1 != NULL);
444 assert(s2 != NULL);
445
446 const char *ptr;
447 for (ptr = s1; *ptr != '\0'; ++ptr) {
448 if (!posix_strchr(s2, *ptr)) {
449 break;
450 }
451 }
452 return ptr - s1;
453}
454
455/**
456 * Find a substring. Uses Knuth-Morris-Pratt algorithm.
457 *
458 * @param s1 String in which to look for a substring.
459 * @param s2 Substring to look for.
460 * @return Pointer to the first character of the substring in s1, or NULL if
461 * not found.
462 */
463char *posix_strstr(const char *haystack, const char *needle)
464{
465 assert(haystack != NULL);
466 assert(needle != NULL);
467
468 /* Special case - needle is an empty string. */
469 if (needle[0] == '\0') {
470 return (char *) haystack;
471 }
472
473 /* Preprocess needle. */
474 size_t nlen = posix_strlen(needle);
475 size_t prefix_table[nlen + 1];
476
477 {
478 size_t i = 0;
479 ssize_t j = -1;
480
481 prefix_table[i] = j;
482
483 while (i < nlen) {
484 while (j >= 0 && needle[i] != needle[j]) {
485 j = prefix_table[j];
486 }
487 i++; j++;
488 prefix_table[i] = j;
489 }
490 }
491
492 /* Search needle using the precomputed table. */
493 size_t npos = 0;
494
495 for (size_t hpos = 0; haystack[hpos] != '\0'; ++hpos) {
496 while (npos != 0 && haystack[hpos] != needle[npos]) {
497 npos = prefix_table[npos];
498 }
499
500 if (haystack[hpos] == needle[npos]) {
501 npos++;
502
503 if (npos == nlen) {
504 return (char *) (haystack + hpos - nlen + 1);
505 }
506 }
507 }
508
509 return NULL;
510}
511
512/**
513 * String comparison using collating information.
514 *
515 * Currently ignores locale and just calls strcmp.
516 *
517 * @param s1 First string to be compared.
518 * @param s2 Second string to be compared.
519 * @return Difference of the first pair of inequal characters,
520 * or 0 if strings have the same content.
521 */
522int posix_strcoll(const char *s1, const char *s2)
523{
524 assert(s1 != NULL);
525 assert(s2 != NULL);
526
527 return posix_strcmp(s1, s2);
528}
529
530/**
531 * Transform a string in such a way that the resulting string yields the same
532 * results when passed to the strcmp as if the original string is passed to
533 * the strcoll.
534 *
535 * Since strcoll is equal to strcmp here, this just makes a copy.
536 *
537 * @param s1 Transformed string.
538 * @param s2 Original string.
539 * @param n Maximum length of the transformed string.
540 * @return Length of the transformed string.
541 */
542size_t posix_strxfrm(char *restrict s1, const char *restrict s2, size_t n)
543{
544 assert(s1 != NULL || n == 0);
545 assert(s2 != NULL);
546
547 size_t len = posix_strlen(s2);
548
549 if (n > len) {
550 posix_strcpy(s1, s2);
551 }
552
553 return len;
554}
555
556/**
557 * Get error message string.
558 *
559 * @param errnum Error code for which to obtain human readable string.
560 * @return Error message.
561 */
562char *posix_strerror(int errnum)
563{
564 static const char *error_msgs[] = {
565 [E2BIG] = "[E2BIG] Argument list too long",
566 [EACCES] = "[EACCES] Permission denied",
567 [EADDRINUSE] = "[EADDRINUSE] Address in use",
568 [EADDRNOTAVAIL] = "[EADDRNOTAVAIL] Address not available",
569 [EAFNOSUPPORT] = "[EAFNOSUPPORT] Address family not supported",
570 [EAGAIN] = "[EAGAIN] Resource unavailable, try again",
571 [EALREADY] = "[EALREADY] Connection already in progress",
572 [EBADF] = "[EBADF] Bad file descriptor",
573 [EBADMSG] = "[EBADMSG] Bad message",
574 [EBUSY] = "[EBUSY] Device or resource busy",
575 [ECANCELED] = "[ECANCELED] Operation canceled",
576 [ECHILD] = "[ECHILD] No child processes",
577 [ECONNABORTED] = "[ECONNABORTED] Connection aborted",
578 [ECONNREFUSED] = "[ECONNREFUSED] Connection refused",
579 [ECONNRESET] = "[ECONNRESET] Connection reset",
580 [EDEADLK] = "[EDEADLK] Resource deadlock would occur",
581 [EDESTADDRREQ] = "[EDESTADDRREQ] Destination address required",
582 [EDOM] = "[EDOM] Mathematics argument out of domain of function",
583 [EDQUOT] = "[EDQUOT] Reserved",
584 [EEXIST] = "[EEXIST] File exists",
585 [EFAULT] = "[EFAULT] Bad address",
586 [EFBIG] = "[EFBIG] File too large",
587 [EHOSTUNREACH] = "[EHOSTUNREACH] Host is unreachable",
588 [EIDRM] = "[EIDRM] Identifier removed",
589 [EILSEQ] = "[EILSEQ] Illegal byte sequence",
590 [EINPROGRESS] = "[EINPROGRESS] Operation in progress",
591 [EINTR] = "[EINTR] Interrupted function",
592 [EINVAL] = "[EINVAL] Invalid argument",
593 [EIO] = "[EIO] I/O error",
594 [EISCONN] = "[EISCONN] Socket is connected",
595 [EISDIR] = "[EISDIR] Is a directory",
596 [ELOOP] = "[ELOOP] Too many levels of symbolic links",
597 [EMFILE] = "[EMFILE] File descriptor value too large",
598 [EMLINK] = "[EMLINK] Too many links",
599 [EMSGSIZE] = "[EMSGSIZE] Message too large",
600 [EMULTIHOP] = "[EMULTIHOP] Reserved",
601 [ENAMETOOLONG] = "[ENAMETOOLONG] Filename too long",
602 [ENETDOWN] = "[ENETDOWN] Network is down",
603 [ENETRESET] = "[ENETRESET] Connection aborted by network",
604 [ENETUNREACH] = "[ENETUNREACH] Network unreachable",
605 [ENFILE] = "[ENFILE] Too many files open in system",
606 [ENOBUFS] = "[ENOBUFS] No buffer space available",
607 [ENODATA] = "[ENODATA] No message is available on the STREAM head read queue",
608 [ENODEV] = "[ENODEV] No such device",
609 [ENOENT] = "[ENOENT] No such file or directory",
610 [ENOEXEC] = "[ENOEXEC] Executable file format error",
611 [ENOLCK] = "[ENOLCK] No locks available",
612 [ENOLINK] = "[ENOLINK] Reserved",
613 [ENOMEM] = "[ENOMEM] Not enough space",
614 [ENOMSG] = "[ENOMSG] No message of the desired type",
615 [ENOPROTOOPT] = "[ENOPROTOOPT] Protocol not available",
616 [ENOSPC] = "[ENOSPC] No space left on device",
617 [ENOSR] = "[ENOSR] No STREAM resources.",
618 [ENOSTR] = "[ENOSTR] Not a STREAM",
619 [ENOSYS] = "[ENOSYS] Function not supported",
620 [ENOTCONN] = "[ENOTCONN] The socket is not connected",
621 [ENOTDIR] = "[ENOTDIR] Not a directory",
622 [ENOTEMPTY] = "[ENOTEMPTY] Directory not empty",
623 [ENOTRECOVERABLE] = "[ENOTRECOVERABLE] State not recoverable",
624 [ENOTSOCK] = "[ENOTSOCK] Not a socket",
625 [ENOTSUP] = "[ENOTSUP] Not supported",
626 [ENOTTY] = "[ENOTTY] Inappropriate I/O control operation",
627 [ENXIO] = "[ENXIO] No such device or address",
628 [EOPNOTSUPP] = "[EOPNOTSUPP] Operation not supported",
629 [EOVERFLOW] = "[EOVERFLOW] Value too large to be stored in data type",
630 [EOWNERDEAD] = "[EOWNERDEAD] Previous owned died",
631 [EPERM] = "[EPERM] Operation not permitted",
632 [EPIPE] = "[EPIPE] Broken pipe",
633 [EPROTO] = "[EPROTO] Protocol error",
634 [EPROTONOSUPPORT] = "[EPROTONOSUPPORT] Protocol not supported",
635 [EPROTOTYPE] = "[EPROTOTYPE] Protocol wrong type for socket",
636 [ERANGE] = "[ERANGE] Result too large",
637 [EROFS] = "[EROFS] Read-only file system",
638 [ESPIPE] = "[ESPIPE] Invalid seek",
639 [ESRCH] = "[ESRCH] No such process",
640 [ESTALE] = "[ESTALE] Reserved",
641 [ETIME] = "[ETIME] Stream ioctl() timeout",
642 [ETIMEDOUT] = "[ETIMEDOUT] Connection timed out",
643 [ETXTBSY] = "[ETXTBSY] Text file busy",
644 [EWOULDBLOCK] = "[EWOULDBLOCK] Operation would block",
645 [EXDEV] = "[EXDEV] Cross-device link",
646 };
647
648 return (char *) error_msgs[posix_abs(errnum)];
649}
650
651/**
652 * Get error message string.
653 *
654 * @param errnum Error code for which to obtain human readable string.
655 * @param buf Buffer to store a human readable string to.
656 * @param bufsz Size of buffer pointed to by buf.
657 * @return Zero on success, errno otherwise.
658 */
659int posix_strerror_r(int errnum, char *buf, size_t bufsz)
660{
661 assert(buf != NULL);
662
663 char *errstr = posix_strerror(errnum);
664
665 if (posix_strlen(errstr) + 1 > bufsz) {
666 return ERANGE;
667 } else {
668 posix_strcpy(buf, errstr);
669 }
670
671 return 0;
672}
673
674/**
675 * Get length of the string.
676 *
677 * @param s String which length shall be determined.
678 * @return Length of the string.
679 */
680size_t posix_strlen(const char *s)
681{
682 assert(s != NULL);
683
684 return (size_t) (posix_strchr(s, '\0') - s);
685}
686
687/**
688 * Get limited length of the string.
689 *
690 * @param s String which length shall be determined.
691 * @param n Maximum number of bytes that can be examined to determine length.
692 * @return The lower of either string length or n limit.
693 */
694size_t posix_strnlen(const char *s, size_t n)
695{
696 assert(s != NULL);
697
698 for (size_t sz = 0; sz < n; ++sz) {
699
700 if (s[sz] == '\0') {
701 return sz;
702 }
703 }
704
705 return n;
706}
707
708/**
709 * Get description of a signal.
710 *
711 * @param signum Signal number.
712 * @return Human readable signal description.
713 */
714char *posix_strsignal(int signum)
715{
716 static const char *const sigstrings[] = {
717 [SIGABRT] = "SIGABRT (Process abort signal)",
718 [SIGALRM] = "SIGALRM (Alarm clock)",
719 [SIGBUS] = "SIGBUS (Access to an undefined portion of a memory object)",
720 [SIGCHLD] = "SIGCHLD (Child process terminated, stopped, or continued)",
721 [SIGCONT] = "SIGCONT (Continue executing, if stopped)",
722 [SIGFPE] = "SIGFPE (Erroneous arithmetic operation)",
723 [SIGHUP] = "SIGHUP (Hangup)",
724 [SIGILL] = "SIGILL (Illegal instruction)",
725 [SIGINT] = "SIGINT (Terminal interrupt signal)",
726 [SIGKILL] = "SIGKILL (Kill process)",
727 [SIGPIPE] = "SIGPIPE (Write on a pipe with no one to read it)",
728 [SIGQUIT] = "SIGQUIT (Terminal quit signal)",
729 [SIGSEGV] = "SIGSEGV (Invalid memory reference)",
730 [SIGSTOP] = "SIGSTOP (Stop executing)",
731 [SIGTERM] = "SIGTERM (Termination signal)",
732 [SIGTSTP] = "SIGTSTP (Terminal stop signal)",
733 [SIGTTIN] = "SIGTTIN (Background process attempting read)",
734 [SIGTTOU] = "SIGTTOU (Background process attempting write)",
735 [SIGUSR1] = "SIGUSR1 (User-defined signal 1)",
736 [SIGUSR2] = "SIGUSR2 (User-defined signal 2)",
737 [SIGPOLL] = "SIGPOLL (Pollable event)",
738 [SIGPROF] = "SIGPROF (Profiling timer expired)",
739 [SIGSYS] = "SIGSYS (Bad system call)",
740 [SIGTRAP] = "SIGTRAP (Trace/breakpoint trap)",
741 [SIGURG] = "SIGURG (High bandwidth data is available at a socket)",
742 [SIGVTALRM] = "SIGVTALRM (Virtual timer expired)",
743 [SIGXCPU] = "SIGXCPU (CPU time limit exceeded)",
744 [SIGXFSZ] = "SIGXFSZ (File size limit exceeded)"
745 };
746
747 if (signum <= _TOP_SIGNAL) {
748 return (char *) sigstrings[signum];
749 }
750
751 return (char *) "ERROR, Invalid signal number";
752}
753
754/** @}
755 */
Note: See TracBrowser for help on using the repository browser.