Monday, November 24, 2008

Man page - write

NAME
write - write to a file descriptor

SYNOPSIS
#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t count);

DESCRIPTION
write() writes up to count bytes from the buffer pointed buf to the
file referred to by the file descriptor fd.

The number of bytes written may be less than count if, for example,
there is insufficient space on the underlying physical medium, or the
RLIMIT_FSIZE resource limit is encountered (see setrlimit(2)), or the
call was interrupted by a signal handler after having written less than
count bytes. (See also pipe(7).)

For a seekable file (i.e., one to which lseek(2) may be applied, for
example, a regular file) writing takes place at the current file off
set, and the file offset is incremented by the number of bytes actually
written. If the file was open(2)ed with O_APPEND, the file offset is
first set to the end of the file before writing. The adjustment of the
file offset and the write operation are performed as an atomic step.

POSIX requires that a read(2) which can be proved to occur after a
write() has returned returns the new data. Note that not all file sys
tems are POSIX conforming.

RETURN VALUE
On success, the number of bytes written is returned (zero indicates
nothing was written). On error, -1 is returned, and errno is set
appropriately.

If count is zero and fd refers to a regular file, then write() may
return a failure status if one of the errors below is detected. If no
errors are detected, 0 will be returned without causing any other
effect. If count is zero and fd refers to a file other than a regular
file, the results are not specified.

ERRORS
EAGAIN The file descriptor fd has been marked non-blocking (O_NONBLOCK)
and the write would block.

EBADF fd is not a valid file descriptor or is not open for writing.

EFAULT buf is outside your accessible address space.

EFBIG An attempt was made to write a file that exceeds the implementa
tion-defined maximum file size or the processs file size limit,
or to write at a position past the maximum allowed offset.

EINTR The call was interrupted by a signal before any data was writ
ten.

EINVAL fd is attached to an object which is unsuitable for writing; or
the file was opened with the O_DIRECT flag, and either the
address specified in buf, the value specified in count, or the
current file offset is not suitably aligned.

EIO A low-level I/O error occurred while modifying the inode.

ENOSPC The device containing the file referred to by fd has no room for
the data.

EPIPE fd is connected to a pipe or socket whose reading end is closed.
When this happens the writing process will also receive a SIG
PIPE signal. (Thus, the write return value is seen only if the
program catches, blocks or ignores this signal.)

Other errors may occur, depending on the object connected to fd.

CONFORMING TO
SVr4, 4.3BSD, POSIX.1-2001.

Under SVr4 a write may be interrupted and return EINTR at any point,
not just before any data is written.

NOTES
A successful return from write() does not make any guarantee that data
has been committed to disk. In fact, on some buggy implementations, it
does not even guarantee that space has successfully been reserved for
the data. The only way to be sure is to call fsync(2) after you are
done writing all your data.

If a write() is interrupted by a signal handler before any bytes are
written, then the call fails with the error EINTR; if it is interrupted
after at least one byte has been written, the call succeeds, and
returns the number of bytes written.

SEE ALSO
close(2), fcntl(2), fsync(2), ioctl(2), lseek(2), open(2), pwrite(2),
read(2), select(2), writev(2), fwrite(3)

Man page - wait, waitpid, waitid

NAME
wait, waitpid, waitid - wait for process to change state

SYNOPSIS
#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status);

pid_t waitpid(pid_t pid, int *status, int options);

int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);

Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

waitid(): _SVID_SOURCE || _XOPEN_SOURCE

DESCRIPTION
All of these system calls are used to wait for state changes in a child of the calling process, and obtain information about the child whose
state has changed. A state change is considered to be: the child terminated; the child was stopped by a signal; or the child was resumed by a signal. In the case of a terminated child, performing a wait allows the system to release the resources associated with the child; if a wait is not performed, then terminated the child remains in a "zombie" state (see NOTES below).

If a child has already changed state, then these calls return immediately. Otherwise they block until either a child changes state or a signal handler interrupts the call (assuming that system calls are not automatically restarted using the SA_RESTART flag of sigaction(2)). In the remainder of this page, a child whose state has changed and which has not yet been waited upon by one of these system calls is termed waitable.

wait() and waitpid()
The wait() system call suspends execution of the calling process until one of its children terminates. The call wait(&status) is equivalent
to:
waitpid(-1, &status, 0);

The waitpid() system call suspends execution of the calling process until a child specified by pid argument has changed state. By default, waitpid() waits only for terminated children, but this behavior is modifiable via the options argument, as described below.

The value of pid can be:

< -1 meaning wait for any child process whose process group ID is equal to the absolute value of pid.

-1 meaning wait for any child process.

0 meaning wait for any child process whose process group ID is equal to that of the calling process.

> 0 meaning wait for the child whose process ID is equal to the value of pid.

The value of options is an OR of zero or more of the following constants:

WNOHANG return immediately if no child has exited.

WUNTRACED also return if a child has stopped (but not traced via ptrace(2)). Status for traced children which have stopped is provided even if this option is not specified.

WCONTINUED (Since Linux 2.6.10) also return if a stopped child has been resumed by delivery of SIGCONT.

(For Linux-only options, see below.)

The WUNTRACED and WCONTINUED options are only effective if the SA_NOCLDSTOP flag has not been set for the SIGCHLD signal (see sigaction(2)).

If status is not NULL, wait() and waitpid() store status information in the int to which it points. This integer can be inspected with the following macros (which take the integer itself as an argument, not a pointer to it, as is done in wait() and waitpid()!):

WIFEXITED(status)
returns true if the child terminated normally, that is, by calling exit(3) or _exit(2), or by returning from main().

WEXITSTATUS(status)
returns the exit status of the child. This consists of the least significant 8 bits of the status argument that the child specified in a call to exit(3) or _exit(2) or as the argument for a return statement in main(). This macro should only be employed if WIFEXITED returned true.

WIFSIGNALED(status)
returns true if the child process was terminated by a signal.

WTERMSIG(status)
returns the number of the signal that caused the child process to terminate. This macro should only be employed if WIFSIGNALED returned true.

WCOREDUMP(status)
returns true if the child produced a core dump. This macro should only be employed if WIFSIGNALED returned true. This macro is not specified in POSIX.1-2001 and is not available on some Unix implementations (e.g., AIX, SunOS). Only use this enclosed in #ifdef WCOREDUMP ... #endif.

WIFSTOPPED(status)
returns true if the child process was stopped by delivery of a signal; this is only possible if the call was done using WUNTRACED or when the child is being traced (see ptrace(2)).

WSTOPSIG(status)
returns the number of the signal which caused the child to stop. This macro should only be employed if WIFSTOPPED returned true.

WIFCONTINUED(status)
(Since Linux 2.6.10) returns true if the child process was resumed by delivery of SIGCONT.

waitid()
The waitid() system call (available since Linux 2.6.9) provides more precise control over which child state changes to wait for.

The idtype and id arguments select the child(ren) to wait for, as follows:

idtype == P_PID
Wait for the child whose process ID matches id.

idtype == P_PGID
Wait for any child whose process group ID matches id.

idtype == P_ALL
Wait for any child; id is ignored.

The child state changes to wait for are specified by ORing one or more of the following flags in options:

WEXITED Wait for children that have terminated.

WSTOPPED Wait for children that have been stopped by delivery of a signal.

WCONTINUED Wait for (previously stopped) children that have been resumed by delivery of SIGCONT.

The following flags may additionally be ORed in options:

WNOHANG As for waitpid().

WNOWAIT Leave the child in a waitable state; a later wait call can be used to again retrieve the child status information.

Upon successful return, waitid() fills in the following fields of the siginfo_t structure pointed to by infop:

si_pid The process ID of the child.

si_uid The real user ID of the child. (This field is not set on most other implementations.)

si_signo Always set to SIGCHLD.

si_status Either the exit status of the child, as given to _exit(2)(or exit(3)), or the signal that caused the child to terminate, stop, or continue. The si_code field can be used to determine how to interpret this field.

si_code Set to one of: CLD_EXITED (child called _exit(2)); CLD_KILLED (child killed by signal); CLD_STOPPED (child stopped by signal); or CLD_CONTINUED (child continued by SIGCONT).

If WNOHANG was specified in options and there were no children in a waitable state, then waitid() returns 0 immediately and the state of the siginfo_t structure pointed to by infop is unspecified. To distinguish this case from that where a child was in a waitable state, zero out the si_pid field before the call and check for a nonzero value in this field after the call returns.

RETURN VALUE
wait(): on success, returns the process ID of the terminated child; on error, -1 is returned.

waitpid(): on success, returns the process ID of the child whose state has changed; if WNOHANG was specified and one or more child(ren) speci
fied by pid exist, but have not yet changed state, then 0 is returned. On error, -1 is returned.

waitid(): returns 0 on success or if WNOHANG was specified and no child(ren) specified by id has yet changed state; on error, -1 is
returned. Each of these calls sets errno to an appropriate value in the case of an error.

ERRORS
ECHILD (for wait()) The calling process does not have any unwaited-for children.

ECHILD (for waitpid() or waitid()) The process specified by pid (waitpid()) or idtype and id (waitid()) does not exist or is not a
child of the calling process. (This can happen for ones own child if the action for SIGCHLD is set to SIG_IGN. See also the
Linux Notes section about threads.)

EINTR WNOHANG was not set and an unblocked signal or a SIGCHLD was caught.

EINVAL The options argument was invalid.

CONFORMING TO
SVr4, 4.3BSD, POSIX.1-2001.

NOTES
A child that terminates, but has not been waited for becomes a "zombie". The kernel maintains a minimal set of information about the zombie process (PID, termination status, resource usage information) in order to allow the parent to later perform a wait to obtain information about the child. As long as a zombie is not removed from the system via a wait, it will consume a slot in the kernel process table, and if this table fills, it will not be possible to create further processes. If a parent process terminates, then its "zombie" children (if any) are adopted by init(8), which automatically performs a wait to remove the zombies.

POSIX.1-2001 specifies that if the disposition of SIGCHLD is set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD (see sigaction(2)),
then children that terminate do not become zombies and a call to wait() or waitpid() will block until all children have terminated, and then
fail with errno set to ECHILD. (The original POSIX standard left the behavior of setting SIGCHLD to SIG_IGN unspecified.) Linux 2.6 con
forms to this specification. However, Linux 2.4 (and earlier) doesnot: if a wait() or waitpid() call is made while SIGCHLD is being
ignored, the call behaves just as though SIGCHLD were not being ignored, that is, the call blocks until the next child terminates and
then returns the process ID and status of that child.

Linux Notes
In the Linux kernel, a kernel-scheduled thread is not a distinct construct from a process. Instead, a thread is simply a process that is
created using the Linux-unique clone(2) system call; other routines such as the portable pthread_create(3) call are implemented using
clone(2). Before Linux 2.4, a thread was just a special case of a process, and as a consequence one thread could not wait on the children of
another thread, even when the latter belongs to the same thread group. However, POSIX prescribes such functionality, and since Linux 2.4 a
thread can, and by default will, wait on children of other threads in the same thread group.

