Unix Programming FAQ (v1.24) Archive-Name: unix-faq/programmer/faq Comp-unix-programmer-Archive-Name: faq URL: http://www.erlenstar.demon.co.uk/unix/faq_toc.html URL: http://www.whitefang.com/unix/faq_toc.html Copyright: Collection Copyright (C) 1997 Andrew Gierth. Last-Modified: 1997/10/21 07:13:36 Version: 1.24 ============================================================================== About this FAQ ************** $Id: rawfaq.texi,v 1.24 1997/10/21 07:13:36 andrew Exp $ This FAQ was originally begun by Patrick Horgan in May 1996; I took it over after it had been lying idle for several months. I've reorganised it a bit and added some stuff; I still regard it as 'under development'. Comments, suggestions, additions, corrections etc. should be sent to the maintainer at: . A hypertext version of this document is available on the WWW. The home site is located at `http://www.erlenstar.demon.co.uk/unix/faq_toc.html'. A US mirror site is available at `http://www.whitefang.com/unix/faq_toc.html'. This document is available by FTP from the news.answers archives at rtfm.mit.edu and its many mirror sites worldwide. The official archive name is `unix-faq/programmer/faq'. Sites which also archive *.answers posts by group should also carry the file under the `comp.unix.programmer' directory. Other sources of information are not listed here. You can find pointers to other FAQs, books, source code etc. in the regular [READ ME FIRST] posting that should appear weekly in comp.unix.programmer. Administrivia regarding newsgroup conduct, etc., are also found there; I want to reserve this document specifically for technical Q's and A's. All contributions have been edited by the maintainer, therefore any errors or omissions are my responsibility rather than that of the contributor. This FAQ is now maintained as Texinfo source; I'm generating a raw text version for Usenet using the `makeinfo' program, and an HTML version using `texi2html'. Copyright (C) 1997 Andrew Gierth. This document may be distributed freely on Usenet or by email; it may be archived on FTP or WWW sites that mirror the news.answers archives, provided that all reasonable efforts are made to ensure that the archive is kept up-to-date. (This permission may be withdrawn on an individual basis.) It may not be published in any other form, whether in print, on the WWW, on CD-ROM, or in any other medium, without the express permission of the maintainer. List of contributors in no particular order: Andrew Gierth Patrick J. Horgan withheld Stephen Baynes James Raynard withheld Michael F. Quigley withheld Ken Pizzini withheld Thamer Al-Herbish withheld Nick Kew Dan Abarbanel withheld Billy Chambless Walter Briscoe Jim Buchanan Dave Plonka Daniel Stenberg withheld Ralph Corderoy Stuart Kemp withheld Sergei Chernev Bjorn Reese withheld Joe Halpin List of Questions ***************** 1. Process Control 1.1 Creating new processes: fork() 1.1.1 What does fork() do? 1.1.2 What's the difference between fork() and vfork()? 1.1.3 Why use _exit rather than exit in the child branch of a fork? 1.2 Environment variables 1.2.1 How can I get/set an environment variable from a program? 1.2.2 How can I read the whole environment? 1.3 How can I sleep for less than a second? 1.4 How can I get a finer-grained version of alarm()? 1.5 How can a parent and child process communicate? 1.6 How do I get rid of zombie processes? 1.6.1 What is a zombie? 1.6.2 How do I prevent them from occuring? 1.7 How do I get my program to act like a daemon? 1.8 How can I look at process in the system like ps does? 1.9 Given a pid, how can I tell if it's a running program? 1.10 What's the return value of system/pclose/waitpid? 1.11 How do I find out about a process' memory usage? 1.12 Why do processes never decrease in size? 1.13 How do I change the name of my program (as seen by 'ps')? 1.14 How can I find a process' executable file? 1.14.1 So where do I put my configuration files then? 2. General File handling (including pipes and sockets) 2.1 How to manage multiple connections? 2.1.1 How do I use select()? 2.1.2 How do I use poll()? 2.1.3 Can I use SysV IPC at the same time as select or poll? 2.2 How can I tell when the other end of a connection shuts down? 2.3 Best way to read directories? 2.4 How can I find out if someone else has a file open? 2.5 How do I 'lock' a file? 2.6 How do I find out if a file has been updated by another process? 2.7 How does the 'du' utility work? 2.8 How do I find the size of a file? 2.9 How do I expand '~' in a filename like the shell does? 2.10 What can I do with named pipes (FIFOs)? 2.10.1 What is a named pipe? 2.10.2 How do I create a named pipe? 2.10.3 How do I use a named pipe? 2.10.4 Can I use a named pipe across NFS? 2.10.5 Can multiple processes write to the pipe simultaneously? 2.10.6 Using named pipes in applications 3. Terminal I/O 3.1 How can I make my program not echo input? 3.2 How can I read single characters from the terminal? 3.3 How can I check and see if a key was pressed? 3.4 How can I move the cursor around the screen? 3.5 What are pttys? 3.6 How to handle a serial port or modem? 4. System Information 4.1 How can I tell how much memory my system has? 4.2 How do I check a user's password? 4.2.1 How do I get a user's password? 4.2.2 How do I get shadow passwords by uid? 4.2.3 How do I verify a user's password? 5. Miscellaneous programming 5.1 How do I compare strings using wildcards? 5.1.1 How do I compare strings using filename patterns? 5.1.2 How do I compare strings using regular expressions? 5.2 What's the best way to send mail from a program? 5.2.1 The simple method: /bin/mail 5.2.2 Invoking the MTA directly: /usr/lib/sendmail 5.2.2.1 Supplying the envelope explicitly 5.2.2.2 Allowing sendmail to deduce the recipients 6. Use of tools 6.1 How can I debug the children after a fork? 6.2 How to build library from other libraries? 6.3 How to create shared libraries / dlls? 6.4 Can I replace objects in a shared library? 6.5 How can I generate a stack dump from within a running program?  * 1. Process Control *  ****************** 1.1 Creating new processes: fork() ================================== 1.1.1 What does fork() do? -------------------------- #include #include pid_t fork(void); The `fork()' function is used to create a new process from an existing process. The new process is called the child process, and the existing process is called the parent. You can tell which is which by checking the return value from `fork()'. The parent gets the child's pid returned to him, but the child gets 0 returned to him. Thus this simple code illustrate's the basics of it. pid_t pid; switch (pid = fork()) { case -1: /* Here pid is -1, the fork failed */ /* Some possible reasons are that you're */ /* out of process slots or virtual memory */ perror("The fork failed!"); break; case 0: /* pid of zero is the child */ /* Here we're the child...what should we do? */ /* ... */ /* but after doing it, we should do something like: */ _exit(0); default: /* pid greater than zero is parent getting the child's pid */ printf("Child's pid is %d\n",pid); } Of course, one can use `if()... else...' instead of `switch()', but the above form is a useful idiom. Of help when doing this is knowing just what is and is not inherited by the child. This list can vary depending on Unix implementation, so take it with a grain of salt. Note that the child gets COPIES of these things, not the real thing. Inherited by the child from the parent: * process credentials (real/effective/saved UIDs and GIDs) * environment * stack * memory * open file descriptors (note that the underlying file positions are shared between the parent and child, which can be confusing) * close-on-exec flags * signal handling settings * nice value * scheduler class * process group ID * session ID * current working directory * root directory * file mode creation mask (umask) * resource limits * controlling terminal Unique to the child: * process ID * different parent process ID * Own copy of file descriptors and directory streams. * process, text, data and other memory locks are NOT inherited. * process times, in the tms struct * resource utilizations are set to 0 * pending signals initialized to the empty set * timers created by timer_create not inherited * asynchronous input or output operations not inherited 1.1.2 What's the difference between fork() and vfork()? ------------------------------------------------------- Some systems have a system call `vfork()', which was originally designed as a lower-overhead version of `fork()'. Since `fork()' involved copying the entire address space of the process, and was therefore quite expensive, the `vfork()' function was introduced (in 3.0BSD). *However*, since `vfork()' was introduced, the implementation of `fork()' has improved drastically, most notably with the introduction of 'copy-on-write', where the copying of the process address space is transparently faked by allowing both processes to refer to the same physical memory until either of them modify it. This largely removes the justification for `vfork()'; indeed, a large proportion of systems now lack the functionality of `vfork()' completely. For compatibility, though, there may still be a `vfork()' call present, that simply calls `fork()' without attempting to emulate the `vfork()' semantics. As a result, it is *very* unwise to actually make use of any of the differences between `fork()' and `vfork()'. Indeed, it is probably unwise to use `vfork()' at all, unless you know exactly *why* you want to. The basic difference between the two is that when a new process is created with `vfork()', the parent process is temporarily suspended, and the child process borrows the parent's address space. This strange state of affairs continues until the child process either exits, or calls `execve()', at which point the parent process continues. This means that the child process of a `vfork()' must be *extremely* careful to avoid unexpectedly modifying variables of the parent process. In particular, the child process must *not* return from the function containing the `vfork()' call, and it must *not* call `exit()' (if it needs to exit, it should use `_exit()'; actually, this is also true for the child of a normal `fork()'). (There are some deviant systems, e.g. SCO OpenServer, that have a `vfork()' that is distinct from `fork()', but only emulates part of the original `vfork()' - in this case, it suspends the parent process, but doesn't share the address space with the child. I have no idea why they thought this would be useful.) 1.1.3 Why use _exit rather than exit in the child branch of a fork? ------------------------------------------------------------------- There are a few differences between `exit()' and `_exit()' that become significant when `fork()', and especially `vfork()', is used. The basic difference between `exit()' and `_exit()' is that the former performs clean-up related to user-mode constructs in the library, and calls user-supplied cleanup functions, whereas the latter performs only the kernel cleanup for the process. In the child branch of a `fork()', it is normally incorrect to use `exit()', because that can lead to stdio buffers being flushed twice, and temporary files being unexpectedly removed. In C++ code the situation is worse, because destructors for static objects may be run incorrectly. (There are some unusual cases, like daemons, where the *parent* should call `_exit()' rather than the child; the basic rule, applicable in the overwhelming majority of cases, is that `exit()' should be called only once for each entry into `main'.) In the child branch of a `vfork()', the use of `exit()' is even more dangerous, since it will affect the state of the *parent* process. 1.2 Environment variables ========================= 1.2.1 How can I get/set an environment variable from a program? --------------------------------------------------------------- Getting the value of an environment variable is done by using `getenv()'. #include char *getenv(const char *name); Setting the value of an environment variable is done by using `putenv()'. #include int putenv(char *string); The string passed to putenv must *not* be freed or made invalid, since a pointer to it is kept by `putenv()'. This means that it must either be a static buffer or allocated off the heap. The string can be freed if the environment variable is redefined or deleted via another call to `putenv()'. Remember that environment variables are inherited; each process has a separate copy of the environment. As a result, you can't change the value of an environment variable in another process, such as the shell. Suppose you wanted to get the value for the `TERM' environment variable. You would use this code: char *envvar; envvar=getenv("TERM"); printf("The value for the environment variable TERM is " if(envvar) { printf("%s\n",envvar); } else { printf("not set.\n"); } Now suppose you wanted to create a new environment variable called `MYVAR', with a value of `MYVAL'. This is how you'd do it. static char envbuf[256]; sprintf(envbuf,"MYVAR=%s","MYVAL"); if(putenv(envbuf)) { printf("Sorry, putenv() couldn't find the memory for %s\n",envbuf); /* Might exit() or something here if you can't live without it */ } 1.2.2 How can I read the whole environment? ------------------------------------------- If you don't know the names of the environment variables, then the `getenv()' function isn't much use. In this case, you have to dig deeper into how the environment is stored. A global variable, `environ', holds a pointer to an array of pointers to environment strings, each string in the form `"NAME=value"'. A `NULL' pointer is used to mark the end of the array. Here's a trivial program to print the current environment (like `printenv'): #include extern char **environ; int main() { char **ep = environ; char *p; while ((p = *ep++)) printf("%s\n", p); return 0; } In general, the `environ' variable is also passed as the third, optional, parameter to `main()'; that is, the above could have been written: #include int main(int argc, char **argv, char **envp) { char *p; while ((p = *envp++)) printf("%s\n", p); return 0; } However, while pretty universally supported, this method isn't actually defined by the POSIX standards. (It's also less useful, in general.) 1.3 How can I sleep for less than a second? =========================================== The `sleep()' function, which is available on all Unixes, only allows for a duration specified in seconds. If you want finer granularity, then you need to look for alternatives: * Many systems have a function `usleep()' * You can use `select()' or `poll()', specifying no file descriptors to test; a common technique is to write a `usleep()' function based on either of these (see the comp.unix.questions FAQ for some examples) * If your system has itimers (most do), you can roll your own `usleep()' using them (see the BSD sources for `usleep()' for how to do this) * If you have POSIX realtime, there is a `nanosleep()' function Whichever route you choose, it is important to realise that you may be constrained by the timer resolution of the system (some systems allow very short time intervals to be specified, others have a resolution of, say, 10ms and will round all timings to that). Also, as for `sleep()', the delay you specify is only a *minimum* value; after the specified period elapses, there will be an indeterminate delay before your process next gets scheduled. 1.4 How can I get a finer-grained version of alarm()? ===================================================== Modern Unixes tend to implement alarms using the `setitimer()' function, which has a higher resolution and more options than the simple `alarm()' function. One should generally assume that `alarm()' and `setitimer(ITIMER_REAL)' may be the same underlying timer, and accessing it both ways may cause confusion. Itimers can be used to implement either one-shot or repeating signals; also, there are generally 3 separate timers available: `ITIMER_REAL' counts real (wall clock) time, and sends the `SIGALRM' signal `ITIMER_VIRTUAL' counts process virtual (user CPU) time, and sends the `SIGVTALRM' signal `ITIMER_PROF' counts user and system CPU time, and sends the `SIGPROF' signal; it is intended for interpreters to use for profiling. Itimers, however, are not part of many of the standards, despite having been present since 4.2BSD. The POSIX realtime extensions define a similar, but different, function: `settimer()'. There are also functions defined to query the resolution of POSIX timers. 1.5 How can a parent and child process communicate? =================================================== A parent and child can communicate through any of the normal inter-process communication schemes (pipes, sockets, message queues, shared memory), but also have some special ways to communicate that take advantage of their relationship as a parent and child. One of the most obvious is that the parent can get the exit status of the child. Since the child inherits file descriptors from its parent, the parent can open both ends of a pipe, fork, then the parent close one end and the child close the other end of the pipe. This is what happens when you call the `popen()' routine to run another program from within yours, i.e. you can write the the file descriptor returned from popen() and the child process sees it as its stdin, and you can read from the file descriptor and see what the program wrote to it's stdout. Also, the child process inherits memory segments mmapped anonymously (or by mmapping the special file `/dev/zero') by the parent; these shared memory segments are not accessible from unrelated processes. 1.6 How do I get rid of zombie processes? ========================================= 1.6.1 What is a zombie? ----------------------- When a program forks and the child finishes before the parent, the kernel still keeps some of its information about the child in case the parent might need it - for example, the parent may need to check the child's exit status. To be able to get this information, the parent calls `wait()'; when this happens, the kernel can discard the information. In the interval between the child terminating and the parent calling `wait()', the child is said to be a "zombie" (if you do 'ps', the child will have a 'Z' in its status field to indicate this). Even though it's not running, it's still taking up an entry in the process table. (It consumes no other resources, but some utilities may show bogus figures for e.g. CPU usage; this is because some parts of the process table entry have been overlaid by accounting info to save space.) This is not good, as the process table has a fixed number of entries and it is possible for the system to run out of them. Even if the system doesn't run out, there is a limit on the number of processes each user can run, which is usually smaller than the system's limit. This is one of the reasons why you should always check if `fork()' failed, by the way! If the parent terminates without calling wait(), the child is "adopted" by `init', which handles the work necessary to cleanup after the child. (This is a special system program with process ID 1 - it's actually the first program to run after the system boots up). 1.6.2 How do I prevent them from occuring? ------------------------------------------ You need to ensure that your parent process calls `wait()' (or `waitpid()', `wait3()', etc.) for every child process that terminates; or, on some systems, you can instruct the system that you are uninterested in child exit states. Another approach is to `fork()' *twice*, and have the immediate child process exit straight away. This causes the grandchild process to be orphaned, so the init process is responsible for cleaning it up. For code to do this, see the function `fork2()' in the examples section. To ignore child exit states, you need to do the following (check your system's manpages to see if this works): struct sigaction sa; sa.sa_handler = SIG_IGN; #ifdef SA_NOCLDWAIT sa.sa_flags = SA_NOCLDWAIT; #else sa.sa_flags = 0; #endif sigemptyset(&sa.sa_mask); sigaction(SIGCHLD, &sa, NULL); If this is successful, then the `wait()' functions are prevented from working; if any of them are called, they will wait until *all* child processes have terminated, then return failure with `errno == ECHILD'. The other technique is to catch the SIGCHLD signal, and have the signal handler call `waitpid()' or `wait3()'. See the examples section for a complete program. 1.7 How do I get my program to act like a daemon? ================================================= A "daemon" process is usually defined as a background process that does not belong to a terminal session. Many system services are performed by daemons; network services, printing etc. Simply invoking a program in the background isn't really adequate for these long-running programs; that does not correctly detach the process from the terminal session that started it. Also, the conventional way of starting daemons is simply to issue the command manually or from an rc script; the daemon is expected to put *itself* into the background. Here are the steps to become a daemon: 1. `fork()' so the parent can exit, this returns control to the command line or shell invoking your program. This step is required so that the new process is guaranteed not to be a process group leader. The next step, `setsid()', fails if you're a process group leader. 2. `setsid()' to become a process group and session group leader. Since a controlling terminal is associated with a session, and this new session has not yet acquired a controlling terminal our process now has no controlling terminal, which is a Good Thing for daemons. 3. `fork()' again so the parent, (the session group leader), can exit. This means that we, as a non-session group leader, can never regain a controlling terminal. 4. `chdir("/")' to ensure that our process doesn't keep any directory in use. Failure to do this could make it so that an administrator couldn't unmount a filesystem, because it was our current directory. [Equivalently, we could change to any directory containing files important to the daemon's operation.] 5. `umask(0)' so that we have complete control over the permissions of anything we write. We don't know what umask we may have inherited. [This step is optional] 6. `close()' fds 0, 1, and 2. This releases the standard in, out, and error we inherited from our parent process. We have no way of knowing where these fds might have been redirected to. Note that many daemons use `sysconf()' to determine the limit `_SC_OPEN_MAX'. `_SC_OPEN_MAX' tells you the maximun open files/process. Then in a loop, the daemon can close all possible file descriptors. You have to decide if you need to do this or not. If you think that there might be file-descriptors open you should close them, since there's a limit on number of concurrent file descriptors. 7. Establish new open descriptors for stdin, stdout and stderr. Even if you don't plan to use them, it is still a good idea to have them open. The precise handling of these is a matter of taste; if you have a logfile, for example, you might wish to open it as stdout or stderr, and open `/dev/null' as stdin; alternatively, you could open `/dev/console' as stderr and/or stdout, and `/dev/null' as stdin, or any other combination that makes sense for your particular daemon. Almost none of this is necessary (or advisable) if your daemon is being started by `inetd'. In that case, stdin, stdout and stderr are all set up for you to refer to the network connection, and the `fork()'s and session manipulation should *not* be done (to avoid confusing `inetd'). Only the `chdir()' and `umask()' steps remain as useful. 1.8 How can I look at process in the system like ps does? ========================================================= You really *don't* want to do this. The most portable way, by far, is to do `popen(pscmd, "r")' and parse the output. (pscmd should be something like `"ps -ef"' on SysV systems; on BSD systems there are many possible display options: choose one.) In the examples section, there are two complete versions of this; one for SunOS 4, which requires root permission to run and uses the `kvm_*' routines to read the information from kernel data structures; and another for SVR4 systems (including SunOS 5), which uses the `/proc' filesystem. It's even easier on systems with an SVR4.2-style `/proc'; just read a psinfo_t structure from the file `/proc/PID/psinfo' for each PID of interest. However, this method, while probably the cleanest, is also perhaps the least well-supported. (On FreeBSD's /proc, you read a semi-undocumented printable string from `/proc/PID/status'; Linux has something similar.) 1.9 Given a pid, how can I tell if it's a running program? ========================================================== Use `kill()' with 0 for the signal number. There are four possible results from this call: * `kill()' returns 0 - this implies that a process exists with the given PID, and the system would allow you to send signals to it. It is system-dependent whether the process could be a zombie. * `kill()' returns -1, `errno == ESRCH' - either no process exists with the given PID, or security enhancements are causing the system to deny its existence. (On some systems, the process could be a zombie.) * `kill()' returns -1, `errno == EPERM' - the system would not allow you to kill the specified process. This means that either the process exists (again, it could be a zombie) or draconian security enhancements are present (e.g. your process is not allowed to send signals to *anybody*). * `kill()' returns -1, with some other value of `errno' - you are in trouble! The most-used technique is to assume that success or failure with `EPERM' implies that the process exists, and any other error implies that it doesn't. 1.10 What's the return value of system/pclose/waitpid? ====================================================== The return value of `system()', `pclose()', or `waitpid()' doesn't seem to be the exit value of my process... or the exit value is shifted left 8 bits... what's the deal? The man page is right, and so are you! If you read the man page for `waitpid()' you'll find that the return code for the process is encoded. The value returned by the process is normally in the top 16 bits, and the rest is used for other things. You can't rely on this though, not if you want to be portable, so the suggestion is that you use the macros provided. These are usually documented under `wait()' or `wstat'. Macros defined for the purpose (in `') include (stat is the value returned by `waitpid()'): `WIFEXITED(stat)' Non zero if child exited normally. `WEXITSTATUS(stat)' exit code returned by child `WIFSIGNALED(stat)' Non-zero if child was terminated by a signal `WTERMSIG(stat)' signal number that terminated child `WIFSTOPPED(stat)' non-zero if child is stopped `WSTOPSIG(stat)' number of signal that stopped child `WIFCONTINUED(stat)' non-zero if status was for continued child `WCOREDUMP(stat)' If WIFSIGNALED(stat) non-zero this is non-zero if core dumped 1.11 How do I find out about a process' memory usage? ===================================================== Look at `getrusage()', if available. 1.12 Why do processes never decrease in size? ============================================= When you free memory back to the heap with free(), on almost all systems that *doesn't* reduce the memory usage of your program. The memory 'free'd is still part of the process' address space, and will be used to satisfy future `malloc()' requests. If you really need to free memory back to the system, look at using `mmap()' to allocate private anonymous mappings. When these are unmapped, the memory really is released back to the system. Of course, if your program increases in size when you think it shouldn't, you may have a 'memory leak' - a bug in your program that results in unused memory not being freed. 1.13 How do I change the name of my program (as seen by 'ps')? ============================================================== On BSDish systems, the `ps' program actually looks into the address space of the running process to find the current `argv[]', and displays that. That enables a program to change its 'name' simply by modifying `argv[]'. On SysVish systems, the command name and usually the first 80 bytes of the parameters are stored in the process' u-area, and so can't be directly modified. There may be a system call to change this (unlikely), but otherwise the only way is to perform an `exec()', or write into kernel memory (dangerous, and only possible if running as root). Some systems (notably Solaris) may have two separate versions of `ps', one in `/usr/bin/ps' with SysV behaviour, and one in `/usr/ucb/ps' with BSD behaviour. On these systems, if you change `argv[]', then the BSD version of `ps' will reflect the change, and the SysV version won't. Check to see if your system has a function `setproctitle()'. 1.14 How can I find a process' executable file? =============================================== This would be a good candidate for a list of "Frequently Unanswered Questions", because the fact of asking the question usually means that the design of the program is flawed :-) You can make a "best guess" by looking at the value of `argv[0]'. If this contains a `/', then it is probably the absolute or relative (to the current directory at program start) path of the executable. If it does not, then you can mimic the shell's search of the `PATH' variable, looking for the program. However, success is not guaranteed, since it is possible to invoke programs with arbitrary values of `argv[0]', and in any case the executable may have been renamed or deleted since it was started. The most common reason people ask this question is in order to locate configuration files with their program. This is considered to be bad form; directories containing executables should contain *nothing* except executables, and administrative requirements often make it desirable for configuration files to be located on different filesystems to executables. A less common, but more legitimate, reason to do this is to allow the program to call `exec()' *on itself*; this is a method used (e.g. by some versions of `sendmail') to completely reinitialise the process (e.g. if a daemon receives a `SIGHUP'). 1.14.1 So where do I put my configuration files then? ----------------------------------------------------- The correct directory for this usually depends on the particular flavour of Unix you're using; `/var/opt/PACKAGE', `/usr/local/lib', `/usr/local/etc', or any of several other possibilities. User-specific configuration files are usually hidden 'dotfiles' under `$HOME' (e.g. `$HOME/.exrc'). From the point of view of a package that is expected to be usable across a range of systems, this usually implies that the location of any sitewide configuration files will be a compiled-in default, possibly using a -prefix option on a configure script (Autoconf scripts do this). You might wish to allow this to be overridden at runtime by an environment variable. (If you're not using a configure script, then put the default in the Makefile as a -D option on compiles, or put it in a `config.h' header file, or something similar.) User-specific configuration should be either a single dotfile under `$HOME', or, if you need multiple files, a dot-subdirectory. (Files or directories whose names start with a dot are omitted from directory listings by default.) Avoid creating multiple entries under `$HOME', because this can get very cluttered. Again, you can allow the user to override this location with an environment variable. Programs should always behave sensibly if they fail to find any per-user configuration.  * 2. General File handling (including pipes and sockets) *  ****************************************************** See also the Sockets FAQ, available at: `http://kipper.york.ac.uk/~vic/sock-faq/' `ftp://rtfm.mit.edu/pub/usenet/news.answers/unix-faq/socket' 2.1 How to manage multiple connections? ======================================= I have to monitor more than one (fd/connection/stream) at a time. How do I manage all of them? Use `select()' or `poll()'. Note: `select()' was introduced in BSD, whereas `poll()' is an artifact of SysV STREAMS. As such, there are portability issues; pure BSD systems may still lack `poll()', whereas some older SVR3 systems may not have `select()'. SVR4 added `select()', and the Posix.1g standard defines both. `select()' and `poll()' essentially do the same thing, just differently. Both of them examine a set of file descriptors to see if specific events are pending on any, and then optionally wait for a specified time for an event to happen. [Important note: neither `select()' nor `poll()' do anything useful when applied to plain files; they are useful for sockets, pipes, ptys, ttys & possibly other character devices, but this is system-dependent.] There the similarity ends.... 2.1.1 How do I use select()? ---------------------------- The interface to `select()' is primarily based on the concept of an `fd_set', which is a set of FDs (usually implemented as a bit-vector). In times past, it was common to assume that FDs were smaller than 32, and just use an int to store the set, but these days, one usually has more FDs available, so it is important to use the standard macros for manipulating fd_sets: fd_set set; FD_ZERO(&set); /* empties the set */ FD_SET(fd,&set) /* adds FD to the set */ FD_CLR(fd,&set); /* removes FD from the set */ FD_ISSET(fd,&set) /* true if FD is in the set */ In most cases, it is the system's responsibility to ensure that fdsets can handle the whole range of file descriptors, but in some cases you may have to predefine the `FD_SETSIZE' macro. *This is system-dependent*; check your `select()' manpage. Also, some systems have problems handling more than 1024 file descriptors in `select()'. The basic interface to select is simple: int select(int nfds, fd_set *readset, fd_set *writeset, fd_set *exceptset, struct timeval *timeout); where `nfds' the number of FDs to examine; this must be greater than the largest FD in any of the fdsets, *NOT* the actual number of FDs specified `readset' the set of FDs to examine for readability `writeset' the set of FDs to examine for writability `exceptfds' the set of FDs to examine for exceptional status (note: errors are *NOT* exceptional statuses) `timeout' NULL for infinite timeout, or points to a timeval specifying the maximum wait time (if `tv_sec' and `tv_usec' both == 0, then the status of the FDs is polled, but the call never blocks) The call returns the number of 'ready' FDs found, and the three fdsets are modified in-place, with only the ready FDs left in the sets. Use the `FD_ISSET' macro to test the returned sets. Here's a simple example of testing a single FD for readability: int isready(int fd) { int rc; fd_set fds; struct timeval tv; FD_ZERO(&fds); FD_SET(fd,&fds); tv.tv_sec = tv.tv_usec = 0; rc = select(fd+1, &fds, NULL, NULL, &tv); if (rc < 0) return -1; return FD_ISSET(fd,&fds) ? 1 : 0; } Note that we can pass `NULL' for fdsets that we aren't interested in testing. 2.1.2 How do I use poll()? -------------------------- Poll accepts a pointer to a list of `struct pollfd', in which the descriptors and the events you wish to poll for are stored. The events are specified via a bitwise mask in the events field of the structure. The instance of the structure will later be filled in and returned to you with any events which occured. Macros defined by `poll.h' on SVR4 (probably older versions as well), are used to specify the events in the field. A timeout may be specified in milliseconds, only the type provided is an integer which is quite perplexing. A timeout of 0 causes `poll()' to return immediately, a value of -1 will suspend poll till an event is found to be true. struct pollfd { int fd; /* The descriptor. */ short events; /* The event(s) is/are specified here. */ short revents; /* Events found are returned here. */ }; Alot like select, the return value if positive reflects how many descriptors were found to satisfy the events requested. A zero return value is returned if the timeout period is reached before any of the events specified have occured. A negative value should immediately be followed by a check of errno, since it signifies an error. If no events are found, revent is cleared, so there's no need for you to do this yourself. The returned events are tested to contain the event. Here's an example: /* Poll on two descriptors for Normal data, or High priority data. If any found call function handle() with appropriate descriptor and priority. Dont timeout, only giveup if error, or one of the descriptors hangs up. */ #include #include #include #include #include #include #include #include #define NORMAL_DATA 1 #define HIPRI_DATA 2 int poll_two_normal(int fd1,int fd2) { struct pollfd poll_list[2]; int retval; poll_list[0].fd = fd1; poll_list[1].fd = fd2; poll_list[0].events = POLLIN|POLLPRI; poll_list[1].events = POLLIN|POLLPRI; while(1) { retval = poll(poll_list,(unsigned long)2,-1); /* Retval will always be greater than 0 or -1 in this case. Since we're doing it while blocking */ if(retval < 0) { fprintf(stderr,"Error while polling: %s\n",strerror(errno)); return -1; } if(((poll_list[0].revents&POLLHUP) == POLLHUP) || ((poll_list[0].revents&POLLERR) == POLLERR) || ((poll_list[0].revents&POLLNVAL) == POLLNVAL) || ((poll_list[1].revents&POLLHUP) == POLLHUP) || ((poll_list[1].revents&POLLERR) == POLLERR) || ((poll_list[1].revents&POLLNVAL) == POLLNVAL)) return 0; if((poll_list[0].revents&POLLIN) == POLLIN) handle(poll_list[0].fd,NORMAL_DATA); if((poll_list[0].revents&POLLPRI) == POLLPRI) handle(poll_list[0].fd,HIPRI_DATA); i