===========
  PROCESS.H
 ===========
 Functions
 =========
  abort    
  _cexit   
  _c_exit  
  execl    
  execle   
  execlp   
  execlpe  
  execv    
  execve   
  execvp   
  execvpe  
  exit     
  _exit    
  getpid   
  spawnl   
  spawnle  
  spawnlp  
  spawnlpe 
  spawnv   
  spawnve  
  spawnvp  
  spawnvpe 
  system   

 Constants, data types, and global variables
 ===========================================
  P_NOWAIT 
  P_OVERLAY
  P_WAIT   
  _psp     

 See Also
 ========
  List of all Header files


========== ASSERT.H ========== Includes ======== STDIO.H STDLIB.H Functions ========= assert See Also ======== List of all Header files
========== SETJMP.H ========== Functions ========= longjmp setjmp Constants, data types, and global variables =========================================== jmp_buf See Also ======== List of all Header files
========== SIGNAL.H ========== Functions ========= raise signal Constants, data types, and global variables =========================================== predefined signal handlers sig_atomic_t type SIG_DFL SIG_ERR SIG_ING SIGABRT SIGFPE SIGILL SIGINT SIGSEGV SIGTERM See Also ======== List of all Header files
P_xxxx <PROCESS.H> ======== Modes used by the spawn function. Constant | Meaning -----------+--------------------------------------------------------- P_WAIT | Child runs separately, parent waits until exit P_NOWAIT | Child and parent run concurrently (Not implemented) P_OVERLAY | Child replaces parent so that parent no longer exists
=================== exec... functions <PROCESS.H> =================== Enable your program to load and run other files (child processes) Use these execl... functions when you know how many separate arguments you'll have: Declaration: * int execl (char *path, char *arg0, ..., NULL); * int execle (char *path, char *arg0, ..., NULL, char **env); * int execlp (char *path, char *arg0, ...); * int execlpe(char *path, char *arg0, ..., NULL, char **env); Use these execv... functions when you don't know in advance how many separate arguments you will have: Declaration: * int execv (char *path, char *argv[]); * int execve (char *path, char *argv[], char **env); * int execvp (char *path, char *argv[]); * int execvpe(char *path, char *argv[], char **env); Remarks: When an exec... call succeeds, the child process overlays the parent process. There must be sufficient memory available for loading and executing the child process. The l, v, e, and p suffixes added to "exec" specify certain capabilities of the exec... function. Argument | What It Is/Does ----------+---------------------------------------------------------------- path | File name of the called child process argN | Argument pointer(s) passed as separate arguments argv[N] | Argument pointer(s) passed as an array of pointers env | Array of character pointers. The exec... functions search for path using the standard DOS search algorithm. When an exec... function call is made, any open files remain open in the child process. Return Value: * On success, the functions do not return. * On error, the functions return -1 and set errno to one of the following: E2BIG Arg list too long EACCES Permission denied EMFILE Too many open files ENOENT Path or file name not found ENOEXEC Exec format error ENOMEM Not enough core Portability: + DOS + UNIX + Windows + ANSI C + C++ Only + | Yes | | | | | +-----+------+---------+--------+----------+ See Also: searchpath spawn... system Examples: execl example execlp example execle example execlpe example execv example execvp example execve example execvpe example
execl example =============== #include <stdio.h> #include <process.h> int main(int argc, char *argv[]) { int loop; printf("%s running...\n\n", argv[0]); if (argc == 1) { /* check for only one command-line parameter */ printf("%s calling itself again...\n", argv[0]); execl(argv[0], argv[0], "ONE", "TWO", "THREE", NULL); perror("EXEC:"); exit(1); } printf("%s called with arguments:\n", argv[0]); for (loop = 1; loop <= argc; loop++) puts(argv[loop]); /* Display all command-line parameters */ return 0; }
execlp example ================ #include <process.h> #include <stdio.h> #include <errno.h> int main( int argc, char *argv[]) { int i; printf("Command line arguments:\n"); for (i=0; i < argc; ++i) printf("[%2d] %s\n", i, argv[i]); printf("About to exec child with arg1 arg2 ...\n"); execlp("CHILD.EXE", "CHILD.EXE", "arg1", "arg2", NULL); perror("exec error"); exit(1); return 0; }
execle example ================ #include <process.h> #include <stdlib.h> #include <stdio.h> int main(int argc, char *argv[], char *env[]) { int loop; char *new_env[] = { "TESTING", NULL }; printf("%s running...\n\n", argv[0]); if (argc == 1) { /* check for only one command-line parameter */ printf("%s calling itself again...\n", argv[0]); execle(argv[0], argv[0], "ONE", "TWO", "THREE", NULL, new_env); perror("EXEC:"); exit(1); } printf("%s called with arguments:\n", argv[0]); for (loop = 1; loop <= argc; loop++) puts(argv[loop]); /* display all command-line parameters */ /* display the first environment parameter */ printf("value of env[0]: %s\n",env[0]); return 0; }
execlpe example ================= #include <process.h> #include <stdio.h> #include <errno.h> int main(int argc, char *argv[], char **envp ) { int i; printf("Command line arguments:\n"); for (i=0; i < argc; ++i) printf("[%2d] : %s\n", i, argv[i]); printf("About to exec child with arg1 arg2 ...\n"); execlpe("CHILD.EXE", "CHILD.EXE", "arg1", "arg2", NULL, envp); perror("exec error"); exit(1); return 0; }
execv example =============== #include <process.h> #include <stdio.h> #include <errno.h> int main(int argc, char *argv[]) { int i; printf("Command line arguments:\n"); for (i=0; i < argc; i++) printf("[%2d] : %s\n", i, argv[i]); printf("About to exec child with arg1 arg2 ...\n"); execv("CHILD.EXE", argv); perror("exec error"); exit(1); return 0; }
execve example ================ #include <process.h> #include <stdio.h> #include <errno.h> int main(int argc, char *argv[], char **envp) { int i; printf("Command line arguments:\n"); for (i=0; i < argc; ++i) printf("[%2d] : %s\n", i, argv[i]); printf("About to exec child with arg1 arg2 ...\n"); execve("CHILD.EXE", argv, envp); perror("exec error"); exit(1); return 0; }
execvp example ================ #include <process.h> #include <stdio.h> #include <errno.h> int main(int argc, char *argv[]) { int i; printf("Command line arguments:\n"); for (i=0; i < argc; ++i) printf("[%2d] : %s\n", i, argv[i]); printf("About to exec child with arg1 arg2 ...\n"); execvp("CHILD.EXE", argv); perror("exec error"); exit(1); return 0; }
execvpe example ================= #include <process.h> #include <stdio.h> #include <errno.h> int main(int argc, char *argv[], char **envp) { int i; printf("Command line arguments:\n"); for (i=0; i < argc; ++i) printf("[%2d] : %s\n", i, argv[i]); printf("About to exec child with arg1 arg2 ...\n"); execvpe("CHILD.EXE", argv, envp); perror("exec error"); exit(1); return 0; }
l, v, e, and p suffixes ========================= The l, v, e, and p suffixes specify certain capabilities of the exec... and spawn... functions. Each function in these families must have one of the two argument-specifying suffixes (either l or v): Suffix| Capabilities of the exec... or spawn... Function ------+------------------------------------------------------------------- l | Argument pointers (arg0, ..., argN) passed as separate arguments v | Argument pointers (argv[0], ..., argv[N]) passed as an array | of pointers The environment inheritance (e) and path search (p) suffixes are optional: Suffix| Capabilities of the exec... or spawn... Function ------+------------------------------------------------------------------- e | The function passes the env argument to the child process to | alter the child's environment. Without the "e" suffix, the child | inherits the parent's environment. | p | The function searches for the child process in the directories | specified by the DOS environment variable PATH.
Standard DOS Search Algorithm =============================== Argument = FILENAME (no dot, no extension) ========================================== 1) If no explicit extension is given, the function searches for the file as given. 2) If the file is not found, the function adds .COM and searches again. 3) If that search is not successful, it adds .EXE and searches one last time. Argument = FILENAME. or FILENAME.EXT ==================================== If an explicit extension or a period is given, the function searches for the file exactly as given.
argN and argv[N] arguments to exec... and spawn... ==================================================== The exec... and spawn... functions must pass at least one argument (arg0 or argv[0]) to the child process. This argument is, by convention, a copy of path. (Using a different value for this 0th argument won't produce an error.) * Under DOS 3.x, the variable path is available for the child process. * Under earlier versions of DOS, the child process can't use the passed value of the 0th argument (arg0 or argv[0]). "l" Suffix ========== When you use the "l" suffix with exec... or spawn..., arg0 usually points to path, and (arg1, ..., argN) point to character strings that form the new list of arguments. A mandatory null following argN marks the end of the list. The combined length of (arg0 + arg1 + ... + argN) or of (argv[0] + argv[1] + ... + argv[N]) must be less than 128 bytes (including space characters that separate the arguments). Null terminators are not counted.
env argument to exec... and spawn... ====================================== When you use the "e" suffix with exec... or spawn..., you pass a list of new environment settings through the argument env. *env is an array of character pointers. The last element in env is null. Each element points to a null-terminated character string of the form envvar = value * envvar is the name of an environment variable * value is the string value to which envvar is set When *env is null, the child inherits the parent's environment settings.
========= _exit <PROCESS.H, STDLIB.H> _c_exit <PROCESS.H> ========= * _exit terminates the program * _c_exit performs _exit cleanup without terminating the program Declaration: * void _exit(int status); * void _c_exit(void); Remarks: _exit terminates execution without closing any files, flushing any output, or calling any exit functions. _c_exit performs the same cleanup as _exit, except that it does not terminate the calling process. _c_exit restores interrupt vectors altered by the startup code, but performs no other cleanup. status ====== With _exit, status is provided for the calling process as the exit status of the process. Typically a value of 0 indicates a normal exit, and a non-zero value indicates some error. Return Value: None Portability: + DOS + UNIX + Windows + ANSI C + C++ Only + _exit | Yes | Yes | Yes | | | _c_exit | Yes | | Yes | | | +-----+------+---------+--------+----------+ See Also: abort atexit _cexit exec... exit _dos_keep signal spawn... Examples: _exit example _c_exit example
_exit example =============== #include <stdlib.h> #include <stdio.h> void done(void); int main(void) { atexit(done); _exit(0); return 0; } void done() { printf("hello\n"); }
_c_exit example ================= #include <process.h> #include <io.h> #include <fcntl.h> #include <stdio.h> #include <dos.h> main() { int fd; char c; if ((fd = open("_c_exit.c",O_RDONLY)) < 0) { printf("Unable to open _c_exit.c for reading\n"); return 1; } if (read(fd,&c,1) != 1) printf("Unable to read from open file handle %d before _c_exit\n",fd); else printf("Successfully read from open file handle %d before _c_exit\n",fd); printf("Interrupt zero vector before _c_exit = %Fp\n",_dos_getvect(0)); _c_exit(); if (read(fd,&c,1) != 1) printf("Unable to read from open file handle %d after _c_exit\n",fd); else printf("Successfully read from open file handle %d after _c_exit\n",fd); printf("Interrupt zero vector after _c_exit = %Fp\n",_dos_getvect(0)); return 0; }
========= _cexit, <PROCESS.H> exit <PROCESS.H, STDLIB.H> ========= * exit terminates the program * _cexit performs exit cleanup without terminating the program Declaration: * void exit(int status); * void _cexit(void); Remarks: exit terminates the calling process. Before termination, exit does the following: * closes all files * writes buffered output (waiting to be output) * calls any registered "exit functions" (posted with atexit) _cexit performs the same cleanup as exit, except that it does not close files or terminate the calling process. _cexit restores interrupt vectors altered by the startup code. status ====== With exit, status is provided for the calling process as the exit status of the process. Typically a value of 0 indicates a normal exit, and a non-zero value indicates some error. You use the following to set status: status | Indicates --------------+-------------------------------------------------- EXIT_SUCCESS | Normal program termination EXIT_FAILURE | Abnormal program termination. Signal to operating | system that program has terminated with an error. Return Value: None Portability: + DOS + UNIX + Windows + ANSI C + C++ Only + _cexit | Yes | | Yes | | | exit | Yes | Yes | Yes | Yes | | +-----+------+---------+--------+----------+ See Also: abort atexit _c_exit _dos_keep exec... _exit keep signal spawn... Examples: _cexit example exit example
exit example ============== #include <stdlib.h> #include <conio.h> #include <stdio.h> int main(void) { int status; printf("Enter either 1 or 2\n"); status = getch(); /* Sets DOS errorlevel */ exit(status - '0'); /* Note: this line is never reached */ return 0; }
_cexit example ================ #include <process.h> #include <io.h> #include <fcntl.h> #include <stdio.h> #include <dos.h> main() { int fd; char c; if ((fd = open("_cexit.c",O_RDONLY)) < 0) { printf("Unable to open _cexit.c for reading\n"); return 1; } if (read(fd,&c,1) != 1) printf("Unable to read from open file handle %d before _cexit\n",fd); else printf("Successfully read from open file handle %d before _cexit\n",fd); printf("Interrupt zero vector before _cexit = %Fp\n",_dos_getvect(0)); _cexit(); if (read(fd,&c,1) != 1) printf("Unable to read from open file handle %d after _cexit\n",fd); else printf("Successfully read from open file handle %d after _cexit\n",fd); printf("Interrupt zero vector after _cexit = %Fp\n",_dos_getvect(0)); return 0; }
======== getpid <PROCESS.H> ======== Gets the process ID of the program Remarks: getpid is a macro that gets the process ID of the program. A process ID uniquely identifies a program. This concept is borrowed from multitasking operating systems like UNIX, where each process is associated with a unique process number. Return Value: Returns the segment value of the PSP (program segment prefix). Portability: + DOS + UNIX + Windows + ANSI C + C++ Only + | Yes | Yes | Yes | | | +-----+------+---------+--------+----------+ Example: #include <stdio.h> #include <process.h> int main() { printf("This program's process identification number (PID) " "number is %X\n", getpid()); printf("Note: under DOS it is the PSP segment\n"); return 0; }
==================== spawn... functions <PROCESS.H> ==================== Enable your programs to run other files (child processes). spawn... functions return control to your program when the child processes finish. Use these spawn... functions when you know how many separate arguments you'll have: Declaration: * int spawnl (int mode, char *path, char *arg0, ..., NULL); * int spawnle (int mode, char *path, char *arg0, ..., NULL, char *envp[]); * int spawnlp (int mode, char *path, char *arg0, ..., NULL); * int spawnlpe(int mode, char *path, char *arg0, ..., NULL, char *envp[]); Use these spawn... functions when you don't know how many separate arguments you'll have: Declaration: * int spawnv (int mode, char *path, char *argv[]); * int spawnve (int mode, char *path, char *argv[], char *envp[]); * int spawnvp (int mode, char *path, char *argv[]); * int spawnvpe(int mode, char *path, char *argv[], char *envp[]); Remarks: The functions in the spawn... family create and run (execute) other files, known as child processes. There must be sufficient memory available for loading and executing a child process. The l, v, e, and p suffixes added to "spawn" specify certain capabilities of the spawn... function. Argument | What It Is/Does ----------+---------------------------------------------------------------- mode | Determines what action the calling function (parent process) | takes after the spawn... call. path | File name of the called child process argN | Argument pointer(s) passed as separate arguments argv[N] | Argument pointer(s) passed as an array of pointers envp | Array of character pointers. The spawn... functions search for path using the standard DOS search algorithm. When a spawn... function call is made, any open files remain open in the child process. If the child specifically calls exit with a non-zero argument, its exit status can be set to a non-zero value. Return Value: * On a successful execution, the spawn... functions return the child process's exit status (0 for a normal termination). * On error (the process can't be spawned successfully), the spawn... functions return -1, and set errno to one of the following: E2BIG Arg list too long EINVAL Invalid argument ENOENT Path or file name not found ENOEXEC Exec format error ENOMEM Not enough core Portability: + DOS + UNIX + Windows + ANSI C + C++ Only + | Yes | | | | | +-----+------+---------+--------+----------+ See Also: _exit _fpreset abort atexit exec exit searchpath system Examples: spawnl example spawnlp example spawnle example spawnlpe example spawnv example spawnvp example spawnve example spawnvpe example
mode argument of the spawn... functions ========================================= These are the possible values of mode: Constant | Meaning -----------+-------------------------------------------------------------- P_WAIT | Puts parent process "on hold" until child process completes | execution. P_NOWAIT | Continues to run parent process while child process runs. P_OVERLAY | Overlays child process in memory location formerly occupied | by parent. Same as an exec... call. P_NOWAIT is currently not available; using it generates an error.
spawnl example ================ #include <process.h> #include <stdio.h> #include <conio.h> void spawnl_example(void) { int result; clrscr(); result = spawnl(P_WAIT, "bcc.exe", NULL); if (result == -1) { perror("Error from spawnl"); exit(1); } } void spawnle_example(void) { int result; clrscr(); result = spawnle(P_WAIT, "bcc.exe", NULL, NULL); if (result == -1) { perror("Error from spawnle"); exit(1); } } int main(void) { spawnl_example(); spawnle_example(); return 0; }
spawnle example ================= #include <process.h> #include <stdio.h> #include <conio.h> void spawnl_example(void) { int result; clrscr(); result = spawnl(P_WAIT, "bcc.exe", NULL); if (result == -1) { perror("Error from spawnl"); exit(1); } } void spawnle_example(void) { int result; clrscr(); result = spawnle(P_WAIT, "bcc.exe", NULL, NULL); if (result == -1) { perror("Error from spawnle"); exit(1); } } int main(void) { spawnl_example(); spawnle_example(); return 0; }
spawnlp example ================= /* spawnlp example */ #include <process.h> #include <stdio.h> #include <errno.h> void main(int argc, char *argv[]) { int i; printf("Command line arguments:\n"); for (i=0; i<argc; ++i) printf("[%2d] : %s\n", i, argv[i]); printf("About to exec child with arg1 arg2 ...\n"); spawnlp(P_WAIT, "C:\\BORLANDC\\BIN\\BCC.EXE", argv[1], argv[2], NULL); perror("exec error"); exit(1); }
spawnlpe example ================== /* spawnlpe example */ #include <process.h> #include <stdio.h> #include <errno.h> int main( int argc, char *argv[], char **envp ) { int i; printf("Command line arguments:\n"); for (i=0; i < argc; ++i) printf("[%2d] %s\n", i, argv[i]); printf("About to exec child with arg1 arg2 ...\n"); spawnlpe(P_WAIT, "C:\\BORLANDC\\BIN\\BCC.EXE", argv[1], argv[2], NULL, envp); perror("exec error"); exit(1); return 0; }
spawnv example ================ /* spawnv example */ #include <process.h> #include <stdio.h> #include <errno.h> void main(int argc, char *argv[]) { int i; printf("Command line arguments:\n"); for (i=0; i<argc; ++i) printf("[%2d] : %s\n", i, argv[i]); printf("About to exec child with arg1 arg2 ...\n"); spawnv(P_WAIT,"C:\\BORLANDC\\BIN\\BCC.EXE", argv); perror("exec error"); exit(1); }
spawnve example ================= /* spawnve example */ #include <process.h> #include <stdio.h> #include <errno.h> void main(int argc, char *argv[], char **envp) { int i; printf("Command line arguments:\n"); for (i=0; i<argc; ++i) printf("[%2d] : %s\n", i, argv[i]); printf("About to exec child with arg1 arg2 ...\n"); spawnve(P_WAIT, "C:\\BORLANDC\\BIN\\TDMEM.EXE", argv, envp); perror("exec error"); exit(1); }
spawnvp example ================= /* spawnvp example */ #include <process.h> #include <stdio.h> #include <errno.h> void main(int argc, char *argv[]) { int i; printf("Command line arguments:\n"); for (i=0; i<argc; ++i) printf("[%2d] : %s\n", i, argv[i]); printf("About to exec child with arg1 arg2 ...\n"); spawnvp(P_WAIT, "C:\\BORLANDC\\BIN\\BCC.EXE", argv); perror("exec error"); exit(1); }
spawnvpe example ================== /* spawnvpe example */ #include <process.h> #include <stdio.h> #include <errno.h> int main( int argc, char *argv[], char **envp ) { int i; printf("Command line arguments:\n"); for (i=0; i < argc; ++i) printf("[%2d] %s\n", i, argv[i]); printf("About to exec child with arg1 arg2 ...\n"); spawnvpe(P_WAIT, "C:\\BORLANDC\\BIN\\BCC.EXE", argv, envp); perror("exec error"); exit(1); return 0; }
======== system <PROCESS.H, STDLIB.H> ======== Issues a DOS command Declaration: int system(const char *command); Remarks: system invokes the DOS command interpreter file from inside an executing C program to execute a DOS command, batch file, or other program named by the string "command". To be located and executed, the program must be in the current directory or in one of the directories listed in the PATH string in the environment. Because the COMSPEC environment variable is used to find the command interpreter file, the command interpreter file does not need to be in the current directory. Return Value * On success, returns 0 * On error, returns -1 and sets errno to ENOENT, ENOMEM, E2BIG, or ENOEXEC. Portability: + DOS + UNIX + Windows + ANSI C + C++ Only + | Yes | Yes | | Yes | | +-----+------+---------+--------+----------+ See Also: _fpreset exec... searchpath spawn... Example: #include <stdlib.h> #include <stdio.h> int main(void) { printf("About to spawn command interpreter and run a DOS command\n"); system("dir"); return 0; }
NDEBUG <ASSERT.H> ======== NDEBUG means "Use #define to treat assert as a macro or a true function". Can be defined in a user program. If defined, assert is a true function; otherwise assert is a macro.
======== assert <ASSERT.H> ======== Tests a condition and possibly aborts. Declaration: void assert(int test); Remarks: assert is a macro that expands to an if statement. If test evaluates to 0, assert prints this message on stderr: Assertion failed: test, file filename, line linenum and calls abort to abort the program. The filename and linenum listed in the message are the source file name and line number where the assert macro appears. If you place the #define NDEBUG directive ("no debugging") in the source code before the #include <ASSERT.H> directive, the assert statement is commented out. Return Value: None Portability: + DOS + UNIX + Windows + ANSI C + C++ Only + | Yes | Yes | Yes | Yes | | +-----+------+---------+--------+----------+ See Also: abort Example: #include <assert.h> #include <stdio.h> #include <stdlib.h> struct ITEM { int key; int value; }; /* add item to list, make sure list is not null */ void additem(struct ITEM *itemptr) { assert(itemptr != NULL); /* add item to list */ } int main(void) { additem(NULL); return 0; }
jmp_buf <SETJMP.H> ========= A buffer of type jmp_buf is used to save and restore the program task state. typedef struct { unsigned j_sp, j_ss, unsigned j_flag, j_cs; unsigned j_ip, j_bp; unsigned j_di, j_es; unsigned j_si, j_ds; } jmp_buf[1];
================= setjmp, longjmp <SETJMP.H> ================= * setjmp sets up for a nonlocal goto * longjmp performs a nonlocal goto Declaration: * int setjmp(jmp_buf jmpb); * void longjmp(jmp_buf jmpb, int retval); Remarks: * setjmp captures the complete task state in jmpb and returns 0. NOTE: setjmp MUST be called before longjmp. * A later call to longjmp with jmpb restores the captured task state and returns in such a way that setjmp appears to have returned with the value retval. NOTE: longjmp can't pass the value 0; if 0 is passed in retval, longjmp will substitute 1. Task State ========== A task state consists of the following: * all segment registers (CS, DS, ES, SS) * register variables (SI, DI) * stack pointer (SP) * frame base pointer (BP) * flags A task state is complete enough that setjmp and longjmp can be used to implement coroutines. The routine that calls setjmp and sets up jmpb must still be active and can't have returned before the longjmp is called. If it has returned, the results are unpredictable. setjmp is useful for dealing with errors and exceptions encountered in a low-level subroutine of a program. If Your Program Is Overlaid =========================== If your program is overlaid, you can't use setjmp and longjmp to implement coroutines. Normally, setjmp and longjmp save and restore all the registers needed for coroutines, but the overlay manager needs to keep track of stack contents and assumes there is only one stack. When you implement coroutines, there are usually either two stacks or two partitions of one stack, and the overlay manager will not track them properly. You can have background tasks that run with their own stacks or sections of stack, but * you must ensure that the background tasks do not invoke any overlaid code, and * you must not use the overlay versions of setjmp or longjmp to switch to and from background. When you avoid using overlay code or support routines, the existence of the background stacks does not disturb the overlay manager. Return Value: * setjmp returns 0 when it is initially called. If the return is from a call to longjmp, setjmp returns a non-zero value. * longjmp does not return. Portability: + DOS + UNIX + Windows + ANSI C + C++ Only + | Yes | Yes | Yes | Yes | | +-----+------+---------+--------+----------+ See Also: ctrlbrk signal Example (for both functions): #include <stdio.h> #include <setjmp.h> #include <stdlib.h> void subroutine(jmp_buf); int main(void) { int value; jmp_buf jumper; value = setjmp(jumper); if (value != 0) { printf("Longjmp with value %d\n", value); exit(value); } printf("About to call subroutine ... \n"); subroutine(jumper); return 0; } void subroutine(jmp_buf jumper) { longjmp(jumper,1); }
SIG_xxx <SIGNAL.H> ========= Predefined functions for handling signals generated by raise or by external events. Name | Meaning ---------+---------------------------- SIG_DFL | Terminate the program SIG_IGN | No action, ignore signal SIG_ERR | Return error code See Also: signal signal types
SIGxxxx <SIGNAL.H> ========= Signal types used by raise and signal. Signal |Note| Meaning | Default Action ---------+----+-----------------------------------+----------------------- SIGABRT | (*)| Abnormal termination | = to calling _exit(3) SIGFPE | | Bad floating-point operation | = to calling _exit(1) | | Arithmetic error caused by | | | division by 0, invalid operation, | | | etc. | SIGILL | (#)| Illegal operation | = to calling _exit(1) SIGINT | | Control-C interrupt | Is to do an INT 23h SIGSEGV | (#)| Invalid access to storage | = to calling _exit(1) SIGTERM | (*)| Request for program termination | = to calling _exit(1) (*) Signal types marked with a (*) aren't generated by DOS or Borland C++ during normal operation. However, they can be generated with raise. (#) Signals marked by (#) can't be generated asynchronously on 8088 or 8086 processors but can be generated on some other processors (see signal for details).
sig_atomic_t <SIGNAL.H> ============== Atomic entity type.
======= raise <SIGNAL.H> ======= Sends software signal to the executing program Declaration: int raise(int sig); Remarks: raise sends a signal of type sig to the program. * If the program has installed a signal handler for the signal type specified by sig, that handler will be executed. * If no handler has been installed, the default action for that signal type will be taken. Return Value * On success, raise returns 0. * Otherwise, returns non-zero. Portability: + DOS + UNIX + Windows + ANSI C + C++ Only + | Yes | Yes | Yes | Yes | | +-----+------+---------+--------+----------+ See Also: abort signal Example: #include <signal.h> int main(void) { int a, b; a = 10; b = 0; if (b == 0) /* preempt divide by zero error */ raise(SIGFPE); a = a / b; return 0; }
======== signal <SIGNAL.H> ======== Specifies signal-handling actions Declaration: void (*signal(int sig, void (*func) (int sig[,int subcode])))(int); Remarks: Signals are raised when an exception condition occurs or when raise is called. signal determines how receipt of signal number sig will be treated. You can install a user-specified handler routine or use one of the two predefined handlers, SIG_DFL and SIG_IGN (declared in SIGNAL.H). Function | Pointer | Meaning ---------+----------------------------------- SIG_DFL | Terminates the program SIG_ERR | Indicates error return from signal SIG_IGN | Ignore this type signal SIGNAL.H defines a type called sig_atomic_t, the largest integer type the processor can load or store atomically in the presence of asynchronous interrupts. For the 8086 family, this is a 16-bit word: a Borland C++ integer. When a signal is generated by the raise function or by an external event, the following happens: 1) If a user-specified handler has been installed for the signal, the action for that signal type is set to SIG_DFL. 2) The user-specified function is called with the signal type as the parameter. User-specified handler functions can terminate by a return or by a call to abort, _exit, exit, or longjmp. Borland C++ implements an extension to ANSI C when the signal type is SIGFPE, SIGSEGV, or SIGILL. Return Value: * On success (if the call succeeds), signal returns a pointer to the previous handler routine for the specified signal type. * On failure (if the call fails), signal returns SIG_ERR and sets errno to EINVAL. Portability: + DOS + UNIX + Windows + ANSI C + C++ Only + | Yes | | Yes | Yes | | +-----+------+---------+--------+----------+ See Also: _control87 abort ctrlbrk exit longjmp raise setjmp Example: /* This example installs a signal handler routine for SIGFPE, catches an integer overflow condition, makes an adjustment to AX register, and returns. This example program MAY cause your computer to crash, and will produce runtime errors depending on which memory model is used. */ #pragma inline #include <stdio.h> #include <signal.h> #ifdef __cplusplus typedef void (*fptr)(int); #else typedef void (*fptr)(); #endif void Catcher(int *reglist) { printf("Caught it!\n"); *(reglist + 8) = 3; /* make return AX = 3 */ } int main(void) { signal(SIGFPE, (fptr)Catcher); /* cast Catcher to appropriate type */ asm mov ax,07FFFH /* AX = 32767 */ asm inc ax /* cause overflow */ asm into /* activate handler */ /* The handler set AX to 3 on return. If that hadn't happened, there would have been another exception when the next 'into' was executed after the 'dec' instruction. */ asm dec ax /* no overflow now */ asm into /* doesn't activate */ return 0; }
Borland C++ extensions to signal ================================== Borland C++ implements an extension to ANSI C when the signal type is SIGFPE, SIGSEGV, or SIGILL. The user-specified handler function is called with either one or two extra parameters. Explicit call to raise ====================== If SIGFPE, SIGSEGV, or SIGILL has been raised as the result of an explicit call to raise, the user-specified handler is called with one extra parameter, an integer specifying that the handler is being explicitly invoked. These are the explicit activation values for SIGFPE, SIGSEGV, and SIGILL: Signal Type | Meaning -------------+------------------- SIGFPE | FPE_EXPLICITGEN SIGSEGV | SEGV_EXPLICITGEN SIGILL | ILL_EXPLICITGEN Floating-point Exception ======================== If SIGFPE is raised because of a floating-point exception, the user handler is called with one extra parameter that specifies the FPE_xxx type of the signal. Processor Exception =================== If SIGSEGV, SIGILL, or the integer-related variants of SIGFPE signals (FPE_INTOVFLOW or FPE_INTDIV0) are raised as the result of a processor exception, the user handler is called with two extra parameters: 1) The SIGFPE, SIGSEGV, or SIGILL exception type (see FLOAT.H for all these types). This first parameter is the usual ANSI signal type. 2. An integer pointer into the stack of the interrupt handler that called the user- specified handler. This pointer points to a list of the processor registers saved when the exception occurred. The registers are in the same order as the parameters to an interrupt function: BP, DI, SI, DS, ES, DX, CX, BX, AX, IP, CS, FLAGS To have a register value changed when the handler returns, change one of the locations in this list. For example, to have a new SI value on return, do something like this: *((int*)list_pointer + 2) = new_SI_value; In this way, the handler can examine and make any adjustments to the registers that you want. Return from Signal Handler ========================== When the signal type is SIGFPE, SIGSEGV, or SIGILL, a return from a signal handler is generally not advisable because one of the following has probably occurred: * The results of an integer division are wrong. * The state of the 8087 is corrupt. * An operation that shouldn't have overflowed did. * A bound instruction failed. * An illegal operation was attempted. These are the only times a return from a signal handler is reasonable: * The handler alters the registers so that a reasonable return context exists, or * The signal type indicates that the signal was generated explicitly (for example, FPE_EXPLICITGEN, SEGV_EXPLICITGEN, or ILL_EXPLICITGEN). Generally in this case you would print an error message and terminate the program using _exit, exit, or abort. If a return is executed under any other conditions, the program's action will probably be unpredictable upon resuming. See Also: SIGFPE type signals SIGSEGV type signals SIGILL type signals