System Dependencies
From: http://www.lysator.liu.se/c/c-faq/index.html#EoPS
Section 16. System Dependencies
16.1: How can I read a single character from the keyboard without waiting
for a newline?
Contrary to popular belief and many people's wishes, this is not a C-related
question. (Nor are closely-related questions concerning the echo of
keyboard input.) The delivery of characters from a "keyboard" to a C
program is a function of the operating system in use, and has not been
standardized by the C language. Some versions of curses have a cbreak()
function which does what you want. If you're specifically trying to read a
short password without echo, you might try getpass(). Under Unix, use ioctl
to play with the terminal driver modes (CBREAK or RAW under "classic"
versions; ICANON, c_cc[VMIN] and c_cc[VTIME] under System V or Posix
systems). Under MS-DOS, use getch(). Under VMS, try the Screen Management
(SMG$) routines, or curses, or issue low-level $QIO's with the IO$_READVBLK
(and perhaps IO$M_NOECHO) function codes to ask for one character at a time.
Under other operating systems, you're on your own. Beware that some
operating systems make this sort of thing impossible, because character
collection into input lines is done by peripheral processors not under
direct control of the CPU running your program.
Operating system specific questions are not appropriate for comp.lang.c .
Many common questions are answered in frequently-asked questions postings in
such groups as comp.unix.questions and comp.os.msdos.programmer . Note that
the answers are often not unique even across different variants of a system;
bear in mind when answering system-specific questions that the answer that
applies to your system may not apply to everyone else's.
References: PCS Sec. 10 pp. 128-9, Sec. 10.1 pp. 130-1.
16.2: How can I find out if there are characters available for reading (and
if so, how many)? Alternatively, how can I do a read that will not block if
there are no characters available?
These, too, are entirely operating-system-specific. Some versions of curses
have a nodelay() function. Depending on your system, you may also be able
to use "nonblocking I/O", or a system call named "select", or the FIONREAD
ioctl, or kbhit(), or rdchk(), or the O_NDELAY option to open() or fcntl().
16.3: How can I clear the screen? How can I print things in inverse video?
Such things depend on the terminal type (or display) you're using. You will
have to use a library such as termcap or curses, or some system-specific
routines, to perform these functions.
16.4: How do I read the mouse?
Consult your system documentation, or ask on an appropriate system-specific
newsgroup (but check its FAQ list first). Mouse handling is completely
different under the X window system, MS- DOS, Macintosh, and probably every
other system.
16.5: How can my program discover the complete pathname to the executable
file from which it was invoked?
argv[0] may contain all or part of the pathname, or it may contain nothing.
You may be able to duplicate the command language interpreter's search path
logic to locate the executable if the name in argv[0] is present but
incomplete. However, there is no guaranteed or portable solution.
16.6: How can a process change an environment variable in its caller?
In general, it cannot. Different operating systems implement name/value
functionality similar to the Unix environment in different ways. Whether
the "environment" can be usefully altered by a running program, and if so,
how, is system-dependent.
Under Unix, a process can modify its own environment (some systems provide
setenv() and/or putenv() functions to do this), and the modified environment
is usually passed on to any child processes, but it is not propagated back
to the parent process.
16.7: How can I check whether a file exists? I want to query the user
before overwriting existing files.
On Unix-like systems, you can try the access() routine, although it's got a
few problems. (It isn't atomic with respect to the following action, and
can have anomalies if used in setuid programs.) Another option (perhaps
preferable) is to call stat() on the file. Otherwise, the only guaranteed
and portable way to test for file existence is to try opening the file
(which doesn't help if you're trying to avoid overwriting an existing file,
unless you've got something like the BSD Unix O_EXCL open option
available).
16.8: How can I find out the size of a file, prior to reading it in?
If the "size of a file" is the number of characters you'll be able to read
from it in C, it is in general impossible to determine this number in
advance. Under Unix, the stat call will give you an exact answer, and
several other systems supply a Unix-like stat which will give an approximate
answer. You can fseek to the end and then use ftell, but this usage is
nonportable (it gives you an accurate answer only under Unix, and otherwise
a quasi-accurate answer only for ANSI C "binary" files). Some systems
provide routines called filesize or filelength.
Are you sure you have to determine the file's size in advance? Since the
most accurate way of determining the size of a file as a C program will see
it is to open the file and read it, perhaps you can rearrange the code to
learn the size as it reads.
16.9: How can a file be shortened in-place without completely clearing or
rewriting it?
BSD systems provide ftruncate(), several others supply chsize(), and a few
may provide a (possibly undocumented) fcntl option F_FREESP. Under MS-DOS,
you can sometimes use write(fd, "", 0). However, there is no truly portable
solution.
16.10: How can I implement a delay, or time a user's response, with sub
-second resolution?
Unfortunately, there is no portable way. V7 Unix, and derived systems,
provided a fairly useful ftime() routine with resolution up to a
millisecond, but it has disappeared from System V and Posix. Other routines
you might look for on your system include nap(), setitimer(), msleep(),
usleep(), clock(), and gettimeofday(). The select() and poll() calls (if
available) can be pressed into service to implement simple delays. On MS
-DOS machines, it is possible to reprogram the system timer and timer
interrupts.
16.11: How can I read in an object file and jump to routines in it?
You want a dynamic linker and/or loader. It is possible to malloc some
space and read in object files, but you have to know an awful lot about
object file formats, relocation, etc. Under BSD Unix, you could use
system() and ld -A to do the linking for you. Many (most?) versions of
SunOS and System V have the -ldl library which allows object files to be
dynamically loaded. There is also a GNU package called "dld". See also
question 7.6.
16.12: How can I invoke an operating system command from within a program?
Use system().
References: K&R II Sec. B6 p. 253; ANSI Sec. 4.10.4.5; H&S Sec. 21.2; PCS Sec. 11 p. 179;
16.13: How can I invoke an operating system command and trap its output?
Unix and some other systems provide a popen() routine, which sets up a stdio
stream on a pipe connected to the process running a command, so that the
output can be read (or the input supplied). Alternately, invoke the command
simply (see question 16.12) in such a way that it writes its output to a
file, then open and read that file.
References: PCS Sec. 11 p. 169 .
16.14: How can I read a directory in a C program?
See if you can use the opendir() and readdir() routines, which are available
on most Unix systems. Implementations also exist for MS-DOS, VMS, and other
systems. (MS-DOS also has FINDFIRST and FINDNEXT routines which do
essentially the same thing.)
16.15: How can I do serial ("comm") port I/O?
It's system-dependent. Under Unix, you typically open, read, and write a
device in /dev, and use the facilities of the terminal driver to adjust its
characteristics. Under MS-DOS, you can either use some primitive BIOS
interrupts, or (if you require decent performance) one of any number of
interrupt-driven serial I/O packages.