environment, the s
return argument must be specified as a pointer to a character buffer having at least L_ctermid
bytes. It was felt that this restriction was sufficient, without defining a new variant to also specify the size of the buffer. Program getlogin.c
shows how to call these functions. Notice that these functions do not depend on threads, or <pthread.h>, in any way, and may even be provided on systems that don't support threads.
¦ getlogin.c
1 #include <limits.h>
2 #include 'errors.h'
3
4 /*
5 * If either TTY_NAME_MAX or LOGIN_NAME_MAX are undefined
6 * (this means they are 'indeterminate' values), assume a
7 * reasonable size (for simplicity) rather than using sysconf
8 * and dynamically allocating the buffers.
9 */
10 #ifndef TTY_NAME_MAX
11 # define TTY_NAME_MAX 128
12 #endif
13 #ifndef LOGIN_NAME_MAX
14 # define LOGIN_NAME_MAX 32
15 #endif
16
17 int main (int argc, char *argv[])
18 {
19 char login_str[LOGIN_NAME_MAX];
20 char stdin_str[TTY_NAME_MAX];
21 char cterm_str[L_ctermid], *cterm_str_ptr;
22 int status;
23
24 status = getlogin_r (login_str, sizeof (login_str));
25 if (status != 0)
26 err_abort (status, 'Get login');
27 cterm_str_ptr = ctermid (cterm_str);
28 if (cterm_str_ptr == NULL)
29 errno_abort ('Get cterm');
30 status = ttyname_r (0, stdin_str, sizeof (stdin_str));
31 if (status != 0)
32 err_abort (status, 'Get stdin');
33 printf ('User: %s, cterm: %s, fd 0: %s
',
34 login_str, cterm_str, stdin_str);
35 return 0;
6.5.2 Directory searching
int readdir_r (DIR *dirp, struct dirent *entry, struct dirent **result);
This function performs essentially the same action as readdir. That is, it returns the next directory entry in the directory stream specified by dirp. The difference is that instead of returning a pointer to that entry, it copies the entry into the buffer specified by entry. On success, it returns 0 and sets the pointer specified by result to the buffer entry. On reaching the end of the directory stream, it returns 0 and sets result to NULL. On failure, it returns an error number such as
EBADF.
Refer to program pipe .c, in Section 4.1, for a demonstration of using readdir_r to allow your threads to search multiple directories concurrently.
6.5.3 String token
char *strtok_r ( char *s, const char *sep, char **lasts);
This function returns the next token in the string s. Unlike strtok, the context (the current pointer within the original string) is maintained in lasts, which is specified by the caller, rather than in a static pointer internal to the function.
In the first call of a series, the argument s gives a pointer to the string. In subsequent calls to return successive tokens of that string, s must be specified as NULL. The value lasts is set by strtok_r to maintain the function's position within the string, and on each subsequent call you must return that same value of lasts. The strtok_r function returns a pointer to the next token, or NULL when there are no more tokens to be found in the original string.
6.5.4 Time representation
char *asctime_r (const struct tm *tm, char *buf);
char *ctime_r (const time_t *clock, char *buf);
struct tm *gmtime_r (const time_t *clock, struct tm *result);
struct tm *localtime_r (const time_t *clock, struct tm *result);
The output buffers (buf and result) are supplied by the caller, instead of returning a pointer to static storage internal to the functions. Otherwise, they are identical to the traditional variants. The asctime_r and ctime_r routines, which return ASCII character representations of a system time, both require that their buf argument point to a character string of at least 26 bytes.
6.5.5 Random number generation
int rand_r (unsigned int *seed);
The seed is maintained in caller-supplied storage (seed) rather than using static storage internal to the function. The main problem with this interface is that it is not usually practical to have a single seed shared by all application and library code within a program. As a result, the application and each library will generally have a separate 'stream' of random numbers. Thus, a program converted to use rand_r instead of rand is likely to generate different results, even if no threads are created. (Creating threads would probably change the order of calls to rand, and therefore change results anyway.)
6.5.6 Group and user database