The function mktime takes a broken-down time,expressed as a local time,and converts it into a time_t value.
#include <time.h>
time_t mktime(struct tm *tmptr);
The strftime function is a printf-like function for time values. It is complicated by the multitude of arguments available to customize the string it produces
#include <time.h>
size_t strftime(char *restrict buf,size_t maxsize,const char *restrict format,const struct tm *restrict tmptr);
size_t strftime_l(char *restrict buf,const struct tm *restric tmptr,local_t locale);
The strftime and strftime_l functions are the same,except that the strftime_l function allows the caller to specify the locale as an argument. The strftime function uses the locale specified by the TZ environment variable.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
time_t t;
struct tm *tmp;
char buf1[16];
char buf2[64];
time(&t);
tmp=localtime(&t);
if(strftime(buf1,16,"time and date: %r,%a,%b,%d,%Y",tmp)==0)
printf("buffer length 16 is too small\n");
else
printf("%s\n",buf1);
if(strftime(buf2,64,tmp)==0)
printf("buffer length 64 is too small\n");
else
printf("%s\n",buf2);
return 0;
}
Using the strftime function
The strptime function is the inverse of strftime. It takes a string and converts it into a broken-down time.
#include <time.h>
char strptime(const char *restrict buf,struct tm *restrict tmptr);
Process Environment
In this chapter,we’ll see how the main function is called when the program is executed,how command-line arguments are passed to the new program,what the typical memory layout looks like,how to allocate additional memory,how the process can use environment variables,and varIoUs ways for the
process to terminate. Additionally,we’ll look at the longjmp and setjmp functions and their interaction with the stack. We finish the chapter by examining the resource limits of a process.
main Function
A C program starts execution with a function called main. The prototype for the main function is
int main(int argc,char *argv[]);
where argc is the number of command-line arguments,and argv is an array of pointers to the arguments. We describe these arguments in later chapter.
Process Termination
There are eight ways for a process to terminate. Normal termination occurs in five ways:
1.Return from main
2.Calling exit
3.Calling _exit or _Exit
4.Return of the last thread from its start routine
5.Calling pthread_exit from the last thread
Abnormal termination occurs in three ways:
6.Calling abort
7.Receipt of a signal
8.Response of the last thread to a cancellation request
If the start-up routine were coded in C (it is often coded in assembly language) the call to main could look like
exit(main(argc,argv));
Exit Function
Three functions terminate a program normally: _exit and _Exit,which return to the kernel immediately,and exit,which performs certain cleanup processing and then returns to the kernel.
#include <stdlib.h>
void exit(int status);
void _Exit(int status);
#include <unistd.h>
void _exit(int status);
The reason for the different headers is that exit and _Exit are specified by ISO C,whereas _exit is specified by POSIX.1.
Historically,the exit function has always performed a clean shutdown of the standard I/O library: the fclose function is called for all open streams.
Returning an integer value from the main function is equivalent to calling exit with the same value. Thus
exit(0);
is the same as
return(0);
from the main function.
#include <stdio.h>
main()
{
printf("hello world");
}
Classic C program
Note the compiler warning when we enable the 1999 ISO C extensions. This warning is printed because the type of the main function is not explicitly declared to be an integer. If we were to add this declaration,the message would go away. However,if we were to enable all recommended warnings from the compiler (with the -Wall flag),then we would see a warning message something like ‘‘control reaches end of nonvoid function.’’
The declaration of main as returning an integer and the use of exit instead of return produces needless warnings from some compilers and the lint(1) program. The problem is that these compilers don’t know that an exit from main is the same as a return.
With ISO C,a process can register at least 32 functions that are automatically called by exit. These are called exit handlers and are registered by calling the atexit function.
#include <stdlib.h>
int atexit(void (*func)(void));
The program demonstrates the use of the atexit function.
#include "apue.h"
static void my_exit1(void);
static void my_exit2(void);
int main(void)
{
if(atexit(my_exit2)!=0)
err_sys("can't register my_exit2");
if(atexit(my_exit1)!=0)
err_sys("can't register my_exit1");
if(atexit(my_exit1)!=0)
err_sys("can't register my_exit1");
printf("main is done\n");
return 0;
}
static void my_exit1(void)
{
printf("first exit hander\n");
}
static void my_exit2(void)
{
printf("second exit hander\n");
}
Example of exit handlers
An exit handler is called once for each time it is registered. Note that we don’t call exit; instead,we return from main.