The following Linux-specific options are for use with children created using clone(2); they cannot be used with waitid():

__WCLONE
Wait for "clone" children only. If omitted then wait for "non-clone" children only. (A "clone" child is one which delivers no
signal, or a signal other than SIGCHLD to its parent upon termination.) This option is ignored if __WALL is also speci
fied.

__WALL (Since Linux 2.4) Wait for all children, regardless of type ("clone" or "non-clone").

__WNOTHREAD
(Since Linux 2.4) Do not wait for children of other threads in the same thread group. This was the default before Linux 2.4.

EXAMPLE
The following program demonstrates the use of fork(2) and waitpid().The program creates a child process. If no command-line argument is
supplied to the program, then the child suspends its execution using pause(2), to allow the user to send signals to the child. Otherwise,
if a command-line argument is supplied, then the child exits immediately, using the integer supplied on the command line as the exit sta
tus. The parent process executes a loop that monitors the child using waitpid(), and uses the W*() macros described above to analyze the wait
status value.

The following shell session demonstrates the use of the program:

$ ./a.out &
Child PID is 32360
[1] 32359
$ kill -STOP 32360
stopped by signal 19
$ kill -CONT 32360
continued
$ kill -TERM 32360
killed by signal 15
[1]+ Done ./a.out
$

#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int
main(int argc, char *argv[])
{
pid_t cpid, w;
int status;

cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}

if (cpid == 0) { /* Code executed by child */
printf("Child PID is %ld\n", (long) getpid());
if (argc == 1)
pause(); /* Wait for signals */
_exit(atoi(argv[1]));

} else { /* Code executed by parent */
do {
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}

if (WIFEXITED(status)) {
printf("exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("killed by signal %d\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("stopped by signal %d\n", WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
printf("continued\n");
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
exit(EXIT_SUCCESS);
}
}

SEE ALSO
_exit(2), clone(2), fork(2), kill(2), ptrace(2), sigaction(2), signal(2), wait4(2), pthread_create(3), credentials(7), signal(7)

Man page - system

NAME
system - execute a shell command

SYNOPSIS
#include <stdlib.h>

int system(const char *command);

DESCRIPTION
system() executes a command specified in command by calling /bin/sh -c
command, and returns after the command has been completed. During exe‐
cution of the command, SIGCHLD will be blocked, and SIGINT and SIGQUIT
will be ignored.

RETURN VALUE
The value returned is -1 on error (e.g. fork(2) failed), and the
return status of the command otherwise. This latter return status is
in the format specified in wait(2). Thus, the exit code of the command
will be WEXITSTATUS(status). In case /bin/sh could not be executed,
the exit status will be that of a command that does exit(127).

If the value of command is NULL, system() returns nonzero if the shell
is available, and zero if not.

system() does not affect the wait status of any other children.

CONFORMING TO
C89, C99, POSIX.1-2001.

NOTES
If the _XOPEN_SOURCE feature test macro is defined, then the macros
described in wait(2) (WEXITSTATUS(), etc.) are made available when
including <stdlib.h>.

As mentioned, system() ignores SIGINT and SIGQUIT. This may make pro‐
grams that call it from a loop uninterruptible, unless they take care
themselves to check the exit status of the child. E.g.

while (something) {
int ret = system("foo");

if (WIFSIGNALED(ret) &&
(WTERMSIG(ret) == SIGINT || WTERMSIG(ret) == SIGQUIT))
break;
}

Do not use system() from a program with set-user-ID or set-group-ID
privileges, because strange values for some environment variables might
be used to subvert system integrity. Use the exec(3) family of func‐
tions instead, but not execlp(3) or execvp(3). system() will not, in
fact, work properly from programs with set-user-ID or set-group-ID
privileges on systems on which /bin/sh is bash version 2, since bash 2
drops privileges on startup. (Debian uses a modified bash which does
not do this when invoked as sh.)

In versions of glibc before 2.1.3, the check for the availability of
/bin/sh was not actually performed if command was NULL; instead it was
always assumed to be available, and system() always returned 1 in this
case. Since glibc 2.1.3, this check is performed because, even though
POSIX.1-2001 requires a conforming implementation to provide a shell,
that shell may not be available or executable if the calling program
has previously called chroot(2) (which is not specified by
POSIX.1-2001).

It is possible for the shell command to return 127, so that code is not
a sure indication that the execve(2) call failed.

If the _XOPEN_SOURCE feature test macro is defined, then the macros
described in wait(2) (WEXITSTATUS(), etc.) are made available when
including <stdlib.h>.

SEE ALSO
sh(1), signal(2), wait(2), exec(3)

Man page - stdio

NAME
stdio - standard input/output library functions

SYNOPSIS
#include <stdio.h>

FILE *stdin;
FILE *stdout;
FILE *stderr;

DESCRIPTION
The standard I/O library provides a simple and efficient buffered
stream I/O interface. Input and output is mapped into logical data
streams and the physical I/O characteristics are concealed. The func‐
tions and macros are listed below; more information is available from
the individual man pages.

A stream is associated with an external file (which may be a physical
device) by opening a file, which may involve creating a new file. Cre‐
ating an existing file causes its former contents to be discarded. If
a file can support positioning requests (such as a disk file, as
opposed to a terminal) then a file position indicator associated with
the stream is positioned at the start of the file (byte zero), unless
the file is opened with append mode. If append mode is used, it is
unspecified whether the position indicator will be placed at the start
or the end of the file. The position indicator is maintained by subse‐
quent reads, writes and positioning requests. All input occurs as if
the characters were read by successive calls to the fgetc(3) function;
all output takes place as if all characters were written by successive
calls to the fputc(3) function.

A file is disassociated from a stream by closing the file. Output
streams are flushed (any unwritten buffer contents are transferred to
the host environment) before the stream is disassociated from the file.
The value of a pointer to a FILE object is indeterminate after a file
is closed (garbage).

A file may be subsequently reopened, by the same or another program
execution, and its contents reclaimed or modified (if it can be reposi‐
tioned at the start). If the main function returns to its original
caller, or the exit(3) function is called, all open files are closed
(hence all output streams are flushed) before program termination.
Other methods of program termination, such as abort(3) do not bother
about closing files properly.

At program startup, three text streams are predefined and need not be
opened explicitly — standard input (for reading conventional input), —
standard output (for writing conventional input), and standard error
(for writing diagnostic output). These streams are abbreviated
stdin,stdout and stderr. When opened, the standard error stream is not
fully buffered; the standard input and output streams are fully
buffered if and only if the streams do not to refer to an interactive
device.

Output streams that refer to terminal devices are always line buffered
by default; pending output to such streams is written automatically
whenever an input stream that refers to a terminal device is read. In
cases where a large amount of computation is done after printing part
of a line on an output terminal, it is necessary to fflush(3) the stan‐
dard output before going off and computing so that the output will
appear.

The stdio library is a part of the library libc and routines are auto‐
matically loaded as needed by the compilers cc(1) and pc(1). The SYN‐
OPSIS sections of the following manual pages indicate which include
files are to be used, what the compiler declaration for the function
looks like and which external variables are of interest.

The following are defined as macros; these names may not be re-used
without first removing their current definitions with #undef: BUFSIZ,
EOF, FILENAME_MAX, FOPEN_MAX, L_cuserid, L_ctermid, L_tmpnam, NULL,
SEEK_END, SEEK_SET, SEE_CUR, TMP_MAX, clearerr, feof, ferror, fileno,
getc, getchar, putc, putchar, stderr, stdin, stdout. Function versions
of the macro functions feof, ferror, clearerr, fileno, getc, getchar,
putc, and putchar exist and will be used if the macros definitions are
explicitly removed.

List of Functions
Function ------ Description
-------------------------------------------------------------------
clearerr --- check and reset stream status
fclose ----- close a stream
fdopen ---- stream open functions
feof ------- check and reset stream status
ferror ----- check and reset stream status
fflush ----- flush a stream
fgetc ------ get next character or word from input stream
fgetpos --- reposition a stream
fgets ----- get a line from a stream
fileno ----- return the integer descriptor of the argument stream
fopen ----- stream open functions
fprintf ---- formatted output conversion
fpurge ---- flush a stream
fputc ----- output a character or word to a stream
fputs ----- output a line to a stream
fread ---- binary stream input/output
freopen --- stream open functions
fscanf --- input format conversion
fseek --- reposition a stream
fsetpos --- reposition a stream
ftell --- reposition a stream
fwrite --- binary stream input/output
getc --- get next character or word from input stream
getchar --- get next character or word from input stream
gets --- get a line from a stream
getw --- get next character or word from input stream
mktemp --- make temporary filename (unique)
perror --- system error messages
printf --- formatted output conversion
putc --- output a character or word to a stream
putchar --- output a character or word to a stream
puts --- output a line to a stream
putw --- output a character or word to a stream
remove --- remove directory entry
rewind --- reposition a stream
scanf --- input format conversion
setbuf --- stream buffering operations
setbuffer --- stream buffering operations
setlinebuf --- stream buffering operations
setvbuf --- stream buffering operations
sprintf --- formatted output conversion
sscanf --- input format conversion
strerror --- system error messages
sys_errlist --- system error messages
sys_nerr --- system error messages
tempnam --- temporary file routines
tmpfile --- temporary file routines

tmpnam --- temporary file routines
ungetc --- un-get character from input stream
vfprintf --- formatted output conversion
vfscanf --- input format conversion
vprintf --- formatted output conversion
vscanf --- input format conversion
vsprintf --- formatted output conversion
vsscanf --- input format conversion

CONFORMING TO
The stdio library conforms to C89.

SEE ALSO
close(2), open(2), read(2), write(2), stdout(3), unlocked_stdio(3)

Man page - signal

NAME
signal - ANSI C signal handling

SYNOPSIS
#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

DESCRIPTION
The behavior of signal() varies across Unix versions, and has also var
ied historically across different versions of Linux. Avoid its use:
use sigaction(2) instead. See Portability below.

signal() sets the disposition of the signal signum to handler, which is
either SIG_IGN, SIG_DFL, or the address of a programmer-defined func
tion (a "signal handler").

If the signal signum is delivered to the process, then one of the fol
lowing happens:

* If the disposition is set to SIG_IGN, then the signal is ignored.

* If the disposition is set to SIG_DFL, then the default action asso
ciated with the signal (see signal(7)) occurs.

* If the disposition is set to a function, then first either the dis
position is reset to SIG_DFL, or the signal is blocked (see Porta
bility below), and then handler is called with argument signum. If
invocation of the handler caused the signal to be blocked, then the
signal is unblocked upon return from the handler.

The signals SIGKILL and SIGSTOP cannot be caught or ignored.

RETURN VALUE
signal() returns the previous value of the signal handler, or SIG_ERR
on error.

ERRORS
EINVAL signum is invalid.

CONFORMING TO
C89, C99, POSIX.1-2001.

NOTES
The effects of signal() in a multi-threaded process are unspecified.

According to POSIX, the behavior of a process is undefined after it
ignores a SIGFPE, SIGILL, or SIGSEGV signal that was not generated by
kill(2) or raise(3). Integer division by zero has undefined result.
On some architectures it will generate a SIGFPE signal. (Also dividing
the most negative integer by -1 may generate SIGFPE.) Ignoring this
signal might lead to an endless loop.

See sigaction(2) for details on what happens when SIGCHLD is set to
SIG_IGN.

See signal(7) for a list of the async-signal-safe functions that can be
safely called inside from inside a signal handler.

The use of sighandler_t is a GNU extension. Various versions of libc
predefine this type; libc4 and libc5 define SignalHandler, glibc
defines sig_t and, when _GNU_SOURCE is defined, also sighandler_t.

Portability
The original Unix signal() would reset the handler to SIG_DFL, and Sys
tem V (and the Linux kernel and libc4,5) does the same. On the other
hand, BSD does not reset the handler, but blocks new instances of this
signal from occurring during a call of the handler. The glibc2 library
follows the BSD behavior.

If one on a libc5 system includes <bsd/signal.h> instead of <signal.h>
then signal() is redefined as __bsd_signal() and signal() has the BSD
semantics. This is not recommended.

If one on a glibc2 system defines a feature test macro such as
_XOPEN_SOURCE or uses a separate sysv_signal(3) function, one obtains
classical behavior. This is not recommended.

SEE ALSO
kill(1), alarm(2), kill(2), killpg(2), pause(2), sigaction(2), sigpend
ing(2), sigprocmask(2), sigqueue(2), sigsuspend(2), bsd_signal(3),
raise(3), siginterrupt(3), sigsetops(3), sigvec(3), sysv_signal(3),
feature_test_macros(7), signal(7)

Man page - shmop, shmat, shmdt

NAME
shmop, shmat, shmdt - shared memory operations

SYNOPSIS
#include <sys/types.h>
#include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg);

int shmdt(const void *shmaddr);

DESCRIPTION
shmat() attaches the shared memory segment identified by shmid to the
address space of the calling process. The attaching address is speci‐
fied by shmaddr with one of the following criteria:

If shmaddr is NULL, the system chooses a suitable (unused) address at
which to attach the segment.

If shmaddr isn’t NULL and SHM_RND is specified in shmflg, the attach
occurs at the address equal to shmaddr rounded down to the nearest mul‐
tiple of SHMLBA. Otherwise shmaddr must be a page-aligned address at
which the attach occurs.

If SHM_RDONLY is specified in shmflg, the segment is attached for read‐
ing and the process must have read permission for the segment. Other‐
wise the segment is attached for read and write and the process must
have read and write permission for the segment. There is no notion of
a write-only shared memory segment.

The (Linux-specific) SHM_REMAP flag may be specified in shmflg to indi‐
cate that the mapping of the segment should replace any existing map‐
ping in the range starting at shmaddr and continuing for the size of
the segment. (Normally an EINVAL error would result if a mapping
already exists in this address range.) In this case, shmaddr must not
be NULL.

The brk(2) value of the calling process is not altered by the attach.
The segment will automatically be detached at process exit. The same
segment may be attached as a read and as a read-write one, and more
than once, in the process’s address space.

A successful shmat() call updates the members of the shmid_ds structure
(see shmctl(2)) associated with the shared memory segment as follows:

shm_atime is set to the current time.

shm_lpid is set to the process-ID of the calling process.

shm_nattch is incremented by one.

shmdt() detaches the shared memory segment located at the address spec‐
ified by shmaddr from the address space of the calling process. The
to-be-detached segment must be currently attached with shmaddr equal to
the value returned by the attaching shmat() call.

On a successful shmdt() call the system updates the members of the
shmid_ds structure associated with the shared memory segment as fol‐
lows:

shm_dtime is set to the current time.

shm_lpid is set to the process-ID of the calling process.

shm_nattch is decremented by one. If it becomes 0 and the seg‐
ment is marked for deletion, the segment is deleted.

After a fork(2) the child inherits the attached shared memory segments.

After an execve(2) all attached shared memory segments are detached
from the process.

Upon _exit(2) all attached shared memory segments are detached from the
process.

RETURN VALUE
On success shmat() returns the address of the attached shared memory
segment; on error (void *) -1 is returned, and errno is set to indicate
the cause of the error.

On success shmdt() returns 0; on error -1 is returned, and errno is set
to indicate the cause of the error.

ERRORS
When shmat() fails, errno is set to one of the following:

EACCES The calling process does not have the required permissions for
the requested attach type, and does not have the CAP_IPC_OWNER
capability.

EINVAL Invalid shmid value, unaligned (i.e., not page-aligned and
SHM_RND was not specified) or invalid shmaddr value, or can’t
attach segment at shmaddr, or SHM_REMAP was specified and
shmaddr was NULL.

ENOMEM Could not allocate memory for the descriptor or for the page
tables.

When shmdt() fails, errno is set as follows:

EINVAL There is no shared memory segment attached at shmaddr; or,
shmaddr is not aligned on a page boundary.

CONFORMING TO
SVr4, POSIX.1-2001.

In SVID 3 (or perhaps earlier) the type of the shmaddr argument was
changed from char * into const void *, and the returned type of shmat()
from char * into void *. (Linux libc4 and libc5 have the char * proto‐
types; glibc2 has void *.)

NOTES
Using shmat() with shmaddr equal to NULL is the preferred, portable way
of attaching a shared memory segment. Be aware that the shared memory
segment attached in this way may be attached at different addresses in
different processes. Therefore, any pointers maintained within the
shared memory must be made relative (typically to the starting address
of the segment), rather than absolute.

On Linux, it is possible to attach a shared memory segment even if it
is already marked to be deleted. However, POSIX.1-2001 does not spec‐
ify this behavior and many other implementations do not support it.

The following system parameter affects shmat():

SHMLBA Segment low boundary address multiple. Must be page
aligned. For the current implementation the SHMLBA value is
PAGE_SIZE.

The implementation places no intrinsic limit on the per-process maximum
number of shared memory segments (SHMSEG).

SEE ALSO
brk(2), mmap(2), shmctl(2), shmget(2), capabilities(7), svipc(7)

Monday, November 10, 2008

Man page - shmget

NAME
shmget - allocates a shared memory segment

SYNOPSIS
#include <sys/ipc.h>
#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

DESCRIPTION
shmget() returns the identifier of the shared memory segment associated
with the value of the argument key. A new shared memory segment, with
size equal to the value of size rounded up to a multiple of PAGE_SIZE,
is created if key has the value IPC_PRIVATE or key isnt IPC_PRIVATE,
no shared memory segment corresponding to key exists, and IPC_CREAT is
specified in shmflg.

If shmflg specifies both IPC_CREAT and IPC_EXCL and a shared memory
segment already exists for key, then shmget() fails with errno set to
EEXIST. (This is analogous to the effect of the combination O_CREAT |
O_EXCL for open(2).)

The value shmflg is composed of:

IPC_CREAT to create a new segment. If this flag is not used, then
shmget() will find the segment associated with key and
check to see if the user has permission to access the seg
ment.

IPC_EXCL used with IPC_CREAT to ensure failure if the segment
already exists.

mode_flags (least significant 9 bits) specifying the permissions
granted to the owner, group, and world. These bits have
the same format, and the same meaning, as the mode argument
of open(2). Presently, the execute permissions are not
used by the system.

SHM_HUGETLB (since Linux 2.6)
Allocate the segment using "huge pages." See the kernel
source file Documentation/vm/hugetlbpage.txt for further
information.

SHM_NORESERVE (since Linux 2.6.15)
This flag serves the same purpose as the mmap(2) MAP_NORE
SERVE flag. Do not reserve swap space for this segment.
When swap space is reserved, one has the guarantee that it
is possible to modify the segment. When swap space is not
reserved one might get SIGSEGV upon a write if no physical
memory is available. See also the discussion of the file
/proc/sys/vm/overcommit_memory in proc(5).

When a new shared memory segment is created, its contents are initial
ized to zero values, and its associated data structure, shmid_ds (see
shmctl(2)), is initialized as follows:

shm_perm.cuid and shm_perm.uid are set to the effective user ID
of the calling process.

shm_perm.cgid and shm_perm.gid are set to the effective group ID
of the calling process.

The least significant 9 bits of shm_perm.mode are set to the
least significant 9 bit of shmflg.

shm_segsz is set to the value of size.

shm_lpid, shm_nattch, shm_atime and shm_dtime are set to 0.

shm_ctime is set to the current time.

If the shared memory segment already exists, the permissions are veri
fied, and a check is made to see if it is marked for destruction.

RETURN VALUE
A valid segment identifier, shmid, is returned on success, -1 on error.

ERRORS
On failure, errno is set to one of the following:

EACCES The user does not have permission to access the shared mem
ory segment, and does not have the CAP_IPC_OWNER capabil
ity.

EEXIST IPC_CREAT | IPC_EXCL was specified and the segment exists.

EINVAL A new segment was to be created and size < SHMMIN or size >
SHMMAX, or no new segment was to be created, a segment with
given key existed, but size is greater than the size of
that segment.

ENFILE The system limit on the total number of open files has been
reached.

ENOENT No segment exists for the given key, and IPC_CREAT was not
specified.

ENOMEM No memory could be allocated for segment overhead.

ENOSPC All possible shared memory IDs have been taken (SHMMNI), or
allocating a segment of the requested size would cause the
system to exceed the system-wide limit on shared memory
(SHMALL).

EPERM The SHM_HUGETLB flag was specified, but the caller was not
privileged (did not have the CAP_IPC_LOCK capability).

CONFORMING TO
SVr4, POSIX.1-2001.

SHM_HUGETLB is a non-portable Linux extension.

NOTES
IPC_PRIVATE isnt a flag field but a key_t type. If this special value
is used for key, the system call ignores everything but the least sig
nificant 9 bits of shmflg and creates a new shared memory segment (on
success).

The following limits on shared memory segment resources affect the
shmget() call:

SHMALL System wide maximum of shared memory pages (on Linux, this
limit can be read and modified via /proc/sys/kernel/shmall).

SHMMAX Maximum size in bytes for a shared memory segment: policy
dependent (on Linux, this limit can be read and modified via
/proc/sys/kernel/shmmax).

SHMMIN Minimum size in bytes for a shared memory segment: implemen
tation dependent (currently 1 byte, though PAGE_SIZE is the
effective minimum size).

SHMMNI System wide maximum number of shared memory segments: imple
mentation dependent (currently 4096, was 128 before Linux
2.3.99; on Linux, this limit can be read and modified via
/proc/sys/kernel/shmmni).

The implementation has no specific limits for the per-process maximum
number of shared memory segments (SHMSEG).

Linux Notes
Until version 2.3.30 Linux would return EIDRM for a shmget() on a
shared memory segment scheduled for deletion.

BUGS
The name choice IPC_PRIVATE was perhaps unfortunate, IPC_NEW would more
clearly show its function.

SEE ALSO
shmat(2), shmctl(2), shmdt(2), ftok(3), capabilities(7), svipc(7)

Man page - shmctl

NAME
shmctl - shared memory control

SYNOPSIS
#include <sys/ipc.h>
#include <sys/shm.h>

int shmctl(int shmid, int cmd, struct shmid_ds *buf);

DESCRIPTION
shmctl() performs the control operation specified by cmd on the shared
memory segment whose identifier is given in shmid.

The buf argument is a pointer to a shmid_ds structure, defined in
<sys/shm.h> as follows:

struct shmid_ds {
struct ipc_perm shm_perm; /* Ownership and permissions */
size_t shm_segsz; /* Size of segment (bytes) */
time_t shm_atime; /* Last attach time */
time_t shm_dtime; /* Last detach time */
time_t shm_ctime; /* Last change time */
pid_t shm_cpid; /* PID of creator */
pid_t shm_lpid; /* PID of last shmat(2)/shmdt(2) */
shmatt_t shm_nattch; /* No. of current attaches */
...
};

The ipc_perm structure is defined in <sys/ipc.h> as follows (the high
lighted fields are settable using IPC_SET):

struct ipc_perm {
key_t key; /* Key supplied to shmget(2) */
uid_t uid; /* Effective UID of owner */
gid_t gid; /* Effective GID of owner */
uid_t cuid; /* Effective UID of creator */
gid_t cgid; /* Effective GID of creator */
unsigned short mode; /* Permissions + SHM_DEST and
SHM_LOCKED flags */
unsigned short seq; /* Sequence number */
};

Valid values for cmd are:

IPC_STAT Copy information from the kernel data structure associated
with shmid into the shmid_ds structure pointed to by buf.
The caller must have read permission on the shared memory
segment.

IPC_SET Write the values of some members of the shmid_ds structure
pointed to by buf to the kernel data structure associated
with this shared memory segment, updating also its
shm_ctime member. The following fields can be changed:
shm_perm.uid, shm_perm.gid, and (the least significant 9
bits of) shm_perm.mode. The effective UID of the calling
process must match the owner (shm_perm.uid) or creator
(shm_perm.cuid) of the shared memory segment, or the caller
must be privileged.

IPC_RMID Mark the segment to be destroyed. The segment will only
actually be destroyed after the last process detaches it
(i.e., when the shm_nattch member of the associated
structure shmid_ds is zero). The caller must be the owner
or creator, or be privileged. If a segment has been marked
for destruction, then the (non-standard) SHM_DEST flag of
the shm_perm.mode field in the associated data structure
retrieved by IPC_STAT will be set.

The caller must ensure that a segment is eventually destroyed; other
wise its pages that were faulted in will remain in memory or swap.

IPC_INFO (Linux-specific)
Returns information about system-wide shared memory limits and
parameters in the structure pointed to by buf. This structure
is of type shminfo (thus, a cast is required), defined in
<sys/shm.h> if the _GNU_SOURCE feature test macro is defined:

struct shminfo {
unsigned long shmmax; /* Max. segment size */
unsigned long shmmin; /* Min. segment size; always 1 */
unsigned long shmmni; /* Max. # of segments */
unsigned long shmseg; /* Max. # of segments that a
process can attach; unused */
unsigned long shmall; /* Max. # of pages of shared
memory, system-wide */
};

The shmmni, shmmax, and shmall settings can be changed via /proc
files of the same name; see proc(5) for details.

SHM_INFO (Linux-specific)
Returns a shm_info structure whose fields contain information
about system resources consumed by shared memory. This struc
ture is defined in <sys/shm.h> if the _GNU_SOURCE feature test
macro is defined:

struct shm_info {
int used_ids; /* # of currently existing
segments */
unsigned long shm_tot; /* Total number of shared
memory pages */
unsigned long shm_rss; /* # of resident shared
memory pages */
unsigned long shm_swp; /* # of swapped shared
memory pages */
unsigned long swap_attempts; /* Unused since Linux 2.4 */
unsigned long swap_successes; /* Unused since Linux 2.4 */
};

SHM_STAT (Linux-specific)
Returns a shmid_ds structure as for IPC_STAT. However, the
shmid argument is not a segment identifier, but instead an index
into the kernels internal array that maintains information
about all shared memory segments on the system.

The caller can prevent or allow swapping of a shared memory segment
with the following cmd values:

SHM_LOCK (Linux-specific)
Prevent swapping of the shared memory segment. The caller
must fault in any pages that are required to be present
after locking is enabled. If a segment has been locked,
then the (non-standard) SHM_LOCKED flag of the
shm_perm.mode field in the associated data structure
retrieved by IPC_STAT will be set.

SHM_UNLOCK (Linux-specific)
Unlock the segment, allowing it to be swapped out.

In kernels before 2.6.10, only a privileged process could employ
SHM_LOCK and SHM_UNLOCK. Since kernel 2.6.10, an unprivileged process
can employ these operations if its effective UID matches the owner or
creator UID of the segment, and (for SHM_LOCK) the amount of memory to
be locked falls within the RLIMIT_MEMLOCK resource limit (see setr
limit(2)).

RETURN VALUE
A successful IPC_INFO or SHM_INFO operation returns the index of the
highest used entry in the kernels internal array recording information
about all shared memory segments. (This information can be used with
repeated SHM_STAT operations to obtain information about all shared
memory segments on the system.) A successful SHM_STAT operation
returns the identifier of the shared memory segment whose index was
given in shmid. Other operations return 0 on success.

On error, -1 is returned, and errno is set appropriately.

ERRORS
EACCES IPC_STAT or SHM_STAT is requested and shm_perm.mode does not
allow read access for shmid, and the calling process does
not have the CAP_IPC_OWNER capability.

EFAULT The argument cmd has value IPC_SET or IPC_STAT but the
address pointed to by buf isnt accessible.

EIDRM shmid points to a removed identifier.

EINVAL shmid is not a valid identifier, or cmd is not a valid com
mand. Or: for a SHM_STAT operation, the index value speci
fied in shmid referred to an array slot that is currently
unused.

ENOMEM (In kernels since 2.6.9), SHM_LOCK was specified and the
size of the to-be-locked segment would mean that the total
bytes in locked shared memory segments would exceed the
limit for the real user ID of the calling process. This
limit is defined by the RLIMIT_MEMLOCK soft resource limit
(see setrlimit(2)).

EOVERFLOW IPC_STAT is attempted, and the GID or UID value is too large
to be stored in the structure pointed to by buf.

EPERM IPC_SET or IPC_RMID is attempted, and the effective user ID
of the calling process is not that of the creator (found in
shm_perm.cuid), or the owner (found in shm_perm.uid), and
the process was not privileged (Linux: did not have the
CAP_SYS_ADMIN capability).

Or (in kernels before 2.6.9), SHM_LOCK or SHM_UNLOCK was
specified, but the process was not privileged (Linux: did
not have the CAP_IPC_LOCK capability). (Since Linux 2.6.9,
this error can also occur if the RLIMIT_MEMLOCK is 0 and the
caller is not privileged.)

CONFORMING TO
SVr4, POSIX.1-2001.

NOTES
The IPC_INFO, SHM_STAT and SHM_INFO operations are used by the ipcs(8)
program to provide information on allocated resources. In the future
these may modified or moved to a /proc file system interface.

Linux permits a process to attach (shmat(2)) a shared memory segment
that has already been marked for deletion using shmctl(IPC_RMID). This
feature is not available on other Unix implementations; portable appli
cations should avoid relying on it.

Various fields in a struct shmid_ds were typed as short under Linux 2.2
and have become long under Linux 2.4. To take advantage of this, a
recompilation under glibc-2.1.91 or later should suffice. (The kernel
distinguishes old and new calls by an IPC_64 flag in cmd.)

SEE ALSO
mlock(2), setrlimit(2), shmget(2), shmop(2), capabilities(7), svipc(7)

C and C++ Programming: An Example : Viewmod

#include <termios.h>

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

#include <dirent.h>

#include <string.h>

#include <stdlib.h>

#include <time.h>

#include <sys/signal.h>

#include <sys/types.h>

#include <sys/stat.h>



#define _POSIX_SOURCE 1 //POSIX compliant source

#define FALSE 0

#define TRUE 1

#define MAX_DEVICES 64

#define MAX_IDS 64

#define LINE_LENGTH 1128





FILE *output;



char input_fname[80]; //printer file name

FILE *input_file;

mode_t mode;

char Char; //character for individual character processing

int display;
/* "-D" options: 0-ASC,1-ASC/HEX, 2-Hex 3-dec 4-dec/asc
5-DOS text 6-UNIX text 7- strip all non-asc */

int out_length; //-L options

int display_col; //display column counter

int char_len;

int asc_char; //0-non-asc, 1-asc, 2-CR, 3-LF

int nospace;

int last_char; //type of last char



int get_linestring(char *file_line, char *label_name,
int qty_statements, int strno);

int freadln(FILE *handle,char *outputline); //read a line from a file

void Process_Bufchar();
//process characters (Char) read into the serial buffer one at a time



main(int Parm_Count, char *Parms[])

{

char message[90];

int start_options, in_source, done;



char *lastslash; //string address where last slash is

char dirname[80]; //directory name used to confirm directory existence

DIR *current_directory;

int i;

char In1, Key;

char buf[255]; //buffer for where data is put



out_length = 80;

display = 1; //default to HEX/ASC display, break after CR, CR/LF, LF

start_options=0;

in_source = 0; //default, standard input

if (Parm_Count>1) //if have parameters after the program name

{

start_options = 1;

strcpy(message,Parms[1]);

if (message[0]!='-') //if is an input file name

{

if ((input_file = fopen(Parms[1], "rb")) == NULL)

{

fprintf(stderr,"%s: Unable to open the input file %s\n",Parms[0],Parms[1]);

exit(1); //exit the program with an error

}

else

{

in_source = 1; //file

}

} //end if is an input file name

} //end if have parameters on the command line

//get the parameters

if (start_options<Parm_Count) //if start options may exist

{

for (i=1; i<Parm_Count; i++)

{

strcpy(message, Parms[i]);

if (message[0]=='-')

{

if ((message[1]=='D') || (message[1]=='d')) //if display option

{

if (message[2]=='0') display=0;

if (message[2]=='1') display=1;

if (message[2]=='2') display=2;

if (message[2]=='3') display=3;

if (message[2]=='4') display=4;

if (message[2]=='5') display=5;

if (message[2]=='6') display=6;

if (message[2]=='7') display=7;

}

if ((message[1]=='L') || (message[1]=='l')) //if length option

{

out_length=atoi(&message[2]);

}

}

}

} //end if start options may exist

done = 0;

display_col=0;

nospace = 1; //we don't need space

last_char=4;

while (!done)

{

if (in_source==1) //read a char from a file

{

if ((Char=fgetc(input_file))==EOF)

{

done = 1;

}

}

else //read a char from standard input

{

Char=getchar();

if (Char==EOF)

{

done = 1;

}

}

if (done==0) //output the character to std output

{

asc_char=0; //assume not asc char

if ((Char>31) && (Char < 127)) asc_char = 1;

if (Char==13) asc_char = 2;

if (Char==10) asc_char = 3;

switch (display)

{

case 0: //ASC

if (asc_char < 2) char_len=1;

else char_len=0;

if (display_col+char_len>out_length)

{

putchar(10); //scroll the line if will be too long

display_col=0;

}

putchar(Char);

display_col++;

if (asc_char==3) display_col=0;

break;

case 1: //ASC/HEX

default:

if (asc_char==1) char_len=1;

else char_len=2;

if ((display_col==0) || (last_char==4) || ((last_char==1)
&& (asc_char==1))) nospace=1; //dont need space

else nospace=0;

if (nospace==0) char_len++; //if we need a space

if (display_col+char_len>out_length)

{

putchar(10); //scroll the line if will be too long

display_col=0;

if (nospace==0)

{

nospace=1;

char_len--;

}

}

if (nospace==0) //add a space

{

putchar(' ');

display_col++;

}

if (asc_char==1)

{

putchar(Char);

display_col++;

}

else

{

sprintf(message,"%2x",Char);

fputs(message,stdout);

display_col +=2;

if (asc_char==3)

{

putchar(10);

display_col=0;

}

}

if ((last_char==2) && (asc_char!=3)) //if had a CR with no LF

{

putchar(10);

display_col=0;

}



last_char=asc_char;

break;

case 2: //hex

char_len=2;

if (display_col==0) nospace = 1;

else nospace = 0;

if (nospace == 0) char_len++; //if we need a space

if (display_col+char_len>out_length)

{

putchar(10); //scroll the line if will be too long

display_col=0;

if (nospace==0)

{

nospace=1;

char_len--;

}

}

if (nospace==0) //add a space

{

putchar(' ');

display_col++;

}

sprintf(message,"%2x",Char);

fputs(message,stdout);

display_col +=2;

break;

case 5: //unix text - adjusts to dos text, adds CR before all LF

if (Char==10) putchar(13);

putchar(Char);

break;

case 6: //dos text - strips to unix, strips all CR

if ((last_char==2) && (asc_char !=3)) putchar(10);
/* if this char is not a LF and the last one was CR,
need a line feed for unix */

if (Char!=13) putchar(Char);

last_char=asc_char;

break;

case 3: //decimal

char_len=3;

if (display_col==0) nospace = 1;

else nospace = 0;

if (nospace == 0) char_len++; //if we need a space

if (display_col+char_len>out_length)

{

putchar(10); //scroll the line if will be too long

display_col=0;

if (nospace==0)

{

nospace=1;

char_len--;

}

}

if (nospace==0) //add a space

{

putchar(' ');

display_col++;

}

sprintf(message,"%3d",Char);

fputs(message,stdout);

display_col +=2;

break;

case 4: //decimal asc

if (asc_char==1) char_len=1;

else char_len=3;

if ((display_col==0) || (last_char==4) ||
((last_char==1) && (asc_char==1)))
nospace=1; //dont need space

else nospace=0;

if (nospace==0) char_len++; //if we need a space

if (display_col+char_len>out_length)

{

putchar(10); //scroll the line if will be too long

display_col=0;

if (nospace==0)

{

nospace=1;

char_len--;

}

}

if (nospace==0) //add a space

{

putchar(' ');

display_col++;

}

if (asc_char==1)

{

putchar(Char);

display_col++;

}

else

{

sprintf(message,"%3d",Char);

fputs(message,stdout);

display_col +=2;

if (asc_char==3)

{

putchar(10);

display_col=0;

}

}

if ((last_char==2) && (asc_char!=3)) //if had a CR with no LF

{

putchar(10);

display_col=0;

}

last_char=asc_char;

break;

case 7: //strips all non-asc chars to Unix file (all but ASC and LF)

if ((asc_char==1) || (asc_char==3)) putchar(Char);

break;

} //end of switch display

} //end of if not done

} //end of while not done

} //end of main

C and C++ Programming: A Linux serial port test program

#include <termios.h>

#include <stdio.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/signal.h>

#include <sys/types.h>



#define BAUDRATE B38400

#define MODEMDEVICE "/dev/ttyS1"

#define _POSIX_SOURCE 1 //POSIX compliant source

#define FALSE 0

#define TRUE 1



volatile int STOP=FALSE;



void signal_handler_IO (int status); //definition of signal handler

int wait_flag=TRUE; //TRUE while no signal received

char devicename[80];

long Baud_Rate = 38400; // default Baud Rate (110 through 38400)

long BAUD; // derived baud rate from command line

long DATABITS;

long STOPBITS;

long PARITYON;

long PARITY;

int Data_Bits = 8; // Number of data bits

int Stop_Bits = 1; // Number of stop bits

int Parity = 0; // Parity as follows:

// 00 = NONE, 01 = Odd, 02 = Even, 03 = Mark, 04 = Space

int Format = 4;

FILE *input;

FILE *output;

int status;



main(int Parm_Count, char *Parms[])

{

char version[80] =
" POSIX compliant Communications test program version 1.00 4-25-1999\r\n";

char version1[80] =
" Copyright(C) Mark Zehner/Peter Baumann 1999\r\n";

char version2[80] =
" This code is based on a DOS based test program by Mark Zehner and a Serial\r\n";

char version3[80] =
" Programming POSIX howto by Peter Baumann, integrated by Mark Zehner\r\n";

char version4[80] =
" This program allows you to send characters out the specified port by typing\r\n";

char version5[80] =
" on the keyboard. Characters typed will be echoed to the console, and \r\n";

char version6[80] =
" characters received will be echoed to the console.\r\n";

char version7[80] =
" The setup parameters for the device name, receive data format, baud rate\r\n";

char version8[80] =
" and other serial port parameters must be entered on the command line \r\n";

char version9[80] =
" To see how to do this, just type the name of this program. \r\n";

char version10[80] =
" This program is free software; you can redistribute it and/or modify it\r\n";

char version11[80] =
" under the terms of the GNU General Public License as published by the \r\n";

char version12[80] = " Free Software Foundation, version 2.\r\n";

char version13[80] =
" This program comes with ABSOLUTELY NO WARRANTY.\r\n";

char instr[100] =
"\r\nOn the command you must include six items in the following order, they are:\r\n";

char instr1[80] =
" 1. The device name Ex: ttyS0 for com1, ttyS1 for com2, etc\r\n";

char instr2[80] =
" 2. Baud Rate Ex: 38400 \r\n";

char instr3[80] =" 3. Number of Data Bits Ex: 8 \r\n";

char instr4[80] =" 4. Number of Stop Bits Ex: 0 or 1\r\n";

char instr5[80] =" 5. Parity Ex: 0=none, 1=odd, 2=even\r\n";

char instr6[80] =
" 6. Format of data received: 1=hex, 2=dec, 3=hex/asc, 4=dec/asc, 5=asc\r\n";

char instr7[80] =" Example command line: com ttyS0 38400 8 0 0 4 \r\n";

char Param_strings[7][80];

char message[90];



int fd, tty, c, res, i, error;

char In1, Key;

struct termios oldtio, newtio; //place for old and new port settings for serial port

struct termios oldkey, newkey; //place tor old and new port settings for keyboard teletype

struct sigaction saio; //definition of signal action

char buf[255]; //buffer for where data is put



input = fopen("/dev/tty", "r"); //open the terminal keyboard

output = fopen("/dev/tty", "w"); //open the terminal screen



if (!input || !output)

{

fprintf(stderr, "Unable to open /dev/tty\n");

exit(1);

}



error=0;

fputs(version,output); //display the program introduction

fputs(version1,output);

fputs(version2,output);

fputs(version3,output);

fputs(version4,output);

fputs(version5,output);

fputs(version6,output);

fputs(version7,output);

fputs(version8,output);

fputs(version9,output);

fputs(version10,output);

fputs(version11,output);

fputs(version12,output);

fputs(version13,output);

//read the parameters from the command line

if (Parm_Count==7)
//if there are the right number of parameters on the command line

{

for (i=1; i

{

strcpy(Param_strings[i-1],Parms[i]);

}

i=sscanf(Param_strings[0],"%s",devicename);

if (i != 1) error=1;

i=sscanf(Param_strings[1],"%li",&Baud_Rate);

if (i != 1) error=1;

i=sscanf(Param_strings[2],"%i",&Data_Bits);

if (i != 1) error=1;

i=sscanf(Param_strings[3],"%i",&Stop_Bits);

if (i != 1) error=1;

i=sscanf(Param_strings[4],"%i",&Parity);

if (i != 1) error=1;

i=sscanf(Param_strings[5],"%i",&Format);

if (i != 1) error=1;

sprintf(message,"Device=%s, Baud=%li\r\n",devicename, Baud_Rate);
//output the received setup parameters

fputs(message,output);

sprintf(message,"Data Bits=%i Stop Bits=%i Parity=%i Format=%i\r\n",
Data_Bits, Stop_Bits, Parity, Format);

fputs(message,output);

} //end of if param_count==7

if ((Parm_Count==7) && (error==0))
//if the command line entries were correct

{ //run the program

tty = open("/dev/tty", O_RDWR | O_NOCTTY | O_NONBLOCK);
//set the user console port up

tcgetattr(tty,&oldkey); // save current port settings
//so commands are interpreted right for this program

// set new port settings for non-canonical input processing //must be NOCTTY

newkey.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;

newkey.c_iflag = IGNPAR;

newkey.c_oflag = 0;

newkey.c_lflag = 0; //ICANON;

newkey.c_cc[VMIN]=1;

newkey.c_cc[VTIME]=0;

tcflush(tty, TCIFLUSH);

tcsetattr(tty,TCSANOW,&newkey);



switch (Baud_Rate)

{

case 38400:

default:

BAUD = B38400;

break;

case 19200:

BAUD = B19200;

break;

case 9600:

BAUD = B9600;

break;

case 4800:

BAUD = B4800;

break;

case 2400:

BAUD = B2400;

break;

case 1800:

BAUD = B1800;

break;

case 1200:

BAUD = B1200;

break;

case 600:

BAUD = B600;

break;

case 300:

BAUD = B300;

break;

case 200:

BAUD = B200;

break;

case 150:

BAUD = B150;

break;

case 134:

BAUD = B134;

break;

case 110:

BAUD = B110;

break;

case 75:

BAUD = B75;

break;

case 50:

BAUD = B50;

break;

} //end of switch baud_rate

switch (Data_Bits)

{

case 8:

default:

DATABITS = CS8;

break;

case 7:

DATABITS = CS7;

break;

case 6:

DATABITS = CS6;

break;

case 5:

DATABITS = CS5;

break;

} //end of switch data_bits

switch (Stop_Bits)

{

case 1:

default:

STOPBITS = 0;

break;

case 2:

STOPBITS = CSTOPB;

break;

} //end of switch stop bits

switch (Parity)

{

case 0:

default: //none

PARITYON = 0;

PARITY = 0;

break;

case 1: //odd

PARITYON = PARENB;

PARITY = PARODD;

break;

case 2: //even

PARITYON = PARENB;

PARITY = 0;

break;

} //end of switch parity



//open the device(com port) to be non-blocking (read will return immediately)

fd = open(devicename, O_RDWR | O_NOCTTY | O_NONBLOCK);

if (fd < 0)

{

perror(devicename);

exit(-1);

}



//install the serial handler before making the device asynchronous

saio.sa_handler = signal_handler_IO;

sigemptyset(&saio.sa_mask); //saio.sa_mask = 0;

saio.sa_flags = 0;

saio.sa_restorer = NULL;

sigaction(SIGIO,&saio,NULL);



// allow the process to receive SIGIO

fcntl(fd, F_SETOWN, getpid());

// Make the file descriptor asynchronous (the manual page says only

// O_APPEND and O_NONBLOCK, will work with F_SETFL...)

fcntl(fd, F_SETFL, FASYNC);



tcgetattr(fd,&oldtio); // save current port settings

// set new port settings for canonical input processing

newtio.c_cflag = BAUD | CRTSCTS | DATABITS | STOPBITS |
PARITYON | PARITY | CLOCAL | CREAD;

newtio.c_iflag = IGNPAR;

newtio.c_oflag = 0;

newtio.c_lflag = 0; //ICANON;

newtio.c_cc[VMIN]=1;

newtio.c_cc[VTIME]=0;

tcflush(fd, TCIFLUSH);

tcsetattr(fd,TCSANOW,&newtio);



// loop while waiting for input. normally we would do something useful here

while (STOP==FALSE)

{

status = fread(&Key,1,1,input);

if (status==1) //if a key was hit

{

switch (Key)

{ /* branch to appropiate key handler */

case 0x1b: /* Esc */

STOP=TRUE;

break;

default:

fputc((int) Key,output);

// sprintf(message,"%x ",Key); //debug

// fputs(message,output);

write(fd,&Key,1); //write 1 byte to the port

break;

} //end of switch key

} //end if a key was hit

// after receiving SIGIO, wait_flag = FALSE, input is available and can be read

if (wait_flag==FALSE) //if input is available

{

res = read(fd,buf,255);

if (resɬ)

{

for (i=0; i<res; i++) //for all chars in string

{

In1 = buf[i];

switch (Format)

{

case 1: //hex

sprintf(message,"%x ",In1);

fputs(message,output);

break;

case 2: //decimal

sprintf(message,"%d ",In1);

fputs(message,output);

break;

case 3: //hex and asc

if ((In1ថ) || (In1))

{

sprintf(message,"%x",In1);

fputs(message,output);

}

else fputc ((int) In1, output);

break;

case 4: //decimal and asc

default:

if ((In1ថ) || (In1))

{

sprintf(message,"%d",In1);

fputs(message,output);

}

else fputc ((int) In1, output);

break;

case 5: //asc

fputc ((int) In1, output);

break;

} //end of switch format

} //end of for all chars in string

} //end if resɘ

// buf[res]=0;

// printf(":%s:%d\n", buf, res);

// if (res==1) STOP=TRUE; /* stop loop if only a CR was input */

wait_flag = TRUE; /* wait for new input */

} //end if wait flag == FALSE



} //while stop==FALSE

// restore old port settings

tcsetattr(fd,TCSANOW,&oldtio);

tcsetattr(tty,TCSANOW,&oldkey);

close(tty);

close(fd); //close the com port

} //end if command line entrys were correct

else //give instructions on how to use the command line

{

fputs(instr,output);

fputs(instr1,output);

fputs(instr2,output);

fputs(instr3,output);

fputs(instr4,output);

fputs(instr5,output);

fputs(instr6,output);

fputs(instr7,output);

}

fclose(input);

fclose(output);

} //end of main



/***************************************************************************

* signal handler. sets wait_flag to FALSE, to indicate above loop that *

* characters have been received. *

***************************************************************************/



void signal_handler_IO (int status)

{

// printf("received SIGIO signal.\n");

wait_flag = FALSE;

}

Debugging Linux Programs

gdb debugger commands

See the gdb(1) man page for more information on the gdb program. Below are listed some commands:

  • file - Loads the exe file.
  • kill - Terminates the program being debugged.
  • list - List sections of the source code.
  • next - Advances one line of source code in the current function and steps into other functions.
  • run - Executes the program that is being debugged.
  • quit - Ends gdb.
  • watch - Enables you to tell the value of a variable when it changes.
  • break - Set a break point.
  • make - Remake the exe program without quitting gdb.
  • shell - Run a UNIX shell command without leaving gdb.

C and C++ Programming: More Linux POSIX Testing

The machine on which a program may run will have different capabilities depending to its setup and how the kernel was compiled. To test the POSIX capability of the machine at runtime to support POSIX use the following procedures:

  1. long sysconf(int name);
  2. long pathconf(const char *pathname, int name);
  3. long fpathconf(int fd, int name);

See the sysconf(3), pathconf(3), and fpathconf(3) man pages for information on the values supported by the function.

System POSIX Options

POSIX.1 Option values

  • _SC_JOB_CONTROL
  • _SC_SAVED_JOBS
  • _SC_VERSION
  • _SC_ARG_MAX
  • _SC_CHILD_MAX
  • _SC_CLK_TCK
  • _SC_NGROUPS_MAX
  • _SC_OPEN_MAX
  • _SC_STREAM_MAX
  • _SC_TZNAME_MAX

POSIX.4 Option Values

  • _SC_ASYNCHRONOUS_IO
  • _SC_MAPPED_FILES
  • _SC_MEMLOCK
  • _SC_MEMLOCK_RANGE
  • _SC_MEMORY_PROTECTION
  • _SC_MESSAGE_PASSING
  • _SC_PRIORITIZED_IO
  • _SC_PRIORITY_SCHEDULING
  • _SC_REALTIME_SIGNALS
  • _SC_SEMAPHORES
  • _SC_FSYNC
  • _SC_SHARED_MEMORY_OBJECTS
  • _SC_SYNCHRONIZED_IO
  • _SC_TIMERS
  • _SC_AIO_LIST_IO_MAX
  • _SC_AIO_MAX
  • _SC_AIO_PRIO_DELTA_MAX
  • _SC_DELAYTIMER_MAX
  • _SC_MQ_OPEN_MAX
  • _SC_MQ_PRIO_MAX
  • _SC_PAGESIZE
  • _SC_RTSIG_MAX
  • _SC_SEM_NSEMS_MAX
  • _SC_SEM_VALUE_MAX
  • _SC_SIGQUEUE_MAX
  • _SC_TIMER_MAX

File and Directory Related POSIX Options

POSIX.1 Option Values

  • _PC_CHOWN_RESTRICTED
  • _PC_NO_TRUNC
  • _PC_VDISABLE
  • _PC_LINK_MAX
  • _PC_MAX_CANNON
  • _PC_MAX_INPUT
  • _PC_NAME_INPUT
  • _PC_PATH_MAX
  • _PC_PIPE_BUF

POSIX.4 Option Values

  • _PC_ASYNC_IO
  • _PC_PRIO_IO
  • _PC_SYNC_IO

C and C++ Programming: Linux POSIX System Capabilities

This section explains how to determine if various parts of POSIX are supported by your system. The easiest way to do this is to look at /usr/include/unistd.h on the system. This file will define the _POSIX_SOURCE versions. It may include other header files which include POSIX definitions. One that you should look at is /usr/include/bits/posix_opt.h which should have most of the POSIX definitions. All the below parameters are listed there. However, the most sure way is to run the below program. This is because the /usr/include/inistd.h file may not be the only one available and it may not be used by your system. Also you need to be aware your kernel may not support all the listed functions. It will depend on the library used to compile it and the options used at the compile time. The kernel will have a great affect on the support of POSIX.4 functions since it controls memory allocation and processes, including the signals between them.

The Test Program


The program listing below will output values based on what your system supports. I call it "posixtst.c". This is a tar and gz version of the source and binary program with a small README file with install instructions. posixtst-1.0.0

#define _POSIX_SOURCE
#define _POSIX_C_SOURCE 199309
#include <unistd.h>

long val;
int errno;

main()
{
#ifndef _POSIX_VERSION
printf("No support for POSIX on this system!\n");
#else //see what POSIX version
printf("POSIX_VERSION = %d.\n",_POSIX_VERSION);
printf("POSIX2_VERSION = %d.\n",_POSIX2_VERSION);
printf("POSIX2_C_VERSION = %d.\n",_POSIX2_C_VERSION);
#if _POSIX_VERSION == 199009
printf("This system supports POSIX.1 without support for POSIX.4.\n");
#else
#if _POSIX_VERSION >= 199309
printf ("This system supports POSIX.1 and POSIX.4. \n");
#else
printf("This system supports a strange POSIX version between 199009 and 199309.\n");
#endif
//DO POSIX.4 tests
printf ("POSIX.4 Options Test Results:\n");
#ifdef _POSIX_REALTIME_SIGNALS
printf(" POSIX.4 Additional real time signals are supported.\n");
#ifdef _POSIX_RTSIG_MAX
printf(" _POSIX_RTSIG_MAX=%d Max real time signals.\n",_POSIX_RTSIG_MAX);
#else
printf(" No _POSIX_RTSIG_MAX value exists.\n");
#endif
#ifdef _POSIX_SIGQUEUE_MAX
printf(" _POSIX_SIGQUEUE_MAX=%d Max real time

signals at once per process.\n",_POSIX_RTQUEUE_MAX);
#else
printf(" No _POSIX_SIGQUEUE_MAX value exists.\n");
#endif
#else
printf(" POSIX.4 Additional real time signals are not

supported.\n");
#endif
#ifdef _POSIX_PRIORITY_SCHEDULING
printf(" POSIX.4 Priority scheduling is supported.\n");
#else
printf(" POSIX.4 Priority scheduling is not supported.

\n");
#endif
#ifdef _POSIX_TIMERS
printf(" POSIX.4 Clocks and timers are supported.\n");
#ifdef _POSIX_TIMER_MAX
printf(" _POSIX_TIMER_MAX=%d Max number of concur

rent timers a process can have.\n",_POSIX_TIMER_MAX);
#else
printf(" No _POSIX_TIMER_MAX value exists.\n");
#endif
#ifdef _POSIX_DELAYTIMER_MAX
printf(" _POSIX_DELAYTIMER_MAX=%d Max number of

times a timer can have a detectable overrun.\n", _POSIX_DELAYTIMER_MAX);
#else
printf(" No _POSIX_DELAYTIMER_MAX value exists.\n");
#endif
#else
printf(" POSIX.4 Clocks and timers are not supported.\n");
#endif
#ifdef _POSIX_ASYNCHRONOUS_IO
printf(" POSIX.4 Asynchronous I/O is supported.\n");
#ifdef _POSIX_AIO_LISTIO_MAX
printf(" _POSIX_AIO_LISTIO_MAX=%d Max operations in one call\n",_POSIX_AIO_LISTIO_MAX);
#else
printf(" No _POSIX_AIO_LISTIO_MAX value exists.\n");
#endif
#ifdef _POSIX_AIO_MAX
printf(" _POSIX_AIO_MAX=%d Max concurrent Async I/Os\n",_POSIX_AIO_MAX);
#else
printf(" No _POSIX_AIO_MAX value exists.\n");
#endif
#else
printf(" POSIX.4 Asynchronous I/O is not supported.\n");
#endif
#ifdef _POSIX_SYNCHRONIZED_IO //Only supported if Asynchronous I/O is supported
printf(" POSIX.4 Synchronized I/O is supported.\n");
#else
printf(" POSIX.4 Synchronized I/O is not supported.\n");
#endif
#ifdef _POSIX_PRIORITIZED_IO
printf(" POSIX.4 Prioritized asynchronous I/O is supported.\n");
#ifdef _POSIX_AIO_PRIO_DELTA_MAX
printf(" _POSIX_AIO_PRIO_DELTA_MAX=%d Max amount AIO priority can be decreased.\n",_POSIX_AIO_PRIO_DELTA_MAX);
#else
printf(" No _POSIX_AIO_PRIO_DELTA_MAX value exists.\n");
#endif
#else
printf(" POSIX.4 Prioritized asynchronous I/O is not supported.\n");
#endif
#ifdef _POSIX_FSYNC
printf(" POSIX.4 The fsync function is supported.\n");
#else
printf(" POSIX.4 The fsync function is not supported.\n");
#endif
#ifdef _POSIX_MAPPED_FILES
printf(" POSIX.4 Mapping files as memory is supported.\n");
#else
printf(" POSIX.4 Mapping files as memory is not supported.\n");
#endif
#ifdef _POSIX_MEMLOCK
printf(" POSIX.4 Locking memory is supported.\n");
#else
printf(" POSIX.4 Locking memory is not supported.\n");
#endif
#ifdef _POSIX_MEMLOCK_RANGE
printf(" POSIX.4 Locking memory ranges is supported.\n");
#else
printf(" POSIX.4 Locking memory ranges is not supported.\n");
#endif
#ifdef _POSIX_MEMORY_PROTECTION
printf(" POSIX.4 Setting memory protection is supported.\n");
#else
printf(" POSIX.4 Setting memory protection is not supported.\n");
#endif
#ifdef _POSIX_MESSAGE_PASSING
printf(" POSIX.4 Message Queues are supported.\n");
#ifdef _POSIX_MQ_OPEN_MAX
printf(" _POSIX_MQ_OPEN_MAX=%d Max # of message queues per process.\n",_POSIX_MQ_OPEN_MAX);
#else
printf(" No _POSIX_MQ_OPEN_MAX value exists.\n");
#endif
#ifdef _POSIX_MQ_PRIO_MAX
printf(" _POSIX_MQ_PRIO_MAX=%d Max # of message priorities.\n",_POSIX_MQ_PRIO_MAX);
#else
printf(" No _POSIX_MQ_PRIO_MAX value exists.\n");
#endif
#else
printf(" POSIX.4 Message Queues are not supported.\n");
#endif
#ifdef _POSIX_SEMAPHORES
printf(" POSIX.4 Semaphores are supported.\n");
#ifdef _POSIX_SEM_NSEMS_MAX
printf(" _POSIX_SEM_NSEMS_MAX=%d Max # of open semaphores per process.\n",_POSIX_SEM_NSEMS_MAX);
#else
printf(" No _POSIX_SEM_NSEMS_MAX value exists.\n");
#endif
#ifdef _POSIX_SEM_VALUE_MAX
printf(" _POSIX_SEM_VALUE_MAX=%d Maximum semaphore value.\n",_POSIX_SEM_VALUE_MAX);
#else
printf(" No _POSIX_SEM_VALUE_MAX value exists.\n");
#endif
#else
printf(" POSIX.4 Semaphores are not supported.\n");
#endif
#ifdef _POSIX_SHARED_MEMORY_OBJECTS
printf(" POSIX.4 Shared memory objects are supported.\n");
#else
printf(" POSIX.4 Shared memory objects are not supported.\n");
#endif

#ifdef _POSIX_THREADS
printf(" POSIX.1c pthreads are supported.\n");
#else
printf(" POSIX.1c pthreads are not supported.\n");
#endif
#ifdef _POSIX_THREAD_ATTR_STACKADDRTHREAD_ATTR_STACKADDR
printf(" POSIX.4 Thread stack address attribute option is supported.\n");
#else
printf(" POSIX.4 Thread stack address attribute option is not supported.\n");
#endif
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
printf(" POSIX.4 Thread stack size attribute option is supported.\n");
#else
printf(" POSIX.4 Thread stack size attribute option is not supported.\n");
#endif
#ifdef _POSIX_THREAD_SAFE_FUNCTIONS
printf(" POSIX.4 Thread-safe functions are supported.\n");
#else
printf(" POSIX.4 Thread-safe functions are not supported.\n");
#endif
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
printf(" POSIX.1c thread execution scheduling is supported.\n");
#else
printf(" POSIX.1c thread execution scheduling is not supported.\n");
#endif
#ifdef _POSIX_THREAD_PRIO_INHERIT
printf(" POSIX.4 Thread priority inheritance option is supported.\n");
#else
printf(" POSIX.4 Thread priority inheritance option is not supported.\n");
#endif
#ifdef _POSIX_THREAD_PROCESS_SHARED
printf(" POSIX.4 Process-shared synchronization is supported.\n");
#else
printf(" POSIX.4 Process-shared synchronization is not supported.\n");
#endif
#ifdef _POSIX_POSIX_PII
printf(" Protocol-independent interfaces are supported.\n");
#else
printf(" Protocol-independent interfaces are not supported.\n");
#endif
#ifdef _POSIX_PII_XTI
printf(" XTI protocol-indep. interfaces are supported.\n");
#else
printf(" XTI protocol-indep. interfaces are not supported.\n");
#endif
#ifdef _POSIX_PII_SOCKET
printf(" Socket protocol-indep. interfaces are supported.\n");
#else
printf(" Socket protocol-indep. interfaces are not supported.\n");
#endif
#ifdef _POSIX_PII_INTERNET
printf(" Internet family of protocols is supported.\n");
#else
printf(" Internet family of protocols is not supported.\n");
#endif
#ifdef _POSIX_PII_INTERNET_STREAM
printf(" Connection-mode Internet protocol is supported.\n");
#else
printf(" Connection-mode Internet protocol is not supported.\n");
#endif
#ifdef _POSIX_PII_INTERNET_DGRAM
printf(" Connectionless Internet protocol is supported.\n");
#else
printf(" Connectionless Internet protocol is not supported.\n");
#endif
#ifdef _POSIX_PII_OSI
printf(" ISO/OSI family of protocols is supported.\n");
#else
printf(" ISO/OSI family of protocols is not supported.\n");
#endif
#ifdef _POSIX_PII_OSI_COTS
printf(" Connection-mode ISO/OSI service is supported.\n");
#else
printf(" Connection-mode ISO/OSI service is not supported.\n");
#endif
#ifdef _POSIX_PII_OSI_CLTS
printf(" Connectionless ISO/OSI service is supported.\n");
#else
printf(" Connectionless ISO/OSI service is not supported.\n");
#endif
#ifdef _POSIX_POLL
printf(" Implementation supports `poll' function.\n");
#else
printf(" poll function is not supported.\n");
#endif
#ifdef _POSIX_SELECT
printf(" Implementation supports `select' and `pselect'.\n");
#else
printf(" Implementation does not support `select' and `pselect'.\n");
#endif
#ifdef _XOPEN_REALTIME
printf(" X/Open realtime support is available.\n");
#else
printf(" X/Open realtime support is not available..\n");
#endif
#ifdef _XOPEN_REALTIME_THREADS
printf(" X/Open realtime thread support is available.\n");
#else
printf(" X/Open realtime thread support is not available.\n");
#endif
#ifdef _XOPEN_SHM
printf(" XPG4.2 Shared memory interface is supported.\n");
#else
printf(" XPG4.2 Shared memory interface is not supported.\n");
#endif
#ifdef _XBS5_ILP32_OFF32
printf(" 32-bit int, long, pointer, and off_t types are supported.\n");
#else
printf(" 32-bit int, long, pointer, and off_t types are not supported.\n");
#endif
#ifdef _XBS5_ILP32_OFFBIG
printf(" 32-bit int, long, and pointer and off_t with at least 64 bits is supported.\n");
#else
printf(" 32-bit int, long, and pointer and off_t with at least 64 bits is not supported.\n");
#endif
#ifdef _XBS5_LP64_OFF64
printf(" 32-bit int, and 64-bit long, pointer, and off_t types are supported.\n");
#else
printf(" 32-bit int, and 64-bit long, pointer, and off_t types are not supported.\n");
#endif
#ifdef _XBS5_LPBIG_OFFBIG
printf(" 32 bits int and long, pointer, and off_t with at least 64 bits are supported.\n");
#else
printf(" 32 bits int and long, pointer, and off_t with at least 64 bits are not supported.\n");
#endif


#endif
//Do POSIX.1 tests
printf ("POSIX.1 Options Test Results:\n");
#ifdef _POSIX_JOB_CONTROL
printf(" POSIX.1 Job control is supported.\n");
#else
printf(" POSIX.1 Job control is not supported.\n");
#endif
#ifdef _POSIX_CHOWN_RESTRICTED
printf(" POSIX.1 Chown restrictions are supported.\n");
#else
printf(" POSIX.1 Chown restrictions are not supported.\n");
#endif
#ifdef _POSIX_SAVED_IDS
printf(" POSIX.1 Process saved IDs are supported.\n");
#else
printf(" POSIX.1 Process saved IDs are not supported.\n");
#endif
#ifdef _POSIX_NO_TRUNC
printf(" POSIX.1 Long pathname errors are supported.\n");
#else
printf(" POSIX.1 Long pathname errors are not supported.\n");
#endif
#ifdef _POSIX_VDISABLE
printf(" POSIX.1 Some terminal charactistics disabling is supported.\n");
#else
printf(" POSIX.1 Some terminal charactistics disabling is not supported.\n");
#endif
#ifdef NGROUPS_MAX
printf(" POSIX.1 Supplementary group IDs is supported.\n");
#else
printf(" POSIX.1 Supplementary group IDs is not supported.\n");
#endif

#endif

//System Run time testing
printf("\nSystem run time tests:\n");
errno=0;
val=sysconf(_SC_JOB_CONTROL);
if ((val == -1) && (errno))
{
printf("Bad option _SC_JOB_CONTROL\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.1 JOB CONTROL not Supported.\n");
}
else
{
printf("POSIX.1 JOB CONTROL Supported.\n");
}
errno=0;
val=sysconf(_SC_SAVED_IDS);
if ((val == -1) && (errno))
{
printf("Bad option _SC_SAVED_IDS\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.1 SAVED IDS not Supported.\n");
}
else
{
printf("POSIX.1 SAVED IDS Supported.\n");
}
errno=0;
val=sysconf(_SC_VERSION);
if ((val == -1) && (errno))
{
printf("Bad option _SC_VERSION\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.1 VERSION not Supported.\n");
}
else
{
printf("POSIX.1 VERSION Supported.\n");
}

val=sysconf(_SC_ARG_MAX);
if (val == -1)
{
printf("Bad option _SC_ARG_MAX\n");
}
else
{
printf("POSIX.1 ARG MAX Value=%d.\n",val);
}
val=sysconf(_SC_CHILD_MAX);
if (val == -1)
{
printf("Bad option _SC_CHILD_MAX\n");
}
else
{
printf("POSIX.1 CHILD MAX Value=%d.\n",val);
}
val=sysconf(_SC_CLK_TCK);
if (val == -1)
{
printf("Bad option _SC_CLK_TCK\n");
}
else
{
printf("POSIX.1 CLK TCK Value=%d.\n",val);
}
val=sysconf(_SC_NGROUPS_MAX);
if (val == -1)
{
printf("Bad option _SC_NGROUPS_MAX\n");
}
else
{
printf("POSIX.1 NGROUPS MAX Value=%d.\n",val);
}
val=sysconf(_SC_OPEN_MAX);
if (val == -1)
{
printf("Bad option _SC_OPEN_MAX\n");
}
else
{
printf("POSIX.1 OPEN MAX Value=%d.\n",val);
}
val=sysconf(_SC_STREAM_MAX);
if (val == -1)
{
printf("Bad option _SC_STREAM_MAX\n");
}
else
{
printf("POSIX.1 STREAM MAX Value=%d.\n",val);
}
val=sysconf(_SC_TZNAME_MAX);
if (val == -1)
{
printf("Bad option _SC_TZNAME_MAX\n");
}
else
{
printf("POSIX.1 TZNAME MAX Value=%d.\n",val);
}


errno=0;
val=sysconf(_SC_ASYNCHRONOUS_IO);
if ((val == -1) && (errno))
{
printf("Bad option _SC_ASYNCHRONOUS_IO\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 ASYNCHRONOUS IO not Supported.\n");
}
else
{
printf("POSIX.4 ASYNCHRONOUS IO Supported.\n");
}
errno=0;
val=sysconf(_SC_MAPPED_FILES);
if ((val == -1) && (errno))
{
printf("Bad option _SC_MAPPED_FILES\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 MAPPED FILES not Supported.\n");
}
else
{
printf("POSIX.4 MAPPED FILES Supported.\n");
}
errno=0;
val=sysconf(_SC_MEMLOCK_RANGE);
if ((val == -1) && (errno))
{
printf("Bad option _SC_MEMLOCK_RANGE\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 MEMLOCK RANGE not Supported.\n");
}
else
{
printf("POSIX.4 MEMLOCK RANGE Supported.\n");
}
errno=0;
val=sysconf(_SC_MEMORY_PROTECTION);
if ((val == -1) && (errno))
{
printf("Bad option _SC_MEMORY_PROTECTION\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 MEMORY PROTECTION not Supported.\n");
}
else
{
printf("POSIX.4 MEMORY PROTECTION Supported.\n");
}
errno=0;
val=sysconf(_SC_MESSAGE_PASSING);
if ((val == -1) && (errno))
{
printf("Bad option _SC_MESSAGE_PASSING\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 MESSAGE PASSING not Supported.\n");
}
else
{
printf("POSIX.4 MESSAGE PASSING Supported.\n");
}
errno=0;
val=sysconf(_SC_PRIORITIZED_IO);
if ((val == -1) && (errno))
{
printf("Bad option _SC_PRIORITIZED_IO\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 PRIORITIZED IO not Supported.\n");
}
else
{
printf("POSIX.4 PRIORITIZED IO Supported.\n");
}
errno=0;
val=sysconf(_SC_PRIORITY_SCHEDULING);
if ((val == -1) && (errno))
{
printf("Bad option _SC_PRIORITY_SCHEDULING\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 PRIORITY SCHEDULING not Supported.\n");
}
else
{
printf("POSIX.4 PRIORITY SCHEDULING Supported.\n");
}
errno=0;
val=sysconf(_SC_REALTIME_SIGNALS);
if ((val == -1) && (errno))
{
printf("Bad option _SC_REALTIME_SIGNALS\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 REALTIME SIGNALS not Supported.\n");
}
else
{
printf("POSIX.4 REALTIME SIGNALS Supported.\n");
}
errno=0;
val=sysconf(_SC_SEMAPHORES);
if ((val == -1) && (errno))
{
printf("Bad option _SC_SEMAPHORES\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 SEMAPHORES not Supported.\n");
}
else
{
printf("POSIX.4 SEMAPHORES Supported.\n");
}
errno=0;
val=sysconf(_SC_FSYNC);
if ((val == -1) && (errno))
{
printf("Bad option _SC_FSYNC\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 FSYNC not Supported.\n");
}
else
{
printf("POSIX.4 FSYNC Supported.\n");
}
errno=0;
val=sysconf(_SC_SHARED_MEMORY_OBJECTS);
if ((val == -1) && (errno))
{
printf("Bad option _SC_SHARED_MEMORY_OBJECTS\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 SHARED_MEMORY_OBJECTS not Supported.\n");
}
else
{
printf("POSIX.4 SHARED_MEMORY_OBJECTS Supported.\n");
}
errno=0;
val=sysconf(_SC_SYNCHRONIZED_IO);
if ((val == -1) && (errno))
{
printf("Bad option _SC_SYNCHRONIZED_IO\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 SYNCHRONIZED IO not Supported.\n");
}
else
{
printf("POSIX.4 SYNCHRONIZED IO Supported.\n");
}
errno=0;
val=sysconf(_SC_TIMERS);
if ((val == -1) && (errno))
{
printf("Bad option _SC_TIMERS\n");
}
else if ((val == -1) && (!errno))
{
printf("POSIX.4 TIMERS not Supported.\n");
}
else
{
printf("POSIX.4 TIMERS Supported.\n");
}

val=sysconf(_SC_AIO_LISTIO_MAX);
if (val == -1)
{
printf("Bad option _SC_AIO_LISTIO_MAX\n");
}
else
{
printf("POSIX.4 AIO LISTIO MAX Value=%d.\n",val);
}
val=sysconf(_SC_AIO_MAX);
if (val == -1)
{
printf("Bad option _SC_AIO_MAX\n");
}
else
{
printf("POSIX.4 AIO MAX Value=%d.\n",val);
}
val=sysconf(_SC_AIO_PRIO_DELTA_MAX);
if (val == -1)
{
printf("Bad option _SC_AIO_PRIO_DELTA_MAX\n");
}
else
{
printf("POSIX.4 AIO PRIO DELTA MAX Value=%d.\n",val);
}
val=sysconf(_SC_DELAYTIMER_MAX);
if (val == -1)
{
printf("Bad option _SC_DELAYTIMER_MAX\n");
}
else
{
printf("POSIX.4 DELAYTIMER MAX Value=%d.\n",val);
}
val=sysconf(_SC_MQ_OPEN_MAX);
if (val == -1)
{
printf("Bad option _SC_MQ_OPEN_MAX\n");
}
else
{
printf("POSIX.4 MQ OPEN MAX Value=%d.\n",val);
}
val=sysconf(_SC_MQ_PRIO_MAX);
if (val == -1)
{
printf("Bad option _SC_MQ_PRIO_MAX\n");
}
else
{
printf("POSIX.4 MQ PRIO MAX Value=%d.\n",val);
}
val=sysconf(_SC_PAGESIZE);
if (val == -1)
{
printf("Bad option _SC_PAGESIZE\n");
}
else
{
printf("POSIX.4 PAGESIZE Value=%d.\n",val);
}
val=sysconf(_SC_RTSIG_MAX);
if (val == -1)
{
printf("Bad option _SC_RTSIG_MAX\n");
}
else
{
printf("POSIX.4 RTSIG MAX Value=%d.\n",val);
}
val=sysconf(_SC_SEM_NSEMS_MAX);
if (val == -1)
{
printf("Bad option _SC_SEM_NSEMS_MAX\n");
}
else
{
printf("POSIX.4 SEM NSEMS MAX Value=%d.\n",val);
}
val=sysconf(_SC_SEM_VALUE_MAX);
if (val == -1)
{
printf("Bad option _SC_SEM_VALUE_MAX\n");
}
else
{
printf("POSIX.4 SEM VALUE MAX Value=%d.\n",val);
}
val=sysconf(_SC_SIGQUEUE_MAX);
if (val == -1)
{
printf("Bad option _SC_SIGQUEUE_MAX\n");
}
else
{
printf("POSIX.4 SIGQUEUE MAX Value=%d.\n",val);
}
val=sysconf(_SC_TIMER_MAX);
if (val == -1)
{
printf("Bad option _SC_TIMER_MAX\n");
}
else
{
printf("POSIX.4 TIMER MAX Value=%d.\n",val);
}

} //end of main

Other system limits

The "/usr/include/limits.h" file defines the various limits for the system such as SEM_NSEMS_MAX which is the maximum number of semaphores that one process can have open at a time. This file includes the following:

#ifdef __USE_POSIX
/* POSIX adds things to <limits.h>. */
# include <bits/posix1_lim.h>
#endif

#ifdef __USE_POSIX2
# include <bits/posix2_lim.h>
#endif

#ifdef __USE_XOPEN
# include <bits/xopen_lim.h<
#endif

Which means, the files "/usr/include/bits/posix1_lim.h" and "/usr/include/bits/posix2_lim.h" define the system limits.

Send SMS for Free