Multi-Threaded Programming With POSIX Threads - Linux Systems Programming
Multi-Threaded Programming With POSIX Threads - Linux Systems Programming
Multi-Threaded Programming With POSIX Threads - Linux Systems Programming
v1.1.1
Before We Start...
This tutorial is an attempt to help you become familiar with multi-threaded programming with the POSIX threads
(pthreads) library, and attempts to show how its features can be used in "real-life" programs. It explains the different
tools defined by the library, shows how to use them, and then gives an example of using them to solve programming
problems. There is an implicit assumption that the user has some theoretical familiarity with paralell programming (or
multi-processing) concepts. Users without such background might find the concepts harder to grasp. A seperate tutorial
will be prepared to explain the theoreticl background and terms to those who are familiar only with normal "serial"
programming.
I would assume that users which are familiar with asynchronous programming models, such as those used in
windowing environments (X, Motif), will find it easier to grasp the concepts of multi-threaded programming.
When talking about POSIX threads, one cannot avoid the question "Which draft of the POSIX threads standard shall be
used?". As this threads standard has been revised over a period of several years, one will find that implementations
adhering to different drafts of the standard have a different set of functions, different default values, and different
nuances. Since this tutorial was written using a Linux system with the kernel-level LinuxThreads library, v0.5,
programmers with access to other systems, using different versions of pthreads, should refer to their system's manuals
in case of incompatibilities. Also, since some of the example programs are using blocking system calls, they won't
work with user-level threading libraries (refer to our parallel programming theory tutorial for more information).
Having said that, i'd try to check the example programs on other systems as well (Solaris 2.5 comes to mind), to make it
more "cross-platform".
/* NOT REACHED */
return 0;
}
Note that for some of the programs later on this tutorial, one may need to add a '-D_GNU_SOURCE' flag to this
compile line, to get the source compiled.
The source code for this program may be found in the pthread_create.c file.
What Is A Mutex?
A basic mechanism supplied by the pthreads library to solve this problem, is called a mutex. A mutex is a lock that
guarantees three things:
1. Atomicity - Locking a mutex is an atomic operation, meaning that the operating system (or threads library)
assures you that if you locked a mutex, no other thread succeeded in locking this mutex at the same time.
2. Singularity - If a thread managed to lock a mutex, it is assured that no other thread will be able to lock the thread
until the original thread releases the lock.
3. Non-Busy Wait - If a thread attempts to lock a thread that was locked by a second thread, the first thread will be
suspended (and will not consume any CPU resources) until the lock is freed by the second thread. At this time,
the first thread will wake up and continue execution, having the mutex locked by it.
From these three points we can see how a mutex can be used to assure exclusive access to variables (or in general
critical code sections). Here is some pseudo-code that updates the two variables we were talking about in the previous
section, and can be used by the first thread:
lock mutex 'X1'.
set first variable to '0'.
set second variable to '0'.
unlock mutex 'X1'.
Assuming both threads use the same mutex, we are assured that after they both ran through this code, either both
variables are set to '0', or both are set to '1'. You'd note this requires some work from the programmer - If a third thread
was to access these variables via some code that does not use this mutex, it still might mess up the variable's contents.
Thus, it is important to enclose all the code that accesses these variables in a small set of functions, and always use only
these functions to access these variables.
In order to create a mutex, we first need to declare a variable of type pthread_mutex_t, and then initialize it. The
simplest way it by assigning it the PTHREAD_MUTEX_INITIALIZER constant. So we'll use a code that looks
something like this:
One note should be made here: This type of initialization creates a mutex called 'fast mutex'. This means that if a thread
locks the mutex and then tries to lock it again, it'll get stuck - it will be in a deadlock.
There is another type of mutex, called 'recursive mutex', which allows the thread that locked it, to lock it several more
times, without getting blocked (but other threads that try to lock the mutex now will get blocked). If the thread then
unlocks the mutex, it'll still be locked, until it is unlocked the same amount of times as it was locked. This is similar to
the way modern door locks work - if you turned it twice clockwise to lock it, you need to turn it twice
counter-clockwise to unlock it. This kind of mutex can be created by assigning the constant
PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP to a mutex variable.
In order to lock a mutex, we may use the function pthread_mutex_lock(). This function attempts to lock the
mutex, or block the thread if the mutex is already locked by another thread. In this case, when the mutex is unlocked by
the first process, the function will return with the mutex locked by our process. Here is how to lock a mutex (assuming
it was initialized earlier):
int rc = pthread_mutex_lock(&a_mutex);
if (rc) { /* an error has occurred */
perror("pthread_mutex_lock");
pthread_exit(NULL);
}
/* mutex is now locked - do your stuff. */
.
.
After the thread did what it had to (change variables or data structures, handle file, or whatever it intended to do), it
should free the mutex, using the pthread_mutex_unlock() function, like this:
rc = pthread_mutex_unlock(&a_mutex);
if (rc) {
perror("pthread_mutex_unlock");
pthread_exit(NULL);
}
Destroying A Mutex
After we finished using a mutex, we should destroy it. Finished using means no thread needs it at all. If only one thread
finished with the mutex, it should leave it alive, for the other threads that might still need to use it. Once all finished
using it, the last one can destroy it using the pthread_mutex_destroy() function:
rc = pthread_mutex_destroy(&a_mutex);
After this call, this variable (a_mutex) may not be used as a mutex any more, unless it is initialized again. Thus, if one
destroys a mutex too early, and another thread tries to lock or unlock it, that thread will get a EINVAL error code from
the lock or unlock function.
After we have seen the full life cycle of a mutex, lets see an example program that uses a mutex. The program
introduces two employees competing for the "employee of the day" title, and the glory that comes with it. To simulate
that in a rapid pace, the program employs 3 threads: one that promotes Danny to "employee of the day", one that
promotes Moshe to that situation, and a third thread that makes sure that the employee of the day's contents is
consistent (i.e. contains exactly the data of one employee).
Two copies of the program are supplied. One that uses a mutex, and one that does not. Try them both, to see the
differences, and be convinced that mutexes are essential in a multi-threaded environment.
The programs themselves are in the files accompanying this tutorial. The one that uses a mutex is
employee-with-mutex.c. The one that does not use a mutex is employee-without-mutex.c. Read the comments inside
the source files to get a better understanding of how they work.
Again we should remember that pthread_mutex_lock() might block for a non-determined duration, in case of
the mutex being already locked. If it remains locked forever, it is said that our poor thread is "starved" - it was trying to
acquire a resource, but never got it. It is up to the programmer to ensure that such starvation won't occur. The pthread
library does not help us with that.
The pthread library might, however, figure out a "deadlock". A deadlock is a situation in which a set of threads are all
waiting for resources taken by other threads, all in the same set. Naturally, if all threads are blocked waiting for a
mutex, none of them will ever come back to life again. The pthread library keeps track of such situations, and thus
would fail the last thread trying to call pthread_mutex_lock(), with an error of type EDEADLK. The programmer
should check for such a value, and take steps to solve the deadlock somehow.
A condition variable is a mechanism that allows threads to wait (without wasting CPU cycles) for some even to occur.
Several threads may wait on a condition variable, until some other thread signals this condition variable (thus sending a
notification). At this time, one of the threads waiting on this condition variable wakes up, and can act on the event. It is
possible to also wake up all threads waiting on this condition variable by using a broadcast method on this variable.
Note that a condition variable does not provide locking. Thus, a mutex is used along with the condition variable, to
provide the necessary locking when accessing this condition variable.
Creation of a condition variable requires defining a variable of type pthread_cond_t, and initializing it properly.
Initialization may be done with either a simple use of a macro named PTHREAD_COND_INITIALIZER or the usage
of the pthread_cond_init() function. We will show the first form here:
In order to signal a condition variable, one should either the pthread_cond_signal() function (to wake up a
only one thread waiting on this variable), or the pthread_cond_broadcast() function (to wake up all threads
waiting on this variable). Here is an example using signal, assuming 'got_request' is a properly initialized condition
variable:
int rc = pthread_cond_signal(&got_request);
Or by using the broadcast function:
int rc = pthread_cond_broadcast(&got_request);
When either function returns, 'rc' is set to 0 on success, and to a non-zero value on failure. In such a case (failure), the
return value denotes the error that occured (EINVAL denotes that the given parameter is not a condition variable.
ENOMEM denotes that the system has run out of memory.
Note: success of a signaling operation does not mean any thread was awakened - it might be that no thread was
waiting on the condition variable, and thus the signaling does nothing (i.e. the signal is lost).
It is also not remembered for future use - if after the signaling function returns another thread starts waiting on this
condition variable, a further signal is required to wake it up.
If one thread signals the condition variable, other threads would probably want to wait for this signal. They may do so
using one of two functions, pthread_cond_wait() or pthread_cond_timedwait(). Each of these
functions takes a condition variable, and a mutex (which should be locked before calling the wait function), unlocks the
mutex, and waits until the condition variable is signaled, suspending the thread's execution. If this signaling causes the
thread to awake (see discussion of pthread_cond_signal() earlier), the mutex is automagically locked again by
the wait funciton, and the wait function returns.
The only difference between these two functions is that pthread_cond_timedwait() allows the programmer to
specify a timeout for the waiting, after which the function always returns, with a proper error value (ETIMEDOUT) to
notify that condition variable was NOT signaled before the timeout passed. The pthread_cond_wait() would
wait indefinitely if it was never signaled.
Here is how to use these two functions. We make the assumption that 'got_request' is a properly initialized condition
variable, and that 'request_mutex' is a properly initialized mutex. First, we try the pthread_cond_wait()
function:
As you can see, the timed wait version is way more complex, and thus better be wrapped up by some function, rather
then being re-coded in every necessary location.
Note: it might be that a condition variable that has 2 or more threads waiting on it is signaled many times, and yet one
of the threads waiting on it never awakened. This is because we are not guaranteed which of the waiting threads is
awakened when the variable is signaled. It might be that the awakened thread quickly comes back to waiting on the
condition variables, and gets awakened again when the variable is signaled again, and so on. The situation for the
un-awakened thread is called 'starvation'. It is up to the programmer to make sure this situation does not occur if it
implies bad behavior. Yet, in our server example from before, this situation might indicate requests are coming in a
very slow pace, and thus perhaps we have too many threads waiting to service requests. In this case, this situation is
actually good, as it means every request is handled immediately when it arrives.
Note 2: when the mutex is being broadcast (using pthread_cond_broadcast), this does not mean all threads are running
together. Each of them tries to lock the mutex again before returning from their wait function, and thus they'll start
running one by one, each one locking the mutex, doing their work, and freeing the mutex before the next thread gets its
chance to run.
After we are done using a condition variable, we should destroy it, to free any system resources it might be using. This
can be done using the pthread_cond_destroy(). In order for this to work, there should be no threads waiting on
this condition variable. Here is how to use this function, again, assuming 'got_request' is a pre-initialized condition
variable:
int rc = pthread_cond_destroy(&got_request);
if (rc == EBUSY) { /* some thread is still waiting on this condition variable */
/* handle this case here... */
.
.
}
What if some thread is still waiting on this variable? depending on the case, it might imply some flaw in the usage of
this variable, or just lack of proper thread cleanup code. It is probably good to alert the programmer, at least during
debug phase of the program, of such a case. It might mean nothing, but it might be significant.
A note should be taken about condition variables - they are usually pointless without some real condition checking
combined with them. To make this clear, lets consider the server example we introduced earlier. Assume that we use
the 'got_request' condition variable to signal that a new request has arrived that needs handling, and is held in some
requests queue. If we had threads waiting on the condition variable when this variable is signaled, we are assured that
one of these threads will awake and handle this request.
However, what if all threads are busy handling previous requests, when a new one arrives? the signaling of the
condition variable will do nothing (since all threads are busy doing other things, NOT waiting on the condition variable
now), and after all threads finish handling their current request, they come back to wait on the variable, which won't
necessarily be signaled again (for example, if no new requests arrive). Thus, there is at least one request pending, while
all handling threads are blocked, waiting for a signal.
In order to overcome this problem, we may set some integer variable to denote the number of pending requests, and
have each thread check the value of this variable before waiting on the variable. If this variable's value is positive, some
request is pending, and the thread should go and handle it, instead of going to sleep. Further more, a thread that handled
a request, should reduce the value of this variable by one, to make the count correct.
Lets see how this affects the waiting code we have seen above.
As an example for the actual usage of condition variables, we will show a program that simulates the server we have
described earlier - one thread, the receiver, gets client requests. It inserts the requests to a linked list, and a hoard of
threads, the handlers, are handling these requests. For simplicity, in our simulation, the receiver thread creates requests
and does not read them from real clients.
The program source is available in the file thread-pool-server.c, and contains many comments. Please read the source
file first, and then read the following clarifying notes.
1. The 'main' function first launches the handler threads, and then performs the chord of the receiver thread, via its
main loop.
2. A single mutex is used both to protect the condition variable, and to protect the linked list of waiting requests.
This simplifies the design. As an exercise, you may think how to divide these roles into two mutexes.
3. The mutex itself MUST be a recursive mutex. In order to see why, look at the code of the 'handle_requests_loop'
function. You will notice that it first locks the mutex, and afterwards calls the 'get_request' function, which locks
the mutex again. If we used a non-recursive mutex, we'd get locked indefinitely in the mutex locking operation
of the 'get_request' function.
You may argue that we could remove the mutex locking in the 'get_request' function, and thus remove the
double-locking problem, but this is a flawed design - in a larger program, we might call the 'get_request' function
from other places in the code, and we'll need to check for proper locking of the mutex in each of them.
4. As a rule, when using recursive mutexes, we should try to make sure that each lock operation is accompanied by
a matching unlock operation in the same function. Otherwise, it will be very hard to make sure that after locking
the mutex several times, it is being unlocked the same number of times, and deadlocks would occur.
5. The implicit unlocking and re-locking of the mutex on the call to the pthread_cond_wait() function is
confusing at first. It is best to add a comment regarding this behavior in the code, or else someone that reads this
code might accidentally add a further mutex lock.
6. When a handler thread handles a reuqest - it should free the mutex, to avoid blocking all the other handler
threads. After it finished handling the request, it sohuld lock the mutex again, and check if there are moer
requests to handle.
"Private" thread data - Thread-Specific Data
In "normal", single-thread programs, we sometimes find the need to use a global variable. Ok, so good old teach' told
us it is bad practice to have global variables, but they sometimes do come handy. Especially if they are static variables -
meaning, they are recognized only on the scope of a single file.
In multi-threaded programs, we also might find a need for such variables. We should note, however, that the same
variable is accessible from all the threads, so we need to protect access to it using a mutex, which is extra overhead.
Further more, we sometimes need to have a variable that is 'global', but only for a specific thread. Or the same 'global'
variable should have different values in different threads. For example, consider a program that needs to have one
globally accessible linked list in each thread, but note the same list. Further, we want the same code to be executed by
all threads. In this case, the global pointer to the start of the list should be point to a different address in each thread.
In order to have such a pointer, we need a mechanism that enables the same global variable to have a different location
in memory. This is what the thread-specific data mechanism is used for.
In the thread-specific data (TSD) mechanism, we have notions of keys and values. Each key has a name, and pointer to
some memory area. Keys with the same name in two separate threads always point to different memory locations - this
is handled by the library functions that allocate memory blocks to be accessed via these keys. We have a function to
create a key (invoked once per key name for the whole process), a function to allocate memory (invoked separately in
each thread), and functions to de-allocate this memory for a specific thread, and a function to destroy the key, again,
process-wide. we also have functions to access the data pointed to by a key, either setting its value, or returning the
value it points to.
The pthread_key_create() function is used to allocate a new key. This key now becomes valid for all threads in
our process. When a key is created, the value it points to defaults to NULL. Later on each thread may change its copy
of the value as it wishes. Here is how to use this function:
/* create the key, supplying a function that'll be invoked when it's deleted. */
rc = pthread_key_create(&list_key, cleanup_list);
Some notes:
1. After pthread_key_create() returns, the variable 'list_key' points to the newly created key.
2. The function pointer passed as second parameter to pthread_key_create(), will be automatically invoked
by the pthread library when our thread exits, with a pointer to the key's value as its parameter. We may supply a
NULL pointer as the function pointer, and then no function will be invoked for key. Note that the function will
be invoked once in each thread, even thought we created this key only once, in one thread.
If we created several keys, their associated destructor functions will be called in an arbitrary order, regardless of
the order of keys creation.
3. If the pthread_key_create() function succeeds, it returns 0. Otherwise, it returns some error code.
4. There is a limit of PTHREAD_KEYS_MAX keys that may exist in our process at any given time. An attempt to
create a key after PTHREAD_KEYS_MAX exits, will cause a return value of EAGAIN from the
pthread_key_create() function.
After we have created a key, we may access its value using two pthread functions: pthread_getspecific() and
pthread_setspecific(). The first is used to get the value of a given key, and the second is used to set the data
of a given key. A key's value is simply a void pointer (void*), so we can store in it anything that we want. Lets see how
to use these functions. We assume that 'a_key' is a properly initialized variable of type pthread_key_t that contains
a previously created key:
.
.
/* and somewhere later in our code... */
.
.
/* get the value of key 'a_key' and print it. */
{
int* p_keyval = (int*)pthread_getspecific(a_key);
if (p_keyval != NULL) {
printf("value of 'a_key' is: %d\n", *p_keyval);
}
}
Note that if we set the value of the key in one thread, and try to get it in another thread, we will get a NULL, since this
value is distinct for each thread.
Note also that there are two cases where pthread_getspecific() might return NULL:
1. The key supplied as a parameter is invalid (e.g. its key wasn't created).
2. The value of this key is NULL. This means it either wasn't initialized, or was set to NULL explicitly by a
previous call to pthread_setspecific().
Deleting Thread-Specific Data Block
The pthread_key_delete() function may be used to delete keys. But do not be confused by this function's name:
it does not delete memory associated with this key, nor does it call the destructor function defined during the key's
creation. Thus, you still need to do memory cleanup on your own if you need to free this memory during runtime.
However, since usage of global variables (and thus also thread-specific data), you usually don't need to free this
memory until the thread terminate, in which case the pthread library will invoke your destructor functions anyway.
Using this function is simple. Assuming list_key is a pthread_key_t variable pointing to a properly created key,
use this function like this:
int rc = pthread_key_delete(key);
the function will return 0 on success, or EINVAL if the supplied variable does not point to a valid TSD key.
A Complete Example
None yet. Give me a while to think of one...... sorry. All i can think of right now is 'global variables are evil'. I'll try to
find a good example for the future. If you have a good example, please let me know.
Canceling A Thread
When we want to terminate a thread, we can use the pthread_cancel function. This function gets a thread ID as a
parameter, and sends a cancellation request to this thread. What this thread does with this request depends on its state.
It might act on it immediately, it might act on it when it gets to a cancellation point (discussed below), or it might
completely ignore it. We'll see later how to set the state of a thread and define how it acts on cancellation requests. Lets
first see how to use the cancel function. We assume that 'thr_id' is a variable of type pthread_id containing the ID
of a running thread:
pthread_cancel(thr_id);
A thread's cancel state may be modified using several methods. The first is by using the
pthread_setcancelstate() function. This function defines whether the thread will accept cancellation requests
or not. The function takes two arguments. One that sets the new cancel state, and one into which the previous cancel
state is stored by the function. Here is how it is used:
int old_cancel_state;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_cancel_state);
This will disable canceling this thread. We can also enable canceling the thread like this:
int old_cancel_state;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_cancel_state);
Note that you may supply a NULL pointer as the second parameter, and then you won't get the old cancel state.
A similar function, named pthread_setcanceltype() is used to define how a thread responds to a cancellation
request, assuming it is in the 'ENABLED' cancel state. One option is to handle the request immediately
(asynchronously). The other is to defer the request until a cancellation point. To set the first option (asynchronous
cancellation), do something like:
int old_cancel_type;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old_cancel_type);
int old_cancel_type;
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &old_cancel_type);
Note that you may supply a NULL pointer as the second parameter, and then you won't get the old cancel type.
You might wonder - "What if i never set the cancellation state or type of a thread?". Well, in such a case, the
pthread_create() function automatically sets the thread to enabled deferred cancellation, that is,
PTHREAD_CANCEL_ENABLE for the cancel mode, and PTHREAD_CANCEL_DEFERRED for the cancel type.
Cancellation Points
As we've seen, a thread might be in a state where it does not handle cancel requests immediately, but rather defers them
until it reaches a cancellation point. So what are these cancellation points?
In general, any function that might suspend the execution of a thread for a long time, should be a cancellation point. In
practice, this depends on the specific implementation, and how conformant it is to the relevant POSIX standard (and
which version of the standard it conforms to...). The following set of pthread functions serve as cancellation points:
● pthread_join()
● pthread_cond_wait()
● pthread_cond_timedwait()
● pthread_testcancel()
● sem_wait()
● sigwait()
This means that if a thread executes any of these functions, it'll check for deferred cancel requests. If there is one, it will
execute the cancellation sequence, and terminate. Out of these functions, pthread_testcancel() is unique - it's
only purpose is to test whether a cancellation request is pending for this thread. If there is, it executes the cancellation
sequence. If not, it returns immediately. This function may be used in a thread that does a lot of processing without
getting into a "natural" cancellation state.
Note: In real conformant implementations of the pthreads standard, normal system calls that cause the process to
block, such as read(), select(), wait() and so on, are also cancellation points. The same goes for standard C
library functions that use these system calls (the various printf functions, for example).
One of the features the pthreads library supplies is the ability for a thread to clean up after itself, before it exits. This is
done by specifying one or more functions that will be called automatically by the pthreads library when the thread
exits, either due to its own will (e.g. calling pthread_exit()), or due to it being canceled.
Two functions are supplied for this purpose. The pthread_cleanup_push() function is used to add a cleanup
function to the set of cleanup functions for the current thread. The pthread_cleanup_pop() function removes the
last function added with pthread_cleanup_push(). When the thread terminates, its cleanup functions are called
in the reverse order of their registration. So the the last one to be registered is the first one to be called.
When the cleanup functions are called, each one is supplied with one parameter, that was supplied as the second
parameter to the pthread_cleanup_push() function call. Lets see how these functions may be used. In our
example we'll see how these functions may be used to clean up some memory that our thread allocates when it starts
running.
/* and finally, we unregister the cleanup handler. our method may seem */
/* awkward, but please read the comments below for an explanation. */
As we can see, we allocated some memory here, and registered a cleanup handler that will free this memory when our
thread exits. After the execution of the main loop of our thread, we unregistered the cleanup handler. This must be done
in the same function that registered the cleanup handler, and in the same nesting level, since both
pthread_cleanup_pop() and pthread_cleanup_pop() functions are actually macros that add a '{' symbol
and a '}' symbol, respectively.
As to the reason that we used that complex piece of code to unregister the cleanup handler, this is done to assure that
our thread won't get canceled in the middle of the execution of our cleanup handler. This could have happened if our
thread was in asynchronous cancellation mode. Thus, we made sure it was in deferred cancellation mode, then
unregistered the cleanup handler, and finally restored whatever cancellation mode our thread was in previously. Note
that we still assume the thread cannot be canceled in the execution of pthread_cleanup_pop() itself - this is
true, since pthread_cleanup_pop() is not a cancellation point.
Sometimes it is desired for a thread to wait for the end of execution of another thread. This can be done using the
pthread_join() function. It receives two parameters: a variable of type pthread_t, denoting the thread to be
joined, and an address of a void* variable, into which the exit code of the thread will be placed (or
PTHREAD_CANCELED if the joined thread was canceled).
The pthread_join() function suspends the execution of the calling thread until the joined thread is terminated.
For example, consider our earlier thread pool server. Looking back at the code, you'll see that we used an odd
sleep() call before terminating the process. We did this since the main thread had no idea when the other threads
finished processing all pending requests. We could have solved it by making the main thread run a loop of checking if
no more requests are pending, but that would be a busy loop.
A cleaner way of implementing this, is by adding three changes to the code:
1. Tell the handler threads when we are done creating requests, by setting some flag.
2. Make the threads check, whenever the requests queue is empty, whether or not new requests are supposed to be
generated. If not, then the thread should exit.
3. Make the main thread wait for the end of execution of each of the threads it spawned.
The first 2 changes are rather easy. We create a global variable named 'done_creating_requests' and set it to '0' initially.
Each thread checks the contents of this variable every time before it intends to go to wait on the condition variable (i.e.
the requests queue is empty).
The main thread is modified to set this variable to '1' after it finished generating all requests. Then the condition
variable is being broadcast, in case any of the threads is waiting on it, to make sure all threads go and check the
'done_creating_requests' flag.
The last change is done using a pthread_join() loop: call pthread_join() once for each handler thread. This
way, we know that only after all handler threads have exited, this loop is finished, and then we may safely terminate the
process. If we didn't use this loop, we might terminate the process while one of the handler threads is still handling a
request.
The modified program is available in the file named thread-pool-server-with-join.c. Look for the word 'CHANGE' (in
capital letters) to see the locations of the three changes.
Detaching A Thread
We have seen how threads can be joined using the pthread_join() function. In fact, threads that are in a 'join-able'
state, must be joined by other threads, or else their memory resources will not be fully cleaned out. This is similar to
what happens with processes whose parents didn't clean up after them (also called 'orphan' or 'zombie' processes).
If we have a thread that we wish would exit whenever it wants without the need to join it, we should put it in the
detached state. This can be done either with appropriate flags to the pthread_create() function, or by using the
pthread_detach() function. We'll consider the second option in our tutorial.
The pthread_detach() function gets one parameter, of type pthread_t, that denotes the thread we wish to put
in the detached state. For example, we can create a thread and immediately detach it with a code similar to this:
Of-course, if we wish to have a thread in the detached state immediately, using the first option (setting the detached
state directly when calling pthread_create() is more efficient.
Our next example is much larger then the previous examples. It demonstrates how one could write a multi-threaded
program in C, in a more or less clean manner. We take our previous thread-pool server, and enhance it in two ways.
First, we add the ability to tune the number of handler threads based on the requests load. New threads are created if the
requests queue becomes too large, and after the queue becomes shorter again, extra threads are canceled.
Second, we fix up the termination of the server when there are no more new requests to handle. Instead of the ugly
sleep we used in our first example, this time the main thread waits for all threads to finish handling their last requests,
by joining each of them using pthread_join().
The code is now being split to 4 separate files, as follows:
1. requests_queue.c - This file contains functions to manipulate a requests queue. We took the add_request()
and get_request() functions and put them here, along with a data structure that contains all the variables
previously defined as globals - pointer to queue's head, counter of requests, and even pointers to the queue's
mutex and condition variable. This way, all the manipulation of the data is done in a single file, and all its
functions receive a pointer to a 'requests_queue' structure.
2. handler_thread.c - this contains the functions executed by each handler thread - a function that runs the main
loop (an enhanced version of the 'handle_requests_loop()' function, and a few local functions explained below).
We also define a data structure to collect all the data we want to pass to each thread. We pass a pointer to such a
structure as a parameter to the thread's function in the pthread_create() call, instead of using a bunch of
ugly globals: the thread's ID, a pointer to the requests queue structure, and pointers to the mutex and condition
variable to be used.
3. handler_threads_pool.c - here we define an abstraction of a thread pool. We have a function to create a thread, a
function to delete (cancel) a thread, and a function to delete all active handler threads, called during program
termination. we define here a structure similar to that used to hold the requests queue, and thus the functions are
similar. However, because we only access this pool from one thread, the main thread, we don't need to protect it
using a mutex. This saves some overhead caused by mutexes. the overhead is small, but for a busy server, it
might begin to become noticeable.
4. main.c - and finally, the main function to rule them all, and in the system bind them. This function creates a
requests queue, creates a threads pool, creates few handler threads, and then starts generating requests. After
adding a request to the queue, it checks the queue size and the number of active handler threads, and adjusts the
number of threads to the size of the queue. We use a simple water-marks algorithm here, but as you can see from
the code, it can be easily be replaced by a more sophisticated algorithm. In our water-marks algorithm
implementation, when the high water-mark is reached, we start creating new handler threads, to empty the queue
faster. Later, when the low water-mark is reached, we start canceling the extra threads, until we are left with the
original number of handler threads.
After rewriting the program in a more manageable manner, we added code that uses the newly learned pthreads
functions, as follows:
1. Each handler thread created puts itself in the deferred cancellation mode. This makes sure that when it gets
canceled, it can finish handling its current request, before terminating.
2. Each handler thread also registers a cleanup function, to unlock the mutex when it terminates. This is done, since
a thread is most likely to get canceled when calling pthread_cond_wait(), which is a cancellation point.
Since the function is called with the mutex locked, it might cause the thread to exit and cause all other threads to
'hang' on the mutex. Thus, unlocking the mutex in a cleanup handler (registered with the
pthread_cleanup_push() function) is the proper solution.
3. Finally, the main thread is set to clean up properly, and not brutally, as we did before. When it wishes to
terminate, it calls the 'delete_handler_threads_pool()' function, which calls pthread_join for each remaining
handler thread. This way, the function returns only after all handler threads finished handling their last request.
Please refer to the source code for the full details. Reading the header files first will make it easier to understand the
design. To compile the program, just switch to the thread-pool-server-changes directory, and type 'gmake'.
Exercise: our last program contains some possible race condition during its termination process. Can you see what this
race is all about? Can you offer a complete solution to this problem? (hint - think of what happens to threads deleted
using 'delete_handler_thread()').
Exercise 2: the way we implement the water-marks algorithm might come up too slow on creation of new threads. Try
thinking of a different algorithm that will shorten the average time a request stays on the queue until it gets handled.
Add some code to measure this time, and experiment until you find your "optimal pool algorithm". Note - Time should
be measured in very small units (using the getrusage system call), and several runs of each algorithm should be
made, to get more accurate measurements.
As an example, we will write a simple character-mode program that counts the number of lines in a file, while allowing
the user to cancel the operation in the middle.
Our main thread will launch one thread to perform the line counting, and a second thread to check for user input. After
that, the main thread waits on a condition variable. When any of the threads finishes its operation, it signals this
condition variable, in order to let the main thread check what happened. A global variable is used to flag whether or not
a cancel request was made by the user. It is initialized to '0', but if the user-input thread receives a cancellation request
(the user pressing 'e'), it sets this flag to '1', signals the condition variable, and terminates. The line-counting thread will
signal the condition variable only after it finished its computation.
Before you go read the program, we should explain the use of the system() function and the 'stty' Unix command.
The system() function spawns a shell in which it executes the Unix command given as a parameter. The stty Unix
command is used to change terminal mode settings. We use it to switch the terminal from its default, line-buffered
mode, to a character mode (also known as raw mode), so the call to getchar() in the user-input thread will return
immediatly after the user presses any key. If we hadn't done so, the system will buffer all input to the program until the
user presses the ENTER key. Finally, since this raw mode is not very useful (to say the least) once the program
terminates and we get the shell prompt again, the user-input thread registers a cleanup function that restores the normal
terminal mode, i.e. line-buffered. For more info, please refer to stty's manual page.
The program's source can be found in the file line-count.c. The name of the file whose lines it reads is hardcoded to
'very_large_data_file'. You should create a file with this name in the program's directory (large enough for the
operation to take enough time). Alternatively, you may un-compress the file 'very_large_data_file.Z' found in this
directory, using the command:
uncompress very_large_data_file.Z
note that this will create a 5MB(!) file named 'very_large_data_file', so make sure you have enough free disk-space
before performing this operation.
Side-Notes
water-marks algorithm
An algorithm used mostly when handling buffers or queues: start filling in the queue. If its size exceeds a
threshold, known as the high water-mark, stop filling the queue (or start emptying it faster). Keep this state until
the size of the queue becomes lower then another threshold, known as the low water-mark. At this point, resume
the operation of filling the queue (or return the emptying speed to the original speed).
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Tutorials
The following set of tutorials reflects an effort to give Unix programmers and programmers
wanna-be a chance to get familiar with various aspects of programming on Unix-like systems,
without the need to buy an expensive set of books and spending a lot of time in understanding
lots of technical material. The one assumption common to all tutorials (unless stated otherwise)
is that you already know C programming on any system.
The general intention is to allow someone to get familiar with a subject rather quickly, so they
can start experimenting with it, and allow them to read a more thorough user manual or
reference manual after they got over the initial "fear". By no means will these tutorials suffice to
turn anyone into a proficient professional, but one needs to start somewhere and then again,
why not do it for free?
Tutorials Index (note - each tutorial may be browsed online, or downloaded as a .tar.gz
archive). Size of each tutorial is given in ammount of screen-pages when viewed using the lynx
text-based web browser (assuming 25 lines per page):
1. Unix Beginners
1. Compiling C/C++ Programs On Unix (archive) (~15 lynx pages)
2. Debugging With "gdb" (archive) (~11 lynx pages)
3. Automating Program Compilation Using Makefiles (archive) (~13 lynx pages)
4. Manipulating Files And Directories In Unix (archive) (~50 lynx pages)
2. Intermediate Level
1. Creating And Using C Libraries (archive) (~18 lynx pages)
2. Unix Signals Programming (archive) (~27 lynx pages)
3. Internetworking With Unix Sockets (archive) (~21 + ~44 lynx pages)
4. Accessing User Information On A Unix System (archive) (~38 lynx pages)
5. Graphics Programming
1. Basic Graphics Programming With The Xlib Library (archive) (~59 + ~44
lynx pages)
3. Advanced Topics
1. Parallel Programming - Basic Theory For The Unwary (archive) (~29 lynx pages)
2. Multi-Threaded Programming With The Pthreads Library (archive) (~60 lynx
pages)
3. Multi-Process Programming Under Unix (archive) (~80 lynx pages)
Note: The levels mentioned here are just to give one a basic idea of what they are sticking their
head into, before they delve into the tutorial. Your experience will vary based on your
theoretical background, and your experience (for example, an experienced programmer coming
from another platform will probably find most of these tutorials to be rather easy).
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
The LUPG's little site is dedicated to people who want to learn about Unix programming. Is is
intended to form a little community of people who will focus on learning various programming
topics, and then teach others.
The majority of the site is dedicated to a set of tutorials, each dedicated to one issue in Unix
programming. The tutorials are divided to small groups of inter-related categories, and all can
be either browsed online, or downloaded to your computer and viewed locally.
Other sections of the site include project ideas and a new section with essays about software
engineering issues.
There is also the unavoidable page of info about related sites and material.
If you want to get automatic e-mail notifications about new tutorials or changes to this site, you
may use the automatic e-mail notification form.
Note: This site is presented as a spare-time activity, in the hope that it will be useful, but
without any expressed or implied warranty. See the standard disclaimer for more info.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
This site is generated using the power of vim, perl, and gnu make.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Background
Quite often we write applications that have a large amount of options the user can configure. To ease the user's life, we allow her to write
a small configuration file, that our application will read when it starts running, and act upon. If we are not too lazy, we also write some
interface that lets the user modify the configuration, and the configuration file is updated automatically.
Details
3. API. The following set of functions should be written, which will
be used as an interface for the programmer. Other functions may be
added in order to make your code more readable and flexible.
Write the contents of the given configuration data into the given
file. If the file does not exist, create it and emit the contents.
If the file already exists, only update the new, modified and
deleted variables, preserving any comments that might have existed
in the file, and preserving the order of its lines. New variables
should be appended to the end of the file.
.
char* home = getenv("HOME");
if (!home) {
fprintf(stderr, "Error: Environment variable "HOME" not defined!\n");
exit(1);
}
.
Now variable 'home' points to the contents of the HOME environment
variable.
1. The configuration file resides in the home directory of the user running the program. Finding the full path to this directory will be
done by reading the environment variable "HOME" using the getenv() function, as follows:
2. Configuration file format. The file is made of a set of independent
lines. Each line may have any of the following formats:
❍ Lines starting with the '#' sign are comments, and should be ignored.
name = value
❍ A line that is not a comment and does not contain the "=" character
should be printed out with a "bad syntax" error message (again,
including the line number and the line's contents).
❍ To make life easier, assume the file may not contain more then
100 variables (i.e. use arrays to hold the variables, not linked
lists or other less trivial data structures).
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Background
Any web server today keeps a log file into which it writes a line for each file that was served to a client. Each log record
contains the URL of the file, date and time of the retrieval, the IP address from which the client connected, and possibly some
more data.
One of the problems people face when trying to analyze this data, is understanding how many people actually entered their site,
and what each visitor exactly looked for in their site.
Of-course, the log file never allows us to get accurate data (sometimes an IP address stands for a proxy server representing
many users, sometimes people re-load the same page more then once, and so on), but we may deduce some general data that
will give us a "feeling" of what's going on. We can crudely treat all requests coming from the same IP address in a short period
of time, as representing a single user, and treat them accordingly. If we see another access from this IP address after a long
period of time (say, more then half an hour), we may assume it's a new user that happens to use the same IP address.
Details
1. The log file is kept in the default format that apache uses:
As an example, here is the LUPG's November 1998 log file, that you may use for testing your program.
2. Program's Output. The program should print out the following data:
❍ Number of users that accessed the site.
3. Log file may be very long. We should not make assumptions in our program regarding the size of the log file, and thus
should allocate memory dynamically as required.
4. Data Structures Used. In order to allow easy collection of data, we will define a structure to hold data for a specific
client, and an array to hold data for all clients. Here is how our data structures might look:
/* constants definitions */
#define MAX_TIME_LEN 26
#define MAX_ADDR_LEN 50
#define MAX_CONCURRENT_CLIENTS 200
We will make the assumption that the delay between two consecutive requests of a given client may not be more then
half an hour. This allows us to keep a rather small array of clients. We will see how this helps us when we discuss the
scanning algorithm. We also make the assumption that an entry in the clients array whose address field is an empty
string, is free for re-use.
6. Additions. One problem with our data structure is its slow lookup method. A site having many simultaneous visitors will
have its log file parsed very slow by our program. By using a move advanced data lookup method (such as hash tables,
we can speed up the whole program. Another problem is the usage of a lot of memory allocation. Other additions may be
better configure-ability (e.g. allow the user to change the "half hour rotation factor" using a command line option, allow
to also check how much data transfer each client has made, allow checking only fetches of files of a specific type.).
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Background
Many Unix servers and programs tend to maintain a log file, into which they write data about
operations they perform and their success or failure. For example, an ftp server will write each
login made through it, and possibly which files were erased via the server. The log data can
later be used to analyze security problems, or server malfunctions. These log files tend to grow,
and unless truncated, might fill up the disk.
The most common way of handling log file growth is via a rotation procedure. We first define
how many old copies of the log file we want to create, and the rate at which we want to rotate
them (once a day, once a week and so on). When we rotate a given log file, we rename the
original file to have a '.1' suffix, rename the old '.1' file to have a '.2' suffix, and so on. The last
copy of the log file (with suffix '.n') is being erased. of-course, we do this renaming from last to
first, otherwise we will end up with 'n' copies of the current log file. Once done, we create a
new, empty log file, with the same access permissions as the original log file.
Often the log file is kept open by the server writing into it, so we need to restart the server, so it
will start writing into the new log file. However, we will ignore this issue for this exercise.
Details
1. Rotation Procedure.
Write a function named 'rotate', that gets a file name and the number of old copies to
maintain as its parameters. This function will do the file renaming according to the
algorithm shown earlier. It will assume that the log file is in the current directory.
Remember to handle the case where less then 'n' old copies of the log file exist. In such
cases, the number of old copies should grow by one.
2. Main Function.
Write the main function, that reads three parameters from the command line: full path of
the logs directory, name of the log file to rotate, and number of old copies to maintain.
The main function will check that the directory exists, and that we have both read and
write access permission to the directory. It will then switch to the logs directory, and
invoke the 'rotate' function to do the actual job.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Background
Many programs are required to store some data in memory, and later on to look it up. Many types of data structures were
formed to handle these operations (such as arrays, linked lists, binary search trees, etc), with varying levels of complexity,
and a varying set of operations supported (adding items, deleting items, sorting items, locating items, finding the largest item
and so on). One of the genuine data structure used for purposes of very efficient data lookup is the hash table.
A hash table may contain objects that have keys, and values. The hash table is made of an array into which objects may be
inserted, and a hashing function. The hashing function takes a key as an argument, and uses it to calculate some index in the
range of the table's array. This function is used to map different elements to different arrays in the table.
When we want to insert an element in to the hash table, we calculate its hash value (the result of activating the hash function
on the element's key), and then go to the place in the array whose index equals this hash value, and insert the item there. If
this location in the table is already in use, we look for the nearest free location and place the element there (there are various
other variations for how to handle such "collisions". the method we describe here is called "simple hashing).
When we want to locate an element in the array (given its key), we calculate its hash value, and then start scanning the table
at the location whose index matches this hash value. If we find the element, we are done. If we find a different element, we
move to the next higher location (moving back to the beginning of the array if we are at the last element). We keep scanning
until we either find the element, or find an empty cell. Such an empty cell denotes that the element was not found in the
table, and thus the search fails.
When we want to delete an item from the hash table, we first locate it using the search algorithm. When we find it, we mark
that location as free, not as empty. Why is that? this will let the search algorithm go past this freed item, instead of stopping
there. Lets see an example. Suppose that we have a hash table made of 6 cells, and we insert three items 'A', 'B' and 'C', all of
which have '3' as their hash value. The first ('A') will be inserted into cell '3', the second ('B') to cell '4' (since '3' is now in
use), and the third ('C') will go into cell '5' (since both cells '3' and '4' are now in use):
-------------------------
| | | a | b | c | |
-------------------------
If we try to search for element 'C' now, we calculate its hash value, go look for it in location 2 (that contains 'A'), and due to
the mismatch start scanning to the right, skipping 'B', and eventually landing on 'C'. Now lets try to remove element 'B'. If we
marked its location as empty, the table would now look like this:
-------------------------
| | | a | | c | |
-------------------------
If we try to search for 'C' again, we calculate its hash value (2, as you probably remember), find element 'A' (no match) and
the next cell is empty, so we wrongly declare that 'C' was not found. Now, if when deleting 'B' we would mark it as 'free'
instead of as 'empty', the table would look like this:
-------------------------
| | | a | * | c | |
-------------------------
(* denotes a free cell). If we go to search for 'C' again, we land on 'A' (no match), go to the next cell (free cell, so no match,
but keep on looking), and finally land on 'C' - a match was found.
One last saying goes to the efficiency of the insert, search and lookup operations on a hash table. This is a function of two
factors: the density of the hash table (i.e. what percent of its cells actually contain elements), and the quality of the hashing
function, in the sense of how well it spreads the hashing values of its elements. For example, if the hashing function would
always return the value '1' for any element, then it's obvious to see that its associated hash table acts just like a linked list,
which is not very efficient for search operations (in average, you will need to scan half the table's cells in order to find an
item, and as the amount of elements grows, the search gets longer). Now, assuming a good hash function, it was found the if
the table is no more then 50% filled up, finding an element in the table takes about a single operation, while finding that a
table is not in the table takes about 2 operations (a good hash function will cause every other cell to be empty, and thus the
longest sequence of filled cells is.. 1 cell long). Note that this efficiency is affected only by the density of the table, not by
the number of elements in the table. Obviously, it is hard to find such a perfect hash function (unless we know something
about the nature of the elements' keys in advance), but many good hash functions would lead us to near-optimal results.
Details
1. API. The following set of functions should be written, which will be used as an interface for the programmer. Other
functions may be added in order to make your code more readable and flexible.
1. struct hash_table* create_hash_table(int size);
Create an empty hash table, with "size" cells. Return a pointer to a structure with the table's information, of
NULL in case of failure (e.g. out of free memory).
Insert the given element, with the given key, to the given hash table. Return '1' on success, '0' if an element with
the same key is already found in the table, or '-1' if the table is full.
Remove the element with the given key from the hash table. Return a pointer to the removed element, or NULL
if the element was not found in the table.
Delete the given hash table, freeing any memory it currently uses (but do NOT free any elements that might still
be in it).
Not an external function, but a must. There was a lot of research done regarding "what is a good hashing
function?". I'll present a very simple one here, but you should try your own ideas, and test them out on various
input sets:
Add the ASCII values of all characters in the key, and take the
result of their sum modulo the table size (in C notation, the '%'
operator calculates the modulo of a number. "i1 Modulo i2" means
"the remainder of dividing the i1 by i2).
2. Table With Varying Size. Since we saw how important it is for the table not to be too dense, we will now implement a
hash table of varying size. When an element's insertion causes the table to be too dense (for example, more then 70%
filled), we will make the table twice as large (thus making it about 35% filled). When an element's deletion causes the
table to be too dense (for example, less then 20% filled), we will cut its size by half (making it about 40% filled).
These table expansion and shrinking operations might be very costly - we need to modify the hash function to so that
it will generate numbers within the new range, and need to re-insert all the elements into the new table. However, in
most operations we win the efficiency of the very sparse table, so the efficiency for a set of insertion, deletion and
lookup operations is still kept. An Extended API is required to support this modified table:
1. void hash_set_resize_high_density(struct hash_table* htable, int
fill_factor);
Set the fill density of the table after which it will be expanded. The fill factor is a number between 1 and 100.
Set the fill density of the table below which it will be shrank. The fill factor is a number between 1 and 100.
Get the "high" fill density of the table. The fill factor is a number between 1 and 100.
Get the "low" fill density of the table. The fill factor is a number between 1 and 100.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Background
We have seen how we can generate timers using the ALRM signal, and we can use them in order to handle some
time-based operations. A good example would be writing a simple computer game, and what would be better then
trying out the old game of PacMan? It's much simpler then you might think...
The game allows the user to control Pac using the keyboard. Every short period of time (e.g. every two seconds)
the game needs to move the computer-controlled ghosts in a semi-intelligent manner (i.e. make it look like they are
chasing Pac). In addition to that, we need to set the keyboard into "raw" mode (so we can process key presses as
they are made, as opposed to the default line-mode of VT-100 terminals). At the end of the game (either normal
end, or brutal Ctrl-C end) we need to reset the keyboard to its normal line mode.
The "graphics" will be done using plain-text, with a 'c' denoting Pac, A '@' denoting a ghost, a '.' denoting a normal
point that Pac can eat, and a '%' denotes a power-point, that when ate by Pac, gives him the power to eat the ghosts
for a short period. Making the text displayed in specific locations on screen will be handled using something called
"VT-100 Escape sequences". These are character sequences that are interpreted specially by the terminal emulation
(instead of being printed as-is to the screen) and contains commands such as "place cursor in location X,Y", "clear
screen", and so on.
Details
1. VT-100 Escape Sequences.
All VT-100 escape sequences begin with the Escape character (ASCII code 033, in octal. In a string it is
denoted as '\033'). Here are a few useful sequences, and their meanings:
\033[2J
Clear the screen.
\033[H
Place the cursor at the top-left of the screen.
\033[30;20Hhello world
Print the string 'hello world' starting at row '30', column '20' on screen. 'hello world' may be replaced
by any other string. The same goes for the co-ordinates
\033[?25l
Disable echoing the cursor on screen (only supported in VT-220 or better emulations)
\033[?25h
Re-enable echoing the cursor on screen (only supported in VT-220 or better emulations)
2. Double Buffering.
When displaying animation, one can display all changes directly on the screen. When more then a single
change at a time is made, this has the effect of causing the screen to flicker. In order to avoid that, most
programs calculate all changes first, and then redraws the modified area in a single operation. This technique
is called double-buffering. In our program, we could use a two dimensional array to denote the screen, make
all calculations using this array, and then re-print the whole array at once. To be more efficient, we can hold
two such arrays. One shows the current state of the screen, the other is used to calculate the next screen-shot.
When we paint the new screen, we compare all cells of the two arrays, only redrawing those that differ.
There are various methods of handling of moving a character: where is Pac or a ghost allowed to go to, how
to make the movement "flow", etc. One method of checking where to go is by checking "what is in there?",
and defining a different icon for each type of square - 'W' for a wall, 'w' for the location of the ghosts house
(where Pac may not enter), '.' for a normal pill, '%' for a power pill, and a blank for an empty square. We say
that Pac is allowed to walk onto places containing anything but 'W' or 'w'. We also define that when Pac
steps on a pill, he eats it. However, when a ghost steps on a pill, it does not eat it, so we need to remember
the pill was there (and what was its type), in order to place it back there in the ghost's next move.
4. Screen Layout.
A game screen might look something like this layout. Note that in one place on each side there is a missing
wall - this forms the tunnel that allows Pac (as well as the ghosts) to "teleport" from one side of the screen to
the other in an instant. In the original game, moving through the tunnel took a short while, and it might be
that a ghost would kill Pac while both travel in the tunnel coming from opposite directions.
By default, a Unix terminal is set to line mode (or buffered mode). In this mode, the kernel buffers the user's
input until they press the ENTER key, allowing her to do simple editing (backspace over characters, delete
the whole line, etc). Once the user presses the ENTER key, the kernel passes the whole line of input to the
process reading from the terminal. This means that even if we use a function to read a single character, it
won't receive any input until the user presses ENTER. obviously, this is not a good idea for an action game,
when the user needs quick response to key presses. Furthermore, when the user presses a key, the system
echos it back on screen. This is also not good for an action game (we don't want to see the keys echoed back
to us, rather see them causing little Pac to move all over the screen).
The easy (and lazy) way to make these mode switches is by using the "stty" command. Here is how to enter
raw-mode with no echo (while still allowing Ctrl-C, Ctrl-Z and Ctrl-\ to send signals):
system("stty raw -echo isig");
The system() function executes the given Unix command in a sub-shell. In this case - runs stty with "raw
-echo isig" as its parameters. In order to restore normal mode (line mode with echo), we can use this:
system("stty -raw echo");
If you wish, you may read the manual page of "stty" for more info.
When we saw how to set timers using the alarm() system call, we were limited to delays of full seconds.
For an action game, this is not sufficient. Thus, we could use the setitimer() to generate the ALRM
signals. It allows us to specify intervals of micro-seconds, and to even ask the system to reinstate a timer
automatically after the first got set off. Note that setitimer() is not defined in POSIX, but it appears in
both BSD systems and SVR4 systems, so it may be assumed to be portable. Here is how to use it:
/* define the first timer to set off after 40,000 micro seconds. */
h.it_value.tv_sec = 0;
h.it_value.tv_usec = 40000;
/* define the interval between each two timer set-offs ('clicks') */
/* to be 40,000 micro seconds as well. */
h.it_interval.tv_sec = 0;
h.it_interval.tv_usec = 40000;
After the first call to setitimer(), the timer will set off every 40,000 microseconds, invoking whatever
handler we set for the SIGALRM signal.
In order to allow the program to handle both user input and alarms, our program will use the read()
system call in order to read user input, rather then the getchar() function. This is because receiving a
signal will cause read() to return immediately (this assumes the signal handler for SIGALRM was defined
using sigaction(), not using signal()). Thus, the main loop will begin with a read() on file
descriptor 0 (which is used for standard input), and then a test for the return code. If it is '-1', and errno
equals EINTR, then we probably got a SIGALRM, and thus should call the elements moving function.
Otherwise, the user probably pressed a key, and we should check which one, and switch Pac's moving
direction accordingly.
1. Write two functions to switch screen mode to raw mode and back.
2. Write a function that accepts 3 parameters: X and Y coordinates, and a string. The function prints the
given string in the given screen location (using VT-100 escape sequences). Remember NOT to print a
new-line character in the end!
3. Write a signal handler for SIGINT (Ctrl-C) to restore normal screen mode before exiting. Write
another handler for SIGTSTP (Ctrl-Z) to restore normal screen mode and suspend, and to restore raw
mode when the process resumes execution.
4. Write a signal handler for SIGALRM that sets a flag stating an alarm was received.
5. Write a function that moves Pac in his current direction, blocking him if he bounces to a wall, eating a
pill (and increasing score) if the new point contains a pill, setting on "power" mode if he eats a power
pill (or setting it off if it was set on, and the time limit for "power" mode has elapsed), killing Pac if he
stepped on a ghost (or killing the ghost, if this happens while "power" mode is set on).
6. Write a function that moves a single ghost, killing Pac if the ghost steps on Pac (or killing the ghost, if
"power" mode was on). The function should calculate where the ghost should go to next in order to
chase Pac. A simple function will just try to get it closer to Pac. Note that a ghost may never reverse
its moving direction. It may choose to continue forward, move left, or move right. This is how it is
done in the original game.
7. Write a function that performs all characters movements: moving Pac and moving the ghosts.
8. Write a function that gets two arrays, one describing the current screen layout, another that describes
the new (desired) screen layout. The function will perform the drawing, as described in the
double-buffering scheme earlier. Note that in order to allow the user a fair game, Pac must move faster
then the ghosts initially. As the game proceeds, the ghosts speed should be increased, to make it harder
to play. A good way to perform that is to make the timer tick very quickly, and then make Pac move
every 50 ticks, while the ghosts move every 100 ticks. As the game proceeds, decrease the number of
ticks between every move of the ghosts.
9. Finally, the main function registers the signal handlers, starts the timer (with setitimer()) and
performs the main loop of waiting for user input (or alarms).
9. Small Enhancements.
❍ Add levels to the game. The higher the level is, the faster the ghosts move.
❍ Add magical prizes, like in the original game. On occasion (randomally) they appear just below the
ghosts house, and give many points if Pac eats them. If they are left there for a period (for example, 15
seconds) they disappear.
❍ Enhance the ghosts' chasing algorithm. Make them cooperate (i.e. if one sees another is chasing back,
it will try to come in from the other direction). Try to come up with your own ideas.
❍ Write a "demo" mode, in which Pac is moved by the computer. Try to think of a smart algorithm for
Pac that enables him to eat all pills on screen, while keeping away from the ghosts.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Background
Serving files is one of the most common services of Unix servers. This is done using many
different types of protocols, such as FTP, NFS, SMB etc. These protocols are not very easy to
implement, so we will limit our exercise to our own proprietary protocol.
Generally, the file server has a given sub-directory on the server from which it serves files. Any
file path given to the file server by a client, is interpreted relative to that sub-directory. For
example, if the sub-directory on the server is "/export/files", and a client asks for a file whose
path is "/data/config.txt", the server will serve the file "/export/files/data/config.txt".
We also need to define some protocol used between the client and the server. The client will
send commands (with optional parameter), and the server will send responses. Each message
transfered will be preceded by the size of the message, so the receiving side will know how
many bytes to read. A message sent by the server will contain a return code, and may contain
the output of a command (such as a directory listing), or even a file (for a file transfer request).
Details
1. Protocol Details.
Once the command's output has been sent to the client, the server terminates the
connection.
You should define a constant for each message code, and use a shared header file that is
included by both the client and the server's code.
2. Flow Control.
In order not to abuse the system, every time a message is sent, the sending party should
perform proper checking to see if the socket is ready for write operations (using the
select() system call).
3. Security/Sanity Checks.
The server must check any parameter it got from the client:
1. Make sure the file path begins with a '/' character, and does not contain a '..'
sequence in it.
2. Allocate buffers large enough to accept reasonable command sizes. If the client
specifies a too long message size, send an "Internal Error" message and terminate
the connection.
4. The Client.
The client will have a command-line interface. It will accept a command and an optional
parameter, and send them to the server. The only command it accepts is "get", with a full
file path as a parameter.
5. Logging.
The server should write a one-line message to a log file regarding any of the following
operations (with a time and date at the beginning of each message):
1. A connection to a client is established. Write out the file descriptor of the socket
created for this connection.
2. A command was received from a client. Write out the command code, its
parameter, and the file descriptor through which it arrived.
3. A response was sent to a client. Write out the response code, its parameter, and the
file descriptor through which it arrived. The parameter is the message text (in case
of an error), or the file path (in case of a file transfer).
6. Advanced Options.
1. Multiple Clients.
Add support for multiple clients. The server should keep track of the state of
conversation it has with each client, and handle sending data for more then a given
amount of time - the connection to the stuck client is terminated.
2. Extra Commands.
Add support for the command "list" (with a path to a file or a directory as a
parameter, and a message code of '102'). The server will reply with a formated list
of the directory's contents (in case of a directory) or the file (if the path is that of a
file). The reply's message code will be '302' (if successful).
3. Persistent Connection.
Add support for a persistent connection (i.e. the TCP connection is kept open after
the server sent the response, to allow the client to send more requests). This time it
is the client that terminates the connection when done. Add a commands-reading
loop to the client side, so the user can type in more then one command. Add a
notion of a "current directory" in the client (NOT in the server), so the user can
type in partial paths (note that the "cd" command requires asking the server if the
new path is really a directory. add a new message type for checking this to the
protocol, and a new response type).
4. Timeout.
Add a checking for timeout by the server - if it got stuck with sending data for
more then a given amount of time - the connection to the stuck client is terminated.
This is tricky, and requires adding timers support on top of the select() loop.
Think how to implement this, using a delta list of timers, and the timeout
parameter of the select() system call.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Background
The HTTP (version 1.0) protocol is a simple protocol that allows a (web) client to requests files
from a server. Various types of requests can be sent by the client, the most basic (and the one
we'll implement) is the "GET" request, to fetch data files. The checks the request, returns a
header containing a result code, with the file attached after the header. Finally, the server closes
the connection.
The client's request might actually contain much more data (e.g. the preferred language for the
document, what MIME types the client understands etc.). Our server will simply ignore any of
these hints. This way, we will be able test our server using commonly used web browsers (lynx,
netscape, and even *gasp* internet explorer).
When the server sends a data file to the client, it needs to tell it a few things about the file: the
file's size (in bytes), the last modification date of the file (in the same format as returned by the
ctime() function), and the MIME type of the file. A MIME type is a string made of two
parts, separated by a '/' character. The first tells us what type of file we have (text, image, audio
and so on). The second part tells us the specific sub-type (gif and jpeg for images, x-wav and
mpeg for audio, html or plain for text, and so on). The server usually deduces the MIME type of
the file based on its extensions, not its contents, for efficiency reasons. Here are a few common
file extensions and their associated mime types:
.html
text/html
.htm
text/html
.txt
text/plain
.gif
image/gif
.jpg
image/jpeg
.qt
video/quicktime
If the server encounters an unknown suffix, it should attach a default mime type to the file
(many servers default to 'text/plain' for unknown suffixes, others use 'application/octet-stream',
to make sure the client won't try to mess with the file, but rather allow the user to save it to
disk).
Details
1. General Server Data. The server will serve files from a directory knows as the "root
documents directory". Any file path supplied by the client should be relative to this
directory.
2. Requests Acceptor Thread. One thread will work as the requests acceptor thread. It will
usually be blocked on the accept() system call, and then create a "client structure",
and place it on the incoming requests queue, an a fashion similar to that demonstrated in
our "multi-threaded requests handler" example.
3. Handler Threads. Each requests will be dequeued by a handler thread. The thread will get
the socket from the request, read the data from the client, and act upon it.
4. Request Parsing Module. A module should be written to parse the HTTP request, and
extract the relevant data from it (i.e. the request type and the file path). This module will
read directly from the socket, and generate a structure containing the parsed data. An
HTTP request might look like this:
GET / HTTP/1.0
<more headers come here>
Note that an empty line is used to denote the end of the request. If anything other then a
'GET' request is sent, we should eventually reply with an error message.
5. Reply Preparation Module. This module will take a request structure, and prepare a reply
structure, containing the result code, data and time, full path the the data file (if any),
MIME type of the file and last modification data of the file.
6. MIME-Type Deducing Module. This module is used to deduce the MIME type of a file,
based on the file name's extension. It will be made of a single function that gets a file
name as a parameter, and returns a string containing its MIME type. Initially we can store
all the MIME type mapping information in an array in memory, and search it linearly.
7. Reply Emitting Module. Another module will be responsible for generating a reply. It
will be given the reply structure, and will send its data over the socket, in an HTTP reply
format. This includes writing the header (result code, server type, date and time, MIME
type and size of attached file, if any, and last modification date of the file), followed by
the contents of the data file (again, if any). The reply would looks something like this:
HTTP/1.0 200 OK
Date: Fri, 13 Nov 1998 16:32:44 GMT
Server: Tiny-Tux/0.1a
Last-Modified: Sun, 01 Nov 1998 12:48:09 GMT
Content-Length: 4782
Content-Type: text/html
This reply is sent in case of success (i.e. request understood, file found and the server
managed to access it). Note the empty line separating the reply's header from the reply's
body.
If there was some error, the result code (first line) should be replaced by an appropriate
result code, and the file-related fields (e.g. "Last-Modified:", "Content-Length:" and
"Content-Type:") removed. Error codes go as follows:
HTTP/1.0 404 File Not Found
The requested file was not found.
HTTP/1.0 403 Forbidden
The server cannot open the file for reading.
HTTP/1.0 501 Method Not Implemented
The given request type is not implemented (i.e. something other then GET was
requested, such as 'PUT' or something completely illegal).
HTTP/1.0 400 Bad Request
The server failed to parse the request (e.g. the file path has an invalid format, the
protocol type/version was not specified, etc.).
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Unix Programming Frequently Asked
Questions
● About this FAQ
● 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?
❍ 1.15 Why doesn't my process get SIGHUP when its parent dies?
❍ 1.16 How can I kill all descendents of a process?
● 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?
■ 3.6.1 Serial device names and types
■ 3.6.2 Setting up termios flags
■ 3.6.2.1 c_iflag
■ 3.6.2.2 c_oflag
■ 3.6.2.3 c_cflag
■ 3.6.2.4 c_lflag
■ 3.6.2.5 c_cc
● 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?
● Examples
❍ Catching SIGCHLD
❍ Reading the process table -- SUNOS 4 version
❍ Reading the process table -- SYSV version
❍ Reading the process table -- AIX 4.2 version
❍ Reading the process table using popen and ps
❍ Daemon utility functions
❍ Modem handling example
❍ Job Control example
This document was generated on 1 September 2000 using the texi2html translator version 1.51.
Welcome to the home of the UNIX Socket FAQ!
There's some really major "under the hood" changes I've just made to the FAQ software that
drives this site. I've seperated the content from the functionality, and I'm releasing the source
under the GPL. I've named the software "Self Serve FAQ" because of the way it empowers the
users to add questions and provide answers without intervention from the FAQ maintainer. I've
created a new site on lcg.org for it at http://www.lcg.org/ssfaq/ and you can find out more about
it there.
I've added a couple of new features. First, you can download a single file version of the faq
here. Second, the main page now shows the most recent updates. Let me know if you notice any
quirks.
I've "upgraded" the sock-faq to the new software, so please let me know if you find any
problems by posting to the new ssfaq site. Hopefully I'll get any problems worked out early on.
My mirrors appear to have dissapeared, and it may be because they were difficult to keep
up-to-date before. One of the first things I want to work on with the new software is making the
whole mirror thing easier, so I hope to have mirrors available soon.
If you are looking for Dr. Charles Campbell's Simple Sockets Library, you can download
version 2.09 here.
Uncategorized Questions:
1. tracking socket calls
2. How can I determine the space available in the send buffer of a socket?
3. Socket question
4. How to act as server and client at the same time.
5. What are the implications of reducing receive buffer size?
6. reversed name resolving
7. How can I send packet on a choosen interface ?
8. Fix IP source address ?
9. How do I reject a pending connection?
10. Different Flavors of Pipe Signal
11. how to restart a server immediately
12. How to use sendmsg/recvmsg (or does anyone actually use this "feature"?)
13. Motorola 88k Gotcha
14. Socket question
15. Errors in sockets
16. problem in socket programming
17. client/server environment
18. Sending large ( > 50 meg) files (binary + ascii) through sockets
19. Proxy Handling
20. socket and XTI
21. Sending & Receiving data on a socket
22. Stream Sockets, Multithreading, and Windows
23. Subsequent connect call fails (EBADF); why?
24. HTML Client
25. Passing sockets to pre-forked children
26. Unix domain sockets using linux
27. Can port be shared ?
28. Reading from a port
29. java.net objects for reading port
30. Socket Programming
31. How do I get a MAC address using code on Solaris?
32. send object through socket
33. Client/Server mystery (sockets)
34. Connec to different hosts/ports from the same host/port
35. Compiler Difficulty
36. How to know if the sending buffer is fully empty?
37. How do I get the IP Adress to which a client connected to my server ?
38. client server program
39. What are the limits on the number of sockets?
40. How much new Bytes are in the Buffer for Inread ?
41. Socket and thread
42. Undefined Symbol Problem
43. synchronous and asynchronous communication using sockets
44. PORT NOT RESPONDING
45. How....
46. Asynchronous client
47. What do you do to constantly poll a file on the client side (Unix) and send it to server
(NT) ?
48. Asynchronous client ?
49. writeset in select
50. no client server setup !
51. Autoflush
52. using loopback interface for testing socket programs
53. Check readset and writeset at the same time
54. How to bind using struct sockaddr_ll..?
55. Opening a socket on a random port number
56. What is the meaning of the IDLE state in netstat command
57. How can the client know, if the server has accepted the connection?
58. How can the client know, if the server has accepted the connection?
59. Which error detection method to use?
60. concurrent server !
61. Discarding unwanted socket data
62. Options besides concurrent servers
63. read write continuosly!!!
64. Can I determine the number of pending connection request in the listen queue?
65. How can i get the IP address form name domain?
66. How do I put my NIC in promiscuous mode?
67. What port do I broadcast messages to?
68. sendto/recvfrom errors on Solaris
69. Unix socket programming vs NT window socket programming
70. optimal solution
71. Chat program in C/UNIX
72. how to create second socket on my client application
73.
74. how many simultaneous socket connections can a concurrent server accept?
75. Sending integer values to sockets.
76. can u answer this ??
77. C to unix base by win sock
78. C to unix base by win sock
79. Multiple blocking on select.
80. multiple connections
81. using libpcap
82. buffer limit
83. How to find local IP address in client.c program
84. Swap area
85. Using socket fuctions and debugging
86. how does one measure throughput in TCP and UDP?
87. defnition
88. source-IP equals dest-IP
89. Proxy Server written in C using sockets
90. gethostbyname
91. select() for timing
92. nic card
93. How do I access individual packets being received on a socket?
94. Time out on Recv
95. restart server
96. SO_RCVBUF
97. recv() fails with EGAIN for a blocking socket
98. sending floats over winsock
99. A server on multiple machines behind a Net Address Translation Device
100. qustion about socket
101. how to determine if socket is blocking or non-blocking
102. read() and timeouts
103.
104.
105. XDR
106. Proxy with Sockets - grabbing the http portion
107. How do i send file(s) to server
108. NT sockets VS Unix sockets
109. Blocking/Non-Blocking
110. sockets
111. Why does select not see available buffer space on a loopback socket?
112. socket bufsize recv and send > 4k
113. Blocking writes fail
114. When gethostbyname() doesn´t work...
115. viewing active data over socket
116. why is my client not able to connect to the server after the first time
117. Adding delay between IP package
118. psuedo terminals
119. transmit files via socket
120. Error bind
121. How can I check the evolution of a non blocking write on a socket?
122. discard socket data
123. discard socket data
124. Starting server when disconnected from ethernet fails to run
125. packets lost using SOCK_STREAM
126. packets lost using SOCK_STREAM
127.
128. using select to check if the second end is alive
129. package loss and delay
130. Sockets with Unix
131. Number of Ports? Newbie question
132. binding multiple file descriptors to a single port
133. recv() on unconnected socket ?
134. Sockets, timeout, signals
135. Port in use question?
136. Accept call on unconnected socket
137. Send & Receive using the same port
138. Ports in use
139. Newbie-Question:How to start with a proxy server?
140. Why my ping fails?
141. Final result of setting Timeout for connect() in socket
142. how many clients??
143. raw socket with udp port scan
144. raw socket
145. raw socket
146. How do i program different socket types??..Example: type 8 type 3, etc..
147. How do i program different socket types??..Example: type 8 type 3, etc..
148. TIME_WAIT
149.
150. printf() and select()?
151. Should socket be closed if sendto() or recvfrom() fails ?
152. TIMEOUT USING SELECT
153. CLosing connexion
154. problems in UDP socket programming(recvfrom)
155. Problems in recieving UDP packets
156. UDP socket. receiving broadcast problem.
157. FTP protocol
158. multiple applications on same host using same socket
159. Connecting to a Web server
160. Reading &Writing from UDP Port. (Help needed for Win)
161. Server: accepting and handling multiple clients
162.
163. bind fails with udp socket
164.
165. sending structures through TCPIP sockets
166. I need help, i am a beginner
167. Listening to port traffic?
168. how do i convert binary..
169. how do i convert binary..
170. How can i receive a file which size is unknown?
171. Err#9 EBADF on door_info call
172. Problem with write
173. How can I know my peer is dead(or close the socket) without read or write?
174. sigaction and sigset
175.
176. What is EAGAIN ??
177. Question on select() and send()
178. Problems with setting a timeout on connect
179. setting a timeout on connect
180. read() and MSS
181. unable to establish socket connection
182. exception in java
183. How could I know that the client stopped sending the data and waiting for me to
response?
184. recv returns 0!
185. writing into file
186.
187. TCP/IP called address for a ANY_HOST listen
188. VB client to Perl Server
189. How can i make a server act as connection oriented as well as connection less at same
time
190. Cannot create UDP socket - port number in use
191. socket c programming
192. question
193. How can i send communication break
194. How can i send communication break
195. Data comes together
196. Link Error.
197. demon.
198. MX lookup
199. hostname
200. accept() hangs
201. Semantics of ioctl with FIONREAD and recv
202. Server Application
203. WWW
204. TCP/IP does not preserve message boundaries
205. MX lookup
206. Using select() for web-server program
207. Ports that Hang
208. read-write problem
209. I am getting connection refused when ftp from UNIX to NT based system
210. can select() notify if a tcp/ip fd is readable?
211. write files to NT
212. TIME_WAIT and EPIPE
213. IPC using -shared memmory and semaphore Vs Sockets
214. Memory corrupted by child process
215. Number of sockets and OPEN_MAX limit
216. SIGPIPE in multi-threaded client/server program
217. How to use select() ?
218. listen fails on OpenServer 5.0.5
219. Authorizations doubts
220. About sharing the same socket/same connection to server for two programs
221. c++ and sockets (problem using close)
222. select/recv: how to read complete message?
223. Blocked I/O Timeout?
224. Securing sockets
225. how to get all listening ports ?
226. If ISocket permission denied
227. many http request via single socket.
228. HOW can I tell protocol?
229. Problems receiving UDP Broadcast...
230. Changing the buffer size of a listening socket
231. read count diff when accessing web server.
232. How to allocate the server buffer effectively?
233. signal(SIGPIPE,SIG_IGN) still doesnt ignore SIGPIPE
234. Socket send guarantee delivery ?
235. Problems with socket UDP
236. Socket Latency
237. Connect to a server
238. RECVFROM and IOCTL Question
239. sockets program to retrieve web content
240. How to bind a socket to multiple known ports?
241. Re: Sending files over ( Socket )
242. Why Select is not realizing that there is data on socket to read.
243. How to get ISP assigned IP
244.
245. UDP has connection in linux?
246. UDP has connection in linux?
247. Why UDP is used for the Internet instead of TCP?
248. sockaddr structure oddity
249. Can same port be used by two processes?
250. how to choose my own source port
251. Socket Address Structure
252. IPC
253.
254. XDR
255. accept() error!
256. How to post data using Post method to a servlet
257. my program gets stuck when closing a socket.
258. why does bind() give EADDRINUSE
259. Compilation problem
260. live AP_INET SOCK_STREAM connection
261. TCP/IP issue on HP Unix
262. select() between a UDP socket and a TCP client socket
263. recv gives a segmentation fault.
264. select question
265. Single server with multiple clients
266. How to write socket programming between UNIX & Windows platform
267. CONNECTION ABORT
268.
269. MAC Address from client w/o using ARP?
270. Threads and sockets
271. write() Hanging Program.
272. KCP
273. TCP Send-Q Retransmission
274. How can I do a ftp???
275. reading from buffer
276. How to retrieve data sent by client to server when data sent is stored in a buffer?
277. broken pipe?
278. about recv() call
279. binary file prob
280. how to signal select function
281. Java linux socket problem
282.
283. Web Hostinb
284. Reg send() socket call
285. exit parameter when send call fails
286. Using recv function
287. CLOSE_WAIT
288. CCGI - C socket communication
289. setsockopt with IP_MULTICAST_IF question
290. Socket is not being released
291. Can I bind socket descriptor to a port which bound by others ? How ?
292. How Many Sockets?
293. Questions regarding both Clients and Servers (TCP/SOCK_STREAM)
294. Questions regarding both Clients and Servers (TCP/SOCK_STREAM)
295. How can I bind to port use different name ?
296. how to bind a port that was bound ?
297. Accept method
298. Winsocket><sockets
299. is there any way to determine which process id is running a particular server ?
300. simplest way to send structures via sockets
301. Recv and Send functions Result
302. HOW MANY BITS ARE IN A TCP SOCKET?
303. server host name
304. blocking write
305. TIME_WAIT
306. How to flush the socket ?
307. client /server problem
308. Maximum speed in the socket
309. Socket reliability
310. blocking ip address
311. send a buffer from server to all clients?
312. Accessing non-HTTP servers through a proxy
313. re: socket error
314. Asynchronous I/O
315. Encrypting data on socket
316. RE: Adding packet handler for socket
317. Select hangs randomly
318.
319. tcp server
320. non blocking connect with select
321. socketing data loss between Unix and Windows
322. SCO -> DOS Communication via socket
323.
324. Meaning of UDP "connection"
325. How to delete a route using API calls
326. select() on blocking environment
327. Where can I download QT v2.2.2
328. how to write optimal performance TCP server
329. Client and Servers.
330. SOCKETS AND IMAP SERVER
331. client/server to check a file in a dir
332. recv() - the delay between recv()s
333. OOB msgs
334. timeout on send with SO_SNDTIMEO??
335. Server-Client Design
336. CLOSE_WAIT Error
337.
338. SO_RCVTIMEO question
339. Why does Apache only accept a message after the socket closes?
340. How can I Receive or Deal with Out-of-Band Data
341. SIGURG & OOB problem ?
342. SIGURG & OOB problem ?
343. Broadcast and receive DHCP messages
344. What is Meant By RFCxxxx ?
345. How we can Get Mails From Servers Using Sockets.
346. How we can Get Mails From Servers Using Sockets.
347. Can someone answer to that ??!!
348. select statement times out when there is data
349. sending File Descriptors across Unix Sockets
350. Server servicing multiple sockets (ports)
351. How to use "errorfds
352. How to use "errorfds
353. How to use "errorfds" in select()
354. Select returns EBADF
355. core dump on send/recv
356. socket programming
357. transfer data from winsock to unix by C/C++ socket programming
358. NT Socket to Unix
359. pthread_join
360. sending binary file from a windows client to a unix server
361.
362.
363. using socket to connect : a client to a server and a client to another client ?
364. Send a file and struct
365. configure tcpip/ppp using unix interprise 5.05 sco
366. Determining MAC from IP w/ARP
367. Sockets Intialization Failed!
368. Anonymous FTP
369. Problem with socket-timeout
370. Which langage is better for network programming ?
371. server
372. I need to send 0x00 0x00 0x00 0x1 ?
373. Broken Pipe
374. Open a session
375. Can i Read more than a PAGESIZE in a single read call......
376. kick off Unix process from Windows 2000/NT
377. Why my recv is too slow?
378. select loop..
379. udp port reuse
380. sockets
381. socket send timeout
382. byte order of data received
383. Searching For: Inline "Hex to Decimal" conversion routine - to be used during execution
of Socket Datagram Program
384. How to determine which IP client is calling?
385. How to reconnect a TCP socket?
386. Ada Language Unix-based "Datagram Link Program" Type Error When Porting To And
Recompiling On A Linux Machine
387. call to write blocks forever
388. persistent connection to a web server
389. Windows / Unix Socket Communication
390. DANGER : big bug in Select() !!
391. Socket on Unix
392. rebinding bound socket
393. How can a process know its hostname ?
394. Sending info down sockets
395. Sending info down sockets
396. GET Protocol
397. get multiple documents from www server
398. problems receiving UDP Broadcast
399. To change, my IP address.
400. socket and rpc
401. What is "IDMaps" and how to use it in indentifying the closest mirror site?
402. fprintf error code
403. % sign in a file read by my SOCKET server
404.
405. socket 7 processor
406. Need help in compilation error2001
407. Controlling an unexpected socket close.
408. What is a Blocked socket ?
409. server/multiple clients
410. Connection failures
411. Socket Programming
412. problem in client identification by server
413. Connecting a socket throw a proxy with autentication
414. How to test if a server closed my socket?
415. Line down condition
416. Select Read problem
417. How does server control number of client---help
418. how to detect SIGCHLD
419. TCP Socket Read/Write With Two Threads
420. Data Flow from socket call(s) to a network device driver
421. Data Flow from socket call(s) to a network device driver
422. Data Flow from socket call(s) to a network device driver
423. Select on a unconnected socket
424. What is client IP on a multi-IP machine?
425. Can I increment an IP address "IP=IP+1"?
426. SCO Socket
427. How socket calls are get mapped to network device driver functions
428. using C program to get connect to the web server
429. urgently required!!!!!!!1
430. UDP Buffers
431. Read and write irrespective of the order
432. how to use a C client to connect to an RMI port?
433. resource temporarily unavailable - recv problem
434. setting file permissions for sockets
435. Timeout period affecting selects ability to detect data
436. Making sockets working over the internet
437. EINTR Testing
438. Where can I get the converter to convert Windows to Unix?
439. TCP/UDP on same server
440. HOW CAN I open n connections working at the same time ??
441. non blocking socket
442. RST packet ???????
443. Source Code client.c And Server.c for UNIX
444. how to check if a socket is connected or not?
445. NBT packets???
446. TCP UDP on same server
447. i want to implement a natwork game, i want to discover all hosts on a subnet that are
participating in it, what shall i do?
448. Using select with recv send
449. communication between a java program and a c program
450. Getting Signal Number 2147482380 While sending data on socket
451. Time Polling
452. UDP BraodCast
453. Recv ( ) in blocking mode
454. Why is my socket not ready for writing?
455. writing to RAW ethernet socket
456. Tcp port configuration
457. Max data that can be send in one send
458. Regarding Non blocking calls
459. Why do I get "accept: Too many open files" error
460. Errors when a remote host crashes
461. using poll for packet timeout
462. How can I prevent from losing packet
463. client to multi-homed server
464. deleting files and directories
465. packet demultiplexing
466. number of connectons
467. Are there Token Ring programmer ?
468. UDP with retransmission?
469. UDP Server and Client on same machine gives Address already in use error
470. problem transferring file through socket
471. cgi and socket with DB
472. question about UDP SOCKET buffering
473. Broadcast a large file
474. recv Socket
475.
476.
477. Telecom call routing
478. why is inet_addr() not working??
479. NFILE parameter increases!
480. Blocking Vs Non-blocking
481. TCP connection re-establishment
482. single program acting as server and client
483. How can a server let other server connect with a client ?
484.
485. CGI problems.
486.
487. which is best Fork () or pthread ?
488. Timestamp
489. Difference between port & socket
490. Client write to closed server
491. How to flush a udp socket?
492. Binding of RAW Sockets
493. Server does not receive message sent by Client
494. problems with sending files
495. Difference between socket and port
496. Forwarding data from one interface to another
497. problem with error "unresolved text symbol" in UDP program using recvfrom & sendto
498. API to get state of socket?
499. Looking for advice on non-blocking sockets
500. how to specify a rang of port numbers to be used
501. Raw socket programming
502. IP-telephony
503. re-establish socket connection
504. Output Queue Gets Full
505. Transfer a file using UDP
506. SO_LINGER socket option does not work
507. Multiple Servers
508. How to terminate the read/recv call..?
509. Error in bindind an UDP socket
510. Invalid argument!?
511. Blocking socket recv with pthread
512. Instant Messaging Server
513. How to detect if process id is running
514. Broadcasting Problem
515. select problem
516. peer-to-peer chat application
517. help on UDP broadcasts
518. select question
519. Socket usage with Unixware 7.1.1
520. How can I send data from server to client?
521. socket source code
522. OPEN_MAX SUN app to Linux
523. multi-threaded connections
524. Open connection!
525. accept file descriptor
526. Unix command to know the ports.
527. Can UDP be used for sms
528. sending http request via proxy
529. Can you help me.?
530. Reuse of socket descriptors in linux
531. Non-blocking client
532. Multiple IP Address in Client, how to....
533. ERROR - CORE DUMP
534. How to create Sockets in UNIX
535. Socket and mutual exclusion
536. Connection testing using select() and recv()
537. testing TCP related APIs!!
538. How can I prevent from losing data ?
539. Disconnecting from modem
540. Receiving packet over a specific interface?
541. buffer question.
542. 6 second delay ...
543. Ho to make blocking send with UDP socket?
544. TCP Sockets with pthreads
545. Unable to catch SIGCHLD on a HP workstation.
546. Unable to catch SIGCHLD on a HP workstation.
547. Unable to catch SIGCHLD on a HP workstation.
548. Try to make a secure conection
549. Error while compiling
550. ftp server bind with REUSEADDR ?
551. Specific concurrent server port
552. socket deadlock
553. Select problem with NT and Solaris sockets
554. Where can I find the source code for server written for broadcasting audio ?
555. download component on Unix
556. UDP server question
557. Regarding connect system call
558. Could someone explain me something strange
559. what is HUP
560. Java Multicast Client with two NICs
561. Creating non_blocking sockets
562. how to write a port scanner on unix using c c++
563.
564. how can i attach file in a email
565. strings
566. Listening for remote socket error using poll
567. accept(); fills sock_addr structre with the same ip forever after one fail
568. Info
569. how to find the memory used by the Stack and the Heap for a function??
570. where is the memory fora local array allocated
571. Async. IO, How to store Clients IP and Port
572. writing to socket descriptor newSD
573. What is UMODE
574. Socket error
575. ENOBUFS Returned from Connect()
576. Broadcast UDP on linux gives ENOPERM
577. TCP programming
578. Program exits with code 141 during recv()
579. recv()?
580. please.... run it always wrong ( on linux 7.0)
581. What happens with incoming buffer over-run
582. How does it know to send back the right information
583. C function to empty a socket
584. Windows sockets
585. How to bind Multi-IP to a MAC
586. How can I run a program and set some environment variable when "startx" on RedHat ?
587. How can I run a program and set some environment variable when "startx" on RedHat ?
588. Limit on maximum number of sockets
589. Select problem - read()
590. socket programming
591. can u send a .gif file through a socket. ?
592. About IP Alias
593. Connection refused when using syslog()
594. How can we use the LENGTH in recvfrom() in UDP socket?
595. Multiple clients using select
596. Problem in Sockets while using Message Queues
597. Asynchronous programming
598. confused with backlog of listen()
599. select() problems on DEC Alpha XP900
600. Mapping PDU data over tcp/ip
601. I loss data when I receive from a unix socket!!!
602. aix 4.3 ftp client data socket question (can you help?)
603. question
604. unix for submitting html form to a server
605. RAW Sockets
606. counter-wait system
607. Consulting C++
608. read() hangs w/ binary transfers
609. Asynchronous DNS lookups
610. When does EPROTO occur?
Categorized Questions:
1. General Information and Concepts
1. What's new?
2. About this FAQ
3. Who is this FAQ for?
4. What are Sockets?
5. How do Sockets Work?
6. Where can I get source code for the book [book title]?
7. Where can I get more information?
8. Where can I get the sample source code?
2. Questions regarding both Clients and Servers (TCP/SOCK_STREAM)
1. How can I tell when a socket is closed on the other end?
2. What's with the second parameter in bind()?
3. How do I get the port number for a given service?
4. If bind() fails, what should I do with the socket descriptor?
5. How do I properly close a socket?
6. When should I use shutdown()?
7. Please explain the TIME_WAIT state.
8. Why does it take so long to detect that the peer died?
9. What are the pros/cons of select(), non-blocking I/O and SIGIO?
10. Why do I get EPROTO from read()?
11. How can I force a socket to send the data in its buffer?
12. Where can I get a library for programming sockets?
13. How come select says there is data, but read returns zero?
14. Whats the difference between select() and poll()?
15. How do I send [this] over a socket
16. How do I use TCP_NODELAY?
17. What exactly does the Nagle algorithm do?
18. What is the difference between read() and recv()?
19. I see that send()/write() can generate SIGPIPE. Is there any advantage to handling
the signal, rather than just ignoring it and checking for the EPIPE error?
20. After the chroot(), calls to socket() are failing. Why?
21. Why do I keep getting EINTR from the socket calls?
22. When will my application receive SIGPIPE?
23. What are socket exceptions? What is out-of-band data?
24. How can I find the full hostname (FQDN) of the system I'm running on?
25. How do I monitor the activity of sockets?
3. Writing Client Applications (TCP/SOCK_STREAM)
1. How do I convert a string into an internet address?
2. How can my client work through a firewall/proxy server?
3. Why does connect() succeed even before my server did an accept()?
4. Why do I sometimes lose a server's address when using more than one server?
5. How can I set the timeout for the connect() system call?
6. Should I bind() a port number in my client program, or let the system choose one
for me on the connect() call?
7. Why do I get "connection refused" when the server isn't running?
8. What does one do when one does not know how much information is comming
over the socket? Is there a way to have a dynamic buffer?
9. How can I determine the local port number?
4. Writing Server Applications (TCP/SOCK_STREAM)
1. How come I get "address already in use" from bind()?
2. Why don't my sockets close?
3. How can I make my server a daemon?
4. How can I listen on more than one port at a time?
5. What exactly does SO_REUSEADDR do?
6. What exactly does SO_LINGER do?
7. What exactly does SO_KEEPALIVE do?
8. 4.8 How can I bind() to a port number < 1024?
9. How do I get my server to find out the client's address / hostname?
10. How should I choose a port number for my server?
11. What is the difference between SO_REUSEADDR and SO_REUSEPORT?
12. How can I write a multi-homed server?
13. How can I read only one character at a time?
14. I'm trying to exec() a program from my server, and attach my socket's IO to it, but
I'm not getting all the data across. Why?
5. Writing UDP/SOCK_DGRAM applications
1. When should I use UDP instead of TCP?
2. What is the difference between "connected" and "unconnected" sockets?
3. Does doing a connect() call affect the receive behaviour of the socket?
4. How can I read ICMP errors from "connected" UDP sockets?
5. How can I be sure that a UDP message is received?
6. How can I be sure that UDP messages are received in order?
7. How often should I re-transmit un-acknowleged messages?
8. How come only the first part of my datagram is getting through?
9. Why does the socket's buffer fill up sooner than expected?
6. Advanced Socket Programming
1. How would I put my socket in non-blocking mode?
2. How can I put a timeout on connect()?
3. How do I complete a read if I've only read the first part of something, without
again calling select()?
4. How to use select routine
5. RAW sockets
6. Restricting a socket to a given interface
7. Receiving all incoming traffic through a RAW-socket?
8. Multicasting
9. getting IP header of a UDP message
10. To fork or not to fork?
7. Sample Source Code
1. Looking for a good C++ socket library
2. perl examples of source code
3. Where is the source code from Richard Stevens' books?
8. Bugs and Strange Behaviour
1. send() hangs up when sending to a switched off computer
2. Error when using inetd
Contents are Copyright© by the author of the content. Permission is granted to do anything you like with this contents so long as you don't claim the
work, or copyright for yourself. The Self Serve FAQ is Copyright© by it's authors, and available under the terms of the GNU GPL.
Raw IP Networking FAQ
The FAQ is maintained by Thamer Al-Herbish [email protected]. Feel free to mail in
suggestions and additions to any material found on this page.
Related Documents:
● The BSD Packet Filter: A New Architecture for User Level Packet capture.
● Data Link Provider Interface Specification
● How to Use DLPI (SunOS 5.x)
Related Links
Related FAQs
❍ US Mirror
❍ US Mirror
Also you may want to join the Raw IP Networking mailing list, if you still have trouble.
© 1997 Whitefang Dawt Kawm.
[email protected]
1. Answers to frequently asked questions
for comp.programming.threads: Part 1 of
1
Copyright © 1996, 1997
Bryan O'Sullivan
Last modified: Wed Sep 3 10:21:39 1997
$Revision: 1.10 $
0. Table of contents
1. Answers to frequently asked questions for comp.programming.threads: Part 1 of 1
2. Introduction
2.1. Reader contributions and comments
2.2. How to read this FAQ
2.3. Acknowledgments and caveats
3. What are threads?
3.1. Why are threads interesting?
3.2. A little history
4. What are the main families of threads?
4.1. POSIX-style threads
4.2. Microsoft-style threads
4.3. Others
5. Some terminology
5.1. (DCE, POSIX, UI) Async safety
5.2. Asynchronous and blocking system calls
5.3. Context switch
5.4. Critical section
5.5. Lightweight process
5.6. MT safety
5.7. Protection boundary
5.8. Scheduling
6. What are the different kinds of threads?
6.1. Architectural differences
6.2. Performance differences
6.3. Potential problems with functionality
7. Where can I find books on threads?
7.1. POSIX-style threads
7.2. Microsoft-style threads
7.3. Books on implementations
7.4. The POSIX threads standard
8. Where can I obtain training on using threads?
9. (Unix) Are there any freely-available threads packages?
10. (DCE, POSIX, UI) Why does my threaded program not handle signals sensibly?
11. (DCE?, POSIX) Why does everyone tell me to avoid asynchronous cancellation?
12. Why are reentrant library and system call interfaces good?
12.1. (DCE, POSIX, UI) When should I use thread-safe "_r" library calls?
13. (POSIX) How can I perform a join on any thread?
14. (DCE, UI, POSIX) After I create a certain number of threads, my program crashes
15. Where can I find POSIX thread benchmarks?
16. Does any DBMS vendor provide a thread-safe interface?
17. Why is my threaded program running into performance problems?
18. What tools will help me to program with threads?
19. What operating systems provide threads?
20. What about other threads-related software?
21. Where can I find other information on threads?
21.1. Articles appearing in periodicals
22. Notice of copyright and permissions
2. Introduction
This posting consists of answers to many of the questions most frequently asked and summaries of the
topics most frequently covered on comp.programming.threads, the Usenet newsgroup for discussion of
issues in multithreaded programming. The purpose of this posting is to circulate existing information, and
to avoid rehashing old topics of discussion and questions. Please read all parts of this document before
posting to this newsgroup.
The FAQ is posted monthly to comp.programming.threads, in multiple parts. It is also available on the
World-Wide Web, at <URL: http://www.serpentine.com/~bos/threads-faq>. You may prefer to browse the
FAQ on the Web rather than on Usenet, as it contains many useful hyperlinks (and tables are readable,
which is unfortunately not the case for the text version).
❍ You will often see POSIX threads referred to as POSIX.1c threads, since 1003.1c is the
section of the POSIX standard that deals with threads.
❍ You may also see references to draft 10 of POSIX.1c, which became the standard.
● DCE threads are based on draft 4 (an early draft) of the POSIX threads standard (which was
originally named 1003.4a, and became 1003.1c upon standardisation). You may find these on some
Unix implementations.
● Unix International (UI) threads, also known as Solaris threads, are based on the Unix International
threads standard (a close relative of the POSIX standard). The only major Unix variants that
support UI threads are Solaris 2, from Sun, and UnixWare 2, from SCO.
Both DCE and UI threads are fairly compatible with the POSIX threads standard, although converting
from either to "real" POSIX threads will require a moderate amount of work.
Those few tardy Unix vendors who do not yet ship POSIX threads implementations are expected to do so
"real soon now". If you are developing multithreaded applications from scratch on Unix, you would do
well to use POSIX threads.
4.2. Microsoft-style threads
This family consists of two subgroups, both originally developed by Microsoft.
● WIN32 threads are the standard threads on Microsoft Windows 95 and Windows NT.
Although both of these were originally implemented by Microsoft, they have diverged somewhat over the
years. Moving from one to the other will require a moderate amount of work.
4.3. Others
Mach and its derivatives (such as Digital UNIX) provide a threads package called C threads. This is not
very widely used.
5. Some terminology
The terms here refer to each other in a myriad of ways, so the best way to navigate through this section is
to read it, and then read it again. Don't be afraid to skip forwards or backwards as the need appears.
5.6. MT safety
If some piece of code is described as MT-safe, this indicates that it can be used safely within a
multithreaded program, and that it supports a "reasonable" level of concurrency. This isn't very
interesting; what you, as a programmer using threads, need to worry about is code that is not MT-safe.
MT-unsafe code may use global and/or static data. If you need to call MT-unsafe code from within a
multithreaded program, you may need to go to some effort to ensure that only one thread calls that code at
any time.
Wrapping a global lock around MT-unsafe code will generally let you call it from within a multithreaded
program, but since this does not permit concurrent access to that code, it is not considered to make it
MT-safe.
If you are trying to write MT-safe code using POSIX threads, you need to worry about a few issues such
as dealing correctly with locks across calls to fork(2) (if you are wondering what to do, read about the
pthread_atfork(3) library call).
● Kernel-supported threads.
There are several sets of differences between these different threads implementations.
● Systems in which the kernel cooperates with a user-level library to do scheduling are known as
two-level, or hybrid, systems. Typically, the kernel schedules LWPs, and the user-level library
schedules threads onto LWPs.
Because of its performance problems (caused by the need to cross the user/kernel protection boundary
twice for every thread context switch), the former class has fewer members than does the latter (at least on
Unix variants). Both classes allow threads to be run across multiple processors in parallel.
Warning
LinuxThreads is now closely integrated in the glibc GNU C library. The initial author of LinuxThreads (Xavier
Leroy) is no longer active on LinuxThreads; maintenance and further developments are mostly handled by Kaz
Kylheku and the glibc team, in particular Ulrich Drepper.
The information on this Web page has not been updated in a while and may not be 100% up to date (except the
FAQ, which is still actively maintained). The glibc mailing lists often contain more up-to-date information.
General questions about LinuxThreads and programming with POSIX threads should be posted on the
comp.programming.threads newsgroup.
Bug reports should be sent directly to the glibc development team using the glibcbug script that is installed
on your machine along with glibc itself.
Obtaining LinuxThreads
For Linux systems based on glibc 2 (e.g. RedHat 5.0 and later): the glibc 2 version of LinuxThreads is
distributed along with glibc 2 itself. If you have installed a Linux distribution based on glibc 2 (such as
RedHat 5.0 and later, or indeed most major Linux distributions these days), you already have LinuxThreads on
your computer. Congratulations. Otherwise, both glibc 2 and the associated LinuxThreads distribution can
be found on Cygnus/RedHat source collection, and also on any FTP site that mirrors GNU software (the
Cygnus/RedHat site is sometimes more up-to-date than the GNU sites).
For Linux systems based on libc 5 (e.g. old versions of Slackware): The source distribution of
LinuxThreads for libc 5 is available at
ftp://ftp.inria.fr/INRIA/Projects/cristal/Xavier.Leroy/linuxthreads.tar.gz.
Please note that the libc 5 version of LinuxThreads is obsolete and no longer maintained. An upgrade to glibc 2
is highly recommended for reliable multithreading programming.
Debugging threaded programs with GDB: Recent versions of gdb and glibc support the debugging of
multithreaded programs. For instance, RedHat 6.2 and later come with a thread-aware version of gdb.
For older systems: see H.J.Lu's patches for gdb, which include thread support and more. The very first attempt
at multi-threaded debugging for LinuxThreads was the patches for gdb 4.17 developed at The Open Group,
Grenoble, but this is now largely obsolete. The Open Group patches are for glibc 2. Kaz Kylheku back-ported
them to libc 5: patch for LinuxThreads 0.71/libc5 and patch for GDB 4.17.
Documentation
● Two FAQs from comp.programming.threads: O'Sullivan's FAQ and Lewis' FAQ.
● Getting Started With POSIX Threads, by Tom Wagner and Don Towsley.
● Sun's pthread pages.
● LinuxThreads comes with a complete set of man pages.
● Code samples from Programming with POSIX® Threads, D. R. Butenhof, Addison-Wesley.
● Code samples, sources, infos from Multithreading Programming Techniques, S. Prasad, McGraw Hill.
LinuxThreads-related software
● Richard Neitzel's libaio, a library of POSIX.1b compliant asynchronous I/O functions based on
LinuxThreads.
● The Adaptive Communication Environment (ACE) contains C++ wrappers for LinuxThreads and much,
much more.
● Jim Doyle's DCE Threads Emulation Package for LinuxThreads allows applications written with DCE
threads (a.k.a. draft 4 POSIX threads) to run easily on top of LinuxThreads.
● The AOL multithreaded Web server uses LinuxThreads for its Linux version.
● Software AG's port of DCOM for Linux also uses LinuxThreads.
● LinuxThreads is used in MpegTV Player, a commercial/shareware real-time MPEG Video player (with
audio/sync) and Video-CD player for Linux.
● Com-One's Video live server runs under Linux and uses LinuxThreads.
● Blackdown's port of the Java Development Kit 1.2 for Linux supports "native" threads built on top of
LinuxThreads as an alternative to the JDK's own "green" threads. The Kaffe Java implementation does
the same.
● GNAT, the GNU Ada95 compiler, comes with a "native" run-time system that implements Ada tasks
using LinuxThreads.
● Ted Baker's FLORIST package is a POSIX.5 library for GNAT that can be used as an Ada95 interface
to LinuxThreads and other Linux system calls. It also includes a POSIX conformance test kit.
● Proxy, a threaded IP filtering proxy server.
[email protected]
Lynx
Lynx is a text browser for the World Wide Web. Lynx 2.8.3 runs on Un*x, VMS, Windows
95/98/NT but not 3.1 or 3.11, on DOS (386 or higher) and OS/2 EMX. The current
developmental version is also available for testing. Ports to Mac are in beta test.
● How to get Lynx, and much more information, is available at Lynx links.
● Many user questions are answered in the online help provided with Lynx. Press the '?'
key to find this help.
● If you are encountering difficulty with Lynx you may write to [email protected]. Be as
detailed as you can about the URL where you were on the Web when you had trouble,
what you did, what Lynx version you have (try '=' key), and what OS you have. If you
are using an older version, you may well need to upgrade.
Maintained by [email protected].
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
v1.0.2
If you're already familiar with that, it's recommended to learn about makefiles, and then go and
learn other C programming topics and practice the usage of makefiles, before going on to read
about C libraries. This last issue is only relevant to larger projects, while makefiles make sense
even for a small program composed of but a few source files.
As a policy, we'll stick with the basic features of programming tools mentioned here, so that the
information will apply to more then a single tool version. This way, you might find the
information here useful, even if the system you're using does not have the GNU tools installed.
In this lovely tutorial, we'll deal with compilation of a C program, using the compiler directly
from the command line. It might be that you'll eventually use a more sophisticated interface (an
IDE - Integrated Development Environment) of some sort, but the common denominator you'll
always find is the plain command line interface. Further more, even if you use an IDE, it could
help you understand how things work "behind the scenes". We'll see how to compile a program,
how to combine several source files into a single program, how to add debug information and
how to optimize code.
cc single_main.c
Note that we assume the compiler is called "cc". If you're using a GNU compiler, you'll write
'gcc' instead. If you're using a Solaris system, you might use 'acc', and so on. Every compiler
might show its messages (errors, warnings, etc.) differently, but in all cases, you'll get a file
'a.out' as a result, if the compilation completed successfully. Note that some older systems (e.g.
SunOs) come with a C compiler that does not understand ANSI-C, but rather the older 'K&R' C
style. In such a case, you'll need to use gcc (hopefully it is installed), or learn the differences
between ANSI-C and K&R C (not recommended if you don't really have to), or move to a
different system.
You might complain that 'a.out' is a too generic name (where does it come from anyway? - well,
that's a historical name, due to the usage of something called "a.out format" for programs
compiled on older Unix systems). Suppose that you want the resulting program to be called
"single_main". In that case, you could use the following line to compile it:
cc single_main.c -o single_main
Every compiler I've met so far (including the glorious gcc) recognized the '-o' flag as "name the
resulting executable file 'single_main'".
single_main
However, this requires that the current directory be in our PATH (which is a variable telling our
Unix shell where to look for programs we're trying to run). In many cases, this directory is not
placed in our PATH. Aha! - we say. Then lets show this computer who is smarter, and thus we
try:
./single_main
This time we explicitly told our Unix shell that we want to run the program from the current
directory. If we're lucky enough, this will suffice. However, yet one more obstacle could block
our path - file permission flags.
When a file is created in the system, it is immediately given some access permission flags.
These flags tell the system who should be given access to the file, and what kind of access will
be given to them. Traditional Unix systems use 3 kinds of entities to which they grant (or deny)
access: The user which owns the file, the group which owns the file, and everybody else. Each
of these entities may be given access to read the file ('r'), write to the file ('w') and execute the
file ('x').
Now, when the compiler created the program file for us, we became owners of the file.
Normally, the compiler would make sure that we get all permissions to the file - read, write and
execute. It might be, thought that something went wrong, and the permissions are set
differently. In that case, we can set the permissions of the file properly (the owner of a file can
normally change the permission flags of the file), using a command like this:
This means "the user ('u') should be given ('+') permissions read ('r'), write ('x') and execute ('x')
to the file 'single_main'. Now we'll surely be able to run our program. Again, normally you'll
have no problem running the file, but if you copy it to a different directory, or transfer it to a
different computer over the network, it might loose its original permissions, and thus you'll need
to set them properly, as shown above. Note too that you cannot just move the file to a different
computer an expect it to run - it has to be a computer with a matching operating system (to
understand the executable file format), and matching CPU architecture (to understand the
machine-language code that the executable file contains).
Finally, the run-time environment has to match. For example, if we compiled the program on an
operating system with one version of the standard C library, and we try to run it on a version
with an incompatible standard C library, the program might crush, or complain that it cannot
find the relevant C library. This is especially true for systems that evolve quickly (e.g. Linux
with libc5 vs. Linux with libc6), so beware.
Creating Debug-Ready Code
Normally, when we write a program, we want to be able to debug it - that is, test it using a
debugger that allows running it step by step, setting a break point before a given command is
executed, looking at contents of variables during program execution, and so on. In order for the
debugger to be able to relate between the executable program and the original source code, we
need to tell the compiler to insert information to the resulting executable program that'll help the
debugger. This information is called "debug information". In order to add that to our program,
lets compile it differently:
cc -g single_main.c -o single_main
The '-g' flag tells the compiler to use debug info, and is recognized by mostly any compiler out
there. You will note that the resulting file is much larger then that created without usage of the
'-g' flag. The difference in size is due to the debug information. We may still remove this debug
information using the strip command, like this:
strip single_main
You'll note that the size of the file now is even smaller then if we didn't use the '-g' flag in the
first place. This is because even a program compiled without the '-g' flag contains some symbol
information (function names, for instance), that the strip command removes. You may want
to read strip's manual page (man strip) to understand more about what this command does.
cc -O single_main.c -o single_main
The '-O' flag tells the compiler to optimize the code. This also means the compilation will take
longer, as the compiler tries to apply various optimization algorithms to the code. This
optimization is supposed to be conservative, in that it ensures us the code will still perform the
same functionality as it did when compiled without optimization (well, unless there are bugs in
our compiler). Usually can define an optimization level by adding a number to the '-O' flag. The
higher the number - the better optimized the resulting program will be, and the slower the
compiler will complete the compilation. One should note that because optimization alters the
code in various ways, as we increase the optimization level of the code, the chances are higher
that an improper optimization will actually alter our code, as some of them tend to be
non-conservative, or are simply rather complex, and contain bugs. For example, for a long time
it was known that using a compilation level higher then 2 (or was it higher then 3?) with gcc
results bugs in the executable program. After being warned, if we still want to use a different
optimization level (lets say 4), we can do it this way:
And we're done with it. If you'll read your compiler's manual page, you'll soon notice that it
supports an almost infinite number of command line options dealing with optimization. Using
them properly requires thorough understanding of compilation theory and source code
optimization theory, or you might damage your resulting code. A good compilation theory
course (preferably based on "the Dragon Book" by Aho, Sethi and Ulman) could do you good.
This will first annoy us - we'll get all sorts of warnings that might seem irrelevant. However, it
is better to eliminate the warnings then to eliminate the usage of this flag. Usually, this option
will save us more time than it will cause us to waste, and if used consistently, we will get used
to coding proper code without thinking too much about it. One should also note that some code
that works on some architecture with one compiler, might break if we use a different compiler,
or a different system, to compile the code on. When developing on the first system, we'll never
see these bugs, but when moving the code to a different platform, the bug will suddenly appear.
Also, in many cases we eventually will want to move the code to a new system, even if we had
no such intentions initially.
Note that sometimes '-Wall' will give you too many errors, and then you could try to use some
less verbose warning level. Read the compiler's manual to learn about the various '-W' options,
and use those that would give you the greatest benefit. Initially they might sound too strange to
make any sense, but if you are (or when you will become) a more experienced programmer, you
will learn which could be of good use to you.
Compiling A Single-Source "C++" Program
Now that we saw how to compile C programs, the transition to C++ programs is rather simple.
All we need to do is use a C++ compiler, in place of the C compiler we used so far. So, if our
program source is in a file named 'single_main.cc' ('cc' to denote C++ code. Some programmers
prefer a suffix of 'C' for C++ code), we will use a command such as the following:
Or on some systems you'll use "CC" instead of "g++" (for example, with Sun's compiler for
Solaris), or "aCC" (HP's compiler), and so on. You would note that with C++ compilers there is
less uniformity regarding command line options, partially because until recently the language
was evolving and had no agreed standard. But still, at least with g++, you will use "-g" for
debug information in the code, and "-O" for optimization.
This will cause the compiler to compile each of the given files separately, and then link them all
together to one executable file named "hello_world". Two comments about this program:
1. If we define a function (or a variable) in one file, and try to access them from a second
file, we need to declare them as external symbols in that second file. This is done using
the C "extern" keyword.
2. The order of presenting the source files on the command line may be altered. The
compiler (actually, the linker) will know how to take the relevant code from each file into
the final program, even if the first source file tries to use a function defined in the second
or third source file.
The problem with this way of compilation is that even if we only make a change in one of the
source files, all of them will be re-compiled when we run the compiler again.
In order to overcome this limitation, we could divide the compilation process into two phases -
compiling, and linking. Lets first see how this is done, and then explain:
cc -c main.cc
cc -c a.c
cc -c b.c
cc main.o a.o b.o -o hello_world
The first 3 commands have each taken one source file, and compiled it into something called
"object file", with the same names, but with a ".o" suffix. It is the "-c" flag that tells the
compiler only to create an object file, and not to generate a final executable file just yet. The
object file contains the code for the source file in machine language, but with some unresolved
symbols. For example, the "main.o" file refers to a symbol named "func_a", which is a function
defined in file "a.c". Surely we cannot run the code like that. Thus, after creating the 3 object
files, we use the 4th command to link the 3 object files into one program. The linker (which is
invoked by the compiler now) takes all the symbols from the 3 object files, and links them
together - it makes sure that when "func_a" is invoked from the code in object file "main.o", the
function code in object file "a.o" gets executed. Further more, the linker also links the standard
C library into the program, in this case, to resolve the "printf" symbol properly.
To see why this complexity actually helps us, we should note that normally the link phase is
much faster then the compilation phase. This is especially true when doing optimizations, since
that step is done before linking. Now, lets assume we change the source file "a.c", and we want
to re-compile the program. We'll only need now two commands:
cc -c a.c
cc main.o a.o b.o -o hello_world
In our small example, it's hard to notice the speed-up, but in a case of having few tens of files
each containing a few hundred lines of source-code, the time saving is significant; not to
mention even larger projects.
Getting a Deeper Understanding - Compilation
Steps
Now that we've learned that compilation is not just a simple process, lets try to see what is the
complete list of steps taken by the compiler in order to compile a C program.
1. Driver - what we invoked as "cc". This is actually the "engine", that drives the whole
set of tools the compiler is made of. We invoke it, and it begins to invoke the other tools
one by one, passing the output of each tool as an input to the next tool.
2. C Pre-Processor - normally called "cpp". It takes a C source file, and handles all
the pre-processor definitions (#include files, #define macros, conditional source code
inclusion with #ifdef, etc.) You can invoke it separately on your program, usually with a
command like:
cc -E single_source.c
Try this and see what the resulting code looks like.
3. The C Compiler - normally called "cc1". This is the actual compiler, that translates
the input file into assembly language. As you saw, we used the "-c" flag to invoke it,
along with the C Pre-Processor, (and possibly the optimizer too, read on), and the
assembler.
4. Optimizer - sometimes comes as a separate module and sometimes as the found inside
the compiler module. This one handles the optimization on a representation of the code
that is language-neutral. This way, you can use the same optimizer for compilers of
different programming languages.
5. Assembler - sometimes called "as". This takes the assembly code generated by the
compiler, and translates it into machine language code kept in object files. With gcc, you
could tell the driver to generated only the assembly code, by a command like:
cc -S single_source.c
6. Linker-Loader - This is the tool that takes all the object files (and C libraries), and
links them together, to form one executable file, in a format the operating system
supports. A Common format these days is known as "ELF". On SunOs systems, and
other older systems, a format named "a.out" was used. This format defines the internal
structure of the executable file - location of data segment, location of source code
segment, location of debug information and so on.
As you see, the compilation is split in to many different phases. Not all compiler employs
exactly the same phases, and sometimes (e.g. for C++ compilers) the situation is even more
complex. But the basic idea is quite similar - split the compiler into many different parts, to give
the programmer more flexibility, and to allow the compiler developers to re-use as many
modules as possible in different compilers for different languages (by replacing the
preprocessor and compiler modules), or for different architectures (by replacing the assembly
and linker-loader parts).
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Note that we run the program from the same directory it was compiled in, otherwise gdb won't find the source file, and thus
won't be able to show us where in the code we are at a given point. It is possible to ask gdb to search for extra source files in
some directory after launching it, but for now, it's easier to just invoke it from the correct directory.
Running A Program Inside The Debugger
Once we invoked the debugger, we can run the program using the command "run". If the program requires command line
parameters (like our debug_me program does), we can supply them to the "run" command of gdb. For example:
Note that we used quotation marks to denote that "hello, world" is a single parameter, and not to separate parameters (the
debugger assumes white-space separates the parameters).
Setting Breakpoints
The problem with just running the code is that it keeps on running until the program exits, which is usually too late. For this,
breakpoints are introduced. A break point is a command for the debugger to stop the execution of the program before
executing a specific source line.We can set break points using two methods:
1. Specifying a specific line of code to stop in:
break debug_me.c:9
Will insert a break point right before checking the command line arguments in our program (see the file supplied with
this tutorial).
2. Specifying a function name, to break every time it is being called:
break main
this will set a break point right when starting the program (as the function "main" gets executed automatically on the
beginning of any C or C++ program).
break main
run "hello, world" "goodbye, world"
Note that you won't always get the warnings i got - it just goes to show you how lousy my system setup is. In any case, these
warnings are not relevant to our code, as we do not intend to debug any shared libraries.
Now we want to start running the program slowly, step by step. There are two options for that:
1. "next" - causes the debugger to execute the current command, and stop again, showing the next command in the code
to be executed.
2. "step" - causes the debugger to execute the current command, and if it is a function call - break at the beginning of that
function. This is useful for debugging nested code.
Now is your time to experiment with these options with our debug program, and see how they work. It is also useful to read
the debuggers help, using the command "help break" and "help breakpoints" to learn how to set several breakpoints, how to
see what breakpoints are set, how to delete breakpoints, and how to apply conditions to breakpoints (i.e. make them stop the
program only if a certain expression evaluates to "true" when the breakpoint is reached).
print i
$1 = 0
For example, if you break inside the "print_string" function and try to print the value of "i", you'll get this message.
You may also try to print more complex expressions, like "i*2", or "argv[3]", or "argv[argc]", and so on. In fact, you may
also use type casts, call functions found in the program, and whatever your sick mind could imagine (well, almost). Again,
this is a good time to try this out.
This means the currently executing function is "print_string", at file "debug_me.c", line 7. The function that called it is
"main". We also see which arguments each function had received. If there were more functions in the call chain, we'd see
them listed in order. This list is also called "a stack trace", since it shows us the structure of the execution stack at this point
in the program's life.
Just as we can see contents of variables in the current function, we can see contents of variables local to the calling function,
or to any other function on the stack. For example, if we want to see the contents of variable "i" in function "main", we can
type the following two commands:
frame 1
print i
The "frame" command tells the debugger to switch to the given stack frame ('0' is the frame of the currently executing
function). At that stage, any print command invoked will use the context of that stack frame. Of-course, if we issue a "step"
or "next" command, the program will continue at the top frame, not at the frame we requested to see. After all, the debugger
cannot "undo" all the calls and continue from there.
Attaching To an Already Running Process
It might be that we'll want to debug a program that cannot be launched from the command line. This may be because the
program is launched from some system daemon (such as a CGI program on the web), and we are too lazy to make it possible
to run it directly from the command line. Or perhaps the program takes very long time to run its initialization code, and
starting it with a debugger attached to it will cause this startup time to be much much longer. There are also other reasons, but
hopefully you got the point. In order to do that, we will launch the debugger in this way:
Here we assume that "debug_me" is the name of the program executed, and that 9561 is the process id (PID) of the process
we want to debug.
What happens is that gdb first tries looking for a "core" file named "9561" (we'll see what core files are in the next section),
and when it won't find it, it'll assume the supplied number is a process ID, and try to attach to it. If there process executes
exactly the same program whose path we gave to gdb (not a copy of the file. it must be the exact same file that the process
runs), it'll attach to the program, pause its execution, and will let us continue debugging it as if we started the program from
inside the debugger. Doing a "where" right when we get gdb's prompt will show us the stack trace of the process, and we can
continue from there. Once we exit the debugger, It will detach itself from the process, and the process will continue execution
from where we left it.
This assumes the program was launched using this path, and the core file is in the current directory. If it is not, we can give
the path to the core file. When we get the debugger's prompt (assuming the core file was successfully read), we can issue
commands such as "print", "where" or "frame X". We can not issue commands that imply execution (such as "next", or the
invocation of function calls). In some situations, we will be able to see what caused the crash.
One should note that if the program crashed due to invalid memory address access, this will imply that the memory of the
program was corrupt, and thus that the core file is corrupt as well, and thus contains bad memory contents, invalid stack
frames, etc. Thus, we should see the core file's contents as one possible past, out of many probable pasts (this makes core file
analysis rather similar to quantum theory. almost).
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
v1.0.1
Preface
Compiling a program made of one source file is easy. Compiling one made of few sources is slightly annoying,
but may be automated via a simple shell script. Anything larger then that would start to get on your nerves. This
is where makefiles are helpful.
A makefile is a collection of instructions that should be used to compile your program. Once you modify some
source files, and type the command "make" (or "gmake" if using GNU's make), your program will be recompiled
using as few compilation commands as possible. Only the files you modified and those dependent upon them will
be recompiled. Of-course, this is not done via usage of magic. You need to supply the rules for compiling various
files and file types, and the list of dependencies between files (if file "A" was changed, then files "B", "C" and
"D" also need to be re-compiled), but that only has to be done once.
CFLAGS = -g -Wall
SRCS = main.c file1.c file2.c
CC = gcc
● Dependency Rules - these lines define under what conditions a given file (or a type of file) needs to be
re-compiled, and how to compile it. For example:
main.o: main.c
gcc -g -Wall -c main.c
This rule means that "main.o" has to be recompiled whenever "main.c" is modified. The rule continues to
tell us that in order to compile "main.o", the command "gcc -g -Wall -c main.c" needs to be
executed.
Note that each line in the commands list must begin with a TAB character. "make" is quite picky about the
makefile's syntax.
● Comments - Any line beginning with a "#" sign, or any line that contains only white-space.
Order Of Compilation
When a makefile is executed, we tell the make command to compile a specific target. A target is just some name
that appears at the beginning of a rule. It can be a name of a file to create, or just a name that is used as a starting
point (such a target is also called a "phony" target).
When make Is invoked, it first evaluates all variable assignments, from top to bottom, and when it encounters a
rule "A" whose target matches the given target (or the first rule, if no target was supplied), it tries to evaluate this
rule. First, it tries to recursively handle the dependencies that appear in the rule. If a given dependency has no
matching rule, but there is a file in the disk with this name, the dependency is assumed to be up-to-date. After all
the dependencies were checked, and any of them required handling, or refers to a file newer then the target, the
command list for rule "A" is executed, one command at a time.
This might appear a little complex, but the example in the next section will make things clear.
# we'll skip all the variable definitions, just take them from the previous
# makefile
.
.
# linking rule remains the same as before.
$(PROG): $(OBJS)
$(LD) $(LDFLAGS) $(OBJS) -o $(PROG)
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
The FILE structure is the basic data type used when handling files with the standard C library. When we open a file, we get a
pointer to such a structure, that we later use with all other operations on the file, until we close it. This structure contains
information such as the location in the file from which we will read next (or to which we will write next), the read buffer, the
write buffer, and so on. Sometimes this structure is also referred to as a "file stream", or just "stream".
In order to work with a file, we must open it first, using the fopen() function. We specify the path to the file (full path, or
relative to the current working directory), as well as the mode for opening the file (open for reading, for writing, for reading
and writing, for appending only, etc.). Here are a few examples of how to use it:
As you can see, the mode of opening the file is given as an abbreviation. More options are documented in the manual page
for the fopen() function. The fopen() function returns a pointer to a FILE structure on success, or a NULL pointer in
case of failure. The exact reason for the failure may be anything from "file does not exist" (in read mode), "permission
denied" (if we don't have permission to access the file or its directory), I/O error (in case of a disk failure), etc. In such a case,
the global variable "errno" is being set to the proper error code, and the perror() function may be used to print out a text
string related to the exact error code.
Once we are done working with the file, we need to close it. This has two effects:
1. Flushing any un-saved changes to disk (actually, to the operating system's disk cache).
2. Freeing the file descriptor (will be explained in the system calls section below) and any other resources associated with
the open file.
Closing the file is done with the fclose() function, as follows:
if (!fclose(f_readwrite)) {
perror("Failed closing file '/usr/local/lib/db/users':");
exit(1);
}
fclose() returns 0 on success, or EOF (usually '-1') on failure. It will then set "errno" to zero. One may wonder how could
closing a file fail - this may happen if any buffered writes were not saved to disk, and are being saved during the close
operation. Whether the function succeeded or not, the FILE structure may not be used any more by the program.
Once we have a pointer for an open file's structure, we may read from it using any of several functions. In the following code,
assume f_read and f_readwrite pointers to FILE structures returned by previous calls to fopen().
/* read one line from the file. A line is all characters up to a new-line */
/* character, or up to the end of the file. At most 200 characters will be */
/* read in (i.e. one less then the number we supply to the function call). */
/* The string read in will be terminated by a null character, so that is */
/* why the buffer was made 201 characters long, not 200. If a new line */
/* character is read in, it is placed in the buffer, not removed. */
/* note that 'stdin' is a FILE structure pre-allocated by the */
/* C library, and refers to the standard input of the process (normally */
/* input from the keyboard). */
fgets(buf, 201, stdin);
/* place the given character back into the given file stream. The next */
/* operation on this file will return this character. Mostly used by */
/* parsers that analyze a given text, and try to guess what the next */
/* is. If they miss their guess, it is easier to push the last character */
/* back to the file stream, then to make book-keeping operations. */
ungetc(c, stdin);
/* check if the read/write head has reached past the end of the file. */
if (feof(f_read)) {
printf("End of file reached\n");
}
/* read one block of 120 characters from the file stream, into 'buf'. */
/* (the third parameter to fread() is the number of blocks to read). */
char buf[120];
if (fread(buf, 120, 1, f_read) != 1) {
perror("fread");
}
There are various other file reading functions (getc() for example), but you'll be able to learn them from the on-line
manual.
Note that when we read in some text, the C library actually reads it from disk in full blocks (with a size of 512 characters, or
something else, as optimal for the operating system we work with). For example, if we read 20 consecutive characters using
fgetc() 20 times, only one disk operation is made. The rest of the read operations are made from the buffer kept in the
FILE structure.
Just like the read operations, we have write operations as well. They are performed at the current location of the read/write
pointer kept in the FILE structure, and are also done in a buffered mode - only if we fill in a full block, the C library's write
functions actually write the data to disk. Yet, we can force it to write data at a given time (e.g. if we print to the screen and
want partially written lines to appear immediately). In the following example, assume that f_readwrite is a pointer to a FILE
structure returned from a previous call to fopen().
/* write the string "hi there, mate" to the standard input (screen) */
/* a new-line in placed in the string, to make the cursor move */
/* to the next line on screen after writing the string. */
fprintf(stdout, "hi there, mate\n");
/* write twice the string "hello, great world. we feel fine!\n" to 'f_readwrite'. */
/* (the third parameter to fwrite() is the number of blocks to write). */
char buf[100];
strcpy(buf, "hello, great world. we feel fine!\n");
if (fwrite(buf, strlen(buf), 2, f_readwrite) != 2) {
perror("fwrite");
}
Note that when the output is to the screen, the buffering is done in line mode, i.e. whenever we write a new-line character, the
output is being flushed automatically. This is not the case when our output is to a file, or when the standard output is being
redirected to a file. In such cases the buffering is done for larger chunks of data, and is said to be in "block-buffered mode".
Until now we have seen how input and output is done in a serial mode. However, in various occasions we want to be able to
move inside the file, and write to different locations, or read from different locations, without having to scan the whole code.
This is common in database files, when we have some index telling us the location of each record of data in the file.
Traveling in a file stream in such a manner is also called "random access".
The fseek() function allows us to move the read/write pointer of a file stream to a desired location, stated as the number of
bytes from the beginning of the file (or from the end of file, or from the current position of the read/write pointer). The
ftell() function tells us the current location of the read/write header of the given file stream. Here is how to use these
functions:
A Complete Example
Two examples are given for the usage of the standard C library I/O functions. The first example is a file copying program,
that reads a given file one line at a time, and writes these lines to a second file. The source code is found in the file
stdc-file-copy.c. Note that this program does not check if a file with the name of the target already exists, and thus viciously
erases any existing file. Be careful when running it! Later, when discussing the system calls interface, we will see how to
avoid this danger.
The second example manages a small database file with fixed-length records (i.e. all records have the same size), using the
fseek() function. The source is found in the file stdc-small-db.c. Functions are supplied for reading a record and for
writing a record, based on an index number. See the source code for more info. This program uses the fread() and
fwrite() functions to read data from the file, or write data to the file. Check the on-line manual page for these functions to
see exactly what they do.
The basic system object used to manipulate files is called a file descriptor. This is an integer number that is used by the
various I/O system calls to access a memory area containing data about the open file. This memory area has a similar role to
the FILE structure in the standard C library I/O functions, and thus the pointer returned from fopen() has a role similar to
a file descriptor.
Each process has its own file descriptors table, with each entry pointing to a an entry in a system file descriptor table. This
allows several processes to share file descriptors, by having a table entry pointing to the same entry in the system file
descriptors table. You will encounter this phenomena, and how it can be used, when learning about multi-process
programming.
The value of the file descriptor is a non-negative integer. Usually, three file descriptors are automatically opened by the shell
that started the process. File descriptor '0' is used for the standard input of the process. File descriptor '1' is used for the
standard output of the process, and file descriptor '2' is used for the standard error of the process. Normally the standard input
gets input from the keyboard, while standard output and standard error write data to the terminal from which the process was
started.
Opening files using the system call interface is done using the open() system call. Similar to fopen(), it accepts two
parameters. One containing the path to the file to open, the other contains the mode in which to open the file. The mode may
be any of the following:
O_RDONLY
Open the file in read-only mode.
O_WRONLY
Open the file in write-only mode.
O_RDWR
Open the file for both reading and writing.
In addition, any of the following flags may be OR-ed with the mode flag:
O_CREAT
If the file does not exist already - create it.
O_EXCL
If used together with O_CREAT, the call will fail if the file already exists.
O_TRUNC
If the file already exists, truncate it (i.e. erase its contents).
O_APPEND
Open the file in append mode. Any data written to the file is appended at the end of the file.
O_NONBLOCK (or O_NDELAY)
If any operation on the file is supposed to cause the calling process block, the system call instead will fail, and errno be
set to EAGAIN. This requires caution on the part of the programmer, to handle these situations properly.
O_SYNC
Open the file in synchronous mode. Any write operation to the file will block until the data is written to disk. This is
useful in critical files (such as database files) that must always remain in a consistent state, even if the system crashes
in the middle of a file operation.
Unlike the fopen() function, open() accepts one more (optional) parameter, which defines the access permissions that
will be given to the file, in case of file creation. This parameter is a combination of any of the following flags:
S_IRWXU
Owner of the file has read, write and execute permissions to the file.
S_IRUSR
Owner of the file has read permission to the file.
S_IWUSR
Owner of the file has write permission to the file.
S_IXUSR
Owner of the file has execute permission to the file.
S_IRWXG
Group of the file has read,write and execute permissions to the file.
S_IRGRP
Group of the file has read permission to the file.
S_IWGRP
Group of the file has write permission to the file.
S_IXGRP
Group of the file has execute permission to the file.
S_IRWXO
Other users have read,write and execute permissions to the file.
S_IROTH
Other users have read permission to the file.
S_IWOTH
Other users have write permission to the file.
S_IXOTH
Other users have execute permission to the file.
Here are a few examples of using open():
/* Open the file run.log (in the current directory) in write-only mode. */
/* and truncate it, if it has any contents. */
fd_write = open("run.log", O_WRONLY | O_TRUNC);
if (fd_write < 0) {
perror("open");
exit(1);
}
if (close(fd) == -1) {
perror("close");
exit(1);
}
This will cause the file to be closed. Note that no buffering is normally associated with files opened with open(), so no
buffer flushing is required.
Note: If a file that is currently open by a Unix process is being erased (using the Unix "rm" command, for example), the file
is not really removed from the disk. Only when the process (or all processes) holding the file open, the file is physically
removed from the disk. Until then it is just removed from its directory, not from the disk.
Once we got a file descriptor to an open file (that was opened in read mode), we may read data from the file using the
read() system call. This call takes three parameters: the file descriptor to read from, a buffer to read data into, and the
number of characters to read into the buffer. The buffer must be large enough to contain the data. Here is how to use this call.
We assume 'fd' contains a file descriptor returned from a previous call to open().
/* return value from the read() call. */
size_t rc;
/* buffer to read data into. */
char buf[20];
As you can see, read() does not always read the number of bytes we asked it to read. This could be due to a signal
interrupting it in the middle, or the end of the file was encountered. In such a case, read() returns the number of bytes it
actually read.
Just like we used read() to read from the file, we use the write() system call, to write data to the file. The write
operations is done in the location of the current read/write pointer of the given file, much like the various standard C library
output functions did. write() gets the same parameters as read() does, and just like read(), might write only part of
the data to the given file, if interrupted in the middle, or for other reasons. In such a case it will return the number of bytes
actually written to the file. Here is a usage example:
As you can see, there is never an end-of-file case with a write operation. If we write past the current end of the file, the file
will be enlarged to contain the new data.
Sometimes, writing out the data is not enough. We want to be sure the file on the physical disk gets updated immediately
(note that even thought the system calls do not buffer writes, the operating system still buffers write operations using its disk
cache). In such cases, we may use the fsync() system call. It ensures that any write operations for the given file descriptor
that are kept in the system's disk cache, are actually written to disk, when the fsync() system call returns to the caller. Here
is how to use it:
Note that fsync() updates both the file's contents, and its book-keeping data (such as last modification time). If we only
need to assure that the file's contents is written to disk, and don't care about the last update time, we can use fdatasync()
instead. This is more efficient, as it will issue one fewer disk write operation. In applications that need to synchronize data
often, this small saving is important.
Just like we used the fseek() function to move the read/write pointer of the file stream, we can use the lseek() system
call to move the read/write pointer for a file descriptor. Assuming you understood the fseek() examples above, here are a
few similar examples using lseek(). We assume that 'fd_read' is an integer variable containing a file descriptor to a
previously opened file, in read only mode. 'fd_readwrite' is a similar file descriptor, but for a file opened in read/write mode.
Note that lseek() might not always work for a file descriptor (e.g. if this file descriptor represents the standard input,
surely we cannot have random-access to it). You will encounter other similar cases when you deal with network
programming and inter-process communications, in the future.
Since Unix supports access permissions for files, we would sometimes need to check these permissions, and perhaps also
manipulate them. Two system calls are used in this context, access() and chmod().
The access() system call is for checking access permissions to a file. This system call accepts a path to a file (full or
relative), and a mode mask (made of one or more permission modes). It returns '0' if the specified permission modes are
granted for the calling process, or '-1' if any of these modes are not granted, the file does not exist, etc. The access is granted
or denied based on the permission flags of the file, and the ID of the user running the process. Here are a few examples:
As you can see, we can check for read, write and execute permissions, as well as for the existence of a file, and the same for a
directory. As an example, we will see a program that checks out if we have read permission to a file, and notifies us if not -
where the problem lies. The full source code for this program is found in file read-access-check.c.
Note that we cannot use access() to check why we got permissions (i.e. if it was due to the given mode granted to us as
the owner of the file, or due to its group permissions or its word permissions). For more fine-grained permission tests, see the
stat() system call mentioned below.
The chmod() system call is used for changing the access permissions for a file (or a directory). This call accepts two
parameters: a path to a file, and a mode to set. The mode can be a combination of read, write and execute permissions for the
user, group or others. It may also contain few special flags, such as the set-user-ID flag or the 'sticky' flag. These permissions
will completely override the current permissions of the file. See the stat() system call below to see how to make
modifications instead of complete replacement. Here are a few examples of using chmod().
/* give the owner read and write permission to the file "blabla", */
/* and deny access to any other user. */
if (chmod("blabla", S_IRUSR | S_IWUSR) == -1) {
perror("chmod");
}
/* give the owner read and write permission to the file "blabla", */
/* and read-only permission to anyone else. */
if (chmod("blabla", S_IRUSR | S_IWUSR | S_IRGRP | S_IWOTH) == -1) {
perror("chmod");
}
For the full list of access permission flags to use with chmod(), please refer to its manual page.
We have seen how to manipulate the file's data (write) and its permission flags (chmod). We saw a primitive way of checking
if we may access it (access), but we often need more then that: what are the exact set of permission flags of the file? when
was it last changed? which user and group owns the file? how large is the file?
All these questions (and more) are answered by the stat() system call.
stat() takes as arguments the full path to the file, and a pointer to a (how surprising) 'stat' structure. When stat()
returns, it populates this structure with a lot of interesting (and boring) stuff about the file. Here are few of the fields found in
this structure (for the rest, read the manual page):
umode_t st_mode
Access permission flags of the file, as well as information about the type of file (file? directory? symbolic link? etc).
uid_t st_uid
The ID of the user that owns the file.
gid_t st_gid
The ID of the group that owns the file.
off_t st_size
The size of the file (in bytes).
time_t st_atime
Time when the file was last accessed (read from or written to). Time is given as number of seconds since 1 Jan, 1970.
time_t st_mtime
Time when the file was last modified (created or written to).
time_t st_ctime
Time when the file was last changed (had its permission modes changed, or any of its book-keeping, but NOT a
contents change).
Here are a few examples of how stat() can be used:
The last item should be explained better. For some reason, the 'stat' structure uses the same bit field to contain file type
information and access permission flags. Thus, to get only the access permissions, we need to mask off the file type bits. The
mask for the file type bits is 'S_IFMT', and thus the mask for the permission modes is its logical negation, or '~S_IFMT'. By
logically "and"-ing this value with the 'st_mode' field of the 'stat' structure, we get the current access permission modes. We
can add new modes using the logical or ('|') operator, and remove modes using the logical and ('&') operator. After we create
the new modes, we use chmod() to set the new permission flags for the file.
Note that this operation will also implicitly modify the 'ctime' (change time) of the file, but that won't be reflected in our 'stat'
structure, unless we stat() the file again.
Renaming A File
The rename() system call may be used to change the name (and possibly the directory) of an existing file. It gets two
parameters: the path to the old location of the file (including the file name), and a path to the new location of the file
(including the new file name). If the new name points to a an already existing file, that file is deleted first. We are allowed to
name either a file or a directory. Here are a few examples:
/* move the file 'data' from the current directory to directory "/old/info" */
if (rename("data", "/old/info/data") == -1) {
perror("rename (2):");
exit(1);
}
Note: If the file we are renaming is a symbolic link, then the symbolic link will be renamed, not the file it is pointing to. Also,
if the new path points to an existing symbolic link, this symbolic link will be erased, not the file it is pointing to.
Deleting A File
Deleting a file is done using the unlink() system call. This one is very simple:
The file will be removed from the directory in which it resides, and all the disk blocks is occupied will be marked as free for
re-use by the system. However, if any process currently has this file open, the file won't be actually erased until the last
process holding it open erases it. This could explain why often erasing a log file from the system does not increase the
amount of free disk space - it might be that the system logger process (syslogd) holds this file open, and thus the system won't
really erase it until syslogd closes it. Until then, it will be removed from the directory (i.e. 'ls' won't show it), but not from the
disk.
We have encountered symbolic links earlier. lets see how to create them, with the symlink() system call:
So the first parameter is the file being pointer to, and the second parameter is the file that will be the symbolic link. Note that
the first file does not need to exist at all - we can create a symbolic link that points nowhere. If we later create the file this
link points to, accessing the file via the symbolic link will work properly.
If you created files with open() or fopen(), and you did not supply the mode for the newly created file, you might
wonder how does the system assign access permission flags for the newly created file. You will also note that these "default"
flags are different on different computers or different account setups. This mysteriousness is due to the usage of the
umask() system call, or its equivalent umask shell command.
The umask() system call sets a mask for the permission flags the system will assign to newly created files. By default,
newly created files will have read and write permissions to everyone (i.e. rw-rw-rw- , in the format reported by 'ls -l'). Using
umask(), we can denote which flags will be turned off for newly created files. For example, if we set the mask to 077 (a
leading 0 denotes an octal value), newly created files will get access permission flags of 0600 (i.e. rw-------). If we set the
mask to 027, newly created files will get flags of 0640 (i.e. rw-r-----). Try translating these values to binary format in order to
see what is going on here.
Here is how to mess with the umask() system call in a program:
/* set the file permissions mask to '077'. save the original mask */
/* in 'old_mask'. */
int old_mask = umask(077);
/* newly created files will now be readable only by the creating user. */
FILE* f_write = fopen("my_file", "w");
if (f_write) {
fprintf(f_write, "My name is pit stanman.\n");
fprintf(f_write, "My voice is my pass code. Verify me.\n");
fclose(f_write);
}
Note: the permissions mask affects also calls to open() that specify an exact permissions mask. If we want to create a file
whose permission are less restrictive the the current mask, we need to use umaks() to lighten these restrictions, before
calling open() to create the file.
Note 2: on most systems you will find that the mask is different then the default. This is because the system administrator has
set the default mask in the system-wide shell startup files, using the shell's umask command. You may set a different default
mask for your own account by placing a proper umask command in your shell's starup file ("~/.profile" if you're using "sh"
or "bash". "~/.cshrc" if you are using "csh" or "tcsh").
A Complete Example
As an example to the usage of the system calls interface for manipulating files, we will show a program that handles simple
log file rotation. The program gets one argument - the name of a log file, and assumes it resides in a given directory
("/tmp/var/log"). If the size of the log file is more then 1024KB, it renames it to have a ".old" suffix, and creates a new
(empty) log file with the same name as the original file, and the same access permissions. This code demonstrates combining
many system calls together to achieve a task. The source code for this program is found in the file rename-log.c.
When we want to read the contents of a directory, we have a function that opens a directory, and returns a DIR structure. This
structure contains information used by other calls to read the contents of the directory, and thus this structure is for directory
reading, what the FILE structure is for files reading.
When we use the DIR structure to read the contents of a directory, entry by entry, the data regarding a given entry is returned
in a dirent structure. The only relevant field in this structure is d_name, which is a null-terminated character array,
containing the name of the entry (be it a file or a directory). note - the name, NOT the path.
In order to read the contents of a directory, we first open it, using the opendir() function. We supply the path to the
directory, and get a pointer to a DIR structure in return (or NULL on failure). Here is how:
When we are done reading from a directory, we can close it using the closedir() function:
if (closedir(dir) == -1) {
perror("closedir");
exit(1);
}
closedir() will return '0' on success, or '-1' if it failed. Unless we have done something really silly, failures shouldn't
happen, as we never write to a directory using the DIR structure.
After we opened the directory, we can start scanning it, entry by entry, using the readdir() function. The first call returns
the first entry of the directory. Each successive call returns the next entry in the directory. When all entries have been read,
NULL is returned. Here is how it is used:
/* this structure is used for storing the name of each entry in turn. */
struct dirent* entry;
/* read the directory's contents, print out the name of each entry. */
printf("Directory contents:\n");
while ( (entry = readdir(dir)) != NULL) {
printf("%s\n", entry.d_name);
}
If you try this out, you'll note that the directory always contains the entries "." and "..", as explained in the beginning of this
tutorial. A common mistake is to forget checking these entries specifically, in recursive traversals of the file system. If these
entries are being traversed blindingly, an endless loop might occur.
Note: if we alter the contents of the directory during its traversal, the traversal might skip directory entries. Thus, if you
intend to create a file in the directory, you would better not do that while in the middle of a traversal.
After we are done reading the contents of a directory, we can rewind it for a second pass, using the rewinddir() function:
rewinddir(dir);
Sometimes we wish to find out the current working directory of a process. The getcwd() function is used for that. Other
times we wish to change the working directory of our process. This will allow using short paths when accessing several files
in the same directory. The chdir() system call is used for this. Here is an example:
A Complete Example
As an example, we will write a limited version of the Unix 'find' command. This command basically accepts a file name and
a directory, and finds all files under that directory (or any of its sub-directories) with the given file name. The original
program has zillions of command line options, and can also handle file name patterns. Our version will only be able to handle
substrings (that is, finding the files whose names contain the given string). The program changes its working directory to the
given directory, reads its contents, and recursively scans each sub-directory it encounters. The program does not traverse
across symbolic-links to avoid possible loops. The complete source code for the the program is found in the find-file.c file.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
v1.0.1
This command creates a static library named 'libutil.a' and puts copies of the object files "util_file.o", "util_net.o" and
"util_math.o" in it. If the library file already exists, it has the object files added to it, or replaced, if they are newer then
those inside the library. The 'c' flag tells ar to create the library if it doesn't already exist. The 'r' flag tells it to
replace older object files in the library, with the new object files.
After an archive is created, or modified, there is a need to index it. This index is later used by the compiler to speed up
symbol-lookup inside the library, and to make sure that the order of the symbols in the library won't matter during
compilation (this will be better understood when we take a deeper look at the link process at the end of this tutorial). The
command used to create or update the index is called 'ranlib', and is invoked as follows:
ranlib libutil.a
On some systems, the archiver (which is not always ar) already takes care of the index, so ranlib is not needed (for
example, when Sun's C compiler creates an archive, it is already indexed). However, because 'ar' and 'ranlib' are
used by many makefiles for many packages, such platforms tend to supply a ranlib command that does nothing. This
helps using the same makefile on both types of platforms.
Note: when an archive file's index generation date (stored inside the archive file) is older then the file's last modification
date (stored in the file system), a compiler trying to use this library will complain its index is out of date, and abort. There
are two ways to overcome the problem:
1. Use 'ranlib' to re-generate the index.
2. When copying the archive file to another location, use 'cp -p', instead of only 'cp'. The '-p' flag tells
'cp' to keep all attributes of the file, including its access permissions, owner (if "cp" is invoked by a superuser)
and its last modification date. This will cause the compiler to think the index inside the file is still updated. This
method is useful for makefiles that need to copy the library to another directory for some reason.
This will create a program using object file "main.o", and any symbols it requires from the "util" static library. Note that
we omitted the "lib" prefix and the ".a" suffix when mentioning the library on the link command. The linker attaches
these parts back to the name of the library to create a name of a file to look for. Note also the usage of the '-L' flag -
this flag tells the linker that libraries might be found in the given directory ('.', refering to the current directory), in
addition to the standard locations where the compiler looks for system libraries.
For an example of program that uses a static library, try looking at our static library example directory.
cc -fPIC -c util_file.c
cc -fPIC -c util_net.c
cc -fPIC -c util_math.c
cc -shared libutil.so util_file.o util_net.o util_math.o
The first three commands compile the source files with the PIC option, so they will be suitable for use in a shared library
(they may still be used in a program directly, even thought they were compiled with PIC). The last command asks the
compiler to generate a shared library
The linker will look for the file 'libutil.so' (-lutil) in the current directory (-L.), and link it to the program, but will
not place its object files inside the resulting executable file, 'prog'.
The run-time part is a little trickier. Normally, the system's dynamic loader looks for shared libraries in some system
specified directories (such as /lib, /usr/lib, /usr/X11/lib and so on). When we build a new shared library that is not part of
the system, we can use the 'LD_LIBRARY_PATH' environment variable to tell the dynamic loader to look in other
directories. The way to do that depends on the type of shell we use ('tcsh' and 'csh', versus 'sh', 'bash', 'ksh' and similar
shells), as well as on whether or not 'LD_LIBRARY_PATH' is already defined. To check if you have this variable
defined, try:
echo $LD_LIBRARY_PATH
If you get a message such as 'LD_LIBRARY_PATH: Undefined variable.', then it is not defined.
Here is how to define this variable, in all four cases:
1. 'tcsh' or 'csh', LD_LIBRARY_PATH is not defined:
LD_LIBRARY_PATH=/full/path/to/library/directory
export LD_LIBRARY_PATH
LD_LIBRARY_PATH=/full/path/to/library/directory:${LD_LIBRARY_PATH}
export LD_LIBRARY_PATH
After you've defined LD_LIBRARY_PATH, you can check if the system locates the library properly for a given program
linked with this library:
ldd prog
You will get a few lines, each listing a library name on the left, and a full path to the library on the right. If a library is not
found in any of the system default directories, or the directories mentioned in 'LD_LIBRARY_PATH', you will get a
'library not found' message. In such a case, verify that you properly defined the path to the directory inside
'LD_LIBRARY_PATH', and fix it, if necessary. If all goes well, you can run your program now like running any other
program, and see it role...
For an example of a program that uses a shared library, try looking at our shared library example directory.
The dlopen() function gets two parameters. One is the full path to the shared library. The other is a flag defining
whether all symbols refered to by the library need to be checked immediatly, or only when used. In our case, we may use
the lazy approach (RTLD_LAZY) of checking only when used. The function returns a pointer to the loaded library, that
may later be used to reference symbols in the library. It will return NULL in case an error occured. In that case, we may
use the dlerror() function to print out a human-readable error message, as we did here.
As you can see, errors might occur anywhere along the code, so we should be carefull to make extensive error checking.
Surely, you'll also check that 'a_file' is not NULL, after you call your function.
dlclose(lib_handle);
This will free down all resources taken by the library (in particular, the memory its executable code takes up).
This means that linking will be slower (library 'A' will be processed twice). This also hints that one should try not to have
such mutual dependencies between two libraries. If you have such dependencies - then either re-design your libraries'
contents, or combine the two libraries into one larger library.
Note that object files found on the command line are always fully included in the executable file, so the order of
mentioning them does not really matter. Thus, a good rule is to always mention the libraries after all object files.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Ctrl-Z
Pressing this key causes the system to send a TSTP signal (SIGTSTP) to the running process. By default,
this signal causes the process to suspend execution.
Ctrl-\
Pressing this key causes the system to send a ABRT signal (SIGABRT) to the running process. By default,
this signal causes the process to immediately terminate. Note that this redundancy (i.e. Ctrl-\ doing the same
as Ctrl-C) gives us some better flexibility. We'll explain that later on.
For example, in order to send the INT signal to process with PID 5342, type:
This has the same affect as pressing Ctrl-C in the shell that runs that process.
If no signal name or number is specified, the default is to send a TERM signal to the process, which normally
causes its termination, and hence the name of the kill command.
fg
On most shells, using the 'fg' command will resume execution of the process (that was suspended with
Ctrl-Z), by sending it a CONT signal.
.
.
.
/* and somewhere later in the code.... */
.
.
The complete source code for this program is found in the catch-ctrl-c.c file.
Notes:
● the pause() system call causes the process to halt execution, until a signal is received. it is surely better
then a 'busy wait' infinite loop.
● the name of a function in C/C++ is actually a pointer to the function, so when you're asked to supply a
pointer to a function, you may simply specify its name instead.
● On some systems (such as Linux), when a signal handler is called, the system automatically resets the signal
handler for that signal to the default handler. Thus, we re-assign the signal handler immediately when
entering the handler function. Otherwise, the next time this signal is received, the process will exit (default
behavior for INT signals). Even on systems that do not behave in this way, it still won't hurt, so adding this
line always is a good idea.
Pre-defined Signal Handlers
For our convenience, there are two pre-defined signal handler functions that we can use, instead of writing our
own: SIG_IGN and SIG_DFL.
SIG_IGN:
Causes the process to ignore the specified signal. For example, in order to ignore Ctrl-C completely (useful
for programs that must NOT be interrupted in the middle, or in critical sections), write this:
signal(SIGINT, SIG_IGN);
SIG_DFL:
Causes the system to set the default signal handler for the given signal (i.e. the same handler the system
would have assigned for the signal when the process started running):
signal(SIGTSTP, SIG_DFL);
int how
defines if we want to add signals to the current mask (SIG_BLOCK), remove them from the current mask
(SIG_UNBLOCK), or completely replace the current mask with the new mask (SIG_SETMASK).
const sigset_t *set
The set of signals to be blocked, or to be added to the current mask, or removed from the current mask
(depending on the 'how' parameter).
sigset_t *oldset
If this parameter is not NULL, then it'll contain the previous mask. We can later use this set to restore the
situation back to how it was before we called sigprocmask().
Note: Older systems do not support the sigprocmask() system call. Instead, one should use the sigmask()
and sigsetmask() system calls. If you have such an operating system handy, please read the manual pages for
these system calls. They are simpler to use then sigprocmask, so it shouldn't be too hard understanding them once
you've read this section.
You probably wonder what are these sigset_t variables, and how they are manipulated. Well, i wondered too,
so i went to the manual page of sigsetops, and found the answer. There are several functions to handle these
sets. Lets learn them using some example code:
Now that we know all these little secrets, lets see a short code example that counts the number of Ctrl-C signals a
user has hit, and on the 5th time (note - this number was "Stolen" from some quite famous Unix program) asks the
user if they really want to exit. Further more, if the user hits Ctrl-Z, the number of Ctrl-C presses is printed on the
screen.
.
.
/* and somewhere inside the main function... */
.
.
You should note that using sigprocmask() the way we did now does not resolve all possible race conditions.
For example, It is possible that after we entered the signal handler, but before we managed to call the
sigprocmask() system call, we receive another signal, which WILL be called. Thus, if the user is VERY quick
(or the system is very slow), it is possible to get into races. In our current functions, this will probably not disturb
the flow, but there might be cases where this kind of race could cause problems.
The way to guarantee no races at all, is to let the system set the signal masking for us before it calls the signal
handler. This can be done if we use the sigaction() system call to define both the signal handler function
AND the signal mask to be used when the handler is executed. You would probably be able to read the manual
page for sigaction() on your own, now that you're familiar with the various concepts of signal handling. On
old systems, however, you won't find this system call, but you still might find the sigvec() call, that enables a
similar functionality.
.
.
/* and inside the main program... */
.
.
.
.
/* do something with the received user name */
.
.
The complete source code for this program is found in the use-alarms.c file.
As you can see, we start the timer right before waiting for user input. If we started it earlier, we'll be giving the
user less time then promised to perform the operation. We also stop the timer right after getting the user's input,
before doing any tests or processing of the input, to avoid a random timer from setting off due to slow processing
of the input. Many bugs that occur using the alarm() system call occur due to forgetting to set off the timer at
various places when the code gets complicated. If you need to make some tests during the input phase, put the
whole piece of code in a function, so it'll be easier to make sure that the timer is always set off after calling the
function. Here is an example of how NOT to do this:
return result;
}
Lets count the mistakes and bad programming practices in the above function:
1. * Too short timeout:
3 seconds might be enough for superman to type his user name, but a normal user obviously needs more
time. Such a timeout should actually be tunable, because not all people type at the same pace, or should be
long enough for even the slowest of users.
2. * Printing while timer is ticking:
Norty Norty. This printing should have been done before starting up the timer. Printing may be a time
consuming operation, and thus will leave less time then expected for the user to type in the expected input.
3. * Exiting function without turning off timer:
This kind of mistake is hard to catch. It will cause the program to randomally exit somewhere LATER
during the execution. If we'll trace it with a debugger, we'll see that the signal was received while we were
already executing a completely different part of the program, leaving us scratching our head and looking up
to the sky, hoping somehow inspiration will fall from there to guide us to the location of the problem.
4. * Making long checks before turning off timer:
As if it's not enough that we gave the poor user a short time to check for the input, we're also inserting some
database checking operation while the timer is still ticking. Even if we also want to timeout the database
operation, we should probably set up a different timer (and a different ALRM signal handler), so as not to
confuse a slow user with a slow database server. It will also allow the user to know why we are timing out.
Without this information, a person trying to figure out why the program suddenly exits, will have hard time
finding where the fault lies.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Table of contents
(yeah, I know I promised to avoid an index, but an un-detailed one is necessary)
1. Internet
2. Client and Server Model
3. Preparing an Internet Address
4. The Socket Interface
5. Writing Clients
6. Single-Client Servers
7. Multi-Client Servers
8. Conclusions
9. See Also - or, where to go from here.
Appendices:
1. LANs (Local Area Networks)
2. DNS (Domain Name Servers)
1. Internet
(Skip this if you know what Internet is, what protocols it uses, what kind of addresses are used over Internet,
etc).
Preview
The Internet is a computer communication network. Every computer connected to the Internet is also known as
a "host", so we could say that Internet's role is to allow hosts to talk amongst themselves. I assume you are
already familiar with Internet, as a user of programs such as 'Telnet', 'Ftp', 'Irc' and others. Lets first discuss
Internet addresses a little, before we talk about the Internet protocols, and various programming aspects
regarding network uniformity.
Internet Addresses
(Skip this if you know what IP addresses are and what ports in Internet are).
An Internet address (or an IP address, or an IP number) is a number made of 4 bytes (numbers between 0 and
255), written in what is called 'a dot notation'. for example, "128.0.46.1" is a valid Internet address. Such an
address identifies a computer which is connected to the Internet. Note that a computer might have more then
one such address, if it has more then one physical connections to the Internet (such as having two Ethernet
cards connected. What's Ethernet? read the appendices, or ignore this).
However, when a normal human being uses Internet, they usually use human-readable (oh, really?) addresses
of the form "uunet.uu.net" or "wuarchive.wustl.edu". A system in the Internet called "The Domain Name
System" or DNS for short, is responsible to translate between human-readable addresses and IP addresses
(again, read the appendices for information about DNS). You will not have to know anything about DNS in
order to use it in your programs, so do not worry about it now.
OK. We said that IP numbers define a computer. Well, usually there is more then one program that wants to
use the network, that runs on a given computer. For this purpose, the Internet people made up some extension
for an IP address, called a port number. Each communications address is made up of an IP number AND a port
number. Port numbers could be any number between 1 and 65535, although for certain reasons, you will use
port numbers above 1024, unless you have a superuser privileges on your machine (also stated sometimes as
"having root password").
For our purposes, we will use addresses of the form: 114.58.1.6:6072 where the "114.58.1.6" part is the IP
number, and the "6072" part is the port number. Remember this for later usage.
Internet protocols
(Skip this if you know what IP, TCP and UDP are).
You probably heard the term "TCP/IP" and wondered, or had some vague idea about what it means. Lets make
things clearer:
The Internet is a network. In order to talk on a network, you need some kind of a "language". That language is
also called "a protocol". The Internet has many kinds of protocols used to talk on it, in a manner called
"layering".
Layering means that instead of defining one protocol that will do everything, which will be very hard to design
and implement, the tasks are divided between several protocols, sitting on top of each other.
What does this mean? Think about it as sending letters: you write your letter on a paper, and then put it in an
envelope and write the address on it. The postman doesn't care WHAT you wrote in your letter, as long as you
wrote the correct address on the envelope.
The same thing is done when layering protocols. If one protocol contains the data sent and knows how to make
sure the data is correct, then a lower protocol will contain the address to be used, and will know how to
transfer the data to the correct target. The lower protocol does not understand the format of the data in the
upper protocol, and the upper protocol doesn't have to know how to actually transfer the data. This way, each
protocol becomes much simpler to design and test. Furthermore, If we will want to use the same protocol for
writing the data, but send the data on a different network, we will only need to replace the protocol that knows
how to transfer the data over the network, not the whole set of protocols.
(By the way, This sort of packing up several protocols on top of each other is called Encapsulation.)
One other important notion about the Internet is that it forms something known as a "packet switching
network". This means that every message sent out is divided into small amounts of information, called packets.
The different protocols send the data in packets, which might get divided into smaller packets while it travels
to the target host, due to "Electrical" limitations of physical networks. The target machine will eventually
combine the small packets (also known as fragments) and build the original message again.
The packets are what allows several connections to use the same physical network simultaneously, in a manner
transparent to the network users. No machine will take over a line completely, even if it needs to send a large
message. Instead, it will send the message in small fragments, allowing other machines to send their packets
too.
Let us now name out some of the Internet protocols, and explain briefly each one of them:
IP
IP is the basic protocol used on the Internet. It is responsible to make it possible to transfer packets from
one computer to another, given their IP addresses. Most other protocols are placed on top of IP. As a
programmer you will usually not use IP directly.
TCP
TCP is the most useful Internet protocol for a programmer. Most networking programs you use (such as
'Telnet', and 'Ftp') are placed on top of TCP. TCP is placed on top of IP, and adds 3 functionalities:
1. The notion of ports (IP supports only Internet addresses, as mentioned above).
2. The notion of a 'safe' protocol, i.e. no errors will be encountered in packets sent using TCP, so no
error correcting mechanisms are required in programs using TCP (well, this is almost true, but lets
assume so for now).
3. Connection-mode link. After you make a connection between two programs using TCP, you have
a steadily open connection on which you can send data without having to specify who you want
the data to be sent to. This works very similar to reading or writing on a pipeline, or on a regular
file.
UDP
UDP is another protocol that is placed on top of IP. It is used for services that send small amounts of
data between programs that do not require a long-time connection, or that send only little amount of data
at a time. The 'talk' program uses the UDP protocol.
UDP adds only port numbers to the functionality IP gives, so the programmer needs to worry about
checking for errors in messages (that come due to line noises and such), making sure the data sent using
UDP arrives in the right order (which is not automatically achieved, due to IP's nature of not having a
constantly open connection), and such.
There are various other protocols used in conjunction with IP, such as ARP, RARP, ICMP, SNMP and others,
but those won't be dealt with in this document. Look at the 'See Also' part to find pointers to articles discussing
those protocols.
Network uniformity
(Skip this if you already know what byte ordering means, and what are 'well known ports' across Internet)
It is important to understand that protocols need to define some low-level details, in order to be able to talk to
each other. We will discuss two such aspects here, in order to understand the example programs given later on.
Byte Order
It is an old argument amongst different computer manufacturers how numbers should be kept in a
computer.
As all computers divide memory into bytes (or octets) of information, each 8 bit long, there is no
problem with dealing with byte-sized numbers. The problem arises as we use larger numbers: short
integers (2 bytes long) and long integers (4 bytes long). Suppose we have a short integer number, FE4Ch
(that is, FE4C in hexadecimal notation). Suppose also that we say this number is kept in memory
address 100h. This could mean one of two things, lets draw them out:
1. Big Endian:
---------------
Address: | 100h | 101h |
---------------
Contents: | FEh | 4Ch |
---------------
2. Little Endian:
---------------
Address: | 100h | 101h |
---------------
Contents: | 4Ch | FEh |
---------------
In the first form, also called 'Big Endian', The Most Significant Byte (MSB) is kept in the lower address,
while the Least significant Byte (LSB) is kept in the higher address.
In the second form, also called 'Little Endian', the MSB is kept in the higher address, while the LSB is
kept in the lower address.
Different computers used different byte ordering (or different endianess), usually depending on the type
of CPU they have. The same problem arises when using a long integer: which word (2 bytes) should be
kept first in memory? the least significant word, or the most significant word?
In a network protocol, however, there must be a predetermined byte and word ordering. The IP protocol
defines what is called 'the network byte order', which must be kept on all packets sent across the
Internet. The programmer on a Unix machine is not saved from having to deal with this kind of
information, and we'll see how the translation of byte orders is solved when we get down to
programming.
Well Known Ports
When we want two programs to talk to each other across Internet, we have to find a way to initiate the
connection. So at least one of the 'partners' in the conversation has to know where to find the other one.
This is done by letting one partner know the address (IP number + port number) of the other side.
However, a problem could arise if one side's address is randomly taken over by a third program. Then
we'll be in real trouble. In order to avoid that, There are some port numbers which are reserved for
specific purposes on any computer connected to the Internet. Such ports are reserved for programs such
as 'Telnet', 'Ftp' and others.
These port numbers are specified in the file /etc/services on any decent Unix machine. Following is an
excerpt from that file:
daytime 13/tcp
daytime 13/udp
netstat 15/tcp
qotd 17/tcp quote
chargen 19/tcp ttytst source
chargen 19/udp ttytst source
ftp-data 20/tcp
ftp 21/tcp
telnet 23/tcp
smtp 25/tcp mail
Read that file to find that Telnet, for example, uses port 23, and Ftp uses port 21. Note that for each kind
of service, not only a port number is given, but also a protocol name (usually TCP or UDP). Note also
that two services may use the same port number, provided that they use different protocols. This is
possible due to the fact that different protocols have what is called different address spaces: port 23 of a
one machine in the TCP protocol address space, is not equivalent to port 23 on the same machine, in the
UDP protocol address space.
So how does this relate to you? When you will write your very own programs that need to 'chat' over
Internet, you will need to pick an unused port number that will be used to initiate the connection.
Roles of Clients
(Skip this if you already know what clients are supposed to do)
A client's main feature is giving a convenient User interface, hiding the details of how the server 'talks' from
the user. Today, people are trying to write mostly graphical clients, using windows, pop-up-menus and other
such fancy stuff. We will leave this to someone else to explain, and concentrate on the networking part. The
client needs to first establish a connection with the server, given it's address. After the connection is
established, The Client needs to be able to do two things:
1. Receive commands from the user, translate them to the server's language (protocol) and send them to the
server.
2. Receive messages from the server, translate them into human-readable form, and show them to the user.
Some of the messages will be dealt with by the client automatically, and hidden from the user. This
time, the Client designer's choice.
This forms the basic loop a client performs:
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
v1.0.1
Preface
One type of information that many programs require, is user information. This includes finding out the home directory of a
given user, finding the list of groups a user belongs to, finding out who is logged on the system at a given time and so on.
Most Unix systems keep this data in a set of files spread across the system. In order to allow programs to access this data in a
portable manner, some system functions (or API - Application Programming Interface) and data structures are defined, and
documented in different manual pages. This tutorial is an attempt at collecting the information that is common across most
Unix systems into one location, and at giving a few examples of using this information.
You will note one great problem with these APIs - they are exclusively read-only. You can use them in order to read user
information, but not to write out anything (i.e. create new data, update existing data or delete existing data). This makes these
APIs useless for writing a program that allows (for example) creation of new users, addition of groups for a user and so on.
Some hints will be supplied here as to how these tasks could be accomplished, but should be taken as time-bombs - do NOT
rely only on this information if you are trying to write such programs, as you might find your system's data corrupt, your list
of users erased, or something similar - DO THIS AT YOUR VERY OWN RISK. Now that we have made this point clear, we
can get started.
Accessing Info About User Accounts
The most basic info one would want to know about user accounts is - what user accounts exist on a system? or, is a given
user name valid on this system? This information is traditionally kept in the file named "/etc/passwd", and on current Unix
systems, in other files as well.
The "/etc/passwd" file contains one line (or record) per user account, and may NOT contain any comments. Each line is made
of a set of fields, separated by a colon (':') character. An example of such an line would be:
root:UQstWvHV002G1:0:0:root:/root:/bin/tcsh
This example shows a "root" (or superuser) account's entry. Most fields serve the same purpose on all Unix systems, and
would be as follows:
User Name
The name used to identify this account in all human-readable printouts, as well as when the user tries to log on to the
system.
Password
The encrypted password of the user (see the manual page of "crypt" for more information on password encryption). on
many systems, this field may also serve as a marker that the password is kept elsewhere - see discussion of shadow
passwords below.
User ID
The numeric ID of the given user on the system - this number is used internally by the system instead of the user name,
mostly because numbers occupy a fixed size in binary format (usually 2 or 4 bytes), and are much faster to handle, to
use as keys in search tables, etc.
User's Group ID
The numeric ID of a group this user belongs to. Every user belongs to at least one group on the system. Additional
groups may be specified for a user using the /etc/group file.
GECOS field
This field is a general-purpose field in which a comment about this user may be kept. This will often contain the name
of the account holder. Some systems use this to store the phone number, address and office room number of the
account holder. The contents of this field are never crucial for the account's proper operation (on a non-modified
system).
Home Directory
Full path to the home directory of this user. This will be used by the login program to place this user in this directory
when logged on, for example.
Shell.
The default shell this user will use. This shell is launched for the user when logging on to the system.
The "/etc/passwd" file is readable for all users on the system, but writable only to its owner - root. This means that users
cannot directly change the contents of this file - instead, there are specialized programs that allow a user to change her
password, default shell and GECOS field. See the manual page for the "passwd" command for more info on these programs.
The first API we will introduce is the function for fetching the "/etc/passwd" entry of a given user. There are two functions
for doing that - getpwnam() and getpwuid().
getpwnam is used to fetch a "/etc/passwd" record of a user, given his user name. The function will return a pointer to a
struct passwd, or NULL, if the user does not exist on the system. This structure is defined as follows:
struct passwd {
char *pw_name; /* user name */
char *pw_passwd; /* user password */
uid_t pw_uid; /* user id */
gid_t pw_gid; /* group id */
char *pw_gecos; /* real name */
char *pw_dir; /* home directory */
char *pw_shell; /* shell program */
};
Here is an example of using this function:
Just like we used the getpwnam() function, we may also use the getpwuid() function, supplying it the UID of the given
user. For example, we know that the "root" account always has the UID of '0', so doing the above can be done by:
One important note about these two functions: The structure they return is allocated in static memory. This means that the
same structure will be re-filled with new information after each call to the same function, erasing any data it returned in a
previous call. If you need to get info about two users and have it stored in memory, you should copy the structure returned
from the first call, and store it in a struct passwd you allocated (as a local variable, or using malloc()). Here is an
example:
The next API we will encounter is made of a set of functions that allow us to scan the full list of user accounts on our system.
A set of functions are used here: getpwent(), setpwent() and endpwent().
The getpwent() function will fetch, on first invocation, the struct passwd info of the first user account on the
system. On the next invocation it will fetch the info of the second user, and so on. After fetching the last user's info, if we call
getpwent() again, it will return NULL. Here is a sample of printing out the list of user names on our system:
Various types of programs need to authenticate users. This is often done by the user supplying a user name and a password,
and the program verifying that it has this user name and password combination in its list of users.
The login program on Unix systems works in a similar fashion, thought a little more secure. When a user logges on, she is
prompted for a user name and a password. The login program then uses this password as a key for encrypting some constant
text, using the crypt() function. This produces a string that is then compared to a string stored in the password field of the
user. If the strings match - the user is assumed to be authenticated, and is allowed to log in. The crypt() function performs
an algorithm known as DES (Data Encryption Standard). One property of this algorithm is that there is no way to find the
original password given the encrypted string that crypt() generates. This means that if a user got a copy of the
"/etc/passwd" file, they won't be able to calculate the original passwords of users using a simple algorithm (this does not
preclude using other methods to crack passwords...).
Lets see how one uses the crypt() function. It accepts two parameters. The first is the key (normally, the password to
encrypt) and the second is called "salt". This is a two-character string that is used to further alter the results of crypt. One
must make sure that the same salt is used when storing the password (actually the encrypted result of crypt()), and when
authenticating the user. The login program often uses the first two characters of the user name as the "salt" string. crypt()
returns an encrypted string when it returns, 13 characters long. Lets see a program that asks a user for their password, and
compares it to the password, as taken from the "/etc/passwd" file.
/* compare the results of crypt, with the user's stored password field. */
if (strcmp(user_info->pw_passwd, encrypted_password) != 0) {
printf("login incorrect.\n");
exit(1);
}
/* authentication succeeded... */
printf("login successful.\n");
The source code of this program is also available in the authenticate-user.c file. Note that on Linux systems based on the
GNU C library version 2 (glibc2), there is a need to link this program with the crypt library, by adding the option "-lcrypt" to
the compilation command.
Keeping the encrypted password of a user in the "/etc/passwd" file is considered insecure - even thought the encryption
algorithm cannot be reversed (i.e. given the encrypted password, there is no algorithm to find out the original password), a
user could copy out the "/etc/passwd" file of a system to their own system, and try running a password cracker that will in
turn try to guess passwords for all accounts. On most systems, and with most users, this will allow them to guess passwords
of a few accounts at least.
In order to reduce this risk, shadow passwords were invented. On a system that uses shadow passwords, the passwords of the
users are kept in a different file, that is only readable to its owner - root. the password entry in the "/etc/passwd" file (for each
user) will contain a special mark-up character, defining that the actual password is kept in the shadow file. This mark-up is
done differently on different operating systems, and the shadow file's path is also different for different systems. Thus,
although shadow passwords exist for at least a decade, there is no standard implementation for them.
When reading a user account's info (using getpwnam() for example), the password field in the returned structure will
contain the place-holder string, rather then the encrypted password. This makes it impossible to write simple programs that
authenticate users using their account's password. The solution to this problem is usually a specialized (non-standard)
function supplied by the operating system, to perform such authentication. Such a password will normally accept a user name
and an encrypted password, and will return '1' if this encrypted password matches that of the given user, or '0' if it does not.
This still allows people to write password crackers, but then they must be ran on the same system whose accounts they are
trying to break into, making it much easier to spot this activity and to block it (e.g. by disabling an account if too many
authentication attempts are made against it, in a given period of time).
The "/etc/group" file is a text file that contains a set of lines, each defining membership of a list of users in a given group.
Each group may be defined by one or more lines, and the users of this group include all the users defined in all these lines, as
well as the users having this group's GID (Group ID) in their "/etc/passwd" entries. Here is an example of a valid "/etc/group"
line:
bin::1:root,bin,daemon
This example shows some information about the "bin" group. This line is composed of a set of fields, separated by a colon
(':') character (like in the "/etc/passwd" file). The fields serve the following purposes:
Group Name
The name of the group this line defines.
Password
The password for this group. Normally empty, and implying that no password is required for the group.
Group ID.
The numeric ID of the given group.
Users List
A list of user names that belong to this group. The names are separating using comma (',') characters.
Thus, the above line states that the "bin" group has a GID of '1', and has users "root", "bin" and "daemon" as members.
Again, remember that there may be several lines for the group "bin" in this file, and they should all have the same GID. The
order of such lines is not important.
Finally, note that much like the "/etc/passwd" file, the "/etc/group" file is readable by anyone, and writable only by its owner
- root. However, unlike for the "/etc/passwd" file, there are no standard programs that allow changing the contents of the
"/etc/group" file.
The first API we will deal with is used to get the list of users belonging to a given group. This is done using the
getgrnam() or the getgrgid() functions.
The getgrnam() function gets a group name as its parameter, and returns a pointer to a struct group containing
information about the given group. The function will return NULL if the group does not exist on the system. The group
structure that is returned is defined as follows:
struct group {
char *gr_name; /* group name */
char *gr_passwd; /* group password */
gid_t gr_gid; /* group id */
char **gr_mem; /* group members */
};
Note that the gr_mem field is made of a list of user names, terminated by a NULL pointer. This group will contain all
members of the group - no matter if they are defined on several separate lines. However, users associated with the group only
via the GID field in their "/etc/passwd" entries (and not via proper lines in the "/etc/group" file) would NOT be included in
this list. This makes this function somewhat broken.
Here is an example of a code that prints out the list of members in the "strange" group:
The getgrgid() function works the same as getgrnam(), except that its parameter is the numeric GID of the desired
group. hopefully you would be able to write your own example of using this function.
One last note about the getgrnam() and getgrgid() functions is that just like the getpwnam() function, they return
pointers to statically allocated structures, and thus erase the results of the previous call on each consecutive call.
Similarly to the API used to enumerate user accounts, there are APIs used to enumerate "/etc/group" file entries. There are
getgrent(), setgrent() and endgrent(). they work in exactly the same way as their counter APIs for the
"/etc/group" file. Here is a quick example:
/* start the scan of the "/etc/group" file. */
struct group* group_info = getgrent();
As it was mentioned before, groups may be defined in two places: by using the GID field of a user's entry in the
"/etc/passwd" file, and by an entry in the "/etc/group" file. A group specified in the "/etc/group" file always has a group name,
while a group specified in the "/etc/passwd" file does not have a name (unless there is a group with the same GID defined in
the "/etc/group" file).
Another difference (already mentioned before) is that the getgr*() functions will show members specified in the
"/etc/group" file, but will not show members specified via the "/etc/group" file.
Finally, we will refer the user to the groups command. This command will print the names of all groups the currently
logged on user belongs to, or all groups a given user belongs to. This list of group will contain all relevant entries, whether
found in the "/etc/group" file, or in the "/etc/passwd" file. Read the manual page for the "groups" command for more
information.
Determining the UID of a process is done using the getuid() system call, and a set of its cousins that will be discussed
when we explain about Set UID programs below. This system call gets no parameters, and returns the effective UID of the
process. Here is an example that prints out the name of the user executing this process:
Sometimes our program might want to know which groups its process (or rather, it's process's user) is part of. For example,
consider a file manager that allows us to change the group owning a file. It will present us with a menu containing all groups
which we belong to. For this, the getgroups() system call may be used. This system call accepts two parameters: the
maximal number of groups IDs we want to receive, and an array into which the GIDs will be stored by the system call.
getgroups() returns the number of GIDs actually stored in the array. A special case is if we supply '0' in the first
parameter. In this case, the array is unmodified, and the return value is the total number of groups associated with the
process. Here is how we can receive all the groups in a single call:
If you remember, we mentioned earlier that the "/etc/passwd" file is only writable for "root". Yet, there is a program named
"passwd" that allows other users to change the contents of certain fields in this file. You might wonder how this is done. The
idea is rather simple. If you check out the permissions of the "passwd" program, you will see something like this (using 'ls -l
/usr/bin/passwd'):
struct utmp {
short ut_type; /* type of login */
pid_t ut_pid; /* pid of process */
char ut_line[UT_LINESIZE]; /* device name of tty - "/dev/" */
char ut_id[2]; /* init id or abbrev. ttyname */
time_t ut_time; /* login time */
char ut_user[UT_NAMESIZE]; /* user name */
char ut_host[UT_HOSTSIZE]; /* host name for remote login */
long ut_addr; /* IP addr of remote host */
};
This structure may be defined differently on different operating systems, but it will usually contain at least the user name and
the time of the login. For our purpose, the login name is all that matters. Here is a sample program that lists the names of the
currently logged in users:
printf("'%s',", user_name);
}
printf("\n");
close(fd);
The source code of this program is also available in the show-logged-users.c file.
● String fields (user name, host name) are terminated by a null character ('\0'), unless their contents are as large as the
field's size. In such a case, we must add the missing null character before treating the value as a string.
● The code showed here is buggy. just think what happens if in the middle of scanning the file a new user is logged in.
To avoid this, some file locking is necessary (e.g. using the fcntl). However, this should not be done for a long
period of time, or else no user will be able to log in (the login program will get blocked when it tries to update the utmp
file) - so try this only at home - not on a production system.
● The same user may have several records in the utmp file - one for each session the user currently has. If we wanted to
only show the user names, we should remove these duplicates.
● On some systems, there might be a non-standard API for reading from (and possibly writing to) the the utmp file. It is
better to use that API then to use this code, thought it will be even less portable.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
v1.0
Preface
This tutorial is the first in a series of "would-be" tutorials about graphical programming in the X window environment.
By itself, it is useless. A real X programmer usually uses a much higher level of abstraction, such as using Motif (or its
free version, lesstiff), GTK, QT and similar libraries. However, we need to start somewhere. More then this, knowing
how things work down below is never a bad idea.
After reading this tutorial, one would be able to write very simple graphical programs, but not programs with a descent
user interface. For such programs, one of the previously mentioned libraries would be used.
The Client And Server Model Of The X Window System
The X window system was developed with one major goal - flexibility. The idea was that the way things look is one
thing, but the way things work is another matter. Thus, the lower levels provide the tools required to draw windows,
handle user input, allow drawing graphics using colors (or black and white screens), etc. To this point, a decision was
made to separate the system into two parts. A client that decides what to do, and a server that actually draws on the
screen and reads user input in order to send it to the client for processing.
This model is the complete opposite of what one is used to when dealing with clients and servers. In our case, the user
seats near the machine controlled by the server, while the client might be running on a remote machine. The server
controls the screen, mouse and keyboard. A client may connect to the server, request that it draws a window (or several
windows), and ask the server to send it any input the user sends to these windows. Thus, several clients may connect to
a single X server - one might be running an email software, one running a WWW browser, etc. When input it sent by
the user to some window, the server sends a message to the client controlling this window for processing. The client
decides what to do with this input, and sends the server requests for drawing in the window.
The whole session is carried out using the X message protocol. This protocol was originally carried over the TCP/IP
protocol suite, allowing the client to run on any machine connected to the same network that the server is. Later on the
X servers were extended to allow clients running on the local machine more optimized access to the server (note that an
X protocol message may be several hundreds of KB in size), such as using shared memory, or using Unix domain
sockets (a method for creating a logical channel on a Unix system between two processes).
The X Display
The major notion of using Xlib is the X display. This is a structure representing the connection we have open with a
given X server. It hides a queue of messages coming from the server, and a queue of pending requests that our client
intends to send to the server. In Xlib, this structure is named 'Display'. When we open a connection to an X server, the
library returns a pointer to such a structure. Later, we supply this pointer to any Xlib function that should send
messages to the X server or receive messages from this server.
When we perform various drawing operations (graphics, text, etc), we may specify various options for controlling how
the data will be drawn - what foreground and background colors to use, how line edges will be connected, what font to
use when drawing some text, etc). In order to avoid the need to supply zillions of parameters to each drawing function,
a graphical context structure, of type 'GC' is used. We set the various drawing options in this structure, and then pass a
pointer to this structure to any drawing routines. This is rather handy, as we often needs to perform several drawing
requests with the same options. Thus, we would initialize a graphical context, set the desired options, and pass this GC
structure to all drawing functions.
Object Handles
When various objects are created for us by the X server - such as windows, drawing areas and cursors - the relevant
function returns a handle. This is some identifier for the object that actually resides in the X server's memory - not in
our application's memory. We can later manipulate this object by supplying this handle to various Xlib functions. The
server keeps a mapping between these handles and the actual objects it manages. Xlib provides various type definitions
for these objects (Window, Cursor, Colormap and so on), which are all eventually mapped to simple integers. We
should still use these type names when defining variables that hold handles - for portability reasons.
Various structure types are used in Xlib's interface. Some of them are allocated directly by the user. Others are
allocated using specific Xlib functions. This allows the library to initialize properly these structures. This is very handy,
since these structures tend to contain a lot of variables, making it rather tedious for the poor programmer to initialize.
Remember - Xlib tries to be as flexible as possible, and this means it is also as complex as it can get. Having default
values will enable a beginner X programmer to use the library, without interfering with the ability of a more
experienced programmer to tweak with these zillions of options.
As for freeing memory, this is done in one of two ways. In cases where we allocated the memory - we free it in the
same manner (i.e. use free() to free memory allocated using malloc()). In case we used some Xlib function to
allocate it, or we used some Xlib query method that returns dynamically allocated memory - we will use the XFree()
function to free this memory block.
Events
A structure of type 'XEvent' is used to pass events received from the X server. Xlib supports a large amount of event
types. The XEvent structure contains the type of event received, as well as the data associated with the event (e.g.
position on the screen where the event was generated, mouse button associated with the event, region of screen
associated with a 'redraw' event, etc). The way to read the event's data depends on the event type. Thus, an XEvent
structure contains a C language union of all possible event types (if you're not sure what C unions are, it is time to
check your proffered C language manual...). Thus, we could have an XExpose event, an XButton event, an XMotion
event, etc.
XCloseDisplay(display);
This would cause all windows created by the program (if any are left) to be automatically closed by the server, and any
resources stored on the server on behalf of the clients - to be freed. Note that this does not cause our client program to
terminate - we could use the normal exit() function to do that.
/* this variable will be used to store the ID of the root window of our */
/* screen. Each screen always has a root window that covers the whole */
/* screen, and always exists. */
Window root_window;
/* these variables will be used to store the IDs of the black and white */
/* colors of the given screen. More on this will be explained later. */
unsigned long white_pixel;
unsigned long black_pixel;
XMapWindow(win);
To see all the code we have gathered so far, take a look at the simple-window.c program. You'll see two more function
not explained so far - XFlush() and XSync(). The XFlush() function flushes all pending requests to the X server
- much like the fflush() function is used to flash standard output. The XSync() function also flushes all pending
requests to the X server, and then waits until the X server finishes processing these requests. In a normal program this
will not be necessary (you'll see why when we get to write a normal X program), but for now we put it there. Try
compiling the program either with or without these function calls to see the difference in its behavior.
Drawing In A Window
Drawing in a window can be done using various graphical functions - drawing pixels, lines, circles, rectangles, etc. In
order to draw in a window, we first need to define various general drawing parameters - what line width to use, which
color to draw with, etc. This is done using a graphical context (GC).
As we said, a graphical context defines several attributes to be used with the various drawing functions. For this, we
define a graphical context. We can use more then one graphical context with a single window, in order to draw in
multiple styles (different colors, different line widths, etc.). Allocating a new GC is done using the XCreateGC()
function, as follows (in this code fragment, we assume "display" is a pointer to a Display structure, and "win" is the ID
of a previously created window):
/* this variable will contain the handle to the returned graphics context. */
GC gc;
/* these variables are used to specify various attributes for the GC. */
/* initial values for the GC. */
XGCValues values = CapButt | JoinBevel;
/* which values in 'values' to check when creating the GC. */
unsigned long valuemask = GCCapStyle | GCJoinStyle;
After we have created a GC, we can draw on a window using this GC, with a set of Xlib functions, collectively called
"drawing primitives". Without much fuss, lets see how they are used. We assume that "gc" is a previously initialized
GC, and that 'win' contains the handle of a previously created window.
/* draw a pixel at position '5,60' (line 5, column 60) of the given window. */
XDrawPoint(display, win, gc, 5, 5);
/* draw a line between point '20,20' and point '40,100' of the window. */
XDrawLine(display, win, gc, 20, 20, 40, 100);
/* draw an arc whose center is at position 'x,y', its width (if it was a */
/* full ellipse) is 'w', and height is 'h'. Start the arc at angle 'angle1' */
/* (angle 0 is the hour '3' on a clock, and positive numbers go */
/* counter-clockwise. the angles are in units of 1/64 of a degree (so 360*64 */
/* is 360 degrees). */
int x = 30, y = 40;
int h = 15, w = 45;
int angle1 = 0, angle2 = 2.109;
XDrawArc(display, win, gc, x-(w/2), y-(h/2), w, h, angle1, angle2);
/* draw a filled rectangle of the same size as above, to the left of the */
/* previous rectangle. note that this rectangle is one pixel smaller then */
/* the previous line, since 'XFillRectangle()' assumes it is filling up */
/* an already drawn rectangle. This may be used to draw a rectangle using */
/* one color, and later to fill it using another color. */
XFillRectangle(display, win, gc, 60, 150, 50, 60);
Hopefully, you got the point by now. We will mention a few more functions that may be used in a similar fashion. For
example, XFillArc() takes the same parameters as XDrawArc(), but draws only the inside of this arc (like
XFillRectangle() does to a rectangle drawn using the XDrawRectangle() function). There is also an
XFillPolygon() function that fills the inside of a polygon. It takes almost the same parameters as
XDrawLines(). However, if the last point in the array has a different location then the first point in the array, the
XFillPolygon() function automatically adds another "virtual" lines, connecting these two points. Another
difference between the two functions, is that XFillPolygon() takes an additional parameters, shape, that is used to
help the X server optimize its operation. You can read about it in your manual pages. There are also plural versions for
these functions, namely XFillArcs() and XFillRectangles().
The source code for a program doing these drawings is found in the file simple-drawing.c.
X Events
In an Xlib program, everything is driven by events. Event painting on the screen is sometimes done as a response to an
event - an "expose" event. If part of a program's window that was hidden, gets exposed (e.g. the window was raised
above other windows), the X server will send an "expose" event to let the program know it should repaint that part of
the window. User input (key presses, mouse movement, etc.) is also received as a set of events.
After a program creates a window (or several windows), it should tell the X server what types of events it wishes to
receive for this window. By default, no events are sent to the program. It may register for various mouse (also called
"pointer") events, keyboard events, expose events and so on. This is done for optimizing the server-to-client connection
(i.e. why send a program (that might even be running at the other side of the globe) an event it is not interested in?).
In Xlib, we use the XSelectInput() function to register for events. This function accepts 3 parameters - the display
structure, an ID of a window, and a mask of the event types it wishes to get. The window ID parameter allows us to
register for receiving different types of events for different windows. Here is how we register for "expose" events for a
window whose ID is 'win':
After we have registered for the event types we are interested in, we need to enter a loop of receiving events and
handling them. There are various ways to write such a loop, but the basic loop looks like this:
The XNextEvent() function fetches the next event coming from the X server. If no event is waiting, it blocks until
one is received. When it returns, the event's data is placed in the XEvent variable given to the function as the second
parameter. After that, the "type" field of this variable specifies what type of event we got. Expose is the event type
that tells us there is a part of the window that needs to be redrawn. After we handle this event, we go back and wait for
the next event to process. Obviously, we will need to give the user some way of terminating the program. This is
usually done by handling a special "quit" event, as we'll soon see.
Expose Events
The "expose" event is one of the most basic events an application may receive. It will be sent to us in one of several
cases:
● A window that covered part of our window has moved away, exposing part (or all) of our window.
You should note the implicit assumption hidden here - the contents of our window is lost when it is being obscured
(covered) by other windows. One may wonder why the X server does not save this contents. The answer is - to save
memory. After all, the number of windows on a display at a given time may be very large, and storing the contents of
all of them might require a lot of memory (for instance, a 256 color bitmap covering 400 pixels by 400 pixels takes
160KB of memory to store. Now think about 20 windows, some much larger then this size). Actually, there is a way to
tell the X server to store the contents of a window in special cases, as we will see later.
When we get an "expose" event, we should take the event's data from the "xexpose" member of the XEvent structure
(in our code example we refer to it as "an_event.xexpose"). It contains several interesting fields:
count
Number of other expose events waiting in the server's events queue. This may be useful if we got several expose
events in a row - we will usually avoid redrawing the window until we get the last of them (i.e. until count is 0).
Window window
The ID of the window this expose event was sent for (in case our application registered for events on several
windows).
int x, y
The x and y coordinates (in pixels) from the top-left of the window, of the window's region that needs to be
redrawn.
int width, height
The width and height (in pixels) of the window's region that needs to be redraw.
In our demo programs, we will tend to ignore the region supplied, and simply re-draw all the window. However, this is
very inefficient, and we will try to demonstrate some techniques for drawing only the relevant section of screen later
on.
As an example, here is how we will draw a line across our window, whenever we receive "expose" events. Assume this
'case' is part of the event loop's switch command.
case Expose:
/* if we have several other expose events waiting, don't redraw. */
/* we will do the redrawing when we receive the last of them. */
if (an_event.xexpose.count > 0)
break;
/* ok, now draw the line... */
XDrawLine(display, win, gc, 0, 100, 400, 100);
break;
Getting User Input
User input traditionally comes from two sources - the mouse and the keyboard. Various event types exist to notify us of
user input - a key being pressed on the keyboard, a key being released on the keyboard, the mouse moving over our
window, the mouse entering (or leaving) our window and so on.
The first event type we'll deal with is a mouse button-press (or button release) event in our window. In order to register
to such an event type, we would add one (or more) of the following masks to the event types we specify for the
XSelectInput() function:
ButtonPressMask
Notify us of any button that was pressed in one of our windows.
ButtonReleaseMask
Notify us of any button that was released over one of our windows.
The event types to be checked for in our event-loop switch, are any of the following:
ButtonPress
A button was pressed over one of our windows.
ButtonRelease
A button was released over one of our windows.
The event structure for these event types is accessed as "an_event.xbutton", and contains the following interesting
fields:
Window window
The ID of the window this button event was sent for (in case our application registered for events on several
windows).
int x, y
The x and y coordinates (in pixels) from the top-left of the window, of the mouse pointer, during the click.
int button
The number of mouse button that was clicked. May be a value such as Button1, Button2, Button3.
Time time
time (in millisecond) the event took place in. May be used to calculate "double-click" situations by an application
(e.g. if the mouse button was clicked two times in a duration shorter then a given amount, assume this was a
double-click).
As an example, here is how we will draw a black pixel at the mouse position, whenever we receive "button press"
events, with the 1st mouse button, and erase that pixel (i.e. draw a white pixel) when the 2nd mouse button is pressed.
We assume the existence of two GCs, gc_draw with foreground color set to black, and gc_erase, with foreground color
set to white.
Assume that the following 'case' is part of the event loop's switch command.
case ButtonPress:
/* store the mouse button coordinates in 'int' variables. */
/* also store the ID of the window on which the mouse was */
/* pressed. */
x = an_event.xbutton.x;
y = an_event.xbutton.y;
the_win = an_event.xbutton.window;
/* check which mouse button was pressed, and act accordingly. */
switch (an_event.xbutton.button) {
case Button1:
/* draw a pixel at the mouse position. */
XDrawPoint(display, the_win, gc_draw, x, y);
break;
case Button2:
/* erase a pixel at the mouse position. */
XDrawPoint(display, the_win, gc_erase, x, y);
break;
default: /* probably 3rd button - just ignore this event. */
break;
}
break;
Similar to mouse button press and release events, we also can be notified of various mouse movement events. These
can be split into two families. One is of mouse pointer movement while no buttons are pressed, and the second is a
mouse pointer motion while one (or more) of the buttons are pressed (this is sometimes called "a mouse drag
operation", or just "dragging"). The following event masks may be added in the call to XSelectInput() for our
application to be notified of such events:
PointerMotionMask
Events of the pointer moving in one of the windows controlled by our application, while no mouse button is held
pressed.
ButtonMotionMask
Events of the pointer moving while one (or more) of the mouse buttons is held pressed.
Button1MotionMask
Same as ButtonMotionMask, but only when the 1st mouse button is held pressed.
Button2MotionMask, Button3MotionMask, Button4MotionMask, Button5MotionMask
Likewise, for 2nd mouse button, or 3rd, 4th or 5th.
The event types to be checked for in our event-loop switch, are any of the following:
MotionNotify
The mouse pointer moved in one of the windows for which we requested to be notified of such events.
The event structure for these event types is accessed as "an_event.xbutton", and contains the following interesting
fields:
Window window
The ID of the window this mouse motion event was sent for (in case our application registered for events on
several windows).
int x, y
The x and y coordinates (in pixels) from the top-left of the window, of the mouse pointer, when the event was
generated.
unsigned int state
A mask of the buttons (or keys) held down during this event - if any. This field is a bitwise OR of any of the
following:
❍ Button1Mask
❍ Button2Mask
❍Button3Mask
❍ Button4Mask
❍ Button5Mask
❍ ShiftMask
❍ LockMask
❍ ControlMask
❍ Mod1Mask
❍ Mod2Mask
❍ Mod3Mask
❍ Mod4Mask
❍ Mod5Mask
Their names are self explanatory, where the first 5 refer to mouse buttons that are being pressed, while the rest
refer to various "special keys" that are being pressed (Mod1 is usually the 'ALT' key or the 'META' key).
Time time
time (in millisecond) the event took place in.
As an example, the following code handles a "draw mode" for a painting program, that is, if the user moves the mouse
while the 1st mouse button is being held down, then we 'draw' on the screen. Note that this code has a flow: Since
mouse movement may generate many events, it might be that we won't get a mouse motion event for each pixel the
mouse moved over. Our program should be able to cope with such a situation. One way to do that would be to
remember the last pixel the mouse was dragged over, and draw a line between that position and the new mouse pointer
position. Assume that the following 'case' is part of the event loop's switch command.
case MotionNotify:
/* store the mouse button coordinates in 'int' variables. */
/* also store the ID of the window on which the mouse was */
/* pressed. */
x = an_event.xmotion.x;
y = an_event.xmotion.y;
the_win = an_event.xbutton.window;
/* if the 1st mouse button was held during this event, draw a pixel */
/* at the mouse pointer location. */
if (an_event.xmotion.state & Button1Mask) {
/* draw a pixel at the mouse position. */
XDrawPoint(display, the_win, gc_draw, x, y);
}
break;
Another type of event that applications might be interested at, is a mouse pointer entering a window the program
controls, or leaving such a window. Some programs use these events to show the user that the application is now in
focus. In order to register for such an event type, we would add one (or more) of the following masks to the event types
we specify for the XSelectInput() function:
EnterWindowMask
Notify us when the mouse pointer enters any of our controlled windows.
LeaveWindowMask
Notify us when the mouse pointer leaves any of our controlled windows.
The event types to be checked for in our event-loop switch, are any of the following:
EnterNotify
The mouse pointer just entered one of our controlled windows.
LeaveNotify
The mouse pointer just left one of our controlled windows.
The event structure for these event types is accessed as "an_event.xcrossing", and contains the following interesting
fields:
Window window
The ID of the window this button event was sent for (in case our application registered for events on several
windows).
Window subwindow
The ID of the child window from which the mouse entered our window (in an EnterNotify event), or into which
the mouse pointer has moved (in a LeaveNotify event), or None, if the mouse moved from outside our window.
int x, y
The x and y coordinates (in pixels) from the top-left of the window, of the mouse pointer, when the event was
generated.
int mode
The number of mouse button that was clicked. May be a value such as Button1, Button2, Button3.
Time time
time (in millisecond) the event took place in. May be used to calculate "double-click" situations by an application
(e.g. if the mouse button was clicked two times in a duration shorter then a given amount, assume this was a
double-click).
unsigned int state
A mask of the buttons (or keys) held down during this event - if any. This field is a bitwise OR of any of the
following:
❍ Button1Mask
❍ Button2Mask
❍ Button3Mask
❍ Button4Mask
❍ Button5Mask
❍ ShiftMask
❍ LockMask
❍ ControlMask
❍ Mod1Mask
❍ Mod2Mask
❍ Mod3Mask
❍ Mod4Mask
❍ Mod5Mask
Their names are self explanatory, where the first 5 refer to mouse buttons that are being pressed, while the rest
refer to various "special keys" that are being pressed (Mod1 is usually the 'ALT' key or the 'META' key).
Bool focus
Set to True if the window has the keyboard focus, False otherwise.
There may be many windows on a screen, but only a single keyboard attached to them. How does the X server then
know which window should be sent a given keyboard input? This is done using the keyboard focus. Only a single
window on the screen may have the keyboard focus at a given time. There are Xlib functions that allow a program to
set the keyboard focus to a given window. The user can usually set the keyboard focus using the window manager
(often by clicking on the title bar of the desired window). Once our window has the keyboard focus, every key press or
key release will cause an event to be sent to our program (if it registered for these event types...).
If a window controlled by our program currently holds the keyboard focus, it can receive key press and key release
events. In order to register for such events, any of the following masks may be added to the call to
XSelectInput():
KeyPressMask
Notify our program when a key was pressed while any of its controlled windows had the keyboard focus.
KeyPressMask
Notify our program when a key was released while any of its controlled windows had the keyboard focus.
The event types to be checked for in our event-loop switch, are any of the following:
KeyPress
A key was just pressed on the keyboard while any of our windows had the keyboard focus.
KeyRelease
A key was just released on the keyboard while any of our windows had the keyboard focus.
The event structure for these event types is accessed as "an_event.xkey", and contains the following interesting fields:
Window window
The ID of the window this button event was sent for (in case our application registered for events on several
windows).
unsigned int keycode
The code of the key that was pressed (or released). This is some internal X code, that should be translated into a
key symbol, as will be explained below.
int x, y
The x and y coordinates (in pixels) from the top-left of the window, of the mouse pointer, when the event was
generated.
Time time
time (in millisecond) the event took place in. May be used to calculate "double-click" situations by an application
(e.g. if the mouse button was clicked two times in a duration shorter then a given amount, assume this was a
double-click).
unsigned int state
A mask of the buttons (or modifier keys) held down during this event - if any. This field is a bitwise OR of any
of the following:
❍ Button1Mask
❍ Button2Mask
❍ Button3Mask
❍ Button4Mask
❍ Button5Mask
❍ ShiftMask
❍ LockMask
❍ ControlMask
❍ Mod1Mask
❍ Mod2Mask
❍ Mod3Mask
❍ Mod4Mask
❍ Mod5Mask
Their names are self explanatory, where the first 5 refer to mouse buttons that are being pressed, while the rest
refer to various "special keys" that are being pressed (Mod1 is usually the 'ALT' key or the 'META' key).
As we mentioned, the key code is rather meaningless on its own, and is affected by the specific keyboard device
attached to the machine running the X server. To actually use this code, we translate it into a key symbol, which is
standardized. We may use the XKeycodeToKeysym() function to do the translation. This function gets 3
parameters: a pointer to the display, the key code to be translated, and an index (we'll supply '0' for this parameter).
Standard Xlib key codes are found in the include file "X11/keysymdef.h". As an example for using the key press events
together with the XKeycodeToKeysym function, we'll show how to handle key presses of this sort: Pressing '1' will
cause painting the pixel where the mouse pointer is currently located. Pressing the DEL key will cause to erase that
pixel (using a 'gc_erase' GC). Pressing any of the letters (a to z, upper case or lower case) will cause it to be printed to
standard output. Any other key pressed will be ignored. Assume that the following 'case' is part of the event loop's
switch command.
case KeyPress:
/* store the mouse button coordinates in 'int' variables. */
/* also store the ID of the window on which the mouse was */
/* pressed. */
x = an_event.xkey.x;
y = an_event.xkey.y;
the_win = an_event.xkey.window;
{
/* translate the key code to a key symbol. */
KeySym key_symbol = XKeycodeToKeysym(display, an_event.xkey.keycode, 0);
switch (key_symbol) {
case XK_1:
case XK_KP_1: /* '1' key was pressed, either the normal '1', or */
/* the '1' on the keypad. draw the current pixel. */
XDrawPoint(display, the_win, gc_draw, x, y);
break;
case XK_Delete: /* DEL key was pressed, erase the current pixel. */
XDrawPoint(display, the_win, gc_erase, x, y);
break;
default: /* anything else - check if it is a letter key */
if (key_symbol >= XK_A && key_symbol <= XK_Z) {
int ascii_key = key_symbol - XK_A + 'A';
printf("Key pressed - '%c'\n", ascii_key);
}
if (key_symbol >= XK_a && key_symbol <= XK_z) {
int ascii_key = key_symbol - XK_a + 'a';
printf("Key pressed - '%c'\n", ascii_key);
}
break;
}
}
break;
As you can see, key symbols refer to the physical key on the keyboard in some manner, so one should be careful to
properly check all possible cases (as we did for the '1' key in the above example). We also assume that the letter keys
have consecutive key symbol values, or else the range checking tricks and the key symbol to ASCII code translations
wouldn't have worked.
X Events - A Complete Example
As an example for handling events, we will show the events.c program. This program creates a window, makes some
drawings on it, and then enters an event loop. If it gets an expose event - it redraws the whole window. If it gets a left
button press (or motion) event, it draws the pixel under the mouse pointer in black color. If it gets a middle button press
(or motion) event, it draws the pixel under the mouse pointer in white color (i.e. erases this pixel). Some note should be
taken as to how these picture changes are handled. It is not sufficient to just draw the pixel with the appropriate color.
We need to make a note of this color change, so on the next expose event we will draw the pixel again with the proper
color. For this purpose, we use a huge (1000 by 1000) array representing the window's pixels. Initially, all cells in the
array are initialized to '0'. When drawing a pixel in black, we set the matching array cell to '1'. When drawing a pixel in
white, we set the matching array cell to '-1'. we cannot just reset it back to '0', otherwise the original drawing we
painted on the screen will always be erased. Finally, when the user presses on any on the keyboard, the program exits.
When running this program, you will note that motion events often skip pixels. If the mouse was moved from one point
to another in a quick motion, we will not get motion events for each pixel the mouse pointer moved over. Thus, if it
was our intention to handle these gaps properly, we would need to remember the location of the last motion event, and
then perhaps draw a line between that location and the location of the next motion event. This is what painting
programs normally do.
In order to support flexible fonts, a font structure is defined, of type XFontStruct. This structure is used to contain
information about a font, and is passed to several functions that handle fonts selection and text drawing.
Loading A Font
As a first step to draw text, we use a font loading function, such as XLoadQueryFont(). This function asks the X
server to load data that defines a font with a given name. If the font is found, it is loaded by the server, and an
XFontStruct pointer is returned. If the font is not found, or the loading operation fails, a NULL value is returned.
Each font may have two names. One is a long string, that specifies the full properties of the font (font family, font size,
italic/bold/underline attributes, etc.). The other is a short nickname for the font, configured for the specific X server. As
an example, we will try to load a "*-helvetica-*-12-*" font (the '*' characters work the same as wildcard characters in a
shell):
After we load the font, we need to assign it to a GC. assuming that 'gc' is a variable of type GC that's already initialized,
here is how this is done:
Once we got our wanted font loaded and assigned to our GC, we can draw text in our window, using a function such as
XDrawString(). This function will draw a given text string at a given location on the window. The location would
be that of the lower-left corner of the drawn text string. Here is how it is used:
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Processes
A process is an entity that executes a computer program, and manipulates all other resources in
order to fulfill the mission of the program. Several (or many) processes may be running on the
same computer, or on different computers. Usually a single process is running on a single
computer. Also, usually each process has its own address space, as well as a few other private
resources (an private execution stack, for example).
Note - what we call here 'process' is a broader entity then what you might know as a Unix
process. We should have actually called it a 'runnable', and in practice it could be a Unix
process, a Unix thread and so on.
Resources
A resource is an entity that can be used by a process to perform some specific operation. There
could be physical resources, as well as logical (or virtual) resources.
A physical resource could be, for example, a disk, which is used for saving files. Or a keyboard,
which is used to read data from the user.
A logical resource could be a shared memory area, which several processes may access in order
to read data to, or read data from.
Executers
An executer is a special resource that is used to execute a process. Usually, this is a CPU, so
we'll use the term CPU from now on. Note that not all CPUs are equal - some are
general-purpose, and might carry out the program as a whole. Others are specialized for
different tasks - a CPU that only does mathematical floating point operations; A CPU that only
handles graphical operations (commonly found on graphical screen cards, and serving as a
graphic accelerator) and so on.
Schedulers
A scheduler is an entity specifying when processes will run, on which CPUs (executors) they
will run, and in what order. Such a scheduler may be controlling a single computer, or several
computers (see clustering below).
Synchronizers
A synchronizer is an entity used to control the access of processes to resources. Some
synchronizers are used to make sure only a single process uses a given resource at any one time.
Other synchronizers are used to make sure a given resource is accessed in a given order of
priority by different processes. There is a host of other types of synchronizers to be dealt with.
You will most likely bump into synchronizers such as Mutexes, Semaphores, Monitors,
Conditions, etc.
Process Scheduling
Process Preemption
An event of the system suspending the execution of a process that is in the middle of
putting the CPU to good use, in order to let other processes run. This makes sure no
single process will take over the full CPU, even if it gets into an infinite loop and does
not make any blocking system calls.
Context Switch
The method by which the operating system makes one CPU suspend the execution of on
process, and continue executing a second process. This is called a context switch since
the CPU needs to switch to using the full context of the second process - its execution
stack, its memory area, the values the registers contained when last executing this
process, etc. A context switch may occure when the running process blocks waiting for
some resource to become free, when it yields the CPU voluntarily, or when it is being
preempted by the operating system's scheduler. (mantra - you talk to your mom on the
phone, while trying to watch a very interesting T.V. program - you switch your attention
between you T.V. and your mom constantly, always taking a short while to remember
where you were before the last switch).
Round-Robin Scheduling
A scheduling algorithm in which several processes are being executed by an executed
one after the other in turn, each getting the same amount of time to run. After this time
slice passes, a context-switch is made, where the first process on the list gets to run next,
while the suspended process is being put back at the end of the list. (mantra - when the
ideal teacher in class makes sure every pupil gets a chance to speak in turn - well, as if
that ideal teacher exists...).
Prioritized Scheduling
A scheduling algorithm in which a priority is assigned to each process, and when several
processes are waiting for the CPU to get executed, the one with highest priority is being
run, usually until it gets blocked waiting for some resource, or until a process with a
higher priority wakes up and demands CPU time. (mantra - on a T.V. debate, some
people are given higher priority then others, and interrupt everybody else when they have
something to say. On Israeli T.V. - see under 'Popolitica').
Load Balancing
A method by which several tasks are scheduled for separate CPUs or computers, based
on the current load on each CPU. Sometimes this includes the ability to migrate processes
from one CPU (or computer) to another during its execution.
Commands Pipelining
A process in which commands are broken into several smaller steps, that may be
executed in sequence using different components of the CPU, meanwhile allowing others
components of the CPU to start executing the next command in parallel. For example,
suppose that we have a CPU component that can read data from memory, and another
that can do mathematical calculations. If we have two consecutive addition commands
that don't affect each other (i.e. working on un-related parameters), the CPU could first
load the data for the first command using its I/O component, and then while the
mathematical component calculates the sum of the data, the I/O component can start
fetching the data for the next command in parallel, making overall execution faster.
(mantra - when you wake up very late, and find you are very late for school, you start
wearing your shirt, and while slipping it on your body with one hand, the other hand
rushes to pick up a new pair of socks from the drawer, and so on).
Multi Processes
This time we use the term process to denote an operating system process. All Unix systems, as
well as many other operating systems, are multi-process systems. In most of these systems, each
process is given its own address space, and they all share the same CPU in turn. The scheduling
algorithm might be a simple round-robin algorithm, or one that takes priorities into account
(priorities are mostly needed for real-time programs, that must be granted some limits on how
long it'll take since an event they need arrives, until they are allowed to execute it).
A system similar to the multi-process system, except that here a process may be divided into
several threads. All threads share the same data area, and are being scheduled in a similar way
to how processes are scheduled. Due to the sharing of data area (and few other resources), a
context-switch between two threads of the same process is faster then a context switch between
two processes. Also, passing data between threads is easier then between two processes, due to
the shared address space. On the other hand, protection of threads from one another is weaker
then that given to processes - if one thread corrupts its memory area, all other threads in its
process may be directly affected. Threads supported by the kernel are sometimes called
'Light-Weight Processes' (LWP).
Similar to the kernel-based threads, except that the operating system's kernel is not aware of
these threads - they are created and handled by a library. The advantage is that
"context-switching" between them is faster - it does not involve any system call (with the
overhead of switching into kernel mode). On the other hand, if one thread gets blocked by the
operating system when invoking some system call (e.g. sleep(), or waiting for input from a
network device), the whole process gets suspended, including all its threads. Thus a
multi-threaded library implementation is suitable for calculation-intensive applications, not for
I/O intensive applications.
Implementations In Hardware
Implementations of parallel systems often involve using extra hardware - several CPUs that can
execute different processes in parallel being the most notable hardware addition.
This method is used to contain several CPUs in a single computer, each of which has access to
the same set of memory chips, and each working as a general-purpose CPU, that can execute
any process in the system. The operating system is responsible for assigning newly created
processes to specific processes, using some load-balancing algorithm. Sometimes these systems
also handle moving a process from one CPU to another, that just became free.
In the past it was a simple task (after the current CPU finished executing one command, simple
copy its registers contents into another CPU, and set it to continue execution from the same
position). However, these days a CPU executes several commands of a process simultaneously,
using pipelining techniques, and also contains an internal cache containing some data and
commands, making such a process migration harder to implement, and more wasteful (all the
partially-completed commands in the pipeline have to be flashed, the cache of the second CPU
has to be reloaded, etc).
SMP systems exist now on many platforms, including PCs running with Intel and Intel-clone
CPUs, Sun SPARC stations, using Ultra-SPARC CPUs (or older SPARC-10 and SPARC-20
CPUs), IBM RS/6000 systems using several PowerPC CPUs, and so on. Support for SMP
systems is built into many operating systems running on these types of hardware, usually
different by the amount of CPUs supported, as well as various internal implementation
parameters.
This is a different concept of having a parallel system with several CPUs. sometimes this
system uses specialized processes to do different tasks, sometimes the access to just access to
different memory parts is done in an asymmetric way (i.e. every CPU (or group of CPUs) have
its own memory part, and thus memory is not shared between CPUs). An example of such a
system is Silicon Graphic's Origin 2000 system. CC-NUMA systems are usually harder to
implement then SMP systems (and thus more expensive), and thus normally not found in
low-end or mid-sized systems.
Clustering
Clustering is a technique used to make several computers act as one larger machine, splitting
tasks amongst them. They allow one to take several cheap stations, and combine them together
to a larger system. It also allows for more redundancy for the system - if one machine in the
cluster dies off, the other machines can cover up for it until the malfunctioning machine is
repaired, and all this without bringing the whole system down. This type of setup is thus
common in systems that must run 24 hours non-stop.
Clustering is often implemented in software, often using a protocol named PVM to
communicate between the different machines. Examples fir such systems are Beowulf, for
Linux systems, or the clustering system by Tandem corporation.
Remote Procedure Calls (RPC) are a method originally developed by Sun microsystems©,
allows one process to activate a procedure in a second process, passing it parameters, and
optionally getting a result back from the call.
The set of procedures supported by a process are defined in a file using notation called 'RPC
Language', and is pre-processed by a tool named 'rpcgen', which creates two groups of files
forming two 'stubs'. One stub defines functions whose invocation will cause a message to be
sent to the remote process, with a request to invoke a certain procedure. This function is
invoked by the first (client) process, and returns when we get a reply from the second (server)
process, with the value it returned. The second stub contains declarations of functions that need
to be implemented by the second (server) process, in order to actually implement the
procedures.
During the years, new RPC variants were created, most notably 'DCE RPC', which is part of the
'Distributed Computing Environment', now being maintained by the open group.
CORBA (Common Object Request Broker Architecture) was started up as an attempt of few
hundreds of companies to define a standard that allows clients to invoke methods on specific
objects running in remote servers.
This framework defines a language-neutral protocol to allow processes to communicate even if
they are written in different programming languages, or running on different operating systems.
A declarative language, named IDL (Interface Definition Language) was defined to allow
specifying language-neutral interfaces. Each interface has a name, and contains a set of methods
and attributes. The interface is then pre-processed by some tool, and generates client and server
stubs, similarly to how it is done with 'rpcgen' for RPC. An entity named 'ORB' (Object Request
Broker) is then used to allow these clients and servers to communicate.
Above this basic interface, a set of standard services were defined, that supply features that are
commonly required: A naming service, to allow client processes to locate remote objects by
name, An event service, to allow different objects to register for events sent by other objects,
and so on. These services are collectively known as 'Horizontal CORBA Services'.
Yet other services are being defined for different areas of computing, for instance, services to
be used by medical applications. These are called 'vertical services'.
For more information about CORBA, please refer to the Object Management Group's web site.
You may also check the free CORBA page to locate and download various 'free'
implementations of CORBA.
I might annoy some of the readers here, but although we are dealing here with Unix
programming, we cannot ignore what appears to be the currently more developed distributed
objects framework, DCOM (Distributed Component Object Model). DCOM gives us rather
similar services to what CORBA does, and people usually argue that their range of services is
smaller then what CORBA provides. However, DCOM served as the foundation for the
ActiveX set of interfaces, that are used to allow one windows application to activate another
one and fully control it. This is most commonly used to allow one application to embed an
object created by another application, and allow the user to manipulate the embedded object by
invoking the second application when required. Of-course, the ActiveX interface allows much
more then that.
There are several reasons why DCOM is important also for Unix programmers:
1. In many cases, one needs to be able to make Unix and Windows programs communicate.
For that reason, a standard for a CORBA to DCOM interface has been defined by the
OMG, and you, as a Unix programmer, might find yourself in a need to interface with
such programs.
2. There are various ideas that exist in DCOM, that are worthy of looking at, and
implementing on top of native Unix frameworks (such as CORBA). The rule here is -
"don't throw out the baby with the bath water".
3. The Win32 API system is being ported to the Unix environment by several companies,
and COM (the non-distributed version of DCOM) is already available for various Unix
platforms. DCOM is also being ported to these platforms. When this is done, Unix
programmers will be able to employ DCOM without the need to use a Microsoft©
operating system.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
v1.01
Process Creation
As you might (hopefully) already know, it is possible for a user to run a process in the system, suspend it (Ctrl-Z), and
move it to the background (using the 'bg' command). If you're not familiar with this, you would do best to read the 'Job
Control' section of the 'csh' manual page (or of 'bash', if that is the shell you normally use). However, we are interested
in learning how to create new processes from within a C program.
The fork() system call is the basic way to create a new process. It is also a very unique system call, since it returns
twice(!) to the caller. Sounds confusing? good. This confusion stems from the attempt to define as few systems calls as
possible, it seems. OK, lets see:
fork()
This system call causes the current process to be split into two processes - a parent process, and a child process.
All of the memory pages used by the original process get duplicated during the fork() call, so both parent and
child process see the exact same image. The only distinction is when the call returns. When it returns in the
parent process, its return value is the process ID (PID) of the child process. When it returns inside the child
process, its return value is '0'. If for some reason this call failed (not enough memory, too many processes, etc.),
no new process is created, and the return value of the call is '-1'. In case the process was created successfully,
both child process and parent process continue from the same place in the code where the fork() call was
used.
To make things clearer, lets see an example of a code that uses this system call to create a child process that prints (you
guessed it) "hello world" to the screen, and exits.
/* storage place for the pid of the child process, and its exit status. */
pid_t child_pid;
int child_status;
/* lets fork off a child process... */
child_pid = fork();
Notes:
● The perror() function prints an error message based on the value of the errno variable, to stderr.
● The wait() system call waits until any child process exits, and stores its exit status in the variable supplied.
There are a set of macros to check this status, that will be explained in the next section.
Note: fork() copies also a memory area known as the 'U Area' (or User Area). This area contains, amongst other
things, the file descriptor table of the process. This means that after returning from the fork() call, the child process
inherits all files that were open in the parent process. If one of them reads from such an open file, the read/write
pointer is advanced for both of them. On the other hand, files opened after the call to fork() are not shared by both
processes. Further more, if one process closes a shared file, it is still kept open in the other process.
The simple way of a process to acknowledge the death of a child process is by using the wait() system call. As we
mentioned earlier, When wait() is called, the process is suspended until one of its child processes exits, and then the
call return with the exit status of the child process. If it has a zombie child process, the call returns immediately, with
the exit status of that process.
The problem with calling wait() directly, is that usually you want the parent process to do other things, while its
child process executes its code. Otherwise, you're not really enjoying multi-processes, do you? That problem has a
solution by using signals. When a child process dies, a signal, SIGCHLD (or SIGCLD) is sent to its parent process.
Thus, using a proper signal handler, the parent will get an asynchronous notification, and then when it'll call wait(),
the system assures that the call will return immediately, since there is already a zombie child. Here is an example of our
"hello world" program, using a signal handler this time.
wait(&child_status);
printf("child exited.\n");
}
.
.
/* and somewhere in the main() function ... */
.
.
child_pid = fork();
switch (child_pid) {
case -1: /* fork() failed */
perror("fork");
exit(1);
case 0: /* inside child process */
printf("hello world\n");
sleep(5); /* sleep a little, so we'll have */
/* time to see what is going on */
exit(0);
default: /* inside parent process */
break;
}
/* parent process goes on, minding its own business... */
/* for example, some output... */
for (i=0; i<10; i++) {
printf("%d\n", i);
sleep(1); /* sleep for a second, so we'll have time to see the mix */
}
}
What Is A Pipe?
One of the mechanisms that allow related-processes to communicate is the pipe, or the anonymous pipe. A pipe is a
one-way mechanism that allows two related processes (i.e. one is an ancestor of the other) to send a byte stream from
one of them to the other one. Naturally, to use such a channel properly, one needs to form some kind of protocol in
which data is sent over the pipe. Also, if we want a two-way communication, we'll need two pipes, and a lot of
caution...
The system assures us of one thing: The order in which data is written to the pipe, is the same order as that in which
data is read from the pipe. The system also assures that data won't get lost in the middle, unless one of the processes
(the sender or the receiver) exits prematurely.
This system call is used to create a read-write pipe that may later be used to communicate with a process we'll fork off.
The call takes as an argument an array of 2 integers that will be used to save the two file descriptors used to access the
pipe. The first to read from the pipe, and the second to write to the pipe. Here is how to use this function:
If the call to pipe() succeeded, a pipe will be created, pipes[0] will contain the number of its read file descriptor, and
pipes[1] will contain the number of its write file descriptor.
Now that a pipe was created, it should be put to some real use. To do this, we first call fork() to create a child
process, and then use the fact that the memory image of the child process is identical to the memory image of the parent
process, so the pipes[] array is still defined the same way in both of them, and thus they both have the file descriptors of
the pipe. Further more, since the file descriptor table is also copied during the fork, the file descriptors are still valid
inside the child process.
Lets see an example of a two-process system in which one (the parent process) reads input from the user, and sends it
to the other (the child), which then prints the data to the screen. The sending of the data is done using the pipe, and the
protocol simply states that every byte passed via the pipe represents a single character typed by the user.
/* now enter a loop of reading data from the pipe, and printing it */
while ((rc = read(data_pipe[0], &c, 1)) > 0) {
putchar(c);
}
/* now enter a loop of read user input, and writing it to the pipe. */
while ((c = getchar()) > 0) {
/* write the character to the pipe. */
rc = write(data_pipe[1], &c, 1);
if (rc == -1) { /* write failed - notify the user and exit */
perror("Parent: write");
close(data_pipe[1]);
exit(1);
}
}
/* now fork off a child process, and set their handling routines. */
pid = fork();
switch (pid) {
case -1: /* fork failed. */
perror("fork");
exit(1);
case 0: /* inside child process. */
do_child(data_pipe);
/* NOT REACHED */
default: /* inside parent process. */
do_parent(data_pipe);
/* NOT REACHED */
}
As we can see, the child process closed the write-end of the pipe (since it only needs to read from the pipe), while the
parent process closed the read-end of the pipe (since it only needs to write to the pipe). This closing of the un-needed
file descriptor was done to free up a file descriptor entry from the file descriptors table of the process. It isn't necessary
in a small program such as this, but since the file descriptors table is limited in size, we shouldn't waste unnecessary
entries.
The complete source code for this example may be found in the file one-way-pipe.c.
In a more complex system, we'll soon discover that this one-way communications is too limiting. Thus, we'd want to be
able to communication in both directions - from parent to child, and from child to parent. The good news is that all we
need to do is open two pipes - one to be used in each direction. The bad news, however, is that using two pipes might
cause us to get into a situation known as 'deadlock':
Deadlock
A situation in which a group of two or more processes are all waiting for a set of resources that are currently
taken by other processes in the same group, or waiting for events that are supposed to be sent from other
processes in the group.
Such a situation might occur when two processes communicate via two pipes. Here are two scenarios that could led to
such a deadlock:
1. Both pipes are empty, and both processes are trying to read from their input pipes. Each one is blocked on the
read (cause the pipe is empty), and thus they'll remain stuck like this forever.
2. This one is more complicated. Each pipe has a buffer of limited size associated with it. When a process writes to
a pipe, the data is placed on the buffer of that pipe, until it is read by the reading process. If the buffer is full, the
write() system call gets blocked until the buffer has some free space. The only way to free space on the
buffer, is by reading data from the pipe.
Thus, if both processes write data, each to its 'writing' pipe, until the buffers are filled up, both processes will get
blocked on the write() system call. Since no other process is reading from any of the pipes, our two processes
have just entered a deadlock.
Lets see an example of a (hopefully) deadlock-free program in which one process reads input from the user, writes it to
the other process via a pipe. the second process translates each upper-case letter to a lower-case letter and sends the
data back to the first process. Finally, the first process writes the data to standard output.
/* loop: read input, send via one pipe, read via other */
/* pipe, and write to stdout. exit on EOF from user. */
while ((c = getchar()) > 0) {
/* write to translator */
rc = write(output_pipe[1], &c, 1);
if (rc == -1) { /* write failed - notify the user and exit. */
perror("user_handler: write");
close(input_pipe[0]);
close(output_pipe[1]);
exit(1);
}
/* read back from translator */
rc = read(input_pipe[0], &c, 1);
if (rc <= 0) { /* read failed - notify user and exit. */
perror("user_handler: read");
close(input_pipe[0]);
close(output_pipe[1]);
exit(1);
}
/* print translated character to stdout. */
putchar(c);
}
/* now fork off a child process, and set their handling routines. */
pid = fork();
switch (pid) {
case -1: /* fork failed. */
perror("main: fork");
exit(1);
case 0: /* inside child process. */
translator(user_to_translator, translator_to_user); /* line 'A' */
/* NOT REACHED */
default: /* inside parent process. */
user_handler(translator_to_user, user_to_translator); /* line 'B' */
/* NOT REACHED */
}
A few notes:
1. Character handling: isascii() is a function that checks if the given character code is a valid ASCII code.
isupper() is a function that checks if a given character is an upper-case letter. tolower() is a function that
translates an upper-case letter to its equivalent lower-case letter.
2. Note that both functions get an input_pipe and an output_pipe array. However, when calling the functions we
must make sure that the array we give one as its input pipe - we give the other as its output pipe, and vice versa.
Failing to do that, the user_handler function will write a character to one pipe, and then both functions will try to
read from the other pipe, thus causing both of them to block, as this other pipe is still empty.
3. Try to think: what will happen if we change the call in line 'A' above to:
Named Pipes
One limitation of anonymous pipes is that only processes 'related' to the process that created the pipe (i.e. siblings of
that process.) may communicate using them. If we want two un-related processes to communicate via pipes, we need to
use named pipes.
A named pipe (also called a named FIFO, or just FIFO) is a pipe whose access point is a file kept on the file system. By
opening this file for reading, a process gets access to the reading end of the pipe. By opening the file for writing, the
process gets access to the writing end of the pipe. If a process opens the file for reading, it is blocked until another
process opens the file for writing. The same goes the other way around.
A named pipe may be created either via the 'mknod' (or its newer replacement, 'mkfifo'), or via the mknod() system
call (or by the POSIX-compliant mkfifo() function). To create a named pipe with the file named 'prog_pipe', we can
use the following command:
mknod prog_pipe p
We could also provide a full path to where we want the named pipe created. If we then type 'ls -l prog_pipe', we will
see something like this:
The 'p' on the first column denotes this is a named pipe. Just like any file in the system, it has access permissions, that
define which users may open the named pipe, and whether for reading, writing or both.
Opening a named pipe is done just like opening any other file in the system, using the open() system call, or using
the fopen() standard C function. If the call succeeds, we get a file descriptor (in the case of open(), or a 'FILE'
pointer (in the case of fopen()), which we may use either for reading or for writing, depending on the parameters
passed to open() or to fopen().
Reading from a named pipe is very similar to reading from a file, and the same goes for writing to a named pipe. Yet
there are several differences:
1. Either Read Or Write - a named pipe cannot be opened for both reading and writing. The process opening it must
choose one mode, and stick to it until it closes the pipe.
2. Read/Write Are Blocking - when a process reads from a named pipe that has no data in it, the reading process is
blocked. It does not receive an end of file (EOF) value, like when reading from a file. When a process tries to
write to a named pipe that has no reader (e.g. the reader process has just closed the named pipe), the writing
process gets blocked, until a second process re-opens the named pipe.
Thus, when writing a program that uses a named pipe, we must take these limitations into account. We could also turn
the file descriptor via which we access the named pipe to a non-blocking mode. This, however, is out of the scope of
our tutorial. For info about how to do that, and how to handle a non-blocking pipe, please refer to the manual pages of
'open(2)', fcntl(2), read(2) and write(2).
As an example to an obscure usage of named pipes, we will borrow some idea from a program that allows one to count
how many times they have been "fingered" lately. As you might know, on many Unix systems, there is a finger
daemon, that accepts requests from users running the "finger" program, with a possible user name, and tells them when
this user last logged on, as well as some other information. Amongst other thing, the finger daemon also checks if the
user has a file named '.plan' (that is dot followed by "plan") in her home directory. If there is such a file, the finger
daemon opens it, and prints its contents to the client. For example, on my Linux machine, fingering my account might
show something like:
[choo@simey1 ~]$ finger choo
Login: choo Name: guy keren
Directory: /home/choo Shell: /bin/tcsh
On since Fri Nov 6 15:46 (IDT) on tty6
No mail.
Plan:
- Breed a new type of dogs.
- Water the plants during all seasons.
- Finish the next tutorial on time.
As you can see, the contents of the '.plan' file has been printed out.
This feature of the finger daemon may be used to create a program that tells the client how many times i was fingered.
For that to work, we first create a named pipe, where the '.plan' file resides:
mknod /home/choo/.plan p
If i now try to finger myself, the output will stop before showing the 'plan' file. How so? this is because of the blocking
nature of a named pipe. When the finger daemon opens my '.plan' file, there is no write process, and thus the finger
daemon blocks. Thus, don't run this on a system where you expect other users to finger you often.
The second part of the trick, is compiling the named-pipe-plan.c program, and running it. note that it contains the full
path to the '.plan' file, so change that to the appropriate value for your account, before compiling it. When you run the
program, it gets into an endless loop of opening the named pipe in writing mode, write a message to the named pipe,
close it, and sleep for a second. Look at the program's source code for more information. A sample of its output looks
like this:
When you're done playing, stop the program, and don't forget to remove the named pipe from the file system.
System V IPC
Many variants of Unix these days support a set of inter-process communications methods, which are derived from Unix
System V release 4, originating from AT&T Bell laboratories. These mechanisms include message queues (used for
sending and receiving messages), shared memory (used to allow several processes share data in memory) and
semaphores (used to co-ordinate access by several processes, to other resources). Each of these resource types is
handled by the system, and unlike anonymous pipes, may out-live the process that created it. These resources also have
some security support by the system, that allows one to specify which processes may access a given message queue, for
example.
The fact that these resources are global to the system has two contradicting implications. On one hand, it means that if a
process exits, the data it sent through a message queue, or placed in shared memory is still there, and can be collected
by other processes. On the other hand, this also means that the programmer has to take care of freeing these resources,
or they occupy system resources until the next reboot, or until being removed by hand.
I am going to make a statement here about these communications mechanisms, that might annoy some readers: System
V IPC mechanisms are evil regarding their implementation, and should not be used unless there is a very good reason.
One of the problem with these mechanism, is that one cannot use the select() (or its replacement, poll()) with
them, and thus a process waiting for a message to be placed in a message queue, cannot be notified about messages
coming via other resources (e.g. other message queues, pipes or sockets). In my opinion, this limitation is an oversight
by the designers of these mechanisms. Had they used file descriptors to denote IPC resources (like they are used for
pipes, sockets and files) life would be easier.
Another problem with System V IPC is their system-global nature. The total number of message queues that may live
in the system, for example, is shared by all processes. Worse then that, the number of messages waiting in all messages
queues is also limited globally. One process spewing many such messages will break all processes using message
queues. The same goes for other such resources. There are various other limitations imposed by API (Application
programming interface). For example, one may wait on a limited set of semaphores at the same time. If you want more
then this, you have to split the waiting task, or re-design your application.
Having said that, there are still various applications where using system V IPC (we'll call it SysV IPC, for short) will
save you a large amount of time. In these cases, you should go ahead and use these mechanism - just handle with care.
Permission Issues
Before delving into the usage of the different System V IPC mechanisms, we will describe the security model used to
limit access to these resources.
Each resource in SysV IPC may be either private or public. Private means that it may be accessed only by the process
that created it, or by child processes of this process. Public means that it may be potentially accessed by any process in
the system, except when access permission modes state otherwise.
SysV IPC resources may be protected using access mode permissions, much like files and directories are protected by
the Unix system. Each such resource has an owning user and an owning group. Permission modes define if and how
processes belonging to different users in the system may access this resource. Permissions may be set separately for the
owning user, for users from the owning group, and everyone else. permissions may be set for reading the resource (e.g.
reading messages from a message queue), or writing to the resource (e.g. sending a message on a queue, changing the
value of a semaphore). A structure of type 'ipc_perm', which is defined as follows:
struct ipc_perm
{
key_t key; /* key identifying the resource */
ushort uid; /* owner effective user ID and effective group ID */
ushort gid;
ushort cuid; /* creator effective user ID and effective group ID */
ushort cgid;
ushort mode; /* access modes */
ushort seq; /* sequence number */
};
These fields have the following meanings:
● key - the identifier of the resource this structure refers to.
● mode - access permission modes for the given resource. This is a bit field, with the lowest 9 bits denoting access
flags, and are a bit-wise 'or' of the following (octal) values:
❍ 0400 - owning user may read from this resource.
● seq - used to keep system-internal info about the resource. for further info, check your kernel's sources (you are
working on a system with free access to its source code, right?).
Part of the SysV IPC API allows us to modify the access permissions for the resources. We will encounter them when
discussing the different IPC methods.
Since SysV IPC resources live outside the scope of a single process, there is a need to manage them somehow - delete
resources that were left by irresponsible processes (or process crashes); check the number of existing resources of each
type (especially to find if the system-global limit was reached), etc. Two utilities were created for handling these jobs:
'ipcs' - to check usage of SysV IPC resources, and 'ipcrm' - to remove such resources.
Running 'ipcs' will show us statistics separately for each of the three resource types (shared memory segments,
semaphore arrays and message queues). For each resource type, the command will show us some statistics for each
resource that exists in the system. It will show its identifier, owner, size of resources it occupies in the system, and
permission flags. We may give 'ipcs' a flag to ask it to show only resources of one type ('-m' for shared Memory
segments, -q for message Queues and '-s' for Semaphore arrays). We may also use 'ipcs' with the '-l' flag to see the
system enforced limits on these resources, or the '-u' flag to show us usage summary. Refer to the manual page of 'ipcs'
for more information.
The 'ipcrm' command accepts a resource type ('shm', 'msg' or 'sem') and a resource ID, and removes the given resource
from the system. We need to have the proper permissions in order to delete a resource.
In order to use a message queue, it has to be created first. The msgget() system call is used to do just that. This
system call accepts two parameters - a queue key, and flags. The key may be one of:
● IPC_PRIVATE - used to create a private message queue.
The second parameter contains flags that control how the system call is to be processed. It may contain flags like
IPC_CREAT or IPC_EXCL, which behave similar to O_CREAT and O_EXCL in the open() system call, and will be
explained later, and it also contains access permission bits. The lowest 9 bits of the flags are used to define access
permission for the queue, much like similar 9 bits are used to control access to files. the bits are separated into 3 groups
- user, group and others. In each set, the first bit refers to read permission, the second bit - to write permission, and the
third bit is ignored (no execute permission is relevant to message queues).
Before we go to writing messages to the queue or reading messages from it, we need to see how a message looks. The
system defines a structure named 'msgbuf' for this purpose. Here is how it is defined:
struct msgbuf {
long mtype; /* message type, a positive number (cannot be zero). */
char mtext[1]; /* message body array. usually larger then one byte. */
};
The message type part is rather obvious. But how do we deal with a message text that is only 1 byte long? Well, we
actually may place a much larger text inside a message. For this, we allocate more memory for a msgbuf structure then
sizeof(struct msgbuf). Lets see how we create an "hello world" message:
Few notes:
1. When allocating a space for a string, one always needs to allocate one extra byte for the null character
terminating the string. In our case, we allocated strlen(msg_text) more then the size of "struct
msgbuf", and didn't need to allocate an extra place for the null character, cause that's already contained in the
msgbuf structure (the 1 byte of mtext there).
2. We don't need to place only text messages in a message. We may also place binary data. In that case, we could
allocate space as large as the msgbuf struct plus the size of our binary data, minus one byte. Of-course then to
copy the data to the message, we'll use a function such as memset(), and not strcpy().
Once we created the message queue, and a message structure, we can place it on the message queue, using the
msgsnd() system call. This system call copies our message structure and places that as the last message on the queue.
It takes the following parameters:
1. int msqid - id of message queue, as returned from the msgget() call.
2. struct msgbuf* msg - a pointer to a properly initializes message structure, such as the one we prepared in
the previous section.
3. int msgsz - the size of the data part (mtext) of the message, in bytes.
4. int msgflg - flags specifying how to send the message. may be a logical "or" of the following:
❍ IPC_NOWAIT - if the message cannot be sent immediately, without blocking the process, return '-1', and
set errno to EAGAIN.
to set no flags, use the value '0'.
So in order to send our message on the queue, we'll use msgsnd() like this:
Note that we used a message size one larger then the length of the string, since we're also sending the null character.
msgsnd() assumes the data in the message to be an arbitrary sequence of bytes, so it cannot know we've got the null
character there too, unless we state that explicitly.
We may use the system call msgrcv() In order to read a message from a message queue. This system call accepts the
following list of parameters:
1. int msqid - id of the queue, as returned from msgget().
2. struct msgbuf* msg - a pointer to a pre-allocated msgbuf structure. It should generally be large enough to
contain a message with some arbitrary data (see more below).
3. int msgsz - size of largest message text we wish to receive. Must NOT be larger then the amount of space we
allocated for the message text in 'msg'.
4. int msgtyp - Type of message we wish to read. may be one of:
❍ 0 - The first message on the queue will be returned.
❍ a positive integer - the first message on the queue whose type (mtype) equals this integer (unless a certain
flag is set in msgflg, see below).
❍ a negative integer - the first message on the queue whose type is less then or equal to the absolute value of
this integer.
5. int msgflg - a logical 'or' combination of any of the following flags:
❍ IPC_NOWAIT - if there is no message on the queue matching what we want to read, return '-1', and set
errno to ENOMSG.
❍ MSG_EXCEPT - if the message type parameter is a positive integer, then return the first message whose
type is NOT equal to the given integer.
❍ MSG_NOERROR - If a message with a text part larger then 'msgsz' matches what we want to read, then
truncate the text when copying the message to our msgbuf structure. If this flag is not set and the message
text is too large, the system call returns '-1', and errno is set to E2BIG.
Lets then try to read our message from the message queue:
A few notes:
1. If the message on the queue was larger then the size of "hello world" (plus one), we would get an error, and thus
exit.
2. If there was no message on the queue, the msgrcv() call would have blocked our process until one of the
following happens:
❍ a suitable message was placed on the queue.
❍ the queue was removed (and then errno would be set to EIDRM).
❍ our process received a signal (and then errno would be set to EINTR.
Now that you've seen all the different parts, you're invited to look at the private-queue-hello-world.c program, for the
complete program.
Message Queues - A Complete Example
As an example of using non-private message queues, we will show a program, named "queue_sender", that creates a
message queue, and then starts sending messages with different priorities onto the queue. A second program, named
"queue_reader", may be run that reads the messages from the queue, and does something with them (in our example -
just prints their contents to standard output). The "queue_reader" is given a number on its command line, which is the
priority of messages that it should read. By running several copies of this program simultaneously, we can achieve a
basic level of concurrency. Such a mechanism may be used by a system in which several clients may be sending
requests of different types, that need to be handled differently. The complete source code may be found in the
public-queue directory.
A semaphore is a resource that contains an integer value, and allows processes to synchronize by testing and setting this
value in a single atomic operation. This means that the process that tests the value of a semaphore and sets it to a
different value (based on the test), is guaranteed no other process will interfere with the operation in the middle.
Two types of operations can be carried on a semaphore: wait and signal. A set operation first checks if the semaphore's
value equals some number. If it does, it decreases its value and returns. If it does not, the operation blocks the calling
process until the semaphore's value reaches the desired value. A signal operation increments the value of the
semaphore, possibly awakening one or more processes that are waiting on the semaphore. How this mechanism can be
put to practical use will be explained soon.
A semaphore set is a structure that stores a group of semaphores together, and possibly allows the process to commit a
transaction on part or all of the semaphores in the set together. In here, a transaction means that we are guaranteed that
either all operations are done successfully, or none is done at all. Note that a semaphore set is not a general parallel
programming concept, it's just an extra mechanism supplied by SysV IPC.
Creation of a semaphore set is done using the semget() system call. Similarly to the creation of message queues, we
supply some ID for the set, and some flags (used to define access permission mode and a few options). We also supply
the number of semaphores we want to have in the given set. This number is limited to SEMMSL, as defined in file
/usr/include/sys/sem.h. Lets see an example:
Note that in the second case, if a semaphore set with ID 250 already existed, we would get access to the existing set,
rather then a new set be created. This works just like it worked with message queues.
After the semaphore set is created, we need to initialize the value of the semaphores in the set. We do that using the
semctl() system call. Note that this system call has other uses, but they are not relevant to our needs right now. Lets
assume we want to set the values of the three semaphores in our second set to values 3, 6 and 0, respectively. The ID of
the first semaphore in the set is '0', the ID of the second semaphore is '1', and so on.
There are one comment to be made about the way we used semctl() here. According to the manual, the last
parameter for this system call should be a union of type union semun. However, since the SETVAL (set value)
operation only uses the int val part of the union, we simply passed an integer to the function. The proper way to use
this system call was to define a variable of this union type, and set its value appropriately, like this:
We used the first form just for simplicity. From now on, we will only use the second form.
Sometimes we have a resource that we want to allow only one process at a time to manipulate. For example, we have a
file that we only want written into only by one process at a time, to avoid corrupting its contents. Of-course, we could
use various file locking mechanisms to protect the file, but we will demonstrate the usage of semaphores for this
purpose as an example. Later on we will see the real usage of semaphores, to protect access to shared memory
segments. Anyway, here is a code snippest. It assumes the semaphore in our set whose id is "sem_set_id" was
initialized to 1 initially:
/* this function updates the contents of the file with the given path name. */
void update_file(char* file_path, int number)
{
/* structure for semaphore operations. */
struct sembuf sem_op;
FILE* file;
/* Comment 2 */
/* we "locked" the semaphore, and are assured exclusive access to file. */
/* manipulate the file in some way. for example, write a number into it. */
file = fopen(file_path, "w");
if (file) {
fprintf(file, "%d\n", number);
fclose(file);
}
This code needs some explanations, especially regarding the semantics of the semop() calls.
1. Comment 1 - before we access the file, we use semop() to wait on the semaphore. Supplying '-1' in
sem_op.sem_op means: If the value of the semaphore is greater then or equal to '1', decrease this value by
one, and return to the caller. Otherwise (the value is 1 or less), block the calling process, until the value of the
semaphore becomes '1', at which point we return to the caller.
2. Comment 2 - The semantics of semop() assure us that when we return from this function, the value of the
semaphore is 0. Why? it couldn't be less, or else semop() won't return. It couldn't be more due to the way we
later on signal the semaphore. And why it cannot be more then '0'? read on to find out...
3. Comment 3 - after we are done manipulating the file, we increase the value of the semaphore by 1, possibly
waking up a process waiting on the semaphore. If several processes are waiting on the semaphore, the first that
got blocked on it is wakened and continues its execution.
Now, lets assume that any process that tries to access the file, does it only via a call to our "update_file" function. As
you can see, when it goes through the function, it always decrements the value of the semaphore by 1, and then
increases it by 1. Thus, the semaphore's value can never go above its initial value, which is '1'. Now lets check two
scenarios:
1. No other process is executing the "update_file" concurrently. In this case, when we enter the function, the
semaphore's value is '1'. after the first semop() call, the value of the semaphore is decremented to '0', and thus
our process is not blocked. We continue to execute the file update, and with the second semop() call, we raise
the value of the semaphore back to '1'.
2. Another process is in the middle of the "update_file" function. If it already managed to pass the first call to
semop(), the value of the semaphore is '0', and when we call semop(), our process is blocked. When the
other process signals the semaphore with the second semop() call, it increases the value of the semaphore back
to '0', and it wakes up the process blocked on the semaphore, which is our process. We now get into executing
the file handling code, and finally we raise the semaphore's value back to '1' with our second call to semop().
We have the source code for a program demonstrating the mutex concept, in the file named sem-mutex.c. The program
launches several processes (5, as defined by the NUM_PROCS macro), each of which is executing the "update_file"
function several times in a row, and then exits. Try running the program, and scan its output. Each process prints out its
PID as it updates the file, so you can see what happens when. Try to play with the DELAY macro (specifying how long
a process waits between two calls to "update_file") and see how it effects the order of the operations. Check what
happens if you replace the delay loop in the "do_child_loop" function, with a call to sleep().
Using a semaphore as a mutex is not utilizing the full power of the semaphore. As we saw, a semaphore contains a
counter, that may be used for more complex operations. Those operations often use a programming model called
"producer-consumer". In this model, we have one or more processes that produce something, and one or more
processes that consume that something. For example, one set of processes accept printing requests from clients and
place them in a spool directory, and another set of processes take the files from the spool directory and actually print
them using the printer.
To control such a printing system, we need the producers to maintain a count of the number of files waiting in the spool
directory and incrementing it for every new file placed there. The consumers check this counter, and whenever it gets
above zero, one of them grabs a file from the spool, and sends it to the printer. If there are no files in the spool (i.e. the
counter value is zero), all consumer processes get blocked. The behavior of this counter sounds very familiar.... it is the
exact same behavior of a counting semaphore.
Lets see how we can use a semaphore as a counter. We still use the same two operations on the semaphore, namely
"signal" and "wait".
Note that our "wait" and "signal" operations here are just like we did with when using the semaphore as a mutex. The
only difference is in who is doing the "wait" and the "signal". With a mutex, the same process did both the "wait" and
the "signal" (in that order). In the producer-consumer example, one process is doing the "signal" operation, while the
other is doing the "wait" operation.
The full source code for a simple program that implements a producer-consumer system with two processes, is found in
the file sem-producer-consumer.c.
As a complete example of using semaphores, we write a very simple print spool system. Two separate programs will be
used. One runs as the printing command, and is found in the file tiny-lpr.c. It gets a file path on its command line, and
copies this file into the spool area, increasing a global (on-private) semaphore by one. Another program runs as the
printer daemon, and is found in the file tiny-lpd.c. It waits on the same global semaphore, and whenever its value is
larger then one, it locates a file in the spool directory and sends it to the printer. In order to avoid race conditions when
copying files into the directory and removing files from this directory, a second semaphore will be used as a mutex, to
protect the spool directory. The complete tiny-spooler mini-project is found in the tiny-spool directory.
One problem might be that copying a file takes a lot of time, and thus locking the spool directory for a long while. In
order to avoid that, 3 directories will be used. One serves as a temporary place for tiny-lpr to copy files into. One will
be used as the common spool directory, and one will be used as a temporary directory into which tiny-lpd will move the
files before printing them. By putting all 3 directories on the same disk, we assure that files can be moved between
them using the rename() system call, in one fast operation (regardless of the file size).
Shared Memory
As we have seen, many methods were created in order to let processes communicate. All this communications is done
in order to share data. The problem is that all these methods are sequential in nature. What can we do in order to allow
processes to share data in a random-access manner?
Shared memory comes to the rescue. As you might know, on a Unix system, each process has its own virtual address
space, and the system makes sure no process would access the memory area of another process. This means that if one
process corrupts its memory's contents, this does not directly affect any other process in the system.
With shared memory, we declare a given section in the memory as one that will be used simultaneously by several
processes. This means that the data found in this memory section (or memory segment) will be seen by several
processes. This also means that several processes might try to alter this memory area at the same time, and thus some
method should be used to synchronize their access to this memory area (did anyone say "apply mutual exclusion using
a semaphore" ?).
In order to understand the concept of shared memory, we should first check how virtual memory is managed on the
system.
In order to achieve virtual memory, the system divides memory into small pages each of the same size. For each
process, a table mapping virtual memory pages into physical memory pages is kept. When the process is scheduled for
running, its memory table is loaded by the operating system, and each memory access causes a mapping (by the CPU)
to a physical memory page. If the virtual memory page is not found in memory, it is looked up in swap space, and
loaded from there (this operation is also called 'page in').
When the process is started, it is being allocated a memory segment to hold the runtime stack, a memory segment to
hold the programs code (the code segment), and a memory area for data (the data segment). Each such segment might
be composed of many memory pages. When ever the process needs to allocate more memory, new pages are being
allocated for it, to enlarge its data segment.
When a process is being forked off from another process, the memory page table of the parent process is being copied
to the child process, but not the pages themselves. If the child process will try to update any of these pages, then this
page specifically will be copied, and then only the copy of the child process will be modified. This behavior is very
efficient for processes that call fork() and immediately use the exec() system call to replace the program it runs.
What we see from all of this is that all we need in order to support shared memory, is to some memory pages as shared,
and to allow a way to identify them. This way, one process will create a shared memory segment, other processes will
attach to them (by placing their physical address in the process's memory pages table). From now all these processes
will access the same physical memory when accessing these pages, thus sharing this memory area.
A shared memory segment first needs to be allocated (created), using the shmget() system call. This call gets a key
for the segment (like the keys used in msgget() and semget()), the desired segment size, and flags to denote
access permissions and whether to create this page if it does not exist yet. shmget() returns an identifier that can be
later used to access the memory segment. Here is how to use this call:
If several processes try to allocate a segment using the same ID, they will all get an identifier for the same page, unless
they defined IPC_EXCL in the flags to shmget(). In that case, the call will succeed only if the page did not exist
before.
After we allocated a memory page, we need to add it to the memory page table of the process. This is done using the
shmat() (shared-memory attach) system call. Assuming 'shm_id' contains an identifier returned by a call to
shmget(), here is how to do this:
As you can see, a page may be attached in read-only mode, or in read-write mode. The same page may be attached
several times by the same process, and then all the given addresses will refer to the same data. In the example above,
we can use 'shm_addr' to access the segment both for reading and for writing, while 'shm_addr_ro' can be used for
read-only access to this page. Attaching a segment in read-only mode makes sense if our process is not supposed to
alter this memory page, and is recommended in such cases. The reason is that if a bug in our process causes it to
corrupt its memory image, it might corrupt the contents of the shared segment, thus causing all other processes using
this segment to possibly crush. By using a read-only attachment, we protect the rest of the processes from a bug in our
process.
Placing data in a shared memory segment is done by using the pointer returned by the shmat() system call. Any kind
of data may be placed in a shared segment, except for pointers. The reason for this is simple: pointers contain virtual
addresses. Since the same segment might be attached in a different virtual address in each process, a pointer referring to
one memory area in one process might refer to a different memory area in another process. We can try to work around
this problem by attaching the shared segment in the same virtual address in all processes (by supplying an address as
the second parameter to shmat(), and adding the SHM_RND flag to its third parameter), but this might fail if the
given virtual address is already in use by the process.
Here is an example of placing data in a shared memory segment, and later on reading this data. We assume that
'shm_addr' is a character pointer, containing an address returned by a call to shmat().
strcpy(countries[0].capital_city, "U.S.A");
strcpy(countries[0].capital_city, "Washington");
strcpy(countries[0].currency, "U.S. Dollar");
countries[0].population = 250000000;
(*countries_num)++;
strcpy(countries[1].capital_city, "Israel");
strcpy(countries[1].capital_city, "Jerusalem");
strcpy(countries[1].currency, "New Israeli Shekel");
countries[1].population = 6000000;
(*countries_num)++;
strcpy(countries[1].capital_city, "France");
strcpy(countries[1].capital_city, "Paris");
strcpy(countries[1].currency, "Frank");
countries[1].population = 60000000;
(*countries_num)++;
Since the memory page was already allocated when we called shmget(), there is no need to use malloc()
when placing data in that segment. Instead, we do all memory management ourselves, by simple pointer
arithmetic operations. We also need to make sure the shared segment was allocated enough memory to
accommodate future growth of our data - there are no means for enlarging the size of the segment once allocated
(unlike when using normal memory management - we can always move data to a new memory location using the
realloc() function).
2. Memory alignment.
In the example above, we assumed that the page's address is aligned properly for an integer to be placed in it. If it
was not, any attempt to try to alter the contents of 'countries_num' would trigger a bus error (SIGBUS) signal.
further, we assumed the alignment of our structure is the same as that needed for an integer (when we placed the
structures array right after the integer variable).
By placing all the data relating to our data model in the shared memory segment, we make sure all processes
attaching to this segment can use the full data kept in it. A naive mistake would be to place the countries counter
in a local variable, while placing the countries array in the shared memory segment. If we did that, other
processes trying to access this segment would have no means of knowing how many countries are in there.
After we finished using a shared memory segment, we should destroy it. It is safe to destroy it even if it is still in use
(i.e. attached by some process). In such a case, the segment will be destroyed only after all processes detach it. Here is
how to destroy a segment:
Note that any process may destroy the shared memory segment, not only the one that created it, as long as it has write
permission to this segment.
A Complete Example
As a naive example of using shared memory, we collected the source code from the above sections into a file named
shared-mem.c. It shows how a single process uses shared memory. Naturally, when two processes (or more) use a
single shared memory segment, there may be race conditions, if one process tries to update this segment, while another
is reading from it. To avoid this, we need to use some locking mechanism - SysV semaphores (used as mutexes) come
to mind here. An example of two processes that access the same shared memory segment using a semaphore to
synchronize their access, is found in the file shared-mem-with-semaphore.c.
One note should be taken: if we remove the file and then re-create it, the system is very likely to allocate a new disk
sector for this file, and thus activating the same ftok call with this file will generate a different key. Thus, the file used
should be a steady file, and not one that is likely to be moved to a different disk or erased and re-created.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Change Log
● 12-May-2001:
❍ Added mutex-unlock call in the various thread pool server examples of the
multi-threading tutorial. Without this unlock operation, the hander thread locks out
all other handler threads while it services the request, making the pool work
serially, and not parallely. (thanks to Mike Hansen for pointing out this crucial
bug).
❍ Added a note about the need to use '-D_GNU_SOURCE' on current Linux
systems, to have the source of some of the programs compiled properly.
❍ Add a new essays section to the site.
❍ Fixed the 'clear screen' and 'get cursor to top of screen' vt100 sequences in the
Writing A VT100-Based PacMan Game project idea.
❍ Fixed dangling links in the related material section. (thanks to Olaf for pointing
that out).
❍ Made some cosmetic/typos fixes to various tutorials (thanks to Markus Wolf for
pointing me towards them).
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Standard Disclaimer
The material (information and programs) on these web pages are provided AS IS, without any
expressed or implied warranty or claim of fitness for a particular purpose. Neither the author
nor any contributers shell be liable for any damages done directly or indirectly by using the
material presented on this web site, even if they were warned of the possibility of such
problems.
Having that said, I still hope this material will be useful for its readers, and help them get on the
fast-lane to being productive Unix programmers. If you find a mistake, inaccuracy or other fault
with any of the tutorials material, please let me know, via email.
Microsoft© and Microsoft Windows© are registered trademarks of Microsoft Corporation, Ltd.
Sun Microsystems© SPARC© and UltraSPARC are registered trademarks, and Java is a
trademark of Sun Microsystems, Inc. IBM©, AIX© and RS/6000© are registered trademarks of
International Business Machines. All other trademarks mentioned in these pages and tutorials
are registered trademarks of their respective owners.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Last update: Sat Jun 30 14:30:00
Welcome to VIM - "Vi IMproved"!
MEST 2001
[Search www.vim.org]
NEWSFLASH
The following is just an excerpt of the News. You can find them all on the News Page.
DATE NEWS
June Vim Book Errata List now available:
19th http://www.moolenaar.net/vim_errata.html
If you find a mistake in the book that isn't in the list yet, or perhaps an item in the errata list that's
wrong, send Bram a message. Preferably use the same format as used on the page.
June Vim is now a topic on Wikipedia, "a collaborative project to produce a complete encyclopedia
13th from scratch":
● http://www2.wikipedia.com/wiki.cgi?VIM
The idea is that anyone can edit the webpages, so everyone can add info when he feels like it. have
fun!
June 4th Turkish translation of the short description on Vim in six kilobytes. Translated by Kutlay Topatan
[email protected] - thanks!
May Linux Journal, June 2001, "Algorithms in Africa", by Wayne Marshall:
25th http://www2.linuxjournal.com/lj-issues/issue86/4657.html (local copies: HTML and Text)
Bram: "It is about the relation between software in third world countries. It's very well written and
gives you a good idea of what people in Africa really need. The last section is about Vim in
Uganda."
May Czech translation of the short description on Vim in six kilobytes. Translated by Tomá¹
20th Znamenáèek [email protected] - thanks!
May 8th A short overview to the Vim-6.0ae - options and their defaults. Hopefully someone has some use
for this.
May 3rd An Interview with Vim Authors - translated to Chinese (GB) by [email protected]
April "What is your favorite Tcl programming editor or environment?" Results:
23rd ● http://www.ajubasolutions.com/poll/poll-results.tcl?poll_id=281
April 20 Vim was added to the "Developer Tools - Editors" section on SoftlandIndia.com, "India's Website
for Linux OS and Applications Downloads.": http://www.softlandindia.com/Linux/Editors.htm
April 11 The Vim Book is expected to ship on April 18th. Author: Steve Oualline; ISBN: 0735710015;
Pubilisher For more info see page http://www.iccf.nl/click5.html
April 11 Bram: "Vim 6.0 is still a few months away. Don't know how many." [Bram won't release it until he
sees that it is good. So stop bugging us about it. ;-)
April 08 To all developers and testers of Vim-6 alpha versions:
@@@@@@@@@@@@@@@@.@@@@@@@@@@@@@@@
@@@@@@@@@MMFFF99.99FFFMM@@@@@@@@
@@@@@@MMMFFFF9fi.if9FFFFMMM@@@@@
@@@@MMMFFFFF9.m...m.9FFFFFMMM@@@
@@@MMMMFFFF9fw.....wf9FFFFMMMM@@
@@MMMMFFF99flw.....wlf99FFFMMMM@
@MMMMMFF99l...........l99FFMMMMM
@MMMMMFfl...............lfFMMMMM
MMMMMMM9.m.............m.9MMMMMM
@MMMMMMF99f...........f99FMMMMMM
@MMMMMMMMFF9fffffffff9FFMMMMMMMM
@@MMMMMMMMMFFFFFFFFFFFMMMMMMMMM@
@@@MMMMMMMMMMMMMFMMMMMMMMMMMMM@@
@@@@MMMMMMMMMMMMMMMMMMMMMMMMM@@@
@@@@@@MMMMMMMMMMMMMMMMMMMMM@@@@@
@@@@@@@@@MMMMMMMMMMMMMMM@@@@@@@@
[Search www.vim.org]
http://www3.sympatico.ca/dany.stamant/vim/
For further info look at the page on Vim on MacOS.
Please read all of the VIM FAQ before asking questions. Thanks!
[Search www.vim.org]
[Search www.vim.org]
It is also a good idea to print out the "Vim Guide" (by Oleg Raisky):
●
http://physlab.sci.ccny.cuny.edu/%7Eorycc/vim-main.html
[Search www.vim.org]
News/Usenet:
However, I prefer "talking" about Vim on News (aka Usenet).
It is much easier to use a newsreader to subscribe and
unsubscribe to newsgroups than it is with mailing lists.
Furthermore, your messages are automatically archived on
deja.com which
has a powerful search interface for the medium.
comp.editors :-)
[Search www.vim.org]
Editing Example
Vim colorizes texts according to the syntax that defines the "language" the text was written in. Here's an
example:
Here I am editing a post to the newsgroup comp.editors that explains the use of the "listchars" option which
show you TABs, trailing spaces, and the end-of-line. (Why doesn't every editor allow you to show these?)
The colorization is done automatically by vim (using the description of the syntax file "mail.vim").
By the way, my newsreader is slrn which also works on color terminals (see some pictures).
Would you like to see more screen-shots of editing with Vim? Let me know!
[Search www.vim.org]
A Note on Mirrors
The current home address of these pages is
http://www.math.fu-berlin.de/~guckes/vim/
All other sites are mirrors!
So if you cannot see any changes on http://www.vim.org/ that's because it is a mirror which is updated only
once a day (well, actually at 2am MET).
A complete list of mirrors is given on
● Distribution Page
If you want to mirror these pages then you are very welcome to do so. Please take a look at the
● HowTo Mirror Page.
[Search www.vim.org]
[Search www.vim.org]
SEE ALSO
There are more sites about Vi and its clones:
● Vi-Editor.org (aka "Vi Pages")
This site has everything else that applies to Vi - not only to Vim. It gives info about everything else that applies
to Vi, including other Vi clones. There are lots of links to other documentation about Vi (intro, tips and tricks,
the Vi FAQ) and also specialized info eg on the substitution command (aka search+replace).
[Search www.vim.org]
Send Feedback!
From: Sven Guckes <[email protected]>
To: You <[email protected]>
Subject: Feedback, please!
Sven
--·
Sven Guckes [email protected]
"The wonderful thing about Tiggers
Is Tiggers are wonderful chaps
They're loaded with vim and with vigor..."
A small note on the signature...
Slow connection? Get faster access at a web mirror Sven [email protected] ©1995-2001
Newsletter | Perl Conference 5.0: July
Search
23-27
Sponsored By:
Downloads
Perl Runs Sweden's
Documentation Pension System
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their respective owners.
For problems or assistance with this site, email [email protected]
GNU Make
Make is a tool which controls the generation of executables and other non-source files of a
program from the program's source files.
Make gets its knowledge of how to build your program from a file called the makefile, which
lists each of the non-source files and how to compute it from other files. When you write a
program, you should write a makefile for it, so that it is possible to use Make to build and install
the program.
Capabilities of Make
● Make enables the end user to build and install your package without knowing the details
of how that is done -- because these details are recorded in the makefile that you supply.
● Make figures out automatically which files it needs to update, based on which source
files have changed. It also automatically determines the proper order for updating files, in
case one non-source file depends on another non-source file.
As a result, if you change a few source files and then run Make, it does not need to
recompile all of your program. It updates only those non-source files that depend directly
or indirectly on the source files that you changed.
● Make is not limited to any particular language. For each non-source file in the program,
the makefile specifies the shell commands to compute it. These shell commands can run a
compiler to produce an object file, the linker to produce an executable, ar to update a
library, or TeX or Makeinfo to format documentation.
● Make is not limited to building a package. You can also use Make to control installing or
deinstalling a package, generate tags tables for it, or anything else you want to do often
enough to make it worth while writing down how to do it.
A rule in the makefile tells Make how to execute a series of commands in order to build a target
file from source files. It also specifies a list of dependencies of the target file. This list should
include all files (whether source files or other targets) which are used as inputs to the commands
in the rule.
Here is what a rule looks like:
GNU Make has many powerful macro features for use in makefiles, beyond what other Make
versions have. It can also regenerate, use, and then delete intermediate files which need not be
saved.
GNU Make also has a few simple features that are very convenient. For example, the -o file
option which says ``pretend that source file file has not changed, even though it has changed.''
This is extremely useful when you add a new macro to a header file. Most versions of Make
will assume they must therefore recompile all the source files that use the header file; but GNU
Make gives you a way to avoid the recompilation, in the case where you know your change to
the header file does not require it.
However, the most important difference between GNU Make and most versions of Make is that
GNU Make is free software.
Full documentation for GNU make is found in the Make manual, which is included in the GNU
Make distribution. You can also buy printed copies of the Make manual from the Free Software
Foundation; the money we raise goes to fund free software development.
Alternatively you can browse the online documentation available at
www.gnu.org/manual/make/index.html
You can download GNU make from the GNU FTP site ftp.gnu.org or one of its mirrors. You
can also obtain it by buying the GNU Source Code CD-ROM from the Free Software
Foundation; this too helps fund free software development.
GNU make was written by Richard Stallman and Roland McGrath.
We have developed conventions for how to write Makefiles, which all GNU packages ought to
follow. It is a good idea to follow these conventions in your program even if you don't intend it
to be GNU software, so that users will be able to build your package just like many other
packages, and will not need to learn anything special before doing so.
These conventions are found in the chapter ``Makefile conventions'' (147 k characters) of the
GNU Coding Standards (147 k characters).
Return to GNU's home page.
Please send FSF & GNU inquiries & questions to [email protected]. There are also other ways to
contact the FSF.
Please send comments on these web pages to [email protected], send other questions
to [email protected].
Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc., 59 Temple Place - Suite
330, Boston, MA 02111, USA
Verbatim copying and distribution of this entire article is permitted in any medium, provided
this notice is preserved.
Updated: 6 Sep 2000 neelakanth
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
v1.0.0
Abstract
Many universities and other institutions try to teach software engineering concepts to their
students, either as part of their regular programming courses, in courses designed to teach just
software engineering, or as a set of such courses.
In this short essay, I'll supply a loose definition of "Software Engineering", show why it is so
hard (or impossible) teaching it to inexperienced programmers, and try to illustrate a few
methods that may be used to still put some sense of engineering into inexperienced
programmers.
More On Students
As we saw, software engineering requires large projects to make sense. It also requires
experience to make sense. In particular, bad experience - if you write software in the right way,
you don't get to see how wrong badly written software can get, and thus don't learn to
appreciate the right ways. Thus, part of learning software engineering is achieved by seeing
how lack of it can hurt large software projects. For students "a large project" might be
something they have written in one semester, in which they also studied a few other courses.
Given a software made of a few thousands lines of code, or a few tens of classes, inexperienced
programmers consider the software to be a large project. Later on, when they get out to work in
the industry, they will begin to realize those were in fact rather small projects. In such small
projects, lack of proper engineering won't usually reveal the problems it causes, since those
projects only need to work once or twice (when demonstrating them to the teacher) and don't
get developed further afterwards.
Another aspect of software engineering is designing the software to be easy to maintain. Since
most student projects don't get tested by end-users users, many of their bugs remain hidden, and
thus the programmer isn't exposed to the amount of time it would take to debug and fix it until it
becomes on the level of usable release software - something which often would take more then
the amount of time it took to originally write the code and make it run. The original developer
of the code tends not to stress-test their code in its weak spots, since they subconsciously know
it'll cause the software to crash or malfunction - something which will require more work, that
isn't really appreciated when the project is graded. Thus, the programmer cannot see how their
software design affected the ability to isolate bugs in the code, and get the false impression that
their design generated bug-free software.
Another aspect of learning about software engineering, is seeing how it affects the life cycle of
a software project. Sometimes, experienced software engineers make decisions that look like
small neat-peaking to the naked eye. Only after a while, as the project evolves to different
directions, these original decisions begin to make sense to an inexperienced programmer. Some
people will claim that this ability to see the need for those small decisions in advance comes
with experience - and yet, this is what software engineering strives for - the ability to make
these decisions using a methodological process, that generates repeated success.
Finally, there are students that understand the rules of thumb, and believe that they might be
useful, but still prefer not using them for their exercises on the grounds that understanding is
enough, and when they get involved in large projects, they will know how to deal with them.
The problem is that by the time they get to working on large projects, they might gather bad
habits and find it hard to free themselves of these bad habits. They also overlook the little things
that can only be achieved with real practice, and thus will stay behind fellow students, who have
spent a few years of their undergraduate studies to actually apply these rules, and gained some
experience, and thus more insight.
So the conclusion we come to is that you need good familiarity and hands-on involvement in
large and lasting software projects, both successful and failures, in order to grasp the essence of
software engineering, and appreciate it. And in university environments (or various
programming courses, for that matter) the ability to participate in such activities is rather
limited.
More On Universities
What do universities do in order to try and teach software engineering? One thing they do is try
to teach it as a set of rules of thumb, hoping that students will follow them, even if only because
they are being enforced somehow when grading exercises and exams. The problem with this
approach is that often the people who do the actual grading are graduate students, who
themselves haven't had the chance to grab the concept of software engineering (especially if
they entered graduate school directly after finishing undergraduate school).
Even if some of the teachers, or teaching assistants, do have experience with large and lasting
software projects, often their students don't know about that, and hence don't trust them. When
you don't trust someone, you don't listen to advise they give you if you cannot see an immediate
benefit (and in software engineering, there is no benefit for very small exercises). Thus, the
students actually tend to ignore their teachers' rules of thumb, seeing them as a burden, and this
causes more damage then if those rules were never given in the first place.
At other times, there might be a good software engineering teacher, that indeed has experience
in the field, and tries to show some real life examples to their students. These efforts, however,
might be lost if the students don't get their own hands-on experience with such software.
Learning software engineering on a theoretical bases, and using small code examples (since
there is no time to really delve into large code examples) makes no sense, except for people
who already understand software engineering in the first place - kind of a chicken-and-egg
problem.
How To Make It Work?
After seeing what is needed to make students appreciate software engineering, we might as well
spell out a few things that will make teaching it possible. First, we need to have accredited
teachers. These teachers may either be people with past or current experience in the industry,
that can use it to back their claims to students. They could also be people who participated in
large academic projects, that got enough credit for being large and lasting. A good example
would be the work done in the MIT university, and their Athena project (see also A review of -
MIT project Athena: a model for distributed campus computing). Another good example is the
work done at the Washington university in Seattle, by the Distributed Object Computing (DOC)
group. There exist various other such examples. The important factor is that they are large
projects, involve quite a few staff members (including graduate students), and last for quite a
few years, and thus carry a scope similar to that of large industrial projects.
It is also important that the students will know that their teachers have that experience. This is
not to be used as a method of bragging, but rather to assure the students that their teacher is not
just talking about theoretical software engineering methods; That the teacher has actually
applied them, and can show them good, real-life examples, of why these methods are useful,
and should be practiced even for smaller projects.
Carrying out large projects by university staff members is also good as it allows graduate
students to participate in such projects, and thus be more credible to serve as teaching assistants
in software engineering related courses. With good project management, it is also possible to
allow undergraduate students to take part in such projects, and witness, from first hand, the
complexity of such a project. When they have to delve into code created by other programmers,
possibly code that is 2-3 years old, they will learn to appreciate how hard it is to get into code
parts that weren't properly engineered, and how relatively easy it is to get into parts that were
properly engineered. And having specific parts of the code that are badly engineered on
purpose, would serve the teaching goal quite well.
Of-course, getting students involved in large software projects should be done gradually. At
first, they may be introduced to small modules, learn them, and be guided in making small
changes to them. It is a very useful quality to be able to delve into existing source bases, and
inexperienced programmers often find it hard to do. At later phases, these students will be able
to write new classes or modules. Getting credit for such projects will be more desirable then
letting these students design their own software in a software project course, that will turn out to
be small (they don't have enough time to work on it, and usually only 2-3 of them work on the
code of such project) and having to create software that will most likely not last, and not be a
part of a lasting project.
Financing Academic Software Projects
One of the major problems with carrying large software projects in universities is financing
them. You need more equipment then with theoretical research, more system management staff,
and more researchers then for a theoretical research.
The equipment needed is often not so hard to get as a donation from large hardware
manufacturers and resellers. They already have such donation relationship with universities,
sometimes donating full labs for students to work on, in a hope that these students will get used
to their development environments, and endorse them when they get some influence in their
future working place.
Another option is carrying software research projects that are useful for large industrial
companies. Showing these companies how this research can help them, it is possible to
convince them to sponsor such projects. The fact that financing a project in which graduate
students and undergraduate students perform large parts of the work, would be cheaper then
financing it inside the industry, it might look appealing to industrial companies. The TAO
project carried by the DOC group at the Washington university and university of California, is a
good example of such a relationship.
Another major problem is attracting good software engineers that both wish to carry out
research work in their field, and have the skills to manage large projects at the same time. The
success of such a project in fact often relies on one or more such enthusiast leaders, that carries
a good reputation in the academic field, as well as in the industry. It would be easier to attract
such people to the academy, if they know they will get a supportive environment, and financing
to projects that will seem feasible and are personally appealing to them. Sometimes, it does not
require paying them better then in the industry. The fact that they get more freedom, and
without the pressure of marketing personnel, would be enough to attract a few of them to
moving to the academic world.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
MIT Project Athena
In May 1983, MIT announced the establishment of a five-year program to explore new,
innovative uses of computing in the MIT curriculum. The MIT faculty was concerned that too
little was being done to integrate the new computational technology into the undergraduate
educational experience. Project Athena, as the program was called, arose from this concern.
Project Athena's mandate was to explore diverse uses of computing and to build the base of
knowledge needed for a longer term strategic decision about how computers fit into the MIT
curriculum. In January of 1988, Project Athena was granted a three-year extension to the
original five-year program, and on June 30, 1991, Project Athena came to an end. But the fruit
of Project Athena -- the Athena service environment -- was adopted as MIT's academic
computing infrastructure, with plans to extend it beyond the educational sphere, into the
research and administrative activities of the Institute.
The product of eight years of research, the Athena environment provides computing resources
to nearly 14,000 users across the MIT campus through a vast system of 1,300 computers in
more than 40 clusters, private offices, and machine rooms, all connected to the campus network.
Athena users have access to software to help them write papers, create graphs, analyze data,
communicate with their colleagues, play games, and perform countless other tasks, as well as
software designed specifically for classwork.
Athena has pervaded campus life. At last count, 99% of MIT undergraduates and 81% of MIT
graduate students had Athena accounts. On a typical day, over 6,000 different users access their
personal files and various software packages on the system.
A review of -
Reviewed by Mark C. Sheehan, published in the February 1992 issue of Database magazine, a
publication of Online Inc. (Note: This is a copy of my original manuscript. Minor changes made
by the publisher are not reflected here.)
Distributed Object Computing (DOC)
Group
Electrical and
Computer Department
Engineering of Computer
University of Science
California, Washington
Irvine University
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 © 1997, 1998, 1999, 2000 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 <[email protected]>
Patrick J. Horgan withheld
Stephen Baynes <[email protected]>
James Raynard withheld
Michael F. Quigley withheld
Ken Pizzini withheld
Thamer Al-Herbish withheld
Nick Kew <[email protected]>
Dan Abarbanel withheld
Billy Chambless <[email protected]>
Walter Briscoe <[email protected]>
Jim Buchanan <[email protected]>
Dave Plonka <[email protected]>
Daniel Stenberg withheld
Ralph Corderoy <[email protected]>
Stuart Kemp withheld
Sergei Chernev <[email protected]>
Bjorn Reese withheld
Joe Halpin <[email protected]>
Aaron Crane <[email protected]>
Geoff Clare <[email protected]>
1. Process Control
1.1 Creating new processes: fork()
1.1.1 What does fork() do?
#include <sys/types.h>
#include <unistd.h>
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;
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
● nice value
● scheduler class
● process group ID
● session ID
● root directory
● resource limits
● controlling terminal
● process, text, data and other memory locks are NOT inherited.
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.
#include <stdlib.h>
#include <stdlib.h>
char *envvar;
envvar=getenv("TERM");
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 */
}
#include <stdio.h>
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 <stdio.h>
● 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
Of the above, select() is probably the most portable (and strangely, it is often much more efficient
than usleep() or an itimer-based method). However, the behaviour may be different if signals are
caught while asleep; this may or may not be an issue depending on the application.
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 some similar, but different, functions.
❍ 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 @math{-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 @math{-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 @math{-1}, with some other value of errno
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.
An alternative exists, if you are writing specifically for a system (or all those systems) that provide a
`/proc' filesystem: checking for the existence of `/proc/PID' may work.
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 `<sys/wait.h>') 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) is non-zero, this is non-zero if the process left behind a core dump.
● if tostop is set in the terminal modes, it will be stopped with SIGTTOU if it attempts to write to
the terminal (attempting to change the terminal modes should also cause this, independently of the
current setting of tostop)
● The subprocess will not receive keyboard signals from the terminal (e.g. SIGINT or SIGQUIT)
In many applications input and output will be redirected anyway, so the most significant effect will be the
lack of keyboard signals. The parent application should arrange to catch at least SIGINT and SIGQUIT
(and preferably SIGTERM as well) and clean up any background jobs as necessary.
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 equal zero, 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:
FD_ZERO(&fds);
FD_SET(fd,&fds);
tv.tv_sec = tv.tv_usec = 0;
return FD_ISSET(fd,&fds) ? 1 : 0;
}
Note that we can pass NULL for fdsets that we aren't interested in testing.
struct pollfd {
int fd; /* The descriptor. */
short events; /* The event(s) is/are specified here. */
short revents; /* Events found are returned here. */
};
A lot 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, revents 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:
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <stropts.h>
#include <poll.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#define NORMAL_DATA 1
#define HIPRI_DATA 2
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);
if((poll_list[1].revents&POLLIN) == POLLIN)
handle(poll_list[1].fd,NORMAL_DATA);
if((poll_list[1].revents&POLLPRI) == POLLPRI)
handle(poll_list[1].fd,HIPRI_DATA);
}
}
2.1.3 Can I use SysV IPC at the same time as select or poll?
No. (Except on AIX, which has an incredibly ugly kluge to allow this.)
In general, trying to combine the use of select() or poll() with using SysV message queues is
troublesome. SysV IPC objects are not handled by file descriptors, so they can't be passed to select() or
poll(). There are a number of workarounds, of varying degrees of ugliness:
● Abandon SysV IPC completely. :-)
● fork(), and have the child process handle the SysV IPC, communicating with the parent process
by a pipe or socket, which the parent process can select() on.
● As above, but have the child process do the select(), and communicate with the parent by
message queue.
● Arrange for the process that sends messages to you to send a signal after each message. Warning:
handling this right is non-trivial; it's very easy to write code that can potentially lose messages or
deadlock using this method.
(Other methods exist.)
2.2 How can I tell when the other end of a connection
shuts down?
If you try to read from a pipe, socket, FIFO etc. when the writing end of the connection has been closed,
you get an end-of-file indication (read() returns 0 bytes read). If you try and write to a pipe, socket etc.
when the reading end has closed, then a SIGPIPE signal will be delivered to the process, killing it unless
the signal is caught. (If you ignore or block the signal, the write() call fails with EPIPE.)
flock();
lockf();
fcntl();
flock() originates with BSD, and is now available in most (but not all) Unices. It is simple and effective
on a single host, but doesn't work at all with NFS. It locks an entire file. Perhaps rather deceptively, the
popular Perl programming language implements its own flock() where necessary, conveying the
illusion of true portability.
fcntl() is the only POSIX-compliant locking mechanism, and is therefore the only truly portable lock. It
is also the most powerful, and the hardest to use. For NFS-mounted file systems, fcntl() requests are
passed to a daemon (rpc.lockd), which communicates with the lockd on the server host. Unlike
flock() it is capable of record-level locking.
lockf() is merely a simplified programming interface to the locking functions of fcntl().
Whatever locking mechanism you use, it is important to sync all your file IO while the lock is active:
lock(fd);
write_to(some_function_of(fd));
flush_output_to(fd); /* NEVER unlock while output may be buffered */
unlock(fd);
do_something_else; /* another process might update it */
lock(fd);
seek(fd, somewhere); /* because our old file pointer is not safe */
do_something_with(fd);
...
A few useful fcntl() locking recipes (error handling omitted for simplicity) are:
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
if(stat(path,&file_stats))
return -1;
*size = file_stats.st_size;
return 0;
}
if (path.length() == 1 || pos == 1)
{
pfx = getenv("HOME");
if (!pfx)
{
// Punt. We're trying to expand ~/, but HOME isn't set
struct passwd *pw = getpwuid(getuid());
if (pw)
pfx = pw->pw_dir;
}
}
else
{
string user(path,1,(pos==string::npos) ? string::npos : pos-1);
struct passwd *pw = getpwnam(user.c_str());
if (pw)
pfx = pw->pw_dir;
}
if (!pfx)
return path;
string result(pfx);
if (pos == string::npos)
return result;
result += path.substr(pos+1);
return result;
}
/* set the umask explicitly, you don't know where it's been */
umask(0);
if (mknod("test_fifo",
S_IFIFO | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
0))
{
perror("mknod");
exit(1);
}
● If you open for reading (O_RDONLY), the open will block until another process opens the FIFO for
writing, unless O_NONBLOCK is specified, in which case the open succeeds.
● If you open for writing O_WRONLY, the open will block until another process opens the FIFO for
reading, unless O_NONBLOCK is specified, in which case the open fails.
When reading and writing the FIFO, the same considerations apply as for regular pipes and sockets, i.e.
read() will return EOF when all writers have closed, and write() will raise SIGPIPE when there are
no readers. If SIGPIPE is blocked or ignored, the call fails with EPIPE.
3. Terminal I/O
3.1 How can I make my program not echo
input?
How can I make my program not echo input, like login does when asking for your
password?
There is an easy way, and a slightly harder way:
The easy way, is to use getpass(), which is probably found on almost all Unices. It takes a
string to use as a prompt. It will read up to an EOF or newline and returns a pointer to a static
area of memory holding the string typed in.
The harder way is to use tcgetattr() and tcsetattr(), both use a struct termios
to manipulate the terminal. The following two routines should allow echoing, and non-echoing
mode.
#include <stdlib.h>
#include <stdio.h>
#include <termios.h>
#include <string.h>
void echo_off(void)
{
struct termios new_settings;
tcgetattr(0,&stored_settings);
new_settings = stored_settings;
new_settings.c_lflag &= (~ECHO);
tcsetattr(0,TCSANOW,&new_settings);
return;
}
void echo_on(void)
{
tcsetattr(0,TCSANOW,&stored_settings);
return;
}
Both routines used, are defined by the POSIX standard.
#include <stdlib.h>
#include <stdio.h>
#include <termios.h>
#include <string.h>
void set_keypress(void)
{
struct termios new_settings;
tcgetattr(0,&stored_settings);
new_settings = stored_settings;
tcsetattr(0,TCSANOW,&new_settings);
return;
}
void reset_keypress(void)
{
tcsetattr(0,TCSANOW,&stored_settings);
return;
}
O_NONBLOCK
Opening a dial-in or modem-controlled device will block until carrier is present,
unless this flag is used. A nonblocking open gives you the opportunity to disable
the modem controls (see CLOCAL below) if necessary.
O_NOCTTY
On 4.4BSD-derived systems this is redundant, but on other systems it controls
whether the serial device can become a control terminal for the session. In most
cases you probably don't want to acquire a control terminal, and should therefore
specify this flag, but there are exceptions.
● Use tcgetattr() to retrieve the current device modes. While one will often ignore
most or all of the initial settings thus obtained, it's still a convenient way of initialising a
struct termios.
● Set suitable values for c_iflag, c_oflag, c_cflag, c_lflag, and c_cc in the
termios structure. (See below.)
● Use cfsetispeed() and cfsetospeed() to set the desired baud rate. Very few
systems allow you to set differing input and output speeds, so as a general rule you
should set both to your desired speed.
● Use tcsetattr() to set the device modes.
● You may wish, if you used O_NONBLOCK when opening the port, to use fcntl() to
ensure that O_NONBLOCK is turned off again. Systems seem to differ as to whether a
nonblocking open on a tty will affect subsequent read() calls; better to be explicit.
Once you have opened and set up the port, you can then use read() and write() normally.
Note that the behaviour of read() will be controlled by the flag settings you gave to
tcsetattr().
tcflush(), tcdrain(), tcsendbreak() and tcflow() are additional useful
functions that you should be aware of.
When you're done with the port, and want to close it, be aware of a very nasty little hazard on
some systems; if there's any pending output waiting to be written to the device (e.g. if output
flow is stopped by hardware or software handshaking), your process can hang unkillably in the
close() call until the output drains. Calling tcflush() to discard any pending output is
probably a wise move.
(Blocked output on tty devices is by far the most common cause of "unkillable" processes in my
experience.)
● A blocking open of a modem-control or dial-in device will wait for DCD (and possibly
also DSR and/or CTS) to be raised, usually after asserting DTR/RTS.
● An open of a dial-out device while an open call to the corresponding dial-in device is
blocked waiting for carrier may or may not cause the open of the dial-in port to complete.
Some systems implement a simple sharing scheme for dial-in and dial-out ports whereby
the dial-in port is effectively "put to sleep" while the dial-out port is in use; other systems
do not do this, and sharing the port between dial-in and dial-out on such systems requires
external cooperation (e.g. use of UUCP lockfiles) to avoid contention problems.
3.6.2.1 c_iflag
You probably want to set all the bits in c_iflag to 0, unless you want to use software flow
control (ick) in which case you set IXON and IXOFF.
3.6.2.2 c_oflag
Most of the bits of c_oflag are hacks of one sort or another to make output to slow terminals
work, and as such some newer systems have dropped almost all of them as obsolete (especially
all the gory output-padding options). As with c_iflag, setting everything to 0 is reasonable
for most applications.
3.6.2.3 c_cflag
When setting the character size, remember to mask using CSIZE first; e.g. to set 8-bit
characters, use:
3.6.2.4 c_lflag
Most applications will probably want to turn off ICANON (canonical, i.e. line-based, input
processing), ECHO, and ISIG.
IEXTEN is a more complex issue. If you don't turn it off, the implementation is allowed to do
nonstandard things (like define additional control characters in c_cc) that might cause
unexpected results, but you might need to leave IEXTEN enabled on some systems to get useful
features like hardware flow control.
3.6.2.5 c_cc
This is an array of characters that have special meanings on input. These characters are given
names like VINTR, VSTOP etc.; the names are indexes into the array.
(Two of these "characters" are not really characters at all, but control the behaviour of read()
when ICANON is disabled; these are VMIN and VTIME.)
The indexes are often referred to as though they were actual variables, e.g. "set VMIN to 1"
actually means "set c_cc[VMIN] to 1". The shorthand is useful and only occasionally
confusing.
Many of the slots in c_cc are only used if some other combination of flags is set:
Used only if ICANON is set
VEOF, VEOL, VERASE, VKILL (and also VEOL2, VSTATUS and VWERASE if defined
and IEXTEN is set)
Used only if ISIG is set
VINTR, VQUIT, VSUSP (and also VDSUSP if defined and IEXTEN is set)
Used only if IXON or IXOFF is set
VSTOP, VSTART
Used only if ICANON is not set
VMIN, VTIME
Implementations may define additional entries in c_cc. It may be prudent to initialise all the
entries to _POSIX_VDISABLE (the constant NCCS gives the array size) before setting the
specific values you wish to use.
VMIN and VTIME (which may share slots with VEOF and VEOL respectively, depending on the
implementation) have the following meaning. The value of VTIME is (if not 0) always
interpreted as a timer in tenths of seconds.
c_cc[VMIN] > 0, c_cc[VTIME] > 0
read() will return when either VMIN bytes of input are available, or if at least one
character has been read and VTIME has expired between characters, or if interrupted by a
signal.
c_cc[VMIN] > 0, c_cc[VTIME] == 0
read() will return when VMIN bytes of input are available, or if interrupted. Otherwise
it will wait indefinitely.
c_cc[VMIN] == 0, c_cc[VTIME] > 0
read() will return as soon as any input is available; if VTIME expires with no data
arriving, it will return with no characters read. (This conflicts slightly with the end-of-file
indication received in the event of modem hangup; using 1 for VMIN and either
alarm() or select() for a timeout avoids this particular problem.)
c_cc[VMIN] == 0, c_cc[VTIME] == 0
read() will always return immediately; if no data is available it will return with no
characters read (with the same problem as above).
4. System Information
4.1 How can I tell how much memory my
system has?
This is another `Frequently Unanswered Question'. In most cases, you should not even attempt to
find out.
If you really must, then it can usually be done, but in a highly system-dependent fashion. For
example, on Solaris, you can use sysconf(_SC_PHYS_PAGES) and
sysconf(_SC_PAGESIZE); on FreeBSD, you can use sysctl(); on Linux you can read
and parse `/proc/meminfo' (being careful to allow any of the historically valid formats for
this file); other systems may have their own methods. I'm not aware of any more portable
methods.
For HP-UX (9 and 10), the following code has been contributed:
#include <stdlib.h>
#include <stdio.h>
#include <pwd.h>
#include <shadow.h>
return shadow;
}
The problem is, that some systems do not keep the uid, or other information in the shadow
database.
4.2.3 How do I verify a user's password?
The fundamental problem here is, that various authentication systems exist, and passwords aren't
always what they seem. Also with the traditional one way encryption method used by most
UNIX flavours (out of the box), the encryption algorithm may differ, some systems use a one
way DES encryption, others like the international release of FreeBSD use MD5.
The most popular way is to have a one way encryption algorithm, where the password cannot be
decrypted. Instead the password is taken in clear text from input, and encrypted and checked
against the encrypted password in the database. The details of how to encrypt should really come
from your man page for crypt(), but here's a usual version:
5. Miscellaneous programming
5.1 How do I compare strings using wildcards?
The answer to that depends on what exactly you mean by `wildcards'.
There are two quite different concepts that qualify as `wildcards'. They are:
Filename patterns
These are what the shell uses for filename expansion (`globbing').
Regular Expressions
These are used by editors, grep, etc. for matching text, but they normally aren't applied to
filenames.
#include <stdio.h>
int main()
{
FILE *mail = popen(MAILPROG " -s 'Test Message' root", "w");
if (!mail)
{
perror("popen");
exit(1);
}
if (pclose(mail))
{
fprintf(stderr, "mail failed!\n");
exit(1);
}
}
If the text to be sent is already in a file, then one can do:
The recipients of a message can simply be specified on the command line. This has the drawback that
mail addresses can contain characters that give system() and popen() considerable grief, such as
single quotes, quoted strings etc. Passing these constructs successfully through shell interpretation
presents pitfalls. (One can do it by replacing any single quotes by the sequence single-quote backslash
single-quote single-quote, then surrounding the entire address with single quotes. Ugly, huh?)
Some of this unpleasantness can be avoided by eschewing the use of system() or popen(), and
resorting to fork() and exec() directly. This is sometimes necessary in any event; for example,
user-installed handlers for SIGCHLD will usually break pclose() to a greater or lesser extent.
Here's an example:
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sysexits.h>
/* #include <paths.h> if you have it */
#ifndef _PATH_SENDMAIL
#define _PATH_SENDMAIL "/usr/lib/sendmail"
#endif
while (recipients[num_recip])
++num_recip;
if (!num_recip)
return 0; /* sending to no recipients is successful */
/* fork */
/* Plumbing */
if (fd != STDIN_FILENO)
dup2(fd, STDIN_FILENO);
/* go for it: */
execv(_PATH_SENDMAIL, argvec);
_exit(EX_OSFILE);
default: /* parent */
free(argvec);
rc = waitpid(pid, &status, 0);
if (rc < 0)
return -1;
if (WIFEXITED(status))
return WEXITSTATUS(status);
return -1;
The `-t' option to sendmail instructs sendmail to parse the headers of the message, and use all the
recipient-type headers (i.e. To:, Cc: and Bcc:) to construct the list of envelope recipients. This has the
advantage of simplifying the sendmail command line, but makes it impossible to specify recipients
other than those listed in the headers. (This is not usually a problem.)
As an example, here's a program to mail a file on standard input to specified recipients as a MIME
attachment. Some error checks have been omitted for brevity. This requires the `mimencode' program
from the metamail distribution.
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
/* #include <paths.h> if you have it */
#ifndef _PATH_SENDMAIL
#define _PATH_SENDMAIL "/usr/lib/sendmail"
#endif
char tfilename[L_tmpnam];
char command[128+L_tmpnam];
void cleanup(void)
{
unlink(tfilename);
}
if (argc < 2)
{
fprintf(stderr, "usage: %s recipients...\n", argv[0]);
exit(2);
}
if (tmpnam(tfilename) == NULL
|| (msg = fopen(tfilename,"w")) == NULL)
exit(2);
atexit(cleanup);
fclose(msg);
msg = fopen(tfilename,"a");
if (!msg)
exit(2);
/* Subject */
fprintf(msg, "Subject: file sent by mail\n");
/* MIME stuff */
fputc('\n',msg);
fclose(msg);
/* invoke mailer */
return 0;
}
6. Use of tools
6.1 How can I debug the children after a fork?
Depending on the tools available there are various ways:
Your debugger may have options to select whether to follow the parent or the child process (or
both) after a fork(), which may be sufficient for some purposes.
Alternatively, your debugger may have an option which allows you to attach to a running process.
This can be used to attach to the child process after it has been started. If you don't need to
examine the very start of the child process, this is usually sufficient. Otherwise, you may wish to
insert a sleep() call after the fork() in the child process, or a loop such as the following:
{
volatile int f = 1;
while(f);
}
which will hang the child process until you explicitly set f to 0 using the debugger.
Remember, too, that actively using a debugger isn't the only way to find errors in your program;
utilities are available to trace system calls and signals on many unix flavours, and verbose logging
is also often useful.
/* end shrobj.c */
/* file hello.c */
#include <stdio.h>
main()
{
printf("%s\n", myfunc());
return 0;
}
/* end hello.c */
By far the best method if you want the library and build procedure to be anything approaching
portable is to use GNU Libtool. This is a small suite of utilities which know about the
platform-dependent aspects of building shared libraries; you can distribute the necessary bits with
your program, so that when the installer configures the package, he or she can decide what
libraries to build. Libtool works fine on systems which do not support shared libraries. It also
knows how to hook into GNU Autoconf and GNU Automake (if you use those tools to manage
your program's build procedure).
If you don't want to use Libtool, then for compilers other than gcc, you should change the
compiler options as follows:
AIX 3.2 using xlc (unverified)
Drop the `-fpic', and use `-bM:SRE -bE:libshared.exp' instead of `-shared'. You also need to
create a file `libshared.exp' containing the list of symbols to export, in this case
`myfunc'. In addition, use `-e _nostart' when linking the library (on newer versions of AIX, I
believe this changes to `-bnoentry').
SCO OpenServer 5 using the SCO Development System (unverified)
Shared libraries are only available on OS5 if you compile to ELF format, which requires the
`-belf' option. Use `-Kpic' instead of `-fpic', and `cc -belf -G' for the link step.
Solaris using SparcWorks compilers
Use `-pic' instead of `-fpic', and use `ld -G' instead of `gcc -shared'.
(Submission of additional entries for the above table is encouraged.)
Other issues to watch out for:
● AIX and (I believe) Digital Unix don't require the -fpic option, because all code is position
independent.
● AIX normally requires that you create an `export file', which is a list of symbols to be
exported from the shared library. Some versions of the linker (possibly only the SLHS
linker, svld?) have an option to export all symbols.
● If you want to refer to your shared library using the conventional `-l' parameter to the linker,
you will have to understand how shared libraries are searched for at runtime on your
system. The most common method is by using the LD_LIBRARY_PATH environment
variable, but there is usually an additional option to specify this at link time.
● Most implementations record the expected runtime location of the shared library internally.
Thus, moving a library from one directory to another may prevent it from working. Many
systems have an option to the linker to specify the expected runtime location (the `-R' linker
option on Solaris, for example, or the LD_RUN_PATH environment variable).
● ELF and a.out implementations may have a linker option `-Bsymbolic' which causes
internal references within the library to be resolved. Otherwise, on these systems, all symbol
resolution is deferred to the final link, and individual routines in the main program can
override ones in the library.
void dump_stack(void)
{
char s[160];
return;
}
You will need to tweak the commands and parameters to dbx according to your system, or even
substitute another debugger such as gdb, but this is still the most general solution to this particular
problem that I've ever seen. Kudos to Ralph Corderoy for this one :-)
Here's a list of the command lines required for some systems:
Most systems using dbx
"/bin/echo 'where\ndetach' | dbx /path/to/program %d"
AIX
"/bin/echo 'where\ndetach' | dbx -a %d"
IRIX
"/bin/echo 'where\ndetach' | dbx -p %d"
Examples
Catching SIGCHLD
int main()
{
struct sigaction act;
pid_t pid;
/*
* We're only interested in children that have terminated, not ones
* which have been stopped (eg user pressing control-Z at terminal)
*/
act.sa_flags = SA_NOCLDSTOP;
/*
* Make these values effective. If we were writing a real
* application, we would probably save the old value instead of
* passing NULL.
*/
if (sigaction(SIGCHLD, &act, NULL) < 0)
{
fprintf(stderr, "sigaction failed\n");
return 1;
}
/* Fork */
switch (pid = fork())
{
case -1:
fprintf(stderr, "fork failed\n");
return 1;
default: /* parent */
sleep(10); /* give child time to finish */
}
return 0;
}
/*
* The signal handler function -- only gets called when a SIGCHLD
* is received, ie when a child terminates
*/
void sig_chld(int signo)
{
int status, child_val;
/*
* We now have the info in 'status' and can manipulate it using
* the macros in wait.h.
*/
if (WIFEXITED(status)) /* did child exit normally? */
{
child_val = WEXITSTATUS(status); /* get child's exit status */
printf("child's exited normally with status %d\n", child_val);
}
}
Reading the process table -- SUNOS 4 version
#define _KMEMUSER
#include <sys/proc.h>
#include <kvm.h>
#include <fcntl.h>
char regexpstr[256];
#define INIT register char *sp=regexpstr;
#define GETC() (*sp++)
#define PEEKC() (*sp)
#define UNGETC(c) (--sp)
#define RETURN(pointer) return(pointer);
#define ERROR(val)
#include <regexp.h>
pid_t
getpidbyname(char *name,pid_t skipit)
{
kvm_t *kd;
char **arg;
int error;
char *p_name=NULL;
char expbuf[256];
char **freeme;
int curpid;
struct user * cur_user;
struct user myuser;
struct proc * cur_proc;
if((kd=kvm_open(NULL,NULL,NULL,O_RDONLY,NULL))==NULL){
return(-1);
}
sprintf(regexpstr,"^.*/%s$",name);
compile(NULL,expbuf,expbuf+256,'\0');
while(cur_proc=kvm_nextproc(kd)){
curpid = cur_proc->p_pid;
if((cur_user=kvm_getu(kd,cur_proc))!=NULL){
error=kvm_getcmd(kd,cur_proc,cur_user,&arg,NULL);
if(error==-1){
if(cur_user->u_comm[0]!='\0'){
p_name=cur_user->u_comm;
}
}
else{
p_name=arg[0];
}
}
if(p_name){
if(!strcmp(p_name,name)){
if(error!=-1){
free(arg);
}
if(skipit!=-1 && ourretval==skipit){
ourretval=-1;
}
else{
close(fd);
break;
}
break;
}
else{
if(step(p_name,expbuf)){
if(error!=-1){
free(arg);
}
break;
}
}
}
if(error!=-1){
free(arg);
}
p_name=NULL;
}
kvm_close(kd);
if(p_name!=NULL){
return(curpid);
}
return (-1);
}
pid_t
getpidbyname(char *name,pid_t skipit)
{
DIR *dp;
struct dirent *dirp;
prpsinfo_t retval;
int fd;
pid_t ourretval=-1;
if((dp=opendir("/proc"))==NULL){
return -1;
}
chdir("/proc");
while((dirp=readdir(dp))!=NULL){
if(dirp->d_name[0]!='.'){
if((fd=open(dirp->d_name,O_RDONLY))!=-1){
if(ioctl(fd,PIOCPSINFO,&retval)!=-1){
if(!strcmp(retval.pr_fname,name)){
ourretval=(pid_t)atoi(dirp->d_name);
if(skipit!=-1 && ourretval==skipit){
ourretval=-1;
}
else{
close(fd);
break;
}
}
}
close(fd);
}
}
}
closedir(dp);
return ourretval;
}
#include <stdio.h>
#include <procinfo.h>
pid = *nextPid;
while(1)
{
if(getprocs(&pi, sizeof pi, 0, 0, &pid, 1) != 1)
break;
if(!strcmp(name, pi.pi_comm))
{
retval = pi.pi_pid;
*nextPid = pid;
break;
}
}
return retval;
}
if(argc == 1)
{
printf("syntax: %s <program> [program ...]\n",argv[0]);
exit(1);
}
/* figure out where the command name is from the column headings.
* (BSD-ish machines put the COMMAND in the 5th column, while SysV
* seems to put CMD or COMMAND in the 4th column.)
*/
for (linep = line; ; linep = (char *)0)
{
if ((char *)0 == (token = strtok(linep, " \t\n")))
{
pclose(fp);
return (char *)0;
}
if (0 == strcmp("COMMAND", token) || 0 == strcmp("CMD", token))
{ /* we found the COMMAND column */
cmd = token;
break;
}
}
status = pclose(fp);
if (!WIFEXITED(status) || 0 != WEXITSTATUS(status))
return (char *)0;
return token;
}
int main(int argc, char *argv[])
{
puts(procname(atoi(argv[1])));
exit(EXIT_SUCCESS);
}
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
/* daemon() - detach process from user and disappear into the background
* returns -1 on failure, but you can't do much except exit in that case
* since we may already have forked. This is based on the BSD version,
* so the caller is responsible for things like the umask, etc.
*/
switch (fork())
{
case 0: break;
case -1: return -1;
default: _exit(0);
}
if (!nochdir)
chdir("/");
if (!noclose)
{
closeall(0);
open("/dev/null",O_RDWR);
dup(0); dup(0);
}
return 0;
}
int fork2()
{
pid_t pid;
int rc;
int status;
if (!(pid = fork()))
{
switch (fork())
{
case 0: return 0;
case -1: _exit(errno); /* assumes all errnos are <256 */
default: _exit(0);
}
}
return -1;
}
An example of using the above functions:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <errno.h>
int daemon(int,int);
int fork2(void);
void closeall(int);
fclose(out);
}
/* This is the daemon's main work -- listen for connections and spawn */
void process()
{
struct sockaddr_in addr;
int addrlen = sizeof(addr);
int sock = socket(AF_INET, SOCK_STREAM, 0);
int flag = 1;
int rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
&flag, sizeof(flag));
if (rc < 0)
errexit("setsockopt");
addr.sin_family = AF_INET;
addr.sin_port = htons(TCP_PORT);
addr.sin_addr.s_addr = INADDR_ANY;
rc = listen(sock, 5);
if (rc < 0)
errexit("listen");
for (;;)
{
rc = accept(sock, (struct sockaddr *) &addr, &addrlen);
if (rc >= 0)
switch (fork2())
{
case 0: close(sock); run_child(rc); _exit(0);
case -1: errreport("fork2"); close(rc); break;
default: close(rc);
}
}
}
int main()
{
if (daemon(0,0) < 0)
{
perror("daemon");
exit(2);
}
process();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h> /* maybe; system-dependent */
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
/* system-dependent */
#define CFLAGS_HARDFLOW (CRTSCTS)
if (fd < 0)
return close_and_complain(-1, "open", errno);
/* local modes */
{
int i;
#ifdef _POSIX_VDISABLE
attr.c_cc[0] = _POSIX_VDISABLE;
#else
attr.c_cc[0] = fpathconf(fd, _PC_VDISABLE);
#endif
for (i = 1; i < NCCS; i++)
attr.c_cc[i] = attr.c_cc[0];
}
attr.c_cc[VSTART] = 0x11;
attr.c_cc[VSTOP] = 0x13;
attr.c_cc[VMIN] = 1;
attr.c_cc[VTIME] = 0;
/* baud rate */
cfsetispeed(&attr, baud);
cfsetospeed(&attr, baud);
/* write settings */
return fd;
}
if (usec < 0)
usec += 1000000, --sec;
res->tv_sec = sec;
res->tv_usec = usec;
/* this doesn't try and cope with pathological strings (e.g. ababc)
* timeout is in millisecs
* A more usual approach to this is to use alarm() for the timeout.
* This example avoids signal handling for simplicity and to illustrate
* an alternative approach
*/
gettimeofday(&end, NULL);
timeradd(&end, timeo/1000, timeo%1000);
FD_ZERO(&fds);
FD_SET(fd, &fds);
if (select(fd+1, &fds, NULL, NULL, &left) <= 0)
return -1;
if (read(fd, &c, 1) != 1)
return -1;
return 0;
}
if (argc < 2)
die("no port specified");
putchar('\n');
tcflush(fd, TCIOFLUSH);
close(fd);
return 0;
}
Job Control example
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
sigemptyset(&sigs);
sigaddset(&sigs,SIGTTOU);
sigprocmask(SIG_BLOCK, &sigs, &oldsigs);
rc = tcsetpgrp(ctty, pgrp);
return rc;
}
/* Like fork(), but does job control. FG is true if the newly-created
* process is to be placed in the foreground. (This implicitly puts
* the calling process in the background, so watch out for tty I/O
* after doing this.) PGRP is -1 to create a new job, in which case
* the returned pid is also the pgrp of the new job, or specifies an
* existing job in the same session (normally used only for starting
* second or subsequent process in a pipeline). */
if (fg)
{
pid_t curpgrp;
case 0: /* child */
if (pgrp < 0)
pgrp = getpid();
return 0;
default: /* parent */
if (pgrp < 0)
pgrp = pid;
setpgid(pid, pgrp);
return pid;
}
/*NOTREACHED*/
}
if (curpgrp != getpgrp())
return errno = EPERM, (pid_t)-1;
int foreground_self()
{
pid_t curpgrp;
int ctty;
if (!cmd)
return errno = EINVAL, -1;
if (!error)
{
pid_t pid = spawn_job(0, -1);
switch (pid)
{
case -1: /* fork failure */
error = errno;
break;
execl("/bin/sh","sh","-c",cmd,(char*)NULL);
_exit(127);
close(nullfd);
if (infd)
close(pipefds[0][0]), *infd = pipefds[0][1];
if (outfd)
close(pipefds[1][1]), *outfd = pipefds[1][0];
if (errfd)
close(pipefds[2][1]), *errfd = pipefds[2][0];
return pid;
}
}
{
int i,j;
for (i = 0; i < 3; ++i)
for (j = 0; j < 2; ++j)
if (pipefds[i][j] >= 0)
close(pipefds[i][j]);
}
if (nullfd >= 0)
close(nullfd);
/*--------------------------------------------------------------------*/
/* This bit is a somewhat trivial example of using the above. */
#ifndef WCOREDUMP
/* If WCOREDUMP is missing, you might want to supply a correct
* definition for your platform (this is usually (status & 0x80) but
* not always) or punt (as in this example) by assuming no core dumps.
*/
# define WCOREDUMP(status) (0)
#endif
int check_children()
{
pid_t pid;
int status;
int count = 0;
++count;
if (WIFEXITED(status))
fprintf(stderr,"Process %ld exited with return code %d\n",
(long)pid, WEXITSTATUS(status));
else if (WIFSIGNALED(status))
fprintf(stderr,"Process %ld killed by signal %d%s\n",
(long)pid, WTERMSIG(status),
WCOREDUMP(status) ? " (core dumped)" : "");
else if (WIFSTOPPED(status))
fprintf(stderr,"Process %ld stopped by signal %d\n",
(long)pid, WSTOPSIG(status));
else
fprintf(stderr,"Unexpected status - pid=%ld, status=0x%x\n",
(long)pid, status);
}
return count;
}
int main()
{
struct sigaction act;
int sigcount = 0;
act.sa_handler = sighandler;
act.sa_flags = 0;
sigemptyset(&act.sa_mask);
sigaction(SIGINT,&act,NULL);
sigaction(SIGQUIT,&act,NULL);
sigaction(SIGTERM,&act,NULL);
sigaction(SIGTSTP,&act,NULL);
sigaction(SIGCHLD,&act,NULL);
if (!check_children())
pause();
}
fprintf(stderr,"Done - exiting\n");
return 0;
}
This will search for words or phrases in the contents of the FAQ. Multiple keywords are not
allowed. There are no special characters, and searches are not case sensitive.
| FAQ Home || Your User Profile || About Me || Books |
Contents are Copyright© by the author of the content. Permission is granted to do anything you like with this contents so long as you don't claim the
work, or copyright for yourself. The Self Serve FAQ is Copyright© by it's authors, and available under the terms of the GNU GPL.
User Profile
Setting up a user profile simply sets some cookies in your browser so that your name and email
address come up automatically when you post comments. Cookies are also used to notify you
which questions are new to you. Nothing about you (other than your comments) is stored on the
web server, so if you change browsers, or loose your cookie file, the settings will dissapear.
I know a lot of people don't like cookies, and that is just fine. This feature is provided for those
who want it as a convenience. If you don't like cookies, don't fill out the form, and they won't be
sent to you.
Your Name:
Your Email:
Create Profile
Contents are Copyright© by the author of the content. Permission is granted to do anything you like with this contents so long as you don't claim the
work, or copyright for yourself. The Self Serve FAQ is Copyright© by it's authors, and available under the terms of the GNU GPL.
My name is Vic Metcalfe, and I maintain the UNIX Socket FAQ, and this
web site. I started learning how to write network applications when I wanted
to create a MS-Windows GUI for CVS. I don't run Windows anymore, but
I'm grateful to Microsoft for re-creating the need for UNIX.
I run mostly Linux, and I also have an old SparcStation 2 running Solaris 2.6,
and another machine running Solaris x86 2.5.
Outside of computers I have a beautiful wife, Angela, a tiny baby girl named
Carolyn, and a dog named Bjarne after Mr. Stroustrup of C++ fame. I hope he wouldn't take
any offense; he's a good dog.
I also have an interested in television. I use to direct a local cable show, and I've taken six
courses at the Second City in Toronto on improv. I highly recommend their classes to anyone.
Contents are Copyright© by the author of the content. Permission is granted to do anything you like with this contents so long as you don't claim the
work, or copyright for yourself. The Self Serve FAQ is Copyright© by it's authors, and available under the terms of the GNU GPL.
You will find reviews and comments on these books from amazon.com,
where you can also buy the books. When you do, I get a small cut of the
action. It has worked out to about $100/year. Thanks to all of you who
have purchased books here! It is nice to receive a little compensation for
the work done on the faq.
This is the most often recommended book
about programming in the Unix
Advanced Programming in the Unix Environment environment. If you take the subject
seriously and don't have a copy, I strongly
By W. Richard Stevens
suggest you pick this one up. It contains
ISBN: 0-201-56317-7
explanations of many advanced topics,
complete with commented example code.
This book rocks.
If you are focusing on writing Network
applications for Unix, this is also a must
Unix Network Programming : Networking APIs: have book. This is the first, and only
volume currently available of a three
Sockets and Xti
volume series. The other two books are in
By W. Richard Stevens development. You can also still get the
ISBN: 0-13-490012-X original single volume Unix Network
Programming, as featured in the motion
picture "Wayne's World 2".
UNIX Network Programming Volume 2:
Interprocess Communications Volume 2 of the popular UNIX Network
By W. Richard Stevens Programming series
ISBN: 0130810819
I used this book as an introduction to
programming in the Unix environment. It
POSIX Programmer's Guide was great because it focuses on writing
By Donald Lewine portable code, and contains a lot a good
ISBN: 0-937175-73-0 general programming advice. If you are
interested in portability, you will find this
book a good read.
The casual browser might notice that
almost all of my recommended books are
written by Stevens. This is because I have
TCP/IP Illustrated, Volume 1 : The Protocols found his books to be the most useful.
This book in particular is a great help
By W. Richard Stevens
when a network application isn't behaving
ISBN: 0201633469
the way you would expect it to. It will
help you to understand what is happening
at the protocol level so that you can solve
problems at the application level.
Contents are Copyright© by the author of the content. Permission is granted to do anything you like with this contents so long as you don't claim the
work, or copyright for yourself. The Self Serve FAQ is Copyright© by it's authors, and available under the terms of the GNU GPL.
Self Serve FAQ
Download the Self Serve FAQ 0.2 Here. (Zip file Here)
This is not the UNIX Socket FAQ. Questions not related to the Self Serve FAQ software
will be deleted. For UNIX network programming questions, please use the UNIX Socket
FAQ.
Welcome to the home of the "Self Serve FAQ"! The "Self Serve FAQ" is software to help
maintain lists of questions and answers using the web. It is available under the GNU GPL at no
cost with source code.
The software is a set of PHP scripts, and requires an Apache server with mod_php4 or
mod_php3 built with MySQL support.
Uncategorized Questions:
1. Getting a cookie error
2. Installation problem - admin.php3
3. Who can answer a question?
4. Who can help me on this problem?
5. test
6. Am I an advanced beginner?
7. Contabilidad
8. Are you interested in listing sites that use this?
9. testing
10. Problem with detail.php
11. subjet
12. subject
13. Hey
14. tring it NOW
15. rt
16. Microsoft is super!
17. Content Management
18. test
19. This is Mike's test
20. Subjects can't have single quote without \
21. prova
22. fucker, fucker
23. Socket Implementation.
24. wella
25. arrrèt
26. ’†•§
27.
28. test de faq
29.
30. bug with other character sets
31. c source code to get connect to the internet and get the contents
32. c source code to get connect to the internet and get the contents
33. pop
34. stst
35.
36. Bugs
37. Using this SSFAQ
38. ƒeƒXƒg
39.
40. gdfs
41. Guess what??
42. try
43. Hola, estoy haciendo una pregunta
44. no listen
45.
46. Anything Goes
47. ÇáÓáÇã Úáíßã
48. Bug in header when you view the questions...
49. ƒeƒXƒg
50. ÓÄÇá
51. Prova III
52. who is the man ?
53. The bototm linee
54. Configuration
55. dfdfdf
56. problem
57. query about socket
58. This is a test
59. Where will this question end up?
60. How to categorise questions?
61. Running create.sql
62. Is this a good idea?
63. A new q from me.
64. How to distinguish?
65. dfsgdfggggggggggggggggggg
66. test
67.
68. teste
69. dfd
70. test
71. Test
72. comment faire un essai
73. tertre
74. Should you give a blind man a digital watch?
75.
76. En liten provtur
77. if my client encounter the firewall....
78. Eesti keeles polegi
Categorized Questions:
1. General Questions
1. What is the 'Self Serve FAQ'?
2. What are the system requirements?
3. Where can I get it?
2. From the Users Perspective
1. Place test comments here
2. Can users specify which section they want to use?
3. What is beind the different comment types ?
3. Administering the Self Serve FAQ
1. Why does it look like this? How can I customize it?
2. Why MySQL? Can I use another database?
3. Creating the database and user for MySQL
4. Problem with a proxy server?
4. Requests for Features
1. Some possible additions maybe ?
2. Faq layout
5. Bugs
1. Cannot get to the save or delete buttons
2. Static version of FAQ contains blank entries
3. PHP4 Installed, now the FAQ is not working.
4. Problem with magic_quotes and addslashes()
Contents are Copyright© by the author of the content. Permission is granted to do anything you like with this contents so long as you don't claim the
work, or copyright for yourself. The Self Serve FAQ is Copyright© by it's authors, and available under the terms of the GNU GPL.
Unix Socket FAQ
Welcome to the home of the UNIX Socket FAQ!
There's some really major "under the hood" changes I've just made to the FAQ software that drives this site. I've
seperated the content from the functionality, and I'm releasing the source under the GPL. I've named the software "Self
Serve FAQ" because of the way it empowers the users to add questions and provide answers without intervention from
the FAQ maintainer. I've created a new site on lcg.org for it at http://www.lcg.org/ssfaq/ and you can find out more about
it there.
I've added a couple of new features. First, you can download a single file version of the faq here. Second, the main page
now shows the most recent updates. Let me know if you notice any quirks.
I've "upgraded" the sock-faq to the new software, so please let me know if you find any problems by posting to the new
ssfaq site. Hopefully I'll get any problems worked out early on.
My mirrors appear to have dissapeared, and it may be because they were difficult to keep up-to-date before. One of the
first things I want to work on with the new software is making the whole mirror thing easier, so I hope to have mirrors
available soon.
If you are looking for Dr. Charles Campbell's Simple Sockets Library, you can download version 2.09 here.
Categorized Questions:
1. General Information and Concepts
1. What's new?
2. About this FAQ
3. Who is this FAQ for?
4. What are Sockets?
5. How do Sockets Work?
6. Where can I get source code for the book [book title]?
7. Where can I get more information?
8. Where can I get the sample source code?
2. Questions regarding both Clients and Servers (TCP/SOCK_STREAM)
1. How can I tell when a socket is closed on the other end?
2. What's with the second parameter in bind()?
3. How do I get the port number for a given service?
4. If bind() fails, what should I do with the socket descriptor?
5. How do I properly close a socket?
6. When should I use shutdown()?
7. Please explain the TIME_WAIT state.
8. Why does it take so long to detect that the peer died?
9. What are the pros/cons of select(), non-blocking I/O and SIGIO?
10. Why do I get EPROTO from read()?
11. How can I force a socket to send the data in its buffer?
12. Where can I get a library for programming sockets?
13. How come select says there is data, but read returns zero?
14. Whats the difference between select() and poll()?
15. How do I send [this] over a socket
16. How do I use TCP_NODELAY?
17. What exactly does the Nagle algorithm do?
18. What is the difference between read() and recv()?
19. I see that send()/write() can generate SIGPIPE. Is there any advantage to handling the signal, rather than just
ignoring it and checking for the EPIPE error?
20. After the chroot(), calls to socket() are failing. Why?
21. Why do I keep getting EINTR from the socket calls?
22. When will my application receive SIGPIPE?
23. What are socket exceptions? What is out-of-band data?
24. How can I find the full hostname (FQDN) of the system I'm running on?
25. How do I monitor the activity of sockets?
3. Writing Client Applications (TCP/SOCK_STREAM)
1. How do I convert a string into an internet address?
2. How can my client work through a firewall/proxy server?
3. Why does connect() succeed even before my server did an accept()?
4. Why do I sometimes lose a server's address when using more than one server?
5. How can I set the timeout for the connect() system call?
6. Should I bind() a port number in my client program, or let the system choose one for me on the connect()
call?
7. Why do I get "connection refused" when the server isn't running?
8. What does one do when one does not know how much information is comming over the socket? Is there a
way to have a dynamic buffer?
9. How can I determine the local port number?
4. Writing Server Applications (TCP/SOCK_STREAM)
1. How come I get "address already in use" from bind()?
2. Why don't my sockets close?
3. How can I make my server a daemon?
4. How can I listen on more than one port at a time?
5. What exactly does SO_REUSEADDR do?
6. What exactly does SO_LINGER do?
7. What exactly does SO_KEEPALIVE do?
8. 4.8 How can I bind() to a port number < 1024?
9. How do I get my server to find out the client's address / hostname?
10. How should I choose a port number for my server?
11. What is the difference between SO_REUSEADDR and SO_REUSEPORT?
12. How can I write a multi-homed server?
13. How can I read only one character at a time?
14. I'm trying to exec() a program from my server, and attach my socket's IO to it, but I'm not getting all the data
across. Why?
5. Writing UDP/SOCK_DGRAM applications
1. When should I use UDP instead of TCP?
2. What is the difference between "connected" and "unconnected" sockets?
3. Does doing a connect() call affect the receive behaviour of the socket?
4. How can I read ICMP errors from "connected" UDP sockets?
5. How can I be sure that a UDP message is received?
6. How can I be sure that UDP messages are received in order?
7. How often should I re-transmit un-acknowleged messages?
8. How come only the first part of my datagram is getting through?
9. Why does the socket's buffer fill up sooner than expected?
6. Advanced Socket Programming
1. How would I put my socket in non-blocking mode?
2. How can I put a timeout on connect()?
3. How do I complete a read if I've only read the first part of something, without again calling select()?
4. How to use select routine
5. RAW sockets
6. Restricting a socket to a given interface
7. Receiving all incoming traffic through a RAW-socket?
8. Multicasting
9. getting IP header of a UDP message
10. To fork or not to fork?
7. Sample Source Code
1. Looking for a good C++ socket library
2. perl examples of source code
3. Where is the source code from Richard Stevens' books?
8. Bugs and Strange Behaviour
1. send() hangs up when sending to a switched off computer
2. Error when using inetd
reply
connect ftp.zymsys.com
binary
uuencode
get pub/sockets/examples.tar.gz
quit
Save the reply as examples.uu, and type:
% uudecode examples.uu
% gunzip examples.tar.gz
% tar xf examples.tar
This will create a directory called socket-faq-examples which contains the sample code from this faq, plus a sample client
and server for both tcp and udp.
Note that this package requires the gnu unzip program to be installed on your system. It is very common, but if you don't
have it you can get the source for it from:
ftp://prep.ai.mit.edu/pub/gnu/gzip-1.2.4.tar
If you don't have ftp access, you can obtain it in a way similar to obtaining the sample source. I'll leave the exact changes
to the body of the message as an excersise for the reader.
rc = read(sock,buf,sizeof(buf));
if (rc > 0)
{
write(file,buf,rc);
/* error checking on file omitted */
}
else if (rc == 0)
{
close(file);
close(sock);
/* file received successfully */
}
else /* rc < 0 */
{
/* close file and delete it, since data is not complete
report error, or whatever */
}
2. What's with the second parameter in bind()?
The man page shows it as "struct sockaddr *my_addr". The sockaddr struct though is just a place holder
for the structure it really wants. You have to pass different structures depending on what kind of socket you have. For an
AF_INET socket, you need the sockaddr_in structure. It has three fields of interest:
sin_family
Set this to AF_INET.
sin_port
The network byte-ordered 16 bit port number
sin_addr
The host's ip number. This is a struct in_addr, which contains only one field, s_addr which is a u_long.
3. How do I get the port number for a given service?
Use the getservbyname() routine. This will return a pointer to a servent structure. You are interested in the
s_port field, which contains the port number, with correct byte ordering (so you don't need to call htons() on it).
Here is a sample routine:
/* Take a service name, and a service type, and return a port number. If the
service name is not found, it tries it as a decimal number. The number
returned is byte ordered for the network. */
int atoport(char *service, char *proto) {
int port;
long int lport;
struct servent *serv;
char *errpos;
/* First try to read it from /etc/services */
serv = getservbyname(service, proto);
if (serv != NULL)
port = serv->s_port;
else { /* Not in services, maybe a number? */
lport = strtol(service,&errpos,0);
if ( (errpos[0] != 0) || (lport < 1) || (lport > 5000) )
return -1; /* Invalid port address */
port = htons(lport);
}
return port;
}
4. If bind() fails, what should I do with the socket descriptor?
If you are exiting, I have been assured by Andrew that all unixes will close open file descriptors on exit. If you are not
exiting though, you can just close it with a regular close() call.
5. How do I properly close a socket?
This question is usually asked by people who try close(), because they have seen that that is what they are supposed
to do, and then run netstat and see that their socket is still active. Yes, close() is the correct method. To read about the
TIME_WAIT state, and why it is important, refer to 2.7 Please explain the TIME_WAIT state..
6. When should I use shutdown()?
From Michael Hunter ([email protected]):
shutdown() is useful for deliniating when you are done providing a request to a server using TCP. A typical use is to
send a request to a server followed by a shutdown(). The server will read your request followed by an EOF (read of 0
on most unix implementations). This tells the server that it has your full request. You then go read blocked on the socket.
The server will process your request and send the necessary data back to you followed by a close. When you have
finished reading all of the response to your request you will read an EOF thus signifying that you have the whole
response. It should be noted the TTCP (TCP for Transactions -- see R. Steven's home page) provides for a better method
of tcp transaction management.
S.Degtyarev ([email protected]) wrote a nice in-depth message to me about this. He shows a practical example of
using shutdown() to aid in synchronization of client processes when one is the "reader" process, and the other is the
"writer" process. A portion of his message follows:
Sockets are very similar to pipes in the way they are used for data transfer and client/server transactions, but not like
pipes they are bidirectional. Programs that use sockets often fork() and each process inherits the socket descriptor. In
pipe based programs it is strictly recommended to close all the pipe ends that are not used to convert the pipe line to
one-directional data stream to avoid data losses and deadlocks. With the socket there is no way to allow one process only
to send data and the other only to receive so you should always keep in mind the consequences.
Generally the difference between close() and shutdown() is: close() closes the socket id for the process but the
connection is still opened if another process shares this socket id. The connection stays opened both for read and write,
and sometimes this is very important. shutdown() breaks the connection for all processes sharing the socket id. Those
who try to read will detect EOF, and those who try to write will reseive SIGPIPE, possibly delayed while the kernel
socket buffer will be filled. Additionally, shutdown() has a second argument which denotes how to close the
connection: 0 means to disable further reading, 1 to disable writing and 2 disables both.
The quick example below is a fragment of a very simple client process. After establishing the connection with the server
it forks. Then child sends the keyboard input to the server until EOF is received and the parent receives answers from the
server.
/*
* Sample client fragment,
* variables declarations and error handling are omitted
*/
s=connect(...);
close(s);
exit(0);
}
Assume that a connection is in ESTABLISHED state, and the client is about to do an orderly release. The client's
sequence no. is Sc, and the server's is Ss. The pipe is empty in both directions.
Client Server
====== ======
ESTABLISHED ESTABLISHED
(client closes)
ESTABLISHED ESTABLISHED
------->>
FIN_WAIT_1
<<--------
FIN_WAIT_2 CLOSE_WAIT
<<-------- (server closes)
LAST_ACK
, ------->>
TIME_WAIT CLOSED
(2*msl elapses...)
CLOSED
Note: the +1 on the sequence numbers is because the FIN counts as one byte of data. (The above diagram is equivalent to
fig. 13 from RFC 793).
Now consider what happens if the last of those packets is dropped in the network. The client has done with the
connection; it has no more data or control info to send, and never will have. But the server does not know whether the
client received all the data correctly; that's what the last ACK segment is for. Now the server may or may not care
whether the client got the data, but that is not an issue for TCP; TCP is a reliable rotocol, and must distinguish between
an orderly connection close where all data is transferred, and a connection abort where data may or may not have been
lost.
So, if that last packet is dropped, the server will retransmit it (it is, after all, an unacknowledged segment) and will expect
to see a suitable ACK segment in reply. If the client went straight to CLOSED, the only possible response to that
retransmit would be a RST, which would indicate to the server that data had been lost, when in fact it had not been.
(Bear in mind that the server's FIN segment may, additionally, contain data.)
DISCLAIMER: This is my interpretation of the RFCs (I have read all the TCP-related ones I could find), but I have not
attempted to examine implementation source code or trace actual connections in order to verify it. I am satisfied that the
logic is correct, though.
More commentarty from Vic:
The second issue was addressed by Richard Stevens ( [email protected], author of "Unix Network Programming", see
1.6 Where can I get source code for the book [book title]?). I have put together quotes from some of his postings and
email which explain this. I have brought together paragraphs from different postings, and have made as few changes as
possible.
From Richard Stevens ( [email protected]):
If the duration of the TIME_WAIT state were just to handle TCP's full-duplex close, then the time would be much
smaller, and it would be some function of the current RTO (retransmission timeout), not the MSL (the packet lifetime).
A couple of points about the TIME_WAIT state.
● The end that sends the first FIN goes into the TIME_WAIT state, because that is the end that sends the final ACK.
If the other end's FIN is lost, or if the final ACK is lost, having the end that sends the first FIN maintain state about
the connection guarantees that it has enough information to retransmit the final ACK.
● Realize that TCP sequence numbers wrap around after 2**32 bytes have been transferred. Assume a connection
between A.1500 (host A, port 1500) and B.2000. During the connection one segment is lost and retransmitted. But
the segment is not really lost, it is held by some intermediate router and then re-injected into the network. (This is
called a "wandering duplicate".) But in the time between the packet being lost & retransmitted, and then
reappearing, the connection is closed (without any problems) and then another connection is established between
the same host, same port (that is, A.1500 and B.2000; this is called another "incarnation" of the connection). But
the sequence numbers chosen for the new incarnation just happen to overlap with the sequence number of the
wandering duplicate that is about to reappear. (This is indeed possible, given the way sequence numbers are chosen
for TCP connections.) Bingo, you are about to deliver the data from the wandering duplicate (the previous
incarnation of the connection) to the new incarnation of the connection. To avoid this, you do not allow the same
incarnation of the connection to be reestablished until the TIME_WAIT state terminates. Even the TIME_WAIT
state doesn't complete solve the second problem, given what is called TIME_WAIT assassination. RFC 1337 has
more details.
● The reason that the duration of the TIME_WAIT state is 2*MSL is that the maximum amount of time a packet can
wander around a network is assumed to be MSL seconds. The factor of 2 is for the round-trip. The recommended
value for MSL is 120 seconds, but Berkeley-derived implementations normally use 30 seconds instead. This means
a TIME_WAIT delay between 1 and 4 minutes. Solaris 2.x does indeed use the recommended MSL of 120
seconds.
A wandering duplicate is a packet that appeared to be lost and was retransmitted. But it wasn't really lost ... some router
had problems, held on to the packet for a while (order of seconds, could be a minute if the TTL is large enough) and then
re-injects the packet back into the network. But by the time it reappears, the application that sent it originally has already
retransmitted the data contained in that packet.
Because of these potential problems with TIME_WAIT assassinations, one should not avoid the TIME_WAIT state by
setting the SO_LINGER option to send an RST instead of the normal TCP connection termination (FIN/ACK/FIN/ACK).
The TIME_WAIT state is there for a reason; it's your friend and it's there to help you :-)
I have a long discussion of just this topic in my just-released "TCP/IP Illustrated, Volume 3". The TIME_WAIT state is
indeed, one of the most misunderstood features of TCP.
I'm currently rewriting "Unix Network Programming" (see 1.6 Where can I get source code for the book [book title]?).
and will include lots more on this topic, as it is often confusing and misunderstood.
An additional note from Andrew:
Closing a socket: if SO_LINGER has not been called on a socket, then close() is not supposed to discard data. This is
true on SVR4.2 (and, apparently, on all non-SVR4 systems) but apparently not on SVR4; the use of either
shutdown() or SO_LINGER seems to be required to guarantee delivery of all data.
8. Why does it take so long to detect that the peer died?
From Andrew Gierth ( [email protected]):
Because by default, no packets are sent on the TCP connection unless there is data to send or acknowledge.
So, if you are simply waiting for data from the peer, there is no way to tell if the peer has silently gone away, or just isn't
ready to send any more data yet. This can be a problem (especially if the peer is a PC, and the user just hits the Big
Switch...).
One solution is to use the SO_KEEPALIVE option. This option enables periodic probing of the connection to ensure that
the peer is still present. BE WARNED: the default timeout for this option is AT LEAST 2 HOURS. This timeout can
often be altered (in a system-dependent fashion) but not normally on a per-connection basis (AFAIK).
RFC1122 specifies that this timeout (if it exists) must be configurable. On the majority of Unix variants, this
configuration may only be done globally, affecting all TCP connections which have keepalive enabled. The method of
changing the value, moreover, is often difficult and/or poorly documented, and in any case is different for just about
every version in existence.
If you must change the value, look for something resembling tcp_keepidle in your kernel configuration or network
options configuration.
If you're sending to the peer, though, you have some better guarantees; since sending data implies receiving ACKs from
the peer, then you will know after the retransmit timeout whether the peer is still alive. But the retransmit timeout is
designed to allow for various contingencies, with the intention that TCP connections are not dropped simply as a result of
minor network upsets. So you should still expect a delay of several minutes before getting notification of the failure.
The approach taken by most application protocols currently in use on the Internet (e.g. FTP, SMTP etc.) is to implement
read timeouts on the server end; the server simply gives up on the client if no requests are received in a given time period
(often of the order of 15 minutes). Protocols where the connection is maintained even if idle for long periods have two
choices:
1. use SO_KEEPALIVE
2. use a higher-level keepalive mechanism (such as sending a null request to the server every so often).
9. What are the pros/cons of select(), non-blocking I/O and SIGIO?
Using non-blocking I/O means that you have to poll sockets to see if there is data to be read from them. Polling should
usually be avoided since it uses more CPU time than other techniques.
Using SIGIO allows your application to do what it does and have the operating system tell it (with a signal) that there is
data waiting for it on a socket. The only drawback to this soltion is that it can be confusing, and if you are dealing with
multiple sockets you will have to do a select() anyway to find out which one(s) is ready to be read.
Using select() is great if your application has to accept data from more than one socket at a time since it will block
until any one of a number of sockets is ready with data. One other advantage to select() is that you can set a time-out
value after which control will be returned to you whether any of the sockets have data for you or not.
10. Why do I get EPROTO from read()?
From Steve Rago ([email protected]):
EPROTO means that the protocol encountered an unrecoverable error for that endpoint. EPROTO is one of those catch-all
error codes used by STREAMS-based drivers when a better code isn't available.
And an addition note from Andrew ([email protected]):
Not quite to do with EPROTO from read(), but I found out once that on some STREAMS-based implementations,
EPROTO could be returned by accept() if the incoming connection was reset before the accept completes.
On some other implementations, accept seemed to be capable of blocking if this occured. This is important, since if
select() said the listening socket was readable, then you would normally expect not to block in the accept() call.
The fix is, of course, to set nonblocking mode on the listening socket if you are going to use select() on it.
11. How can I force a socket to send the data in its buffer?
From Richard Stevens ([email protected]):
You can't force it. Period. TCP makes up its own mind as to when it can send data. Now, normally when you call
write() on a TCP socket, TCP will indeed send a segment, but there's no guarantee and no way to force this. There are
lots of reasons why TCP will not send a segment: a closed window and the Nagle algorithm are two things to come
immediately to mind.
(Snipped suggestion from Andrew Gierth to use TCP_NODELAY)
Setting this only disables one of the many tests, the Nagle algorithm. But if the original poster's problem is this, then
setting this socket option will help.
A quick glance at tcp_output() shows around 11 tests TCP has to make as to whether to send a segment or not.
Now from Dr. Charles E. Campbell Jr. ([email protected]):
As you've surmised, I've never had any problem with disabling Nagle's algorithm. Its basically a buffering method;
there's a fixed overhead for all packets, no matter how small. Hence, Nagle's algorithm collects small packets together
(no more than .2sec delay) and thereby reduces the amount of overhead bytes being transferred. This approach works
well for rcp, for example: the .2 second delay isn't humanly noticeable, and multiple users have their small packets more
efficiently transferred. Helps in university settings where most folks using the network are using standard tools such as
rcp and ftp, and programs such as telnet may use it, too.
However, Nagle's algorithm is pure havoc for real-time control and not much better for keystroke interactive applications
(control-C, anyone?). It has seemed to me that the types of new programs using sockets that people write usually do have
problems with small packet delays. One way to bypass Nagle's algorithm selectively is to use "out-of-band" messaging,
but that is limited in its content and has other effects (such as a loss of sequentiality) (by the way, out-of-band is often
used for that ctrl-C, too).
More from Vic:
So to sum it all up, if you are having trouble and need to flush the socket, setting the TCP_NODELAY option will usually
solve the problem. If it doesn't, you will have to use out-of-band messaging, but according to Andrew, "out-of-band data
has its own problems, and I don't think it works well as a solution to buffering delays (haven't tried it though). It is not
'expedited data' in the sense that exists in some other protocols; it is transmitted in-stream, but with a pointer to indicate
where it is."
I asked Andrew something to the effect of "What promises does TCP make about when it will get around to writing
data to the network?" I thought his reply should be put under this question:
Not many promises, but some.
I'll try and quote chapter and verse on this:
References:
RFC 1122, "Requirements for Internet Hosts" (also STD 3)
RFC 793, "Transmission Control Protocol" (also STD 7)
1. The socket interface does not provide access to the TCP PUSH flag.
2. RFC1122 says (4.2.2.2): A TCP MAY implement PUSH flags on SEND calls. If PUSH flags are not implemented,
then the sending TCP: (1) must not buffer data indefinitely, and (2) MUST set the PSH bit in the last buffered
segment (i.e., when there is no more queued data to be sent).
3. RFC793 says (2.8): When a receiving TCP sees the PUSH flag, it must not wait for more data from the sending
TCP before passing the data to the receiving process. [RFC1122 supports this statement.]
4. Therefore, data passed to a write() call must be delivered to the peer within a finite time, unless prevented by
protocol considerations.
5. There are (according to a post from Stevens quoted in the FAQ [earlier in this answer - Vic]) about 11 tests made
which could delay sending the data. But as I see it, there are only 2 that are significant, since things like retransmit
backoff are a) not under the programmers control and b) must either resolve within a finite time or drop the
connection.
The first of the interesting cases is "window closed" (ie. there is no buffer space at the receiver; this can delay data
indefinitely, but only if the receiving process is not actually reading the data that is available)
Vic asks:
OK, it makes sense that if the client isn't reading, the data isn't going to make it across the connection. I take it
this causes the sender to block after the recieve queue is filled?
The sender blocks when the socket send buffer is full, so buffers will be full at both ends.
While the window is closed, the sending TCP sends window probe packets. This ensures that when the window finally
does open again, the sending TCP detects the fact. [RFC1122, ss 4.2.2.17]
The second interesting case is "Nagle algorithm" (small segments, e.g. keystrokes, are delayed to form larger segments if
ACKs are expected from the peer; this is what is disabled with TCP_NODELAY)
Vic Asks:
Does this mean that my tcpclient sample should set TCP_NODELAY to ensure that the end-of-line code is indeed
put out onto the network when sent?
No. tcpclient.c is doing the right thing as it stands; trying to write as much data as possible in as few calls to write() as
is feasible. Since the amount of data is likely to be small relative to the socket send buffer, then it is likely (since the
connection is idle at that point) that the entire request will require only one call to write(), and that the TCP layer will
immediately dispatch the request as a single segment (with the PSH flag, see point 2.2 above).
The Nagle algorithm only has an effect when a second write() call is made while data is still unacknowledged. In the
normal case, this data will be left buffered until either: a) there is no unacknowledged data; or b) enough data is available
to dispatch a full-sized segment. The delay cannot be indefinite, since condition (a) must become true within the
retransmit timeout or the connection dies.
Since this delay has negative consequences for certain applications, generally those where a stream of small requests are
being sent without response, e.g. mouse movements, the standards specify that an option must exist to disable it.
[RFC1122, ss 4.2.3.4]
Additional note: RFC1122 also says:
[DISCUSSION]:
When the PUSH flag is not implemented on SEND calls, i.e., when the application/TCP interface uses a pure
streaming model, responsibility for aggregating any tiny data fragments to form reasonable sized segments is
partially borne by the application layer.
So programs should avoid calls to write() with small data lengths (small relative to the MSS, that is); it's better to
build up a request in a buffer and then do one call to sock_write() or equivalent.
The other possible sources of delay in the TCP are not really controllable by the program, but they can only delay the
data temporarily.
Vic asks:
By temporarily, you mean that the data will go as soon as it can, and I won't get stuck in a position where one side
is waiting on a response, and the other side hasn't recieved the request? (Or at least I won't get stuck forever)
You can only deadlock if you somehow manage to fill up all the buffers in both directions... not easy.
If it is possible to do this, (can't think of a good example though), the solution is to use nonblocking mode, especially for
writes. Then you can buffer excess data in the program as necessary.
12. Where can I get a library for programming sockets?
There is the Simple Sockets Library by Charles E. Campbell, Jr. PhD. and Terry McRoberts. The file is called ssl.tar.gz,
and you can download it from this faq's home page. For c++ there is the Socket++ library which is on
ftp://ftp.virginia.edu/pub/socket++-1.11.tar.gz. There is also C++ Wrappers. The file is called
ftp://ftp.huji.ac.il/pub/languages/C++/C++_wrappers.tar.gz. Thanks to Bill McKinnon for tracking it down for me! From
http://www.cs.wustl.edu/~schmidt you should be able to find the ACE toolkit. Another C++ library called libtcp++ is
also available at http://www.sashanet.com/internet/download.html. PING Software Group has some libraries that include
a sockets interface among other things. It seems to be all Java stuff now. You can find their stuff at
http://www.nerosworld.com/ping/. Thanks to Reid Judd for hunting that down for us!
Philippe Jounin has developed a cross platform library which includes high level support for http and ftp protocols, with
more to come. You can find it at http://perso.magic.fr/jounin-ph/P_tcp4u.htm, and you can find a review of it at
http://www6.zdnet.com/cgi-bin/texis/swlib/hotfiles/info.html?fcode=000H4F
I don't have any experience with any of these libraries, so I can't recomend one over the other.
13. How come select says there is data, but read returns zero?
The data that causes select to return is the EOF because the other side has closed the connection. This causes read to
return zero. For more information see 2.1 How can I tell when a socket is closed on the other end?
14. Whats the difference between select() and poll()?
From Richard Stevens ([email protected]):
The basic difference is that select()'s fd_set is a bit mask and therefore has some fixed size. It would be possible
for the kernel to not limit this size when the kernel is compiled, allowing the application to define FD_SETSIZE to
whatever it wants (as the comments in the system header imply today) but it takes more work. 4.4BSD's kernel and the
Solaris library function both have this limit. But I see that BSD/OS 2.1 has now been coded to avoid this limit, so it's
doable, just a small matter of programming. :-) Someone should file a Solaris bug report on this, and see if it ever gets
fixed.
With poll(), however, the user must allocate an array of pollfd structures, and pass the number of entries in this
array, so there's no fundamental limit. As Casper notes, fewer systems have poll() than select, so the latter is more
portable. Also, with original implementations (SVR3) you could not set the descriptor to -1 to tell the kernel to ignore an
entry in the pollfd structure, which made it hard to remove entries from the array; SVR4 gets around this. Personally, I
always use select() and rarely poll(), because I port my code to BSD environments too. Someone could write an
implementation of poll() that uses select(), for these environments, but I've never seen one. Both select() and
poll() are being standardized by POSIX 1003.1g.
15. How do I send [this] over a socket
Anything other than single bytes of data will probably get mangled unless you take care. For integer values you can use
htons() and friends, and strings are really just a bunch of single bytes, so those should be OK. Be careful not to send a
pointer to a string though, since the pointer will be meaningless on another machine. If you need to send a struct, you
should write sendthisstruct() and readthisstruct() functions for it that do all the work of taking the
structure apart on one side, and putting it back together on the other. If you need to send floats, you may have a lot of
work ahead of you. You should read RFC 1014 which is about portable ways of getting data from one machine to another
(thanks to Andrew Gabriel for pointing this out).
16. How do I use TCP_NODELAY?
First off, be sure you really want to use it in the first place. It will disable the Nagle algorithm (see 2.11 How can I force a
socket to send the data in its buffer?), which will cause network traffic to increase, with smaller than needed packets
wasting bandwidth. Also, from what I have been able to tell, the speed increase is very small, so you should probably do
it without TCP_NODELAY first, and only turn it on if there is a problem.
Here is a code example, with a warning about using it from Andrew Gierth:
int flag = 1;
int result = setsockopt(sock, /* socket affected */
IPPROTO_TCP, /* set option at TCP level */
TCP_NODELAY, /* name of option */
(char *) &flag, /* the cast is historical
cruft */
sizeof(int)); /* length of option value */
if (result < 0)
... handle the error ...
TCP_NODELAY is for a specific purpose; to disable the Nagle buffering algorithm. It should only be set for applications
that send frequent small bursts of information without getting an immediate response, where timely delivery of data is
required (the canonical example is mouse movements).
17. What exactly does the Nagle algorithm do?
It groups together as much data as it can between ACK's from the other end of the connection. I found this really
confusing until Andrew Gierth ([email protected]) drew the following diagram, and explained:
This diagram is not intended to be complete, just to illustrate the point better...
Case 1: client writes 1 byte per write() call. The program on host B is tcpserver.c from the FAQ examples.
CLIENT SERVER
APP TCP TCP APP
[connection setup omitted]
"h" ---------> [1 byte]
------------------>
-----------> "h"
[ack delayed]
"e" ---------> [Nagle alg. .
now in effect] .
"l" ---------> [ditto] .
"l" ---------> [ditto] .
"o" ---------> [ditto] .
"\n"---------> [ditto] .
.
.
[ack 1 byte]
<------------------
[send queued
data]
[5 bytes]
------------------>
------------> "ello\n"
<------------ "HELLO\n"
[6 bytes, ack 5 bytes]
<------------------
"HELLO\n" <----
[ack delayed]
.
.
. [ack 6 bytes]
------------------>
Total segments: 5. (If TCP_NODELAY was set, could have been up to 10.) Time for response: 2*RTT, plus ack delay.
Case 2: client writes all data with one write() call.
CLIENT SERVER
APP TCP TCP APP
[connection setup omitted]
read() is equivalent to recv() with a flags parameter of 0. Other values for the flags parameter change the
behaviour of recv(). Similarly, write() is equivalent to send() with flags == 0.
It is unlikely that send()/recv() would be dropped; perhaps someone with a copy of the POSIX drafts for socket calls can
check...
Portability note: non-unix systems may not allow read()/write() on sockets, but recv()/send() are usually ok.
This is true on Windows and OS/2, for example.
19. I see that send()/write() can generate SIGPIPE. Is there any advantage to handling the signal, rather than just
ignoring it and checking for the EPIPE error?
From Andrew Gierth ([email protected]):
In general, the only parameter passed to a signal handler is the signal number that caused it to be invoked. Some systems
have optional additional parameters, but they are no use to you in this case.
My advice is to just ignore SIGPIPE as you suggest. That's what I do in just about all of my socket code; errno values
are easier to handle than signals (in fact, the first revision of the FAQ failed to mention SIGPIPE in that context; I'd got
so used to ignoring it...)
There is one situation where you should not ignore SIGPIPE; if you are going to exec() another program with stdout
redirected to a socket. In this case it is probably wise to set SIGPIPE to SIG_DFL before doing the exec().
Jesse Norell has pointed out that if you are using SO_KEEPALIVE to test the connection, and you aren't doing reads or
writes very frequently, you might want to leave SIGPIPE enabled so that your server process gets signalled when the
system determines your link is dead. Normally though you will just check returns from read()/write() and act
appropriately.
20. After the chroot(), calls to socket() are failing. Why?
From Andrew Gierth ([email protected]):
On systems where sockets are implemented on top of Streams (e.g. all SysV-based systems, presumably including
Solaris), the socket() function will actually be opening certain special files in /dev. You will need to create a /dev
directory under your fake root and populate it with the required device nodes (only).
Your system documentation may or may not specify exactly which device nodes are required; I can't help you there
(sorry). (Editors note: Adrian Hall ([email protected]) suggested checking the man page for ftpd, which should list the
files you need to copy and devices you need to create in the chroot'd environment.)
A less-obvious issue with chroot() is if you call syslog(), as many daemons do; syslog() opens (depending on
the system) either a UDP socket, a FIFO or a Unix-domain socket. So if you use it after a chroot() call, make sure
that you call openlog() *before* the chroot.
21. Why do I keep getting EINTR from the socket calls?
This isn't really so much an error as an exit condition. It means that the call was interrupted by a signal. Any call that
might block should be wrapped in a loop that checkes for EINTR, as is done in the example code (See 1.8. Sample
Source Code).
Very simple: with TCP you get SIGPIPE if your end of the connection has received an RST from the other end. What
this also means is that if you were using select instead of write, the select would have indicated the socket as being
readable, since the RST is there for you to read (read will return an error with errno set to ECONNRESET).
Basically an RST is TCP's response to some packet that it doesn't expect and has no other way of dealing with. A
common case is when the peer closes the connection (sending you a FIN) but you ignore it because you're writing and not
reading. (You should be using select.) So you write to a connection that has been closed by the other end and the other
end's TCP responds with an RST.
23. What are socket exceptions? What is out-of-band data?
Unlike exceptions in C++, socket exceptions do not indicate that an error has occured. Socket exceptions usually refer to
the notification that out-of-band data has arrived. Out-of-band data (called "urgent data" in TCP) looks to the application
like a separate stream of data from the main data stream. This can be useful for separating two different kinds of data.
Note that just because it is called "urgent data" does not mean that it will be delivered any faster, or with higher priorety
than data in the in-band data stream. Also beware that unlike the main data stream, the out-of-bound data may be lost if
your application can't keep up with it.
24. How can I find the full hostname (FQDN) of the system I'm running on?
From Richard Stevens ([email protected]):
Some systems set the hostname to the FQDN and others set it to just the unqualified host name. I know the current BIND
FAQ recommends the FQDN, but most Solaris systems, for example, tend to use only the unqualified host name.
Regardless, the way around this is to first get the host's name (perhaps an FQDN, perhaps unaualified). Most systems
support the Posix way to do this using uname(), but older BSD systems only provide gethostname(). Call
gethostbyname() to find your IP address. Then take the IP address and call gethostbyaddr(). The h_name
member of the hostent{} should then be your FQDN.
25. How do I monitor the activity of sockets?
From: Matthias Rabast ([email protected])
For monitoring throughput there are tools such as IPAudit that will monitor throughput. I can't remember which tool I
used to use for this purpose, but a quick search found IPAudit. I haven't tried it, so let me know if it works, or if you
know some better tools.
You can use netstat -a under solaris and look at the Swind and Rwind columns for send and recieve window sizes.
I'm not aware of any tools for monitoring how often a socket blocks. Someone please add a comment if you have any
suggestions for this.
You could parse the output of snoop/tcpdump to get some of this information. Let me know if you know a good parser
and I'll list it here.
Once you have done a listen() call on your socket, the kernel is primed to accept connections on it. The usual UNIX
implementation of this works by immediately completing the SYN handshake for any incoming valid SYN segments
(connection attempts), creating the socket for the new connection, and keeping this new socket on an internal queue ready
for the accept() call. So the socket is fully open before the accept is done.
The other factor in this is the 'backlog' parameter for listen(); that defines how many of these completed connections
can be queued at one time. If the specified number is exceeded, then new incoming connects are simply ignored (which
causes them to be retried).
4. Why do I sometimes lose a server's address when using more than one server?
From Andrew Gierth ([email protected]):
Take a careful look at struct hostent. Notice that almost everything in it is a pointer? All these pointers will refer to
statically allocated data.
For example, if you do:
Normally you cannot change this. Solaris does let you do this, on a per-kernel basis with the ndd
tcp_ip_abort_cinterval parameter.
The easiest way to shorten the connect time is with an alarm() around the call to connect(). A harder way is to use
select(), after setting the socket nonblocking. Also notice that you can only shorten the connect time, there's
normally no way to lengthen it.
From Andrew Gierth ([email protected]):
First, create the socket and put it into non-blocking mode, then call connect(). There are three possibilities:
● connect succeeds: the connection has been successfully made (this usually only happens when connecting to the
same machine)
● connect fails: obvious
● connect returns -1/EINPROGRESS. The connection attempt has begun, but not yet completed.
Hi, my question is: When I write a client, how can I know the port number that the socket bound in my machine?
I worked all this lot out from the GNU C Library Manual (on-line
documentation). Here's some code I wrote - you can adapt it as necessary:
#include
#include
#include
#include
#include
#include
#include
/* Global variables */
...
volatile sig_atomic_t keep_going = 1; /* controls program termination */
/* Function prototypes: */
...
void termination_handler (int signum); /* clean up before termination */
int
main (void)
{
...
/* Become a daemon: */
switch (fork ())
{
case -1: /* can't fork */
perror ("fork()");
exit (3);
case 0: /* child, process becomes a daemon: */
close (STDIN_FILENO);
close (STDOUT_FILENO);
close (STDERR_FILENO);
if (setsid () == -1) /* request a new session (job control) */
{
exit (4);
}
break;
default: /* parent returns to calling process: */
return 0;
}
void
termination_handler (int signum)
{
keep_going = 0;
signal (signum, termination_handler);
}
4. How can I listen on more than one port at a time?
The best way to do this is with the select() call. This tells the kernel to let you know when a socket is available for
use. You can have one process do i/o with multiple sockets with this call. If you want to wait for a connect on sockets 4,
6 and 10 you might execute the following code snippet:
fd_set socklist;
The SO_KEEPALIVE option causes a packet (called a 'keepalive probe') to be sent to the remote system if a long time
(by default, more than 2 hours) passes with no other data being sent or received. This packet is designed to provoke an
ACK response from the peer. This enables detection of a peer which has become unreachable (e.g. powered off or
disconnected from the net). See 2.8 Why does it take so long to detect that the peer died? for further discussion.
Note that the figure of 2 hours comes from RFC1122, "Requirements for Internet Hosts". The precise value should be
configurable, but I've often found this to be difficult. The only implementation I know of that allows the keepalive
interval to be set per-connection is SVR4.2.
8. 4.8 How can I bind() to a port number < 1024?
From Andrew Gierth ([email protected]):
The restriction on access to ports < 1024 is part of a (fairly weak) security scheme particular to UNIX. The intention is
that servers (for example rlogind, rshd) can check the port number of the client, and if it is < 1024, assume the request
has been properly authorised at the client end.
The practical upshot of this, is that binding a port number < 1024 is reserved to processes having an effective UID ==
root.
This can, occasionally, itself present a security problem, e.g. when a server process needs to bind a well-known port, but
does not itself need root access (news servers, for example). This is often solved by creating a small program which
simply binds the socket, then restores the real userid and exec()s the real server. This program can then be made setuid
root.
9. How do I get my server to find out the client's address / hostname?
From Andrew Gierth ([email protected]):
After accept()ing a connection, use getpeername() to get the address of the client. The client's address is of
course, also returned on the accept(), but it is essential to initialise the address-length parameter before the accept call
for this will work.
Jari Kokko ([email protected]) has offered the following code to determine the client address:
int t;
int len;
struct sockaddr_in sin;
struct hostent *host;
● On some stacks, apparently only those with multicast support, I get duplicate incoming messages on the
INADDR_ANY socket.
13. How can I read only one character at a time?
This question is usually asked by people who are testing their server with telnet, and want it to process their keystrokes
one character at a time. The correct technique is to use a psuedo terminal (pty). More on that in a minute.
According to Roger Espel Llima ([email protected]), you can have your server send a sequence of control characters:
0xff 0xfb 0x01 0xff 0xfb 0x03 0xff 0xfd 0x0f3, which translates to IAC WILL ECHO IAC WILL
SUPPRESS-GO-AHEAD IAC DO SUPPRESS-GO-AHEAD. For more information on what this means, check out
std8, std28 and std29. Roger also gave the following tips:
● This code will suppress echo, so you'll have to send the characters the user types back to the client if you want the
user to see them.
● Carriage returns will be followed by a null character, so you'll have to expect them.
● If you get a 0xff, it will be followed by two more characters. These are telnet escapes.
Use of a pty would also be the correct way to execute a child process and pass the i/o to a socket.
I'll add pty stuff to the list of example source I'd like to add to the faq. If someone has some source they'd like to
contribute (without copyright) to the faq which demonstrates use of pty's, please email me!
14. I'm trying to exec() a program from my server, and attach my socket's IO to it, but I'm not getting all the data
across. Why?
If the program you are running uses printf(), etc (streams from stdio.h) you have to deal with two buffers. The
kernel buffers all socket IO, and this is explained in section 2.11. The second buffer is the one that is causing you grief.
This is the stdio buffer, and the problem was well explained by Andrew:
(The short answer to this question is that you want to use a pty rather than a socket; the remainder of this article is an
attempt to explain why.)
Firstly, the socket buffer controlled by setsockopt() has absolutly nothing to do with stdio buffering. Setting it to 1
is guaranteed to be the Wrong Thing(tm).
Perhaps the following diagram might make things a little clearer:
Process A Process B
+---------------------+ +---------------------+
| | | |
| mainline code | | mainline code |
| | | | ^ |
| v | | | |
| fputc() | | fgetc() |
| | | | ^ |
| v | | | |
| +-----------+ | | +-----------+ |
| | stdio | | | | stdio | |
| | buffer | | | | buffer | |
| +-----------+ | | +-----------+ |
| | | | ^ |
| | | | | |
| write() | | read() |
| | | | | |
+-------- | ----------+ +-------- | ----------+
| | User space
------------|-------------------------- | ---------------------------
| | Kernel space
v |
+-----------+ +-----------+
| socket | | socket |
| buffer | | buffer |
+-----------+ +-----------+
| ^
v |
(AF- and protocol- (AF- and protocol-
dependent code) dependent code)
Assuming these two processes are communicating with each other (I've deliberately omitted the actual comms
mechanisms, which aren't really relevent), you can see that data written by process A to its stdio buffer is completely
inaccessible to process B. Only once the decision is made to flush that buffer to the kernel (via write()) can the data
actually be delivered to the other process.
The only guaranteed way to affect the buffering within process A is to change the code. However, the default buffering
for stdout is controlled by whether the underlying FD refers to a terminal or not; generally, output to terminals is
line-buffered, and output to non-terminals (including but not limited to files, pipes, sockets, non-tty devices, etc.) is fully
buffered. So the desired effect can usually be achieved by using a pty device; this, for example, is what the 'expect'
program does.
Since the stdio buffer (and the FILE structure, and everything else related to stdio) is user-level data, it is not preserved
across an exec() call, hence trying to use setvbuf() before the exec is ineffective.
A couple of alternate solutions were proposed by Roger Espel Llima ([email protected]):
If it's an option, you can use some standalone program that will just run something inside a pty and buffer its
input/output. I've seen a package by the name pty.tar.gz that did that; you could search around for it with archie or
AltaVista.
Another option (**warning, evil hack**) , if you're on a system that supports this (SunOS, Solaris, Linux ELF do; I don't
know about others) is to, on your main program, putenv() the name of a shared executable (*.so) in LD_PRELOAD,
and then in that .so redefine some commonly used libc function that the program you're exec'ing is known to use early.
There you can 'get control' on the running program, and the first time you get it, do a setbuf(stdout, NULL) on
the program's behalf, and then call the original libc function with a dlopen() + dlsym(). And you keep the
dlsym() value on a static var, so you can just call that the following times.
(Editors note: I still haven't done an expample for how to do pty's, but I hope I will be able to do one after I finish the
non-blocking example code.)
If a UDP socket is unconnected, which is the normal state after a bind() call, then send() or write() are not
allowed, since no destination address is available; only sendto() can be used to send data.
Calling connect() on the socket simply records the specified address and port number as being the desired
communications partner. That means that send() or write() are now allowed; they use the destination address and
port given on the connect call as the destination of the packet.
3. Does doing a connect() call affect the receive behaviour of the socket?
From Richard Stevens ([email protected]):
Yes, in two ways. First, only datagrams from your "connected peer" are returned. All others arriving at your port are not
delivered to you.
But most importantly, a UDP socket must be connected to receive ICMP errors. Pp. 748-749 of "TCP/IP Illustrated,
Volume 2" give all the gory details on why this is so.
4. How can I read ICMP errors from "connected" UDP sockets?
If the target machine discards the message because there is no process reading on the requested port number, it sends an
ICMP message to your machine which will cause the next system call on the socket to return ECONNREFUSED. Since
delivery of ICMP messages is not guarenteed you may not recieve this notification on the first transaction.
Remember that your socket must be "connected" in order to receive the ICMP errors. I've been told, and Alan Cox has
verified that Linux will return them on "unconnected" sockets. This may cause porting problems if your application isn't
ready for it, so Alan tells me they've added a SO_BSDCOMPAT flag which can be set for Linux kernels after 2.0.0.
5. How can I be sure that a UDP message is received?
You have to design your protocol to expect a confirmation back from the destination when a message is received. Of
course is the confirmation is sent by UDP, then it too is unreliable and may not make it back to the sender. If the sender
does not get confirmation back by a certain time, it will have to re-transmit the message, maybe more than once. Now the
receiver has a problem because it may have already received the message, so some way of dropping duplicates is
required. Most protocols use a message numbering scheme so that the receiver can tell that it has already processed this
message and return another confirmation. Confirmations will also have to reference the message number so that the
sender can tell which message is being confirmed. Confused? That's why I stick with TCP.
6. How can I be sure that UDP messages are received in order?
You can't. What you can do is make sure that messages are processed in order by using a numbering system as mentioned
in 5.5 How can I be sure that a UDP message is received?. If you need your messages to be received and be received in
order you should really consider switching to TCP. It is unlikely that you will be able to do a better job implementing this
sort of protocol than the TCP people already have, without a significant investment of time.
7. How often should I re-transmit un-acknowleged messages?
The simplest thing to do is simply pick a fairly small delay such as one second and stick with it. The problem is that this
can congest your network with useless traffic if there is a problem on the lan or on the other machine, and this added
traffic may only serve to make the problem worse.
A better technique, described with source code in "UNIX Network Programming" by Richard Stevens (see 1.6 Where
can I get source code for the book [book title]?), is to use an adaptive timeout with an exponential backoff. This
technique keeps statistical information on the time it is taking messages to reach a host and adjusts timeout values
accordingly. It also doubles the timeout each time it is reached as to not flood the network with useless datagrams.
Richard has been kind enough to post the source code for the book on the web. Check out his home page at
http://www.kohala.com/~rstevens.
Technically, fcntl(soc, F_SETFL, O_NONBLOCK) is incorrect since it clobbers all other file flags. Generally one
gets away with it since the other flags (O_APPEND for example) don't really apply much to sockets. In a similarly rough
vein, you would use fcntl(soc, F_SETFL, 0) to go back to blocking mode.
To do it right, use F_GETFL to get the current flags, set or clear the O_NONBLOCK flag, then use F_SETFL to set the
flags.
And yes, the flag can be changed either way at will.
2. How can I put a timeout on connect()?
Andrew Gierth ([email protected]) has outlined the following procedure for using select() with
connect(), which will allow you to put a timeout on the connect() call:
First, create the socket and put it into non-blocking mode, then call connect(). There are three possibilities:
● connect succeeds: the connection has been successfully made (this usually only happens when connecting to the
same machine)
● connect fails: obvious
● connect returns -1/EINPROGRESS. The connection attempt has begun, but not yet completed.
Contents are Copyright© by the author of the content. Permission is granted to do anything you like with this contents so long as you don't claim the work, or copyright for yourself. The
Self Serve FAQ is Copyright© by it's authors, and available under the terms of the GNU GPL.
New Questions: How does it know to send
back the right information
From: Dwayne
If you have two or more programs sending information to a server and both requesting
information back, how does it know that this program should get this and this program should
get this. To me its like a walkie talkie everyone is sending on the same channel, should they get
everbody response.
Note: Keep in mind the programs sending the inforamtion are started from CGI scripts in
different process but there all use the same socket.
From: zhan dong
From: Dwayne
Thanks I thought that a socket was just a IP address and a port. I never knew that a port is one
to many relatioship with sockets
From: manikandan
Hi,
When multiple clients communicate with a server. the server is designed in such a way that for
each connection or a request a instance of the server is created, and connection is established
with the client and the server instance.
remember new requests come thru socket() system call and the subsequent requests comes thru
accept() system call, where both will give socket descriptors.
Regards
Mani.
Add a Comment
New Questions: C function to empty a socket
From: JAIME SIEIRO
Regards
Manikandan
Add a Comment
New Questions: confused with backlog of
listen()
From: peng cheng
It is the maximum length the queue can grow to. If the queue is full and a new connection
arrives then it might get a ECONNREFUSED error.
Hi,
It the sum of incompelte connection queue and the connection completed queue (SYN_RCVD
state,ESTABLISHED state respectivily)
Add a Comment
New Questions: Problem in Sockets while
using Message Queues
From: Girish Mohan
I am using System V message queues along with sockets and everytime I read my Message
Queue, I get some activity (Junk) on the socket connection. I am using select() system call to
schedule my socket connection.
Hi,
There should not be any problem while using socket with message queues b'cause socket and a
MQ are different entities . Can u send some piece of code or some detail explanation.
Mani
Add a Comment
New Questions: I loss data when I receive from
a unix socket!!!
From: Sevil Demir
socket(...);
bind (...);
listen(....);
new_sock=accept(.....);
i=recv(new_sock,buf,MAXDATASIZE,0);
I test this program SCO Unix...At the same machine the result is true, But when I run the
program at a different machine ,i= returns 1460 or 536 everytime.... But buf length is longer
then i...
8192 var ya onu 4096'a dusur hatta 1024 ve 512'yi dene. Bu yavaslatir dogal olarak ama test
amacli. Belki kerneldaki max. paket boyutu bi nedenden dolayi daha kucuge ayarlanmis
olabilir. ayni kod linux'ta falan calisiyo mu?
From: Extirpater
ha bi de $u var ki. Bunu nasil test ettin? yani buna bilgi gonderen ek bi program yazdiysan
sorun ikisinin anlasamamasida olabilir. Ornegin biri cok bilgi gonderiyodur digeri yetisemedigi
icin alamiyo butun bilgiyi. her paketten sonra aldim anlamina gelen bisi gondersen bu data
bekleyen kisim... fikir sadece...
From:
From: manikandan
Hi,
Try to increase the receive buffer using setsockopt with SO_RCVBUF option.
Regards
Mani
Add a Comment
New Questions: tracking socket calls
From: Venkat Raghavan
Hi, I need to track socket calls any application makes and emulate them in my own protocol
stack implementation. If there already exists tools to do this for either linux or bsd I'd appreciate
any pointers to this. thanks in advance -venkat raghavan_at_csl_dot_sr_dot_com
From: Venkat Raghavan
You can trace avery system call by using the "strace" tool in Linux.
If you specify the "-e trace=network" only the network related system calls will be displayed.
You can even trace system calls of already running processes by using the -p option (-p
PID_OF_THE_PROCESS).
From: banda
banda maagia
From: Jens Meissner
Hallo,
How can I get Data from the Netwrok (TCP/IP-Packets ) directly from the Ehernetcard ?
Is There a Port or socket ?
Is there a request to the Kernel or an C-Programm which gives me the Information into an File
where I can get all Binäries ?
Where can I get this Information is there a RFC ?
I use SUSE 7.0
Best regardes JM
From: Deepak Kotian
For hpux-11, you can find tusc command, which is downloadable from the net .This can also all
system calls
for a running process or execute a process.
Hi,
This can be achieved quite simply under Linux, however I am not sure as to the portability of
this method.
You create a shared object (eg, wrap-myprotocol.so) which contains functions with the same
prototypes as those of the socket calls. These functions may then call the normal socket
functions by loading the library containing those calls using dlopen(3), and then dlsym(3) to get
the address of that function in memory.
Once you have created this you can then override the libc/socket lib calls by exporting
LD_PRELOAD="/path/to/libdl.so /path/to/yourlib.so"
and then running the required program.
I've managed to add SSL to virtually any program using this method. It works quite well :)
From: bimalendu
hi,
One way I can suggest is that use PF_PACKET type socket
(for linux at least) to get the raw packets directly from
the device driver.
open a socket
sockfd = socket(PF_PACKET,int socket_type,int protocol)
use htons(ETH_P_ALL) for protocol ,then you can get the data for
for all protocols (like IP, arp etc)
and use socket_type to SOCK_RAW to get raw packets including
link level header is received.
and then read in an unsigned char buffer, the arriving data.
read(sockfd,buffer,sizeof(buffer))
But you need a root to use PF_PACKET socket
Add a Comment
New Questions: How can I determine the space
available in the send buffer of a socket?
From: Lyman Neuschaefer
I want to write a function which attempts to write a message to socket. Either it succeeds,
writing the full content of the message to the send buffer or it fails, writing none (0 bytes) to the
send buffer. Querying the socket to determine the available space in the send buffer would
enable such a function. Do you have any ideas how to proceed? Thanks, Lyman Neuschaefer
From: Daniel Kiracofe
Well, what might work for you would be to set the SO_SNDLOWAT option to setsockopt to
the size of your packet, and then set the socket to non-blocking. This way, either the whole
packet gets processed, or none of it does.
I do not know of any standard way to determine the available send buffer space of a socket
(although I did hack up a patch to linux 2.2 get that information).
There are two possible solutions which can, and should, be used simultaneously for your
purposes, assuming a SOL_SOCKET type.
1. Set the O_NONBLOCK option on the socket using fcntl(2) and use sendmsg(3XN) to write
the message to the socket.
If there is insufficient space at the sending socket to hold the message, and O_NONBLOCK is
set, sendmsg(3XN) will fail.
2. Set the size of the send buffer yourself using setsockopt(3XN) (command argument:
SO_SNDBUF), then the application will know
the size of the buffer.
Warren Nash's suggestion may be based on a misunderstanding of the question. write(2) is not
guaranteed to write the full
contents of the byte buffer in one operation. It only ATTEMPTS to write the number of bytes
specified by the third argument.
It is guaranteed not to write more than this number of bytes. If successfull, the return value of
write(2) indicates the number
of bytes actually written. It is the responsibility of the programmer to keep track of this number
and adjust the byte buffer
offset, and number of bytes to write, on subsequent calls to write(2) in order to ensure that the
entire contents of the buffer
are written. Since this may require several calls it does not meet your specifications, and it is
not a viable solution for your
purposes.
Add a Comment
New Questions: Socket question
From: Alexey
and after opening this connection I need to know the current meanings SEQ and ACK. How it is
possible them to find out?
From: Hifny
hello Alexey,
for obtaining SEQ and ACK you should use SOCK_RAW socket,
but connect(2) is only for SOCK_STREAM and SOCK_DGRAM.
so, you should create SOCK_RAW socket, and use recvfrom(2) & sendto(2)
routines to obtain packets with TCP headers.
you will probably need root to do this.
From: neal
what alternatives exist to using a socket?
From: Jatin Patel
I want to knwo that how can i change the program of TCP to UDP. I mean what changes i have
to made?
From: rgbulusu
i am a beginner and i want to know wheteher we can simulate network programminng on stand
alone systems want you to send reply to [email protected]
From: alfredo
i have seen set of all the questions but unfortunately i could not found answer of them, will you
please help me
From: LIEN
Add a Comment
New Questions: How to act as server and
client at the same time.
From: Theo Wilhelm
I did a 'man select' in Linux and derived this handy function from the program in the man pages
:
FD_ZERO(&rfds);
FD_SET(sock, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 0;
tv.tv_usec = 1;
Please note : avail(int) works for file descriptors, which are basically sockets returned from the
socket(...) command.
From: franz
It is pretty easy if you are already familiar with socket programming and concepts.
You can have different port numbers for the servers on different machines, but why bother
complicating the situation.
Your program should pretty much be based on a server program - open a socket and listen on it.
Then you add some code to try and connect to each of the other hosts at the start of the
program. If the connection fails you just clean up the failed fd and wait for the other host(s) to
connect to you instead.
In the rare scenario that both programs try to connect to each other at the same time you may
need to add some special code. If the network is down when both application starts you may
want to do periodic re-attempts to connect unestablished connections.
In the program I wrote, I created a function that checked a list of all required connections - and
if it was down it would try and connect it. If all connections are up, it simply returns.
The same function can be used anytime. I use it at startup of the application, once a minute,
whenever a socket closes, and triggered after a signal was handled.
This list of connections would be updated after accept()ing a connection or a successful
connect().
The list is also used to determine which fd's to include in my select() statement.
main()
{
struct appdata app;
app.port = 8888;
Your checkSockets() routine should do a select() on your listening port and all connected
sockets.
Connected sockets include both initiated and accepted sockets.
When you accept a socket you can tell where it is from by using the following code ..
You can use memcmp on sa.sin_addr (from accept) and sin.sin_addr (used in connect) to see
where this connection is from. This is more useful when there are more then one possible
clients.
if( (hp=gethostbyname(host)) == 0 )
{
fprintf( stderr, "Unknown host '%s'\n", host );
return;
}
memcpy( &sin.sin_addr, hp->h_addr, hp->h_length );
FV.
Add a Comment
New Questions: What are the implications of
reducing receive buffer size?
From: Sateesh Potturu
Add a Comment
New Questions: reversed name resolving
From: Efrat Meir
Keep in mind that a host can have multiple A records, as well as multiple PTR records. These
functions return lists of aliases, and IP addresses. With multiple A records, most DNS servers
will return a different IP in the first slot each time a request is made. This is to make it easy to
do cheap "load balancing".
You should always get back the same information (until the DNS records change), but not
always in the same order.
Add a Comment
New Questions: How can I send packet on a
choosen interface ?
From: Frederic Pont
Take a look at the function sendto(). I've used this function with raw sockets and specified my
prefered interface, such as eth1, in the struct sockaddr *to. Its tricky at first, but it works.
From: Nikhil Dalal
There is one more way for doing this. you can use the set socket options at the ip protocol
level(IPPROTO_IP). In this u can set the IP_BROADCAST_IF to the address of the interface.
From: Arthur Lung
Add a Comment
New Questions: Fix IP source address ?
From: Frederic Pont
Yes It should give an error message 'cos addresses are resolved by the DNS server and we
cannot use IP addresses to our fancy.It should be cofigured during installn:
From:
If you wish to set the source address of a udp packet to something that is not an interface on the
machine; the best method is to obtain a library such as libnet and create a raw packet.
Add a Comment
New Questions: How do I reject a pending
connection?
From: Joaquin M Lopez
Heyo :)
why dont you try make a fucntion that retrieves the ip adress / host of the user trying to
connect... then parse the ip addresses. and only accept the ones that you specify..
thats ideally what you need.
but is there a way of seeing who was "trying " to connect to your socket?
thats the big question i guess
seeya laytah
From: Chris Leisman
AFAIK the connection has already been "accepted" by the OS
at this point (the three-way handshake is complete). So
accepting and then calling close() shouldn't be a real issue.
Per previous reply - Under Unix(es) and some other OS's the listen() queue has already
accepted the connection request into the queue list (pending an accept). So your choice to only
accept, compare remote address if you really want to let them in - then continue your normal
operation, otherwise close the socket. This also free's up the queue list (which is limited to 5
pending or less on most operating systems).
Ozz Nixon
www.dxsock.com
From: Juhan Aslak Näkkäläjärvi
accept ()
getpeername ()
myMagicCheckPeerAndDecideIfIWantThisConnection ()
close () // Only if you don't want this connection
Add a Comment
New Questions: Different Flavors of Pipe
Signal
From: Naresh Motwani
Any program reading from a socket should use the 4 argument select() function
to test if the file handle representing the socket has data which is ready to
be read. If so, only then should the program attempt to read data from it. You
set the timeout on select(), say 15 seconds, so that if the file handle has no
data ready to be read in 15 seconds, you can close the connection to avoid a
possible SIGPIPE. Similarly, a program writing to a socket should use the 4
argument select() function to test that the socket is ready to be written to.
It is still possible for the program to receive a SIGPIPE, and you should set
up a signal handler to catch it so that the program can handle it cleanly.
The reason for the SIGPIPE should be in the Perl built in variable $!. In
string context $! will hold a string descripton of the error. In numeric
context it yields the the corresponding error number.
Add a Comment
New Questions: how to restart a server
immediately
From: jerry
Check out 2.7. Please explain the TIME_WAIT state. This is the question that prompted me to
start this faq!
From: Richard Foletta
Install a signal handler in your program to catch SIGINT. This signal handler will set a flag
(rcvd_sigint = 1) when
the program receives a SIGINT from someone pressing CTL-C. Somewhere in your program
you should be checking this flag and if set you should exit your program gracefully by shutting
down your sockets.
From: Nick
Actually, this is because the server socket has entered the TIME_WAIT state after it was closed
by the server when you sent it the SIGINT signal with Cntrl-C. you can see this by typing
"netstat" after you close the server. You will see TIME_WAIT under the State column.
To fix this, simply set the socket option to re-use the address. Every concurrent server should do
this between the calls to socket and bind!
Here is the line that you want:
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
where on is an int with value 1. Hope this helps.
-Nick-
From: Mourad
You're absolutely right, Nick. I've been struggling with that problem for a long time (not being
able to bind to the same port immediately after an ungraceful exit because it is in a state of
TIME_WAIT according to netstat).
Anyway, you helped a great deal. Thanks.
From: Andrey
Remember that the socket option should be set BEFORE the call to bind.
From: Suresh
Hai Nick,
The information u gave is really useful and it really worked. Thanks a lot.
Add a Comment
New Questions: How to use sendmsg/recvmsg
(or does anyone actually use this "feature"?)
From: Tom Emerson
The subject pretty much sums it up -- I'm looking into writing a "custom" application to send
arbitrary-length records over a network, and it appears sendmsg/recvmsg will do the
blocking/deblocking for me so I get discrete records rather than fragmented/recombined records
on the read/recv call.
3) is the "accessrights" string really neccessary (and if so, what do I put into this string?)
4) what is the purpose of the "alternate address" and how should/would it be used?
Add a Comment
New Questions: Motorola 88k Gotcha
From: Alan Peakall
Question:
My use of a non-blocking socket for a connect with a specified timeout fails on Motorola 88k.
Answer:
Using the code outlined in the FAQ for doing a connect with a specified timeout, may fail on
Motorola 88k Unix. The problem is that this system uses errno==EAGAIN as the return
condition from `connect' where other systems use EINPROGRESS.
#include <errno.h>
#ifndef EINPROGRESS
#define EINPROGRESS EAGAIN
#endif
Add a Comment
New Questions: Socket question
From: Steph
Hello!
I am into the telecom field,i think i can extend some help
Set me the code with exact problem encountered.
B.S.Banerjee
From: sanjukta
The SocketServer is receiving a SIG-SIGALARM on a reading socket when the client is trying
to writ the first attempt of a socket connection.
Thanks in advance
Sanjukta
Add a Comment
New Questions: Errors in sockets
From: Alejandro Botello
Why some code that work fine in many UNIX operating systems (like Solaris, AIX or Irix) not
work properly under LINUX (RedHat 4.2)?. I run a simple server using sockets and get the
following error mesages in recv(): "Broken pipe" and "Socket operation on non-socket". What
code I have to add to this work well?..Someone could helpme?
From:
Add a Comment
New Questions: problem in socket
programming
From: azizan mohamad
...
...
n = strlen(s1);
cout << "sending message"<<s1<<"\..";
cout <<((send(sock,s1,n,0)==-1)?"Error:"Done")<<endl;
while(1)
if (recv(nsock,s3,sizeof(s3),0)==-1)
{
cout << "Error";
break;
}
else
{
cout << " message" << s3;
}
From: Tarkan Alptekin DURMUS
Am new to socket programming ,what could be the possible reasons for getting a bad socket
descriptor while issuing a connect call and how am get over it ,
Hi,
Your problem is simple: you are using sizeof(s3) which returns the size of the pointer to a char
(if s3 is a char array). You must use the number of characters your array can hold or the
maximun number of chars you are expecting (whichever is less)
To satish:
Are you using socket() before calling connect()???
If you post your code it would be easier...
From: vinay pole
From: Raja
My server is not able to receive the message sent by the client which established connection to
server thru sockets.
From: abed
I wrote one client_server program but I did a few process between each of sending and
recieving message, my program only worked for first send and recieve.Remainder of send and
receive messages weren`t done.Please guide me.
Add a Comment
New Questions: client/server environment
From: ezzete
I think its best you buy Richard Stevens book - as it describes everything you need
e.g.all the functions.
From: mn
u also should read the rfc 821,then u'll know what u should do.
From: camran
heey mn;
your problem is laziness ; read that book twice then u will understand good, dont ask for
chapters, I M sure u will find your answer.
Add a Comment
New Questions: Sending large ( > 50 meg) files
(binary + ascii) through sockets
From: Randy Randleson
I want to send large files that would exceed the send and
receive buffer size limitations. What would be the best
method of doing this? Any code out there that gets at this
would be much appreciated.
From: Randy Randleson
Don't care
do
{
brec += send (.......)
}
while(brec < 50 megs ) ;
Hello,
Could any one tel me how to re-assemble the packets once received.
From: THoK
the best way i know to do it is to open a file in binary mode and put into it each packets you
receive (fixed size or not, who care) and close the file after the transfert.
Correct Answer:
Yes a protocol solution is viable, but you still have the problem of overrunning the outbound
socket buffer, or the receiver's socket buffer (especially when they are on a slower connection).
Making the assumption your packet will get there is down right stupid! I hear this from
customers all the time, it is not going to get there, if the remote buffer is full - duh! It gets
dropped.
The correct answer is to develop calculations of delivery performance. There are ICMP
messages the remote will send to say "SLOW DOWN - YOU ARE TOO DAMN FAST!". This
is done at transparent to the receiver's code - which is simply doing a read loop. So you must
implement support for handling these. I have not seen anyone release a good example of doing
this correctly, but my staff is building an example for a project we are developing. Which
requires the ability to throttle out socket suite - doing bulk delivery.
Ozz Nixon
www.dxsock.com
Add a Comment
New Questions: Proxy Handling
From: Sankalp Upadhyay
to proxy site:port. Maybe you'd like to use LWP::UserAgent PERL module, it already have
proxy interface.
Add a Comment
New Questions: socket and XTI
From: guyot patrick
Yes, it is possible.
It is the application protocol (HTTP, Telnet, amd so on)
and the transport layer (TCP or UDP) that determine interoperability. The API we use to write
the code makes
no difference.
Add a Comment
New Questions: Sending & Receiving data on a
socket
From: Eileen
Eileen, I am having a similar problem when using the Tools++ Professional library. I am
waiting on select on the client side, and only some of the messages get through. I mproved it a
little by flushing the buffers, but it still didn't work 100%. Interestingly, when I killed the server
side, suddenly all of the messages appeared on the client side before it shut down with a read
error. Have you found a reason, and better still, a solution?
From: Mahafuz
From: frankv
If you are using UDP it is theoretically possible. Less likely if the server and client are on the
same machine.
Non-unix systems used to be really crap at handling UDP and dropped packets left right and
centre unless you wrote a handler to read packets asap and buffer them manually yourself. I
don't know (or care) if it has been improved since then.
If you are worried about losing info you should really use tcp/ip SOCK_STREAM.
If you are using SOCK_STREAM (which I assume anyway) there is either something seriously
wrong here, or it is just a silly simple oversight.
The previous suggestion about using FD_SET everytime is important. If select gets an error
your set remains unmodified and you may believe there is info available.
The same goes vise-versa - if your fd gets cleared from the set somehow it needs to be added
again. Remember that the call to select will modifiy your sets. Is it possible you are using the
same readset reference somewhere else?
From your message it seems that select is returning 0. Is it returning before the ten seconds
timelimit?? Is it possible that signals are interupting your select?
If select is returning -1, check errno for more info.
fv.
Add a Comment
New Questions: Stream Sockets,
Multithreading, and Windows
From: Daniel Morgan
I currently I have basic basic understanding and can do the above mentioned.
It is just rather hard putting all three together to form something useful.
Let's say I wanted to implement a GUI POP3 client, GUI IRC client, or a GUI FTP
client.
I wnt to know
if i want to create program for connct server with c++ in UNIX and Windows System
if you have an example coding program with c then can you sent to me for learning
Thanks you
From: lost
From:
Add a Comment
New Questions: Subsequent connect call fails
(EBADF); why?
From: arp
(where i've left out the error checking and extraneous stuff).
The second connect (step 5) fails with errno == EBADF. This
happens even after adding a 'shutdown' before step 4.
Is this correct? The man pages & GNU libc.info don't indicate
that close does anything strange to the socket descriptor.
Why do i need to create another one with socket (...)? Or
is this a Linux bug (sorry, i don't have access to other
UNICES to test against)?
If this is addressed in the FAQ, slap me with a wet noodle and point
me in the correct direction please.
From: Vic Metcalfe
Close frees all the kernel resources associated with the file descriptor, so yes, you do need to
call socket() again.
And no, that wasn't in the FAQ, so no wet noodle for you!
Take care,
Vic.
From: Andy Kanch
Thanks for the info. I was alos facing the same problem in CICS. Now I know what to do.
Add a Comment
New Questions: HTML Client
From: Craig Matsuura
Where can I find example code for writing a simple HTML Client
(Web Browser). In C.
Try looking up the source code to Lynx, a text-only web browser. Also check libwww at
www.w3c.org
Add a Comment
New Questions: Passing sockets to pre-forked
children
From: Carlos M. Gutierrez
If I have server (like Apache) and that server "pre-forks" several children, how are incoming
socket connections passed to the pre-forked children? Because they are "pre-forked", they can't
inherit directly from the parent's file descriptors...
From: Josef Pojsl
You can do socket(), bind() and listen() in the original process and then fork() as many children
as you like and do select() on the socket in each forked child. After select(), use accept(), serve
the call and return to the loop beginning with select(). This works for me on FreeBSD, at least.
From: Jim Rogers
One method is to have all incoming connection requests handled by the parent. The parent
generates an event, passes the incoming socket info to the child, and closes the socket. The
child catches the event and establishes its own socket connection with the client.
From: Chris Wood
The question Carlos asked was how to pass a socket to a pre-forked child.
Pre-forking the child means that the child does not know what do with the integer we normally
call a "file descriptor", because this integer really doesn't describe anything; it is an index into
an array we don't normally see as programmers. So, we need to pass the underlying information
to the child somehow.
The general technique for solving this problem is to set up a method of IPC between child and
parent before the inbound connection arrives. I like to use AF_UNIX domain sockets for this.
Then, when the parent needs to send a socket to the child, it constructs a msghdr with an iovec
containing the underlying information. The receiving process will almost certainly have a
difference file descriptor number than the sending process does, for the same open file (socket).
There is an example in W. Richard Stevens' TCP/IP Illustrated Volume I of how to do this. (If
not this book, maybe the first Unix IPC book? I know it's there somewhere..)
Also, Apache does this, as Carlos pointed out. Why not read the source?
From: Wes
Chapter 27.9, "TCP Preforked Server, Descriptor Passing", on page 746 of UNIX Network
Programming, Volume 1, Second Edition. W. Richard Stevens, ISBM 0-13-490012-X.
Add a Comment
New Questions: Unix domain sockets using
linux
From: All
I'm using Redhat 6.0. I'm trying to implement a client and aserver model using unix domain
sockets.
I'm using GNOM windows manager. I want the client to communicate with the server that is
located in a defferent user acount
so I'm using two Xtermials to run each of the client and the server. since they are in different
directory I gave the client the right path to bind. But When I run the client the system gives me
an error message
saying can not connect. if any one knows the answere please let me know.
From: Jacqueline Guerrero
Are you sure that your server is actually waiting to receive messages on the socket that your
client is sending to?
From: S.M.Krish
Hai Friend
If You Receive "Connection Refused" Error message
Probably The Server May not be in Ready Condition while
you run your client. And Also Check the Directory
Path Permissions between Your client and Servers.
And the "Socket File's" Access permission. If You Receive
Error Still, Post your error message clearly. Thanks and bye
From: soupa
You can do client/server programming over the local loopback interface (lo -- 127.0.0.1). It will
allow one program to talk to another program on the same machine over a socket, without
actually needing a real network card.
From: Sougat
Hi,
I am receiving an error when I try to start Websphere Commerce Suite on Aix4.3.3.
CMN0310E: The socket name is already in use.
CMN0519E: Server controller TCP/IP service 'newcom' is already in use, an instance of server
controller may already be running.
The problem gets resolved when we reboot the machine. Could someone tell as to how to
resolve this problem without reboot.
Thanks,
Sougat
Add a Comment
New Questions: Can port be shared ?
From: Kim Dong Ho
When two hosts, client C and server S, make connection each other.
In this situation, a new host H want to communicate with client C through the port - ex, port
1000 - which is assigned
to communicate with server S.
Of course, there is no connection with client C and new host H.
Can the new host H send packet to the client's opened port, port 1000.
And, Can the client receive the packet from new host H through the port, port 1000, which is
opened to
server S.
Lets look at a specific real life example. Lets say that [email protected] and [email protected] send
email to one another at the same time. Here's what happens...
● Joe's email client sends his message to his smtp server which happens to be
mail.hostA.net.
● Jane's email client sends her message to her smtp server which happens to be
mail.hostB.net.
● The SMTP server at mail.hostA.net does an MX lookup on hostB.net which returns
mail.hostB.net
● The SMTP server at mail.hostB.net does an MX lookup on hostA.net which returns
mail.hostA.net
● The SMTP server at mail.hostA.net connects to port 25 of mail.hostB.net
Each connection is unique, and there is no conflict. Otherwise mail servers wouldn't be able to
communicate with one another at the same time, you couldn't run a web browser from a web
server, etc.
I hope this helps,
Vic.
From: Jay
Hi,
It cant be possible because when u sent mesg u will connect and connect will fail bcoz
connect intern call bind and u cant bind single port to two sockets.
From: caspre
Jay: You're right that you can't bind two sockets to the same port, but when you accept a
connection from a listening socket on a port using accept(), a new socket is created on the same
port. This means that you now have the listening socket, and a new socket, both on the same
port
From: Arthur Lung
So to summarize:
Actually, Arthur, that's not exactly it either. If your computer has MORE than one IP address,
you can configure your server processes to listen to a particular IP and PORT combination. I
have a colocated Linux box with IPs x.y.z.7 and x.y.z.8. Apache listens to x.y.z.7:80 and
Tomcat (another webserver) listens to x.y.z.8:80.
You can also configure stuff to only listen to 127.0.0.1, which is a common way to secure stuff
from the outside world without turning it off completely.
Add a Comment
New Questions: Reading from a port
From: Niraj Shah
Hi,
I have been successfull in establishing client / server socket connection in UNIX. I want to
read from port 5000 of my local system (192.168.9.23). How can I go about this ?
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
void main(void) {
int sock, newsock, i = 0;
char c, line[BUFSIZ];
struct sockaddr_in server;
int addrsize = sizeof server;
printf("Server\n");
/* Step 1: Create a socket */
/***************************/
printf("Creating unbound socket...\n");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
printf("Can't create socket\n");
exit(1);
}
Hi,
Cheers,
Terrance
Add a Comment
New Questions: java.net objects for reading
port
From: Niraj Shah
Hi,
I want to know what are the equivalent functions in UNIX socket programming for
Datainputstream and Outputstream objects of java.net package for reading a port.
From: Thierry¨PAIN
Add a Comment
New Questions: Socket Programming
From: Veerendra Moodbidri
Hi everyone,
I have written a "C" program to create a socket in Unix system. After creating, I am able to
"bind" this socket to a local host system. My requirement is to "bind" this socket to a Remote
Unix system. When i try this I am getting "bind failed" error. I have mentioned the IP address of
the remote system in hexadecimal in the C program. After binding i need to read the 5000 port
of the Remote unix system (Intranet).
Thanks in advance
Veeru
From: Aner Gusic
Try printing the actual error code after your bind and see the description in
/usr/include/sys/errno.h
I suspect you need to use "setsockopt" for this problem, after opening the socket.
From: Thierry PAIN
When the client's port address does not match with server's
port address, then you will get "bind error". When you get a bind error,
server takes some time to release the port. If you try before
that to execute again, you will get bind error. So if you
get "bind error", change the port number in both client and
server then compile both programs and execute.
From: Hector Lasso
You can only bind sockets on local interfaces (at least it works that way for TCP/IP)
From: bao nguyen
bao
Add a Comment
New Questions: How do I get a MAC address
using code on Solaris?
From: xin
From: S.Chandrasekaran
Hi
You may have to use DLPI primitives to get that information (also have super user access).
You may
have to open /dev/le (or /dev/hme) and then use DLPI
primitives to get the information. See man dlpi, man le
and also the file /usr/include/sys/dlpi.h for more
information
From: Heba M Naguib
you ca use the unix command ifconfig -a to show thw mac address of your card,or use arp
command
From: Ozz Nixon
You will see in there, you have the ability to get down and dirty with the NIC. (Assuming
newer Solaris 2.6 or newer)
Ozz Nixon
www.dxsock.com
From: Wes
Those ioctls are also available on 2.5.1 (at least on recent patch clusters). Do a truss on ifconfig
-a for more clues.
Wes
Add a Comment
New Questions: send object through socket
From: Yan Xu
It's strongly recommended to send structures (and objects) item-by-item, writing its members
individually (and taking care of byte order,etc ;)
The reason is difference in allocation customs (alignment,padding,etc) of different compilers
even on the same machine/OS.
So if I have to send objects, I have to write methods for writing its members to the socket and
for extracting them. Anyway, you have to initialize
the object-receiver, but not simply extract it from the socket.
As for passing code, I can't understand the need to do it. Maybe you think of RPC?
From: Hector Lasso
Hello,
Java uses serialization to create a binary representation of the objects before sending them via
opened connections.
This procedure makes possible to send object containers with their content (other objects). And
even send references to Remote objects if any (the stub is sent).
To write such code is a relly hard task, so you should try defining some protocol for your set of
objects (you're not going to send any kind of object, are you?) and then using this protocol to
exchange the contents/state of the objects.
Moving Objects across a socket - can be done. We developed a component for our socket suite
that makes this a snap. Basically what we do is push the object into a stream, then push the
stream across the socket using pointers. (That is the 2 second description).
Ozz Nixon
www.dxsock.com
Add a Comment
New Questions: Client/Server mystery
(sockets)
From: Tara King
Thanks,
Tara King
(703) 676-5543
[email protected]
From: venkat
I am not sure if I understand your situation well enough, but it seems to me that you should not
have any sockets code in your server program if you are using inetd. inetd handles this for you.
-- Jacob.
From: Taylor
I too had this problem, without the inetd part -- just two
socket apps that wouldn't talk when I ported them to Unix.
I would have to start the server first. Putting a call to
"close" on the socket ID on the client side, after a failed
connect call, seems to do the trick. Oh, followed by another
call to "socket" to initialize it.
Hi !!!!
Add a Comment
New Questions: Connec to different
hosts/ports from the same host/port
From: Fabio Bettoni
Single socket bindes on remote machine can accept more than one connection from
the other Machine.
From: Harshit
Add a Comment
New Questions: Compiler Difficulty
From: Han Guowen
/* socket_server.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
char *strs[NSTRS] = {
"This is the first string from the server.\n",
"This is the second string from the server.\n",
"This is the third string from the server.\n"};
main()
{
char c;
FILE *fp;
int fromlen;
register int i, s, ns, len;
struct sockaddr_un saun, fsaun;
/* Accept connections.
When we accept one, ns will be connected to the client.
fsaun will contain the address of the client */
if ((ns = accept(s, (struct sockaddr *)&fsaun, &fromlen)) < 0){
perror("server: accept");
exit(1);
}
exit(0);
}
/* socket_client.c */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdio.h>
#include <stdlib.h>
char *strs[NSTRS] = {
"This is the first string from the client.\n",
"This is the second string from the client.\n",
"This is the third string from the client.\n"};
main()
{
char c;
FILE *fp;
register int i, s, len;
struct sockaddr_un saun;
I also have this problem. I am a starter in socket programming. When I first copied someone's
program, and using "gcc filename" command to compile. But the link always failed because the
compiler does not know socket, connect, bind, etc even I put all the relevant header files in my
program.
I also want to find out how to compile socket program. There must be some easy tips!!!
From: Sam
-lnsl -lsocket is generally needed on Sys V based systems which put BSD specific functions
into separate libraries from its C library. If -lnsl -lsocket is needed, you probably also need -lucb
for other BSD functions. You need these options for Solaris.
From: roshan
do anyone please tell if we can have many clients in the server program above without the fork
option,ie if there has to be inetraction between the clients of the same network..
From: Norvin
The linker options -lsocket and -lnsl don't seem to work on HPUX. Any special issues here?
Add a Comment
New Questions: How to know if the sending
buffer is fully empty?
From: Paul Mamin
How could I know that the sending buffer is fully empty (i.e. all data were sent or almost sent to
the peer)?
By select() I could only know that there's some space in the sending buffer and nothing more.
From: Jill
Hi Paul,
This is how I've checked my data. Since it's ANSI C you can use it on both Unix & PC
platforms.
int send_chk;
If (send_chk != strlen(szMsg))
{
printf("send_chk = %d\tszMsg = %d\n\n", \
send_chk, strlen(szMsg));
Hi,
I haven't found a way to check the number of bytes available in the send or receive buffers.
getsockopt() with SO_RCVBUF/SO_SNDBUF return the size of the buffers however.
Do you need to know the available size of the buffers just for information or to do something
special. Maybe there is another way to do it without having the available size.
Add a Comment
New Questions: How do I get the IP Adress to
which a client connected to my server ?
From: Jens Thiele
If you bind to INADDR_ANY rather than a specific address then your server will listen() on all
the host's IP's.
After you accept() the new connection use getpeername() on the new socket fd to get the
address and port the client connected from.
In the same manner, call getsockname() on the new socket fd to get the address and port the
client connected to.
You can also use getsockname() on the original listening socket fd after you bind() it to find out
which port it will be listening on (in case you bound to port 0).
From: Paresh Mehta
Hi,
From: bob
bang
Add a Comment
New Questions: client server program
From: Raghu
I also want this sample program.But this program should be work even I take out the cable and
until I plug in back.
Add a Comment
New Questions: What are the limits on the
number of sockets?
From: Michael Friedman
What are the limits on the number of sockets from a single server?
I'm looking at an application where a single server will have relatively light weight connections
to over 100,000 clients. I strongly suspect that I cannot dedicate one socket per client, but I'm
not sure.
Are there any OSes with higher limits on the number of possible sockets?
From: Gavin
How can you increase the FD_SETSIZE to allow more then X amount of connections that the
OS defaults to.
From: Ville
I am trying to accomplish a similar feat, so far some test code has shown that Win2k can do
about 8000 connections, dropping with lower versions of NT. Win9x can only do between 80
and 120, so my hope was Linux would be the answer. So far I've missed it, being able to get
1000 connections - some have pointed me to multi-threading or multi-processing, but as Im new
to both topics I have not been able to get anywhere. Any advice would be appreciated.
From: Rob Seace
Well, there are a few different things that will limit you
from having ridiculously huge numbers of sockets... One is
the OS-imposed limits on number of file descriptors; both
on a per-process basis, and system-wide... Another is your
libc's "fd_set" size ("FD_SETSIZE")... Another is simple
exhaustion of system resources (each open FD sucks up some
amount of RAM in your process, and likely in your kernel)...
Actually, if it's the server you're talking about, then you can use on port. Sockets are determined
by the 4-tuple of <destaddr,srcaddr,dstport,srcport> so if you had 100,000 clients then the
srcaddr and srcport would be different for every client. The only way you would run into
problems is if the 100,000 clients are all on the same machine.
Derek
From: Andy Ning
I have test the method and it works well. Only thing I'm not
sure and don't know how to figure out is the performance.
Say, one process handle 512 connections versus two process
each handle 256 connectons, which one is more efficient?
Andy
From: Xuemei Zhang
Hi, all
Xuemei
Only newly created connections will work with the new configuration.
From: Frank
I might be missing something, but if you're trying to maintain 100,000 connections at once,
that's impossible with TCP/IP - you can only have 64,000ish ports connected at the same time
because that's all that TCP can handle...
From: Willy
For an extremely large number of light weight connections (i.e. few bytes transmitted at
large...by computer standards...time intervals), why not use a connectionless protocol like
datagrams and do the error-retransmit logic internally?
Add a Comment
New Questions: How much new Bytes are in
the Buffer for Inread ?
From: Stefan Schnuderl
How can I get the number of new bytes in the buffer, which have been received from the Server
since the last call of read(socket, *buffer, len) ?
/\
||
I need to know this len.
if (ioctl(aDescriptor,FIONREAD,&availBytes) != -1)
return availBytes;
else
{
perror("availableBytes");
return 0;
}
}
From: Daniel Liljebladh
Fantastic ! It works excellent :)
Add a Comment
New Questions: Socket and thread
From: Mario
How can I do to that one application work with sock and thread sametime?
From: Mark
Add a Comment
New Questions: Undefined Symbol Problem
From: Eric Johnston
I have been able to compile, but not link, a client-side socket program, and have been
consistently receiving the following error messages:
This only appears to occur on Solaris 5.6 (SPARC) -- Which is my target platform.
I have not received this error message on Linux 6.0 (Intel) -- where the test program runs
properly.
The information you were looking for is the first thing listed in the SYNOPSIS section of the
socket(3N) or socket(3XN) man pages.
From: Anurag Mishra
This undefined symbol can be removed by properly linking the header file.
If its compiling then do like this & try.
I have been same problem and I haven't get the answer for this
question.I can't find words to say how thankful I am.
i meet another problem, i use method above to compile my program, i use the inet_aton method
in program, when compile i meet the "Undefined symbol inet_aton". how can do it. Thank you
for advance.
jason
Add a Comment
New Questions: synchronous and
asynchronous communication using sockets
From: Paresh Mehta
Hello sir/s,
From: Gangadhar
Hi,
Can you please tell me how I can do asynchronous socket programming in UNIX.
thanks
Gangadhar
From: James Kassabian
Use the select(3C) function from the standard C library for synchronous I/O multiplexing. You
pass 3 pointers to file descriptor sets (fd_set objects), among other arguments, to the function.
An fd_set object is just a bit vector. One fd_set object is for those file descriptors to be tested
for reading, one fd_set object is for those file descriptors to be tested for writing, and one fd_set
object will indicate which file descriptors have pending error conditions.
Initialze the fd_set objects with the FD_SET macro. select(3C) modifies the fd_set objects
passed as argument on output. If a file descriptor is not ready, select(3C) clears the bit for the
file descriptor in the corresponding fd_set object. You use the FD_ISSET macro to test if the bit
for a file descriptor has been cleared or not. If it was not cleared it is ready. Always test the
same bit in the error fd_set object first. If the bit is set in the error fd_set
object you should test the file descriptor for errors instead of using it.
Add a Comment
New Questions: PORT NOT RESPONDING
From: VENKAT
Dear All,
Thanks
-Venkat
From: Asha
Hi,
We are facing the same problem. if you figure it out, could you please let us know.
Asha
From: Rob Seace
You say that if you change the port that the client is
using, it works? Then, my guess would be that the problem
is the old connection is still in the TIME_WAIT state, and
hadn't yet timed out, so you wouldn't be allowed to connect
with the same exact source port and IP to the same exact
destination port and IP... See the other sections in the
main FAQ here for more details about the TIME_WAIT state...
But, I think you already came up with the logical solution
to the problem: use a different source port on the client
for every connection... That's what you SHOULD be doing,
anyway... In general, unless there is some very special
need for a specific source port, all clients should let the
system assign them an unused port, and should NOT specify
their own... I believe that's mentioned here in the FAQ
somewhere, too... Ie: your client should simply not bother
with calling bind() at all, and just let the connect()
handle it for you; or, if you must call bind() for some
reason, just set "sin_port" to 0 in the sockaddr_in struct,
and then bind() will generate a new port# for you, and fill
it into "sin_port" for you...
Add a Comment
New Questions: How....
From: Bob Andrews
Does anyone have any idea how to create a client using sockets that does the following,
Follows a starting URL, parses that file for url links, then puts those links into a log file. It then
verifies each of the links and returns their status using HTTP responses??.
Bob
From: Thierry PAI
You probably don't even need to use sockets...just call nc from your C program.
system("nc www.google.com 80 > tempfile");
<OR>
FILE *fp = popen("nc www.google.com 80", "r");
loop using fgets(buffer, bufsize, fp);
pclose(fp);
popen() does something like re-route stdout from the system call to FILE *fp
...check the man pages.
Add a Comment
New Questions: Asynchronous client
From: jagadeesh
Hello,
I need to send more than one request to server to get the respective response message. I need to
develop an Asynchronous client. pl. send me some details .
Thanks
Jagadeesh
From: Mahafuz
Pls try creating thread where every thread will send a request to server & get the respective
reply.
or
Add a Comment
New Questions: What do you do to constantly
poll a file on the client side (Unix) and send it
to server (NT) ?
From: Navin Agrawal
Q : In short I am developing a program which transfers data from Unix box to NT. Now NT
acts as server and Unix box is the client. I have developed the connectivity between the 2. My
problem is that this Unix Box has to constantly keep on polling on one HEX file (which may
reach a size of 35GB) and any NEW changes (just the changes) in this file should be sent to the
NT side where the necessary processing will be done.
Now can someone give me the proper code on the Unix side. And this is URGENT because I
am really short of time and have to complete this in a day or two. I hope I made myself clear
about my question.
From: John
Since the client process never knows when more is going to be added to the file, and since using
select on the file
won't help you, in this case you must simply poll the file
by repeatedly attempting to read it.
I hope this answers your question.
From: jay
John has given the solution but I think u should poll the file for updatation means u have to
check when file is updated if the time is greating the the last check u can transfer the file to
unix. For file updation u can use standard C library function.
From: Jay
The simple is answer is: don't re-invent the wheel! You've described pretty much exactly what
rsync() does. It is open source, and can be made to run on Windows.
Wes
Add a Comment
New Questions: Asynchronous client ?
From: jagadeesh
Thanks
From: VP
Async client :
. Open socket
. Establish connection
. set it async (can use fcntl() F_GETFL & F_SETFL options)
. fork ()
. Child :
for(;;)
Take/Read input messages/data - say user_query
use select() for 'writable' check/wait
Send across
. Parent :
for(;;)
use select() for 'readable' check
Receive processed output/data
Do the needful - say, answer user query,
update DB etc
The basic idea is to getaway with BLOCKING calls of
sockets() and as shown above, I think we can use select()
for achieving the same purpose and the same can be extended
to server side also.
--
VP
Add a Comment
New Questions: writeset in select
From: AK
TIA,
AK
From: John
The write set allows you to test when you can write to a socket. This is useful if you are writing
a lot of data to a socket and the buffer fills up. The select will then indicate that you cannot
write on the socket, so your process can do something else, instead of blocking while trying to
write until the buffer empties.
If you are not writing much to a socket, of have a program that doesn't have anything else it can
usefully do instead of writing, then you can let the program block on write and not bother with
the write set in the select().
Add a Comment
New Questions: no client server setup !
From: Sameer kamat
I want to know some kind of implementation detail of how I could have only a client client
setup and have a commmunication between them. I want to one client to communicate with a
server of another client and vice versa. Please clear this doubt !
-Sameer
From: Jay
Add a Comment
New Questions: Autoflush
From: Rino Morin
I Have 2 Question.
2. In C. how do you do autoflush, to clear the buffer. OS/2 and Windows automatically flushes
it, but in unix. ther has to be a way to flush the buffer.?
From: James Kassabian
1. Use fcntl().
2. Use setbuf(3S).
Add a Comment
New Questions: using loopback interface for
testing socket programs
From: Anup Ochani
yup
Add a Comment
New Questions: Check readset and writeset at
the same time
From: Winnie
i'm wondering whether i can check the readset and writeset at the same time (within a select())
call?
From: John Vincent
can you explain me how readset and writeset can be done at one time.can you give the eg code.
Add a Comment
New Questions: How to bind using struct
sockaddr_ll..?
From: joelle teh
struct sockaddr_spkt is obselete in Kernel 2.2 and struct sockaddr_ll should be used.
but i'm facing problem in specifying the socket to bind to the particular NIC using this
soscket address structure.
thank u..
From: Lars Westerhoff
The sockaddr_ll is not only used for binding but also for
returning informations about a received packed (recvfrom(2)).
For bind() you only need to fill sll_family (AF_PACKET),
sll_protocol (the link-layer protocol, e.g. ETH_P_IP)
and sll_ifindex. See packet(7) for details.
Add a Comment
New Questions: Opening a socket on a random
port number
From: Tom
Dear all,
Does anybody know how to bind a socket to a random port number (>1024), by letting the
system assign a currently available port to your socket? I'll briefly explain why : it's an FTP
client, and I need to create a listening (client-side) socket for the data connection, and then
notify the server of the port number with the PORT FTP command.
Alternatively, is there an easy way to return the port number of a currently available socket (ie
not just guessing one and testing it's availability)?
Tom
From: Richard Foletta
You tell the system to give you a port number by setting the SOCKADDR_IN.sin_port to 0.
Then do the bind(). The bind() will give you a socket fd. use the getsockname() function to fill
in a new SOCKADDR_IN structure. the sin_port member will now hold the value of the port
that was given to by the system. Following is some sample code.
//-----------------------------------------
// bind the queue_addr to the socket
//-----------------------------------------
rc = bind(queue_fd, (SOCKADDR_IN*) &queue_addr, sizeof(queue_addr));
if ( rc<0 ) {
error_it(__FILE__,__LINE__,"Could not bind to socket, errno=%d
%s\n",errno,strerror(errno));
return Q_BINDERR;
}
//-----------------------------------------
// If the qname.port was set to zero then
// the system picked the port for us on the
// bind call above. use getsockname on the
// queue_fd to find out what the port is
// that the system gave us so we can make
// it available to the user of this object.
//-----------------------------------------
if(atoi(qname.port) == 0) {
SOCKADDR_IN test_addr;
int len = sizeof(test_addr);
memset(&test_addr,0,len);
getsockname(queue_fd,(SOCKADDRPTR) &test_addr,&len);
ushort portnum = ntohs(test_addr.sin_port);
sprintf(qname.port,"%d",portnum);
}
Add a Comment
New Questions: What is the meaning of the
IDLE state in netstat command
From: JES
Add a Comment
New Questions: How can the client know, if the
server has accepted the connection?
From: Virat Patel
As long as the server is listening , if the client make a connect - it succeds immediately. It is
important for me that I know when the server has accepted the connection. One thing I can do is
once I make a connect , I can do a blocking read and let the server send a message when it
accepts the connection. But I am sure there can be another way, I believe TCP certain internal
message to be send to the client - when the server does an accept.
thank you
From: Ahmed
Connect system call returns as successful only if the connection had been established between
the two systems.. TCP handshaking messages are exchanged internally..
From: Warren Nash
i will uses wsaasyncselect() function to ask notify about completed connection.. for example :
after i use mysocket = connect();
i write wsaasyncselect(mysocket,mywinhandle,wm_getconnect(*where its my custom
message),FD_CONNECT);
so thats after mysocket complete connection (or same as accepted by server) winsock will send
message wm_getconnect to my progie where i have to write what the process will do after.
From: Acidblosoom #kumkum
I beg ur pardon cauze what i explain above is uses in windows environment. try to use select()
instead wsaasyncselect().
Add a Comment
New Questions: How can the client know, if the
server has accepted the connection?
From: Virat Patel
As long as the server is listening , if the client make a connect - it succeds immediately. It is
important for me that I know when the server has accepted the connection. One thing I can do is
once I make a connect , I can do a blocking read and let the server send a message when it
accepts the connection. But I am sure there can be another way, I believe TCP certain internal
message to be send to the client - when the server does an accept.
thank you
From: jeff dennison
1) open socket
2) use ioctl to set up non-blocking socket
3) set socket options SOL_SOCKET, SO_REUSEADDR
4) issues the connect() from within loop and check the errno returned by connect(). if connect
returns 0 or connect return < 0 AND errno = EISCONN then break the loop
5) You are connected
From: jeff dennison
1) open socket
2) use ioctl to set up non-blocking socket
3) set socket options SOL_SOCKET, SO_REUSEADDR
4) issues the connect() from within loop and check the errno returned by connect(). if connect
returns 0 or connect return < 0 AND errno = EISCONN then break the loop
5) You are connected
Add a Comment
New Questions: Which error detection method
to use?
From: Jonathan Rynd
Is there a standard way of determining when to use the errno variable, and when to use
getsockopt() ?
Add a Comment
New Questions: concurrent server !
From: jaya wijethilake.
Hi,
Also Do I have to use event table to keep track of all sockets and how I create
a event table. When to close child socket and master sockets?. And specialy my connetion
to main server must be allways up. So onece the first request accepted for a one serivce
that must be up forever { for all 3 services). Mulltiple connections for all three
services I must handle.
best regards,
Jaya.
Jaya,
Richard's book has everything you need - even the source code
is available at his web page.
Add a Comment
New Questions: Discarding unwanted socket
data
From: Tom
Hi,
is there a way to throw away n bytes of data from the receive buffer of a socket, without
RECVing it into a local buffer and then throwing the returned data away?
I would like to be able to retreive a single line of text from a socket at a time. I had planned to
do this by RECVing say 2048 bytes of data with the MSG_PEEK flag, searching this data for
the end-of-line character, calculating the number of bytes that the single line of text consumes,
and then discarding that number of bytes from the socket recieve buffer. It seems ineffecient to
RECV the data twice (first peeking and then reading), so is there a way to discard socket data?
Tom
Add a Comment
New Questions: Options besides concurrent
servers
From: Yishai
I'm writing a TCP server but instead of spawning off a child process for each connection that
comes in, I just want to handle the request with any process from a pool of pre_created
processes. I need to do this as the processes have a large memory overhead which would make a
fork() prohibitvely expensive.
Add a Comment
New Questions: read write continuosly!!!
From: jaya
hi,
jaya.
From: jagadeesh
send and receive some junk message to keep connection alive at certain interval of time.
Identify type of message and process it. If the message is not with respect to your requrements
discard and send and send some junk message. Do the othe end alos in the same way.
-jsh
From: manohar
I would prefer to increase the number of pre-forked children of socket based server, depending
on the number of pending connection in the listen queue. There's a way to determine this
number ? Thanks in advance.
Add a Comment
New Questions: How can i get the IP address
form name domain?
From: Mario Rugeles
ej.
IP = 204.71.202.160
I believe you're looking for gethostbyname(). Note however, that I have never been successful
in understanding the hostent structure. Any in-depth explanation of the structure you find would
help me greatly.
From: Rob Seace
phostinfo = gethostbyname(query);
if (phostinfo!=NULL)
{
IP = inet_ntoa (*(struct in_addr *) *phostinfo->h_addr_list);
return IP;
}
From: Danny shaul
phostinfo = gethostbyname(query);
if (phostinfo!=NULL)
{
IP = inet_ntoa (*(struct in_addr *) *phostinfo->h_addr_list);
return IP;
}
From: Danny shaul
use this :
phostinfo = gethostbyname(query);
if (phostinfo!=NULL)
{
IP = inet_ntoa (*(struct in_addr *) *phostinfo->h_addr_list);
return IP;
}
From: Danny shaul
use this :
phostinfo = gethostbyname(query);
if (phostinfo!=NULL)
{
IP = inet_ntoa (*(struct in_addr *) *phostinfo->h_addr_list);
return IP;
}
From: sam
go to hell
Add a Comment
New Questions: How do I put my NIC in
promiscuous mode?
From: Scott
Hello,
I am trying to write an application for automatic IP adress allocation and have been tring to find
out how to place a NIC in promiscuous mode.
Thanks,
Scott
Thanking you,
Waiting for Your Reply...
Add a Comment
New Questions: What port do I broadcast
messages to?
From: Steven
My server needs to broadcast a datagram (UDP) message to several clients. What port, on the
HPUX machine, should i send to?
Thanks,
Steven
From: Hunter
Well, i'm not familiar with HPUX but the question should be:
"What ADDRESS should I broadcast messages to?"
I suppose that if you send a message (say ICMP ECHO) to the
broadcast address of your network, all machines will answer
to it....
the port should be the port your clients are listening on...
I hope i have helped....
Regards,
Hunter
Add a Comment
New Questions: sendto/recvfrom errors on
Solaris
From: Neil Milani
Add a Comment
New Questions: Unix socket programming vs
NT window socket programming
From: Patrick
I wrote a network game. The server is in Unix. And I tested that client could run in win98 and
win95. However, when I
tested the client running in NT. The server seems that cannot bind the socket. Why? Pls. help
me. Thanks a lot
From: Duda
hi,the socket on windows are more complicated.for you will have to initilize the socket
library.and use a type as SOCKET instead of int.
From:
1.What does Windows ahve to do with it, if the server (where bind() problem) run un UNIX ?
2. Check tcp number port translation ( htons(...) )
Add a Comment
New Questions: optimal solution
From: Eliahu
You might want to consider UDP. TCP requires the three way handshake to set up each
connection, so for quick messages between numerous hosts there is a lot of overhead.
Of course once you get a TCP connection established it isn't so bad, and does take care of
re-transmits, etc. It all depends on whether you want to keep all these connections alive or
prefer to stay connectionless.
From: Jay
Use multithreaded program which is faster then the server who use forking. Bcoz creating a
thread use less OS operation and u dont have to use much IPC.
So ur server can be fast.
Add a Comment
New Questions: Chat program in C/UNIX
From: EY
Where can I get the source code(client/server) for chat program written in
C/Unix ?
From: MANOJ KARANTH
are yaar ,
instead of putting the question here,why don't u find it your self
good luck,
;-)
From: Akintayo
Can any one tell me where can i find the source code for the chat program written in c on unix
From: sudhakar
how can i get the source code for chat program using socket programming
From: charlie
where can i get a souce code for Internet browser on UNIX environment?
From: kiran
All these programs are inclided in linux (standard package)with codes. so pls look in linux for
these codes. You'll get a lot of them.
From: lost
If u want source code to a simple client\server chat program then email me...ill be glad to send u
the one i made
From: Arindam Malakar
Hi,
Please send me the source code for the chat program and
also the source code for file transfer through ftp if
these are avilable with you.
With Regards,
Arindam Malakar
From: Andy
If you are wondering about chat programs called 'talkers' there there's a variaty of sources for
them, depending on the type you want. Here are a few places to check out to get source code:
http://amnuts.talker.com/
http://pgplus.ewtoo.org/
http://asteroid-b612.org/ncohafmuta/index.shtml
http://www.ogham.demon.co.uk/nuts.html
http://download.ewtoo.org/
http://www.talker.com/libtalkercodes.html
Andy
From: Banjo
how can i get the source code for chat program using socket programming
From: tito
From: Dan
Come on people.. Look around some.. look in the code examples, perhaps, in the main part of
the faq??
Well if you are looking for a irc server, hybrid(which is used on a good portion of efnet servers)
is at http://www.ircd-hybrid.org/
Add a Comment
New Questions: how to create second socket
on my client application
From: kurumlu aliye
I have two client applications to communicate one unique Server. For the first application I
establish a session by using socket() and connect()functions. But for the second conncetion
when I do the same thing for my second connection, Server refused my connection. I guess
reason for it is to use same socket Id for both connections. My question is how I can create
another socket in my second client application
From: Warren Nash
Add a Comment
New Questions: how many simultaneous
socket connections can a concurrent server
accept?
From: Jaeyoun Chung
Hello,
I'm writing a TCP concurrent server which should accept from many many clients and keep the
connections -- from time to time, it sends back some informations to the client. I used select call
in the while loop body so that it can service concurrently. But the accept() call fail when there's
about 60 client connections there. Should I fork a new server and listen() and accept() again
after closing all the descriptors that have been opened?
From: Xidong Wang
hmm, each process has its own upper limit of opened file decriptor, maybe 60 is your program'
limit.
bye the way, maybe you can check the retrun value of accept and errno value, they can tell you
more about the situation.
-wxd
From: AK
How would you get more than 1024 connections? Would you need to use multiple processes, or
could multi-threading work?
Add a Comment
New Questions: Sending integer values to
sockets.
From: skuzzlebutt
Skuz.
From: Rob Seace
int i = 42;
write (sockfd, &i, sizeof (int));
int i;
read (sockfd, &i, sizeof (int));
SENDING
int id;
id = 10;
if ((send(sockfd, id, sizeof(int), 0)) == -1)
{
/* error handling */
}
RECEIVING
int id;
if ((recv(sockfd, id, sizeof(int),0)) == -1)
{
/* error handling */
}
else
{
printf ("The recv'd id is %d \n", id);
}
I have tried both htonl/ntohl & htons/ntohs
but I never receive anything like the data I am expecting.
Skuz.
From: skuzzlebutt
Cheers Rob, I've got it sorted, your example put me in the right direction.
Skuz.
From: Rob Seace
Add a Comment
New Questions: can u answer this ??
From: ganesh
Can we write a C-program which writes to a file for which all the permission bits are disabled ?
From: Wang Xidong
As a SU, you turn on the write bit, write to the file, then turn it back off again
From: S.Krishna
Add a Comment
New Questions: C to unix base by win sock
From: yeow choon hong
Add a Comment
New Questions: C to unix base by win sock
From: yeow choon hong
Add a Comment
New Questions: Multiple blocking on select.
From: chris orthner
How do I use select() within a server application to comunicate to multiple sockets within a
looping structure?
It seems after the first itteration the select() call no longer blocks, it just returns -1. It seems to
be an issue with the read, write and error bitmasks and the FD_SET/FD_ZERO/etc. macros.
Obviously it can be done, I'm just not sure how to use the macros properly.
while(1){
FD_ZERO(&readfd);
FD_ZERO(&writefd);
FD_ZERO(&exceptfd);
FD_SET(listenSock, &readfd);
FD_SET(listenSock, &exceptfd);
}
From: skuzzlebutt
... }
doesnt do the trick, what's the size i got to use?
it blocks once, but not twice ...
greets
Pieter
From: Rob Seace
FD_ZERO (&permfds);
FD_SET (listenfd, &permfds);
maxfd = listenfd + 1;
for (;;) {
tmpfds = permfds;
/* or memcpy (&tmpfds, &permfds, sizeof (fd_set)); */
cnt = select (maxfd, &tmpfds, NULL, NULL, NULL);
if (cnt > 0) {
for (fd = 0; fd < maxfd; fd++) {
if (FD_ISSET (fd, &tmpfds)) {
if (fd == listenfd) {
/* it's an incoming new client */
newfd = accept (listenfd, NULL, NULL);
if (newfd < 0) {
/* error; die or whatever */
} else {
FD_SET (newfd, &permfds);
if (newfd >= maxfd)
maxfd = newfd + 1;
}
} else {
/* it's a client connection; read() */
/* from it, or write() to it */
}
}
}
}
}
From: Pier
i tried your suggestions, but it didnt work. i included a larger snippet of code. I did use
&rdfstmp (i changed it to tmpfds). I dont have a clue, btw: im running this on a 2.4.0-test1 i686
linux machine, could that be the problem?
kind regards
Pieter
FD_ZERO(&readfds);
FD_SET(fd, &readfds);
FD_SET(STDIN, &readfds);
while(1) {
// memcpy(&tmpfds, &readfds, sizeof(fd_set));
tmpfds = readfds; //same result as with memcpy
tv.tv_sec = 2;
tv.tv_usec = 500000;
hi
now i check for a zero return value, but it still doesnt work cause it returns 1, but there is no
data (the read returns 0). The select also doesnt wait the hole 2.5 sec, so it doesn't time out.
i start the program, wait a few seconds, then press enter and in 1 sec i get thousends of
messages below (cause its in a loop)
this is my output:
UIT: 0
UIT: 0
UIT: 0
UIT: 1
A key was pressed!
UIT: 1
A key was pressed!
UIT: 1
A key was pressed!
code snippet:
greets
Pieter
From: Rob Seace
code:
output:
UIT: 1
READ:0:Login:...
UIT: 1
READ:0:Login:...
regards
Pier
From: Rob Seace
regards
Pieter
Add a Comment
New Questions: multiple connections
From: yhel
How can I filter the connection to a limited number of clients. I tried to accept connection but
only 1 client
can be accepted. Does it has something to do with the format of the parameter I passed in the
accept() function.
From: vinay
Add a Comment
New Questions: using libpcap
From: Marc
Hello all,
I am using Net::RawIP and libpcap for Perl. My question is,
when i use the program on my LAN i can capture packets. But,
when i try this on the internet i get nothing. I am on a
cable modem, and I have heard that this prevents packet
capturing. Is this true? Anyone know about this or away
around it?
Thanks,
-Marc
From: Andreas Forsgren
True, but you should still be able to capture packets going in/out from your local interface.
From: Johnathan Ingram
Hi
Now if you where connected to a switch or your modem, the ethernet packets are not repeated
accross all ports on the switch. You cannot "sniff" packet as the packet will never reach you nic
unless it was destined for it.
This is why we have switches. To reduce traffic on lans and to prevent packets from been
sniffed.
L8r
Add a Comment
New Questions: buffer limit
From: Anup
Add a Comment
New Questions: How to find local IP address in
client.c program
From: Warren Nash
Lastly, I was wondering if anyone out there has a proper client.c and server.c
e.g. Robert Stevens that has "printf" debugging through - so
So I could see waht gets passed / updated / returned by all the
functions that could be used in client.c and server.c
King Regards
Warren Nash
From: Rob Seace
Give the actual array size of str instead calling the sizeof(str), which gives you only 4 bytes
result
From: Jim Patterson
When you call getsockname(), you need to initialize len to the size of the socket address
structure you pass in before calling it. That might be why your code crashed.
From: Anil Maipady
MIB II have an entry which stores the ipaddress of the host that is
"iso.org.dod.internet.mgmt.mib-2.ip.ipAddrTable.ipAddrEntry.ipAddress" you can query this to
find the IP address of local host, since socket calls will always do a look up.
Add a Comment
New Questions: Swap area
From: Anup
If it were, it would be hard to understand why some servers running under Unix can process
millions of requests every day and stay up for months and even years without being restarted. It
sounds to me as if something you believe you deallocate, probably a buffer, you don't. A good
investment for a programmer is a debugging heap allocator, the equivalent of something like
Smartheap in the Windows world. Many Unix libc's come with one, eg. GNU. Best to exhaust
this possibility before assuming something horrible about the operating system.
Add a Comment
New Questions: Using socket fuctions and
debugging
From: Warren Nash
Rob,
Thanks for the reply - but I have tried to use the getsocketname()
function and I receive a segmentation error. Here is part of my code.
Lastly, I was wondering if anyone out there has a proper client.c and server.c
e.g. Robert Stevens that has "printf" debugging through - so
So I could see waht gets passed / updated / returned by all the
functions that could be used in client.c and server.c
King Regards
Warren Nash
Add a Comment
New Questions: how does one measure
throughput in TCP and UDP?
From: Abhinav Keswani
Maybe take a look at bing... It actually seems to use ICMP to do its measurements, rather than
TCP/UDP, but it may give you some ideas...
From: Andy
download an IP sniffer. A good one will give you readings on num of packets, size, bytes, etc,
as well as source & destination address and port.
From: Anton Hendriks
What is the underlying mechanism used by UNIX 'snoop' command (source code?) so that I can
butch it, get rid of the 'content' and simply catch the byte size of each packet?
Add a Comment
New Questions: defnition
From: anitha
what is socket?
From: Mahafuz
pardon my english.
Add a Comment
New Questions: source-IP equals dest-IP
From: Lukas
Add a Comment
New Questions: Proxy Server written in C
using sockets
From: Warren Nash
Does someone have an example of how to write a proxy - while using the
example(s) in Richard's Unix Network Programming Book.
From: Vaishali
Excellent!!!!
From: Wang Xidong
I have implemented one socks proxy and one http proxy, is there anyone who want to see it?
From: Warren Nash
Yes I would like too see the HTTP proxy - as I am at the moment
not reeiving all data back from the web server, I would be very
interested how someone else may have written there proxy server.
Warren Nash
[email protected]
From: Antonio
From: srini
sir,
Add a Comment
New Questions: gethostbyname
From: hanaa al-ostad
I'm trying to write a client program that uses gethostbyname to look up the machine names at
my site .
it's a simple program but when I complied it it gave me an error that the gethostbyname is not
defined
although I have included all necessary file and I wrote exactly as in my book .
Hai
i guess u have to include the library option -lxnet for including those library.It should work by
that way.
Kumaran M
From: Kumaran M
Hai
i guess u have to include the library option -lxnet for including those library.It should work by
that way.
Kumaran M
From: Arthur Lung
If it's a link time error, and you're sure that you have all
of the correct libraries included, and you're sure you didn't
spell it wrong, it could be that your library path is wrong.
Add a Comment
New Questions: select() for timing
From: Johanna
Why does this function call return the error "No such file or descriptor":
select(0,NULL,NULL,NULL,&tval) where tval is set to a value greater than 0? This works as a
timer on one machine environment without Forte running and does not work on another
machine environment with Forte running. Is it Forte or is it some other environment setting?
From: johanna
After further testing, the select statements work well when the calls to Forte are commented out.
As soon as I call ForteStartup, I get system interrupts to my select statement. The errno value
was not valid since I was calling select within a pthread which has it's own errno, correct?
From: Warren Nash
I solved my timer problem by using pthread_cond_timedwait instead of select(). But then the
select I used for reading the sockets kept returning "Interrupted system call" (as perror showed),
but the errno value was still "No such file or directory". So now I check for ENOENT instead of
EINTR and call select again and everything works fine. Strange!
From: Corey
you may also be getting some issues with linking multi-threaded and non-threaded libraries
together.
Or more specifically, having _REENTRANT defined before #including <errno.h>
- _REENTRANT affects the way errno works - which sometimes causes the wrong errno to be
referenced.
Also, you should be able to pass all NULL sets, but there is no reason that you can't pass a set
which has no FDs set in it (ie an FD_ZEROed set). There is also no reason to say maxfd is zero,
as long as your sets are NULL or empty. This may make it work. Other then that, only signals
may be stuffing up your select.
cond_timedwait is a pretty good solution for timing because it can be cut short by another
thread at leisure. Great for indicating that you do not need to wait any longer.
fv.
Add a Comment
New Questions: nic card
From: asheesh
hello
iam making a simple program to capture frames. can someone tell me how to get the address of
the
buffer in my system memory where the buffer is created? Can someone tell is there a version of
tcpdump for winnnt?
(iam rather new to net. prog. ; therefore the question might look
trivial to some.
regrads
asheesh.
Add a Comment
New Questions: How do I access individual
packets being received on a socket?
From: Tym
Hi,
Is there a way to read/write one packet at a time on a socket? Idealy I'd like to call something
like readpacket(sock, buff), and I would get back the data contained in the first packet that is
read from the socket, as well as how many bytes were read. Similar thing for writing (ie. write a
packet at a time). Is this possible with sockets, and if not, how would I do this in UNIX. Do I
need to use Raw Sockets, and/or libpcap?
tym
From: Bruce Edgerton
Tym, a simple way is to write the length of the packet first and then at the other end do one read
to get the length, followed by another read for the actual packet.
Regards,
Jacques
From: kapil
Hi !
I think u can do it by using the writen and readn functions given in the richers stevens book.
hope this helps
Add a Comment
New Questions: Time out on Recv
From: Krishnakanth
I am using select to time out on a recv. This socket is a UDP socket. Sometimes even after
select returns, FD_ISSET is not set. When i tested by ignoring this recv call gives me an error
"Bad file descriptor:" .
Thanx in advance
Krishna
From: Rob Seace
Well, without seeing the code, one can only guess... But,
possible causes are: the timeout is being exceeded; or, you
are getting hit with a signal of some sort which interrupts
select()... What is "errno" set to? What exactly is the
return value from select()?
From: sapnakaiya
Hi Krisnakanth,
Thanks,
sapna.
Add a Comment
New Questions: restart server
From: V.C.Mahadevan
Sir,
I am now engaged in a Multithreaded distributed fault tolerant software
development.When the user wants to change the mode from distributed to
non-distributed mode (or viceversa),he can give a command,in which case the
application spawns a thread and communicates with the user.Obviously,
its neccessary for the application to be restarted in other
mode.But while restarting I am unable to bind a new server,
as the old socket is still in TIME_WAIT state.What should I do,
for avoiding this unnecessary wait state?
Well, you should probably start by actually looking through the existing questions in the FAQ
to make sure your question isn't already answered before asking it... Specifically, this issue is
covered in Question 7, Section 2, and Question 5, Section 4... In short, you'll need to use the
SO_REUSEADDR socket option...
Add a Comment
New Questions: SO_RCVBUF
From: jagadeesh
Add a Comment
New Questions: recv() fails with EGAIN for a
blocking socket
From: AK
Hi,
if(ioctl(sockfd,FIONBIO, &on))
{
printf("ioctl failed\n"));
close(sockfd);
}
printf("socket %d has been set to blocking\n", sockfd));
I'm facing the foll. problem: the packet header says there
are a finite no. of bytes to be read in the packet.
But when i go on to actually read those no. of bytes,
recv() is failing with error EGAIN (Resource temporarily
unavailable).
What does this error mean and why is read
returning at all if the socket is blocking ??
From: Terrance
Got this error too - but what I did was to go into a wait
state ( e.g. sleep( 10 ) ) and try the socket connection
again. If this does not work - it will loop and wait a
number of times before reporting it as an error.
EAGAIN means:
Your socket is set to non-blocking mode, and the receive
operation would block (because there's no data, or you tried
to read more than there is), OR, you set a receive timeout, and
the timeout expired before any data became available.
From: sielim
Yes, that it is. See man pages about poll and select functions.
And how to use nonblocking sockets in this faq.
Add a Comment
New Questions: sending floats over winsock
From: vikram
Hi,
I have been trying to pass a float buffer through a windows stream socket.
the send() method only accepts char* ! conversion of float into char is one method i thought of.
But this kills the resolution of the data.
Could anyone please help??
Thanks in advance
Vik
From: Shawn Elliott
I'd try to write a conversion function on both ends to convert with more detail. I've had to do
this on some UNIX systems where some functions were missing.
From: Phil Frisbie
You don't need to cast the floats to chars, you just need to
cast your float * to a char *. And when you receive, cast
the char * back to a float *.
From: Rob Seace
Note that Phil's method will only work if both the client
and server are exactly the same platform, or just happen to
share the same binary storage method for floats (not to
mention byte ordering)... In general, sending raw binary
data over sockets is a no-no... But, if you KNOW both ends
are going to be on the same platform, you can get away with
it... (I do it myself all the time, actually... But, that
doesn't make it any less of a bad idea, in general... ;-))
Add a Comment
New Questions: A server on multiple machines
behind a Net Address Translation Device
From: Richard Foletta
The question is how do I get the nat to map one of its ports to A's 55565. I think maybe the first
thing my server should do is bind to its port 55565 and make the connection to C allowing the
nat to map the port. Then close the connection and then listen on its port 55565. But wont the
nat drop the mapping when the connection to C is closed. I need the map to be set up and stay
set up as long as the nat is connected to its ISP.
Another thought was for a serparte program using a different port to make a connection to C
and send some data containing A's IP and port 55565 through the socket in some protocol that
the nat will recognize and do the mapping. When C reads the data the port in the data will have
been changed by the nat to that of its port that it had mapped to A's 55565.
Add a Comment
New Questions: qustion about socket
From: DHAVAL
hello sir
i have a question that can i change the address of a socket
why and how?
From: Warren Nash
Or are you talking about IP address - see previous for possible answer.
From: Raja
Actually theres a server which was executing some flow.Now i want that server to accept
requests from other server and based on the message it has to perform the actions apart from the
normal flow.So i was trying to create new thread apart from normal flow of execution and that
thread keeps listening at one portnumber and IPaddress so that whenever a request saying
"STATUS" comes it sends back "UP" and if the message is "SHUTDOWN" it shud close the
thread and also the normal flow.So i was using the sockets concept where it accepts messages
and sends back the respective message.Thats it of my execution.So pls give me some
suggestions on that.I'm able to send message from the other server but this server is not able to
catch though its listening one the same port to which the other server is establishing a cnnection
for sending message.pls respond me quickly.
From: raju
Are you doing a connect from the second server to the first server?
You do the same things that you do from a client socket, connect, send in your
second server.
Add a Comment
New Questions: how to determine if socket is
blocking or non-blocking
From: TR
Hi,
TIA,
TR.
From: Rob Seace
As to how to set the option, be sure you do a GET_FL, or in O_NONBLOCK, and then do the
SET_FL. IIRC, there is a code snippet for doing this in the categorized section of the FAQ.
From: kapil
Hi !
I think read is a blocking system call but write is not a blocking system call.
Add a Comment
New Questions: read() and timeouts
From: Chris Parr
Hello,
I'm communicating over sockets and need some way to timeout the read() call after x seconds.
Thanks in advance
Chris Parr
From: Rob Seace
tv.tv_sec = sec;
tv.tv_usec = usec;
FD_ZERO(&rset);
FD_SET(fd, &rset);
http://cvs.sourceforge.net/cgi-bin/cvsweb.cgi/DroneUtil/src/ReadableTimeOut.c?rev=1.9&content-type=text/x-cvsweb-markup&cvsroot=droneutil
Add a Comment
New Questions: XDR
From: Warren Nash
you only need to use XDR when the machines in your site
are different in architecture (intell , matorolla ,...)
Add a Comment
New Questions: Proxy with Sockets - grabbing
the http portion
From: Warren Nash
How can I grab the GET or HEAD part of a URL web page, including
the pictures URL's. This is used to limit / stop access to certain
web pages. I am building an additional proxy to the ones
already available in linux.
Add a Comment
New Questions: How do i send file(s) to server
From: ezzete
I use send/recv to send and receive data from/to client/server but i don't
know how to send file(s) using send command since the format for send command is
int send (int sockfd, char * buff,int bytes,int flags).
Anyone please help!!
From: Hanan
You can read the data from the file , to a buffer , and then send the data using sockets functions.
From: issam qasas
How do you send a file to a server with an associated file name associated with the buffer. How
do you store the file once transfered in the current working directory?
From: Rajiv
You can send the filename firstly, and then send the file contents.
Add a Comment
New Questions: NT sockets VS Unix sockets
From: sheenu Chopra
Eg : WSASocket,WSACleanup,WSAStartup,WSAGetLastError
From:
unix sockets(BSD style) i believe, are actually much more easy to use than windows sockets.
There is no WSAStartup or WSACleanup. For unix doesn't use dlls. You just need to create
your socket with a socket() call and manipulate it from there. To control your i/o polling you
need to use either select() or poll(). Select is easier to use but i like poll better.
WSAAsyncSelect() is no more. Also in a unix enviroment there is a command called 'man', it is
your friend. type 'man socket' and poof it will bring up the socket section of the manual. 'man 2
socket' means find the sockets manual section 2. Often written as socket(2).
From: Johnathan Ingram
Hi
Use errno if a socket functions returns -1 in order to determine the error that occured. As stated
above.. man is your best friend and will give you the error codes.
You can also use strerror(errno) to convert the error to a string readable error.
L8r
From: Johnathan Ingram
Hi
Use errno if a socket functions returns -1 in order to determine the error that occured. As stated
above.. man is your best friend and will give you the error codes.
You can also use strerror(errno) to convert the error to a string readable error.
L8r
From: dzhan
Add a Comment
New Questions: Blocking/Non-Blocking
From: Marc Soda
Add a Comment
New Questions: sockets
From: mary
What happens when you kill a socket, what are the methods.
From: mathur
one doesnt 'kill' a socket, one 'closes' it by the close() system call.
for a TCP socket it does not lead to an immediate 'disconnection' but the
kernel keeps sending the data in the send buffer.this is followed by sending a
'close connection' request to the peer.then we wait for an ACK and then send a return ACK
_then_ the logical connection is considered closed. now the socket descriptor can be discarded.
Add a Comment
New Questions: Why does select not see
available buffer space on a loopback socket?
From: Alastair Rae
From: Kieran
You could try sleep()ing in the reader and writer tasks for
a short while after you send each message. There is
a possibility that the socket is ready for more writes but
the select has not yet been "woken".
Add a Comment
New Questions: socket bufsize recv and send
> 4k
From: jagadeesh
How can receive more than 4k bytes of data in a recv system call?
I need to receive at least 8k of bytes of data at a time. I'm using the sockoption (SNDBUF)
system call to set the buffer size in server side and also RECVBUF option is set the buffer size
in client side. I'm haven't get any errors but the data is receiving only 4k. Can you anybody
helps to get at least 8 k bytes of data.
Thanks
Jagadeesh
From: URAL YALCIN
use this
recv( newsockfd,buff, size,MSG_WAITALL);
Hi,
I've got solution,I'm just looping till to buffered all the data.
Thank you for your solution. I'll try this also.
-jsh
From:
hi,
we have the same situation. can u show me the solution for this.
Add a Comment
New Questions: Blocking writes fail
From: Mike Tarnowski
I am working with an API interface that does raw BSD socket routines.
Occasionally, we get a blocking write failure. What can cause the writes
to fail, and how should they be handled to stop API failure?
From: Alastair Rae
Assuming the connection is intact, the only thing that can cause a block write to fail a blocking
write is a signal (EINTR) and no data will have been transferred. You should retry the write.
Add a Comment
New Questions: When gethostbyname()
doesn´t work...
From: Flávio
I´m programing to the BeOS and I´m having a problem to get the IP of an adress.
The host->h_addr_list[] have a hundred numbers of IP and I just have to know
wich one is the right Ip when I debug the program. In a case, the right IP was the
host->h_addr_list[82] in another the host->h_addr_list[86].
Everybody write to use the host->h_addr_list[0] but it is not working.
I´m using the BeOS in the University and I am behind a Firewall.
Is there a logic?
Is the problem with the Firewall?
How can I do?
Thanks.
Add a Comment
New Questions: viewing active data over
socket
From: Nash
I'm trying to build a simple web server and was wondering what functions I would
be using to actively look at the data being sent over my socket.
Basically how to interpret the HTTP headers so I know when to stop reading
(ie when I receive a CRLF on its own). I'm coding in C
I wrote a simple HTTP server that compiled to 13K. If you email me I can get it to you.
Otherwise, go to www.acme.com and look at the HTTP server examples there.
Add a Comment
New Questions: why is my client not able to
connect to the server after the first time
From: latha
i have written a server and a client prog in c for unix socket communication.
when i run it for the first time everything works well.for the second time
the client program gives a 'connect' error(cannot connect).
please suggest me a solution or an alternative
thank you in advance
latha
From: skuzzlebutt
It's possible you are closing the socket on the server when
your first run of the client disconnects. It may be that you are
not disconnecting properly hence your second run won't be able
to connect as the server socket will still be in use.
From: Crich
Hello ,
maybe you forgot to set the reuseaddress option in the setsockopt() - call .. i had a problem like
this too ..
From: Michael H. Ward
optval = 1;
status = setsockopt(listenSocket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
Add a Comment
New Questions: Adding delay between IP
package
From: Loui
Hi all
I have therefore made two client-server program to send data from client to the server. One of
them using TCP socket and the other using UDP socket (In Unix platform ).
I want to ask
-How could I add some delay in between each IP package going to the server ?
select(0,NULL,NULL,NULL,&tv);
Add a Comment
New Questions: psuedo terminals
From: Barel Gil
Thank you.
Add a Comment
New Questions: transmit files via socket
From: ezzete
so far i had succesfully transmit integer and character throug socket using
send and recv command. Can anyone tell me how to transmit files using
send and recv command or is there any way else to do this?
From: David McReynolds
You'll have to define what type of file you wish to transmitt (ascii or binary). Are you planning
on using your transmission technique in a heterogenous computing environment? Or, will the
sender and the receiver be the same type of platform? Why not just use FTP?
From: tybins
I need to exchange binary files between clients and servers, I Would like to know if it would be
possible to invoke and use the ftp program from my server and client code, and just let ftp
handle this work without having to reinvent the wheel.
From: Alisha
I would also like to know how to transfer entire files from my server to my client and also once
I transfer files to my client how I would store the entire file with the associated file name in my
current working directory.
Alisha
Add a Comment
New Questions: Error bind
From: ezzete
From: S.M.Krish
Hai ezeete
Why are you finding sizeof() and all. you simply pass
any integer address only.
just as below
int sz;
struct sockaddr_in addr;
newfd = accept(sockfd,(struct sockaddr *)&addr,&sz);
In my Linux Machine its coming with out any error.
On return The structure will be filled with the client
address.
Thanks and bye.
From: Rob Seace
Add a Comment
New Questions: How can I check the evolution
of a non blocking write on a socket?
From: Irina
Thanks.
From: Kieran
if in client you call closesocket on blocking socket right after calling send it is not guaranteed
that the recv call on the other peer succeeds.
Add a Comment
New Questions: discard socket data
From: Beli
________________________________
30 10.55496 193.152.37.57 -> SSMRRO5 ETHER Type=0800 (IP), size = 61 bytes
30 10.55496 193.152.37.57 -> SSMRRO5 IP D=195.235.104.13 S=193.152.37.57
LEN=47, ID=19716
30 10.55496 193.152.37.57 -> SSMRRO5 TCP D=7047 S=15357
Ack=1583335949 Seq=2845681306 Len=7 Win=4380
ASCEND MANDA 1 1 1 1 1 1 1
________________________________
31 10.58554 193.152.37.57 -> SSMRRO5 ETHER Type=0800 (IP), size = 61
bytes
31 10.58554 193.152.37.57 -> SSMRRO5 IP D=195.235.104.13 S=193.152.37.57
LEN=47, ID=19972
31 10.58554 193.152.37.57 -> SSMRRO5 TCP D=7047 S=15357
Ack=1583335949 Seq=2845681313 Len=7 Win=4380
ASCEND MANDA 1 1 1 1 1 1 1
________________________________
32 10.58557 SSMRRO5 -> 193.152.37.57 ETHER Type=0800 (IP), size = 54
bytes
32 10.58557 SSMRRO5 -> 193.152.37.57 IP D=193.152.37.57 S=195.235.104.13
LEN=40, ID=22549
32 10.58557 SSMRRO5 -> 193.152.37.57 TCP D=15357 S=7047
Ack=2845681320 Seq=1583335949 Len=0 Win=9112
________________________________
33 10.61476 193.152.37.57 -> SSMRRO5 ETHER Type=0800 (IP), size = 61
bytes
33 10.61476 193.152.37.57 -> SSMRRO5 IP D=195.235.104.13 S=193.152.37.57
LEN=47, ID=20228
33 10.61476 193.152.37.57 -> SSMRRO5 TCP D=7047 S=15357
Ack=1583335949 Seq=2845681320 Len=7 Win=4380
ASCEND MANDA 1 1 1 1 1 1 CR
From: Beli
Add a Comment
New Questions: discard socket data
From: Beli
________________________________
30 10.55496 193.152.37.57 -> SSMRRO5 ETHER Type=0800 (IP), size = 61 bytes
30 10.55496 193.152.37.57 -> SSMRRO5 IP D=195.235.104.13 S=193.152.37.57
LEN=47, ID=19716
30 10.55496 193.152.37.57 -> SSMRRO5 TCP D=7047 S=15357
Ack=1583335949 Seq=2845681306 Len=7 Win=4380
_______________________________
31 10.58554 193.152.37.57 -> SSMRRO5 ETHER Type=0800 (IP), size = 61
bytes
31 10.58554 193.152.37.57 -> SSMRRO5 IP D=195.235.104.13 S=193.152.37.57
LEN=47, ID=19972
31 10.58554 193.152.37.57 -> SSMRRO5 TCP D=7047 S=15357
Ack=1583335949 Seq=2845681313 Len=7 Win=4380
________________________________
32 10.58557 SSMRRO5 -> 193.152.37.57 ETHER Type=0800 (IP), size = 54
bytes
32 10.58557 SSMRRO5 -> 193.152.37.57 IP D=193.152.37.57 S=195.235.104.13
LEN=40, ID=22549
32 10.58557 SSMRRO5 -> 193.152.37.57 TCP D=15357 S=7047
Ack=2845681320 Seq=1583335949 Len=0 Win=9112
________________________________
33 10.61476 193.152.37.57 -> SSMRRO5 ETHER Type=0800 (IP), size = 61
bytes
33 10.61476 193.152.37.57 -> SSMRRO5 IP D=195.235.104.13 S=193.152.37.57
LEN=47, ID=20228
33 10.61476 193.152.37.57 -> SSMRRO5 TCP D=7047 S=15357
Ack=1583335949 Seq=2845681320 Len=7 Win=4380
When I read this characters I can't read it all with one recv, I have to do it three times, firs time I
read
Second time:
Add a Comment
New Questions: Starting server when
disconnected from ethernet fails to run
From: Andy
I have written a WINSOCK based server that runs infallably except under one set of
circumstances:
1) The server is running
2) The ethernet cable is pulled
3) The server is shut down and re-started
4) The cable is plugged in.
While disconnected, the server gets up and running and establishes a socket in the listening state
(with a blocking select call). After plugging the cable back in, when I try to connect to it, I get
WSAError 10061 (connection forcefully rejected). Running the server under any other
circumstances, a connect causes select to return so that a connection can be accepted (expected
behavior).
Andy
From:
Sorry, actually the WINSOCK error 10061 is ConnRefused, not ConnForcefullyRejected. But
the problem persists.
Add a Comment
New Questions: packets lost using
SOCK_STREAM
From: David
what should I do to get all the packets? here is the client: #include #include #include #include
#include #include #include main(int argc, char *argv[]) { int rc, s, i; struct hostent *hen; struct
sockaddr_in sa; char str[1024]; hen=gethostbyname("ai-way.local"); if (NULL==hen) {
perror("hostname error\n"); return 0; } memset(&sa, 0, sizeof(sa)); sa.sin_port=htons(1200);
sa.sin_family=AF_INET; memcpy(&sa.sin_addr.s_addr, hen->h_addr_list[0], hen->h_length);
s=socket(AF_INET, SOCK_STREAM, 0); if (-1==s) { perror("socket open error\n"); return 0;
} rc=connect(s, &sa, sizeof(sa)); if (-1==rc) { perror("connect error\n"); return 0; } for (i=1;
argc>i; i++) { sprintf(str, "%d\t%s\n", i, argv[i]); rc=write(s, str, strlen(str)+1);
printf("%d\t>>\t", rc); printf("%s", str); } close(s); return 0; } and here is the server: #include
#include #include #include #include #include main() { int rc, s, csa_size, cs; struct sockaddr_in
sa, csa; char str[1024]; memset(&sa, 0, sizeof(sa)); sa.sin_port=htons(1200);
sa.sin_family=AF_INET; /* sa.sin_addr.s_addr=inet_addr("127.0.0.1"); */
sa.sin_addr.s_addr=INADDR_ANY; s=socket(AF_INET, SOCK_STREAM, 0); if (-1==s) {
perror("socket error\n"); return 1; } rc=bind(s, &sa, sizeof(sa)); if (-1==rc) { perror("bind
error\n"); return 1; } csa_size=sizeof(csa); rc=listen(s, 5); if (-1==rc) { perror("listen error\n");
return 1; } while (1) { cs=accept(s, &csa, &csa_size); if (cs<0) continue; while (0<(rc=read(cs,
str, 1024))) { printf("%s", str); } printf("%d\n", rc); close(cs); } return 0; }
Add a Comment
New Questions: packets lost using
SOCK_STREAM
From: David
what should I do to get all the packets? here is the client: #include #include #include #include
#include #include #include main(int argc, char *argv[]) { int rc, s, i; struct hostent *hen; struct
sockaddr_in sa; char str[1024]; hen=gethostbyname("ai-way.local"); if (NULL==hen) {
perror("hostname error\n"); return 0; } memset(&sa, 0, sizeof(sa)); sa.sin_port=htons(1200);
sa.sin_family=AF_INET; memcpy(&sa.sin_addr.s_addr, hen->h_addr_list[0], hen->h_length);
s=socket(AF_INET, SOCK_STREAM, 0); if (-1==s) { perror("socket open error\n"); return 0;
} rc=connect(s, &sa, sizeof(sa)); if (-1==rc) { perror("connect error\n"); return 0; } for (i=1;
argc>i; i++) { sprintf(str, "%d\t%s\n", i, argv[i]); rc=write(s, str, strlen(str)+1);
printf("%d\t>>\t", rc); printf("%s", str); } close(s); return 0; } and here is the server: #include
#include #include #include #include #include main() { int rc, s, csa_size, cs; struct sockaddr_in
sa, csa; char str[1024]; memset(&sa, 0, sizeof(sa)); sa.sin_port=htons(1200);
sa.sin_family=AF_INET; /* sa.sin_addr.s_addr=inet_addr("127.0.0.1"); */
sa.sin_addr.s_addr=INADDR_ANY; s=socket(AF_INET, SOCK_STREAM, 0); if (-1==s) {
perror("socket error\n"); return 1; } rc=bind(s, &sa, sizeof(sa)); if (-1==rc) { perror("bind
error\n"); return 1; } csa_size=sizeof(csa); rc=listen(s, 5); if (-1==rc) { perror("listen error\n");
return 1; } while (1) { cs=accept(s, &csa, &csa_size); if (cs<0) continue; while (0<(rc=read(cs,
str, 1024))) { printf("%s", str); } printf("%d\n", rc); close(cs); } return 0; }
Add a Comment
New Questions: using select to check if the
second end is alive
From: Helena
Sorry, forgot to fill the subject before... I'm trying to check the avaliability of the second end
socket with the select(), but even when the second end socket disconnected, the select()
indicates as ready to read/write... How can I check that the second end (whatever client or
server) was disconnected?
I must say that I read almost all the FAQs here, they are realy helpfull, but anyhow I'm not
succeeding in this simple task.
From: Rob Seace
See Question 1, Section 2 and Question 13, Section 2... Basically, you really need to try to
read(), and get the 0 return in order to know for sure... (Unless you happen to know that no data
should be getting sent by the remote end at this time, in which case you can just select() for
readability, and if it becomes readable, then you know it must be the EOF/FIN waiting to be
read...)
From: Rajiv
Add a Comment
New Questions: package loss and delay
From: Sam
Hi all
I was wandering when we get package loss and delay in a network ? what is the reason for that
? are there any information abut these topic available in the net ?
hi,if you are working on a very crowded network.with a lot of communication works to do.then
you may get collision error.and lose your package sometime.
Add a Comment
New Questions: Sockets with Unix
From: Sylvain Nadeau
I want to write an application (in Visual Basic if possible) that will interface with a Unix
system.
I want to send and receive files, execute scripts on the unix server, get the contents of the stdout
of the script and display it on the client station.
I want to do all this with a minimun of opened connection between the client and the server.
I don't want to open a connection and close it with each file transfer or script execution because
there will by many developpers that will use my application.
I have tried to use wsock32.dll and mswinsck.ocx but I don't know how to use them properly.
Do you have code samples that could help me build my application (Visual Basic if possible,
else C/C++ will do) ?
Thanks
From: gates Bill
Add a Comment
New Questions: Number of Ports? Newbie
question
From: Agent
hi,
Is there an upper limit to the number of ports available?
regards
From: Rob Seace
Add a Comment
New Questions: binding multiple file
descriptors to a single port
From: Brent
Are there any issues I should be concerned about in binding two file descriptors to the same
port?
Add a Comment
New Questions: recv() on unconnected socket
?
From: AK
Hi,
What does recv() return when used for a socket that is not connected? Does it return 0 or <0.
If <0, then what is the errno that it sets ?
TIA.
Add a Comment
New Questions: Sockets, timeout, signals
From: Gejzir
Hi all!
I've written a complex data distribution system using Linux servers and both Win32 and unix
clients, and Stream sockets.
When a client connection goes into broken state, I can see, that the timer for the socket is on,
and counting.
(netstat -to)
After a counter reaches a value (where can I set the limit?), my application receives a signal,
and terminates.
BUT. This is working fine on a 4-5 Linux machine I've tested, but is NOT working on the final
machines of the customer. The counter starts, I can see it in netstat, but it counts forever, my
application just doesn't get a signal.
I've checked that the kernel versions are the same, the .so libraries are the same. I've checked it
with many kernel versions. On the most machines this is working well, but on the others it
doesn't.
Questions:
1. How can I set the value of the timeout period when a connection brakes.
2. What could be the difference beetween the two configuration?
Regards: Gejzir
From: Shawn Elliott
I had a similar problem. What I did was write a cleanup function that ran through all of the
Socket Descriptors and sends a * through. If the write gives me an error then the socket is
closed and I proceed to kill the Threaded process.
Add a Comment
New Questions: Port in use question?
From: Paul Chafin
If we stop the server program and restart it we get the message "Can't bind
socket port already in use".
Look up SO_LINGER. Depending on your application, you may be able to set it to false.
From: Muslim Moiz Ghadiali
kill the client first then kill the server...disable server if port in use by first saying 'ps' in unix
and 'kill ##' commands.
From: Sudhakar
in case that port no is already taken up by other process, how to determine which is using port.
Is there any unix command to identify the process
From: nitin
Use lsof command .it will give u the process which is using the specifed port.
From: Suresh
Hai Paul,
U can see the solution in the question number 11
"how to restart a server immediately"
That worked out for me.
Try.
Suresh
Add a Comment
New Questions: Accept call on unconnected
socket
From: Beth Rourke
server = socket()
listen(server, 1);
From: Kieran
<continuation>
FD_SET(server, &readfds);
timeval.secs = timeval.usecs = 0; // check struct member names!
select(1, &readfds, NULL, NULL, timeval);
I suspect what you were missing was the bind() and/or the
listen() call; some accept() calls do a bind() and
listen() implicitly.
From: Kieran
fd_set readfds;
struct timeval timer;
server = socket(...);
timer.secs = timer.usecs = 0;
FD_ZERO(&readfds);
FD_SET(server, &readfds);
should the first argument to select be the value of the server sockfd+1 in you example?
Add a Comment
New Questions: Send & Receive using the
same port
From: Michele Piccini
I use the same port and the same socket to send & receive, i wait for input with a bocking
select(socket,fdread,NULL,NULL,timeout) but whenever i write to the socket the select wait
for input returns.
How can read and write to the same port without having my select() returned whenever i write?
From: Eric J Krejci
Add a Comment
New Questions: Ports in use
From: Valentin Chartier
Try "netstat -a" to show you the ports in use (add "-n" for
raw numeric ports, rather than service names)... Or,
alternatively, you could use a port scanner like "nmap"...
(Which can show you the ports in use not just on the local
host, but on remote hosts as well...) As for what processes
are bound to those ports, how to get at that info depends
greatly on your OS... I can tell you how to do so on Linux
or QNX; other than that, I can't help you... On Linux,
"netstat" has a "-p" switch to list the programs using each
listed port... (Or, alternatively, you can use something
like "lsof", or manually dig through "/proc" and find the
data yourself... Actually, the "lsof" idea will probably
be useful on many other Unix-alikes, as well; I believe
that's widely ported...) On QNX, a "sin fd" should give
you the info...
Add a Comment
New Questions: Newbie-Question:How to start
with a proxy server?
From: Joerg
Hello everybody!
I am quite new to socket programming but not new to (V)C++ and I am trying to program an
app, which (should)check, which URL a user typed in into any webbrowser on the system. I
want to do this, because, I want to block certain websites and make them not viewable for the
user. I soon figured out, I need to program a proxy server but I have no idea how to do that. Is
there something on the web, you can recommedn as a turorial for proxy programming or just
give me an idea how to set a proxy up (not detailed of course :) ).
I'd use a FindTest API on the Window of the browser. Find what site they are on that way. Alot
easier
From: Ram
hi,
i would like ask the question as that of joerg.if anyone has tips.please respond
From: Mukhben Singh
Download squid caching proxy server from http://squid.nlanr.net/ and follow the instructions. It
is the best and most popular proxy server around. You will have to configure it on a machine
which has direct net access and block other machines from using the net directly at ur firewall.
I hope it helps
Add a Comment
New Questions: Why my ping fails?
From: sandman
that's not realy a socket question, but maybe somebody knows the answer. i wrote a ping prog
(icmp socket). in the id field of the icmp header i write some id (let's say 14). when the answer
arrives the id field is zero, but it should be 14. i just don't know, whats wrong!
sandman
Add a Comment
New Questions: Final result of setting Timeout
for connect() in socket
From: Ramzan Ul Haq
Then what would be the final thing to set the timeout for connect() call in socket programming?
Please do answer clearly, with code preferably.
Thanks
From: Mukhben Singh
u can use SIGALRM signal. set an alarm with alarm function. set the signal handler before the
call to conenct. and after the call unset the alarm and install the previous signal handler. for
details consult UNIX NETWORK PROGRAMMING
by richard stevens.
--mukhben
From: frankv
If you have multiple connects going at the same time (multi-threaded) you can't use sigalarm.
See the man page for details.
Try using a non-blocking connect instead and use select to find out when it is
ready(/connected).
fv.
Add a Comment
New Questions: how many clients??
From: rikin
How can i determine how many clients are conencted to my server. I've tried everthing, using
pointers, trying to get an array, , but nothing seems to work. if anyone knows, please email me
back. thanks
Rikin
From: Michael H. Ward
Add a Comment
New Questions: raw socket with udp port scan
From: Danny
Add a Comment
New Questions: raw socket
From: Danny shaul
Add a Comment
New Questions: raw socket
From: Danny shaul
Add a Comment
New Questions: How do i program different
socket types??..Example: type 8 type 3, etc..
From: hermes haley
Add a Comment
New Questions: How do i program different
socket types??..Example: type 8 type 3, etc..
From: hermes haley
i would like to program raw socket types.. i'm not sure how..i would also appreciate if you
explained to me how
a firewall constantly has access to your tcp stack and can interfere with it, as in block your
packet i/o, thnx - hermes haley
Add a Comment
New Questions: TIME_WAIT
From: Michael Hecht
Hallo,
I want to connect with a client to a server every about 5
seconds, send data and disconnect. If I do so, the connection
impossible after about 195 connections on my SGI O2 and after
about 100 connections on a Siemens RM600. If I call netstat
there are all 195 (100) socket connections in the
CLOSE_WAIT status (from client and in FIN_WAIT_2 status
from server [both are running on the same computer at the moment]).
I know that this problem is related to the TIME_WAIT behaviour
of TCP/IP, but what is to do to avoid my problem?
Thanks in advance
Michael
From: Rob Seace
No, actually, the problem you describe is NOT related to
the TIME_WAIT state issue, I don't think... I think what
your problem is, is that the end sitting in the CLOSE_WAIT
state never actually issues a close() call of its own, so
the socket remains in this undead state, never fully
shutting down... The states you describe (FIN_WAIT_2 on
one end, and CLOSE_WAIT on the other) would seem to indicate
a situation in which only ONE end (the FIN_WAIT_2 end) has
close()'d their socket... Once the other end (the
CLOSE_WAIT end) close()'s the socket, the FIN_WAIT_2 should
change to TIME_WAIT for a period (which is normal, and
desirable), while the CLOSE_WAIT should just go to CLOSED,
and disapear...
From: Michael Hecht
Hello Rob,
Michael
From: Helios de Creisquer
Hi !
I've got the same problem for basic client/Server talk
of about 1 sec, with a TIME_WAIT persistent during 1 minute
After reading the previous comments, I added a
shutdown(sock, SHUT_RDWR) before the close(sock)
to both server&client (one's never know ;o).
But the TIME_WAIT status is always here for about 1 minute
and neither 'listen' or 'connect' are possible on this port
Thanks in advance.
From: Rob Seace
No, TIME_WAIT is NOT a problem; it's normal, desirable behavior... Don't try to get around it;
it's there for a good reason... See question 2.7 in the main FAQ...
Add a Comment
New Questions: printf() and select()?
From: Andy
Using W Richard Stevens tcpservselect01.c, I'm trying to change it to write anything received to
ALL sockets.
I thought that changing the Writen() call to something like:
for (j =0; j < maxi; j++ {
if (client[j] < 0)
continue;
Writen(client[j], line, n);
}
Any Ideas?
From: Andy
Please ignore above, printf does work, it's just that for some reason, the client is not connecting
to the server. Why I do not know - it appears to, and echoes back to itself but it doesn't.
Add a Comment
New Questions: Should socket be closed if
sendto() or recvfrom() fails ?
From: AK
Hi,
the subject line basically says it all. I wish to know whether it is necessary to close down the
socket if a sendto()or recvfrom() call
for a UDP socket fails ? In case of a TCP socket, a failure could mean that the socket is no
longer connected, so it should be closed down
in that case. But since in case of UDP there is no concept of "connections", i feel read/write
failures should not mean socket must be closed
down. Am i right in thinking this ?
Thanks in advance,
AK.
From: Frank Binder
Hi,
you only have to close an UDP-Socket if you called a bind() on it, so that you can use the recv()
and send() calls. Else the port won't be available anymore, unless your application is exiting. If
you don't use bind(), you don't need to close the socket to free the port, but to free the socket
descriptor, I would suppose. Does anybody disagree?
Greetings
Frank
From:
Hi,
The UDP socket still needs to be closed as it is a file descriptor that has been allocated. Calling
or not calling bind() should have nothing to do with this.
Add a Comment
New Questions: TIMEOUT USING SELECT
From: Mikael Chambon
Add a Comment
New Questions: CLosing connexion
From: Mikael Chambon
Add a Comment
New Questions: problems in UDP socket
programming(recvfrom)
From: Azza
Note:
this is sample of my code:
client.c
--------
{
struct sockaddr_in broadcast_addr;
struct sockaddr_in local_addr;
int RREQ_Sock;
int sent,bound;
RREQ *RouteReq;
int optval;
int optlen;
if((RREQ_Sock=socket(AF_INET,SOCK_DGRAM,0))==-1)
{ //for test
printf("can't create socket\n"); //for test
return -1;
} //for test
broadcast_addr.sin_family=AF_INET;
broadcast_addr.sin_port=BROADCAST_PORT;
optlen=sizeof(int); //for test
optval=1; //for test
setsockopt(RREQ_Sock,SOL_SOCKET,SO_BROADCAST,(char *)&optval,optlen);
broadcast_addr.sin_addr.s_addr=inet_addr("255.255.255.255");
*************************************************
I saw that
client sent data correctly to server
but server sent to client an ICMP packet that:
- Destination unreachable
- Port unreachable
and server was blocked forever
what is a problem?
Add a Comment
New Questions: Problems in recieving UDP
packets
From: Azza
or
From: devnull
Add a Comment
New Questions: UDP socket. receiving
broadcast problem.
From: devnull
Add a Comment
New Questions: FTP protocol
From: kaler
Please help me to find the detail of FTP protocol and some samples for client. thank you
From: Rob Seace
FTP is detailed in RFC 959 (which you can find many places, including here)... As for sample
implementations, there should be several to choose from: the ones distributed with Linux distros
should have source available, as should those that come with *BSD...
Add a Comment
New Questions: multiple applications on same
host using same socket
From: John Peterman
Hi!
I hope this hasn't been covered somewhere, and I just overlooked it....
Here's the situation I'm looking at. Host A will be sending messages through a socket to Host B.
Application(s) on Host B will need to acknowledge messages from Host A, and also to send
messages through the socket to Host A. Basically, what I'm trying to figure out is this: Can two
separate applications running on Host B use the same socket for communicating with Host A.
Or can only one application on Host B use that socket? If two applications can use the socket,
then I can have one program acknowledge incoming messages, and another program send
messages to host A.
John, as long as Host A is acting as a server and binds to a particular port (see socket, bind,
listen functions), it can then listen for and accept any number of connections on that port from
other client hosts (see gethostbyname, socket, setsockopt and connect functions). I suggest
getting a copy of Unix Network Programming Volume 1 by W. Richard Stevens, it reveals all.
The Tools++ Professional class library from RogueWave (if you are using C++) greatly
simplifies the task. If you are using C, there is quite a bit of work.
Add a Comment
New Questions: Connecting to a Web server
From: Iztok Polanic
Hi!
How can I connect to a Web server and then get it's context (of the page)?
From: devnull
hello !
you should create SOCK_STREAM socket,
connect it to ip address / port of a web server,
and then send() him a HTTP request:
char *msg= "GET http://server/you/want HTTP/1.0";
send(s, (void*)msg, strlen(msg), 0);
you cat put various HTTP headers in a message:
char *msg= "GET http://<url> HTTP/1.1\0xd\x0a"\
"User-Agent: some agent\0x0d\x0a";
and so so
after that get a reply !
that's all.
From: Sudipto Basu
You can look after my code listed below it is doing the same thing.
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h> /* for struct hostent */
#include <strings.h> /* for bcopy() */
#include <unistd.h> /* for read() */
#include <stdlib.h> /* for exit() */
#define SERVER_PORT 80
#define MAXHOSTNAMELEN 256
/* #define SERV_HOST_ADDR "203.163.50.62" */
/* #define SERV_HOST_ADDR "128.163.2.27" */
#define SERV_HOST_ADDR "www.uky.edu"
/* global variable */
struct hostent *servInfo;
for(n=1;n<maxlen;n++)
{
if ( (rc = read (fd,&c,1)) == 1 )
{
*ptr++=c;
if ( c =='\n') break;
} else if ( rc ==0 ) {
if ( n==1) return(0);
else break;
} else return(-1);
}
*ptr = 0;
return(n);
}
nleft = nbytes;
while (nleft > 0) /* keep writing until the entire request is sent */
{
nwritten = write (fd, ptr, nleft);
if ( nwritten <= 0 ) return(nwritten);
nleft -= nwritten;
ptr += nwritten;
}
return(nbytes - nleft);
}
void str_cli(fp,sockfd)
FILE *fp;
int sockfd;
{
int n;
char sendline[80], recvline[81];
if ( sd < 0 )
{
printf("cannot open the socket");
exit(1);
}
From: jagan
parse error
parse error
Give me your address and I'll drive over to your house and
hold your hand while you do it...
Add a Comment
New Questions: Reading &Writing from UDP
Port. (Help needed for Win)
From: Mathew T
Hi,
I want to write a procedure in Perl for writing & reading data from UDP port(Windows). I
would like to check the port for messages & if messages are there i want them & if not i would
like to wait a specified time & then check again.....
But i am not sure how?......... I am new to perl & if anyone could suggest some tutorial for
perl-socket programming or some source codes.... that would be really helpful.
Add a Comment
New Questions: Server: accepting and
handling multiple clients
From: G.Gabriele
FD_ZERO (&active_fd_set);
FD_SET (server_socket, &active_fd_set);
while (1)
{
read_fd_set = active_fd_set;
select (FD_SETSIZE, &read_fd_set, NULL, NULL, NULL);
for (si = 0; si < max_users_number; ++si)
if (FD_ISSET (si, &read_fd_set))
{
if (si == server_socket)
{
printf("got connection.\n");
client_socket[client_n] = gpe_server_socket_accept(server_socket);
FD_SET (client_socket[client_n], &active_fd_set);
client_sockets_status[client_n] = 1;
++client_n;
}
else
{
char buffer[200];
int size;
else {
int i;
for (i = 0; i < max_users_number; ++i)
{
if (client_sockets_status[i] == 1)
{
gpe_socket_write(client_socket[i], buffer);
}
}
}
}
}
}
}
Add a Comment
New Questions: bind fails with udp socket
From: Marc Summers
Any idea at all why I get this error, and what I can do
to fix it?
Also do I need to put any entry in the /etc/services file?
I am programming in C on a Unix system HP-UX 10.20
Thanks
From: Rob Seace
Add a Comment
New Questions: sending structures through
TCPIP sockets
From: Sebastian
i have a server prog and a client prog, both running on the same machine. I try to send
structures with send(sockfd, &strct, sizeof(struct STRUC), 0). The client should receive data
but it only receive the first sent structure correctly, the next ones get messed up.
The client uses recv(sockfd, &st, sizeof(struct STRUC), 0).
I would be grateful if someone would help.
From: Jianxin Ge
Add a Comment
New Questions: I need help, i am a beginner
From: Angel Valencia
How do i use the function connect(), i need to know what is the socket descriptor and what type
of variable is it.
From: Sebastian
go to
http://www.ecst.csuchico.edu/~beej/guide/net/
this is where i started learning (3days ago).
Add a Comment
New Questions: Listening to port traffic?
From: smitty
I'm trying to figure out how to intercept the incomming and outgoing traffic on a particular local
port, hopefully without interrupting the traffic. Could anyone tell me how to do this, or point me
in the direction of an article to read?
From: Rob Seace
It sounds like you want to get yourself a packet sniffer... You didn't say what OS you were
using, so I can't recommend one... But, assuming a Unix-like OS, tcpdump is the standard
workhorse command-line sniffer... But, my personal favorite is a GUI sniffer called Ethereal,
which is just excellent... Another popular one is sniffit... If you're on a Windoze system though,
your choices are much more limited (unless you're willing to shell out some bucks)... Someone
ported "tcpdump" to Windoze, and called it windump... Other than that, the only decent free
sniffer I've seen is an old Back Orifice plug-in, by the bizarre name of "Butt-Sniffer"... ;-)
(which I can sadly no longer find an official page for, but you can easily find a copy on several
less than trustworthy pages via search engine, if you really must have a copy... I'd say
"windump" is your best bet, though... Or, better yet, get yourself a free copy of Linux and install
that; Red Hat even ships with "tcpdump" installed, standard... ;-))
From: Jacques Richer
Add a Comment
New Questions: how do i convert binary..
From: lguo
Add a Comment
New Questions: how do i convert binary..
From: lguo
hi, i have created a server socket, and the client sent me a access file which is binary. i save it to a file,
when i open a file, it is like this
"^A~^^A~\^A~\^A~\^A~X^A~X^A~X^A~X^A~X^A~X^A~X^Ap^Al^Af^AD^A6^A$^Aö.............."
how can i convert them to charater???
thanks alot
From: soullace
Binary data just means there are bytes that are not printable, using a standard character set like ASCII.
When you open up a file(in a text editor) it assumes that the bytes in the file are printable (i.e.
characters). Using the ASCII standard, there are 'characters' which are not printable. So the text editor
trys to display some of them as ^A, ^X, ^M, and so forth, the rest it doesn't display. If you tried
opening up the file in a HexEditor, it might make more since, or it might not.
Add a Comment
New Questions: How can i receive a file which
size is unknown?
From: gary
hi, i wrote a server socket which can receive a string which size has been set up. i want to know
how i can receive a database or whatever other file which size in no known and how i can store
the whole file, and seperate each data? is it anything related to packet?
thanks
Add a Comment
New Questions: Err#9 EBADF on door_info call
From: Chris Milner
Hi,
I'm running PHP4, Apache, Oracle8i on Solaris 2.7. I have an intermitment TNS-12154 Cannot
resolve service name in the browser when trying to connect to the db server. A PHP developer
has looked into this and has fixed the bug, (some sort of double closure of the Oracle socket
was occuring in one the PHP Apache modules). BUT, the problem came back after applying the
patch.
I've truss'd the httpd processes and in one of the truss output, an error frequently appears which
concerns me. The error is...
The PHP developer reckons there's now another problem, in that something, somewhere is
closing the Oracle socket??? Is this what this error suggests. I know that TNS-12154 definately
suggests that it cannot find the tnsnames.ora file.
Have you got any suggestions for us on how to proceed...can we trace this further....maybe we
need to truss the processes from the start to see it working, then watch it fail and hopefully see
why it failed.
Add a Comment
New Questions: Problem with write
From: Ram
I am developing a multithreaded socketserver which accepts connections from client and also
connects back to clients.(inessence a server talking to another server). When I tried to write to
other server to which I connected to and if the socket is invalid my program exits whitout
giving me any message. I tried catching SIGPIPE but in vain.
Has anyone encountered this error before.
From: Matthias Blankenhaus
Add a Comment
New Questions: How can I know my peer is
dead(or close the socket) without read or
write?
From: sung-jin,kim
That is,
my server want to know whether my peer(client) is dead or close the connection without read or
write the socket-descriptor.
I've tried to this using select + ioctl(FIONREAD), because if r_set is true in select, and read
buffer count is zero,
I can recognize that client was dead.
but, sometimes the read buffer count is not zero with client death situation.
maybe, I can do this if I would know about server socket-descriptor state with CLOSE_WAIT.
bye
From: Sam Horrocks
The only way to tell when the client is dead is when the
read returns 0 bytes. If the client dies and there is still
some unread data on the socket, you will see a read with a
non-zero value, but the next read after that will return 0
bytes.
Also, if your client dies, it may not shut down the tcp
connection properly, and your server will never be informed.
You may want to use the socket option "SO_KEEPALIVE" so
that you'll be informed if the client is no longer
responding.
Add a Comment
New Questions: sigaction and sigset
From: Ram
Hi,
Can anyone tell me when to use sigaction() and when to use sigset()
From: Ninja
sigaction is the generic signal handler on Linux, ported and improved from BSD standards.
However, it does have some problems, since most signals perform default actions anyway and
the signal handler is not always cleanly unloaded from memory. sigset avoids this problem.
Think of sigset as a sigaction (or sigvec, if you are a BSD lover:D) that just doesn't mess up
anything (almost). The safest choice if you do not need to much of refinement is using the
standard ANSI library function signal, that is built on top of sigaction but works most of the
time without too much trouble.
Add a Comment
New Questions: What is EAGAIN ??
From: AK
Hi,
I would like to know what the error EAGAIN means in the case of <<blocking>> sockets?
Also, what is the cause of this error occurring - does it have anything to do with the
load on that particular server ?
Thanx in advance,
AK.
From: Chad
The only time I have seen the EAGAIN is when I write to socket that is full. In our situation the
reader was doing too much processing before getting back to the select while our sender was
sending a steady stream of data.
From: Michael H. Ward
The EAGAIN (or EWOULDBLOCK under the new POSIX standard (1g))
basically says that if you are in NONBLOCKing mode, and made
a call to accept(), there is nothing there are no clients there
waiting to connect. The accept() will return a -1, and the
errno will be set to EWOULDBLOCK. So if you are wanting to
let various client machines connect to your server and you
don't want your server to hang on the accept() function (i.e.
you may need the server routine to run off and do other tasks)
you set the O_NOBLOCK option on the socket, then set up a
loop that executes an accept() command. If the accept()
returns -1 and errno == WOULDBLOCK, then there is really no
error, just nobody to connect to so your server is free to
go about it's tasks. If accept() returns something else, then
you have a client trying to connect, so you need to process
that connection.
Add a Comment
New Questions: Question on select() and
send()
From: Chong
Hi,
I generate a 15475 bytes of data in client (n1) and
my server (n2) uses select() to read the data. But why
the select() don't receive the whole chunk of data at the
same time? You can see the output from the server as following,
and the result from tcpdump at the client(n1) side.
/*******************************
******* Client Result *********
********************************/
/*******************************
******** Server Code *********
********************************/
While(1){
waitT->tv_sec = 0;
waitT->tv_usec = 500;
n = select (maxfd + 1, &rfds, NULL, NULL, NULL);
.....
}//while
/*******************************
******* Server Result ********
********************************/
GW:receive 2896 chars
GW:receive 1448 chars
GW:receive 1448 chars
GW:receive 2896 chars
GW:receive 2896 chars
GW:receive 3891 chars
/*******************************
***** tcpdump (n1) Result ****
********************************/
We effectively use 2 reads, one is for an int which is the size of the data to follow and the next
read blocks waiting for data of that size.
Add a Comment
New Questions: Problems with setting a
timeout on connect
From: jb
Add a Comment
New Questions: setting a timeout on connect
From: jb
how would i go about doing this i've heard so many ways, 0block then use select, that didn't
work for me, then
using signals and whatnot, can someone please set me straight heh
From: poop`
ok heres what ya do...first you open the socket and then u put your millimeter peter in
it...OR...you can go buy a fufme and put your finger in one and have the other go up yer ass
From: jb's pimp
This is a unix faq board...not some lame highschool board..how about u answere his question u
faggets
Add a Comment
New Questions: read() and MSS
From: chong
I find that my client write() two packets with 722 and 1028
bytes respectively, but the server read() two buffers
with 1448 and 302 bytes respectively. I think 1448 is the
MSS in the ethernet (1500-20-20-12), but why the server
reveive the two packets at the different pattern?
Thank you,
-Chong
From: chong
Add a Comment
New Questions: unable to establish socket
connection
From: Sarah
Hi, I'm trying to connect to my unix server(I'm brand new to this) and I keep getting the error,
unable to establish socket connection. Any ideas? Thanks
From: Sarah
I fixed it thanks
From: issam qasas
thanks
Add a Comment
New Questions: exception in java
From: frank
Is it possible that socketexception in java shuts down the entire webserver. Below you can find
the exception message I received:
Add a Comment
New Questions: How could I know that the
client stopped sending the data and waiting for
me to response?
From: Dimitry
What is the reliable way to know that the client stopped sending the data and waiting for
me(server) to response?
Does the POLLOUT event on the server side means that that
the client stopped sending the data and blocked in recv()/select()/poll()?
Thank you!
From: K E V I N
Also, what kind of function can catch those events such as when data is comming?? so that I
can call recv() or send()...
how do I do to let my socket client and server can communicate "simultaneously"?? I mean
when data is comming, it will automatically calls recv(); and when I input, it calls send()....
Add a Comment
New Questions: recv returns 0!
From: Dimitry
Hi there!
oes the receiving zero form recv() means that the client closed the connection?
Does it 100% reliable?
I mean - can I receive zero, but the client does not close the connection?
TIA
From: g.jagadish
Yes, you are received 0 bytes, the Client and Server connection is alive.
-jsh
From: Rob Seace
Well you can receive a read of 0 and the error number will be set to EAGAIN..
Youhave to check for the error number before you come to conclusions.
When a socket is non-blocking, and you call recv(), it will return -1 (indicating an error) and
errno will be set to EAGAIN when there is no data ready to be read for the socket. I think
Jayant is wrong about this.
The recv() documentation doesn't say that you should expect 0 when you get the EOF, however,
read() does return 0 when EOF.
From: David Bruhn
On a blocking socket, recv() returns zero if the peer closed the connection.
On a non blocking socket, recv() returns zero if the peer closed the connection or if there is no
data to read.
FYI I include this quote from W. Richard Stevens, UNIX Network Programming, vol.1, 2nd
edition, chapter 15:
"Traditionally, System V has returned the error EAGAIN for a nonblocking I/O operation that
cannot be satisfied while Berkley-derived implementations have returned the error
EWOULDBLOCK. To confuse things even more, Posix.1 specifies that EAGAIN is used while
Posix.1g specifies that EWOULDBLOCK is used. Fortunately, most current systems (including
SVR4 and 4.4BSD) define these two error codes to be the same (check your system's
<sys/errno.h> header), so it doesn't matter which one we use."
From: Rob Seace
Rob, you are correct. I unfortunately posted behavior of a Roguewave implementation of recv()
on a nonblocking socket. Thanks for clearing this up. I'm rewriting my code to use the socket
APIs.
Add a Comment
New Questions: writing into file
From: Pratibha
Hi
My server application reads from and updates a text file. How di I synchronise the file
operations so as to enable mutliple clients to access the file simultaneously?
From: Muslim Moiz Ghadiali
put your program in a continuous while loop and keep forking new children each time a client
gets connected.remember that the accept function comes outside the loop and after forking the
new child close the old socket and use the new one created by 'accept'.
From: ornaz
Add a Comment
New Questions: TCP/IP called address for a
ANY_HOST listen
From: Leclercq
Is it possible to know the called ip address on a multi ip address machine when the the listen has
been done on ANY_HOST ?
From: Rob Seace
Add a Comment
New Questions: VB client to Perl Server
From: Lee Turner
How do you send data to a local port using VB and have a perl server accept the connection. I
am trying to use Winsock in Vb but the 'Accept' command in Perl does not work in conjuncion
with VB's 'Connect' command
Add a Comment
New Questions: How can i make a server act
as connection oriented as well as connection
less at same time
From: Eswar
Add a Comment
New Questions: Cannot create UDP socket -
port number in use
From: David Friedman
Add a Comment
New Questions: socket c programming
From: matt
Hi,
I am writing a program that does a bunch of stuff with MQSeries and it needs to be
compatible with UNIX and NT. My question is: Is there a C command that I can get the
"hostname" of the system w/o having to go to the command prompt and do it a command?
Thanks,
matt
From: Rob Seace
Add a Comment
New Questions: question
From: allen
Add a Comment
New Questions: How can i send
communication break
From: Arul Anand.J
Add a Comment
New Questions: How can i send
communication break
From: Arul Anand.J
Add a Comment
New Questions: Data comes together
From: Rafael Rocha
The problem is that when the connection is thought a modem, sometimes data arrives together.
No data is being lost, but the VB aplication thing so. Because it receives more than one data at
the ssame time.
Thanks in advance.
Rafael.
Add a Comment
New Questions: Link Error.
From: Carlos A
I've read your question at Unix Socket FAQ and noticed that you have
some experience programming sockets on Solaris. Currently I'm
programming a client-server app using sockets and when compiling I get
this:
Thanks,
Carlos A
Add a Comment
New Questions: demon.
From: Facundo
Hi!
Fac.
From: Rob Seace
Add a Comment
New Questions: MX lookup
From: Mikael Chambon
Thx
From: zhan dong
Add a Comment
New Questions: hostname
From: ethan hunt
Hello.
I need a command (used in a c program) that works for unix and nt, that gets the hostname.
gethostname() and uname() work for unix but not for nt. does anyone know if there is a
command that can be used for nt, and aix and solaris boxes?
thanks.
ethan.
Add a Comment
New Questions: accept() hangs
From: Haim Lichaa
Add a Comment
New Questions: Semantics of ioctl with
FIONREAD and recv
From: Yannis Pavlidis
Hi,
I am facing the following situation. Select is triggered and is informing me that there is data in
the socket to be read. Before going to read data I call ioctl(fd, FIONREAD, &nLen) to
determine how much to read. The ioctl returns 0 (based on the man page it is correct) and the
value of nLen is zero. When I call the recv of course it will return zero. Based on the semantics
of the recv it means that the socket was closed gracefully by the other end.
Is this right?
My second question is why does the server says that the socket was closed? I am 100% that the
client does not do something like this. Which are the causes. The platform is redhat 6.2
Yannis.
From: Rob Seace
Add a Comment
New Questions: Server Application
From: Yigal Petreanu
Is there a way to pass a socket from a server to another process (which is not its child!),
without the client knowing about it ?
From: Rob Seace
Add a Comment
New Questions: WWW
From: Daniel
My unix workstation is unable to surf the net or ping and external IP address after reinstallation.
Could someone help me to solve the problem? Thanks a million!
Add a Comment
New Questions: TCP/IP does not preserve
message boundaries
From: CECE
Hello,
I have a problem. As you all know, tcp does not preserve message boundaries. But, in my
project, I have to separate each single message from the others. And I can't use a header (which
may include the real length of the message) for the messages sent and received, because the
senders are not in control of me. If any of you know something to handle this condition, please
give me some detailed explanation.
From: Rob Seace
Add a Comment
New Questions: MX lookup
From: Mikael Chambon
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int
ns_sprintrrf1(const u_char *msg, size_t msglen,
const char *name, ns_class class, ns_type type,
u_long ttl, const u_char *rdata, size_t rdlen,
const char *name_ctx, const char *origin,
char *buf, size_t buflen);
static size_t prune_origin(const char *name, const char *origin);
static int charstr(const u_char *rdata, const u_char *edata,
char **buf, size_t *buflen);
static int addname(const u_char *msg, size_t msglen,
const u_char **p, const char *origin,
char **buf, size_t *buflen);
static void addlen(size_t len, char **buf, size_t *buflen);
static int addstr(const char *src, size_t len,
char **buf, size_t *buflen);
static int addtab(size_t len, size_t target, int spaced,
char **buf, size_t *buflen);
char*
getmxname(char* name1) {
u_char *msgbase;size_t msglen;
u_char *rdata;size_t rdlen;
u_long ttl;
char name[MAXDNAME];
u_char answer[8*1024];
int c, n, i = 0;
u_int32_t ul;
int nameservers = 0, class, type, len;
struct in_addr q_nsaddr[MAXNS];
struct hostent *q_nsname;
HEADER *hp;
int stream = 0, debug = 0;
ns_msg handle;
int success, proto_type;
/* set defaults */
len = MAXDNAME;
gethostname(name, len);
class = C_IN;
type = T_ANY;
strcpy(name, name1);
proto_type = sym_ston(__p_type_syms,
"MX", &success);
if (success)
type = proto_type;
else {
return NULL;
}
len = sizeof(answer);
res.options |= RES_USEVC;
if (nameservers != 0) {
res.nscount = nameservers;
for (i = nameservers - 1; i >= 0; i--) {
res.nsaddr_list[i].sin_addr.s_addr = q_nsaddr[i].s_addr;
res.nsaddr_list[i].sin_family = AF_INET;
res.nsaddr_list[i].sin_port = htons(NAMESERVER_PORT);
}
}
if (name[strlen(name) - 1] == '.') {
n = res_nquery(&res, name, class, type, answer, len);
if (n < 0) {
fprintf(stderr, "Query failed (h_errno = %d) : %s\n",
h_errno, h_errlist[h_errno]);
return NULL;
}
} else if ((n = res_nsearch(&res, name, class, type,
answer, len)) < 0) {
fprintf(stderr, "Query failed (h_errno = %d) : %s\n",
h_errno, h_errlist[h_errno]);
return NULL;
}
n = ns_sprintrrf1(ns_msg_base(handle), ns_msg_size(handle),
ns_rr_name(rr), ns_rr_class(rr), ns_rr_type(rr),
ns_rr_ttl(rr), ns_rr_rdata(rr), ns_rr_rdlen(rr),
NULL, NULL, buf, sizeof buf);
if(n<0){
fprintf(stderr, ";; ns_sprintrr: %s\n",
strerror(errno));
return NULL;
}
return buf;
}
return NULL;
}
static size_t
prune_origin(const char *name, const char *origin) {
const char *oname = name;
static int
charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
const u_char *odata = rdata;
size_t save_buflen = *buflen;
char *save_buf = *buf;
static void
addlen(size_t len, char **buf, size_t *buflen) {
*buf += len;
*buflen -= len;
}
static int
addstr(const char *src, size_t len, char **buf, size_t *buflen) {
if (len >= *buflen) {
errno = ENOSPC;
return (-1);
}
memcpy(*buf, src, len);
addlen(len, buf, buflen);
**buf = '\0';
return (0);
}
static int
addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
size_t save_buflen = *buflen;
char *save_buf = *buf;
int t;
/*
* Owner.
*/
if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
addstr("\t\t\t", 3, &buf, &buflen);
} else {
len = prune_origin(name, origin);
if (len == 0) {
// addstr("@\t\t\t", 4, &buf, &buflen);
} else {
// addstr(name, len, &buf, &buflen);
/* Origin not used and no trailing dot? */
if ((!origin || !origin[0] || name[len] == '\0') &&
name[len - 1] != '.') {
// addstr(".", 1, &buf, &buflen);
len++;
}
// spaced = addtab(len, 24, spaced, &buf, &buflen);
}
}
/*
* TTL, Class, Type.
*/
// x = ns_format_ttl(ttl, buf, buflen);
// addlen(x, &buf, &buflen);
// len = sprintf(tmp, " %s %s", p_class(class), p_type(type));
// addstr(tmp, len, &buf, &buflen);
// spaced = addtab(x + len, 16, spaced, &buf, &buflen);
/*
* RData.
*/
switch (type) {
case ns_t_mx:
case ns_t_afsdb:
case ns_t_rt: {
u_int t;
t = ns_get16(rdata);
rdata += NS_INT16SZ;
len = sprintf(tmp, "%u ", t);
// addstr(tmp, len, &buf, &buflen);
default:
comment = "unknown RR type";
goto hexify;
}
return (buf - obuf);
formerr:
comment = "RR format error";
hexify: {
int n, m;
char *p;
Add a Comment
New Questions: Using select() for web-server
program
From: Alvin Chang
I've got a question of how to write a code which uses select instead of just fork each child
process to deal with different request. i.e, instead of
if (!fork())
{
recv(request);
send(response);
}
but to use select() to go through a list of connect_id and fds...
Thank u!
From: Magnus Boden
This is in pseudo code.
fd_set readfds;
while(1){
FD_ZERO(&readfds);
FD_SET(socket1,&readfds); // and one of these for every socket
select(maxfds,&readfds,NULL,NULL,0);
if(FD_ISSET(socket1,&readfds)){ // you should make some
readrequest(); // kind of loop to check
writerequest(); // all sockets
}
}
If you intend to make a proper app then you might want
to keep a state of the sockets so you know when to readrequest()
and when to writerequest(); and use a writefds to for all sockets
so you know when you can write to them, otherwise just because
you might be able to read from them it doesn't necessarily
mean you can write to them.
Good try
Add a Comment
New Questions: Ports that Hang
From: Casey Milford
Hello,
I have a situation that I hope someone can help me
with. We have several UNIX (Digital) boxes that run
our online applications. We also have an SDK that
uses said applications. If one of the applications
should fail, the ports open by the SDK users will
hang. The client software does not recognise the
application is down, so it holds the ports for
approximately 15 minutes. Of course, the server
side application cannot restart if the ports are
being used. So, aside from writing the client to
free its connection if the application is down,
how can I _kill_ the ports so that our downtime
is minimal? I am sorry for the long story, but
I felt it necessary to tell the whole story.
No. The socket will move to a TIME_WAIT until the program quits, then it moves to a
FIN_WAIT2. Then the FIN_WAIT2 hangs until the client releases the port.
Thank you again for your help.
From: freeze
The FIN_WAIT2 state means that the connection is closed, and the socket is waiting for a
shutdown from the remote end
later,
freeze
From: Baskar K
Try to use shutdown socket call instead of close.This should solve your problem.
Add a Comment
New Questions: read-write problem
From: Ben
I am writing a pretty elementary socket program. Without getting into the details, it writes an
HTTP request to a socket, then reads back the response and parses it in a certain way. I have
two routines, both write to the socket then read back the response (they parse it differently). If I
call them individually, they both work exactly as they should. However, if I call them
consecutively, the 1st one called works, and the 2nd one will not write to the socket. I am
getting a -1 returned from my call to write(). So, basically, I can write, then read, but I can't then
do another write. Anyone have a clue?
Thanks,
Ben
From: Rob Seace
Add a Comment
New Questions: I am getting connection
refused when ftp from UNIX to NT based
system
From: Somin
Dear friends,
I have a utility which ftp a file from UNIX system to the NT
server .
but when I use the UNIX utility (HP_UX) , it throws back an
error of connection refused.
I thought may be the Nt system requires IIS .
similarly when I create a TCP connection , It throws error
no 127 : Connection Refused .
Please help me out .
Regards and Thanks ,
Somin
From: Arthur Lung
Trying to ftp from unix to nt? Make sure there's an ftp server
running on the nt box, that it works, that it's using the
correct ftp port, that it's actually running, that you have
a route to get to it from your unix box.
Whenever u want to ftp from one system to another system then u should have ftp server
daemon running on the other end and the ftp client daemon running on ur end. Then only u can
ftp to that system. Normally on NT systems there is no ftp server daemon running. It only has
ftp client daemon. So u can't ftp to any of the NT systems. The Network Neighbourhood utility
is used to connect from a windows system to another windows system. But u can't connect from
UNIX to NT. But U can ftp from NT to UNIX, because it has ftp client daemon running.
From: Loco
There is no ftp client daemon... It's just an ftp client application. You just run it and can connect
to any ftp server your machine can access.
You can configure the FTP server on NT using IIS. YOu don't need to configure the HTTP
server under IIS if you don't want to, they are separate services of IIS.
You can also download a lightweight ftp server for windows from any of the download sites in
the web.
Unix normally comes with an FTP server in its distribution. It doesn't mean it is running, so you
have to check it.
A simple "ps -ef | grep ftp" might be enough to find out if a server is running, however the best
way to check it is to connect to the 21 port using telnet and see the response:
"telnet localhost 21" (use whatever address your host or any remote host has)
a response like: "telnet: Unable to connect to remote host: Connection refused" means you
cannot connect to that specific port on the host which could be caused by many things, one of
them is that the service is not running
You can share files from windows systems with unix systems, look for information on NFS and
SAMBA.
Add a Comment
New Questions: can select() notify if a tcp/ip fd
is readable?
From: sreekanth
is it possible to wait for a certern amount of time for reading in a tcp/ip socket? i am not sure if
select()is the function to use for this.
From: Rob Seace
Add a Comment
New Questions: write files to NT
From: Jonas
I have a problem, the code is written in a oracle db. And now we problem with files in the db
cause we have started to use a Unix server, earlier we have used a NT-SERVER.
Files that I earlier could be placed by giving path in the application ex \\computername\test\
Have stopt working. The files can be stored on the UNIX server.
Is it possible to write the files from the unix server to your localy NT-computer ?
(the files are about 100kb)
/Jonas
From: Dema_Lamer
(DBI, DBDOracle)
Add a Comment
New Questions: TIME_WAIT and EPIPE
From: kevin
I have an app (IPCReader) on a Unixware system that opens a socket on an NT Server and write
msgs it gets from an IPC queue. The IPCReader is forked from a parent who's job it is to read
msgs from the socket and send it back to the IPC owner. Works fine, except under load testing.
Each socket is only open for a couple millisecs, it finishes and closes its socket. During load
testing this process to repeated every 5 secs while each of 48 IPC owners send data thru the
socket. After several hundred successes, the sockets in TIME_WAIT are pilling up and then
each new IPC msg is able to create/connect to a new socket, but the first send results in an
EPIPE! Is this normal? I bumped my open fds up to 150, but 48 is the highest number of socks
I'll ever have....
Add a Comment
New Questions: IPC using -shared memmory
and semaphore Vs Sockets
From: Sridhar S
ghfh
Add a Comment
New Questions: Memory corrupted by child
process
From: KBS
I have a global variable initiated by the parent process. This variable is suppose to share by all
the child processes after forked.
In my program, I forked out 2 child processes, one to do some calculation work (let's call it
"pCal") and the other to send and receive message from another server("pHost"). Everything
run very smoothly until one day the other server went down, somehow it affect my pCal process
and the variable data being currupted. One thing to highlight is the variable is never being used
in the pHost process and the variable data in the parent process is perfectly ok even after this.
Add a Comment
New Questions: Number of sockets and
OPEN_MAX limit
From: Kevin F. Webb
I think there are some hard limits that are defined. These are called Kernel Parameters. I am not
sure the exact way you go about changing kernel parameters on Solaris. But on HP-UX you can
use SAM (system administration tool) to change these parameters which will let you bump up
max number of file descriptors, number of processes and so on..
basically the whole gamut of parameters that the kernel uses.
After this you will be required to re-compile the kernel (which may be done transparently by the
system admin tool).
This way you can get over the hard limits you are seeing currently.
Add a Comment
New Questions: SIGPIPE in multi-threaded
client/server program
From: Matthias Blankenhaus
Ok, here is the problem: I am using blocking socket I/O between a client and a server which are
different Posix threads within the same process. My server-thread binds and then blocks in its
accept stmt. My client thread comes up and tries to connect to the server. I am doing the
conntect() call within a loop, therefore calling connect() as often as it takes to establish
successfuly a connection.
So after connect() indicated a successful execution I try to send data to the server (The server
blocks in a read after accepting the client connection request.). The client's send() stmt triggers
a SIGPIPE.
Does anyone has a clue whats going on ? BTW, I am using Solaris 2.6.
Thanx in advance,
Matthias
From: Matthias Blankenhaus
I got the solution. Looking closely at the man page of connect()
shows that in case of a ECONNECTREFUSED you should close the socket,
create a new socket and then try to establish the connection again.
I should have rtfm. Basically after a failed connect() the socket
is in a not defined state. If I add that to my code, then it just
works fine !
Add a Comment
New Questions: How to use select() ?
From: Antonio Vilei
Hi,
a multicast ftp server has to send a file (divided into blocks) to a multicast IP address through a
DATAGRAM socket and it has to receive (just a few) NACK packets from the receivers (the
say which data blocks were lost). The server should go on sending data blocks without stopping
while receiving nacks: i.e. no stop and wait.
Thanks in advance.
Antonio Vilei
From:
Add a Comment
New Questions: listen fails on OpenServer
5.0.5
From: Bob Hepple
any ideas what I am doing wrong???? - I have tried running as root and
using different ports, all to no avail. I've tried putting 12396 into
/etc/services - do I need to register that port anywhere?????
Cheers
Bob
// port = 12396
int
StartSocket(short port, SOCKET * pListener)
{
int err;
SOCKADDR_IN localAddr;
SOCKET listener;
/*
// Prepare to accept client connections. Allow some pending
// connections.
*/
err = listen(listener, 2); // .... returns -1 !!!!!!!
if (err != 0) {
logerr (FN"pid %d: Socket Listen Failed errno=%d (%s)\n", _getpid(),
errno, sys_errlist[errno]);
return -1;
}
*pListener = listener;
return 0;
}
From: Rob Seace
Add a Comment
New Questions: Authorizations doubts
From: Daniele
How can I make my server not to accept requests from clients that are not in
an authorizated machines list?
Add a Comment
New Questions: About sharing the same
socket/same connection to server for two
programs
From: angus
After finish running c program, the socket will be automatically closed. How can I prevent this
situation occurs?
Also, if the first program create the connection. how can the second program can use same
connection that created by first program
Add a Comment
New Questions: c++ and sockets (problem
using close)
From: James
Thanks
James Skinner
From: Rob Seace
Add a Comment
New Questions: select/recv: how to read
complete message?
From: manu
my idea:
- on a select() return, test by recv(MSG_PEEK) or ioctl(FIONREAD) if the
message is complete
- if complete, read it by recv(0)
- if not, let it in the buffer and go on select()ing
The problem:
select() continues to tell there is something to read in the buffer
even if there is no new byte in it
Any idea?
From: Arthur Lung
Add a Comment
New Questions: Blocked I/O Timeout?
From: Tom
Say the receiving program quits reading data with connection open. The write call eventually
blocks. What mechanisms exist to return control out of this blocked write call and close the
port.
From: Rob Seace
FD_ZERO (&fd);
FD_SET(Socket->m_Socket, &fd); // adds sock to the file descriptor set
tv.tv_sec = TimeoutSeconds;
tv.tv_usec = 0;
assert (Socket);
assert (Buffer);
if (0 == Socket->m_Socket)
return (0); // Allready closed
return (BytesSent);
} // End of Send
You should just loop until the read returns 0. All data can be
read this way. Just like in file.
Add a Comment
New Questions: Securing sockets
From: Pete
I would have thought that your first point of call would be to look into
Eric Young's OpenSSL library. www.openssl.org.
Add a Comment
New Questions: how to get all listening ports ?
From: dummyNode
Add a Comment
New Questions: If ISocket permission denied
From: vishwanath
Hi,
If I try to connect one IRIX machine to another or if I ping it it gives an error message
of socket permission denied. Can anybody aanswer my query?
Add a Comment
New Questions: many http request via single
socket.
From: hallian
hi all,
I was wondering:
Has anyone created own packets to send many HTTP request from a single socket,
so that it does not consume system resources as if I open one socket for each http
request. Also, each time a packet is sent, the source address should be different.
thanks,
hallian
From: Gautam
I doubt because http is stateless protocol. So u serve the request & the connection is lost. For
next request another socket..& so on. There is a runway ..u catch the stream & don't leave it
unless the client leaves (but a very crude way) also this is possible through clients that are
written so as to request through same socket....standered browsers will not!!! so choice is to
write ur own browser ;) or write a applet..
Cheers,
Gautam
From: Bill Klein
If I'm understanding your question correctly, the answer is yes. In HTTP/1.1 you can have
persistent connections (and in fact it is the default) and can thus make multiple requests in the
same session. See http://www.faqs.org/rfcs/rfc2616.html for more info.
Add a Comment
New Questions: HOW can I tell protocol?
From: Sridhar
I'm writing a port scanner program which scans all ports or a range of ports on a system. The
program connects to each port and checks for any initial response and reports whether it can
connect to that port or not. The problem is, How can I tell which protocol the port is
implementing. If I use tcp to connect to all sockets, will I be able to read from UDP or ICMP
sockets as well? Before anyone suggests me to get the protocol from /etc/services, let me ask:
What if the port number is different? for example, in /etc/services in my computer, udp/13 is set
for the daytime protocol. What if in some other host, the daytime protocol is udp/14? How can I
know what protocol 14 is under their computer?
Please help!!!!
I would greatly appreciate it if You could contact me by e-mail at [email protected]
-Sridhar
From: Mark
If you connect with a wrong protocol, you will get an error.
Maybe you need a protocol scanner with try and error as well.
From: Rob Seace
There's really NO way you can tell what is running on a remote machine, on any given port#...
The best you can do is hope they are sticking to the standard port# assignments, and base your
assumptions on that... However, why create a port scanner? There are several good ones already
in existence... Or, is this just a project to recreate the wheel, for a fun learning experience? Even
so, you may wish to check out nmap... It's a superb free port-scanner, with full source code
available...
From:
One universal way. Connect to each port a bajillion times.
Each time, try to talk to it using one of the bajillion different
protocols. Hopefully, eventually it will seem like it's working,
and you can hope that the protocol is what you think it is
and not something similiar.
So like the dude above this said, I'd stick with assuming
anything listening on port 23 is either a telnet server, or
one of those stupid programs designed to tell you when you're
being scanned.
Add a Comment
New Questions: Problems receiving UDP
Broadcast...
From: Todd Gruben
I have a simple python application that basically forwards a UDP broadcast through a tcp socket
accross the internet. This app worked great on NT. On my linux box, is see that the broadcast is
occuring via the tcpdump command but for some reason my sockets app is not seeing those
packets. Is this a sockets problem or a network config problem?
Add a Comment
New Questions: Changing the buffer size of a
listening socket
From: Irina
Thanks.
From: Arthur Lung
The documentation says that it copies "most" of it's socket
options to the newly created socket. I'm not sure what
constitutes "most" though. I know the new socket will inheret
stuff like wether it's a blocking socket or not. About the
only way to be sure would be to accept a connection and then
examine it to see if what you're looking for is already set.
It's not clear if the "most" options are the same across
platforms.
Either way, the gist is that when accept creates a new socket,
that socket inherits settings. But if you later change the
listening socket's options, they don't carry over to the
sockets that have already been accepted.
Add a Comment
New Questions: read count diff when
accessing web server.
From: Terrance
Hi,
When I access a web site using the following loop, I usually
get different number of bytes. And when I print it out it
is very different from what I see when I use the View Source
in Netscape. How do the browsers always get the page
correctly ?
char c;
int i = 0;
cout << "Word count : [" << i << "]" << endl;
Thanks !
Terrance
Add a Comment
New Questions: How to allocate the server
buffer effectively?
From: biju
Dear sir,
Add a Comment
New Questions: signal(SIGPIPE,SIG_IGN) still
doesnt ignore SIGPIPE
From: Per Arneng
signal does not return SIG_ERR. here is the code where i check:
if(signal(SIGPIPE,SIG_IGN)==SIG_ERR) {
//it doesnt come here.. but if i change SIGPIPE
//to a random number it reports an error
// so this step seems ok
perror("signal");
}
//---------------------------------------
Seems very odd. I have done handlers for othe signals like SIGINT and others,, and they work
fine.. its just sigpipe. Well im getting a new harddrive tomorrow and im going to reinstall
debian .. the i will compile again and see if i get the same error. Well this is really a strange
error.. or mayby a bug. Could it be that some special things happen just with my code. i compile
with -D_REENTRANT amongst other things.. (threaded webserver). If anyone want i can send
the code..
Using SOCK_STREAM i'm using send and checking the return value. send only checks that the
data has been successfully passed to the local transport provider though.
I need to be absolutely certain the data has been read by the server program (not running on
same machine).
Whats the best way to do this. I realise i could implement my own acknowledgement but can't
TCP/IP guarantee the successful delivery of my message ?
From: Rob Seace
TCP does "guarantee" delivery of data... If it is at all possible to get it there... Ie: if TCP can't
get it there, there's not a lot YOU are going to be able to do about it, via any other method,
instead...
Is your requirement that you just need to know for sure WHEN the remote side has successfully
received the data you sent? If so, personally, I would make the design such that the remote end
had to send some message back to confirm receipt, as you mentioned (but, didn't like)... But, if
that were not doable, for some reason, the only choices I can see are: 1) set a small send buffer
on your socket, preferably exactly the size of your outgoing message, and then monitor the
socket with select() after your write(), and watch for it to become writable again, which means
the buffer has room in it again; 2) use a raw socket to monitor all inbound TCP traffic, and
watch for the incoming ACK for your outgoing message... #2 is probably overly complicated
for any normal usage... (But, now that you mention it, it does seem a shame that the standard
sockets API doesn't define a way to be notified of when your packets get ACK'd... I can see
how that could certainly be handy...) And, I really can't guarantee the accuracy of #1... But, it
sure SOUNDS like it should work, to me... The message shouldn't leave the send buffer until
the remote side ACKs it, I wouldn't think... So, I don't know why it shouldn't work... But, this is
all just theory; I've never had a need to try anything like that before...
You may want to check out the following sections of the FAQ here, as well, which may or may
not be helpful to your situation: 2.11, 2.16, 2.17...
From: Roy
According to Stevens book "when TCP sends data it requires an acknowledgement in return. If
an acknowledgement is not received TCP retransmitts the data, and after some retransmissions
TCP will give up - time spent retrying depending on implementation (typically between 4 & 10
mins)".
Trouble with this is i can see no way of detecting that TCP has given up with a particular data
segment. (Hence still no guarantee of delivery/detection)
Also in Stevens "only when ACK received from peer can TCP discard the data from the socket
send buffer"
If i have interpreted this correctly then setting the buffer size to be the length of my message
will mean that i can send no other data (it will block) while that packet is being re-sent. While
this enables detection that the data hasn't recieved an ACK whilst in the buffer, it also means
i'm blocked sending any other data for the given 4 to 10 mins!.
No, you don't need to block with another write(); you can
just call select() after the first write(), and when the
socket select()'s as writable again, presumably that should
mean the other side has ACK'd the first message... However,
this assumes you want/need to know the state of every
message immediately after it's sent... If, instead, you
just want to blast out a bunch of messages, and then go back
after, and find out for certain whether or not they've all
(or, any particular one) has made it, it may be harder...
From: sielim
Add a Comment
New Questions: Problems with socket UDP
From: Jose Luis
I have an application client/server UDP. If the server this up, the client works correctly.
However, if there is not server, the client he sends correctly but when staying
to he listens to it, the function recvfrom returns the error "Refused Connection." To that can be
due?
Because this happens when there is not connection settled down to be UDP?. Thank you.
Client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
memset(buf,0,T_MENSAJE);
soc=socket(AF_INET,SOCK_DGRAM,0);
if (soc < 0)
{
perror("Error en socket\n");
exit(1);
}
if ((h_puntero=gethostbyname("JOSE_PC"))==NULL)
{
perror("Error en gethostbyname\n");
exit(1);
}
memcpy(&dir_local.sin_addr,h_puntero->h_addr,h_puntero->h_length);
dir_local.sin_family=AF_INET;
//dir_local.sin_addr.s_addr=INADDR_ANY;
dir_local.sin_port=htons(1040);
if (bind(soc,(struct sockaddr *)&dir_local,sizeof(dir_local))<0)
{
perror("Error en bind\n");
exit(1);
}
lon=sizeof(dir_local);
if(getsockname(soc,(struct sockaddr *)&dir_local,&lon)<0)
{
perror("Error en getsockname\n");
exit(1);
}
printf ("\nPuesto asignado: %d\n",ntohs(dir_local.sin_port));
if ((h_puntero=gethostbyname("JOSE_PC"))==NULL)
{
perror("Error en gethostbyname\n");
exit(1);
}
memcpy(&dir_remota.sin_addr,h_puntero->h_addr,h_puntero->h_length);
dir_remota.sin_family=AF_INET;
dir_remota.sin_port=htons(atoi(argv[1]));
if ((datos=sendto(soc,DATOS,sizeof(DATOS),0,(struct sockaddr
*)&dir_remota,sizeof(dir_remota)))<0)
{
perror("Error en sendto\n");
exit(1);
}
fflush(soc);
printf ("\ndatos enviados\n");
Add a Comment
New Questions: Socket Latency
From: Nitin
Add a Comment
New Questions: Connect to a server
From: antonatos spyros
Add a Comment
New Questions: RECVFROM and IOCTL
Question
From: Tammy
I have a client setup on a different machine than the server. The client sends acknowledgements
to the server and waits 5 seconds for a response. When the server goes into the function to read
the socket, it does this:
The Acknowledgement that the client sent was 12 bytes long, and that is what count equals after
the recvfrom statement is executed. However, size is equal to 28 bytes. What can be causing
this? We have another program that does a very similar thing that works correctly.
Add a Comment
New Questions: sockets program to retrieve
web content
From: Madhu Garlanka
Is there anyone who has sample code to retrieve web content using sockets programming?
Thanks,
Madhu
Add a Comment
New Questions: How to bind a socket to
multiple known ports?
From: ed
Hi! I want to bind my server socket to more than one ports, so that it can listen to more ports. I
don't know whether it is possible. Thank you!
From: Rob Seace
Add a Comment
New Questions: Re: Sending files over (
Socket )
From: Bryan Lee
How do i send files over socket, what commands and functions can i use?
From: Mahafuz
Add a Comment
New Questions: Why Select is not realizing
that there is data on socket to read.
From: Muhammad Mobeen
I have written the following code for reading data from sockets using Select but the problem is..
there is data sent by client but the select doesnot see it. If i write the read statement before the
select it is recieving the data and outputting it, but if i remove it then the select waits upto the
time out and then just exiting.
listenfd=socket(....)
bind(....)
listen(listenfd,...)
FD_ZERO(&rset);
FD_ZERO(&allset);
FD_SET(listenfd,&allset);
for (;;)
{
rset=allset;
nready=select(maxfd,&rset,NULL,NULL,NULL);
if (FD_ISSET(listenfd,&rset))
{
// Accepting the request from client
connfd=accept(listenfd,.....);
FD_SET(connfd,&allset);
printf("Connection and select succesful\n");
//read the data from socket and proces....
......
}
This is v simple and i think the select should work but it is not working, it is just blocking on
select.
You are doing select on the wrong set. you have added your
file descriptor in wrong set.
insted of
FD_ZERO(&rset);
FD_ZERO(&allset);
FD_SET(listenfd,&allset);
Do:
FD_ZERO(&rset);
FD_ZERO(&allset);
FD_SET(listenfd,&rset);
Since you are selecting only for read event , you should
add your file descriptor to read set.
From: gustavo
From: Nagendra M
sockfd=socket();
fd_set read_fds;
FD_CLR(&read_fds);
FD_SET(sockfd,&read_fds);
select(maxfd,&read_fds,NULL,NULL,NULL);
use this
From: Hector Lasso
I think that the problem is that you are trying to copy "allset" into "rset" before calling select()
like this: "rset=allset;". This shouldn't work because fd_set is a complex structure. Use
"memcpy(rset, allset, sizeof(rset));" instead.
Also, Rob points another issue, in your code i can't see any reference to maxfd. I guess you are
tracking the greatest file descriptor plus one in this variable.
If the memcpy() doesn't work, try a loop to fill rset:
FD_ZERO(&rset);
for (i=0;i<maxfd;i++)
if (FD_ISSET(i, &allset))
FD_SET(i, &rset);
I've used memcpy() before and it has worked just fine, however, looking at the fd_set structure i
have found it very complex, so i don't feel very comfortable about it.
I'll just take a closer look at what the FD_XXXX macros do and how the sructure is filled
before using memcpy() again.
Good luck
After select the read,write and exception sets gets cleared , so we require to set all again.
Hence all the FD_ZERO and FD_SET should be placed inside 'for' loop.
Best Regards,
Satya
Add a Comment
New Questions: How to get ISP assigned IP
From: Mahafuz
Hi,
I'm writing a TCP/IP server app and i want to bind() my server to a socket with the IP address
dynamically assigned by my ISP. Assume that i'm connected to internet while i'm starting up
my server. My problem is, how can I find out (programmatically) the ip address assigned by my
ISP.
-- Mahafuz
close (fd);
Now i want to query my system for available interfaces. I've seen that ifconfig does it by
reading proc file system. It seemed to complex code to me. I have little
knowledege about proc files. So i couldn't understand very much.
I Couldn't find if_nameindex() in man pages. But its there in net/if.h. Thanks.
From: Lost
just for anyones reference, on linux, you can just use get_myaddress() like this
get_myaddress(&my_addr);
printf("Your ip is %s\n", inet_ntoa(my_addr.in_addr);
From: lost
Add a Comment
New Questions: UDP has connection in linux?
From: meng
I sent message from host A to B useing UDP in linux. When B close the socket, in A I got a
"connection refuse" system warnning.In a few minute, even if B bind to the UDP port
again,from A still cann't send message to B.Usaging tcpdump on A, I found a ICMP package of
"network unrecahable".
How can I resend message after B is restart quickly?
Is there virtual conection in linux for UDP?
In Winnt, this will not happen?
Who can help me?
Add a Comment
New Questions: UDP has connection in linux?
From: meng
I sent message from host A to B useing UDP in linux. When B close the socket, in A I got a
"connection refuse" system warnning.In a few minute, even if B bind to the UDP port
again,from A still cann't send message to B.Usaging tcpdump on A, I found a ICMP package of
"network unrecahable".
How can I resend message after B is restart quickly?
Is there virtual conection in linux for UDP?
In Winnt, this will not happen?
Who can help me?
Add a Comment
New Questions: Why UDP is used for the
Internet instead of TCP?
From: K.Kumar
Why UDP(unreliable protocol) is being chosen for the Internet instead of TCP which is
reliable?
From: Rob Seace
Um, what exactly are you talking about?? I'd say TCP is
used FAR more widely on the Net than UDP is... But, UDP
does have its uses... (Eg: Quake is a perfect example: you
need the absolute blazingest fast speed possible, with 0
overhead, and also don't really care if you drop a few
packets here and there...)
From: K.Kumar
U mean that the http uses connection-oriented protocol (TCP) (maintaining session)? Explain
about Quake.
From: Mahafuz
--- Mahafuz
At the following link, click on the Networks Section under "Table of Contents" for a good
overview of Network Protocols:
http://www.sftw.umac.mo/resources/LDP/LDP/tlk/tlk.html
Happy computing!
Add a Comment
New Questions: sockaddr structure oddity
From: ak
Why do the generic socket address and the protocol specific socket addresses have the first 2
fields common (unit8_t and sa_family_t) ?
Add a Comment
New Questions: Can same port be used by two
processes?
From: Mohan Rao Kakumani
Hi all,
Is it possible, for two processes in the same system to use the same port i.e while issueing
socket(..) system call, can we give same port number in both the processes?
However, one process only uses the socket(port) for sending messages, while other uses it only
for receiving messages.
Is there any ways to get around of the above problem. Normally when we issue socket() system
call with the same port number, it gives error. But, i want to open sockets in the same port, in
two processes of same machine, one used for reading while the other for sending.
http://www.ecst.csuchico.edu/~beej/guide/net/
It reveals all.
From: eric
Hi, the problem we're facing is that when we want to send a udp message, the operating system
chooses a source port for the packets. Problem is, we want to packets through a source port
chosen by us. How?
ziv
p.s. we're using sendto() for the sending.
From: Mahafuz
Add a Comment
New Questions: Socket Address Structure
From: Kidd Smith
By using the first filed, who to interpret the rest of the address is determined. Since there are
various protocol specific address structues and the fucntions like
connect(...) are protocol independent( they take pointer to generic address structure) , they uses
the first field to determine the type of the address structure and uses the rest of the strucure.
From: David Johnson
Without this convention there has to be protocol specific functions. ie. connect_XXXX(...)
where XXXX is the protocol family.
Add a Comment
New Questions: IPC
From: Kidd Smith
Hmmmm, well I'd guess that pipes would probably be the most
straightforward to convert over to sockets... Mainly,
because the I/O API remains the same (they're still just
file descriptors, which you can read()/write()/whatever)...
However, there are some notable differences: mainly, sockets
are bi-directional (full duplex), while pipes are only
uni-directional... So, what you needed two pipes to do
before, can really be done with a single socket... But, if
you wanted to get by with the least code change possible,
you could just kluge around that by dup()'ing the socket FD,
to create an artificially separate 'reading' vs. 'writing'
end...
Add a Comment
New Questions: XDR
From: Kidd Smith
Add a Comment
New Questions: accept() error!
From: zhangg
/*
explain: I use accept() function to wait Client connect ,
but accept() error when client connect number more than 19.
errno is :bad file number .
*/
if (bind(s,(struct sockaddr*)&ServerAddr,sizeof(ServerAddr))==-1)
{
exit(0);
}
if ( listen(s, 1 )== -1 )
{
exit(0);
}
if( (AcceptPID=fork())==0 )
{
//accept loop
for( ; ; )
{
SockAddrLen=sizeof(ClientAddr);
if ( new_s== -1)
{
//accept error!
//errno is : bad file number .
exit(0);
}
/*do something */
}//continue wait connect
}
From: Mahafuz
/*do something */
From: Mahafuz
From: Mahafuz
Pls make sure you are not closing the socket descriptor - "s" on which you are acceping,
somewhere in
/* do something*/
From: zhangg
Add a Comment
New Questions: How to post data using Post
method to a servlet
From: Sudipto Basu
Hi,
Look, the servlet have some text fields like name and
id. and i want to post this two parameters from my
client program.
with regards,
Sudipto Basu,India
Add a Comment
New Questions: my program gets stuck when
closing a socket.
From: Ma'ayan
Hi,
thanks in advance,
Ma'ayan.
Add a Comment
New Questions: why does bind() give
EADDRINUSE
From: Duane Ellis
I have a fork()ing server application, that I need the ability to quickly kill and restart. If there
are no clients attached at the time the server goes down and comes right back up all is well.
If there is a client attached to a fork()ed instance of the server, and the server goes down (ie:
during a restart) the client dies. When the server comes back up and trys to re-bind()to the same
port bind() fails with EADDRINUSE.
If I wait some period of time (more then 30 seconds) it works. Why?
ANSWER: When the server dies, the open socket enters the TIME_WAIT state, basically
TIME_WAIT is suppose to handle any floating packets still enroute between the two machines.
During that time, the port number you where using is 'IN USE' (so that it can safely ignore the
lost packets that majically re-appear)
To let your server come back up quickly, you need to call the function setsockopt() turning on
the option "SO_REUSEADDR" like this:
s = socket( .... );
int flag; flag = 1;
setsockopt( s, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag) );
... then ...
bind( s, .... );
This took quite a while for me to find, and might well be the source of alot of the TIME_WAIT
confusion.
From: Rob Seace
Well, that's true, but this exact issue is already covered quite extensively in the FAQ proper:
4.1, 4.5, and 1.7... ;-)
Add a Comment
New Questions: Compilation problem
From: Minko Govedarov
Thanks,
Minko
From: Minko Govedarov
regards,
Minko
Add a Comment
New Questions: live AP_INET SOCK_STREAM
connection
From: Flawd95
what steps do you need to take in makng a connection that constantly reads from a server? I've
managed to get it connected, but would like some help in how I can "monitor" the socket for
incomming data without having to recv 100 times.
From: flawd95
sorry for the double post. an example of what I want to know would be something like an IRC
client. as the data comes, it comes up in the window. I'm brand new to socket programming. I'm
sure I can manage do display the information (I hope :)) I'm guessing that there's a loop
somewheres?
From: Rob Seace
Add a Comment
New Questions: TCP/IP issue on HP Unix
From: ravinder Singh
The issue is that I have 2 demon process both for reading and writing into the same socket in
TCP/IP. The first process creates the socket, but second process gets the socket id from a file as
first process stores the same into this file. But the second process is not able to write into that
socket.
Is there some constrain for the same or do we need to have some privilege for the same. The
error that I get is : Value after write function [-1]<send_msg> write buffer fail - errno: <4>
Sir, file descriptor is an index to a table of files that are opened associated with perticular
process.
From: Btvrao
Sir,
Add a Comment
New Questions: select() between a UDP socket
and a TCP client socket
From: oemar
Hi all,
I'm having this problem with select. You see I have a TCP client socket (connected to a tcp
server) and a UDP socket running together inside a loop.
The size of data travelling between these sockets was set to 4k, time out in select() is set to 1
second.
Now the problem.. when I send data from the tcp server, select() doesn't return anything (still
blocking). When I send data from a peer to the UDP port the same thing happened, select still
blocks. I checked the select FD_SET and it's waiting on the right sockets.
I am having almost the same problem. I added a TCP socket fd and a UDP socket fd to a read
set. Then I use select on the read set. My situation is a little different in that when a tcp
connection is made, select returns correctly, however, when a udp broadcast is received, the
select doesn't return. Through netstat I noticed that there is data in the recv queue of the udp
socket. One other weird thing - my FD_ISSET() check on the udp socket actually is successful
ONLY when a tcp connection is made (after there is already queued data for the udp
socket)...weird
any help??
From: orna
Hello,
Add a Comment
New Questions: recv gives a segmentation
fault.
From: Bharat
Hi,
I setup a TCP conection between the server and 10 clients(yaah some people do petty things and
still get stuck in it:->). The client is able to send a message to the server and the server receives
it, but when the server sends it a message, the client gets a segmentation fault in its recv call.
I would believe that if there was some problem with the way recv is called, it would returm -1
setting the pertinent errorno. But, that doesn't seem to happen. I do assign the buffer of the
required size(in case smbdy has a doubt about that).
I check the connection using getsockname() and getpeername() before the recv, and everything
looks in order.
Can anybody come up with a scenario wherein the recv will give you a segmentation fault?
Would really appreciate it if anybody could give me a clue, 'coz I am completely clueless(:->)
about this.
Thanks
Bharat
From: Magnus Boden
Add a Comment
New Questions: select question
From: ornaz
thanks in advance
ornaz
From: Rob Seace
thanks
Orna
From: Rob Seace
Now, if there really did exist a function that fit the API
I mentioned, where it only returned a small array/list of
the FDs that were ready for processing, that MAY improve
efficiency a bit... I say MAY, because in order to have
such an API, the array/list it returned would likely need
to be dynamically allocated on the fly, so you would have
the overhead of dynamic memory allocation/freeing, in place
of the extra looping/bitmask-testing... You'd just be
shifting the inefficiency into the library function, rather
than your code... So, I really don't think there's much of
any way to make such a scenerio as efficient as you'd
probably like it to be... *shrug*
You have discovered the very reason why select is not used. Its
sequential, like the programming we did in the 80s. Use threads.
From: Rob Seace
Threads are all well and good, but have several problems and
limitations... If you propose to have a single thread for
handling each and every FD, you're talking about a LOT of
overhead, for the hundreds of FDs being discussed... And,
what exactly makes you think your OS is going to time-share
between all your threads, such that it turns out you are
responding to incoming data more efficiently than you would
be by doing a simple search through an fd_set for a set bit?
And, even if that were the case, is it worth the overhead
incurred by such an approach (extra memory taken up by all
the threads, extra processing time eaten up swapping between
each thread (depending on your local implementation of
threads, anyway), and added code complexity)? In some
cases, absolutely, I'm sure... I've certainly used such an
approach, where it makes sense to do so... But, it's not
the end-all, be-all, one-and-only solution, either... There
are many cases where it just doesn't make sense to use, at
all...
From: Loco
Rob is right. Threads are useful and very powerful tools to use in some cases, in others they can
be a real pain in the ass.
What i understand is that you want a more efficient way than just loop through all the file
descriptors checking that each of them is set or not in the structure. I don't see it as a real
problem. This kind of loops are very frequent, and as long as the code it executes is "light" then
it will be bearable. If you put lots of code inside the loop then you will have a problem.
Usually the effort spent optimizing code is lost in parts that really won't have any impact on the
overall performance. So i suggest you try the simple select() model, and see it working, when
you have seen it then find the code most repeated and most "expensive" and optimize it. After
that continue until you reach your desired performance. I am almost sure the loop you mention
won't be of any importance to your overall performance.
:D (HAL)
Add a Comment
New Questions: Single server with multiple
clients
From: Stephen Callan
When I just use 1 client the program runs properly, and you can send data from the server to the
client.
However when you try to use a server to send data to 2 clients on the same port, with the 2
clients on different locations, you get a connection refused message on both client stations.
Sir, i think that in ur server program whenever connection comes u didn't fork the loop . if u
fork the loop that child will take care of new connection.
Sir, i think that in ur server program whenever connection comes u didn't fork the loop . if u
fork the loop that child will take care of new connection.
I want write a socket programming between UNIX and Windows (95/98/NT) using C on UNIX
and Visual Basic or Visual C++ on Windows. How could I integrate this two since they are in
two different platform? In Windows it is most likely to use winsock. Can anyone help me on
this or suggest any website to refer to? Thank.
From: Todd Stout
The winsock API is modeled after the BSD socket API that
appeared many years ago on UNIX platforms. The MS
winsock API is not 100% BSD but it's close. There
are a few major differences such as error codes and
the fact that Windows requires an explicit initialization
of the TCP/IP stack (it's not part of the kernel) However,
I have found that it is relativiely easy to write C/C++
code that compiles and runs on UNIX and Windows without
an excessive amount of #ifdefs in the code.
One drawback to this however is that most unices are
moving away from the BSD API in favor of the POSIX API.
The POSIX api is similar to BSD but different enough
to require code changes. I have no idea if MS is planning
on supporting a POSIX socket API in the future. Since
open standards are against Microsoft's business plan,
I'd doubt they will ever support it.
Add a Comment
New Questions: CONNECTION ABORT
From: Erin
Periodically, when a client connects to my server process, I'll get Connection Aborted errors on
my server. Is this a "catch-all" for many different things that could go wrong - or does anyone
know of (even a small number) of reasons why this would occur?
Add a Comment
New Questions: MAC Address from client w/o
using ARP?
From: supafuz
Hey, im looking for some help with this issue im having ...
w/o reinventing the wheel.
I would like to find the MAC address of clients which sends
a UDP packet to my server. I see two ways to do it:
1) use ioctrl(sockfd, SIOCGARP, &pointer)
2) sniff at the MAC layer and wait for something destined to me
number 2) seems like too much work for the kernel/CPU to do for
what I need. But, it may be the only solution?
-imallears
From: Rob Seace
What is the errno set to when the ioctl() fails? Have you
tried simply retrying the ioctl() after the failure? Maybe
it's simply a temporary/transient failure, of some sort...
Add a Comment
New Questions: Threads and sockets
From: John Arcade
I'm writing a sliding window protocol using UDP, and the problem I have is I cannot recvfrom the client. I have a
thread that sends the data to the client, and another thread that is supposed to constantly listen to the client. The
code below is the listening thread.
size=sizeof(fromAddr);
rsize=1;
sock=((struct ThreadArgs *) threadArgs) -> clntSock;
rstate=((struct ThreadArgs *) threadArgs) -> lswps;
free(threadArgs);
printf("\n in Thread Listen... recvfrom");
Add a Comment
New Questions: write() Hanging Program.
From: Twilight
I am using write() to send data back to sockets. The problem is that every few hours the server
hangs on the write() command. Should I use some other command? or check to make sure the
fd is still active some how?
Add a Comment
New Questions: KCP
From: K.Kumar
In which site can I find the detailed documentation of KCP(Kiva Communication Protocol)?
Thanks in advance.
Add a Comment
New Questions: TCP Send-Q Retransmission
From: Claes
Hi, I have a problem with a Linux game server. The clients just don't get the TCP Send-Q
Retransmissions. Is there any way to improve the performance of the retransmission of not
Ack'ed tiny datagrams?
From: Rob Seace
Not sure if this is exactly what you're looking for, but it sounds similar: try disabling the Nagle
algorithm... Though, that is really related to delays with small packets initially, not
retransmission of them... But, it still may be of use, if you're not already using it... But, it may
just be that for a game server, you want to be using UDP rather than TCP... (Just like Quake...)
Then, you don't need to worry about the vagaries of the TCP stack and how it retransmits and
other such things... You can just code your own retransmission behavior as you like... (If you
need any at all... You could just do like Quake does, and EXPECT packets to be dropped, and
not consider that a problem... Just let them drop, and move on... It requires a protocol that can
recover from such a situation though... Ie: one that is able to catch up on any missed info, with
later packets that DO make it though...)
Add a Comment
New Questions: How can I do a ftp???
From: Sofy and Miriam
Hello friends!!!
Thanks a lot!!!
From: Luca
I'd like to know how to do too.(in C language).
From: TRC
SOCKETS in C
www.ecst.csuchico.edu/~beej/guide/net
From: Hector Lasso
Hi,
This is not a simple matter. FTP is a protocol, its specification is written in RFC 959 (which you
can find easily on the web - ftp://nic.merit.edu/documents/rfc/rfc0959.txt).
It uses TCP connections from client to server to transfer files and do some other operations
(such as listing files).
When the client connects to the server it creates a TCP connection that is used to authenticate
the user, to send commands to server and to receive status notifications about the commands.
This connection is called the control connection. However, when data is transfered a temporary
connection must be used (the data connection), which is created from the server to the client, or
from the client to the server. This temporary connection is used to send data and need not exist
throughout the session (i mean, it can be closed when there is no data going from one side to the
other...)
Add a Comment
New Questions: reading from buffer
From: larry
How can data(char datatype) passed on from client program to the server through sockets be
retrieved?
From: Andreas Forsgren
Add a Comment
New Questions: How to retrieve data sent by
client to server when data sent is stored in a
buffer?
From: Lara
hi
I've written a client program which sends data, input by the user of type char[],the server
basically gets data sent by client and prints it at the output which works fine.My problem is how
do i sort out the data sent by the client.
The buffer where in i get data from client contains a series of values,eg:date,name,folder,string
value etc..
Kindly help
regards
Add a Comment
New Questions: broken pipe?
From: irene
hi
Why do i get the run time error 'broken pipe' when i run my client and server programs
From: Rob Seace
Basically, it's normal behavior which you should expect in any sockets program... I always
ignore SIGPIPE, and then just check for an error return from read()/write() (it'll set errno to
EPIPE)...
From: Muslim Moiz Ghadiali
It basically means your connection between the server and client sockets is been terminated for
some reason.Happens mostly in programs running in continous loops at both ends.
From: Rajesh
When the server to which the client wants to connect is not running, this happens. run the client
only, yule get broken pipe.
Add a Comment
New Questions: about recv() call
From: dana
I am trying to created a connection oriented socket, & I find my accept call is succeeding &
returning a valid socket descriptor, but my recv() call is returning 0 when it receives a packet. I
dont know what is happening. could anyone help.
thankx
dana
From: Magnus Boden
We have the exact same problem under win32 on certain configuration only. (win2K AND
win98...)
Can anyone help?
From: Topo
I´m having the exact same problem!
Please somebody answer...
Add a Comment
New Questions: binary file prob
From: supafuz
My problem:
I have:
length = fileLength; // this is done in a separate function
// with fseek ...
fp = fopen(file,"rb");
file_stuff = malloc(length);
fread(file_stuff, length, 1, fp);
...
bind() ...
...
rc = sendto(sd, filechunk, sizeof(filechunk), 0,
(struct sockaddr *) &remoteServAddr,
sizeof(remoteServAddr));
-------
Im using gcc with linux RH 6.1
Everything works fine with ASCII files.
The first 0x00 encountered terminates sendto().
When I try to compile the same code with gcc on Winnt
using cygwin (www.cygnus.com), which provides a Unix
working environment, both ASCII and BINARY files work fine.
Im really confused and have been stuck on this for two weeks.
You know anything about this?
Add a Comment
New Questions: how to signal select function
From: ornaz
i have 2 threads:
1. connect_thread that responsable to reconnect close sockets.
2. read_thread that responsable to do select on multi active
sockets and do recv.
i have the following problem:
the read_thread is waiting on select on certain sockets
but meanwhile there are new active sockets
so how do i signal the read_thread - the select to return
for adding the new sockets?
From: Nospam
Create a pipe and put the read end of the pipe in the
read set of the select. Writes to the write end of the
pipe will wake up the select. If the pipe fd is readable,
then you know to check for whatever internal condition you may have. This is generally how
multi-threaded (or multi-processed) applications signal each other when one is blocked in
select.
Add a Comment
New Questions: Java linux socket problem
From: sagi
Tom
Add a Comment
New Questions: Web Hostinb
From: Bombino
Add a Comment
New Questions: Reg send() socket call
From: dana
-dana
From: Hector Lasso
If the client process is terminated, the server will detect that the socket was closed the next time
you use send() and when you use send() again it will generate a SIGPIPE signal that by default
will terminate the sending process unless you handle the signal or ignore it. If you ignore the
signal (by using sigaction() or alike), the send() function will return -1 and errno will be EPIPE.
You can also get the same behaviour if you use the MSG_NOSIGNAL value in the flag
parameter of send().
However, detection of disconnection is not assured, and the documentation clearly states that
"No indication of failure to deliver is implicit in a send. Locally detected errors are indicated by
a return value of -1." (man 2 send)
I think you should use some kind of acknowledgement or message from the client to let know
that it received the last message, or that it won't be able to receive further messages.
Good luck
From: dana
Add a Comment
New Questions: exit parameter when send call
fails
From: dana
When my send call fails, I want to terminate my process by calling exit call.What parameter
should i pass for exit either exit(0) or exit(1)?
From: Hector Lasso
I'm looking for an example of how to use the "recv" function. Specifically, I'm trying to use it to
enable my code to deal with interrupts, and retry a system call that is interrupted:
do
{
sysret = recv(...);
} while (sysret < 0 && errno == EINTR);
My question is: what parameters do I fill in where the suspension marks are? Does anyone have
a specific example of recv usage in this context?
--Gabi
From: Rob Seace
Well, the basic prototype of recv() is:
Add a Comment
New Questions: CLOSE_WAIT
From: Prabin
Thank you.
From: Mike Temelkovski
Anybody got the answer for that, except rebooting the machine?
From: Michael H. Ward
Here's a question. Suppose I have a server whose sockets are set to DONTLINGER. I have a
bunch of clients who are still set to linger. Are there any situations where the server would close
sockets but get stuck in CLOSE_WAIT? Is it expecting more data from the client in that case
(despite the DONTLINGER), and is the way to fix this to make the clients DONTLINGER, or
is it something else? I should also mention the server is NT-based. Anybody seen this before?
Thanks,
Jake
From: Juan Forero
Isn´t there a way to set a time out to close sockets in CLOSE_WAIT state?
Thx
Add a Comment
New Questions: CCGI - C socket
communication
From: subrahmanyam
hi friends
Client is C socket
server is C - CGI program
Along with this How i can reflect environment variables values while sending data to cgi
program.
every thimg should be in C language
If any person knows please guide me
From: Rex
I'd also like to see how this is done.
From: Hector Lasso
Hi,
I assume your CGI is correctly installed and configured in the web server software.
To communicate the server and client you must use the HTTP protocol from the client,
especially the methods GET and PUT.
The server will get the information from the client using its stdin, and will output results or
whatever to stdout.
The client will have to connect to the web server (usually port 80), send a POST or GET
command with the appropriate URL, and the information it wants to send to the CGI program
Example:
// You have already conected to port 80
// The CGI is in /cgi-bin and is named my_cgi
// I will use the POST method
send(my_socket, "POST /cgi-bin/my_cgi\n", 22, 0);
send(my_socket, "Content-type: text/plain\n", 26,0);
// You will send n bytes, so tell the server so
n = strlen(data_buffer);
sprintf(some_buffer, "Content-length: %d\n", n);
send(my_socket, some_buffer, strlen(some_buffer),0);
send(my_socket, data_buffer, n, 0);
You will have to study HTTP a little bit more to make this code work, but it isn't much
problem. It's been a lot of time since i wrote some code for this, so i hope i haven't missed
something.
Good luck
Add a Comment
New Questions: setsockopt with
IP_MULTICAST_IF question
From: Antonio Vilei
Hi there,
In Linux I need to choose a sending interface (192.168.0.1) from 2 interfaces when
sending to a multicast group.
I tried setsockopt() with IP_MULTICAST_IF but it failed saying that address
cannot be assigned. It fails even if I try to bind the socket before calling
setsockopt(), but I get the same error.
Here is the code:
int sockfd;
struct sockaddr_in their_addr; // multicast receivers' group information
struct in_addr interface_addr;
interface_addr.s_addr = inet_addr("192.168.0.1");
if (setsockopt (socket, IPPROTO_IP, IP_MULTICAST_IF, &interface_addr,
sizeof(interface_addr)) < 0)
{
perror("setsockopt failed");
exit(1);
}
Add a Comment
New Questions: Socket is not being released
From: jagadeesh
Hi,
I've a Java tcp client, it is conneted to java server which is running on solaries. the socket is not
being released soon after the network cable is pulled out. Any one can answer me how can i
re-establish the connection immediately in the same java tcp client to the server.
Thanks
Jagadeesh
Add a Comment
New Questions: Can I bind socket descriptor
to a port which bound by others ? How ?
From: Jack
Well, it depends on your OS... Some allow you to steal a bound address away from a daemon
listening on INADDR_ANY, by instead binding to a specific IP, for the same port... Some also
support SO_REUSEPORT, which will do it, as long as all programs use it... (See question 4.11
in the main FAQ for more info on that...) In general though, I sure wouldn't think you would
really WANT to do such a thing...
Add a Comment
New Questions: How Many Sockets?
From: JiK
How can you tell how many sockets your system will allow you to have open concurrently?
From: Rob Seace
if you write a program to open sockets it will fail at the file descriptor limit for a process and
not the operating system.
Add a Comment
New Questions: Questions regarding both
Clients and Servers (TCP/SOCK_STREAM)
From: Naim Far
how can connect() and write() in the client succeed while the server's accept() doesn't accept
any message from the client ?!
From: Rob Seace
In short, any listening socket will pre-accept a number of clients, and keep them queued, until
the server accept()'s them...
And, write() will just fill the outgoing socket buffer, and the data will be sent later, when it can
be... (Or, it may even pre-buffer it on the receiving side... Not sure...)
Add a Comment
New Questions: Questions regarding both
Clients and Servers (TCP/SOCK_STREAM)
From: Naim Far
how can the client's connect() fails while the server has his accept() running?!
Add a Comment
New Questions: How can I bind to port use
different name ?
From: Jack
A socket, a IP address and a port was bound, I want to bind another socket to this port now. I
know, I must use a different IP address, but how ?
Add a Comment
New Questions: how to bind a port that was
bound ?
From: Jack
A socket, a IP address and a port was bound, I want to bind another socket to this port now. Can
I use same address and same port ? And I can not use UDP.
Didn't you ask this, and I already respond to it, the other day, already? Yep, here it is...
Add a Comment
New Questions: Accept method
From: Nir
When waiting for a client to connect via accept method - is there any default
timeout set for accept to wait ?
The problem appeared after the server waits on a client to coonect and after
an uncertain time period it hangs.
Any advices ?
Thanx in advance.
From: Rob Seace
Add a Comment
New Questions: Winsocket> From: Vadim
Hi...im very freash at this area...so maybe you
could help me.
Q: Can unix comunicate throug sockets to
winsocket..(or onother win-based socket) with
TCP/IP
thanks!
From: mike
Yes, of course they can. The good thing about
TCP/IP is that it's a standard protocol, and all
systems can communicate with each other.
Add a Comment
New Questions: is there any way to determine
which process id is running a particular server
?
From: AK
Hi all,
Add a Comment
New Questions: simplest way to send
structures via sockets
From: Gregory
I am very new to socket programming but loving it by the day. I'm trying to write client /server
programs which send various info between each other. How can i send this info in structures.
All the read /write functions for sockets seem to require string arrays. I've told a can use RPC.
What is it and where can i find it.
From: Glenn
One implementation is to have some message codes that tell the other side of the socket what
kind of structure to use, then do a memcpy from the byte array into the structure.
From: sulfy
some example code would be great, since sending structures are giving me and my compiler a
headache =)
From: Loco
The sender code would look like:
// struct definition
struct mystruct {
char somestring[SIZE];
int someint;
//etc...
};
...
// Sending data
struct mystruct mydata;
// fill struct
send(mysocket, (void*)&mydata, sizeof(struct mystruct), 0);
The struct definition must be the same for both parties. You must be aware about datatypes in
different platforms.
htons(), htonl(), ntohs() and ntohl() may help you send integers in a consistent format.
Do not send pointers (they are useless out of the context of your process) neither file
descriptors.
:) (HAL)
Add a Comment
New Questions: Recv and Send functions
Result
From: Ismail Civgaz
Add a Comment
New Questions: HOW MANY BITS ARE IN A
TCP SOCKET?
From: Tommy
?
From: John Doe
In excess of 4.
From: dave
yes
From: George
Fish.
Add a Comment
New Questions: server host name
From: Vaidhyanathan
i have made a client/server program.the command line arguements to server program are
portnumber and hostname.if hostname is not given i am using INADDR_ANY to find the host
name.client's command line arguements are server hostname and portnumber.how can i find the
server host name.
i have written the program in c under unix environment.
From: mahesh
-mahesh
Add a Comment
New Questions: blocking write
From: orna
thanks in advance
orna
Add a Comment
New Questions: TIME_WAIT
From: mahesh
hi,
i'm trying to write a proxy server, (browser contacts me, i forward the
request to webserver, webserver replies to me, i forward the reply to
browser). i'm facing problem with the TIME_WAIT states. a site like
www.cnn.com seems to be opening about 20 connections at one time and if
i continue to access it in quick successions the no. of connections with
TIME_WAIT state increases and my programs gives an error (# 24) too many
files open. i know that TIME_WAIT state remains for 2*MSL or 120 sec.
one of the solutions i found after going through several articles was to
send RST message instead of or after closing the socket. i don't know
how to send a RST message, if you knwo it please let me know. if you
have faced this problem before and have been able to solve this
problem, please share it with me.
i think the client/server that initiates the close (sends the FIN)
reaches the TIME_WAIT state. in my program, i close the connection once
i write the data to the proxy client. so i make as many no. of closes as
the no. of connections the proxy client makes, and hence my program ends
up accumulating the TIME_WAIT states. i think if the browser closes the
connection before i close, i might end up with CLOSE_WAIT state, but the
problem is how do i tell the browser (i'm using netscape for my proxy,
HTTP 1.0) to close the connection. or is there a way around to avoid
accumulating the TIME_WAIT states.
i found the problem, and the problem was i'd missed to close
one of the file descriptors which kept on growing until it
gave the error "too many files open".
Add a Comment
New Questions: How to flush the socket ?
From: acheng
when I write a chat server with socket ,i encount such a problem-- i cannot flush a socket
efficiently as do with a file stream. who can help me? Any help will be greatly appreciated.
From: Rob Seace
First, I'll assume you're not using stdio file pointers for your sockets... If you are, that could lead
to problems, because you're then going through two sets of buffers (the stdio buffers, then the
socket buffers)...
See questions 2.11, and 2.16 in the main FAQ section... Disabling the Nagle algorithm might be
what you're looking for...
From: acheng
But I use SCO unix, the OS has no TCP_NODELAY option , i can not disable Nagle algorithm
. what should I do next?
From: Rob Seace
Add a Comment
New Questions: client /server problem
From: nu
Add a Comment
New Questions: Maximum speed in the socket
From: juanuker
Thanks in advance.
From: Rob Seace
Thanks.
From: alex
Your speed for connections (other than localhost) are limited to the speed of light.
Add a Comment
New Questions: Socket reliability
From: Ankur
Using socket API, how do we know that the peer end has received the data without an
acknowledgement from that side. I hope the write system call return the number of bytes written
in local TCP buffer not at the peer buffer.
From: Mahafuz
Add a Comment
New Questions: blocking ip address
From: Donny S.
Add a Comment
New Questions: send a buffer from server to
all clients?
From: cabbe
Im writing a chat program and a server to learn about sockets and threads. How can i send the
recieved(server) buffer to the sockets in all threads? (server -> all clients). can that be done?
Add a Comment
New Questions: Accessing non-HTTP servers
through a proxy
From: YMS
Hello,
I am experimenting with web proxy servers. For testing, I telnet to my web proxy and type:
to access a web page outside of my firewall . I am now trying to access a server outside of my
firewall that is not HTTP-based; I want to use a protocol that I developed myself. Is this
possible via a web proxy? What kind of string to I need to pass to the web proxy?
Thanks,
YMS
From: Rob Seace
I think you want something like httptunnel...
From: Hector Lasso
Hi,
If your proxy allows the CONNECT command, you may use it to connect to some other server
like this:
I tested it on my proxy (enabling access control for some ports) and it worked just fine!!!
Example
Good luck
Add a Comment
New Questions: re: socket error
From: Emily
I can login to my novell network successfully, but there is a problem when i open outlook
express and IE 5.5.... the error message is "server not found" and "socket error". pls advise....
Add a Comment
New Questions: Asynchronous I/O
From: Christos
I want to implemment a client program to send and recieve data from a TCP/IP connection.
Also the client wants to receive data from another connection established by the server. The
second communication channel should be an asynchronous one. I have define a function to
establish a protocol when the SIGIO sent but I can not return to the main control of my
program.
Add a Comment
New Questions: Encrypting data on socket
From: Roy
I need to protect the data i'm sending on a TCP socket on unix (Our own client and server
programs).
Suggestions i've had are
1) Using secure sockets
2) secure shell on unix
3) DES encrypt message in our code before sending
I'm don't know very much about first 2 options (is option 2 valid?) to compare against option 3.
Well, I'd certainly recommend going with something standard and already widely in use, such
as SSL, rather than rolling your own encryption method... Just much less chance of screwing
something up, and much higher likelihood that the data will be secured well... There is a freely
available implementation of SSL, which you can use, if you like: OpenSSL...
Your option #2 (tunnelling through SSH) is also certainly a possibility... SSH is also highly
trusted, as far as encryption strength/integrity goes, and it's easily able to tunnel any TCP traffic
you like... However, you then have to deal with setting up the tunnel, completely outside of
your own app... Which MAY be ideal, depending on your circumstances... If you wish to be
able to operate in the clear, in some cases, it may be best to let some external thing like SSH
worry about all the encryption stuff, and let your app just do everything the same way, no
matter what... But, if you always want to encrypt everything, it's probably best to code it right
into your app, by using SSL calls throughout, rather than rely on an external tunnelling app...
Add a Comment
New Questions: RE: Adding packet handler for
socket
From: Harshad
Other than using dev_add_packet to add packet handler for a packet type is there any other way
to do the same thing ?
Trying to install my code handler to do some pre-processing before passing packets to IPv4
handler.
Any help appreciated.
Thanx.
Add a Comment
New Questions: Select hangs randomly
From: David Mack
I have an application that will periodically hang on the select statement for no apparent reason.
It works great and then every once in a while it will just hang.
This is a server application that uses forks to handle the incoming connections. Any ideas can
be emailed to me.
I have checked the file descriptors are being zeroed out each time but it hangs. This is a proxy
server by the way
From: cma
me too.... mine uses select() for the tcp socket and rpcs for other calls, and it just hangs after
about 1 hour.... used truss, but still cant tell exactly whats happening
From: Loco
Post code!!!!
Add a Comment
New Questions: tcp server
From: Tom Thorpe
hi. i have used SO_REUSEADDR to bind more than one socket to a port. my problem is now
using select to get incoming connection requests on them - no matter how many clients try to
connect, select only returns 1. a look at netstat shows that the sockets are being opened
correctly. help ?
Add a Comment
New Questions: non blocking connect with
select
From: ornaz
Add a Comment
New Questions: socketing data loss between
Unix and Windows
From: John R. C.
Folks,
I have an application which is running under Windows and another application running under
UNIX that are connected via a socket. The Windows application is the server and the UNIX
application is the client. When I send data thru the socket, from Windows to UNIX, data is lost.
Everything seems fine for a short time (a few hundred characters) and then data begins to get
lost.
The most probably reason for such a problem is that your program doesn't
verify values returned by send/recv/write/read functions.
These calls may transmitt less bytes that requested by your program.
So the command
rc = send( sock, buffer, sizeof( buffer ), 0 );
may actually send less bytes that sizeof( buffer ), even on blocking
socket. The count of actually transmitted bytes will be returned as
a function value.
This is normal behavior, it's not the error. You program must verify
values returned by send/receive calls and call these functions again
if required.
--
Wishes, Pzz
From: Raul Sanchez
Hi, friends
I'm Raul from Ecuador, I'm working in a university project and I read about conexion between
windows and linux by a sockest, wher I could get programs, source code or something about it!
Tanks
Add a Comment
New Questions: SCO -> DOS Communication
via socket
From: Edmund Schurnik
For the first - please excuse my bad english, i hope, you understand whats my problem:
I have a P166-Server with SCO Unix and some DOS-Terminals (Siemens ES235). The
Siemens-Terminals are connectet via TCP/IP to the Unix-Server. All works correctly.
Now i take a new Server (HP-E800 Pentium III 866). Now the socket-server says "read 0 byte"
and the communicaten to the Siemens-Terminals failed. The software for the socket-server is
been recompiled on the new server, but it dosn't work.
The network-parameters are all the same like the old server, i can "ping" the siemens terminals
without errors.
At two times - i don't know why - the connection was ok, i can send data from terminal to the
server, i receive answers from the server. The next login failed.
Can there be some timing-problems with the new, fast PIII-866 Server ????
I hope, somebody can help me ! It's very, very urgent !!!!!
Add a Comment
New Questions: Meaning of UDP "connection"
From: Sanjay
I have another question: When I "connect" a UDP socket to a remote addr and port, is there a
corresponding "accept" at the other end for my "connect" to go through? I know that when a
TCP socket is connected, the connection happens when the server "accept"s the connection.
What is the equivalent thing for UDP sockets?
From: Hironimo
You can call connect on a UDP socket if you want to. If you
connect () a UDP socket, then you can read/write to it using
send/recv instead of sendto/recvfrom. There is no corrosponding
accept on the other side. All the connect () really does
is tell the kernel that from now on, when you send data
using this socket, it should go to that particular address.
This is supposed to enhance performance as well, but I'm not
sure if that's still the case now, or if it was only true
back when Stevens wrote the networking bible.
Add a Comment
New Questions: How to delete a route using
API calls
From: reena
I want to delete route between two machines on a network using socket programming & WIN
API calls.It is posible to delete it manually.But i want to create an application which does this
task as soon as i switch on the machine.
From:
Add a Comment
New Questions: select() on blocking
environment
From: datawar
Code:
while(1){
FD_ZERO(&rs);
FD_SET(sock, &rs);
/* add all sockets to the read set */
for(n=0;n<=i;n++)
FD_SET(hostl[n].rsock, &rs);
to.tv_sec = 0;
to.tv_usec = 100;
sel = select(FD_SETSIZE+1, &rs, NULL, NULL, &to);
switch(sel){
case 0:
printf("yo timeout\n");
fflush(stdout);
break;
case -1:
printf("yo error\n");
fflush(stdout);
break;
}
if(FD_ISSET(sock, &rs)){
if(i == MAX_CON) continue;
slen = sizeof(hostl[i].r);
hostl[i].sock = accept(sock, &hostl[i].r, &slen);
hostl[i].rsock = new_sock();
i++;
continue;
}
for(n=0;n<=i;n++){
if(FD_ISSET(hostl[n].rsock, &rs)){
printf("i got a msg\n", buf);
fflush(stdout);
}
}
}
From: Hector Lasso
Hi,
As every new connection creates and binds other sockets (and i don't see any accept() for
sockets different to the main socket, i assume it is telling you that you have not "accepted" any
of the connections to the other sockets...
From: datawar
Add a Comment
New Questions: Where can I download QT
v2.2.2
From: Jack
Add a Comment
New Questions: how to write optimal
performance TCP server
From: Mahafuz
1. I can fork() server process and have one process server one command.
After serving the request the child ends.
or
2. I can create a thread to server the client request from server
process. After serving the request the thread ends.
Hi,
Apache does something like this (which is, i think, a very good approach):
The server process creates a socket, binds it, and then executes "listen()".
After doing this, it forks as many children as the configuration file tells it to. And waits on a
infinite loop for events such as a dead child, or not enough servers available, the parent process
will never serve the clients.
Every child inherits the socket, so every one "accept()s" on the socket (one at a time using a
lock file to serialize) . As soon as a connection is available, the process that accept'ed it serves
the client through the connection. When the task is done, the process closes the peer socket (not
the one created by the parent process) and returns to the loop where it will (eventually) accept
another connection.
While the process is serving a connection, it won't accept any other, however, the other
processes will be there to receive the connections.
Every children has a counter or something similar, and will die after a fixed number of
connections (which can be configured through httpd.conf or similar).
If you need more information see www.apache.org. It has a lot of information regarding their
decision to use preforked processes.
Best regards
From: Mahafuz
I'm not positive what Apache does, either... Your best bet would
be to just download the source code and look at what it does... (That's
available from "www.apache.org", among other places...)
I believe that Apache can be built to either fork a child process to process an HTTP request or
create a thread to do so. As I understand it, the architecture is kept flexible because threads are a
relatively new addition to Unices, and not all versions support eg. the POSIX model, while
fork() is very old and is universally portable. I don't dispute that spinning off a new thread for
each accepted connection is faster than forking a new child - even on Linux - but the
significance of this really depends on what the server serves up to its clients. A (traditional)
HTTP server closes its connection as soon as it has fulfilled the client's request to be sent a
page, hence the business of establishing the connection takes up a considerable part of the total
time to process a request. But with a different kind of server, eg. one serving up long-lasting
TELNET connections (I'm thinking of MTREK :), the overhead of establishing the connection
is miniscule in comparison to the total time that the client is connected. In this case, it seems to
me, a traditional forking server is much more attractive.
Add a Comment
New Questions: Client and Servers.
From: Aman
Hi,
I want to have a server that listens at a port X for some connection from a client. Once the client
is connected this server should start another server that talks with this client at yet another port
Y.
Aman.
Add a Comment
New Questions: SOCKETS AND IMAP SERVER
From: Marty
Hi,
I have a problem. I have a client program connecting to an IMAP server on port 143. I can
log-on to the server but cannot send anything thereafter. In fact, once connected any SEND or
RECV still has the original response from the connect command in the buffer of the RECV
command. Very Strange!!! Can anyone help.
Thanks
Marty
Add a Comment
New Questions: client/server to check a file in
a dir
From: Tomaz
Hi.. i am trying to write a client and server program,in which i want to check if a file exists in a
directory,if it exists it returns ok,if not returns an error.can somebody help me how to start
writing this program thanks in advance.
From: datawar
Server
------
bind a socket to a port and start listening, then u can
detect the msg file with a recv() call from the client
and do a stat() on the dir requested (use chdir() for that).
stat() will do the work for you.
Client
------
Connect to the server on the listening port and just
send the filename with send() the server will detect
and send you back a reply, u can use select() to check
if the server responds.
--datawar
Add a Comment
New Questions: recv() - the delay between
recv()s
From: Erik Mattsson
0.1 secs are a way to long time when sending messages between
localhosts. Why is there the 0.1 secs delay sometimes, and
is there ANY way of removing it ? (kernel/etc?)
Testoutput:
As you can see sometimes it doesnt fill the buffer (row 2), and
another recv() must be called. (there is no problem with
the send() ). You can also see the delay in the third recv()
BUT since the message is sent in the same thread, then it should
not be any problem of recv() a full buffer. Any idea why ?
Receiving. Size to read : 1024 Actual read size :1024 Total size read :1024 Total size :2833
time=2.5e-05
Receiving. Size to read : 1024 Actual read size :436 Total size read :1460 Total size :2833
time=3.7e-05
Receiving. Size to read : 1024 Actual read size :1024 Total size read :2484 Total size :2833
time=0.098295
Receiving. Size to read : 349 Actual read size :349 Total size read :2833 Total size :2833
time=8.2e-05
Code:
::recv(m_socket, (char *) buf, size, 0);
Add a Comment
New Questions: OOB msgs
From: datawar
Thanks
From: datawar
Add a Comment
New Questions: timeout on send with
SO_SNDTIMEO??
From: ornaz
From: ornaz
Hello,
Add a Comment
New Questions: CLOSE_WAIT Error
From: Yogesh Malik
Hi,
i have a problem.
I have a nshttps server listening at port 80...it works fine until at some point of time sudennly all
the port starts to go into CLOSE_WAIT state and with time number of ports in CLOSE_WAIT
state increase until i recycle the server process...can anyone giv me clue tothis problem execpt
recycling the server process
thanks
YM
From: Wen Hu
Add a Comment
New Questions: SO_RCVTIMEO question
From: ornaz
tnx
Orna
Add a Comment
New Questions: Why does Apache only accept
a message after the socket closes?
From: Donncha
Hi there,
I am a complete newbie to sockets although questios on this site and other have helped me
along a lot. My task is to run a CGI script on a remote computer from a C++ program. Normally
the CGI is run from a webpage, but I need to interface directly (it's part of the product I'm
working on). So, my plan is to connect to the webserver port, and send a HTTP request to the
script (GET or POST operation) to run it with the appropriate data. I'm testing my program with
a plain Apache webserver, but it seems as though Apache only processes the message after the
socket is closed (by which time the client has timed out). Is this how webservers usually work
(I've tried my client with a simple example server and it works fine, not timing out, server
processes message and replies immediately) or is there something wrong with my socket:
sock = socket(AF_INET, SOCK_STREAM, 0);
Aaargh!
I can't believe how stupid my mistake was!
Here's my command line for running the little client program (it's trying to download my home
page from the machine called selma)
Spot what's wrong with the GET command - it's not followed by two line feeds/carriage returns!
Needless to say, you just leave out the last quote, hit <return> three or four times, the put in the
last quote (you're basically adding the LFs by hand) and then it works fine, spitting back the raw
HTML page.
Anyway, that's sorted that out, I'll just put this here in case any other struggling socket
programmers run into the same thing!
Add a Comment
New Questions: How can I Receive or Deal
with Out-of-Band Data
From: Krish
1)SIGURG
2)select
3)look the stream for the OOB mark
Add a Comment
New Questions: SIGURG & OOB problem ?
From: datawar
Add a Comment
New Questions: SIGURG & OOB problem ?
From: datawar
Hi,
I've worked with OOB data in X.25 domain sockets, but only with one socket per process...
I suggest you try the following:
1) Place the sockets in non-blocking mode
2) When the SIGURG signal is caught, use the recv() function with MSG_OOB and check to
see if the return value is not -1... I guess if there is no OOB data the recv() would return -1 and
errno would be set to EAGAIN or EWOULDBLOCK...
Good luck
From: datawar
Thanks,
DatawaR
Add a Comment
New Questions: Broadcast and receive DHCP
messages
From: Zhang Wei
I am a beginner of socket programming. I want to write a "partial" DHCP code so that I can
broadcast a DHCPDISCOVER and receive a DHCPOFFER message because I want to extract
information from the DHCPOFFER message. I know that DHCP works on UDP and it must be
able to broadcast and receive messages even without an IP. That's where I encounter problems.
I tried writing a code using a normal UDP socket. Although it can send("sendto") a broadcast
message when the interface has an IP, it cannot send messages without an IP, and it can never
receive("recvfrom") the message from DHCP server. (I think it's because the message is not
sent to the address of my interface that is bound by the kernel)
I just want to have some idea of how I can send a broadcast message(with port number
specified, e.g. 67) even without an IP, and how I can receive a reply that is directed to my
hardware address? Shall I use raw socket? Or datalink access? Can someone just give me some
idea of what is the right thing to do? I work on Linux. Thank!
From: Nils O. Selåsdal
I suggest you get the source code for an existing dhcp
client and look. Source code for e.g. pump is pretty small
and you should find it at www.freshmeat.net or www.rpmfind.net.
Add a Comment
New Questions: What is Meant By RFCxxxx ?
From: S.Murali Krishna
RFC = Request For Comments... They are just documents written up by various people,
describing certain Internet standards/protocols/etc... They are generally looked upon as the
definitive guides to how things should officially be done... You can find all of them online
many places... Faqs.org has a good RFC section... The IETF is probably the most official
source... But, you can find them all over the place...
From: I gwana
porn
Add a Comment
New Questions: How we can Get Mails From
Servers Using Sockets.
From: S.Murali Krishna
Add a Comment
New Questions: How we can Get Mails From
Servers Using Sockets.
From: S.Murali Krishna
With mail server IP address and Port you can send/recive mail. Thats how its done.
Pls see RFCs for these protocols and you'll know what to do.
Add a Comment
New Questions: Can someone answer to that
??!!
From: ornaz
tnx
Orna
From: Mahafuz
As far as i understood,
according to richard Stevens book - "Unix Network Programming" the socket option
SO_RECVTIMEO &
SO_SNDTIMEO are meaningless. I mean they don't
do anything ( "don't currently affects timers" ).
Is this true??
Hi,
The timeouts affected by these two options "... are fixed to a protocol specific setting in Linux
and cannot be read or written. ..." according to the man page in Linux.
Add a Comment
New Questions: select statement times out
when there is data
From: David Mack
I have a program that for proxy program that for some reason will timeout. I am using
FD_ISSET to check the file descriptors to see which ones have data and I expect them to have
data but the timeout still happens on the select. It's almost like it's stalled for some reason.
Any help is appreciated.
From: Hector
Maybe you need to check the first parameter in select, it should be the highest number of all file
descriptors in every fd_sets.
Add a Comment
New Questions: sending File Descriptors
across Unix Sockets
From: Andy Bitton
I am trying to send an open file descriptor from one process to another over a Unix domain
socket.
The problem is that the sendmsg call fails with a EBADF error even though the socket will send
and receive data before and after the call.
Any ideas ??
Add a Comment
New Questions: Server servicing multiple
sockets (ports)
From: Dave Zavetz
I am writing an application in which a single server needs to service 5 different sockets. Here's
the catch - each socket must reside on it's own unique port. I'm sure that select() is involved
somehow or other but could someone give me a clue on how to get started.
Also, to further complicate matters, the server (perhaps via a 2nd application) needs to monitor
a 6th socket (port) for SNMP (UDP) traffic.
Dave
From: Hector Lasso
Hello,
I think you need to create 5 different sockets, bind each one to a different port and then listen on
every one of them using "select()" to know which one is receiving a new connection (the file
descriptor is set in readfds).
I still don't know why you need 5 different ports as one port can do the trick -> accept 5
connections on the same port.
Best regards
Add a Comment
New Questions: How to use "errorfds
From: Mark Johnson
Add a Comment
New Questions: How to use "errorfds
From: Mark Johnson
Add a Comment
New Questions: How to use "errorfds" in
select()
From: Mark Johnson
fd_set read;
FD_ZERO(&read);
fd_set errorfds;
FD_ZERO( &errorfds );
memcpy( &errorfds, &read, sizeof(fd_set) );
//
// i assume that select will modify the appropriate
// entries in "errorfds" to reflect pending error
//
int rv = select( nfds, &read, NULL, &errords, NULL );
if( rv == -1 )
{
switch( errno )
{
case EBADF:
// find the culprit
for( int i = 0; i < nfds; ++i )
{
int flag = FD_ISSET(SdList[i], &errorfds);
if( flag )
{
FD_CLR( SdList[i], read );
// clean up SdList and bad sd...
}
}
break;
default:
// etc..
}
}
Hi,
Good luck
From: Rob Seace
But, if you have the extra source fd_set, that serves the
same function as having them in an array... That's all I
was saying: you can make your life simpler, and save some
overhead, by replacing the array of FDs with just another
fd_set... Then, it's ready for easy memcpy()'ing into the
fd_sets you want to pass to select(), AND you can still do
any checking of it that you want to, to see which FDs from
0 to "nfds" are currently in use... My point was you don't
want to be treating "i" in the above loop as an array index,
but rather as a file descriptor, itself... (One which may
or may not actually be in use by you... But, if it's not in
use by you, FD_ISSET() won't return true, so you're all set
there...)
From: Hector Lasso
Rob,
As far as I can understand, the error set is used for other reasons - exception handling. Dont ask
me what that is supposed to mean, but it is not going to tell you which fd is bad.
The only solution I have managed to come up with is to rip through all the fd's one by one using
select (with zero timeout) until I have got the one causing an error - usually it means the socket
has closed, so all you need to do is get rid of it. It works, but the method isn't very satisfactory.
Does anyone know the proper way of finding out the culprit??
fv.
From: Rob Seace
Add a Comment
New Questions: Select returns EBADF
From: Andra Fralin
I have a server that runs fine most of the time however sometimes it returns EBADF on a select
statement and I don't understand why. I have three file descriptors in one set and when I do
select every once in a while select will return a number < 0 and then errno will equal EBADF.
Any help is appreciated
From: Rob Seace
Is one of your FDs getting closed, but not removed from the
fd_set, maybe? It's difficult to guess what the problem
might be without seeing the code in question...
Add a Comment
New Questions: core dump on send/recv
From:
my application coredumps when sending/receiving data that exceeds the buffer size (definitely).
how can the client/server receive/send indefinite amount of data through send()/recv(). need
source code.
From: Hector Lasso
Hi,
You will have to use a buffer large enough to hold the data, or you will have to receive the data
your buffer can hold, move it to another location/process the data and continue receiving in the
same buffer.
do {
// Be sure you have data to read, or else the function
// will block until data becomes available
// Use select() for example
r = recv(soc, buffer, buffer_capacity, 0);
if (r > 0) {
// Received r bytes, do soething with them
do_something_with_the_data(buffer, r);
}
else if (r < 0) {
// Error
do_error_handling();
}
else {
// Your socket has been closed...
shutdown(soc,2);
close(soc);
}
} while (1);
From:
thanks hector, i am now done with the sending part. but what if the receiver side does not know
the capacity of the buffer. initially i set the buffer_size to 1024 (for the receiving side). but the
sender sends more than 1024 and the receiver definitely will get only 1024. how can i the
receive receive all the data coming from the sender?
From: Rob Seace
This same basic question is addressed in the main FAQ: question 3.8...
Add a Comment
New Questions: socket programming
From: Mathin
How can we transfer data from winsock application to unix by C/C++ socket programming? Is
there software about it? Please suggest me.
Add a Comment
New Questions: transfer data from winsock to
unix by C/C++ socket programming
From: Mathin
How can we transfer data from winsock application to unix by C/C++ socket programming? Is
there software about it? Please suggest me.
From: Hector Lasso
Programming with Winsock is very much like programming sockets under C for Unix.
Anyway, both sides can communicate regardless of the interface used to program, what is
important is that they use the same protocol, and that data is exchanged in a consistent format.
Add a Comment
New Questions: NT Socket to Unix
From: Amit
Hello:
I have A client program in C++ written using Winsock and I need to port this to UNIX. Can
anybody help me in telling me whats the way to do . I dont have any unix idea. The client in NT
is a simple V c++ program.
From: Hector Lasso
Add a Comment
New Questions: pthread_join
From: Arul Ananad
Hi,
my doubts is,
can i join to the same thread ( pthread_t ) more than one time.
bye
Arul
From: Someone
pthread_join() suspends the calling thread until the thread identified by the first parameter
terminates (either by calling pthread_exit or by being cancelled) That means that if you run
again pthread_join() using the same first parameter it will fail and the error will be ESRCH,
unless you have created another thread that uses the same thread identifier (is it possible?)
You can call pthread_join() many times from the same thread joining different threads
Add a Comment
New Questions: sending binary file from a
windows client to a unix server
From: Aleksey
Hi
Windows client sends a message to tell the server it wants to transmit a file (including file size
and desired name), and then immediately dumps the entire file to the socket.
The problem is, whenever header+file size is over 4k (receive buffer size on the server), after
reading the first buffer-full of data, select gets confused and says there is no more. But, when I
do netstat, I can see that there is data in the Recv-Q on that port, and if file is big enough, I can
see even see Recv-Q grow over the default 4k.
Should I force the client send the file in smaller chunks and have it wait for an ACK message
from the server before sending more?
From: Rob Seace
FD_ZERO(&ReadSockSet);
FD_SET(m_nSock,&ReadSockSet);
result=select(m_nSock+1, &ReadSockSet, NULL, NULL, &tv);
if (result == 0)
printf("Timeout\n");
else if (result == -1)
perror("select error\n");
else
{
// perform read
}
From: Rob Seace
After windows client dumps the whole file to the socket, select successfully detects something
has arrived, and the first 4k is read, all successive calls to select return 0 (timeout).
tv is initialized to 0,500000 (.5 sec) and is reset before every call to select (though as far as I'm
aware SCO UNIX doesn't modify the value of tv).
Perhaps the error is not in the select call but in how sockets work in the OS.
From: Hector Lasso
Do you reset the ReadSocketSet struct in the loop before calling select()?
If you are doing two writes in one end of socket that doesn't mean that there will be two read in
other end.
TCP/IP send data by its own buffer size (fragmentation/ defragmentation occurs).
My suggestion is, after first read from socket you know the amount of data read and from the
file size sent from client side, you can easily calculate the rest amount of data. Just normally
read again from the socket buffer by buffer until you get the rest amount of data. Its a simle &
stright recv(...)/read(...) loop. Pls don't go for select again.
From: Aleksey
I'm not sure where you got that information from. Both the select() man page on my system,
and Steven's book on network programming say select() returns the total number of ready
descriptors in all sets, 0 for timeout, or -1 for error.
If this really is the case, it would indeed explain why the problem is occurring, but this leaves
me with another problem. I'm stuck with a blocking socket and can't do blind reads.
From: Mahafuz
I don't think what i said contradicts/disagrees with man pages of select(...). Select is associated
with the concept of asynchronous i/o. It helps you to get evevts instead of blocking polling.
Anyway, refering to your problem what i can suggested that,
whenever you get read event in select(..) you should start a thread/fork the process to go on
reading incoming data. The main process again goes to select(...). This way your reading is not
blocked and you can serve may clients at the same time.
From: Mahafuz
I don't think what i said contradicts/disagrees with man pages of select(...). Select is associated
with the concept of asynchronous i/o. It helps you to get evevts instead of blocking polling.
Anyway, refering to your problem what i can suggested that,
whenever you get read event in select(..) you should start a thread/fork the process to go on
reading incoming data. The main process again goes to select(...). This way your reading is not
blocked and you can serve may clientÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
From: Rob Seace
Add a Comment
New Questions: using socket to connect : a
client to a server and a client to another client
?
From: Floriane
I would like to know if it is possible to have 2 clients, connected thanks to sockets to the same
server, open a socket with each other, so that they don't pass through the server anymore?
And if yes, how can I do that ?
Thanks !
From: Hector Lasso
Both clients connect to the same server. One of the clients sends through the server a message
to the other client telling it its address, and probably a port where it will be listening. The
second client connects to the address and port given, and the communication between both
clients continues without the server.
Add a Comment
New Questions: Send a file and struct
From: Luca
And a Structure?
From: Hector Lasso
To send a file through a socket you could just read the file and send it through the socket using
write()/send(). However, you should tell the receiving program something about the file, for
example file size, in order for the receiver to know how many bytes coming from the socket it
should expect.
To send structs is a little bit trickier. If you are using the same platform in both ends you just
cast your struct to char*:
You can find more details in the main FAQ: Question 2.15
Add a Comment
New Questions: configure tcpip/ppp using unix
interprise 5.05 sco
From: BRYANT BORDERS
Add a Comment
New Questions: Determining MAC from IP
w/ARP
From: Todd
I'm on a UnixWare 7.1 platform. I need to look up a MAC address in the ARP cache from a
known IP address. I foudn the following example source but it does not work. What am I doing
wrong?
#include <stdlib.h>
#include <stdio.h>
#include <sys/sockio.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
if(argc!=2) {
printf("usage: %s <IP address>\n",argv[0]);
exit(0);
}
sin.sin_family = AF_INET;
if(inet_aton(argv[1], &sin.sin_addr)==0) {
printf("%s: IP address '%s' not valid\n",argv[0],argv[1]);
exit(0);
}
/*strcpy(myarp.arp_dev, "eth0");*/
errno = 0;
if (ioctl(sockfd, SIOCGARP, &myarp) == -1) {
printf("%s: no entry in arp_cache for '%s', errno = %d\n",argv[0],argv[1],
errno);
exit(0);
}
ptr = &myarp.arp_ha.sa_data[0];
printf("%s: MAC address for '%s' is : ",argv[0],argv[1]);
printf("%x:%x:%x:%x:%x:%x\n",*ptr, *(ptr+1),*(ptr+2),
*(ptr+3),*(ptr+4),*(ptr+5));
return 1;
}
From: Todd
I found the problem. The example code was using a socket's file descriptor, which would work
on a connected socket. For my purposes I had to open /dev/arp and use that file descriptor.
Add a Comment
New Questions: Sockets Intialization Failed!
From: Richie
Out of the blue my computer tells me that "Sockets initialization Failed!" when i try to run an
internet related application, eg IE5 or ICQ. I can connect to my ISP fine but thats as far as
things go!
HELP ME!!
please reply.
From: Rob Seace
Add a Comment
New Questions: Anonymous FTP
From: Johannes Herseni
You should read the documentation that comes with your FTP server.
Add a Comment
New Questions: Problem with socket-timeout
From: Carsten Schaudel
Hello together !
I have the following problem:
When I establish an TCP-Connection (in my case client and server are running on the same PC)
the connection seems to have an timeout if I don't transmit cyclic data in both directions.
Suddenly (after about 30 Min) I get an error ETIMEOUT on the client when I try to receive
data. Just before this error it was no problem to send data from the server to the client.
From: Aleksey
Hi !
I allready tried setting SO_KEEPALIVE, but that hasn't changed anything regarding this
problem.
Add a Comment
New Questions: Which langage is better for
network programming ?
From: Francky
Hello,
I am a beginner in network programming and I have
read the Stevens Book called 'Unix Network Programming' and
many others too, I also have the source code of a game
server, and it looks like everybody use C for server coding,
so I would like to know if there is a difference between
a C coded server and a C++ coded server (performance,...)
All the reference books are using C instead of C++, maybe
there is a good reason for that.
I need to design a server with a huge number of connected
clients (3000 at the same time) so should I be using C or
C++ knowing that my server will be an online game server.
So the server will also have to create the behaviour of
some monsters using Artificial intelligence algorithm,
the problem with C is that we can't use the STL library for
example (am i right ?)
or an AI library, what could you suggest me ?
Thanks in advance.
From: Rob Seace
Add a Comment
New Questions: server
From: sohail
hello,
i got this small querry.
i have a unix server.i have a small html file n my server which is a form template for submitting
a particular form.
now,i usually access this html from my browser.
my problem is that my isp speed is very slow in india so it take lots of time to surf from my
browser.
is it possible for me to access the html file from my server itself[without the need of my ISP
speed].
i tried using telnet and lynx to access the file but eventually the ISP comes in the picture .
I need to submit this form every 5 minutes for 1 hr per week.is there any script which works
from the server itself and sends the form from the server-without the isp .
Please help.
Regards
SOhail
Add a Comment
New Questions: I need to send 0x00 0x00 0x00
0x1 ?
From: julio
I need to send 0x00 0x00 0x00 0x1 but the write or send does not work it send none how can I
do it.
msg[0]=0x00;
msg[0]=0x00;
msg[0]=0x00;
msg[0]=0x1;
n= wriet(my_socket,msg,4); or n send(my_socket,msg,4,0);
printf("%i",n);
>>> this print 0
julio.
Australia
From: Wes
{
int data;
data = ntohl(1);
write(fd, &data, sizeof(data));
}
Add a Comment
New Questions: Broken Pipe
From: julio
But, basically, it probably means the other end of the socket has been closed... I recommend
always ignoring SIGPIPE, then you can just check for EPIPE on write() failures, if you need
to...
From: Baskar K
This normally means that you were performing a data transfer on a socket connection
and the socket connection is broken during the transfer.This
might have happened when your process is killed or some network
interruption problems.
You can normally ignore SIGPIPE and check for the return value of recv and send
socket calls.
Add a Comment
New Questions: Open a session
From: Luca
I have to write a prog that connect to a host and do a log on it with login a pwd.
Add a Comment
New Questions: Can i Read more than a
PAGESIZE in a single read call......
From: Arul
Hi,
Add a Comment
New Questions: kick off Unix process from
Windows 2000/NT
From: Utpal
I am need to write a C function which will kick off a unix batch process. I want to include that
function in a win32 DLL. Would you please suggest how can I accomplish that?
From: schang
NT:
- use winsock on NT in your application, then establish connection to tcp listener on Unix,
- send batchid and other parameters via tcp socket connection
- wait for the confirmation from Unix server
- close socket
- check your job run schedules from database
Unix:
in child process:
Add a Comment
New Questions: Why my recv is too slow?
From: Mok
Hi:
Here is my recv function, i notice my receiving procecess is take
long time to download a file (from UNIX server) which 1/2M in size.
It this any problem in my coding. Can u tell me, the receiving speed
is depend on what factor beside the network/modem speed???
Thank U
if (soc == INVALID_SOCKET)
{
return 0;
}
nTry =0;
nRet =0;
while (nTry < 100)
{
err =recv(soc,(char FAR *)cstr,256,0);
if (err == SOCKET_ERROR)
{
err = WSAGetLastError();
if (err == WSAEWOULDBLOCK)
{
nTry++; // no data
nRet = 2;
Sleep(30);
}else
{
nTry=10; //exit lloop
nRet =1;
}
}
else
{
nTry=10;
nRet =3;
Tmp =cstr;
strcpy(cData,Tmp.Mid(0,err));
}
}
return nRet; // have data
}
From: johnny
I noticed in your recv statement, you have a 256 byte block size. Change this (and your buffer)
to the max, which on most systems is around 8K (8192). This should improve your speed
considerably.
Add a Comment
New Questions: select loop..
From: Dan
I've encountered an odd little happening in my code which loops (to all intents and purposes)
forever, polling a sockset alternately for read and write..
The code works fine if it finds something it can read from everytime (forget the writing bit for
the moment), but the first time it times out and fails to read anything from the socket, it
sobotages its ability to ever read anything again! From that point onwards, it doesn't seem to
actually be polling the set properly, and just returns 0, whether there is stuff to be read or not..
Hope sum1 can cast some kind of light on this, as it would be much appreciated..
From: Dan
I've made a slight alteration which makes it (kinda) work.. I've simply cleared the sockset and
reinitialised it inside the loop.. like I say, it works, but surely there's a better way of doing it? I
must be using select wrong somehow?
From: Wes
When select() returns, it clears the fds that it says there is data for. You need to (at the very
least) re-insert the fd back into the fd_set with the FD_SET macro.
It may be possible to make a copy of the fd_set, and re-initialize from the copy (when selecting
over a hard-to-get fd_set), but I am not sure if this technique is portable, as it relies on the
internal representation of the fd_set as being a bit field, and not (say) an array of int *s or
something.
From: Dan
ok, thanx 4 the help :) I only have 1 socket in the fd_set so it isn't much of a problem!
From: Hector Lasso
Hi,
Whenever select() returns, the file descriptors are cleared from the sets if they are not ready for
the corresponding operation...
Also, the timeout value should be reset before calling select() again...
FD_SET(socket_descriptor, &rset);
// Add other descriptors if any
do {
memcpy(&rsettmp, &rset, sizeof(rset));
select(maxfd, &rsettmp, NULL, NULL, NULL); // No timeout
// Process results here...
} while (some_flag);
From: Dan
An example implementation I saw out there on the net. Maybe this can help?
--Begin:
/*
* do_select() - based on select_loop() from the Harvest Broker.
* -- Courtesy: Darren Hardy, [email protected]
*/
int do_select(sock, sec)
int sock; /* the socket to wait for */
int sec; /* the number of seconds to wait */
{
struct timeval to;
fd_set qready;
int err;
FD_ZERO(&qready);
FD_SET(sock, &qready);
to.tv_sec = sec;
to.tv_usec = 0;
if ((err = select(sock + 1, &qready, NULL, NULL, &to)) < 0) {
if (errno == EINTR)
return 0;
perror("select");
return -1;
}
if (err == 0)
return 0;
--End
From: Stephen Silvey
Another little tip, from the same example code (just in case, but this is pretty old):
--Begin:
void reinitialize(s)
int s;
{
/* To force main-while loop call reinitialize_server() after do_select() */
glimpse_reinitialize = 1;
#ifdef __svr4__
/* Solaris 2.3 insists that you reset the signal handler */
(void)signal(s, reinitialize);
#endif
}
--End
From: Wes
Hector said: "Also, the timeout value should be reset before calling select() again..."
This is an absolute must when trying to write portable code. On some platforms (BSD comes to
mind), select() will change the struct timeval to indicate the amount of time left in the timeout
when select returned.
Add a Comment
New Questions: udp port reuse
From: LI Jiang
But I can listen on the same udp port P using the following tcpdump command:
I would like to hnow how to bind and then listen on a udp port P, while
there is another active socket on the same port.
LI Jiang
From: Wes
I seem to remember something about using SO_REUSEPORT in this context when reading
Stevens: UNPv1. You may wish to investigate that.
Add a Comment
New Questions: sockets
From: noniesha
why do we need unix sockets when the internet sockets can provide us with the same
functionality as unix sockets ?
plus i want to ask that how do we use unix socekts on a LAN
From: Premjee K. Abraham
Sir,
I had a problem of connecting to FTP port (21) of a Unix system from a windows NT machine
using java Socket programming. I created a socket with the Unix Machines IP address and port
no 21. But i am not able to login to the Unix system since the password i wrote to the socket
output stream is not taking. Please tell me how to get a file from a unix machine to a Windows
machine using Sockets. ?...
Add a Comment
New Questions: socket send timeout
From: stefano
Dear All,
I have a server socket connected via lan bnc to client one. The
protocol is tcp and i used a realtime OS supports TCP.
If i disconnect the lan between the machine or one machine reboots itself,
the send() on sockets doesn't fail (it will fail after 11 minutes).
For me it is too long time, is there any possibilities (setsockopt or ioctl)
to change this timeout ?.
thanks
Stefano
From: Rob Seace
This is covered in the main FAQ in question 2.8... Basically, the keepalive timeout is usually
configured SOMEHOW, but how is not standardized at all, and it's generally only on a
system-wide basis, not a per-connection basis... I can tell you how to set it on Linux
("/proc/sys/net/ipv4/tcp_keepalive_*"), and I have a rough idea of how you'd do it on QNX
(they seem to have a per-connection "TCP_KEEPALIVE" sockopt, which sets SOME value
related to it, but, I'm not sure if it's the initial timeout, or just the time between successive
probes), but anything other than that, I have no idea... It's a very system-specific setting, I'm
afraid... (I really wish someone would standardize all these little differences, like this...)
From: Rob Seace
D'oh! The dangers of cut-and-paste rear its head... ;-) That's obviously not the correct URL...
(Though, it is the URL for downloading a very cool book... ;-)) What I meant was: question
2.8...
Add a Comment
New Questions: byte order of data received
From: Chad
We are trying to create client/server environment between BSD 4.1 and a Tandem machine. The
data going back and forth seem to be byte swapped. Is there a socket flag/option that takes care
of this for us or do we need to write our own?
From: Stephen Silvey
I'm unclear if this will work on IPv4, but its worth looking
into.
http://beta.ttt.bme.hu/info/libc.info.Byte_Order.html
Good luck.
Add a Comment
New Questions: Searching For: Inline "Hex to
Decimal" conversion routine - to be used
during execution of Socket Datagram Program
From: Stephen Silvey
--Stephen Silvey--
(re: [email protected])
From: Rob Seace
Add a Comment
New Questions: How to determine which IP
client is calling?
From: Tomek
Hello.
I have got a server with two IP addresses assigned to it, and a programm that creates a socket on
a specific port.
Clients that connect to this port are divided into two groups, each group use different IP, but the
same port number to connect.
Having accepted the connection, how to determine which of my two IPs the client used to
connect to my server?
From: Satya Prakash Prasad
Add a Comment
New Questions: How to reconnect a TCP
socket?
From: Ched
In order to minimize the number of socket creations in my client app (which has to send TCP
requests to many different servers), I would like to reuse my existing sockets.
- Is it worth to do it? I mean, does a call to socket() cost a lot?
- To reuse my socket, I call shutdown(read&write) on my TCP socket and then I try to connect
it to another destination.
- Unfortunately, I've got an error "EISCONN". How can I fix this?
Thanks a lot for your help.
From: Rob Seace
Add a Comment
New Questions: Ada Language Unix-based
"Datagram Link Program" Type Error When
Porting To And Recompiling On A Linux
Machine
From: Stephen Silvey
Add a Comment
New Questions: call to write blocks forever
From: Franck
Hello,
my server program, after working well during about 30 seconds
suddenly block forever in a call to write.
I used 'strace' to try to understand what's hapening. I call
write in a loop as follows :
(taken from Richard Stevens's book)
ptr = vptr;
nleft = n;
while( nleft >0 )
{
if( (nwritten = write(fd, ptr, nleft)) <=0 )
{
if( errno == EINTR)
{
nwritten = 0;
}
else
{
return(-1);
}
}
nleft -= nwritten;
ptr += nwritten;
}
return(n);
}
write(7, "4 0 5.5 99.6 288.33 147.5 669 15"..., 174) = 151
Thanks in advance
Add a Comment
New Questions: persistent connection to a
web server
From: Sener BALCI
/Sener
From: Hector Lasso
(two CRs)
Good luck
From: Ched
Add a Comment
New Questions: Windows / Unix Socket
Communication
From: Paul Murray
Sorry to be a learner, but I am only just getting into the world of sockets.
Although this FAQ has answered practically everything I needed to know about Unix sockets
(including references and sample code), I now need to obtain similar references to windows
sockets ....
Can anyone point me in the write direction for a good windows socket reference ???
Thanks in advance,
Paul.
From: Daniel Gustafson
You should have take a look at http://www.allapi.net/ which is a great listing of Windows API
calls. They have tutorials and examples on socket communications through Windows. Although
there are ActiveX controls to do the socket work for you in f.e VB, the Windows API will
perform better.
Add a Comment
New Questions: DANGER : big bug in Select()
!!
From: tybins
1) Which Stevens book? UNPv1 has code for pselect() on page 168, but it's certainly not a
complete example.
2) This is almost certainly a bug in your code. You're saying that your reading the data from the
wrong client. Select has nothing to do with what data you're reading.
3) Shorten your code to the smallest possible length to show the "bug", and post it for comment.
Wes
From: jos
i dont know about linux, but unix system v, select is a library call, not a kernel level call.
consequnetially it is not atomic in nature. that could be the cause of your problem, especially
since it looks like a race condition
Add a Comment
New Questions: Socket on Unix
From: Gurumurthy
>>nslookup
> www.nba.com
Server: remus.rutgers.edu
Address: 128.6.13.3
Name: nba.com
Address: 129.33.0.36
Aliases: www.nba.com
Add a Comment
New Questions: rebinding bound socket
From: Khubilai
I have an socket (UDP) that is bound to a specific port. What is the proper way to release the
bound port and bind the socket to another port?
From: Ched
I think the only way to do this is to close the socket and create it and bind it again.
If you try to rebind your socket you will get systematically an EINVAL error, meaning the
protocol stack does not support rebinding.
Add a Comment
New Questions: How can a process know its
hostname ?
From: Zulius
In trying to simulate FTP i faced this problem. In FTP whenever there is a tranafer of data
involved, the client creates another socket, exclusively for data trnsfer. Now the client sends its
IP address and the port number on which it wants a socket to listen, to the server. So my
question is how can the client get the IP address of the host on which it is running, without
passing any parameter ? The functions gethostname(), gethostbyname() dont work because they
already require the name of a host.
From: Rob Seace
But, I'm not sure what you mean by gethostname() requiring a hostname; it requires nothing,
and gives you the current host name, in the buffer you pass it...
However, if you only require an IP, you probably have a much simpler situation on your hands,
anyway... If you already have an established socket connection, you can easily find out the IP of
your end of it, by calling getsockname(), which will give you the full sockaddr_in struct that is
bound to your end of it, which will contain both your local IP and port#... It's the companion to
getpeername(), basically... And, that's probably all you really need...
From: God
ass
Add a Comment
New Questions: Sending info down sockets
From: bal
we have a set up within our public_html directory and have written a basic concurrent server.
Using socket coding what is the coding required to access such pages with netscape?
Add a Comment
New Questions: Sending info down sockets
From: bal
we have a set up within our public_html directory and have written a basic concurrent server.
Using socket coding what is the coding required to access such pages with netscape?
Add a Comment
New Questions: GET Protocol
From: scooby doo
how do u implement the GET Protocol into the below web server.
cheers
#include <unistd.h>
#include <iostream.h>
#include <cstddef>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>
#include <cstdlib>
#include <sys/time.h>
#include <sys/types.h>
if(argc != 2) {
cerr << "usage: server-prog port-num\n"; exit(1);
}
while (true) {
cliaddrlen = sizeof(struct sockaddr_in);
newsock=accept(sock,(struct sockaddr *) &cliaddr,&cliaddrlen);
if(newsock < 0) {
cerr << "server accept error\n"; exit(1);}
hostip = inet_ntoa(cliaddr.sin_addr);
cout << "server: connect from IP " << hostip << "\n";
gettimeofday(&now,0);
datestr = ctime(&now.tv_sec);
write(newsock,datestr,strlen(datestr)+1);
close(newsock);
close(sock);
}
pthread_detach(pthread_self());
rc = read(s,buffer,2048);
while(rc > 0) {
write(s,buffer,rc);
rc = read(s,buffer,2048);
}
if(rc < 0) { cerr << "read failed\n"; }
close(s);
return 0;
}
From: b
Add a Comment
New Questions: get multiple documents from
www server
From: dzhan
Add a Comment
New Questions: problems receiving UDP
Broadcast
From: Atenea
I am trying to receive packets (datagram) from a vxworks machine (can`t change machine
configuration) wich sends packets to a x.x.x.0 address. Recvfrom is blocked when trying to
receive those packets. What I have to do to solve this problem?.
Add a Comment
New Questions: To change, my IP address.
From: Andrés
Hello;
I want, to change my IP address, when I connect to the Web Server, but I don't kown.
From: Mahafuz
changes the ip address of your eth0 interface from the old one to the new ip address
XXX.XXX.XXX.XXX.
andres=gethostbyname((char *) "Lisa");
cout << "The name of the host is: " << andres->h_name << endl;
cout << "The IP is: " << inet_ntoa(*((struct in_addr*)andres->h_addr << endl;
Andres,
Add a Comment
New Questions: socket and rpc
From:
What are differences between socket and rpc?
Add a Comment
New Questions: What is "IDMaps" and how to
use it in indentifying the closest mirror site?
From: Xu,Zhong
Add a Comment
New Questions: fprintf error code
From: Jessy
May I please know what does error 47 means when fprintf is executed to write into a file from
buffer?
From: Hector Lasso
If you just need to know what the number in errno means use something like:
printff("The error was %d -> %s\n", errno, strerror(errno));
Add a Comment
New Questions: % sign in a file read by my
SOCKET server
From: Jessy
I need to know how to "escape" a "%" sign from a message being read by my socket server. Can
someone please help?
I'm in a desperate situation.
From: frankv
My guess is that you the % is being interpreted by printf or something becuase there should be
no need to escape the %.
char string[1024];
Other then that you need to be more specific about why this is a problem, because it doesn't
seem to be a socket issue.
Add a Comment
New Questions: socket 7 processor
From: maricel avena
#include "motherboard.h"
Add a Comment
New Questions: Need help in compilation
error2001
From: amadas
HI Everybody,
I knew this FAQ is for Unix enviroment but I need help in
windows to compile very simple creating socket program
I get it No error No Warnings to compile but when I link the
program I get:
winsock1.obj : error LNK2001: unresolved external symbol _socket@12
Debug/winsock1.exe : fatal error LNK1120: 1 unresolved externals
Error executing link.exe.
I appreciate your support.
My simple code :
#include <winsock.h>
SOCKET PASCAL FAR socket ( int af, int type, int protocol );
#define af PF_INET
#define type SOCK_STREAM
#define protocol 0
void main()
{
socket ( af, type, protocol );
}
Add a Comment
New Questions: Controlling an unexpected
socket close.
From: Daniel Gustafson
How do I detect these abnormal socket shutdowns and appropriately close the socket
on the server ?
From: Rob Seace
You're saying the client closes its end of the socket, yet
the server's read() does NOT return 0 to indicate EOF?? It
sure should, and I've never seen it NOT do so, except in
cases where the remote connection was not actually closed,
but rather the client just disappeared off the Net, so to
speak... (Eg: their machine crashed, or the route between
you and then went down, or something like that...) Then,
you get into SO_KEEPALIVE type issues... But, if the remote
connection truly was closed, then there's no reason I can
think of why your read() would not return 0... *shrug*
Add a Comment
New Questions: What is a Blocked socket ?
From: Mala Bankal
What is a 'blocked socket' and what is the differece between a 'blocked socket' and an
'unblocked socket' ?
From: ornaz
for example blocking send call does not return until the message
has been safetly stored away so the sender can freely reuse the sender
buffer buffer
OR
the recv blocking not return until the msg stored in the recive buffer
Add a Comment
New Questions: server/multiple clients
From: savi
Hi,
I am trying to write a server which handles requests from multiple clients at the same time. To
handle 1 client I used the fork() call. But now i dont know how to proceed, if it has to handle
several clients.
Any help in this regard will be very much appreciated.
Thanks,
savi
From: Hector Lasso
Hi,
There are different ways to serve many clients. Rob Seace makes a very good description of the
advantages and disadvantages of them in <A
HREF="http://www.lcg.org/sock-faq/detail.php3?id=428">Question 328</A>
You could use select() in one single process to serve all the clients, you could also fork() a child
for each connection, or create a thread for each connection.
As you have already worked with fork() i'll tell you how you can do it very easily:
1) I assume you've already bound the socket, and created a loop that looks something like this
...
do {
// ...
psocket = accept(ssocket, ...);
if (psocket > -1) {
create_child(psocket);
close(psocket); // Don't need this
}
// etc...
} while (some_very_interesting_condition);
...
Add a Comment
New Questions: Connection failures
From: Chris
Add a Comment
New Questions: Socket Programming
From: Sunil Philip
Hi,
Iam using Linux server and NT client.How will i receive the contents of the database from the
client using structures?
Not only that ,the server has to respond to multiple clients without using thread() or fork().
Add a Comment
New Questions: problem in client identification
by server
From: suneet chandok
if a two or more clients are connected to server, how can server differentiate rather identify
them to send messages
From: Satya
Once a client get connected to the server the server can easily detect what is the peer's IP
address and its socket handle.
Server can simply store the details in memory for further use.
Add a Comment
New Questions: Connecting a socket throw a
proxy with autentication
From: LFM
hi,
i'm developing a program that needs to connect a socket throw a proxy server.
best regards
Luís Meira
Add a Comment
New Questions: How to test if a server closed
my socket?
From: Mel Tan
But, you seem to indicate that these don't work for you?
If that's true, I can only assume the "SOCK_STREAM"
reference must have been a mistake, and you're really using
UDP, or something... In which case, there's no connection
at all, so of course no way to detect "closing" it, since
it was never "open" in the first place... If you're really
using TCP, and these things don't work, then I have to
assume either there's a problem with your code, or your OS's
TCP/IP implimentation is broken, somehow... It might help
if you posted the code that doesn't work... (Try to create
just a very simple client and server, purely to demonstrate
the concept of what you're doing, and show it not working...
That's much better than mere snippets from real code,
because matters don't get confused by irrelevent stuff in
the real code, and people can pull down the full trivial
code and try it on their own systems... PLUS, most of the
time you'll discover that the trivial code will work just
fine, which points to some other problem with your own code
which is causing the failure...)
From: Mel
First thing you should ask me if I am dreaming. Yes I am. So, it's AF_INET and
SOCK_STREAM. No UDP here.
So, the client has connected without a problem but the server just goes ahead and closes the
accepted connection. Now the client writes to the server but the write doesn't give any errors
that the other side of the connection is closed. The write is successful. If I do a read, it will
block. So obviously the file descriptor is valid even
though the connection is closed on one end.
It's just that simple. My code is over 1500 lines and broken
up into C++ classes so needless to say, it is pretty fragmented and all over the place. On the plus
side, there are no errors except one. Doing a select() and timeout is
not an option here. Is there a way to get an acknowledgement
from the server if the message I sent was read out of the
buffer?
From: Rob Seace
Well, the only thing that seems to make sense is that your
client gets its write() in BEFORE the server actually
close()'s the connection... Because, if the connection
were truly closed at the time of the write(), then it just
MUST fail with EPIPE, unless your OS is just broken, or
something... (What system is this being run on, anyway?)
But, if it gets the write() is before the close (which is
highly possible, since the OS will accept the connection
long before the server does its accept(), which will make
the client's connect() succeed right away), then the written
data will just queue up, waiting for the remote side to
eventually read it... Now, when the server finally does the
accept() and immediately close()'s the connection, that
queued data will just be discarded... And, sadly, there's
really no way for you to detect THAT, I don't think...
Unless you establish some app-level ACK'ing of messages
between client and server... However, you should be able
to EVENTUALLY detect the fact that the connection was
closed... Either on your next write() (after the close()
actually takes place), or read(), or even YOUR close()...
You say a call to read() blocks? Does it CONTINUOUSLY
block, even long after the server's close() was really done?
That definitely should NOT happen... As soon as the remote
close() is done, your read()/recv() should unblock and
return 0, to indicate EOF... If it's really not doing that,
then I'm not sure WHAT is happening... But, it sounds very
odd... As I said, you'd probably be well off to create
yourself a very simplified client and server, to duplicate
what is happening, and verify that this simplified code
still behaves the same way... If it DOES, post it... If it
DOESN'T, then it means there's some other hidden bug in your
original code that's responsible...
Add a Comment
New Questions: Line down condition
From: ArK
Hi,
Is it possible to sense, when a cable is
plugged out from the network? Is TCP/IP
provides any signal when the cable is plugged out?
( Unix Platforms ).
Add a Comment
New Questions: Select Read problem
From: Sameer Tilak
Hi All,
while(1) {
build_select_list(serv_sock);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
ready_sock = 0;
ready_sock = select(highsock+1, &socks, (fd_set*) 0,
(fd_set*) 0, NULL);
if (ready_sock < 0)
{
perror("select"); exit(EXIT_FAILURE); }
if (ready_sock == 0)
{
/* Nothing ready to read, just show that we're alive */
printf("...");
fflush(stdout);
}
else
{
printf("\n One more hit %d \n",ready_sock);
read_socks(serv_sock); printf("\n Just now serviced %d
\n",ready_sock);
}
}
}
read_socks(int serv_sock)
{
int listnum;
/* Current item in connectlist for for loops */ /* OK, now socks will be set with whatever
socket(s)
are ready for reading. Lets first check our "listening" socket, and then check the sockets in
connectlist. */ /* If a client is trying to connect()
to our listening socket, select() will consider that as the socket being 'readable'. Thus, if the
listening socket is part of the fd_set, we need
to accept a new connection. */
if (FD_ISSET(serv_sock,&socks))
handle_new_connection(serv_sock);
/* Now check connectlist for available data */
-Sameer.
Add a Comment
New Questions: How does server control
number of client---help
From: taohuang
Hi:
In my project, I need server control the number of client
the MAX_NUMBER is 5, when the sixth coming, server tell it's
busy, and some one disconnect, server've one available.
How can I do this.
Thanks for any help.
----new guy
Add a Comment
New Questions: how to detect SIGCHLD
From: taohuang
Add a Comment
New Questions: TCP Socket Read/Write With
Two Threads
From: schang
Is it possible to read/write TCP socket concurrently by two separate worker threads? Both
read/write channels belong to the same connection. If it's possible, are there'any side-effects, or
areas I need to pay special attention? e.g. locking issues or external interrupt event like TERM
signal?
Diagram:
Add a Comment
New Questions: Data Flow from socket call(s)
to a network device driver
From: chandraiah P
Dear
If any one knows how the Linux kernel maps different socket calls to a corresponding Network
device driver functions please explain me.
like
socket call
|
Add a Comment
New Questions: Data Flow from socket call(s)
to a network device driver
From: chandraiah P
Dear
If any one knows how the Linux kernel maps different socket calls to a corresponding Network
device driver functions please explain me.
like
thanking you
with regards
chandraiah
Add a Comment
New Questions: Data Flow from socket call(s)
to a network device driver
From: chandraiah P
Dear
If any one knows how the Linux kernel maps different socket calls to a corresponding Network
device driver functions please explain me.
like
thanking you
with regards
chandraiah
Add a Comment
New Questions: Select on a unconnected
socket
From: Indy De
I have also experienced this - but sorry I don't know why it happens.
Add a Comment
New Questions: What is client IP on a multi-IP
machine?
From: Dave Zavetz
Let's say that I have a single PC with a number of NICs with each port having it's own IP
address ... like this:
ethernet port 1 -> X.X.X.1
ethernet port 2 -> X.X.X.2
ethernet port 3 -> X.X.X.3, etc.
Now let's say that my application has data to send (to another PC) and I need the data to be sent
over port 2 (X.X.X.2). How do I assign a client to a particular "outgoing" IP address?
From: Rob Seace
3. A thread does a chdir. What effect does this have on the other threads.
From: Rob Seace
Add a Comment
New Questions: Can I increment an IP address
"IP=IP+1"?
From: Alberto Fernandez
I want to make a scan program who try to connect in one port on all host of my subnet in the
form (x.x.x.0-x.x.x.255)
From: Rob Seace
long l;
struct in_addr in;
l = ntohl (in.s_addr);
l++;
in.s_addr = l;
/* ... */
From: Rob Seace
Add a Comment
New Questions: SCO Socket
From: bakterius
Add a Comment
New Questions: How socket calls are get
mapped to network device driver functions
From: chandraiah p
I want to know how the different socket calls are mapped under datalink layer network device
driver functions.
Please explain me how the network device driver functions are get called by any application.
Add a Comment
New Questions: using C program to get connect
to the web server
From: jagan
sir
i want the source code that connect to the internet via http request Or url and to get the html page
source code from the internet
please help me to do the needful.....
From: talles
############
# open_TCP #
############
#
# Given ($file_handle, $dest, $port) return 1 if successful, undef when
# unsuccessful.
#
# Input: $fileHandle is the name of the filehandle to use
# $dest is the name of the destination computer,
# either IP address or hostname
# $port is the port number
#
# Output: successful network connection in file handle
#
use Socket;
$host="www.yahoo.com";
$port=80;
close (F);
################################################################################
# Client's side tcp connection
################################################################################
sub open_TCP
{
# get parameters
my ($FS, $dest, $port) = @_;
# print "FS=$FS\n";
my $proto = getprotobyname('tcp');
socket($FS, PF_INET, SOCK_STREAM, $proto);
my $sin = sockaddr_in($port,inet_aton($dest));
connect($FS,$sin) || return undef;
Add a Comment
New Questions: urgently required!!!!!!!1
From: SENTHIL KUMAR
sir,
i want to connect to internet via the proxy using c-codings and have to fetch the html source
code for any type of internet page.
pls send me c-coding as soon as possible...
senthil...
Add a Comment
New Questions: UDP Buffers
From: Jason
I am writing a small UDP application that is NRT (near real time.) It has to always have the
most recent status down to the millisecond, so I'm not worried about a lost message. The actual
message is small (~10 bytes) I think I'm seeing some buffering, but I don't know if it's just host
delay. Ideally, the most recent and complete packet will come out when I do a recvfrom. How
can I ensure this. I've looked around the linux source, but not to any avail =(.
Thanks in advance.
Add a Comment
New Questions: Read and write irrespective of
the order
From: bhishm
Hi ,
I made a client and a server .Both of which can recv and send ,I want to make the
communication asychronous irrespective of the recv or send system calls order which are of
blocking in nature .If the socket sends then the client will receive ir-respective of the order and
vice versa like online chat .
Can you help me by giving some small sample example code or idea .
Add a Comment
New Questions: how to use a C client to
connect to an RMI port?
From: Kaushik
hi,
I have a Client server program written in C for Linux and the program is
working when I transfer files from one directory to another
on a normal port created in C.
Now I have a PORT that is created using JAVA RMIREGISTRY
( rmiregistry 4677 &). What changes do I have to make to connect
my program to this port?
Hi,
Add a Comment
New Questions: resource temporarily
unavailable - recv problem
From: aliye
I have a client program written in C++ and running on Unix platform. It has a TCP/IP
connection with the server. And my socket is using non-blocking socket mode.
The problem is , not always but occacionaly, it is getting "Resource temporarily unavailable"
error on recv.
When this error occurs, I repeat 3 more times to receive the data but these attemps are never
successfull.
Any idea, why I would get these error? Is there any way to avoid it? What is the risk of loosing
data in case of this error?
Thanks in advance
From: matt
check that your not trying yo recv from your master socket
From: aliye
Could you explain little bit more. What is the master socket. If you mean the server socket. As
far as I can check it does not get any problem for sending packages at the same time.
From: matt
by master socket i mean the socket you bind and listen on.
Add a Comment
New Questions: setting file permissions for
sockets
From: matt
how do you set file permissions for sockets? should you fchown after you call socket or at the
end after you listen()??
From: Hector Lasso
Hi,
I think it is impossible to set file permissions on sockets because sockets are not files. I may be
wrong however so you don't lose anything if you make a test. I guess you would receive an
ENOENT error or EBADF...
Add a Comment
New Questions: Timeout period affecting
selects ability to detect data
From: Alan Harding
I have a program that is connecting up to a remote system and listening for data.
Here is my code:
tv.tv_sec = 2;
tv.tv_usec = 0;
/* ---------------------------------- */
/* Initialise the file descriptor set */
/* ---------------------------------- */
FD_ZERO(&readfds);
FD_SET(s, &readfds);
while (TRUE)
{
if (select(s+1, &readfds, NULL, NULL, &tv) == -1)
{
perror("select");
exit(1);
}
i = (FD_ISSET(s, &readfds));
if (i != 0)
{
if ((i = recv(s, &in_buf, 1, NULL)) <= 0)
{
if (i == 0)
{
printf("\nConnection closed, errno %d\n", errno);
exit (0);
}
else
{
printf("Socket read failed (1), errno %d\n", errno);
exit(0);
}
}
}
else
{
printf("\nNo data\n");
}
}
The problem that I am running in to is that the select never sees data waiting in the buffer with
tv.tv_sec = 2. If I set the value to 60 then it works fine. Right now I am just seeing a 'heartbeat'
from the server I am connecting to which is sending out a message every 40 seconds. From my
experiments it seems that after the first timeout select never sees data in the buffer again.
Any ideas?
thanks!
From: Alan Harding
I just fixed my onw problem, the FD_ZERO and FD_SET have to be inside the loop because
select overwrites them.
From: Rob Seace
Not only do you need the fd_set initialization inside the
loop, but you should ALSO move the timeval initialization
in there, as well... Because, some OS's will modify the
timeout value as well (setting it to the remaining time left
before timeout expiration, if it returns before the timeout
goes off)... Some will not... But, you can't rely on one
behavior or the other, so you're best off just explicitly
setting it to however long you really want to wait, each
and every time before you call select()... (Unless you know
for certain that your OS does modify the timeval, and you're
in fact counting on that behavior...)
Add a Comment
New Questions: Making sockets working over
the internet
From: David
First of all, you will need a machine that has a permanent valid internet IP address, or maybe an
invalid address behind a NAT device that can map it to a valid address.
Second, you will need to distribute your chat client application (or do you think you can chat to
yourself for more than 12 seconds???, believe me i've tried it many times and it's really boring)
Then you'd probably want to see it work, so you'll have to set up the chat server in your server
(the one that has the valid internet address and a button that is normally used to power it
up/down)
Oops i forgot: Modify your client program to use this address (the valid one) and then call the
people you gave your program to and tell them about the new enhancement to your software,
send them the new program and bill them for the new system (i learned this at M*cro$xxx).
If they have problems installing the application bill them again and send your ten-year-old
brother to do the dirty work of copying another bunch of DLLs that the application needs to run
properly...
If there is someone left that wishes to use your chat then let him use it for a while. Add some
stupid features (that no one uses) as well as some really useful features, but make them
nonconfigurable. As soon as the users are using the chat regularly charge them for every
message or something... develop a new version that includes some configuration windows for
the useful stuff and some more stupid features no one uses. Name it the professional version.
Sell it for 3 or 4 times the price of the original one.
If you get rich please don't forget the royalties for the intelectual property that you should pay
me
:D (HAL)
Add a Comment
New Questions: EINTR Testing
From: Jeff Halbgewachs
Hi,
Add a Comment
New Questions: Where can I get the converter
to convert Windows to Unix?
From: Thomas Lee
Where can I get the converter to convert Windows to Unix? If anyone knows please e-mail to
me and let me know.
-thank you
From: Hector Lasso
Do you need to convert from one byte-ordering scheme to the other? Or do you want to use
Windows software on a Unix box?
From: Loco
I would read about ntohl(), ntohs(), htonl() and htons() for the simple ones...
Call (974) 555-**** and ask for Bill. Tell him about your problem, maybe he could help you
with this. Tell him that you need him to convert Windows to Unix because it Winsocks...
:D (HAL)
From: arjun
hey what the fuck r u askin got to fuck u now come and see me
From: sudmah
hey !! I think U probably lost the concepts of basics of
computers! better refer to the website , www.microsoft.com.
There U`ll get the real basics and converters!
From: Arik Baratz
Contrary to common belief, ther eis a very easy way to convert Windows to UNIX.
All you have to do is take your Windows(tm) distribution disk, and a felt tip marker. Then
simply write UNIX on the disk.
Once you have done this, you have neutralized the Windows socket code on the disk. Next you
have to magnetically retrace the disk to make it UNIX compatible. This can be done by
standing on the edge of large buildings and waving the disk back and fro, as far away from the
building as you can.
Do try to get as far from the building as you can by reaching away as far as you can with your
hand and preferably your entire body. You must perform this procedure with care that the edge
is directly above the street; That the building is at least 20 story high; That there is nothing
obstructing on the way down.
Then just put the CD in your computer and boot.
From: Loco
Add a Comment
New Questions: TCP/UDP on same server
From: Anurag Goel
I need to implement a date/time/echo server that can fulfill both TCP/UDP requests. How do I
do that?
Add a Comment
New Questions: HOW CAN I open n
connections working at the same time ??
From: overflash
Just kidding. You could do a lot of things, but the basic idea is: You can select(), fork(), or
pthread_xx()
Or a combination of any of them. Use your imagination.
:D (HAL)
Add a Comment
New Questions: non blocking socket
From: Mauro
I would like to do a port scanner using non-blocking socket, but in this case the connect()
function always return -1. Someone could telle me how I can see (looking errno) if a port is
open, close or firewalled? Thanks.
From: Rob Seace
Add a Comment
New Questions: RST packet ???????
From: Marios Karagiannopoulos
Hi. Where could I find the reasons of sending a RST flag(reset flag in a tcp packet) in a packet?
I know that a reason could be the non existing port number, but I would like to get all the
reasons for this packet !!
Sometimes connections can get stuck in the FIN_WAIT state and it would be really nice to
ABORT rather than wait the full 10 minutes + 75 seconds to timeout.
Add a Comment
New Questions: Source Code client.c And
Server.c for UNIX
From: Lee
i have server.c and client.c and that u can run with the same command ( client will give
command, server will execute it and will give the execution result to client )
using,
gcc filename -o filename -lsocket -lnsl
From: samc
Add a Comment
New Questions: how to check if a socket is
connected or not?
From: David
Hey all,
I was wondering if there is anyway to check if a client socket is connected to a remote address.
As an example, say that create my socket and after successfully connecting to some server on
the Internet, i call sleep(10), and close my dial-up connection. Right after, i try writing to the
socket and it still succeeds even though the connection is down.
Is there anyway to check if connected at any given time?
Thanks in advance,
David
From: Hector Lasso
I don't know if this can help. I've never tried it but i think that using setsockopt() with
SO_KEEPALIVE on your socket can help you.
Add a Comment
New Questions: NBT packets???
From: Marios K.
Does anyone know when a Netbios packet is sent over a tcp/ip network?
thanx
From: Hector Lasso
Hi,
From: Marios K.
Thanx a lot for the info, I have already captured the tcp packets and I have seen this NBT
packet a lot of times. I would like to know what is the reason that this packet is sent. When a
NT machine is supposed to sent this packet?
Thanx
From: Hector Lasso
Hi,
NT can use both protocols NetBEUI and TCP/IP to exchange NetBIOS info, however which
one it uses depends mainly on your bindings configuration and the protocol supported by the
other party. First check the bindings order in the Network Configuration Dialog Box. If you
want to disable NBT you should delete NetBIOS from the bindings only in the TCP/IP section.
You can also change the binding order to force the machine to use NetBEUI first and TCP/IP if
NetBEUI is not supported by the other party.
Add a Comment
New Questions: TCP UDP on same server
From: andy
HI
Apologies if this has been asked before (I have checked FAQ but couldn't find any relevant).
If it is not possible, I take it two servers can listen using the same port ?
Thanks in advance
Andy
From: Rob Seace
From: ggbutcher
nmap.
From: Hector Lasso
Every computer that participates (or wishes to participate) can bind an UDP socket to a
especific port.
Your server sends a broadcast packet to the subnet's broadcast address, and port mentioned
above. All the computers will receive the packet and would send a reply to this packet
informing they are available (or not, maybe they are already playing something else) and
whatever information you wish to send (player's name for example)
That is it.
Add a Comment
New Questions: Using select with recv send
From: Bhishm
HI ,
I want to make the send-recv system calls asynchronous like yahoo chat or any other chatting
service .
If I make a client and server both interacting with each other, than the call to either send or
receive blocked until it receive/send a message .
Add a Comment
New Questions: communication between a
java program and a c program
From: ait ettaleb
how can i make communication throw sockets (using UDP protocol) between a program written
in c and an other written in java ?
From: Kennedy
Have you looked at the JNI? You use this so you can write
native methods in a program like C, and call them from your
java program.
Add a Comment
New Questions: Getting Signal Number
2147482380 While sending data on socket
From: Vignesh Bhatta
Hi
I am facing problem , in my server and client program.
My program is getting signal number 2147482380 once send on client socket was performed.
I am suspecting some where stack corruption. It is occuring only when there is heavy load on
the
socket. What i mean is if program is transmitting data on socket at the rate of avg 100msec.
Could I get the answer please from any body to email. Machine is Pentius III. OS is Sco 5.0.4
Thanking you
Vignesh
Add a Comment
New Questions: Time Polling
From: Jacob Noffke
I am writing a typical client/server socket program that continuosly sends messages for twenty
seconds. These messages are to be sent at random times. How can I time the generation of
messages?
From: ashok
u havent told in what state u exactly r .. but i can think of three of them ..
1) u dont have to watch any sockets during the period ( meaning u r not using select)
-- in such a case u can put ur 'write' call in a loop with the dealy u need .. using either 'sleep()' or
'usleep()' depending on the duration of the interval u need between each 'write'
the pseudo code could be ..
2) u need to watch sockets for activity and duration u need between intervals is less than a
second( u r using select )
-- then u can use the last argument of select for setting the duration that u need between the
intervals .. and u need to do some coding to take care when select returns a value which is
greater than 0 .. becoz this means that the interval that u wanted to wait for has not completely
elapsed and u need to subtract the elapsed time from the duration u r going to wait next ..
the pseudo code could be
3)u need to watch sockets for activity and the duration u need between each 'write' is in seconds
( u r using select )
-- this time u can use the 'alarm()' ..althought select will work ... but this will make ur job
simpler ... but dont forget to put this peice of code near select ..
pseudo code would be ...
Add a Comment
New Questions: UDP BraodCast
From: Paulson
Hi,
How to Broadcast the data using UDP ? I am now opening a UDP Port(127.0.0.1) and sending
the data to it. I want this to to read by all clients connected to the server through TCP.
Now When I am trying to recv the data , Only the first client is getting the data. Each clients (
created uisng Fork) are looking in to this same UDP port ?
How can set the UDP port to recieve data for all the clients instead of one client ??
Thanks
Paulson
From: Loco
-127.0.0.1 is your own addres, in fact it is the localhost address, a message sent to this address
will never leave your host (like some relatives when visiting you, they stay for months, did i
ever tell you bout the time my grandmother...? sorry, focus man)...
- You should use 255.255.255.255 for all addresses in your local net (i guess some routers do
forward this packages to all of their interfaces, but i'm not sure, so let's assume they get only to
the LAN ur host is connected to)...
- If you need to send to all machines in LAN A (addresses 192.168.0/24 for example) and you
are on LAN B (addresses 10.1.2/24 for example) then use the destination broadcast address
which would be 192.168.0.255 (just OR the net address with NOT netmask and voilà, there you
go!!!!!!)
- Aha, you tell me it ain't working... it must be some problem in your satellite dish that is
messing with the infrared waves your wireless card sends, and... Are you sure you allowed your
UDP socket to use broadcast addresses as destination??? NO? I knew it...
If you don't allow the socket to use broadcast addresses, how do you expect it to work?
Well, it is a very long and expensive process, and if you send me $1000USD i will tell you all
about it. Please don't try to do it by yourself because it is very dangerous (at least for my bank
account). Being the nice person i've always been i will give you a clue:
int opt;
setsockopt(yoursocket, SOL_SOCKET, SO_BROADCAST, (void*)&opt, sizeof(int));
Sh*t, i wrote it all... can't find the undo key.. f*ck... Don't forget to send me the $1K...
Remember everybody, my email address has changed (i don't know who is [email protected],
but this guy must be receiving many strong emails from people of this FAQ!!! I hope he don't
get my money, mon)
:D (HAL)
From: Hector Lasso
Hello,
My questions are:
- Do your clients run in different machines? (remember that only one process can bind a socket
to an (address,port,protocol). If u create the UDP socket and then fork() children then the socket
can be used by all of them, however only one will receive a message unless he uses the
MSG_PEEK flag in recv()
- What is the destination address you are using? Does it match to your network's broadcast
address?
- Could you post a simplified version of your code?
From: Paulson
Dear Loco,
You are totally wrong ... I am sending to the local address only. The destination is the server
itself and I am using 127.0.0.1. Probably I will explain in detail .....
I am currently involved in the development of an internet based trading system, and is using a
data feed from exchange. The program is working perfectly for a single connection.
One process recieves the data from the stock exchange and will put into the shared memory.
When ever there is a change in the data it will send the data to the one UDP port. The
destination is the local server itself.
Another process keeps on waiting for a new client(TCP connection)and when there is one it will
fork for a new child. Each child is waiting for data from the the UDP port above. But now only
one client is getting the data and the port is cleared after that.
I have tested the MSG_PEEK flag in recv() but it is going into the infinite loop. I think the new
data which is coming into the UDP port is waiting in the queue becase the exisitng data is not
cleared from the port. Is there any way we can force the data to write even if new data is
existing? Is there any other solution ?
Thanks a lot
Paulson
From: Loco
Hey man,
Now i get it... Wow, it's been the first time ever in my whole life that i've got it all wrong. Well
maybe it has happened before.. what the hell, it happens all time but who cares...
OK, what my friend up there told you is very misleading. If you use MSG_PEEK, every
process will get the message (because the message is still in the queue) but which one should
get the message out of there??? That is the problem.
I suggest you use other methods to broadcast the information to your client processes such as
pipes:
The forker (the one that listens and forks for each connection - you were thinking different
weren't you) can be the receiver of the UDP packets. Whenever it accepts a new connection
creates a pipe that can be used to communicate with the child that forks.
It keeps a list of the pipes, and whenever a new UDP packet is received, this process writes to
each and every pipe it has in its list. Obviously it has to capture the SIGCHLD signal, and close
those pipes related to dead children...
I guess there must be some way to do this with UNIX sockets, but i've never worked with'em. If
anyone knows about it please let me know.
Well, time to go... My jailer came back and he's gonna take my cigarettes away.
:D (HAL)
Add a Comment
New Questions: Recv ( ) in blocking mode
From: rupashri
Hi ,
I have written a program using TCP socket communication.
Once the Client connects to the Server program, i want the connection to be kept alive until the
client sends a request to tear down the connection.
I want my recv() function to work in blocking mode.
How do i do it?
main()
{
socket();
bind();
listen()
for(;;)
{
newsockfd=accept(...);
while(1)
{
recv(newsockfd,buffer,len,0);
.
.
if(some condition)
break;
}
}
From: Loco
What do you want to do? Do you want your server to work like those cheap restaurants where
there is only one waiter and he is always waiting on somebody else?
So your code will probably work, but when your process receives a new connection it will just
go on to serve this client and the others will have to wait until this one decides to finish the
communication.
When you come back to "accept()" maybe the other side is no longer there and it could take a
little bit 'till you find this out, and so on, causing your server to behave strangely and your
clients to think it doesn't work, that it just wastes his time in internet, visiting FAQs just for fun
and reading stupid jokes...
I suggest you use fork(), or just go with plain-old select(). If you dare to use threads then good
luck.
PS: Did you forget about close()/shutdown() or didn't want to include'em in your example.
:D (HAL)
Add a Comment
New Questions: Why is my socket not ready
for writing?
From: Julian
Why would a socket not be ready for writing? I have a program where I call write to send 1024
bytes of data to the socket. The call hangs in write. If I put a select call in just before the write,
with a timeout, I see that the socket is not ready for reading or writing. Also there is no
exception pending.
Thanks,
Julian
From: Rob Seace
One likely reason would be that your socket send buffers are
full... Which probably means whoever you're sending to
isn't reading nearly as fast as you're sending... Or, maybe
the network connection temporarily went haywire, so packets
are getting backed up... *shrug*
From: Julian Palmer
This is the conclusion I'm coming to as well. If I add *big* delays, then things work.
Unfortunately the delays are too big to be acceptible in the code (order seconds between
packets).
The situation here is the application is responding to a web page request issued by Netscape
Navigator 4.5. The requested data is around 26KB and is being sent in 1KB socket writes for
internal application reasons.
Is there anything funny known about how Netscape handles incoming HTML response pages
that is relevant here? It works fine if the browser is Internet Explorer. It also seems to behave
better if the amount of data being returned is smaller. Strangely enough,uploading bigger
non-HTML files seems to be ok. Could it be that Netscape is doing something different with
HTML than other document types?
fwiw the OS here for the application is a Linux 2.2 kernel. Is there any OS debug stuff I could
look at that would tell me what was going on? Netstat just says the connection is
ESTABLISHED. Tcpdump doesn't show any problems.
Julian
From: Rob Seace
We can't just block on the write as it never unblocks. i.e. the socket is stuck for all time.
Aborting the browser request (hitting the Stop button) clears everything of course.
We have tried other browsers. It works fine with all versions of IE we can use. It also works
with the same rev of Netscape running on a Linux box, just not on Windows. It also works with
Netscape 6 on Windows. Sigh... ;-) Also clearing the browser cache provokes it every time...
We're also going to try writing the data to the socket in different sized chunks to see if that
affects it. We'll try the tools you suggest too - if they exist under Windows!
Is there anything I can look at on our application side on the Linux box that would tell me why
the socket is stuck? e.g. an errno value or some such?
Julian
From: Rob Seace
It's odd that the blockage never clears out at all... (How
long have you waited, before giving up?) I would've thought
it was just a matter of the client being too slow, and not
reading the incoming packets fast enough... But, if so, it
should EVENTUALLY get around to reading them, and thereby
clear out your backed-up write buffers, and allow you to
start sending more data... But, instead, it sounds like
it's just getting totally locked-up, and refusing to read
any more data from you, at all... I have no idea why it
would do such a thing, though... I think you can safely
chalk it up to a client app bug though, rather than
something on your end... Of course, if you NEED to support
the buggy client anyway, then I guess it unfortunately
becomes your problem, anyway... ;-) I don't know what more
to suggest to kluge around it, though... Maybe key off the
browser's identity, and for Netscape on Windoze, only feed
it data in tiny, slow, bite-sized chunks that it can
swallow easily? ;-)
Add a Comment
New Questions: writing to RAW ethernet
socket
From: Dries Pruimboom
Hello,
sock = socket(AF_INET,SOCK_PACKET,htons(ETH_P_ALL));
then i try to read from the socket using something like this :
read(sock,buffer,4096);
ethaddr.sa_family = AF_PACKET;
memcpy(ethaddr.sa_data,addr,6);
sendto(socket,send_data,128,0,ðaddr,sizeof(struct sockaddr));
but this doesn't seem to work, does anyone know what's wrong ?
From: Rob Seace
You should take a look at the source for libnet... In fact, you might consider using it, perhaps in
combination with libpcap, in order to have very portable raw packet reading/writing
capabilities, rather than just directly coding up your own support, which is going to be very
platform-dependent... (Note: if packetfactory.net is down, which it often seems to be, you can
find libnet many other places... I'd recommend searching for it on packet storm...)
However, based on a quick peek at the libnet source, I think what you want to stuff in your
sockaddr is the interface name which you want to send the packet through... (Eg: "eth0", or
whatever...)
Add a Comment
New Questions: Tcp port configuration
From: Aida
Hi!
I would like to know if there is a simple way of
finding out how to configure tcp port for Solaris 2.6.
What files should I look at (beside /etc/services)?
Are there some commands I have to run?
Regards
Aida
From:
no idea
Add a Comment
New Questions: Max data that can be send in
one send
From: yogesh
Hi , I just wanted to know , what is the maximum size of data , or maximum bytes can I send in
one send or sento ?
Add a Comment
New Questions: Regarding Non blocking calls
From: yogesh
Hi ,in my application , no of clients are sending the data on the same server port , currently I am
using Select since its a non blocking sockets .
Right now I am reading using datagram sockets i.e. recvfrom (), using this I can able to read
only one message send by any client at a time, but is there any simple method via which I can
read all the messsages waiting on the recv at a time and I need the IP adds of sender too.
Add a Comment
New Questions: Why do I get "accept: Too
many open files" error
From: Jessy
Hi there,
We have written a C rpogram of a socket server. After a few users conect to it, I get accept : too
many open files error which scrolls on the screen.
Can you please explain the cause of it?
Thank you.
From: Loco
Hi,
The error indicates that the process has run out of file descriptors, and as accept creates a new
file descriptor when a client connects (you knew you needed a file descriptor for every
connected socket didn't you?), it couldn't create it and failed to accept the connection.
This could be caused by many things (for example, taking a shower after 10:00 PM while the
neighbor is watching the football game on Fox Sports...), but i've seen this happen when you
fork a child process for every connection and the child process is the one that works on the
client socket. People normally forget to close the socket in the parent process (reading the man
pages you'll find out that close doesn't close the "socket or connection" unless it is the only
descriptor for that socket, you would have to use "shutdown" to close it explicitly), which
would just release the file descriptor. If this is what is happening, you'll run out of file
descriptors after a few thousand connections (even from the same client).
You should close the descriptor after fork() from the parent:
pid = fork();
if (pid > 0) {
// Parent, close the descriptor
close(peer_socket);
}
else if (pid == 0) {
// Child, do something, such as exec
execl(...);
}
else {
// Error
}
However, it is possible that you are losing file descriptors another way, so please post your code
or a simple version of it to know what the problem is...
If you want to handle more descriptors than your process can handle currently, i think this guy
Seace has written a lot about it in previous questions so go on and read about it.
:D (HAL)
From: Jessy
Add a Comment
New Questions: Errors when a remote host
crashes
From: Giorgio Spagnardi
If I'm waiting for read() (in blocking mode on a connect() socket) and the
sender host crashes(=turn off or reset), what errors my read() return?
Many Thaks
Add a Comment
New Questions: using poll for packet timeout
From: Justin
I'm trying to implement a sliding window algorithm and I'm trying to use poll to tell me when a
packet has been gone too long and needs to be retransmitted. I can't figure out for the life of me
how to use poll here. Poll seems to look at file descriptors but there is only one fd for the socket
and not one for every packet that gets sent. so how do I check for timeouts on individual
packets that are sent????? thanks
Justin
From: mrx
Add a Comment
New Questions: How can I prevent from losing
packet
From: Mitsuhiro Tokura
I use three sockets( that has different prot ) in the same program. There is no loss if receive in
slow speed. But as speed go up, losing packets happened. I tested the program that was changed
from three sockets to one socket. This resulted in receiving without loss.
Please tell me the reason for losing packets.
From: Loco
Post some code, maybe some people here can help you with your problem.
:D (HAL)
From: Mitsuhiro Tokura
width = 0;
FD_ZERO(&Mask);
FD_SET( soc_TKY, &Mask);
FD_SET( soc_OSK, &Mask);
FD_SET( soc_NGY, &Mask);
width = soc_NGY + 1;
while(1){
readOk = Mask;
switch( select(width, (fd_set *)&readOk, NULL,NULL,NULL ))
{
case -1:
return( RETURN_ERROR ); break;
case 0:break;
default:
memset(buf, NULL, sizeof( buf ));
if(FD_ISSET( soc_TKY, &readOk)){
addr_size = sizeof( struct sockaddr_in );
if( soc_TKY !=-1 ){
if( recvfrom(soc_TKY, buf, sizeof(buf), 0
,(struct sockaddr*)&server, &addr_size ) < 0 ){
return( RETURN_ERROR );
}
}else{
return( RETURN_ERROR );
}
}else if(FD_ISSET( soc_OSK, &readOk)){
( continue )
width = 0;
FD_ZERO(&Mask);
FD_SET( soc_TKY, &Mask);
width = soc_TKY + 1;
while(1){
readOk = Mask;
switch( select(width, (fd_set *)&readOk, NULL,NULL,NULL))
{
case -1:
return( RETURN_ERROR ); break;
case 0:break;
default:
memset(buf, NULL, sizeof( buf ));
if(FD_ISSET( soc_TKY, &readOk)){
addr_size = sizeof( struct sockaddr_in );
if( soc_TKY !=-1 ){
if( recvfrom(soc_TKY, buf, sizeof(buf), 0
,(struct sockaddr*)&server, &addr_size ) < 0 ){
return( RETURN_ERROR );
}
}else{
return( RETURN_ERROR );
}
}
}
( continue )
----------------------------------------------
protocol : UDP/IP MULTICAST
From: Hector Lasso
Hi,
You are putting your 3 sockets in the mask. However, when select() returns you check the first
socket, if it isn't ready to receive check the second and so on. This could cause some trouble
with the second and third sockets, for example:
Suppose your clients are sending packets constantly. When select() returns the 3 sockets are
ready for reading. You check the first socket and recv() its packet. Go again to select() and as
there are packets in all the sockets go again and recv() only on the first socket. This cold cause a
"denial of service" to the other sockets for as long as the first socket is redy to read the others
won't be processed.
I would change the code to look something like:
while (1) {
readOk = Mask;
switch (select(width, &readOk, NULL, NULL, NULL)) {
case -1:
return ERROR;
case 0:
break;
default:
// If buf is "char*" then sizeof(buf) sizeof(char*)
memset(buf, 0, BUFFER_LENGTH);
if (FD_ISSET(soc_TKY, &readOk)) {
// process soc_TKY
}
// In your code it is "else if (...)"
if (FD_ISSET(soc_OSK, &readOk)) {
// process soc_OSK
}
if (FD_ISSET(soc_NGY, &readOk)) {
// process soc_NGY
}
break;
} // switch()
} // while()
I tested the way adviced me in this page. But test resulted in the same before.(program lose
receive datas.) I think searching in the descriptor list at the select() is slow, (I don't know this
reason ) so datas overflowed the socket buffer and lose. I use AIX ver4.3, is there anyone know
this reason?
From: Stephan Krings
Maybe I misunderstood something completely, but you're using UDP (socket created with
SOCK_DGRAM), aren't you?
If this is right, it's completely normal, that you're losing packets. A fast sender can easily
"overrun" a receiver, especially if the latter one is serving on several sockets, processing the
request etc. The packet may also be lost due to bad network conditions. In short: Datagram
sockets are completely unreliable.
If you need reliability either use stream-sockets (SOCK_STREAM), or design your protocol, so
that it can retransmit lost packets.
See R. Stevens "Unix Network Programming" for an in-depth discussion of this topic.
From: Hector Lasso
Stephan,
I think the problem is not packets lost in the net. In the original question Mitsuhiro points that
using one socket instead of three stops the packet loss, so for some reason, the code to handle
three sockets is slow enough to make the sender "overrun" the receiver.
My comment was valid as the code posted by Mitsuhiro had a problem, however, the changes
didn't work.
Mitsuhiro, i think you can do many things to stop losing packets. These are just ideas, i might
be wrong:
- Use TCP connections as Stephan suggests.
- Create a retransmission protocol to send again packets lost (there are many ways to do this,
some may adapt better to your requirements) - i'd rather use tcp connections instead of this
- Use a thread for each socket -> it doesn't assure you'll get the packets, you might have the
same problems as with select(), however, it will process the data faster when one or two of the
sockets are not receiving data as the recvfrom() call will block and the OS won't give processor
time to those threads. Trying doesn't hurt...
- You can still use select() to check for data available, read the data and put it into a buffer that
another thread with less priority can process, playing with priorities can help you avoid packet
loss.
I am most thankful for your advice. To tell the truth, this program receive information of the
stock market, sending specifications is defined, so I can't use TCP/IP. And packets must be
processed in good order. Because I am not familiar with c, it seems to be difficult to
synchronize threads each other.
From: Hector Lasso
Mitsuhiro:
I see you receive from three different sources: Your test using one socket only received from
one of them, or from all of them on the same port?
Do you still lose packets if you create three different processes each one dedicated to a different
source? (this is a very simple test so i suggest you do it)
Do you need to receive from the three sources in a unique process? If you don't, and the
previous question is negative (you don't lose packets with three processes) then we have worked
it out.
UDP is a protocol meant to be used when you need speed but not accuracy. For example, in
video streaming it doesn't matter if you lose a couple of frames per second, what really matters
is that you have an average frame rate and have the frames in real time, you don't want perfect
image of what the server sent a couple of hours ago but an acceptable image of what the server
is sending right now.
If the sources use UDP with this high send rate (such that it can overflow the receiver's buffer)
means you can afford losing some packets, and there might be a way to calculate the lost
packets from the others if they are indispensable.
In fact, some packets are lost in the network, and you cannot do anything about it, you never
know they were sent (unless they include some sort of serial number). If you have a way to
detect lost packets then there may be a way to ask the sender to repeat the packet.
You are right. The most important thing is that process handle the packets in real time as you
say. I'm going to examine this process under understanding of packet losing.
By the way I tested using one socket only received from one of three sources. Your advice was
very helpful to me.
Add a Comment
New Questions: client to multi-homed server
From: Dave Zavetz
Let's say I have a handful of machines, each with 6 physical interfaces, with each interface
having it's own unique IP address. The machines are interconnected in a way so that there are
multiple routes from each PC to another PC. Each PC has two functions, a software router and a
data generator/collector. For now let's assume I'm using RIP and as of now I'm not running a
DNS.
Now let's say that I need to get data from PC1 to PC4 via a socket connection (TCP or UDP).
PC1 has 6 interfaces out and PC4 has 6 interfaces coming in. The socket connection will pass
through PC2 and PC3, which in this case are acting simply as routers. I don't care which
interfaces are used on PC1 and PC4 as long as it is the shortest path (RIP). For my client app on
PC1, I'm not bind()ing to a specific client IP (outgoing) address. I assume that by doing this I'm
letting the local routing table make that choice. But, what IP address do I try to connect() to on
the server (PC4)? Like I said, there are 6 physical interfaces coming in to PC4 and I don't care
which one is being used as long as it is part of the shortest path from PC1 -> PC4. It's almost
like I need to assign my server app it's own IP address. Or somehow use DNS to assign all 6
interfaces the same hostname and let the routing protocol deal with it. Any suggestions?
Add a Comment
New Questions: deleting files and directories
From: Dalibor Sver
Since I'm not good at administration especially Unix, please help me: I can't delete (rm) file
which has mod 755 in directory that has mod 777. I get constantly 'Permission denied' (file was
uploaded throug my PHP script and directory was also created by the same script)
Thank you!
Add a Comment
New Questions: packet demultiplexing
From: Priyanka Gupta
Hi,
Can anyone please explain to me the meaning of packet demultiplexing
logic withen the NIC.
Also, what is a two copy packet transport inetface??
Add a Comment
New Questions: number of connectons
From: matt
thanx
matt
From: Mike
first: i hope it´s not too late (it´s already the 04/06/2001)
a few hints:
1. TCP/IP Layer is definitely able to handle more than 40 connections.
2. If you are using a Unix environment like Solaris
there is a "soft" and a "hard" limitation on open file-handles -> socket handle is only a file
handle for the unix kernel
3. to get information about this "soft" limit:
ulimit -Sn
Sorry, but i don´t know how the limits are set under windows nt, because normally i use a real
operating system like solaris and don´t have to mess with MS for developing systems.
mike
(anything written here is completely my personal opinion and has not been authorized by the
company i´m currently working for)
From: Hector Lasso
Hi,
It might be a problem in your code. However, to know more about the problem could help a lot.
If you are doing something like this:
do {
select()
for each socket {
if (FD_ISSET(current socket)) {
do something with data received
}
}
} forever
then probably the problem is you are spending too much time processing each client request and
the others have to wait.
From: matt
matt
Hi,
do {
// set timeout here
FD_SET(fd_of_listening_socket, &readset);
result = select(fd_o_l_s+1, &readset, NULL, NULL, &your_timeout);
if (result > 0) {
// Have connection (it's the only fd in the set)
// Accept the connection
}
} while (result > 0);
I check the result of select() inside the loop and not the set because if there's an error the set
becomes undefined and you should not rely on it. As it is the only descriptor in the set i don't
check it with FD_ISSET() (should i???)
There is another strange thing i found in Solrais 2.6 when using OpenLDAP.
There is a select loop inside the OpenLDAP code.
When the hard limit of connections is reached the accept does not retrun a valid
socket handle. Because i don't get a handle i can't close the TCP connection.
But the undelying driver level does noct drop the connection !
So the client connected to the LDAP server keeps connected.
If you snoop the connection you can see the 3-way handshake of the TCP connection
the connection is established on the client side.
The result ist that the server seems to hang. No more clients get connected because
the hanging clients don't drop their connections ...
I fixed the problem by changing the logic a little bit.
The server simply closes the highest acceptable connection when it get accept()ed.
This way there is allways one spare connection listening.
I'm not shure if this is the right way to handle the problem but it was
the only solution i could find. I think it's a bug in the Solrais protocollstack.
I don't know if this still exists in 2.8
Add a Comment
New Questions: Are there Token Ring
programmer ?
From: NEC
Hi,
I'm a student and i have to make a program in C. This program must run as Token Ring.
If anyone want to tell me, links, help.....
Add a Comment
New Questions: UDP with retransmission?
From: Andreas
Hello!
In a client/server-connection with UDP, is it possible for the server to which packets that are
lost?
I would like to try to implement some kind of retransmission, or at least find out how many
packets that we are losing.
Add a Comment
New Questions: UDP Server and Client on
same machine gives Address already in use
error
From: Halle
Hi.
I'm writing a very simple beginner UDP server and client, and when I try to run the server and
client on the same machine, I get the infamous error of address already in use by bind(). This
happens of course when I run the client after running the server.
sd = socket(PF_INET,SOCK_DGRAM, 0);
bzero(&mon_s,sizeof(mon_s));
mon_s.sin_family = PF_INET;
mon_s.sin_port = htons(PORT);
n=bind(sd,(struct sockaddr*)&mon_s,sizeof(mon_s));
And of my client:
hs=gethostbyname("zulu");
sd = socket(PF_INET,SOCK_DGRAM, 0);
bzero(&son_s,sizeof(son_s));
bcopy(hs->h_addr, &son_s.sin_addr, hs->h_length);
son_s.sin_family = PF_INET;
son_s.sin_port = htons(PORT);
bzero(&mon_s,sizeof(mon_s));
mon_s.sin_addr.s_addr = INADDR_ANY;
mon_s.sin_family =PF_INET;
mon_s.sin_port = htons(PORT);
n=bind(sd,(struct sockaddr*)&mon_s,sizeof(mon_s));
where mon_s is the client's sock_addr_in structure, and son_s is the server's.
You're trying to give the client the same local port# as the
server's port# you are connecting to... Do you really need
to do that, for some reason? If not, you should probably
just let the OS assign you a free port of its own choosing,
rather than attempt to choose your own... If you really
need the client to have that port, then you simply won't be
able to ever run client and server on the same machine...
From: Halle
Well, I guess you figured that I had defined PORT as some number in both the client and the
server (the same number). I tried changing the port number for the client, and I don't get the
error anymore (yay! we're advancing!) however I don't believe the client manages to 'find' the
server. It just sends its messages out into the ether, and the server is in lala land. So, if I changed
the port number, how will the client know where the socket is? Forgive me if these are all dumb
questions, I guess I reek of newbieness.
Thanks!
Halle.
From: Hector Lasso
Hi,
Best regards
From: Rob Seace
Add a Comment
New Questions: problem transferring file
through socket
From: vinay
Add a Comment
New Questions: cgi and socket with DB
From: eric moulin
I want create an architecture where most Web client communicate on a DB via CGI and socket
in C .
How can I do ?
From: Loco
If you mean Database when you write DB then the following answer would apply, otherwise
disregard this note:
I guess i would code a daemon which stays connected to the database and acts as a session pool.
The CGI just uses IPC to get a session from the pool and request services from it. Very simple.
Hey, i've already written that code!!!
As i haven't mentioned the "socket" part then i would add a socket interface to the first
mentioned daemon... it doesn't matter where it comes from, the IPC is the important part:
+--------+ +--------+
| HTTP | | Socket |
| client | | client |
+--------+ +--------+
||
HTTP Your own protocol over TCP or UDP
||
+--------+ +--------+
| HTTP | | Socket |
| server | | server |
+--------+ +--------+
||
Forks a Forks or creates thread with
||
+----------+ +-----------+
| CGI | | Client |
| instance | | processor |
+----------+ +-----------+
||
IPC services such as message queues,
UNIX sockets, shared mem, etc
||
+----------+ |
| Session | <-+
| pool |
+----------+
|||||
Database connections
|||||
+----------+
| Database |
||
+----------+
:D (HAL)
From: Loco
Sorry man, but my graphics were not so good after i posted the comment, so it'll be really
troublesome trying to understand anything from the answer above...
HTTP client --HTTP protocol--> HTTP Server (such as apache) --forks a--> CGI instance
--communicates via IPC to--> Session pool --trough a DB session-->Database
The socket interface would work different from client to server, however, from that point on it
would be the same system:
Socket client --own protocol over TCP or UDP--> socket server --forks or creates thread that-->
process client requests --uses services (via IPC) of--> Session pool --trough a DB
session-->Database
That is it!
Add a Comment
New Questions: question about UDP SOCKET
buffering
From: Mitsuhiro Tokura
I made the program that use UDP/IP MULTICAST on AIX version 4.3. When this program
was receiving packets, I checked the number generated by the "vmstat". Then "fre" of "avm"
has been decreacing. And the number of generated by the "netstat -sm " has been
increasing(especially "256") . I set socket option "SO_RCVBUF" to 256k. I think this is caused
by soket buffering that carry out the "malloc" in mbuf whithout the "free". Is this true????
Add a Comment
New Questions: Broadcast a large file
From: Andreas
Is there anybody out there who knows how to do if I want to broadcast a large file to clients. All
source codes and comments are welcome. Thanx
From: Loco
While this may seem an idiot response, i think it is easy and you won't have the problem of
creating a new protocol. However, you will have to learn the SMTP protocol (which is almost
rocket science. lol) and some of the encoding formats.
The pros are:
- You won't have to worry about network conditions between your server and each client, just
with the SMTP server
- You can send the same file in just one connection using a list of addresses
It has some drawbacks:
- Your clients must have mailboxes
- You have to configure mail clients
- Each client will have to poll the mail server constantly
- The file size will increase because of the encoding making the message considerably larger
than the file
- Message size is important as almost every mail server has quotas
- You won't have inmediate confirmation
----------
Another option:
You could broadcast UDP packets in your network and expect confirmation from a list of
"expected receivers". You should then serialize your packets so you could repeat the packets
lost and the clients could reassemble the file using the packets. A sliding window algorithm
could help you improve performance by expecting less confirmation packets.
:D (HAL)
From: Khubilai
I have tried to send files using UDP broadcast and it requires a lot of code to work. Too much
code to post here. There is a lot to think about if you want to do it. You have to think about
everything that can go wrong, and it's a lot when dealing with UDP. UDP broadcast doesn't
work over the Internet. Contact me if there is anything you want to know about UDP broadcast,
but remember, there's a lot of work to make it work.
From: Hector Lasso
Hi,
My choice would be to use TCP connections from clients, sending the file through every socket
connected. Using select() you can follow up advance for every client connected. If your clients
have different bandwiths, and the transfer time is different i would use dedicated processes or
threads.
From: Khubilai
TCP/IP is the easiest way to make this work. It may take more time to transfer the files, but it
will save you a lot of time when you are going to write the code. I think I used around 1000
lines of code to make my transfers work when I used UDP broadcast. TCP/IP transfers is more
reliable than UDP transfers. It's differculd to find every bug when you use UDP.
Add a Comment
New Questions: recv Socket
From: Fabien
I already read the subjcet which deals with the reading of data, but i don't really find solution.
The server send a lot of inforamtions. The client don't answer to the server. The client must
simply read the data sent by the server. But i don't know the size of these data. How do you do
to adjust the size of the buffer in the instruction recv or read
From: kathy
Hey Fabien
u can adjust the size in send and recv , u only need to use the right commands used dont be
confused with different books , every book uses its own way of explanation.
From: Hector Lasso
Fabien,
You can allocate memory (either dinamically or have a static buffer) that could hold the data if
you know the maximum size of data you will receive beforehand.
You can also allocate a small buffer and grow it when needed.
For example:
#define IN_SIZE 10000
#define INCREM 5000
#define CHUNKS 1024
...
char *buffer, *temp;
int rec, offset, size;
buffer = (char*)malloc(IN_SIZE);
size = IN_SIZE;
offset = 0;
do {
rec = recv(sockfd, buffer+offset, CHUNKS, 0);
if (rec > 0) {
offset += rec;
if ((offset+CHUNKS) >= size) {
temp = realloc(buffer, size+INCREM);
if (temp == NULL)
break;
buffer = temp;
size += INCREM;
}
}
...
} while (some_condition);
In this code the buffer is created with an initial size of IN_SIZE. The message is read in chunks
of 1024 bytes, and added to the end of the buffer.
The offset variable will contain the point of insertion of the data received, which is also the total
length of the data read.
In this code i didn't check for errors (except for realloc()).
There is a problem with this code: It expands the buffer although the memory is not needed yet
(and probably won't be needed), and the buffer grows using increments that can be too big or
too small. To expand buffer size after knowing the data won't fit into the current buffer you
could use a temporary buffer to hold data read, and if it doesn't fit then you expand the buffer
and copy the data.
You can also use the code above and after reading all the data you just allocate a new buffer
sized to the total bytes read, copy the data and deallocate the old buffer (i wouldn't do this but
some people may find it useful).
You can play around with the code until you find the solution that best solves your
requirements.
Add a Comment
New Questions: Telecom call routing
From: AGF
Your question tells me that you are establishing TCP connections or sendign UDP packets when
the clients dial the numbers. I suggest you change your approach to the one i explained above, it
resembles more closely the network (the lines are there already established, so are the TCP
connections, a new call is just some signals put on the line).
Regarding port numbers, you would use just one TCP port on the server, and the clients would
connect to this port. Each new client that is connected and is assigned an ID in your telephone
network is just like a new line that is added to the network.
The server could handle the connections using select(), threads, or even separate processes. As
you are working with small number of clients and the code doesn't seem to be very difficult i
suggest you use select(). Also as you need to handle a centralized structure to know states,
parties and stuff like that, you would have to be very careful when accessing those objects from
different threads.
:D (HAL)
Add a Comment
New Questions: why is inet_addr() not
working??
From: dhairesh oza
i tried compilling a code which used inet_addr(char *) to convert from dotted ip form to
sin_addr form but the compiler is saying unidentified symbol inet_addr in file tcp.c. i have
included files netinet/in.h and arpa/inet.h
this is on sco unix 7.1 so what might be the prob?
From: Rajaji
Check out the man page whether we need to include any library while compiling the code like
-lnsl, -lxns etc...
Add a Comment
New Questions: NFILE parameter increases!
From: Jessy
Hi there,
I've written a SOCKET server program on HP-UX 10.20.
I use close and then shutdown for all requests from clients to close their session.
But what I have noticed is that, the NFILE parameter of the system table increases
tremendously.
Isn't it suppose to decrease everytime a connection is closed?
Can someone please please please help me. I need to know how can I enusre that the NFILE
does not increase!
Everytime the a certain limit is reached(of the NFILE), I get the Accept : Too many open files
error scrolling on the console and the socket server is shutdown.
PLease someone help me. I am really confused and have come to a dead end!
Regards,
Jessy
From: Loco
If you fork() a process for every connection established, then you might be running out of file
descriptors on the listnening process if you don't close the peer socket file descriptor after
forking the other process.
:D (HAL)
From: Loco
Hi,
One common error is what i told in the previous comment. You fork() a child to handle a single
socket. This client shutdown()s and close()s the descriptor, however you don't close the
descriptor from the parent process, as it will be receiving new connections it will run out of fd
and won't be able to accept incoming connections.
If you printf the file descriptor returned by accept() it should be always the same if you close
them after forking children (and don't create new file descriptors in the mean time)
I hope this helps, however, posting code would be better if you don't find any solution.
Don't worry, i usually don't fee more than $3K or $4K per hour...
:D (HAL)
From: Anthony
Hi Loco,
where, for every accept call and child is forked, I do a close and shutdown process to the peer.
In fact the child processes are getting closed properly.
Maybe i'm not such expert because i cannot see any other posibility for such a problem. I would
like to take a look at your code if it is possible. If you don't want to post the code in the FAQ
there is no problem, just send it to my email address ([email protected]) and i will answer as
soon as possible. However, it's better to post the code in the FAQ cause many of the people who
access this site are really good in this and could find the problem as well. (Others are
completely crazy or don't have anything else to do)
It would be better that you send a simplified version of your code that can reproduce the
behaviour. I will test it on Linux and on HP-UX 10.20
I hope it is a programming error or something and not a problem with the OS (which i have
seen behave strangely under certain conditions - but what the hell i'm not an expert on this and
the sysadmin was doing a really bad job)
:) (HAL)
From: Anthony Raj
Hi Loco,
if (listen(sockfd,BACKLOG) == -1) {
perror("Error in Socket Listen listen \n",errno);
exit(1);
}
logfile=fopen("socketlog","a");
strcat(buf,readbuf);
TQ
From: Rob Seace
Hi Anthony,
Rob is right. Your shutdown() call should fail because the file descriptor is no longer valid after
close(). Probably the error is EBADF. As he says this is not the problem for the lost descriptors.
I would also like to see the parent code in the fork() where i think the problem might be.
You are either not checking for an error condition after the fork or always showing an error.
fork() returns:
>0 to the parent process indicating everything went just fine and the number will be the PID of
the child process.
0 to the child process (you are checkiing this)
-1 to the parent process indicating there was an error and the child could not be created.
I guess your code continues like this:
if (!fork()) {
your child code here
}
close(new_fd);
If you don't have this last line then you are losing file descriptors each time a new child is
created.
fork() creates a copy of your process which (fortunately or unfortunately) copy the file
descriptors, which means both processes will have file equal but separated file descriptors (just
like when you use dup(), but with the same number). So if you are not planning to use a specific
descriptor on one of the processes then you should release it.
:D (HAL)
Add a Comment
New Questions: Blocking Vs Non-blocking
From: Rajaji Selvarajau
Rajaji.
From: Loco
When you call IO blocking functions the OS will pause the thread until the task can be
completed (data available or buffers available). In fact, the thread will enter a special state
known as BLOCKED (i guess that is why they call it blocking calls). This means that the thread
stops executing until the OS can fulfill the caller's request or some other event happens.
Non-blocking function calls return inmediately whether the OS could or could not fulfill the
request. In the former case, it will return whatever the caller asked for (eg. data received), in the
later case it will return an error indicating that the operation could not be completed because the
system would have to block the thread.
Add a Comment
New Questions: TCP connection
re-establishment
From: Mahesh Kallanagoudar
regards,
mahesh
The only way i could get this behaviour is by shutting down the out stream on the socket
"shutdown(fd, 1);".
Unless you are not telling everything that happens i don't think the problem is caused by a
programming error but a system bug.
From: Mahesh Kallanagoudar
Rob,
I don't know TCP much. What is the difference between
CLOSE_WAIT and TIME_WAIT? I thought both are same.
Your guess is right. I close the fd and use the same
port. I shall try your suggestion of using system assigned port.
Hector,
By read, I mean it receives the data sent by the other party.
I also checked netstat it showns the connection in Established state.
That's what suprises me also. The thing is it works fine If I wait
for 4 mins before re-establishing the connection. In one of TCP FAQs,
I read a related comment by Richard Stevens. He says you should wait for
CLOSE_WAIT time, before re-establishing the connection. Otherwise, the packets
of previous connection which are stuck in some router may re-appear in the new
connection causing sequence number problems. He calls them
wandering duplicates.
regards,
mahesh
From: Rob Seace
Hi Rob,
Client()
{
if((sfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) {
printf("Error errno %d\n,errno);
exit(0);
}
gPollfd.fd = sfd;
gPollfd.event = POLLIN;
while(1) {
switch(poll(&gPollfd,1,-1)) {
case 0:
case -1:
break;
default:
/* Poll success case */
if(gPollfd.event & POLLIN) {
}
}
}
From: Mahesh Kallanagoudar
Hi Rob,
Client()
{
if((sfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) {
printf("Error errno %d\n,errno);
exit(0);
}
gPollfd.fd = sfd;
gPollfd.event = POLLIN;
while(1) {
switch(poll(&gPollfd,1,-1)) {
case 0:
case -1:
break;
default:
/* Poll success case */
if(gPollfd.event & POLLIN) {
}
}
}
From: Mahesh Kallanagoudar
Hi Rob,
Client()
{
if((sfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) {
printf("Error errno %d\n,errno);
exit(0);
}
memset((void *)&locAddr, 0, sizeof(struct sockaddr_in));
locAddr.sin_family = AF_INET;
locAddr.sin_addr.s_addr = htonl(INADDR_ANY);
locAddr.sin_port = htons(0);
if (bind(sfd, (struct sockaddr *)&locAddr, sizeof(locAddr)) < 0)
{
printf("sockbind failed errno 0x%x\n",errno);
close(sfd);
return -1;
}
regards,
mahesh
From: Rob Seace
I know you said the above code isn't real, and to ignore
errors, but I have to ask about the bit where you do the
re-connect... I'll assume you've got another connect()
up near the top, after your bind(), which you just don't
show... But, do you also have another socket() call, and
another bind(), prior to the connect() you do show, for
reconnecting after a broken connection? (Actually, you
really don't even need the bind() there, for a client...
The connect() will do your bind() for you... Best to just
let it do so... But, you DO need to recreate the socket
with another call to socket(), after you close it...) Also,
you probably don't want to JUST do it only on ECONNRESET,
either... What do you do for other errno values? It might
help to see more realistic code, because I don't know if
these are actual problems, or just problems in the sample
bogus code...
From: Hector Lasso
Hi,
Hi,
The actual code is bit hard to follow, So I provided the
sample code.
Client()
{
locAddr.sin_addr.s_addr = htonl(INADDR_ANY);
locAddr.sin_port = htons(0);
if (bind(sfd, (struct sockaddr *)&locAddr, sizeof(locAddr)) < 0)
{
printf("sockbind failed errno 0x%x\n",errno);
close(sfd);
return -1;
}
regards,
mahesh
Hi,
The actual code is bit hard to follow, So I provided the
sample code. I am not doing the obvious mistakes in the
actual code.
Client()
{
signal(SIGPIPE,reconnect);
/* reconnect() functions does exactly same thing what is
* shown currently when ECONNRESET error happens. close(),
* socket(), bind and connect().
*/
if((sfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP)) < 0) {
printf("Error errno %d\n,errno);
exit(0);
}
memset((void *)&locAddr, 0, sizeof(struct sockaddr_in));
locAddr.sin_family = AF_INET;
locAddr.sin_addr.s_addr = htonl(INADDR_ANY);
locAddr.sin_port = htons(0);
if (bind(sfd, (struct sockaddr *)&locAddr, sizeof(locAddr)) < 0)
{
printf("sockbind failed errno 0x%x\n",errno);
close(sfd);
return -1;
}
Hi,
I guess you are zeroing the sin_port element of locAddrright before calling bind() when
re-establishing the connection. If you don't do it then it could be a problem and this is where
Rob tells you to use 0.
However, bind() is not necessary (as Rob pointed early) because connect does this for you. I
suggest you get rid of all the bind() calls and let connect() take care of it.
If that doesn't work then i think it could be an OS bug. Check your OS' homepage to find out
about any documented bug related to the problem you've been facing.
From: Rob Seace
I tried removing all the binds on the Client side. But it didn't
help. As I explained earlier I am registering for SIGPIPE signal
. But I am not getting that SIGNAL whenever there is a break
in the TCP connection. Is it because socket is non-blocking.
I shall include EPIPE error also. I didn't get what do mean by
reconnecting when there is a random error. what about
errors which are not related Connection? Since we have only
one errno, it could be set because of someother unrelated
errors.
regards,
mahesh
regards,
mahesh
From: Mahesh Kallanagoudar
I tried removing all the binds on the Client side. But it didn't
help. As I explained earlier I am registering for SIGPIPE signal
. But I am not getting that SIGNAL whenever there is a break
in the TCP connection. Is it because socket is non-blocking.
I shall include EPIPE error also. I didn't get what do mean by
reconnecting when there is a random error. what about
errors which are not related Connection? Since we have only
one errno, it could be set because of someother unrelated
errors.
regards,
mahesh
regards,
mahesh
From: Rob Seace
Add a Comment
New Questions: single program acting as
server and client
From: bhavani
Iam doing virtual router project in which I have a single program acting as server and client.
The programs create server and client sockets, that should contact each other:
I know that one way is to do select but Iam confused with how to use it . If anyone can help
with this. I would be really thankful.
Add a Comment
New Questions: How can a server let other
server connect with a client ?
From: Jack
When a server receive a connection request, how can it let other server connect with this client ?
From: Loco
Be more specific. Give examples. I am not very smart so i cannot understand your question
clearly...
From: Jack
When a connect request was happened, I create a NEW socket, bind with OTHER PORT, and I
want the NEW socket connect with this client, how ?
From: Loco
I still don't get it.
Your server listens for connections. When one client connects you already have a connected
socket. But you want another one that connects from the server to the client, don't you?
If the client is not listening then you cannot do it, you will have to bind a port in the client and
listen for connections. The server can take the address of the client from the sockaddr_in struct
filled by accept()
Add a Comment
New Questions: CGI problems.
From: Sandra
Hi Sandra,
I guess your problem is that CGI's normally are run at the server side not the client side.
If you write an HTTP client then you are writing a piece of software that connects to a server
and asks for services, in this case an HTTP server.
CGIs are programs that are executed by the HTTP server to respond to certain requests from the
clients. The communication between server and CGI is done using a simple interface, so you
can write a CGI in almost any programming language supported by the particular OS you run
the HTTP server on. The decission to execute the program is taken by the HTTP server which
normally uses a configuration file and MIME types to take this decission.
Add a Comment
New Questions: which is best Fork () or
pthread ?
From: Baswaraj
-----------------------------------------------------------
THANKS IN ADVANCE
Baswaraj
From: Chris Gilliard
You may want to look into using the select() function. It does what you want to do without
having multiple processes/threads at the same time. The idea is that you can check multiple file
descriptors (in this case sockets) and the select call will block until there is something to be read
on one of the descriptors. This lets your program block until someone sends a message over the
socket. At that point you can handle it. There is a similar system call called poll. It may be more
efficent than select if you have a bunch of other file descriptors open which most likely not the
case, but read the man pages for more details on this. If you still want to use a forking or
threaded server, I'd perfer threads. Good luck!
From: Hector Lasso
Hi,
I would use a structure to pass data from one thread to the other.
When the "receiver" thread gets a request it just puts the request in the structure, fires an event
and continues waiting for data from the clients. When the client sends the data, then the
"receiver" thread puts the data in the same structure and once again fires the event.
The "processor" thread will wait indefinetely for the event, and when awaken, will read the data
in the structure and process the request, however, as the request and data for it don't come in the
same message, it will have to decide whether it can go on with that or just go back to wait for
another event. It's a classic producer-consumer approach.
It may or may not be the best way to do it, however, this is sockets FAQ and your question is
not related to sockets.
Add a Comment
New Questions: Timestamp
From: Andreas
I'm multicasting through the Internet. My question is: I want to create a buffer at the receiver
side. Since I am sending audio, the buffer should sort the packets. I need to include a timestamp
in the UDP-packets. Anyone have an example on how to do that?
From: Hector Lasso
Add a Comment
New Questions: Difference between port &
socket
From: Stefanie Stubb
Can anyone tell what is the difference between port & socket?
Add a Comment
New Questions: Client write to closed server
From: Fabrics
I have the following problem: my client tries to write to a server that has closed its socket, the
first time the client receives no exception in its operation so my message is lost, while the
second time it gets an exception.
How can I understand the fist time that the socket on server side is closed?
Thanks to everyone who will help me.
P.S.: I'm using Java.
Add a Comment
New Questions: How to flush a udp socket?
From: Itai Ashlagi
In a client/server, the client sends all the time udp packets to the server.
In the server I have sometimtes timeouts , so packets are accumalting in the
socket buffer.
After the timeout I want to clean the buffer and start recieving again.
How? (except reopening the socket).
Add a Comment
New Questions: Binding of RAW Sockets
From: Veeru
Hi,
Is it necessary to bind a RAW Socket with the local address.
I need the exact information about this.i need the information urgently.
Regards,
Veeru
From: Loco
Add a Comment
New Questions: Server does not receive
message sent by Client
From: Vijay
Hello,
I have a Client/Server application. The Client establishes a TCP Connection with the Server and
sends a message to the Server. But the server does not receive the packet until the socket
connection is closed or the Client terminates (effectively closing the socket).
Can anyone tell me why this is happening and how to over come this.
Thanks,
Vijay.
From: Fabrics
It is possible that you don't do the flush on your socket and so it is automatically flushed only
before closing it and the server receive it in that moment.
From: frankv
You may be trying to recv more bytes then are sent (and available) on the socket. In tcp/ip
SOCK_STREAM sockets there are no boundaries between messages, so
br = recv( fd, buf, 1024, flags );
will generally wait (block) until there are 1024 bytes available, because it assumes you *know*
there are 1024 bytes waiting.
Conversely the opposite may happen also. You may recv less then what you asked for even
though there should be more there. I am not sure if this actually happens though.
There are basically two ways to send messages with boundaries on SOCK_STREAM sockets.
1 - Always send the same size messages. This way you can safely specify the number of bytes
in recv().
2 - Send a header before the body which indicates how big the body is. That way you can read
the (fixed length) header first, followed by the body.
Add a Comment
New Questions: problems with sending files
From: Joakim Fredriksson
Hi, I have written a program that sends binary files using tcp/ip in windows.
The problem I have is that packets are lost, I have a while loop that reads in 4096 bytes at the
time from the file then send them on the socket without any sleep or slowdown, so I suppose
that I send to fast and that therefore packets are lost, but my question is how can I get the
OS/network to tell me if I`m sending to fast so I can slow down, its very annoying. Sure I can
put in a sleep or something but then the max speed I get is about 300kb/s without the sleep I`m
sending at >800kb/s
Add a Comment
New Questions: Difference between socket
and port
From: Stefanie Stubb
Hi,
a socket is an endpoint for network communication.
In simple, it consists of a ip-address to distinguish a host
and a port to distinguish the different communication channel on this host.
Thorsten
Add a Comment
New Questions: Forwarding data from one
interface to another
From: Jad
I have two ethernet cards , basically i have these two interfaces . I want to read a IP datagram
from one interface ,change the target IP address, and then output the datagram on the second
interface.The reverse should work also ie changes the source IP from interface 2 and outputs it
to interface 1.
The problem I am facing is how to make this work both ways without discarding received IP
datagrams.
(And, BTW, if you've got a Linux box, you can just do this
sort of thing with built-in kernel IP-masquerading, without
the need to write your own app at all, anyway... ;-))
Add a Comment
New Questions: problem with error
"unresolved text symbol" in UDP program
using recvfrom & sendto
From: Shivani
Add a Comment
New Questions: API to get state of socket?
From: Howard Lander
Thanks
Howard
Add a Comment
New Questions: Looking for advice on
non-blocking sockets
From: Loren Frank
Hi. I'm writing a data acquisition application that uses sockets but I'm running into problems
when I try to send large amounts of data from one program to another. I am sending messages
among the programs that make up the application and these messages contain either short
commands (a few bytes) or data buffers that can be fairly large (~400K).
Right now, I have everything set up to be non-blocking so that the programs can run
independently, checking for a message every few hundred microseconds to see if there is a new
message or new data. Everything works when the data messages are less than the socket buffer
size, but as soon as the messages get larger, the "write" that writes the message ends up writing
only a single socket buffer worth of information. I understand why this happens (the write fills
the buffer and then returns) but I don't know exactly how I should fix it.
So ... any advice on how I should write the messaging so that I can do transfers that are larger
than the socket buffer size?
Thanks,
Loren Frank
From: Rob Seace
Check out the code for the sock_write() function in the example code for this very FAQ...
You should always code your read()/write() calls similarly: wrap them in a loop to ensure
everything gets read/written, since there's absolutely no guarantee a single call will do the
whole job... Now, with non-blocking sockets, you're likely going to have to wait for a bit after
you fill up the write buffer, until it clears out again so you can start writing; otherwise, all your
write()'s will just immediately fail with EAGAIN/EWOULDBLOCK... You might need to
select() on it until it becomes writable again, or keep track of how much you've written so far,
and just periodically try to write a bit more... *shrug*
From: Loren Frank
That makes sense. The only problem I would then have is that it is important that the process
writing to the socket be able to write out the data and continue even if the reading process isn't
ready. The idea is that the data collection subroutine could go on collecting data even if the
processing routine that it talks to falls a bit behind. Is there any way that you know of to do
interprocess communications where arbitrarily large amounts of data are buffered by the
system, or do I have to write the buffering code as part of my program?
Loren
From: Rob Seace
Got it. I'm working on a linux system and, as I understand things, the maximum socket size is
set in the file /proc/sys/net/core/wmem_max. I can change that file to increase the size of the
buffer, but I have been a bit leery of doing so. Do you know what possible problems I might run
into? I'd like it to be a few megabytes, but I don't know what sort of side effects that might
cause. The only thing I found on that topic was a website that suggested it could be increased to
at least 8 MB (www-unix.gridforum.org/mail_archive/data-wg/pdf00000.pdf) but I'd like to be
sure....
Loren
From: Rob Seace
Well, the "/proc" file you refer to only controls the upper
limit; you'd still need to have your app increase its
default size to that limit via SO_SNDBUG setsockopt()...
(Or, you could also change the "wmem_default" proc file, to
make all processes get that size buffer by default... But,
that's probably not a good idea...)
No, I've never done this, and am not sure what bad
side-effects it might have... But, I really wouldn't think
there should be any... The only real factor should be how
much free memory you have available on your system... If
you start trying to have huge buffers large than your free
memory, then things will quite probably get a bit screwy...
(It'll probably have to dip into swap space for some of the
buffer, and drag down performance with tons of swapping...
But, even then, nothing majorly horrible should happen...)
But, assuming you've got the memory, I don't know why you
shouldn't be able to have it as large as you like... *shrug*
I guess the best thing to do is just try it; it can't do too
much damage... ;-)
Add a Comment
New Questions: how to specify a rang of port
numbers to be used
From: Ben
thanks in advance
From: Loco
When you open a TCP connection (i guess you are using TCP sockets) to a port, the client uses
any available port above port #1024 (unless you explicitly bind your socket), but the destination
port remains the same, so to allow a connection to be made through your firewall you just have
to open that particular port on the firewall accepting connections from any source port.
For example:
Your client is 192.168.1.100, your server is 192.168.12.5, you have a firewall separating both
networks (192.168.1.0 and 192.168.12.0). You have a daemon waiting for connections on port
80 (HTTP port) and want allow the client to connect to this port then you just add a rule to your
firewall like this:
The atual rule depends on your firewall, for example, in Linux using ipchains it would be:
ipchains -A input -p tcp -s 192.168.1.100 -d 192.168.12.5 80 -j ACCEPT
:)
Add a Comment
New Questions: Raw socket programming
From: Ramamoorthy
Hi,
I wants to capture the raw data packet. Can I use sockets (SOCKET_RAW option) for this
purpose. Or can I use any other method? Please help me out with source code examples.
Thanks
Ramamoorthy
From:
Take a look at the man page of raw(7)
"[...]A raw socket can be bound to a specific local address using the bind(2) call. If it isn't
bound all packets with the specified IP protocol are received. In addition a RAW socket can be
bound to a specific network device using SO_BINDTODEVICE; see socket(7) [...]"
Add a Comment
New Questions: IP-telephony
From: Anders And
In Unix you can use /dev/dsp to record and then send the buffer through a socket. My question
is how to open(play) it in windows? Unix uses open("/dev/dsp"...) and then write(...).
Thanks in advance.
Add a Comment
New Questions: re-establish socket
connection
From: Dave Hallett
I'm trying to write a server that can disable and re-enable reads. I can use
shutdown(fd, 0) to disable reads, but how can I re-enable reading on that same
socket?
Add a Comment
New Questions: Output Queue Gets Full
From: Peter Carlson
We have an application that gets a packet in and reflects it to a list of clients. The server is linux
and the clients are Winxxxx. Every now and then the output queue for one of the sockets gets
clobbered with 50k or so of data waiting to be sent. This causes the server to get real slow on
the send(). Any idea. We've had this problem twice now, porting the server to NT, made the
problem go away. Sigh...I'd rather have my server run on linux!
-Peter
Add a Comment
New Questions: Transfer a file using UDP
From: Kenny
I'm making a client/server program that transfers a file using UDP, but I'm having problems
with how to actually wrap and send the frames, and how to make sure it has reach it's
destination. And, no, not TCP allowed... Any help would be appreciated !!
From: Mr. Suggester
Send everything as bytes, otherwise you may be working on this for a long time. I don't know
your details, but maybe you should try raw sockets.
From: Loco
Well, about making the frames, i cannot help you. I just don't understand that thing about frame
size, packet size, window size and packet fragmentation.
However, to make sure your client received all the packets you sent him, you could use some
sort of acknowledgement from client to server. Take a look at the description of sliding window
protocols...
I've written a program that does this and it was a lot of work. I used around 1000 lines of code
to make it work properly (including broadcast support and the ability to send several files). It
can be done with less, but you still got a lot of work to do. The biggest problems was to make
sure that every package reaches it's destination and that the file doesn't get corrupted. Another
problem was actually to make it work to send several files. This may seem quite easy, but more
things can go wrong than you think. It can be differculd to find every bug in the code. A lot of
things can go wrong when using UDP. Things may work almost every time, but suddenly,
something fails, and you don't know what it is.
Are you really sure that you have to do it this way?
If you still want to do this, I may be able to help, but I want you to know that this isn't as easy as
it may seem.
Contact me if there is anything you want to know. Atleast, I know some of the misstakes that is
easy to make
Add a Comment
New Questions: SO_LINGER socket option
does not work
From: Evan
I am try to set the SO_LINGER socket option to avoid the TIME_WAIT state however when I
run the following code a call to netstat -a still reveals the socket in TIME_WAIT. Is it possible I
do not have the permission to set this option? I am running it on a university linux box.
//write buffer
write(temp_socket, "helloworld\n", strlen("helloworld\n")+1);
close(temp_socket);
Add a Comment
New Questions: Multiple Servers
From: Andy
Please give more details. What operating system (Unix or Windows - I presume), and what
architecture or platform are these machines on, for example Sun, HP, ...? It will be easier to
give you a more precise answer then.
From: Andy
It will be for the Linux Operating system and the Solaris stations (SUN OS 5.6). The aim is to
have a server on each monitored machine that runs checking script,
after a connection is made the raw data will be sent to the client processed and displayed as a
GUI interface.
Any references or suggestions will be great
Cheers
Add a Comment
New Questions: How to terminate the read/recv
call..?
From: Vijay
Hi,
I'm writing a client/server application using sockets.To read the data from the client/server I
tried with read() and again with recv().The problem is,both the functions didn't return "0" or
"-1" at the end of data.The functions simply hangs up(indefinitely waiting for some more data)
when end of data was reached without returning any values.Any one could suggest me how to
terminate the reading when end of data encountered? Any alternative methods r there to finish
the read/receive??
I set the options as
n=read(sockfd,buf,strlen(buf),0);
or
n=recv(sockfd,buf,strlen(buf),0);
Hi,
Regarding the question: I guess 'buf' is the buffer to hold the data recv'd and not the buffer
length. read() expects 3 parameters, so the last 0 is not needed. You should use the maximum
capacity of your buffer or the maximum number of bytes you expect to receive, and not the
current string legth in your buffer (i guess this is an error, but it might as well be ok because of
your program's logic)
There are many ways to "timeout" a call to recv/read, however i think the problem is in your
code or in your question:
When you mention "end of data" you mean the other end closed the connection, or just finished
sending some data?
Is the recv/read function call inside a loop, meaning it enters once again after it has returned
some data?
read/recv always block until data is available. That is their normal behaviour. They will not
return until data is available or a signal is caught.
You can change a file descriptor to non-blocking mode. That means it will behave a little bit
different, i suggest you read about non-blocking mode in this faq's section.
You can also use select() on sockets with timeout parameter which will let you regain control
after some period of time when no data is available.
Also, you could just set a timer with alarm() and then call read/recv, you'll have to set a signal
handler for this or your program will exit. When the signal handler returns, the function is
aborted returning -1 and errno=EINTR
Add a Comment
New Questions: Error in bindind an UDP
socket
From: Nedu
Add a Comment
New Questions: Invalid argument!?
From: James McLean
Everytime I try to utilize the function recv() it provides me with a totally inexplicable error:
Invalid argument... Despite my efforts at resolving this dilemma and reducing the code to its
most simplistic form, I am still unable to get passed this. Any suggestions?
From: Rob Seace
Add a Comment
New Questions: Blocking socket recv with
pthread
From: Jean-Sebastien
Add a Comment
New Questions: Instant Messaging Server
From: John
Thanx
From: Loco
I wrote an instant messaging service for my company. We had about 5 servers, each with
10,000 constant TCP connetions to it and it worked perfectly. The benifits of keeping constant
connections far outway the cons. Just make sure you are using at least the 2.4 kernel of linux, or
some other OS that supports a high level of open fds.
From: chris
but, how did you write the daemon? does he fork every time a connection's coming in? or how?
greets,
chris
Add a Comment
New Questions: How to detect if process id is
running
From: EPal
Try:
kill(YOUR_PROCESS_ID, SIGUSR1);
from within your code, if errno == ESRCH then your process did not exist...
If it is ok, then the process is now probably death because the default action for SIGUSR1 is to
terminate the process, unless it handles this signal...
I'll try to find more info on it...
:D (HAL)
From: Loco
Hi,
You can also use "getsid(PROCESS_ID);" which would return the session id of the process or
-1 when the process does not exist...
Some OSes have a "prctl()" system call that can be used to interact with a process, however i
have not found much documentation regarding this.
:( (HAL)
From: Rob Seace
Using a signal of 0, instead of a real signal#, in a kill()
will just check for the process being alive, but not send
any real signal...
Add a Comment
New Questions: Broadcasting Problem
From: redbull
I am having a very peculiar problem ..I am running my program on port 9099 on machine A , B,
C , D ..
I have set the socket on port 9099 to NON_BLOCKING mode and also it has been bound to the
host's IP addres
Now , when the app on Machine A broadcasts a datagram (the socket has been set to broadcast
mode) , over the
interface B/C addr to port 9099 , machines B, C , D on port 9000 are
NOT receiving any of my datagrams ?
However , I can do a point2 point communication(e.g A-B :9099)
Thanks in advance
Red
From: redbull
bull
From: Khubilai
Add a Comment
New Questions: select problem
From: red bull
Here is my code :
FD_ZERO (&readset);
FD_SET (sockfd, &readset);
signal(SIGALRM, NiceMonitor_handler);
alarm(20);
(void) setnonblocking(sockfd);
for (;;)
{
bcopy((char *)&readset, (char *)&rset, sizeof(readset));
n = (select (FD_SETSIZE,&rset,NULL,NULL,NULL));
if (n < 0 )
{
if (_nice_monitor_timeout == 1)
{
printf ("\n LEAVING NICE_MONITOR \n");
return;
}
else
printf ("\n ERROR in select () in NICE_MONITOR () ");
exit (EXIT_FAILURE);
}
if (n == 0 && _nice_monitor_timeout == 1){
printf ("\n....");
return;
}
Add a Comment
New Questions: peer-to-peer chat application
From: Selim
I need a peer-to-peer chat application code that is written in c/c++ computer programming
language and Berkeley sockets programming language immediately. How can I find such a
code.
Add a Comment
New Questions: help on UDP broadcasts
From: voci
Hi, Im having some trouble with broadcast UDP messages in linux (kernel 2.4.3). Basically Im
creating a socket as follows:
The socket gets bound properly and recieves any messages sent to it specifically (ie
192.168.0.151) but does not receive broadcast messages (ie 192.168.0.255 or 255.255.255.255).
Whats more, the code works correctly on a windows system (with the appropriate conversion
between sys/socket.h and winsock2.h).
Nathan
From: redbull
I thought Id answer my own question in case anyone is wondering. After much searching I
discovered that to recieve UDP broadcasts you need to bind the socket that is recieving them to
0.0.0.0, not the address of a specific ethernet adapter.
Hope this saves someone the 2000 hours of searching the web that I had to go through!
From: rebull
Add a Comment
New Questions: select question
From: redbull
Add a Comment
New Questions: Socket usage with Unixware
7.1.1
From: Belinda
Add a Comment
New Questions: How can I send data from
server to client?
From: shyang
I am a newer ,and Now I can receive data from client,but I can't send data to client ,How can I
do ?
Add a Comment
New Questions: socket source code
From: Dave Hallett
Where can I find the source code for socket system calls?
(e.g. socket, accept, listen, shutdown, setsockopt, etc)
From: Rob Seace
Add a Comment
New Questions: OPEN_MAX SUN app to Linux
From: Jesper Nordestgaard
Hi
I'm porting a C application from SUN to Linux. The only problem is the OPEN_MAX variable
defined in unistd.h.
This variable holds information about all open files e.g count. My compiler stops be course it
does not know this variable. What’s the name of the corresponding Linux variable?
From: Rob Seace
Add a Comment
New Questions: multi-threaded connections
From: Kallol
I m trying to connect to 3 different machines using threads but the problemm is that the some
threads are endlessly trying to connect....even when the receiving end (one of the 3 servers) is
ready to accept any connections....this is a random phenomenon but always atleast a single
thread loops trying to connect...........please give me ur advices
From: Shanawaz
Add a Comment
New Questions: Open connection!
From: Rajaji Selvaraju
Hi,
I am facing a dilemma and i want somebody to help me out on this please....
Let me explain my scenario here.
I opened a connection to the remote host and the data has been sent successfully only for the
first time(second time it fails). In the sender's side, i don't want to close the socket descriptor
and i want to use the same open descriptor for further transactions. Is it possible?
If not how do i over come this problem?
Please help me.
Thanks,
Rajaji Selvaraju.
Add a Comment
New Questions: accept file descriptor
From: HHoxha
Hi.
In pop service started by inetd when you telnet to port 110 you got a connection.
From this moment on , i imagine , this proccess has got its own file descriptors returned from
accept
call(inetd)How could one find these file descriptors for use ??Is there any mean.
Thanks
Hysen
Add a Comment
New Questions: Unix command to know the
ports.
From: Andy
Add a Comment
New Questions: Can UDP be used for sms
From: Tomaz
Hi
I'm new to socket programming can somebody help & advise me on this subject.I'm doing a
project to Send & Recv SMS(short messageing service) from a modem driver i like to know if
UDP Sockets can be used for this program Thanks in Advance Have a nice day..
Tomaz
From: udayan
You can do it if you are using a protocol like SMPP for short message services.The SMPP
PDU's that you make can be transported over UDP/IP
Add a Comment
New Questions: sending http request via proxy
From: Jharana Mehta
How can I make a URL connection through a proxy if the proxy server requires login
information (user name,
password)?
From: thirunadha rao
Here is the example using the username as thiru and password as abc. There are many utilities
available on the net to convert a given string to BASE64 encoding.
GET http://www.rediff.com HTTP/1.0 \r\n Proxy-Authorization: Basic dGhpcnU6YWJj \r\n
Add a Comment
New Questions: Can you help me.?
From: Carmen
sock = socket(.....);
And you want to show the socket descriptor in integer, then you should just
Add a Comment
New Questions: Reuse of socket descriptors in
linux
From: Yannis Pavlidis
Hi,
I am running my server on 2.2.16-22 red hat linux and I would like to ask the following
question. The Server accepts a connection from a client and I print out the socket handle. Then
after serving the request and closing the connection and accepting a new connecion the handle
is the same as in the first request. My question is does the kernel/tcp stack makes the socker
descriptor reusable immediatelly after it is closed? Cause in other OS I see that the socket
descriptor is keep incrementing.
Thank you,
Yannis.
From: Jean-Sebastien
Add a Comment
New Questions: Non-blocking client
From: Marvin Massih
Well, here's the code (the printf()'s are just debug messages):
int main()
{
//...
if(fcntl(socket, F_SETFL, O_NONBLOCK) != 0){
printf("Damn! Couldn't set non-blocking flag: %s\n",
strerror(errno));
exit(1);
} //...
}
old = s;
TIA
Marvin <[email protected]>
Add a Comment
New Questions: Multiple IP Address in Client,
how to....
From: Sudhakar Chakravarthi
Hi,
I am facing one small problem it will be greatful if you can guide me.
I am writing Client/Server program using socket.
My Client host is having two IP address(Two NIC Cards, ex 192.168.1.1 and 192.168.2.1). Two
NIC Cards each one in different LAN ie. my client is in two LANs )
I want to connect to the server 192.168.1.10. While connecting to the server do i need to
bind() the client end for the ip address 192.168.1.1(B'cos same LAN)? Or Operating system
itself will select the client interface?
Thanks in advance,
Sudhakar.
From: Rob Seace
Yes, it's possible... Though, it's generally a real pain to code... ;-) It typically involves a lot of
obscure ioctl() calls... Your best bet is to find code that does it, and copy it... Try the "ifconfig"
code for your system, or the libpcap source... Or, check if your system has the if_nameindex()
function available (it seems to be available under Linux, at least)... That makes things a lot
easier, by doing the really dirty work for you: obtaining the list of all local network interfaces...
Once you have that, it's fairly trivial to obtain the IP associated with each one, via
SIOCGIFADDR...
Add a Comment
New Questions: ERROR - CORE DUMP
From: sandy
Hi,
While running some of my C++ prgrms in solaris,I got a CORE dump
error.When I used dbx <prgrm name> core and then typed where
I got a runtime stack trace of all functions recurrsively called
One of the function on the stack was of the form
3] RWTValOrderedVector<RWCString>::insertAt(0x33764, 0x0, 0xeffd7524,
0x0, 0x0, 0x0), at 0xef718064
Add a Comment
New Questions: How to create Sockets in UNIX
From: Grottoli
People,
Thanx
From: Jacob Harris
Hello,
If you can, I'd pick up a copy of "Unix Network Programming," which gives the C API for
sockets on UNIX. You can find many of your questions answered here as well I'm sure, but that
is just an excellent book to own on the topic.
Yours,
Jake
Add a Comment
New Questions: Socket and mutual exclusion
From: Jean-Sebastien
I have a server that runs many threads (linux pthread) at the same time, and it is possible that
two threads write to the same socket (using 'send') at the same time.
Does socket implementation provides built-in mutual exclusion or I have to explicitly enforce it
using a mutex for each opened socket, to be sure that the data from
the two 'send' call is not all messed up.
Thanx!
From: Bill Ahern
Well, you can safely write PIPE_BUF bytes to a pipe() atomically. I dunno whether this applies
to sockets as well.
I had the same question, but never went ahead w/ my implementation. I believe POSIX requires
a minimum PIPE_BUF of something greater than 129 bytes (which is what I needed). I think
the POSIX requirement might by at least 2x's what I needed, I forgot.
Add a Comment
New Questions: Connection testing using
select() and recv()
From: Chad
Hello folks,
Thanks,
Chad
tcptest.c--------------------------------------------------
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
/* Check a socket for write ability using select() and read ability
using recv(... MSG_PEEK). Time-out values are also passed (seconds
and microseconds) for the select() call.
FD_ZERO(&checkset);
FD_SET(sock, &checkset);
to.tv_sec = tosec;
to.tv_usec = tousec;
return ret;
}
if (argc < 3) {
printf("Need arguments\nUsage: tcptest host port\n");
exit(1);
}
host = argv[1];
port = atoi(argv[2]);
memset(&inet_addr, 0, sizeof(inet_addr));
inet_addr.sin_family = AF_INET;
inet_addr.sin_port = htons(port);
inet_addr.sin_addr = *(struct in_addr *)hostinfo->h_addr_list[0];
/* Set non-blocking IO */
if ( (fdflags = fcntl(sock, F_GETFL)) >= 0)
fcntl(sock, F_SETFL, fdflags | O_NONBLOCK);
/* sleep(1); */
/* Try a read() */
bytesread = read(sock, (void *) buffer, 100);
if (bytesread == -1)
printf("read:%d, %s\n", bytesread, strerror(errno));
else if (bytesread == 0)
printf("read:%d, %s\n", bytesread, strerror(errno));
close(sock);
}
Add a Comment
New Questions: testing TCP related APIs!!
From: Prem
Does somebody have any idea about any existing work to test the TCP related API's ( like
socket, connect, send etc)
I am looking for an application which does the verfies the general functionalities of these API's.
Thanks!
Add a Comment
New Questions: How can I prevent from losing
data ?
From: jack wei
I create a socket with SOCK_STREAM, and use select() to check data available.
When select() returns this socket are ready for reading, I use recv() to read it.
But when the data size is larger(260120 bytes), It's wrong -- some data is lose.
...
...
result:
recv 8192 bytes data.
Leave length:243820.
recv 8192 bytes data.
Leave length:235628.
recv 8192 bytes data.
Leave length:227436.
recv 8192 bytes data.
Leave length:219244.
recv 8192 bytes data.
Leave length:211052.
recv 8192 bytes data.
Leave length:202860.
recv 8192 bytes data.
Leave length:194668.
Add a Comment
New Questions: Disconnecting from modem
From: Sunil Philip
Hi,
I have a server program which receives data from client.
The problem that iam facing is,when i disconnect my modem iam not able to know whether the
client is disconnected or not.On the other hand, when i physically close the client program my
server is able to detect that.
Can anybody help me plz.
sunil
Add a Comment
New Questions: Receiving packet over a
specific interface?
From: Phani
Thanks
From: Rob Seace
I am writing a socket, which just sit there waiting for income data(so I decided to use UDP),
and then display all the income data. I use sock_dgram. I have a question about how to use
recvfrom function. The income data maybe very large(I have no idea how large it will be), if it
is larger than the buffer size in recvfrom function, it will return error message: errno
EMSGSIZE triggered. Do you have a solution for this.
while (1) {
n=recvfrom(sock,buf,buffSize,0,(struct sockaddr *) &from,&fromlen);
if(n<0) error("ERROR on recvfrom");
printf("Here is the data: %s", buf);
}
return 0;
}
Most operating systems max buffer size for a packet is limited to 8192 by default.
replace your 4096 with 8192. This makes it faster. And then make a loop until recvfrom returns
0.
Remember that unlike TCP packets, sometimes UDP packets can be lost. If this is a
mission-critical program then make your own ACK system.
good luck...
-Melih
Add a Comment
New Questions: 6 second delay ...
From: Eli Sidwell
All,
I have program that moves data from a Unix box to a windows box socket to socket. The
problem is that I experience a 6 second delay when the windows box sends data to the Unix
port.
This problem has been present for some time, but I was told that before we had Nortel network
switches and routers installed that this problem did not exist.
My network guru tells me that nothing should be wrong and he sees a bunch of NetBeui traffic.
I believe the delay is encountered when the Windows box transmits back to Unix
Sid...
Add a Comment
New Questions: Ho to make blocking send
with UDP socket?
From: DrWatson
I need blocking "send" call with UDP socket on Linux. What should I do?
From: Loco
Hi,
All your socket calls are blocking by default. If you haven't changed your file descriptor's mode
then you are issuing blocking calls.
Blocking write means the call will wait until there is enough room in the buffer to hold the data
you are trying to send, not until the other party gets the data.
:D (HAL)
From: DrWatson
long bytesSent = 0;
while (true) {
bytesSent+=sendto(...);
if (some_condition) break;
}
Add a Comment
New Questions: TCP Sockets with pthreads
From: Don
Is it possible to have one thread do a blocking read from a TCP socket while another thread
does a blocking write from the same TCP socket? Will the separate threads work completely
independently or might one thread block, waiting for socket resources being used by the other
thread?
Add a Comment
New Questions: Unable to catch SIGCHLD on a
HP workstation.
From: Jyoti
Hi!!,
while running the following on a HP Work station, I get the following error message everytime
the child process exits.
Pid 27218 was killed due to failure in writing the signal context.
vxfs: mesg 001: vx_nospace - /dev/vg00/lvol5 file system full (1 block extent)
Memory fault
Kindly help..
Thanks in Advance..
Thanking you,
Jyoti
Add a Comment
New Questions: Unable to catch SIGCHLD on a
HP workstation.
From: Jyoti
Hi!!,
while running the following on a HP Work station, I get the following error message everytime
the child process exits.
Pid 27218 was killed due to failure in writing the signal context.
vxfs: mesg 001: vx_nospace - /dev/vg00/lvol5 file system full (1 block extent)
Memory fault
Kindly help..
Thanks in Advance..
Thanking you,
Jyoti
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<signal.h>
#define SERV_TCP_PORT 5000
void sig_handler(int)
{ int status; pid_t pid;
signal(SIGCHLD,sig_handler);
printf("Child killed\n");
if((pid=wait(&status))<0)
{
perror("wait eror\n");
printf("pid=%d\n",pid);
}
return;
}
main(argc,argv)
int argc;
char *argv[];
{
int sockfd,childsockfd,clilen,childpid;
struct sockaddr_in cli_addr,serv_addr;
/* Open a TCP Socket now...*/
if((sockfd=socket(AF_INET,SOCK_STREAM,0)) < 0)
perror("Server: Cant open the socket\n");
/* Now initialize the "sockaddr_in" structure...*/
bzero((char *) &serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_addr.sin_port=htons(SERV_TCP_PORT);
if((childpid=fork())<0)
perror("Server: Fork Error\n");
if (childpid==0)
{
if(execlp("/usr/bin/X11/xterm","xterm",(char *)0)<0)
{
perror("Exec Error\n");
exit(0);
}
Add a Comment
New Questions: Unable to catch SIGCHLD on a
HP workstation.
From: Jyoti
Hi!!,
while running the following on a HP Work station, I get the following error message everytime
the child process exits.
Pid 27218 was killed due to failure in writing the signal context.
vxfs: mesg 001: vx_nospace - /dev/vg00/lvol5 file system full (1 block extent)
Memory fault
Kindly help..
Thanks in Advance..
Thanking you,
Jyoti
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<signal.h>
#define SERV_TCP_PORT 5000
void sig_handler(int)
{ int status; pid_t pid;
signal(SIGCHLD,sig_handler);
printf("Child killed\n");
if((pid=wait(&status))<0)
{
perror("wait eror\n");
printf("pid=%d\n",pid);
}
return;
}
main(argc,argv)
int argc;
char *argv[];
{
int sockfd,childsockfd,clilen,childpid;
struct sockaddr_in cli_addr,serv_addr;
/* Open a TCP Socket now...*/
if((sockfd=socket(AF_INET,SOCK_STREAM,0)) < 0)
perror("Server: Cant open the socket\n");
/* Now initialize the "sockaddr_in" structure...*/
bzero((char *) &serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_addr.sin_port=htons(SERV_TCP_PORT);
if((childpid=fork())<0)
perror("Server: Fork Error\n");
if (childpid==0)
{
if(execlp("/usr/bin/X11/xterm","xterm",(char *)0)<0)
{
perror("Exec Error\n");
exit(0);
}
/* The control should never reach here....... */
else
perror("New Child Session Started\n");
exit(0);
}
printf("Waiting fro my childs death\n");
}
if((close(childsockfd))<0)
printf("Error closing the socket\n");
exit(0);
}
Add a Comment
New Questions: Try to make a secure
conection
From: ptic
Hello, i have made conection with socket in C, i want to know how to secure the conection,
only register client can connect to the server (with a login and password)
thanks
Add a Comment
New Questions: Error while compiling
From: Jyoti
Hi!!
while compiling my C programme with the following switches,
while creating the executable with any other name, the operation is successful
Kindly Help..
Thanking you,
Jyoti
Add a Comment
New Questions: ftp server bind with
REUSEADDR ?
From: Brent Thomas
update:
Add a Comment
New Questions: Specific concurrent server
port
From: Treke
Hello.
Thanx in advance
Ed Toth (Treke)
From: Treke
So, you have two separate processes, and you open a new
socket (via accept()) in one, and which the OTHER one to be
able to then write to it? Well, ok, you could do that by
just passing file descriptors from one to the other... To
do that, look into sendmsg()/recvmsg(), using SCM_RIGHTS...
(On my system, an example of passing file descriptors this
way can be found in the "man cmsg" page...) You'd need a
separate Unix-domain connection between the two processes,
to pass the FDs over, as well...
Aside from that though, you don't really have many other
choices, I don't think... Aside from simply restructuring
your program, if that's possible... Ie: have the same
process that accept()'s (or, a direct child of it) do the
sending/receiving of data...
Add a Comment
New Questions: socket deadlock
From: phil
I have a situation where 2 connected sockets both end up blocking in a call to bsd_recvfrom
(according to debug):
This occurs regularly, though at unpredictable (to me) instances. I have lots of other information
including a log of all socket functions called by the programs, along with the corresponding
tcpdump output. I will post these as needed. The basic behavior of the programs is:
1) client connects to the server
2) server accepts
3) client calls send() and immediately falls into a recv() at which point it blocks waiting for the
response
4) the server returns from select(), gets the client's request via recv() and immediately calls
send(), thereby completing the server part of the cycle - it then returns to select() for the next
request
5) the client returns from recv() with the server's response, thereby completing the client part of
the cycle.
The same socket is used for sending and receiving. The client has at least 2 connections to the
server. The server has many different applications connecting to it, all following the same
"protocol" outlined above.
Thanks in advance...
Phil
From: phil
I forgot to mention that the client and the server are always both on the same machine, and the
sockets are INET style, not UNIX.
Also, here is a bit more info for those of you who are too shy to ask.
TCPDUMP:
23:06:08.20 127.0.0.1.22679 > 127.0.0.1.2141: P 12517:13113(596) ack 12517 win 16384 (DF)
(ttl 64, id 56117)
23:06:08.26 127.0.0.1.2141 > 127.0.0.1.22679: P 12517:13113(596) ack 13113 win 16384 (DF)
(ttl 64, id 56155)
23:06:08.30 127.0.0.1.22679 > 127.0.0.1.2141: P 13113:13709(596) ack 13113 win 16384 (DF)
(ttl 64, id 56184)
23:06:08.31 127.0.0.1.2141 > 127.0.0.1.22679: P 13113:13709(596) ack 13709 win 16384 (DF)
(ttl 64, id 56203)
23:06:08.51 127.0.0.1.22679 > 127.0.0.1.2141: . ack 13709 win 16384 (DF) (ttl 64, id 56374)
23:06:19.81 127.0.0.1.22679 > 127.0.0.1.2141: P 13709:14305(596) ack 13709 win 16384 (DF)
(ttl 64, id 10792)
23:06:19.85 127.0.0.1.2141 > 127.0.0.1.22679: P 13709:14305(596) ack 14305 win 16384 (DF)
(ttl 64, id 10844)
23:06:19.88 127.0.0.1.22679 > 127.0.0.1.2141: P 14305:14901(596) ack 14305 win 16384 (DF)
(ttl 64, id 10939)
23:06:19.92 127.0.0.1.2141 > 127.0.0.1.22679: P 14305:14901(596) ack 14901 win 16384 (DF)
(ttl 64, id 11060)
23:06:20.12 127.0.0.1.22679 > 127.0.0.1.2141: . ack 14901 win 16384 (DF) (ttl 64, id 11702)
23:06:29.85 127.0.0.1.22679 > 127.0.0.1.2141: P 14901:15497(596) ack 14901 win 16384 (DF)
(ttl 64, id 47716)
23:06:29.87 127.0.0.1.2141 > 127.0.0.1.22679: P 14901:15497(596) ack 15497 win 16384 (DF)
(ttl 64, id 47775)
23:06:30.07 127.0.0.1.22679 > 127.0.0.1.2141: . ack 15497 win 16384 (DF) (ttl 64, id 48603)
23:06:43.85 127.0.0.1.22679 > 127.0.0.1.2141: P 15497:16093(596) ack 15497 win 16384 (DF)
(ttl 64, id 49324)
23:06:43.96 127.0.0.1.2141 > 127.0.0.1.22679: P 15497:16093(596) ack 16093 win 16384 (DF)
(ttl 64, id 49921)
23:06:44.03 127.0.0.1.22679 > 127.0.0.1.2141: P 16093:16689(596) ack 16093 win 16384 (DF)
(ttl 64, id 50264)
23:06:44.11 127.0.0.1.2141 > 127.0.0.1.22679: P 16093:16689(596) ack 16689 win 16384 (DF)
(ttl 64, id 50685)
23:06:44.31 127.0.0.1.22679 > 127.0.0.1.2141: . ack 16689 win 16384 (DF) (ttl 64, id 51658)
23:06:55.70 127.0.0.1.22679 > 127.0.0.1.2141: P 16689:17285(596) ack 16689 win 16384 (DF)
(ttl 64, id 48496)
23:06:55.90 127.0.0.1.2141 > 127.0.0.1.22679: . ack 17285 win 15788 (DF) (ttl 64, id 49564)
The processes blocked at this point. When the operators notice the processes are hung they kill
the client...
23:18:01.79 127.0.0.1.22679 > 127.0.0.1.2141: F 17285:17285(0) ack 16689 win 16384 (DF)
(ttl 64, id 40982)
23:18:01.79 127.0.0.1.2141 > 127.0.0.1.22679: . ack 17286 win 15788 (DF) (ttl 64, id 40983)
23:18:03.46 127.0.0.1.2141 > 127.0.0.1.22679: P 16689:17285(596) ack 17286 win 16384 (DF)
(ttl 64, id 49594)
23:18:03.46 127.0.0.1.22679 > 127.0.0.1.2141: R 1648373204:1648373204(0) win 0 (ttl 64, id
49599)
APPLICATION LOG:
Note - the application logs each call to socket functions immediately upon return from that
function via a fifo to another application which writes the log message to a file. Also, the
tcpdump time is an hour behind the application time - go figure...
Hmmmm... no takers yet. Is it because of too much data? Or its been read and nobody has any
ideas? If its the former, here is a more concice outline:
Q = query
R = response
client:
send Q1 596 bytes
return from send
recv
wait in bsd_recvfrom
return from recv R1 596 bytes
[process response]
[process response]
server:
select
Q1
01-06-01_00:06:43 send 22679:2141
01-06-01_00:06:43 recv 2141:22679
23:06:43.85 127.0.0.1.22679 > 127.0.0.1.2141: P 15497:16093(596) ack 15497 win 16384 (DF)
(ttl 64, id 49324)
R1
01-06-01_00:06:43 send 2141:22679
01-06-01_00:06:43 recv 22679:2141
23:06:43.96 127.0.0.1.2141 > 127.0.0.1.22679: P 15497:16093(596) ack 16093 win 16384 (DF)
(ttl 64, id 49921)
Q2
01-06-01_00:06:44 send 22679:2141
01-06-01_00:06:44 recv 2141:22679
23:06:44.03 127.0.0.1.22679 > 127.0.0.1.2141: P 16093:16689(596) ack 16093 win 16384 (DF)
(ttl 64, id 50264)
R2
01-06-01_00:06:44 recv 22679:2141
01-06-01_00:06:44 send 2141:22679
23:06:44.11 127.0.0.1.2141 > 127.0.0.1.22679: P 16093:16689(596) ack 16689 win 16384 (DF)
(ttl 64, id 50685)
23:06:44.31 127.0.0.1.22679 > 127.0.0.1.2141: . ack 16689 win 16384 (DF) (ttl 64, id 51658)
Q3
01-06-01_00:06:55 send 22679:2141
23:06:55.70 127.0.0.1.22679 > 127.0.0.1.2141: P 16689:17285(596) ack 16689 win 16384 (DF)
(ttl 64, id 48496)
23:06:55.90 127.0.0.1.2141 > 127.0.0.1.22679: . ack 17285 win 15788 (DF) (ttl 64, id 49564)
Also, if anyone knows why and when acks are sent (with no flag or data), I'd like to know.
Thanks.
From: Rob Seace
About the client FD discrepency, the debug stack dump and the application log extracts were
taken from different days, but the stack dump is ALWAYS the same.
The clients open/close connections up to 4 times per second rather that maintain a single
connection - totally unnecessary, but the code's so badly written (its not mine...) that its
imossible to change this - the TCP stuff is ok, but its mish-mashed with a ton of other stuff.
Even though, theoretically, I guess that that should not cause problems. I will try using
AF_UNIX sockets instead of AF_INET - *shrug*.
Thanks again.
Add a Comment
New Questions: Select problem with NT and
Solaris sockets
From: Jacob Harris
I seem to have a rather interesting problem on my hands. I have a centralized service that had to
be written in NT that fields requests from many separate Solaris processes with threads. Since it
is Windows NT, the service occaisionally crashes, and sometimes I find that the Solaris client
hangs on the read (despite the use of a select). The code in the client looks something like the
following:
Ooops,
timeval tv;
tv.tv_sec = timeout_value;
tv.tv_usec = 0;
As near as I can tell, it seems to get stuck on the read. It seems that the remote service crashes
between the select call and the actual read. Select indicates there is data to be read, but the read
itself blocks waiting for data (it seems that the socket does not receive a close). The stack trace
reveals it's sitting in _poll, although I can't seem to find who's calling that (the read or the
select). It's obviously a race condition, but what can I do to avoid such a situation? Would
peeking at the socket's data help? Or would that fall victim to the same race condition?
Yours,
Jake
From: Rob Seace
Hello,
Thanks for the insight. It has some good ideas. Of course, I'm a bit perplexed, since the select
seems to block for longer than the timeout setting. So, is it possible for select to block without
timing out, or perhaps timing out on the longer TCP timeout (those can be tweaked in the
Kernel)? In any event, it seems like the NT machine is having problems due to another service
generating a ton of network connections that get stalled in FIN_WAIT_1 (mentioned in another
question on this site?). We'll see what's up with that.
Yours,
Jake
From: Jacob Harris
Well, it wasn't the OS, but the server application, through what turns out to be a rather stupid
bug. It does seem like NT fails to close the connections properly or something. Still, there is a
problem with using KEEPALIVE on the client side. According to my understanding, Keepalive
has 4 behaviors:
The problem is that this doesn't seem to be working for the client. I purposefully kill the server
and restart, but I get neither an immediate response (eg, RST from NT) or the timeout. It almost
seems like NT is keeping the connection open in some sort of limbo. Does this sound familiar to
anyone, or am I just a bit confused?
Yours,
Jake
From: Jacob Harris
Duh! I forgot that Keepalive probing is not triggered until tcp_keepalive_interval msec has
passed on the connection. By default, under Solaris, it's 7200000 or 2 hours. I'll keep that for
now I guess, but do people here prefer tweaking that to lower values with ndd (I know, it can be
dangerous to get too low).
Add a Comment
New Questions: Where can I find the source
code for server written for broadcasting audio
?
From: shilpa
Where can I find the source code for server written for broadcasting audio ?
Is Perl version of the same available anywhere?
Add a Comment
New Questions: download component on Unix
From: Satish Suttatti
Hi,
would like to have a component in C++ which would download a url...preferably running on
Unix and other platforms.
Pointers to the same will be appreciated!
Thanks
Satish
Add a Comment
New Questions: UDP server question
From: Andy G
I am trying to "proxy" between two boxes communicating via UDP. They each have a client
server pair on them, with both servers using port 3386. The problem I have is that if I put a
server on my "proxy" box, on port 3386, it receives packets from both hosts, but does not know
which one to send on to after processing.
Is there a way that I can either differentiate packets arriving based on their source IP address,
or, can I set up two servers, each of which will only accept packets from specific IP addresses?
Andy
From: Loco
1) You can check the source address of the received packet by using recvfrom() function.
(This is just an example, no error checking...)
In this example, to1 and to2 are sockaddr_in structs that have the addresses of each client.
After receiving a packet the source address is compared against one of the addresses and the
destination of the packet is defined based on the result. Then the packet is sent using the same
socket it was received on.
2) You can bind your socket to any of the addresses you have on your computer:
(no error checking)
addr.sin_port = 3386;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("192.168.1.100");
len = sizeof(addr);
// bind first socket on 192.168.1.100
bind(sock1, &addr, len);
addr.sin_port = 3386;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("1.2.3.4");
// bind second socket on 1.2.3.4
bind(sock2, &addr, len);
And voilà, you have two UDP sockets bound to two different IP addresses, but on the same
port.
You will receive packets on one socket and send through the other one. Probably you will use
select() to know when data is ready on any of them...
:) (HAL)
Add a Comment
New Questions: Regarding connect system
call
From: manjunath.m.n
I this connect system call is being called without any socket system
call. But all I found is it is initially checking whether
inetd is configured properly or not. further, it is used for
connection oriented socket. Please reply asap.
Add a Comment
New Questions: Could someone explain me
something strange
From: Jean-Sebastien
Hi,
I develop a server on linux which runs on a machine connected to
the internet. I run clients to test the application on machines
that are in a LAN behind a firewall which can access the internet
by a gateway. (I'm not sure what I'm saying is correct since I'm
not very familiar with network component, but I have different IP on
LAN and on the Internet). So my program establish a persistent TCP
connection between server and client. The client is a Windows program
and it seems to happen sometime that the server recv a packet
of length 0 from a socket without the client explicitly send
a close. In that case my server program close the socket because
it thinks the client close the socket on his side which cause
a problem when the client did not actually close the socket in fact.
Does somebody have any idea why I would receive a messge of length
0 from a socket which has not been explicitly closed on the client
side? Is it possible that it is caused by the gateway between
the LAN and the Internet?
Thanx a lot
Jean-Sebastien
Add a Comment
New Questions: what is HUP
From: Tomaz
Add a Comment
New Questions: Java Multicast Client with two
NICs
From: Sandi
I am trying to write a Multicast Client in Java 1.2 using the java.net.MulticastSocket. The
problem is that my client host has two NIC cards connected to two different networks. I need to
specify an interface for the socket to bind to at creation time because the interface that I need to
receive on is not the default, INADDR_ANY.
There is a method setInterface() for the MulticastSocket, but it seems to be only for outgoing
packets because it does not change the local address. Also, I've looked at the Java 1.3 source for
the MulticastSocket and when it binds the socket it specifies INARRD_ANY as the local
address to bind to. There does not seem to be anyway to set the local address on a
MulticastSocket.
Thanks,
Sandi
Add a Comment
New Questions: Creating non_blocking
sockets
From: Mathew
Hi,
I have a server program running on linux (developed in c).I am not able to make my socket
non_blocking.I tried with fcntl(socket,F_SETFL,O_NONBLOCK) but it did not work.Can
anybody please help me.
Iam not so experienced in socket programming.
thank u
Mathew
From: Rob Seace
Add a Comment
New Questions: how to write a port scanner on
unix using c c++
From: sinni
Hi,
Why reinvent the wheel? If you want an excellent (and free) port-scanner, use nmap... Or, if
you just want to see how one works, it comes with full source code, too...
Add a Comment
New Questions: how can i attach file in a email
From: steve
Add a Comment
New Questions: strings
From: bob
how can i take the first letter of a string so that it can be compared with another character??
From: Loco
char mystring[20];
strcpy(mystring, "Hello world");
if (mystring[0] == 'X') // Comparing 'X' versus first char
printf("The first character in %s is X"\n", mystring);
else if (mystring[0] == 'X') // 'H' vs first char
printf("The first character in %s is H"\n", mystring);
(HAL)
Add a Comment
New Questions: Listening for remote socket
error using poll
From: Oliver
I (as client) am trying to use poll to listen to server errors, mainly a shutdown. So I would like
to get notified that the server has shutdown, and i am trying to accomplish this by using:
Add a Comment
New Questions: accept(); fills sock_addr
structre with the same ip forever after one fail
From: MAT
After Accept fails once ( return -1, usually because a client left before i got around to him )
from that point on accept() will always fill my stuctures with the same client ip forever
Add a Comment
New Questions: Info
From: Justine James
Thanking you
Add a Comment
New Questions: how to find the memory used
by the Stack and the Heap for a function??
From: Jyoti
Hi!! ,
could me suggest me any method to find the amount of memory
used by the stack and heap of a process while execution at any stage?
Thanks in advance,
Jyoti
From: Joy Patra
Add a Comment
New Questions: where is the memory fora
local array allocated
From: jyoti
Hi!!,
I have a lil doubt. As I always thought, memory for an array is allocated
on the heap during the compilation. But what about an array that is declared and initialised
inside a function?? The memory allocation is in the Stack or Heap?
Thanks in advance,
Jyoti
From: jdev
Add a Comment
New Questions: Async. IO, How to store
Clients IP and Port
From: Chandra
Hi,
Scenario :
1. create a TCP/Stream socket using socket() call - Call bind() and listen() to
make this a listening socket.
2. Use select() to accept connections - ie., the server would be infinitely blocking till a
connection comes, and select will be used to notify a connection request to the server.
3. Without calling an accept(), again use select() on the listening socket to recv data.
4. After recving data, trying to echo back the data() using select() again on the listening socket
only.
As from the above scenario, none of the calls listen(), select(), recv() store the information
about the clients port and address which are required for send() operation to succeed on stream
sockets.
Now the question is, when and how should we store the info. regarding the client's IP and port
so that send() succeeds. Is there any prescribed/standard way for this.
Thanks
Chandra.
From: Loco
Hi,
You say you are reading from the bound socket that is currently listening for new connections?
Well, that is not the way it is supposed to work:
The socket you bind and listens on a port should "yield" a new socket for every connected
client. That is the purpose of accept(): it gives you a socket descriptor of a new connection.
You should listen() for connections, when select() returns, accept() a new socket descriptor, add
it to the fd_set, and when there is data ready from this descriptor just read it!
Add a Comment
New Questions: writing to socket descriptor
newSD
From: Flash gordon
Hi
output on netscape:
.
.
.
strcpy(send,"Content-Type: application/x-shockwave-flash");
write(newSD, send, strlen(send));
movie.WriteMovie(newSD);
close(newSD);
}
return 0;
}
Add a Comment
New Questions: What is UMODE
From: Mike
Hello
I would like to know what does UMODE means.
Thanks in advance
Mike
From: susi
Hi Again,
Thanks for your response..sorry for not beign clear about UMODE,I came across a article in
Linux saying
User and group ID to create files as Umode in Linux OS..
Just wanted to clear myself on this.
Thanks & Regards
Mike
Add a Comment
New Questions: Socket error
From: Sougat
Hi,
I am receiving an error when I try to start Websphere Commerce Suite on Aix4.3.3.
CMN0310E: The socket name is already in use.
CMN0519E: Server controller TCP/IP service 'newcom' is already in use, an instance of server
controller may already be running.
The problem gets resolved when we reboot the machine. Could someone tell as to how to
resolve this problem without reboot.
Thanks,
Sougat
Add a Comment
New Questions: ENOBUFS Returned from
Connect()
From: Harvey Davis
Add a Comment
New Questions: Broadcast UDP on linux gives
ENOPERM
From: Steve Carter
Just what it says on the title, really. I get ENOPERM when trying to sendto() UDP packets to
my broadcast address.
Add a Comment
New Questions: TCP programming
From: SM
I wrote a simple client/server program using TCP protocol under NetBSD OS. The client sends
data at rate 800Kbps, but the server's cell loss rario (CLR) is too high, more than 18%. The
higher sending rate, the more CLR.
I can't understand the result. If I use UDP, there is no CLR even at rate 10Mbps.
Add a Comment
New Questions: Program exits with code 141
during recv()
From: Willem Roos
Hi all,
My threaded socket server exits during the recv() system call with exit code 141 - ie. the recv()
doesn't return, the whole program exits. No SEGV, no nothing. Same behaviour on AIX and
Unixware. Has anyone seen this before?
From: Rob Seace
Just a guess: you're getting hit with SIGPIPE, and you have
no handler (and, aren't ignoring it)... SIGPIPE is very
common, and MUST be expected in all sockets code... I
always simply ignore the signal, myself (then, you can just
easily deal with the read()/recv()/write()/send() failures,
with EPIPE)...
Add a Comment
New Questions: recv()?
From: Ramon Alvarez
Hey, I'm trying to get into socket programming, this will be easily answered I'm sure but will
save me from having more headaches...I'm connecting to a deamon on whatever port and such
and when I connect it sends me 4 or so values. I've been told to refer to them as ints, but I keep
calling them, in this case, numbers ;p. How could I get those numbers printf()'d and how would
I go about multipling them together and sending them back?
Add a Comment
New Questions: please.... run it always wrong (
on linux 7.0)
From: kolp
proto.h
#define PORT 2345
#define CHALLENGE 0
#define CORRECT 1
#define WRONG 2
struct mrecv {
int flag;
int b[4];
char nextpass[10];
};
struct msend {
int answer;
char prevpass[10];
};
typedef struct msend t_send;
int answer;
char prevpass[10];
};
typedef struct msend t_send;
newbie7.c
#include "proto.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>
#include <arpa/inet.h>
int
main ( int argc ,char **argv){
int s;
int reclen;
int answ;
struct sockaddr_in sa;
t_recv m_recv;
t_send m_send;
if ( argc != 3 )
printf ( " %s USAGE: %s < host > <port> \n ",argv[0],argv[0]);
if ( (s=socket(AF_INET,SOCK_STREAM,0)) == -1)
printf ( " THE SOCKET IS ERROR!!! \n ");
if (strcmp((char *)m_recv.flag,(char*)0)==0)
answ = (m_recv.b[0])*(m_recv.b[1])*(m_recv.b[2])*(m_recv.b[3]);
else printf ( " THE CHELLENGE IS WRONG \n ");
m_send.answer = answ;
m_send.prevpass[0]='3';
m_send.prevpass[1]='S';
m_send.prevpass[2]='i';
m_send.prevpass[3]='g';
m_send.prevpass[4]='e';
m_send.prevpass[5]='1';
m_send.prevpass[6]='V';
m_send.prevpass[7]='e';
m_send.prevpass[8]='\0';
Um, no, that's not valid either... What exactly are you
trying to do?? I can't tell you the correct way to do it,
until I know that... And, I just can't even hazard a guess
at what you're trying to accomplish with these bizarre
strcmp()'s on integers and NULL pointers and such...
From: kolp
k... from now on, you'll need programming skills... i suggest you learn c,
but i think it's also possible to do newbie8 in perl
Your goal is to write a client for the daemon running on port 2345.
The server sends you a CHALLENGE (0), with 4 ints, and you'll have to
multiply the ints (int1*int2*int3*int4) and send it back as the answer,
together with the newbie7 pass in prevpass.
When you get the answer right, the server sends a CORRECT (1) back, with
the next level's pass in nextpass
If the answer is wrong, the server sends a WRONG(2) back, and terminates
Add a Comment
New Questions: What happens with incoming
buffer over-run
From: Stephen Hucker
I`m writing a small TCP server on linux and i wanted to know what happen to the data when it
is greater than the max lenght to copy into the buffer. This is when using the command
recvfrom(int socket,char* buffer, int lenght etc.. and lenght is the buffer size. I want to know
this, to make sure data can`t start writing into other parts of memory, if the clients sends more
data than can be read into the buffer. Cheers Stephen.
From: Rob Seace
Cheers Rob
Add a Comment
New Questions: Windows sockets
From: Srinivasa Reddy
I am using windows sockets and i want the program control to come out of this accept()
function when no requests are coming. Is this possible?
thanks
Bsreddy
From: Scott Weber
If you already have a window message loop set up, this is extremely simple. Use the
WSAAsyncSelect() function and register for the FD_ACCEPT event. Then when you receive
the message from your call to GetMessage() or PeekMessage() or whatever, you are guaranteed
that a call to accept() will succeed immediately.
Add a Comment
New Questions: How to bind Multi-IP to a MAC
From: rapide.zhang
I want to bind more than one IP to a server in my UNIX program so that it can provide different
service, but i don't know how to implement it, can you help me?
Add a Comment
New Questions: How can I run a program and
set some environment variable when "startx"
on RedHat ?
From: Newer
Add a Comment
New Questions: How can I run a program and
set some environment variable when "startx"
on RedHat ?
From: Newer
Add a Comment
New Questions: Limit on maximum number of
sockets
From: Chris Black
Thanks
Add a Comment
New Questions: Select problem - read()
From: Martin Lexa
Hello all!
Situation:
1) multithreaded Client/Server program (Linux)
2) one thread waiting for connection and then
creating work thread
3) work thread - read select() on UNIX socket;
4) reading data; when found specific data
connect to another Client/Server machine (HP/UX).
5) work thread - read select() on UNIX socket
and new TCP socket (HP/UX), write select() on new TCP
socket (HP/UX).
I think the problem is you are setting your socket non-blocking before calling "connect()". In
this case, the connect call will return inmediately with -1 and errno set to EINPROGRESS.
When the connection is established the select() call wil flag the socket descriptor in the write
set.
So, to avoid this problem try setting the socket to non-blocking AFTER calling select, or check
the connect() return value and errno variable and use a flag to know when the connection is
completely established.
The man page for connect reads:
"[...]After select indicates writability, use getsock-opt(2) to read the SO_ERROR option at level
SOL_SOCKET to determine whether connect completed successfully (SO_ERROR is zero) or
unsuccessfully (SO_ERROR is one of the usual error codes listed here, explaining the reason
for the failure).[...]"
:) (HAL)
From: Martin Lexa
Hello!
Thank you for your response Loco, but this wasn't helped me ;-)
I've always have connect() in blocking mode and every call is checked
for return value. Connect and accept is returning positive value,
so I don't expect there is much room for error.
BTW, connect is set to blocking mode by default or am I wrong?
One more thing: It's never happen in first round, only in laters when socket
was allready closed and reopened. With this I mean connect() gives the new
connection same descriptor number as previously used and correctly closed
socket connection.
BTW, before closing connection I'm sending shutdown(desc, 2) call. And yes,
I'm verifying every return code, so shutdown and close call are returning
positive numbers.
Wepre on our third attempt at using DSL, but problems still dog us,(excuse the pun, I'm a
dog-lover as well). The scary error message,"fatal, could not create socket". Any help to offer?
Thanks, Nan
Add a Comment
New Questions: socket programming
From: vipul singhal
Add a Comment
New Questions: can u send a .gif file through a
socket. ?
From: Manikandan
I am connecting to a server, when connected it sends me a .gif file. in the client program, i
receive it in the STREAM format. i use open,read,write system calls to write to a file. i receive
as character stream and write it to a file.I do a ftp to win'nt machince but could not open the .gif
file. how do i convert a character into binary ?
Mani
From: kb
you mentioned a character stream in your description. A gif file is binary -- you should get the
file and write it as is. When you ftp it to a windows box be sure to set ftp mode to bin as
opposed to ascii
From: Manikandan
Yes, what i am doing right now is reading as character stream. i known, .gif file is a binary one,
but i am not clear in reading binary data. During ftp i switched to bi mode before put(ing) the
file. can u give me a better picture.
Add a Comment
New Questions: About IP Alias
From: rapide.zhang
thanks.
Add a Comment
New Questions: Connection refused when
using syslog()
From: Jappe Reuling
Hi,
#include<syslog.h>
...
openlog("MY SERVER NAME", LOG_NDELAY, LOG_USER);
...
printSyslog(LOG_INFO, "Started");
...
closelog;
Server:
remote.sin_family = AF_INET;
remote.sin_addr.s_addr = htonl(INADDR_ANY);
noTimeout.tv_sec = 0;
noTimeout.tv_usec = 0;
FD_ZERO(&readFdSet);
FD_SET(localSocket, &readFdSet);
if(FD_ISSET(localSocket, &readFdSet)) {
if( (acceptedSocket = accept(localSocket, (struct sockaddr *)&remote,
&addrSize)) < 0)
close(acceptedSocket);
client:
remote.sin_family = AF_INET;
shutdown(replySocket, 2);
close(inputSocket);
I've let allot of the error handling out of the above code
(e.g. below each 'if' there is a function which handles the
error).
if(extra != NULL)
syslog(level, "%s: %s", message, extra);
else
syslog(level, "%s", message);
Hmmmm, well that's fairly short and sweet; not too much
room to hide a bug, there... The only thing slightly
odd I see is the explicit declaration of your "message" arg
as a sized array, rather than a simple "char*"... I've
seen some compilers do odd things when you specify function
arguments like that, and then feed them a "char*" instead...
They probably shouldn't though... Eg: some people declare
their main() argvs as "char **argv", while others use
"char *argv[]", and either one should really work just
fine... However, when you start throwing in actual array
sizes inside the brackets, I'm not sure if that's even
defined as to what it means or does, in ANSI C...
Basically, I'm saying if *I* were writing this, I'd define
it "char *message", and leave it at that... But, I'm really
not convinced this is your problem, either... I can imagine
a compiler might do something wacky with it as currently
defined (I've seen some pretty wacky compiler behavior, in
my days ;-)), but I wouldn't bet on it... I'd think it'd
more likely simply ignore your given array size, and
basically give you "char message[]", which is basically
exactly the same as "char *message", in a function arg...
But, who knows? It wouldn't hurt to change it to "char*",
and see if that helps... *shrug*
From: Jappe Reuling
while(1) {
create udp socket
send udp broadcast
The client reacts on the udp broadcast but then the tcp
socket hasn't been created due to all debugging stuff.
while(1) {
while(1) {
create udp socket
send udp broadcast
The client reacts on the udp broadcast but then the tcp
socket hasn't been created due to all debugging stuff.
while(1) {
Add a Comment
New Questions: How can we use the LENGTH
in recvfrom() in UDP socket?
From: Franz
But if we don't know the length of data sent by UDP server, how can we fiil this field?
From:
It's the maximum length you're willing to accept (the size of the buffer). How much depends on
the protocol that you're using, but 64K is the maximum. But UDP-packets of this size will have
to be broken in fragments (size: MTU), and many networks don't allow fragmented
UDP-packets.
Add a Comment
New Questions: Multiple clients using select
From: RaviShankar C S
Add a Comment
New Questions: Asynchronous programming
From: kane
I've just been introduced to asynchronous programming... learning mostly from trial and error.
I'm running into a problem where my server is not sending out the entire buffer.
I make a send() call.
I catch the FD_WRITE event and it only shows a fraction of the buffer size being written to the
socket.
Then a MFD_DELIVER event is thrown and the bytes delivered is equal to that written to the
socket.
From this point on, I'm expecting the socket to eventually send out the rest of the buffer, but it
just hangs.
Thanks in advance.
Add a Comment
New Questions: select() problems on DEC
Alpha XP900
From: Jan Mannekens
Hi all,
I have a server and a client program, where the server acts as an echo-server, sending back the
received packets to the client.
Everything works fine under Linux on my PC, but when I go to my DEC Alpha machine I
experience some funny things:
On the server there is a select() with a timeout of 10 seconds and with one single client that is
endlessly exchanging packets
the select() timeout is reported every 10 seconds, although it is not expected to timeout.
Greetings,
Jan
From: Loco
Hi,
The only idea i can come up with is to reset the timeval struct before calling select(). If this is
the problem (not resetting the variable) then Linux should also fail as it modifies the value to
reflect the amount of time not slept.
Problem is solved. Had something to do with the first parameter in the select(). I used
FD_SETSIZE, which was initialized to 32768 and on DEC this gives a problem (2048 solves
my problem).
Funny that the same executable gave different behaviour on 3 different DEC Alpha machines.
From: Loco
You should use a different value for the first parameter to select().
It should be the highest value of the descriptors you are "selecting" plus one.
I don't know if using a higher value could do any harm (as you already wrote it does), but
maybe it could make things slower... Gotta go again on the kernel code to see how it is
handled...
Good luck
:D HAL
Add a Comment
New Questions: Mapping PDU data over tcp/ip
From: udayan
I have a PDU structure in which some fields are string, some are integer and some are long. I
understand that if i have to use the send() system the information in the buffer has to be og
character type. How can i send a whole PDU without converting each of the fields into char.. I
want to avoid using RPC. Can anybody help
Add a Comment
New Questions: aix 4.3 ftp client data socket
question (can you help?)
From: brent thomas
i'm working on an ftp client which talks to a standard ftp server (system ftp)
on an 4.3 aix system. My client opens the control socket,
logs in as a specific user/password, performs a cwd. Then
I bind an emphemeral data socket and call listen on it.
After the listen i take the port information and send it via
the control connection in a PORT command to the server.
then I send a 'STOR file.name' across the control socket to
kick the server to perform the active open to my waiting
data socket. Then an accept is posted to the data socket
which returns with a new socket (0 -- this is unix so 0 should
be a valid socket) -- having done the accept and
gotten the new socket i attempt to send to the socket but
get the indication errno 57 stating that the socket (0)
is not a socket (ENOTSOCK).
my first question is: as the client, after the server has opened me (in the accept)
is there anything else i need to do before attempting to send
to the socket?
yes, i think, use RAW sockets, which will bypass the tranport layer. i have tried. please try.
Mani
Add a Comment
New Questions: unix for submitting html form
to a server
From: Digger
Hello,
i need to develop a unix script which works from a server side.
the script needs to submit a html form[a form template] to a particular web server[something
like http://sc.satinc.com/s/ss/].
The form has to be submitted as many times as possible per second simultaeously.[you can
imagine the program automatically clicking the submit button of around 1000 similar form
templates simultaeously].
Someone recommended me unix since it allows multiple threads.ive been told that the unix
program used is very basic and simple.
I would appreciate any help from you unix gurus.
Thanks
Digs
Add a Comment
New Questions: RAW Sockets
From: Mike Cramp
I have a piece of code, socket(AF_INET, SOCK_STREAM, 2) and it won't create the socket if I
specify a windows machine. Why not?
From: Loco
Try using
Add a Comment
New Questions: counter-wait system
From: Ali Ahmad
Thank you
Add a Comment
New Questions: Consulting C++
From: Stefan Olsson
Hi!
Our company is developing a multithreaded server in C++ and are now in the optimization
phase.
Is there anyone of you that are really into sockets and C++ that would be interested in some
consulting work?
The code is isolated to a class that creates both client and server sockets and have methods for
sending and recieving data and if successful we would be happy to share the resulting class as
GPL
Thanks in advance!
Add a Comment
New Questions: read() hangs w/ binary
transfers
From: Cal
Hi everyone,
I'm working on a sort of 'ground up' approach to a file transfer protocol, just for fun. I have an
issue with read() hanging after the file is completely transfered. If I ctrl-C on the server side,
and the socket closes, then read() will exit giving an EOF. I could establish a completely
separate socket connection for file transfers, (I also use a command line interface over the
socket) but that seems like it could be a hassle with authentication. I have also tried using dup()
on the server socket, and closing the dup'ed socket, but that didn't seem to work either.
Server
---------------------------------------
/* This is where the server recieves
the 'get' command from client */
rfp = open(cmd2, O_RDONLY);
if (rfp < 0)
{
perror("open()");
}
printf("writing\n");
while(1)
{
readsize = read(rfp, buffer, sizeof(buffer));
if (readsize == 0)
{
printf("encountered End of File\n");
break;
}
if (readsize < 0)
{
perror("read()");
break;
}
writesize = write(connectsock, buffer, readsize);
/* Note: using readsize for count bytes because
we may not read the full buffer for the last read.
therefor, write() will only write the amount of bytes
that we have read to the socket
Note2: this is setup exactly like client side
(except reversed) ... don't know if both need
to cut off the buffer, or if one needs to use
something like sizeof(buffer) for count.
*/
if (writesize == 0)
{
printf("writesize is 0");
break;
}
if (writesize < 0)
{
perror("write()");
break;
}
}
close(rfp);
printf("write complete... file closed");
---------------------------------------
Client
--------------------------------------
/* Open local file on client */
wfp = open(cmd3, O_WRONLY|O_TRUNC|O_CREAT, 0666);
if (wfp < 0)
{
perror("open");
fprintf(stderr, "could not open file %s", cmd3);
}
/* This starts the transfer code server-side */
if ( sock_puts(connectsock, sndbuffer) == -1)
{
perror("sock_puts()");
}
while (loop)
{
// debug
printf("%d", readsize);
if (readsize < sizeof(readbuffer))
{
/* we're on the last read */
loop = 0;
}
if (readsize == 0)
{
printf("end of file\n");
break;
}
if (readsize < 0)
{
printf("read error\n");
perror("read()");
break;
}
printf("."); // print a '.' for a successfull sock read
writesize = write(wfp, readbuffer, readsize);
/* Note: using readsize for count bytes because
we may not read the full buffer for the last read.
therefor, write() will only write the amount of bytes
that we have read from the socket
*/
if (writesize == 0)
{
printf("writesize is 0");
break;
}
if (writesize < 0)
{
printf("write error\n");
perror("write()");
break;
}
printf(":"); // print a ':' for successfull file write
readsize = 0; // for debug purposes
}
close(wfp);
printf("file get complete... file closed\n");
--------------------------------------
The file transfers perfectly fine, but I can't get read() to exit on the client side. I have read
through the faq, but I don't know what the best solution is: either use alarm() or somehow
timeout the read() function, or use non-blocking mode. I've read through some info about using
select() but I havn't really seen any good examples using it. Could anyone provide a link to
some good examples? Any suggestions at all would be greatly appreciated.
-Cal
From: Loco
Hi,
I wouldn't use "sizeof(readbuffer)" as the parameter to read(), as it will return the size of a
char*, not the real size of the buffer. Use a constant or a variable containing the buffer's size. It
will greatly increase your application performance.
Don't expect to read the same number of bytes that were written by the other party. It is possible
that you have to issue multiple reads for a write, even if the buffers' capacities are the same. So
don't count on it to know when the transmission ends.
while (1) {
bread = read(fd, buffer, MAX_BUFFER_SIZE);
if (bread <= 0)
break;
write(soc, buffer, bread);
}
shutdown(soc, 2);
close(soc);
close(fd);
As you can see both codes are almost identical. NO error catching included!
:D (HAL)
Add a Comment
New Questions: Asynchronous DNS lookups
From: Chris
Hi,
I know that the gethostby*() functions can block execution, and I was wondering, what's the
"common solution" to this? I guess you could fork() or create a thread, or use alarm() or
something..
What solution(s) do you use to get around this problem?
Thanks in advance,
Chris
Add a Comment
New Questions: When does EPROTO occur?
From: manikandan
Add a Comment
General Information and Concepts: What's
new?
You can find out what is new by looking at the main page for questions that have been recently
submitted. You can also set up a user profile for yourself that will allow the main page to tell
you what questions have been added, and which questions have new comments since your last
visit.
From: Georg Wagner
Add a Comment
General Information and Concepts: About this
FAQ
This FAQ is maintained by Vic Metcalfe ([email protected]), with lots of assistance from Andrew
Gierth ([email protected]). I am depending on the true wizards to fill in the
details, and correct my (no doubt) plentiful mistakes. The code examples in this FAQ are
written to be easy to follow and understand. It is up to the reader to make them as efficient as
required. I started this faq because after reading comp.unix.programmer for a short time, it
became evident that a FAQ for sockets was needed.
The FAQ is available at the following locations:
Usenet: (Posted on the 21st of each month)
news.answers, comp.answers, comp.unix.answers, comp.unix.programmer
FTP:
ftp://rtfm.mit.edu/pub/usenet/news.answers/unix-faq/socket
WWW:
http://www.ibrado.com/sock-faq
http://kipper.york.ac.uk/~vic/sock-faq
http://www.ntua.gr/sock-faq
Please email me if you would like to correct or clarify an answer. I would also like to hear from
you if you would like me to add a question to the list. I may not be able to answer it, but I can
add it in the hopes that someone else will submit an answer. Every hour I seem to be getting
even busier, so if I am slow to respond to your email, please be patient. If more than a week
passes you may want to send me another one as I often put messages aside for later and then
forget about them. I'll have to work on dealing with my mail better, but until then feel free to
pester me a little bit.
Add a Comment
General Information and Concepts: Who is this
FAQ for?
This FAQ is for C programmers in the Unix environment. It is not intended for WinSock
programmers, or for Perl, Java, etc. I have nothing against Windows or Perl, but I had to limit
the scope of the FAQ for the first draft. In the future, I would really like to provide examples for
Perl, Java, and maybe others. For now though I will concentrate on correctness and
completeness for C.
This version of the FAQ will only cover sockets of the AF_INET family, since this is their most
common use. Coverage of other types of sockets may be added later.
Add a Comment
General Information and Concepts: What are
Sockets?
Sockets are just like "worm holes" in science fiction. When things go into one end, they
(should) come out of the other. Different kinds of sockets have different properties. Sockets are
either connection-oriented or connectionless. Connection-oriented sockets allow for data to
flow back and forth as needed, while connectionless sockets (also known as datagram sockets)
allow only one message at a time to be transmitted, without an open connection. There are also
different socket families. The two most common are AF_INET for internet connections, and
AF_UNIX for unix IPC (interprocess communication). As stated earlier, this FAQ deals only
with AF_INET sockets.
From:
From: cara
Bull Shit!!
From: Syndicate
Picture a socket (AF_INET) as a imaginary hole in your computer.. Other computers can
connect to those holes. or you can use those holes to conenct to other computers. its a way to
communicate across a network.
From: Jose
Great!! But, what are Sockets? Your answer is not an answer for me.
From: Jose
A socket is kinda like a virtual adapter between a program and a network protocol. Consider an
ftp server going online, one socket is created by the ftp server program. This socket's jobs are to
listen at TCP port 21 and if IP passes any packets to TCP port 21, the socket will pass them on
to the ftp server program.
From: Sarah
Thanks
From:
A simple explination of a socket is two or more processes
(programs running) wanting to share information. A socket is used
to send or recieve data directly to or from another process without
one having to write to a file and the other read the data from
the file.
From: boby
pardon my english.
From: Mahafuz
From: Helge
Come on folks, if you can't understand what this is saying, not to mention all the other
explanations here, you really shouldn't be trying to program. You should continue your life as a
pathetic end-user, wandering around asking people who don't have time to answer a question
that answers itself to explain to you why your computer won't turn on when you don't have it
plugged in... Go Away!
From: Cowards best friend
You bunch of yahoos couldn't explain a thing in simple english because you don't really know
how it works.
Tell me once you create a socket in a program, how does that data stream pass to the
communication buffer area and distinguish itself with other communication processes.
From: Sivapriya
From: Ravi
Can you have multiple sockets over a single port? I.e. is it safe to say that when i have multiple
netscape windows open, that each of these creates a socket which communcates over the TCP
port?
From: caspre
Can you have multiple sockets over a single port? I.e. is it safe to say that when i have multiple
netscape windows open, that each of these creates a socket which communcates over the TCP
port?
From: joanna
How many streams can you have on a socket *3*. PERIOD. If you have a multithreaded
server listening on a port for client connections and you try
making all the clients use the same streams on the same socket,
you are in for some bad mojo. It is all quite simple. Remember,
port is just the address. INFINITE sockets on a port. *3* Streams on a socket.
From: Loco
I think you have IN, OUT, OOB in, OOB out streams. I've never heard about an "err" stream in
a socket but i may be wrong.
However, if your clients connect to a port bound on your machine it will have as many sockets
as clients connected to that port plus the bound socket. It doesn't mean that you can bind many
sockets on that port.
The number of sockets connected to a port doesn't depend directly on bandwidth but on file
descriptors and memory available. There are many discussions about this in the FAQ and i don't
want to begin another one, so i suggest you read the questions.
The interace consists of sockets descriptors, some structures, and a set of functions to perform
operations on the descriptors.
The socket descriptor is just a file descriptor which allows you to use some of the functions
normally used on file descriptors (such as read and write). As this interface shields the
programmer from the network communication details you don't need to understand what lies
beneath to program sockets.
Programming sockets is not difficult for doing simple tasks. Using TCP sockets (TCP/IP
protocol, STREAM sockets) involves two parties: the server and the client. The difference
between the parties is that the server creates the socket, binds it to a specific port, signal that it
can receive connections, and waits for those connections; while the client just creates the socket
and connects to the server to the port it is waiting to receive connections.
The server normally expects some clients will be connected to it, so it has to give some way for
them to find it. That is why it uses one socket to receive connections, and for each connection it
uses a separate socket, so it will have as many sockets as the number of clients connected.
Loco,
All sockets have an error queue, which can be read using recvmsg() with the
MSG_ERRQUEUE flag. Maybe this is what Chris was talking about.
From: Vinny
Why are sockets used ?? What kinda applications would need to use sockets (other than FTP,
Telnet, Web Browsers) ? Can I use sockets to do inter process communication between two
process connected by ethernet and use sockets to issue commands to the client process which
will process it and return status back ? Can i trnasfer huge files 64MB using sockets ? Is it used
as a layer over TCP/IP, so that we dont have to use the complex TCP/IP specification ?
From: Geetha Ramanathan
Thanks,
Geetha
From: arun
A Socket can be assumed as a communication tunnel established between two comm ports for
data to be transfered. Socket is not a physical entity but a virtual one established when IP addess
is being initialized for a network or node
From: Practic
I am a novice programmer so I do not really understand the inner workings of sockets myself.
However, I believe I can explain what one is in simple terminology. Think of this: say you have
two programs that are either on the same computer, or on different computers, and they want to
communicate. How can they do this? They can't call functions in one another like one object to
another within a program. They need some sort of common reference point. One way would be
that they communicate by writing to a file. They both have a pre-agreed 'physical' file on a
hardisk. They both write to it and read to it, with possible proper headers. However, writing to a
hard disk is slow. So instead, they can both communicate through the operating system on the
computer. What sockets are (I think) is basically a point of reference managed by the operating
system. Basically when you want to 'listen' to a socket, your program tells the operating system
(by a function call) that it wants to listen to a specific socket, identified by an integer. Then,
whenver another program writes information to that socket, ie, sends the operating system that
information with the attached idea of "send this info to the socket", the OS then checks its list of
listeners to that socket, and then sends the data that is to be written to the socket to all the
programs 'listenig' to that socket. That is, in simple terms, what a socket it. It is merely a
centralized mechanism in the operating system by which different programs communicate. It is
not 'physical'. It is not on the hard disk, etc. It is basically one program telling something to the
operating system, which then the operating system sends to any program that wants to listen.
From: Lamer
Add a Comment
General Information and Concepts: How do
Sockets Work?
The implementation is left up to the vendor of your particular unix, but from the point of view
of the programmer, connection-oriented sockets work a lot like files, or pipes. The most
noticeable difference, once you have your file descriptor is that read() or write() calls
may actually read or write fewer bytes than requested. If this happens, then you will have to
make a second call for the rest of the data. There are examples of this in the source code that
accompanies the faq.
From: Stanislav Shalunov
Actually, no standard I am aware of prohibits short read()'s and write()'s for pipes or even
regular files.
From: Pinocchio
So if sockets can do more than pipes, why does anyone use named pipes?
From: S.Murali Krishna
What is the difference between FIFOS and Unix domain
sockets. Both of them are doing the same job (interprocess
Communication) then what is the difference (or advantage)
between them ? Can anyone tell me in detail.
Thanks - S.M.K
From: Rob Seace
Add a Comment
General Information and Concepts: Where can
I get source code for the book [book title]?
Here is a list of the places I know to get source code for network programming books. It is very
short, so please mail me with any others you know of.
Title: Unix Network Programming
Author: W. Richard Stevens ( [email protected])
Publisher: Prentice Hall, Inc.
ISBN: 0-13-949876-1
URL: http://www.kohala.com/~rstevens
Just a small thing - the source code for Stevens' book has
moved to: http://www.kohala.com/start/unpv12e.html
Add a Comment
General Information and Concepts: Where can
I get more information?
I keep a copy of the resources I know of on my socks page on the web. I don't remember where
I got most of these items, but some day I'll check out their sources, and provide ftp information
here. For now, you can get them at http://www.ibrado.com/sock-faq.
Add a Comment
General Information and Concepts: Where can
I get the sample source code?
The sample source code is no longer included in the faq. To get it, please download it from one
of the unix-socket-faq www pages:
http://www.ibrado.com/sock-faq
http://kipper.york.ac.uk/~vic/sock-faq
http://www.ntua.gr/sock-faq
If you don't have web access, you can ftp it with ftpmail by following the following
instructions.
To get the sample source by mail, send mail to [email protected], with no subject line
and a body like this:
reply
connect ftp.zymsys.com
binary
uuencode
get pub/sockets/examples.tar.gz
quit
Save the reply as examples.uu, and type:
% uudecode examples.uu
% gunzip examples.tar.gz
% tar xf examples.tar
This will create a directory called socket-faq-examples which contains the sample code from
this faq, plus a sample client and server for both tcp and udp.
Note that this package requires the gnu unzip program to be installed on your system. It is very
common, but if you don't have it you can get the source for it from:
ftp://prep.ai.mit.edu/pub/gnu/gzip-1.2.4.tar
If you don't have ftp access, you can obtain it in a way similar to obtaining the sample source.
I'll leave the exact changes to the body of the message as an excersise for the reader.
From: Vic Metcalfe
Oops, I forgot to add a link to the source in the new site design. The examples are still here.
You can get them from http://www.lcg.org/sock-faq/examples.tar.gz, or the corresponding URL
for the mirrors. I'll correct the problem soon.
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): How can I tell when a
socket is closed on the other end?
From Andrew Gierth ( [email protected]):
AFAIK:
If the peer calls close() or exits, without having messed with SO_LINGER, then our calls to
read() should return 0. It is less clear what happens to write() calls in this case; I would
expect EPIPE, not on the next call, but the one after.
If the peer reboots, or sets l_onoff = 1, l_linger = 0 and then closes, then we should
get ECONNRESET (eventually) from read(), or EPIPE from write().
I should also point out that when write() returns EPIPE, it also raises the SIGPIPE signal -
you never see the EPIPE error unless you handle or ignore the signal.
If the peer remains unreachable, we should get some other error.
I don't think that write() can legitimately return 0. read() should return 0 on receipt of a
FIN from the peer, and on all following calls.
So yes, you must expect read() to return 0.
As an example, suppose you are receiving a file down a TCP link; you might handle the return
from read() like this:
rc = read(sock,buf,sizeof(buf));
if (rc > 0)
{
write(file,buf,rc);
/* error checking on file omitted */
}
else if (rc == 0)
{
close(file);
close(sock);
/* file received successfully */
}
else /* rc < 0 */
{
/* close file and delete it, since data is not complete
report error, or whatever */
}
From: Andrew Maholski
This answer does not really tell what to do if you wish to check a socket prior to your read
attempt. If the server requires you to maintain an open socket but will time out after a period of
inactivity you should use select with a shot timeout to determine the socket status. The
following code demonstrates this:
int Socket_Status(int sock, int to_secs, int to_msecs)
{
int sval;
int ret_val = 1;
fd_set check_set;
struct timeval to;
FD_ZERO(&check_set);
FD_SET(sock,&check_set);
to.tv_sec = to_secs;
to.tv_usec = to_msecs;
return(ret_val);
if(Socket_Status(sock,0,1))
{
logprintf(LOG_EVERYTHING,"The socket is not up.");
/*close your end of the thing*/
}
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): What's with the second
parameter in bind()?
The man page shows it as "struct sockaddr *my_addr". The sockaddr struct
though is just a place holder for the structure it really wants. You have to pass different
structures depending on what kind of socket you have. For an AF_INET socket, you need the
sockaddr_in structure. It has three fields of interest:
sin_family
Set this to AF_INET.
sin_port
The network byte-ordered 16 bit port number
sin_addr
The host's ip number. This is a struct in_addr, which contains only one field,
s_addr which is a u_long.
From: Anup Ochani
The socket address structure is protocol specific. sockaddr_un(Unix Protocol) is much larger
than sockaddr_in(INTERNET protocol).
connect() and bind() system calls cater for both the protocols. To handle socket address
structures of different sizes,
the system calls use a pointer to the structure and the size of that structure.
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): How do I get the port number for a
given service?
Use the getservbyname() routine. This will return a pointer to a servent structure. You are interested in the
s_port field, which contains the port number, with correct byte ordering (so you don't need to call htons() on it).
Here is a sample routine:
/* Take a service name, and a service type, and return a port number. If the
service name is not found, it tries it as a decimal number. The number
returned is byte ordered for the network. */
int atoport(char *service, char *proto) {
int port;
long int lport;
struct servent *serv;
char *errpos;
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): If bind() fails, what
should I do with the socket descriptor?
If you are exiting, I have been assured by Andrew that all unixes will close open file descriptors
on exit. If you are not exiting though, you can just close it with a regular close() call.
From: mike wainwright
The app has exited as has the client. (20000 was the port number)
If the client crashes, maybe close doesn't get called then netstat shows the socket still bound as:
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): How do I properly
close a socket?
This question is usually asked by people who try close(), because they have seen that that is
what they are supposed to do, and then run netstat and see that their socket is still active. Yes,
close() is the correct method. To read about the TIME_WAIT state, and why it is important,
refer to 2.7 Please explain the TIME_WAIT state..
From:
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): When should I use shutdown()?
From Michael Hunter ([email protected]):
shutdown() is useful for deliniating when you are done providing a request to a server using TCP. A typical
use is to send a request to a server followed by a shutdown(). The server will read your request followed by
an EOF (read of 0 on most unix implementations). This tells the server that it has your full request. You then go
read blocked on the socket. The server will process your request and send the necessary data back to you
followed by a close. When you have finished reading all of the response to your request you will read an EOF
thus signifying that you have the whole response. It should be noted the TTCP (TCP for Transactions -- see R.
Steven's home page) provides for a better method of tcp transaction management.
S.Degtyarev ([email protected]) wrote a nice in-depth message to me about this. He shows a practical
example of using shutdown() to aid in synchronization of client processes when one is the "reader" process, and
the other is the "writer" process. A portion of his message follows:
Sockets are very similar to pipes in the way they are used for data transfer and client/server transactions, but not
like pipes they are bidirectional. Programs that use sockets often fork() and each process inherits the socket
descriptor. In pipe based programs it is strictly recommended to close all the pipe ends that are not used to
convert the pipe line to one-directional data stream to avoid data losses and deadlocks. With the socket there is
no way to allow one process only to send data and the other only to receive so you should always keep in mind
the consequences.
Generally the difference between close() and shutdown() is: close() closes the socket id for the
process but the connection is still opened if another process shares this socket id. The connection stays opened
both for read and write, and sometimes this is very important. shutdown() breaks the connection for all
processes sharing the socket id. Those who try to read will detect EOF, and those who try to write will reseive
SIGPIPE, possibly delayed while the kernel socket buffer will be filled. Additionally, shutdown() has a
second argument which denotes how to close the connection: 0 means to disable further reading, 1 to disable
writing and 2 disables both.
The quick example below is a fragment of a very simple client process. After establishing the connection with
the server it forks. Then child sends the keyboard input to the server until EOF is received and the parent
receives answers from the server.
/*
* Sample client fragment,
* variables declarations and error handling are omitted
*/
s=connect(...);
if( fork() ){ /* The child, it copies its stdin to
the socket */
while( gets(buffer) >0)
write(s,buf,strlen(buffer));
close(s);
exit(0);
}
DESCRIPTION
fork creates a child process that differs from the parent
process only in its PID and PPID, and in the fact that
resource utilizations are set to 0. File locks and pend-
ing signals are not inherited.
RETURN VALUE
On success, the PID of the child process is returned in
the parent's thread of execution, and a 0 is returned in
the child's thread of execution. On failure, a -1 will be
returned in the parent's context, no child process will be
created, and errno will be set appropriately.
From: Ken Whaley
For folks new to shutdown(), it's helpful to remind them that shutdown() is NOT a replacement for close(). You
still must close() sockets when you're done with them (after the calls to shutdown()) in order to not leak a file
descriptor. Many examples of shutdown() omit the close() after shutdown() because they're test programs where
the process exits after the shutdown() (and the process exit of course cleans up all open descriptors). Stevens
section on shutdown() doesn't make this clear (his wording implies to me an "either/or" between shutdown() and
close()).
From: george elgin
the use of shutdown(1) circumvents what the kernel SHOULD accomplishes
automatically. when the open file descriptor count reaches 0 a FIN
is sent to the partner which begins the sequence of wait states
FIN_WAIT, FIN_WAIT_2 etc. for the reader. When both sides readers
have then completed this orderly shutdown the file descriptor
is returned to the operating system.
Agree.
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): Please explain the TIME_WAIT
state.
Remember that TCP guarantees all data transmitted will be delivered, if at all possible. When you close a
socket, the server goes into a TIME_WAIT state, just to be really really sure that all the data has gone through.
When a socket is closed, both sides agree by sending messages to each other that they will send no more data.
This, it seemed to me was good enough, and after the handshaking is done, the socket should be closed. The
problem is two-fold. First, there is no way to be sure that the last ack was communicated successfully. Second,
there may be "wandering duplicates" left on the net that must be dealt with if they are delivered.
Andrew Gierth ( [email protected]) helped to explain the closing sequence in the following usenet
posting:
Assume that a connection is in ESTABLISHED state, and the client is about to do an orderly release. The
client's sequence no. is Sc, and the server's is Ss. The pipe is empty in both directions.
Client Server
====== ======
ESTABLISHED ESTABLISHED
(client closes)
ESTABLISHED ESTABLISHED
------->>
FIN_WAIT_1
<<--------
FIN_WAIT_2 CLOSE_WAIT
<<-------- (server closes)
LAST_ACK
, ------->>
TIME_WAIT CLOSED
(2*msl elapses...)
CLOSED
Note: the +1 on the sequence numbers is because the FIN counts as one byte of data. (The above diagram is
equivalent to fig. 13 from RFC 793).
Now consider what happens if the last of those packets is dropped in the network. The client has done with the
connection; it has no more data or control info to send, and never will have. But the server does not know
whether the client received all the data correctly; that's what the last ACK segment is for. Now the server may or
may not care whether the client got the data, but that is not an issue for TCP; TCP is a reliable rotocol, and must
distinguish between an orderly connection close where all data is transferred, and a connection abort where data
may or may not have been lost.
So, if that last packet is dropped, the server will retransmit it (it is, after all, an unacknowledged segment) and
will expect to see a suitable ACK segment in reply. If the client went straight to CLOSED, the only possible
response to that retransmit would be a RST, which would indicate to the server that data had been lost, when in
fact it had not been.
(Bear in mind that the server's FIN segment may, additionally, contain data.)
DISCLAIMER: This is my interpretation of the RFCs (I have read all the TCP-related ones I could find), but I
have not attempted to examine implementation source code or trace actual connections in order to verify it. I am
satisfied that the logic is correct, though.
More commentarty from Vic:
The second issue was addressed by Richard Stevens ( [email protected], author of "Unix Network
Programming", see 1.6 Where can I get source code for the book [book title]?). I have put together quotes from
some of his postings and email which explain this. I have brought together paragraphs from different postings,
and have made as few changes as possible.
From Richard Stevens ( [email protected]):
If the duration of the TIME_WAIT state were just to handle TCP's full-duplex close, then the time would be
much smaller, and it would be some function of the current RTO (retransmission timeout), not the MSL (the
packet lifetime).
A couple of points about the TIME_WAIT state.
● The end that sends the first FIN goes into the TIME_WAIT state, because that is the end that sends the
final ACK. If the other end's FIN is lost, or if the final ACK is lost, having the end that sends the first FIN
maintain state about the connection guarantees that it has enough information to retransmit the final ACK.
● Realize that TCP sequence numbers wrap around after 2**32 bytes have been transferred. Assume a
connection between A.1500 (host A, port 1500) and B.2000. During the connection one segment is lost
and retransmitted. But the segment is not really lost, it is held by some intermediate router and then
re-injected into the network. (This is called a "wandering duplicate".) But in the time between the packet
being lost & retransmitted, and then reappearing, the connection is closed (without any problems) and
then another connection is established between the same host, same port (that is, A.1500 and B.2000; this
is called another "incarnation" of the connection). But the sequence numbers chosen for the new
incarnation just happen to overlap with the sequence number of the wandering duplicate that is about to
reappear. (This is indeed possible, given the way sequence numbers are chosen for TCP connections.)
Bingo, you are about to deliver the data from the wandering duplicate (the previous incarnation of the
connection) to the new incarnation of the connection. To avoid this, you do not allow the same
incarnation of the connection to be reestablished until the TIME_WAIT state terminates. Even the
TIME_WAIT state doesn't complete solve the second problem, given what is called TIME_WAIT
assassination. RFC 1337 has more details.
● The reason that the duration of the TIME_WAIT state is 2*MSL is that the maximum amount of time a
packet can wander around a network is assumed to be MSL seconds. The factor of 2 is for the round-trip.
The recommended value for MSL is 120 seconds, but Berkeley-derived implementations normally use 30
seconds instead. This means a TIME_WAIT delay between 1 and 4 minutes. Solaris 2.x does indeed use
the recommended MSL of 120 seconds.
A wandering duplicate is a packet that appeared to be lost and was retransmitted. But it wasn't really lost ...
some router had problems, held on to the packet for a while (order of seconds, could be a minute if the TTL is
large enough) and then re-injects the packet back into the network. But by the time it reappears, the application
that sent it originally has already retransmitted the data contained in that packet.
Because of these potential problems with TIME_WAIT assassinations, one should not avoid the TIME_WAIT
state by setting the SO_LINGER option to send an RST instead of the normal TCP connection termination
(FIN/ACK/FIN/ACK). The TIME_WAIT state is there for a reason; it's your friend and it's there to help you :-)
I have a long discussion of just this topic in my just-released "TCP/IP Illustrated, Volume 3". The TIME_WAIT
state is indeed, one of the most misunderstood features of TCP.
I'm currently rewriting "Unix Network Programming" (see 1.6 Where can I get source code for the book [book
title]?). and will include lots more on this topic, as it is often confusing and misunderstood.
On the question of using SO_LINGER to send a RST on close to avoid the TIME_WAIT state: I've been having
some problems with router access servers (names withheld to protect the guilty) that have problems dealing with
back-to-back connections on a modem dedicated to a specific channel. What they do is let go of the connection,
accept another call, attempt to connect to a well-known socket on a host, and the host refuses the connection
because there is a connection in TIME_WAIT state involving the well-known socket. (Steve's book TCP
Illustrated Vol 1 discusses this problem in more detail.) In order to avoid the connection-refused problem, I've
had to install an option to do reset-on-close in the server when the server initiates the disconnection.
My server is a Linux system running 2.0.34 if that level of detail is important to the discussion.
The IP address is usually the same, but the socket number is always different -- I've logged the socket
numbers used by the router access servers and they are indeed different. I don't have a log for refused
connections, however. (Interested in how to record this information, by the way.)
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): Why does it take so
long to detect that the peer died?
From Andrew Gierth ( [email protected]):
Because by default, no packets are sent on the TCP connection unless there is data to send or
acknowledge.
So, if you are simply waiting for data from the peer, there is no way to tell if the peer has
silently gone away, or just isn't ready to send any more data yet. This can be a problem
(especially if the peer is a PC, and the user just hits the Big Switch...).
One solution is to use the SO_KEEPALIVE option. This option enables periodic probing of the
connection to ensure that the peer is still present. BE WARNED: the default timeout for this
option is AT LEAST 2 HOURS. This timeout can often be altered (in a system-dependent
fashion) but not normally on a per-connection basis (AFAIK).
RFC1122 specifies that this timeout (if it exists) must be configurable. On the majority of Unix
variants, this configuration may only be done globally, affecting all TCP connections which
have keepalive enabled. The method of changing the value, moreover, is often difficult and/or
poorly documented, and in any case is different for just about every version in existence.
If you must change the value, look for something resembling tcp_keepidle in your kernel
configuration or network options configuration.
If you're sending to the peer, though, you have some better guarantees; since sending data
implies receiving ACKs from the peer, then you will know after the retransmit timeout whether
the peer is still alive. But the retransmit timeout is designed to allow for various contingencies,
with the intention that TCP connections are not dropped simply as a result of minor network
upsets. So you should still expect a delay of several minutes before getting notification of the
failure.
The approach taken by most application protocols currently in use on the Internet (e.g. FTP,
SMTP etc.) is to implement read timeouts on the server end; the server simply gives up on the
client if no requests are received in a given time period (often of the order of 15 minutes).
Protocols where the connection is maintained even if idle for long periods have two choices:
1. use SO_KEEPALIVE
2. use a higher-level keepalive mechanism (such as sending a null request to the server
every so often).
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): What are the pros/cons
of select(), non-blocking I/O and SIGIO?
Using non-blocking I/O means that you have to poll sockets to see if there is data to be read
from them. Polling should usually be avoided since it uses more CPU time than other
techniques.
Using SIGIO allows your application to do what it does and have the operating system tell it
(with a signal) that there is data waiting for it on a socket. The only drawback to this soltion is
that it can be confusing, and if you are dealing with multiple sockets you will have to do a
select() anyway to find out which one(s) is ready to be read.
Using select() is great if your application has to accept data from more than one socket at a
time since it will block until any one of a number of sockets is ready with data. One other
advantage to select() is that you can set a time-out value after which control will be
returned to you whether any of the sockets have data for you or not.
From: c0redump
yeah man, i do the same except when i am sucking cock, i kinda multiplex so i can do erm all at
the same time, then when they are ready to cum, i just check their dicks, etc.
From: Ura Moron
Ajji footi
From: sickened
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): Why do I get EPROTO
from read()?
From Steve Rago ([email protected]):
EPROTO means that the protocol encountered an unrecoverable error for that endpoint.
EPROTO is one of those catch-all error codes used by STREAMS-based drivers when a better
code isn't available.
And an addition note from Andrew ([email protected]):
Not quite to do with EPROTO from read(), but I found out once that on some
STREAMS-based implementations, EPROTO could be returned by accept() if the incoming
connection was reset before the accept completes.
On some other implementations, accept seemed to be capable of blocking if this occured. This
is important, since if select() said the listening socket was readable, then you would
normally expect not to block in the accept() call. The fix is, of course, to set nonblocking
mode on the listening socket if you are going to use select() on it.
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): How can I force a
socket to send the data in its buffer?
From Richard Stevens ([email protected]):
You can't force it. Period. TCP makes up its own mind as to when it can send data. Now,
normally when you call write() on a TCP socket, TCP will indeed send a segment, but
there's no guarantee and no way to force this. There are lots of reasons why TCP will not send a
segment: a closed window and the Nagle algorithm are two things to come immediately to
mind.
(Snipped suggestion from Andrew Gierth to use TCP_NODELAY)
Setting this only disables one of the many tests, the Nagle algorithm. But if the original poster's
problem is this, then setting this socket option will help.
A quick glance at tcp_output() shows around 11 tests TCP has to make as to whether to send a
segment or not.
Now from Dr. Charles E. Campbell Jr. ([email protected]):
As you've surmised, I've never had any problem with disabling Nagle's algorithm. Its basically a
buffering method; there's a fixed overhead for all packets, no matter how small. Hence, Nagle's
algorithm collects small packets together (no more than .2sec delay) and thereby reduces the
amount of overhead bytes being transferred. This approach works well for rcp, for example: the
.2 second delay isn't humanly noticeable, and multiple users have their small packets more
efficiently transferred. Helps in university settings where most folks using the network are using
standard tools such as rcp and ftp, and programs such as telnet may use it, too.
However, Nagle's algorithm is pure havoc for real-time control and not much better for
keystroke interactive applications (control-C, anyone?). It has seemed to me that the types of
new programs using sockets that people write usually do have problems with small packet
delays. One way to bypass Nagle's algorithm selectively is to use "out-of-band" messaging, but
that is limited in its content and has other effects (such as a loss of sequentiality) (by the way,
out-of-band is often used for that ctrl-C, too).
More from Vic:
So to sum it all up, if you are having trouble and need to flush the socket, setting the
TCP_NODELAY option will usually solve the problem. If it doesn't, you will have to use
out-of-band messaging, but according to Andrew, "out-of-band data has its own problems, and I
don't think it works well as a solution to buffering delays (haven't tried it though). It is not
'expedited data' in the sense that exists in some other protocols; it is transmitted in-stream, but
with a pointer to indicate where it is."
I asked Andrew something to the effect of "What promises does TCP make about when it
will get around to writing data to the network?" I thought his reply should be put under this
question:
Not many promises, but some.
I'll try and quote chapter and verse on this:
References:
RFC 1122, "Requirements for Internet Hosts" (also STD 3)
RFC 793, "Transmission Control Protocol" (also STD 7)
1. The socket interface does not provide access to the TCP PUSH flag.
2. RFC1122 says (4.2.2.2): A TCP MAY implement PUSH flags on SEND calls. If PUSH
flags are not implemented, then the sending TCP: (1) must not buffer data indefinitely,
and (2) MUST set the PSH bit in the last buffered segment (i.e., when there is no more
queued data to be sent).
3. RFC793 says (2.8): When a receiving TCP sees the PUSH flag, it must not wait for more
data from the sending TCP before passing the data to the receiving process. [RFC1122
supports this statement.]
4. Therefore, data passed to a write() call must be delivered to the peer within a finite
time, unless prevented by protocol considerations.
5. There are (according to a post from Stevens quoted in the FAQ [earlier in this answer -
Vic]) about 11 tests made which could delay sending the data. But as I see it, there are
only 2 that are significant, since things like retransmit backoff are a) not under the
programmers control and b) must either resolve within a finite time or drop the
connection.
The first of the interesting cases is "window closed" (ie. there is no buffer space at the receiver;
this can delay data indefinitely, but only if the receiving process is not actually reading the data
that is available)
Vic asks:
OK, it makes sense that if the client isn't reading, the data isn't going to make it across the
connection. I take it this causes the sender to block after the recieve queue is filled?
The sender blocks when the socket send buffer is full, so buffers will be full at both ends.
While the window is closed, the sending TCP sends window probe packets. This ensures that
when the window finally does open again, the sending TCP detects the fact. [RFC1122, ss
4.2.2.17]
The second interesting case is "Nagle algorithm" (small segments, e.g. keystrokes, are delayed
to form larger segments if ACKs are expected from the peer; this is what is disabled with
TCP_NODELAY)
Vic Asks:
Does this mean that my tcpclient sample should set TCP_NODELAY to ensure that the
end-of-line code is indeed put out onto the network when sent?
No. tcpclient.c is doing the right thing as it stands; trying to write as much data as possible in as
few calls to write() as is feasible. Since the amount of data is likely to be small relative to
the socket send buffer, then it is likely (since the connection is idle at that point) that the entire
request will require only one call to write(), and that the TCP layer will immediately
dispatch the request as a single segment (with the PSH flag, see point 2.2 above).
The Nagle algorithm only has an effect when a second write() call is made while data is still
unacknowledged. In the normal case, this data will be left buffered until either: a) there is no
unacknowledged data; or b) enough data is available to dispatch a full-sized segment. The delay
cannot be indefinite, since condition (a) must become true within the retransmit timeout or the
connection dies.
Since this delay has negative consequences for certain applications, generally those where a
stream of small requests are being sent without response, e.g. mouse movements, the standards
specify that an option must exist to disable it. [RFC1122, ss 4.2.3.4]
Additional note: RFC1122 also says:
[DISCUSSION]:
When the PUSH flag is not implemented on SEND calls, i.e., when the application/TCP
interface uses a pure streaming model, responsibility for aggregating any tiny data
fragments to form reasonable sized segments is partially borne by the application layer.
So programs should avoid calls to write() with small data lengths (small relative to the MSS,
that is); it's better to build up a request in a buffer and then do one call to sock_write() or
equivalent.
The other possible sources of delay in the TCP are not really controllable by the program, but
they can only delay the data temporarily.
Vic asks:
By temporarily, you mean that the data will go as soon as it can, and I won't get stuck in a
position where one side is waiting on a response, and the other side hasn't recieved the
request? (Or at least I won't get stuck forever)
You can only deadlock if you somehow manage to fill up all the buffers in both directions... not
easy.
If it is possible to do this, (can't think of a good example though), the solution is to use
nonblocking mode, especially for writes. Then you can buffer excess data in the program as
necessary.
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): Where can I get a
library for programming sockets?
There is the Simple Sockets Library by Charles E. Campbell, Jr. PhD. and Terry McRoberts.
The file is called ssl.tar.gz, and you can download it from this faq's home page. For c++ there is
the Socket++ library which is on ftp://ftp.virginia.edu/pub/socket++-1.11.tar.gz. There is also
C++ Wrappers. The file is called ftp://ftp.huji.ac.il/pub/languages/C++/C++_wrappers.tar.gz.
Thanks to Bill McKinnon for tracking it down for me! From http://www.cs.wustl.edu/~schmidt
you should be able to find the ACE toolkit. Another C++ library called libtcp++ is also
available at http://www.sashanet.com/internet/download.html. PING Software Group has some
libraries that include a sockets interface among other things. It seems to be all Java stuff now.
You can find their stuff at http://www.nerosworld.com/ping/. Thanks to Reid Judd for hunting
that down for us!
Philippe Jounin has developed a cross platform library which includes high level support for
http and ftp protocols, with more to come. You can find it at
http://perso.magic.fr/jounin-ph/P_tcp4u.htm, and you can find a review of it at
http://www6.zdnet.com/cgi-bin/texis/swlib/hotfiles/info.html?fcode=000H4F
I don't have any experience with any of these libraries, so I can't recomend one over the other.
From: Zhao Cheng
Hi,
In your FAQ Item -- 2.12 "Where can I get a library for programming sockets?". Links to
ssl.tar.gz and ftp://ftp.virginia.edu/pub/socket++-1.11.tar.gz are broken.
By the way, your web site is really very helpful for me.
Result: http://wauug.erols.com/pub/sunsite/libs/ssl.tar.gz
From:
The Socket++ library has a website:
http://www.cs.utexas.edu/users/lavender/courses/socket++/index.html
From: Lauri Nurmi
I have modified Socket++ version 1.11 to make it compile with recent GCC versions under
Linux (i386).
The modified version is available as tar.gz and RPM here. You will also find the original,
unmodified socket++-1.11.tar.gz there.
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): How come select says
there is data, but read returns zero?
The data that causes select to return is the EOF because the other side has closed the
connection. This causes read to return zero. For more information see 2.1 How can I tell when a
socket is closed on the other end?
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): Whats the difference
between select() and poll()?
From Richard Stevens ([email protected]):
The basic difference is that select()'s fd_set is a bit mask and therefore has some fixed
size. It would be possible for the kernel to not limit this size when the kernel is compiled,
allowing the application to define FD_SETSIZE to whatever it wants (as the comments in the
system header imply today) but it takes more work. 4.4BSD's kernel and the Solaris library
function both have this limit. But I see that BSD/OS 2.1 has now been coded to avoid this limit,
so it's doable, just a small matter of programming. :-) Someone should file a Solaris bug report
on this, and see if it ever gets fixed.
With poll(), however, the user must allocate an array of pollfd structures, and pass the
number of entries in this array, so there's no fundamental limit. As Casper notes, fewer systems
have poll() than select, so the latter is more portable. Also, with original implementations
(SVR3) you could not set the descriptor to -1 to tell the kernel to ignore an entry in the pollfd
structure, which made it hard to remove entries from the array; SVR4 gets around this.
Personally, I always use select() and rarely poll(), because I port my code to BSD
environments too. Someone could write an implementation of poll() that uses select(),
for these environments, but I've never seen one. Both select() and poll() are being
standardized by POSIX 1003.1g.
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): How do I send [this]
over a socket
Anything other than single bytes of data will probably get mangled unless you take care. For
integer values you can use htons() and friends, and strings are really just a bunch of single
bytes, so those should be OK. Be careful not to send a pointer to a string though, since the
pointer will be meaningless on another machine. If you need to send a struct, you should write
sendthisstruct() and readthisstruct() functions for it that do all the work of
taking the structure apart on one side, and putting it back together on the other. If you need to
send floats, you may have a lot of work ahead of you. You should read RFC 1014 which is
about portable ways of getting data from one machine to another (thanks to Andrew Gabriel for
pointing this out).
From: Gregory
Where can i find sendthisstruct and readthisstruct. What library are they in and are there
definitions of what arguments they take and return.These functions seem like they could solve
alot of my problems Thanks
From: Rob Seace
No, I think the point was that YOU are supposed to write
those functions yourself... Because, only you will know
the contents of your structures, and how to properly
assemble and disassemble them...
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): How do I use TCP_NODELAY?
First off, be sure you really want to use it in the first place. It will disable the Nagle algorithm (see 2.11 How can I
force a socket to send the data in its buffer?), which will cause network traffic to increase, with smaller than
needed packets wasting bandwidth. Also, from what I have been able to tell, the speed increase is very small, so
you should probably do it without TCP_NODELAY first, and only turn it on if there is a problem.
Here is a code example, with a warning about using it from Andrew Gierth:
int flag = 1;
int result = setsockopt(sock, /* socket affected */
IPPROTO_TCP, /* set option at TCP level */
TCP_NODELAY, /* name of option */
(char *) &flag, /* the cast is historical
cruft */
sizeof(int)); /* length of option value */
if (result < 0)
... handle the error ...
TCP_NODELAY is for a specific purpose; to disable the Nagle buffering algorithm. It should only be set for
applications that send frequent small bursts of information without getting an immediate response, where timely
delivery of data is required (the canonical example is mouse movements).
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): What exactly does the
Nagle algorithm do?
It groups together as much data as it can between ACK's from the other end of the connection. I found
this really confusing until Andrew Gierth ([email protected]) drew the following
diagram, and explained:
This diagram is not intended to be complete, just to illustrate the point better...
Case 1: client writes 1 byte per write() call. The program on host B is tcpserver.c from the FAQ
examples.
CLIENT SERVER
APP TCP TCP APP
[connection setup omitted]
CLIENT SERVER
APP TCP TCP APP
[connection setup omitted]
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): What is the difference
between read() and recv()?
From Andrew Gierth ([email protected]):
read() is equivalent to recv() with a flags parameter of 0. Other values for the flags
parameter change the behaviour of recv(). Similarly, write() is equivalent to send()
with flags == 0.
It is unlikely that send()/recv() would be dropped; perhaps someone with a copy of the POSIX
drafts for socket calls can check...
Portability note: non-unix systems may not allow read()/write() on sockets, but
recv()/send() are usually ok. This is true on Windows and OS/2, for example.
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): I see that send()/write()
can generate SIGPIPE. Is there any advantage
to handling the signal, rather than just ignoring
it and checking for the EPIPE error?
From Andrew Gierth ([email protected]):
In general, the only parameter passed to a signal handler is the signal number that caused it to
be invoked. Some systems have optional additional parameters, but they are no use to you in
this case.
My advice is to just ignore SIGPIPE as you suggest. That's what I do in just about all of my
socket code; errno values are easier to handle than signals (in fact, the first revision of the FAQ
failed to mention SIGPIPE in that context; I'd got so used to ignoring it...)
There is one situation where you should not ignore SIGPIPE; if you are going to exec()
another program with stdout redirected to a socket. In this case it is probably wise to set
SIGPIPE to SIG_DFL before doing the exec().
Jesse Norell has pointed out that if you are using SO_KEEPALIVE to test the connection, and
you aren't doing reads or writes very frequently, you might want to leave SIGPIPE enabled so
that your server process gets signalled when the system determines your link is dead. Normally
though you will just check returns from read()/write() and act appropriately.
From: Corey
And once you receive an EPIPE error on the client are you forced to close that connection and
reestablish a new connection? Even though the server thinks there is still a connection?
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): After the chroot(), calls
to socket() are failing. Why?
From Andrew Gierth ([email protected]):
On systems where sockets are implemented on top of Streams (e.g. all SysV-based systems,
presumably including Solaris), the socket() function will actually be opening certain special
files in /dev. You will need to create a /dev directory under your fake root and populate it with
the required device nodes (only).
Your system documentation may or may not specify exactly which device nodes are required; I
can't help you there (sorry). (Editors note: Adrian Hall ([email protected]) suggested checking
the man page for ftpd, which should list the files you need to copy and devices you need to
create in the chroot'd environment.)
A less-obvious issue with chroot() is if you call syslog(), as many daemons do;
syslog() opens (depending on the system) either a UDP socket, a FIFO or a Unix-domain
socket. So if you use it after a chroot() call, make sure that you call openlog() *before*
the chroot.
From: Stanislav Shalunov
On Solaris you need /dev/tcp (and/or /dev/udp) in order for programs linked with -lsocket -lnsl
to work. The libraries will also use /etc/netconfig which may or may not need to be copied to
chroot jail depending on versions. (In Solaris, /dev/tcp will be a symlink to ../devices/pseudo/...;
you need to notice the major and minor numbers of the file /dev/tcp points to and recreate that.
The partition must not be mounted nosuid because in Solaris nosuid implies nodev. Ouch, or
use BSD.)
From: Stanislav Shalunov
In most version of libc, openlog() itself will not be sufficient to cause the library to actually
open the connection. You would have to actually syslog() something. Alternatively, a
system-dependent FIFO (like /dev/log might be moved to the chroot jail and a symlink be put in
the original location. This will obviously work only if you have a single chroot'ed daemon.
Wietse Venema's Postfix MTA has scripts that set up chroot jail for various Unices.)
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): Why do I keep getting
EINTR from the socket calls?
This isn't really so much an error as an exit condition. It means that the call was interrupted by a
signal. Any call that might block should be wrapped in a loop that checkes for EINTR, as is
done in the example code (See 1.8. Sample Source Code).
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): When will my
application receive SIGPIPE?
From Richard Stevens ([email protected]):
Very simple: with TCP you get SIGPIPE if your end of the connection has received an RST
from the other end. What this also means is that if you were using select instead of write, the
select would have indicated the socket as being readable, since the RST is there for you to read
(read will return an error with errno set to ECONNRESET).
Basically an RST is TCP's response to some packet that it doesn't expect and has no other way
of dealing with. A common case is when the peer closes the connection (sending you a FIN) but
you ignore it because you're writing and not reading. (You should be using select.) So you
write to a connection that has been closed by the other end and the other end's TCP responds
with an RST.
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): What are socket
exceptions? What is out-of-band data?
Unlike exceptions in C++, socket exceptions do not indicate that an error has occured. Socket
exceptions usually refer to the notification that out-of-band data has arrived. Out-of-band data
(called "urgent data" in TCP) looks to the application like a separate stream of data from the
main data stream. This can be useful for separating two different kinds of data. Note that just
because it is called "urgent data" does not mean that it will be delivered any faster, or with
higher priorety than data in the in-band data stream. Also beware that unlike the main data
stream, the out-of-bound data may be lost if your application can't keep up with it.
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): How can I find the full
hostname (FQDN) of the system I'm running
on?
From Richard Stevens ([email protected]):
Some systems set the hostname to the FQDN and others set it to just the unqualified host name.
I know the current BIND FAQ recommends the FQDN, but most Solaris systems, for example,
tend to use only the unqualified host name.
Regardless, the way around this is to first get the host's name (perhaps an FQDN, perhaps
unaualified). Most systems support the Posix way to do this using uname(), but older BSD
systems only provide gethostname(). Call gethostbyname() to find your IP address.
Then take the IP address and call gethostbyaddr(). The h_name member of the
hostent{} should then be your FQDN.
From: Stanislav Shalunov
Since the DNS can be very slow in some setups it might be preferable to try to use uname() if
it is supported. If the program is supposed to be portable then GNU autoconf would be the way
to go. (The results of not doing this can be quite annoying: e.g., GNU Emacs does a reverse
lookup to find FQDN on startup, which means that if the nameserver is not local and the system
has no network connection at the moment you'd have to wait a long time to see the editor
started.)
From: Erik Landry
Add a Comment
Questions regarding both Clients and Servers
(TCP/SOCK_STREAM): How do I monitor the
activity of sockets?
From: Matthias Rabast ([email protected])
For monitoring throughput there are tools such as IPAudit that will monitor throughput. I can't
remember which tool I used to use for this purpose, but a quick search found IPAudit. I haven't
tried it, so let me know if it works, or if you know some better tools.
You can use netstat -a under solaris and look at the Swind and Rwind columns for send
and recieve window sizes.
I'm not aware of any tools for monitoring how often a socket blocks. Someone please add a
comment if you have any suggestions for this.
You could parse the output of snoop/tcpdump to get some of this information. Let me know if
you know a good parser and I'll list it here.
Add a Comment
Writing Client Applications (TCP/SOCK_STREAM):
How do I convert a string into an internet address?
If you are reading a host's address from the command line, you may not know if you have an
aaa.bbb.ccc.ddd style address, or a host.domain.com style address. What I do with these, is first try to use
it as a aaa.bbb.ccc.ddd type address, and if that fails, then do a name lookup on it. Here is an example:
IMO it is better to use only BSD sockets. Or at least specify your platform.
From: Rob Seace
Screwtape, you're wrong: I'm sitting at a "Linux 2.2" system right now, and I can assure you it has both
inet_pton() and getaddrinfo()... And, in fact, I've got software sitting right here on the machine, which
USES both of those functions, and works quite well... (To be more specific, the system is running Red Hat
6.2... But, I've used the functions since at least RH 6.0... But, really, all that matters is the version of glibc,
since THAT is what is implementing them; the version of the kernel is not really relevent...) You'll find
getaddrinfo() defined in "/usr/include/netdb.h", along with the standard gethostby*() functions... And,
you'll find inet_pton() defined in "/usr/include/arpa/inet.h", along with inet_addr(), and all the various
other similar functions...
But, more than just being available under Linux (or any other platform glibc is available on), those
functions are defined as part of the POSIX.1g standard, now... So, any OS that is POSIX complaint
SHOULD be implementing them... But, given that the standards are fairly new still (and, last I heard, were
still in flux), I'm sure many still don't support them... Regardless, I still maintain that IF they are available
to you, you should use them... If they just aren't available on the platform you need to write code for, then
obviously you can't use them... (Well, actually, you COULD, because there are available source code
implementations, which you could borrow... If you don't want to dig the code out of glibc, I believe the
late, great, and dearly missed W. Richard Stevens made available implementations in the source code for
his wonderful "Unix Network Programming" book... Yep, you can get the code right here... Then, after
extracting it, you'll find the getaddrinfo() implementation under "unpv12e/libgai/", and inet_pton() under
"unpv12e/libfree/"...)
From: Rob Seace
Oh, and if you're interested in more info on the use of getaddrinfo(), inet_pton(), and various other
relatively new (and, better) socket functions, I would recommend reading RFC-2553, which details
various socket API changes necessary for dealing with IPv6, and mentions both getaddrinfo() and
inet_pton()...
Add a Comment
Writing Client Applications
(TCP/SOCK_STREAM): How can my client
work through a firewall/proxy server?
If you are running through separate proxies for each service, you shouldn't need to do anything.
If you are working through sockd, you will need to "socksify" your application. Details for
doing this can be found in the package itself, which is available at:
ftp://coast.cs.purdue.edu/pub/tools/unix/socks/
Some have reported that they can't get to the coast archive because it blocks hosts which do not
have a PTR DNS record for reverse lookups. Here are alternative (and probably better)
locations for socks protocol information:
ftp://ftp.nec.com:/pub/socks/ for Socks V4 stuff
http://www.socks.nec.com/ for Socks V5 stuff
Take care,
Vic.
Add a Comment
Writing Client Applications
(TCP/SOCK_STREAM): Why does connect()
succeed even before my server did an
accept()?
From Andrew Gierth ([email protected]):
Once you have done a listen() call on your socket, the kernel is primed to accept
connections on it. The usual UNIX implementation of this works by immediately completing
the SYN handshake for any incoming valid SYN segments (connection attempts), creating the
socket for the new connection, and keeping this new socket on an internal queue ready for the
accept() call. So the socket is fully open before the accept is done.
The other factor in this is the 'backlog' parameter for listen(); that defines how many of
these completed connections can be queued at one time. If the specified number is exceeded,
then new incoming connects are simply ignored (which causes them to be retried).
Add a Comment
Writing Client Applications
(TCP/SOCK_STREAM): Why do I sometimes
lose a server's address when using more than
one server?
From Andrew Gierth ([email protected]):
Take a careful look at struct hostent. Notice that almost everything in it is a pointer? All these
pointers will refer to statically allocated data.
For example, if you do:
respected sir,
please explain when we click any hyperlink
what are the procedures takes place before getting the require
data.
with regards,
t.v.rao
Add a Comment
Writing Client Applications
(TCP/SOCK_STREAM): How can I set the
timeout for the connect() system call?
From Richard Stevens ([email protected]):
Normally you cannot change this. Solaris does let you do this, on a per-kernel basis with the
ndd tcp_ip_abort_cinterval parameter.
The easiest way to shorten the connect time is with an alarm() around the call to
connect(). A harder way is to use select(), after setting the socket nonblocking. Also
notice that you can only shorten the connect time, there's normally no way to lengthen it.
From Andrew Gierth ([email protected]):
First, create the socket and put it into non-blocking mode, then call connect(). There are three
possibilities:
● connect succeeds: the connection has been successfully made (this usually only happens
when connecting to the same machine)
● connect fails: obvious
● connect returns -1/EINPROGRESS. The connection attempt has begun, but not yet
completed.
If the connection succeeds:
● the socket will select() as writable (and will also select as readable if data arrives)
This answer doesn't cover how to force the actual _timeout_. I assume a simple close() will do,
but it'd be nice to have the FAQ bit answer the actual question. (And yes, this is actually a
situation that came up, in a server where identd query will be waited for limited time before
letting the main connection in)
From: jagadeesh
Hello,
Try this
sts = connect(mysock, &msaddr, sizeof (msaddr));
if (sts)
{
if (errno == ECONNREFUSED)
{
printf("connection refused\n");
return;
}
else if (errno == ETIMEDOUT)
{
printf("connection attempt timed out\n");
return;
From: Tan Nguyen
Nope, that doesn't solve the problem at all. For example, we attempt to connect to a
non-existent host (ie 209.blah.blah.blah), then connect() just keeps trying to look up the routing
table for the host. Thus, you never get a return from connect().
From: Oren Bassik
I'm not sure about this, but if you get an alarm signal while connecting, it will return with
EINTR.
Add a Comment
Writing Client Applications
(TCP/SOCK_STREAM): Should I bind() a port
number in my client program, or let the system
choose one for me on the connect() call?
From Andrew Gierth ([email protected]):
Add a Comment
Writing Client Applications
(TCP/SOCK_STREAM): Why do I get
"connection refused" when the server isn't
running?
The connect() call will only block while it is waiting to establish a connection. When there
is no server waiting at the other end, it gets notified that the connection can not be established,
and gives up with the error message you see. This is a good thing, since if it were not the case
clients might wait for ever for a service which just doesn't exist. Users would think that they
were only waiting for the connection to be established, and then after a while give up, muttering
something about crummy software under their breath.
Add a Comment
Writing Client Applications
(TCP/SOCK_STREAM): What does one do
when one does not know how much
information is comming over the socket? Is
there a way to have a dynamic buffer?
This question asked by Niranjan Perera ([email protected]).
When the size of the incoming data is unknown, you can either make the size of the buffer as
big as the largest possible (or likely) buffer, or you can re-size the buffer on the fly during your
read. When you malloc() a large buffer, most (if not all) varients of unix will only allocate
address space, but not physical pages of ram. As more and more of the buffer is used, the kernel
allocates physical memory. This means that malloc'ing a large buffer will not waste resources
unless that memory is used, and so it is perfectly acceptable to ask for a meg of ram when you
expect only a few K.
On the other hand, a more elegant solution that does not depend on the inner workings of the
kernel is to use realloc() to expand the buffer as required in say 4K chunks (since 4K is the size
of a page of ram on most systems). I may add something like this to sockhelp.c in the example
code one day.
From: Sujay
Lets say your application does this: buf = (char *)malloc(10000000000); Your
machine has only 128MB of ram. If the OS actually tried to allocate that much RAM, it would
exhaust the system's resources. What most operating systems do is allocate only the memory
that is used. On most systems that I've used, memory allocation is done in 4K "pages". The
above malloc() doesn't actually allocate anything but address space. No physical RAM is
allocated. So if I then added... buf[0] = 0; buf[5] = 0; buf[9999999999] =
0; The first assignment would cause a page-fault because the memory for it has not yet been
allocated. The OS traps the page-fault, sees that it did promise that memory to an application,
allocates it and allows the assignment to continue. Now, assuming a page size of 4K the first
4096 characters of the buffer have been allocated. The second assignment produces no page
fault and no additional memory is allocated. Now what do you expect to happen with the last
assign? The buffer at that possition has not been mapped to physical memory yet, so it too
produces a page fault. Once again the OS traps the error, allocates the memory and allows the
assignment to continue. Note that it does not allocate all pages between the two blocks. The OS
will have only allocated two blocks for a total of 8K of physical RAM. If you know that the OS
you are targetting does physical allocation of memory on demand you can take advantage of the
fact. In this example you can use it to create an expanding buffer with no tricky coding
required. You could also use it for a very sparse array. The more correct thing to do is
realloc() the buffer as required. I've coded this sort of thing a few times, but of course now
that I want to pull out an example to share with you I can't find one. It isn't complicated
anyway, you just look for the buffer to fill, and then realloc() it a bit bigger each time it fill
up. Hope this helps, Vic.
From: Garen Parham
A good way to handle the unexpected length of data which could be coming in is to use a
fixed-length buffer which could be the largest size of data you expect to receive, but in one
read() you may not get it all into your static-length buffer either because it's too short or there
wasn't enough data in the kernels receive queue at the time of the read(). The fixed length buffer
could then be used as a kind of ring queue data structure, if you reach the end of your buffer and
didn't receive all of what you expected (say for instance with a line protocol, you didn't get the
\r\n or \n (CR-LF or LF)) you could write that over the beginning of your fixed length buffer,
update the write position to point past that so the next read concatenates it for you and so on.
From:
test1
From:
test2
From:
test3
From:
test4
From: David Gillies
/***************************************************************
ReadBufferedData
***************************************************************/
bytesLeft=bufLen;
do
{
bytesThisTime=recv(readSocket,buffer+bytesSoFar,bytesLeft,0);
if(bytesThisTime==0)
{
readErr=socketEOFErr;
done=TRUE;
}
if(bytesThisTime==-1)
{
readErr=socketReadErr;
*errnoBack=errno;
done=TRUE;
}
else
{
bytesSoFar+=bytesThisTime;
bytesLeft-=bytesThisTime;
if(bytesLeft==0)
done=TRUE;
}
}while(!done);
if((readErr==noErr)||(readErr==socketEOFErr))
*bytesRead=bytesSoFar;
return readErr;
}
Add a Comment
Writing Client Applications
(TCP/SOCK_STREAM): How can I determine
the local port number?
From: Fajun Shi ([email protected]):
Hi, my question is: When I write a client, how can I know the port number that the socket
bound in my machine?
From: Jörg Jensch
Hi!
Greetings
Jayjay
Add a Comment
Writing Server Applications
(TCP/SOCK_STREAM): How come I get
"address already in use" from bind()?
You get this when the address is already in use. (Oh, you figured that much out?) The most
common reason for this is that you have stopped your server, and then re-started it right away.
The sockets that were used by the first incarnation of the server are still active. This is further
explained in 2.7 Please explain the TIME_WAIT state., and 2.5 How do I properly close a
socket?.
Add a Comment
Writing Server Applications
(TCP/SOCK_STREAM): Why don't my sockets
close?
When you issue the close() system call, you are closing your interface to the socket, not the
socket itself. It is up to the kernel to close the socket. Sometimes, for really technical reasons,
the socket is kept alive for a few minutes after you close it. It is normal, for example for the
socket to go into a TIME_WAIT state, on the server side, for a few minutes. People have
reported ranges from 20 seconds to 4 minutes to me. The official standard says that it should be
4 minutes. On my Linux system it is about 2 minutes. This is explained in great detail in 2.7
Please explain the TIME_WAIT state..
From: Erik landry
Also, the kernel will NOT shutdown a socket on a close(2) if another process (e.g., a child that
inherited the file descriptor) still has the socket open. For more information, see shutdown(2) or
2.2 When should I use shutdown()
Add a Comment
Writing Server Applications (TCP/SOCK_STREAM): How
can I make my server a daemon?
There are two approaches you can take here. The first is to use inetd to do all the hard work for you. The second is to
do all the hard work yourself.
If you use inetd, you simply use stdin, stdout, or stderr for your socket. (These three are all created with
dup() from the real socket) You can use these as you would a socket in your code. The inetd process will even
close the socket for you when you are done. For more information on setting this up, look at the man page for inetd.
If you wish to write your own server, there is a detailed explanation in "Unix Network Programming" by Richard
Stevens (see 1.6 Where can I get source code for the book [book title]?). I also picked up this posting from
comp.unix.programmer, by Nikhil Nair ([email protected]). You may want to add code to ignore SIGPIPE,
because if this signal is not dealt with, it will cause your application to exit. (Thanks to [email protected] for
pointing this out).
I worked all this lot out from the GNU C Library Manual (on-line
documentation). Here's some code I wrote - you can adapt it as necessary:
#include
#include
#include
#include
#include
#include
#include
/* Global variables */
...
volatile sig_atomic_t keep_going = 1; /* controls program termination */
/* Function prototypes: */
...
void termination_handler (int signum); /* clean up before termination */
int
main (void)
{
...
if (chdir (HOME_DIR)) /* change to directory containing data
files */
{
fprintf (stderr, "`%s': ", HOME_DIR);
perror (NULL);
exit (1);
}
/* Become a daemon: */
switch (fork ())
{
case -1: /* can't fork */
perror ("fork()");
exit (3);
case 0: /* child, process becomes a daemon: */
close (STDIN_FILENO);
close (STDOUT_FILENO);
close (STDERR_FILENO);
if (setsid () == -1) /* request a new session (job control) */
{
exit (4);
}
break;
default: /* parent returns to calling process: */
return 0;
}
void
termination_handler (int signum)
{
keep_going = 0;
signal (signum, termination_handler);
}
Add a Comment
Writing Server Applications
(TCP/SOCK_STREAM): How can I listen on
more than one port at a time?
The best way to do this is with the select() call. This tells the kernel to let you know when a
socket is available for use. You can have one process do i/o with multiple sockets with this call.
If you want to wait for a connect on sockets 4, 6 and 10 you might execute the following code
snippet:
fd_set socklist;
I tested on IRIX 6.5, and the fd_set should NOT be in the writeset, but in the read-set. I.e.
select(11, &fds, 0, 0, 0). If you put it in the write-set IRIX 6.5 lets you wait forever.
From: Gavin
Add a Comment
Writing Server Applications
(TCP/SOCK_STREAM): What exactly does
SO_REUSEADDR do?
This socket option tells the kernel that even if this port is busy (in the TIME_WAIT state), go
ahead and reuse it anyway. If it is busy, but with another state, you will still get an address
already in use error. It is useful if your server has been shut down, and then restarted right away
while sockets are still active on its port. You should be aware that if any unexpected data comes
in, it may confuse your server, but while this is possible, it is not likely.
It has been pointed out that "A socket is a 5 tuple (proto, local addr, local port, remote addr,
remote port). SO_REUSEADDR just says that you can reuse local addresses. The 5 tuple still
must be unique!" by Michael Hunter ([email protected]). This is true, and this is why it is
very unlikely that unexpected data will ever be seen by your server. The danger is that such a 5
tuple is still floating around on the net, and while it is bouncing around, a new connection from
the same client, on the same system, happens to get the same remote port. This is explained by
Richard Stevens in 2.7 Please explain the TIME_WAIT state..
Add a Comment
Writing Server Applications
(TCP/SOCK_STREAM): What exactly does
SO_LINGER do?
On some unixes this does nothing. On others, it instructs the kernel to abort tcp connections
instead of closing them properly. This can be dangerous. If you are not clear on this, see 2.7
Please explain the TIME_WAIT state..
Add a Comment
Writing Server Applications
(TCP/SOCK_STREAM): What exactly does
SO_KEEPALIVE do?
From Andrew Gierth ([email protected]):
The SO_KEEPALIVE option causes a packet (called a 'keepalive probe') to be sent to the
remote system if a long time (by default, more than 2 hours) passes with no other data being
sent or received. This packet is designed to provoke an ACK response from the peer. This
enables detection of a peer which has become unreachable (e.g. powered off or disconnected
from the net). See 2.8 Why does it take so long to detect that the peer died? for further
discussion.
Note that the figure of 2 hours comes from RFC1122, "Requirements for Internet Hosts". The
precise value should be configurable, but I've often found this to be difficult. The only
implementation I know of that allows the keepalive interval to be set per-connection is SVR4.2.
From: Mahmoud Chilali
the value is configurable via sysctl on FreeBSD and friends. on these systems, keepalive is set
by default on a per system basis, so applications do not need to set the option.
Add a Comment
Writing Server Applications
(TCP/SOCK_STREAM): 4.8 How can I bind() to
a port number < 1024?
From Andrew Gierth ([email protected]):
The restriction on access to ports < 1024 is part of a (fairly weak) security scheme particular to
UNIX. The intention is that servers (for example rlogind, rshd) can check the port number of
the client, and if it is < 1024, assume the request has been properly authorised at the client end.
The practical upshot of this, is that binding a port number < 1024 is reserved to processes
having an effective UID == root.
This can, occasionally, itself present a security problem, e.g. when a server process needs to
bind a well-known port, but does not itself need root access (news servers, for example). This is
often solved by creating a small program which simply binds the socket, then restores the real
userid and exec()s the real server. This program can then be made setuid root.
Add a Comment
Writing Server Applications
(TCP/SOCK_STREAM): How do I get my server
to find out the client's address / hostname?
From Andrew Gierth ([email protected]):
After accept()ing a connection, use getpeername() to get the address of the client. The
client's address is of course, also returned on the accept(), but it is essential to initialise the
address-length parameter before the accept call for this will work.
Jari Kokko ([email protected]) has offered the following code to determine the client address:
int t;
int len;
struct sockaddr_in sin;
struct hostent *host;
Add a Comment
Writing Server Applications
(TCP/SOCK_STREAM): How should I choose a
port number for my server?
The list of registered port assignments can be found in STD 2 or RFC 1700. Choose one that
isn't already registered, and isn't in /etc/services on your system. It is also a good idea to let
users customize the port number in case of conflicts with other un-registered port numbers in
other servers. The best way of doing this is hardcoding a service name, and using
getservbyname() to lookup the actual port number. This method allows users to change
the port your server binds to by simply editing the /etc/services file.
From: Stephen Satchell
In the course of researching this question, I found a reference in some BSD documentation that
port numbers from 48K to 64K should be used by applications for well-known-socket numbers.
So in an application I wrote, I used 54001 as the well-known port.
Wouldn't you know, I found a TCP/IP product that wouldn't allow me to use that number!
That product (name withheld to protect the guilty) allows socket numbers from zero to 32768.
(NOT 32767, the usual boundry condition. Surprised me, it did.) So I provided for setting an
alternate port address for those people using the *** ******* products. Other products worked
just fine with 54001.
From: Charles E. Campbell, Jr
If you plan to distribute your server, you should consider registering your server with IANA
(http://www.iana.org/)
From: Warren Nash
Add a Comment
Writing Server Applications
(TCP/SOCK_STREAM): What is the difference
between SO_REUSEADDR and
SO_REUSEPORT?
SO_REUSEADDR allows your server to bind to an address which is in a TIME_WAIT state. It
does not allow more than one server to bind to the same address. It was mentioned that use of
this flag can create a security risk because another server can bind to a the same port, by
binding to a specific address as opposed to INADDR_ANY. The SO_REUSEPORT flag allows
multiple processes to bind to the same address provided all of them use the SO_REUSEPORT
option.
From Richard Stevens ([email protected]):
This is a newer flag that appeared in the 4.4BSD multicasting code (although that code was
from elsewhere, so I am not sure just who invented the new SO_REUSEPORT flag).
What this flag lets you do is rebind a port that is already in use, but only if all users of the port
specify the flag. I believe the intent is for multicasting apps, since if you're running the same
app on a host, all need to bind the same port. But the flag may have other uses. For example the
following is from a post in February:
From Stu Friedberg ([email protected]):
SO_REUSEPORT is also useful for eliminating the try-10-times-to-bind hack in
ftpd's data connection setup routine. Without SO_REUSEPORT, only one ftpd
thread can bind to TCP (lhost, lport, INADDR_ANY, 0) in preparation for
connecting back to the client. Under conditions of heavy load, there are more
threads colliding here than the try-10-times hack can accomodate. With
SO_REUSEPORT, things work nicely and the hack becomes unnecessary.
I have also heard that DEC OSF supports the flag. Also note that under 4.4BSD, if you are
binding a multicast address, then SO_REUSEADDR is condisered the same as SO_REUSEPORT
(p. 731 of "TCP/IP Illustrated, Volume 2"). I think under Solaris you just replace
SO_REUSEPORT with SO_REUSEADDR.
From a later Stevens posting, with minor editing:
Basically SO_REUSEPORT is a BSD'ism that arose when multicasting was added, even thought
it was not used in the original Steve Deering code. I believe some BSD-derived systems may
also include it (OSF, now Digital Unix, perhaps?). SO_REUSEPORT lets you bind the same
address *and* port, but only if all the binders have specified it. But when binding a multicast
address (its main use), SO_REUSEADDR is considered identical to SO_REUSEPORT (p. 731,
"TCP/IP Illustrated, Volume 2"). So for portability of multicasting applications I always use
SO_REUSEADDR.
Add a Comment
Writing Server Applications
(TCP/SOCK_STREAM): How can I write a
multi-homed server?
The original question was actually from Shankar Ramamoorthy ([email protected]):
I want to run a server on a multi-homed host. The host is part of two networks and
has two ethernet cards. I want to run a server on this machine, binding to a
pre-determined port number. I want clients on either subnet to be able to send
broadcast packates to the port and have the server receive them.
And answered by Andrew Gierth ([email protected]):
Your first question in this scenario is, do you need to know which subnet the packet came from?
I'm not at all sure that this can be reliably determined in all cases.
If you don't really care, then all you need is one socket bound to INADDR_ANY. That simplifies
things greatly.
If you do care, then you have to bind multiple sockets. You are obviously attempting to do this
in your code as posted, so I'll assume you do.
I was hoping that something like the following would work. Will it? This is on
Sparcs running Solaris 2.4/2.5.
I don't have access to Solaris, but I'll comment based on my experience with other Unixes.
[Shankar's original code omitted]
What you are doing is attempting to bind all the current hosts unicast addresses as listed in
hosts/NIS/DNS. This may or may not reflect reality, but much more importantly, neglects the
broadcast addresses. It seems to be the case in the majority of implementations that a socket
bound to a unicast address will not see incoming packets with broadcast addresses as their
destinations.
The approach I've taken is to use SIOCGIFCONF to retrieve the list of active network
interfaces, and SIOCGIFFLAGS and SIOCGIFBRDADDR to identify broadcastable interfaces
and get the broadcast addresses. Then I bind to each unicast address, each broadcast address,
and to INADDR_ANY as well. That last is necessary to catch packets that are on the wire with
INADDR_BROADCAST in the destination. (SO_REUSEADDR is necessary to bind
INADDR_ANY as well as the specific addresses.)
This gives me very nearly what I want. The wrinkles are:
● I don't assume that getting a packet through a particular socket necessarily means that it
actually arrived on that interface.
● I can't tell anything about which subnet a packet originated on if its destination was
INADDR_BROADCAST.
● On some stacks, apparently only those with multicast support, I get duplicate incoming
messages on the INADDR_ANY socket.
Add a Comment
Writing Server Applications
(TCP/SOCK_STREAM): How can I read only
one character at a time?
This question is usually asked by people who are testing their server with telnet, and want it to
process their keystrokes one character at a time. The correct technique is to use a psuedo
terminal (pty). More on that in a minute.
According to Roger Espel Llima ([email protected]), you can have your server send a
sequence of control characters: 0xff 0xfb 0x01 0xff 0xfb 0x03 0xff 0xfd
0x0f3, which translates to IAC WILL ECHO IAC WILL SUPPRESS-GO-AHEAD IAC
DO SUPPRESS-GO-AHEAD. For more information on what this means, check out std8, std28
and std29. Roger also gave the following tips:
● This code will suppress echo, so you'll have to send the characters the user types back to
the client if you want the user to see them.
● Carriage returns will be followed by a null character, so you'll have to expect them.
● If you get a 0xff, it will be followed by two more characters. These are telnet escapes.
Use of a pty would also be the correct way to execute a child process and pass the i/o to a
socket.
I'll add pty stuff to the list of example source I'd like to add to the faq. If someone has some
source they'd like to contribute (without copyright) to the faq which demonstrates use of pty's,
please email me!
From: lore
Add a Comment
Writing Server Applications (TCP/SOCK_STREAM): I'm
trying to exec() a program from my server, and attach
my socket's IO to it, but I'm not getting all the data
across. Why?
If the program you are running uses printf(), etc (streams from stdio.h) you have to deal with two
buffers. The kernel buffers all socket IO, and this is explained in section 2.11. The second buffer is the one that
is causing you grief. This is the stdio buffer, and the problem was well explained by Andrew:
(The short answer to this question is that you want to use a pty rather than a socket; the remainder of this article
is an attempt to explain why.)
Firstly, the socket buffer controlled by setsockopt() has absolutly nothing to do with stdio buffering.
Setting it to 1 is guaranteed to be the Wrong Thing(tm).
Perhaps the following diagram might make things a little clearer:
Process A Process B
+---------------------+ +---------------------+
| | | |
| mainline code | | mainline code |
| | | | ^ |
| v | | | |
| fputc() | | fgetc() |
| | | | ^ |
| v | | | |
| +-----------+ | | +-----------+ |
| | stdio | | | | stdio | |
| | buffer | | | | buffer | |
| +-----------+ | | +-----------+ |
| | | | ^ |
| | | | | |
| write() | | read() |
| | | | | |
+-------- | ----------+ +-------- | ----------+
| | User space
------------|-------------------------- | ---------------------------
| | Kernel space
v |
+-----------+ +-----------+
| socket | | socket |
| buffer | | buffer |
+-----------+ +-----------+
| ^
v |
(AF- and protocol- (AF- and protocol-
dependent code) dependent code)
Assuming these two processes are communicating with each other (I've deliberately omitted the actual comms
mechanisms, which aren't really relevent), you can see that data written by process A to its stdio buffer is
completely inaccessible to process B. Only once the decision is made to flush that buffer to the kernel (via
write()) can the data actually be delivered to the other process.
The only guaranteed way to affect the buffering within process A is to change the code. However, the default
buffering for stdout is controlled by whether the underlying FD refers to a terminal or not; generally, output to
terminals is line-buffered, and output to non-terminals (including but not limited to files, pipes, sockets, non-tty
devices, etc.) is fully buffered. So the desired effect can usually be achieved by using a pty device; this, for
example, is what the 'expect' program does.
Since the stdio buffer (and the FILE structure, and everything else related to stdio) is user-level data, it is not
preserved across an exec() call, hence trying to use setvbuf() before the exec is ineffective.
A couple of alternate solutions were proposed by Roger Espel Llima ([email protected]):
If it's an option, you can use some standalone program that will just run something inside a pty and buffer its
input/output. I've seen a package by the name pty.tar.gz that did that; you could search around for it with archie
or AltaVista.
Another option (**warning, evil hack**) , if you're on a system that supports this (SunOS, Solaris, Linux ELF
do; I don't know about others) is to, on your main program, putenv() the name of a shared executable (*.so)
in LD_PRELOAD, and then in that .so redefine some commonly used libc function that the program you're
exec'ing is known to use early. There you can 'get control' on the running program, and the first time you get it,
do a setbuf(stdout, NULL) on the program's behalf, and then call the original libc function with a
dlopen() + dlsym(). And you keep the dlsym() value on a static var, so you can just call that the
following times.
(Editors note: I still haven't done an expample for how to do pty's, but I hope I will be able to do one after I
finish the non-blocking example code.)
Add a Comment
Writing UDP/SOCK_DGRAM applications:
When should I use UDP instead of TCP?
UDP is good for sending messages from one system to another when the order isn't important
and you don't need all of the messages to get to the other machine. This is why I've only used
UDP once to write the example code for the faq. Usually TCP is a better solution. It saves you
having to write code to ensure that messages make it to the desired destination, or to ensure the
message ordering. Keep in mind that every additional line of code you add to your project in
another line that could contain a potentially expensive bug.
If you find that TCP is too slow for your needs you may be able to get better performance with
UDP so long as you are willing to sacrifice message order and/or reliability.
Philippe Jounin would like to add...
In chapter 5.1 you say UDP allows more throughput than TCP. It is rarely the case
if you have to pass several routers.
For instance, if you connect two LANs via X25 (a common way in Europe!), every
UDP datagram will :
● establish a Virtual Channel (VC)
Add a Comment
Writing UDP/SOCK_DGRAM applications:
What is the difference between "connected"
and "unconnected" sockets?
From Andrew Gierth ([email protected]):
If a UDP socket is unconnected, which is the normal state after a bind() call, then send()
or write() are not allowed, since no destination address is available; only sendto() can be
used to send data.
Calling connect() on the socket simply records the specified address and port number as
being the desired communications partner. That means that send() or write() are now
allowed; they use the destination address and port given on the connect call as the destination of
the packet.
From: Sanjay Pujare
I have another question: When I "connect" a UDP socket to a remote addr and port, is there a
corresponding "accept" at the other end for my "connect" to go through? I know that when a
TCP socket is connected, the connection happens when the server "accept"s the connection.
What is the equivalent thing for UDP sockets?
From: Rob Seace
Yes, in two ways. First, only datagrams from your "connected peer" are returned. All others
arriving at your port are not delivered to you.
But most importantly, a UDP socket must be connected to receive ICMP errors. Pp. 748-749 of
"TCP/IP Illustrated, Volume 2" give all the gory details on why this is so.
Add a Comment
Writing UDP/SOCK_DGRAM applications: How
can I read ICMP errors from "connected" UDP
sockets?
If the target machine discards the message because there is no process reading on the requested
port number, it sends an ICMP message to your machine which will cause the next system call
on the socket to return ECONNREFUSED. Since delivery of ICMP messages is not guarenteed
you may not recieve this notification on the first transaction.
Remember that your socket must be "connected" in order to receive the ICMP errors. I've been
told, and Alan Cox has verified that Linux will return them on "unconnected" sockets. This may
cause porting problems if your application isn't ready for it, so Alan tells me they've added a
SO_BSDCOMPAT flag which can be set for Linux kernels after 2.0.0.
From: meng
I feel very lucky to see this faq. I have been looking for it for a long time.
As you said that "Linux will return them on "unconnected" sockets. This may cause porting
problems if your application isn't ready for it". I have this problem.
But I still have some questions on how to use the flag SO_BSDOCMPAT. It is use in server or
client? What are other parameters of setsockopt?
Thank you very much.
From: meng
I look for man 7 socket, and get the explaination. The 4nd parameter of system call setsockopt()
should be 1,and the 5 should be sizeof it. setsockopt() should be called on the client.
Now it works well.
Best regards!
Add a Comment
Writing UDP/SOCK_DGRAM applications: How
can I be sure that a UDP message is received?
You have to design your protocol to expect a confirmation back from the destination when a
message is received. Of course is the confirmation is sent by UDP, then it too is unreliable and
may not make it back to the sender. If the sender does not get confirmation back by a certain
time, it will have to re-transmit the message, maybe more than once. Now the receiver has a
problem because it may have already received the message, so some way of dropping duplicates
is required. Most protocols use a message numbering scheme so that the receiver can tell that it
has already processed this message and return another confirmation. Confirmations will also
have to reference the message number so that the sender can tell which message is being
confirmed. Confused? That's why I stick with TCP.
From: Paul Beardsell
Add a Comment
Writing UDP/SOCK_DGRAM applications: How
can I be sure that UDP messages are received
in order?
You can't. What you can do is make sure that messages are processed in order by using a
numbering system as mentioned in 5.5 How can I be sure that a UDP message is received?. If
you need your messages to be received and be received in order you should really consider
switching to TCP. It is unlikely that you will be able to do a better job implementing this sort of
protocol than the TCP people already have, without a significant investment of time.
From: Paul Beardsell
Add a Comment
Writing UDP/SOCK_DGRAM applications: How
often should I re-transmit un-acknowleged
messages?
The simplest thing to do is simply pick a fairly small delay such as one second and stick with it.
The problem is that this can congest your network with useless traffic if there is a problem on
the lan or on the other machine, and this added traffic may only serve to make the problem
worse.
A better technique, described with source code in "UNIX Network Programming" by Richard
Stevens (see 1.6 Where can I get source code for the book [book title]?), is to use an adaptive
timeout with an exponential backoff. This technique keeps statistical information on the time it
is taking messages to reach a host and adjusts timeout values accordingly. It also doubles the
timeout each time it is reached as to not flood the network with useless datagrams. Richard has
been kind enough to post the source code for the book on the web. Check out his home page at
http://www.kohala.com/~rstevens.
Add a Comment
Writing UDP/SOCK_DGRAM applications: How
come only the first part of my datagram is
getting through?
This has to do with the maximum size of a datagram on the two machines involved. This
depends on the sytems involved, and the MTU (Maximum Transmission Unit). According to
"UNIX Network Programming", all TCP/IP implementations must support a minimum IP
datagram size of 576 bytes, regardless of the MTU. Assuming a 20 byte IP header and 8 byte
UDP header, this leaves 548 bytes as a safe maximum size for UDP messages. The maximum
size is 65516 bytes. Some platforms support IP fragmentation which will allow datagrams to be
broken up (because of MTU values) and then re-assembled on the other end, but not all
implementations support this.
This information is taken from my reading of "UNIX Netowrk Programming" (see 1.6 Where
can I get source code for the book [book title]?).
Andrew has pointed out the following regarding large UDP messages:
Another issue is fragmentation. If a datagram is sent which is too large for the network interface
it is sent through, then the sending host will fragment it into smaller packets which are
reassembled by the receiving host. Also, if there are intervening routers, then they may also
need to fragment the packet(s), which greatly increases the chances of losing one or more
fragments (which causes the entire datagram to be dropped). Thus, large UDP datagrams should
be avoided for applications that are likely to operate over routed nets or the Internet proper.
Add a Comment
Writing UDP/SOCK_DGRAM applications: Why
does the socket's buffer fill up sooner than
expected?
From Paul W. Nelson ([email protected]):
In the traditional BSD socket implementation, sockets that are atomic such as UDP keep
received data in lists of mbufs. An mbuf is a fixed size buffer that is shared by various protocol
stacks. When you set your receive buffer size, the protocol stack keeps track of how many bytes
of mbuf space are on the receive buffer, not the number of actual bytes. This approach is used
because the resource you are controlling is really how many mbufs are used, not how many
bytes are being held in the socket buffer. (A socket buffer isn't really a buffer in the traditional
sense, but a list of mbufs).
For example: Lets assume your UNIX has a small mbuf size of 256 bytes. If your receive socket
buffer is set to 4096, you can fit 16 mbufs on the socket buffer. If you receive 16 UDP packets
that are 10 bytes each, your socket buffer is full, and you have 160 bytes of data. If you receive
16 UDP packets that are 200 bytes each, your socket buffer is also full, but contains 3200 bytes
of data. FIONREAD returns the total number of bytes, not the number of messages or bytes of
mbufs. Because of this, it is not a good indicator of how full your receive buffer is.
Additionaly, if you receive UDP messages that are 260 bytes, you use up two mbufs, and can
only recieve 8 packets before your socket buffer is full. In this case, only 2080 bytes of the 4096
are held in the socket buffer.
This example is greatly simplified, and the real socket buffer algorithm also takes into account
some other parameters. Note that some older socket implementations use a 128 byte mbuf.
Add a Comment
Advanced Socket Programming: How would I
put my socket in non-blocking mode?
From Andrew Gierth ([email protected]):
Hi,
I tried this and works great as non-blocking socket. I have a different problem is that, when I
made it as non-blocking the accept() on the server comes out immediately with non-block error.
Instead I want accept() to wait for some time (set a timeout) before giving that error. Is there
any way I can set the timeout on accept().
Thanks in advance.
Vish
From: Jonathan Rynd
This is normal for all socket nonblocking operations: if you call them, you should be prepared
to handle 2 cases: 1, they succeed right away, 2, they 'fail' with the "EWOULDBLOCK"
non-blocking error (it's not a real failure, it just means "we can't satisfy that right now'. You
then have to create a FD_SET structure and use it as input to select() with the proper timeout.
See the manpage for select. Depending on the call, when select() returns to indicate success,
you may need to make the call again.
Add a Comment
Advanced Socket Programming: How can I put
a timeout on connect()?
Andrew Gierth ([email protected]) has outlined the following procedure for using
select() with connect(), which will allow you to put a timeout on the connect() call:
First, create the socket and put it into non-blocking mode, then call connect(). There are
three possibilities:
● connect succeeds: the connection has been successfully made (this usually only happens
when connecting to the same machine)
● connect fails: obvious
● connect returns -1/EINPROGRESS. The connection attempt has begun, but not yet
completed.
If the connection succeeds:
● the socket will select() as writable (and will also select as readable if data arrives)
Another common solution is to use an alarm to interrupt the connection. Here is some example
code:
.
.
.
signal(SIGALRM, AlarmHandler);
sTimeout = 0;
alarm(CONNECT_TIMEOUT);
sTimeout = 0;
alarm(CONNECT_TIMEOUT);
.
.
.
From: Mark Papadakis
The alarm way is not really useful if you are writting a threaded application...
You should therefore rely on the select() solution.
Mark
From: Tan Nguyen
True. In a threaded application, alarm() is not helpful at all. However, how can we use select()
to interrupt connect() if connect() never returns? (ie trying to connect to some non-existent host)
From: Tan D Nguyen
Ignore my last post. Another thing though, it seems that when we set the socket to non-block
mode, we cannot read the stream. I tested it by adding something to the bottom of the select()
example. recv() always returns -1. Am I missing something?
if (rc)
fprintf(stderr,"connect failed - error %d (%s)\n",rc,strerror(rc));
else
{
int sent = 0;
int received = 0;
fprintf(stderr,"connect successful\n");
sent = send(sock, "GET / HTTP/1.0 \r\n\r\n", 19, 0);
printf("Bytes sent : %d\n", sent);
char buf[1024];
received = recv(sock, buf, 1023, 0);
printf("Bytes received : %d\n", received);
buf[1024] = '\0';
if (received > 0)
printf("Recieved some data\n");
}
close(sock);
return 0;
From: jsh
Tan,
If the socket is still in non-blocking mode then your recv() will return -1 and errno will be
EAGAIN unless there is data available at this time.
Add a Comment
Advanced Socket Programming: How do I complete a read if I've only read the
first part of something, without again calling select()?
From: Ilya
I am looking for some recommendation to handle situation as follows: select() says data is available to be read. I read 4096 bytes(this is size for socket receive
buffer), parse buffer and see that there are 25 complete messages in buffer and part of the next message. I would like to read rest of uncompleted message without
call select(). I would like call select only after I finished read rest of uncompleted message. Thanks
From: Tom
In answering Ilya's question, I would use the following approach to read message one by one (in this case, the messages are strings separate by NULL characters):
while (1)
{
bzero(buffer, sizeof(buffer));
Hi,
i use part of your function, to get reliable data transfert over TCP,
here is my func:
call select
if readable continue;
if not return
recv (MSG_PEEK)
does buffer has \r\n
if yes continue
if no return
recv
return len buffer
Cheers
---
Alexandre
From: Bob
Replace MSG_PEEK by 0.
this should chage the fd status
Add a Comment
Advanced Socket Programming: How to use
select routine
From: Starch Melo de Souza
I need to use select routine for receive several response at the same time. How to write the
code??? Thanks.
From: Michael Song
int sock_ready(sock)
int sock;
{
int res;
fd_set sready;
struct timeval nowait;
FD_ZERO(&sready);
FD_SET((unsigned int)sock,&sready);
/*bzero((char *)&nowait,sizeof(nowait));*/
memset((char *)&nowait,0,sizeof(nowait));
res = select(sock+1,&sready,NULL,NULL,&nowait);
if( FD_ISSET(sock,&sready) )
res = 1;
else
res = 0;
return(res);
}
From: S.Murali Krishna
Explanation of above select code.
Q: How to use select call for multiplexing.
Um, res is an int, not a pointer, it wont be overwritten, cos its copied
to the calling function by value, and theres no n. Why else is the
code unfortunate?
Add a Comment
Advanced Socket Programming: RAW sockets
From: Steve McDonald
How would a socket using the SOCK_RAW protocol be used, and what, if any, advantages
would it have over SOCK_DGRAM or SOCK_STREAM protocols?
From: Stanislav Shalunov
To those who cant be bothered searching the ftp for the file location, its available here
ftp://rtfm.mit.edu/pub/usenet-by-group/comp.unix.programmer/Raw_IP_Networking_FAQ
[v0rt]
v0rt@deadprotocol
http://security.dayrom.com.au
From: [v0rt]
To those who cant be bothered searching the ftp for the file location, its available here
ftp://rtfm.mit.edu/pub/usenet-by-group/comp.unix.programmer/Raw_IP_Networking_FAQ
[v0rt]
[email protected]
http://security.dayrom.com.au
From: Bret Watson
Cheers,
Bret Watson
http://www.ticm.com
From: khodadad nezhadkorki
I'm looking for a script in c for creating a spoofed udp packet. It must allow me to specify the
destination address as well as the destinatin port. it also must allow me to specify a source
address and port. The last thing is that I must be able to send a message in plain text w/ it.
I know nothing about c so if you know where i can get a script, please let me know.
From: Nullzilla
What else do I need to do other than what I already have done in this code?
I am doing this on vxWorks.
#define IPPROTO_TEST 88
#define BUFSIZE 1500
char buf[BUFSIZE];
char rcvbuf[BUFSIZE];
int s;
int nSize;
Raw Sockets are used to send Packets of protocols like ICMP,IGMP, which of course are not
TCP(SOCK STREAM) or UDP (DGRAM). With Raw sockets you can spoof IP addresses as u
can control Ip headers.
Add a Comment
Advanced Socket Programming: Restricting a
socket to a given interface
From: Georg Wagner
How do I restrict a socket to a specific inteace i.e. that it only listens and accepts from the given
interface ?
From: Bret Watson
Difficult.. Unless you are going to patch the kernel I don't think this is possible.
What I have seen in most firewall implementations is that the "inetd" wrapper does some
filtering up front, including:
Check if the src and dest belong to the same network - if so ignore packet.
Make filtering decisions based on src,dest, ports..
Bret
From: Bret Watson
As a second check I dug through the source of the juniper firewall - which does identify
interfaces as trusted or non-trusted
I found there was a file called "Kernel_patch" which patched the kernel so that the socket
identified which interface it was on.
So there you go - you will need to patch things within netinet unless you are running a version
of linux that supports such things.
Bret
From: John
Add a Comment
Advanced Socket Programming: Receiving all
incoming traffic through a RAW-socket?
From: Juhana Lehtiniemi
http://www.whitefang.com/rin/
what is the way to take for founding more docummentation for the broacasting whith
socket_raw
Add a Comment
Advanced Socket Programming: Multicasting
From: Robert G. Brown
These online resources are fabulous -- one can find nearly any
aspect of socket programming discussed complete with sample code.
How can I send out one packet and have it read by all of my subscribing clients? Why congest
the network with redundant information?
Add a Comment
Advanced Socket Programming: getting IP
header of a UDP message
From: Dmitri
Thanks
From: E McWhorter
Add a Comment
Advanced Socket Programming: To fork or not
to fork?
From: Chris Briggs
-Chris Briggs
From: senthil
Add a Comment
Sample Source Code: Looking for a good C++
socket library
From: Russ Fink
What good freeware C++ class libraries for sockets are out there? I've seen a couple, but they
are all several years old, which makes me wonder if anyone is keeping them up anymore. What
good options are available to me under C++ that are low-cost? Thanks in advance -- Russ
From: Byron Harris
You may want to look at The ADAPTIVE Communications Environment (ACE), which can be
downloaded at http://www.cs.wustl.edu/~schmidt/ACE.html. It includes a number of C++
classes to aid developing extensible and portable communications code.
Socket access is part of ACE.
From:
fufu
From: fdsaf
ewrgregfdsgfdg
From: fdsaf
ewrgregfdsgfdg
From: Dema_Lamer
www.licq.org
From: Shivakumar
coolcoolcoolcoolcoolcool
From: Lonnie Cumberland
http://www.ispras.ru/~knizhnik/
Unsure if this will help, but libnet has a good C (Not C++) Package for doing packets.
Why do people like cool post such useless messages and waste there own and other peoples
time.It is disgusting.
From: Stephen Silvey
http://users.erols.com/astronaut/ssl/
From: Stephen Silvey
Search Google for "WFC" and "Blackburn" - Sam Blackburn wrote the WFC library (source
included) and it is very good. I think it's now on the CodeProject site.
Add a Comment
Sample Source Code: perl examples of source
code
From: Dave Atkins
The only examples in the sample source code are for C programs. Are perl examples available?
From: Lars Gregersen
There are several documents comming with Perl that contains information on sockets. I have
found the standard documentation very helpful and have used code based on the examples on
Windows and Unix.
Lars Gregersen
1/4 of this book's content deals with network programming. Also, if you are into PERl as much
as I am, you need this one on your shelf. You will not be dissapointed.
Enjoy !!
From: Marc
I get some problem writing sockets in perl. When I want to send an array at client to the server,
the server doesn't get the data correctly. I use 'send(SOCK, @array, 4, 0);'. Is there something
wrong with the code? I also tried to send a char but failed too. Could someone give me a hint
how to solve this problem? And how can I assemble some variables to a block of data (like a
buffer) and send it out through the socket? I'd really appreciate it a lot!
From: Daniel Gustafson
Add a Comment
Sample Source Code: Where is the source
code from Richard Stevens' books?
From: Madhumathi
hi madhumati
u can get the source code for stevens book at the following site i guess
www.kohala.com/~rstevens
www.kohala.com/start
Add a Comment
Bugs and Strange Behaviour: send() hangs up
when sending to a switched off computer
From: Raed Sirhan
I have a server program that sends a lot of TCP messages to a group of clients (array of
sockets), but I have a problem that the send() will hang up when sending many messages to a
switched off computer (or to a computer that already disconnected from the network by cable or
hub failure). I tried SO_KEEPALIVE but it takes a long of time before detecting that the socket
was broken. so please, till what should I do to prevent the temporary hang up of the send()
command
From: Vic Metcalfe
It seems to me that non blocking sockets would be a help here, but I don't have any good
resources to point to for non blocking sockets. Its a topic I'd like to cover more in the faq, and
add to the examples, but with other projects pressing for time it just hasn't been done. You
might be able to do it by piecing together information from DejaNews. Good luck! Vic.
From: Ian Berry
I have a similar problem, but I am using non-blocking sockets.
I am trying to create a simple server client using stream sockets where the server can handle the
client stopping without properly closing the socket (in most cases i will be ctrl-c'ing the client).
In general everything works, unless you ctrl-c at the point when the server is doing a send to the
client, at which point the server stops totally returning me to the prompt.
any thoughts?
From: Xidong Wang
you can catch the signal SIGINT, which is send to all the foreground processes by entering
Ctrl-C.
From: Rob Seace
Yeah, but if he's seeing the SERVER process croak after
killing the client, while the server is trying to write to
the client, then the most likely problem is SIGPIPE that's
killing it, not SIGINT... (INT is killing the client, but
PIPE is most likely killing the server...) Personally, in
literally EVERY TCP/IP related program I write, one of the
first things I do is "signal (SIGPIPE, SIG_IGN);"... Then,
you don't get hit with SIGPIPE while writing to a closed
socket; but, instead, you get an error return from the
write, with errno set to EPIPE (which is a LOT easier to
deal with)... I believe this is all covered elsewhere in
this FAQ, too...
Add a Comment
Bugs and Strange Behaviour: Error when
using inetd
From: Walter Moore
I've written a client/server program to replace someone's code that entailed a multitude of rsh's.
This server can be called on the command line, as well as via inetd. My problem is that the
inetd calling is not working correctly. When the client connects to the port, it receives this
message: ld.so.1: (unknown): fatal: libct.so: can't open file: errno=2 What does this mean?
Thanks
Add a Comment
Add a new question to the FAQ
Comments will fall under the same copyright as the FAQ, which permits anything except taking
ownership of the work. You can use HTML tags, and line breaks will be converted to html
<BR> tags.
Your Name:
Your Email:
Subject:
Contents are Copyright© by the author of the content. Permission is granted to do anything you like with this contents so long as you don't claim the
work, or copyright for yourself. The Self Serve FAQ is Copyright© by it's authors, and available under the terms of the GNU GPL.
Raw IP Networking FAQ
---------------------
Version 1.3
http://www.whitefang.com/rin/
The webpage also contains material that supplements this FAQ, along
with a very spiffy html version.
Copyright
---------
Introduction
------------
If you find anything you can add, have some corrections for me or
would like a question answered, please send email to:
Please remember to include whether or not you want your email address
reproduced on the FAQ (if you're contributing). Also remember that
you may want to post your question to Usenet, instead of sending it
to me. If you get a response which is not found on this FAQ, and you
feel is relevant, mail me both copies and I'll attempt to include it.
A final note, a Raw IP Networking mailing list is up. You can join by
sending an empty message to [email protected]
Caveat
------
Table of Contents
-----------------
1) General Questions:
2.3) What bugs should I look out for when using a raw socket?
3.1) Why should I use libpcap, instead of using the native API on
my operating system for packet capturing?
3.2) Does libpcap have any disadvantages which I should be aware
of?
3.3) Where can I find example libpcap source code?
4) List of contributors
1) General Questions:
---------------------
tcptrace:
http://jarok.cs.ohiou.edu/software/tcptrace/tcptrace.html
Not an actual sniffer, but can read from the logs
produced by many other well known sniffers to
produce output in different formats and in
adjustable details (includes diagnostics).
tcpflow
http://www.circlemud.org/~jelson/software/tcpflow/
tcpflow is a program that captures data
transmitted as part of TCP connections (flows),
and stores the data in a way that is convenient
for protocol analysis or debugging.
etherfind: SunOS.
nettl/ntfmt: HP/UX
SOCK_PACKET: Linux.
--------------------------------------------------------------
--------------------------------------------------------------
http://www.packetfactory.net/libnet/
1.9) Are there any high level language APIs (Not C) for raw
IP access?
--------------------------------------------------------------
http://quake.skif.net/RawIP/
ftp://ftp.python.org/pub/python/contrib/Network/
The BSD socket API allows one to open a raw socket and bypass
layers in the TCP/IP stack. Be warned that if an OS doesn't
support correct BSD semantics (correct is used loosely here),
you're going to have a hard time making it work. Below, an
attempt is made to address some of the bugs or surprises
you're in store for. On almost all sane systems only root
(superuser) can open a raw socket.
----------------------------------------------------------
char on = 1;
setsockopt(sockd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));
- TCP and UDP: no one other than the kernel gets these.
- all other protocols that the kernel doesn't deal with (OSPF,
etc.): these all get passed to all matching raw sockets."
2.3) What bugs should I look out for when using a raw socket?
-------------------------------------------------------------
----------------------------------------------------------
--------------------------------------------------------------
--------------------------------------------------------------
4) List of contributors.
------------------------
The webpage also contains material that supplements this FAQ, along with a very spiffy
html version.
If you wish to mirror it officially, please contact me for details.
Copyright
I, Thamer Al-Herbish reserve a collective copyright on this FAQ. Individual
contributions made to this FAQ are the intellectual property of the contributor.
I am responsible for the validity of all information found in this FAQ.
This FAQ may contain errors, or inaccurate material. Use it at your own risk. Although
an effort is made to keep all the material presented here accurate, the contributors and
maintainer of this FAQ will not be held responsible for any damage -- direct or indirect --
which may result from inaccuracies.
You may redistribute this document as long as you keep it in its current form, without
any modifications. Please keep it updated if you decide to place it on a publicly
accessible server.
Introduction
The following FAQ attempts to answer questions regarding raw IP or low level IP
networking, including raw sockets, and network monitoring APIs such as BPF and DLPI.
Please remember to include whether or not you want your email address reproduced on
the FAQ (if you're contributing). Also remember that you may want to post your question
to Usenet, instead of sending it to me. If you get a response which is not found on this
FAQ, and you feel is relevant, mail me both copies and I'll attempt to include it.
Also a word on raw socket bugs. I get approximately a couple of emails a month about
them, and sometimes I just can't verify if the bug exists on a said system. Before mailing
in the report, double check with my example source code. If it looks like it's a definite
bug, then mail it in.
Special thanks to John W. Temples <[email protected]> for his constant healthy
criticism and editing of the FAQ.
Credit is given to the contributor as his/her contribution appears in the FAQ, along with a
list of all contributors at the end of this document.
A final note, a Raw IP Networking mailing list is up. You can join by sending an empty
message to [email protected]
Caveat
This FAQ covers only information relevant to the UNIX environment.
Table of Contents
❍ 1) General Questions:
■ 1.1) What tools/sniffers can I use to monitor my network?
■ 1.2) What packet capturing facilities are available?
■ 1.3) Is there a portable API I can use to capture packets?
■ 1.4) How does a packet capturing facility work?
■ 1.5) How do I limit packet loss when sniffing a network?
■ 1.6) What is packet capturing usually used for?
■ 1.7) Will I have to replace any packets captured off the network?
■ 1.8) Is there a portable API to send raw packets into a network?
■ 1.9) Are there any high level language APIs (Not C) for raw IP access?
■ 2.3) What bugs should I look out for when using a raw socket?
■ 2.3.1) IP header length/offset host/network byte order (feature/bug?)
■ 2.3.2) Unwanted packet processing on some systems.
■ 2.4) What are raw sockets commonly used for?
❍ 4) List of contributors
❍ 1) General Questions:
The exact details are dependent on the operating system. However, the
following will attempt to illustrate the usual technique used in various
implementations:
The user process opens a device or issues a system call which gives it a
descriptor with which it can read packets off the wire. The kernel then
passes the packets straight to the process.
However, this wouldn't work too well on a busy network or a slow machine.
The user process has to read the packets as fast as they appear on the
network. That's where buffering and packet filtering come in.
The kernel will buffer up to X bytes of packet data, and pass the packets one
by one at the user's request. If the amount exceeds a certain limit (resources
are finite), the packets are dropped and are not placed in the buffer.
Packet filters allow a process to dictate which packets it's interested in. The
usual way is to have a set of opcodes for routines to perform on the packet,
reading values off it, and deciding whether or not it's wanted. These opcodes
usually perform very simple operations, allowing powerful filters to be
constructed.
BPF filters and then buffers; this is optimal since the buffer only contains
packets that are interesting to the process. It's hoped that the filter cuts down
the amount of packets buffered to stop overflowing the buffer, which leads
to packet loss.
NIT, unfortunately, does not do this; it applies the filter after buffering,
when the user process starts to read from the buffered data.
According to route <[email protected]> Linux' SOCK_PACKET does
not do any buffering and has no kernel filtering.
Your mileage may vary with other packet capturing facilities.
If you're experiencing a lot of packet loss, you may want to limit the scope
of the packets read by using filters. This will only work if the filtering is
done before any buffering. If this still doesn't work because your packet
capturing facility is broken like NIT, you'll have to read the packets faster in
a user process and send them to another process -- basically attempt to do
additional buffering in user space.
Another way of improving performance, is by using a larger buffer. On Irix
using SNOOP, the man page recommends using SO_RCVBUF. On BSD
with BPF one can use the BIOCSBLEN ioctl call to increase the buffer size.
On Solaris bufmod and pfmod can be used for altering buffer size and filters
respectively.
Remember, the longer your process is busy and not attending the incoming
packets, the quicker they'll be dropped by the kernel.
■ 1.7) Will I have to replace any packets captured off the network?
No, the packet capturing facilities mentioned make copies of the packets,
and do not remove them from the system's TCP/IP stack. If you wish to
prevent packets from reaching the TCP/IP stack you need to use a firewall,
(which should be able to do packet filtering). Don't confuse the packet
filtering done by packet capturing facilities with those done by firewalls.
They serve different purposes.
■ 1.9) Are there any high level language APIs (Not C) for raw IP
access?
Back to Top
The BSD socket API allows one to open a raw socket and bypass layers in
the TCP/IP stack. Be warned that if an OS doesn't support correct BSD
semantics (correct is used loosely here), you're going to have a hard time
making it work. Below, an attempt is made to address some of the bugs or
surprises you're in store for. On almost all sane systems only root
(superuser) can open a raw socket.
Depending on what you want to send, you initially open a socket and
give it its type.
sockd = socket(AF_INET,SOCK_RAW,<protocol>);
You can choose from any protocol including IPPROTO_RAW. The
protocol number goes into the IP header verbatim. IPPROTO_RAW
places 0 in the IP header.
Most systems have a socket option IP_HDRINCL which allows you
to include your own IP header along with the rest of the packet. If
your system doesn't have this option, you may or may not be able to
include your own IP header. If it is available, you should use it as
such:
char on = 1;
setsockopt(sockd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));
Of course, if you don't want to include an IP header, you can always
specify a protocol in the creation of the socket and slip your transport
level header under it.
You then build the packet and use a normal sendto().
Traditionally the BSD socket API did not allow you to listen to just
any incoming packet via a raw socket. Although Linux (2.0.30 was
the last version I had a look at), did allow this, it has to do with their
own implementation of the TCP/IP stack. Correct BSD semantics
allow you to get some packets which match a certain category (see
below).
There's a logical reason behind this; for example TCP packets are
always handled by the kernel. If the port is open, send a SYN-ACK
and establish the connection, or send back a RST. On the other hand,
some types of ICMP (I compiled a small list below), the kernel can't
handle. Like an ICMP echo reply, is passed to a matching raw socket,
since it was meant for a user program to receive it.
The solution is to firewall that particular port if it was a UDP or TCP
packet, and sniff it with a packet capturing API (a list is mentioned
above). This prevents the TCP/IP stack from handling the packet, thus
it will be ignored and you can handle it yourself without intervention.
If you don't firewall it, and reply yourself you'll wind up having
additional responses from your operating system!
Here's a concise explanation of the semantics of a raw BSD socket,
taken from a Usenet post by W. Richard Stevens
From <[email protected]> (Sun Jul 6 12:07:07 1997) :
Systems derived from 4.4BSD have a bug in which the ip_len and
ip_off members of the ip header have to be set in host byte order
rather than network byte order. Some systems may have fixed this.
I've confirmed this bug has been fixed on OpenBSD 2.1.
Some systems will process some of the fields in the IP and transport
headers. I've attempted to verify the reports I've received here's what I
can verify for sure.
Solaris (at least 2.5/2.6) and changes the IP ID field, and adds a Do
Not Fragment flag to the IP header (IP_DF). It also expects the
checksum to contain the length of the transport level header, and the
data.
Further reports which I cannot verify (can't reproduce), consist of
claims that Solaris 2.x and Irix 6.x will change the sequence and
acknowledgment numbers. Irix 6.x is also believed to have the
problem mentioned in the previous paragraph. If you experience these
problems, double check with the example source code.
You'll save yourself a lot of trouble by just getting Libnet
http://www.packetfactory.net/libnet/
Various UNIX utilities use raw sockets, among them are: traceroute, ping,
arp. Also, a lot of Internet security tools make use of raw sockets. However
in the long run, raw sockets have proven bug ridden, unportable and limited
in use.
■ 3.1) Why should I use libpcap, instead of using the native API on
my operating system for packet capturing?
Yes, libpcap will only use in-kernel packet filtering when using BPF, which
is found on BSD derived systems. This means any packet filters used on
other operating systems which don't use BPF will be done in user space, thus
losing out on a lot of speed and efficiency. This is not what you want,
because packet loss can increase when sniffing a busy network.
DEC OSF/1 has an API which has been extended to support BPF-style
filters; libpcap does utilize this.
In the future, libpcap may translate BPF style filters to other packet
capturing facilities, but this has not been implemented yet as of version 0.3
Refer to question 1.4 to see how packet filters help in reliably monitoring
your network.
❍ 4) List of contributors.
Administrative articles:
● [READ ME FIRST] Welcome to comp.unix.programmer
● Plain text
● Texinfo source
You may make copies of the FAQ for private use, or to put up on internal or private web
servers, without restriction. To assist with this, you may download a .tar.gz copy of the whole
FAQ. You MUST NOT put copies of this FAQ on public webservers without permission,
except as part of a properly maintained news.answers archive. (This restriction is purely to
prevent proliferation of old versions of the document.)
● Shigio Yamaguchi's Kernel Source Tour; HTMLized and indexed FreeBSD and Linux
kernel sources.
● FreeBSD.
● XFree86.
● Jennifer Myers' Unix Reference Desk. (Loads of good stuff!)
● More links please!
[email protected]
Frequently Asked Questions about
Unix Programming
This is a mirror copy of the FAQ document for the comp.unix.programmer newsgroup. Please
send all comments, queries, suggestions, criticism etc. to the maintainer,
[email protected]. Suggestions for new questions or answers are always
welcome.
● A gzipped tar archive of both the HTML and plain text versions (c. 70k)
This copy is current as of September 01, 2000. If it is more than two months old, then please
inform the maintainer of the archive where you obtained it, or obtain an updated copy from the
distribution sites listed below.
Distribution policy
You may make copies for personal use, or for access on a private network, without restriction.
Please do not put up copies on publicly-accessible servers of any kind without permission.
(This is not intended to restrict distribution, simply to try and ensure that old versions are
updated properly.)
The full hypertext copy is available at the following sites:
● http://www.erlenstar.demon.co.uk/unix/ (the master copy)
● http://www.whitefang.com/unix/
In addition, the raw Texinfo source is available only at the master site; it currently doesn't work
to generate Info output, but usually produces passable hardcopy.
The plain text version is posted to comp.unix.programmer, comp.answers and news.answers
every two weeks, and can always be found in the news.answers archives.
[email protected]
Welcome of the web site for the UNIX Socket FAQ! I will be getting back to updating this site
soon, to restore the old links, etc. I'll also automate the mirroring so new questions go out to the
mirror sites.
Please help a friend of mine who is promoting his single by downloading and listening to
'Notawasaga'. You'll be helping him to find more listeners, and maybe it'll help soothe your
nerves when your clients and servers just aren't communicating like they should.
You are using a static mirror of the faq, so not all features will be available to you. The home
page that has all the features can be found at http://www.lcg.org/sock-faq/.
Categorized Questions:
1. General Information and Concepts
1. What's new?
2. About this FAQ
3. Who is this FAQ for?
4. What are Sockets?
5. How do Sockets Work?
6. Where can I get source code for the book [book title]?
7. Where can I get more information?
8. Where can I get the sample source code?
2. Questions regarding both Clients and Servers (TCP/SOCK_STREAM)
1. How can I tell when a socket is closed on the other end?
2. What's with the second parameter in bind()?
3. How do I get the port number for a given service?
4. If bind() fails, what should I do with the socket descriptor?
5. How do I properly close a socket?
6. When should I use shutdown()?
7. Please explain the TIME_WAIT state.
8. Why does it take so long to detect that the peer died?
9. What are the pros/cons of select(), non-blocking I/O and SIGIO?
10. Why do I get EPROTO from read()?
11. How can I force a socket to send the data in its buffer?
12. Where can I get a library for programming sockets?
13. How come select says there is data, but read returns zero?
14. Whats the difference between select() and poll()?
15. How do I send [this] over a socket
16. How do I use TCP_NODELAY?
17. What exactly does the Nagle algorithm do?
18. What is the difference between read() and recv()?
19. I see that send()/write() can generate SIGPIPE. Is there any advantage to handling
the signal, rather than just ignoring it and checking for the EPIPE error?
20. After the chroot(), calls to socket() are failing. Why?
21. Why do I keep getting EINTR from the socket calls?
22. When will my application receive SIGPIPE?
23. What are socket exceptions? What is out-of-band data?
24. How can I find the full hostname (FQDN) of the system I'm running on?
3. Writing Client Applications (TCP/SOCK_STREAM)
1. How do I convert a string into an internet address?
2. How can my client work through a firewall/proxy server?
3. Why does connect() succeed even before my server did an accept()?
4. Why do I sometimes lose a server's address when using more than one server?
5. How can I set the timeout for the connect() system call?
6. Should I bind() a port number in my client program, or let the system choose one
for me on the connect() call?
7. Why do I get "connection refused" when the server isn't running?
8. What does one do when one does not know how much information is comming
over the socket? Is there a way to have a dynamic buffer?
4. Writing Server Applications (TCP/SOCK_STREAM)
1. How come I get "address already in use" from bind()?
2. Why don't my sockets close?
3. How can I make my server a daemon?
4. How can I listen on more than one port at a time?
5. What exactly does SO_REUSEADDR do?
6. What exactly does SO_LINGER do?
7. What exactly does SO_KEEPALIVE do?
8. 4.8 How can I bind() to a port number < 1024?
9. How do I get my server to find out the client's address / hostname?
10. How should I choose a port number for my server?
11. What is the difference between SO_REUSEADDR and SO_REUSEPORT?
12. How can I write a multi-homed server?
13. How can I read only one character at a time?
14. I'm trying to exec() a program from my server, and attach my socket's IO to it, but
I'm not getting all the data across. Why?
5. Writing UDP/SOCK_DGRAM applications
1. When should I use UDP instead of TCP?
2. What is the difference between "connected" and "unconnected" sockets?
3. Does doing a connect() call affect the receive behaviour of the socket?
4. How can I read ICMP errors from "connected" UDP sockets?
5. How can I be sure that a UDP message is received?
6. How can I be sure that UDP messages are received in order?
7. How often should I re-transmit un-acknowleged messages?
8. How come only the first part of my datagram is getting through?
9. Why does the socket's buffer fill up sooner than expected?
6. Advanced Socket Programming
1. How would I put my socket in non-blocking mode?
2. How can I put a timeout on connect()?
Contents are copyright by the author of the content. Permission is granted to do anything you like with this contents so long as you don't claim the
work, or copyright for yourself. Some graphics are copyright© by www.arttoday.com and used with permission. Any questions regarding this site
should be directed to [email protected].
ITPRC.COM
The TCP/IP FAQ
Technologies
Physical
Data Link
TCP/IP Frequently Asked
Content Networking
Directories
IP Routing
Questions
OSs
QoS
SANs
TCP/IP
Table of Contents
TCP/IP FAQ
Voice & Data This is the Table of Contents for the Frequently Asked Questions (FAQ) list for the
VPNs & Encryption
comp.protocols.tcp-ip Usenet newsgroup. The FAQ provides answers to a selection of
Wireless
common questions on the various protocols (IP, TCP, UDP, ICMP and others) that make
Operations up the TCP/IP protocol suite. It is posted to the news.answers, comp.answers and
ISP Resources
Network Management comp.protocols.tcp-ip newsgroups on or about the first Friday of every month.
Network Security
The FAQ is posted in two parts. Part 1 contains answers to general questions and
Other questions that concern the fundamental components of the suite. Part 2 contains answers
Guides
Humor to questions concerning common applications that depend on the TCP/IP suite for their
Link of the Week network connectivity.
Miscellaneous
Comments on this document can be emailed to the FAQ maintainer at
<[email protected]>.
About TCP/IP
1. What is TCP/IP?
2. How is TCP/IP defined?
3. Where can I find RFC's?
4. How do I find the right RFC?
About IP
1. What is IP?
2. How is IP carried on a network?
3. Does IP Protect Data on the Network?
4. What is ARP?
5. What is IPv6?
6. What happened to IPv5?
7. What is the 6bone?
8. What is the MBONE?
9. What is IPsec?
About TCP
1. What is TCP?
2. How does TCP try to avoid network meltdown?
3. How do applications coexist over TCP and UDP?
4. Where do I find assigned port numbers?
About UDP
1. What is UDP?
About ICMP
1. What is ICMP?
TCP/IP Programming
1. What are sockets?
2. How can I detect that the other end of a TCP connection has crashed?
3. Can TCP keepalive timeouts be configured?
4. Are there object-oriented network programming tools?
This compilation contains the opinions of the FAQ maintainer and the various FAQ
contributors. Any resemblance to the opinions of the FAQ maintainer's employer is
entirely coincidental.
Copyright (C) Mike Oliver 1997-1999. All Rights Reserved.
Secure UNIX Programming FAQ
The FAQ is maintained by Thamer Al-Herbish send comments to: [email protected].
I've setup a mailing list for the discussion of secure UNIX programming. Take a look at the
announcement made on comp.security.unix
Mirrors
Related FAQs
❍ US Mirror
❍ US Mirror
Welcome to comp.os.research
Part 1
● Introduction
❍ Reader contributions and comments
❍ Acknowledgments and caveats
● Recurrent discussions
❍ Microkernels, macrokernels, and the in-betweenies
❍ Threads
■ Distinguishing features
■ Characterising implementations of multithreading
■ The history of threads
● File systems
❍ Extent-based versus log-structured file systems
● Mobile and disconnected computing
❍ Constraints on software
❍ Communications protocols
❍ Access to files
❍ Power management
❍ Other issues
❍ An introductory mobile computing bibliography
● Operating systems teaching
❍ What good undergraduate-level texts are available?
❍ Graduate-level texts
❍ Do any texts cover the implementation of specific operating systems?
❍ What instructional operating systems can I use?
❍ Where can I find the canonical list of OS papers for grad courses?
Part 2
● Available software
❍ Where can I find Unix process checkpointing and restoration packages?
❍ What threads packages are available for me to use?
❍ Can I use distributed shared memory on my Unix system?
❍ Where can I find operating systems distributions?
■ Distributed systems and microkernels
■ Unix lookalikes
■ Others
● Performance and workload studies
❍ TCP internetwork traffic characteristics
❍ File system traces
❍ Modern Unix file and block sizes
■ File sizes
■ Block sizes
■ Inode ratios
● Papers, reports, and bibliographies
❍ From where are papers for distributed systems available?
❍ Where can I find other papers?
❍ Where can I find bibliographies?
● General Internet-accessible resources
❍ Wide Area Information Service (WAIS) and World-Wide Web (WWW) servers
❍ Refdbms---a distributed bibliographic database system
❍ Willow -- the information looker-upper
❍ Computer science bibliographies and technical reports
❍ The comp.os.research archive
❍ Miscellaneous resources
● Disclaimer and copyright
Part 3
● Distributed systems
❍ What is the current status of the (insert name) project?
❍ How do approaches to load balancing differ?
❍ Fault tolerance in distributed systems
❍ Naming in distributed systems
❍ Distributed shared memory
■ Data consistency
■ Strictly consistent systems
■ Relaxing consistency
■ Application-specific coherence
■ Access synchronisation
■ Transfer and caching granularity
■ Address space structure
■ Fault tolerance
■ A brief bibliography on distributed shared memory
❍ What have we learned?
● Needful things
For the textual version of the FAQ, see the archive on rtfm.mit.edu, or below:
● Part 1
● Part 2
● Part 3
● Welcome to comp.os.research
Bryan O'Sullivan, maintainer
Search by Title... Go
Author Appearances
Check out the appearances that Addison-Wesley authors will be
making.
Coming Soon
Check out these titles that will be published soon.
Performance Programming
Solutions Open Service
Connie U. Smith, Gateways with
Lloyd G. Williams Java Embedded
0-201-72229-1 Server™
Technology
Kirk Chen, Li
Gong
0-201-71102-8
Human-Computer Metadata
Interaction in the Solutions
New Millennium Adrienne
John M. Carroll Tannenbaum
0-201-70447-1 0-201-71976-2
Tradeshows
Check out the Tradeshows Addison-Wesley will be attending.
Rational User Conference 2001
Rational User Conference 2001 - "Blazing
New Trails" - is all about finding better
ways to negotiate the ever-changing
landscape of software development. If
software is key to your success, you need
to be a part of this extraordinary event.
You'll hear about the latest tools, trends
and tricks of the trade from Rational's
technology leaders, as well as learn from
your colleagues how they're blazing new
trails of their own with Rational. With the
dynamics of software changing at the
"speed of business," you can't afford to
miss it!
July 22 - 26, 2001
Colorado Convention Center
Denver, Colorado
Addison-Wesley Professional is Booth
#218
Learn more about RUC
Book Reviews
Check out what others say about Addison-Wesley books.
Mailing List
Stay up-to-date on our new publications by subscribing to our
mailing list.
------------------------
Course List
top
Summary
Features
Table of Contents
1. Introduction.
2. Windows NT Thread Interface.
3. Thread Synchronization.
4. Monitors.
5. Simulating Monitors.
6. Deadlock Analysis.
7. Thread-Package Architectures.
8. Programming Models.
9. Threads in Distributed Applications.
Appendix A. WorkCrew Implementation.
Bibliography.
Index.
top
© 2000 Prentice Hall Inc. / A Pearson Education Company / Upper Saddle River, New Jersey 07458 / Legal Notice / Privacy Statement
Search by Title... Go
Addison-Wesley Professional
Publishing Group
This page has moved. If you are looking for a specific book,
source code, errata or additional book information, please use
one of the two following options.
● Use the Search Engine A search can be done by title,
author's last name or ISBN in the search engine box
located at the right top corner of this page.
● Enter the Book URL A book can be found by entering
its URL in the following format:
http://www.awl.com/cseng/titles/I-S-B-N. The book
ISBN should be entered with the dashes in the
appropriate places. You'll find the ISBN on the back
cover of the book by the bar-code.
Multithreaded Programming Education
Multithreading Seminars
Multithreading Books
comp.programming.threads newsgroup
URLWatch:
For notice when this page changes, fill in your email address.
Maintained by: Webmaster, Linux Online Inc.
Last modified: 04-Jul-2001 11:10AM.
Views since 16-Aug-2000: 10144017.
Search
Today's News
Other Products
Exchange 2000 Service Pack 1. New Downloads
Get the update that makes Exchange more reliable than
Information For ever. MSN Messenger.
Home/Home Office Stay in touch with instant
messages, teleconferencing,
Deploy Active Directory. voice chat, and more.
Businesses Get technical help with this core piece of Windows 2000
Server. Internet Explorer 6 Preview
Refresh.
IT Professionals
Beta test the latest in
$50 rebate. privacy, reliability, and
Developers Save on Office XP when you order by July 31. U.S. and multimedia. Updated.
Canada only. Media Player 7.1:
Microsoft Partners Get the newest video and
audio players for PC and
Educators Pocket PC.
Journalists
Last Updated: Sunday, July 8, 2001 - 11:40 p.m. Pacific Time
Resources
Support
Windows Update
Office Tools
bCentral
Shop
Books
Jobs
Freedom to Innovate
Contact Us | Microsoft This Week! Newsletter | Text Only
©2001 Microsoft Corporation. All rights reserved. Terms of Use | Privacy Statement | Accessibility
SGI Worldwide
Fast Find
Search
sun.com My Sun | Regional Sites | Site Index | How To Buy
----------------------------
ONLINE DISCUSSION: Jiro[tm] Technology and Federated Management Architecture July 24-27,
2001
Join us for a special discussion forum with Paul Monday, coauthor of The Jiro[tm] Technology
Programmer's Guide and Federated Management Architecture.
More»
Copyright 1994-2001 Sun Microsystems, Inc., 901 San Antonio Road, Palo Alto, CA 94303 USA. All rights
reserved.
Terms of Use. Privacy Policy. Feedback
An OO Network
The Programming
ADAPTIVE Toolkit in C++
Communication
Environment
(ACE )
(TM)
1. Draft chapters from volume one of our C++ Network Programming book series
2. Pattern-Oriented Software Architecture: Patterns for Concurrent and Networked Objects
Query: Search
Help on: [ Syntax | Options | Compression of results | Improving your query | Query examples ]
Boolean operators:and and or. Use () to group boolean subexpressions.
Example: (specification or verification) and asynchronous
Contents:
1. Introduction
2. Hello World
3. Thread Synchronization
4. Coordinating Activities With Semaphores
5. Pragmatics
6. Appendix A - Semaphore Library
7. Appendix B - Notes on some questionable
usage of pointers to functions
● Tutorial as Postscript
● Uncompressed Tutorial as Postscript
Copyright © 1995, Thomas Wagner and Don Towsley All rights reserved.
Special: Readers' choice awards
Local
Select a country
IBM PartnerWorld ®
PartnerWorld for
Developers
Marketing & sales e-developerEDGE
Education After 10 years as AIXpert, we have renamed the magazine to reflect its content
Technical support as we broaden its focus from AIX and RS/6000 to include other UNIX®
Incentives & business related topics such as NUMA-Q, Project Monterey, Java technology, and
support e-business. e-developerEDGE is distributed via CD-ROM to commercial
members of PartnerWorld for Developers.
Financing
Membership center Members can access the latest issue of e-developerEDGE, as
Community well as the complete online collection. Recent issues (still
named AIXpert) are available to all. The current level of Adobe Acrobat
News & events Reader is recommended for accessing these issues.
Library
Programmer's Recent issues
information
White papers Focus on AIX WebSphere
December 1999
Application Server
Magazines
July 1999 Focus on AIX Performance Tuning
Books March 1999 Focus on AIX Packaging
Developer briefs December 1998 Focus on XML
September 1998 Focus on 3-D Graphics
e-business
June 1998 Focus on Client/Server Programs
Servers
March 1998 Focus on Internet Technologies
Software
December 1997 Focus on Parallel Programming
Technologies
September 1997 Focus on 64-bit Architecture
Feedback
June 1997 Focus on Network Computing
Site map & help
March 1997 Focus on Internet at the Olympics
Search PartnerWorld
for Developers:
Local
Related links:
developerWorks
alphaWorks
PartnerWorld for:
Software
Systems & Services
Personal Systems
DESCRIPTION:
REQUIREMENTS:
- Linux version 2.0 and up (requires the new clone() system call
and the new realtime scheduler).
- Also supports glibc 2 (a.k.a. libc 6), which actually comes with
a specially-adapted version of this library.
- Currently supports Intel, Alpha, Sparc, Motorola 68k and MIPS platforms.
INSTALLATION:
- Do "make".
- Do "make install".
USING LINUXTHREADS:
STATUS:
WARNING:
See the file README.Xfree3.3 for info on how to compile the Xfree 3.3
libraries to make them compatible with LinuxThreads.
- The current implementation uses the two signals SIGUSR1 and SIGUSR2,
so user-level code cannot employ them. Ideally, there should be two
signals reserved for this library. One signal is used for restarting
threads blocked on mutexes or conditions; the other is for thread
cancellation.
- The stacks for the threads are allocated high in the memory space,
below the stack of the initial process, and spaced 2M apart.
Stacks are allocated with the "grow on demand" flag, so they don't
use much virtual space initially (4k, currently), but can grow
up to 2M if needed.
Reserving such a large address space for each thread means that,
on a 32-bit architecture, no more than about 1000 threads can
coexist (assuming a 2Gb address space for user processes),
but this is reasonable, since each thread uses up one entry in the
kernel's process table, which is usually limited to 512 processes.
Another potential problem of the "grow on demand" scheme is that
nothing prevents the user from mmap'ing something in the 2M address
window reserved for a thread stack, possibly causing later extensions of
that stack to fail. Mapping at fixed addresses should be avoided
when using this library.
LinuxThreads is a Linux library for multi-threaded programming. It implements the Posix 1003.1c API
(Application Programming Interface) for threads. It runs on any Linux system with kernel 2.0.0 or more recent, and
a suitable C library (see section C).
A thread is a sequential flow of control through a program. Multi-threaded programming is, thus, a form of parallel
programming where several threads of control are executing concurrently in the program. All threads execute in the
same memory space, and can therefore work concurrently on shared data.
Multi-threaded programming differs from using multiple Unix processes in that all threads share the same memory
space (and a few other system resources, such as file descriptors), instead of running in their own memory space as
is the case with Unix processes.
Threads are useful for several reasons. First, they allow a program to exploit multi-processor machines: the threads
can run in parallel on several processors, allowing a single program to divide its work between several processors,
thus running faster than a single-threaded program, which runs on only one processor at a time. Second, even on
uniprocessor machines, threads allow overlapping I/O and computations in a simple way. Last, some programs are
best expressed as several threads of control that communicate together, rather than as one big monolithic sequential
program. Examples include server programs, overlapping asynchronous I/O, and graphical user interfaces.
It's an API for multi-threaded programming standardized by IEEE as part of the POSIX standards. Most Unix
vendors have endorsed the POSIX 1003.1c standard. Implementations of the 1003.1c API are already available
under Sun Solaris 2.5, Digital Unix 4.0, Silicon Graphics IRIX 6, and should soon be available from other vendors
such as IBM and HP. More generally, the 1003.1c API is replacing relatively quickly the proprietary threads library
that were developed previously under Unix, such as Mach cthreads, Solaris threads, and IRIX sprocs. Thus,
multithreaded programs using the 1003.1c API are likely to run unchanged on a wide variety of Unix platforms.
LinuxThreads implements almost all of Posix 1003.1c, as well as a few extensions. The only part of LinuxThreads
that does not conform yet to Posix is signal handling (see section J). Apart from the signal stuff, all the Posix
1003.1c base functionality, as well as a number of optional extensions, are provided and conform to the standard (to
the best of my knowledge). The signal stuff is hard to get right, at least without special kernel support, and while
I'm definitely looking at ways to implement the Posix behavior for signals, this might take a long time before it's
completed.
The basic functionality (thread creation and termination, mutexes, conditions, semaphores) is very stable. Several
industrial-strength programs, such as the AOL multithreaded Web server, use LinuxThreads and seem quite happy
about it. There used to be some rough edges in the LinuxThreads / C library interface with libc 5, but glibc 2 fixes
all of those problems and is now the standard C library on major Linux distributions (see section C).
B.2: I'd like to be informed of future developments on LinuxThreads. Is there a mailing list for this
purpose?
I post LinuxThreads-related announcements on the newsgroup comp.os.linux.announce, and also on the mailing list
[email protected]. You can subscribe to the latter by writing [email protected].
For questions about programming with POSIX threads in general, use the newsgroup comp.programming.threads.
Be sure you read the FAQ for this group before you post.
For Linux-specific questions, use comp.os.linux.development.apps and comp.os.linux.development.kernel. The
latter is especially appropriate for questions relative to the interface between the kernel and LinuxThreads.
If you're using glibc 2, the best way by far is to use the glibcbug script to mail a bug report to the glibc
maintainers.
If you're using an older libc, or don't have the glibcbug script on your machine, then e-mail me directly
([email protected]).
In both cases, before sending the bug report, make sure that it is not addressed already in this FAQ. Also, try to
send a short program that reproduces the weird behavior you observed.
B.5: I'd like to read the POSIX 1003.1c standard. Is it available online?
Unfortunately, no. POSIX standards are copyrighted by IEEE, and IEEE does not distribute them freely. You can
buy paper copies from IEEE, but the price is fairly high ($120 or so). If you disagree with this policy and you're an
IEEE member, be sure to let them know.
On the other hand, you probably don't want to read the standard. It's very hard to read, written in standard-ese, and
targeted to implementors who already know threads inside-out. A good book on POSIX threads provides the same
information in a much more readable form. I can personally recommend Dave Butenhof's book, Programming with
POSIX threads (Addison-Wesley). Butenhof was part of the POSIX committee and also designed the Digital Unix
implementations of POSIX threads, and it shows.
Another good source of information is the X/Open Group Single Unix specification which is available both on-line
and as a book and CD/ROM. That specification includes pretty much all the POSIX standards, including 1003.1c,
with some extensions and clarifications.
The best choice by far is glibc 2, a.k.a. libc 6. It offers very good support for multi-threading, and LinuxThreads has
been closely integrated with glibc 2. The glibc 2 distribution contains the sources of a specially adapted version of
LinuxThreads.
glibc 2 comes preinstalled as the default C library on most Linux distributions nowadays, such as RedHat 5 and up,
and Debian 2 and up. Those distributions include the version of LinuxThreads matching glibc 2.
C.2: My system has libc 5 preinstalled, not glibc 2. Can I still use LinuxThreads?
Yes, but you're likely to run into some problems, as libc 5 only offers minimal support for threads and contains
some bugs that affect multithreaded programs.
The versions of libc 5 that work best with LinuxThreads are libc 5.2.18 on the one hand, and libc 5.4.12 or later on
the other hand. Avoid 5.3.12 and 5.4.7: these have problems with the per-thread errno variable.
I'd recommend you switch to glibc 2. Even for single-threaded programs, glibc 2 is more solid and more
standard-conformant than libc 5. And the shortcomings of libc 5 almost preclude any serious multi-threaded
programming.
Switching an already installed system from libc 5 to glibc 2 is not completely straightforward. See the Glibc2
HOWTO for more information. Much easier is (re-)installing a Linux distribution based on glibc 2, such as RedHat
6.
C.4: Where can I find glibc 2 and the version of LinuxThreads that goes with it?
Both glibc 2 and the associated LinuxThreads distribution can be found on Cygnus' Sourceware collection, and
also on any FTP site that mirrors GNU software (the Cygnus site is sometimes more up-to-date than the GNU
sites).
C.5: Where can I find libc 5 and the version of LinuxThreads that goes with it?
C.6: How can I recompile the glibc 2 version of the LinuxThreads sources?
You must transfer the whole glibc sources, then drop the LinuxThreads sources in the linuxthreads/
subdirectory, then recompile glibc as a whole. There are now too many inter-dependencies between LinuxThreads
and glibc 2 to allow separate re-compilation of LinuxThreads.
C.7: What is the correspondence between LinuxThreads version numbers, libc version numbers,
and RedHat version numbers?
Here is a summary. (Information on Linux distributions other than RedHat are welcome.)
LinuxThreads C library RedHat
0.7, 0.71 (for libc 5) libc 5.x RH 4.2
0.7, 0.71 (for glibc 2) glibc 2.0.x RH 5.x
0.8 glibc 2.1.1 RH 6.0
0.8 glibc 2.1.2 RH 6.1 and 6.2
D.2: When I compile LinuxThreads, I run into problems with /usr/include/sched.h: there are
several occurrences of _p that the C compiler does not understand
Yes, /usr/include/sched.h that comes with libc 5.3.12 is broken. Replace it with the sched.h file
contained in the LinuxThreads distribution. But really you should not be using libc 5.3.12 with LinuxThreads! (See
question C.1.)
D.3: My program does fdopen() on a file descriptor opened on a pipe. When I link it with
LinuxThreads, fdopen() always returns NULL!
You're using one of the buggy versions of libc (5.3.12, 5.4.7., etc). See question C.1 above.
D.4: My program creates a lot of threads, and after a while pthread_create() no longer returns!
This is known bug in the version of LinuxThreads that comes with glibc 2.1.1. An upgrade to 2.1.2 is
recommended.
D.5: When I'm running a program that creates N threads, top or ps display N+2 processes that
are running my program. What do all these processes correspond to?
Due to the general "one process per thread" model, there's one process for the initial thread and N processes for the
threads it created using pthread_create. That leaves one process unaccounted for. That extra process
corresponds to the "thread manager" thread, a thread created internally by LinuxThreads to handle thread creation
and thread termination. This extra thread is asleep most of the time.
D.6: Scheduling seems to be very unfair when there is strong contention on a mutex: instead of
giving the mutex to each thread in turn, it seems that it's almost always the same thread that gets
the mutex. Isn't this completely broken behavior?
That behavior has mostly disappeared in recent releases of LinuxThreads (version 0.8 and up). It was fairly
common in older releases, though. What happens in LinuxThreads 0.7 and before is the following: when a thread
unlocks a mutex, all other threads that were waiting on the mutex are sent a signal which makes them runnable.
However, the kernel scheduler may or may not restart them immediately. If the thread that unlocked the mutex tries
to lock it again immediately afterwards, it is likely that it will succeed, because the threads haven't yet restarted.
This results in an apparently very unfair behavior, when the same thread repeatedly locks and unlocks the mutex,
while other threads can't lock the mutex.
In LinuxThreads 0.8 and up, pthread_unlock restarts only one waiting thread, and pre-assign the mutex to that
thread. Hence, if the thread that unlocked the mutex tries to lock it again immediately, it will block until other
waiting threads have had a chance to lock and unlock the mutex. This results in much fairer scheduling.
Notice however that even the old "unfair" behavior is perfectly acceptable with respect to the POSIX standard: for
the default scheduling policy, POSIX makes no guarantees of fairness, such as "the thread waiting for the mutex for
the longest time always acquires it first". Properly written multithreaded code avoids that kind of heavy contention
on mutexes, and does not run into fairness problems. If you need scheduling guarantees, you should consider using
the real-time scheduling policies SCHED_RR and SCHED_FIFO, which have precisely defined scheduling
behaviors.
D.7: I have a simple test program with two threads that do nothing but printf() in tight loops,
and from the printout it seems that only one thread is running, the other doesn't print anything!
Again, this behavior is characteristic of old releases of LinuxThreads (0.7 and before); more recent versions (0.8
and up) should not exhibit this behavior.
The reason for this behavior is explained in question D.6 above: printf() performs locking on stdout, and
thus your two threads contend very heavily for the mutex associated with stdout. But if you do some real work
between two calls to printf(), you'll see that scheduling becomes much smoother.
D.8: I've looked at <pthread.h> and there seems to be a gross error in the
pthread_cleanup_push macro: it opens a block with { but does not close it! Surely you forgot a
} at the end of the macro, right?
Nope. That's the way it should be. The closing brace is provided by the pthread_cleanup_pop macro. The
POSIX standard requires pthread_cleanup_push and pthread_cleanup_pop to be used in matching
pairs, at the same level of brace nesting. This allows pthread_cleanup_push to open a block in order to
stack-allocate some data structure, and pthread_cleanup_pop to close that block. It's ugly, but it's the
standard way of implementing cleanup handlers.
D.9: I tried to use real-time threads and my program loops like crazy and freezes the whole
machine!
Versions of LinuxThreads prior to 0.8 are susceptible to ``livelocks'' (one thread loops, consuming 100% of the
CPU time) in conjunction with real-time scheduling. Since real-time threads and processes have higher priority than
normal Linux processes, all other processes on the machine, including the shell, the X server, etc, cannot run at all
and the machine appears frozen.
The problem is fixed in LinuxThreads 0.8.
D.10: My application needs to create thousands of threads, or maybe even more. Can I do this
with LinuxThreads?
Because it's not part of the (final) POSIX 1003.1c standard. Several drafts of the standard contained
pthread_yield(), but then the POSIX guys discovered it was redundant with sched_yield() and dropped
it. So, just use sched_yield() instead.
E.2: I've found some type errors in <pthread.h>. For instance, the second argument to
pthread_create() should be a pthread_attr_t, not a pthread_attr_t *. Also, didn't you
forget to declare pthread_attr_default?
No, I didn't. What you're describing is draft 4 of the POSIX standard, which is used in OSF DCE threads.
LinuxThreads conforms to the final standard. Even though the functions have the same names as in draft 4 and
DCE, their calling conventions are slightly different. In particular, attributes are passed by reference, not by value,
and default attributes are denoted by the NULL pointer. Since draft 4/DCE will eventually disappear, you'd better
port your program to use the standard interface.
E.3: I'm porting an application from Solaris and I have to rename all thread functions from
thr_blah to pthread_blah. This is very annoying. Why did you change all the function names?
POSIX did it. The thr_* functions correspond to Solaris threads, an older thread interface that you'll find only
under Solaris. The pthread_* functions correspond to POSIX threads, an international standard available for
many, many platforms. Even Solaris 2.5 and later support the POSIX threads interface. So, do yourself a favor and
rewrite your code to use POSIX threads: this way, it will run unchanged under Linux, Solaris, and quite a lot of
other platforms.
E.4: How can I suspend and resume a thread from another thread? Solaris has the
thr_suspend() and thr_resume() functions to do that; why don't you?
The POSIX standard provides no mechanism by which a thread A can suspend the execution of another thread B,
without cooperation from B. The only way to implement a suspend/restart mechanism is to have B check
periodically some global variable for a suspend request and then suspend itself on a condition variable, which
another thread can signal later to restart B.
Notice that thr_suspend() is inherently dangerous and prone to race conditions. For one thing, there is no
control on where the target thread stops: it can very well be stopped in the middle of a critical section, while
holding mutexes. Also, there is no guarantee on when the target thread will actually stop. For these reasons, you'd
be much better off using mutexes and conditions instead. The only situations that really require the ability to
suspend a thread are debuggers and some kind of garbage collectors.
If you really must suspend a thread in LinuxThreads, you can send it a SIGSTOP signal with pthread_kill.
Send SIGCONT for restarting it. Beware, this is specific to LinuxThreads and entirely non-portable. Indeed, a truly
conforming POSIX threads implementation will stop all threads when one thread receives the SIGSTOP signal!
One day, LinuxThreads will implement that behavior, and the non-portable hack with SIGSTOP won't work
anymore.
These optional functions are provided in recent versions of LinuxThreads (0.8 and up). Earlier releases did not
provide these optional components of the POSIX standard.
Even if pthread_attr_setstacksize() and pthread_attr_setstackaddr() are now provided, we
still recommend that you do not use them unless you really have strong reasons for doing so. The default stack
allocation strategy for LinuxThreads is nearly optimal: stacks start small (4k) and automatically grow on demand to
a fairly large limit (2M). Moreover, there is no portable way to estimate the stack requirements of a thread, so
setting the stack size yourself makes your program less reliable and non-portable.
With a "one-to-one" model, as in LinuxThreads (one kernel execution context per thread), there is only one
scheduler for all processes and all threads on the system. So, there is no way to obtain the behavior of
PTHREAD_SCOPE_PROCESS.
E.7: LinuxThreads does not implement process-shared mutexes, conditions, and semaphores.
Why?
This is another optional component of the POSIX standard. Portable applications should test
_POSIX_THREAD_PROCESS_SHARED before using this facility.
The goal of this extension is to allow different processes (with different address spaces) to synchronize through
mutexes, conditions or semaphores allocated in shared memory (either SVR4 shared memory segments or
mmap()ed files).
The reason why this does not work in LinuxThreads is that mutexes, conditions, and semaphores are not
self-contained: their waiting queues contain pointers to linked lists of thread descriptors, and these pointers are
meaningful only in one address space.
Matt Messier and I spent a significant amount of time trying to design a suitable mechanism for sharing waiting
queues between processes. We came up with several solutions that combined two of the following three desirable
features, but none that combines all three:
● allow sharing between processes having different UIDs
● supports cancellation
● supports pthread_cond_timedwait
We concluded that kernel support is required to share mutexes, conditions and semaphores between processes.
That's one place where Linus Torvalds's intuition that "all we need in the kernel is clone()" fails.
Until suitable kernel support is available, you'd better use traditional interprocess communications to synchronize
different processes: System V semaphores and message queues, or pipes, or sockets.
F. C++ issues
F.1: Are there C++ wrappers for LinuxThreads?
Douglas Schmidt's ACE library contains, among a lot of other things, C++ wrappers for LinuxThreads and quite a
number of other thread libraries. Check out http://www.cs.wustl.edu/~schmidt/ACE.html
F.2: I'm trying to use LinuxThreads from a C++ program, and the compiler complains about the
third argument to pthread_create() !
You're probably trying to pass a class member function or some other C++ thing as third argument to
pthread_create(). Recall that pthread_create() is a C function, and it must be passed a C function as
third argument.
F.3: I'm trying to use LinuxThreads in conjunction with libg++, and I'm having all sorts of trouble.
From what I understand, thread support in libg++ is completely broken, especially with respect to locking of
iostreams. H.J.Lu wrote:
If you want to use thread, I can only suggest egcs and glibc. You can find egcs at
http://www.cygnus.com/egcs. egcs has libsdtc++, which is MT safe under glibc 2. If you really want to
use the libg++, I have a libg++ add-on for egcs.
Yes, but not with the stock gdb 4.17. You need a specially patched version of gdb 4.17 developed by Eric Paire and
colleages at The Open Group, Grenoble. The patches against gdb 4.17 are available at
http://pauillac.inria.fr/~xleroy/linuxthreads/gdb-4.17-debug-threads.patch.gz.
H.J.Lu also develops patches for gdb 4.17 that include thread support and more; those are available at
ftp://ftp.valinux.com/pub/support/hjl/gdb/. More recent versions of gdb seem to include
LinuxThreads support.
Some Linux distributions provide an already-patched version of gdb; others don't. For instance, the gdb in RedHat
5.2 and RedHat 6.2 is thread-aware, but apparently not the one in RedHat 6.0. Just ask (politely) the makers of your
Linux distributions to please make sure that they apply the correct patches to gdb.
Not very well. Generally, the core file does not correspond to the thread that crashed. The reason is that the kernel
will not dump core for a process that shares its memory with other processes, such as the other threads of your
program. So, the thread that crashes silently disappears without generating a core file. Then, all other threads of
your program die on the same signal that killed the crashing thread. (This is required behavior according to the
POSIX standard.) The last one that dies is no longer sharing its memory with anyone else, so the kernel generates a
core file for that thread. Unfortunately, that's not the thread you are interested in.
Assertions and printf() are your best friends. Try to debug sequential parts in a single-threaded program first.
Then, put printf() statements all over the place to get execution traces. Also, check invariants often with the
assert() macro. In truth, there is no other effective way (save for a full formal proof of your program) to track
down concurrency bugs. Debuggers are not really effective for subtle concurrency problems, because they disrupt
program execution too much.
H.2: Why is it so important that each thread has its own errno variable?
If all threads were to store error codes in the same, global errno variable, then the value of errno after a system call
or library function returns would be unpredictable: between the time a system call stores its error code in the global
errno and your code inspects errno to see which error occurred, another thread might have stored another error code
in the same errno location.
H.3: What happens if I link LinuxThreads with code not compiled with -D_REENTRANT?
Lots of trouble. If the code uses getc() or putc(), it will perform I/O without proper interlocking of the stdio
buffers; this can cause lost output, duplicate output, or just crash other stdio functions. If the code consults errno, it
will get back the wrong error code. The following code fragment is a typical example:
do {
r = read(fd, buf, n);
if (r == -1) {
if (errno == EINTR) /* an error we can handle */
continue;
else { /* other errors are fatal */
perror("read failed");
exit(100);
}
}
} while (...);
Assume this code is not compiled with -D_REENTRANT, and linked with LinuxThreads. At run-time, read() is
interrupted. Since the C library was compiled with -D_REENTRANT, read() stores its error code in the location
pointed to by __errno_location(), which is the thread-local errno variable. Then, the code above sees that
read() returns -1 and looks up errno. Since _REENTRANT is not defined, the reference to errno accesses the
global errno variable, which is most likely 0. Hence the code concludes that it cannot handle the error and stops.
H.4: With LinuxThreads, I can no longer use the signals SIGUSR1 and SIGUSR2 in my programs!
Why?
The short answer is: because the Linux kernel you're using does not support realtime signals.
LinuxThreads needs two signals for its internal operation. One is used to suspend and restart threads blocked on
mutex, condition or semaphore operations. The other is used for thread cancellation.
On ``old'' kernels (2.0 and early 2.1 kernels), there are only 32 signals available and the kernel reserves all of them
but two: SIGUSR1 and SIGUSR2. So, LinuxThreads has no choice but use those two signals.
On recent kernels (2.2 and up), more than 32 signals are provided in the form of realtime signals. When run on one
of those kernels, LinuxThreads uses two reserved realtime signals for its internal operation, thus leaving SIGUSR1
and SIGUSR2 free for user code. (This works only with glibc, not with libc 5.)
H.5: Is the stack of one thread visible from the other threads? Can I pass a pointer into my stack
to other threads?
Yes, you can -- if you're very careful. The stacks are indeed visible from all threads in the system. Some
non-POSIX thread libraries seem to map the stacks for all threads at the same virtual addresses and change the
memory mapping when they switch from one thread to another. But this is not the case for LinuxThreads, as it
would make context switching between threads more expensive, and at any rate might not conform to the POSIX
standard.
So, you can take the address of an "auto" variable and pass it to other threads via shared data structures. However,
you need to make absolutely sure that the function doing this will not return as long as other threads need to access
this address. It's the usual mistake of returning the address of an "auto" variable, only made much worse because of
concurrency. It's much, much safer to systematically heap-allocate all shared data structures.
That's a prime example of the errno problem described in question H.2. The binaries for Xlib you're using have not
been compiled with -D_REENTRANT. It happens Xlib contains a piece of code very much like the one in question
H.2. So, your Xlib fetches the error code from the wrong errno location and concludes that an error it cannot handle
occurred.
This is a lot of work. Don't you have precompiled thread-safe X libraries that you could
distribute?
No, I don't. Sorry. But consider installing a Linux distribution that comes with thread-safe X libraries, such as
RedHat 6.
Most libraries cannot be used "as is" in a multithreaded program. For one thing, they are not necessarily
thread-safe: calling simultaneously two functions of the library from two threads might not work, due to internal
use of global variables and the like. Second, the libraries must have been compiled with -D_REENTRANT to avoid
the errno problems explained in question H.2.
I.4: What if I make sure that only one thread calls functions in these libraries?
This avoids problems with the library not being thread-safe. But you're still vulnerable to errno problems. At the
very least, a recompile of the library with -D_REENTRANT is needed.
I.5: What if I make sure that only the main thread calls functions in these libraries?
That might actually work. As explained in question I.1, the main thread uses the global errno variable, and can
therefore execute code not compiled with -D_REENTRANT.
With a recent kernel (2.2 or later) and the glibc version of LinuxThreads, there should be no problems. With older
kernels or LinuxThreads version, both LinuxThreads and SVGAlib use the signals SIGUSR1 and SIGUSR2. See
question H.4.
Signal handlers are shared between all threads: when a thread calls sigaction(), it sets how the signal is
handled not only for itself, but for all other threads in the program as well.
On the other hand, signal masks are per-thread: each thread chooses which signals it blocks independently of
others. At thread creation time, the newly created thread inherits the signal mask of the thread calling
pthread_create(). But afterwards, the new thread can modify its signal mask independently of its creator
thread.
J.2: When I send a SIGKILL to a particular thread using pthread_kill, all my threads are killed!
That's how it should be. The POSIX standard mandates that all threads should terminate when the process (i.e. the
collection of all threads running the program) receives a signal whose effect is to terminate the process (such as
SIGKILL or SIGINT when no handler is installed on that signal). This behavior makes a lot of sense: when you
type "ctrl-C" at the keyboard, or when a thread crashes on a division by zero or a segmentation fault, you really
want all threads to stop immediately, not just the one that caused the segmentation violation or that got the SIGINT
signal. (This assumes default behavior for those signals; see question J.3 if you install handlers for those signals.)
If you're trying to terminate a thread without bringing the whole process down, use pthread_cancel().
J.3: I've installed a handler on a signal. Which thread executes the handler when the signal is
received?
If the signal is generated by a thread during its execution (e.g. a thread executes a division by zero and thus
generates a SIGFPE signal), then the handler is executed by that thread. This also applies to signals generated by
raise().
If the signal is sent to a particular thread using pthread_kill(), then that thread executes the handler.
If the signal is sent via kill() or the tty interface (e.g. by pressing ctrl-C), then the POSIX specs say that the
handler is executed by any thread in the process that does not currently block the signal. In other terms, POSIX
considers that the signal is sent to the process (the collection of all threads) as a whole, and any thread that is not
blocking this signal can then handle it.
The latter case is where LinuxThreads departs from the POSIX specs. In LinuxThreads, there is no real notion of
``the process as a whole'': in the kernel, each thread is really a distinct process with a distinct PID, and signals sent
to the PID of a thread can only be handled by that thread. As long as no thread is blocking the signal, the behavior
conforms to the standard: one (unspecified) thread of the program handles the signal. But if the thread to which PID
the signal is sent blocks the signal, and some other thread does not block the signal, then LinuxThreads will simply
queue in that thread and execute the handler only when that thread unblocks the signal, instead of executing the
handler immediately in the other thread that does not block the signal.
This is to be viewed as a LinuxThreads bug, but I currently don't see any way to implement the POSIX behavior
without kernel support.
The less you mix them, the better. Notice that all pthread_* functions are not async-signal safe, meaning that
you should not call them from signal handlers. This recommendation is not to be taken lightly: your program can
deadlock if you call a pthread_* function from a signal handler!
The only sensible things you can do from a signal handler is set a global flag, or call sem_post on a semaphore,
to record the delivery of the signal. The remainder of the program can then either poll the global flag, or use
sem_wait() and sem_trywait() on the semaphore.
Another option is to do nothing in the signal handler, and dedicate one thread (preferably the initial thread) to wait
synchronously for signals, using sigwait(), and send messages to the other threads accordingly.
J.4: When one thread is blocked in sigwait(), other threads no longer receive the signals
sigwait() is waiting for! What happens?
It's an unfortunate consequence of how LinuxThreads implements sigwait(). Basically, it installs signal
handlers on all signals waited for, in order to record which signal was received. Since signal handlers are shared
with the other threads, this temporarily deactivates any signal handlers you might have previously installed on these
signals.
Though surprising, this behavior actually seems to conform to the POSIX standard. According to POSIX,
sigwait() is guaranteed to work as expected only if all other threads in the program block the signals waited for
(otherwise, the signals could be delivered to other threads than the one doing sigwait(), which would make
sigwait() useless). In this particular case, the problem described in this question does not appear.
One day, sigwait() will be implemented in the kernel, along with others POSIX 1003.1b extensions, and
sigwait() will have a more natural behavior (as well as better performances).
K. Internals of LinuxThreads
K.1: What is the implementation model for LinuxThreads?
LinuxThreads follows the so-called "one-to-one" model: each thread is actually a separate process in the kernel.
The kernel scheduler takes care of scheduling the threads, just like it schedules regular processes. The threads are
created with the Linux clone() system call, which is a generalization of fork() allowing the new process to
share the memory space, file descriptors, and signal handlers of the parent.
Advantages of the "one-to-one" model include:
● minimal overhead on CPU-intensive multiprocessing (with about one thread per processor);
● a simple and robust implementation (the kernel scheduler does most of the hard work for us).
The main disadvantage is more expensive context switches on mutex and condition operations, which must go
through the kernel. This is mitigated by the fact that context switches in the Linux kernel are pretty efficient.
There are basically two other models. The "many-to-one" model relies on a user-level scheduler that
context-switches between the threads entirely in user code; viewed from the kernel, there is only one process
running. This model is completely out of the question for me, since it does not take advantage of multiprocessors,
and require unholy magic to handle blocking I/O operations properly. There are several user-level thread libraries
available for Linux, but I found all of them deficient in functionality, performance, and/or robustness.
The "many-to-many" model combines both kernel-level and user-level scheduling: several kernel-level threads run
concurrently, each executing a user-level scheduler that selects between user threads. Most commercial Unix
systems (Solaris, Digital Unix, IRIX) implement POSIX threads this way. This model combines the advantages of
both the "many-to-one" and the "one-to-one" model, and is attractive because it avoids the worst-case behaviors of
both models -- especially on kernels where context switches are expensive, such as Digital Unix. Unfortunately, it
is pretty complex to implement, and requires kernel support which Linux does not provide. Linus Torvalds and
other Linux kernel developers have always been pushing the "one-to-one" model in the name of overall simplicity,
and are doing a pretty good job of making kernel-level context switches between threads efficient. LinuxThreads is
just following the general direction they set.
[email protected]
GNU libc
This is a small web page for the GNU libc program, glibc. Look at the official FSF home page for glibc
for more information.
Get glibc announcements:
your e-mail address Subscribe
Availability
Glibc releases and pre-releases are available by anonymous ftp.
The FAQ, distributed in the source tree, is also available online. It is quite long already (around 75kB)
and still growing. So be careful when hitting the link.
You can access the development source tree a couple of different ways.
Anonymous CVS read-only access
Mailing list
There are four mailing lists regarding glibc hosted on sourceware.cygnus.com and one hosted on
gnu.org: libc-announce, libc-alpha, libc-hacker, glibc-cvs, and bug-glibc.
Please note that libc-hacker is a closed list. You may look at the archives of this list, but
subscription and posting are not open.
Bug database
Glibc has a bug database at the FSF. Got a problem? Want to know if you're the first to have it? Check
this database.
This page was last modified with loving care by [email protected] on 1999-11-29.
GNU FTP list (Text Version Only)
Updates
A possibly more up-to-date list of GNU FTP sites is at http://www.gnu.org/order/ftp.html
How to FTP
Use the ftp program on your system (ask locally if you can't find it) to connect to the host you
are ftping from. Unless indicated otherwise, login in as user "anonymous", with password:
"your e-mail address" and set "binary" mode (to transfer all eight bits in each byte).
ALWAYS USE BINARY/IMAGE MODE TO TRANSFER THESE FILES! Text mode does
not work for tar files or compressed files.
GNU Software and How To FTP It
GNU software is available on ftp.gnu.org under the directory /gnu. diff files to convert between
versions exist for some of these programs. Some programs have misc support files as well.
Have a look on ftp.gnu.org to see which ones. In most cases, the tar or diff files are compressed
with the `gzip' program; this is indicated with the .gz suffix.
Descriptions of GNU software are available at http://www.gnu.org/software/software.html and
in the Free Software Directory at http://www.gnu.org/directory/index.html
■ gatekeeper.dec.com/pub/GNU/
■ ftp.keystealth.org/pub/gnu/
■ ftp.itcentrx.com/pub/gnu/
❍ Illinois
■ uiarchive.cso.uiuc.edu/pub/ftp/ftp.gnu.org/gnu/ (Internet address
128.174.5.14)
❍ Kentucky
■ gnu.ms.uky.edu/pub/mirrors/gnu/
❍ Maryland
■ ftp.digex.net/pub/gnu/ (Internet address 164.109.10.23)
❍ Massachusetts
■ aeneas.mit.edu/pub/gnu/
❍ Michigan
■ gnu.egr.msu.edu/pub/gnu/
■ ftp.wayne.edu/gnu_mirror/
❍ Missouri
■ wuarchive.wustl.edu/systems/gnu/
❍ New Mexico
■ ftp.cs.unm.edu/mirrors/gnu/
❍ New York
■ ftp.cs.columbia.edu/archives/gnu/prep/
❍ Ohio
■ ftp.cis.ohio-state.edu/mirror/gnu/
❍ Pennsylvania
■ boron.club.cc.cmu.edu/gnu/
❍ Tennessee
■ sunsite.utk.edu/pub/gnu/ftp/
■ thales.memphis.edu/pub/gnu/
❍ Virginia
■ ftp.uu.net/archive/systems/gnu/
❍ Washington
■ ftp.nodomainname.net/pub/mirrors/gnu/
■ gnu.wwc.edu/
❍ Wisconsin
■ ftp.twtelecom.net/pub/GNU/
● Africa
❍ South Africa
■ ftp.sun.ac.za/gnu/
● The Americas
❍ Brazil
■ ftp.unicamp.br/pub/gnu/
■ master.softaplic.com.br/pub/gnu/
■ ftp.matrix.com.br/pub/gnu/
❍ Canada
■ ftp.cs.ubc.ca/mirror2/gnu/
❍ Chile
■ ftp.inf.utfsm.cl/pub/gnu/ (Internet address 146.83.198.3)
❍ Costa Rica
■ sunsite.ulatina.ac.cr/Mirrors/GNU/
❍ Mexico
■ ftp.uaem.mx/pub/gnu/
■ www.gnu.unam.mx/pub/gnu/software/
■ gnu.cem.itesm.mx/pub/mirrors/gnu.org/
● Australia
❍ Australia
■ ftp.progsoc.uts.edu.au/pub/gnu/
■ mirror.aarnet.edu.au/pub/gnu/
■ gnu.mirror.pacific.net.au/gnu/
● Asia
❍ China
■ ftp.sea9.com/pub/gnu/
■ ftp.cs.cuhk.edu.hk/pub/gnu/
■ sunsite.ust.hk/pub/gnu/
■ ftp.shellhung.org/pub/gnu/
❍ Japan
■ tron.um.u-tokyo.ac.jp/pub/GNU/prep/
■ ftp.cs.titech.ac.jp/pub/gnu/
■ core.ring.gr.jp/pub/GNU/
■ ftp.ring.gr.jp/pub/GNU/
■ mirrors.hbi.co.jp/gnu/
❍ Korea
■ cair-archive.kaist.ac.kr/pub/gnu/ (Internet address 143.248.186.3)
■ ftpmirror.hanyang.ac.kr/GNU/
■ ftp.linux.sarang.net/mirror/gnu/gnu/ (also mirrors alpha.gnu.org/gnu/ at
../alpha/)
■ ftp.xgate.co.kr/pub/mirror/gnu/
❍ Saudi Arabia
■ ftp.isu.net.sa/pub/mirrors/prep.ai.mit.edu/pub/gnu/
❍ Taiwan
■ coda.nctu.edu.tw/UNIX/gnu/
■ ftp1.sinica.edu.tw/pub3/GNU/gnu/
■ ftp://ftp.nctu.edu.tw/UNIX/gnu/
❍ Thailand
■ ftp.nectec.or.th/pub/mirrors/gnu/ (Internet address - 192.150.251.32)
● Europe
❍ Austria
■ ftp.gnu.vbs.at/
■ ftp.univie.ac.at/packages/gnu/
■ gd.tuwien.ac.at/gnu/gnusrc/
❍ Belgium
■ ftp.be.gnu.org/
❍ Austria
■ http://gd.tuwien.ac.at/gnu/gnusrc/
❍ Czech Republic
■ ftp.fi.muni.cz/pub/gnu/
❍ Denmark
■ ftp.denet.dk/mirror/ftp.gnu.org/pub/gnu
■ ftp.dkuug.dk/pub/gnu/
❍ Finland
■ ftp.funet.fi/pub/gnu/prep/
❍ France
■ ftp.irisa.fr/pub/gnu/
■ ftp.medasys-digital-systems.fr/pub/gnu/
■ ftp.fuitad.net/mirrors/ftp.gnu.org/
■ hansolo.mtesa.net/gnu/
❍ Germany
■ ftp://ftp.cs.tu-berlin.de/pub/gnu/
■ ftp.leo.org/pub/comp/os/unix/gnu/
■ ftp.informatik.rwth-aachen.de/pub/gnu/
■ ftp.de.uu.net/pub/gnu/
■ ftp.freenet.de/pub/ftp.gnu.org/gnu/
■ ftp.gigabell.net/pub/gnu/
■ ftp.cs.uni-bonn.de/pub/gnu/
■ ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/
■ http://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.gnu.org/
■ ftp.stw-bonn.de/pub/mirror/ftp.gnu.org/
❍ Greece
■ ftp.forthnet.gr/pub/gnu/
■ ftp.ntua.gr/pub/gnu/
■ ftp.duth.gr/pub/gnu/
■ ftp.aua.gr/pub/mirrors/GNU/ (Internet address 143.233.187.61)
■ ftp.physics.auth.gr/pub/gnu/
❍ Hungary
■ ftp.kfki.hu/pub/gnu/
❍ Ireland
■ ftp.esat.net/pub/gnu/ (Internet address 193.120.14.241)
❍ Italy
■ ftp.oasi.gpa.it/pub/gnu/
❍ Netherlands
■ ftp.eu.net/gnu/ (Internet address 192.16.202.1)
■ ftp.nluug.nl/pub/gnu/
■ ftp.mirror.nl/pub/mirror/gnu/
■ ftp.nl.uu.net/pub/gnu/
❍ Norway
■ ftp.ntnu.no/pub/gnu/ (Internet address 129.241.11.142)
■ ftp.gnu.no/
■ sunsite.uio.no/pub/gnu/
❍ Poland
■ ftp.task.gda.pl/pub/gnu/
■ sunsite.icm.edu.pl/pub/gnu/
❍ Portugal
■ ftp.ci.uminho.pt/pub/mirrors/gnu/
■ http://ciumix.ci.uminho.pt/mirrors/gnu/
■ ftp.ist.utl.pt/pub/gnu/
■ mirrors.netvisao.pt/gnu/
❍ Romania
■ archive.logicnet.ro/mirrors/ftp.gnu.org/gnu/
■ ftp.timisoara.roedu.net/mirrors/ftp.gnu.org/
❍ Russia
■ ftp.chg.ru/pub/gnu/
❍ Slovenia
■ ftp.arnes.si/gnu/
❍ Spain
■ ftp.etsimo.uniovi.es/pub/gnu/
■ ftp.rediris.es/pub/gnu/
❍ Sweden
■ ftp.isy.liu.se/pub/gnu/
■ ftp.stacken.kth.se/pub/gnu/
■ ftp.luth.se/pub/unix/gnu/
■ ftp.sunet.se/pub/gnu/ (Internet address 130.238.127.3)
■ ftp.chl.chalmers.se/pub/gnu/
❍ Switzerland
■ ftp.eunet.ch/mirrors4/gnu/
■ ftp.ulak.net.tr/pub/gnu/
❍ United Kingdom
■ ftp.mcc.ac.uk/pub/gnu/ (Internet address 130.88.203.12)
■ ftp.mirror.ac.uk/sites/ftp.gnu.org/pub/gnu/
■ ftp.warwick.ac.uk/pub/gnu/ (Internet address 137.205.192.13)
■ sunsite.org.uk/gnu/ (Internet address 193.195.63.2)
How to FTP GNU Emacs
Emacs is in the directory /gnu/emacs on ftp.gnu.org. The emacs distribution itself has a
filename in the form emacs-M.N.tar.gz, where M and N stand for the version numbers; the
Emacs Lisp Reference Manual is in a separate file, named elisp-manual-NN.tar.gz.
Read the files INSTALL and README in the top level C Scheme directory.
Information on how to uucp some GNU programs is available via electronic mail from:
uunet!hutch!barber, hqda-ai!merlin, acornrc!bob, hao!scicom!qetzal!upba!ugn!nepa!denny,
ncar!noao!asuvax!hrc!dan, bigtex!james (aka [email protected]), oli-stl!root,
[email protected] (Germany), [email protected] (Japan) and [email protected].
If You Like The Software
If you like the software developed and distributed by the Free Software Foundation, please
express your satisfaction with a donation. Your donations will help to support the Foundation
and make our future efforts successful, including a complete development and operating
system, called GNU (Gnu's Not Unix), which will run Unix user programs. For more
information on GNU and the Foundation, contact us at the above address, or see our web site at
http://www.gnu.org.
Ordering a GNU Source Code CD-ROM or Source Code CD-ROM Subscription is a good way
for your organization to help support our work.
Return to GNU's home page.
FSF & GNU inquiries & questions to [email protected]. Other ways to contact the FSF.
Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111, USA
Verbatim copying and distribution of this entire article is permitted in any medium, provided
this notice is preserved.
‹³zÜ5a´[ywâÆ–ÿÎ|ˆJç•#°Á¯q¿¸mÜqÆÛ:y™¼>:B XHzZLû%ýÝç.UR‰ÅK¦§O¨êÖ-»ß_#o<Í8“Ñ°¹³ÙÞkÞÜ]|Ø‚O[ÃX:÷Qè馛?^zRm6›ÏL®¦™8‰b!D«}Ø…ÿ»¢}p°_-×ëë)W™WΣ]ÑÞ?ììÂLžöâÙnìŠ:¾üðCUl½½?¦S/˜gf©(H%
1cñáìýfµ)„8
£ÇØ›LS ¶¿ÛÀ×=z=À׃½¶éu›^;ôºC¯]z¥Y{D®øwK)úá8•;±çaŒœÔƒ†¸ÜÍjý«®Ý z(•çÖU1˜z‰{¾ð7râT„cˆ
in·w»•ö¶¨ó›’*ÿKÒ8sS1óoæøvò8†¾x;;Bºüo&Ž…†÷Yd—‡Ù©üœ
kœ®83Ù×//ÂRDÃáïÄÔÛ~_;ÒòôÆšժÍJâø›‘äû¿^½¿¹´•>¹üسOÎÎîzý>ŽÉ§H?‘$5ý˜/*±L³88ªÖõ£4F&ÒE9Âð±ŒìȵC03lÒbB5ƒ4áY|—
/H$H8•{®ŽF¶“ßg‘a“•S «Ì`ÌhË$o·4-“ËKûý]ïä¿no.®ÀØ°V-Wp_Ãæ»ô1’âøØ
ÏpÖƆ€ÇšŒ`&‹§–bßÉa6™ ³À¨–øóOœ˜ïöØÜ|-Fóµ$‰½/(õ—
Æa@"S;væ¶!ÃHcÃZ±
Yegw¯‹nÞÙÝßnì‘M~ë•GL·7°/o®?ütukNîà#Rq•t*µPJ+½Q_¾áõžiCëϵ_N6ñ&¯àá5£•ïŒÖ‡r7ÆÞdËëìïnù^•}ÞœMË•wÕˆ5¡}ÕÐÊ/rD!~{[´:‡Û•ÃvgMˆ_9]gˆNC}»}¸Ý-B}·±#êø‚P×'ûüâ²w,‚Y“)LéÛ³Þ-~ß?Giì¸r3Iè{CøߥN<•w•î›îÔóGðÁ
cé‡sx÷O4jüØt •¨GÍXNÀrq>0쟛•ŸÈ0^6T‹é6J`æëÔ”>+¼ôåjJW¨©ûr5¥%5v;ð¿PÓ6ªIû©©
ÑLG2bÉì©÷0æJé15ôX-•ÙJ‚’|PF(ðw/ Ä•%À~Š‰äàùÓ{ûöT|«Œãp&¾'çÈÆ›ÓwÕúÕÀ>=¿<ùL4Ïlûc¿g_]ôO!dcîë÷î~îÝÙ£°žâãÅZ*,p½ô+}^SÅàºÚ}•®e§Ún¶vmíí ºàÈ£Â
QË8/I«¤1;–3ˆåöÜIÝ)šÛ“»“+ÈE~ˆ¼QCœÞÜqò¤ÖÀÙ—•20‚×!!ö³(
!bý…›€/º%•€jĽw&r“²hŸ¼m÷g§¶]-—KÉßÊ´ƒcÏ¡7ªÖM¢v ç¶..r¶‹õ¹-k#‰ʘoݼÿ
¤&Ö®•1˜r§N,Þ.°B³ÓÐF–„¹Š‹b¸u{q¶À€A‹žk£Ž%T}'DqèJ0-I*£·w=г7öíÝÍi¯wfõ½ÛE–Éò0t1Ö–E Ó•z}e_^\•ü‡ý#*û….Áÿ>åaù•8X>–Üã''bG´öÑ¿¶w¨¼~Ú¿ŒùОü”ØÕ´÷·÷;F{r°Oõ4þÍ«é‹€œÀu‰õ7¾GZ
z7Ž¡ü.A5´ã뢕&BìÃ!º²ƒ¹ŽØiS)æa<‚ô¤TÞ-yßÇ÷š¤š·)Pì¢ÚÔJ>èÙ§?ž\\[Ð:%4¾&8ZÆWPz`Êž:ÁÈ—±•+ȘŠ¿‹ÒPú«BYå°7’¶ÒøÑf•)•‡"Q•&ZhYö‚ŒÓ”XÇZ^ !vŒi‡¢…uª²ÿ",Q$£ñ68¤,~µAMWó«¤CïkÂZ¢§žÔ°0K?3Ç•CÐÖ÷Ò÷1i‰ùT‚Z8b/D%³<„.µi°ep¤$G¤îá£8¿£P¢5¤bê<`Ár
Ù†’¦p’$t=¨Gbî¥Sᥠã‹1ü}…w=›ÀÒ×$°ô©¶÷‚f0€ÝÃ8é¾
tèjàµæ¡<¬8„bžÇO®?n]"U”ºï Ûí×6ñ¥6ý«´âÝÆ>ÔQÝÆ^W¼ßz•ëg#)Þ”#ÐôeØùÍxœ`Eµ.X
DöS0.‹a\¢¡J#ë{2ÔGò`пøpzs=èýcE•}s~Þï
@TœÆ½•SÄ‚h)}9KÕñK—[:{+bP™õ.{W½ë•Ý¿øŸ0óo 30×P¢šçÞ$!Tþï•œn”çžï‚
0Ù÷³8âøOš ''`•ü"¡‚‰ e'óâ$Åá(”!:U0股ɶ7•Ñ|ê¹S¢7GzØB0ÁÈU›5vmxœ³-<p9àQ S7Œ<Ь
BÌ ©=æQ<Üæ‚•Æyt’¹®ÊYËÝó)“ÎCXæÞ–r÷rslᨚX&Æ”FVØn¯G%ô+Lªþ¤IYíñ‚÷Êa¼V1tW
-Yáÿ•
2F’Aö¤Èªe1ñ¤
µÞŒ’pÙÐ
Ú(JK¥P¾€šn¡Œ=¹X–™ìš‹åœ€‚e¹Yƒ‹ù•‚Ò-Aš‚7ùqÉH8É‘lÍ«².—m…-%£zìâÚÖ|;2¾´"·!®
Tî[½Œ…ÛzwIXíäƒÄšƒZ•D')I™ªª‰M±,TSxHœþY‹ïNj+(õ®Ï
:bI?ø¨.ö5ûg„;C:u;ʹ‹èe
LàT•)
-Ý.„¢ýñäúì²wGÂ%d”¥Þ³´ÿ‰!ƒw{|¬ðSUCï©íSõ”DV•fæú¸–Ü9ÇRqCðôxI6“yw†]ÀV€ÖïèeaWIyS•Ó/.Ïì»^ÿãUO-åU‘¢À@j†¬¨Ø
ÐÌïƒpÎÑ”–4ÆpÆøJ±;yÆfTÕ.Kõ×þ)‚¥ Ì[ÑúìŽö[`Ýâo-Ïû-r
0s(ØÆÁ%¦Z1k©õpc³™a±ŽéŒS2Š¼šCæ*®+`Chäǧ¢ÂŽ?w1!ì†@.˜L‹Ê?QZi
¥ëd
'†Ô%åØgヾS"•ªC¢†ªÏ"‘©ç£4oò³t³æ5cƒI!Ný“Ÿ{g«Oν;¥bHoù¡e«xÇ»²t§/c9ñ™Õ¿s•rìŠ&U*•:ºý\›•©;X™RêÐÂa€=AMèl¡r죑—r®0B<4§X5³‘“m.D×…FbÁçHÅ6Ä…—4,`î)´${
ýý‚X_"î•žä²L{¦Õ-–]nä@¸$WÝâü‚Ö…Ñ$¯cuøèß\^¼·)¬Â»k¨úÒlÌ¥¡Âów¨foµUKLôÊ`´³÷аÆX8cЕÃ!œÜÝleI¼¥já-
[ˆ9Œh]h -Kxbÿ+¡6L}ÑVÖ€«¸á,~ã-?tF°Õ(K¹œl‘S€0ta©“˜dÃÁ§Y
¹aF£ç¯õˆ-ábÕqÏõÉ’}uòë{Bûר¨gtÄ„G¯„G‚YsÖYÓ¸©gO7ljPå<ö¨Qko#Òî*¤q=¢'. ŒíÃÖÞúÚ+c¢³ÙB=Ì ,•Œ†
e:ñÃ!dš'N°*7hTÞØl½®=Ó³¾ZsÖ9hì‰:½¦ƒvgTb³,Ií$K"P®Í Ù‘ ¸¬@Õh¨ÜÔö µcœï¬ÀÔŒ1Otâ=Ak§‹M
=Š½ØôÜzBm“c¶N†Ù:õPS(!Lñö)-0ÿ…«Æƒ5¶iŒ¨ô¡8 Ãl‹âk‡•u‚9«ÌuÀ*wŒÃ$>RÄ?¬Ã/Üb¯;V¬çÝ÷÷•e¡s“â×ë`ÅWî`
àooãF÷Ú•F»»« HU ´Ž ŸÂ]rå‰ÐG«B{þ¢°ûE¬Ë‚Þ×¹‡2ÂY‡U’ƒ¹•2WU+j ¹%iªmlþ54ÜR•O_
…ì•'ùj}Þã\¨ŽåW¤wzþ:DÌ”òÛÎ'u/ϵiÈšÔ-(+µ¨‘š¦&°
AUC±CØØзԱ•‘Öó•
3æ8U½•±¶B;l-UK
U|ä†S-•Q)õc€I”PµÆB›`€› È?@†@
#42|DÅÐò#I3ÁtCp²Dþ+“•+¹10Îür•‘ë^‹(ý†lÏÍ|'f3R³J¦Rf•hð5!íZE5¢¹9Ä-WZŸ»û•JF¾øOé|¦o†û{{-úW™…>6{{•ü1õ#L
ÜŽ¨Û"=L…f§1uÐ-²Àƒõ ]QÀò եěEØs¤ÐEˆÏ•Ì±×„Ò†¢=‘„\>9Ác^ßÖÿB7pAÏcJ•Ž˜zЖ•º©FˆTðŠ¹ÿPd
eæzÄ•€@]Ÿ;•î}ÞSÏQ?à°µ˜¹áN™ßsVÑc!n5 À@.YÃrĵYˆ„ç^"MvÉfr†MfƒI™Y]4ÍM¥®A!’ħÂ<Ç©±ãÃj ©ä•-Ø
3•$~Ï ¨-}æ•ÀÞžŸrü昘+"`…O2'v vÊ‚Ä*Æc•ÔÉÀ•ÝC)¬ºfº™¤B§Üsõ^´ØºÎjQì|ötlPA%
‹|vQQ¨è™"WÆ,ÀÝ¢•c„D1ý¶ÿéhù‰&ûÛ'q,þèp
•N†¯àWðÚj-¾º#|…VÿQôœ†Øå!Ôìt‚p¥„¾X|H[#Ž F¬‰o–âb³-È$àD ‹¸o}¢Q•ðPR2{X•••õÖ_õ:Â$›Œü~—?ÌÇ·Íñqdq–;Ò³vÍYEŒÉ'@Eãd~zX1·‚—·àbDóå¤v‡Åžå1ëžø>ìq·5øª^WbY'Mè=C¢$&ïÓ¢T—åª>9\ÆÒ&ÐPJ)1‰]À!ÓøbBŽÔóCʈƒÂ=àm¹ùLJ|"”¤•¾\†Ë‚µmõ_+¸¼´owöû‹•Øê‹ÓOè›O¹1GiŒµMÊyn’i~‘q$G(]É8†]Ï1;tà@9ÎD‚<òpeª6å;•X³b’ÂÀ‡mBŽâ1$zÄq¥Jz«K‘¬\K,gªÓ@ЇM†J-¾•·Pµè0RÀKs¾·KaK£ÆGX•¯Žá
"Ýšßl…Xþ¼½;9íCò+*|7ÅD[-º9ƒÍ˜®š´í¨› GÆG¦?Ë ›i¹ª†ÿhÛ 1&“$=Zuéë…Íót° B
EðžÐïšmÅ(˜×Ç•[„¾Ù&ò¸ƒX©™fÂR<p-Š9•±‚0hò\äÌ®¡º¨7,'P¿Aþ
êÞ哱Æx æ
¥A}—Ö`ƒØ.
5kjî†U¤'™Á`P)ÚáÅõÇI¦¸Tü‡_ty˜Ì:r‘&‰§¸5¼G— gK+¯ ¤yUWyÿü“k
øʲJðõ»wß0ÎÝm<7©‰·bŸ.ôV*•KÎÏÕí^Î#Å]fdn%û8¼$/¼î“ïåÅâ5N‘D)×ÒeU¤ò-LÇzÁÄ—MTˆÀÛìK®\ÐX ¥ã¶×Ag‚z£ÖÐÝ{9RòÜ!ÑÌ{
¥›/æŽG…¤'ÙŽT7•j¾2—Ê‚¨mþ*_̽™lßBDœkk–cß•Ö>/5;U¸<÷;‹=’Z8÷RD•#zR¾]§Í.•$¹3K§¦<•°*ó=½Âºx=³'¬(sW±WmìOxø¹Ý«&ôȉÄ9|¯÷€ÿ汗ʬs¤f|Y!v¶%-súƒV`sDF•¡Ñ
¾}h©°9°c~½íÕD«‘óS•„´e©˜[3‚="J’6vLt'¬7¼ú•DTlU¾w(l1ê›
D¡@EOÂc*(-‚·Å÷ëÀ±|À
ll•6VLZl÷»ÛÆÞv#üÓÞV½n*AFN’àad*KWÕ•ÏåñIFv•'ÐmQ¥†«Äðá/LCæžžEȺ)ˆÅ••6]>ŸÆeR‘¦•6¢Ô˜sr2lË9¥§ÕgÁô©¾]¯Zz¼B±ëËSÊjÝéä8)!žx4Ú|ƒþ‰k"x¸G7EZú€Ba•ëÄM˜áÙÃñÀ†Ðv¡8¹!tOj²´8åàDX¾w/¹lgw-p×¢é5àL]|PÝAíµ"ô©Îm‹SPUí-Õÿ•â›×,pLÃø™T•®0äqsdé˜.Û¤Z€@•ÄKñü8•K¨ñK‡Ó2櫤¸w‚€Ü4ƒd¤Ç\;K¤ÿ
s¤§–¤»ˆØPàÊ*V´8Vìk³ªb3•z®ª[ÁéÙ‡Uû#òâ{ùä‚LìjK¨jÃc´‰¤¨"P ¦òIˆ¶Fe‚Sþ9yú2ÈÓ6¦Æ
ú8‹|Ïõèð^Óô¬S$Uæ5à]@Tfc"ÖŠLû<¿„™(W†¯TàM±a‚-ƒ°UËÍÍ•—â;J*S‹»ÓËÒ¢xõêì¤A¸¥ëKð#¨5ðP[Šÿþí¡:gÈ7£îÿâE£»ý•}&Åwé\k;?á"œ˜k0fý;X‰¢ØÍLN_(ÎS-~šo=⣼’ …Õl-WÏ#¨?ùÆø§Í¿¬ÿ½T×P&ˆð‡%d<²I4YÑ#ô‹O8æ‹>Õëì6Ú]Qït·ÆO适"”ê‰u
IžŽFä¤eC$LÍ+®Š(Zª ¤É
T•—ªk¹Q’iSÝ7\[ò›•jQžSaø
µe¨qŠss'àû{ä8¢\RL²‘Œ |áûÓ
ÛÂ[qÈ[ݬ6Õˆ‹±
Ú•Ô#‚FáÀ¼©æZ×aª}uæÃ7Üȹè:©£îÛ”Hkf%}}õÆt~Ži•ü@r ‹¨–:É0ö&hšŠ–1™;‚)h™8^€g$©x3JLêÒŽ¢+ ‘÷Òïøæ
“N<ü‘’ãoÖŠæs½Hõ%|Õ‡
mè+ÝjSª(˜µ1ÝÙ‘j|¢T¡H…•Ä8B?ô,¬®WPç}Ôئôd#Íßn¬‰?ä7;;”vº-F»¥’€‰>…ÁåÏ%µs }]ÛTÁƒr…ê•rˆrãõÉ¥Í0ĉCˆÅ•¶ŠŸñÙ®
³T-S=ÔÆû'õîv·±³güÐYßQJl
rqô…Ï!º‰ð•¢Ì«.>á·1§vgÝ•WÄ6¢$ŒNtÅÂO¯ùúåž“¼Âzú¹¥1’¯,äg}ÂwÀVam;¶:[Á^ŽÇ0‘Oï ĉl>JŽŸI#¥ël›çÓBO%›(À†¥G?ÍÝ/·¿e4.V)6•¥×á‚›"
8@²)¹¼ž„À±Í3Te™,@oËðmÂ?+þh–˜Åô“z5¬Ä(çB•K•ß
çƒùöa•f/aèz]㉩ÈÇp·:emä×–ões=VEBy-™‚,YàñR5d
ü2tF«ŽwW o{=)ð•‰o,‰|cµÌ7„¾ñ´Ô7^
ö•e¹o¬üÆ*Éo¬ýÆ¢ì•p¨F㥈|ÿÛÞõ?Gq#ûŸ‡z•ÄØUÉíâµcC>så“øŘs¸µµØcXØ/~;»6„ð¿?õ7©¥‘fƆ;ò®^ªî€Y•FjI-îÖ§?•·ü-gvé¾*_üs²Ü¦Š«èüCo
y#®Ÿ
?üSÞÙÇöï
™?ͦe)ð¬ï¿ÿ’gîÜÚ0•Ð~DÍædV¥I¹Ó¯•é‰“Â(Á`+ênºh%íÚ•>C5@Laï×G»÷Œ3@ûÊâ³ÙÐ8U!ÄPù6R úÆÆä
ãü¯Y»;:Ñß
k·Ò‰om¹ÔQݸhÙÀ•R¿s‘F·×ÙzŽ¼¨ß‘¯âTi<Æ =Å°…Þ¡1ovž=y²{p´ÿC†‡{?u(ªMß}553\Õ>ylö±¢´V•p’Âh¤6/°î.ÙN‹NØ!×#óCŠ‹¹Hâ¹sç8Wwoßb,dÆ[xž%„4Ÿƒ¢Z”ä=aÁjŸòLü—•[·•“fãÖ·{Ú¤¡HX5Eyζ•üvš§1ë߀¿
Ø.;¯h‚(6/žOÞýI•L7¶0iF‚è?k×`ã²¥UT{ïà`÷Iÿèç태ÛÜÕÛz}‰¶ÄîV^Ó`:•@AâøË…êõÄv{Óˆ™Qôìí¼„óMãÎÓX¼†ü<Œ<™RsXCrBŒm<ãŸBáÐ|k†Ý¨¤•oï~+¼:ǶŠ|K¾„|)ã):G³÷>kʬ_F=LçbOŠöXÀ4ÿ½<ï«/MŽ]S8:Õ~ðüàéóGpúxÿï»ý•Çv¥ö5Ê£¹úK°
+SÀŸþØ>F… Èó-ˆqáöh•ý, ‚•òǹ+r•+0aºv—{/£Ü…s©ºˆÙìCê’¸¦X
å²°Þᨳ_‚³ÔòÑhkÿä·1„NdI`-Àa`GèŒî7>;†¨*~™Moñªå1ƒ²P4y( x
rr¶ÁG'¤Š¸nSª<ƒJp|w÷6j¨ï¿ýž5©!D„YƒèÖ=ÏÛÒ¶ƒh‹/¨ˆ¨ÔgSB0œ© ] ׌÷x†yQKIpˆÐ~´%Šð
Û'ö@G’‡(²dŸ®Œœ'ðÍÇFïÑÈÜýöõ•X¿Û»}Ûmrª25ãøAa‡íÍô•²ß°ÈÁW$Î}ðÐmÚ#ƒ]Ãøð`Jø€œ®®N÷Å<ò§6Ua[lþˆ´Ï;aú\
ÄJ#-ÔϯÐDušõùZŒ[ÿ%ÙÊjP¥æ$l|I•‚“0yš8 “Ÿ³GF÷bþÿ÷9ÐsÜa •$/žpÞ¾÷•—‘r2RîHFÊ ÑÏàd™ilŠÊô¼˜
ðX‹•ž£ßy4-ç]WlVŒÂÉyÝe>^0$“óHÒ™,Äå÷ ù,ß•¶¬–•ïî|ß»JÿÂJà&ü•¿¨ŠÜñ›ÉxæáâàÊFá
³¡¹ëkX窩´ûÓÝýÝ•£þÞÀ'¿³)$PRà¨n¿€´ÙÕ.ðrBÕ6:†‡ÐóM#¼›m×ÄiŠœA•ki¨®QcE-ÃÔuj¬§m•Z‡§oHè9•"”ëL£U§Pä¡Ñ5¯:@•‚®™-ƒ#ݸ°€(eÁâ°T
CP*¯>]Ú’‘I”+Þ•çBd¸ûëŽ"RäX÷ëÙ@΄˜Vµ¯³”k1zvC•c°‚Ö•¢ûØUÅ]
Òˆ7•ÏÓü—öù@71༤Ÿ:MMnhH‘§
M-?£ÚEM}¨^Ö×ï}»N©Mí½â4õí•{ßn¤É]œ¦–ÃmÐØxîC¤Åäb8›N`‰–Ñ8'¿ŒÖ³yIy-Ê*õK’uõÊd0õü-ͺë›ÌgC³¾)x¾óþÕdQ
‘š1é•gÃùÜÀüößÓ×FúœõŠ•k0aþŸbc„øÝ`¾÷ÐÿÙÅü‹ÁKHêÁõòbNø˜ýÂ;æI~
y$d,v:½œ`ÀÕÅã
zˆG÷gŒ›ÉYIQ4yMµ^²cGMP¸W[˜U¢bÙÉ0ïmSÀ•¶Lae›a¶³¾9-.¾™,F#J4±•|ý;˜õë0ë!Ë'œõäIuî¯+ÅõÞ:Ìý•Ûßa¸`ƒÞ—ù¨¸(à,^´ÏѸ:‚#éS÷l¾œ)Â/³ÈÔmœœÆ6MÏ/ù‘•Høýª+¹ºM»[ÍŠÓaÉ3œã&ߘ¦Ž§F9½7æï<_`bZÅl\JÄÚÿ“q”ff{<\¼ós•xRLà\Ý|ž”¯qÑÜX•ò©îlæÅwë‹bVÂ6qK¾ÀÕõÌ6|c¥3ÀvflA¤ÁÅãm0÷ì‹Ñ^»ÎY¤ókcMòñ÷Üæܘÿl12£;ùñÞÑÏ•ŸåÛÏóãí'O¶Žžo¢gŽB˜h‹\_ƒdÁiû••G»OvŒ+z´ýãÞþÞÑs@æ?Ü;::㇕ŸäÛ`;ÚÛy¶¿ý$?|öäðñÓ]HIÅ4¢âÆJ•TÏpX`‘óÁpTb•Ÿ›aä384
gÅI1„¬‹½o¬+Dº¢ß:WÒÛ„ý3»J*Q
oo¬„Ó²—›erT€}–Ž`a¬e
ïß¾m´ñ•Æ`‡¢•¶óõ[«·×ïôògO·í±!áhJ˜•‹QáL½’µd‰¹¥Ç}ŒÑXêt8$»¤(•ü¬kPbŸ14•<ŠNwõåáñž©)õNË¡¿¶qµ›Ú§9•¶=<]ÌxÎÁº#9‚H•
8Š…öÉü¯éUñz::%i”Ìç ÏÔ›pÇÑ-¯Ýå-×M~Âê-µõµ;]ɧ{‚:g2½ì¥?lÙïN`õš&žƒq34“¾d‡\¤ÛJã7LxI+1`
›±¤Pë¾Ì
G•
\!,€7ïI&ÎôCÇÁ~*0Ææ"bœÎ¤`€#³Pª
Éõv÷)•6p¶#+Ê3D
ƒøˆÓá`!•;‡Gýí££í•Ÿ{ùÚÚZ7Gf•ùlQ²×‰Sâñ¡1šŽöBÍçh4ð J©=¨g¦cÎÝvþO"T¤oR•¼Ö³¨B8ôæ²ÚMqª†
é–±.²ª¢(•bå~3{¸;n¤¼J^"bä9g×H3‡1`ä?¦ÒÒKÓðSP¯±¦`<é€ÓÂýFs»Ñ RÅ
õ¥ˆË6Äöº•?‹»%#¹mvÉw(‚—`¬–‹—c°ÚNE©ÑV
ãÅæôyª/
«!³ÇWš‡É¥‰“ébXÁVãJÍ´ SÃpn|˜33QZ°ÃG–%W:¦±Óµ‡è€¼s¥t-•±ÐÑ{jØpŽÈ80çeð†33ÛÍÎX2Ø]3ÌÂê2©ÊˆòM¡V˜2¥%'|,&V˜
)ص ߌ¢Ù®O¨£‹”ˆ(N>˜xf¦PênO¤\i ÕjzôCšÕ§°wLU´÷‘›•t
˜”½ê9LÚé”ÜèÖ›Ôö•Ûò5ÊüÒx6¯z–J3ª7_ƒ‹áÚfL€?K×Ê÷““צ¢áï–ËãmQœK{ƘÂg¼^…†ÖIqpé@¹öú>È
%<þ'›xòœ4JËü“Hª¥Ñ²ve•Ÿ`JÇF¿•¼³ÿø`7þ¶•ýÉ»œyiž3yTq`$ìÎòi¤AËú‘x¥ÞC—7á=6ö<8CÕ§>ñŸS—ý¨@ý¤2(W6Z8$êÏ“MtZ
boIìO0}ÎüF«zÈýg—ez^úTÍææ
?œÎŒ!ujìš³!ÒT€×¹ÕZ¨=ò:»Ûf¢™Zšä¡š]ò’×ÿS]`Å¢ÁèMd.Á}ª«k<˜˜?£$ëái¥&þ]¢rÍr&O²Bþ½}…h<buA=
kSþŽÓ»Ee“Å«2•¾4½2•»Œ†§,°ØA†EYÅ–2{'ÓéÝp¼«Ú¼&Ö×BIÙ<˜Ø¨Rbcƒ©;W©‹Œ¨ÊÊ×ôwaoˆX§„iÊl.I›ú!*†ãÚ§‘m®›ZÑ$Nœb¶v™rð•ºFñL²ïÉÌ’÷¼7oz¯"GÞCÔˆ]G‘¯FÞ¥í&ò:ïCuíÆ
ËI“zPÚÝ‹¢Ô³ÜƒÂk†ÑÈ0±šÆƒò-O(C>!î¡ûš¦ ËŠää[ÎI›ÄOgºxp{•••ÖUû·¨ÞÏ•D#
£nN¨.êZãÕNgƒÙ{§0lbESUØXªÃÑ‚÷ȧ‰uµ‘ÁÛZ3cÌ•òÆG¹dÉI¬gT}?cPªÒ8_B`!ÊMÊèUŸ•\¤ÚÌx
œÓÛý
±ÃµSÂÕ‚çÉ›aMð°u
xÞ[©Ÿ¶èÍ X¨#×™•íƒ•Ýý«õ…êð»Âõ´ê
¿ïw„+ˆôƒí†Ä@Kú¼ÝÙ²ó¬ôp–I0ùd&ˬΦ½8UOšP•)žýóç~™÷È]C+¾ìæÊÇ@=ªEóûtürXÐüÿîMMÒ™- Õ—û°•kk±õ«Ê<´´Š•Õ-bŽ¡÷Éî£Ç•ßUg`ý•<~ôãÞn§?ÄÅ”§GMø诵ݰä¡õrû
ªÁ?å(«¡|Ý7_lR5ueVW±ÐGÏs™çŠö)ê4iÞN¤à<úÙÈëAßÍù,Û¸•Ó*xöôÉ-Ú7v•Ý;2å×]ù•dypP²ÿ€¶ÿ—¦Áäö_éùá®&ñ•!¦xá•“¤Ù‚˜B•t‡c>s܈Àñ¨ûzn×ÆðÙ
–%¢‹
U
¯lÍ¢Ž<%qß8•ØÝgÉÔ} r"q`·°AM8÷x‚‘è“ׂûæÈáFÞåCS¼žxÅà÷§G•!6×ÔY¼Á0g¹P´Lå@Ûgf‘W•±Z&•™,΢´ÿ<ƒà5êd+*÷?-ã†-ܼännbyz2È;á\Êozw-t#Ð>àT9Bù¶øuIÂâˇ8<æÏÕUE5N•¾`¸¶ðÆÒ6?e•š÷6™eª"Û‚âIŽNMUù–KI•Š•âÅf²vé]MÕP¤¶^H~ˆ0Š®ˆC8Þ{“÷¹]Þ¥¬_\Ä6eL,E#Wpo›I!oÕð‚éÚ„(žæ±×¨‰È©Ì{à2KõRùÈÒ–¬:• xòþ¶.زEi¥L3}ÃIÇV_m/âË„¹F
«–ÔC-ßÞÅ ®“Pï[8•£/¢ÙŒ—føű“›–-DòxÅí ð‚É<ï
Y.*+ÐU¢©Ì¶u™/Î-‘.ËÍÍ°+••:eÅåŹz8nF)70õ„Ç“• ©=|ë:>|á¾#‰ÑgŠE»ÆÊx"…\.ÄŠ0爓l'0û3Ã0¢ØyjÛº~ÕF.•Œ•¾ð§•õ%ûè§^iazËÒÕÑ°6efºÙ
ý)¨úd×feá|L
‹T–&¬Ã•o}I#•ØÖ[Héf©«Ö(±ˆáÕ #a2+ƒ,RZ—¯‘òvuÕÄ}G&¨£í îÊ‹n@_kù5|uœ6@·xÉFÊÚ Œ•0Y•ùXõ…˜ipˆ’ó©ªïrmB•8x[7
¼ª-êù™ªÊ.’€‰&–ò:•¯•¶à%V•ñË߆´%óõoÞLhñð¸Ðù/—ŽÝî™fp‚è…91µ2R]/¹ieʧ•r2¥/¿ÁkÏ[åoõF—æݽvÅhûÛ=ø/B£|<½õ®‰FÃ5ß硯©ùpæ¢O˜Ù¾T‡3=XqÜ>¤;êÜ„Ç]´••kJ‰´œ_JqZËM©l]gC¤ZÖ•â£ÙŽìküWÌp
ùôÂ`6dd/â},`YJ?8é§ ’]á};àüo¾’ŽZS¥í
=µýAÓE Nÿc·›> é—M¦
ôJ*¤-H2ÝçÉ{á•ã9]Wm•¼?"Kh^³¿t–×P×fƒÉda%¤ÈÚܜޣТÇãÁž©aîPâ}³©öÈê5ón¦{ßåì¼rˆ0ñJœÅ·¨Þ„>ØäoxÙ¿I/ûj
ãÍ‹5—ªêù>aiñöI¾š?ØÝyânÚÁØ•¸[[µ¡¡®»ì}©ùcŒÙ6o$ÃDop•+V¶Œ4A«‘®$a·i;¡ÒËÓ`‚ÉäÝêPÃ8æ•mr•æøZC-™4)ƒY¢(£aÉ=†Ñiˆ³„zL“¶Ö•Ö5œh$·òÚ9fÚff~}Ъ-–"â‘m÷ôOÒÛMa!¨•®¬øêJ¦ð/`E"‡º4kÁÈ´0ýô|Mµ°Jº8Ø/{ûûu–äÍhîYßç„÷µõ'T¼Ép~m«.D8QdbÁÅs‘ªŸÛMiÅ(=ÐëÖ{¸‰s<YNjÑ
¢YûÎÅèb•()üxýÙp•…ït¬Â:~ AK;•×†47t@
êÇÐOÔϼ‘UôÝä™xe±=_0-`•ès噪&XÍRדŽáX7W-WA\Ö®X}¡ŠÛî—jQ»Ì•‚ô+‹‰&`9(.…w%F¶"+™Q瞬bûó1œÇâMNI™£ïÒ,ój4{æSjGF$¥4ÂI^‰M1Ÿ?Áê "út*
ô•(võ¹BWíTI›è–tMÅ] •Áïú-v"þDC´)b:Xÿye%8O-‚ù^¼¹j\Ý7ú’T•û$—yzù°„§¬,4ËÆbuœq®íÝ÷W•<’¥Æ“•Æ¯§ÚBB
µSŠXë§IS‘_ð Ó¤5â4Ú•7r§évÆ"`›)þ/%•*<åÊs»£ÎpJ"QùcR4¼¸ÿü¢‰6[I&.…G«ÌÇ3m)1ÓT—iÚz# bgRRlÐxv!¹1j'å
qÿš¯ûhÉYR• ^‰¥´)E#XqëÃXMêu¢Çú@µxVVò•M*ì™õ…?z½Z
w~o„ä&nnRs)S„uI‹‰ùî’Tu®Ü?mEÙ½îП©ˆª¦ÚÎ…•0¥pui¹i»D+…—Óé4ä2†BÚ•Ùœ ·ƒ1Ž‘†2Ë|èmN!A„zd:Q»Ót♄ôæèFùu¸/]è¤prÝM]AήR
½¡¯r°MýuˆB”ŸO-Ãî¨RÖ¯-Šq[1j™de…Ri›ý
cNUMžê§¡(,‘³ÈòxuúÒÔg,—™£q\Ö¹Â,›ÓpÁ®ýª´4ždåV
Hw•¼ÒÝìj/³˜˜–>ª¾F(ÖÈ>RUTôº]µ’÷¾ûç<¯EˆÞ]Ô4Õk§£_ã,¯Ÿ¬•ö%À‡¯Ÿo 4Ìñº™Ø,ô¦ZÚˆüOýOxuê{
PffÂ+êàÊ×,èþ`¦Üs"½ÀSjä>Âf'O”ÜaˆË•—<¾<ç~ÅrñÃ¥öf
›&ŠUAXŽN½‰}áb0RµfÏwu-•p§üSâ$‚ÓA^㮊¾„¼I&œ–…ªƒh•FĘ#òjñ%º‰m<
Ú$ÎÛ¥ÎQu•$l>`ÄN0ìO_¾¡+‰ù/¼ÿ²Ó*¿Þä¿>í؈hkƒ„{sLÑ¥J._iþÔ··Iµ•üQ9ö®ïTïtÆ<œNß.ÎûÁw;Ëý>½ïån){±žô‡n¢T¶™Ž×iÚ€ÕÒO¸Q-åÆÈïChç9[Q}ãC´R¯f—™>=}þèÇÇûý¿oï?£3"à~0Ýíê“RK¶í•áHuט»DÀ«IË;(o––ôÌŒ[ô†ÈTOuÜ•õÚ¡J‹/›.ÜíF]ÖvZmù™MKF@²ow“¸þ¹üUùÏe¥Ð’âsj:ù«!L͈ø‚ãRÁIÔ‹.ûEG%•^zX²üÚÑ×/>,‚
iô˜ÿC"QëÏ5 Êhû¢ê˙ϕÊKY™_Tu9Á}î!£î•[Ö-†ClÐ/<,µÏ·‹(«êŽ…ùzÓ
€Ù÷%¥¯U/~±Å˜«Wp–pÕ.ƒ{£ðŠîkØd|buuÛõß#,i^ZPy”3¢…¥{
)õO.)lbkiöóJJâüôÏ?«°‚V¶–—œè×È,•¿½†4å¨íÏ-Í •-¥) ˆO‘&\P‰é•óX4£ú‘´bC`¾M-ë
µûnŒÉ’À îðåùÍêb¶Á•¤ÂÒþ>gÕH£i|§!—þ&ψÊÇëß«oË•ïªQZ•¸!
³V$•„‚î:³Dèä‹ñùü½ÔÎ×ò
0}Pÿå ‘:Iz«
õ$•]Íàf8\ÂÖ?#n8Fô¦ñ@ËË™ÎWï:ójÜE%/¿¤ŒÁtÒMYø
ñ>Ywö¶áª‹âG¤ 6_^¯KëhÞñRû^n^}ê]`¦’]<Þw
F²uêyÄ•¸Ãý-…SXÙ•KéÃóDŸ&EKónx ¦šn׋AÚÔ?ÊŸ+Î#!ÃGƒÙ[ÿfT!z”¶yN•ZËS°O•Òæ[+¸¶D“Ü35‰R
w¬¾˜L-•éä‚ÁûÃSºÔ"’éél¼Æ³ƒVS8AÜcšÈçØXÁËÅÙoëë/Xä%m–yÇ<ïåf¿Ë¿2[n5‹èoù2%o.ç÷òåCˆÍä¼ T•M%ª_ÛÄ€#WšSýpïWºÈ•ÀÓÌ'H™#ÐL¾êò¤XE¨.®1¡¤¤µ'<•áÕÑ‘•<óòtŒ+{øz•>•Ï‚#ÃO*ÍKʈ8Ïåë>Ït¾Iäj71u-¨è·:D~·'öÛšßé’)Ñï÷YQulƳe-[3Ó'!“4nNš¸=l¢ÛÓ„nN%pPY(^|ÊØj8뙯YÖWy•Àꥣ†¥™€eǤ
ú—x•å6"jrøâ/Àx2ž8c@…>*Îæ!¹’ÞÎÕÇ•Ìoþä>-ä¼
x¢JfÏx8%‚]:&šæ—ÓÙ۞Ѐ¾„[õ`À“ÌjY|u²ñ0iE>pë¼14Æp"vëêißå€>•æ\;ÐÅŸF‹wšÅl#DÿÿÑn·Åš¸ûõ×LÍòl•á¦þ—†Ü£%rv¦vçk™"ggÊ9;óΡC¨«ç£Qr©¼•L/…8ÆßsÚÀ}<÷Œˆœ
í0•È¥PÞAögSúå•Fv
iDC— —…˜oÄœÕnŠ®…ËŒ+q„vô‹í}~b®ä‚%k¥ÍÃHÃÝ™€;)Ô!1ýÌž…çÛȆoÜCŸ½þ!»ŸÙ…•Y?.òÃÿêÝJ7„”õ®Å5¶êîVª»´FšŒ3]—ºÒ6šg
€ÌM4‘9KÈ»ë'Äü·Ï•©zÙF6y'»JNP–Nò¹\åõ[qvŽXChë,ÎõÍ&¦°ÚrÊâ-+•©bÑKæ#oxðùTµ
8•.”tÀê]?/ßÊâFLÛÝÌÝ•8+•‘<}o38&gS«ª?Fl¢ÄžÇÛÅbÒl ˆÎdA²~k¯!ã;ê>ÐE_tq¦iÝo¨.UÆ«Và
œðv0šçr{ßi —!ÂÙZìù^Z |¸—‡´!ã:¢˜&1V”äShDýTð*Ñu/§ÓIÿ•ÃH.ª–hΆ7tɦo&p•-Y"½ÁÏV°»ö!yèl˜Z=ºBÂ]ÏeÍÚù
œº;‹¨ÊÀ{ÍêÖ´Œ€Kâй b´È¥Éœ©æ‘&ü5ßOi!œÊ•ó÷•{ÒÕzåd;Âר#¯€éš K§r†•Ç°†ËøOö¢Æ•Ó–ÄULIž=š\ZY˜±E)4žÀ–$µÞf.´ÉèÈ©-YöQ[X‰M×Ë–v€þ6ö®Ÿ5ýÒ5‚ÌíÚä‹è|h»üœiWÅ‚j•³”~’IÞÒ¦%Å7SiSœ$rm›xfjÓM,NOâmæ5ºåT\Š:„ÞLReeú!œÊÞÔd*Á#«ÏðÐv”ÛsÔSß7«ŸzV*ѽeß\¹Å“÷vmë¨Ùå0••tüÍÓ“@"Êb«œJDa•ï3ᔮϸžÐ%Eq2.•¨|1·÷j`ck´AN3NC•íìþ}ðšpbÚ÷š3 Cþ#œú!i§&4ªÒùEM†®Þ׫dlK•ëÛÏD«ÝòŽnußqIòþ¦˜Ú§Ø}PÝÈ,äÕ˜Lý-ÝÛÛBÒ9.÷½@D3i-qgÌHi ü\]}±é¬•xîGzea²ý¸"iYÖžµÌÓ\BÄjÙEµÕ8c¢-É«gÞTB'õô¯b4‘¿f×å~ͨ_³k1¿ªÉúW»—–¬¯´æ˜)wAÖ;h+°••6€jµ71LñâÞ‘Jòb`…È€1¢ðvO¸j¨/Ììp|»ÜG^PÄgJ·1t!¼lM¬©{ÊAe0¡,´£œÙ?î?Þù¥—•¿#Âü0•äÌ£‹ð§^;JÓü•üøàñÏÛ?Æ•&`÷3']·
¼•]åõßQ#£9¹«ïØ'ô†—v'ÁÈ<ŒL±òº~H 7ÓÜW™MZ*%h²Ž7€bª†³àéîÑ£í§¿Èpë³~(•˜L³ø4s?¹Ù-1ÐÕ•xÜøxï!•¹ï>褂^a^õ¬ÐFDǽdØLŒÆè5Ξʕ
Â_«•T–¿BåË;xq•Äd“âÝyqb¬ƒÑû|<,!ør/ÿª\$•\¦=8Õ‘=D¹M•51Ç••tˆùð]Îx¶âX½ÿPI6w¼½wôËÞÁÉíï>ج¼•÷^¬™:+¼g¿<>>ðIáJ•Ä-^ÎSæš5~*_œh¯}„|+f9U¤´^ä[†ƒ¯k+ðji:Í‚s2¹
çu1âà°Š
GN‰ìèÖ0ö9{N—Ž•«•¾‘ûÛúUQz]$ñ$Íšùu3ºÂ)ú&Å«A‚ •fÁõÈìšþcæ³òeL-ßÌo§}Å–_w þ%GE'žb»“•ˆO»Ùîm¦ÈÛðœÑ̳+<'»•¾GK¦BÏŒ™ÌÆKe–
qSæ,?3Õ0hîøAµ£O÷6«¡D÷öXO$-¼¤¦sŒZÚæ¬]ª„‚k\µ@MT¾÷k|á;>~½É•6|;<wäó¤ñª§x-c Õ
•‹‰z‹21X5ì~™ÐŠ'ÞŽSûqÂñÖÇyS€VÐÅeáý]x3óipø•…¶A }?DmÆÔ©Q·²†ý#5<ÈBF@ض’±*Ŭvum{]]û¡}•L+e§‘<Žb¬”ÖÕêF»Áü“0=˘ÝÛ-Æ=¨²V•Šˆ·÷äçÓy1Áà_²§U+V)Þ¼rôtåpj@ás݈jÓTùXõ¬–Úmzʘ•ªÍuéÛI~‡tŸ6He„¨Ø--ûpŸêŒÈuwÄ6„ÃJÕÑkb²<a¦HšÚªÝë)^çz¤jH(ßЕŒãW9Fò¹õêMB?š„OÏ,Ê3\œ%¸Ü<]‚^5®Ÿsô’fAHYþa¦‡^Ï>t=k•TÖ¯žµ@XtBƒ†
| ´Ô¼¦ë&ÞA¹•
upïÆ*u¸Ž½ÓY”÷! uÍ'ùì=¦–ðƒÆÓVÇWn7cŒ†‚qµµw³Ñ‡t#¼‚ ÅäÂC>Ú2›’Š{ÏnšWÿc@ÄyþÉØà
榵ü5zΕÈE€f…›§Ã¢l1ìc£Š&ê«Ý+‚VÿÅ°Ôÿ‡…Uµbˆ÷ºÜ«%ª,†
«L•kàÁ•Oß›§ylš¨pêªóÖøeŠÑÌ/…–ªpÿÄ<ð+˜*Ÿk4²gÝ)õuˆÑÓ0uëƒ3Õ•yW„
`Ÿ³ÏÇ.E…°^pŒ?>sMSÄÄNxH±ºãäîŠg'Ò1/ÚëáLõ¬õ÷Ö?áC½Ô7}mäë>Yvµ
•›!ük®ˆ¨f2GoåFžÀM¬ÁPD.æ•DzhÒ°OŸÀ¡_7¸Úï!öì¿|]ÊÄ•çhýM'º)é¥Vé§Zpy‘BK-R¶ô<ýÚV¦›‘vÚ•\䢕ÿÈ‘«ôÓ¹ˆ>aäÚÊT•&uš5ÉÓ*c•¥Ñ+ÃWCN€’ñs—g‹É2šùËd,ƒª5m<-›áN'ƒIß¼_¹U•zP.Εk®„"Ô¼ÿ‚º4ðÉt2÷t3
Xײþa¹—ái$e¾žÎæxŸmˈàñÈð…Èp¹—óK•ÂÖê•Zm>`ÞåWO§'üÖ:4Bš15öSìùÉh#<$^×ÎŒ”$Œ¼i»eÐ|¤(…C\¥IиrT‹´þ¬˜ÓpV¼2Æ_1+cE(äP[DåWcéX™wf»+>Ö•!0•(û²~••Áª*º¨ÐÂõk¥.¶HËL§ÇC°lÁX¶òx
Þ몕€Mß,Hó—ùùbÞX¶¡Mq••½áF
ÞH5£©½ü4xŽì"–Y->ð0{v1žgäUßz°oFE웤|\¯DE:0™Vôå`=R›N’³•ð2çâKᜟ–QªóÅXi+zmTñ.:Ú¯FYó0½8 „÷ëFø«QÙ'oS?†k·RÀåÔ„/dË(“?ô˜@?>>|Ú•´ýÓÞŽ«|<x5$múqÓq»ö]ÚzßÅÚ}¥Ž˜‰ôë#>ÕýH…J\J}ìBÛ•û•:J6‚
›×/•„º¥…úÛq$[×~ïô´¦XOª'{â•U³h¦ó
diff -urNp linuxthreads-0.71-ORIG/internals.h linuxthreads-0.71/internals.h
--- linuxthreads-0.71-ORIG/internals.h Fri Dec 5 01:28:20 1997
+++ linuxthreads-0.71/internals.h Fri Nov 13 21:53:10 1998
@@ -95,7 +95,7 @@ struct pthread_handle_struct {
struct pthread_request {
pthread_descr req_thread; /* Thread doing the request */
enum { /* Request kind */
- REQ_CREATE, REQ_FREE, REQ_PROCESS_EXIT, REQ_MAIN_THREAD_EXIT
+ REQ_CREATE, REQ_FREE, REQ_PROCESS_EXIT, REQ_MAIN_THREAD_EXIT, REQ_DEBUG
} req_kind;
union { /* Arguments for request */
struct { /* For REQ_CREATE: */
@@ -243,6 +243,8 @@ static inline pthread_descr thread_self
#define ASSERT(x)
#define MSG(msg,arg)
#endif
+
+extern volatile int __pthread_threads_debug;
+ if (self == &__pthread_manager_thread) {
+ /* On reception of a REQ_DEBUG request (sent by new threads created to
+ the thread manager under debugging mode), the thread manager throws
+ PTHREAD_SIG_CANCEL to itself. The debugger (if active) intercepts
+ this signal, takes into account new threads and continue execution
+ of the thread manager by propagating the signal because it doesn't
+ know what it is specifically done for. In the current implementation,
+ the thread manager simply discards it. */
+ return;
+ }
if (__pthread_exit_requested) {
/* Main thread should accumulate times for thread manager and its
children, so that timings for main thread account for all threads. */
diff -urNp gdb-4.17-ORIG/gdb/breakpoint.c gdb-4.17/gdb/breakpoint.c
--- gdb-4.17-ORIG/gdb/breakpoint.c Wed Apr 8 16:51:56 1998
+++ gdb-4.17/gdb/breakpoint.c Fri Nov 13 22:31:40 1998
@@ -1,6 +1,6 @@
/* Everything about breakpoints, for GDB.
- Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
- Free Software Foundation, Inc.
+ Copyright 1986, 1987, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
+ 1998 Free Software Foundation, Inc.
NAT_FILE= nm-linux.h
-NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o core-aout.o
core-regset.o i386v-nat.o i386v4-nat.o
+NATDEPFILES= infptrace.o solib.o inftarg.o fork-child.o corelow.o core-aout.o
core-regset.o i386v-nat.o i386v4-nat.o linuxthreads.o
diff -urNp gdb-4.17-ORIG/gdb/config/i386/linux.mt
gdb-4.17/gdb/config/i386/linux.mt
--- gdb-4.17-ORIG/gdb/config/i386/linux.mt Tue Apr 21 18:23:15 1998
+++ gdb-4.17/gdb/config/i386/linux.mt Fri Nov 13 22:31:40 1998
@@ -2,4 +2,7 @@
TDEPFILES= i386-tdep.o i387-tdep.o
TM_FILE= tm-linux.h
+# The following define is used to get the JB_PC #define from <jmp_buf.h>
+MT_CFLAGS= -D__USE_MISC
+
GDBSERVER_DEPFILES= low-linux.o
diff -urNp gdb-4.17-ORIG/gdb/config/i386/nm-linux.h
gdb-4.17/gdb/config/i386/nm-linux.h
--- gdb-4.17-ORIG/gdb/config/i386/nm-linux.h Tue Apr 21 18:23:16 1998
+++ gdb-4.17/gdb/config/i386/nm-linux.h Fri Nov 13 22:31:40 1998
@@ -74,4 +74,22 @@ i386_insert_watchpoint PARAMS ((int pid,
extern int
i386_remove_watchpoint PARAMS ((int pid, CORE_ADDR addr, int len));
-#define FRAME_CHAIN(thisframe) \
- ((thisframe)->signal_handler_caller \
- ? (thisframe)->frame \
- : (!inside_entry_file ((thisframe)->pc) \
- ? read_memory_integer ((thisframe)->frame, 4) \
- : 0))
+extern CORE_ADDR i386_frame_chain PARAMS ((struct frame_info *));
+
+#define FRAME_CHAIN(FRAME) (i386_frame_chain (FRAME))
#include "i386/tm-i386.h"
/* Figure out where the longjmp will land. Slurp the args out of the stack.
We expect the first arg to be a pointer to the jmp_buf structure from which
@@ -712,6 +718,162 @@ skip_trampoline_code (pc, name)
return 0; /* not a trampoline */
}
+/* i386_frame_chain() takes a frame's nominal address and produces the frame's
+ chain-pointer. In the case of the i386, the frame's nominal address is
+ the address of a 4-byte word containing the calling frame's address. */
+
+CORE_ADDR
+i386_frame_chain (frame)
+ struct frame_info *frame;
+{
+ char buf[4];
+
+ if (frame->signal_handler_caller)
+ return frame->frame;
+
+ if (!inside_entry_file (frame->pc) &&
+ target_read_memory (frame->frame, buf, 4) == 0)
+ return extract_address (buf, 4);
+
+ return 0;
+}
+
+/* Under Linux, signal handler invocations can be identified by the
+ designated code sequence that is used to return from a signal
+ handler. In particular, the return address of a signal handler
+ points to the following sequence:
+
+ 0x58 popl %eax
+ 0xb877000000 movl $0x77,%eax
+ 0xcd80 int $0x80
+
+ Each instruction has a unique encoding, so we simply attempt to
+ match the instruction the pc is pointing to with any of the above
+ instructions. If there is a hit, we know the offset to the start
+ of the designated sequence and can then check whether we really are
+ executing in a designated sequence. If not, -1 is returned,
+ otherwise the offset from the start of the desingated sequence is
+ returned.
+
+ There is a slight chance of false hits: code could jump into the
+ middle of the designated sequence, in which case there is no
+ guarantee that we are in the middle of a sigreturn syscall. Don't
+ think this will be a problem in praxis, though.
+*/
+int
+i386_linux_sigtramp_offset (pc)
+ CORE_ADDR pc;
+{
+ unsigned char code[8];
+ unsigned char sigtramp[] = { 0x58, 0xb8, 0x77, 0x00, 0x00, 0x00, 0xcd, 0x80 };
+ int off, i;
+
+ if (read_memory_nobpt(pc, (char *) code, 1) != 0)
+ return -1;
+
+ switch (code[0])
+ {
+ case 0x58: off = 0; break; /* popl %eax */
+ case 0xb8: off = 1; break; /* movl $0x77,%eax */
+ case 0xcd: off = 6; break; /* int $0x80 */
+ default: return -1;
+ }
+ pc -= off;
+
+ for (i = 0; i < sizeof (code); i++)
+ if (read_memory_nobpt(pc + i, (char *) &code[i], 1) != 0)
+ return -1;
+
+ return memcmp (sigtramp, code, sizeof (code)) == 0 ? off : -1;
+}
+
+/* Get saved user PC for sigtramp from sigcontext for Linux style sigtramp. */
+
+CORE_ADDR
+i386_linux_sigtramp_saved_pc (frame)
+ struct frame_info *frame;
+{
+ char buf[TARGET_PTR_BIT / TARGET_CHAR_BIT];
+ int ptrbytes = TARGET_PTR_BIT / TARGET_CHAR_BIT;
+
+ /* Don't cause a memory_error when accessing sigcontext in case the stack
+ layout has changed or the stack is corrupt. */
+ target_read_memory (SIGCONTEXT_ADDR (frame) + SIGCONTEXT_PC_OFFSET,
+ buf, ptrbytes);
+ return extract_unsigned_integer (buf, ptrbytes);
+}
+
+#ifdef CHILD_RESUME
+
+#include <sys/ptrace.h>
+#ifndef PT_SYSCALL
+#define PT_SYSCALL PTRACE_SYSCALL
+#endif
+#ifndef PT_CONTINUE
+#define PT_CONTINUE PTRACE_CONT
+#endif
+#ifndef PT_STEP
+#define PT_STEP PTRACE_SINGLESTEP
+#endif
+
+void
+child_resume(pid, step, signal)
+ int pid;
+ int step;
+ enum target_signal signal;
+{
+ int request;
+ unsigned char code;
+ CORE_ADDR pc;
+ int i;
+
+ errno = 0;
+
+ if (pid == -1)
+ /* Resume all threads. */
+ /* I think this only gets used in the non-threaded case, where "resume
+ all threads" and "resume inferior_pid" are the same. */
+ pid = inferior_pid;
+
+ if (!step)
+ request = PT_CONTINUE;
+ else
+ {
+ pc = read_pc_pid (pid);
+ for (i = 0; i < SYSCALL_TRAP_SIZE; i++)
+ if (read_memory_nobpt(pc + i, (char *) &code, 1) != 0
+ || code != ((SYSCALL_TRAP >> ((SYSCALL_TRAP_SIZE - 1 - i) * 8))
+ & 0xFF))
+ break;
+
+ if (i < SYSCALL_TRAP_SIZE)
+ request = PT_STEP;
+ else if (!IN_SIGTRAMP (pc, (char *)NULL))
+ {
+ /* Single-step over the syscall in order to avoid being blocked
+ inside the kernel waiting for the thread to be unblocked. */
+ request = PT_SYSCALL;
+ }
+ else
+ {
+ /* Put TF in the eflags from the frame set up by the signal handler */
+ unsigned long eflags;
+ CORE_ADDR addr = read_sp () + SIGCONTEXT_EFLAGS_OFFSET;
+ if (target_read_memory (addr, (char *) &eflags, 4) == 0)
+ {
+ eflags |= 0x100; /* Trap Flag */
+ write_memory (addr, (char *) &eflags, 4);
+ }
+ request = PT_STEP;
+ }
+ }
+ call_ptrace (request, pid, (PTRACE_ARG3_TYPE) 0,
+ target_signal_to_host (signal));
+
+ if (errno)
+ perror_with_name ("ptrace");
+}
+#endif
void
_initialize_i386_tdep ()
diff -urNp gdb-4.17-ORIG/gdb/inferior.h gdb-4.17/gdb/inferior.h
--- gdb-4.17-ORIG/gdb/inferior.h Fri Apr 10 22:39:38 1998
+++ gdb-4.17/gdb/inferior.h Fri Nov 13 22:31:40 1998
@@ -213,6 +213,12 @@ extern int signal_print_state PARAMS ((i
/* Some machines have trampoline code that sits between function callers
and the actual functions themselves. If this machine doesn't have
@@ -210,6 +218,14 @@ static int breakpoints_failed;
+#ifdef PREPARE_TO_PROCEED
+/* When a pid must be single-stepped for going over a breakpoint at
+ proceed (), it should be implicitely stepped by target_resume() in
+ resume (), implicitely waited for in target_wait() and switched to
+ in wait_for_inferior(). */
+
+static int proceeded_pid;
+#endif /* PREPARE_TO_PROCEED */
/* Things to clean up if we QUIT out of resume (). */
/* ARGSUSED */
@@ -259,7 +275,7 @@ resume (step, sig)
/* Install inferior's terminal modes. */
target_terminal_inferior ();
static void
@@ -511,9 +525,47 @@ wait_for_inferior ()
registers_changed ();
if (target_wait_hook)
- pid = target_wait_hook (-1, &w);
+ pid = target_wait_hook (!breakpoints_inserted ? inferior_pid : -1, &w);
else
- pid = target_wait (-1, &w);
+ pid = target_wait (!breakpoints_inserted ? inferior_pid : -1, &w);
+
+#ifdef PREPARE_TO_PROCEED
+ /* Switch to the thread selected by the last PREPARE_TO_PROCEED ().
+ As a side effect, the trap_expected value should be switched. */
+
+ if (proceeded_pid)
+ {
+ if (proceeded_pid != inferior_pid)
+ {
+ trap_expected = 0;
+
+ /* Save infrun state for the old thread. */
+ save_infrun_state (inferior_pid, prev_pc,
+ prev_func_start, prev_func_name,
+ trap_expected, step_resume_breakpoint,
+ through_sigtramp_breakpoint,
+ step_range_start, step_range_end,
+ step_frame_address, handling_longjmp,
+ another_trap);
+
+ inferior_pid = proceeded_pid;
+
+ /* Load infrun state for the new thread. */
+ load_infrun_state (inferior_pid, &prev_pc,
+ &prev_func_start, &prev_func_name,
+ &trap_expected, &step_resume_breakpoint,
+ &through_sigtramp_breakpoint,
+ &step_range_start, &step_range_end,
+ &step_frame_address, &handling_longjmp,
+ &another_trap);
+ printf_filtered ("[Switching to %s]\n",
+ target_pid_to_str (inferior_pid));
+
+ trap_expected = 1;
+ }
+ proceeded_pid = 0;
+ }
+#endif /* PREPARE_TO_PROCEED */
/* Gross.
remove_breakpoints ();
target_resume (pid, 1, TARGET_SIGNAL_0); /* Single step */
- /* FIXME: What if a signal arrives instead of the single-step
- happening? */
+ /* FIXME: What if a signal arrives instead of the
+ single-step happening? */
if (target_wait_hook)
target_wait_hook (pid, &w);
@@ -678,6 +730,9 @@ wait_for_inferior ()
target_wait (pid, &w);
insert_breakpoints ();
-
goto have_waited;
}
@@ -1239,9 +1293,7 @@ wait_for_inferior ()
update_step_sp = 1;
check_sigtramp2:
if (trap_expected
- && IN_SIGTRAMP (stop_pc, stop_func_name)
- && !IN_SIGTRAMP (prev_pc, prev_func_name)
- && read_sp () INNER_THAN step_sp)
+ && START_SIGHANDLER (stop_pc, stop_func_start, stop_func_name))
{
/* What has happened here is that we have just stepped the inferior
with a signal (because it is a signal which shouldn't make
@@ -1847,6 +1908,33 @@ int signal_pass_state (signo)
int signo;
{
return signal_program[signo];
+}
+
+int signal_stop_update (signo, state)
+ int signo;
+ int state;
+{
+ int ret = signal_stop[signo];
+ signal_stop[signo] = state;
+ return ret;
+}
+
+int signal_print_update (signo, state)
+ int signo;
+ int state;
+{
+ int ret = signal_print[signo];
+ signal_print[signo] = state;
+ return ret;
+}
+
+int signal_pass_update (signo, state)
+ int signo;
+ int state;
+{
+ int ret = signal_program[signo];
+ signal_program[signo] = state;
+ return ret;
}
static void
diff -urNp gdb-4.17-ORIG/gdb/linuxthreads.c gdb-4.17/gdb/linuxthreads.c
--- gdb-4.17-ORIG/gdb/linuxthreads.c Wed Dec 31 16:00:00 1969
+++ gdb-4.17/gdb/linuxthreads.c Sat Nov 14 15:59:01 1998
@@ -0,0 +1,1380 @@
+/* Low level interface for debugging GNU/Linux threads for GDB,
+ the GNU debugger.
+ Copyright 1998 Free Software Foundation, Inc.
+
+This file is part of GDB.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* This module implements the debugging interface of the linuxthreads package
+ of the glibc. This package implements a simple clone()-based implementation
+ of Posix threads for Linux. To use this module, be sure that you have at
+ least the version of the linuxthreads package that holds the support of
+ GDB (currently 0.8 included in the glibc-2.0.7).
+
+ Right now, the linuxthreads package does not care of priority scheduling,
+ so, neither this module does; In particular, the threads are resumed
+ in any order, which could lead to different scheduling than the one
+ happening when GDB does not control the execution.
+
+ The latest point is that ptrace(PT_ATTACH, ...) is intrusive in Linux:
+ When a process is attached, then the attaching process becomes the current
+ parent of the attached process, and the old parent has lost this child.
+ If the old parent does a wait[...](), then this child is no longer
+ considered by the kernel as a child of the old parent, thus leading to
+ results of the call different when the child is attached and when it's not.
+
+ A fix has been submitted to the Linux community to solve this problem,
+ which consequences are not visible to the application itself, but on the
+ process which may wait() for the completion of the application (mostly,
+ it may consider that the application no longer exists (errno == ECHILD),
+ although it does, and thus being unable to get the exit status and resource
+ usage of the child. If by chance, it is able to wait() for the application
+ after it has died (by receiving first a SIGCHILD, and then doing a wait(),
+ then the exit status and resource usage may be wrong, because the
+ linuxthreads package heavily relies on wait() synchronization to keep
+ them correct. */
+
+#include <sys/types.h> /* for pid_t */
+#include <sys/ptrace.h> /* for PT_* flags */
+#include <sys/wait.h> /* for WUNTRACED and __WCLONE flags */
+#include <signal.h> /* for struct sigaction and NSIG */
+
+#include "defs.h"
+#include "target.h"
+#include "inferior.h"
+#include "gdbcore.h"
+#include "gdbthread.h"
+#include "wait.h"
+
+#include "breakpoint.h"
+
+extern int child_suppress_run; /* make inftarg.c non-runnable */
+struct target_ops linuxthreads_ops; /* Forward declaration */
+extern struct target_ops child_ops; /* target vector for inftarg.c */
+
+static CORE_ADDR linuxthreads_handles; /* array of linuxthreads handles */
+static CORE_ADDR linuxthreads_manager; /* pid of linuxthreads manager thread */
+static CORE_ADDR linuxthreads_initial; /* pid of linuxthreads initial thread */
+static CORE_ADDR linuxthreads_debug; /* linuxthreads internal debug flag */
+static CORE_ADDR linuxthreads_num; /* number of valid handle entries */
+
+static int linuxthreads_max; /* maximum number of linuxthreads */
+
+static int linuxthreads_sizeof_handle; /* size of a linuxthreads handle */
+static int linuxthreads_offset_descr; /* h_descr offset of the linuxthreads
+ handle */
+static int linuxthreads_offset_pid; /* p_pid offset of the linuxthreads
+ descr */
+
+static int linuxthreads_manager_pid; /* manager pid */
+static int linuxthreads_initial_pid; /* initial pid */
+
+static int *linuxthreads_wait_pid; /* wait array of pid */
+static int *linuxthreads_wait_status; /* wait array of status */
+static int linuxthreads_wait_last; /* last status to be reported */
+static sigset_t linuxthreads_wait_mask; /* sigset with SIGCHLD */
+
+static int linuxthreads_step_pid; /* current stepped pid */
+static int linuxthreads_step_signo; /* current stepped target signal */
+static int linuxthreads_exit_status; /* exit status of initial thread */
+
+static int linuxthreads_inferior_pid; /* temporary internal inferior pid */
+static int linuxthreads_breakpoint_pid; /* last pid that hit a breakpoint
*/
+static int linuxthreads_attach_pending; /* attach command without wait */
+
+static int linuxthreads_breakpoints_inserted; /* any breakpoints inserted */
+
+static int linuxthreads_sig_restart; /* SIG_RESTART target value */
+static int linuxthreads_sig_restart_stop; /* SIG_RESTART stop */
+static int linuxthreads_sig_restart_print; /* SIG_RESTART print */
+
+static int linuxthreads_sig_cancel; /* SIG_CANCEL target value */
+static int linuxthreads_sig_cancel_stop; /* SIG_CANCEL stop */
+static int linuxthreads_sig_cancel_print; /* SIG_CANCEL print */
+
+static struct linuxthreads_breakpoint {
+ CORE_ADDR pc; /* PC of breakpoint */
+ int pid; /* pid of breakpoint */
+ int step; /* whether the pc has been reached after sstep */
+} *linuxthreads_breakpoint_zombie; /* Zombie breakpoints array */
+static int linuxthreads_breakpoint_last; /* Last zombie breakpoint */
+static CORE_ADDR linuxthreads_breakpoint_addr; /* Zombie breapoint address */
+
+#define REMOVE_BREAKPOINT_ZOMBIE(_i) \
+{ \
+ if ((_i) < linuxthreads_breakpoint_last) \
+ linuxthreads_breakpoint_zombie[(_i)] = \
+ linuxthreads_breakpoint_zombie[linuxthreads_breakpoint_last]; \
+ linuxthreads_breakpoint_last--; \
+}
+
+/* This should be part of the linuxthreads package */
+#define LINUXTHREAD_SIG_CANCEL 12 /* SIGUSR2 */
+#define LINUXTHREAD_SIG_EXIT 10 /* SIGUSR1 */
+#define LINUXTHREAD_NSIG _NSIG
+
+
+#ifndef PTRACE_XFER_TYPE
+#define PTRACE_XFER_TYPE int
+#endif
+
+#ifndef PT_STEP
+#define PT_STEP PTRACE_SINGLESTEP
+#endif
+
+#ifndef PT_KILL
+#define PT_KILL PTRACE_KILL
+#endif
+
+#ifndef PT_ATTACH
+#define PT_ATTACH PTRACE_ATTACH
+#endif
+
+#if defined PTRACE_PEEKUSER && !defined PTRACE_PEEKUSR
+#define PTRACE_PEEKUSR PTRACE_PEEKUSER
+#endif
+
+#ifndef PT_READ_U
+#define PT_READ_U PTRACE_PEEKUSR
+#endif
+
+/* Check to see if the given thread is alive. */
+static int
+linuxthreads_thread_alive (pid)
+ int pid;
+{
+ errno = 0;
+ return ptrace (PT_READ_U, pid, (PTRACE_ARG3_TYPE)0, 0) >= 0 || errno == 0;
+}
+
+/* On detach(), find a SIGTRAP status and optionally a SIGSTOP one. */
+static int
+linuxthreads_find_trap (pid, stop)
+ int pid;
+ int stop;
+{
+ int i;
+ int rpid;
+ int status;
+ int found_stop = 0;
+ int found_trap = 0;
+ int last = 0;
+ int *wstatus = alloca (LINUXTHREAD_NSIG * sizeof (int));
+
+ /* Look at the pending status */
+ for (i = linuxthreads_wait_last; i >= 0; i--)
+ if (linuxthreads_wait_pid[i] == pid)
+ {
+ status = linuxthreads_wait_status[i];
+ if (i < linuxthreads_wait_last)
+ {
+ linuxthreads_wait_status[i] =
+ linuxthreads_wait_status[linuxthreads_wait_last];
+ linuxthreads_wait_pid[i] =
+ linuxthreads_wait_pid[linuxthreads_wait_last];
+ }
+ linuxthreads_wait_last--;
+
+ if (!WIFSTOPPED(status)) /* Thread has died */
+ return 0;
+
+ if (WSTOPSIG(status) == SIGTRAP)
+ if (stop)
+ found_trap = 1;
+ else
+ return 1;
+ else if (WSTOPSIG(status) != SIGSTOP)
+ {
+ wstatus[0] = status;
+ last = 1;
+ }
+ else if (stop)
+ found_stop = 1;
+
+ break;
+ }
+
+ if (stop)
+ {
+ if (!found_trap)
+ kill (pid, SIGTRAP);
+ if (!found_stop)
+ kill (pid, SIGSTOP);
+ }
+
+ /* Catch all status until SIGTRAP and optionally SIGSTOP show up. */
+ for (;;)
+ {
+ child_resume (pid, 1, TARGET_SIGNAL_0);
+
+ for (;;)
+ {
+ rpid = waitpid (pid, &status, __WCLONE);
+ if (rpid > 0)
+ break;
+ if (errno == EINTR)
+ continue;
+
+ /* manager has died or pid is initial thread. */
+ rpid = waitpid (pid, &status, 0);
+ if (rpid > 0)
+ break;
+ if (errno != EINTR)
+ perror_with_name ("waitpid");
+ }
+
+ if (!WIFSTOPPED(status)) /* Thread has died */
+ return 0;
+
+ if (WSTOPSIG(status) == SIGTRAP)
+ if (!stop || found_stop)
+ break;
+ else
+ found_trap = 1;
+ else if (WSTOPSIG(status) != SIGSTOP)
+ wstatus[last++] = status;
+ else if (stop)
+ if (found_trap)
+ break;
+ else
+ found_stop = 1;
+ }
+
+ /* Resend all signals to the thread */
+ while (--last >= 0)
+ kill (pid, WSTOPSIG(wstatus[last]));
+
+ return 1;
+}
+
+static void
+restore_inferior_pid (pid)
+ int pid;
+{
+ inferior_pid = pid;
+}
+
+static struct cleanup *
+save_inferior_pid ()
+{
+ return make_cleanup (restore_inferior_pid, inferior_pid);
+}
+
+/* SIGCHLD handler */
+static void
+sigchld_handler(signo)
+ int signo;
+{
+ /* This handler is used to get an EINTR while doing waitpid()
+ when an event is received */
+}
+
+/* Does the process currently have a pending status ? */
+static int
+linuxthreads_pending_status (pid)
+ int pid;
+{
+ int i;
+ for (i = linuxthreads_wait_last; i >= 0; i--)
+ if (linuxthreads_wait_pid[i] == pid)
+ return 1;
+ return 0;
+}
+
+/* Walk through the linuxthreads handles in order to execute a function */
+static void
+iterate_active_threads (func, all)
+ void (*func)(int);
+ int all;
+{
+ CORE_ADDR descr;
+ int pid;
+ int i;
+ int num;
+
+ read_memory (linuxthreads_num, (char *)&num, sizeof (int));
+
+ for (i = 0; i < linuxthreads_max && num > 0; i++)
+ {
+ read_memory (linuxthreads_handles +
+ linuxthreads_sizeof_handle * i + linuxthreads_offset_descr,
+ (char *)&descr, sizeof (void *));
+ if (descr)
+ {
+ num--;
+ read_memory (descr + linuxthreads_offset_pid,
+ (char *)&pid, sizeof (pid_t));
+ if (pid > 0 && (all || (!linuxthreads_pending_status (pid))))
+ (*func)(pid);
+ }
+ }
+
+}
+
+/* Insert a thread breakpoint */
+static void
+insert_breakpoint (pid)
+ int pid;
+{
+ int j;
+
+ /* Remove (if any) the positive zombie breakpoint. */
+ for (j = linuxthreads_breakpoint_last; j >= 0; j--)
+ if (linuxthreads_breakpoint_zombie[j].pid == pid)
+ {
+ if ((linuxthreads_breakpoint_zombie[j].pc - DECR_PC_AFTER_BREAK
+ == linuxthreads_breakpoint_addr)
+ && !linuxthreads_breakpoint_zombie[j].step)
+ REMOVE_BREAKPOINT_ZOMBIE(j);
+ break;
+ }
+}
+
+/* Remove a thread breakpoint */
+static void
+remove_breakpoint (pid)
+ int pid;
+{
+ int j;
+
+ /* Insert a positive zombie breakpoint (if needed). */
+ for (j = 0; j <= linuxthreads_breakpoint_last; j++)
+ if (linuxthreads_breakpoint_zombie[j].pid == pid)
+ break;
+
+ if (in_thread_list (pid) && linuxthreads_thread_alive (pid))
+ {
+ CORE_ADDR pc = read_pc_pid (pid);
+ if (linuxthreads_breakpoint_addr == pc - DECR_PC_AFTER_BREAK
+ && j > linuxthreads_breakpoint_last)
+ {
+ linuxthreads_breakpoint_zombie[j].pid = pid;
+ linuxthreads_breakpoint_zombie[j].pc = pc;
+ linuxthreads_breakpoint_zombie[j].step = 0;
+ linuxthreads_breakpoint_last++;
+ }
+ }
+}
+
+/* Kill a thread */
+static void
+kill_thread (pid)
+ int pid;
+{
+ if (in_thread_list (pid))
+ ptrace (PT_KILL, pid, (PTRACE_ARG3_TYPE) 0, 0);
+ else
+ kill (pid, SIGKILL);
+}
+
+/* Resume a thread */
+static void
+resume_thread (pid)
+ int pid;
+{
+ if (pid != inferior_pid
+ && in_thread_list (pid)
+ && linuxthreads_thread_alive (pid))
+ if (pid == linuxthreads_step_pid)
+ child_resume (pid, 1, linuxthreads_step_signo);
+ else
+ child_resume (pid, 0, TARGET_SIGNAL_0);
+}
+
+/* Detach a thread */
+static void
+detach_thread (pid)
+ int pid;
+{
+ if (in_thread_list (pid) && linuxthreads_thread_alive (pid))
+ {
+ /* Remove pending SIGTRAP and SIGSTOP */
+ linuxthreads_find_trap (pid, 1);
+
+ inferior_pid = pid;
+ detach (TARGET_SIGNAL_0);
+ inferior_pid = linuxthreads_manager_pid;
+ }
+}
+
+/* Stop a thread */
+static void
+stop_thread (pid)
+ int pid;
+{
+ if (pid != inferior_pid)
+ if (in_thread_list (pid))
+ kill (pid, SIGSTOP);
+ else if (ptrace (PT_ATTACH, pid, (PTRACE_ARG3_TYPE) 0, 0) == 0)
+ {
+ if (!linuxthreads_attach_pending)
+ printf_unfiltered ("[New %s]\n", target_pid_to_str (pid));
+ add_thread (pid);
+ }
+}
+
+/* Wait for a thread */
+static void
+wait_thread (pid)
+ int pid;
+{
+ int status;
+ int rpid;
+
+ if (pid != inferior_pid && in_thread_list (pid))
+ {
+ for (;;)
+ {
+ /* Get first pid status. */
+ rpid = waitpid(pid, &status, __WCLONE);
+ if (rpid > 0)
+ break;
+ if (errno == EINTR)
+ continue;
+
+ /* manager has died or pid is initial thread. */
+ rpid = waitpid(pid, &status, 0);
+ if (rpid > 0)
+ break;
+ if (errno != EINTR && linuxthreads_thread_alive (pid))
+ perror_with_name ("waitpid");
+
+ /* the thread is dead. */
+ return;
+ }
+ if (!WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP)
+ {
+ linuxthreads_wait_pid[++linuxthreads_wait_last] = pid;
+ linuxthreads_wait_status[linuxthreads_wait_last] = status;
+ }
+ }
+}
+
+/* Walk through the linuxthreads handles in order to detect all
+ threads and stop them */
+static void
+update_stop_threads (test_pid)
+ int test_pid;
+{
+ struct cleanup *old_chain = NULL;
+
+ if (linuxthreads_manager_pid == 0)
+ {
+ if (linuxthreads_manager)
+ {
+ if (test_pid > 0 && test_pid != inferior_pid)
+ {
+ old_chain = save_inferior_pid ();
+ inferior_pid = test_pid;
+ }
+ read_memory (linuxthreads_manager,
+ (char *)&linuxthreads_manager_pid, sizeof (pid_t));
+ }
+ if (linuxthreads_initial)
+ {
+ if (test_pid > 0 && test_pid != inferior_pid)
+ {
+ old_chain = save_inferior_pid ();
+ inferior_pid = test_pid;
+ }
+ read_memory(linuxthreads_initial,
+ (char *)&linuxthreads_initial_pid, sizeof (pid_t));
+ }
+ }
+
+ if (linuxthreads_manager_pid != 0)
+ {
+ if (old_chain == NULL && test_pid > 0 &&
+ test_pid != inferior_pid && linuxthreads_thread_alive (test_pid))
+ {
+ old_chain = save_inferior_pid ();
+ inferior_pid = test_pid;
+ }
+
+ if (linuxthreads_thread_alive (inferior_pid))
+ {
+ if (test_pid > 0)
+ {
+ if (test_pid != linuxthreads_manager_pid
+ && !linuxthreads_pending_status (linuxthreads_manager_pid))
+ {
+ stop_thread (linuxthreads_manager_pid);
+ wait_thread (linuxthreads_manager_pid);
+ }
+ if (!in_thread_list (test_pid))
+ {
+ if (!linuxthreads_attach_pending)
+ printf_unfiltered ("[New %s]\n",
+ target_pid_to_str (test_pid));
+ add_thread (test_pid);
+ }
+ }
+ iterate_active_threads (stop_thread, 0);
+ iterate_active_threads (wait_thread, 0);
+ }
+ }
+
+ if (old_chain != NULL)
+ do_cleanups (old_chain);
+}
+
+/* Internal linuxthreads signal management */
+
+static void
+linuxthreads_signal_update (on)
+ int on;
+{
+ int sig_restart = target_signal_from_host(linuxthreads_sig_restart);
+ int sig_cancel = target_signal_from_host(linuxthreads_sig_cancel);
+
+ if (on)
+ {
+ linuxthreads_sig_restart_stop = signal_stop_update(sig_restart, 0);
+ linuxthreads_sig_restart_print = signal_print_update(sig_restart, 0);
+ if (linuxthreads_sig_restart_stop != 1 ||
+ linuxthreads_sig_restart_print != 1)
+ fprintf_unfiltered (gdb_stderr,
+ "Linux thread target has modified %s handling\n",
+ target_signal_to_string(sig_restart));
+
+ linuxthreads_sig_cancel_stop = signal_stop_update(sig_cancel, 0);
+ linuxthreads_sig_cancel_print = signal_print_update(sig_cancel, 0);
+ if (linuxthreads_sig_cancel_stop != 1 ||
+ linuxthreads_sig_cancel_print != 1)
+ fprintf_unfiltered (gdb_stderr,
+ "Linux thread target has modified %s handling\n",
+ target_signal_to_string(sig_cancel));
+ }
+ else
+ {
+ signal_stop_update(sig_restart, linuxthreads_sig_restart_stop);
+ signal_print_update(sig_restart, linuxthreads_sig_restart_print);
+ if (linuxthreads_sig_restart_stop != 1 ||
+ linuxthreads_sig_restart_print != 1)
+ fprintf_unfiltered (gdb_stderr,
+ "Linux thread target has restored %s handling\n",
+ target_signal_to_string(sig_restart));
+
+ signal_stop_update(sig_cancel, linuxthreads_sig_cancel_stop);
+ signal_print_update(sig_cancel, linuxthreads_sig_cancel_print);
+ if (linuxthreads_sig_cancel_stop != 1 ||
+ linuxthreads_sig_cancel_print != 1)
+ fprintf_unfiltered (gdb_stderr,
+ "Linux thread target has restored %s handling\n",
+ target_signal_to_string(sig_cancel));
+ }
+}
+
+/* This routine is called whenever a new symbol table is read in, or when all
+ symbol tables are removed. libpthread can only be initialized when it
+ finds the right variables in libpthread.so. Since it's a shared library,
+ those variables don't show up until the library gets mapped and the symbol
+ table is read in. */
+
+void
+linuxthreads_new_objfile (objfile)
+ struct objfile *objfile;
+{
+ struct minimal_symbol *ms;
+ struct sigaction sact;
+
+ if (!objfile || linuxthreads_max)
+ return;
+
+ if ((ms = lookup_minimal_symbol ("__pthread_threads_debug",
+ NULL, objfile)) == NULL)
+ {
+ /* The debugging-aware libpthreads is not present in this objfile */
+ return;
+ }
+ linuxthreads_debug = SYMBOL_VALUE_ADDRESS (ms);
+
+ /* Read internal structures configuration */
+ if ((ms = lookup_minimal_symbol ("__pthread_sizeof_handle",
+ NULL, objfile)) == NULL
+ || target_read_memory (SYMBOL_VALUE_ADDRESS (ms),
+ (char *)&linuxthreads_sizeof_handle,
+ sizeof (linuxthreads_sizeof_handle)) != 0)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Unable to find linuxthreads symbol \"%s\"\n",
+ "__pthread_sizeof_handle");
+ return;
+ }
+
+ if ((ms = lookup_minimal_symbol ("__pthread_offsetof_descr",
+ NULL, objfile)) == NULL
+ || target_read_memory (SYMBOL_VALUE_ADDRESS (ms),
+ (char *)&linuxthreads_offset_descr,
+ sizeof (linuxthreads_offset_descr)) != 0)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Unable to find linuxthreads symbol \"%s\"\n",
+ "__pthread_offsetof_descr");
+ return;
+ }
+
+ if ((ms = lookup_minimal_symbol ("__pthread_offsetof_pid",
+ NULL, objfile)) == NULL
+ || target_read_memory (SYMBOL_VALUE_ADDRESS (ms),
+ (char *)&linuxthreads_offset_pid,
+ sizeof (linuxthreads_offset_pid)) != 0)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Unable to find linuxthreads symbol \"%s\"\n",
+ "__pthread_offsetof_pid");
+ return;
+ }
+
+ if ((ms = lookup_minimal_symbol ("__pthread_sig_restart",
+ NULL, objfile)) == NULL
+ || target_read_memory (SYMBOL_VALUE_ADDRESS (ms),
+ (char *)&linuxthreads_sig_restart,
+ sizeof (linuxthreads_sig_restart)) != 0)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Unable to find linuxthreads symbol \"%s\"\n",
+ "__pthread_sig_restart");
+ return;
+ }
+
+ if ((ms = lookup_minimal_symbol ("__pthread_sig_cancel",
+ NULL, objfile)) == NULL
+ || target_read_memory (SYMBOL_VALUE_ADDRESS (ms),
+ (char *)&linuxthreads_sig_cancel,
+ sizeof (linuxthreads_sig_cancel)) != 0)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Unable to find linuxthreads symbol \"%s\"\n",
+ "__pthread_sig_cancel");
+ return;
+ }
+
+ if ((ms = lookup_minimal_symbol ("__pthread_threads_max",
+ NULL, objfile)) == NULL
+ || target_read_memory (SYMBOL_VALUE_ADDRESS (ms),
+ (char *)&linuxthreads_max,
+ sizeof (linuxthreads_max)) != 0)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Unable to find linuxthreads symbol \"%s\"\n",
+ "__pthread_threads_max");
+ return;
+ }
+
+ /* Read adresses of internal structures to access */
+ if ((ms = lookup_minimal_symbol ("__pthread_handles",
+ NULL, objfile)) == NULL)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Unable to find linuxthreads symbol \"%s\"\n",
+ "__pthread_handles");
+ return;
+ }
+ linuxthreads_handles = SYMBOL_VALUE_ADDRESS (ms);
+
+ if ((ms = lookup_minimal_symbol ("__pthread_handles_num",
+ NULL, objfile)) == NULL)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Unable to find linuxthreads symbol \"%s\"\n",
+ "__pthread_handles_num");
+ return;
+ }
+ linuxthreads_num = SYMBOL_VALUE_ADDRESS (ms);
+
+ if ((ms = lookup_minimal_symbol ("__pthread_manager_thread",
+ NULL, objfile)) == NULL)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Unable to find linuxthreads symbol \"%s\"\n",
+ "__pthread_manager_thread");
+ return;
+ }
+ linuxthreads_manager = SYMBOL_VALUE_ADDRESS (ms) + linuxthreads_offset_pid;
+
+ if ((ms = lookup_minimal_symbol ("__pthread_initial_thread",
+ NULL, objfile)) == NULL)
+ {
+ fprintf_unfiltered (gdb_stderr,
+ "Unable to find linuxthreads symbol \"%s\"\n",
+ "__pthread_initial_thread");
+ return;
+ }
+ linuxthreads_initial = SYMBOL_VALUE_ADDRESS (ms) + linuxthreads_offset_pid;
+
+ /* Allocate gdb internal structures */
+ linuxthreads_wait_pid =
+ (int *)xmalloc (sizeof (int) * (linuxthreads_max + 1));
+ linuxthreads_wait_status =
+ (int *)xmalloc (sizeof (int) * (linuxthreads_max + 1));
+ linuxthreads_breakpoint_zombie = (struct linuxthreads_breakpoint *)
+ xmalloc (sizeof (struct linuxthreads_breakpoint) * (linuxthreads_max + 1));
+
+ /* handle linuxthread exit */
+ sact.sa_handler = sigchld_handler;
+ sigemptyset(&sact.sa_mask);
+ sact.sa_flags = 0;
+ sigaction(linuxthreads_sig_restart, &sact, NULL);
+
+ if (inferior_pid && !linuxthreads_attach_pending)
+ {
+ int on = 1;
+ target_write_memory (linuxthreads_debug, (char *)&on, sizeof (on));
+ linuxthreads_attach_pending = 1;
+ linuxthreads_signal_update (1);
+ update_stop_threads (inferior_pid);
+ linuxthreads_attach_pending = 0;
+ }
+}
+
+/* If we have switched threads from a one that stopped at breakpoint,
+ return 1 otherwise 0. */
+
+int
+linuxthreads_prepare_to_proceed (step)
+ int step;
+{
+ if (!linuxthreads_max
+ || !linuxthreads_manager_pid
+ || !linuxthreads_breakpoint_pid
+ || !breakpoint_here_p (read_pc_pid (linuxthreads_breakpoint_pid)))
+ return 0;
+
+ if (step)
+ {
+ /* Mark the current inferior as single stepping process. */
+ linuxthreads_step_pid = inferior_pid;
+ }
+
+ linuxthreads_inferior_pid = linuxthreads_breakpoint_pid;
+ return linuxthreads_breakpoint_pid;
+}
+
+/* Convert a pid to printable form. */
+
+char *
+linuxthreads_pid_to_str (pid)
+ int pid;
+{
+ static char buf[100];
+
+ sprintf (buf, "%s %d", linuxthreads_max ? "Thread" : "Pid", pid);
+
+ return buf;
+}
+
+/* Attach to process PID, then initialize for debugging it
+ and wait for the trace-trap that results from attaching. */
+
+static void
+linuxthreads_attach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ push_target (&linuxthreads_ops);
+ linuxthreads_breakpoints_inserted = 1;
+ linuxthreads_breakpoint_last = -1;
+ linuxthreads_wait_last = -1;
+ linuxthreads_exit_status = __W_STOPCODE(0);
+
+ child_ops.to_attach (args, from_tty);
+
+ if (linuxthreads_max)
+ linuxthreads_attach_pending = 1;
+}
+
+/* Take a program previously attached to and detaches it.
+ The program resumes execution and will no longer stop
+ on signals, etc. We'd better not have left any breakpoints
+ in the program or it'll die when it hits one. For this
+ to work, it may be necessary for the process to have been
+ previously attached. It *might* work if the program was
+ started via the normal ptrace (PTRACE_TRACEME). */
+
+static void
+linuxthreads_detach (args, from_tty)
+ char *args;
+ int from_tty;
+{
+ if (linuxthreads_max)
+ {
+ int i;
+ int pid;
+ int off = 0;
+ target_write_memory (linuxthreads_debug, (char *)&off, sizeof (off));
+
+ /* Walk through linuxthreads array in order to detach known threads. */
+ if (linuxthreads_manager_pid != 0)
+ {
+ /* Get rid of all positive zombie breakpoints. */
+ for (i = 0; i <= linuxthreads_breakpoint_last; i++)
+ {
+ if (linuxthreads_breakpoint_zombie[i].step)
+ continue;
+
+ pid = linuxthreads_breakpoint_zombie[i].pid;
+ if (!linuxthreads_thread_alive (pid))
+ continue;
+
+ if (linuxthreads_breakpoint_zombie[i].pc != read_pc_pid (pid))
+ continue;
+
+ /* Continue in STEP mode until the thread pc has moved or
+ until SIGTRAP is found on the same PC. */
+ if (linuxthreads_find_trap (pid, 0)
+ && linuxthreads_breakpoint_zombie[i].pc == read_pc_pid (pid))
+ write_pc_pid (linuxthreads_breakpoint_zombie[i].pc
+ - DECR_PC_AFTER_BREAK, pid);
+ }
+
+ /* Detach thread after thread. */
+ inferior_pid = linuxthreads_manager_pid;
+ iterate_active_threads (detach_thread, 1);
+
+ /* Remove pending SIGTRAP and SIGSTOP */
+ linuxthreads_find_trap (inferior_pid, 1);
+
+ linuxthreads_wait_last = -1;
+ linuxthreads_exit_status = __W_STOPCODE(0);
+ }
+
+ linuxthreads_inferior_pid = 0;
+ linuxthreads_breakpoint_pid = 0;
+ linuxthreads_step_pid = 0;
+ linuxthreads_step_signo = TARGET_SIGNAL_0;
+ linuxthreads_manager_pid = 0;
+ linuxthreads_initial_pid = 0;
+ linuxthreads_attach_pending = 0;
+ linuxthreads_signal_update (0);
+ init_thread_list (); /* Destroy thread info */
+ }
+
+ child_ops.to_detach (args, from_tty);
+
+ unpush_target (&linuxthreads_ops);
+}
+
+/* Resume execution of process PID. If STEP is nozero, then
+ just single step it. If SIGNAL is nonzero, restart it with that
+ signal activated. */
+
+static void
+linuxthreads_resume (pid, step, signo)
+ int pid;
+ int step;
+ enum target_signal signo;
+{
+ if (!linuxthreads_max || stop_soon_quietly || linuxthreads_manager_pid == 0)
+ child_ops.to_resume (pid, step, signo);
+ else
+ {
+ int rpid;
+ if (linuxthreads_inferior_pid)
+ {
+ /* Prepare resume of the last thread that hit a breakpoint */
+ linuxthreads_breakpoints_inserted = 0;
+ rpid = linuxthreads_inferior_pid;
+ linuxthreads_step_signo = signo;
+ }
+ else
+ {
+ struct cleanup *old_chain = NULL;
+ int i;
+
+ if (pid < 0)
+ {
+ linuxthreads_step_pid = step ? inferior_pid : 0;
+ linuxthreads_step_signo = signo;
+ rpid = inferior_pid;
+ }
+ else
+ rpid = pid;
+
+ if (pid < 0 || !step)
+ {
+ linuxthreads_breakpoints_inserted = 1;
+
+ /* Walk through linuxthreads array in order to resume threads */
+ if (pid >= 0 && inferior_pid != pid)
+ {
+ old_chain = save_inferior_pid ();
+ inferior_pid = pid;
+ }
+
+ iterate_active_threads (resume_thread, 0);
+ if (linuxthreads_manager_pid != inferior_pid
+ && !linuxthreads_pending_status (linuxthreads_manager_pid))
+ resume_thread (linuxthreads_manager_pid);
+ }
+ else
+ linuxthreads_breakpoints_inserted = 0;
+
+ /* Deal with zombie breakpoint */
+ for (i = 0; i <= linuxthreads_breakpoint_last; i++)
+ if (linuxthreads_breakpoint_zombie[i].pid == rpid)
+ {
+ if (linuxthreads_breakpoint_zombie[i].pc != read_pc_pid (rpid))
+ {
+ /* The current pc is out of zombie breakpoint. */
+ REMOVE_BREAKPOINT_ZOMBIE(i);
+ }
+ break;
+ }
+
+ if (old_chain != NULL)
+ do_cleanups (old_chain);
+ }
+
+ /* Resume initial thread. */
+ if (!linuxthreads_pending_status (rpid))
+ child_ops.to_resume (rpid, step, signo);
+ }
+}
+
+/* Wait for any threads to stop. We may have to convert PID from a thread id
+ to a LWP id, and vice versa on the way out. */
+
+static int
+linuxthreads_wait (pid, ourstatus)
+ int pid;
+ struct target_waitstatus *ourstatus;
+{
+ int status;
+ int rpid;
+ int i;
+ int last;
+ int *wstatus;
+
+ for (;;)
+ {
+ if (!linuxthreads_max)
+ rpid = 0;
+ else if (!linuxthreads_breakpoints_inserted)
+ {
+ if (linuxthreads_inferior_pid)
+ pid = linuxthreads_inferior_pid;
+ else if (pid < 0)
+ pid = inferior_pid;
+ last = rpid = 0;
+ wstatus = alloca (LINUXTHREAD_NSIG * sizeof (int));
+ }
+ else if (pid < 0 && linuxthreads_wait_last >= 0)
+ {
+ status = linuxthreads_wait_status[linuxthreads_wait_last];
+ rpid = linuxthreads_wait_pid[linuxthreads_wait_last--];
+ }
+ else if (pid > 0 && linuxthreads_pending_status (pid))
+ {
+ for (i = linuxthreads_wait_last; i >= 0; i--)
+ if (linuxthreads_wait_pid[i] == pid)
+ break;
+ if (i < 0)
+ rpid = 0;
+ else
+ {
+ status = linuxthreads_wait_status[i];
+ rpid = pid;
+ if (i < linuxthreads_wait_last)
+ {
+ linuxthreads_wait_status[i] =
+ linuxthreads_wait_status[linuxthreads_wait_last];
+ linuxthreads_wait_pid[i] =
+ linuxthreads_wait_pid[linuxthreads_wait_last];
+ }
+ linuxthreads_wait_last--;
+ }
+ }
+ else
+ rpid = 0;
+
+ if (rpid == 0)
+ {
+ int save_errno;
+ sigset_t omask;
+
+ set_sigint_trap(); /* Causes SIGINT to be passed on to the
+ attached process. */
+ set_sigio_trap ();
+
+ sigprocmask(SIG_BLOCK, &linuxthreads_wait_mask, &omask);
+ for (;;)
+ {
+ rpid = waitpid (pid, &status, __WCLONE | WNOHANG);
+ if (rpid > 0)
+ break;
+ if (rpid == 0)
+ save_errno = 0;
+ else if (errno != EINTR)
+ save_errno = errno;
+ else
+ continue;
+
+ rpid = waitpid (pid, &status, WNOHANG);
+ if (rpid > 0)
+ break;
+ if (rpid < 0)
+ if (errno == EINTR)
+ continue;
+ else if (save_errno != 0)
+ break;
+
+ sigsuspend(&omask);
+ }
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ save_errno = errno;
+ clear_sigio_trap ();
+
+ clear_sigint_trap();
+
+ if (rpid == -1)
+ {
+ if (WIFEXITED(linuxthreads_exit_status))
+ {
+ store_waitstatus (ourstatus, linuxthreads_exit_status);
+ return inferior_pid;
+ }
+ else
+ {
+ fprintf_unfiltered
+ (gdb_stderr, "Child process unexpectedly missing: %s.\n",
+ safe_strerror (save_errno));
+ /* Claim it exited with unknown signal. */
+ ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
+ ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+ return -1;
+ }
+ }
+
+ /* Signals arrive in any order. So get all signals until SIGTRAP
+ and resend previous ones to be held after. */
+ if (linuxthreads_max
+ && !linuxthreads_breakpoints_inserted
+ && WIFSTOPPED(status))
+ if (WSTOPSIG(status) == SIGTRAP)
+ {
+ while (--last >= 0)
+ kill (rpid, WSTOPSIG(wstatus[last]));
+
+ /* insert negative zombie breakpoint */
+ for (i = 0; i <= linuxthreads_breakpoint_last; i++)
+ if (linuxthreads_breakpoint_zombie[i].pid == rpid)
+ break;
+ if (i > linuxthreads_breakpoint_last)
+ {
+ linuxthreads_breakpoint_zombie[i].pid = rpid;
+ linuxthreads_breakpoint_last++;
+ }
+ linuxthreads_breakpoint_zombie[i].pc = read_pc_pid (rpid);
+ linuxthreads_breakpoint_zombie[i].step = 1;
+ }
+ else
+ {
+ if (WSTOPSIG(status) != SIGSTOP)
+ {
+ for (i = 0; i < last; i++)
+ if (wstatus[i] == status)
+ break;
+ if (i >= last)
+ wstatus[last++] = status;
+ }
+ child_resume (rpid, 1, TARGET_SIGNAL_0);
+ continue;
+ }
+ if (linuxthreads_inferior_pid)
+ linuxthreads_inferior_pid = 0;
+ }
+
+ if (linuxthreads_max && !stop_soon_quietly)
+ {
+ if (linuxthreads_max
+ && WIFSTOPPED(status)
+ && WSTOPSIG(status) == SIGSTOP)
+ {
+ /* Skip SIGSTOP signals. */
+ if (!linuxthreads_pending_status (rpid))
+ if (linuxthreads_step_pid == rpid)
+ child_resume (rpid, 1, linuxthreads_step_signo);
+ else
+ child_resume (rpid, 0, TARGET_SIGNAL_0);
+ continue;
+ }
+
+ /* Do no report exit status of cloned threads. */
+ if (WIFEXITED(status))
+ {
+ if (rpid == linuxthreads_initial_pid)
+ linuxthreads_exit_status = status;
+
+ /* Remove any zombie breakpoint. */
+ for (i = 0; i <= linuxthreads_breakpoint_last; i++)
+ if (linuxthreads_breakpoint_zombie[i].pid == rpid)
+ {
+ REMOVE_BREAKPOINT_ZOMBIE(i);
+ break;
+ }
+ if (pid > 0)
+ pid = -1;
+ continue;
+ }
+
+ /* Deal with zombie breakpoint */
+ for (i = 0; i <= linuxthreads_breakpoint_last; i++)
+ if (linuxthreads_breakpoint_zombie[i].pid == rpid)
+ break;
+
+ if (i <= linuxthreads_breakpoint_last)
+ {
+ /* There is a potential zombie breakpoint */
+ if (WIFEXITED(status)
+ || linuxthreads_breakpoint_zombie[i].pc != read_pc_pid (rpid))
+ {
+ /* The current pc is out of zombie breakpoint. */
+ REMOVE_BREAKPOINT_ZOMBIE(i);
+ }
+ else if (!linuxthreads_breakpoint_zombie[i].step
+ && WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP)
+ {
+ /* This is a real one ==> decrement PC and restart. */
+ write_pc_pid (linuxthreads_breakpoint_zombie[i].pc
+ - DECR_PC_AFTER_BREAK, rpid);
+ if (linuxthreads_step_pid == rpid)
+ child_resume (rpid, 1, linuxthreads_step_signo);
+ else
+ child_resume (rpid, 0, TARGET_SIGNAL_0);
+ continue;
+ }
+ }
+
+ /* Walk through linuxthreads array in order to stop them */
+ if (linuxthreads_breakpoints_inserted)
+ update_stop_threads (rpid);
+
+ }
+ else if (rpid != inferior_pid)
+ continue;
+
+ store_waitstatus (ourstatus, status);
+
+ if (linuxthreads_attach_pending && !stop_soon_quietly)
+ {
+ int on = 1;
+ target_write_memory (linuxthreads_debug, (char *)&on, sizeof (on));
+ update_stop_threads (rpid);
+ linuxthreads_signal_update (1);
+ linuxthreads_attach_pending = 0;
+ }
+
+ if (linuxthreads_breakpoints_inserted
+ && WIFSTOPPED(status)
+ && WSTOPSIG(status) == SIGTRAP)
+ linuxthreads_breakpoint_pid = rpid;
+ else if (linuxthreads_breakpoint_pid)
+ linuxthreads_breakpoint_pid = 0;
+
+ return rpid;
+ }
+}
+
+/* Fork an inferior process, and start debugging it with ptrace. */
+
+static void
+linuxthreads_create_inferior (exec_file, allargs, env)
+ char *exec_file;
+ char *allargs;
+ char **env;
+{
+ push_target (&linuxthreads_ops);
+ linuxthreads_breakpoints_inserted = 1;
+ linuxthreads_breakpoint_last = -1;
+ linuxthreads_wait_last = -1;
+ linuxthreads_exit_status = __W_STOPCODE(0);
+
+ if (linuxthreads_max)
+ linuxthreads_attach_pending = 1;
+
+ child_ops.to_create_inferior (exec_file, allargs, env);
+}
+
+/* Clean up after the inferior dies. */
+
+static void
+linuxthreads_mourn_inferior ()
+{
+ if (linuxthreads_max)
+ {
+ int off = 0;
+ target_write_memory (linuxthreads_debug, (char *)&off, sizeof (off));
+
+ linuxthreads_inferior_pid = 0;
+ linuxthreads_breakpoint_pid = 0;
+ linuxthreads_step_pid = 0;
+ linuxthreads_step_signo = TARGET_SIGNAL_0;
+ linuxthreads_manager_pid = 0;
+ linuxthreads_initial_pid = 0;
+ linuxthreads_attach_pending = 0;
+ init_thread_list(); /* Destroy thread info */
+ linuxthreads_signal_update (0);
+ }
+
+ child_ops.to_mourn_inferior ();
+
+ unpush_target (&linuxthreads_ops);
+}
+
+/* Kill the inferior process */
+
+static void
+linuxthreads_kill ()
+{
+ int rpid;
+ int status;
+
+ if (inferior_pid == 0)
+ return;
+
+ if (linuxthreads_max && linuxthreads_manager_pid != 0)
+ {
+ /* Remove all threads status. */
+ inferior_pid = linuxthreads_manager_pid;
+ iterate_active_threads (kill_thread, 1);
+ }
+
+ kill_thread (inferior_pid);
+
+ if (linuxthreads_max && linuxthreads_manager_pid != 0)
+ {
+ /* Wait for thread to complete */
+ while ((rpid = waitpid (-1, &status, __WCLONE)) > 0)
+ if (!WIFEXITED(status))
+ kill_thread (rpid);
+
+ while ((rpid = waitpid (-1, &status, 0)) > 0)
+ if (!WIFEXITED(status))
+ kill_thread (rpid);
+ }
+ else
+ while ((rpid = waitpid (inferior_pid, &status, 0)) > 0)
+ if (!WIFEXITED(status))
+ ptrace (PT_KILL, inferior_pid, (PTRACE_ARG3_TYPE) 0, 0);
+
+ linuxthreads_mourn_inferior ();
+}
+
+/* Insert a breakpoint */
+
+static int
+linuxthreads_insert_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ if (linuxthreads_max && linuxthreads_manager_pid != 0)
+ {
+ linuxthreads_breakpoint_addr = addr;
+ iterate_active_threads (insert_breakpoint, 1);
+ insert_breakpoint (linuxthreads_manager_pid);
+ }
+
+ return child_ops.to_insert_breakpoint (addr, contents_cache);
+}
+
+/* Remove a breakpoint */
+
+static int
+linuxthreads_remove_breakpoint (addr, contents_cache)
+ CORE_ADDR addr;
+ char *contents_cache;
+{
+ if (linuxthreads_max && linuxthreads_manager_pid != 0)
+ {
+ linuxthreads_breakpoint_addr = addr;
+ iterate_active_threads (remove_breakpoint, 1);
+ remove_breakpoint (linuxthreads_manager_pid);
+ }
+
+ return child_ops.to_remove_breakpoint (addr, contents_cache);
+}
+
+/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
+
+static int
+linuxthreads_can_run ()
+{
+ return child_suppress_run;
+}
+
+struct target_ops linuxthreads_ops = {
+ "linuxthreads", /* to_shortname */
+ "LINUX threads and pthread.", /* to_longname */
+ "LINUX threads and pthread support.", /* to_doc */
+ 0, /* to_open */
+ 0, /* to_close */
+ linuxthreads_attach, /* to_attach */
+ linuxthreads_detach, /* to_detach */
+ linuxthreads_resume, /* to_resume */
+ linuxthreads_wait, /* to_wait */
+ 0, /* to_fetch_registers */
+ 0, /* to_store_registers */
+ 0, /* to_prepare_to_store */
+ 0, /* to_xfer_memory */
+ 0, /* to_files_info */
+ linuxthreads_insert_breakpoint, /* to_insert_breakpoint */
+ linuxthreads_remove_breakpoint, /* to_remove_breakpoint */
+ 0, /* to_terminal_init */
+ 0, /* to_terminal_inferior */
+ 0, /* to_terminal_ours_for_output */
+ 0, /* to_terminal_ours */
+ 0, /* to_terminal_info */
+ linuxthreads_kill, /* to_kill */
+ 0, /* to_load */
+ 0, /* to_lookup_symbol */
+ linuxthreads_create_inferior, /* to_create_inferior */
+ linuxthreads_mourn_inferior, /* to_mourn_inferior */
+ linuxthreads_can_run, /* to_can_run */
+ 0, /* to_notice_signals */
+ linuxthreads_thread_alive, /* to_thread_alive */
+ 0, /* to_stop */
+ thread_stratum, /* to_stratum */
+ 0, /* to_next */
+ 0, /* to_has_all_memory */
+ 0, /* to_has_memory */
+ 1, /* to_has_stack */
+ 1, /* to_has_registers */
+ 1, /* to_has_execution */
+ 0, /* sections */
+ 0, /* sections_end */
+ OPS_MAGIC /* to_magic */
+};
+
+void
+_initialize_linuxthreads ()
+{
+ struct sigaction sact;
+
+ add_target (&linuxthreads_ops);
+ child_suppress_run = 1;
+
+ /* Attach SIGCHLD handler */
+ sact.sa_handler = sigchld_handler;
+ sigemptyset(&sact.sa_mask);
+ sact.sa_flags = 0;
+ sigaction(SIGCHLD, &sact, NULL);
+
+ /* initialize SIGCHLD mask */
+ sigemptyset(&linuxthreads_wait_mask);
+ sigaddset(&linuxthreads_wait_mask, SIGCHLD);
+}
diff -urNp gdb-4.17-ORIG/gdb/m3-nat.c gdb-4.17/gdb/m3-nat.c
--- gdb-4.17-ORIG/gdb/m3-nat.c Mon May 6 14:27:04 1996
+++ gdb-4.17/gdb/m3-nat.c Fri Nov 13 22:31:40 1998
@@ -1,7 +1,7 @@
/* Interface GDB to Mach 3.0 operating systems.
(Most) Mach 3.0 related routines live in this file.
-mach3_prepare_to_proceed (select_it)
- int select_it;
+mach3_prepare_to_proceed (step)
+ int step;
{
- if (stop_thread &&
+ if (!step &&
+ stop_thread &&
stop_thread != current_thread &&
stop_exception == EXC_BREAKPOINT)
{
- int mid;
-
- if (! select_it)
- return 1;
-
- mid = switch_to_thread (stop_thread);
-
- return 1;
+ switch_to_thread (stop_thread);
+ if (breakpoint_here_p (read_pc ()))
+ return inferior_pid;
}
return 0;
diff -urNp gdb-4.17-ORIG/gdb/target.h gdb-4.17/gdb/target.h
--- gdb-4.17-ORIG/gdb/target.h Wed May 7 18:00:40 1997
+++ gdb-4.17/gdb/target.h Fri Nov 13 22:31:40 1998
@@ -1,5 +1,5 @@
/* Interface between GDB and target environments, including files and processes
- Copyright 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+ Copyright 1990, 1991, 1992, 1993, 1994, 1998 Free Software Foundation, Inc.
Contributed by Cygnus Support. Written by John Gilmore.
This file is part of GDB.
@@ -47,7 +47,8 @@ enum strata {
file_stratum, /* Executable files, etc */
core_stratum, /* Core dump files */
download_stratum, /* Downloading of remote targets */
- process_stratum /* Executing processes */
+ process_stratum, /* Executing processes */
+ thread_stratum /* Executing threads */
};
About MpegTV
MpegTV Products
Ce serveur présente une vidéo temps-réel à partir d'une caméra placée rue Condillac, en plein
centre de Bordeaux, dans les locaux de la société Atlantel Multimédia. Ce n'est pas une vidéo
lue à partir d'un fichier. Si vous regardez en haut à gauche de l'image, vous pourrez voir les
secondes défiler...
Ce service utilise la bibliothèque LinuxThreads sur RedHat LINUX
Si votre navigateur n'est pas compatible JAVA, la visualisation de cette page nécessite
l'installation du plug-in VCR/VCO disponible gratuitement en cliquant ici.
This Web site presents a real time video from a camera located rue Condillac in the main center
of Bordeaux (France). The server is hosted by the Atlantel Multimédia company. This video is
not extracted from a recorded file. If you take a look at the clock at the right up part of the
video, you should see the local time running...
This service uses the LinuxThreads library running on RedHat LINUX
If you browser is not JAVA compatible, this page needs the VCR/VCO plugin, click here to
download it for free.
For information about this technology, contact Pierre Ficheux or Jean-Sébastien Suze.
Download | Status | Bookstore | News and Distribution | Documentation | Products
Bug Reporting | About Us | Site Mirrors
Troubleshooting Contributing to
FAQ. Kaffe:
Develop new
Frequently asked questions Kaffe
components.
about Kaffe licensing.
Port Kaffe to
This covers the relationship new platforms.
between Kaffe and
Transvirtual Technologies
Mailing lists:
and should answer any
questions you have about How to subscribe to
Kaffe's copyright. Kaffe's mailing lists;
How to access the
mailing list archive.
Related projects
For Technical reports and preprints related to the PART project see our public ftp site.
Lynx2-8-3
This page contains links to the April 23, 2000 Lynx v2.8.3 release. This supersedes Lynx v2.8.2.
See: Lynx links for a complete list of distribution sites.
The following v2.8.3 files are available for downloading:
CHANGES - changes made since version 2-8
INSTALLATION - how to configure, build and install Lynx
lynx2-8-3.zip - the distribution file
lynx2-8-3.zip-lst - a list of files in the zip file
lynx2-8-3.tar.Z - the distribution in compressed tar format
lynx2-8-3.tar.gz - the distribution in gzip'd tar format
lynx2-8-3.tar.bz2 - the distribution in bzip2'd tar format
lynx-2.8.3.tar.gz - the distribution with available international message catalogs
lynx2-8-3/ - a v2.8.3 breakout
po/ - message libraries
New features in this release
SSL support for this release
Bug fixes for this release
Get zip/unzip from: ftp://ftp.cdrom.com/pub/infozip
Get gzip from: ftp://ftp.gnu.org/pub/gnu/
Get bzip2 from: http://www.muraroa.demon.co.uk/
Lynx for Win32 is available at http://www.shonai-cit.ac.jp/eci/senshu/
Other versions of Lynx for DOS386+ and Win32 can be found on
http://www.fdisk.com/doslynx/lynxport.htm
If you prefer downloading by FTP, use the following links instead, or use anonymous FTP to
'lynx.isc.org' and 'cd lynx-2.8.3' to find these files (or use this link to see all the files from
an FTP directory listing):
CHANGES - changes made since version 2-8
INSTALLATION - how to configure, build and install Lynx
lynx2-8-3.zip - the distribution file
lynx2-8-3.zip-lst - a list of files in the zip file
lynx2-8-3.tar.Z - the distribution compressed tar format
lynx2-8-3.tar.gz - the distribution in gzip'd tar format
lynx2-8-3.tar.bz2 - the distribution in bzip2'd tar format
lynx-2.8.3.tar.gz - the distribution with available international message catalogs
lynx2-8-3 - a v2.8.3 breakout
po - message libraries
New features in this release
SSL support for this release
Bug fixes for this release
http://lynx.isc.org/lynx-2.8.3/index.html
Page maintained by Thomas Dickey ([email protected])
& James Spath ([email protected]).
Copyright(c) 2000, Thomas Dickey.
Last Updated: 2001-01-31 Valid HTML! Re-validate
This directory contains archive copies of the most recent Lynx development source code. We
are currently working on Lynx 2.8.4.
Mirror sites
For the latest stable release and other help, see http://lynx.browser.org/. For DOS386/Win32
binaries, see below.
The development version also has a breakout subdirectory.
Current version
● (zip): lynx-cur.zip
● (tar.gz): lynx-cur.tgz
● (tar.bz2): lynx-cur.bz2
Version-level Patches
Important Documents
DOS/Win32
A release of Lynx 2.8.4 (dev10 or higher) is available from:
http://www.shonai-cit.ac.jp/eci/senshu/ Note it is compiled for Japanese.
A different release of Lynx and pointers to Lynx for DOS386+ and Win32 are available from:
http://www.fdisk.com/doslynx/lynxport.htm
A release of Lynx built for Win32 with Borland may be found via:
http://www.jim.spath.com/lynx_win32/
Table of Contents
Getting Lynx sources and binaries
The latest release is Lynx version 2.8.3 Some details concerning Lynx 2.8.3 (including new
features) are explored on the release page. Lynx 2.8.3 is distributed under the GNU Public
License. The Lynx Source distribution page has links to sites which carry the Lynx source code
(SSL/https info here). The LYnx BInary Distribution Outlet (LYBIDO) lists Lynx binaries
(.exe's) made available to lynx users.
● Lynx-Dev archives:
❍ http://www.flora.org/lynx-dev/
[ToC]
Search engines:
● AltaVista
● Excite
● Inference Find
● Infoseek
● Lycos
● MetaCrawler
● Savvy Search
● WebCrawler
● Yahoo!
int
main(int argc, char* argv[])
{
printf ("hello world\n");
return 0;
}
#include <iostream.h>
int
main(int argc, char* argv[])
{
cout << "hello world" << endl;
return 0;
}
#include <stdio.h>
int
main(int argc, char* argv[])
{
int a = func_a();
int b = func_b();
char c;
char* bc = &c;
printf("hello world,\n");
printf("a - %d; b - %d;\n", a, b);
return 0;
}
int
func_a()
{
return 5;
}
int
func_b()
{
return 10 * 10;
}
Index of
/~choo/lupg/tutorials/c-on-unix/multi-source
● Parent Directory
● a.c
● b.c
● main.c
#include <stdio.h>
int
main(int argc, char* argv[])
{
int i;
return 0;
}
/*
* stdc-file-copy.c - copy one file to a new location, possibly under a
* different name.
*/
/*
* function: main. copy the given source file to the given target file.
* input: path to source file and path to target file.
* output: target file is being created with identical contents to
* source file.
*/
void
main(int argc, char* argv[])
{
char* file_path_from; /* path to source file. */
char* file_path_to; /* path to target file. */
FILE* f_from; /* stream of source file. */
FILE* f_to; /* stream of target file. */
char buf[MAX_LINE_LEN+1]; /* input buffer. */
/*
* function: get_record. Reads a record from the given file.
* input: pointer to file stream, number of record in file (0 is
* the first record), and a pointer to a buffer.
* output: '1' on success, '0' on failure. In case of success, the record
* is copied to the supplied buffer.
*/
int
get_record(FILE* file, long record_num, char* buf)
{
long file_pos; /* stores the original read/write pointer position. */
int success = 0; /* success/failure indicator. assume failure here. */
/* sanity checks */
if (!file || record_num < 0 || !buf) {
return 0;
}
return success;
}
/*
* function: put_record. Writes a record to the given file.
* input: pointer to file stream, number of the record in file (0 is
* the first record) and a pointer to a buffer containing the
* data to be written.
* output: '1' on success, '0' on failure.
*/
int
put_record(FILE* file, long record_num, char* buf)
{
long file_pos; /* stores the original read/write pointer position. */
int success = 0; /* success/failure indicator. assume failure here. */
/* sanity checks */
if (!file || record_num < 0 || !buf) {
return 0;
}
return success;
}
/*
* function: main. write and read some records to/from a file.
* input: none.
* output: none.
*/
void
main()
{
char* file_name = "small_db.data";
char buf[RECORD_LEN];
FILE* db_file;
if (fclose(db_file) == EOF) {
perror("fclose");
exit(1);
}
}
/*
* read-access-check.c - check if the user has read permission to a given
* file. If not, check where the problem lies.
*
* Background: In order to read from a file, we must have execute permission
* in all directories leading to this file, as well as read access
* to the file itself. For example, to read from file
* "/etc/config/blabla.conf", we must have X permission on '/etc'
* and on '/etc/config', as well as R permission on
* "/etc/config/blabla.conf" itself.
*
* Algorithm: split the file path to its directories, make sure the directory
* exists and that the user has execute permission to all
* directories. Finally check that the file exists, and that the
* user has read permission to the file itself.
*/
/*
* function: main.
* input: full path to a file.
* output: 'OK' if permission is granted, or 'ACCESS DENIED' and a
* detailed explanation if some problem was found.
*/
void
main(int argc, char* argv[])
{
char* file_path; /* full path to file. */
char* dir_path; /* full path to a directory. */
char* p_slash; /* location of next '/' in path. */
/*
* function: main.
* input: name of a log file.
* output: log file is being renamed if it is too big.
*/
void
main(int argc, char* argv[])
{
char* file_name; /* name of the log file. */
char* new_file_name; /* new name for the log file. */
struct stat file_status; /* status info of the log file. */
int fd; /* descriptor for new file. */
umode_t file_mode; /* permissions of old log file. */
/*
* function: findfile. recusively traverse the current directory, searching
* for files with a given string in their name.
* input: string to match.
* output: any file found, printed to the screen with a full path.
*/
void
findfile(char* pattern)
{
DIR* dir; /* pointer to the scanned directory. */
struct dirent* entry; /* pointer to one directory entry. */
char cwd[MAX_DIR_PATH+1]; /* current working directory. */
struct stat dir_stat; /* used by stat(). */
/*
* function: main. find files with a given pattern in their names, in
* a given directory tree.
* input: path to directory to search, and pattern to match.
* output: names of all matching files on the screen.
*/
void
main(int argc, char* argv[])
{
char* dir_path; /* path to the directory. */
char* pattern; /* pattern to match. */
struct stat dir_stat; /* used by stat(). */
/* recursively scan the directory for the given file name pattern. */
findfile(pattern);
}
Index of
/~choo/lupg/tutorials/libraries/static-lib
● Parent Directory
● Makefile
● main.c
● util_file.c
● util_math.c
● util_net.c
Thus, when a company builds a static library and gives it away, it does
not have to give all the object files - the header files, and the
library's archive file will do.
Index of
/~choo/lupg/tutorials/libraries/shared-lib
● Parent Directory
● Makefile
● main.c
● util_file.c
● util_math.c
● util_net.c
Thus, when a company builds a static library and gives it away, it does
not have to give all the object files - the header files, and the
library's archive file will do.
Note that in order to run the program, you need first to add the current
directory to your "LD_LIBRARY_PATH" environment variable. If it is
not defined yet ("echo $LD_LIBRARY_PATH" sais its not defined), then
define it with:
LD_LIBRARY_PATH=/full/path/to/current/directory
export LD_LIBRARY_PATH
LD_LIBRARY_PATH=/full/path/to/current/directory:${LD_LIBRARY_PATH}
export LD_LIBRARY_PATH
To check that you did that properly, run "ldd prog" - it should
show the name of our library (libutil.so) and point to the library
in the current directory. If it does not, check that your LD_LIBRARY_PATH
contains the correct path to the current directory, and that the library
was properly built.
Index of
/~choo/lupg/tutorials/libraries/dynamic-shared
● Parent Directory
● Makefile
● lib1.c
● lib2.c
● main.c
Note that in order to run the program, you need first to add the current
directory to your "LD_LIBRARY_PATH" environment variable. If it is
not defined yet ("echo $LD_LIBRARY_PATH" sais its not defined), then
define it with:
LD_LIBRARY_PATH=/full/path/to/current/directory
export LD_LIBRARY_PATH
To check that you did that properly, you'll need to run the program.
If it sais that the library file was not found, check the definition of
LD_LIBRARY_PATH, and the existance of the library in the current directory.
#include <stdio.h> /* standard I/O functions */
#include <unistd.h> /* standard unix functions, like getpid() */
#include <signal.h> /* signal name macros, and the signal() prototype */
return 0;
}
#include <stdio.h> /* standard I/O functions */
#include <unistd.h> /* standard unix functions, like alarm() */
#include <signal.h> /* signal name macros, and the signal() prototype */
return 0;
}
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Preview
The first thing you need to do when writing network applications, is obtain the addresses of the two involved
machines: your address, and the remote host's address. This process is made up of several stages:
1. Address Resolution - Translating the host name into an IP address.
2. Byte Ordering - Translating host byte order into network byte order.
3. Address Formation - Forming up the remote address in the right structure.
Address Resolution
Given a host name, we want to find it's IP address. We do that using the function gethostbyname(). This function is
defined in the file /usr/include/netdb.h (or the equivalent for your system) as follows:
The input to the function will be the name of the host whose address we want to resolve. The function returns a
pointer to a structure hostent, whose definition is as follows:
struct hostent {
char* h_name; /* official name of host */
char** h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char** h_addr_list; /* list of addresses from name server */
#define h_addr h_addr_list[0] /* address, for backward compatibility */
};
Lets see what each field in the hostent structure means:
● h_name: This is the official name of the host, i.e. the full address.
● h_aliases: a pointer to the list of aliases (other names) the host might have.
● h_length: The length of the address. Different address types might have different lengths.
● h_addr_list: A pointer to the list of addresses of the host. Note that a host might have more then one
address, as explained earlier.
● h_addr: In older systems, there was only the h_addr field, so it is defined here so old programs could
compile without change on newer systems.
Byte Ordering
As explained earlier, we need to form addresses using the network byte order. Luckily, most networking functions
accept addresses in host byte order, and return their results in network byte order. This means only a few fields will
need conversions. These will include the port numbers only, as the addresses are already supplied by the system.
We normally have several functions (or macros) to form 4 types of translations:
● htons() - short integer from host byte order to network byte order.
● ntohs() - short integer from network byte order to host byte order.
● htonl() - long integer from host byte order to network byte order.
● ntohl() - long integer from network byte order to host byte order.
For example, since a port number is represented by a short integer, we could convert it from host byte order to
network byte order by doing:
Address Formation
Forming addresses for Internet protocols is done using a structure named sockaddr_in, whose definition, as given in
the file /usr/include/netinet/in.h, is as follows:
struct sockaddr_in {
short int sin_family; /* Address family */
unsigned short sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
After seeing the structure used for address formation, and having resolved the host name into an IP number, forming
the address is done as follows:
/* get information about the given host, using some the system's */
/* default name resolution mechanism (DNS, NIS, /etc/hosts...). */
hen = gethostbyname(hostname_ser);
if (!hen) {
perror("couldn't locate host entry");
}
Notes:
● perror() is a function that prints an error message based on the global errno variable, and exits the process.
● memset() is a function used to set all bytes in a memory area of a specified size, to a specified value. On
some (older) systems there is a different function that should be used instead named bzero(). Read your
local manual page for additional information on it's usage. Note that memcpy is a part of the standard C
library, so it should be used whenever possible in place of bzero.
● memcpy() is a function used to copy the contents of one memory area into another area. On some systems
there is a different function with the same effect, named bcopy(). Like the bzero function, it should be
avoided whenever memcpy is available.
What is a socket?
A socket is formally defined as an endpoint for communication between an application program, and the underlying
network protocols. This odd collection of words simply means that the program reads information from a socket in
order to read from the network, writes information to it in order to write to the network, and sets sockets options in
order to control protocol options. From the programmer's point of view, the socket is identical to the network. Just
like a file descriptor is the endpoint of disk operations.
Types of sockets
In general, 3 types of sockets exist on most Unix systems: Stream sockets, Datagram sockets and Raw sockets.
Stream sockets are used for stream connections, i.e. connections that exist for a long duration. TCP connections use
stream sockets.
Datagram sockets are used for short-term connections, that transfer a single packet across the network before
terminating. the UDP protocol uses such sockets, due to its connection-less nature.
Raw sockets are used to access low-level protocols directly, bypassing the higher protocols. They are the means for
a programmer to use the IP protocol, or the physical layer of the network, directly. Raw sockets can therefor be used
to implement new protocols on top of the low-level protocols. Naturally, they are out of our scope.
Creating sockets
Creation of sockets is done using the socket() system call. This system call is defined as follows:
address_family defines the type of addresses we want this socket to use, and therefor defines what kind of network
protocol the socket will use. We will concentrate on the Internet address family, cause we want to write Internet
applications.
socket_type could be one of the socket types we mentioned earlier, or any other socket type that exists on your
system. We choose the socket type according to the kind of interaction (and type or protocol) we want to use.
proto_family selects which protocol we want to socket to use. We will usually leave this value as 0 (or the constant
PF_UNSPEC on some systems), and let the system choose the most suitable protocol for us. As for the protocol
itself, In the Internet address family, a socket type of SOCK_STREAM will cause the protocol type to be set to TCP.
A socket type of SOCK_DGRAM (Datagram socket) will cause the protocol type to be set to UDP.
The socket system call returns a file descriptor which will be used to reference the socket in later requests by the
application program. If the call fails, however (due to lack of resources) the value returned will be negative (note
that file descriptors have to be non-negative integers).
As an example, suppose that we want to write a TCP application. This application needs at least one socket in order
to communicate across the Internet, so it will contain a call such as this:
Note the usage of a different type of structure, namely struct sockaddr, then the one we used earlier (struct
sockaddr_in). Why is the sudden change? This is due to the generality of the socket interface: sockets could be
used as endpoints for connections using different types of address families. Each address family needs different
information, so they use different structures to form their addresses. Therefore, a generic socket address type, struct
sockaddr, is defined in the system, and for each address family, a different variation of this structure is used. For
those who know, this means that struct sockaddr_in, for example, is an overlay of struct sockaddr (i.e. it
uses the same memory space, just divides it differently into fields).
There are 4 possible variations of address binding that might be used when binding a socket in the Internet address
family.
The first is binding the socket to a specific address, i.e. a specific IP number and a specific port. This is done when
we know exactly where we want to receive messages. Actually this form is not used in simple servers, since usually
these servers wish to accept connections to the machine, no matter which IP interface it came from.
The second form is binding the socket to a specific IP number, but letting the system choose an unused port number.
This could be done when we don't need to use a well-known port.
The third form is binding the socket to a wild-card address called INADDR_ANY (by assigning it to the
sockaddr_in variable), and to a specific port number. This is used in servers that are supposed to accept packets
sent to this port on the local host, regardless of through which physical network interface the packet has arrived
(remember that a host might have more then one IP address).
The last form is letting the system bind the socket to any local IP address and to pick a port number by itself. This is
done by not using the bind() system call on the socket. The system will make the local bind when a connection
through the socket is established, i.e. along with the remote address binding. This form of binding is usually used by
clients, which care only about the remote address (where they connect to) and don't need any specific local port or
local IP address. However, there are exceptions here too.
The most common way of reading data from a socket is using the read() system call, which is defined like this:
● buflen - Size of the buffer, in bytes (actually, how much data we want to read).
● -1 - The read system call was interrupted, or failed for some reason.
● n - The read system call put 'n' bytes into the buffer we supplied it with.
Note that read() might read less then the number of bytes we requested, due to unavailability of buffer space in
the system.
The most common way of writing data to a socket is using the write() system call, which is defined like this:
● -1 - The write system call was interrupted, or failed for some reason.
● n - The write system call wrote 'n' bytes into the socket.
Note that the system keeps internal buffers, and the write system call write data to those buffers, not necessarily
directly to the network. thus, a successful write() doesn't mean the data arrived at the other end, or was even sent
onto the network. Also, it could be that only some of the bytes were written, and not the actual number we
requested. It is up to us to try to send the data again later on, when it's possible, and we'll show several methods for
doing just that.
Closing a socket.
When we want to abort a connection, or to close a socket that is no longer needed, we can use the close() system
call. it is defined simply as:
5. Writing Clients
This section describes how to write simple client applications, using the socket interface described earlier. As you
remember (hmm, do you?) from the second section,a classic Client makes a connection to the server, and goes into a
loop of reading commands from the user, parsing them, sending requests to the server, receiving responses from the
server, parsing them and echoing them back at the user.
We will begin by showing the C code of a simple Client without user-interaction. This Client connects to the
standard time server of a given host, reads the time, and prints it on the screen. Most (Unix) Internet hosts have a
standard server called daytime, that awaits connections on the well-known port number 13, and when it receives a
connection request, accepts it, writes the time to the Client, and closes the connection.
Lets see how the Client looks. Note the usage of a new system call, connect(), which is used to establish a
connection to a remote machine, and will be further explained immediately following the program text.
/* and terminate */
return 0;
}
The complete source code for this client may be found in the daytime-client.c file.
The Client's code should be pretty easy to understand now. All we did was combine the features we have seen so far
into one program. The only new feature introduced here is the connect() system call.
This system call is responsible to making the connection to the specified address of the remote machine, using the
specified socket. Note that the address is being type-cast into the general address type, struct sockaddr,
because this same system call is used to establish connections in various address families, not just the Internet
address family. How will the system then know we want an Internet connection? The answer is given in the socket's
information. If you remember, we specified this socket will be used in the Internet address family (AF_INET) when
we created it.
Note also how the reading loop is performed. We are asking the system to read as much data as possible in the
read() system call. However, the system might need several reads before it has consumed all the bytes sent by the
server, that's why we used the while loop. Remember, never assume a read() system call will return the exact
number of bytes you specified in the call. If less is available, the call will return quickly, and will not wait for the
rest of the data. On the other hand, if no data is available, the call will block (not return) until data is available. Thus,
when writing "Real" Clients and Servers, some measures have to be taken in order to avoid that blocking.
We will not discuss right now Clients that read user input. This subject will be differed until we learn how to read
information efficiently from several input devices.
6. Single-Clients Servers
Now that we have seen how a Client is written, lets give it a different server to talk to. We will write the "hello
world" (didn't you wait for this?) Server.
The "hello world" Server listens to a predefined port of our choice, and accepts incoming connections. It then writes
the message "hello world" to the remote Client, and closes the connection. This will be done in an infinite loop, so
we can serve a new Client after finishing with the current.
Note the introduction of two new system calls, listen() and accept(). The listen() system call asks the
system to listen for new connections coming to our port. The accept() system call is used to accept (how
obvious) such incoming connections. Both system calls will be explained further following the "hello world"
Server's code.
void main()
{
int rc; /* system calls return value storage */
int s; /* socket descriptor */
int cs; /* new connection's socket descriptor */
struct sockaddr_in sa; /* Internet address struct */
struct sockaddr_in csa; /* client's address struct */
int size_csa; /* size of client's address struct */
The complete source code for this server may be found in the hello-world-server.c file.
Look how little we had to add to the basic stuff in order to form our first server. The only two additions were the
listen() and the accept() system calls. Lets examine them a little more.
If we want to serve incoming connections, we need to ask the system to listen on the specified port. If we don't do
that, the remote Client will get a "connection refused" error. Once the system listens on the port, It could happen that
more then one Client will ask for service simultaneously. We can tell the system how many Clients may "wait in
line". This will be the second parameter to the listen() system call.
After issuing the listen() system call, we still need to actively accept incoming connections. This is done using
the accept() system call. We tell it which socket is bound to the port we want to accept connection from, and
give it the address of a variable in which the call will give us the address of the remote Client, once a connection is
established. It will also update the size of the address, based on the address family used, in the variable whose
address we pass as the third argument. We are not using the Client's address in our simple server, but other servers
that might want to authenticate their Clients (or just to know where they are coming from), will use it.
Finally, the accept() system call returns a number of a new socket, which is allocated for the new established
connection. This gives us a socket bound to the correct local and remote addresses, while not destroying the binding
of the original socket, that we can later use to accept new connections.
7. Multi-Clients Servers
If single-Client Servers were a rather simple case, the multi-Client ones are a tougher nut. There are two main
approaches to designing such servers.
The first approach is using one process that awaits new connections, and one more process (or thread) for each
Client already connected. This approach makes design quite easy, cause then the main process does not need to
differ between servers, and the sub-processes are each a single-Client server process, hence, easier to implement.
However, this approach wastes too many system resources (if child processes are used), and complicates inter-Client
communication: If one Client wants to send a message to another through the server, this will require
communication between two processes on the server, or locking mechanisms, if using multiple threads.
The second approach is using a single process for all tasks: waiting for new connections and accepting them, while
handling open connections and messages that arrive through them. This approach uses less system resources, and
simplifies inter-Client communication, although making the server process more complex.
Luckily, the Unix system provides a system call that makes these tasks much easier to handle: the select()
system call.
The select() system call puts the process to sleep until any of a given list of file descriptors (including sockets)
is ready for reading, writing or is in an exceptional condition. When one of these things happen, the call returns, and
notifies the process which file descriptors are waiting for service.
The select system call is defined as follows:
● timeout - how long to wait before terminating the call in case no file descriptor is ready.
select() returns the number of file descriptors that are ready, or -1 if some error occurred.
We give select() 3 sets of file descriptors to check upon. The sockets in the rfd set will be checked whether they
sent data that can be read. The file descriptors in the wfd set will be checked to see whether we can write into any of
them. The file descriptors in the efd set will be checked for exceptional conditions (you may safely ignore this set
for now, since it requires a better understanding of the Internet protocols in order to be useful). Note that if we don't
want to check one of the sets, we send a NULL pointer instead.
We also give select() a timeout value - if this amount of time passes before any of the file descriptors is ready,
the call will terminate, returning 0 (no file descriptors are ready).
NOTE - We could use the select() system call to modify the Client so it could also accept user input, Simply by
telling it to select() on a set comprised of two descriptors: the standard input descriptor (descriptor number 0)
and the communication socket (the one we allocated using the socket() system call). When the select() call
returns, we will check which descriptor is ready: standard input, or our socket, and this way will know which of
them needs service.
There are three more things we need to know in order to be able to use select. One - how do we know the highest
number of a file descriptor a process may use on our system? Two - how do we prepare those sets? Three - when
select returns, how do we know which descriptors are ready - and what they are ready for?
As for the first issue, we could use the getdtablesize() system call. It is defined as follows:
int getdtablesize();
This system call takes no arguments, and returns the number of the largest file descriptor a process may have. On
modern systems, we could instead use the getrlimit() system call, using the RLIMIT_NOFILE parameter.
Refer to the relevant manual page for more information.
As for the second issue, the system provides us with several macros to manipulate fd_set type variables.
FD_ZERO(fd_set *xfd)
Clear out the set pointed to by 'xfd'.
FD_SET(fd, fd_set *xfd)
Add file descriptor 'fd' to the set pointed to by 'xfd'.
FD_CLR(fd, fd_set *xfd)
Remove file descriptor 'fd' from the set pointed to by 'xfd'.
FD_ISSET(fd, fd_set *xfd)
check whether file descriptor 'fd' is part of the set pointed to by 'xfd'.
An important thing to note is that select() actually modifies the sets passed to it as parameters, to reflect the
state of the file descriptors. This means we need to pass a copy of the original sets to select(), and manipulate
the original sets according to the results of select(). In our example program, variable 'rfd' will contain the
original set of sockets, and 'c_rfd' will contain the copy passed to select().
Here is the source code of a Multi-Client echo Server. This Server accepts connection from several Clients
simultaneously, and echoes back at each Client any byte it will send to the Server. This is a service similar to the one
give by the Internet Echo service, that accepts incoming connections on the well-known port 7. Compare the code
given here to the algorithm of a Multi-Client Server presented in the Client-Server model section.
The complete source code for this server may be found in the multi-client-echo-server.c file.
8. Conclusions
That's it. If you got as far as here, and hopefully tried playing a little with the code examples, you probably got the
basic notion of what it takes to write simple clients and servers that communicate using the TCP protocol. We didn't
cover UDP-based clients and servers, but hopefully, you'll manage getting there by referring to one of the more
advanced resources mentioned below.
And remember: clients, and especially servers, are expected to be robust creatures. Yet, the network is a too shaky
ground to assume everything will work smoothly. Expect the unexpected. Check the return value of any system call
you use, and act upon it. If a system call failed, try to figure out why it failed (using the returned error code and
possibly the errno variable), and if you cannot write code to bypass that kind of failure - at least give your users an
error message they can understand.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
/*
* authenticate-user.c - ask a user for their password, and compare it to
* the password, as taken from the "/etc/passwd" file.
*/
void
main()
{
/* buffers for reading in the user name and the password. */
char user[21];
char* password;
/* storing the encrypted password, and the salt. */
char* encrypted_password;
char salt[2];
/* user's "/etc/passwd" entry. */
struct passwd* user_info;
/* compare the results of crypt, with the user's stored password field. */
if (strcmp(user_info->pw_passwd, encrypted_password) != 0) {
printf("login incorrect.\n");
exit(1);
}
/* authentication succeeded... */
printf("login successful.\n");
}
/*
* show-loged-users.c - list the names of the currently logged in users.
*/
void
main()
{
/* buffer to read one utmp record. */
struct utmp utmp_entry;
/* buffer to store a user name. */
char user_name[UT_NAMESIZE+1];
/* file descriptor for the "utmp" file. */
int fd;
printf("'%s',", user_name);
}
printf("\n");
close(fd);
}
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
Windows Hierarchy
When windows are displayed on an X server, they are always ordered in some hierarchy - every window may have
child windows, each child window may have its own child windows, etc. Lets see a few properties of this hierarchy,
and how they effect the operations like drawing or events propagation.
On each screen, there is a root window. The root window always spans the entire screen size. This window cannot be
destroyed, resized or iconified. When an application creates windows, it first has to create at least one top-level
window. This window becomes a direct descendant of the root window, until it is first mapped on the screen. Before
this window is mapped, the window manager is notified of the operation about to take place. The window manager then
has the privilege of re-parenting the new top-level window. This is used to add a window that will contain the new
window, and will be used to draw its frame, title bar, system menu, etc.
Once such a top-level window (which is actually not a top-level window after the re-parenting operation takes place) is
created, the application can create child windows inside this window. A child can only be displayed inside its parent
window - If it is moved outside, its being clipped by the border of its parent window. Any window may contain more
then one child window, and if this is the case, these windows are being ordered in an internal stack. When a top-level
window is being raised - all its descendant windows are being raised with it, while retaining their internal ordering. If a
child window is raised - it is being raised only amongst its sibling windows.
Lets see how to create a child window inside a given window 'win'.
/* this variable will store the handle of the newly created child window. */
Window child_win;
Events Propagation
We have discussed events propagation earlier - If a window is being sent an event and it does not process the event -
the event is being passed to the this window's parent window. If that parent window does not handle this event - it is
being passed to the parent's parent window, and so on. This behavior does not make a lot of sense for a simple Xlib
application, but it does make sense when higher-level graphic libraries are used. They usually associate functions with
events occurring in specific windows. In such a case, it is useful to pass the event to the relevant window, with which a
proper function is associated.
Window Properties
Many of the parameters communicated to the window manager are passed using data called "properties". These
properties are attached by the X server to different windows, and are stored in a format that makes it possible to read
them from different machines, that may use different architectures (remember that an X client program may run on a
remote machine). Properties may be of various types - numbers, strings, etc. Most window manager hints functions use
text properties. A function named XStringListToTextProperty() may be used to turn a normal C string into
an X text property, that can later be passed to various Xlib functions. Here is how to use it:
The first thing would be to set the name for our window. This is done using the XSetWMName() function. This name
may be used by the window manager as the title of the window (in the title bar), in a task list, etc. This function accepts
3 parameters: a pointer to the display, a window handle, and an XTextProperty containing the desired title. Here is
how it is used:
In various cases, we wish to let the window manager know that we want to have a given size for our window, and to
only let the user resize our window in given quantities. For example, in a terminal application (like xterm), we want our
window to always contain complete rows and columns, so the text we display won't be cut off in the middle. In other
cases we do not want our window to be resized at all (like in many dialog boxes), etc. We can relay this information to
the window manager, although it may simply ignore our request. We need to first create a data structure to hold the
information, fill it with proper data, and use the XSetWMNormalHints() function. Here is how this may be done:
There are some other window manager hints that may be set using the XSetWMHints() function. This function uses
a XWMHints structure to pass the data to the window manager. Here is how it may be used:
In order to set an icon to be used by the window manager, when a user iconifies our application, we use the
XSetWMHints() function mentioned above. However, we first need to create a pixmap that contains the icon's data.
Pixmaps are the way that X servers manipulate images, and will be explained fully later in this tutorial. For now, we'll
just show you how to set the icon for your application. We assume you got a bitmap file representing this icon, stored
using an X bitmap format. An example of such a file is the "icon.bmp" file that comes with this tutorial. Anyway, here
is the code:
/* load the given bitmap data and create an X pixmap containing it. */
Pixmap icon_pixmap = XCreateBitmapFromData(display,
win,
icon_bitmap_bits,
icon_bitmap_width,
icon_bitmap_height);
if (!icon_pixmap) {
fprintf(stderr, "XCreateBitmapFromData - error creating pixmap\n");
exit(1);
}
The first pair of operations we can apply on a window is mapping it, or un-mapping it. Mapping a window causes the
window to appear on the screen, as we have seen in our simple window program example. UN-mapping it causes it to
be removed from the screen (although the window as a logical entity still exists). This gives the effect of making a
window hidden (unmapped) and shown again (mapped). For example, if we have a dialog box window in our program,
instead of creating it every time the user asks to open it, we can create the window once, in an unmapped mode, and
when the user asks to open it, we simply map the window on the screen. When the user clicked the 'OK' or 'Cancel'
button, we simply UN-map the window. This is much faster then creating and destroying the window, however, the
cost is wasted resources, both on the client side, and on the X server side.
You will remember That the map operation can be done using the XMapWindow() operation. The UN-mapping
operation can be done using the XUnmapWindow() operation. Here is how to apply them:
Another operation we might want to do with windows is to move them to a different location. This can be done using
the XMoveWindow() function. It will accept the new coordinates of the window, in the same fashion that
XCreateSimpleWindow() got them when the window was created. The function is invoked like this:
Resizing A Window
Yet another operation we can do is to change the size of a window. This is done using the XResizeWindow()
function:
/* move the window to location x=20 y=30, and change its size */
/* to width=100 and height=150 pixels. */
XMoveResizeWindow(display, win, 20, 30, 100, 150);
Until now we changed properties of a single window. We'll see that there are properties that relate to the window and
other windows. One of them is the stacking order. That is, the order in which the windows are layered on top of each
other. the front-most window is said to be on the top of the stack, while the back-most window is at the bottom of the
stack. Here is how we manipulate our windows stacking order:
One last operation we will show here is the ability to change a window into an iconified mode and vice versa. This is
done using the XIconifyWindow() function - to iconify the window, and the XMapWindow() to de-iconify it. To
understand why there is no inverse function for XIconifyWindow(), we must realize that when a window is
iconified, what actually happens is that the window is being unmapped, and instead its icon window is being mapped.
Thus, to make the original window reappear, we simply need to map it again. The icon is indeed another window that is
simply related strongly to our normal window - it is not a different state of our window. Here is how to iconify a
window and then de-iconify it:
/* iconify our window. Make its icon window appear on the same */
/* screen as our window (assuming we created our window on the */
/* default screen). */
XIconifyWindow(display, win, DefaultScreen(display));
Just like we can set various attributes of our windows, we can also ask the X server supply the current values of these
attributes. For example, we can check where a window is located on screen, what is its current size, whether it is
mapped or not, etc. The XGetWindowAttributes() function may be used to get this information. Here is how it
is used:
/* this variable will store the ID of the parent window of our window. */
Window parent_win;
/* this variable will store the ID of the root window of the screen */
/* our window is mapped on. */
Window root_win;
/* this variable will store an array of IDs of the child windows of */
/* our window. */
Window* child_windows;
/* and this one will store the number of child windows our window has. */
int num_child_windows;
/* at this point, screen_x and screen_y contain the location of our original */
/* window, using screen coordinates. */
As you can see, Xlib sometimes makes us work hard for things that could have been much easier, if its interfaces and
functions were a little more consistent.
As an example of how these operations all work, check out our window-operations.c program.
Color Maps
In the beginning, there were not enough colors. Screen controllers could only support a limited number of colors
simultaneously (16 initially, and then 256). Because of this, an application could not just ask to draw in a "light
purple-red" color, and expect that color to be available. Each application allocated the colors it needed, and when all 16
or 256 color entries were in use, the next color allocation would fail.
Thus, the notion of "a color map" was introduced. A color map is a table whose size is the same as the number of
simultaneous colors a given screen controller. Each entry contained the RGB (Red, Green and Blue) values of a
different color (all colors can be drawn using some combination of red, green and blue). When an application wants to
draw on the screen, it does not specify which color to use. Rather, it specifies which color entry of some color map to
be used during this drawing. Change the value in this color map entry - and the drawing will use a different color.
In order to be able to draw using colors that got something to do with what the programmer intended, color map
allocation functions were supplied. You could ask to allocate a color map entry for a color with a set of RGB values. If
one already existed, you'd get its index in the table. If none existed, and the table was not full, a new cell would be
allocated to contain the given RGB values, and its index returned. If the table was full, the procedure would fail. You
could then ask to get a color map entry with a color that is closest to the one you were asking for. This would mean that
the actual drawing on the screen would be done using colors similar to what you wanted, but not the same.
On today's more modern screens, where one runs an X server with support for 1 million colors, this limitation looks a
little silly, but remember that there are still older computers with older graphics cards out there. Using color maps,
support for these screens becomes transparent to you. On a display supporting 1 million colors, any color entry
allocation request would succeed. On a display supporting a limited number of colors, some color allocation requests
would return similar colors. It won't look as good, but your application would still work.
When you draw using Xlib, you can choose to use the standard color map of the screen your window is displayed on, or
you can allocate a new color map and apply it to a window. In the latter case, each time the mouse moves onto your
window, the screen color map will be replaced by your window's color map, and you'll see all the other windows on
screen change their colors into something quite bizzar. In fact, this is the effect you get with X applications that use the
"-install" command-line option.
In order to access the screen's standard color map, the DefaultColormap macro is defined:
Once we got access to some color map, we can start allocating colors. This is done using the
XAllocNamedColor() and XAllocColor() functions. The first XAllocNamedColor() accepts a color
name (e.g. "red", "blue", "brown" and so on) and allocates the the closest color that can be actually drawn on the
screen. The XAllocColor() accepts an RGB color, and allocates the closest color that can be drawn on the screen.
Both functions use the XColor structure, that has the following relevant fields:
unsigned long pixel
This is the index of the color map entry that can be used to draw in this color.
unsigned short red
the red part of the RGB value of the color.
unsigned short green
the green part of the RGB value of the color.
unsigned short blue
the blue part of the RGB value of the color.
Here is an example of using these functions:
/* this structure will store the color data actually allocated for us. */
XColor system_color_1, system_color_2;
/* this structure will store the exact RGB values of the named color. */
/* it might be different from what was actually allocated. */
XColor exact_color;
After we have allocated the desired colors, we can use them when drawing text or graphics. To do that, we need to set
these colors as the foreground and background colors of some GC (Graphics Context), and then use this GC to make
the drawing. This is done using the XSetForeground() and XSetBackground() functions, as follows:
An X bitmap is a two-color image stored in a format specific to the X window system. When stored in a file, the bitmap
data looks like a C source file. It contains variables defining the width and height of the bitmap, an array containing the
bit values of the bitmap (the size of the array = width * height), and an optional hot-spot location (will be explained
later, when discussing mouse cursors).
A X pixmap is a format used to store images in the memory of an X server. This format can store both black and white
images (such as x bitmaps) as well as color images. It is the only image format supported by the X protocol, and any
image to be drawn on screen, should be first translated into this format.
In actuality, an X pixmap can be thought of as a window that does not appear on the screen. Many graphics operations
that work on windows, will also work on pixmaps - just supply the pixmap ID instead of a window ID. In fact, if you
check the manual pages, you will see that all these functions accept a 'Drawable', not a 'Window'. since both windows
and pixmaps are drawables, they both can be used to "draw on" using functions such as XDrawArc(),
XDrawText(), etc.
We have already seen how to load a bitmap from a file to memory, when we demonstrated setting an icon for an
application. The method we showed earlier required the inclusion of the bitmap file in our program, using the C
pre-processor '#include' directive. We will see here how we can access the file directly.
/* this variable will contain the ID of the root window of the screen */
/* for which we want the pixmap to be created. */
Window root_win = DefaultRootWindow(display);
Once we got a handle to the pixmap generated from a bitmap, we can draw it on some window, using the
XCopyPlane() function. This function allows us to specify what drawable (a window, or even another pixmap) to
draw the given pixmap onto, and at what location in that drawable.
Creating A Pixmap
Sometimes we want to create an un-initialized pixmap, so we can later draw into it. This is useful for image drawing
programs (creating a new empty canvas will cause the creation of a new pixmap on which the drawing can be stored). It
is also useful when reading various image formats - we load the image data into memory, cerate a pixmap on the
server, and then draw the decoded image data onto that pixmap.
/* this variable will store the handle of the newly created pixmap. */
Pixmap pixmap;
/* this variable will contain the ID of the root window of the screen */
/* for which we want the pixmap to be created. */
Window root_win = DefaultRootWindow(display);
/* this variable will contain the color depth of the pixmap to create. */
/* this 'depth' specifies the number of bits used to represent a color */
/* index in the color map. the number of colors is 2 to the power of */
/* this depth. */
int depth = DefaultDepth(display, DefaultScreen(display));
Once we got a handle to pixmap, we can draw it on some window, using the XCopyArea() function. This function
allows us to specify what drawable (a window, or even another pixmap) to draw the given pixmap onto, and at what
location in that drawable.
Finally, when we are done using a given pixmap, we should free it, in order to free resources of the X server. This is
done using the XFreePixmap() function:
There are two methods for creating cursors. One of them is by using a set of pre-defined cursors, that are supplied by
Xlib. The other is by using user-supplied bitmaps.
In the first method, we use a special font named "cursor", and the function XCreateFontCursor(). This function
accepts a shape identifier, and returns a handle to the generated cursor. The list of allowed font identifiers is found in
the include file <X11/cursorfont.h>. Here are a few such cursors:
XC_arrow
The normal pointing-arrow cursor displayed by the server.
XC_pencil
A cursor shaped as a pencil.
XC_watch
A sand watch.
And creating a cursor using these symbols is very easy:
/* this variable will hold the handle of the newly created cursor. */
Cursor watch_cursor;
/* first, we need to define foreground and background colors for the cursor. */
XColor cursor_fg, cursor_bg;
/* finally, generate the cursor. make the 'hot spot' be close to the */
/* top-left corner of the cursor - location (x=5, y=4). */
icon_cursor = XCreatePixmapCursor(display, bitmap, bitmap,
&cursor_fg, &cursor_bg,
5, 4);
One thing to be explained is the 'hot spot' parameters. When we define a cursor, we need to define which pixel of the
cursor is the pointer delivered to the user in the various mouse events. Usually, we will choose a location of the cursor
that visually looks like a hot spot. For example, in an arrow cursor, the tip of the arrow will be defined as the hot spot.
Finally, when we are done with a cursor and no longer need it, we can release it using the XFreeCursor() function:
XFreeCursor(display, icon_cursor);
After we have created a cursor, we can tell the X server to attach this cursor to any of our windows. This is done using
the XDefineCursor(), and causes the X server to change the mouse pointer to the shape of that cursor, each time
the mouse pointer moves into and across that window. We can later detach this cursor from our window using the
XUndefineCursor() function. This will cause the default cursor to be shown when the mouse enter that windows.
[LUPG Home] [Tutorials] [Related Material] [Essays] [Project Ideas] [Send Comments]
/*
* simple-window.c - demonstrate creation of a simple window.
*/
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h> /* getenv(), etc. */
#include <unistd.h> /* sleep(), etc. */
void
main(int argc, char* argv[])
{
Display* display; /* pointer to X Display structure. */
int screen_num; /* number of screen to place the window on. */
Window win; /* pointer to the newly created window. */
unsigned int display_width,
display_height; /* height and width of the X display. */
unsigned int width, height; /* height and width for the new window. */
unsigned int win_x, win_y; /* location of the window's top-left corner. */
unsigned int win_border_width; /* width of window's border. */
char *display_name = getenv("DISPLAY"); /* address of the X display. */
display = XOpenDisplay(display_name);
if (display == NULL) {
fprintf(stderr, "%s: cannot connect to X server '%s'\n",
argv[0], display_name);
exit(1);
}
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h> /* getenv(), etc. */
#include <unistd.h> /* sleep(), etc. */
/*
* function: create_simple_window. Creates a window with a white background
* in the given size.
* input: display, size of the window (in pixels), and location of the window
* (in pixels).
* output: the window's ID.
* notes: window is created with a black border, 2 pixels wide.
* the window is automatically mapped after its creation.
*/
Window
create_simple_window(Display* display, int width, int height, int x, int y)
{
int screen_num = DefaultScreen(display);
int win_border_width = 2;
Window win;
return win;
}
GC
create_gc(Display* display, Window win, int reverse_video)
{
GC gc; /* handle of newly created GC. */
unsigned long valuemask = 0; /* which values in 'values' to */
/* check when creating the GC. */
XGCValues values; /* initial values for the GC. */
unsigned int line_width = 2; /* line width for the GC. */
int line_style = LineSolid; /* style for lines drawing and */
int cap_style = CapButt; /* style of the line's edje and */
int join_style = JoinBevel; /* joined lines. */
int screen_num = DefaultScreen(display);
gc = XCreateGC(display, win, valuemask, &values);
if (gc < 0) {
fprintf(stderr, "XCreateGC: \n");
}
/* define the style of lines that will be drawn using this GC. */
XSetLineAttributes(display, gc,
line_width, line_style, cap_style, join_style);
return gc;
}
void
main(int argc, char* argv[])
{
Display* display; /* pointer to X Display structure. */
int screen_num; /* number of screen to place the window on. */
Window win; /* pointer to the newly created window. */
unsigned int display_width,
display_height; /* height and width of the X display. */
unsigned int width, height; /* height and width for the new window. */
char *display_name = getenv("DISPLAY"); /* address of the X display. */
GC gc; /* GC (graphics context) used for drawing */
/* in our window. */
{
XPoint points[] = {
{0, 0},
{15, 15},
{0, 15},
{0, 0}
};
int npoints = sizeof(points)/sizeof(XPoint);
/* draw a filled rectangle of the same size as above, to the left of the */
/* previous rectangle. */
XFillRectangle(display, win, gc, 60, 150, 50, 60);
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h> /* getenv(), etc. */
/*
* function: create_simple_window. Creates a window with a white background
* in the given size.
* input: display, size of the window (in pixels), and location of the window
* (in pixels).
* output: the window's ID.
* notes: window is created with a black border, 2 pixels wide.
* the window is automatically mapped after its creation.
*/
Window
create_simple_window(Display* display, int width, int height, int x, int y)
{
int screen_num = DefaultScreen(display);
int win_border_width = 2;
Window win;
return win;
}
GC
create_gc(Display* display, Window win, int reverse_video)
{
GC gc; /* handle of newly created GC. */
unsigned long valuemask = 0; /* which values in 'values' to */
/* check when creating the GC. */
XGCValues values; /* initial values for the GC. */
unsigned int line_width = 2; /* line width for the GC. */
int line_style = LineSolid; /* style for lines drawing and */
int cap_style = CapButt; /* style of the line's edje and */
int join_style = JoinBevel; /* joined lines. */
int screen_num = DefaultScreen(display);
/* define the style of lines that will be drawn using this GC. */
XSetLineAttributes(display, gc,
line_width, line_style, cap_style, join_style);
return gc;
}
/*
* function: handle_expose. handles an Expose event by redrawing the window.
* input: display, 2 GCs, XExposeEvent event structure, dimensions of
* the window, pixels array.
* output: none.
*/
void
handle_expose(Display* display, GC gc, GC rev_gc, XExposeEvent* expose_event,
unsigned int win_width, unsigned int win_height,
short pixels[1000][1000])
{
/* if this is the first in a set of expose events - ignore this event. */
if (expose_event->count != 0)
return;
/* draw the contents of our window. */
{
XPoint points[] = {
{0, 0},
{15, 15},
{0, 15},
{0, 0}
};
int npoints = sizeof(points)/sizeof(XPoint);
/* draw a filled rectangle of the same size as above, to the left of the */
/* previous rectangle. */
XFillRectangle(display, expose_event->window, gc, 60, 150, 50, 60);
/*
* function: handle_drag. handles a Mouse drag event - if the left button
* is depressed - draws the pixel below the mouse pointer. if the
* middle button is depressed - erases the pixel below the mouse
* pointer.
* input: display, 2 GCs, XButtonEvent event structure, dimensions of
* the window, pixels array.
* output: none.
*/
void
handle_drag(Display* display, GC gc, GC rev_gc, XButtonEvent* drag_event,
unsigned int win_width, unsigned int win_height,
short pixels[1000][1000])
{
int x, y;
/*
* function: handle_button_down. handles a Mouse press event - if the left
* button is depressed - draws the pixel below the mouse pointer.
* if the middle button is depressed - erases the pixel below the
* mouse pointer.
* input: display, 2 GCs, XButtonEvent event structure, dimensions of
* the window, pixels array.
* output: none.
*/
void
handle_button_down(Display* display, GC gc, GC rev_gc,
XButtonEvent* button_event,
unsigned int win_width, unsigned int win_height,
short pixels[1000][1000])
{
int x, y;
void
main(int argc, char* argv[])
{
Display* display; /* pointer to X Display structure. */
int screen_num; /* number of screen to place the window on. */
Window win; /* pointer to the newly created window. */
unsigned int display_width,
display_height; /* height and width of the X display. */
unsigned int width, height; /* height and width for the new window. */
char *display_name = getenv("DISPLAY"); /* address of the X display. */
GC gc, rev_gc; /* GC (graphics context) used for drawing */
/* in our window. */
short pixels[1000][1000]; /* used to store pixels on screen that were */
/* explicitly drawn or erased by the user. */
/* allocate two new GCs (graphics contexts) for drawing in the window. */
/* the first is used for drawing black over white, the second is used */
/* for drawing white over black. */
gc = create_gc(display, win, 0);
rev_gc = create_gc(display, win, 1);
case ConfigureNotify:
/* update the size of our window, for expose events. */
width = an_event.xconfigure.width;
height = an_event.xconfigure.height;
break;
case ButtonPress:
/* invert the pixel under the mouse pointer. */
handle_button_down(display, gc, rev_gc,
(XButtonEvent*)&an_event.xbutton,
width, height, pixels);
break;
case MotionNotify:
/* invert the pixel under the mouse pointer. */
handle_drag(display, gc, rev_gc,
(XButtonEvent*)&an_event.xbutton,
width, height, pixels);
break;
case KeyPress:
/* exit the application by braking out of the events loop. */
done = 1;
break;
#include <X11/Xlib.h>
#include <stdio.h>
#include <stdlib.h> /* getenv(), etc. */
#include <unistd.h> /* sleep(), etc. */
/*
* function: create_simple_window. Creates a window with a white background
* in the given size.
* input: display, size of the window (in pixels), and location of the window
* (in pixels).
* output: the window's ID.
* notes: window is created with a black border, 2 pixels wide.
* the window is automatically mapped after its creation.
*/
Window
create_simple_window(Display* display, int width, int height, int x, int y)
{
int screen_num = DefaultScreen(display);
int win_border_width = 2;
Window win;
return win;
}
GC
create_gc(Display* display, Window win, int reverse_video)
{
GC gc; /* handle of newly created GC. */
unsigned long valuemask = 0; /* which values in 'values' to */
/* check when creating the GC. */
XGCValues values; /* initial values for the GC. */
unsigned int line_width = 2; /* line width for the GC. */
int line_style = LineSolid; /* style for lines drawing and */
int cap_style = CapButt; /* style of the line's edje and */
int join_style = JoinBevel; /* joined lines. */
int screen_num = DefaultScreen(display);
/* define the style of lines that will be drawn using this GC. */
XSetLineAttributes(display, gc,
line_width, line_style, cap_style, join_style);
return gc;
}
void
main(int argc, char* argv[])
{
Display* display; /* pointer to X Display structure. */
int screen_num; /* number of screen to place the window on. */
Window win; /* pointer to the newly created window. */
unsigned int display_width,
display_height; /* height and width of the X display. */
unsigned int win_width,
win_height; /* height and width for the new window. */
char *display_name = getenv("DISPLAY"); /* address of the X display. */
GC gc; /* GC (graphics context) used for drawing */
/* in our window. */
XFontStruct* font_info; /* Font structure, used for drawing text. */
char* font_name = "*-helvetica-*-12-*"; /* font to use for drawing text. */
{
/* variables used for drawing the text strings. */
int x, y;
char* text_string;
int string_width;
int font_height;
Enter the Real-Time Forum The Open Group Launches Works With LDAP 2000
SGI Joins the Open Group's Real-Time and Embedded Certification Program
Systems Forum as Industry Leader in Real-Time BMC Software Collaborates with The Open Group to
Solutions develop Open Management Standards
Go to the full list of Press Releases
Disclaimer © 1995-2001
Text Only Home Page Trademarks
Privacy Principles The Open Group
We thank Compaq Computer Corporation for providing the system to host our electronic mail services
[ Getting Started Overview ] [ Upcoming Events ] [ Documents and Technology ] [ About The OMG ]
[ OMG News and Information ] [ TC Homepages ]
[ Home ] [ Privacy Statement ] [ Legal Guidelines ] [ Directions To The OMG Headquarters ] [ Contact Us ]
Copyright © 1997-2001 Object Management Group, Inc. All Rights Reserved. For questions about the WEBSITE , please contact [email protected] For
TECHNICAL questions, please contact [email protected] This site is best viewed at 800x600 pixels with Netscape Navigator or Internet Explorer versions
4.0 or later or any browser capable of viewing JavaScript and CSS 2.0 Last Updated Tuesday, July 10, 2001
The Free CORBA page
If you're interested in Java, why not check out my Java page?
If you're interested in distributed objects, why not check out my Enterprise Java Beans page?
Here is a matrix of the various commercial and non-commercial ORBs and the language bindings and features that they
support.
Here is a matrix of the various commercial and non-commercial ORBs and the CORBA services which they support.
Here is a matrix of the various commercial and non-commercial ORBs and the platforms on which they run.
These matrices were created, and are currently maintained, by Ben Eng, who has some other neat stuff on his homepage as
well.
Benchmarks
A new paper from MLC Systeme GmbH and the Distributed Systems Research Group of Prague's Charles University features
comparative benchmarks for Inprise Visibroker, Iona's Orbix, and ORL's OmniORB. The paper can be found here.
ExperSoft has posted a white paper on benchmarking enterprise ORBs. This paper should be helpful to you if you intend to do
comparative benchmarking on prospective ORBs.
Enough chitchat! On to the list!
Free ORBs
VBOrb
From the author:
Flick is the flexible interface definition language (IDL) compiler from the
University of Utah. What sets Flick apart from other IDL compilers is that
it is highly optimizing while also supporting several IDLs, message formats,
and transport mechanisms. Flick currently has front ends for the CORBA, Sun
ONC RPC, and Mach MIG IDLs, and middle and back ends that support CORBA IIOP,
ONC/TCP, MIG-style Mach messages, and other specialized transports. Flick
produces C stubs for all IDLs and both C and C++ stubs for CORBA IDL.
Mico/E
An open-source port of the Mico ORB (see below) to the Eiffel language.
LuaORB
LuaORB is a language binding for the interpreted language Lua. It's been tested with the Orbacus C++ ORB, version 3.1.2.
JavaORB
A Java CORBA 2.3 ORB. Here's their description:
- Services :
Security, Transaction, Notification, Trading, Naming, Persistence, Event
- Extensions :
Pure Java RMI/IIOP implementation
- Free to download and use for both commercial and non-commercial projects
The same folks are also working on an Enterprise JavaBeans implementation called AnEJB
Engine Room CORBA
A free ORB written by Mitchell Britton. Features:
● IDL compiler written in 100% pure Java
● Portable stubs and skeletons produced in 100% pure Java for Java according to the CORBA 2.2 spec.
● Ported to Win95/NT (Borland C++ and Visual C++), Solaris and LINUX
● It's free
Jonathan
From the author: Jonathan is an Object Request Broker written entirely in Java. It is an "open" ORB, in the sense that contrary
to standard ORBs, the abstractions that make up the internal ORB machinery may be used by an application programmer and
specialized to meet specific requirements.
Jonathan ... is now completely free for commercial or non-commercial usage (it is released under the LGPL license).
ORBit
A new Corba 2.2-compliant ORB with C bindings. ADA bindings are also available.
DynaORB
From the author's pages:
DynaORB is a lightweight universal CORBA client component. By lightweight, it is meant that it can be quickly transferred
across a network. By universal, it is meant that it can interoparate (i.e. communicate with) and CORBA v2.x compliant ORB
using IIOP (GIOP over TCP/IP). The 'Dyna' in DynaORB symbolizes that no static client stubs are needed, instead DynaORB
issues dynamic requests to CORBA servers. Finally, DynaORB is a CORBA client and requires a server-side equivalent. Any
CORBA 2.x compliant ORB can be used to publish your object implementations.
ISP
ISP is a CORBA 2 compliant C++ ORB created by the Institute of Systems Programming of the Russian Academy of Sciences
(ISPRAS).
Arachne
Arachne is a toolkit for distributed component-based software development. It includes a CORBA ORB which is "nearly"
CORBA 2.0 compliant, a partial implementation of COS, an IDL-to-C++ translator, some cross-platform portability libraries,
and a CORBA application framework class library. Available for Windows 95/NT, Linux, HP/UX, SunOS 4.x, and Macintosh.
ObjectSpace Voyager
The ObjectSpace Voyager ORB is still free for internal, not-for-resale applications. ObjectSpace has created an entire family
of products based on Voyager, including an application server.
TAO
TAO is a freely available implementation of a CORBA Object Request Broker (ORB) developed at Washington University.
Portions of it are still under development; you can track the progress here.
Fnorb
Fnorb is a Corba ORB written in the Python language. It includes a language mapping for Python. It's free for non-commercial
use. It no longer requires a third-party Interface Repository.
MICO
The MICO project intends to provide a freely available and complete CORBA 2.1 implementation under the GNU public
license. Full source code is available. MICO boasts an impressive list:
OmniORB 2
Omni-ORB 2 is a CORBA 2 - compliant ORB from AT&T Laboratories Cambridge. It supports C++ bindings, and it is freely
available.
As of June 1999, the current version is 2.7.1. JavaIDL Javasoft has released an early-access implementation of JavaIDL. This
is not the alpha version referred to below, but is listed as version 1.1 EA.
JacORB JacORB is a free ORB written in Java.
Gerald Brose, creator of JacORB, had this to say:
If you like, you could also add that it comes with a name and
an event service implementation.
Orbacus (formerly OmniBroker) ORBacus is free for non-commercial use. Source code is also available. A thumbnail sketch
of new features:
CorbaPlus
Expersoft has made the Java edititon of their CorbaPlus ORB available for a 60-day time-limited evaluation.
OAK
OAK is a CORBA2-compliant ORB available for a wide variety of platforms, including Nextstep, Openstep, and WebObjects.
It supports C++ and Objective-C bindings as well as a Java client-side mapping, IIOP, DII, DSI, and supports naming and
events. A full version is available for 30-day evaluation. OAK is also offered free to educational institutions. Additionally,
Paragon Software offers a single-user license for personal non-commercial use, also for free.
OrbixWeb
OrbixWeb is a full CORBA2 ORB implemented in Java and is available for download free for 60 days.
CorbaPlus for C++ Expersoft's CorbaPlus for C++ is available for a 60-day trial download.
Visibroker Visibroker is one of the leading commercial CORBA ORBs available Inprise was formed by a merger of Visigenic
and Borland. These folks make CORBA development tools for both C++ and Java. They're not free, but you can download
them for a free trial, so I included them.
Non-CORBA ORBs
HORB
HORB has been around for quite a while (at least in Java terms). Free for commercial use in unmodified binary form.
RMI
RMI comes with JDK 1.1 or better, and a version for JDK 1.0.2 is available from this link.
... and that's all I've got so far; if you hear of any others, please let me know.
Links to other pages on CORBA and distributed computing
Awards!
The Free CORBA page has been awarded a "Key Resource" Award for the topic of CORBA by Links2Go. From their docs,
they use some sort of intelligent agent to analyze and cross-reference pages, and pick out the 50 pages that are "most
representative" of the topic at hand.
Links2Go
Corba
The Free CORBA page has also been chosen as a Five Star Selection by itmWEB, which maintains a listing of pages that
should be useful for information technology professionals.
June 18, 2001
Rogue Wave Software
Announces Stingray Objective
CUSTOMER ID Studio 2001
Read More
© 2001 Copyright Rogue Wave Software, Inc. All Rights Reserved. Rogue Wave and .h++ are registered trademarks of
Rogue Wave Software, Inc. SourcePro and XML Link are trademarks of Rogue Wave Software, Inc. Solution Services,
Assessment Service, Consulting Services, Project Success Service, Upgrade Service and Education Services are
trademarks of Rogue Wave Software, Inc. All other trademarks are the property of their respective owners.
[email protected]
#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */
/* NOT REACHED */
return 0;
}
#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */
struct employee {
int number;
int id;
char first_name[20];
char last_name[30];
char department[30];
int room_number;
};
to->number = from->number;
to->id = from->id;
strcpy(to->first_name, from->first_name);
strcpy(to->last_name, from->last_name);
strcpy(to->department, from->department);
to->room_number = from->room_number;
/* unlock mutex */
rc = pthread_mutex_unlock(&a_mutex);
}
while (1) {
/* set employee of the day to be the one with number 'my_num'. */
copy_employee(&employees[my_num-1], &employee_of_the_day);
}
}
/* compare employees */
if (eotd.id != worker->id) {
printf("mismatching 'id' , %d != %d (loop '%d')\n",
eotd.id, worker->id, i);
exit(0);
}
if (strcmp(eotd.first_name, worker->first_name) != 0) {
printf("mismatching 'first_name' , %s != %s (loop '%d')\n",
eotd.first_name, worker->first_name, i);
exit(0);
}
if (strcmp(eotd.last_name, worker->last_name) != 0) {
printf("mismatching 'last_name' , %s != %s (loop '%d')\n",
eotd.last_name, worker->last_name, i);
exit(0);
}
if (strcmp(eotd.department, worker->department) != 0) {
printf("mismatching 'department' , %s != %s (loop '%d')\n",
eotd.department, worker->department, i);
exit(0);
}
if (eotd.room_number != worker->room_number) {
printf("mismatching 'room_number' , %d != %d (loop '%d')\n",
eotd.room_number, worker->room_number, i);
exit(0);
}
}
return 0;
}
#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */
struct employee {
int number;
int id;
char first_name[20];
char last_name[30];
char department[30];
int room_number;
};
while (1) {
/* set employee of the day to be the one with number 'my_num'. */
copy_employee(&employees[my_num-1], &employee_of_the_day);
}
}
/* compare employees */
if (eotd.id != worker->id) {
printf("mismatching 'id' , %d != %d (loop '%d')\n",
eotd.id, worker->id, i);
exit(0);
}
if (strcmp(eotd.first_name, worker->first_name) != 0) {
printf("mismatching 'first_name' , %s != %s (loop '%d')\n",
eotd.first_name, worker->first_name, i);
exit(0);
}
if (strcmp(eotd.last_name, worker->last_name) != 0) {
printf("mismatching 'last_name' , %s != %s (loop '%d')\n",
eotd.last_name, worker->last_name, i);
exit(0);
}
if (strcmp(eotd.department, worker->department) != 0) {
printf("mismatching 'department' , %s != %s (loop '%d')\n",
eotd.department, worker->department, i);
exit(0);
}
if (eotd.room_number != worker->room_number) {
printf("mismatching 'room_number' , %d != %d (loop '%d')\n",
eotd.room_number, worker->room_number, i);
exit(0);
}
}
return 0;
}
#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */
#include <stdlib.h> /* rand() and srand() functions */
/*
* function add_request(): add a request to the requests list
* algorithm: creates a request structure, adds to the list, and
* increases number of pending requests by one.
* input: request number, linked list mutex.
* output: none.
*/
void
add_request(int request_num,
pthread_mutex_t* p_mutex,
pthread_cond_t* p_cond_var)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to newly added request. */
#ifdef DEBUG
printf("add_request: added request with id '%d'\n", a_request->number);
fflush(stdout);
#endif /* DEBUG */
/* unlock mutex */
rc = pthread_mutex_unlock(p_mutex);
/*
* function get_request(): gets the first pending request from the requests list
* removing it from the list.
* algorithm: creates a request structure, adds to the list, and
* increases number of pending requests by one.
* input: request number, linked list mutex.
* output: pointer to the removed request, or NULL if none.
* memory: the returned request need to be freed by the caller.
*/
struct request*
get_request(pthread_mutex_t* p_mutex)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to request. */
if (num_requests > 0) {
a_request = requests;
requests = a_request->next;
if (requests == NULL) { /* this was the last request on the list */
last_request = NULL;
}
/* decrease the total number of pending requests */
num_requests--;
}
else { /* requests list is empty */
a_request = NULL;
}
/* unlock mutex */
rc = pthread_mutex_unlock(p_mutex);
/*
* function handle_request(): handle a single given request.
* algorithm: prints a message stating that the given thread handled
* the given request.
* input: request pointer, id of calling thread.
* output: none.
*/
void
handle_request(struct request* a_request, int thread_id)
{
if (a_request) {
printf("Thread '%d' handled request '%d'\n",
thread_id, a_request->number);
fflush(stdout);
}
}
/*
* function handle_requests_loop(): infinite loop of requests handling
* algorithm: forever, if there are requests to handle, take the first
* and handle it. Then wait on the given condition variable,
* and when it is signaled, re-do the loop.
* increases number of pending requests by one.
* input: id of thread, for printing purposes.
* output: none.
*/
void*
handle_requests_loop(void* data)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to a request. */
int thread_id = *((int*)data); /* thread identifying number */
#ifdef DEBUG
printf("Starting thread '%d'\n", thread_id);
fflush(stdout);
#endif /* DEBUG */
#ifdef DEBUG
printf("thread '%d' after pthread_mutex_lock\n", thread_id);
fflush(stdout);
#endif /* DEBUG */
/* do forever.... */
while (1) {
#ifdef DEBUG
printf("thread '%d', num_requests = %d\n", thread_id, num_requests);
fflush(stdout);
#endif /* DEBUG */
if (num_requests > 0) { /* a request is pending */
a_request = get_request(&request_mutex);
if (a_request) { /* got a request - handle it and free it */
/* unlock mutex - so other threads would be able to handle */
/* other reqeusts waiting in the queue paralelly. */
rc = pthread_mutex_unlock(&request_mutex);
handle_request(a_request, thread_id);
free(a_request);
/* and lock the mutex again. */
rc = pthread_mutex_lock(&request_mutex);
}
}
else {
/* wait for a request to arrive. note the mutex will be */
/* unlocked here, thus allowing other threads access to */
/* requests list. */
#ifdef DEBUG
printf("thread '%d' before pthread_cond_wait\n", thread_id);
fflush(stdout);
#endif /* DEBUG */
rc = pthread_cond_wait(&got_request, &request_mutex);
/* and after we return from pthread_cond_wait, the mutex */
/* is locked again, so we don't need to lock it ourselves */
#ifdef DEBUG
printf("thread '%d' after pthread_cond_wait\n", thread_id);
fflush(stdout);
#endif /* DEBUG */
}
}
}
return 0;
}
#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */
#include <stdlib.h> /* rand() and srand() functions */
/*
* function add_request(): add a request to the requests list
* algorithm: creates a request structure, adds to the list, and
* increases number of pending requests by one.
* input: request number, linked list mutex.
* output: none.
*/
void
add_request(int request_num,
pthread_mutex_t* p_mutex,
pthread_cond_t* p_cond_var)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to newly added request. */
#ifdef DEBUG
printf("add_request: added request with id '%d'\n", a_request->number);
fflush(stdout);
#endif /* DEBUG */
/* unlock mutex */
rc = pthread_mutex_unlock(p_mutex);
/*
* function get_request(): gets the first pending request from the requests list
* removing it from the list.
* algorithm: creates a request structure, adds to the list, and
* increases number of pending requests by one.
* input: request number, linked list mutex.
* output: pointer to the removed request, or NULL if none.
* memory: the returned request need to be freed by the caller.
*/
struct request*
get_request(pthread_mutex_t* p_mutex)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to request. */
if (num_requests > 0) {
a_request = requests;
requests = a_request->next;
if (requests == NULL) { /* this was the last request on the list */
last_request = NULL;
}
/* decrease the total number of pending requests */
num_requests--;
}
else { /* requests list is empty */
a_request = NULL;
}
/* unlock mutex */
rc = pthread_mutex_unlock(p_mutex);
/*
* function handle_requests_loop(): infinite loop of requests handling
* algorithm: forever, if there are requests to handle, take the first
* and handle it. Then wait on the given condition variable,
* and when it is signaled, re-do the loop.
* increases number of pending requests by one.
* input: id of thread, for printing purposes.
* output: none.
*/
void*
handle_requests_loop(void* data)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to a request. */
int thread_id = *((int*)data); /* thread identifying number */
#ifdef DEBUG
printf("Starting thread '%d'\n", thread_id);
fflush(stdout);
#endif /* DEBUG */
#ifdef DEBUG
printf("thread '%d' after pthread_mutex_lock\n", thread_id);
fflush(stdout);
#endif /* DEBUG */
/* do forever.... */
while (1) {
#ifdef DEBUG
printf("thread '%d', num_requests = %d\n", thread_id, num_requests);
fflush(stdout);
#endif /* DEBUG */
if (num_requests > 0) { /* a request is pending */
a_request = get_request(&request_mutex);
if (a_request) { /* got a request - handle it and free it */
/* unlock mutex - so other threads would be able to handle */
/* other reqeusts waiting in the queue paralelly. */
rc = pthread_mutex_unlock(&request_mutex);
handle_request(a_request, thread_id);
free(a_request);
/* and lock the mutex again. */
rc = pthread_mutex_lock(&request_mutex);
}
}
else {
/* CHANGE 2 - the thread checks the flag before waiting */
/* on the condition variable. */
/* if no new requests are going to be generated, exit. */
if (done_creating_requests) {
#ifdef DEBUG
printf("thread '%d' unlocking mutex before exiting\n",
thread_id);
fflush(stdout);
#endif /* DEBUG */
pthread_mutex_unlock(&request_mutex);
printf("thread '%d' exiting\n", thread_id);
fflush(stdout);
pthread_exit(NULL);
}
else {
#ifdef DEBUG
printf("thread '%d' going to sleep\n", thread_id);
#endif /* DEBUG */
}
rc = pthread_mutex_lock(&request_mutex);
done_creating_requests = 1;
rc = pthread_cond_broadcast(&got_request);
rc = pthread_mutex_unlock(&request_mutex);
}
pthread_join(p_threads[i], &thr_retval);
}
printf("Glory, we are done.\n");
return 0;
}
#include <stdlib.h> /* malloc() and free() */
#include <assert.h> /* assert() */
/*
* function init_requests_queue(): create a requests queue.
* algorithm: creates a request queue structure, initialize with given
* parameters.
* input: queue's mutex, queue's condition variable.
* output: none.
*/
struct requests_queue*
init_requests_queue(pthread_mutex_t* p_mutex, pthread_cond_t* p_cond_var)
{
struct requests_queue* queue =
(struct requests_queue*)malloc(sizeof(struct requests_queue));
if (!queue) {
fprintf(stderr, "out of memory. exiting\n");
exit(1);
}
/* initialize queue */
queue->requests = NULL;
queue->last_request = NULL;
queue->num_requests = 0;
queue->p_mutex = p_mutex;
queue->p_cond_var = p_cond_var;
return queue;
}
/*
* function add_request(): add a request to the requests list
* algorithm: creates a request structure, adds to the list, and
* increases number of pending requests by one.
* input: pointer to queue, request number.
* output: none.
*/
void
add_request(struct requests_queue* queue, int request_num)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to newly added request. */
#ifdef DEBUG
printf("add_request: added request with id '%d'\n", a_request->number);
fflush(stdout);
#endif /* DEBUG */
/* unlock mutex */
rc = pthread_mutex_unlock(queue->p_mutex);
/*
* function get_request(): gets the first pending request from the requests list
* removing it from the list.
* algorithm: creates a request structure, adds to the list, and
* increases number of pending requests by one.
* input: pointer to requests queue.
* output: pointer to the removed request, or NULL if none.
* memory: the returned request need to be freed by the caller.
*/
struct request*
get_request(struct requests_queue* queue)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to request. */
if (queue->num_requests > 0) {
a_request = queue->requests;
queue->requests = a_request->next;
if (queue->requests == NULL) { /* this was last request on the list */
queue->last_request = NULL;
}
/* decrease the total number of pending requests */
queue->num_requests--;
}
else { /* requests list is empty */
a_request = NULL;
}
/* unlock mutex */
rc = pthread_mutex_unlock(queue->p_mutex);
/*
* function get_requests_number(): get the number of requests in the list.
* input: pointer to requests queue.
* output: number of pending requests on the queue.
*/
int
get_requests_number(struct requests_queue* queue)
{
int rc; /* return code of pthreads functions. */
int num_requests; /* temporary, for result. */
/* sanity check */
assert(queue);
num_requests = queue->num_requests;
/* unlock mutex */
rc = pthread_mutex_unlock(queue->p_mutex);
return num_requests;
}
/*
* function delete_requests_queue(): delete a requests queue.
* algorithm: delete a request queue structure, and free all memory it uses.
* input: pointer to requests queue.
* output: none.
*/
void
delete_requests_queue(struct requests_queue* queue)
{
struct request* a_request; /* pointer to a request. */
/*
* function cleanup_free_mutex(): free the mutex, if it's locked.
* input: pointer to a mutex structure.
* output: none.
*/
static void
cleanup_free_mutex(void* a_mutex)
{
pthread_mutex_t* p_mutex = (pthread_mutex_t*)a_mutex;
if (p_mutex)
pthread_mutex_unlock(p_mutex);
}
/*
* function handle_request(): handle a single given request.
* algorithm: prints a message stating that the given thread handled
* the given request.
* input: request pointer, id of calling thread.
* output: none.
*/
static void
handle_request(struct request* a_request, int thread_id)
{
if (a_request) {
int i;
/*
printf("Thread '%d' handled request '%d'\n",
thread_id, a_request->number);
fflush(stdout);
*/
for (i = 0; i<100000; i++)
;
}
}
/*
* function handle_requests_loop(): infinite loop of requests handling
* algorithm: forever, if there are requests to handle, take the first
* and handle it. Then wait on the given condition variable,
* and when it is signaled, re-do the loop.
* increases number of pending requests by one.
* input: id of thread, for printing purposes.
* output: none.
*/
void*
handle_requests_loop(void* thread_params)
{
int rc; /* return code of pthreads functions. */
struct request* a_request; /* pointer to a request. */
struct handler_thread_params *data;
/* hadler thread's parameters */
#ifdef DEBUG
printf("thread '%d' after pthread_mutex_lock\n", data->thread_id);
fflush(stdout);
#endif /* DEBUG */
/* do forever.... */
while (1) {
int num_requests = get_requests_number(data->requests);
#ifdef DEBUG
printf("thread '%d', num_requests = %d\n",
data->thread_id, num_requests);
fflush(stdout);
#endif /* DEBUG */
if (num_requests > 0) { /* a request is pending */
a_request = get_request(data->requests);
if (a_request) { /* got a request - handle it and free it */
/* unlock mutex - so other threads would be able to handle */
/* other reqeusts waiting in the queue paralelly. */
rc = pthread_mutex_unlock(data->request_mutex);
handle_request(a_request, data->thread_id);
free(a_request);
/* and lock the mutex again. */
rc = pthread_mutex_lock(data->request_mutex);
}
}
else {
/* the thread checks the flag before waiting */
/* on the condition variable. */
/* if no new requests are going to be generated, exit. */
if (done_creating_requests) {
pthread_mutex_unlock(data->request_mutex);
printf("thread '%d' exiting\n", data->thread_id);
fflush(stdout);
pthread_exit(NULL);
}
/* wait for a request to arrive. note the mutex will be */
/* unlocked here, thus allowing other threads access to */
/* requests list. */
#ifdef DEBUG
printf("thread '%d' before pthread_cond_wait\n", data->thread_id);
fflush(stdout);
#endif /* DEBUG */
rc = pthread_cond_wait(data->got_request, data->request_mutex);
/* and after we return from pthread_cond_wait, the mutex */
/* is locked again, so we don't need to lock it ourselves */
#ifdef DEBUG
printf("thread '%d' after pthread_cond_wait\n", data->thread_id);
fflush(stdout);
#endif /* DEBUG */
}
}
/*
* create a handler threads pool. associate it with the given mutex
* and condition variables.
*/
struct handler_threads_pool*
init_handler_threads_pool(pthread_mutex_t* p_mutex,
pthread_cond_t* p_cond_var,
struct requests_queue* requests)
{
struct handler_threads_pool* pool =
(struct handler_threads_pool*)malloc(sizeof(struct handler_threads_pool));
if (!pool) {
fprintf(stderr, "init_handler_threads_pool: out of memory. exiting\n");
exit(1);
}
/* initialize queue */
pool->threads = NULL;
pool->last_thread = NULL;
pool->num_threads = 0;
pool->max_thr_id = 0;
pool->p_mutex = p_mutex;
pool->p_cond_var = p_cond_var;
pool->requests = requests;
return pool;
}
/* sanity check */
assert(pool);
/* remove the first thread from the threads pool (do NOT cancel the thread) */
static struct handler_thread*
remove_first_handler_thread(struct handler_threads_pool* pool)
{
struct handler_thread* a_thread = NULL; /* temporary holder */
/* sanity check */
assert(pool);
return a_thread;
}
/* delete the first thread from the threads pool (and cancel the thread) */
void
delete_handler_thread(struct handler_threads_pool* pool)
{
struct handler_thread* a_thread; /* the thread to cancel */
/* sanity check */
assert(pool);
a_thread = remove_first_handler_thread(pool);
if (a_thread) {
pthread_cancel(a_thread->thread);
free(a_thread);
}
}
/* get the number of handler threads currently in the threads pool */
int
get_handler_threads_number(struct handler_threads_pool* pool)
{
/* sanity check */
assert(pool);
return pool->num_threads;
}
/*
* free the resources taken by the given requests queue,
* and cancel all its threads.
*/
void
delete_handler_threads_pool(struct handler_threads_pool* pool)
{
void* thr_retval; /* thread's return value */
struct handler_thread* a_thread; /* one thread's structure */
/* sanity check */
assert(pool);
add_request(requests, i);
num_requests = get_requests_number(requests);
num_threads = get_handler_threads_number(handler_threads);
/* if there are too many requests on the queue, spawn new threads */
/* if there are few requests and too many handler threads, cancel */
/* a handler thread. */
if (num_requests > HIGH_REQUESTS_WATERMARK &&
num_threads < MAX_NUM_HANDLER_THREADS) {
printf("main: adding thread: '%d' requests, '%d' threads\n",
num_requests, num_threads);
add_handler_thread(handler_threads);
}
if (num_requests < LOW_REQUESTS_WATERMARK &&
num_threads > NUM_HANDLER_THREADS) {
printf("main: deleting thread: '%d' requests, '%d' threads\n",
num_requests, num_threads);
delete_handler_thread(handler_threads);
}
rc = pthread_mutex_lock(&request_mutex);
done_creating_requests = 1;
rc = pthread_cond_broadcast(&got_request);
rc = pthread_mutex_unlock(&request_mutex);
}
/* cleanup */
delete_handler_threads_pool(handler_threads);
delete_requests_queue(requests);
return 0;
}
Index of
/~choo/lupg/tutorials/multi-thread/thread-pool-server-changes
● Parent Directory
● Makefile
● handler_thread.c
● handler_thread.h
● handler_threads_pool.c
● handler_threads_pool.h
● main.c
● requests_queue.c
● requests_queue.h
#include <stdio.h> /* standard I/O routines */
#include <pthread.h> /* pthread functions and data structures */
/* flag to denote if the user requested to cancel the operation in the middle */
/* 0 means 'no'. */
int cancel_operation = 0;
/*
* function: restore_coocked_mode - restore normal screen mode.
* algorithm: uses the 'stty' command to restore normal screen mode.
* serves as a cleanup function for the user input thread.
* input: none.
* output: none.
*/
void
restore_coocked_mode(void* dummy)
{
#ifdef DEBUG
printf("restore_coocked_mode: before 'stty -raw echo'\n\r");
fflush(stdout);
#endif /* DEBUG */
system("stty -raw echo");
#ifdef DEBUG
printf("restore_coocked_mode: after 'stty -raw echo'\n\r");
fflush(stdout);
#endif /* DEBUG */
}
/*
* function: read_user_input - read user input while long operation in progress.
* algorithm: put screen in raw mode (without echo), to allow for unbuffered
* input.
* perform an endless loop of reading user input. If user
* pressed 'e', signal our condition variable and end the thread.
* input: none.
* output: none.
*/
void*
read_user_input(void* data)
{
int c;
/*
* function: file_line_count - counts the number of lines in the given file.
* algorithm: open the data file, read it character by character, and count
* all newline characters.
* input: file name.
* output: number of lines in the given file.
*/
void*
file_line_count(void* data)
{
char* data_file = (char*)data;
FILE* f = fopen(data_file, "r");
int wc = 0;
int c;
if (!f) {
perror("fopen");
exit(1);
}
fclose(f);
return (void*)wc;
}
#ifdef DEBUG
printf("\n\rmain: we got signaled\n\n\r");
fflush(stdout);
#endif /* DEBUG */
return 0;
}
Links2Go
Gnu
What Is SmartGDB
This is a brief (1 page) summary of what SmartGDB is.
Introduction
This document provides an introduction to SmartGDB and an overview of the driving
problems SmartGDB attempts to solve.
Previous Work
This document details the previous work done on SmartGDB by other students.
Working With SmartGDB
This document presents a set of debugging results obtained with SmartGDB.
Documentation
These pages provide documentation on the SmartGDB thread interface and on using
Tcl/Tk inside SmartGDB.
Credits
Credits for SmartGDB go to...
/* now enter a loop of reading data from the pipe, and printing it */
while ((rc = read(data_pipe[0], &c, 1)) > 0) {
putchar(c);
}
/* now enter a loop of read user input, and writing it to the pipe. */
while ((c = getchar()) > 0) {
/* write the character to the pipe. */
rc = write(data_pipe[1], &c, 1);
if (rc == -1) { /* write failed - notify the user and exit */
perror("Parent: write");
close(data_pipe[1]);
exit(1);
}
}
/* now fork off a child process, and set their handling routines. */
pid = fork();
switch (pid) {
case -1: /* fork failed. */
perror("fork");
exit(1);
case 0: /* inside child process. */
do_child(data_pipe);
/* NOT REACHED */
default: /* inside parent process. */
do_parent(data_pipe);
/* NOT REACHED */
}
/* loop: read input from user, send via one pipe to the translator, */
/* read via other pipe what the translator returned, and write to */
/* stdout. exit on EOF from user. */
while ((c = getchar()) > 0) {
/* write to translator */
rc = write(output_pipe[1], &c, 1);
if (rc == -1) { /* write failed - notify the user and exit. */
perror("user_handler: write");
close(input_pipe[0]);
close(output_pipe[1]);
exit(1);
}
/* read back from translator */
rc = read(input_pipe[0], &c, 1);
if (rc <= 0) { /* read failed - notify user and exit. */
perror("user_handler: read");
close(input_pipe[0]);
close(output_pipe[1]);
exit(1);
}
/* print translated character to stdout. */
putchar(c);
}
/* now fork off a child process, and set their handling routines. */
pid = fork();
switch (pid) {
case -1: /* fork failed. */
perror("main: fork");
exit(1);
case 0: /* inside child process. */
translator(user_to_translator, translator_to_user); /* line 'A' */
/* NOT REACHED */
default: /* inside parent process. */
user_handler(translator_to_user, user_to_translator); /* line 'B' */
/* NOT REACHED */
}
#include <stdio.h>
#include <unistd.h>
void main()
{
FILE* plan;
int count = 0;
count++;
fprintf(plan, "I have been fingered %d times today\n", count);
/* close the named pipe. This will cause the reader to get an EOF */
fclose(plan);
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
if (queue_id == -1) {
perror("main: msgget");
exit(1);
}
printf("message queue created, queue id '%d'.\n", queue_id);
msg = (struct msgbuf*)malloc(sizeof(struct msgbuf)+strlen("hello world"));
msg->mtype = 1;
strcpy(msg->mtext, "hello world");
rc = msgsnd(queue_id, msg, strlen(msg->mtext)+1, 0);
if (rc == -1) {
perror("main: msgsnd");
exit(1);
}
free(msg);
printf("message placed on the queue successfully.\n");
recv_msg = (struct msgbuf*)malloc(sizeof(struct msgbuf)+strlen("hello
world"));
rc = msgrcv(queue_id, recv_msg, strlen("hello world")+1, 0, 0);
if (rc == -1) {
perror("main: msgrcv");
exit(1);
}
return 0;
}
/*
* queue_sender.c - a program that reads messages with one of 3 identifiers
* to a message queue.
*/
/* create a public message queue, with access only to the owning user. */
queue_id = msgget(QUEUE_ID, IPC_CREAT | IPC_EXCL | 0600);
if (queue_id == -1) {
perror("main: msgget");
exit(1);
}
printf("message queue created, queue id '%d'.\n", queue_id);
msg = (struct msgbuf*)malloc(sizeof(struct msgbuf)+MAX_MSG_SIZE);
return 0;
}
/*
* queue_reader.c - a program that reads messages with a given identifier
* off of a message queue.
*/
/* access the public message queue that the sender program created. */
queue_id = msgget(QUEUE_ID, 0);
if (queue_id == -1) {
perror("main: msgget");
exit(1);
}
printf("message queue opened, queue id '%d'.\n", queue_id);
msg = (struct msgbuf*)malloc(sizeof(struct msgbuf)+MAX_MSG_SIZE);
This directory contains the source code for two programs - queue_sender,
that sends messages of different types to message queues, and queue_reader,
that reads messages of a given type from the same message queue.
To compile the programs, type 'make' (or 'gmake', to use gnu make).
Experiment with running these programs. The queue_sender will create 100
messages of types 1, 2 or 3, and then exit. The queue_reader may then
be run with a parameter denoting the type of messages it should read
(1, 2 or 3). Thus, in order to read out all messages, you should run three
copies of queue_reader, one with each message type. You may also try to
run more then one copy of the reader program for a given message type, and see
how they consume the messages.
Check what happens when you run the reader before running the sender.
You may also check the message queue created by the sender program,
by issuing the following command:
ipcs -q
If done after running the sender, and before running the reader, you will
see something similar to this:
note that the 'msgid' field contains a value that is different from what
was supplied to the 'msgget()' system call by the sender program. This is
the value that you should use when trying to remove the message
queue, using the 'ipcrm' program.
Try to check the message queue size after when killing the queue_reader
program in the middle of the run (using Ctrl-C, or the 'kill' command).
/*
* sem-mutex.c - demonstrates the usage of a semaphore as a mutex that
* that synchronizes accesses of multiple processes
* to a file.
*/
/* this function updates the contents of the file with the given path name. */
void update_file(int sem_set_id, char* file_path, int number)
{
/* structure for semaphore operations. */
struct sembuf sem_op;
FILE* file;
/* Comment 2 */
/* we "locked" the semaphore, and are assured exclusive access to file. */
/* manipulate the file in some way. for example, write a number into it. */
file = fopen(file_path, "w");
if (file) {
fprintf(file, "%d\n", number);
printf("%d\n", number);
fclose(file);
}
wait(&child_status);
}
return 0;
}
/*
* tiny-lpr.c - a tiny printing command. Gets a file path, and copies that
* file to the spool directory, from which it'll be later
* fetched by a printer daemon.
*/
/*
* function: make_filename. creates a unique file name for the spool directory.
* input: none.
* output: a unique file name.
*/
static char*
make_filename()
{
int counter; /* contents of counter file, as integer. */
static char buf[200]; /* contents of counter file, as string. */
int f_counter; /* pointer to counter file. */
return buf;
}
/*
* function: copyfile. copies a file from one place to a new directory,
* under a new, unique file name.
* input: path to the file to copy, and path to the directory to copy
* it into.
* output: name of the copy of the file.
*/
static char*
copyfile(char* file_path, char* dir_path)
{
char* tmp_file; /* name for temporary file. */
FILE* f_in; /* pointer for source file. */
FILE* f_out; /* pointer for target file. */
char* out_file; /* full path to putput file. */
int c; /* character read/written. */
/* open the input file for reading. open the temporary file for output. */
f_in = fopen(file_path, "r");
if (!f_in) {
fprintf(stderr, "Cannot open file '%s' for reading: \n", file_path);
perror("");
exit(1);
}
f_out = fopen(out_file, "w");
if (!f_out) {
fprintf(stderr, "Cannot open file '%s' for output: \n", out_file);
perror("");
exit(1);
}
fclose(f_in);
fclose(f_out);
return tmp_file;
}
/*
* function: main. perform the whole operation.
* intput: path to file to copy into spool directory.
* output: messages regarding success or failure of the operation.
*/
void
main(int argc, char* argv[])
{
int sem_set_id; /* ID of the semaphore set. */
char* file_path; /* path to the file to print. */
char* tmp_file; /* name of copied file in spool area. */
int rc; /* return value of system calls. */
char tmp_file_path[MAX_PATH]; /* name of copied file in 'in' area. */
char tmp_file_out[MAX_PATH]; /* name of copied file in 'common' area. */
/* check that the file exists, and that we can read it. */
if (access(file_path, F_OK) == -1) {
fprintf(stderr, "%s: file '%s' does not exist.\n", argv[0], file_path);
exit(1);
}
if (access(file_path, R_OK) == -1) {
fprintf(stderr, "%s: file '%s': cannot access.\n", argv[0], file_path);
exit(1);
}
/*
* function: print_file. send a given file to the printer for printing.
* intput: file path.
* output: none.
*/
void
print_file(char* file_path)
{
/* in a real printer daemon, here would come all the nasty */
/* tasks of communicating with the printer using a postscript */
/* driver or some other interface..... */
/*
* function: main. perform the whole operation.
* intput: none.
* output: messages regarding success or failure of operations.
*/
void
main(int argc, char* argv[])
{
int sem_set_id; /* ID of the semaphore set. */
DIR* spool_dir; /* spool directory contents struct. */
struct dirent* dir_entry; /* one entry of spool directory. */
char file_source[MAX_PATH]; /* path to file we operate on. */
char file_target[MAX_PATH]; /* path to file after copying to 'out'. */
int found; /* was a file found in the dir. scan? */
spool_dir = opendir(SPOOL_DIR_COMMON);
if (!spool_dir) {
fprintf(stderr, "%s: Failed opening directory '%s': ",
argv[0], SPOOL_DIR_COMMON);
perror("");
fprintf(stderr, "%s: aborting.\n", argv[0]);
exit(1);
}
/* start reading the directory's contents. */
found = 0;
while ( (dir_entry = readdir(spool_dir)) != NULL) {
/* skip the '.' and '..' entries. */
if (strcmp(dir_entry->d_name, ".") == 0)
continue;
if (strcmp(dir_entry->d_name, "..") == 0)
continue;
/* we found a file. */
found = 1;
/* move file to 'out' spool sub-directory. */
sprintf(file_source, "%s/%s", SPOOL_DIR_COMMON, dir_entry->d_name);
sprintf(file_target, "%s/%s", SPOOL_DIR_OUT, dir_entry->d_name);
if (rename(file_source, file_target) == -1) {
fprintf(stderr, "%s: cannot move file '%s/%s' to '%s':\n",
argv[0], SPOOL_DIR_COMMON, dir_entry->d_name,
SPOOL_DIR_OUT);
perror("");
fprintf(stderr, "%s: aborting.\n", argv[0]);
exit(1);
}
/* free the mutex semaphore. */
sem_signal_mutex(sem_set_id);
This directory contains the source code for two programs - tiny-lpr,
that spools files for printing, and tiny-lpd, a printing daemon that takes
files from the spool directory and sends tem to the printer, one file
at a time.
To compile the programs, type 'make' (or 'gmake', to use gnu make).
Experiment with running these programs. Check what happens if you run multiple
'tiny-lpr' (producer) processes at the same time. Check how the system
works if more then one printer daemon (tiny-lpd) is being run at the same time.
Try modifying the system so that only a single printer daemon may be running
at the same time.
Note: to ease running the programs, the spool directoy path is given as
a relative path (this of-course must be changed to a full path in a real
system). Thus, you should run both programs from the source directory in order
for them to work, or modify the file path macro SPOOL_DIR in file
'tiny-lp-common.h' to a full path, and copy the contents of the 'tiny-spooldir'
directory to the new location.
You may also check the semaphore set created by the tiny-lpd program,
by issuing the following command:
ipcs -s
If done after running tiny-lpd, you will see something similar to this:
note that the 'msgid' field contains a value that is different from what
was supplied to the 'semget()' system call by the tiny-lpd program. This is
the value that you should use when trying to remove the semaphore set,
using the 'ipcrm' command.
/*
* shared-mem.c - demonstrates basic usage of shared memory.
*/
strcpy(countries[0].capital_city, "U.S.A");
strcpy(countries[0].capital_city, "Washington");
strcpy(countries[0].currency, "U.S. Dollar");
countries[0].population = 250000000;
(*countries_num)++;
strcpy(countries[1].capital_city, "Israel");
strcpy(countries[1].capital_city, "Jerusalem");
strcpy(countries[1].currency, "New Israeli Shekel");
countries[1].population = 6000000;
(*countries_num)++;
strcpy(countries[1].capital_city, "France");
strcpy(countries[1].capital_city, "Paris");
strcpy(countries[1].currency, "Frank");
countries[1].population = 60000000;
(*countries_num)++;
/* detach the shared memory segment from our process's address space. */
if (shmdt(shm_addr) == -1) {
perror("main: shmdt: ");
}
return 0;
}
/*
* shared-mem-with-semaphore.c - using a semaphore to synchronize access
* to a shared memory segment.
*/
/*
* function: random_delay. delay the executing process for a random number
* of nano-seconds.
* input: none.
* output: none.
*/
void
random_delay()
{
static int initialized = 0;
int random_num;
struct timespec delay; /* used for wasting time. */
if (!initialized) {
srand(time(NULL));
initialized = 1;
}
/*
* function: sem_lock. locks the semaphore, for exclusive access to a resource.
* input: semaphore set ID.
* output: none.
*/
void
sem_lock(int sem_set_id)
{
/* structure for semaphore operations. */
struct sembuf sem_op;
/* wait on the semaphore, unless it's value is non-negative. */
sem_op.sem_num = 0;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
semop(sem_set_id, &sem_op, 1);
}
/*
* function: sem_unlock. un-locks the semaphore.
* input: semaphore set ID.
* output: none.
*/
void
sem_unlock(int sem_set_id)
{
/* structure for semaphore operations. */
struct sembuf sem_op;
/*
* function: add_country. adds a new country to the counties array in the
* shard memory segment. Handles locking using a semaphore.
* input: semaphore id, pointer to countries counter, pointer to
* counties array, data to fill into country.
* output: none.
*/
void
add_country(int sem_set_id, int* countries_num, struct country* countries,
char* country_name, char* capital_city, char* currency,
int population)
{
sem_lock(sem_set_id);
strcpy(countries[*countries_num].name, country_name);
strcpy(countries[*countries_num].capital_city, capital_city);
strcpy(countries[*countries_num].currency, currency);
countries[*countries_num].population = population;
(*countries_num)++;
sem_unlock(sem_set_id);
}
/*
* function: do_child. runs the child process's code, for populating
* the shared memory segment with data.
* input: semaphore id, pointer to countries counter, pointer to
* counties array.
* output: none.
*/
void
do_child(int sem_set_id, int* countries_num, struct country* counties)
{
add_country(sem_set_id, countries_num, counties,
"U.S.A", "Washington", "U.S. Dollar", 250000000);
random_delay();
add_country(sem_set_id, countries_num, counties,
"Israel", "Jerusalem", "New Israeli Shekel", 6000000);
random_delay();
add_country(sem_set_id, countries_num, counties,
"France", "Paris", "Frank", 60000000);
random_delay();
add_country(sem_set_id, countries_num, counties,
"Great Britain", "London", "Pound", 55000000);
}
/*
* function: do_parent. runs the parent process's code, for reading and
* printing the contents of the 'countries' array in the shared
* memory segment.
* input: semaphore id, pointer to countries counter, pointer to
* counties array.
* output: printout of countries array contents.
*/
void
do_parent(int sem_set_id, int* countries_num, struct country* countries)
{
int i, num_loops;
wait(&child_status);
}
/* detach the shared memory segment from our process's address space. */
if (shmdt(shm_addr) == -1) {
perror("main: shmdt: ");
}
return 0;
}
From: Bram Moolenaar <[email protected]>
To: [email protected]
Subject: Vim version 5.8 has been released
Date: Thu, 31 May 2001 17:40:39 +0200
Message-Id: <[email protected]>
Announcement
------------
This is a minor release of Vim. Since version 5.7 has been released (almost
a year ago!) bugs have been fixed and many syntax files have been added.
Vim 5.8 has been tested by quite a few people over the past weeks, and there
are no big changes since version 5.7. This should be the most stable Vim
version ever. But it's free software, the usual disclaimers apply.
Development of Vim 6.0, the next major release, continues. That version
contains many new features and is an unstable version.
What is Vim?
------------
Vim is an almost 100% compatible version of the UNIX editor Vi. Many new
features have been added: Multi level undo, syntax highlighting, command line
history, filename completion, block operations, etc. Those who don't know Vi
can probably skip this message, unless you are prepared to learn something new
and useful. Vim is especially recommended for editing programs.
Vim runs on almost any Unix flavor, MS-DOS, MS-Windows 3.1, MS-Windows
95/98/ME/NT/2000/XP, OS/2, Atari MiNT, BeOS, VMS, RISC OS, Macintosh and
Amiga.
Ctags is no longer included, it has grown into a project of its own. You can
find it at http://ctags.sf.net.
Where to get it
---------------
You can find a list of distribution sites at
ftp://ftp.vim.org/pub/vim/MIRRORS
Suggested locations:
ftp://ftp.<country>.vim.org/pub/vim/
ftp://ftp.vim.org/pub/vim/
ftp://ftp.us.vim.org/pub/vim/
What is available
-----------------
Note that for all systems the distribution is split into an archive with
runtime files (documentation, syntax files, etc.) and a binary and/or source
archive. You should download at least two archives!
(*) Also for BeOS, OS/2, VMS, Macintosh and Atari MiNT
Mailing lists
-------------
For user questions you can turn to the Vim mailing list. There are a lot of
tips, scripts and solutions. You can ask your Vim questions, but only if you
subscribe. See http://www.vim.org/mail.html. An archive is kept at
http://www.egroups.com/group/vim.
If you want to help developing Vim or get the latest patches, subscribe to the
vim-dev mailing list. An archive is kept at
http://www.egroups.com/group/vimdev.
Reporting bugs
--------------
Send them to <[email protected]>. Please be brief, all the time spent on answering
mail is subtracted from the time that is spent on improving Vim! Always give
a reproducable example and try to find out which settings or other things
influence the appearance of the bug. Try different machines if possible. See
":help bugs" in Vim. Send me patches if you can!
Happy Vimming!
--
"Oh, no! NOT the Spanish Inquisition!"
"NOBODY expects the Spanish Inquisition!!!"
-- Monty Python sketch --
"Oh, no! NOT another option!"
"EVERYBODY expects another option!!!"
-- Discussion in vim-dev mailing list --
The user manual is complete now. You are invited to start proof reading.
Keep in mind that it only contains the most useful features, not every detail.
Major changes
-------------
The distribution files for Unix have been reorganised. The ".gz" files are
now small enough to fit on a floppy. These can be used by (old) standalone
systems. There is one big ".bz2" file that contains everything.
Other changes
-------------
Added the "-M" Vim argument: reset 'modifiable' and 'write', thus disallow
making changes and writing files.
GTK: Allow dropping a http:// and ftp:// URL on Vim. The netrw plugin takes
care of downloading the file. (MiKael Berthe)
Added the 'imcmdline' option: When set the input method is always enabled when
starting to edit a command line. Useful for a XIM that uses dead keys to type
accented characters.
Made CTRL-^ in Insert mode and when editing the command line toggle the use of
an input method when no language mappings are present. Allows switching the
IM back on when halfway typing a line.
":silent !cmd" no longer redraws the screen. The user must use CTRL-L if he
wants a redraw.
Fixes
-----
VMS does not allow function names longer than 31 characters. Renamed
gui_motif_create_fontlist_from_fontset() to gui_motif_fontset2fontlist().
menu.c didn't compile without the multi-language feature when the toolbar is
used. (Maurice Barnum)
When configure was told to use the workshop feature, it would still select the
GTK GUI by default. Give an error message when trying to use workshop without
Motif.
It was possible to make a symlink with the name of a swap file, linking to a
file that doesn't exist. Vim would then silently use another file (if open
with O_EXCL refuses a symlink). Now check for a symlink to exist. Also do
another check for an existing swap file just before creating it to catch a
symlink attack.
When using "vd" to delete an empty line, the first multibyte character in the
next line could be damaged. (Muraoka Taro)
The output of "g CTRL-G" mentioned "Char" but it's actually bytes.
Searching for the end of a oneline region didn't work correctly when there is
an offset for the highlighting.
Athena: The triangle for a submenu could be allocated at the wrong moment.
(David Harrison)
"vimtutor" used "test -e". Apparently not all systems support that. Use
"test -f" instead.
Mac: Vim was eating 80% of the CPU time. (Dany St-Amant)
GTK: When leaving Insert mode the XIM status wasn't obtained correctly. When
re-entering Insert mode it would be disabled.
Folding: When 'foldmethod' is "marker", inserting a line break before a marker
opened folds below it. Was updating the folds twice, once for inserting the
line, which caused all following folds to become nested.
":silent":
- Various commands still produced a message with ":silent": ":write",
":substitute", ":put, ":delete".
- Redirecting messages and using ":silent highlight" doesn't produce the same
output as without the ":silent". Now at least insert one space.
Epilogue
--------
WARNING: This is really an unstable version. Many things have been added
without proper testing. It does crash. It may destroy your work. New
features may change incompatibly in the next version.
More info about the new 6.0 features with ":help version6".
If you don't like the syntax of a command, the name of an option or how the
new features work, let's discuss this in the vim-dev maillist.
Lots of things are not working yet. Check ":help todo" for known items.
Happy Vimming!
Sven Guckes [email protected]
Vim - Distribution and Download ©1995-2001 Last update: Sat Jun 09
14:00:00 MEST 2001
If you need assistance then please hesitate to write until after you've read the following: ;-)
Vim comes in two parts: One archive holds the program (either as source or binary/executable), and another archive holds
the runtime files with the documentation and syntax files. This allows you to update Vim as a program without having to
download the latest documentation. But usually you should update the matching documentation, too. ;-)
The ftp mirrors hold binaries for only some operating systems. There are more maintained binaries on other sites which are
listed on the Binaries Page.
OK, now you've read the Download FAQ and you still have questions? OK - send me an email then. Be sure to include some
info on what you want, what you did, and what went wrong. I'll ask you, anyway. You have been warned!
By country name:
http://www.vim.org/dist.html#Name
http://www.vim.org/dist.html#Germany
By city name:
http://www.vim.org/dist.html#City
http://www.vim.org/dist.html#Berlin
If you want to create an ftp mirror or www mirror of Vim then please read the HowTo Mirror - thanks!
Vim Distribution - Overview
FTP Mirrors Overview and WWW Mirrors Overview
❍ Frankfurt
❍ Oldenburg
● ES - Spain: Oviedo
● FR - France:
❍ Gif-Sur-Yvette
❍ Paris
● GR - Greece: Heraklion
● HU - Hungary:
❍ Miskolc
❍ Budapest [001001]
● IT - Italy: [two entries which need to be checked]
● JP - Japan: Tokio
● KR - Korea:
● MX - Mexico:
● NL - Netherlands:
● PL - Poland:
● PT - Portugal:
● RU - Russia:
● SE - Sweden:
● SK - Slovakia:
● TR - Turkey:
● UK - United Kingdom:
● ZA - South Africa:
USA (com,gov,net):
● California (2):
● Maryland:
● Michigan:
● New York:
● Illinois:
● Washington:
● Michigan:
● Florida:
AT - Austria
AT AUSTRIA [990310] Europe, Austria, Vienna: Univ. of Technology
AT AUSTRIA Mirror FTP info: 150 max connections; (MET)
AT AUSTRIA Mirror FTP source: ftp://ftp.home.vim.org/pub/vim/
AT AUSTRIA Mirror FTP target: ftp://ftp.at.vim.org/pub/vim/
AT AUSTRIA Mirror FTP target: http://ftp.at.vim.org/pub/vim/
AT AUSTRIA Mirror FTP contact: Antonin Sprinzl Antonin.Sprinzl(at)tuwien.ac.at
AT AUSTRIA Mirror FTP updates: updated daily
AT AUSTRIA Mirror FTP comment: Access for both ftp and http!
AU - Australia
BE - Belgium
CA - Canada
Coming up!
001012 Yurais Fernandez Leal
DE - Deutschland (Germany)
ES - España (Spain)
FR - France
GR - Greece
HU - Hungary
IT - Italy
Coming up:
JP - Japan
KR - Korea
MX - Mexico
ftp.mx.vim.org [980721,980723]
contact: Felipe Contreras fhca(at)yahoo.com
connections (max): 256
source: FUB
target: ftp://ftp.mx.vim.org/
Mirrored at midnight Mexico time (GMT-6); directory "beta-test" not included in mirror. "There maybe
info: some blackouts every now and then in this university on some holydays like tomorrow, but it should be
ok on average."
NL - Netherlands
PL - Poland
PT - Portugal
SU - Soviet Union
SK - Slovakia
UK - United Kingdom
ZA - South Africa
USA - com/gov/net
USA7 Walla [961024,990101] America, USA, WA, Walla Walla; Whitman College
USA7 Walla Mirror FTP info: 15 max connections; (Pacific Time - PDT/PST)
USA7 Walla Mirror FTP source: -> OCE
USA7 Walla Mirror FTP target: ftp://wastenot.whitman.edu/pub/vim/
USA7 Walla vim.org name ftp://ftp.wa.usa.vim.org/ [990125 todo!]
USA7 Walla Mirror FTP contact: Albert Schueller schuelaw(at)whitman.edu
● CA - Canada:
● ES - España (Spain):
● FR - France:
● IT - Italy:
● KR - Korea:
● LT - Lithuania:
● MX - Mexico:
● NO - Norway:
● PL - Poland:
● SE - Sweden:
● SK - Slovakia: [2 mirrors]
● SU - Soviet Union:
● TR - Turkey:
● COM - Companies
AT - Austria
CA - Canada
CA CANADA Mirror WWW info: 128 max connections; (EDT +5); nightly
CA CANADA Mirror WWW source: http://www.vim.org/
CA CANADA Mirror WWW target: http://www.vmunix.com/vim/
CA CANADA Mirror WWW contact: Mark Mayo mark(at)vmunix.com
CZ - Czech Republic
DE - Deutschland (Germany)
ES - España (Spain)
FR - France
IT - Italy
KR - Korea
LT - Lithuania
MX - Mexico
SE - Sweden
SK - Slovakia
SU - Soviet Union
Historic Files
Stevie
ftp://ftp.funet.fi/pub/amiga/fish/201-300/ff256/Stevie.lha
Vim was once based on Stevie.
Vim-1.14
ftp://ftp.funet.fi/pub/amiga/fish/501-600/ff591/Vim.lha
The first release of Vim on Fred Fish Disk.
● Change entries to allow for extraction for "orig", nickname, "maintainer", "new", and "todo" (*sigh*).
URL: http://www.math.fu-berlin.de/~guckes/vim/distribution.html
URL: http://www.vim.org/dist.html (mirror)
Created: Sun Jan 1 00:00:00 MET 1995
Sven [email protected] ©1995-2001 Last update: Wed Apr 11 12:00:00 MEST 2001
001221: Vim desktop calendar for 2001 - download, print, and fold.
Available in English (A4 and Letter) and Dutch (A4),
as PostScript (compressed with gzip) and PDF.
Made by Bram himself. See his site http://www.moolenaar.net
Merry Christmas, everyone! :-)
001013: New page: Moved the info about Language Ports onto a new page:
http://www.vim.org/langport.html
001001/001003: Updates:
Vim, c'est quoi? (French)
Wat is Vim? (Dutch)
Translations of the short description on Vim in six kilobytes.
Translated by Lyderic Landry [email protected]
and Dion Nicolaas [email protected] - thanks!
Further translations are very very welcome!
000921: KVim - Vim for KDE ('K' Desktop Environment)
Developer: Thomas Capricelli [email protected]
Page: http://aquila.rezel.enst.fr/thomas/vim/
Please give Thomas some feedback!
URL: http://www.math.fu-berlin.de/~guckes/vim/news.html
URL: http://www.vim.org/news.html (mirror)
Created: Mon Nov 16 12:00:00 CET 1998
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Wed Oct 11 11:11:11 MET DST 2000
Search Vim.org
This is the search page of vim.org using the search engine by atomz.com.
Feedback on this service is much appreciated. Is the speed of the search ok? Did it find the pages
you needed? Send your comments to me at [email protected] - thanks!
SEARCH!
Search For:
Search
Match: Any word All words Exact phrase
✔ Sound-alike matching
Within: Anywhere
Show: 10 with
results summaries
Sort by: score
URL: http://www.math.fu-berlin.de/~guckes/vim/search.html
URL: http://www.vim.org/search.html (mirror)
Created: Mon Mar 27 12:00:00 MET DST 2000
Send feedback on this page to
Sven Guckes [email protected]
Sven Guckes [email protected]
©1995-2001
VIM Pictures - Buttons, (Animated) Icons, and Screenshots
Last update: Sat Apr 21 03:03:03
MEST 2001
VIM - Screenshots
So - here are the screenshots. They are linked one by one, so as not to take a lot of load for this
page. Have fun!
To Add:
● http://www2.raidway.ne.jp/%7Eyzone/bin/vim60t-cygwin-telnet.jpg
#
# ////### ///
////### /// ///#### //
///#### // ///#####//
///#####// ///####//
///####// #///###//##
#///###//## ##///##//####
##///##//#### #///#//####
#///#//#### /////####
/////#### ////####
////#### ///####
///#### // ###
// ### #
#
___ ___ _______ _______ ___ ___ __ __ | | ||_ _|| | | | | ||__|.--------. .--.--.|__|.--------. | | | _| |_ | | |
| || || | | | || || | \_____/ |_______||__|_|__| \_____/ |__||__|__|__| \___/ |__||__|__|__| __ __ ___ __
__ __ __ _ _ \ \ / /|_ _|| \/ | \ \ / /(_) _ __ ___ __ __(_) _ __ ___ \ \ / / | | | |\/| | \ \ / / | || '_ ` _ \ \ \ / /|
|| '_ ` _ \ \ V / | | | | | | \ V / | || | | | | | \ V / | || | | | | | \_/ |___||_| |_| \_/ |_||_| |_| |_| \_/ |_||_| |_| |_| _ __
____ __ ___ _ __ _ _ | | / // _// |/ / | | / /(_)____ ___ _ __ (_)____ ___ | | / / / / / /|_/ / | | / // // __
`__ \ | | / // // __ `__ \ | |/ /_/ / / / / / | |/ // // / / / / / | |/ // // / / / / / |___//___//_/ /_/ |___//_//_/ /_/ /_/
|___//_//_/ /_/ /_/ __ __ ___ __ __ __ __ _ _ \ \ / /|_ _|| \/ | \ \ / /(_) _ __ __ __(_) _ __ \ V / | | | |\/|
| \ V / | || ' \ \ V /| || ' \ \_/ |___||_| |_| \_/ |_||_|_|_| \_/ |_||_|_|_| _ __ ____ __ ___ _ __ _ _ | | / // _// |/
/ | | / /(_)__ _ _ __ (_)__ _ | |/ /_/ / / /|_/ / | |/ // // ' \ | |/ // // ' \ |___//___//_/ /_/ |___//_//_/_/_/
|___//_//_/_/_/ _ _ _ __ __ _ _ _ _ | | || || \ \ | | |<_>._ _ _ _ _ <_>._ _ _ | ' || || | | ' || || ' ' | | | || || ' ' |
|__/ |_||_|_|_| |__/ |_||_|_|_| |__/ |_||_|_|_| _____ _____ _____ _____ _ _ | | || || | | | ||_| _____ _ _ |_|
_____ | | ||- -|| | | | | | || || | | | || || | \___/ |_____||_|_|_| \___/ |_||_|_|_| \_/ |_||_|_|_| Submitted by:
Manfred Gruber [email protected] [990303] __ ___ ___ ____ ____ | |\ / /\ / /\ / |\ / |\ | || / /
/ /__/ / / || / || | || / / / \__\/ / /| || / /| || | || / / / ___ / / | || / / | || | || / / / / /\ / / /| || / / /| || | || / / / / / / / / / | ||/
/ / | || | || / / / / / / / / / | |/ / / | || | || / / / / / / / / / | / / | || | || / / / / / / / / / | / / | || | ||/ / / / / / / / / | / / | || | |/ / /
/ / / / / / |__/ / | || | / / / / / / / / \__\/ | || | / / / / / / / / | || | / / / / / / / / | || |__/ / /__/ / /__/ / |__|| \__\/
\__\/ \__\/ \__\|
Vim - HOWTO add your pictures to
this page
Do you have a pictures to add to this page? Then please send it to me via email!
Here are some things to take care of [I hope you'll understand]:
Submission guidelines
Send address or attach
If your send a screenshot then please do not attach your picture to your email; instead,
just tell me whwre I can download it. So please upload you pictures to your own website
and just send me the URL (address) of the picture. That way your pictures are not within
a mail in my mailbox, saving me time on download and startup of the mailer.
If you cannot upload your pictures to a website then please attach the picture to your
mail; this allows for easy extraction of the data to a file.
Format: GIF, JPG, PNG
Please use a format known by many browsers, so I won't have to convert them. GIF
(GIF89a, interlaced), JPEG (use a suitable compression rate) and PNG are all welcome.
Maximum Size 640x480
Please try to take screenshots from 640x480 screens at most. I'd like to the pictures to be
viewable on 14" monitors, too.
That said, larger screenshots are welcome, too, but you'll have to keep in mind that those
who will view it on a 14" monitor will have to scroll around a lot to see it all.
Please let me know about the size of your picture; of course there are tools to find out
about the size, but it would make it easier on me if you simply added this info to your
mails.
Filenames
Please give your pictures a filename which starts with "vim", includes your last name and
the title of the picture, ie in the format vim.yourname.description.gif,
Example: vim.guckes.edit_with_vim.gif
Screenshot Contents: Show Version Number
Please have your vim show its version number on the screenshot. (enter command
":version" or ":intro" in a subwindow). If possible, show the coloring of some
non-standard file - as there are quite a few shots of source files in C, C++, and Fortran.
Name and Address [000818]
I will add your name and address as given in the From: line of your email. If you want
some other address to appear on this page then please let me know. But I will certainly
add your real name. :-)
THANKS! :-)
Vim Pictures - History (List of
Changes)
● 010420: Added GVim-6.0aa on WindowsNT4
● 010313: Added Vim-6.0w with UTF-8 text
● 010302: Added crée avec Vim
● 001215: Added Created with Vim
● 001104: Added Vim-5.7.2 Startup Screen
● 000817: Added created with Vim
● 000815: Added Vim Tilde Button
● 000704: Added Created with VI
● 000509: Added Vim Document Icon
● 000509: Added Japanese MacVim
● 000509: Added Japanese MacVim
● 000503: Added This Site vim Powered
● 000427: Added I love my editor
● 000222: Added Edited with VIM
● 000116: Added Gvim Japanese
● 991020: Added Vim ASCII Logo
● 990915: Added Vim on Fire
● 990903: Added VIM - the 4 star editor
● 990816: Added When things are dim...
● 990810: Updated Vim - The editor
● 990804: Added Vim and SMIL
● 990803: Added Vim - The editor
● 990708: Added Vim Mirror
● 990303: Added ASCII Logos
● 990302: Added Vim with GTK theme
● 990220: Added Vim with NeXT look
● 990203: Added Vim Icon (transparent)
● 990106: Added Vim on MacOS 8.5.1
● 981223: Added Vim in SQL QuickFix mode (1+2)
● 981218: Added gvim-5.4a with GTK
● 981217: Added This site was created with VIM! :wq
● 981111: Added Edited with Vim
● 981105: Added Just VIM it! (This page is Vim POWERED!)
● 981104: Added Just VIM it! (click here)
● 981023: Added GVim-5.3
● 981001: Added Vi Vimproved
● 980904: Added Vim in SQL Mode
● 980726: Added Vim-5 on RiscOS
● 980721: Added this site powered by vim
● 980717: Added Gvim and Unicode
● 980626: Added VIM-5.0w on rxvt-2.4.3
● 980625: Put most pics outside the current page for faster startup.
● 980622: Added designed with vim
● 980331: Added GVim-5.1a
● 980216: Added Vim Hot Icon
● 971217: Added Vim 1-2-3
● 971127: Added this site vim powered
● 971104: Added Gvim on Perl script
● 971006: Added VIM Life
● 970905: Added VIM color on Perl
● 970828: Added Powered by VIM
● 970404: Updated vim with Farsi (Persian)
● 970207: Added vim on Macintosh
● 961015: Added vim on windows
URL: http://www.math.fu-berlin.de/~guckes/vim/pics.html
URL: http://www.vim.org/pics.html (mirror)
Created: Sat Jun 29 00:00:00 MET 1996
Send screenshots and comments to VI
Sven Guckes [email protected] Powered
by Sven
Sven [email protected] ©1995-2001 Last update: Tue Oct 03 20:00:00 MET DST 2000
Hopefully, all three versions will hopefully merge into *the* MacVim again soon. Until then, please chose yourself
which version you would like to use.
Problems? If you find a problem with either release then please give a reference to the version you use! Check with
command :version first and include the info in your requests. Thankyou!
Example version info:
:ver
VIM - Vi IMproved 5.7 (2000 Jun 24, compiled Jun 26 2000 19:09:11)
Compiled by guckes@ritz, with (+) or without (-):
As I currently have no access to MacOS so I cannot try the latest version. So I am hoping for feedback on the Vim
Goals as described below. Have these things been implemented or fixed yet? Thanks for all feedback!
MacVim FAQs
MacVim Development Requirements
Q: What do I need to take part in coding the Mac port of Vim?
A:
Requirements
❍ CodeWarrior9 - better: CodeWarrior Pro2 (see http://www.metrowerks.com/)
MacVim - Goals
Port to MPW [000519]
Port Vim for use with Apple's MPW compiler.
And you can get Perl, TCL and Python for the Mac as well.
Q: What has been done already with the code?
A:
Completed Items [980221]
● MacOS - memory management: Replacement of malloc/free by NewPtr/DisposePtr
● MacOS - clipboard support: clipboard can be used with register name '*'
● Startup: $VIM defaults to the folder of the application "vim", but if this path ends in ":src" then the above folder
is used.
● Startup - setup file search: The setup filenames starting with a dot take precedence over those starting with an
underscore. The setup file for Vi is tried first (exrc), then those for Vim (vimrc) and then for the Gvim: So the
order is: .exrc, _exrx, .vimrc, _vimrc, .gvimrc, _gvimrc However, the command ":mkvimrc" should create
"_vimrc" or "_gvimrc".
Q: Which features should be implemented next?
A:
Primary Goals
● Menus: add shortcuts for standard menu commands
● Binaries for 68K, PowerPC, FAT - put onto mirrors in StuffIt format
● GUI: Button on title bar: open the window to full size of current screen.
● Screen size bug: The current screen size is set to 640x400 explicitly - instead of being probed from the graphic
device. [Dany, 990215]
● Info box: "Version: Vim-5.0 [980223] for MacOS 68K" and "Comments: Email:
[email protected]"
● ":version" comamnd: include info on person who compiled the binary, as well as info on compiler and OS:
:version
VIM-5.0 [980219] OS: MacOS-7.5.1
Compiled by Sven Guckes [email protected]
on Tue Feb 24 19:32:29 CET 1998
with CodeWarrior Pro2
List of compile options ['+' means "code included for"]:
[etc]
"I'd like to participate in the development." Q: How should I name my version of
A: Please make your version available like this:
Format: vim-5-yymmdd-68k-appl.sit.bin
yy = year mm = month dd = day
Example: vim-5-980406-68k-appl.sit.bin
only the application for 68k Macs,
stuffed and in binary format.
Example: vim-5-980623-PPC-src.sit.hqx
only for PPC, but the complete source,
stuffed and binhexed
Example: vim-5-980623-FAT-src.sit.hqx
the source with binaries for both 68k and PPC Macs,
stuffed and binhexed
Q: What further goals are there for the mac port?
A:
Further goals
● About Box
● File:Print...
● Make vim an IDE for CodeWarrior. Dany sent a suggestion for an IDE menu to the list [990210].
Ideas
● Bundle Vim with set of monospaced fonts
Problems
● Setup files must be in Unix or Dos format. Mac format should be made possible, too. [990210]
● Setup files must be in the same folder as the application. Should be possible to put them into the Preferences
folder, too. [990210]
● syntax coloring takes *very* long, vene for small files - why?
● filename completion: doesn't work for a volume different of the current one. [workaround: Use ":cd volume"
before using filename completion on that volume]
Drag and Drop DONE (+) and TODO (-)
● + open file by dropping onto application icon
File:
OpenFile... Cmd-o Open (:edit) file
Save Cmd-s Save current buffer to current file
SaveAs... Cmd-S Save current buffer to file
Close Cmd-w Closes current subwindow
Print... Cmd-p Prints current buffer
Quit Cmd-q Quits Vim
Edit:
Undo Cmd-z Undo last change (deletion/insertion)
Redo Redo last change
Cut Cmd-x Delete current selected (visual) text
Copy Cmd-c Copy current selected (visual) text to clipboard
and to the unnamed buffer, too, of course
Paste Cmd-v Like 'p' to "put"
Clear
Search Backward
for current word
for current filename
Search Forward
for current word
for current filename
Preferences:
● Show splash screen (if ever)
● Show About box on startup
● Position of startup window
● Font
Mac Utilities
Fonts [000403]
Suggested Fonts for use with MacVim:
URL: http://www.math.fu-berlin.de/~guckes/vim/macs.html
URL: http://www.vim.org/macs.html (mirror)
Created: Sun Jun 16 00:00:00 MET 1996
Send feedback on this page to
Sven Guckes [email protected]
*if_ole.txt* For Vim version 5.7. Last change: 2000 Mar 21
1. Activation |ole-activation|
2. Methods |ole-methods|
3. The "normal" command |ole-normal|
4. Registration |ole-registration|
5. MS Visual Studio integration |MSVisualStudio|
OLE is only available when compiled with the |+ole| feature. See
src/if_ole.INSTALL.
==============================================================================
1. Activation *ole-activation*
Vim acts as an OLE automation server, accessible from any automation client,
for example, Visual Basic, Python, or Perl. The Vim application "name" (its
"ProgID", in OLE terminology) is "Vim.Application".
[Visual Basic]
> Dim Vim As Object
> Set Vim = CreateObject("Vim.Application")
[Python]
> from win32com.client.dynamic import Dispatch
> vim = Dispatch('Vim.Application')
[Perl]
> use Win32::OLE;
> $vim = new Win32::OLE 'Vim.Application';
Vim does not support acting as a "hidden" OLE server, like some other OLE
Automation servers. When a client starts up an instance of Vim, that instance
is immediately visible. Simply closing the OLE connection to the Vim instance
is not enough to shut down the Vim instance - it is necessary to explicitly
execute a quit command (for example, :qa!, :wqa).
==============================================================================
2. Methods *ole-methods*
*ole-sendkeys*
SendKeys(keys) Execute a series of keys.
These examples assume that Vim starts in Normal mode. To force Normal mode,
start the key sequence with CTRL-\ CTRL-N as in
CTRL-\ CTRL-N returns Vim to Normal mode, when in Insert or Command-line mode.
Note that this doesn't work halfway a Vim command
*ole-eval*
Eval(expr) Evaluate an expression.
*ole-setforeground*
SetForeground() Make the Vim window come to the foreground
==============================================================================
3. The "normal" command *ole-normal*
Due to the way Vim processes OLE Automation commands, combined with the method
of implementation of the ex command :normal, it is not possible to execute the
:normal command via OLE automation. Any attempt to do so will fail, probably
harmlessly, although possibly in unpredictable ways.
There is currently no practical way to trap this situation, and users must
simply be aware of the limitation.
==============================================================================
4. Registration *ole-registration*
Before Vim will act as an OLE server, it must be registered in the system
registry. In order to do this, Vim should be run with a single parameter of
"-register".
Once vim is registered, the application path is stored in the registry. Before
moving, deleting, or upgrading Vim, the registry entries should be removed
using the "-unregister" switch.
The OLE mechanism will use the first registered Vim it finds. If a Vim is
already running, this one will be used. If you want to have (several) Vim
sessions open that should not react to OLE commands, use the non-OLE version,
and put it in a different directory. The OLE version should then be put in a
directory that is not in your normal path, so that typing "gvim" will start
the non-OLE version.
==============================================================================
5. MS Visual Studio integration *MSVisualStudio* *VisVim*
The OLE version can be used to run Vim as the editor in Microsoft Visual
Studio. This is called "VisVim". It is included in the archive that contains
the OLE version. The documentation can be found in the VisVim directory, the
README.txt file.
==============================================================================
vim:tw=78:ts=8:sw=8:
Sven [email protected] ©1995-2001 Last update: Wed Apr 11 11:11:11 MEST 2001
command description
viw visualize inner word
viW visualize inner WORD (also works for "up-to-date")
yas yank (copy) all sentence (with surrounding whitespace)
dip delete inner paragraph (without surrounding whitespace)
Number Prefix of commands [980114]
Many commands can take a "number prefix" to perform the commands many times. However, this does not work
some commands. For example, you can copy four lines with "4yy" - but you cannot put the copied text twice with
"2p".
Vim fixes this - number prefixes can be applied to almost all commands.
Search Offsets [980114]
Whenever you search for patterns with Vi it will place the cursor on the first character of the matching text - but
you must then look for the end of a match yourself.
Vim allows to specify a "seach offset", ie you can place the cursor relatively by "begin" or "end" of the matches
text:
DONE/TODO
DONE
● Availability
● Compatibility
● Language Support - Right-to-Left
● Limits
● Multiple Undo
● Redo
● Termcap Support
● More Text Objects
● Number Prefix
● Search Offsets
● Visual Selection
● Text Formatting
● Completion
● TAB expansion
● Digraph Input
● Filetype Recognition
● History for commands and searches
● Configurable "words"
● Multiple Buffers
● Screen Splitting
● Syntax Coloring
● Autocommands
● Macro Recording
● Online Help
● GUI Support
TODO
● Built-in Scripting Language
● Tag Stack Commands
● Escape for one "normal command" with i_CTRL-O
URL: http://www.math.fu-berlin.de/~guckes/vim/why.html
URL: http://www.vim.org/why.html (mirror)
Created: Thu Jan 01 00:00:00 CET 1998
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Mon May 14 02:40:00 MEST 2001
[email protected]
eg [email protected]
If you are using UNIX then these commands should be easiest to (un)subscribe:
Subscribing to "vim"
echo vim rules | mail [email protected]
Unsubscribing to "vim"
echo seeya | mail [email protected]
Commands to subscribe and unsubscribe to the other lists are left to the reader as an exercise. :-)
:help tag
:set options=value
RTFFAQ
RTFM
And this is what it means:
:help tagname
This means "enter this help command and you shall find an explanatory text which contains the answer to your
question". This is often used to answer the request to some feature that already exists. In these cases we just
answer by pointing to the section in the help file which describes this feature. So just enter ":help tagname" and
read the stuff there. If you do not like the feature the way it is then we ask you to give a definition and a few
examples of the way you like it to be. This helps a lot when redesigning a feature!
":set option=value"
This means "enter the command to set the option "option" to the value "value". This change should then change
the behaviour of a command and thus enable you to do with it what you desired.
RTFFAQ
RTFFAQ means "read the fine [list of] frequently asked questions [and answers] in the "VIM FAQ"". Read it and
you shall find the answer!
URL of VIM FAQ:
http://www.vim.org/faq/
RTFM
RTFM means "read the friendly manual". Usually used when someone repeatedly asked for info which is in the
manual and some other help text (such as the Vi FAQ and Vim FAQ). Please take a look at them again and you
will probably find the answer. And if you should use it then please add a pointer. Thanks!
Thank you for understanding! :-)
http://www.yahoogroups.com/list/vimannounce
http://www.yahoogroups.com/list/vim
http://www.yahoogroups.com/list/vimdev
http://www.yahoogroups.com/list/vim-fr
http://www.yahoogroups.com/list/vim-mac
http://www.yahoogroups.com/list/vim-multibyte
http://www.yahoogroups.com/list/vim-vms/
For the record: Some time ago there was an archive for vim mailing lists at the "Insitute of Informatikk" (institute of
computer science) at the University of Bergen, Norway. However, this archive is no longer in function. This archive was
maintained by Eivind Gjelseth [email protected] using the software MHonArc which is based on perl. Thanks for this,
Eivind!
Mailing List - using the mailer "mutt"
Mutt is a mailer hich understands "threading", that is it can group relating messages together - properly!
Here are two sample windowshot for you:
The first windowshot shows my mail folder with all the mails from the vim mailing list:
[a look at Sven's VIM mail
folder]
Mails in red are "From: Bram", mails in yellow have been sent with a broken Message-ID. Mails in dark blue are those
which I have replied to (marked with an 'r'). And the mails in light green are from myself (these are also flagged with
'F'). Mails in dark green are CCed to me at [email protected] (that's why you get to see it twice in the index). And mails
in yellow on magenta have been sent by bad mail programs...
The second windowshot shows mutt's internal pager displaying a message:
[a sample mail viewed by the
internal pager]
The header is limited to the header lines that *I* am interested in to see, and it shows in the order I prefer; they are also
colored by the colors that I have set. (Hey, you might not want any colors at all - fine, because no colors is the default
with mutt.)
Quoted text is shown in its own color - and it can be hidden from view with a command (just type 'T' for the command
"toggle-quoted").
Addresses are shown in its own color, too. (Email addresses have a different color than FTP addresses or Web
addresses.)
Even the signature gets its own color (if you wish); it can even be stripped off automatically on replies.
And the blue tilde characters show that those lines do not belong to the message any more.
By the way, you can view each MIME part of the message on its own, and delete, print, or just save it. You can also
"pipe" each attachment to some arbitrary program or script.
Please give this mailer a try. It works on every terminal and is really fast. It understands PGP, POP and IMAP. And
much more.
About a hundred people on the vim maillists are using mutt with vim already. :-)
One more example:
Mutt allows to "limit" the index of messages to only messages which "match" a "pattern". This is quite useful, eg to
quickly get a list of only the mails "From: Bram" which are announcements of the "available" new versions of version
"6.0"; and, of course, you don't want to see the replies (which usuyally have mostly "re:" in the Subject line and
occasionally a changed Subject, indicated by "was:"):
URL: http://www.math.fu-berlin.de/~guckes/vim/mail.html
URL: http://www.vim.org/mail.html (mirror)
Created: Fri Dec 1 00:00:00 MET 1995
Send feedback on this page to
Sven Guckes [email protected]
Home
Databases On 04-JUL-01, Vincent Foley wrote: I meant Vim gives TON of power
and rapidity, not ON. Sorry about that
On 27-APR-01, Chrup wrote: I've been using vi since 1984 and vim
since I was made aware of it's existence. (V4 or something). Recently I
added the 4GL I use to the syntax-highlight files and now, there is little, I
would rather use. There is one editor which comes close: BBEdit 5.1.1
(not the latest 6.1) which can open files via FTP on my Mac - which is
superb!! But for UNIX files, I have to use a PC and there is nothing in the
PC world which is usable. Beginners and the spoilt-by-GUI people might
not find vi(m) to be easy to get used to and usually give up before they
know what they have - pity them :). Emacs, for simple editing tasks is just
way to big to be useful. Also, the keystrokes I have to learn in Emacs far
outweigh it's usefulness ...
On 18-JAN-01, Jan wrote: The first time I saw vim, I found it sucked, I
more liked GUI-editors, no I feel shame because I once thought that, vim
is simply the best!
On 30-JUL-00, Kay wrote: VIM is the best editor that I have ever used.
It is free! VIM 6.0d (alpha) comes with folding and vertical splits. Just
perfect!
On 22-MAR-00, Chris Horry wrote: Once you get past the initial steep
learning curve it truly is the most powerful editor available, add to this a
thriving Vim community and very approachable developers - Vim rules!
On 14-MAR-00, Bill Randle wrote: The only thing missing (and the
only reason I occasionally fire up Xemacs) is "pretty printing" - i.e.
Postscript output with syntax highlighting.
On 29-FEB-00, Daniel Winner wrote: VIM is the best editor I have ever
used for writing code. I simply can't live without its great features now,
such as keyword completion, and its different modes. I love it!!!
On 17-FEB-00, Jan wrote: vim looks very good especially with a color
xterm. It's also easy to make your own syntax mode for all kinds of
propriatary languages.
On 15-FEB-00, Jim Crockett wrote: vim is the best!!! And I can use it
at work (winnt), at home (linux), and at home (win98)
On 04-FEB-00, someone wrote: I've been using vi since I was knee high
to a grasshopper and Vim is by far the best version I have ever seen!
On 03-FEB-00, Chris wrote: I've been using VIM since pretty much
since it's inception. I will never go back to anything else! Love it.
On 27-JAN-00, Mark Waller wrote: I have used vim for two years now
and it is excellent. By far the best implementation of syntax highlighting I
have seen. All it needs now is folding.
On 24-JAN-00, Unix Pro, Really wrote: it *is* sooooo much better than
vi -- and it even runs on other platforms!
On 22-JAN-00, Lars Amsel wrote: best unix style editor waiting for the
vim book to come
On 21-JAN-00, Sean wrote: VIM is the best and runs circles around
emacs and nedit!
On 20-JAN-00, Kenny wrote: If you type 60+ wpm like me (90+!), and
once you get past the learning curve, it is the most amazing editor. I never
have to use the mouse. And that means I can code full speed without
removing my hands from the keyboard. VI ROX!!
On 19-JAN-00, John Klassa wrote: vim is getting more and more like
GNU Emacs every day... Tons of settings and cryptic key sequences.
On 17-JAN-00, narsi wrote: Vim is a must have for any system. I load it
on every OS that I work with. Anything else is a waste of time.
On 07-JAN-00, Nagu wrote: Can't believe how I survived with just vi all
these years!!!
On 12-DEC-99, Suydam wrote: Interface?! Ha! There isn't one last time
I checked.....at least not in vim the way I'm guessing most of us use it.
However, it's still by far the best editor out there for hardcore
programming. Long live vim!
On 11-DEC-99, someone wrote: I love vim, but can't see how it could
get a high rating for "intuitive interface". Vim would be far more loved by
newbies if, by default, you could backspace over text after changing
modes. That's why it took so long for me to get into it. Now I love it, of
course, but it could have been made so much easier.
On 01-DEC-99, Sinan Unur wrote: ViM offers the right balance (for
me) between features and extensibility. I use it only for source file editing
(mostly C, Java and TeX). It's small, fast, and beautiful.
On 24-NOV-99, Matt Aylward wrote: Vim lets you, the user choose.
You can run it lean and fast in an xterm when you just want to get the job
done, or bulk it up with any number of extensible guis when luxury is
required (even then it is lightning fast). I've used vim for three years on
Linux, Solaris, Digital unix, NT, '95, '98 and I still haven't tested half it's
tricks.
On 16-NOV-99, Charles Stepp wrote: Only free editor that can easily
handle editing very large files on my iMac.
On 14-NOV-99, RLB wrote: Anyone who disses VIM should be shot &
hanged by their balls! I use VIM everywhere, no matter what type of
machine i'm on. I can usually grab a version for it. :) By far it is the
greatest editor of all time. Syntax Formatting, gotta love it. I have a friend
that recently converted to VIM from emacs & can't imagne life without
"Syntax Colouring" as he calls it. Overall, VIM has many features, with a
side for everyone. :)
On 02-NOV-99, Mark Collett wrote: I've been using Vim for 6 years
now. Even when I went to a MS development shop, I still used Vim for
my power editing. My many thanks go to the contributors. I find myself
evangelizing Vim to everyone that will listen!
On 27-OCT-99, Tom wrote: Been using vi++ type tools for a few years
now, but vim really is an improvement. Not quite as powerful as emacs,
but then who wants an operating system as an editor?
On 26-OCT-99, RS3 wrote: The BEST!!!!! The first unix editor I used
with my former company was not available when I moved to my new
company. After moving to my new company I, needed to learn a new text
editor. At first, I tried Emacs but soon after, switch to Vi. Used Vi for
over a year. Then I found Vim. Love at first sight!!! Istalled Vim on every
computer I use, at home and at work. I can no longer live without Vim.
Many thanks to those involved with the Vim product. Keep up the great
work.
On 12-OCT-99, fdj wrote: Those who complain about vim's size should
know you can compile a tiny version with only the features you need. It's
fast and very stable -- the stability complaints folks have with vim are
usually related to the lates features, esp gui. The standard vim from a
terminal or gui without extensive features works great; the standard vim
with lots of features works great, too, but you might discover (and
hopefully submit a report on) a bug.
On 04-OCT-99, Ulf Kister wrote: Vim is one of the most effective and
useful pieces of software I have ever used.
On 02-OCT-99, blux wrote: vim is small and fast, nice syntax files
too.... only bad thing is gvim, but the regular textmode is *GREAT*
On 02-OCT-99, ed wrote: I consider vim superior to vi. HOWEVER, I
view it as a superior vi--neither a competitor nor a replacement for emacs
On 27-SEP-99, David Spriet wrote: I have been using Vim for about 3
years now and I would like to say thanks to all the people who created
and work on VIM.
On 23-SEP-99, raman wrote: Vim is truly the best editor, hands down. I
use it for mail, coding, admin, html, script writing. I love it...get jtags too
On 21-SEP-99, Andrei wrote: The best program I've used. Nice balance
of power/configurability/ease of use. The only perfectly documented open
source program I've seen.
On 17-SEP-99, Chad Bearden wrote: One interface for all OS's. Tons
of features! Wish there was a better tutoria for beginners.
On 17-SEP-99, Tony Clark wrote: Vim 5.4 is great, only things that
beats vim in te editors competition is emacs doing 'perl code debugging,
three way diffs and virtical screens :)'.
On 15-SEP-99, Matt Dunford wrote: If you find yourself typing all day,
Vim is the way to go. Doing the maximum amount of things with the
fewest keystrokes is what it's all about.
On 15-SEP-99, Bill Hill wrote: Fast and powerful on all the platforms I
need.
On 14-SEP-99, H. Shenoy wrote: Vim is the new synonym for the word
"editor". Its easy when U know how!
On 14-SEP-99, totoy wrote: what more can you ask for an editor that is
so lean yet packed a heavy punch on features and usability.
On 14-SEP-99, Herve Foucher wrote: vim is the best editor for me. Its
functionnalities and speed are impressive. Change to VIM !
On 30-AUG-99, David van Popering` wrote: vim just makes sense. Its
the best out there. The End.
On 28-AUG-99, someone wrote: Well I rarely use grep, and the only nix
style box I use with any regularity is my own, but I like vim because of
syntax hilighting for all my favorite languages, the fact that I know its
interface and like it fairly well, and the fact that a blackhole doesnt open
in my computer every time I try to start it.
On 17-AUG-99, Morgan wrote: very fast, but lacks some things that
emacs has the need to go out of input mode to save is also annoying
On 10-AUG-99, Nick Moffitt wrote: The great thing about vim is that it
does syntax color highlighting and multiple windows. All that, and a
properly compiled version still loads several times faster than EMACS.
Privacy | Legal
Moolenaar.net
[home] [Vim] [ICCF] [fun]
-official-
mistake: This mentions the standard copyright notice, but the book is
published under the OPL (Open Publication License), as is mentioned
on the back cover. The paragraph starting with "All rights reserved..."
Page iv, Copyright
should be replaced with: "This material may be distributed only
subject to the terms and conditions set forth in the Open Publication
License, v.1.0 or later (the latest version is presently available at
http://www.opencontent.org/openpub/)."
Page v, Chapter 9 error: "Command" is written twice
-official-
Page xxi,
typo: In the first sentence: "a high quality Vim clone" should be "a
Acknowledgements
high quality Vi clone".
Page xxvi, How to -official-
read this book, mistake: "a Jewish Arab living in Hong Kong" should be "Jewish
second paragraph Iranian living in Hong Kong".
Page xxvi,
spelling: "approbate values" should be "appropriate values".
Notation
Page xxxi, Lines 7 error: Appendix D (Command-Mode Commands) is omitted, and
to 17 Appendices E through I are labeled as D through H.
Page 6, above
mistake: "command mode" should be "Normal mode".
figure 1.3
minor: Indent in the figure differs from what is shown in the text
Page 6, figure 1.3 above it. In the text, remove the indent from the line starting with
"Found".
Page 6, Moving mistake: in the first sentence: "command mode" should be "Normal
around mode".
Page 7, Deleting error: It says "eight" twice, that should be seven. Figure 1.4 shows
characters eight times "x", that should be seven as well.
Page 8, last Note error: "The v command" should be "The u command".
layout: The "xxxx" doesn't line up with the word "very" above it that is
Page 9, top
to be deleted. Same for "xxxxxx" below "turtle".
-official-
Page 9, Getting
error: "This command writes the file and exits" should be "This
Out
command writes the file if modified and exits".
-official-
Page 11, figure 1.8
The last line ends in "for the turtle.", should be "for the turtle!!!".
-official-
Page 12, top half typo: "CTRL+]" should be "CTRL-]". Appears twice. And "CTRL+T"
should be "CTRL-T".
Page 12, at 60%
error: A ) is missing after "(for example, CTRL-A".
down
error: In the "Prefix" column, "v" should be "v_", "i" should be "i_"
Page 13, table 1.1
and "c" should be "c_".
Page 13, last mistake: It says "all the movement commands" and then goes on to
section explain the append command "a". It should say "most commands".
layout: Not all arrows point to the right character. See figure 18.1 for
page 16, figure 2.1
correct arrows.
Page 17, 50%
minor: There should not be a : after "5f<Space>" (in bold font).
down
layout: The arrows point to the same characters in both figures, but
page 17, figures 2.4
they should point to different ones: "f" at the mentioned character, "t"
and 2.5
to the character before it.
error: It mentions "Changed word (screw<blank>)". This should be
page 22, figure "Changed word (screw)". The "cw" command doesn't change the
2.12 following blank.
The highlighted "foul" should be "screw".
page 22, figure error: The seventh command "j>" should be "j^". The eight command
2.13 "f>" should be "f<".
page 23, figure
error: the text says "two lines" but there are three lines.
2.14
minor: "If a count is specified," should be followed by "then," not
Page 24, Line 6
"the".
page 25, figure
error: a"<Esc> should be $a"<Esc>
2.18
-official-
page 25, Digraphs error: to enter the copyright sign use CTRL-KcO (capital O instead of
zero).
page 29, mistake: Change "search for include, for example, the results in all
Highlighting the" to "search for include all the".
page 32, figure error: Several occurences of "the" are not highlighted. The "y" in
3.10 "they" should not be highlighted.
unclear: The CTRL-Wk command applies to the inner, short arrow on
page 46, figure 5.2
the right side, it should be moved inside the large arrow.
-official-
Page 48, The :new
minor: Add this at the end of this section: "CTRL-W n" is equivalent
Command
to ":new".
page 57, below mistake: Move "as shown in Figure 6.5" from then end of the second
figure 6.4 sentence to the end of the first sentence.
page 62, figure error: the highlighted text should not include the space between "long"
6.11 and "line".
page 78, figure confusing: It's not clear what the arrow points to. It should look like
7.15 figure 7.14, but exclude the lines with "{" and "}".
missing: Change "The following command goes to the tag on the list"
page 81, top to "The following command goes to the next tag on the list" (insert
"next").
page 82, figure error: The text below the right picture says "CTRL-W CTRL-[", that
7.21 should be "CTRL-W ]".
page 83, 60%
typo: "g CTRL-]" should be "gCTRL-]", without the space.
down
page 87, figure
error: "parse error before ']'", the ']' should be '}'. Appears twice.
7.25
page 87, figure error: "int i=3" should be "int i=3;". The four lines should be indented
7.26 the same way.
page 88, figure error: "int 1=3" should be "int i=3;". The four lines should be indented
7.27 the same way.
reference: "(as discussed later in this chapter)" should refer to chapter
page 87, Note
23.
page 90, above
Other Interesting mistake: "the first error" should be "the first match". Appears twice.
Commands
error: "The CTRL-V tells Vim literally instead of acting on it" should
page 93, first note be "The CTRL-V tells Vim to use the <Esc> literally instead of acting
on it"
page 101, 40%
error: ":1,/trouble/print" should be ".,/trouble/print".
down
confusing: This introduces a complex substitute command without
Page 103, How to explaining it. And the actual command is missing. My solution is to
change last,first to remove this section and figure 9.2, it's mentioned in another chapter.
first,last The -official- solution is to add a few sentences, which makes it only
more confusing, in my opinion.
page 109,
Microsoft
error: <S-Right Mouse> should be <Right Mouse>.
Windows Mouse
behavior
page 114, first error: The "ruler" has the 1, 2 and 3 above the "3", should be above the
example "0".
page 115, example error: The first block of text has the grey background everywhere. The
near the top blank space after the text should be white.
page 115, Text
mistake: This should be called "Text Formatting Commands", as there
Formatting
are several of them.
Command
page 115, Text
error: the box with text doesn't show the effect of ":center" properly.
Formatting
The first two lines should have one or two spaces before them.
Command
page 116, top error: "gives results in the following": remove "gives".
page 214, near the typesetting: There are three *, the first two look different from the last
bottom one. They should be the same character in the same font.
error: "When inserting lines, p and P commands do not move the
page 220, first
cursor" should be: "When inserting lines, the p and P commands move
sentence
the cursor to the first non-blank character of the inserted text".
page 220, first error: "The cursor is left at the end of the new text" should be "The
paragraph cursor is left just after the end of the new text".
error: The top arrow should be at the third line. The text has a double
page 221, figure
quote before the equal sign that shouldn't be there. A double quote at
20.2
the end is missing for both callouts.
page 223, Special error: Just above the table: You can also use the command ""P..
Registers This should be: You can also use the command "1P..
page 228, just
missing: Change "Place the F mark there because" to "Place the F
above Advanced
mark there with the mF command. Because".
text entry
page 231, 60% mistake: "Pick a nice even number" should be "Pick a nice round
down number".
error: At first the options are in bold, later they are in single quotes,
page 231, 232, The and then in bold and single quotes. They should all be the same. error:
viminfo file There is no \" option, this is the " option with a backslash added to
avoid it being interpreted as the start of a comment.
page 234, last unclear: What isn't clearly mentioned is that all these commands move
paragraph within the current line.
inconsistent: "[count]" is used here for an optional count. It's not clear
page 235, below
that the [ and ] are not to be typed. It should be count with italic style,
figure 20.10
like it is used elsewhere.
page 235, above
typo: "These command move" should be "These commands move".
figure 20.11
page 240, first error: "CTRL-W k goes to the preceding one" should be "CTRL-W k
sentence goes to the window above".
error: The left and right screens should be exchanged. The command is
page 243, figure CTRL-W o, lowercase o.
21.6 confusing: The left screen shows ":only", which is not actually used
here.
page 243, figure
error: The left screen shows ":only", should be ":all" or nothing.
21.7
typos: "position the cursor of the printf on Hello World" should be
page 244, Split
"position the cursor on the printf of Hello World". (change "on" to "of"
Search
and "of" to "on")
page 246, below error: "will be positioned on lnum" should be "will be positioned on
first example line lnum".
error: The second paragraph mentions that marks and registers are
page 248, Sessions
stored, but that is not so.
page 252, figure missing: After "Move using l to the end of line" should add "use j to
22.1 go down".
page 253, Selecting
error: "but also the space after it" should be "but also all the white
Objects, second
space after it".
paragraph
page 254, just
error: the "count i(" item: "Like ab, except" should be "like a(, except".
above figure 22.5
page 254, figure unclear: the curved lines should start at the first "t" of "test", not at the
22.4 space before it. The space is not included.
missing: "count" is mentioned before each item, but not explained
anywhere.
page 254, table
In many items: "and the space after it", "and spaces after it" and "and
with text objects
the following space" should be "and all the white space after it".
The "a<" item: "include" should be "including".
page 254, figure
error: in the left part, the highlighting should include the () braces.
22.5
error: in the text between the screens, "gh i - start select" should be "gh
page 259, figure
start select". "<BS> - Delete text" should be "<BS> Delete text" and
22.13
align the explanations like a table.
Page 262, Figure
error: "0CTRL-D" should be "^CTRL-D"
23.2
Page 266 and 267,
error: The arrows, indicating tabs, should all end in the same column.
Figure 23.3, 23.4
The ones indicating a full tab should all be the same length.
and 23.5
page 266, Smart omission: The last sentence of the first paragraph: "is defined the
Tabs 'shiftwidth' option" should be "is defined with the 'shiftwidth' option".
page 266, Smart error: In the example with three lines, ":set smarttabs" should be ":set
Tabs smarttab".
page 266, Figure error: This is the same figure as 23.3. It should be different in that a
23.4 Tab typed after the X never inserts spaces but a real Tab.
Page 268, The error: The third sentence must be deleted, it's a copy of the first one
:retab Command (except that "tab stops" turns into "tap stops").
Page 269, figure error: last line on the left: "in this case, column 4" should be "in this
23.6 case, column 5".
Page 273, figure error: the last text on the left: "0} - } is the first" should be "0# - # is
23.7 the first".
Page 275,
minor: "in the window you want to move and move it" is wrong. It
Comparing Two
probably should be "in the window you want to move".
Files
Page 277, second minor: The variable is misspelled, "copy_p_date" should be
:ptag example "copy_p_data."
page 284, Locating
error: "The ]j command" should be "The ]i command".
include Files
page 284, Multiple error: First sentence: "The :make file generates" should be "The :make
Error Lists command generates".
error: The line in the middle "$ gvim Makefile" should be:
page 289, figure
:set switchbuf=split
23.20
:make
page 291, last error: "bb is the amount of blue, and yy is the amount of yellow"
paragraph. should be "gg is the amount of green and bb is the amount of blue".
page 292, Syntax error: The table starts with a line of bold words. These should not be
Elements bold.
page 300, last mistake: This paragraph doesn't belong here at all. There is no relation
paragraph between mapping and the 'suffixes' option.
page 303, typo: "Being expert in the command-mode command means..." leave
introduction out "command".
page 310, 25% error: "change Test to b*Test when" should be "change Test to bTest
down when".
page 314, Override typo: "within comments found as well" should be "within comments
Option (!) are found as well".
page 315, Current error: third paragraph: "Now you want shorten the" should be "Now
File you want to shorten the".
mistake: The text starting with "To mark the beginning" is a separate
page 318,
section about marks. It belongs as a separate section below
Undo/Redo
"Miscellaneous Commands".
page 324, Window error: the format for the geometry should read:
size and position -geometry width x height + x_offset + y_offset
page 326, Icon
typo: "the editor in minimized" should be "the editor is minimized".
item
page 327, Note in
typo: "givmrc" should be "gvimrc".
the middle
page 330, first
error: ":set title=85" should be ":set titlelen=85".
example
page 333, Select
error: 'mousemode' should be 'mousemodel'
Mode
page 335, Toolbar
error: "name.xpn on UNIX" should be "name.xpm on UNIX".
Icons
page 339,
Renaming menu missing: Change "The command" to "The following command".
items
page 341, bottom typo: "Ths" should be "This".
page 345,
confusing: Although this section appears just after the secion on
Changing the
Microsoft Windows specific commands, it can be used with all
appearance of the
systems.
cursor
error: In the third column a few items are wrong. In the second table
page 346, row, "35% high" must be "35% wide". In the fourth row, "35% high"
'guicursor' table must be "25% wide". In the fifth row, "20% width" should be "20%
high".
page 350, Special spacing: The second item has been split in two parts in the left column.
variable names The item should be for "Initial uppercase letter and lowercase letter
table somewhere inside".
page 351, last of
The line starting with Note: should have a line break after "associated
the "some
with", so that the double quote is at the start of the next line.
examples"
confusing: What should be mentioned here is that these items can't be
page 353, Entering used in an expression directly. They are to be used after a command
Filenames like ":edit" or as an argument to the expand() function. This section
doesn't really belong here.
page 354,
<amatch> item error: <abuf> should be <afile>
near the top
page 354,
paragraph between error: <cfile:p> should be <cfile>:p
the tables
page 354, :r item mistake: using :r on "../path/test.c" yields "../path/test" and not "test."
Page 356, last error: The "<:" should be "<=". It's not a good example, the loop will
example be infinite as soon as the first "if" statement is true.
error: The example doesn't work, because "a:index" is invalid. The line
page 359, example
should be replaced with:
halfway
execute 'echo "Arg" index "is " a:' . index
error: User commands cannot contain an underscore character. All the
page 360 commands "Delete_first" should be changed to "DeleteFirst",
"Delete_one" should be "DeleteFirst" as well.
error: The text mentions Delete_one while the example uses
page 360, example Delete_first, they should be the same "DeleteFirst". The "-nargs=0"
near the bottom argument must be placed before the command name: ":command
-nargs=0 DeleteFirst 1delete".
page 361,
typo: "while" should be "whole".
"-range=%" item
page 361, near the
typo: "Execute" should be "executes".
bottom
page 364, col()
typo: ''x should be 'x.
function
page 367, first line typo: "[{string}" should be "{string}".
Please see :
● /Feature list
/Talk
Search:
"Vim nedir?"
Alti kilobytelik bir aciklama
Vim metin modundaki her terminalde calisir, ayrica menu ve fare icin
destegi olan bir grafik kullanici arayuzune sahiptir.
Varlik:
Vim bir cok degisik platform icin varlik gosterir ve vi'da bulunmayan
bir cok ozellik icerir. (bkz. http://www.vim.org/doc/vi.diff.txt). Vim
hemen hemen tum vi komutlari ile uyumludur - vi hatalari haric ;)
Isletim Sistemleri:
Vim bir cok isletim sistemi uzerinde calismaktadir:AmigaOS, Atari MiNT,
BeOS, DOS, MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, WIn16 + Win32
(Windows95/98/00/NT) - ve ozellikle FreeBSD ve Linux
Telif Hakki:
Vim'in telif hakki, kodun bas yazari ve bakimcisi Bram Moolenar'in
<[email protected]> elinde bulunmkatadir. Vim "yardim-ware" tipinde bir
programdir ve kullanicilarinin Uganda'daki yetimler yararina bagista
bulunmalari tavsiye olunur.
Kaynak:
Vim'in kod kaynagi Acik Kaynak formunda olup, herkes gelistirmeye
yardim icin davetlidir.
=== Ozellikler
Komut Tamamlama:
Vim girdiyi - komutlar, dosya isimleri ve kelimeleri- tamamlayan
komutlara sahip.
Otomatik Komutlar:
Vim otomatik calistirma icin kullanilan "otokomutlara" da sahip.
(mesela sikistirilmis dosyalarin otomatik olarak acilmasi)
Digraf Girdi:
Vim, iki karakteri kombine olarak kullanarak ozel karakter girilmesine
ve yeni kombinasyonlar tanimlanmasina izin verir. Ornegin [c,]
kombinasyonu ç harfinin basilmasini sagliyacaktir.
Gecmis Listesi:
Vim , onceki komut ve aramalara erisim saglamak veya onlari degistirmek
icin, girilen komutlarin ve yapilan aramalarin listesini "gecmis
liste"sinde saklamaktadir.
Makro kayitlama:
Vim tekrarlanan isleri yeniden oynatabilmek icin yazdiklarinizi
kaydetmeye izin verir.
Bellek Limitleri:
Vim satir uzunlugu ve tampon bolge hacmi acisindan orjinal Vi'a oranla
cok daha esnektir.
Betikleme:
Vim kolay genisletme amacli betikleme dili ile birlikte gelmektedir.
Oturum kurtarma:
Vim duzenleme oturumunuzu bir dosyaya (viminfo) kaydetme imkani saglar,
boylece bir sonraki oturumda tampon listesine, dosya imlerine, yazmaclara
(registers), komut ve arama gecmisine kolay ulasim saglar.
Sekme genisletme:
Vim sekmelerin, ara bosluklari olan metinlerde genisletilmesine olanak
saglar (expandtab, :retab)
Metin Objeleri:
Vim'in paragraf, cumle ve kelime (bosluklarla cevrilmis yada cevrilmemis)
gibi metin objeleri hakkinda daha cok bilgisi vardir ve bu objelerin
tanimini degistirmeye imkan saglar.
Bicim Renklendirme:
Vim metni yazildigi programlama diline bagimli olarak metni renklendirir.
Eger isterseniz doyalarinizin programlama dillerini kendinize gore
degistirebilrisiniz.
Ozel Kod:
Vim Perl, Tcl ve Python ile entegrasyon secenegine sahiptir. Vim, Windows
altinda OLE otomasyon sunucusu olarak calisabilir. Vim ayrica X-windows
destegi ile yuklenebilir. Bu islem fare icin destek ve ayarlanabilir menu
olanagi saglar.
Ve daha nicesi!
=== Baglantilar:
WWW'de vim anasayfasi: http://www.vim.org
Availability:
Vim is available for many platforms and has many added features
compared to Vi. (see http://www.vim.org/doc/vi.diff.txt)
Vim is compatible to almost all Vi commands - except Vi's bugs. ;-)
Operating Systems:
Vim is available for many systems: AmigaOS, Atari MiNT, BeOS, DOS,
MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, Win16 + Win32
(Windows95/98/00/NT) - and especially FreeBSD and Linux. :-)
Copyright:
The copyright is in the hands of the main author
and maintainer, Bram Moolenaar <[email protected]>.
Vim is "charity-ware", ie you are encouraged to make
a donation to orphans in Uganda (see ":help uganda").
Source:
Vim is OpenSource and everybody is welcome to help improve it!
=== Features
Completion Commands:
Vim has commands which complete your input -
either with commands, filenames, and words.
Automatic Commands:
Vim also has "autocommands" for automatic execution of commands
(eg automatic uncompression of compressed files).
Digraph Input:
Vim allows you to enter special characters by a combination
of two characters (eg the combination of " and a yields an ä) -
and allows you to define other combinations, too.
History:
Vim has a "history" for commands and searches, so you can
recall previous commands or search pattern to edit them.
Macro Recording:
Vim allows to "record" your editing for replaying for repetitive tasks.
Memory Limits:
Vim has much higher memory limits for line length
and buffer sizes than vanilla Vi.
Scripting:
Vim has a built-in scripting language for easy extension.
Search Offset:
Vim allows offsets for search commands, so you
place the cursor *after* the found text.
Session Recovery:
Vim allows to store information of an editing session into a file ("viminfo")
which allows them for being used with the next editing session, eg
buffer list, file marks, registers, command and search history.
Tab expansion:
Vim can expand tabs within the text with spaces (expandtab, :retab).
Tag system:
Vim offers to find text in files by using an index with "tags"
together with many tag stack commands.
Text Objects:
Vim knows more text objects (paragraphs, sentences, words and WORDS -
all with and without surrounding whitespace) and allows to configure
the definition for these objects.
Syntax Coloring:
Vim shows text in color - according to its "(programming) language".
You can define the "language" ("syntax") of the files yourself.
Special code:
Vim has optional integration with Perl, Tcl and Python.
Vim can act as an OLE automation server under Windows.
Vim can also be installed with code for X-windows,
adding configurable menus and support for the mouse.
And more. Lots more!
=== Links
vim: tw=70
Linux Journal Home > Magazine > #86 June 2001 > Algorithms in Africa
Friday, May 18, 2001 | Last Updated 02:55:29 PM
Algorithms in Africa
Maybe the rush to market for spreading internet access across the globe isn't in anyone's best
interest--a report from the front.
by Wayne Marshall
Eleven years ago I installed a computer system at a vocational training and development center
in Tutume, Botswana. Tutume is a rural village on the northeastern edge of the Kgalagadi desert
in southern Africa. The computer was intended to help this organization, known as Tutume
Brigades, catch up on its bookkeeping for several business units crucial to the local economy.
Businesses included a brick-making unit, carpentry workshop, auto repair garage, sorghum mill,
school uniform production unit, tractor hire and vegetable garden. For the local village and the
surrounding catchment era, the Brigades were literally the only game in the bush for
commodities, trade skills, training and employment opportunities.
When I arrived in Tutume, I was a pure novice in the field of foreign assistance. I was also a
mid-career financial professional, with several years of experience in nonprofit and health-care
management in the United States. And like most aid workers new on the ground in Africa, I
knew what was best. In my assessment of the center, I believed a computer was essential to get
a handle on the Brigades' financial position, which otherwise consisted of eight separate sets of
badly maintained manual ledgers, over nine months in arrears. Except for the bank statements
of eight separate checking accounts (and even the bank statements proved unreliable), we had
no way of knowing if the center had any money. Every time we had to make payroll or buy
another truckload of cement, we were in the heart of fiscal darkness.
Over the course of the next several months, I proceeded to computerize the records and train
local staff in basic operation of the system. By the end of the first year, the financial records of
the center were timely and accurate. Moreover, other staff members were beginning to use the
computer for tasks such as word processing and spreadsheets. Many of these employees had
never even used a typewriter before.
If I were to tell no more of this story and fade here to one of the glorious Kgalagadi sunsets, this
might be called a win. Although set in the predawn (and pre-Linux) history of the Internet era,
today this would be described as a small success story of ``bridging the digital divide'' in
Africa--like I was a regular Albert Schweitzer of the Information Age or something.
But the truth is not so simple, and the issues of foreign assistance are not so trivial. The fact is, I
am not proud of this story. Because as my time in Tutume went on, I realized I had blundered
badly, to the point of putting the Brigades in serious jeopardy. I began to ask myself such basic
questions as: What would happen to the computer after I left? Was the staff fully capable of
operating the system independently? Would backups be maintained and performed rigorously?
Were skills sufficient to troubleshoot problems and reinstall the system if necessary? If the
equipment failed or was stolen, could the center afford to replace it? And what would the center
do when the staff I had trained for so long were lured away by more lucrative jobs in the big
city?
These questions all led to the same answer: the Brigades would be left in even worse shape than
I found them. Rather than gaining empowerment, independence and enablement, they would
more than likely be left powerless, dependent and possibly ruined. And all because of my own
cultural myopia, despite my good intentions.
It is axiomatic in the field of foreign assistance that the aid program will take credit for the
successes, while failures are blamed on the host country. The psychology of failure can then be
even more severe and long-lasting than the loss of the project. While I was working in Tutume,
for example, a friend of mine was working in the village of Lobatse in southern Botswana.
Seven years earlier, an aid organization from northern Europe had decided a wool sweater
factory would be just the ticket for the economic development of the village. Of course,
northern Europeans are fond of nice wool sweaters and very likely have great need for them,
particularly in the colder climes of northern Europe. The market for wool sweaters is less
extensive in the sweltering and sparsely populated Kgalagadi desert, however. After seven years
of subsidizing the losses of the operation, the aid organization finally decided it was never
going to be sustainable, and they pulled the plug on the effort. My friend's unenviable
assignment was to put all the women out of work, sell the facility and liquidate the equipment.
It was hard for many of the women not to feel that the fault was somehow their own.
Fortunately for Brigades in Tutume, such failure was averted. As the story there continues, once
I realized the risks, I spent the next several months converting the accounting system back to
manual ledgers, hiring and training additional staff in bookkeeping procedures and enabling
them to use the computer primarily as a support system, rather than as the central financial
database.
But what do these stories from Tutume and Lobatse have to do with Linux and emerging
markets? The rest of this article will consider that question.
Algorithms in Africa
When it comes to Africa, the so-called digital divide is just a divide; there isn't anything
especially digital about it. The divide is geographic, because Africa is a long way away, and
cultural, because the traditions and histories of Africans developed independently from those of
Europeans and Americans. Almost incidentally the divide is economic, from the standpoint of
cash resources and differing perceptions of wealth, though the natural resources of this
continent are vast. The divide ends up being mostly one of ignorance, and this gap is at its
widest in America.
Americans in general know very little about Africa, and what little they do know or think they
know is usually prejudiced and fallacious. If I were to know the state of Florida only from news
reports, I would think it was a large mobile-home park of fat pink people constantly flattened by
hurricanes. Similarly, most Americans probably only know Africa as a disaster zone of
epidemic, starvation and genocide. The principal media image Americans hold of African
assistance is usually the one of the brave young (white) woman, a nurse or volunteer, holding a
helpless black infant, center stage among a group of grateful and admiring Africans in the
background.
Of course Africa is nothing like this image at all, and the first step in crossing the divide here is
to banish these offensive stereotypes and learn all one can about what Africa is really like. It
would be a disservice to the many peoples of the continent to generalize and describe the
essence of Africa as though it were a single place. But I would just like to say: Africa is such a
joy! Whenever I am in the streets of Conakry or an upcountry village, I am overwhelmed with
the pure bandwidth of humanity, of color and vitality and life. So much more than can ever be
expressed on even your largest CRT, with even the fastest DSL connection; Africa is the
ultimate realization of broadband in culture and diversity, natural and human content. Maybe a
virtual, flat-screened reality over the Internet is meaningful in the pitifully dreary cubicle of the
US office worker, but Africa is all about face time in real time.
Open-source advocates can be sure that Africans get community; Africans get bazaar. These are
concepts intrinsic to the cultures and traditions throughout the continent, where African
societies had mastered networking long before the invention of the RJ45 jack. Africans have
historically been quite receptive, often at their ultimate peril, to ideas and innovations flowing
between cultures and brought in by outsiders. And in general Africa has been early and
enthusiastic about adopting new communication technologies, particularly when they are
practical and affordable. So in Botswana I was astonished at the number of fax machines per
capita ten years ago, and now find a thriving trade in cell phones, both legitimate and black
market, in Guinea. On a recent visit to a mosque in the interior of the country, a wizened old
muezzin took me up into the minaret specifically to show me their solar-powered amplifier and
loudspeaker system, used to call the village to prayers.
As one learns to develop an appreciation of what Africa is really like, it will then help if one can
develop a sensitivity to the pitfalls of foreign aid and the havoc such programs have brought to
this continent. The subject of other narrations, it is sufficient to observe here that the official
assistance programs of foreign governments are usually a foul brew of political hegemony,
economic imperialism, cultural ethnocentrism, personal avarice and, too rarely, genuine
altruism. Too often the implementation of foreign aid is all about developing market share and
spheres of influence, instead of improving lives. Proponents of foreign assistance may even
argue that these are synonymous, as though markets for American soft drinks, snack foods and
beauty products result in happiness and prosperity for the consumer. The sad fact is, whether
intentional or merely consequential, foreign assistance has often had devastating effects on
communities, local markets, traditional cultures and environmental conditions throughout
Africa.
Finally, it is helpful to bring an honest perspective of one's own history and culture into focus.
For example, the United States represents less than 6% of the world's total population and has
existed for less than a blink of an eye in the span of all human history. So, what makes us think
we've got it right? What evidence is there to suggest this brief record is proof that our way of
life and cultural adaptations will be viable in the long run?
For example, it may be surprising to learn that, due to the predations of infectious illness, urban
population levels were not even sustainable until about 100 years ago and required steady
migration from rural areas. And it was less than 90 years ago, Gina Kolata writes in Flu, when
``Ladies Home Journal proudly declared that the parlor, where the dead had been laid out for
viewing, was now to be called the living room, a room for the living, not the dead.''
Shortly after this proclamation, a global flu of epidemic proportion--the origin of which is still
not understood--killed 1.5 million Americans and 40 million worldwide. This was not in the
murky history of the Dark Ages; this was 1918. Today, with the modern plague of HIV/AIDS,
the re-emergence of tuberculosis and new mysteries like the relationship of human CJD to Mad
Cow Disease, will our mastery of medicine prove all that enduring, even for the world's most
fortunate few?
In any case, those who would help others should at least try to learn from past failures and have
the humility to ask if the modern model of urbanization, congestion, resource utilization and
environmental depletion are sustainable, even desirable, let alone worthy of export to others in
the world.
Then we may be able to accept that the Internet may not be the solution to all problems of
humankind and have the patience to realize that working through the major challenges in Africa
will take time and understanding measured in generations. Now it becomes clear that Linux and
open-source developers are helping Africa best by what they have been doing already. People
who are programming and installing the world-class, free software at the soul of internet
technology are helping others around the world in profound and important ways, no matter what
license they are using. GNU and open-source software are the perfect fit for the emerging
nations of Africa--as for the rest of the world--not only for the superior technical quality of
these systems, but for the values embodied in their development.
The mere existence of Linux and open-source systems give people the chance to use these
powerful technologies for low-cost, grassroots level applications, an opportunity not possible
just ten years ago. The pages of this magazine have described many of these self-directed
success stories, everywhere from Mexico to Pakistan, where Linux solutions enabled people to
make the difference. Such examples are to be found among African communities as well, from
South Africa to Kenya to Nigeria. And Africans like Katim Touray are using Linux servers to
connect other Africans in dialogue around the world.
Beyond the software itself, though, it is the culture of Linux and Open Source communities that
provides the model for meaningful outcomes. This is the culture of sharing and empowerment,
of the thousands of Linux users' groups throughout the world, of the Linux Documentation
Project and the general willingness of one user to selflessly help another. Participating as a
Linux user is all about developing crucial skills and passing them on. Often users' groups hold
regular installation clinics, giving new users personal, one-on-one support from an enthusiastic
peer. And these users' groups are often active in other community projects, such as helping
schools install servers and network connectivity, while transferring the skills necessary to
maintain them. Each of these connections is essentially more human than technical, linking
people together more than their machines, and can lead anywhere. Each of these personal
connections sows the seeds of others, and the spread of the Linux bloom is now reaching to
every corner of the earth. For example, even though the use of internet technology in Guinea is
nascent, Linux certainly preceded my own arrival here. One finds Linux books in French in
bookstores and Guineans eager to learn more about this ``true'' operating system.
And there are other instances of Linux and open source helping to solve problems in Africa.
One of the most inspiring and hopeful to me involves no computers at all.
Vim in Uganda
The emergence and spread of AIDS has been devastating to sub-Saharan Africa. Sure, you are
probably tired of hearing about it. For one thing, it is so hard to come to grips with the scale of
the problem. In the short time since I left Botswana--when AIDS was just beginning to emerge
as an issue there--life expectancy has plummeted, from nearly 60 years to barely 40. It is now
estimated that as many as 40% of the adults in Zimbabwe are HIV positive. This has been a
debilitating setback to the emerging countries of the region, where public health efforts had
previously been making remarkable gains.
The epicenter of AIDS in Africa has been Uganda, which was hit first and perhaps hardest. The
government of Uganda is considered to have mounted an effective and ongoing public health
campaign for its people, and there is hope that the incidence of HIV/AIDS is decreasing.
Nevertheless, the consequences of the disease have been severe. One of the biggest problems is
the large numbers of children left without parents. In a society where children are traditionally
treasured and raised with the supportive assistance of extended families, there are simply too
few adults left to care for growing numbers of orphans.
Bram Moolenaar is the author of Vim, one of the most popular open-source text editors, with
ports available for just about any platform in existence. Bram had already started Vim when he
first went to Uganda in 1994, volunteering to work as a water and sanitation engineer for the
Kibaale Children's Centre (KCC).
The center, located in a rural village of southern Uganda, provides food, medical care and
education to about 600 children, most of whom have been orphaned by AIDS. The conditions
are austere: one book for ten children, a tiny blackboard and a roof with holes.
Bram found that his skills could help at Kibaale, his help made a difference. After a year spent
working with the Centre, he wanted to find ways he could continue helping the project while
also letting other people know of its existence.
That's when Bram hit on the idea of ``charityware'' for Vim. The license for Vim says simply:
``Vim is Charityware. You can use and copy it as much as you like, but you are encouraged to
make a donation to orphans in Uganda. Please read the file doc/uganda.txt for details.''
While using Vim, type :help uganda to get the complete text of the license and a
description of the Kibaale Children's Centre.
Beyond this, though, Bram is fairly modest about the project. Although he asks for copies of
CD distributions that include Vim, he doesn't appeal to distribution vendors directly for any
additional financial support. Bram prefers to remain low key rather than risk annoying people
and turning them away from supporting the Uganda project.
Knowing that Linux distributions in use are now in the billions, one may wonder how
successful the charityware license has been as a fund-raising method for the Centre. Vim users
are asked to make contributions to the International Child Care Fund that Bram and his
colleagues have set up specifically to support the KCC project, and the ICCF web site provides
annual financial reports. For 1999, donation income totaled about $7,000 US (17,800 Dutch
Guilders), up from about $3,500 US in 1998.
These figures may seem rather underwhelming and suggest that the conscience of open-source
users and vendors is not as evolved as one may like to think. But the bottom line for Bram is,
even at such a modest level, these contributions make a huge difference in what the KCC can
accomplish. The funds raised by Vim donors are used to keep the Centre running, maintain and
improve the facilities and recently purchased rainwater tanks so that more people have access to
clean water.
Bram continues his personal involvement with Kibaale to this day, having made return trips in
1996, 1998 and 2000. This experience gives Bram a thorough grounding in the realities of life
in Africa, as well as an understanding of the means of effecting meaningful change. When I
asked for his opinions about the digital divide, he said, ``I'm afraid I don't know what the digital
divide is. Is it about bringing computer-related stuff to Third World countries? Well, the area
around Kibaale first needs a good water supply and a phone.''
When asked if he could give any suggestions to those interested in projects supportive of
African information technology, Bram replied, ``The best suggestion I can make is to work in
small groups. A hundred small projects bring more benefit than one project that's a hundred
times bigger. The strategy and planning done by people in head offices is a waste of time and
money.'' The message here is that the strength of any bridge depends upon its integrity.
In the end, Bram is doing what the Open Source movement has been all about from the
beginning: working with personal conviction, making a difference where one can and sharing
the work one loves with others. These are the ideals of a world seeking connections, the values
that can link Linux and the Internet with an orphanage in Uganda. The human connections of
these efforts empower people, improve lives and build the solid bridges of understanding
among diverse global communities, digital and otherwise.
Resources
Algorithms in Africa
Maybe the rush to market for spreading internet access across the globe isn't in anyone's best
interest--a report from the front.
by Wayne Marshall
Eleven years ago I installed a computer system at a vocational training and development center
in Tutume, Botswana. Tutume is a rural village on the northeastern edge of the Kgalagadi desert
in southern Africa. The computer was intended to help this organization, known as Tutume
Brigades, catch up on its bookkeeping for several business units crucial to the local economy.
Businesses included a brick-making unit, carpentry workshop, auto repair garage, sorghum mill,
school uniform production unit, tractor hire and vegetable garden. For the local village and the
surrounding catchment era, the Brigades were literally the only game in the bush for
commodities, trade skills, training and employment opportunities.
When I arrived in Tutume, I was a pure novice in the field of foreign assistance. I was also a
mid-career financial professional, with several years of experience in nonprofit and health-care
management in the United States. And like most aid workers new on the ground in Africa, I
knew what was best. In my assessment of the center, I believed a computer was essential to get
a handle on the Brigades' financial position, which otherwise consisted of eight separate sets of
badly maintained manual ledgers, over nine months in arrears. Except for the bank statements
of eight separate checking accounts (and even the bank statements proved unreliable), we had
no way of knowing if the center had any money. Every time we had to make payroll or buy
another truckload of cement, we were in the heart of fiscal darkness.
Over the course of the next several months, I proceeded to computerize the records and train
local staff in basic operation of the system. By the end of the first year, the financial records of
the center were timely and accurate. Moreover, other staff members were beginning to use the
computer for tasks such as word processing and spreadsheets. Many of these employees had
never even used a typewriter before.
If I were to tell no more of this story and fade here to one of the glorious Kgalagadi sunsets, this
might be called a win. Although set in the predawn (and pre-Linux) history of the Internet era,
today this would be described as a small success story of ``bridging the digital divide'' in
Africa--like I was a regular Albert Schweitzer of the Information Age or something.
But the truth is not so simple, and the issues of foreign assistance are not so trivial. The fact is, I
am not proud of this story. Because as my time in Tutume went on, I realized I had blundered
badly, to the point of putting the Brigades in serious jeopardy. I began to ask myself such basic
questions as: What would happen to the computer after I left? Was the staff fully capable of
operating the system independently? Would backups be maintained and performed rigorously?
Were skills sufficient to troubleshoot problems and reinstall the system if necessary? If the
equipment failed or was stolen, could the center afford to replace it? And what would the center
do when the staff I had trained for so long were lured away by more lucrative jobs in the big
city?
These questions all led to the same answer: the Brigades would be left in even worse shape than
I found them. Rather than gaining empowerment, independence and enablement, they would
more than likely be left powerless, dependent and possibly ruined. And all because of my own
cultural myopia, despite my good intentions.
It is axiomatic in the field of foreign assistance that the aid program will take credit for the
successes, while failures are blamed on the host country. The psychology of failure can then be
even more severe and long-lasting than the loss of the project. While I was working in Tutume,
for example, a friend of mine was working in the village of Lobatse in southern Botswana.
Seven years earlier, an aid organization from northern Europe had decided a wool sweater
factory would be just the ticket for the economic development of the village. Of course,
northern Europeans are fond of nice wool sweaters and very likely have great need for them,
particularly in the colder climes of northern Europe. The market for wool sweaters is less
extensive in the sweltering and sparsely populated Kgalagadi desert, however. After seven years
of subsidizing the losses of the operation, the aid organization finally decided it was never
going to be sustainable, and they pulled the plug on the effort. My friend's unenviable
assignment was to put all the women out of work, sell the facility and liquidate the equipment.
It was hard for many of the women not to feel that the fault was somehow their own.
Fortunately for Brigades in Tutume, such failure was averted. As the story there continues, once
I realized the risks, I spent the next several months converting the accounting system back to
manual ledgers, hiring and training additional staff in bookkeeping procedures and enabling
them to use the computer primarily as a support system, rather than as the central financial
database.
But what do these stories from Tutume and Lobatse have to do with Linux and emerging
markets? The rest of this article will consider that question.
Algorithms in Africa
When it comes to Africa, the so-called digital divide is just a divide; there isn't anything
especially digital about it. The divide is geographic, because Africa is a long way away, and
cultural, because the traditions and histories of Africans developed independently from those of
Europeans and Americans. Almost incidentally the divide is economic, from the standpoint of
cash resources and differing perceptions of wealth, though the natural resources of this
continent are vast. The divide ends up being mostly one of ignorance, and this gap is at its
widest in America.
Americans in general know very little about Africa, and what little they do know or think they
know is usually prejudiced and fallacious. If I were to know the state of Florida only from news
reports, I would think it was a large mobile-home park of fat pink people constantly flattened by
hurricanes. Similarly, most Americans probably only know Africa as a disaster zone of
epidemic, starvation and genocide. The principal media image Americans hold of African
assistance is usually the one of the brave young (white) woman, a nurse or volunteer, holding a
helpless black infant, center stage among a group of grateful and admiring Africans in the
background.
Of course Africa is nothing like this image at all, and the first step in crossing the divide here is
to banish these offensive stereotypes and learn all one can about what Africa is really like. It
would be a disservice to the many peoples of the continent to generalize and describe the
essence of Africa as though it were a single place. But I would just like to say: Africa is such a
joy! Whenever I am in the streets of Conakry or an upcountry village, I am overwhelmed with
the pure bandwidth of humanity, of color and vitality and life. So much more than can ever be
expressed on even your largest CRT, with even the fastest DSL connection; Africa is the
ultimate realization of broadband in culture and diversity, natural and human content. Maybe a
virtual, flat-screened reality over the Internet is meaningful in the pitifully dreary cubicle of the
US office worker, but Africa is all about face time in real time.
Open-source advocates can be sure that Africans get community; Africans get bazaar. These are
concepts intrinsic to the cultures and traditions throughout the continent, where African
societies had mastered networking long before the invention of the RJ45 jack. Africans have
historically been quite receptive, often at their ultimate peril, to ideas and innovations flowing
between cultures and brought in by outsiders. And in general Africa has been early and
enthusiastic about adopting new communication technologies, particularly when they are
practical and affordable. So in Botswana I was astonished at the number of fax machines per
capita ten years ago, and now find a thriving trade in cell phones, both legitimate and black
market, in Guinea. On a recent visit to a mosque in the interior of the country, a wizened old
muezzin took me up into the minaret specifically to show me their solar-powered amplifier and
loudspeaker system, used to call the village to prayers.
As one learns to develop an appreciation of what Africa is really like, it will then help if one can
develop a sensitivity to the pitfalls of foreign aid and the havoc such programs have brought to
this continent. The subject of other narrations, it is sufficient to observe here that the official
assistance programs of foreign governments are usually a foul brew of political hegemony,
economic imperialism, cultural ethnocentrism, personal avarice and, too rarely, genuine
altruism. Too often the implementation of foreign aid is all about developing market share and
spheres of influence, instead of improving lives. Proponents of foreign assistance may even
argue that these are synonymous, as though markets for American soft drinks, snack foods and
beauty products result in happiness and prosperity for the consumer. The sad fact is, whether
intentional or merely consequential, foreign assistance has often had devastating effects on
communities, local markets, traditional cultures and environmental conditions throughout
Africa.
Finally, it is helpful to bring an honest perspective of one's own history and culture into focus.
For example, the United States represents less than 6% of the world's total population and has
existed for less than a blink of an eye in the span of all human history. So, what makes us think
we've got it right? What evidence is there to suggest this brief record is proof that our way of
life and cultural adaptations will be viable in the long run?
For example, it may be surprising to learn that, due to the predations of infectious illness, urban
population levels were not even sustainable until about 100 years ago and required steady
migration from rural areas. And it was less than 90 years ago, Gina Kolata writes in Flu, when
``Ladies Home Journal proudly declared that the parlor, where the dead had been laid out for
viewing, was now to be called the living room, a room for the living, not the dead.''
Shortly after this proclamation, a global flu of epidemic proportion--the origin of which is still
not understood--killed 1.5 million Americans and 40 million worldwide. This was not in the
murky history of the Dark Ages; this was 1918. Today, with the modern plague of HIV/AIDS,
the re-emergence of tuberculosis and new mysteries like the relationship of human CJD to Mad
Cow Disease, will our mastery of medicine prove all that enduring, even for the world's most
fortunate few?
In any case, those who would help others should at least try to learn from past failures and have
the humility to ask if the modern model of urbanization, congestion, resource utilization and
environmental depletion are sustainable, even desirable, let alone worthy of export to others in
the world.
Then we may be able to accept that the Internet may not be the solution to all problems of
humankind and have the patience to realize that working through the major challenges in Africa
will take time and understanding measured in generations. Now it becomes clear that Linux and
open-source developers are helping Africa best by what they have been doing already. People
who are programming and installing the world-class, free software at the soul of internet
technology are helping others around the world in profound and important ways, no matter what
license they are using. GNU and open-source software are the perfect fit for the emerging
nations of Africa--as for the rest of the world--not only for the superior technical quality of
these systems, but for the values embodied in their development.
The mere existence of Linux and open-source systems give people the chance to use these
powerful technologies for low-cost, grassroots level applications, an opportunity not possible
just ten years ago. The pages of this magazine have described many of these self-directed
success stories, everywhere from Mexico to Pakistan, where Linux solutions enabled people to
make the difference. Such examples are to be found among African communities as well, from
South Africa to Kenya to Nigeria. And Africans like Katim Touray are using Linux servers to
connect other Africans in dialogue around the world.
Beyond the software itself, though, it is the culture of Linux and Open Source communities that
provides the model for meaningful outcomes. This is the culture of sharing and empowerment,
of the thousands of Linux users' groups throughout the world, of the Linux Documentation
Project and the general willingness of one user to selflessly help another. Participating as a
Linux user is all about developing crucial skills and passing them on. Often users' groups hold
regular installation clinics, giving new users personal, one-on-one support from an enthusiastic
peer. And these users' groups are often active in other community projects, such as helping
schools install servers and network connectivity, while transferring the skills necessary to
maintain them. Each of these connections is essentially more human than technical, linking
people together more than their machines, and can lead anywhere. Each of these personal
connections sows the seeds of others, and the spread of the Linux bloom is now reaching to
every corner of the earth. For example, even though the use of internet technology in Guinea is
nascent, Linux certainly preceded my own arrival here. One finds Linux books in French in
bookstores and Guineans eager to learn more about this ``true'' operating system.
And there are other instances of Linux and open source helping to solve problems in Africa.
One of the most inspiring and hopeful to me involves no computers at all.
Vim in Uganda
The emergence and spread of AIDS has been devastating to sub-Saharan Africa. Sure, you are
probably tired of hearing about it. For one thing, it is so hard to come to grips with the scale of
the problem. In the short time since I left Botswana--when AIDS was just beginning to emerge
as an issue there--life expectancy has plummeted, from nearly 60 years to barely 40. It is now
estimated that as many as 40% of the adults in Zimbabwe are HIV positive. This has been a
debilitating setback to the emerging countries of the region, where public health efforts had
previously been making remarkable gains.
The epicenter of AIDS in Africa has been Uganda, which was hit first and perhaps hardest. The
government of Uganda is considered to have mounted an effective and ongoing public health
campaign for its people, and there is hope that the incidence of HIV/AIDS is decreasing.
Nevertheless, the consequences of the disease have been severe. One of the biggest problems is
the large numbers of children left without parents. In a society where children are traditionally
treasured and raised with the supportive assistance of extended families, there are simply too
few adults left to care for growing numbers of orphans.
Bram Moolenaar is the author of Vim, one of the most popular open-source text editors, with
ports available for just about any platform in existence. Bram had already started Vim when he
first went to Uganda in 1994, volunteering to work as a water and sanitation engineer for the
Kibaale Children's Centre (KCC).
The center, located in a rural village of southern Uganda, provides food, medical care and
education to about 600 children, most of whom have been orphaned by AIDS. The conditions
are austere: one book for ten children, a tiny blackboard and a roof with holes.
Bram found that his skills could help at Kibaale, his help made a difference. After a year spent
working with the Centre, he wanted to find ways he could continue helping the project while
also letting other people know of its existence.
That's when Bram hit on the idea of ``charityware'' for Vim. The license for Vim says simply:
``Vim is Charityware. You can use and copy it as much as you like, but you are encouraged to
make a donation to orphans in Uganda. Please read the file doc/uganda.txt for details.''
While using Vim, type :help uganda to get the complete text of the license and a
description of the Kibaale Children's Centre.
Beyond this, though, Bram is fairly modest about the project. Although he asks for copies of
CD distributions that include Vim, he doesn't appeal to distribution vendors directly for any
additional financial support. Bram prefers to remain low key rather than risk annoying people
and turning them away from supporting the Uganda project.
Knowing that Linux distributions in use are now in the billions, one may wonder how
successful the charityware license has been as a fund-raising method for the Centre. Vim users
are asked to make contributions to the International Child Care Fund that Bram and his
colleagues have set up specifically to support the KCC project, and the ICCF web site provides
annual financial reports. For 1999, donation income totaled about $7,000 US (17,800 Dutch
Guilders), up from about $3,500 US in 1998.
These figures may seem rather underwhelming and suggest that the conscience of open-source
users and vendors is not as evolved as one may like to think. But the bottom line for Bram is,
even at such a modest level, these contributions make a huge difference in what the KCC can
accomplish. The funds raised by Vim donors are used to keep the Centre running, maintain and
improve the facilities and recently purchased rainwater tanks so that more people have access to
clean water.
Bram continues his personal involvement with Kibaale to this day, having made return trips in
1996, 1998 and 2000. This experience gives Bram a thorough grounding in the realities of life
in Africa, as well as an understanding of the means of effecting meaningful change. When I
asked for his opinions about the digital divide, he said, ``I'm afraid I don't know what the digital
divide is. Is it about bringing computer-related stuff to Third World countries? Well, the area
around Kibaale first needs a good water supply and a phone.''
When asked if he could give any suggestions to those interested in projects supportive of
African information technology, Bram replied, ``The best suggestion I can make is to work in
small groups. A hundred small projects bring more benefit than one project that's a hundred
times bigger. The strategy and planning done by people in head offices is a waste of time and
money.'' The message here is that the strength of any bridge depends upon its integrity.
In the end, Bram is doing what the Open Source movement has been all about from the
beginning: working with personal conviction, making a difference where one can and sharing
the work one loves with others. These are the ideals of a world seeking connections, the values
that can link Linux and the Internet with an orphanage in Uganda. The human connections of
these efforts empower people, improve lives and build the solid bridges of understanding
among diverse global communities, digital and otherwise.
Resources
Algorithms in Africa
Maybe the rush to market for spreading internet access across the globe
isn't in anyone's best interest--a report from the front.
by Wayne Marshall
Over the course of the next several months, I proceeded to computerize the
records and train local staff in basic operation of the system. By the end
of the first year, the financial records of the center were timely and
accurate. Moreover, other staff members were beginning to use the computer
for tasks such as word processing and spreadsheets. Many of these employees
had never even used a typewriter before.
If I were to tell no more of this story and fade here to one of the glorious
Kgalagadi sunsets, this might be called a win. Although set in the predawn
(and pre-Linux) history of the Internet era, today this would be described
as a small success story of ``bridging the digital divide'' in Africa--like
I was a regular Albert Schweitzer of the Information Age or something.
But the truth is not so simple, and the issues of foreign assistance are not
so trivial. The fact is, I am not proud of this story. Because as my time in
Tutume went on, I realized I had blundered badly, to the point of putting
the Brigades in serious jeopardy. I began to ask myself such basic questions
as: What would happen to the computer after I left? Was the staff fully
capable of operating the system independently? Would backups be maintained
and performed rigorously? Were skills sufficient to troubleshoot problems
and reinstall the system if necessary? If the equipment failed or was
stolen, could the center afford to replace it? And what would the center do
when the staff I had trained for so long were lured away by more lucrative
jobs in the big city?
These questions all led to the same answer: the Brigades would be left in
even worse shape than I found them. Rather than gaining empowerment,
independence and enablement, they would more than likely be left powerless,
dependent and possibly ruined. And all because of my own cultural myopia,
despite my good intentions.
It is axiomatic in the field of foreign assistance that the aid program will
take credit for the successes, while failures are blamed on the host
country. The psychology of failure can then be even more severe and
long-lasting than the loss of the project. While I was working in Tutume,
for example, a friend of mine was working in the village of Lobatse in
southern Botswana. Seven years earlier, an aid organization from northern
Europe had decided a wool sweater factory would be just the ticket for the
economic development of the village. Of course, northern Europeans are fond
of nice wool sweaters and very likely have great need for them, particularly
in the colder climes of northern Europe. The market for wool sweaters is
less extensive in the sweltering and sparsely populated Kgalagadi desert,
however. After seven years of subsidizing the losses of the operation, the
aid organization finally decided it was never going to be sustainable, and
they pulled the plug on the effort. My friend's unenviable assignment was to
put all the women out of work, sell the facility and liquidate the
equipment. It was hard for many of the women not to feel that the fault was
somehow their own.
Fortunately for Brigades in Tutume, such failure was averted. As the story
there continues, once I realized the risks, I spent the next several months
converting the accounting system back to manual ledgers, hiring and training
additional staff in bookkeeping procedures and enabling them to use the
computer primarily as a support system, rather than as the central financial
database.
But what do these stories from Tutume and Lobatse have to do with Linux and
emerging markets? The rest of this article will consider that question.
Nine years have passed since I left Botswana. To put the times into
perspective, the first thing I bought when I got back to the US was a fax
modem, the cheapest, fastest solution to stay connected with the contacts I
had made abroad. My modem then was 2,400 baud. I tried out CompuServe and
decided on Delphi, and the buzz was just starting about something called
PPP.
During the next several years I was in and out of Africa, became a Linux
user in 1995, began installing Linux in nonprofit organizations in 1997,
spent a year and Y2K transition in the former soviet state of Ukraine and
came to the West African country of Guinea in May 2000. At some point during
this period the digital divide was invented.
Actually, the digital divide seems to have its origins in a 1995 report from
the US Department of Commerce, whose National Telecommunications and
Information Administration (NITA) released the first paper in a series
titled ``Falling through the Net''. This report analyzed telecommunication
access by geographic and demographic patterns throughout the United States.
One of the conclusions of the report was the gap between the ``information
rich'' and the ``information poor'' had widened.
Now, as I write this, bridging the digital divide has become one of the
hottest trends in foreign assistance, and many aid organizations and
corporate philanthropists have found publicity for their efforts.
Simplistically, it seems, the gap in information technology has now come to
be identified with access to the Internet. Thus, we have such programs as
the USAID-funded Leland Initiative, designed to bring internet access to
Africa; the Peace Corps announcing an information technology initiative in
partnership with AOL; and a recently formed organization called Geekcorps
sending its second group of volunteers on three-month stints designing web
sites in Accra, the capital of Ghana in West Africa [see LJ April 2001 for
more on the Geekcorps]. Naturally, the high-profile publicity given this
issue has created an opportunity for many international aid organizations to
develop projects and funding appeals for serving the digitally needy.
Delivering the miracle of the Internet is the new zeal of the high-tech
missionary. In what seems to be a rush to market--bringing the Internet to
the developing world--sometimes projects are announced with only naïve
regard to the technical issues and without full consideration of whether
such projects are viable, appropriate, relevant and sustainable. Thus, one
hears of a women's cooperative in Central America marketing their handcrafts
over the Web; advocates describe the potential of ``telemedicine'' for
delivering virtual health care to isolated areas; and the US State
Department Global Technology Corps proclaims, ``We have seen farmers in
Mexico using [the Internet] to check weather conditions and crop prices.''
Where once Norwegians may have seen wool sweaters, the tech visionary now
sees web browsers.
At the extreme, the new economy proselyte promotes the Internet as the
solution for everything from education and health care to pollution,
inequality and world peace. As though everyone who has access will be able
to browse their way to nirvana, as though the path to heaven is paved with
bandwidth. The satellite dish is the new icon of the digital evangelist,
replacing the holy cross.
It should be clear that in this form, divide rhetoric is simply new raiment
for the familiar old taxonomies of prejudice that have long sought to divide
the world between believers and heathens, the enlightened and the savage.
From a historical perspective, rather than helping, these kinds of belief
systems have generally been devastating to their targets.
Even in the US, this kind of awareness is emerging. In ``How Does the Empty
Glass Fill? A Modern Philosophy of the Digital Divide'' (Educause Review,
Nov/Dec 2000), Solveig Singleton and Lucas Mast write: ``From the standpoint
of higher education, students who leave high school without exposure to
digital learning tools such as the Internet will prove a much less serious
problem than students who leave high school with inadequate reading or math
skills.''
The poor are not shunning the Internet because they cannot afford it: the
problem is that they lack the skills to exploit it effectively. So it is
difficult to see how connecting the poor to the Internet will improve
their finances. It would make more sense to aim for universal literacy
than universal Internet access.
It may be that, with the recent outbreak of dot-com bankruptcy and declines
in the stock market, the tenets of the digital religion could be losing
their currency. At a time when the mega-billion, IPO-funded ebiz stars like
Amazon and Yahoo are having a tough go across the US and Europe, it's hard
not to wonder how the promises of e-commerce could possibly prove viable and
sustainable elsewhere, particularly in places where there aren't even good
banking and credit systems. And for someone like me who has lived several
years of the past decade in both rural and urban parts of the developing
world--where most of the population still cook with firewood and carry water
in buckets--the practical value of focusing foreign assistance on IT
projects would seem negligible, if not ludicrous entirely. Given the more
serious fundamental issues facing developing nations--health care (AIDS, TB
and malaria), nutrition, sanitation, education, poverty, pollution and
political corruption--providing the means to surf the Web should probably
fall fairly low on any reasonable scale of human priorities.
Algorithms in Africa
Americans in general know very little about Africa, and what little they do
know or think they know is usually prejudiced and fallacious. If I were to
know the state of Florida only from news reports, I would think it was a
large mobile-home park of fat pink people constantly flattened by
hurricanes. Similarly, most Americans probably only know Africa as a
disaster zone of epidemic, starvation and genocide. The principal media
image Americans hold of African assistance is usually the one of the brave
young (white) woman, a nurse or volunteer, holding a helpless black infant,
center stage among a group of grateful and admiring Africans in the
background.
Of course Africa is nothing like this image at all, and the first step in
crossing the divide here is to banish these offensive stereotypes and learn
all one can about what Africa is really like. It would be a disservice to
the many peoples of the continent to generalize and describe the essence of
Africa as though it were a single place. But I would just like to say:
Africa is such a joy! Whenever I am in the streets of Conakry or an
upcountry village, I am overwhelmed with the pure bandwidth of humanity, of
color and vitality and life. So much more than can ever be expressed on even
your largest CRT, with even the fastest DSL connection; Africa is the
ultimate realization of broadband in culture and diversity, natural and
human content. Maybe a virtual, flat-screened reality over the Internet is
meaningful in the pitifully dreary cubicle of the US office worker, but
Africa is all about face time in real time.
Open-source advocates can be sure that Africans get community; Africans get
bazaar. These are concepts intrinsic to the cultures and traditions
throughout the continent, where African societies had mastered networking
long before the invention of the RJ45 jack. Africans have historically been
quite receptive, often at their ultimate peril, to ideas and innovations
flowing between cultures and brought in by outsiders. And in general Africa
has been early and enthusiastic about adopting new communication
technologies, particularly when they are practical and affordable. So in
Botswana I was astonished at the number of fax machines per capita ten years
ago, and now find a thriving trade in cell phones, both legitimate and black
market, in Guinea. On a recent visit to a mosque in the interior of the
country, a wizened old muezzin took me up into the minaret specifically to
show me their solar-powered amplifier and loudspeaker system, used to call
the village to prayers.
In any case, those who would help others should at least try to learn from
past failures and have the humility to ask if the modern model of
urbanization, congestion, resource utilization and environmental depletion
are sustainable, even desirable, let alone worthy of export to others in the
world.
Then we may be able to accept that the Internet may not be the solution to
all problems of humankind and have the patience to realize that working
through the major challenges in Africa will take time and understanding
measured in generations. Now it becomes clear that Linux and open-source
developers are helping Africa best by what they have been doing already.
People who are programming and installing the world-class, free software at
the soul of internet technology are helping others around the world in
profound and important ways, no matter what license they are using. GNU and
open-source software are the perfect fit for the emerging nations of
Africa--as for the rest of the world--not only for the superior technical
quality of these systems, but for the values embodied in their development.
The mere existence of Linux and open-source systems give people the chance
to use these powerful technologies for low-cost, grassroots level
applications, an opportunity not possible just ten years ago. The pages of
this magazine have described many of these self-directed success stories,
everywhere from Mexico to Pakistan, where Linux solutions enabled people to
make the difference. Such examples are to be found among African communities
as well, from South Africa to Kenya to Nigeria. And Africans like Katim
Touray are using Linux servers to connect other Africans in dialogue around
the world.
Beyond the software itself, though, it is the culture of Linux and Open
Source communities that provides the model for meaningful outcomes. This is
the culture of sharing and empowerment, of the thousands of Linux users'
groups throughout the world, of the Linux Documentation Project and the
general willingness of one user to selflessly help another. Participating as
a Linux user is all about developing crucial skills and passing them on.
Often users' groups hold regular installation clinics, giving new users
personal, one-on-one support from an enthusiastic peer. And these users'
groups are often active in other community projects, such as helping schools
install servers and network connectivity, while transferring the skills
necessary to maintain them. Each of these connections is essentially more
human than technical, linking people together more than their machines, and
can lead anywhere. Each of these personal connections sows the seeds of
others, and the spread of the Linux bloom is now reaching to every corner of
the earth. For example, even though the use of internet technology in Guinea
is nascent, Linux certainly preceded my own arrival here. One finds Linux
books in French in bookstores and Guineans eager to learn more about this
``true'' operating system.
And there are other instances of Linux and open source helping to solve
problems in Africa. One of the most inspiring and hopeful to me involves no
computers at all.
Vim in Uganda
The emergence and spread of AIDS has been devastating to sub-Saharan Africa.
Sure, you are probably tired of hearing about it. For one thing, it is so
hard to come to grips with the scale of the problem. In the short time since
I left Botswana--when AIDS was just beginning to emerge as an issue
there--life expectancy has plummeted, from nearly 60 years to barely 40. It
is now estimated that as many as 40% of the adults in Zimbabwe are HIV
positive. This has been a debilitating setback to the emerging countries of
the region, where public health efforts had previously been making
remarkable gains.
The epicenter of AIDS in Africa has been Uganda, which was hit first and
perhaps hardest. The government of Uganda is considered to have mounted an
effective and ongoing public health campaign for its people, and there is
hope that the incidence of HIV/AIDS is decreasing. Nevertheless, the
consequences of the disease have been severe. One of the biggest problems is
the large numbers of children left without parents. In a society where
children are traditionally treasured and raised with the supportive
assistance of extended families, there are simply too few adults left to
care for growing numbers of orphans.
Bram Moolenaar is the author of Vim, one of the most popular open-source
text editors, with ports available for just about any platform in existence.
Bram had already started Vim when he first went to Uganda in 1994,
volunteering to work as a water and sanitation engineer for the Kibaale
Children's Centre (KCC).
Bram found that his skills could help at Kibaale, his help made a
difference. After a year spent working with the Centre, he wanted to find
ways he could continue helping the project while also letting other people
know of its existence.
That's when Bram hit on the idea of ``charityware'' for Vim. The license for
Vim says simply: ``Vim is Charityware. You can use and copy it as much as
you like, but you are encouraged to make a donation to orphans in Uganda.
Please read the file doc/uganda.txt for details.''
While using Vim, type :help uganda to get the complete text of the license
and a description of the Kibaale Children's Centre.
Beyond this, though, Bram is fairly modest about the project. Although he
asks for copies of CD distributions that include Vim, he doesn't appeal to
distribution vendors directly for any additional financial support. Bram
prefers to remain low key rather than risk annoying people and turning them
away from supporting the Uganda project.
Knowing that Linux distributions in use are now in the billions, one may
wonder how successful the charityware license has been as a fund-raising
method for the Centre. Vim users are asked to make contributions to the
International Child Care Fund that Bram and his colleagues have set up
specifically to support the KCC project, and the ICCF web site provides
annual financial reports. For 1999, donation income totaled about $7,000 US
(17,800 Dutch Guilders), up from about $3,500 US in 1998.
These figures may seem rather underwhelming and suggest that the conscience
of open-source users and vendors is not as evolved as one may like to think.
But the bottom line for Bram is, even at such a modest level, these
contributions make a huge difference in what the KCC can accomplish. The
funds raised by Vim donors are used to keep the Centre running, maintain and
improve the facilities and recently purchased rainwater tanks so that more
people have access to clean water.
Bram continues his personal involvement with Kibaale to this day, having
made return trips in 1996, 1998 and 2000. This experience gives Bram a
thorough grounding in the realities of life in Africa, as well as an
understanding of the means of effecting meaningful change. When I asked for
his opinions about the digital divide, he said, ``I'm afraid I don't know
what the digital divide is. Is it about bringing computer-related stuff to
Third World countries? Well, the area around Kibaale first needs a good
water supply and a phone.''
In the end, Bram is doing what the Open Source movement has been all about
from the beginning: working with personal conviction, making a difference
where one can and sharing the work one loves with others. These are the
ideals of a world seeking connections, the values that can link Linux and
the Internet with an orphanage in Uganda. The human connections of these
efforts empower people, improve lives and build the solid bridges of
understanding among diverse global communities, digital and otherwise.
Resources
Dostupnost a kompatibilita:
Vim je dostupný na mnoha platformách; ve srovnání s vi má mnoho dal¹ích
mo¾ností (viz http://www.vim.org/doc/vi.diff.txt). Vim je kompatibilní
prakticky se v¹emi pøíkazy vi --- kromì chyb, samozøejmì :-)
Operaèní systémy:
Vim je pou¾itelný na mnoha systémech: AmigaOS, Atari MiNT, BeOS, DOS,
MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, Win16 + Win32
(Windows95/98/00/NT) --- no a samozøejmì FreeBSD a Linux :-)
Copyright:
Autorská práva jsou v rukou hlavního autora, Brama Moolenaar
<[email protected]>. Vim je charity-ware, co¾ znamená, ¾e by bylo dobré
pøispìt na sirotky v Ugandì (viz ":help uganda"), pokud se vám Vim líbí.
Zdrojový kód:
Vim je OpenSource a vítán je kdokoliv, kdo chce pøispìt k jeho vylep¹ení.
=== Mo¾nosti
U¾ivatelská pøítulnost:
Vim je pro zaèáteèníky mnohem pøítulnìj¹í, ne¾ vi. Obsahuje toti¾
rozsáhlou online nápovìdu, undo a redo, podporu pro my¹ a nastavitelné
menu.
Jazyky:
Vim má podporu pro psaní zprava doleva (Arab¹tina, Farsi, Hebrej¹tina) a
multi-byte texty --- tedy podporuje i jazyky, jejich¾ znaky jsou
reprezentovány více ne¾ jedním bytem: Èín¹tinu, Japon¹tinu, Korej¹tinu
apod. Technicky øeèeno, Vim podporuje UTF-8 a Unicode.
Doplòování:
Vim doká¾e doplòovat to, co pí¹ete --- a» u¾ jsou to pøíkazy, jména souborù
nebo slova.
Automatické pøíkazy:
Vim umo¾òuje vykonávat pøedem urèené akce, napøíklad dekomprimaci zabalených
souborù.
Speciální znaky:
Vim umo¾òuje vkládat speciální znaky kombinací dvou znakù, napøíklad
kombinace '"' a 'a' vlo¾í do textu 'ä'.
Historie:
Vim si pamatuje pøíkazy, které jste ji¾ napsali a umo¾òuje vám je opìt
vyvolat a upravovat.
Makra:
Vim doká¾e nahrát posloupnost pøíkazù a posléze ji pøehrát, tak¾e
zjednodu¹uje opakovanou práci s textem.
Pamì»ové limity:
Vim toho vydr¾í mnohem víc ne¾ tradièní vi, a» u¾ v délce øádky nebo
velikosti schránek.
Doprovodné soubory:
Vim obsahuje celou øadu souborù, které jsou jeho souèástí, ale nemusí
být pøekládány spolu s programem, napøíklad soubory s definicí syntaxe
nebo soubory s nápovìdou. Vim 5.7 obsahuje 70 souborù s nápovìdou
(kolem dvou megabytù textu), ta popisuje ve¹keré pøíkazy, nastavení
a rùzné tipy ohlednì konfigurace Vimu a úpravy textù. Vim 6.0x obsahuje
85 souborù nápovìdy, dohromady necelé tøi megabyty textu. Nìkteré soubory
nápovìdy se zaobírají specifiky Vimu na konkrétních operaèních systémech.
Skripty:
Vim obsahuje skriptovací jazyk pro jednoduché roz¹iøování.
Ulo¾ení stavu:
Není problém ulo¾it stav celého prostøedí do souboru "viminfo" a pou¾ít
ho a¾ po jisté sléze. Ulo¾it se dají napøíklad v¹echny schránky, pozice
v souborech a zálo¾ky v nich, registry, pøíkazová historie a historie
vyhledávání.
Doplòování tabulátoru:
Vim umo¾òuje automaticky doplnit tabulátory tam, kde je nìjaký tabulátor
obklopený mezerami, pøípadnì mù¾e nahradit odpovídajícím poètem tabulátorù
øetìzec mezer.
Systém tagù:
Tagy jsou èásti textu, které se dají chápat jako náve¹tí --- lze je
prohledávat, skákat z jednoho na druhý apod. Napøíklad v C lze jednodu¹e
odskoèit ze jména funkce na její definici.
Textové objekty:
Vim chápe jisté èásti textu (slovo, vìta, odstavec) jako ucelené objekty
a umo¾òuje s nimi jako¾to s celky pracovat. Je mo¾né upravit definici
tìchto objektù, a tedy zmìnit, co si Vim pøedstaví pod pojmem "slovo" apod.
Dal¹í mo¾nosti:
Do Vimu je mo¾né integrovat Perl, Tcl nebo Python. Pod Windows se Vim mù¾e
chovat jako OLE automation server. Pod X Window umo¾òuje Vim vyu¾ívat
nastavitelná menu a my¹.
=== Odkazy
¡¡¡¡Sven:ÎÒ1967ÄêÉúÓڵ¹ú°ØÁÖ. ÎÒÒ»Ö±ÔÚ°ØÁÖÉú»î,
ÎÒÄ¿Ç°ÔÚ´ÓÊÂÊýѧºÍ¼ÆËã»ú¿ÆѧµÄÑо¿. 1989ÄêÎÒͨ¹ýEmailÁ˽⵽Internet,
1992ÄêÎÒ¿ªÊ¼Ê¹ÓÃÐÂÎÅ×é,
ÎÒ¾-³£ÓÃËü½øÐÐͨѶ.Web³öÏÖºóÎÒ¿ªÊ¼ÔÚÍøÒ³ÉÏÕûÀíÎÒ¹ýȥʹÓùýµÄÕâЩÈí¼þ
¡¡¡¡1999Äê9ÔÂÎÒÖÕÓÚÈ¥ÁËÃÀ¹ú, ÄÇ´ÎÊÇÎÒµ½¼ÓÀû¸£ÄáÑÇÂÃÓÎ,
ÔÚÄÇÀïÎÒ¼ûµ½ÁËÎÒÈÏʶÒѾõÄÍøÓÑÃÇ.
¡¡¡¡ÎÒ´Óû¼ûµ½Bram±¾ÈË, ËùÒÔÎÒÕæµÃ¿´Ò»¿´ËûµÄÕÕƬ²ÅÖªµÀËû³¤Ê²Ã´Ñù.
¡¡¡¡¼Ç:Äãʲôʱºî¿ªÊ¼Ð´vim, ÊÇʲô´ÙʹÄãÏëдһ¸öÕâÑùµÄÈí¼þ,
ÄܸúÎÒÁÄÁÄvimµÄ·¢Õ¹Ê·Âð, ¿ÉÒÔ˵vimÊÇ×îºÃµÄÂð?
¡¡¡¡Sven:1992ÄêÎÒ¾ÍÔÚÕÒÒ»¸ö¿ÉÒÔÔÚÎÒµÄMacintosh IIvx»úÉÏÓõÄvi±à¼-Æ÷ .
ºóÀ´ÎÒÓֻعýÍ·À´ÓÃÁËÒ»Õó×ÓDOS(Ô-ÒòºÜÃ÷ÏÔ), ËäÈ»ÎÒÓиü¶àµÄÀíÓÉϲ»¶ Macintosh,
µ«Ã»ÓÐMacintosh°æµÄvi.
¡¡¡¡1994ÄêÓÐÈËÏòÎÒÍƼöÁËvim-2, ÎÒ¾ªÏ²ÓÚÖÕÓÚÓÐÈË¿ªÊ¼Ôö²¹viµÄ¹¦ÄÜÁË.
ÈËÄÇʱÆðÎҾͿªÊ¼Í¨¹ýÒ»¸öÖ÷Ò³Ö§³ÖvimµÄ·¢Õ¹, ͬʱϣÍûÓÐÒ»Ìì°ÑËüÒ²ÒÆÖ²µ½
MacintoshÉÏÈ¥.
¡¡¡¡vim-4°æûÓгöMacintoshµÄ°æ±¾, ÕâÈÃÎÒʵÔÚÊÇʧÍû.
¡¡¡¡1997Äê9ÔÂÎÒ×¢²áÁËÓòÃûvim.org, ¿ÉÒÔ¸üºÃµØÖ§³ÖvimµÄ·¢Õ¹ÁË.
¡¡¡¡½ñÌìµÄvimÒѾ-Ô¶·ÇÎô±ÈÁË, ºÜ¶àÆäËü±à¼-Æ÷µÄÓÅÁ¼ÌØÐÔÒ²Ó¦Óû§Ö®ÐèÌí¼Óµ½vimÀï,
vim¼¸ºõ¿ÉÒÔÔËÐÐÔÚÿһÖÖƽ̨ÉÏ, ÓÖÓÐÁËͼÐνçÃæ.
²»¹ýMacintosh°æµÄÒÆÖ²ÎÊÌ⻹ÊÇÈÃÎÒ...
¡¡¡¡¼Ç:Äãƽ¾ùÿÖÜ»¨¶àÉÙʱ¼äÔÚvim/vimÍøÒ³ÉÏά»¤ÉÏ, »¨¶àÉÙʱ¼äÈ¥»ØEMAIL ,
»Ø¸²comp.editorsÐÂÎÅ×é, ÄãÔõÑù°²ÅÅ»¨·ÑÔÚÄãµÄ¹¤×÷ÈÎÎñºÍvimÉϵÄʱ¼ä
¡¡¡¡Bram:ÎÒ»¨ÔÚÔĶÁºÍ»Ø¸²vimµÄÐÂÎÅÁбíÉϵÄʱ¼äÌ«¶àÁË, ÓÐʱºîÎÒÕæÏë²»¹ÜËüÁË,
µ«ÎÒ¿´²»µÃÄÇЩÓʼþûÈ˻ظ². ÏÖÔÚ»¹¿ÉÒÔ, ¹¤×÷Ö®ÍâÎÒµÄʱ¼ä»¹ºÜ³äÔ£ ,
²»¹ýÎÒ»¹ÊǾ-³£ÔÚ°ëÒ¹Àï»ØÄÇÀïÓʼþ.
¡¡¡¡ÎÒ¾ö¶¨²»ÔÚcomp.editorsÉϻÁË, ÄǸöÌ«ÀË·Ñʱ¼äÁË,
ÐÒºÃÓÐSvenºÍÆäËûһЩÈ˼°Ê±»Ø´ðÈËÃÇÌáµÄÎÊÌâ.
¡¡¡¡ÎÒ¼¸ºõÿÌ춼ҪΪvim»¨µãʱ¼ä, ÓÐʱֻÊÇÐÞ¸ÄÒ»µãСÎÊÌâ,
ÓÐʱ¾ÍÒª´óµ¶À«¸«µØ×öһЩ´ó¶¯×÷ÁË. Ö»ÓÐÎÒ²»ÔÚ¼ÒʱÎҲſÉÄÜÒ»Ìì²»Åövim.
¡¡¡¡Sven:ÎÒ¼¸ºõËùÓеÄʱ¼ä¶¼»¨ÔÚvimÉÏ,
´ó²¿·Öʱ¼ä¶¼ÔڻشðÎÊÌâ(comp.editorsÉϵÄÌù×Ó, Ö±½Ó·¢¸øÎÒµÄÓʼþ,
»òÕßÊÇ·¢ÔÚvimµÄÓʼþÁбíÉϵÄÓʼþ.)ºÍά»¤ www.vim.orgµÄÍøÕ¾ÉÏ.
¡¡¡¡¾-³£ÓÐÈË·¢Ë͸øÁËÒ»¸ö²¹¶¡°ü, ÓÉÎÒÀ´¾ö¶¨Òª²»Òª°ÑËü¼Ó½øÈ¥,
ÆäʵºÜÄѾܾø±ðÈ˵IJ¹¶¡°ü, ÒòΪÕⶼ·´Ó³ÁËÓû§±¾È˼±ÇÐÏ£Íû¿´µ½µÄÌØÐÔ.
µ«Í¬Ê±Ò²ÓÐÈ˱§Ô¹Ëµvim±äµÃÔ½À´Ô½´óÁË. ÎÒ¾¡Á¦ÒªÔÚÕâÁ½ÕßÖ®¼ä±£³Öƽºâ.
¡¡¡¡Ô-ÔòÉÏÀ´Ëµ, ÿ¸öÈ˶¼¿ÉÒ԰Ѳ¹¶¡·¢¸øÎÒ.
Èç¹ûÎÒ¾õµÃÓбØÒª¾Í»á°ÑËü¼ÓÈëµ½vimµÄÕýʽ°æ±¾ÖÐÀ´,
ÕâÒ²¿´·¢²¹¶¡µÄÈËÒªÇóµÄµ½µ×ÊÇʲô, ÁíÍâ, ²¹¶¡±¾ÉíµÄÖÊÁ¿. µ«ÊÇvimÒѾ-±äµÃºÜÅÓ´óÁË,
ËùÒÔÎÒ¸üҪϸÐÄÕçÑ¡.
¡¡¡¡ÎÒʵÔÚÅå·þËûµÄÔðÈÎÐĺͶԸ÷ÖÖÕù¶ËµÄ°ÑÎÕÄÜÁ¦ - ¼´Ê¹ÊÇÒ»³¡¼¤ÁÒµÄÕùÂÛ .
ÎÒÖÔÐÄÏ£ÍûËûÄÜΪ×Ô¼ºµÄŬÁ¦µÃµ½Ó¦Óеı¨³ê, ºÃÈÃËûÄÜÏóÏÖÔÚÕâÑùϸÐĺǻ¤ vimµÄ³É³¤.
¡¡¡¡µ«Õâ¶Ô¿ªÔ´Èí¼þµÄ¹±Ï×ÕßÃÇÀ´Ëµ»¹ÊÇÒ»¼þûӰµÄÊ - µ½ÄÄÀïÈ¥ÕÒÕâÑùµÄ±¨³êÄØ?
Ò²ÐíÏólinuxfind.orgÕâÑùµÄÕ¾µã»áÌṩһЩÔÞÖú.
¡¡¡¡Bram: vimµÄÌåϵ½á¹¹Ò»Ö±ÔÚ²»¶ÏµÄ¸ïÐÂÖ®ÖÐ.
ÓÐʱҪ¼ÓÈëÒ»¸öеÄÌØÐÔ²»ÐèÒª¸Ä¶¯Ì«¶àµÄ´úÂë. Èç¹ûмÓÈëµÄÌØÐÔÈÅÂÒÁËÕû¸öÏîÄ¿,
ÄÇÎÒ¾ÍÒª·ÑÒ»·¬ÐÄ˼ºÃºÃÏëÏëÕýÈ·µÄ½â¾ö·½°¸ÁË. ÏÖÔÚvimÊÇÒ»¸öºÜ´óµÄ³ÌÐòÁË.
ÕâÑù×ö¿É²»ÈÝÒ×.
¡¡¡¡Sven: ¿ª·¢Ð¡×éµÄ³ÌÐòÔ±ÃǶ¼ÖªµÀvimµÄÔ´´úÂëÊ®·Ö³öÉ«.
µ«ÊÇÿÔö¼ÓÒ»¸öеÄÌØÐÔ¶¼»áÔö¼ÓϵͳµÄ¸´ÔÓÐÔ. Õâ¾ÍʹµÃºÜÄÑΪ´Ëд³ö²¹¶¡.
¡¡¡¡Ã¿´ÎÎÒÐÀϲÓÚvimÓÖ¼ÓÈëÁËÐÂGUIÌØÐÔ¶ø¸üÊÜ»¶Ó-ʱ,
ÕâЩеÄGUIÌØÐÔ¶¼»áÏûºÄÒ»´ó¶Ñ²¹¶¡. ²ÉÓÃÒ»ÖÖеÄGUI×ÜÊÇÌرð·ÑÊÂ,
µ±È»¿ª·¢ÆðÀ´Ò²¸ü·Ñʱ.
¡¡¡¡ÓÐʱÉõÖÁÔö¼ÓÒ»ÖÖÐÂƽ̨µÄÖ§³Ö¶¼±ÈÔö¼ÓÁíÍâÒ»¸öGUIÀ´µÃÈÝÒ×...
¡¡¡¡µ«ÊDz»¹ÜÔõôÀ´ËµvimµÄ·¢Õ¹»¹ÊÇÊ®·ÖѸËÙµÄ - Ïà¶ÔÓÚ¸ú²»Éϲ½µÄÎĵµÀ´Ëµ.
ÓбØÒªÔö¼Ó¸ü¶àµÄÎĵµÀ´ËµÃ÷ÈçºÎ³ä·ÖµØʹÓÃvim.
¡¡¡¡ÏÖÔÚÒѾ-¿ÉÒÔÖ§³ÖÏ£²¨À³ÎĺͲ¨Ë¿ÎÄÁËÒÔ¼°Ò»Ð©ÑÇÖÞÓïϵµÄ±àÂëÁË. ¶ÔÎÒÃÇÀ´Ëµ,
´ÓÓÒµ½×ó½øÐÐÔĶÁ, ¿´×ÅвåÈëµÄ×Ö·ûÊÇÍùºóµ¹µÄÕæÊǾõµÃºÃЦ. ÔÚ6.0
°æ±¾ÖÐÎÒÃǼƻ®Òª¼ÓÈëUTF-8¸ñʽ(ʲô¶«¶«?), ÏÖÔÚÕâÖÖ¸ñʽµÄʹÓÃÔ¶±ÈÒÔÇ°ÒªÀ´µÃÆÕ±éÁË.
¡¡¡¡ÎÒÏ£Íûvim»á¼ÓÈë¹ú¼Ê»¯µÄÏûÏ¢ÏÔʾ, ¶øÇÒ×îºÃÓÐÈËÀ´·-ÒëÔÚÏß°ïÖúϵͳ.
²¢ÇÒÄܼ°Ê±¸ú×ٱ仯µÄ²½·¥. (Ôݲ»¿¼ÂÇ´ÓASCII×Ö·ûµ½ÆäËü×Ö·û¼¯´øÀ´µÄÎÊÌâ)
¡¡¡¡ÎÒÃÇÒѾ-ÔÚΪ°ïÖúÎĵµµÄ·-Òë×ö³öŬÁ¦ÁË. »¶Ó-´ó¼ÒÓ»Ô¾Ö§³Ö -
µ«ÊÇÎÒÊÇÒ»Ïî¼è¿àµÄÈÎÎñ.
¡¡¡¡Bram: ĿǰΪֹ»¹Ã»ÓÐÈËÒòΪvim¸øÎÒÌṩһ·Ý¹¤×÷.
µ«ÊÇÎÒµÄÈ·ÓëÊÀ½ç¸÷µØµÄÈËÃDZ£³Ö×ÅÁªÏµ. Ò²ÐíÕâ»áÓÐÖúÓÚÎÒÕÒµ½Ò»·Ý²»´íµÄ¹¤×÷°É.
¡¡¡¡ÓëÊÀ½ç¸÷µØµÄÈËÃDZ£³ÖÁªÏµÊÇÒ»¼þºÜÓÐȤµÄÊÂ. ËäȻֻÊÇͨ¹ýe-mail.
¸÷ÖÖ²»Í¬µÄÎÄ»¯¾ÍÒþ²ØÔÚËûÃǵÄ×ÖÀïÐмäÀï. e-mailÈÃÕâÒ»Çж¼³ÉΪÁË¿ÉÄÜ,
ÕâÕæÊÇÌ«²»¿É˼ÒéÁË. ¸Õ¿ªÊ¼Ê¹Óò»¾õµÃÔõôÑù. µ«ËûÄÜÈÃÈËÃÇ¿ÕÇ°µØ¾Û¼¯ÔÚÒ»Æð.
¡¡¡¡ºÜ¶àÓû§ËµËûÃÇÏ£ÍûËûÃǵijÌÐòÄÜÖ§³ÖÒ»ÖÖÍⲿµÄ±à¼-Æ÷ÕâÑùËûÃǾͿÉÒÔʹÓÃvim.
ÎÒ¶àôϣÍûÓÐÕâÑùµÄ¹«Ë¾ÄܲÉÄÉÕâÑùµÄÒâ¼û.
¡¡¡¡Ë-ÖªµÀ - Ò²ÐíÓÐÒ»ÌìÄãÄÜÔÚÒ»¸ö´øÓÐÍâ¹Ò±à¼-Æ÷µÄ³ÌÐòÄÚÓÃvim±à¼-Îı¾.
¡¡¡¡Bram: ÕâÊÂÒª´ÓÎÒ×Ô¼ºµÄ¹ÊÊÂ˵Æð.
¡¡¡¡ÎÒÒѾ-ºÜ¶à´ÎÀûÓüÙÆÚµÄʱ¼äµ½²»Í¬µÄ¹ú¼ÒÓëµ±µØµÄÈËÃÇ´ôÔÚÒ»Æð.
ÕâÖÖ·½·¨ÈÃÎÒÁ˽â¸ü¶àµÄÈËÃÇ.
¡¡¡¡ÎÒÓÚ1993ÄêÔÚÎڸɴï´ôÁËÒ»¸öÔÂ. ÄÇÊǸöºÜÌرðµÄµØ·½,
ÒòΪÕâÊÇÎÒÃǵÚÒ»´ÎÅöµ½ÎÒÃÇ¿ÉÒÔÇÐÇÐʵʵÐèÒªÎÒÃÇ°ïÖúµÄÈËÃÇ.
ÔÚÆäËüµØ·½ÈËÃDz¢²»»áÕæÕýÐèÒªÎÒÃÇÈ¥°ïÖúËûÃÇ. »òÕßÎÒÃÇû°ì·¨È¥Ôõô°ïÖúËûÃÇ.
µ«ÔÚÎڸɴï, ÄÇÀïµÄÈËÃÇȷʵÐèÒª°ïÖú. ÈýÖܵÄʱ¼äÄÚÎÒÃdzÉÁ¢ÁËÒ»ËùÓ׶ùÔ°.
ÄÇÊÇÒ»´ÎºÜÌرðµÄ¾-Àú.
¡¡¡¡µÚ¶þÄêÎÒÓÖÈ¥ÁËÄÇÀïÒ»¸öÔÂ. ¿´µ½ÄÇÀïµÄº¢×ÓÃÇÔÚеÄѧУÀïÉÏѧ.
ÕâÖÖÇé¾°´ó´óµØ´¥¶¯ÁËÎÒ, ÎÒ¾ö¶¨ÔÚÄÇÀ﹤×÷ÉÏÒ»Äê.
Ò»Äêʱ¼äÀïÎÒÖÂÁ¦ÓÚÌá¸ßµ±µØÈËÃǵÄÒûË®ÓëÒ½ÁÆÉèÊ©µÄˮƽÉÏ. Ò²¸ü¶àµØÁ˽âÁ˵±µØµÄÈËÃÇ.
¡¡¡¡ËùÓÐÊÕµ½µÄ¾èÔùÆ·¶¼Ô-·â²»¶¯µØÓÃÔÚÁ˺¢×ÓÃÇÉíÉÏ. ÎÒÃǵÄÄ¿±êÊÇÕùÈ¡ÓÐ
5%µÄÈËÀ´¾èÔù, ʵ¼Êˮƽ»¹µÍÓÚÕâ¸öÄ¿±ê(1998ÄêÊÇ1.9%)
¡¡¡¡µ±ÎÒ¶Áµ½"vimÊÇ´ÈÉÆÈí¼þ"ʱÎÒÒâʶµ½vim²»½ö°ïÖúÁËËüµÄÈí¼þÓû§ÃÇ,
Ò²°ïÖúÁ˺ܶà¹Â¶ù. ËùÒÔÎÒÏ£ÍûÎÒÔÚvimÉϵÄŬÁ¦Ò²»á¶ÔËûÃÇÆðµ½¼ä½ÓµÄ°ïÖú×÷ÓÃ.
¡¡¡¡ÎÒûȥ¹ýÎڸɴï, µ«ÎÒÔÚ1977ÄêסÔÚ¶«·Ç¿ÏÄáÑǵļ¸¸öÔÂʱ¼äʱ½Ó´¥ÁËÄÇÀïµÄÈËÃÇ.
ҲȥѧУ¿´ÁË¿´(ÔÚkissi - kissiÊÇʲôµØ·½)
¡¡¡¡Ã¿´Î¿´µ½´ÓÍâÃ湫˾À´µÄEMAILÎÒ¶¼ÄþÔ¸ËûÃÇÊÇÎÊËûÃÇÄÜ·ñΪÎڸɴïµÄ¹Â¶ùÃÇ×öµãʲô¶ø²»ÊÇÎÊvimµÄǧÄê³æÎÊÌâ.
¡¡¡¡ÎÒ¿ÖÅÂÄÑÒÔ¹À¼ÆvimµÄÓû§Ãû, »¨Ê±¼äÈ¥¼ÆËãÕâ¸öÊý×ÖÖ»»áÀË·Ñʱ¼ä.
¡¡¡¡²»¹ýÓÐÒ»¼þÊ¿ÉÒԿ϶¨ -
Ô½À´Ô½¶àµÄÈËÃÇ´Ó×î³õµÄviת¶øʹÓÃviµÄ¸÷ÖÖ¿Ë¡°æ±¾(elvis, lemmy, nvi, vile, vim).
¡¡¡¡vim-5×î´óµÄÐÂÔöÌØÐÔÊÇÓï·¨¸ßÁÁ,
ÕâÒ»¹¦ÄÜʹµÃvim¿ÉÒÔ¸ù¾Ýµ±Ç°±à¼-µÄÎı¾ÀàÐÍËù¶ÔÓ¦µÄÓï·¨¹æÔòÒÔ²»Í¬µÄÑÕÉ«ÏÔʾÎı¾µÄ²»Í¬³É·Ö.
ͨ³£ÕâÓÃÓÚ³ÌÐòÔ±ÃDZà¼-ËûÃǵÄÔ´´úÂëÎļþ.
²»¹ývimÒ²ÄܺܺõØÖ§³ÖEMAILºÍÐÂÎÅ×éÏûÏ¢µÄÓï·¨¸ßÁÁ¹¦ÄÜ.
¡¡¡¡¼Ç:
vim5.4°æ¸Õ·¢²¼Äã¾ÍÕÅÂÞ×ÅÒªÔÚ2000Äê·¢²¼vim6µÄÊÂÁË...ÏÂÒ»¸öǧÄêÖÐÄã¶ÔvimÓÐʲô¼Æ»®?
¡¡¡¡È¥Äê½øÐÐÁËÒ»´Î¹ØÓÚÓû§×îÏ£ÍûµÄvimÌØÐÔµÄͶƱ. ÕâÓÐÖúÓÚÎÒ¾ö¶¨½ÓÏÂÀ´Òª×öʲô.
ÆäÖÐÒ»¸öÌØÐÔÊÇ`ÕÛÐÐ'. ÕâÊÇVim6.0ÖÐÊ×ÒªµÄÐÂÔöÌØÐÔ. `ÕÛÐÐ'¿ÉÒÔÒþ²ØÎı¾µÄÒ»²¿·Ö,
ÕâÑù¿ÉÒÔºÜÈÝÒ×°ÑÎÕÕû¸öÎĵµµÄ½á¹¹. ±ÈÈç˵, Äã¿ÉÒ԰Ѻ¯ÊýÌ嶼¸ø`ÕÛµþ'ÆðÀ´.
ÕâÑùÄã¾Í¿ÉÒÔ¶Ôº¯ÊýÓиö´óÌåµÄ°ÑÎÕ, »òÐíÄãÒªÖØÐÂÅÅÁÐËüÃǵÄ˳Ðò.
¹âÊÇÕâ¸ö¾ÍÓкܶà¾ßÌåµÄÊÂҪȥ×ö, ËùÒÔ×îºÃΪ´Ë·¢²¼Ò»¸öеİ汾.
¡¡¡¡Sven: 1998ÄêµÄͶƱ½á¹ûÏÔʾ`ÕÛÐÐ'ÊÇÓû§×îÏ£ÍûµÄÌØÐÔ.
ËùÒÔvim-6µÄÖ÷ҪĿ±ê¾ÍÊǼÓÉÏÕâÒ»ÌØÐÔ.
¡¡¡¡Óû§ºôÉùÅÅÃûµÚÈýµÄÊÇΪ¸÷ÖÖÓïÑÔÁ¿Éí¶¨×ö`¿ÉÅäÖõÄ×Ô¶¯Ëõ½ø', ÒòΪ
Vim¾ø¶ÔÊÇÒ»¸ö³ÌÐòÔ±µÄ±à¼-Æ÷...
¡¡¡¡¶Ô³õѧÕ߶øÑÔÄÜÔÚÆÁÄ»ÉÏ¿´µ½ËùÓеÄ×Ö·ûÊǺÜÖØÒªµÄ(ÐÐβ¿Õ°××Ö·ûºÍÌØÊâ×Ö·û).
ÌØÊâÑÕÉ«µÄÏÔʾ°ïÁËÕâ¸öµÄ´óæ.
VimÄÚÖõÄÎĵµ¸ñʽ»¯¹¦ÄܶÔÓÚÒª·¢Ë͵½ÐÂÎÅ×éµÄÎı¾»òEMAILÐżþÀ´ËµÊÇÒ»¸öÊ®·ÖÇ¿´óµÄ¹¤¾ß.
¡¡¡¡Í¨¹ýÍøÂçÁ¬½Ó±à¼-Ò»¸öÔ¶³ÌÎļþ, `ÕÛÐÐ'(¼ûÉÏ),
ʹÓöà×Ö½Ú×Ö·ûÓïÑÔµÄÖ§³ÖÒ²ÊǵÃƱºÜ¸ßµÄÇëʾ. µ«ÊÇÕâЩʵÏÖÆðÀ´¿É²»ÈÝÒ×.
ͬʱÎÒҲϣÍû´ó¼ÒÄÜ°ïÖúÎÒÃÇʵÏÖÕâЩÓÕÈ˵ŦÄÜ.
¡¡¡¡ÎÒÓÈÆäÏ£Íû¿´µ½`ÕÛÐÐ'¹¦ÄÜ. ºÜ¶àÓû§½«½èÖúÕâÒ»ÌØÐÔä¯ÀÀËûÃÇÎļþµÄ´ó¸Ù.
ÓʼþÁбíÉϵÄÌÖÂÛ±íÃ÷ÕâʵÏÖÕâÒ»µã»¹ÓкܶàÀ§ÄÑÒª¿Ë·þ, ÕâÕæÊÇÌ«¸»ÓÐÌôÕ½ÐÔÁË!
¡¡¡¡²»¹ý, ÎÒ»¹ÊÇÈÏΪÔÚÔö¼ÓÕâЩÖØͷϷ֮ǰ×îºóÏȽâ¾öһЩСÎÊÌâ.(±ÈÈç:
Ò»¸öÄÚÖõķÇͼÐÎÓû§½çÃæµÄÎļþä¯ÀÀÆ÷.)
¡¡¡¡TODOÁбíÊÇÒ»¸ö¼¼ÊõÉϵÄÄ¿±êÇåµ¥. ÉÏÃæµÄºÜ¶àÌõÄ¿±ê¼Ç×ÅÒª½øÐеļ¼ÊõÉϵÄÌáÉý.
Èç¹ûÄã²»ÄÜÊìÖªVimµÄËùÓиÅÄî¿ÉÊǺÜÄÑ¿´¶®Õâ¸öÁбíµÄ.
¡¡¡¡ºÜ¶àÌØÐÔµÄÔö¼ÓÊÇΪÁËÃÖ²¹Í¼ÐÎÓû§µÄ²»×ã. ¶øÇÒ,
ºÜ¶àʹÓÃViÔËÖ¸Èç·ÉµÄÓû§¸ù±¾²»ÐèÒªÒ»¸öͼÐÎÓû§½çÃæ.
ÎÒ±¾ÈËʹÓÃGUIÒ²Ö»ÊÇΪÁË°ïÖúÁ˽â±ðÈ˹ØÓÚÕâ·½ÃæµÄÎÊÌâ, ×ö×Ô¼ºµÄÊÂÎÒ´ÓÀ´¶¼²»ÓÃËü.
¡¡¡¡´ÓÉÏÃæµÄÕâЩÄãÒ²¿´µÃ³öÀ´ÎÒµÄÐËȤÖ÷ÒªÔÚÓÚvimµÄ·ÇͼÐÎÓû§½çÃæµÄÌØÐÔÉÏ,
ÕâÑùµÄÌØÐÔ¿ÉÒÔÔÚµÄÖÕ¶ËÉÏʹÓÃ, Ö»ÒªÓÃÃüÁî±¾Éí¾ÍÐÐÁË.
ÎÒËùÊÕµ½µÄ·´À¡Ò²±íÃ÷´ó¶àÊýÈËÒªµÄÕýÊÇÕâ¸ö -
¶ø²»ÊÇÖîÈç²Ëµ¥»òһЩÌØÊâ³ÌÐòµÄÖ§³ÖÈçƴд¼ì²éÆ÷»ò±à³ÌÓïÑÔ·½Ãæ.
¡¡¡¡ËùÒԺܾÃÒÔÇ°ÎÒ¾ÍÓÐÁËÒ»·ÝÕâÑùµÄÁбí, ÃèÊöÓû§ÔÚÿÌìµÄ±à¼-¹ý³ÌÖÐʵ¼ÊÅöµ½µÄÎÊÌâ,
ÒÔ°ïÖú¿ª·¢Ð¡×éÈÏʶµ½ÕâЩÎÊÌâ²¢Ìá³ö½â¾ö·½°¸.
¡¡¡¡ÎÒÊ®·Öϲ»¶ÓÃVim½øÐбà¼-,
ÎÒÏ£ÍûÎÒÔÚ¿ªÔ´Èí¼þÉϵÄŬÁ¦Ò²ÄÜ°ïÖú¸ü¶àµÄÈËÃÇ´ïµ½ËûÃǵÄÄ¿±ê.
¡¡¡¡Èç¹ûÄãʹÓÃVim¹ý³ÌÖÐÓöµ½ÎÊÌâ¿ÉÒÔÊÔÒ»ÏÂ":help", ËùÓеÄÔÚÏß°ïÖúÎĵµ¶¼ÊÇ´¿Îı¾µÄ,
ËùÒÔ´òÓ¡³öÀ´Ó¦¸Ã²»»áÓÐʲôÎÊÌâ.
¡¡¡¡¸½¼ÓµÄÎĵµÒ²²¹ÉÏÁË, ±ÈÈçµÂÓï°æµÄHowToºÍ"Vim³õѧÕß"(Ò²ÊǵÂÓï)
¡¡¡¡»¶Ó-ÔÚÄãµÄÖ÷Ò³ÉÏ·¢²¼ÄãµÄ¸öÈËʹÓü¼ÇÉ»òÇÏÃÅ. »òÕßÊÇά»¤Ò»¸öÓï·¨Îļþ,
ijÖÖ²Ù×÷ϵͳµÄ¶þ½øÖÆÎļþ, »òÕßÔÚÐÂÎÅ×é, ÓʼþÁбíÀï»Ø´ð±ðÈ˵ÄÎÊÌâ
¡¡¡¡·Ç³£·Ç³£»¶Ó-Ìṩ¸÷ÖÖÐÎʽµÄ°ïÖú. :-)
---END----
ÖÂ
Àñ£¡
ÕÔÈç·É
[email protected]
Site Information
● Home
● About This Site
● Advertise This Site Editors - Page 1
● Search This Site Last Updated: 10/07/2001
● Submit Software
Software Categories
jEdit Development v3.1 (Editor's Pick)
● Audio
jEdit is a text editor designed for programmers. jEdit's features include: syntax
● CDRW Softwares highlighting for over 30 file types, including C, C++, HTML, Java, and Perl;
● Communications automatic indenting; bracket highlighting and matching; a macro system; and
● Desktop scriptable search and replace capability. You can set up function abbreviations;
record any number of strings and caret positions in multiple registers; perform
● Developer Tools rectangular selections for working with column-based files; and customize file
● Distributions filters in the "Open" and "Save" dialog boxes. The program also includes powerful
text editing commands for working with whole words, lines, and paragraphs; the
● Email
ability to open any number of editor windows; and unlimited undo and redo
● File Management capabilities.
● Graphics [Download] [Home Page] [License: Free To Use But Restricted] [Size: 868KB]
[Date Updated: 23/04/2001]
● Internet
● Network VIM 5.8 (Editor's Pick)
● Office
VIM is an improved version of the editor "vi", one of the standard text editors on
● Security UNIX systems. VIM adds many of the features that you would expect in an editor:
● System unlimited undo, syntax coloring, split windows, visual selection, GUI support, and
much more.
● Video MPEG
[Download] [Home Page] [GNU Public License] [Size: ] [Date Updated:
● Web Design 01/06/2001]
gEdit v0.9.0
gEdit is a text editor for the Gnome desktop environment. gEdit is designed to be
simple, light, and fast, and includes a powerful plug-in system.
[Download] [Home Page] [GNU Public License] [Size: 775KB] [Date Added:
31/03/2001]
Tk Notepad v0.7.7
Tk Notepad is a text editor written using Tcl/Tk. Tk Notepad was written to mimic
the Microsoft Windows Notepad program. The program contains all of the basic
functions of Notepad, such as: cut, copy, paste, and search, but also adds other
features such as, Undo and Redo.
[Download] [Home Page] [GNU Public License] [Size: 20KB] [Date Added:
31/03/2001]
SoftLandIndia
Email: [email protected]
All Rights Reserved.
ICCF Holland
English
[home] [ICCF] [Uganda] [KCC] [News] [sponsoring]
[donation] [click]
You can find the Vim book at the sites below. Buying through these links
will send 5% to 15% of the sales to ICCF Holland. The money is used to
help orphans in Uganda (see the home page). You should also be able to
get the book in other (on-line) bookstores that have the New Riders books.
Amazon
USA
Amazon
United
Kingdom
Amazon
Deutschland
Amazon
France
Proxis
België
(at the bottom
of the list)
For comments on the ICCF Holland pages and for more information contact Bram Moolenaar.
*todo.txt* For Vim version 6.0z. Last change: 2001 Mar 24
This is a veeeery long list of known bugs, current work and desired
improvements. To make it a little bit accessible, the items are grouped by
subject. In the first column of the line a classification is used to be able
to look for "the next thing to do":
Priority classification:
9 next point release
8 next release
7 as soon as possible
6 soon
5 should be included
4 nice to have
3 consider including
2 maybe not
1 probably not
- unclassified
*known-bugs*
-------------------- Known bugs and current work -----------------------
The source archive is over the 1.4M floppy limit. How to avoid this?
E. Virtual edit:
- Still a lot of work to do. Test various commands.
- Using "A" in Insert mode, then <Right><BS> deletes the last char of the
line, even though the cursor doesn't touch it. (Mary Ellen Foster)
Check other <BS> situations in Insert mode.
- Using "C" then then <CR> moves the last remaining character to the next
line. (Mary Ellen Foster)
- Bugs: (Mark Waggoner)
See patches in ~/Mail/oldmail/waggoner/in.00132.
5. 'v' selection is kind of strange. When in virtual space, pressing 'v'
will select the last character on the line, though the cursor remains
in virtual space.
Should set the start of the Visual area in virtual space.
9. Using "C" in virtual space moves back to the end of the current
line to start changing rather than inserting spaces up to the current
point and then changing.
And when the cursor is in a TAB somewhere, it also doesn't work right.
- Leaving Insert mode when 'virtualedit' is "insert" should move the cursor
to a valid character.
- In Visual-block mode highlighting part of a tab is wrong.
- Add more documentation.
- Use vpos_t instead of fpos_t for positions that can have a coladd?
- coladvance2() can be a bit slow.
- Should not insert spaces for yank or filter.
- When past the end of a line that ends in a single character "b" skips that
word.
I. Multi-language support:
- Should handle aliases for different locale settings. "de" is "de_DE" is
"de_DE.ISO8859-1". Perhaps use some code from gettext()?
- Cmdline completion of ":langugage" for "messages" and "lctype".
J. User Friendlier
- ":setlocal option<": reset local option to global value.
9 Add a menu (or sub-menu) with most often used options: 'wrap',
'textwidth', etc.
- Add a way to save local settings and mappings into a new plugin file.
":mkplugin <file>"?
9 Add buffer-local menu. Should offer a choice between removing the menu or
disabling it. Be careful that tear-offs don't disappear (keep one empty
item?).
Alternative: use BufEnter and BufLeave autocommands.
9 Buffer-local autocommands?
:au BufEnter <current> menu enable ...
:au BufLeave <current> menu disable ...
9 Make Windows install program better:
- Add an icon on the Desktop, if the user wants this.
- Add Vim to the Start/Programs menu if the user wants this.
- Detect the OLE version and register it.
- Allow adding a "edit with Vim" entry even when Vim already is in $PATH.
- Create $VIM/vimfiles/[plugin|ftplugin|doc] directories, so that plugins
can really be dropped-in.
- Delete the vim.bat and gvim.bat files.
- Delete a whole tree of Vim files.
- Add mappings local to a window: ":map <window> ..."?
8 Add better control for protecting the user for editing a file twice, file
changed outside of Vim, file protection changed outside of Vim, etc.
Messages:
- In the message history, add a help tag for each message and number the
messages. ":msghelp <nr>" could then be used to jump to help for the
message. (Charles Campbell)
Add the ID to each error message, like: "a7: No match found"?
- Need to hit return after selecting entry for ":ts".
- Remember message line for redraw. Use instead of keep_msg. Integrate the
command line in update_screen().
- Make keep_msg allocated. Using IObuff is dangerous.
- Check: ":cn" message is sometimes cleared.
Various recent:
8 Win32 GUI: With maximized window, ":set go-=r" doesn't use the space that
comes available. (Poucet) It works OK on Win 98 but doesn't work on Win
NT 4.0. Leaves a grey area where the scrollbar was. ":set go+=r" also
doesn't work properly.
- In ":ptag" preview window highlight the tag. Use the new regexp items.
9 Motif GUI: ":hi menu font=name" crashes Vim in some situations. E.g.:
:hi menu font=fixed
:hi menu font=asdf
9 Crash when creating XIC without a fontset. (Diamond) Don't include the
XNFontSet then? Check if gui.normal_font is a fontset?
- Motif GUI: draws in right border of window, scrolling leaves pixels
behind. Scroll two more pixels? Or make window two pixels wider?
8 Motif GUI: The tooltips disappear after one or two seconds. Why don't
they stay? For GTK they also disappear, but re-appear after a second
(making them blink). Is there an event that interferes?
8 Syntax error: Can't reproduce it now. Looked like an "O" command caused a
line to be redrawn that was moved down (since a line was inserted), found
a start-of-comment error on "/*", thus it was using a cached state that
the comment already started in this line (what would be true for this line
before the new line was inserted)
9 These places need to be fixed for EBCDIC:
- AppendToRedobuffLit().
- stuffescaped().
- set_last_insert()
8 gui_w16.c and gui_w32.c still have much code in common. Move this to
gui_w48.c.
9 What happens with :execute "normal a\<Up>\200\<Esc>"?
How to distinguish a special key from a 0x80 byte? CSI too.
9 This pattern in syntax/java.vim causes a recursive call of regmatch():
syn match javaStringError +"\([^"\\]\|\\.\)*$+
A long line with a " in it can cause a crash when it runs out of stack
space (on non-Unix systems). How can we catch this?
8 'cindent' problem: (FooLman)
int x; <- extra indent, ";" ignored.
void func()
{
8 Implement ":tearoff" for other systems than Win32 GUI.
8 ":let @" = "val" should not have side effects for other registers (after
"ayy). (Raul Acevedo)
""yy should probably not change the last used register from "ayy.
9 Support ACLs on more systems.
9 Win32: double clicking on "c:\tmp\{asdf}.txt" edits "c:\tmp{asdf}.txt".
Don't remove backslash before {}? Simlarly for "Edit with Vim". (Ott)
See list with success/failure for different names and situations.
9 Win32: mouseshape doesn't return to normal after a ":set" command.
(Timothy) Stays at "no entry". Only visible with ":set nomousehide".
9 Win32: when 'shell' is "zsh", ":!start notepad file" doesn't work. (Pavol
Juhas).
8 Windows NT/2000: LCTranslateMessage() doesn't work properly. It's
disabled for now. What is the right solution?
- GUI: Implement ":popup" for other systems than Windows.
- GUI: <C--> cannot be mapped. Should be possible to recognize this as a
normal "-" with the Ctrl modifier.
9 GTK GUI with Gnome: When $DISPLAY is wrong, ":gui" unexpectedly exits.
Without Gnome it does work.
Not all Gnome arguments get to gnome_init().
8 Add "display" argument to many items in syntax files, to speed up parsing.
How to avoid that a "display" keyword no longer works? Also for "fold".
8 Make ":syntax include" to search 'runtimepath' for the included syntax
file if the argument is relative.
- update $VIMRUNTIME/optwin for new options.
- When using the file browser in GTK the absolute file name is used. Should
try to simplify it. (Lohner)
- Make it possible to set 'browsedir' to a directory name, which is always
used.
- When checking if a file exists on Unix, uses lstat(), otherwise a symlink
will not be found. Go throught the code to check for this.
- Check all use of islower()/isupper() for negative value (special key).
- Use s:name local variable in :source'ed file.
- Include pty check for Lynx: ~/vim/patches/hahn.pty .
- In an xterm, look ahead for mouse drag events, merge them and use the last
coordinates.
- Remove "\" shown in complete/wildmenu.
Bug: <C-O>:emenu in Insert mode inserts the command.
- When accidentally hitting Shift-R instead of Ctrl-R, further Ctrl-R is not
possible, also when typing <Esc> immediately. (Grahn)
- Include flipcase patch: ~/vim/patches/wall.flipcase2
- "/$" in 'list' mode should put the highlighting on the "$" character, also
for empty lines.
8 Use $install_prefix? (Cabric)
- Where 'suffixesadd' is used, also try removing a trailing "." or "," from
the file name.
8 Test if it possible for a skip pattern to include "\n", so that it can
skip over newlines for a "oneline" region.
- multi-line regexp:
Make test for multi-line regexp and ":s".
Check use of multi-line regexp in syntax highlighting.
- When starting GUI with invalid $DISPLAY, the hit-enter prompt is always in
line 2, while the "cannot open display" is somewhere else.
- When swap file message sees that date of file is newer as date of swap
file, add message "more recent than swap file".
- "ls -1 * | xargs vim" works a bit but not well. Should use stderr for all
term I/O.
- Check libcall() and libcallnr() for Win32. No crash when function returns
1 or -1?
9 ":cwindow!" always open quickfix window, ":cwindow" only open it if there
are recognized errors. ":cclose" to close quickfix window?
8 For ":silent !cmd":
":silent write" still writes a message.
":silent s//" still writes a message.
How to use ":silent" for a search command? ":silent /pat" uses ":/pat".
:silent exe "normal /path\<CR>"
Run the external command silently, don't give the hit-enter prompt.
Remove how it's done for Risc OS with ":!~cmd", see do_shell().
Don't redraw the screen, make a note in the docs that CTRL-L should be
used if the command has any output.
-> pass SHELL_FILTER to call_shell?
-> ":silent!" also stops error messages.
-> ":silent menu" creates menu that doesn't echo its command.
-> ":silent /pattern" doesn't complain when it's not found
-> ":silent :s/pat//" doesn't complain when it's not found and doesn't
report number of substitutions.
-> ":silent map": add flag to mapping, increment "silence" when exeucuting
it, append a command to decrement "silence"; reset silence when
aborting a mapping).
Or use ":map <silent>"?
-> ":silent unmap" shouldn't complain about a non-existing mapping.
Still do the messages for ":redir"?
-> ":silent redir": Remember the last message, print it if waiting for a
key (otherwise the hit-enter prompt could be missed).
Ideas in ~/vim/patches/wall.noredir.tgz (Stephen P. Wall).
- Make syntax keyword table configurable. Set number of bits used with
":syn clear [hashbits]", so that we don't need to reallocate the table.
minimal 4 bits, maximal 16. (Campbell)
- Check all places where buf_write() is called if it takes care of "buf"
becoming invalid because of autocommands. Also callers of
buf_check_timestamp().
- Add "gG": like what "gj" is to "j": go to the N'th window line.
- xterm sends <Esc>O5F for <C-End>
- Support ":browse edit" in console, using explorer.vim?
- When displaying a space with only foreground highlighting, it's the same
as a space without attributes. Avoid displaying spaces for the "~" lines
when starting up in a color terminal.
- Windows NT: writing to aux.* makes Vim hang. (Acevedo)
- Problem with cscope jumping to the wrong position? (Medley)
Selecting item 5 jumps to item 4. (Andrej Borsenkow)
- ":abbr b byte", append "b " to an existing word still expands to "byte".
This is Vi compatible, but can we avoid it anyway?
Vi incompatibility:
8 Docs for ":s&" are not correct. What is it supposed to do? When exactly
are flags re-used? What is a Vim extension?
8 With undo/redo only marks in the changed lines should be changed. Other
marks should be kept. Vi keeps each mark at the same text, even when it
is deleted or restored. (Webb)
Also: A mark is lost after: make change, undo, redo and undo.
Example: "{d''" then "u" then "d''": deletes an extra line, because the ''
position is one line down. (Veselinovic)
8 When using ":s" to split a line, marks are moved to the next line. (Geddes)
8 When using ":n" ":rew", the prev. context mark is in the same place as the
cursor, not on the first line.
8 "zt" should scroll one screen forward and put the cursor in the first
line.
8 ":z#" should list lines with line numbers. (Bob Farmer)
8 text is put in register 1 when using "c" and "d" with a motion character:
<control-A> % ( ) `<character> / ? N n { }
(from Nvi manual).
8 When stdin is not a tty, and Vim reads commands from it, an error should
make Vim exit.
8 Unix Vim (not gvim): Typing CTRL-C in Ex mode should finish the line
(currently you can continue typing, but it's truncated later anyway).
8 When loading a file in the .exrc, Vi loads the argument anyway. Vim skips
loading the argument if there is a file already. When no file argument
given, Vi starts with an empty buffer, Vim keeps the loaded file. (Bearded)
8 In Insert mode, when using <BS> or <Del>, don't wipe out the text, but
only move back the cursor. Behaves like '$' in 'cpoptions'. Use a flag
in 'cpoptions' to switch this on/off.
8 When editing a file which is a symbolic link, Vim opens another symbolic
link on the same file under the name of the first one. Adjust the file
name in the buffer to the last one used? Use several file names in one
buffer???
7 The ":map" command output overwrites the command. Perhaps it should keep
the ":map" when it's used without arguments?
7 When interrupting reading a file, Vi considers the buffer modified. Add a
'cpoptions' flag for this (we don't want it modified always to be able to
do ":q")?
7 CTRL-L is not the end of a section? It is for Posix! Make it an option.
7 Implement 'prompt' option. Init to off when stdin is not a tty.
7 CTRL-T in Insert mode inserts 'shiftwidth' of spaces at the cursor. Add a
flag in 'cpoptions' for this.
7 Add a way to send an email for a crashed edit session. Create a file when
making changes (containing name of the swap file), delete it when writing
the file. Supply a program that can check for crashed sessions (either
all, for a system startup, or for one user, for in a .login file).
7 Vi doesn't do autoindenting when input is not from a tty (in Ex mode).
7 "z3<CR>" should still use the whole window, but only redisplay 3 lines.
7 ":tag xx" should move the cursor to the first non-blank. Or should it go
to the match with the tag? Option?
7 Implement 'autoprint'/'ap' option.
7 Add flag in 'cpoptions' that makes <BS> after a count work like <Del>
(Sayre).
7 Add flag in 'cpoptions' that makes operator (yank, filter) not move the
cursor, at least when canceled. (default vi compatible).
7 Make "5dd" on last-but-one-line not delete anything (Vi compatible).
Add flag in 'cpoptions' for this. When not present, "2dd" in the last
line should delete the last line.
7 This Vi-trick doesn't work: "Q" to go to Ex mode, then "g/pattern/visual".
In Vi you can edit in visual mode, and when doing "Q" you jump to the next
match. Nvi can do it too.
7 Support '\' for line continuation in Ex mode for these commands: (Luebking)
g/./a\ g/pattern1/ s/pattern2/rep1\\
line 1\ line 2\\
line 2\ line 3\\
. line4/
6 ":e /tmp/$tty" doesn't work. ":e $uid" does. Is $tty not set because of
the way the shell is started?
6 Vi compatibility (optional): make "ia<CR><ESC>10." do the same strange
thing. (only repeat insert for the first line).
8 When "cm" termcap entry is missing, starting gvim shouldn't complain about
it. (Lohner) Try out with "vt100" entry (cm replaced with cX).
Athena GUI:
9 Use one of the Syntax menu items. Then ":aunmenu Syntax", Vim crashes.
Also crashes when using Buffers.Refresh.
9 When using ":unmenu" in menu item, the reversing of menu items is wrong.
Happens with Syntax/manual. Problem with not removing the reversed text
when destroying the menu item? For Rochholz Vim crashes.
9 Because destroying a menu can cause a crash, it is not destroyed but
unmanaged. The destoyed Widgets are remembered, this list is never
cleaned up.
9 When closing the confirm() dialog, Vim exits.
9 Menu ordering doesn't work.
9 When using "menu a.b.c.d lll", the "b" submenu does not disappear.
9 When dragging the scrollbar thum very fast, focus is only obtained in
scrollbar itself.
8 When "j" or "k" repeated quickly, display is messed up (Lauther).
8 Has extra stripes here and there. (Zeitlin).
When dragging last status line with the mouse, small black lines appear in
the command line pseudo-scrollbar (only when status line moved quickly).
7 The file selector is not resizable. With a big font it is difficult to
read long file names. (Schroeder)
Motif GUI:
9 When starting GUI with ":gui" while 'writedel' is non-zero, escape
sequences are split up. Motif version crashes.
8 When changing the color of the toolbar with ":hi toolbar", the pixmaps are
not updated. Need to destroy them and allocate with the new colors.
8 Popup menu ordering is wrong.
8 Dialog: Pointer should be moved to the default button. Accelerators don't
work yet.
8 Lesstif 0.89.4: Tearing-off a menu sometimes gives a "Restoring focus to
NULL widget!" error. Probably a Lesstif problem.
8 Lesstif: When deleting a menu that's torn off, the torn off menu becomes
very small instead of disappearing. When closing it, Vim crashes.
(Phillipps)
GUI:
9 When using a very small font, 'columns' can be very big. Pass mouse
events with 16 bits.
9 On Solaris, creating the popup menu causes the right mouse button no
longer to work for extending the selection. (Halevy)
9 When running an external program, it can't always be killed with CTRL-C.
e.g. on Solaris 5.5, when using "K" (Keech). Other 'guipty' problems on
Solaris 2.6. (Marley)
9 On Solaris: Using a "-geometry" argument, bigger than the window where Vim
is started from, causes empty lines below the cmdline. (raf)
8 X11 GUI: When menu is disabled by excluding 'm' from 'guioptions', ALT key
should not be used to trigger a menu (like the Win32 version).
8 When setting 'langmenu', it should be effective immediately. Store both
the English and the translated text in the menu structure. Re-generate
the translation when 'langmenu' has changed.
8 Basic flaw in the GUI code: NextScreen is updated before calling
gui_write(), but the GUI code relies on NextScreen to represent the state
of where it is processing the output.
Need better separation of Vim core and GUI code.
8 When fontset support is enabled, setting 'guifont' to a single font
doesn't work.
8 Menu priority for sub-menus for: Athena, Amiga, Mac, VMS, BeOS.
8 Add menu separators for Athena, Amiga, Mac, RISCOS.
8 Add way to specify the file filter for the browse dialog. At least for
browse().
8 Add dialog for search/replace to other GUIs? Tk has something for this,
use that code? Or use console dialog.
8 When selecting a font with the font dialog and the font is invalid, the
error message disappears too quick.
8 gui_check_colors() is not called at the right moment. Do it much later,
to avoid problems.
8 gui_update_cursor() is called for a cursor shape change, even when there
are mappings to be processed. Only do something when going to wait for
input. Or maybe every 100 ms?
8 X11: When the window size is reduced to fit on screen, there are blank
lines below the text and bottom scrollbar. "gvim -geometry 80x78+0+0".
When the "+0+0" is omitted it works.
8 When the character cell of some fonts is different (ascent/descent), the
cursor leaves an underline behind (Hiebert).
8 When starting an external command, and 'guipty' set, BS and DEL are mixed
up. Set erase character somehow?
8 A dead circumflex followed by a space should give the '^' character
(Rommel). Look how xterm does this.
Also: Bednar has some code for dead key handling.
Also: Nedit 5.0.2 with USE_XMIM does it right. (Gaya)
8 The compose key doesn't work properly (Cepas). Both for Win32 and X11.
7 The compiled-in highlight defaults allocate colors, which will never be
freed. Move them to a startup script? Only use bold and underline for
the compiled-in defaults.
7 The cursor in an inactive window should be hollow. Currently it's not
visible.
8 With wrapping lines, clicking below the scrollbar thumb moves more than a
screenfull of lines. Adjust the thumb size when lines wrap.
7 GUI on Solaris 2.5.1, using /usr/dt/..: When gvim starts, cursor is
hollow, after window lowered/raised it's OK. (Godfrey)
7 When starting GUI with ":gui", and window is made smaller because it
doesn't fit on the screen, there is an extra redraw.
8 When setting font with .Xdefaults, there is an extra empty line at the
bottom, which disappears when using ":set guifont=<Tab>". (Chadzelek)
8 When font shape changes, but not the size, doing ":set font=" does not
redraw the screen with the new font. Also for Win32.
When the size changes, on Solaris 2.5 there isn't a redraw for the
remaining part of the window (Phillipps).
- Flashes really badly in certain cases when running remotely from a Sun.
MSDOS/DJGPP:
8 Win32: Opening a file dir\&file doesn't work. Also \^. Do we care?
8 DJGPP: "cd c:" doesn't work. Works OK in 16-bit version. mch_getperm()
returns -1 for "c:".
9 The 16 bit version runs out of memory in test 31.
9 DOS: Make CTRL-Fx and ALT-Fx work.
CTRL-F1 = CE-5E, CTRL-F2 = CE-5F, .., CTRL-F10 = CE-67
ALT-F1 = CE-68, ALT-F2 = CE-69, .., ALT-F10 = CE-71
Shifted cursor keys produce same codes as unshifted keys. Use bioskey(2)
to get modifier mask for <S-C-M-Fx>.
Use CSI codes to insert modifier mask in input stream? Make this work
like in the GUI, but do handle a typed CSI.
Mapping things like <M-A> doesn't work, because it generates an extended
key code. Use a translation table?
9 Can't read an opened swap file when the "share" command has not been used.
At least ignore the swap files that Vim has opened itself.
8 setlocale() is bogus.
8 Vim busy waits for new characters or mouse clicks. Should put in some
sort of sleep, to avoid eating 50% of the CPU time. Test on an unpatched
Windows 95 system!
8 DJGPP: when shell is bash, make fails. (Donahoe)
7 Hitting CTRL-P twice quickly (e.g. in keyword completion) on a 8088
machine, starts printer echo! (John Mullin).
7 MSDOS 16 bit version can't work with COMSPEC that has an argument, e.g.:
COMSPEC=C:\WINDOWS\COMMAND.COM /E:4096 (Bradley)
Caused by BCC system() function (Borland "make" has the same problem).
8 Makefile.bor can't compile xxd and ctags without editing the makefiles.
Create a Makefile.bor for xxd and ctags.
8 Check if with DJGPP 2.01 the problem of a path starting with a backslash is
still present.
8 Mouse: handle left&right button pressed as middle button pressed. Add
modifier keys shift, ctrl and alt.
7 When too many files are open (depends on FILES), strange things happen.
The Dos16 version runs out of memory, in the Dos32 version "!ls" causes a
crash. Another symptom: .swp files are not deleted, existing files are
"[New file]".
7 DJGPP version doesn't work with graphics display mode. Switch to a mode
that is supported?
8 DJGPP: ":mode" doesn't work for many modes. Disable them.
Windows 95:
8 Editing a file by it's short file name and writing it, makes the long file
name disappear. Use Unix method for making a backup file? Better: make
the way the backup file is made (copy or rename) an option, not a #define
(also needed for OS/2, the icon goes to the backup file).
Use FindFirstFile()->cAlternateFileName in fname_case() (George).
8 Doing wildcard expansion, will match the short filename, but result in the
long filename (both DJGPP and Win32).
Win32 console:
9 When editing a file by its short file name, it should be expanded into its
long file name, to avoid problems like these: (Mccollister)
1) Create a file called ".bashrc" using some other editor.
2) Drag that file onto a shortcut or the actual executable.
3) Note that the file name is something like BASHRC~1
4) Go to File->Save As menu item and type ".bashrc" as the file name.
5) Press "Yes" to indicate that I want to overwrite the file.
6) Note that the message "File exists (use ! to override)" is displayed
and the file is not saved.
Use FindFirstFile() to expand a file name and directory in the path to its
long name.
8 Also implement 'conskey' option for the Win32 console version? Look at
how Xvi does console I/O under Windows NT.
7 Re-install the use of $TERM and support the use of different terminals,
besides the console.
8 Use of <altgr> modifier doesn't work? 5.3 was OK. (Garcia-Suarez/Guckes)
9 Mapping <C-S-Tab> doesn't work correctly.
9 tmpnam() uses file in root of file system: "\asdf". That doesn't work on
a Netware network drive. Use same function as for Win32 GUI?
8 In os_win32.h, HAVE_STRICMP and HAVE_STRNICMP are defined only if __GNUC__
is not defined. Shouldn't that be the other way around?
9 When using libcall() for a function that returns an invalid pointer, Vim
crashes. Check for a bad pointer with isBadReadPtr(). (Zeitlin)
Doesn't appear to work really, at least check for "1".
Amiga:
9 In mch_expandpath() a "*" is to be expanded, but "\*" isn't. Remove
backslashes in result.
8 Executing a shell, only one option for 'shell' is separated. Should do
all options, using white space separation.
Macintosh:
8 Define vim_mkdir() for Macintosh.
9 Explorer.vim isn't working properly.
9 When DiskLock is running, using a swap file causes a crash. Appears to be
a problem with writing a file that starts with a dot. (Giacalone)
9 On G3 Mac, OS version 8, control strip causes characters messed up when
scrolling (CTRL-L cleans it up). (Benji Fisher)
9 On G3 Mac, OS version 8, variable-speed scrolling doesn't work, after two
seconds of scrolling the screen freezes. (Benji Fisher)
scrolling (CTRL-L cleans it up). (Benji Fisher)
9 In mac_expandpath() check that handling of backslashes is done properly.
9 Executable is called "vimPPC" instead of "gvim"? (Amerige)
8 Standard Mac buttons and shortcuts are missing. No close button.
(Amerige)
8 An invocation of gvim hands over control to an existing gvim. (Amerige)
8 Handling of non-fixed width fonts is wrong. (Amerige)
8 StatusLine and StatusLineNC highlighting isn't right. (Amerige)
VMS:
8 VMS: Inserts <NL> every 8291 bytes when writing. (Howie) 4.5 didn't have
this problem. It's caused by the write() function, need to write() every
line separately. It seems read() also returns a single line. Switch I/O
to binary mode somehow?
7 Lots of code in common with os_unix.c, but many fixes are missing. Move
shared code to a common file? Use one file with #ifdefs?
"Small" problems:
8 For a "/*" "**" "*/" comment the end isn't aligned properly.
Using "==" the middle isn't aligned as 'comments' indicates.
:set comments=sr:/*,mb:**,ex:*/,://
8 A nested include file should also be found relative to the file that
includes it. "lev1/foo.h" includes "lev2/bar.h" which is
"lev1/lev2/bar.h". Should pass current file name on from
find_pattern_in_path() to get_file_name_in_path(). (Angus Mackay)
9 When jumping to a tag, the search pattern is put in the history. When
'magic' is on, the pattern may not work. Translate the pattern depending
on p_magic when putting it in the history? Alternative: Store value of
'magic' in history. (Margo)
9 Viminfo file becomes corrupt when editing a file with a <NL> in the name.
(file marks, buffer list, history of marks) (Alexander N.Benner, Wichert
Akkerman, Weisselberg)
Also problems with buffer menu.
9 optwin.vim: Restoring a mapping for <Space> or <CR> is not correct for
":noremap". Add "mapcmd({string}, {mode})? Use code from ":mkexrc".
9 When starting gvim in an xterm, Vim sends t_vi and t_ve to the terminal
(cursor invisible/visible). Should not happen.
9 incsearch is incorrect for "/that/<Return>/this/;//" (last search pattern
isn't updated).
9 term_console is used before it is set (msdos, Amiga).
9 Get out-of-memory for ":g/^/,$s//@/" on 1000 lines, this is not handled
correctly. Get many error messages while redrawing the screen, which
cause another redraw, etc.
9 When first editing file "test", which is symlink to "test2", and then
editing "test2", you end up editing buffer "test" again. Change the name
of the buffer to the actual file, instead of using the name of the
symlink?
8 [<C-I> doesn't work when '*' is in 'iskeyword'. find_pattern_in_path()
must escape special characters in the pattern.
8 Vim can overwrite a read-only file with ":w!". ":w" can't overwrite an
existing file, "w!" can, but perhaps not a read-only file? Then use
":w!!" for that.
Or ask for permission to overwrite it (if file can be made writable) and
restore file to readonly afterwards.
8 Buffers menu, when torn-off, disappears when being refreshed.
8 Is calling msg_start() in main() really needed? Any printed message
should include it already.
8 When in Insert mode with 'scrolloff' set, inserting text at the end of the
file, "!" lines will stay there while they could be used. (Park)
7 When compiled with "xterm_clipboard", startup can be slower and might get
error message for invalid $DISPLAY. Try connecting to the X server in the
background (forked), so that Vim starts up quicker?
8 For xterm need to open a connection to the X server to get the window
title, which can be slow. Can also get the title with "<Esc>[21t", no
need to use X11 calls. This returns "<Esc>]l{title}<Esc>\".
8 Add term entries for function keys on xterm with alt and ctrl (new in pl
94). E.g., Control adds ";5" in "<Esc>[20;5~". Find a generic way to
prepend a modifier in console mode, to avoid having to specify each
individual modified key.
8 When the builtin xterm termcap contains codes that are not wanted, need a
way to avoid using the builtin termcap.
8 '[ and '] should be set to start/end of line when using a linewise operator
(e.g., ":w").
8 CTRL-A can't handle big "long" numbers, they become negative. Check for
"-" character, if not present, use unsigned long.
8 Make it possible to disable the special meaning of "#" in the first column
for ">>".
8 Add suspending with CTRL-Z at the "more" prompt, and when executing a long
script in do_cmdline().
8 When using 'hidden', many swap files will be open. When Vim runs into the
maximum number of open files, error messages will appear. Detect that
this problem is present, and close any hidden files that don't have
changes.
8 With 'viminfo' set such that the ".viminfo" file is written on a FAT
filesystem, an illegal file name may be created: ".vim".
8 For each buffer that is opened, the viminfo file is opened and read to
check for file marks. This can be slow.
7 "dd" on the last line of the file, causes the last but one line to be
redrawn. Should not be necessary.
7 Using "gqj" near the last line of the window, makes the window scroll up,
even though this isn't necessary.
8 Should be able to compile Vim in another directory, with $(srcdir) set to
where the sources are. Add $(srcdir) in the Makefile in a lot of places.
(Netherton)
8 Perl adds arguments to the compiler. Check that compiling a program still
works after that, otherwise following configure checks will fail.
7 In xterm, recognize both vt100 and vt220 cursor keys. Change
add_termcode() to not remove an existing entry for a name, when it's
needed.
Recognize <C-Left> and <C-Right> in new xterm.
Need a generic solution to recognize different codes for the same key.
8 Core dump within signal function: gdb doesn't show stack backtrace! Option
to skip catch_signals()?
8 Pasting with the mouse in Replace mode inserts the text, instead of
overwriting, when it is more than one line. Same for using <C-R>.
7 When using search history, the trailing '/' or '?' needs to be changed
depending on the search command. When there was no '/' or '?', add one, so
flags can be added easily?
7 CTRL-F at the end of the file, when 'so' is set, redraws twice. When the
window is small (< 2 * 'so') it behaves differently.
9 CTRL-E and CTRL-Y don't work in small window when 'so' is 4 and lines are
wrapping (Acevedo/in.226). E.g., when using CTRL-E, window height 7,
window might actually scroll down when last line of buffer is displayed.
--> Remember if the previous command was "cursor follows screen" or
"screen follow cursor" and use this in cursupdate().
9 Text is scrolled up and down: (acevedo)
- set scrolloff to something >1 (i always use "set so=4")
- set the win. hegiht to scrolloff + 1 (i'd do ^W5_)
- load a file with scrolloff + 2 lines
- put the cursor in line scrolloff +1 (5G)
- if you move the cursor along the line (h, l, insert text, etc)
the text is crolled with each keystroke (once up, once down,...)
sometimes with <Esc> the text is scrolled up and down without stop!!!!
7 tilde_replace() can only handle "~/", should also do "~user/".
Get the list of home directories (from /etc/passwd? Use getpwent()) and
use some clever algorithm to match a path with that. Find common strings
in the list?
8 Add 'o' flag to 'mouse'?
8 When dragging status line with mouse, sometimes a jump when first clicking
on the status line (caused by 'winheight'). Select window on button up,
instead of on button down.
7 There are often a few <CR> on a row sent to the screen, should not be
necessary.
8 When performing incremental search, should abort searching as soon as a
character is typed.
8 Make CTRL-C on Unix generate a signal, avoid using select() to check for a
CTRL-C (it's slow). Allow using CTRL-C for "*y, like in MS-Windows.
8 When writing viminfo file, handle CTRL-J in filename (needs to be escaped
with CTRL-V). (Acevedo)
8 When starting Vim, switch terminal to RAW mode asap, so typeahead is
handled correctly (without the need for a <CR>).
8 When the value of $MAKE contains a path, configure can't handle this.
It's an autoconf bug. Remove the path from $MAKE to work around it.
8 How to set VIMRC_FILE to \"something\" for configure? Why does this not
work: CFLAGS='-DVIMRC_FILE=\"/mydir/myfile\"' ./configure
8 The temporary file is sometimes not writable. Check for this, and use an
alternate name when it isn't. Or add the 'temptemplate' option: template
for the temp file name ":set temptemplate=/usr/tmp/?????.tmp".
Also: Win32 version uses Windows temp directory, which might not work for
cygwin bash.
7 Get error "*, \+ or \( operand could be empty" for pattern "\(.\)\1\{3}".
Don't check when compiling, check while matching?
7 When switching to Daylight Saving Time, Vim complains that a file has been
changed since last read. Can we use a function that uses GMT?
7 When completing an environment variable after a '$', check for file names
that contain a '$' after all have been found.
[These have been reported for version 3.0, they may not appear in this version]
- MSDOS: After writing on a network the 'w' bit for others is set.
Documentation:
9 Merge in ideas from ~/vim/patches/tutor.txt (Gabriel Zachmann)
9 Update the overview of options in quickref.txt.
9 Errors in doc to HTML conversion:
autocmd.txt "like \| in a |pattern|"
9 Add 'fold' section to quick reference.
9 Add new options to quick reference.
9 Change all tags for commands from i_<C-R>_<C-O> to i_CTRL-R_CTRL-O to
avoid giving the user the impression that all commands have a tag in the
<C-x> form.
9 Extend the User Manual. Use portions of the Reference Manual.
9 Make the Reference Manual more precise. For each command mention:
- change to cursor position and curswant
- if it can be undone (u/CTRL-R) and redone (.)
- how it works for folded lines
- how it works with multi-byte characters
9 In change.txt, remark about Javadoc isn't right. Right alignment would
work too.
8 Spread the windows commands over the other files. For example, ":stag"
should be with ":tag". cross-link with tags to avoid too much double
text.
8 make vimtutor.bat for DOS and vimtutor script for Amiga. Then add
vimtutor.man to the runtime archive.
8 Add an example vimrc for using Vim as a modeless editor. Emulate an
existing editor (WordStar, Emacs, Brief?).
7 Windows: When a wrong command is typed with an ALT key, give a hint to
look at the help for 'winaltkeys'.
- Check text editor compendium for vi and Vim remarks.
- Add some text for xxd.
Help:
- First try using the ":help" argument literally, before using it as a
pattern. And then match it as part of a tag.
- When a help item has multiple matches make it possible to use ":tn" to go
to the other matches.
- Use GNU Texinfo for the help files somehow? Use Info format files?
At least the other way around: Use Vim to view (and edit) .info files.
- Default mapping for help files: <Tab> to position cursor on next |:tag|.
- When hitting <Esc> or CTRL-C in Normal mode, give a message to help novice
users to get out: "Type :q! to quit Vim".
- Implement a "sticky" help window, some help text lines that are always
displayed in a window with fixed height. (Guckes) Use "~/.vimhelp" file,
user can edit it to insert his favorite commands, new account can contain a
default contents.
- When entering the help window, don't resize to 'helpheight' if the user has
reduced the size before (Webb). Keep the window height that the user set
the window to in a "preferred window height" entry for each window.
- ":help :s^I" should expand to ":help :substitute".
- Make the help key (<F1>) context sensitive?
- Learn mode: show short help while typing commands.
"make test":
- Find a way to skip tests that can't be done. For non-Unix systems, but
also for e.g. the Perl interface.
Folding:
(commands still available: zg zG zI zJ zK zp zP zq zQ zV zw zW zy zY;
secondary: zB zS zT zZ)
- When pressing the down arrow of a scrollbar, a closed fold doesn't scroll
until after a long time. How to make scrolling with closed folds
smoother?
- When a buffer becomes hidden, keep the manual folds for it?
- 'foldmethod' "textobject": fold on sections and paragraph text objects.
- Add 'hidecomment' option: don't display comments in /* */ and after //.
- "zu": undo change in manual fold. "zU" redo change in manual fold. How to
implement this?
- "zJ" command: add the line or fold below the fold in the fold under the
cursor.
- 'foldmethod' "syntax": "fold=3": set fold level for a region.
- Can set 'foldtext' to empty string: don't display any line. How to
implement this?
Multi-byte characters:
- GTK and Win32: Allow selecting fonts for 'guifontset' with the
fontselector somehow.
- GTK and Win32: make it possible to set the font for the menu to make it
possible to have 'encoding' different from the current locale.
- dbcs_class() only works for Japanese and Korean. Implement this for
other encodings. The "euc-jp" and "euc-kr" choices might be wrong.
- Find some way to automatically select the right GUI font or fontset,
depending on the default value of 'encoding'.
For Windows, the charset_pairs[] table could be used. But how do we know
if a font exists?
- Do keyboard conversion from 'termencoding' to 'encoding' with
convert_input() for Mac GUI, RiscOS GUI, BeOS GUI, VMS.
- Add mnemonics from RFC1345 longer than two characters.
Support CTRL-K _{mnemonic}_
- Do we need the reverse of 'keymap', like 'langmap' but with files and
multi-byte characters?
- When breaking a line, take properties of multi-byte characters into
account. The "linebreak" program from Bruno Haible can do it:
ftp://ftp.ilog.fr/pub/Users/haible/gnu/linebreak-0.1.tar.gz
But it's very complicated...
Syntax highlighting:
8 Allow the user to add items to the Syntax menu sorted, without having to
change this for each release.
8 Add a "matchcontains" for regions: items containd in the start or end
pattern, but not in the body.
8 Add a "keepend-contained" argument: Don't change the end of an item this
one is contained in. Like "keepend" but specified on the contained item,
instead of the containing item.
8 For keywords, allow to define the size of the hash table with ":syn
clear". Change KHASH_ defines into variables stored in buffer struct.
Use something else than linear linked list from the hash table. (Campbell)
8 cpp.vim: In C++ it's allowed to use {} inside ().
8 Some syntax files set 'iskeyword'. When switching to another filetype
this isn't reset. Add a special keyword definition for the syntax rules?
8 Add specific syntax item to match with parens/braces that don't have a
"%" match. :syntax nomatch cMatchError (,{,[,),},] [contained]
8 Highlight the text between two matching parens (e.g., with a grey
background) when on one of the parens or in between them.
8 Add a command to jump to the next character highlighted with "Error".
8 When using a cterm, and no ctermfg or ctermbg are defined, use start/stop
sequences. Add remark in docs that :if 'term' == "term-name" should be
used.
8 Add @spell cluster to String and Comment groups for many languages. Will
allow spell checking. (Fleiner)
8 When listing syntax items, try to sort the keywords alphabetically. And
re-insert the [] if possible.
8 Make it possible to use color of text for Visual highlight group (like for
the Cursor).
8 "fg" and "bg" don't work in an xterm. Get default colors from xterm with
an ESC sequence. Ideas in: ~/vim/patches/vikas.xtermcolors .
8 Make it possible to only highlight a sub-expression of a match. Like
using "\1" in a ":s" command.
8 Support for deleting syntax items:
:syn keyword cTodo remove this
:syn match cTodo remove "pattern"
:syn region cString remove start="this" end="that"
8 Add possibility to sync on something else, when the syncing in one way
doesn't find match. For HTML: When no {script} is found, try looking for
a '<'. (Fleiner)
7 Replace the synchronizing method with a state machine specification?
Should be able to start at any line in the file, search forwards or
backwards, and use the result of matching a pattern.
7 Use parsing like awk, so that e.g., a ( without a matching ) can be
detected.
8 Make it possible to use "inverted" highlighting, invert the original
character. For Visual mode. (xterm-selection already does this).
8 Highlight non-printable characters with "SpecialChar", linked to
"Special". Display them with the digraph characters, if possible.
8 Highlight the clipboard-selection with a highlight group.
8 Be able to reset highlighting to its original (default) values.
7 Be able to write current highlighting to a file as commands, similar to
":mkvimrc".
8 Improve c.vim:
- Add check for unterminated strings, with a variable to switch it on:
"c_strict_ansi".
- Detect unbalanced "#endif". Requires looking back a long way...
8 Add an option to restrict the updating of syntax highlighting to the
current line while in Insert mode.
8 When guessing value of 'background', the syntax file has already been
loaded (from the .gvimrc). After changing 'background', load it again?
8 Add ":syn resync" command, to re-parse the whole file until the current
display position.
8 Should support "me" offset for a region start pattern. To be used to
allow searching for the end pattern inside the match of the end pattern.
Example: syn region pikeXX start="([^{]" end=")" should work on "()".
8 When using a regexp for "contains=", should delay matching with it until
redrawing happens. Set a flag when a group is added, check this flag when
highlighting starts.
7 Add "semitrans": Add highlighting. E.g., make the text bold, but keep the
colors. And add colors, so that Green+Red becomes Yellow.
E.g. for this html:
<B> bold text <I> italic+bold text </B> italic text </I>
7 Wild idea: Not only set highlighting, but also change what is displayed
(e.g., remove characters, so that "<B>bold</B>" can be shown as "bold"):
:syn region boldstuff start="<B>" display="" end="</B>" display=""
7 CTRL-] checks the highlight group for finding out what the tag is.
7 Add an explanation how a list of words can be used to highlight misspelled
words.
8 Add spell checking. Use "ispell -a" somehow.
~/vim/patches/wm_vim-5_4d.zip can be used as an example (includes ispell
inside Vim).
7 Command line completion for ":find" should search in 'path'.
8 Add more command line completion for :syntax.
8 Add more command line completion for :highlight.
7 Should find a better way to parse the :syntax and :highlight commands.
Use tables or lists that can be shared by parsing for execution and
completion?
7 Add a few sets of colors (e.g. Borland Turbo C one). With a menu to
select one of the sets.
8 Add offsets to sub-matches: "\(a*\) *"he=e1-1
'e' is end of match 'e1' is end of sub-match 1, 's2' is start of submatch
2, etc.
8 In Insert mode, when there are typeahead characters, postpone the
highlighting (for "." command).
8 Syncing on comments isn't 100% correct when / / lines mix with / * and * /.
For example: What about a line that starts with / / and contains * /?
8 Ignore / * and * / inside strings, when syncing.
7 Build a few more syntax files from the file "/usr/share/misc/vgrindefs":
ISP, LDL, Icon, ratfor. And check "nedit/source/highlight.c".
6 Add possibility to have background color continue until the right edge of
the window. Useful for comment blocks and function headings. (Rogall)
- Make it possible to add "contains" items for all items in a group. Useful
when extending an already existing syntax file.
- Add line-continuation pattern for non-syncing items too?
- Add possibility to highlight specific columns (for Fortran). Or put a
line in between columns (e.g. for 'textwidth').
- Add possibility to highlight the whole line, including the right margin
(for comment blocks).
- Add 'hlmatch' option: List of flags:
'c': highlight match for character under the cursor.
'b': highlight the previous (, and its match.
'a': highlight all text from the previous ( until its match.
Also for {}, <>, etc.?
'e': highlight all braces without a match (slow?)
OR: add an argument "cursor" to the syntax command, which means that the
region/match/keyword is only highlighted when the cursor is on it.
(Campbell)
Or do it like Elvis: define text objects and how to highlight them around
the cursor. (Iain Truskett)
7 Make it possible to use all words in the tags files as Keyword.
Can also be done with a script (but it's slow).
7 Make it possible to call a ":" command when a match is found. Should
allow for adding keywords from the text (e.g. variables that are set).
And allows for sections with different highlighting.
7 Add highlight group for commandline: "Commandline". Make sure it
highlights the command line while typing a command, and any output from
messages. And external commands?
8 Make a version that works like less, but with highlighting: read stdin for
text, exit at end of file, don't allow editing, etc. moreim? lessim?
Code cleanup:
Performance:
8 Avoid alloc() for scratch buffer use, esp. in syntax.c. It's very slow on
Win16.
9 Setting GUI options in the console (e.g., 'guifont') should not cause a
redraw.
8 Profiling shows that in_id_list() is used very often for C code. Can this
function be improved?
8 For an existing file, the page size of the swap file is always the
default, instead of using the block size of the device, because the swap
file is created only after setting the block size in mf_open(). How can
this be improved?
8 Set default for 'ttyscroll' to half a screen height? Should speed up
MS-DOS version. (Negri)
7 Check how performance of loading the wordlist can be imrpoved (adding a
lot of abbreviations).
7 DOS console: Add t_DL support, to make scrolling faster.
7 Compile Ex commands to byte codes. Store byte codes in a vim script file
at the end, after "compiled:. Make it look like a single comment line
for old Vim versions. Insert first line "Vim script compiled <timestamp>.
Only used compiled code when timestamp matches the file stat.
Add command to compile a vim script and add it to the file in-place.
Split Ex command executing into a parsing and executing phase.
Use compiled code for functions, while loops, etc.
8 When editing a file with extremely long lines (e.g., an executable), the
"linerest" in readfile() is allocated twice to be able to copy what was
read so far. Use realloc() instead? Or split the line when allocating
memory fails and "linerest" is big (> 100000)?
8 When defining autocommands (e.g., from $VIMRUNTIME/filetype.vim), need to
compare each pattern with all existing patterns. Use a hash code to avoid
using strcmp() too often?
7 Include turbo_loader patches, speeding up reading a file?
Speed up reading a file by reading it into a fixed-size buffer, creating
the list of indexes in another buffer, and then copying the result into a
memfile block with two copies. Then read the next block into another
fixed-size buffer, create the second list of indexes and copy text from
the two blocks to the memfile block.
7 do_cmdline(): Avoid that the command line is copied to allocated memory
and freed again later all the time. For while loops, and for when called
with an argument that can be messed with.
Generic solution: Make a struct that contains a pointer and a flag that
indicates if the pointer should be freed when replaced.
7 Check that that the file size is not more than "sizeof(long)".
- Further improve finding mappings in maphash[] in vgetorpeek()
8 Dragging the status line doesn't scroll but redraw.
8 Syntax highlighting is slow when deleting lines. Try in
$VIMRUNTIME/filetype.vim.
- "out of memory" after deleting (1,$d) and changing (:%s/^/> /) a lot of
lines (27000) a few times. Memory fragmentation?
- Have a look at how pdksh does memory allocation (alloc.c). (Dalecki)
- Do profiling on:
- :g/pat/normal cmd
- 1000ii<Esc>
- deleting 10Mbyte worth of lines (netscape binary)
- ":g/^/m0" on a 450Kbyte file. And the "u".
- highlighting "~/vim/test/longline.tex", "~/vim/test/scwoop.tcl" and
"~/vim/test/lockup.pl".
- loading a syntax file to highlight all words not from a dictionary.
- editing a vim script with syntax highlighting on (loading vim.vim).
7 Screen updating can be further improved by only redrawing lines that were
changed (and lines after them, when syntax highlighting was used, and it
changed).
- On each change, remember start and end of the change.
- When inserting/deleting lines, remember begin, end, and line count.
- Use macros/duarte/capicua for profiling. Nvi 1.71 is the fastest!
- When using a file with one long line (1Mbyte), then do "$hhhh", is still
very slow. Avoid calling getvcol() for each "h"?
- Executing a register, e.g. "10000@@" is slow, because ins_typebuf has to
move the previous commands forward each time. Pass count from
normal_cmd() down to do_execreg().
- Repeating insert "1000i-<Esc>" displays --INSERT-- all the time, because of
the <Esc> at the end. Make this work faster (disable redrawing).
- Avoid calls to plines() for cursor line, use w_cline_height.
- When only need to redraw the status lines in status_redraw_all(), need to
update NOT_VALID to force the redraw. Should detect that only the status
lines need to be redrawn (add STATUSLN between VALID and NOT_VALID?).
- After :set nowrap remove superflous redraw with wrong hor. offset if cursor
is right of the screen.
Code size:
8 Can't optimize normal.c, because of the big switch. Make it into a table
of functions?
8 GUI: When NO_CONSOLE is defined, more code can be excluded.
- Put getline() and cookie in a struct, so only one argument has to be
passed to do_cmdline() and other functions.
8 move common files between os_unix.c and os_vms.c to one file?
8 Make a GUI-only version for Unix?
Messages:
8 For 'verbose' level 12 prints commands from source'ed files. How to skip
lines that aren't executed? Perhaps move the echoing to do_cmdline()?
8 Use 'report' for ":bdel"? (Krishna) To avoid these messages when using a
script.
8 "vim --version" output goes to stderr, should be stdout. Can all output
from messages using printf() go to stdout?
- Delete message after new command has been entered and have waited for key.
Perhaps after ten seconds?
- Make message history available in "msg" variables: msg1, msg2, .. msg9.
9 Check handling of overwriting of messages and delays:
Very wrong: errors while redrawing cause endless loop.
When switching to another file and screen scrolls because of the long
message and return must be typed, don't scroll the screen back before
redrawing.
7 Add an option, which is a regexp, that disables warning messages which
match that regexp (Tsirkin).
8 When address range is wrong you only get "Invalid range". Be a bit more
specific: Negative, beyond last line, reverse range? Include the text.
8 Make it possible to ignore errors for a moment ('errorignore'?). Another
option to switch off giving error messages ('errorquiet'?). Also an option
not to give any messages ('quiet')? Or ":quiet on", ":quiet off".
Careful: For a severe error (out of memory), and when the user starts
typing, error messages must be switched back on.
Also a flag to ignore error messages for shell commands (for mappings).
- Option to set time for emsg() sleep. Interrupt sleep when key is typed?
sleep before second message?
8 In Ex silent mode or when reading commands from a file, what exactly is
not printed and what is? Check ":print", ":set all", ":args", ":vers",
etc. At least there should be no prompt. (Smulders) And don't clear the
screen when reading commands from stdin. (Kendall)
--> Make a difference between informative messages, prompts, etc. and
error messages, printing text, etc.
8 Window should be redrawn when resizing at the hit-enter prompt.
Also at the ":tselect" prompt. Find a generic solution for redrawing when
a prompt is present (with a callback function?).
Screen updating:
7 Add a string to the 'display' option to make CTRL-E and CTRL-Y scroll one
screen line, also if this means the first line doesn't start with the
first character (like what happens with a single line that doesn't fit).
- screen_line():
- insert/delete character stuff.
- improve delete rest of line (spaces at end of line).
- When moving or resizing window, try to avoid a complete redraw (esp. when
dragging the status line with the mouse).
- When 'lazyredraw' set, don't echo :ex commands? Need a flag to redraw when
waiting for a character.
8 Add a ":refresh [winnr]" command, to force updating a window. Useful from
an event handler where ":normal" can't be used. Also useful when
'lazyredraw' is set in a mapping.
Scrolling:
8 Add "zm" command: scroll horizontally to put the cursor in the middle.
6 Add option to set the overlap for CTRL-F and CTRL-B. (Garhi)
- extend 'scrollbind' option: 'scrollopt' words "search", "relative", etc..
Also 'e'xecute some commands (search, vertical movements) in all bound
windows.
- Allow scrolling by dragging with the mouse. Like the "hand" in Acrobat
reader. With which mouse button?
- Add command to execute some commands (search, vertical movements) in all
bound windows.
- Add 'search' option to 'scrollopt' to allow 'scrollbind' windows to
be bound by regexp searches
- Add "z>" and "z<": scroll sideways one screenfull. (Campbell)
- Add option to set the number of lines when not to scroll, instead of the
fixed number used now (for terminals that scroll slow with a large number
of lines but not with a single line).
Autoconf:
8 Should use acconfig.h to define prototypes that are used by autoheader.
8 Some compilers don't give an error for "-OPT:Olimit" but a warning. (Webb)
Add a check for the warning, so that "Olimit" can be added automatically?
- Autoconf: Use @datadir@ for the system independent files. Make sure the
system dependend and system independed files are separated. (Leitner).
- Add autoconf check for waitpid()/wait4().
- Remove fcntl() from autoconf, all systems have it?
- Set default for 'dictionary', add search for dictionary to autoconf.
Perl interface:
8 Rename typemap file to something else?
7 Make buffers accessed as Perl arrays. (Clark)
7 Make it possible to compile with non-ANSI C?
6 Tcl/Tk has the "load" command: load a shared library (.so or .dll).
Shared libraries:
6 Add support for loading shared libraries, and calling functions in it.
:libload internal-name libname
:libunload internal-name
:liblist
:libcall internal-name function(arg1, arg2, ...)
:libcall function(arg1, arg2, ...)
libcall() can have only one integer or String argument at the moment.
6 Have a look on how Perl handles loading dynamic libraries.
Tags:
7 Count before CTRL-]: jump to N'th match
8 Scope arguments for ":tag", e.g.: ":tag class:cPage open", like Elvis.
8 When output of ":tselect" is long, getting the more-prompt, should be able
to type the tag number directly.
7 Add 'tagignorecase' option from Vile: ignore case for tags.
7 Make output of ":tselect" a bit nicer. Use highlighting?
7 Highlight the "tag 1 of >2" message. New highlight group, or same as "hit
bottom" search message.
7 When using ":tag" at the top of the tag stack, should add another entry,
so CTRL-T can bring you back to where you are now AND to where you were
before the previous ":tag" command. (Webb)
7 When using CTRL-] on someClass::someMethod, separate class from method and
use ":ta class:someClass someMethod".
Include C++ tags changes (Bertin). Change "class::func" tag into "func"
with "class=class"? Docs in oldmail/bertin/in.xxx.
7 Add ":tagargs", to set values for fields:
:tagargs class:someclass file:version.c
:tagargs clear
These are then the default values (changes the order of priority in tag
matching).
7 Support for "gtags" and "global"? With ":rtag" command?
There is an example for how to do this in Nvi.
Or do it like Elvis: 'tagprg' and 'tagprgonce' options. (Yamaguchi)
The Elvis method is far more flexible, do it that way.
7 Support "col:99" extra field, to position the cursor in that column. With
a flag in 'cpoptions' to switch it off again.
7 Better support for jumping to where a function or variable is used. Use
the id-utils, with a connection to "gid" (Emacs can do it too). Add
":idselect", which uses an "ID" database (made by "mkid") like "tselect".
6 Don't store the search pattern from a tag command in the search history
(with an option)?
Security:
- nothing at the moment
Win32 GUI:
8 Make debug mode work while starting up (vim -D). Open console window for
the message and input?
8 Add font argument to set the lfCharSet. (Bobcik)
8 Could keep console open to run multiple commands, to avoid the need to hit
return in every console.
Also: Look at how Emacs does runs external commands:
http://www.cs.washington.edu/homes/voelker/ntemacs.html.
8 When dropping a file onto gvim while at the ":" prompt, insert the file
name. Allows using the name with different commands. (Krishna)
7 Add a way to change the filter menu in the file selection dialog.
8 Need a separate PopUp menu for modeless selection. Need two new commands:
Copy selection to clipboard, Paste selection (as typed text).
8 Dropping a file on a gvim that edits a modified buffer splits the window.
Make an option to replace the current file (use ":e" instead of ":sp")?
When dropping multiple files, display the first one and adjust the
arglist. Or make it an option for the user to chose betwen ":e" and ":sp"?
8 Support copy/paste for other file formats. At least HTML, perhaps RTF.
Add "copy special" and "paste special" commands?
7 Use <C-Tab> to cycle through open windows (e.g., the find dialog).
7 <Esc> should close a dialog.
7 Keep the console for external commands open. Don't wait for a key to be
hit. Re-open it when the user has closed it anyway. Or use a prepended
command: ":nowait {cmd}", or ":quiet", which executes {cmd} without any
prompts.
7 Should be able to set an option so that when you double click a file that
is associated with Vim, you can either get a new instance of Vim, or have
the file added into an already running Vim.
GUI:
9 Make <S-Insert> paste from the clipboard by default. (Kunze)
7 Menu local to a buffer, like mappings. Or local to a filetype?
8 Dragging the mouse pointer outside of a Vim Window should make the text
scroll. Return a value from gui_send_mouse_event() to the machine
specific code to indicate the time in which the event should be repeated.
8 Make it possible to ignore a mouse click when it's used to give Vim (gvim)
window focus. Also when a mouse click is used to bring a window to front.
8 Make the split into system independend code and system specific code more
explicit. There are too many #ifdefs in gui.c.
If possible, separate the Vim code completely from the GUI code, to allow
running them in separate processes.
8 Support a background bitmap. Useful for marking a column. Patch from
Heather Downs (GTK) and Vince Negri (Win32).
7 X11: Support cursorColor resource and "-cr" argument.
8 X11 (and others): CTRL-; is not different from ';'. Set the modifier mask
to include CTRL for keys where CTRL produces the same ASCII code.
8 Visual highlighting should keep the same font (bold, italic, etc.).
8 Make the "Save As.." menu item work like other GUI programs: ":w file",
":e file".
8 Add 'c' flag in 'guioptios' to use console dialogs instead of GUI dialogs.
Esp. for the ATTENTION prompt.
8 Add flag to 'guioptions' to not put anything in the clipboard at all?
8 Should take font from xterm where gvim was started (if no other default).
8 Selecting font names in X11 is difficult, make a script or something to
select one.
8 Should support a way to use keys that we don't recognize yet. Add a
command that adds entries to special_keys somehow. How do we make this
portable (X11, Win32, ..)?
7 Add a flag to 'guioptions' that tells not to remove inactive menu items.
For systems where greying-out or removing menu items is very slow. The
menu items would remain visibly normally, but not do anything.
7 Add ":minimize" and ":maximize", which iconize the window and back.
Useful when using gvim to run a script (e.g. 2html.vim).
7 X11: Is it possible to free allocated colors, so that other programs can
use them again? Otherwise, allow disabling allocating the default colors.
Or allocate an own colormap (check UAE). With an option to use it. For
the commandline, "-install" is mostly used for X11 programs.
7 Add command line argument for "gvim" not to start the GUI. Sort of the
inverse of "vim -g". (Vikas)
6 Local buffer menus. (Zachmann)
7 Should support multi-column menus.
- Should add option for where to put the "Help" menu: like Motif at the far
right, or with the other menus (but still at the right).
- Add menu item to "Keep Insert mode".
8 ":mkgvimrc" command, that includes menus.
6 Big change: Move GUI to separate program "vimgui", to make startup of vim a
lot faster, but still be able to do "vim -g" or ":gui".
6 Make it possible to "drag the text" (grab a character and move it
up/down). Use Alt-LeftMouse for this? (Goldfarb)
7 More explicit mouse button binding instead of 'mousemodel'?
7 Add option to set the position of the window on the screen. 'windowpos',
which has a value of "123,456": <x>,<y>.
Or add a command, like ":winsize"?
7 Add toolbar for non-Win32 GUIs.
7 Make it possible to put the toolbar on top, left, right and/or bottom of
the window? Allows for softkey-like use.
6 Separate the part of Vim that does the editing from the part that runs the
GUI. Communicate through a pseudo-tty. Vim starts up, creates a
pty that is connected to the terminal. When the GUI starts, the pty is
reconnected to the GUI process. When the GUI stops, it is connected to
the terminal again. Also use the pty for external processes, it looks
like a vt100 terminal to them. Vim uses extra commands to communicate GUI
things.
- Motif steals <F10> from us, to pop up menus with the keyboard. How do we
get it back if we want it?
- Paste in Insert mode should not do autowrap etc. Or maybe this should be
changeable with an option?
- Put a nice picture in the icon (but how do we do that?).
7 When using a pseudo-tty Vim should behave like some terminal (vt52 looks
simple enough). Terminal codes to/from shell should be translated.
- Would it be useful to be able to quit the GUI and go back to the terminal
where it was started from?
Autocommands:
9 Make sure that side effects of autocommands are handled correctly. Don't
execute autocommands when a buffer or window is halfway some changes.
Move all apply_autocmds() calls to a higher level where needed.
8 Use another option than 'updatetime' for the CursorHold event. The two
things are unrelated for the user (but the implementation is more
difficult).
8 Can't use ":normal" in CursorHold autocommands. Make the CursorHold event
insert a special key code, and call the autocommand functions from a
higher level, so that vgetc() isn't used recursively.
8 Autocommands should not change registers. And marks? And the jumplist?
And anything else?
8 Autocommand for when modified files have been found, when getting input
focus again (e.g., FileChangedFocus).
Check when: getting focus, jumping to another buffer, ...
8 Add autocommands, user functions and user commands to ":mkvimrc".
8 Add "TagJumpFile" autocommand: When jumping to another file for a tag.
Can be used to open "main.c.gz" when "main.c" isn't found.
7 Add a way to skip an autocommand if going from one *.c file to another *.c
file.
7 When trying to open a directory, don't load the file but trigger an
autocommand event OpenDirectory.
7 Add file type in front of file pattern: <d> for directory, <l> for link,
<x> for executable, etc. <&xxx> for Risc OS. With commas to separate
alternatives. The autocommand is only executed when both the file type
AND the file pattern match. (Leonard)
5 Add option that specifies extensions which are to be discarded from the
file name. E.g. 'ausuffix', with ".gz,.orig". Such that file.c.gz will
trigger the "*.c" autocommands. (Belabas)
7 Add something to break the autocommands for the current event, and for
what follows. Useful for a "BufWritePre" that wants to avoid writing the
file.
8 Detect textmode after executing the autocommands, otherwise the .gz
autocommands don't work for MS-DOS. Needs to be able to remove the ^Ms at
the end of each line. Alternative: don't use a filter command, write the
file, gunzip, set nobin, delete the lines, read the file.
8 Add buffer-local autocommands? Reduces overhead for autocommands that
trigger often (inserting a character, switching mode).
:au Event <buffer> do-something
- Add events to autocommands:
Error - When an error happens
NormalEnter - Entering Normal mode
InsertEnter - Entering Insert mode
ReplaceEnter - Entering Replace mode
CmdEnter - Entering Cmdline mode
VisualEnter - Entering Visual mode
*Leave - Leaving the mode
SearchPost - After doing a search command (e.g. to do "M")
PreDirChanged/PostDirChanged
- Before/after ":cd" has been used (for changing the
window title)
BufReadAction - replaces reading a file
BufWriteAction - replaces writing a file
ShutDown - when the system is about to shut down
InsertCharPre - user typed character Insert mode, before inserting the
char. Set v:char to the character, can be changed. (not
when 'paste' is set).
InsertCharPost - user typed a character in Insert mode, after inserting
the char.
BufModified - When a buffer becomes modified, or unmodified (for
putting a [+] in the window title or checking out the
file from CVS).
BufFirstChange - When making a change, when 'modified' is set. Can be
used to do a :preserve for remote files.
BufChange - after a change was made. Set some variables to indicate
the position and number of inserted/deleted lines, so
that marks can be updated. HierAssist has patch to add
BufChangePre, BufChangePost and RevertBuf. (Shah)
- Add autocommand to be executed every so many seconds? For writing the
file now and then ('autosave').
*'autosave'* *'as'* *'noautosave'* *'noas'*
'autosave' 'aw' number (default 0)
Automatically write the current buffer to file N seconds after the
last change has been made and when |'modified'| is still set.
Default: 0 = do not autosave the buffer.
Command-line editing:
7 Add commands (keys) to delete from the cursor to the end of the command
line.
- Add flags to 'whichwrap' for command line editing (cursor right at end of
lines wraps to start of line).
Insert mode:
9 When 'autoindent' is set, hitting <CR> twice, while there is text after
the cursor, doesn't delete the autoindent in the resulting blank line.
(Rich Wales) This is Vi compatible, but it looks like a bug. Rich has a
suggestion for a patch to fix this.
8 When using CTRL-O in Insert mode, then executing an insert command
"a" or "i", should we return to Insert mode after <Esc>? (Eggink)
Perhaps it can be allowed a single time, to be able to do
"<C-O>10axyz<Esc>". Nesting this further is confusing.
":map <F2> 5aabc<Esc>" works only once from Insert mode.
7 Make ":startinsert" command work directly for functions and scripts?
Also make it possible to append (it's difficult at end of line).
- In Insert mode (and command line editing?): Allow undo of the last typed
character. This is useful for CTRL-U, CTRL-W, delete and backspace, and
also for characters that wrap to the next line.
Also: be able to undo CTRL-R (insert register).
Possibly use 'backspace'="whole" for a mode where at least a <CR> that
inserts autoindent is undone by a single <BS>.
- Use CTRL-G in Insert mode for an extra range of commands, like "g" in
Normal mode.
- Make 'paste' work without resetting other options, but override their
value. Avoids problems when changing files and modelines or autocommands
are used.
- When typing CTRL-V and a digit higher than 2, only expect two digits.
- Insert binary numbers with CTRL-V b.
- Make it possible to undo <BS>, <C-W> and <C-U>. Bash uses CTRL-Y.
'cindent', 'smartindent':
9 closing } not recognized? (Francois-Xavier Menard)
(char *tab[] = {"aaa",
NULL};
char *name;
9 When using 'cino' "f1s" the indent after a function is set to the indent
of the "}", should be zero.
9 Formatting comments should use 'comments' setting. E.g. when lining out
comments like this:
/*
** formatted with comments=sr:/*,mb:**,ex:*/
*/
9 Indent follows "if" instead of "do": (Robert Webb)
do
{
switch (blah)
{
case 1: if (thing)
blah;
}
} while (blah);
here;
9 One indent to much when doing "o" below this "while": (Rouben Rostamian)
{
do
if (1) {
asdf;
} else
qwer;
while (1);
9 brace not indented correctly:
case 'c': if (cond)
{
Should align with "if" in case statement.
7 Allow aligning a closing ")" with the line above, instead of the matching
"(": (Riehm) if (asdfasdf &&
asdf
)
9 "case xx: {", or in general: any { with text before it, a matching }
should not line up with the {, but with the indent at that position.
Add setting for K&R paren style? Should be used for this:
case xx: {
some_cmd;
}
8 "int asdf,<CR>asdf;" should indent the second line more. (Zellner)
8 In C++ it's possible to have {} inside (): (Kirshna)
func(
new String[] {
"asdf",
"asdf"
}
);
7 Separate "(0" option into inside/outside a function (Zellner):
func(
int x) // indent like "(4"
{
if (a
&& b) // indent like "(0"
9 Wrong indent for continuation line with a string:
void foo()
{
x = f("s \
asd\
tem");
ff;
}
Also note that the "tem" line has an extra indent. It appears that the
brace matching doesn't work, because of the single " in the line.
9 Wrong indent for cino=(4, removing the (void) fixes it: (Zellner)
(void) MyFancyFunction(
argument);
7 Make indenting more flexible, like syntax highlighting.
- Make smartindenting configurable. Add 'sioptions', e.g. '#' setting the
indent to 0 should be switched on/off.
7 Support ANSI style function header, with each argument on its own line.
- "[p" and "]p" should use 'cindent' code if it's on (only for the first
line).
- Add option to 'cindent' to set indent for comments outside of {}?
- Make a command to line up a comment after a code line with a previous
comment after a code line. Can 'cindent' do this automatically?
7 Add 'j' flag to 'formatoptions': Remove comment leader when joining lines.
- formatting of struct/array inits:
The lines used to initialize the struct or array above should not be
considered 'continuation' lines just because the previous one does not end
with ';'. If you go back line by line I think it should be possible to
tell the difference. If you find a line that ends in ';', then it's OK to
have continuation lines. If you find a "{", and the character before it
(not counting space & comments) is either ',' or '=', then there should
not be continuation lines. If the character before the "{" is another
"{", then you have to check before that one too.
- When 'cindent'ing a '}', showmatch is done before fixing the indent. It
looks better when the indent is fixed before the showmatch. (Webb)
- Add option to make indenting work in comments too (for commented-out
code), unless the line starts with "*".
- Don't use 'cindent' when doing formatting with "gq"?
- When formatting a comment after some text, insert the '*' for the new line
(indent is correct if 'cindent' is set, but '*' doesn't get inserted).
- For smartindent: When typing 'else' line it up with matching 'if'.
- 'smartindent': allow patterns in 'cinwords', for e.g. TeX files, where
lines start with "\item".
- Support this style of comments (with an option): (Brown)
/* here is a comment that
is just autoindented, and
nothing else */
- Add words to 'cinwords' to reduce the indent, e.g., "end" or "fi".
7 Use Tabs for the indent of starting lines, padd with spaces for
continuation lines. Allows changing 'tabstop' without messing up the
indents.
And/or: Add option to copy indent as-is, without changing spaces to tabs.
Java:
8 Can have {} constructs inside parens. Include changes from Steve
Odendahl?
8 Recognize "import java.util.Vector" and use $CLASSPATH to find files for
"[i" commands and friends.
'comments':
7 When using "comments=fg:--", Vim inserts three spaces for a new line.
When hitting a TAB, these spaces could be removed.
7 The 'n'esting flag doesn't do the indenting of the last (rightmost) item.
6 Make strings in 'comments' option a RE, to be able to match more
complicated things. (Phillipps) Use a special flag to indicate that a
regexp is used.
8 Make the 'comments' option with "/* * */" lines only repeat the "*" line
when there is a "/*" before it? Or include this in 'cindent'?
Text objects:
8 Add test script for text object commands "aw", "iW", etc.
8 Add "gp" and "gP" commands: insert text and make sure there is a single
space before it, unless at the start of the line, and after it, unless at
the end of the line or befor a ".".
7 Add "g{" and "g}" to move to the first/last character of a paragraph
(instead of the line just before/after a paragraph as with "{" and "}").
6 Ignore comment leaders for objects. Make "das" work in reply-email.
5 Make it possible to use syntax group matches as a text object. For
example, define a "ccItem" group, then do "da<ccItem>" to delete one.
Or, maybe just define "dai", delete-an-item, to delete the syntax item the
cursor is on.
Select mode:
7 Alt-leftmouse starts block mode selection in MS Word.
7 Add Cmdline-select mode. Like Select mode, but used on the command line.
- Change gui_send_mouse_event() to pass on mouse events when 'mouse'
contains 'C' or 'A'.
- Catch mouse events in ex_getln.c. Also shift-cursor, etc., like in
normal_cmd().
- remember start and end of selection in cmdline_info.
- Typing text replaces the selection.
Visual mode:
- When dragging the Visual selection with the mouse and 'scrolloff' is zero,
behave like 'scrolloff' is one, so that the text scrolls when the pointer
is in the top line.
8 In Visual block mode, "A" appends to lines that don't extend into the
block, but padding is wrong (always two spaces). Fix the padding.
9 With blockwise Visual mode, "A" works different than "I" when there are
short lines. Make them work the same way. Also make it possible to add
the text to short lines too, with padding where needed.
8 What is "R" supposed to do in Visual mode?
8 Make Visual mode local to the buffer. Allow changing to another buffer.
When starting a new Visual selection, remove the Visual selection in any
other buffer. (Ron Aaron)
7 Support dragging the Visual area to drop it somewhere else. (Aaron)
7 With blockwise Visual mode and "c", "C", "I", "A", etc., allow the use of
a <CR>. The entered lines are repeated over the Visual area.
7 CTRL-V :s should substitute only in the block, not to whole lines. (David
Young is working on this)
7 Filtering a block should only apply to the block, not to the whole lines.
When the number of lines is increased, add lines. When decreased, padd with
spaces or delete? Use ":`<,`>" on the command line.
8 After filtering the Visual area, make "gv" select the filtered text?
Currently "gv" only selects a single line, not useful.
7 Don't move the cursor when scrolling? Needed when the selection should
stay the same. Scroll to the cursor at any movement command. With an
option!
7 In Visual block mode, need to be able to define a corner on a position
that doesn't have text? Also: when using the mouse, be able to select
part of a TAB. Even more: Add a mode where the cursor can be on a screen
position where there is no text. When typing, add spaces to fill the gap.
Other solution: Always use curswant, so that you can move the cursor to
the right column, and then use up/down movements to select the line,
without changing the column.
6 ":left" and ":right" should work in Visual block mode.
7 For Visual mode: Command to do a search for the string in the marked area.
Only when less than two lines. Use "g/" and "g?".
7 CTRL-I and CTRL-O should work in Visual mode, but only jump to marks in the
current buffer.
7 CTRL-A and CTRL-X should increase/decrease all numbers in the Visual area.
6 In non-Block mode, "I" should insert the same text in front of each line,
before the first non-blank, "gI" in column 1.
6 In non-Block mode, "A" should append the same text after each line.
6 ":'<,'>source" should read the selected lines and ":source" them.
6 When in blockwise visual selection (CTRL-V), allow cursor to be placed
right of the line. Could also allow cursor to be placed anywhere on a TAB
or other special character.
6 Add commands to move selected text, without deselecting.
Quickfix:
8 Quickfix mode: Column number should be interpreted with an 8-character
tabstop.
Incsearch:
- Add a limit to the number of lines that are searched for 'incsearch'?
- When incsearch used and hitting return, no need to search again in many
cases, saves a lot of time in big files. (Slootman wants to work on this?)
When not using special characters, can continue search from the last match
(or not at all, when there was no match). See oldmail/webb/in.872.
- With incsearch, use CTRL-N/CTRL-P to go to next/previous match, some other
key to copy matched word to search pattern (Alexander Schmid).
Searching:
8 Would it be possible to allow ":23,45/pat/flags" to search for "pat" in
lines 23 to 45? Or does this conflict with Ex range syntax?
8 Allow identical pairs in 'matchpairs'. Restrict the search to the current
line.
7 Allow longer pairs in 'matchpairs'. Use ~/vim/macros/matchit.vim as an
example.
8 Make it possible to define the character that "%" checks for in
#if/#endif. For nmake it's !if/!endif.
- For "%" command: set hierarchy for which things include other things that
should be ignored (like "*/" or "#endif" inside /* */).
Also: use "%" to jump from start to end of syntax region and back.
Alternative: use matchit.vim
8 "/:/e+1" gets stuck on a match at the end of the line. Do we care?
8 A pattern like "\([^a]\+\)\+" takes an awful long time. Recognize that
the recursive "\+" is meaningless and optimize for it.
This one is also very slow on "/* some comment */": "^\/\*\(.*[^/]\)*$".
7 Recognize "[a-z]", "[0-9]", etc. and replace them with the faster "\l" and
"\d".
8 Flags that apply to the whole pattern.
This works for all places where a regexp is used.
Add "\q" to not store this pattern as the last search pattern?
8 Add an option not to use 'hlsearch' highlighting for ":s" and ":g"
commands. (Kahn) It would work like ":noh" is used after that command.
Also: An extra flag to do this once, and a flag to keep the existing
search pattern.
- Add \%h{group-name}; to search for a specific highlight group.
Add \%s{syntax-group}; to search for a specific syntax group.
- Support Perl regexp. Use PCRE (Perl Compatible RE) package. (Shade)
Or translate the pattern to a Vim one.
Don't switch on with an option for typed commands/mappings/functions, it's
too confusing. Use "\@@" in the pattern, to avoid incompatibilities.
7 Add POSIX regexp, like Nvi, with 'extended' option? It's like very-magic.
- Remember flags for backreferenced items, so that "*" can be used after it.
Check with "\(\S\)\1\{3}". (Hemmerling)
- Add flags to search command (also for ":s"?):
i ignore case
I use case
p use Perl regexp syntax (or POSIX?)
v use Vi regexp syntax
f forget pattern, don't keep it for "n" command
F remember pattern, keep it for "n" command
Perl uses these too:
e evaluate the right side as an expression (Perl only)
m multiple line expression (we don't need it)
o compile only once (Perl only)
s single line expression (we don't need it)
x extended regexp (we don't need it)
When used after ":g" command, backslash needed to avoid confusion with the
following command.
Add 'searchflags' for default flags (replaces 'gdefault').
- Add command to display the last used substitute pattern and last used
pattern. (Margo) Maybe make it accessible through a register (like "/
for search string)?
7 Use T-search algorithm, to speed up searching for strings without special
characters. See C't article, August 1997.
- Add 'fuzzycase' option, so that case doesn't matter, and '-' and '_' are
equivalent (for Unix filenames).
- Add 'v' flag to search command: enter Visual mode, with the matching text
as Visual area. (variation on idea from Bertin)
- Searching: "/this//that/" should find "that" after "this".
- Add global search commands: Instead of wrapping at the end of the buffer,
they continue in another buffer. Use flag after search pattern:
a for the next file in the argument list
f for file in the buffer list
w for file edited in a window.
e.g. "/pat/f". Then "n" and "N" work through files too. "f" flag also for
":s/pat/foo/f"??? Then when 'autowrite' and 'hidden' are both not set, ask
before saving files: "Save modified buffer "/path/file"? (Yes/Hide/No
Save-all/hide-All/Quit) ".
- ":s/pat/foo/3": find 3rd match of "pat", like sed. (Thomas Koehler)
- Special characters in patterns:
Inside []:
\012 octal character
\0x1a hex character
\0<BS> \0<Esc>: special character
7 When searching with 'n' give message when getting back where the search
first started. Remember start of search in '/ mark.
7 Add option that scrolls screen to put cursor in middle of screen after
search always/when off-screen/never. And after a ":tag" command. Maybe
specify how many lines below the screen causes a redraw with the cursor in
the middle (default would be half a screen, zero means always).
6 Support multiple search buffers, so macros can be made without side
effects.
7 From xvim: Allow a newline in search patterns (also for :s, can delete
newline). Add BOW, EOW, NEWL, NLORANY, NLBUTANY, magic 'n' and 'r', etc.
[not in xvim:] Add option to switch on matches crossing ONE line boundary.
7 Add ":iselect", a combination of ":ilist" and ":tselect". (Aaron)
Also ":dselect".
Undo:
8 Make undo more memory-efficient: Compare text before and after change,
only remember the lines that really changed.
7 Add an undo tree: When making a change, instead of clearing any future
undo (thus redo) info, make a new branch. How to navigate through the
undo tree?
- For u_save() include the column number. This can be used to set '[ and '].
And in the future the undo can be made more efficient (Webb).
- In out-of-memory situations: Free allocated space in undo, and reduce the
number of undo levels (with confirmation).
- Instead of [+], give the number of changes since the last write: [+123].
When undoing to before the last write, change this to a negative number:
[-99].
7 Make it possible to jump to the location of the last change. Like doing
"u" "CTRL-R". (Lange) Keep a list of the 10 last changes or so. Use
g_CTRL-O and g_CTRL-I?
- With undo with simple line delete/insert: optimize screen updating.
- When executing macro's: Save each line for undo only once.
- Store undo info in a file that survives until the next edit. Then it's
possible to undo to before the current editing session. Combined with
viminfo?
- When doing a global substitute, causing almost all lines to be changed,
undo info becomes very big. Put undo info in swap file??
Buffer list:
7 Command to execute a command in another buffer: ":inbuf {bufname} {cmd}".
Also for other windows: ":inwin {winnr} {cmd}". How to make sure that
this works properly for all commands, and still be able to return to the
current buffer/window? E.g.: ":inbuf xxx only".
8 Add File.{recent_files} menu entries: Recently edited files.
8 Unix: Check all uses of fnamecmp() and fnamencmp() if they should check
inode too.
7 Add another number for a buffer, which is visible for the user. When
creating a new buffer, use the lowest number not in use. (or the highest
number in use plus one?)
7 Offer some buffer selection from the command line? Like using ":ls" and
asking for a buffer number. (Zachmann)
- When starting to edit a file that is already in the buffer list, use the
file name argument for the new short file name. (Webb)
- Add an option to make ":bnext" and ":bprev" wrap around the end of the
buffer list. Also for ":next" and ":prev"?
7 Add argument to ":ls" which is a pattern for buffers to list.
E.g. ":ls *.c". (Thompson)
7 Add expansion of buffer names, so that "*.c" is expanded to all buffer
names. Needed for ":bdel *.c", ":bunload *.c", etc.
8 Support for <afile> where a buffer name is expected.
8 Some commands don't use line numbers, but buffer numbers. '$'
should then mean the number of the last buffer. E.g.: "4,$bdel".
7 Add an option to mostly use slashes in file names. Separately for
internal use and for when executing an external program?
Viminfo:
7 Can probably remove the code that checks for a writable viminfo file,
because we now do the chown() for root, and others can't overwrite someone
else's viminfo file.
8 Add argument to keep the list of buffers when Vim is started with a file
name. (Schild)
8 Keep the last used directory of the file browser (File/Open menu).
8 Remember a list of last accessed files. To be used in the
"File.Open Recent" menu. Default is to remember 10 files or so.
Also remember which files have been read and written. How to display
this?
7 Also store the ". register (last inserted text).
7 Make it possible to store buffer names in viminfo file relative to some
directory, to make them portable over a network. (Aaron)
6 Store a snapshot of the currently opened windows. So that when quitting
Vim, and then starting again (without a file name argument), you see the
same files in the windows. Use ":mksession" code?
- Make marks present in .viminfo usable as file marks: Display a list of
"last visited files" and select one to jump to.
Modelines:
8 Before trying to execute a modeline, check that it looks like one (valid
option names). If it's very wrong, silently ignore it.
Ignore a line that starts with "Subject: ".
- When an option value is coming from a modeline, do not carry it over to
another edited file? Would need to remember the value from before the
modeline setting.
- Allow setting a variable from a modeline? Only allow using fixed strings,
no function calls, to avoid a security problem.
- Allow ":doauto BufRead x.cpp" in modelines, to execute autocommands for
.cpp files.
- Support the "abbreviate" command in modelines (Kearns). Careful for
characters after <Esc>, that is a security leak.
- Add option setting to ask user if he wants to have the modelines executed
or not. Same for .exrc in local dir.
Options:
8 Make ":mksession" store buffer-specific options for the specific buffer.
8 With ":mksession" always store the 'sessionoptions' option, even when
"options" isn't in it. (St-Amant)
8 When using ":mksession", also store a command to reset all options to
their default value, before setting the options that are not at their
default value.
8 Should ":mksession" restore the current directory when writing the
session, or the directory where the session file is? Probably need a word
in 'sessionoptions' to make a choice:
"curdir" (cd to current directory when session file was generated)
"sessiondir" (cd to directory of session file)
"nodir" (don't cd at all)
8 Add Edit.Settings menu with most often used options:
line numbering on/off
wrap on/off
hlsearch on/off
toolbar on/off
scrollbars left, right, bottom on/off
shiftwidth 2, 3, 4, 5, 6, 8
expandtab on/off
8 Make "old" number options that really give a number of effects into string
options that are a comma separated list. The old number values should
also be supported.
8 Add commands to save and restore an option, which also preserves the flag
that marks if the option was set. Useful to keep the effect of setting
'compatible' after ":syntax on" has been used.
7 There is 'titleold', why is there no 'iconold'? (Chazelas)
External commands:
9 When filtering a buffer (e.g., to gunzip it) marks are changed when they
shouldn't. Add an option to switch of adjusting marks. Use it for .gz
files gunzipping and gzipping.
8 When filtering text, redirect stderr so that it can't mess up the screen
and Vim doesn't need to redraw it. Also for ":r !cmd".
4 Set separate shell for ":sh", piping "range!filter", reading text "r !ls"
and writing text "w !wc". (Deutsche) Allow arguments for fast start (e.g.
-f).
4 Allow direct execution, without using a shell.
4 Run an external command in the background. But how about I/O in the GUI?
Careful: don't turn Vim into a shell!
4 Add feature to disable using a shell or external commands.
Multiple Windows:
6 Add an option to resize the shell when splitting and/or closing a window.
":vsp" would make the shell wider by as many columns as needed for the new
window. Specify a maximum size (or use the screen size). ":close" would
shrink the shell by as many columns as come available. (Demirel)
7 When starting Vim several times, instanciate a Vim server, that allows
communication between the different Vims. Feels like one Vim running with
multiple top-level windows. Esp. useful when Vim is started from an IDE
too. Requires some form of inter process communication.
7 Run Vim as a server, and let other started Vims send an edit command to
the server. Consider patch from Brent Verner to add sockets interface?
~/vim/patches/verner_socket.tgz
- Support a connection to an external viewer. Could call the viewer
automatically after some seconds of non-activity, or with a command.
Allow some way of reporting scrolling and cursor positioning in the viewer
to Vim, so that the link between the viewed and edited text can be made.
Marks:
8 Add a command to jump to a mark and make the motion inclusive. g'm and g`m?
8 When deleting lines, don't delete uppercase marks in them. Move the mark
to the nearest line.
8 The '" mark is set to the first line, even when doing ":next" a few times.
Only set the '" mark when the cursor was really moved in a file.
8 Make `` and '', which would position the new cursor position in the middle
of the window, restore the old topline (or relative position) from when
the mark was set.
7 Make a list of file marks in a separate window. For listing all buffers,
matching tags, errors, etc. Normal commands to move around. Add commands
to jump to the mark (in current window or new window). Start it with
":browse cmd"?
6 Add a menu that lists the Marks like ":marks". (Amerige)
7 For ":jumps", ":tags" and ":marks", for not loaded buffers, remember the
text at the mark. Highlight the column with the mark.
7 Highlight each mark in some way (With "Mark" highlight group).
Or display marks in a separate column, like 'number' does.
7 Use d"m to delete rectangular area from cursor to mark m (like Vile's \m
command).
7 Try to keep marks in the same position when:
- replacing with a line break, like in ":s/pat/^M/", move marks after the
line break column to the next line. (Acevedo)
- filtering lines, try to keep the marks in the filtered lines. Need to
move some marks if the number of lines decreases.
- changing text, e.g. when formatting with "gq".
- inserting/deleting characters in a line.
5 Include marks for start/end of the current word and section. Useful in
mappings.
Digraphs:
- Make it possible to enter "r<C-E>" and "r<C-Y>" (get character from line
below/above).
- Use digraph table to tell Vim about the collating sequence of special
characters?
- Add command to remove (all) digraphs. (Brown)
7 Support different sets of digraphs (depending on the character set?). At
least Latin1/Unicode, Latin-2, MS-DOS (esp. for Win32).
Writing files:
- In vim_rename(), should lock "from" file when deleting "to" file for
systems other than Amiga. Avoids problems with unexpected longname to
shortname conversion.
8 write mch_isdevice() for Amiga, Mac, VMS, etc.
8 When appending to a file, Vim should also make a backup and a 'patchmode'
file.
6 Add an option to write a new, numbered, backup file each time. Like
'patchmode', e.g., 'backupmode'.
6 Make it possible to write 'patchmode' files to a different directory.
E.g., ":set patchmode=~/backups/*.orig". (Thomas)
6 Add an option to prepend something to the backup file name. E.g., "#".
Or maybe allow a function to modify the backup file name?
8 Only make a backup when overwriting a file for the first time. Avoids
loosing the original when writing twice. (Slootman)
7 On non-Unix machines, also overwrite the original file in some situations
(file system full, it's a link on an NFS partition).
7 When editing a file, check that it has been change outside of Vim more
often, not only when writing over it. E.g., at the time the swap file is
flushed. Or every ten seconds or so (use the time of day, check it before
waiting for a character to be typed).
8 When a file was changed since editing started, show this in the status
line of the window, like "[time]".
Make it easier to reload all outdated files that don't have changes.
Automatic and/or with a command.
Substitute:
- :s///p prints the line after a substitution.
- With :s///c replace \&, ~, etc. when showing the replacement pattern.
8 With :s///c allow scrolling horizontally when 'nowrap' is effective.
Also allow a count before the scrolling keys.
- Add number option to ":s//2": replace second occurrence of string? Or:
:s///N substitutes N times.
- Add answers to ":substitute" with 'c' flag, used in a ":global", e.g.:
":g/pat1/s/pat2/pat3/cg": 'A' do all remaining replacements, 'Q' don't do
any replacements.
7 Substitute in a block of text. Use {line}.{column} notation in an Ex
range, e.g.: ":1.3,$.5s" means to substitute from line 1 column 3 to the
last line column 5.
Mouse support:
8 Add 'mouse' flag, which sets a behavior like Visual mode, but automatic
yanking at the button-up event. Or like Select mode, but typing gets you
out of Select mode, instead of replacing the text. (Bhaskar)
7 Checkout sysmouse() for FreeBSD console mouse support.
- Implement mouse support for the Amiga console.
- Using right mouse button to extend a blockwise selection should attach to
the nearest corner of the rectangle (four possible corners).
- Precede mouse click by a number to simulate double clicks?!?
- When mouse click after 'r' command, get character that was pointed to.
Crypt:
8 Also crypt the swapfile, each block separately. Change mf_write() and
mf_read(). How to get b_p_key to these functions?
Argument list:
6 Add command to put all filenames from the tag files in the argument list.
When given an argument, only use the files where that argument matches
(like `grep -l ident`) and jump to the first match.
6 Add command to form an args list from all the buffers?
Registers:
8 Don't display empty registers with ":display". (Etienne)
- When appending to a register, also report the total resulting number of
lines. Or just say "99 more lines yanked", add the "more".
- When inserting a register in Insert mode with CTRL-R, don't insert comment
leader when line wraps?
- The ":@r" commands should take a range and execute the register for each
line in the range.
- Add "P" command to insert contents of unnamed register, move selected text
to position of previous deleted (to swap foo and bar in " + foo")
8 Make "/ register writable. (Maxi)
How to take care of the flags (offset, magic)?
7 Add ! register, for shell commands. (patch from Grenie)
Various improvements:
8 Allow using "**" as a wildcard in commands like ":next" and ":args".
7 Add a message area for the user. Set some option to reserve space (above
the command line?). Use an ":echouser" command to display the message
(truncated to fit in the space).
7 Add %s to 'keywordprg': replace with word under the cursor. (Zellner)
8 Support printing on Unix. Can use "lpansi.c" as an example. (Bookout)
8 Add put command that replaces the text under it. Esp. for blockwise
Visual mode.
7 Enhance termreponse stuff: Add t_CV(?): pattern of term response, use
regexp: "\e\[[>?][0-9;]*c", but only check just after sending t_RV.
7 Add "g|" command: move to N'th column from the left margin (after wrapping
and applying 'leftcol'). Works as "|" like what "g0" is to "0".
7 Add patch from Wall for this one ( ~/Mail/oldmail/wall/in.00019 ):
'flipcase' variable: upper/lower case pairs.
Insert comma's between pairs and allow a range, make it look like
'isfname'. E.g. ":set flipcase=a-zA-Z,xX,23-33:143-153". The colon to
separate the from and to part is optional.
7 Support setting 'euqalprg' to a user function name.
8 Add cursor-column highlighting. Enable it with 'cursorcolumn' option, set
highlighting with "CursorColumn" group. Useful for aligning text.
Also cursor-row highlighting.
7 Highlight the characters after the end-of-line differently.
7 When 'whichwrap' contains "l", "$dl" should join lines?
6 Include the ruby interface?
7 Open a server socket (with an option for IP/port nr) to allow remote
control. Optionally with a password to restrict access.
Use the Simple Sockets Library? (Campbell)
Same sample code (brent verner): http://linux1.org/misc/vim_socket.tar.bz2
8 Include a connection to an external program through a pipe? See patches
from Felbinger for a mathematica inteface.
Or use emacs server kind of thing?
8 Add an argument to configure to use $CFLAGS and not modify it? (Mooney)
8 Enabling features is a mix of configure arguments and defines in
feature.h. How to make this consistent? Feature.h is required for
non-unix systems. Perhaps let configure define CONF_XXX, and use #ifdef
CONF_XXX in feature.h? Then what should min-features and max-features do?
8 Add "g^E" and "g^Y", to scroll a screen-full line up and down.
6 Add ":timer" command, to set a command to be executed at a certain
interval, or once after some time has elapsed. (Aaron)
8 Add ":confirm" handling in open_exfile(), for when file already exists.
8 Use confirm/dialog stuff to ask the user, when a file has changed outside
of Vim, if he wants to reload it. Triggered when focus gained, after
shell command, when entering another buffer, etc..
Also do this when editing a new file, and another application creates
the file before doing ":w" in Vim.
Also check if the file protection has changed. When checking a file into
RCS it is made read-only, when checking out it is made read-write.
8 When quitting with changed files, make the dialog list the changed file
and allow "write all", "discard all", "write some". The last one would
then ask "write" or "discard" for each changed file. Patch in HierAssist
does something like this. (Shah)
7 Use growarray for replace stack.
7 Have a look at viH (Hellenic or Greek version of Vim). But a solution
outside of Vim might be satisfactory (Haritsis).
3 Make "2d%" work like "d%d%" instead of "d2%"?
8 Make "more" prompt accept command characters, like "hit-enter" prompt?
Or extend it with more commands, like "less": 'b' for back, 'j' for one
line down, etc.
8 For the "--more--" prompt, support the 'b'ack command for more commands.
7 "g CTRL-O" jumps back to last used buffer. Skip CTRL-O jumps in the same
buffer. Make jumplist remember the last ten accessed buffers?
- Keep a list of most recently used files for each window, use "[o" to go
back (older file) and "]n" to go forward (newer file) (like ^O and ^I for
jumps) (Webb). Use ":files" and ":ls" to list the files in history order.
7 Add a history of recently accessed buffer. Maybe make "2 CTRL-^" jump to
the 2nd previously visited buffer, "3 CTRL-^" to the third, etc. Or use
"3 g CTRL-^" for this?
5 Add an option to set the width of the 'number' column. Eight positions is
often more than needed. Or adjust the width to the length of the file?
- Add code to disable the CAPS key when going from Insert to Normal mode.
- Set date/protection/etc. of the patchfile the same as the original file.
- Use growarray for termcodes[] in term.c
- Add <window-99>, like <cword> but use filename of 99'th window.
- Make a set of operations on list of names: expand wildcards, replace home
dir, append a string, delete a string, etc.
- Remove mktemp() and use tmpname() only? Ctags does this.
- When replacing environment variables, and there is one that is not set,
turn it into an empty string? Only when expanding options? (Hiebert)
- Option to set command to be executed instead of producing a beep (e.g. to
call "play newbeep.au").
- Add option to show the current function name in the status line. More or
less what you find with "[[k", like how 'cindent' recognizes a function.
(Bhatt).
- "[r" and "]r": like "p" and "P", but replace instead of insert (esp. for
blockwise registers).
- Add 'timecheck' option, on by default. Makes it possible to switch off the
timestamp warning and question. (Dodt).
- Add an option to set the time after which Vim should check the timestamps
of the files. Only check when an event occurs (e.g., character typed,
mouse moved). Useful for non-GUI versions where keyboard focus isn't
noticable.
9 When using ":w <fname>" it's possible that this file is loaded in another
buffer. Give a warning right away, don't wait for a shell command.
- Make 'smartcase' work even though 'ic' isn't set (Webb).
7 When formatting text, allow to break the line at a number of characters.
Use an option for this: 'breakchars'? Useful for formatting Fortran code.
- Add flag to 'formatoptions' to be able to format book-style paragraphs
(first line of paragraph has larger indent, no empty lines between
paragraphs). Complements the '2' flag. Use '>' flag when larger indent
starts a new paragraph, use '<' flag when smaller indent starts a new
paragraph. Both start a new paragraph on any indent change.
8 Allow using a trailing space to signal a paragraph that continues on the
next line. Can be used for continuous formatting. Could use 'autoformat'
option, which specifies a regexp which triggers auto-formatting (for one
line). ":set autoformat=\\s$".
- Be able to redefine where a sentence stops. Use a regexp pattern?
- Be able to redefine where a paragraph starts. For "[[" where the '{' is
not in column 1.
8 ":cd": echo the new current directory.
6 Add ":cdprev": go back to the previous directory. Need to remember a
stack of previous directories. We also need ":cdnext".
7 Should ":cd" for MS-DOS go to $HOME, when it's defined?
- Make "gq<CR>" work on the last line in the file. Maybe for every operator?
8 findmatchlimit() should be able to skip comments. Solves problem of
matching the '{' in /* if (foo) { */ (Fiveash)
- findmatch() should be adjusted for Lisp. See remark at get_lisp_indent().
- Add more redirecting of Ex commands:
:redir @> register (append)
:redir # bufname
:redir #> bufname (append)
:redir = variable
:redir => variable (append)
8 ":redir >$HOME/xxx" should work: expand file name argument of ":redir".
- Setting of options, specifically for a buffer or window, with
":set window.option" or ":set buffer.option=val". Or use ":buffer.set".
Also: "buffer.map <F1> quit".
- Add :delcr command:
*:delcr*
:[range]delcr[!] Check [range] lines (default: whole buffer) for lines
ending in <CR>. If all lines end in <CR>, or [!] is
used, remove the <CR> at the end of lines in [range].
A CTRL-Z at the end of the file is removed. If
[range] is omitted, or it is the whole file, and all
lines end in <CR> 'textmode' is set. {not in Vi}
- Should integrate addstar() and file_pat_to_reg_pat().
- When working over a serial line with 7 bit characters, remove meta
characters from 'isprint'.
- Use fchdir() in init_homedir(), like in FullName().
- In win_update(), when the GUI is active, always use the scrolling area.
Avoid that the last status line is deleted and needs to be redrawn.
- That "cTx" fails when the cursor is just after 'x' is Vi compatible, but
may not be what you expect. Add a flag in 'cpoptions' for this? More
general: Add an option to allow "c" to work with a null motion.
- Give better error messages by using errno (strerror()).
- Give "Usage:" error message when command used with wrong arguments (like
Nvi).
- Make 'restorescreen' option also work for xterm (and others), replaces the
SAVE_XTERM_SCREEN define.
7 Support for ":winpos" In xterm: report the current window position.
- Give warning message when using ":set t_xx=asdf" for a termcap code that
Vim doesn't know about. Add flag in 'shortmess'?
6 Add ":che <file>", list all the include paths which lead to this file.
- For a commandline that has several commands (:s, :d, etc.) summarize the
changes all together instead of for each command (e.g. for the rot13
macro).
- Add command like "[I" that also shows the tree of included files.
- Add command like ":ts" that shows the output of "[I" and asks for a match
to jump to. (Zellner)
- ":set sm^L" results in ":set s", because short names of options are also
expanded. Is there a better way to do this?
- Add ":@!" command, to ":@" like what ":source!" is to ":source".
8 Add ":@:!": repeat last command with forceit set.
- Should be possible to write to a device, e.g. ":w! /dev/null".
- Add 't_normal': Used whenever t_me, t_se, t_ue or t_Zr is empty.
- ":cab map test ^V| je", ":cunab map" doesn't work. This is vi compatible!
- CTRL-W CTRL-E and CTRL-W CTRL-Y should move the current window up or down
if it is not the first or last window.
- Include-file-search commands should look in the loaded buffer of a file (if
there is one) instead of the file itself.
7 Change 'nrformats' to include the leader for each format. Example:
nrformats=hex:$,binary:b,octal:0
Add setting of 'nrformats' to syntax files.
- 'path' can become very long, don't use NameBuff for expansion.
- When unhiding a hidden buffer, put the same line at top of the window as
the one before hiding it. Or: keep the same relative cursor position (so
many percent down the windows).
- Make it possible for the 'showbreak' to be displayed at the end of the
line. Use a comma to separate the part at the end and the start of the
line? Highlight the linebreak characters, add flag in 'highlight'.
- Some string options should be expanded if they have wildcards, e.g.
'dictionary' when it is "*.h".
- Use a specific type for number and boolean options, making it possible to
change it for specific machines (e.g. when a long is 64 bit).
- Add option for <Insert> in replace mode going to normal mode. (Nugent)
- Add a next/previous possibility to "[^I" and friends.
- Add possibility to change the HOME directory. Use the directory from the
passwd file? (Antwerpen)
- When doing "[^I" or "[^D" add position to tag stack.
- Add command to put current position to tag stack: ":tpush".
8 Add commands to push and pop all or individual options. ":setpush tw",
":setpop tw", ":setpush all". Maybe pushing/popping all options is
sufficient. ":setflush" resets the option stack?
How to handle an aborted mapping? Remember position in tag stack when
mapping starts, restore it when an error aborts the mapping?
- Use a builtin grep command for ":grep"? Makes it possible to add the
column number.
- Change ":fixdel" into option 'fixdel', t_del will be adjusted each time
t_bs is set? (Webb)
- "gc": goto character, move absolute character positions forward, also
counting newlines. "gC" goes backwards (Weigert).
- When doing CTRL-^, redraw buffer with the same topline (Demirel). Store
cursor row and window height to redraw cursor at same percentage of window
(Webb).
- Besides remembering the last used line number of a file, also remember the
column. Use it with CTRL-^ et. al.
- When a window resizes, the line with the cursor should stay at the same
percentage from the start of the window as it was before.
- Check for non-digits when setting a number option (careful when entering
hex codes like 0xff).
- Add option to make "." redo the "@r" command, instead of the last command
executed by it. Also to make "." redo the whole mapping. Basically: redo
the last TYPED command.
- Support URL links for ^X^F in Insert mode, like for "gf".
- Add 'wwwpath', used like 'path' for when "gf" used on an URL?
- Support %name% expansion for "gf" on Windows.
- When finding an URL or file name, and it doesn't exist, try removing a
trailing '.'.
- Add ":path" command modifier. Should work for every command that takes a
file name argument, to search for the file name in 'path'. Use
find_file_in_path().
- Highlight control characters on the screen: Shows the difference between
CTRL-X and "^" followed by "X" (Colon).
- Integrate parsing of cmdline command and parsing for expansion.
- Create a program that can translate a .swp file from any machine into a
form usable by Vim on the current machine.
- Add ":noro" command: Reset 'ro' flag for all buffers, except ones that have
a readonly file. ":noro!" will reset all 'ro' flags.
- Add a variant of CTRL-V that stops interpretation of more than one
character. For entering mappings on the command line where a key contains
several special characters, e.g. a trailing newline.
- Add regex for 'paragraphs' and 'sections': 'parare' and 'sectre'. Combine
the two into a regex for searching. (Ned Konz)
- Make '2' option in 'formatoptions' also work inside comments.
- Add 's' flag to 'formatoptions': Do not break when inside a string. (Dodt)
- Add flag to 'formatoptions' to recognize the change of indent as the start
of a new paragraph (for paragraphs without separating empty line, but extra
indent for the new paragraph) (Leitner).
- When window size changed (with the mouse) and made too small, set it back
to the minimal size.
- Add "]>" and "[<", shift comment at end of line (command; /* comment */).
- Should not call cursorcmd() for each vgetc() in getcmdline().
- ":split file1 file2" adds two more windows (Webb).
- Don't give message "Incomplete last line" when editing binary file.
- Add ":a", ":i" for preloading of named buffers.
- Allow autowrite when doing ":e file" (with an option 'eaw').
- Allow a "+command" argument before each file name in the Vim command line:
"vim +123 file1 +234 file2 +345 file3". ???
- When entering text, keep other windows on same buffer updated (when a line
entered)?
- Check out how screen does output optimizing. Apparently this is possible
as an output filter.
- In dosub() regexec is called twice for the same line. Try to avoid this.
- Window updating from memline.c: insert/delete/replace line.
- Optimize ml_append() for speed, esp. for reading a file.
- V..c should keep indent when 'ai' is set, just like [count]cc.
- Updatescript() can be done faster with a string instead of a char.
- Screen updating is inefficient with CTRL-F and CTRL-B when there are long
lines.
- Uppercase characters in ex commands can be made lowercase?
8 Add option to show characters in text not as "|A" but as decimal ("^129"),
hex ("\x81") or octal ("\201") or meta (M-x). Nvi has the 'octal' option
to switch from hex to octal. Vile can show unprintable characters in hex
or in octal.
7 Tighter integration with xxd to edit binary files. Make it more
easy/obvious to use. Command line argument?
- How does vi detect whether a filter has messed up the screen? Check source.
After ":w !command" a wait_return?
- Improve screen updating code for doput() (use s_ins()).
- With 'p' command on last line: scroll screen up (also for terminals without
insert line command).
- Use insert/delete char when terminal supports it.
- Optimize screen redraw for slow terminals.
- Optimize "dw" for long row of spaces (say, 30000).
- Add "-d null" for editing from a script file without displaying.
- In Insert mode: Remember the characters that were removed with backspace
and re-insert them one at a time with <key1>, all together with <key2>.
- Amiga: Add possibility to set a keymap. The code in amiga.c does not work
yet.
- Implement 'redraw' option.
- Add special code to 'sections' option to define something else but '{' or
'}' as the start of a section (e.g. one shiftwidth to the right).
- Add 'indent' option: Always use this amount of indent when starting a new
line and when formatting text.
- Use pipes for filtering on Unix. Requires using fork() to be able to read
and write at the same time, or some select() mechanism.
7 Allow using Vim in a pipe: "ls | vim -u xxx.vim - | yyy". Only needs
implementing ":w" to stdout in the buffer that was read from stdin.
8 Allow opening an unnamed buffer with ":e !cmd" and ":sp !cmd". Vile can
do it.
- Allow for +command and -option on any position in argv[].
- Add commands like ]] and [[ that do not include the line jumped to.
- When :unab without matching "from" part and several matching "to" parts,
delete the entry that was used last, instead of the first in the list.
- Add text justification option.
- Set boolean options on/off with ":set paste=off", ":set paste=on".
- After "inv"ing an option show the value: ":set invpaste" gives "paste is
off".
- Check handling of CTRL-V and '\' for ":" commands that do not have TRLBAR.
- When a file cannot be opened but does exist, give error message.
- Amiga: When 'r' protection bit is not set, file can still be opened but
gives read errors. Check protection before opening.
- When writing check for file exists but no permission, "Permission denied".
- If file does not exists, check if directory exists.
- MSDOS: although t_cv and t_ci are not set, do invert char under cursor.
- Settings edit mode: make file with ":set opt=xx", edit it, parse it as ex
commands.
- ":set -w all": list one option per line.
- Amiga: test for 'w' flag when reading a file.
- :table command (Webb)
- Add new operator: clear, make area white (replace with spaces): "g ".
- Make it possible for a user to define a new operator. Implementation with
internal scripting language or Perl?
- Add command to ":read" a file at a certain column (blockwise read?).
- Add 'resizecmd' option: vi command to be executed when window is resized.
- Add sort of replace mode where case is taken from the old text (Goldfarb).
- Allow multiple arguments for ":read", read all the files.
- Support for tabs in specific columns: ":set tabcol=8,20,34,56" (Demirel).
- Add 'searchdir' option: Directories to search for file name being edited
(Demirel).
- Modifier for the put command: Change to linewise, charwise, blockwise, etc.
- Add commands for saving and restoring options ":set save" "set restore",
for use in macro's and the like.
- Keep output from listings in a window, so you can have a look at it while
working in another window. Put cmdline in a separate window?
- Add possibility to put output of ex commands in a buffer or file, e.g. for
":set all". ":r :set all"?
- 'edit' option: When off changing the buffer is not possible (Really
read-only mode).
- When the 'equalalways' option is set, creating a new window should not
result in windows to become bigger. Deleting a window should not result in
a window to become smaller (Webb).
- When resizing the whole Vim window, the windows inside should be resized
proportionally (Webb).
- Include options directly in option table, no indirect pointers. Use
mkopttab to make option table?
- When doing ":w dir", where "dir" is a directory name, write the current
file into that directory, with the current file name (without the path)?
- Support for 'dictionary's that are sorted, makes access a lot faster
(Haritsis).
- Add "^Vrx" on the command line, replace with contents of register x. Used
instead of CTRL-R to make repeating possible. (Marinichev)
- Add "^Vb" on the command line, replace with word before or under the
cursor?
- Option to make a .swp file only when a change is made (Templeton).
- Support mapping for replace mode and "r" command (Vi doesn't do this)?
5 Add 'ignorefilecase' option: Ignore case when expanding file names.
":e ma<Tab>" would also find "Makefile" on Unix.
From Elvis:
- Use "instman.sh" to install manpages?
- Add ":alias" command.
- fontchanges recognized "\\fB" etc.
- Search patterns:
\@ match word under cursor.
but do:
\@w match the word under the cursor?
\@W match the WORD under the cursor?
8 ":window" command:
:win + next window (up)
:win ++ idem, wrapping
:win - previous window (down)
:win -- idem, wrapping
:win nr to window number "nr"
:win name to window editing buffer "name"
7 ":cc" compiles a single file (default: current one). 'ccprg' option is
program to use with ":cc". Use ":compile" instead of ":cc"?
From Nvi:
- 'searchincr' option, alias for 'incsearch'?
- 'leftright' option, alias for 'nowrap'?
- Have a look at "vi/doc/vi.chart", for Nvi specialities.
8 Add 'keytime', time in 1/10 sec for mapping timeout?
- Add 'filec' option as an alternative for 'wildchar'.
6 Support Nvi command names as an alias:
:bg :hide
:fg fname :buf fname (with 'hidden' set?)
:dis b :ls
:Edit fname :split fname
:Fg fname :sbuf fname (with 'hidden' set?)
:Next :snext (can't do this, already use :Next)
:Previous :sprevious
:Tag :stag
From xvi:
- CTRL-_ : swap 8th bit of character.
- Add egrep-like regex type, like xvi (Ned Konz) or Perl (Emmanuel Mogenet)
From vile:
- When horizontal scrolling, use '<' and '>' for lines continuing outside of
window.
- Support putting .swp files in /tmp: Command in rc.local to move .swp files
from /tmp to some directory before deleting files.
In November 1998 an inquiry was held to allow Vim users to vote for changes to
Vim. Each person was allowed to give 10 positive and 5 negative points to a
list of items. Below is the result. This indicates the desire of users for
certain changes. This will be taken into account when deciding what to do
next from the huge list above.
The first number is the total number of votes. The number in brackets is the
portion of the total which were negative points.
317 (-5) add folding (display only a selected part of the text)
252 (-10) vertically split windows (side-by-side)
197 (-3) add configurable auto-indenting for many languages (like 'cindent')
183 (-5) fix all problems, big and small; make Vim more robust
155 (-8) add Perl compatible search pattern
125 (-1) search patterns that cross line boundaries
125 (-1) improve syntax highlighting speed
116 improve syntax highlighting functionality
101 add a menu that lists all buffers
93 (-1) improve the overall performance
93 (-6) multiple top-level windows for one running Vim
90 (-4) be able to edit the command line with Vi commands
90 (-36) add a shell window (to type and execute shell commands in)
83 add patterns to define sections/paragraphs for "{", "[[", "%", etc.
81 improve Visual block mode: more commands that work on blocks
71 (-13) reduce the size of the executable and the runtime memory use
70 (-5) improve the on-line help
68 improve "gq" formatting of text (left&right justified, 'comments')
68 (-2) improve multi-byte character support
59 (-8) improve the Visual Studio interface (VisVim)
59 (-12) make it possible to run Vim inside a window of another program
58 (-11) add an undo tree (be able to go back to any previous situation)
57 (-9) add support for loading a shared library that defines new commands
54 (-1) add a way to execute a command in multiple buffers/windows
52 improve the Perl interface
51 (-10) improve printing from gvim (File.Print menu entry)
50 (-20) make a "Vim lite" version, which is small and low on features
47 add a method to repeat a prev. executed change ("c.", "d.", etc.)
44 (-8) add more features to the internal scripting language
37 add a command to repeat a whole mapping (not only its last change)
37 (-2) add better support for editing files in projects (with ID utils)
33 (-3) add handling for buffer-changed outside of Vim (when reg. focus)
28 improve Insert mode completion
28 (-14) add persistent undo (undo to before the file was saved/loaded)
25 improve command line completion
23 (-30) be able to run a program in a Vim window, with an interface to it
22 improve the quickfix commands
21 (-1) add mappings and abbreviations local to a buffer
21 (-6) add a special window for editing option values, with short docs
19 (-4) add file locking
18 (-1) add a way to disable (error) messages for a moment
17 (-5) add encryption for loading/storing files and for the swapfile
10 improve the port for MacOS X Server aka Rhapsody
10 add Qt interface
10 (-1) add scope arguments to the ":tag" command (like Elvis)
9 (-3) improve the tutor (course for beginners)
8 improve the port for OS/2
8 (-1) add a stack for saving/restoring options
8 (-3) improve 'viminfo' (keeping information when quitting Vim)
8 (-6) improve the performance of Vim scripts (pre-parse them)
7 (-2) add more autocommand events (for ":cd", start Insert mode, etc.)
6 (-4) improve the TCL interface
6 (-4) add option to move the cursor where there is no text in Visual mode
5 improve the port for MacOS
4 improve the port for GTK
4 add Diff, Merge capability with CVS like in emacs.
4 (-5) add option not to move the cursor when using a scrollbar
4 (-8) add POSIX compatible search patterns
3 improve the port for X Window (use GTK, or Athena)
3 (-2) improve the Cscope interface
3 (-14) add option to move the cursor where there is no text in any mode
2 add support for Borland Delphi (to replace borland's def. editor)
2 add on-the-fly paragraph formatting / word wraps
1 improve the port for "EPOC 32"
1 add GUI to record/stop/play a keystroke macro
0 (-2) improve ":mksession" support (switch to a previously saved state)
-1 (-1) improve the port for * (fill in a system name at the *. E.g. VMS")
-4 (-77) add more GUI functions (requesters, menus, dialogs)
-10 (-14) add "open" mode, like the original Vi
-10 (-15) improve the OLE interface
-10 (-17) improve compatibility of the Ex mode
-12 (-89) add on-the-fly spell checking
-13 (-24) reduce the size of the distribution (harddisk usage)
-13 (-32) improve Vi compatibility
-25 (-38) add a lot of small features, instead of a few big ones
-47 (-53) improve the 16 bit DOS version (avoid out-of-memory problems)
-81 (-123) improve gvim to fit in the MS-Windows look&feel (with an option)
-110 (-136) stop changing Vim, it's fine as it is
-117 (-122) remove functionality, there is too much of it
vim:tw=78:sw=4:sts=4:
vim: set fo+=n :
Sven [email protected] ©1995-2001 Last update: Wed Mar 14 12:00:00 MET 2001
● General Info
● General Development Goals
● General Development Anti-Goals
● Development for Version 6
● Development for Version 7
● Ports
● Projects
● Howto get the latest release
Pro and Contra Discussions:
● Vim - Discussion on Speed
000412: Latest patches for the developer versions is now available from the CVS Server. See the CVS Page for more
info.
All this would just add more code (and bloat to Vim) and result in this compile option list for my Vim:
:ver
VIM - Vi IMproved 6.66 [WinLinux] (1999 Apr 01, compiled Apr 6 1999 12:07:00)
-babel -c64-linux -do-what-i-mean -emacs -gindent -kitchen-sink -lisp-decoder
-mud-frontend -netscape-explorer -not-so-regular-expressions -print-anywhere
-shell-o-rama -swahili-compiler -tea-hot-earl-grey -windows2000 -write-my-thesis
If you want an editor with a builtin ftp client, mailer, and newsreader then by all means, do use Emacs! I hope I have
made a point here.
● Folding
● Project Editing
● Remote Editing
● Toolbar
● Vertical Split
For more info download the latest documentation ("runtime archive") and look at "todo.txt" or by entering the command
:help extensions-improvements
Bram says about the vim-6 alpha versions:
Unicode support is planned for Vim version 6.0. In Vim 5.x there is
double-byte support, which can be used for encodings that have a font
with double-width characters. Thus the current multi-byte support
is rather limited and doesn't work for Unicode yet.
Here are some features/reasons why I have recommended to upgrade to the latest version:
vim-5.6 [TODO]
Still looking for contributions. Please send them to me at [email protected]
vim-5.5 [TODO]
Still looking for contributions. Please send them to me at [email protected]
vim-5.4 [still an alpha/developer version!]
*Some* of the new features of Vim-5.4:
Folding:
980918 David C. Jr. Harrsion [email protected] (offer)
Vertical split:
990115 Pjotr Kourzanoff [email protected] (offer)
=== Code for special features (eg GUI) and support for other programs
DDE support:
Heiko Erhardt [email protected]
GTK+ support:
981217 Marcin Dalecki [email protected]
981217 Andy Kahn [email protected]
Wished for by:
980915 Sung-Hyun Nam [email protected]
981110 Mitsuo Tsukamoto [email protected]
Japanese support:
981129 Marc Espie [email protected] (offer)
990225 Takuhiro Nishioka [email protected] (testing?)
=== Documentation
Amiga:
970911 Michael Nielsen [email protected]
will help developing the GUI
Atari:
Jens M. Felderhoff [email protected]
Interix:
990217 John McMullen [email protected]
[Intel Interix2.2 Service Pack 1 system]
changes to makefile; ctags didn't compile.
Macintosh:
980123 Dany St-Amant [email protected]
much work on the MacOS port. Anyone have an up-to-date
version of CodeWarrior to help him doing this?
(See also the page on Vim on MacOS
CONTRA S-Lang
● Do we really need another scripting language?
● Implementation of new features in S-Lang might be sufficient for most people, thus hampering the implementation
of solutions within C.
● By moving the implementation of functionality to a scripting language and allowing everybody to exchange
functional modules there is no "central authority" for releasing the one true version of VIM, right?
● Someone has to work in the hooks for S-Lang into the code.
S-Lang HomePage
http://www.s-lang.org/
http://space.mit.edu/~davis/jed.html)
Vim Development - Discussion on Speed
Bram Moolenaar on vim-dev on 990727: Before starting discussions about code size, I would rather hear remarks about
real problems. For example, when Vim starts up a bit slow. And then make sure it's not because of your large .vimrc or
'viminfo' setting. [...] Actually, on my own system the main slowdown on startup is cause by viminfo. Especially when
there are a lot of file names in it. Some syntax files load a bit slow too. More accurate measurements should be done to
pinpoint the real problems (anyone with a good profiler can have a try). I suspect that dynamic loading could actually
slowdown Vim startup. For example, if syntax highlighing is dynamically loaded, and you do ":syn on" in your .vimrc, it
would require another series of system calls to load the syntax stuff. That is guaranteed to be slower than including the
code in the executable.
The workaround
Vim can access the clipboard which allows the following workaround:
● Select the message with the mouse.
● Make sure that the option "guiclipboard" contains the flag 'a':
:set go+=a
● Import the text from the clipboard using the register '*', ie paste it into the current buffer with the command "*p.
● Edit the text.
● Copy the edited text into the clipboard, eg with :%"*y. (untested)
● Use CTRL-V to paste the text from the clipboard into the application.
CONTRA CORBA
● Yet more code. -> Bloat!
● Focus on code for "terminal editing" - not on support for other programs.
● The CORBA FAQ says that "Some applications, such as word processing, might not benefit from distribution at
all."
● Requires specification of CORBA interface.
● Requires to split Vim into components - and splitting away the syntax coloring is very difficult. Each component
then has to work before you can use it. break one component and you'll lose everything on top of it. Separating
Vim into components also means that you need to copy every component along to make it work. Forget about the
"Vim fits on a floppy" then.
● Definition of interfaces often change which makes Vim more dependant to these changes. More work will then
have to be put on those.
● You use CORBA when the components are spread acorss the network - does anyone want to "spread Vim's parts"
around?
● Components are no guarantee that the resulting programs are small (see Micro$soft Office).
● There is no standard for "editor" components so far, anyway.
Facts:
● Creation of a Vim ORB is required to allow Vim as an object for their applications.
Open Questions:
● Vim+CORBAR requires Vim to become an ORB. Code for this costs money. Will Vim then be freely available
still?
SEE ALSO:
● http://www.aurora-tech.com/CORBA-FAQ.htm
I know X11 applications are supposed to use resources, but I happen not
to like them. I would greatly appreciate putting in some effort to
avoid having to use them. A Vim user will be much happier when he can
do all settings for Vim in his vimrc file, instead of having to learn to
use resource files (I know I never fully understood them, can you
imagine what trouble a normal user would run into?).
URL: http://www.math.fu-berlin.de/~guckes/vim/deve.html
URL: http://www.vim.org/deve.html (mirror)
Created: Wed Nov 1 00:00:00 MET 1995
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Mon Jul 02 03:04:05 MEST 2001
VIM-6 releases:
2000
VIM-6 releases:
VIM-5 releases:
1999
Vim Milestones
DATE VERSION Milestone
2001 ??? ?? Vim 6.0 Folding (and more)
2000 Jul 09 Vim 6.0a Folding (and more)
1998 Feb 19 Vim 5.0 Syntax coloring/highlighting
1996 May 29 Vim 4.0 Graphical User Interface (Robert Webb).
1994 Aug 12 Vim 3.0 Support for multiple buffers and windows.
Port to Unix. Vim now competes with Vi. This was when Vim
1992 Vim 1.22
became Vi IMproved.
1991 Nov 2 Vim 1.14 First release (on Fred Fish disk #591).
URL: http://www.math.fu-berlin.de/~guckes/vim/hist.html
URL: http://www.vim.org/hist.html (mirror)
Created: Thu Jun 11 11:11:11 CEST 1998
Send feedback on this page to
Sven Guckes [email protected]
Vim 5.x for MacOS
News | System Requirement | Download the latest version | Work in progress | Known bugs |
Todo | Version history
This page tries to keep up to date all the information about the current status of the port of Vim
5.x to the Macintosh. Since I'm trying to work on the port, this page is awfully designed.
What is Vim?
Vim is a text-editor which prone the inverted main MacOS rule. With Vim everything that can
be done with the mouse can be done with the keyboard.
For more information please: VIM Homepage
❍ Sideeffect: a localized version of "menu.vim" and of the MacOS will give two
'Aide', 'Hilfe' or whatever menu.
● Adding Contextual Menu support.
❍ Coding: done
❍ Issues:
■ Unable to erase the backup file when Codewarrior display the errors in the
file
Requirements
● System 7.0 or better (tested on System 7.5, MacOS 8.1 and MacOS 9)
● 68020 or better (tested on 68040 and G3)
● Since the development is done on a G3, the performance on 68k may be sluggish.
Todo
● Vim features
❍ Toolbar
❍ Tearoff Menus
❍ Cursor Blinking
● MacOS integration
❍ Shortcut for menus
Tips'n'Tricks
● Monaco:h9, MPW:h9, Mishawaka:h9 and Courier:h10 co-exist wonderfully.
Mishawaka comes with Eudora
MPW comes with MPW and CodeWarrior
Links
Axel Kielhorn's Vim for MacOS Web Page
Vim Pages
Vim Pages:Macs
Vim Pages:Mailing List
Made on Macintosh with vim 5.x
From: Laurent Duperval <[email protected]> Newsgroups:
comp.editors,news.answers,comp.answers Subject: Vim Editor FAQ Date: 10 Feb 1998
02:29:18 GMT Message-ID: <[email protected]> Archive-name:
editor-faq/vim Posting-Frequency: monthly (second Monday) Last-modified: Mon Feb 9
21:27:50 EST 1998 URL: http://www.grafnetix.com/~laurent/vim/faq.html The Vim Editor
FAQ Created: Tue Mar 12 00:00:00 EST 1996 Last Updated: Date: 1998/02/08 18:03:21
Version: Revision: 1.25 Author: Laurent DUPERVAL <[email protected]> This Page:
<URL:http://www.grafnetix.com/~laurent/vim/faq.html> Vim Pages:
<URL:http://www.vim.org/> This article contains answers to Frequently Asked Questions
about the Vim editor. Questions marked by [CHANGED] are questions that have been modified
since the last release of the FAQ. Questions marked by [NEW] are new questions. The
following topics are addressed: Contents * Contents * 1 ABOUT THIS FAQ o 1.1 What
versions of Vim does this FAQ cover? o 1.2 Who maintains this FAQ? o 1.3 Why him? o 1.4
Can I add to it? o 1.5 What are the restrictions on this FAQ? o 1.6 [CHANGED]
Acknowledgements * 2 GENERAL INFORMATION o 2.1 What is Vim? o 2.2 Who wrote
Vim? o 2.3 Is Vim compatible with Vi? o 2.4 What are some of the improvements of Vim over
Vi? o 2.5 What are the improvements of Vim 4 over Vim 3.x? o 2.6 What are the improvements
of Vim 5.x over Vim 4.x? o 2.7 Is Vim free? * 3 RESOURCES o 3.1 [CHANGED] Where can
I learn more about Vim? o 3.2 Is there a mailing list available? o 3.3 Is there an archive
available for the Vim mailing list? o 3.4 [CHANGED] Where can I report bugs? o 3.5 Where
can the FAQ be found? o 3.6 What if I don't find an answer in this FAQ? * 4 AVAILABILITY
o 4.1 [CHANGED] What is the latest version of Vim? o 4.2 Where can I find the latest version
of Vim? o 4.3 [CHANGED] What platform does it run on? o 4.4 [CHANGED] What do I need
to compile and install Vim? * 5 TIPS AND TECHNIQUES o 5.1 How do I use the help files? o
5.2 Why is a backup file written even if I set nobackup? o 5.3 How can I keep Vim from
beeping all the time? o 5.4 How do I map the Tab key? o 5.5 How do I map the Esc key? o 5.6
How do I tell Vim where the helpfile is? o 5.7 How do I get back to the exact position within a
line I have marked with 'a'? o 5.8 How do I read in the output of a command? o 5.9 Why can't I
abbreviate ``'xy''? o 5.10 How do I jump to the beginning/end of the highlighted text? o 5.11
Why does completion of ``:set n'' not show negated settings, e.g., ``noautoindent''? Completion
of ``:set no'' seems to work. o 5.12 Is there a command to remove any or all digraphs? o 5.13
How do I use a spell checker with Vim? o 5.14 Can I copy the character above the cursor to the
current cursor position? o 5.15 How do I remove empty lines? o 5.16 How do I reduce a range
of empty lines into one line only? o 5.17 How can I paste large amounts of text between two
running sessions of Vim? o 5.18 Can I use compressed versions of the help files? o 5.19 How
come I can't set option ``xxxx''? o 5.20 How do I format a block of C code? o 5.21 How do I put
a command onto the command history without executing it? o 5.22 Why do I hear a beep (why
does my window flash) about 1 second after I hit the Escape key? o 5.23 How do I make the 'c'
and 's' commands display a '$' instead of deleting the characters I'm changing? o 5.24 How do I
add a line before each line with ``pattern'' in it? o 5.25 How can I delete the newline which is
followed by a given character, such as ``|''? o 5.26 How do I use the join command within a
range of lines that ends with ``*'' and begins with the previous ``|''? o 5.27 How do I map/unmap
an abbreviation or a map!ed key sequence? o 5.28 When I use my arrow keys, Vim changes
modes, inserts weird characters in my document but doesn't move the cursor properly. What's
going on? o 5.29 How do I ``auto-outdent'' some lines containing certain keywords (i.e.have
auto-indenting but towards the left margin instead of the right margin)? o 5.30 Is there a
repository for Vim macros? o 5.31 If I have a mapping/abbreviation whose ending is the
beginning of another mapping/abbreviation, how do I keep the first from expanding into the
second one? o 5.32 Modelines are cool but Vim's modeline support is too restrictive. How can I
improve it? o 5.33 How can I use different .vimrc settings for different types of files? o 5.34
How can I search for tags when running Vim over a telnet session? o 5.35 [NEW] I get errors
when trying to put scripts in my mappings. Why? o 5.36 [NEW] When I try to remove
mappings in my autocommands, Vim says my mappings don't exists. What's going on? * 6
DOS-, WINDOWS-, WIN32-SPECIFIC QUESTIONS o 6.1 Why does the Win32 version of
Vim update the screen so slowly on Windows 95? o 6.2 So if the Win32 version updates the
screen so slowly on Windows 95 and the 16-bit DOS version updates the screen quickly, why
would I want to run the Win32 version? o 6.3 And what about the 16-bit DOS version versus
the Win32 version on NT? o 6.4 Why can't I paste into Vim when running Windows 95? o 6.5
How do I type dead keys on Windows 95? o 6.6 How do I type dead keys on Windows NT? o
6.7 When will a real GUI version of Vim (gvim) for Win32 with scrollbars, menus, pasting
from the clipboard, and so on become available? o 6.8 On a Win32 machine, I'm using Vim to
edit a symbolically linked file on a Unix NFS file server. When I write the file, Vim does not
"write through" the symlink. Instead, it deletes the symbolic link and creates a new file in its
place. Why? o 6.9 How do I copy text from Windows applications to the DOS version of Vim?
o 6.10 Why does my Caps Lock affect all the keys characters for all the keys instead of just the
letters? o 6.11 How do I change Vim's window size in Windows? * 7 UNIX-SPECIFIC
QUESTIONS o 7.1 How do I turn off the message ``Thanks for flying Vim'' on Unix stations? o
7.2 How do I prevent <Ctrl-Z> from suspending Vim? o 7.3 How can I make Vim faster on a
Unix station? o 7.4 In Unix, how do I make Vim more colorful? 1 ABOUT THIS FAQ 1.1
What versions of Vim does this FAQ cover? At the time of its creation, version 4.0 was almost
complete (3.21 was already available) therefore the FAQ covers mainly vim4-specific issues.
But some answers may apply to Vim 3.0. There are no plans to make the FAQ ``backward
compatible''. ;-) In particular, in various parts of the FAQ, you will see mentions of ``:h subject''
to get help about a specific subject. Although the help command works in 3.0, you cannot give
it an argument. 1.2 Who maintains this FAQ? The current maintainer of this FAQ is Laurent
Duperval. I can be reached at <[email protected]>. Please insert the keyword NOTSPAM
in the Subject line of your message otherwise it may not reach me. 1.3 Why him? Well, I
volunteered. You could have done it too, had you volunteered before me. ;-) Besides, after
getting so much free and useful stuff off the 'Net, I decided to give something back in the form
of this FAQ. 1.4 Can I add to it? Sure. Just send your questions (and answers!) to
<[email protected]>. Comments and constructive criticism are always welcome. 1.5 What
are the restrictions on this FAQ? Disclaimer: This article is provided as is without any express
or implied warranties. While every effort has been taken to ensure the accuracy of the
information contained in this article, the author / maintainer / contributors (take your pick)
assume(s) no responsibility for errors or omissions, or for damages resulting from the use of the
information contained herein. This article is © Copyright 1996-1997 Laurent Duperval. You
may distribute it as you wish provided this copyright and the above disclaimer is also provided.
You may not sell it without express consent from the author. You may not distribute a modified
version of this article without express consent from the author. 1.6 [CHANGED]
Acknowledgements The following people have contributed (from near or far) to the answers in
this FAQ. Some of them may not even know about it. Bram Moolenar <[email protected]> Sven
Guckes <[email protected]> Robert Webb <[email protected]> George V. Reilly
<[email protected]> Tony Nugent <[email protected]> Ingolf Markhof
<[email protected]> Stan Brown <[email protected]> Raul Segura
Acevedo <[email protected]> Benjamin Elijah Griffin <[email protected]> Dr.
Charles Campbell <[email protected]> 2 GENERAL INFORMATION 2.1 What is
Vim? Vim stands for Vi IMproved. It used to be Vi IMitation, but there are so many
improvements that a name change was appropriate. Vim is a text editor which includes almost
all the commands from the Unix program ``Vi'' and a lot of new ones. It is very useful for
editing programs and other 7-bit or 8-bit ASCII text. All commands can be given with the
keyboard. This has the advantage that you can keep your fingers on the keyboard and your eyes
on the screen. For those who want it, there is mouse support and a GUI version with scrollbars
and menus. Vim is an editor, not a word processor. A word processor is used mainly to do
layout of text. This means positioning it, changing the way it appears on output. More often
than not, the final document is meant to be printed or typeset or what have you, in order to
present it in a pleasing manner to others. Examples of word processors are Microsoft Word,
WordPerfect, FrameMaker, and AmiPro. An editor is simply for entering text. Any typesetting
or laying out of the document is secondary. With an editor, one's main concern is entering text,
not making the text look good. Examples of editors other than Vim and Vi are Emacs, Crisp,
Brief, and xedit. 2.2 Who wrote Vim? Most of Vim was written by Bram Moolenar, with
contributions from too many people to mention here. Try ``:h credits'' for a complete list. Vim is
based on Stevie, worked on by Tim Thompson, Tony Andrews and G.R. (Fred) Walter. 2.3 Is
Vim compatible with Vi? Very. A special mode (``:set compatible'') makes Vim behave almost
exactly like Vi. 2.4 What are some of the improvements of Vim over Vi? Here is a short
summary. For more information, do ``:h diff''. Multi-level undo Allows you to set the number of
times you can undo your changes in a file buffer. You can also redo an undone change. Multiple
windows and buffers Each file can be displayed in its own window. You can move easily from
one window to another. Each file opened during a Vim session also has an associated buffer and
you can easily jump from one to the other. Repeat a series of commands. Vim has a facility
which allows you to record a sequence of typed characters and repeat them any number of
times. Flexible insert mode. Vim allows you to use the arrow keys while in insert mode to move
around in the file. No more hitting <Esc>, moving around, then hitting `i' or `a'. Visual mode.
You can highlight sections of text and execute operations on this section of text only. Block
operators Allow selection and highlighting of rectangular blocks of text in order do execute
specific operations on them. Online help system. You can easily find help on any aspect of
using Vim. Help is displayed in its own window. Command-line editing and history. History
allows you to use the arrow keys to repeat or search for a command that has already been typed.
Allows you to match the beginning of a command with the beginning of another similar
command in the history buffer. You can also edit a command to correct typos or change a few
values. Command line completion. Using the <Tab> key, you can complete commands, options,
filenames, etc. as needed. Horizontal scrolling. Long lines can be scrolled horizontally (with or
without the GUI). Text formatting. With two keystrokes, you can format large sections of text,
without the use of external programs. Edit-compile-edit speedup. You can compile within Vim
and automatically jump to the location of errors in the source code. Improved indenting for C
programs Vim gives you more control over how your C programs appear on screen. Searching
for words in include files Vim allows you to search for a match of the word under the cursor in
the current and included files. Word completion in Insert mode Vim can complete words while
you are typing, by matching the current word with other similar words in the file. Automatic
commands Commands automatically executed when reading or writing a file, jumping to
another buffer, etc. Viminfo Allows storing of the command line history, marks and registers in
a file to be read on startup. Mouse support The mouse is supported in an xterm and for
MS-DOS. It can be used to position the cursor, select the visual area, paste a register, etc.
Graphical User Interface (GUI) (Motif and Athena) You can use the GUI and have access to a
menu bar, scrollbar, etc. You can also define your own menus as well as do many operations
with the mouse instead of the keyboard. 2.5 What are the improvements of Vim 4 over Vim
3.x? Here is a list of some of the improvements of Vim 4 over Vim 3. For a complete list, do
``:h vim_40''. * New on-line help system * Command-line editing improved * Improved
indenting for C programs * Searching for words in include files * Word completion in Insert
mode * Automatic commands * Text objects * New Options * Support for editing one-line
paragraphs * Usage of key names * Viminfo * Compilation improvements * Tag support
improved * Improved (error) messages * Swap file * Mouse support * Graphical User Interface
(GUI) * Support for Windows 95 and NT * Vi compatibility improvements * And more! (As if
all that preceded wasn't reason enough to upgrade) 2.6 What are the improvements of Vim 5.x
over Vim 4.x? Vim 5.0 is not officially out yet, but it will have syntax highlighting! And a
command language! And much, much more! 2.7 Is Vim free? Vim is Charityware. There are no
restrictions on using or copying Vim, but the author encourages you to make a donation to
charity. A document explaining how to do so is included in the distribution. You are allowed to
include Vim on a CD-ROM but you should send the author a copy. Please try ``:h copying''. 3
RESOURCES 3.1 [CHANGED] Where can I learn more about Vim? A mailing list is available
for Vim. See the next question. Vim does not have a newsgroup of its own. But the appropriate
newsgroup to post to is comp.editors. There is a Vim home page available at
<URL:http://www.vim.org/> More information can be found in * Eli's Vim Page
<URL:http://www.netusa.net/~eli/src/vim.html> * The Vi Lovers Home Page
<URL:http://www.cs.vu.nl/~tmgil/vi.html> There is a reference card which is only valid for
version 5. It is available in Postscript by sending email to <[email protected]>.
Please specify a subject as follows: * ``send reference card'' for letter version * ``send reference
card a4'' for a4 version * ``send reference card tex'' for the original LaTeX source Oleg Raisky
<[email protected]> has created a reference guide for Vim and is available at
<URL:http://scisun.sci.ccny.cuny.edu/~olrcc/vim/>. There are versions available for A4 and US
Letter paper sizes. 3.2 Is there a mailing list available? There are three mailing lists for Vim
(description to follow). You can join any of the lists by sending an empty mail message to the
appropriate list handler. If for any reason, things don't work, contact <[email protected]>. *
To (un)subscribe to the Vim Help list mail vim-(un)[email protected] * To (un)subscribe to
the Vim Announcements list mail vim-announce-(un)[email protected] * To (un)subscribe to
the Vim Development list mail vim-dev-(un)[email protected] Each mailing list serves a
different purpose and you should not crosspost between them. This is a brief description of each
list: <[email protected]> For discussions about using existing versions of Vim: Useful mappings,
questions, answers, where to get a specific version, etc. <[email protected]> For discussions
about changing Vim: New features, porting, etc. <[email protected]> Announcements
about new versions of Vim and also beta-test versions and ports to different systems. No
discussions here, please. If you have a question about the usage of Vim then please post it to
comp.editorsor to the vim mailing list. Please note that if you send a message to a Vim mailing
list but are not subscribed, your message will be discarded. You must subscribe in order to send
mail to the mailing lists. Do not send mail to the mailing lists for subscription or unsubscription.
(The maintainer of the list hates that! So do the people subscribed to the lists.) 3.3 Is there an
archive available for the Vim mailing list? There is an archive available for the announcements
made on the vimannounce mailing list at
<URL:http://www.findmail.com/listsaver/vimannounce.html>. There is also a mail archive
available by FTP if you need to check out old messages sent to one of the other lists. They are
available at: <URL:ftp://ftp.ii.uib.no/pub/vim/mail-archive/vim/maillist.html>
<URL:ftp://ftp.ii.uib.no/pub/vim/mail-archive/vimdev/maillist.html>
<URL:ftp://ftp.ii.uib.no/pub/vim/mail-archive/vimannounce/maillist.html> 3.4 [CHANGED]
Where can I report bugs? Well, you don't need to because there are none. ;-) But on the off
chance that you may find an unexpected feature, you may send a description of it to the Vim
Developmentlist. Take a look at <URL:http://www.vim.org/deve.html#bugreport> to see what
type of information should be sent when making a bug report. There is also a script included
with newer versions of Vim, which can be used to create a bug report. We are looking for
someone to take over the tasks of our previous bug maintainer. If you are interested, send a
message to Bram <[email protected]>. If you have patches that you would like to submit for
approval and incorporation in future versions of Vim, you can send them to Bram
<[email protected]>. 3.5 Where can the FAQ be found? This FAQ will be posted on a (hopefully)
regular basis to the comp.editorsnewsgroup. The latest version can be found on
<URL:http://www.grafnetix.com/~laurent/vim/faq.html>. It will also be mirrored at
<URL:http://www.vim.org/faq/>. Eventually, it should make its way into news.answersand
rtfm.mit.edu. You can also find a searchable version of this and many more FAQs at the
Hypertext FAQ Archiveat <URL:http://www.landfield.com/faqs/>. 3.6 What if I don't find an
answer in this FAQ? This FAQ covers mainly Vim-specific questions. You may find more
information suitable for most Vi clones by reading the Vi FAQ. It is posted regularly on
comp.editors. You can also find a copy at
<URL:ftp://rtfm.mit.edu/pub/usenet-by-group/comp.editors>. Please note that although I
maintain the FAQ, I am not the best resource to answer questions about Vim. If you send a
question about using Vim diretly to me, 9 times out of 10 I will redirect you to the Vim mailing
listor to comp.editors. So you might as well send your questions directly there since you're
liable to get a more accurate and useful response than I could give you. 4 AVAILABILITY 4.1
[CHANGED] What is the latest version of Vim? The latest version is 4.6. The latest beta
release is 5.0w (as of February 8, 1998). 4.2 Where can I find the latest version of Vim? The
main archive for the latest versions of Vim is <URL:ftp://ftp.oce.nl/pub/vim> The directory
structure: /pub/vim/amiga /pub/vim/atari /pub/vim/beta-test /pub/vim/os2 /pub/vim/pc
/pub/vim/unix The latest public release can be found in the atari, amiga, os2, pc, and unix
directories. The latest beta-test versions can be found in the beta-test subdirectories. For a
complete and updated list of current FTP sites, please refer to
<URL:http://www.vim.org/dist.html>. 4.3 [CHANGED] What platform does it run on? Vim
should compile with no problems on most flavors of Unix and on DOS, OS/2, Ataris, Amigas,
Windows 95, Windows NT, BeOS and VMS. Binaries for other systems are also available. A
complete list of supported platforms and available binaries can be found at
<URL:http://www.vim.org/dist.html> 4.4 [CHANGED] What do I need to compile and install
Vim? Unless you are on a Unix station, you may not need to compile Vim since there are
various binaries available for Windows, Windows 95, Windows NT, DOS, OS/2 and Amiga
(please see <URL:http://www.vim.org/dist.html#binaries>. But if you need to compile it, you
must have a C compiler and a make utility. Most commercial C compilers come bundled with a
make utility, so if you've got one of those, you're in luck. If you need a compiler or if your make
utility doesn't like the Makefiles provided with Vim, you can get the GNU C compiler and
GNU make at <URL:ftp://prep.ai.mit/edu/pub/gnu> and its mirrors. At that same site, you can
also find sed, binutils, and other GNU tools (such as gzip) which can be useful on certain
systems. For DOS systems, you can look in <URL:ftp://ftp.coast.net/SimTel/msdos/>. If you
plan on compiling the GUI version of Vim under Unix, you must have some kind of widget
library. One of these three should suffice: Motif libraries These libraries are commercial but are
distributed with a number of operating systems. You can find out how to purchase it by going to
<URL:http://www.rdg.opengroup.org/>. Athena libraries This is a freely available widget set
which is included in the X11 distribution. This is a no frills library which implements a number
of widgets that are necessary when building a GUI. Various other similar libraries have been
built from the Athena widget set. These variations allow a 3D look and a NextStep look. These
variations are not part of the X11 distribution. The X11 distribution is available at
<URL:ftp://ftp.x.org/>. Lesstif This is a free Motif clone. It is available at
<URL:http://www.lesstif.org/>. 5 TIPS AND TECHNIQUES Note: This section contains
various macros written in Vim's macro language, called ``<> notation'' (you can find the
description by doing ``:h key_notation''). All macros should be entered as is in your .vimrc file
or on Vim's command line. You should even be able to cut and paste the information. This is a
short description of the language: * Any printable characters are typed directly, except
backslash and '<'. * A backslash is represented with ``\\'', double backslash. * A real '<' is
represented with ``\<''. * ``<key>'' means the special key typed. A few examples: <Esc> Escape
key <C-G> CTRL-G <Up> cursor up key <C-LeftMouse> Control- left mouse click <S-F11>
Shifted function key 11 <M-a> Meta- a ('a' with bit 8 set) <M-A> Meta- A ('A' with bit 8 set)
<t_kd> "kd" termcap entry (cursor down key) If you want to use this notation in Vim, you have
to remove the 'B' flag from 'cpoptions' and make sure the '<' flag is excluded. The default values
for cpoptions should work fine. :set cpo=ceFs For mapping, abbreviation and menu commands
you can then copy-paste the examples and use them directly. Or type them literally, including
the '<' and '>' characters. This does NOT work for other commands, like ``:set'' and ``:autocmd''!
Other tips, not appearing in this FAQ, can be found by doing ``:h tips''. 5.1 How do I use the
help files? Help can be found for all functions of Vim. In order to use it, use ``:h''. This will
bring you to the main help page. On that first page, you will find explanations on how to move
around. Basically, you move around in the help pages the same way you would in a read-only
document. You can jump to specific subjects by using tags. This can be done in two ways: *
Use the ``<Ctrl-]>'' command while standing on the name of a command or option. This only
works when the tag is a keyword. ``<Ctrl-LeftMouse>'' and ``g<LeftMouse>'' work just like
``<Ctrl-]>''. * use the ``:ta subject'' command. This works with all characters. Use ``<Ctrl-T>'' to
jump back to previous positions in the help files. Use ``:q'' to close the help window. If you
want to jump to a specific subject on the help pages, use ``:h {subject}''. If you don't know what
to look for, try ``:h index'' to get a list of all available subjects. Use the standard search keys to
locate the information you want. By version 6 or 7, we should have a search engine available.
;-) 5.2 Why is a backup file written even if I set nobackup? In order to keep Vim from writing a
backup, you must also do ``:set nowritebackup''. 5.3 How can I keep Vim from beeping all the
time? Well, you can use ``set noerrorbells" but it does not turn off the bell for all cases. It only
makes a difference for error messages; the bell will be always be used for a lot of errors without
a message (e.g., hitting <Esc> in Normal mode). If you want Vim to stop beeping then all you
need is ``:set vb'' which tries to do a screen flash rather than an audible beep. Some terminals
can't do screen flashes, but if yours does and you don't want it to flash or beep then use ``:set vb
t_vb=''. 5.4 How do I map the Tab key? :map <Tab> right-hand-side 5.5 How do I map the Esc
key? On some keyboards the escape key is not placed very well. It's either part of the numeric
block or it can be a small button (as with some Macintosh keyboards). But do not despair -
make your own escape key! You can map one of the commands keys you do not need to Esc.
Example: map CTRL-O to ESC: :map <C-O> <Esc> 5.6 How do I tell Vim where the helpfile
is? To tell Vim where to find the help file, ``:set helpfile'' to the correct value, i.e., including the
full path. As with most options you can abbreviate ``helpfile'' to ``hf''. On the other hand, if your
VIM environment variable points to the directory containing the help file, vim will find the help
file with no need to ``:set hf=''. 5.7 How do I get back to the exact position within a line I have
marked with 'a'? Use ```a'' (that's a backtick!). If the backtick is awkwardly placed on your
keyboard, the following maping may be useful to you: map ' ` 5.8 How do I read in the output
of a command? Use ``:r!command''. 5.9 Why can't I abbreviate ``'xy''? The abbreviation consists
of a non-id character followed by two id characters, which does not satisfy either category of a
``full-id''. However, ``_ps'' and ``'p'' will work. 5.10 How do I jump to the beginning/end of the
highlighted text? The command 'o' will jump to the beginning/end of the highlighted text. 5.11
Why does completion of ``:set n'' not show negated settings, e.g., ``noautoindent''? Completion
of ``:set no'' seems to work. The thing is that the ``no'' is not actually part of the option's name;
the name comes after that. So after ``no'', Vim knows to complete any boolean setting name
(starts the completion just after the ``no'', which is not part of the name). After ``n'', Vim will
complete all setting names starting with ``n''. It would be a bummer if you wanted to complete
``number'', but had to wade through all the boolean option names with ``no'' prepended too. 5.12
Is there a command to remove any or all digraphs? No. The digraphs table is defined at compile
time. You can only add new ones. Adding a command to remove digraphs is on the todo list.
5.13 How do I use a spell checker with Vim? You can call a non-interactive spell checker from
Vim without a problem. A function to look up a word is included with the command ``K''. So
what you do is get such a spell checker, then you issue the command ``:set keywordprg=ispell'',
and then hit ``K'' on the word you want to look up, i.e., check. If you need to give options to
your spell checker command, escape all spaces with a backslash. If you need to use an
interactive spell checker and are working with Unix, you can try this approach proposed by Ives
Aerts <[email protected]>: noremap ;ispell :%! ispell-filter<CR><C-L> where ispell-filter is
the following script: #!/bin/sh # # This little script can be used to run ispell on stdin, returning
the result # through stdout. # It can be used from VI like this (or map it to a key sequence): #
:%! ~/bin/ispell-filter # cat > /tmp/tmp.$$ ispell $* /tmp/tmp.$$ < /dev/tty > /dev/tty cat
/tmp/tmp.$$ rm -f /tmp/tmp.$$ or this macro proposed by Dr. Charles E. Campbell Jr.
<[email protected]>: map #fi :w<CR>:!ispell %<CR>:e %<CR> 5.14 Can I copy the
character above the cursor to the current cursor position? In Insert mode, you can copy the
character above the cursor to the current cursor position by typing <Ctrl-Y>. The same can be
done with the characters below the cursor by using <Ctrl-E>. This is neat when you need to
duplicate partial lines without going through the process of yanking a line and deleting the
unwanted part. 5.15 How do I remove empty lines? To remove all empty lines do ``:g/^$/d''.
``:g/[ <Tab>]*$/d'' deletes lines that aren't blank but look it, too. 5.16 How do I reduce a range
of empty lines into one line only? You can try ``:v/./.,/./-1join''. Note that this will give an error
message if the empty lines are at the end of the file. To correct this, use the following mapping
instead: map _b GoZ<Esc>:g/^[ <Tab>]*$/,/[^ <Tab>]/-j<CR>Gdd 5.17 How can I paste large
amounts of text between two running sessions of Vim? If you are using the GUI version of
Vim, with the Motif or Athena interface, you can actually cut and paste between the two, and
text will be copied exactly; that is, tabs will not change into spaces, and if you copy a
rectangular block, then that is what you will paste too! Otherwise, in a terminal Vim, use these
mappings: " _Y: Yank the highlighted block of text (or a single line) to a tmp file. " _P: Put the
text yanked with \_Y (possibly in another invocation of Vim). " nmap _Y :.w! ~/.vi_tmp<CR>
vmap _Y :w! ~/.vi_tmp<CR> nmap _P :r ~/.vi_tmp<CR> Now you just highlight the area you
want to copy with ``V'' etc, and yank it with ``_Y''. Then you can paste it in another Vim with
``_P''. 5.18 Can I use compressed versions of the help files? For those that are really short on
disk space, you can compress the help files and still be able to view them with Vim. This
example assumes you have gzip on your system. You do have it, don't you? :-) If not, you will
need to adapt it to work with a different compression utility. 1. Compress all the help files:
``gzip doc/*.txt''. 2. Edit doc/vim_tags (doc/tags in 5.0) and do :%s=\.txt<Tab>/=.txt.gz<Tab>/=
3. Add these lines to your .vimrc: set helpfile=<dirname>/vim_help.txt.gz autocmd
BufReadPost *.txt.gz set bin | '[,']!gunzip autocmd BufReadPost *.txt.gz set nobin set
cmdheight=2 Where ``dirname'' is the directory where the help files are. If you already have
included autocommands to edit ``.gz'' files you should omit the two ``autocmd'' lines. Note that
you must ``set nocompatible'' for this to work in Vim 5.0. 5.19 How come I can't set option
``xxxx''? Some options are compiled into Vim. If you want to enable these options, then you
must modify the feature.h file. You can see what compile-time options are available by looking
at the version number (:ver). It will give you something like this: Compiled with (+) or without
(-): +autocmd +builtin_terms +cindent -compatible +digraphs -emacs_tags +fork() -GUI
+insert_expand -langmap +lispindent -rightleft +smartindent -terminfo +viminfo +writebackup
+X11 As the example shows, all options compiled into the Vim binary are preceded by a '+'. All
options that are not compiled in are preceded by a '-'. All options that do not appear in this list
do not need to be compiled in. 5.20 How do I format a block of C code? To format C code, use
= instead of Q. Try ``:h C_indenting'' to get more information on controlling the way your code
is formatted. 5.21 How do I put a command onto the command history without executing it?
You need only end the input with <ESC> (not <Ctrl-V><Esc>). 5.22 Why do I hear a beep
(why does my window flash) about 1 second after I hit the Escape key? This is normal
behavior. If your window flashes, then you've got the visual bell on. Otherwise, you should hear
a beep. Vim (and most, if not all, other implementations of Vi) needs a timeout to tell the
difference between a simple escape and, say, a cursor key sequence. When you press a key in
normal mode (and even in insert mode) and that key is the beginning of a mapping, Vim waits a
certain amount of time to see if the rest of the mapping sequence follows. If the mapping
sequence is completed before a given timeout period, the mapping for that sequence of keys is
applied. If you interrupt the mapping, the normal actions associated with the keys are executed.
For example, if you have a mapping defined as ``:imap vvv Vim is great!!'' and you type ``vvv''
quickly, the ``Vim is great!!'' will be inserted into your text. But if you type ``vv v'' then that is
what will put into your text. This is also true if you type ``vvv'' too slowly where ``too slowly''
is longer than the value for the timeout option. Setting the timeout option to a larger value can
help alleviate problems that appear when using function keys over a slow line. Do ``:h timeout''
for more information on using this option and its cohorts. 5.23 How do I make the 'c' and 's'
commands display a '$' instead of deleting the characters I'm changing? Add ``:set
cpoptions=ces$'' to your .vimrc. Vi-compatible behavior can be controlled like this. Do ``:help
cpoptions'' for more information. 5.24 How do I add a line before each line with ``pattern'' in it?
1. Yank the line using Y 2. Insert the line with ``:g/pattern/put!'' 5.25 How can I delete the
newline which is followed by a given character, such as ``|''? Look at this problem this way: If
there is a newline before the character then the character is the first character of the next line,
i.e., it follows the start-of-line meta character (^). So the command to use is to look globally for
all lines starting with the given character and the command to use on these lines is ``go back
one line'' and ``join'' which will remove the next newline. The resulting command is: :g/^|/-1join
5.26 How do I use the join command within a range of lines that ends with ``*'' and begins with
the previous ``|''? :?^|?,/*$/join 5.27 How do I map/unmap an abbreviation or a map!ed key
sequence? In either case, ``:set paste'' will do the trick. Use ``:set nopaste'' to return to normal.
For map!ed key sequences, you have a these tricks also; * After typing the first key of the key
sequence, pause about 1 second before typing the rest of the sequence. * Type <Ctrl-V> before
typing the first key in the key sequence. Normally, you shouldn't need these tricks. When
``:unmap'' finds an argument that is not a ``from'' part, it looks for a matching ``to'' part and
unmaps that one. 5.28 When I use my arrow keys, Vim changes modes, inserts weird characters
in my document but doesn't move the cursor properly. What's going on? There are a couple of
things that could be going on: either you are using Vim over a slow connection or Vim doesn't
understand the key sequence that your keyboard is generating. If you are working over a slow
connection (such as a 2400 bps modem), you can try to set timeout or ttimeout. These options,
combined with timeoutlen and ttimeoutlen, may fix the problem. Do ``:h timeout'' and ``:h
timeoutlen'' for a better description on how to use them. The preceding procedure will not work
correctly if your terminal sends key codes that Vim does not understand. In this situation, your
best option is to map your key sequence to a matching cursor movement command and save
these mappings in a file. You can then ``:source'' the file whenever you work from that terminal.
5.29 How do I ``auto-outdent'' some lines containing certain keywords (i.e.have auto-indenting
but towards the left margin instead of the right margin)? For example (make sure you adapt the
example to your personal needs): for k=1:10, stuff .. end; ^^^ This word marks the end of a loop
and I'd like it to be automatically outdented to the same column as the word for. The following
macro will do this (from Raul Segura Acevedo <[email protected]>): :iab end;
<C-D>end; This abbreviation takes effect when you type a non-keyword character after it (``;'',
``!'', space, tab, <Esc>, <CR>, etc). You can load this macro automatically using the following
autocommands: au! BufEnter *.f,*.ff iab end; <C-D>end; au! BufLeave *.f,*.ff iunab end; 5.30
Is there a repository for Vim macros? As a matter of fact, there is. You can find the latest
versions of contributed macros at <URL:http://www.grafnetix.com/~laurent/vim/macros.html>.
At the time this version of the FAQ was updated, the following macros were available: * A file
browser * Some macros to edit HTML code * Macros to deal with numbered lists * A Tic Tac
Toe game 5.31 If I have a mapping/abbreviation whose ending is the beginning of another
mapping/abbreviation, how do I keep the first from expanding into the second one? Instead of
using :map lhs rhs, use :noremap lhs rhs. For abbreviations, use noreabbrev lhs rhs. The ``nore''
prefix prevents the mapping or abbreviation from being expanded again. You must be using
version 4.5 or greater. 5.32 Modelines are cool but Vim's modeline support is too restrictive.
How can I improve it? >From Benjamin Elijah Griffin <[email protected]>: Vim modelines are
crippled to reduce the security hazards of modelines. For much closer to vi modeline behavior
(with the major risks involved) you can use Benjamin Elijah Griffin's modeline autocmd
system. You can find it at <URL:http://www.netusa.net/~eli/src/modeline.html>. 5.33 How can
I use different .vimrc settings for different types of files? There are a few ways to do this. All of
them involve the use of autocommands. Try ``:h autocommand'' for more information. * You
can define autocommands which do everything for you in your .vimrc file: au!BufRead
*.c,*.cc,*.h set fo=croq cin noic au!BufEnter *.c,*.cc,*.h ab #i #include au BufEnter
*.c,*.cc,*.h ab #d #define au BufEnter *.c,*.cc,*.h map _hello_world :"Hello World"<CR> au
BufEnter *.c,*.cc,*.h normal _hello_world au!BufLeave *.c,*.cc,*.h unab #i | unab #d au
BufLeave *.c,*.cc,*.h unmap _hello_world The ``!'' is used just in the first autocommand for
each event (BufEnter, BufLeave, etc.). * Or you can define one autocommand for each file type
which loads a specific .vimrc file containing the settings you require. autocmd BufNewFile
*.tex read ~/.vim/texmodel autocmd BufEnter *.tex source ~/.vim/texrc autocmd BufLeave
*.tex source ~/.vim/notexrc Remember that all settings that you modify in a BufEnter or
BufNewFile event may need to be unset with a corresponding BufLeave event. By using a first
file pattern with a value of ``*'', you can define default settings for all your files. The
``mapclear'' and ``abclear'' commands can clear all your mappings or abbreviations if needed.
5.34 How can I search for tags when running Vim over a telnet session? Darren Hiebert
<[email protected]> says: Ctrl-] is the the default telnet escape key. Most version of telnet
allow changing or disabling the default escape key. See the man page. If possible, try to use
``rsh'' instead of ``telnet''. It will avoid this problem. 5.35 [NEW] I get errors when trying to put
scripts in my mappings. Why? This is a tricky one which deals with the way bars are treated in
mappings. For example, if you have something like: nmap <f5> :if has("syntax_items") | syntax
off | else | syntax on | endif Vim treats the line as: nmap <f5> :if has("syntax_items") and then
tries syntax off (which is ok), then tries else (which now has no matching if). This parsing
occurs because |'s are used as command separators in Vim. Since those |'s are really part of the
command, they should be replaced by <Bar> in your mapping, to yied something like (on one
line only): nmap <f5> :if has("syntax_items") <Bar> syntax off <Bar> else <Bar> syntax on
<Bar> endif<CR> Thank you to <Dr. Charles Campbell >[email protected] far the
explanation. 5.36 [NEW] When I try to remove mappings in my autocommands, Vim says my
mappings don't exists. What's going on? The explanation for this phenomenon is similar to that
of the previous question. Basically, when unmapping your commands, you must not leave any
spaces after the |'s separating the unmap keyword. For example, using the following
autocommand: au BufRead *.c map <C-N>:cn<CR> | map <C-P>:cp<CR> This will fail to
unmap <C-P>: au BufLeave *.c unmap <C-N> | unmap <C-P> But this will succeed: au
BufLeave *.c unmap <C-N> |unmap <C-P> 6 DOS-, WINDOWS-, WIN32-SPECIFIC
QUESTIONS 6.1 Why does the Win32 version of Vim update the screen so slowly on
Windows 95? The support for Win32 console mode applications is very buggy in Win95. For
some unknown reason, the screen updates very slowly when Vim is run at one of the standard
resolutions (80x25, 80x43, or 80x50) and the 16-bit DOS version updates the screen much more
quickly than the Win32 version. However, if the screen is set to some other resolution, such as
by ``:set columns=100'' or ``:set lines=40'', screen updating becomes about as fast as it is with
the 16-bit version. Changing the screen resolution makes updates faster, but it brings problems
with it of its own. External commands (e.g., ``:!dir'') can cause Vim to freeze when the screen is
set to a non-standard resolution, particularly when columns is not equal to 80. It is not possible
for Vim to reliably set the screen resolution back to the value it had upon startup before running
external commands, so if you change the number of lines or columns, be very, very careful. In
fact, Vim will not allow you to execute external commands when columns is not equal to 80,
because it is so likely to freeze up afterwards. The maintainer of the Win32 port, George V.
Reilly, says he's almost done with the GUI version of Vim. When it is completed, it should fix
all these problems. In his own words: My position at this point is that the console mode APIs
are irredeemably broken on Windows 95 and that I'm no longer interested in trying to come up
with workarounds and hacks when my limited time is better spent trying to get an alpha of the
Windows GUI version out the door. I strongly urge you to use one of the three standard
resolutions (80x25, 80x43, or 80x50) and wait for the GUI version. Or upgrade to NT, where
the console mode stuff works. Sorry. None of the above applies on Windows NT. Screen
updates are fast, no matter how many lines or columns the window is set to, and external
commands will not cause Vim to freeze. 6.2 So if the Win32 version updates the screen so
slowly on Windows 95 and the 16-bit DOS version updates the screen quickly, why would I
want to run the Win32 version? Firstly, the Win32 version isn't that slow, especially when the
screen is set to some non-standard number of lines or columns. Secondly, the 16-bit DOS
version has some severe limitations: it can't edit big files and it doesn't know about long
filenames. The Win32 version doesn't have these limitations and it's faster overall (the same is
true for the 32-bit DJGPP DOS version of Vim). The Win32 version is smarter about handling
the screen, the mouse, and the keyboard than the DJGPP version is. 6.3 And what about the
16-bit DOS version versus the Win32 version on NT? There are no good reasons to run the
16-bit DOS version on NT. The Win32 version updates the screen just as fast as the 16-bit
version when running on NT. All of the above disadvantages apply. Finally, 16-bit DOS
applications can take a long time to start up and will run more slowly. On non-Intel NT
platforms, the DOS version is almost unusably slow, because it runs on top of an 80x86
emulator. 6.4 Why can't I paste into Vim when running Windows 95? In the properties dialog
box for the MS-DOS window, go to ``MS-DOS Prompt/Misc/Fast pasting'' and make sure that
it is not checked. You should also do ``:set paste'' in VIM to avoid unexpected effects. See ``:h
paste''. Also, in the Properties dialog's ``Misc'' tab, you want to make sure that ``Mouse
Exclusive Mode'' is not checked. If you want to use the mouse in the Vim way, also make sure
``Mouse Quick Edit'' is not checked. (You can still cut and paste with the mouse by using the
toolbar buttons.) 6.5 How do I type dead keys on Windows 95? (A dead key is an accent key,
such as acute, grave, or umlaut, that doesn't produce a character by itself, but when followed by
another key, produces an accented character, such as a-acute (á), e-grave (è), u-umlaut (ü),
n-tilde (ñ), and so on. Very useful for most European languages. English-language keyboard
layouts don't use dead keys, as far as we know.) You don't. The console mode input routines
simply do not work correctly in Windows 95, and we have not been able to work around them.
In the words of a senior developer at Microsoft: Win95 console support has always been and
will always be flaky. The flakiness is unavoidable because we are stuck between the world of
MS-DOS keyboard TSRs like KEYB (which wants to cook the data; important for
international) and the world of Win32. So keys that don't "exist" in MS-DOS land (like dead
keys) have a very tenuous existence in Win32 console land. Keys that act differently between
MS-DOS land and Win32 console land (like capslock) will act flaky. Don't even mention the
problems with multiple language keyboard layouts... You may be able to fashion some sort of
workaround with the digraphs mechanism. Alternatively, you can try one of the DOS versions,
where deadkeys do work. 6.6 How do I type dead keys on Windows NT? Dead keys work on
NT. Just type them as you would in any other application. 6.7 When will a real GUI version of
Vim (gvim) for Win32 with scrollbars, menus, pasting from the clipboard, and so on become
available? Work has begun on a GUI version of Vim for Win32. Apart from the features you
might expect in gvim, it is expected that this version will also be able to handle dead keys
correctly and that the problems with external commands will be a thing of the past. 6.8 On a
Win32 machine, I'm using Vim to edit a symbolically linked file on a Unix NFS file server.
When I write the file, Vim does not "write through" the symlink. Instead, it deletes the symbolic
link and creates a new file in its place. Why? On Unix, Vim is prepared for links (symbolic or
hard). A backup copy of the original file is made and then the original file is overwritten. This
assures that all properties of the file remain the same. On non-Unix systems, the original file is
renamed and a new file is written. Only the protection bits are set like the original file.
However, this doesn't work properly when working on an NFS-mounted file system where links
and other things exist. The only way to fix this in the current version is not making a backup
file, by ``:set nobackup nowritebackup''. 6.9 How do I copy text from Windows applications to
the DOS version of Vim? >From John Velman, <[email protected]>: 1. To get Vim to
run in a window, instead of full screen, press <Alt+Enter>. This toggles back and forth between
full screen and a DOS window. 2. Issue the command ``:set paste''. 3. To paste something
*into* Vim, put Vim in insert mode. 4. Put the text you want to paste on the windows clipboard.
5. Click the control box in the upper left of the Vim window. (This looks like a big minus sign).
If you don't want to use the mouse, you can get this with <Alt+Spacebar>. 6. On the resulting
dropdown menu choose 'Edit'. 7. On the child dropdown menu choose 'Paste' 8. Issue the
command ``:set nopaste''. To copy something from the Vim window to the clipboard, 1. Select
the control box to get the control drop down menu. 2. Select 'Edit'. 3. Select 'Mark'. 4. Using
either the the keys or the mouse, select the part of the Vim window that you want to copy. To
use the keys, use the arrow keys, and hold down shift to extend the selection. 5. When you've
completed your selection, press ``<Enter>.'' The selection is now in the Windows clipboard. By
the way, this can be any rectangular selection, for example columns 4-25 in rows 7-10. It can
include anything in the Vim window: the output of a ``:!dir'', for example. >From Stan Brown
<[email protected]>: In Windows 95, you can use a simpler procedure, which works even
when you're using the mouse in the Vim way inside the Vim window (see question 6.4). To
paste into Vim, put Vim in insert mode and click the Paste button on the Vim window's toolbar.
(Depending on your setup, you may want to use ``:set paste'' before and ``:set nopaste'' after
pasting.) To copy from Vim to the clipboard, click the Mark button (the square) on the toolbar,
highlight the desired text with the mouse, and click the Copy button. 6.10 Why does my Caps
Lock affect all the keys characters for all the keys instead of just the letters? It's actually caused
by Windows 95. When CapsLock is down, it acts just as if Shift were being held down:
everything gets shifted, not just the alphabetical keys. 6.11 How do I change Vim's window size
in Windows? If ``:set lines=##'' doesn't work for you, then you should use the ``:mode''
command. Look up ``:h :mode'' for more info. 7 UNIX-SPECIFIC QUESTIONS 7.1 How do I
turn off the message ``Thanks for flying Vim'' on Unix stations? When using Vim in an xterm it
renames the title of that window to ``Thanks for flying Vim'' on exit. Use ``:set notitle'' to stop
this behavior. 7.2 How do I prevent <Ctrl-Z> from suspending Vim? Map <Ctrl-Z> to prevent
the suspending. Here are some suggestions: 1. Make <Ctrl-Z> do nothing: map <C-Z>
<C-V><C-V> 2. Make <Ctrl-Z> start a shell: :map <C-Z> :shell<CR> 3. Make <Ctrl-Z> give
an error message: :map <C-Z> :"suspending disabled<CR> For the last example, the double
quote is necessary in order to keep the message on the status line. 7.3 How can I make Vim
faster on a Unix station? The GUI support in Vim 4.0 can slow down the startup time
noticeably. Until Vim supports dynamic loading, you can speed up the startup time by
compiling two different versions of Vim: one with the GUI and one without the GUI and install
both. Make sure you remove the link from $bindir/gvim to $bindir/vim when installing the GUI
version, though. If screen updating is your problem, you can run Vim in screen. screen is an
ascii terminal multiplexer. The latest version can be found at
<URL:ftp://ftp.uni-erlangen.de:/pub/utilities/screen>. 7.4 In Unix, how do I make Vim more
colorful? You can change some termcap values to send to the screen the proper codes to change
some colors (providing your terminal supports color). Here are some examples of how to do this
if you do ``:h unix'' but it seems as though they don't work all that well. But they help to
understand what has to be done: :set t_me=<Esc>[0;1;36m " normal mode (undoes t_mr and
t_md) :set t_mr=<Esc>[0;1;33;44m " reverse (invert) mode :set t_md=<Esc>[1;33;41m " bold
mode :set t_se=<Esc>[1;36;40m " standout end :set t_so=<Esc>[1;32;45m " standout mode :set
t_ue=<Esc>[0;1;36m " underline end :set t_us=<Esc>[1;32m " underline mode start Quoting
Tony Nugent: You can do some interesting things by putting ansi colour sequences into those
capabilities. What's given here are just examples, and some combinations don't work very well.
You need to discover for yourself a configuration that works. For example, end-modes need to
switch everything back to normal as well as turn things off. Just load ~/.vimrc, play around with
the values, save it and then see what it looks like by sourcing it (:so ~/.vimrc). Don't forget to do
things like ``:/<Ctrl-D>'' and ``:map'' to see all the different effects. And don't forget about the
``:set highlight='' string to fine-tune how the different capabilities are used. BTW, something
like this also works for DOS and Win32 Vims! So it should also work well with windows or
any ansi- and vt100- compatible terminal mode capable of displaying colours (which includes
all colour pc's). It doesn't work so well in plain old xterm's (YMMV - your milage may vary).
You can find a list of terminal codes here:
<URL:http://www.cs.utk.edu/~shuford/terminal_index.html>
<URL:ftp://cs.utk.edu/pub/shuford/terminal/>
<URL:ftp://gatekeeper.dec.com/pub/DEC/termcaps> -- Laurent Duperval, Vim FAQ
Maintainer <[email protected]> Vim Pages: http://www.vim.org/ Vim Mailing List:
[email protected] Vim FAQ: http://www.vim.org/faq/ Vim FAQ Home:
http://www.grafnetix.com/~laurent/vim/faq.html
ʲôÊÇVim?
Ò»¸ö6K³¤µÄ˵Ã÷
»ñµÃVim:
ÓëviÏà±È, Vim ´æÔÚÓÚÐí¶àƽ̨ÉÏ, ²¢ÇÒÔöÌíÁËÐí¶à¹¦ÄÜ. (Ïê¼û
http://www.vim.org/doc/vi.diff.txt). Vim ºÍ¾ø´ó¶àÊýµÄViÃüÁî¼æÈÝ - Vi µÄBUG³ýÍâ:-)
²Ù×÷ϵͳ:
ÔÚÐí¶à²Ù×÷ϵͳÉ϶¼¿ÉÒԵõ½Vim: AmigaOS, Atari MiNT, BeOS, DOS, MacOS, NextStep,
OS/2, OSF, RiscOS, SGI, UNIX, VMS, WIn16 + Win32 (Windows95/98/00/NT) - ÓÈÆäÊÇ
FreeBSD and Linux. :-)
°æȨÐÅÏ¢:
°æȨ¹éVimµÄÖ÷Òª×÷ÕߺÍά»¤ÕßBram MoolenaarËùÓÐ<[email protected]>. Vim ÊÇ"´ÈÉÆÈí¼þ".
Òâ˼ÊǹÄÀøÄã¾èÖúÎڸɴïµÄ¹Â¶ù(Ïê¼û ":help uganda").
Ô´´úÂë:
Vim ÊÇ¿ª·ÅÔ´´úÂëÈí¼þ. »¶Ó-´ó¼Ò°ïæ¸Ä½ø.
=== ÌØÉ«:
³õѧÕߵıà¼-Æ÷ - Óû§ÓѺÃ:
Ïà±ÈVi, Vim¶Ô³õѧÕßÀ´µÄÈÝÒ׶àÁË. ÕâÒª¹é¹¦ÓÚÆäÏ꾡µÄÔÚÏß°ïÖú, "undo" ºÍ "redo"
ÃüÁî (ÄãÓÀÔ¶²»Óõ£ÐÄ·¸´í - Ö»Òª»áÓÃundo+redo!),
ÒÔ¼°¶ÔÊó±êµÄÖ§³ÖºÍ¿ÉÒÔÅäÖõÄͼ±ê¼°²Ëµ¥(GUI).
×Ö·û±àÂëºÍÖÕ¶Ë:
VimÖ§³Öiso-latin1×Ö·û¼¯ºÍtermcap(Vi²»ÄÜÕýÈ·µØÖ§³Ö)
×Ö·ûºÍÓïÑÔ:
Vim Ö§³Ö´ÓÓÒÏò×ó±à¼-(ÀýÈç°¢À-²®ÎÄ, Farsi, Ï£²®À´ÎÄ) ºÍ¶à×Ö½ÚÎÄ×Ö,
±ÈÈçÄÇЩʹÓÃͼÐÎ×Ö·ûµÄÓïÑÔ,Æä×Ö·ûÓöà¸ö×Ö½Ú±íʾ. ±ÈÈçÖÐÎÄ, ÈÕÎÄ, º«ÎÄ,
(´Ó¼¼Êõ½Ç¶ÈÉϽ², VimÖ§³ÖUTF-8ºÍUnicode.)
Îı¾¸ñʽ»¯ºÍVisualģʽ:
ÔÚVimÖÐ, Äã¿ÉÒÔ"¿ÉÊÓµØ"Ñ¡È¡Îı¾(¸ßÁÁÏÔʾ). È»ºó¶ÔËùÑ¡Îı¾½øÐвÙ×÷, ÀýÈ翽±´,
ɾ³ý, Ìæ»», ×óÓÒÒƶ¯, ´óСд±ä»», »ò±£³ÖǶÈë¸ñʽµÄ¸ñʽ»¯. Vim
ÔÊÐí¶Ô³¤·½ÐεÄÎı¾¿é½øÐÐÑ¡ÔñºÍ²Ù×÷.
ÃüÁȫ:
Vim °üº¬²¹È«ÄãµÄÊäÈëµÄÃüÁî - ÎÞÂÛÄãÊäÈëµÄÊÇÃüÁî, ÎļþÃû, »¹Êǵ¥´Ê.
×Ô¶¯ÃüÁî:
Vim »¹ÓÐÓÃÓÚ×Ô¶¯Ö´ÐÐÖ¸ÁîµÄ"×Ô¶¯"ÃüÁî. (ÀýÈç ×Ô¶¯½âѹËõÎļþ.)
(·¢Ò»¸öÒôµÄ)¶þºÏ×Öĸ(Diagraph)ÊäÈë:
ÔÚVimÖÐ, Äã¿ÉÒÔÓÃÁ½¸ö×Ö·ûµÄ×éºÍÊäÈëÒ»¸öÌØÊâ×Ö·û(ÀýÈç`ºÍeµÄ×éºÏÉú³É¨¨-
²¢ÔÊÐíÄ㶨ÒåÆäËû×éºÏ.
Îļþ¸ñʽʶ±ðºÍת»»:
Vim×Ô¶¯Ê¶±ðÎļþµÄÀàÐÍ(DOS, Mac, Unix)²¢ÔÊÐíÒÔ²»Í¬¸ñʽ´æÅÌ -
²»ÓÃÔÚWindowsÉÏÔÙ×÷unix2dosÁË!
ÀúÊ·:
¶ÔÓÚÃüÁîºÍ²éÕÒ²Ù×÷, Vim»¹ÓÐÀúÊ·»úÖÆ.
Äã¿ÉÒÔ°ÑÒÔÇ°Ö´ÐйýµÄÃüÁî»ò²éÕÒģʽµ÷³öÀ´½øÐбà¼-.
ºê¼ÖÆ:
VimÔÊÐí"¼ÖÆ"ÄãµÄ±à¼-²Ù×÷, ÒÔ±ã¶ÔÖظ´µÄÈÎÎñ½øÐÐ"ÖØ·Å".
ÄÚ´æÏÞÖÆ:
VimÖÐÐг¤ºÍ»º³åÇø³¤¶ÈµÄÉÏÏÞ¶¼±È´«Í³Vi¸ß³öÐí¶à.
¶à»º³åÇøºÍÇзִ°¿Ú:
VimÔÊÐíͬʱ±à¼-¶à¸ö»º³åÇø¶øÇÒÄã¿ÉÒÔ°ÑÆÁÄ»·Ö¸î³ÉÐí¶à×Ó´°¿Ú(ˮƽºÍÊúÖ±).
ÕâÑùÄã¾Í¿ÉÒÔ¿´µ½Ðí¶àÎļþ»ò¼¸¸öÎļþµÄÐí¶à²¿·Ö.
ÃüÁîµÄÊý×Öǰ׺:
Ïà±ÈVi, VimÔÊÐí¸ü¶àµÄÃüÁ´øÊý×Öǰ׺(ÀýÈç "put"ÃüÁî).
ÔËÐÐʱÎļþ(°ïÖúºÍÓï·¨Îļþ):
Vim´øÓÐ70¸ö°ïÖúÎļþ. ËüÃÇ°üÀ¨Á˱à¼-µÄ·½·½ÃæÃæ;
ÆäÖÐһЩÎļþÊÇÒò²Ù×÷ϵͳ²»Í¬¶øÒìµÄ.
½Å±¾:
Vim °üº¬Ò»¸öÄÚÖõĽű¾ÓïÑÔÒÔ±ãÓÚÀ¨³ä¹¦ÄÜ.
Æ«ÒƲéÑ°:
Vim ÔÊÐí²éÑ°ÃüÁ´øÆ«ÒÆÁ¿, ÕâÑùÄã¾ÍÄܰѹâ±êÖ±½Ó·ÅÔÚÕÒµ½µÄÎı¾ºóÃæ.
¹ý³Ì(session)»Ö¸´:
VimÔÊÐí½«Ò»¸ö±à¼-¹ý³ÌµÄÏà¹ØÐÅÏ¢±£´æµ½Ò»¸öÎļþÖÐ("viminfo"). ÔÚÏ´αà¼-ÖÐ,
¸ÃÎļþʹÕâЩÐÅÏ¢ÖØÐÂÉúЧ, ÀýÈ绺³åÇøÁбí, Îļþ±ê¼Ç, ¼Ä´æÆ÷, ÃüÁîºÍ²éÕÒÀúÊ·.
Tab¼üÀ©Õ¹:
Vim¿ÉÒÔÔÚÎı¾Öн«TAB¼üÀ©Õ¹Îª¿Õ¸ñ (expandtab, :retab)
±êÇ©(Tag)ϵͳ:
VimÌṩÔÚÎļþÖÐÓñêÇ©¼ÓË÷Òý¼°Ðí¶à±êÇ©¶ÑÕ»ÃüÁî²éÕÒÎı¾.
Îı¾¶ÔÏó:
Vim(Ïà±Èvi)Öªµ½¸ü¶àµÄÎı¾¶ÔÏó(¶ÎÂä, ¾ä×Ó, words ºÍ WORDs -
°üÀ¨ºÍ²»°üÀ¨ÖÜΧµÄ¿Õ¸ñ.) ²¢ÇÒÔÊÐí¶ÔÕâЩ¶ÔÏóÖض¨Òå.
Óï·¨ÉÏÉ«:
VimÓø÷ÖÖÑÕÉ«ÏÔʾÎı¾ - °´ÕÕÆä"(±à³Ì)ÓïÑÔ". Äã¿ÉÒÔ¶¨ÒåÎļþµÄÓïÑÔ(Óï·¨).
Vim×Ô´ø200¶à¸öΪ¸÷ÖÖÓïÑÔÎļþÉÏÉ«µÄÓï·¨Îļþ, ±à³ÌÓïÑÔ(Ada, C, C++, Eiffel,
Fortran, Haskell, Java, Lisp, Modula, Pascal, Prolog, Python, Scheme, Smalltalk,
SQL, Verilog, VisualBasic), Êýѧ³ÌÐò(Maple, Matlab, Mathematica, SAS),
±ê¼ÇÓïÑÔ(DocBook, HTML, LaTeX, PostScript, SGML-LinuxDoc, TeX, WML, XML),
³ÌÐòµÄÊä³ö½á¹û(diff, man), ÅäÖúͳõʼ»¯Îļþ(4DOS, Apache, autoconfig, BibTeX,
CSS, CVS, elm, IDL, LILO, pine, procmail, samba, slrn), shell
½Å±¾ºÍ³õʼ»¯Îļþ(sh, bash, csh, ksh, zsh), ½Å±¾ÓïÑÔ(awk, Perl, sed, yacc),
ϵͳÎļþ(printcap, .Xdefaults). µ±È»°üÀ¨Vim±¾ÉíµÄϵͳºÍ°ïÖúÎļþ.
ÌØÊâ´úÂë:
Vim °üº¬ÓëPerl, Tcl ºÍ Python ¼¯³ÉµÄÑ¡Ïî.
Vim ÔÚWindowsÏ¿ÉÒÔ×÷ΪOLE×Ô¶¯»¯·þÎñÆ÷ÔËÐÐ.
Vim °²×°Ê±¿ÉÒÔ°üº¬ÔÚX-window Öй¤×÷µÄ´úÂë,
ÕâÑù¾Í¿ÉÒÔ¼ÓÈë¿ÉÅäÖò˵¥ºÍ¶ÔÊó±êµÄÖ§³Ö.
ÒÔ¼°ÆäËûÐí¶àÐí¶à¹¦ÄÜ.
VimµÄÖ÷Ò³ÔÚ:
http://www.vim.org/
Ò»¸ö¶ÔVimµÄÌØÉ«¸üÏ꾡µÄÃèÊö¿ÉÒÔ´ÓÏÂÃæµÄÍøÒ³ÕÒµ½:
http://www.vim.org/why.html
Vim 啯以在啄種終端機的文å-—模引下工作,
而且它也具有圖形使用者介镢,例如,镸單功能
ä»¥å•Šæ”¯æ•´æ»‘é¼ ã€‚
易啖得性:
Vim æœ‰è¨±å¤šå¹³è‡ºä¸Šçš„ç‰ˆæœ¬ï¼Œè€Œä¸”ä¹Ÿå¢žåŠ äº†è¨±å¤š Vi
所沒有的功能。
(詳見 http://www.vim.org/doc/vi.diff.txt)
Vim 與幾乎全部的 Vi 指令相容,但是沒有 Vi 的 bug ;-)
作æ¥-系統:
Vim 能在啄種作æ¥-系統上執行,包啫: AmigaOS, Atari MiNT, BeOS, DOS,
MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, Win16 + Win32
(Windows95/98/00/NT) - 而且當然也包括了 FreeBSD 和 Linux. :-)
版權:
版權由原始的作者以啊主覕的ç¶-è-·è€…, Bram Moolenaar <[email protected]>
所擕有。Vim
是「慈善軟體〕,希望您敕錢幫助烕干镔的å-¤å…’們
(詳見 ":help uganda")。
原始碼:
Vim 是開放原始碼軟體,而且æ-¡è¿Žä»»ä½•äººå¹«å¿™ç™¼å±•!
=== 特性
刕å-¸è€…的編輯器 - 易於使用:
相較於 Vi,Vim
尕刕å-¸è€…ä¾†èªªæ›´åŠ å®¹æ˜“ä½¿ç”¨ï¼Œé™¤äº†æœ‰å®Œæ•´çš„ç·šä¸Šèªªæ˜Žä¹‹å¤–ï¼Œ
"undo"(還原)和 "redo"ï¼ˆé‡•å•šï¼‰æŒ‡ä»¤è®“ä½ æ°¸é• ä¸•ç”¨æ“”å¿ƒå‡ºéŒ¯ -
啪覕會用
undo+redoï¼•é‚„æœ‰æ”¯æ•´æ»‘é¼ ï¼Œä»¥å•Šå•¯è¨-定的圖示和镸單(在GUI環境下)。
å-—碼與終端機模引:
Vim 支整 iso-latin1 å-—元集以啊完整的 termcap 支整。
(最原始的 Vi 丕能æ-£å¸¸å·¥ä½œã€‚)
å-—元與語言:
Vim
支整啳至左編輯模引(例如阿拉伯文〕波斯文〕希伯來文),以啊多何元組
æ–‡å-—集,亦啳使用超镎一何元寬度的圖僕å-—型來表示文å-—的語言,僕是ä¸-文〕日
文〕韓文。(就技術镢而言, Vim支整 UTF-8 以啊 Unicode
çš„å-—元。)
æ ¼å¼•åŒ–æ–‡å-—與「視覺〕模引:
Vim
啯以讓您「視覺化〕地镸擇文å-—(以高亮度表示),之後冕尕其進行擕作,
例如複製〕刪除〕啖代〕左啳平移〕改變å-—æ¯•å¤§å°•å¯«ï¼Œæˆ–æ˜¯ä¿•æŒ•ç¸®æŽ’ä¸¦ä¸”æ ¼å¼•åŒ–
æ–‡å-—。Vim 也兕許您镸啖並且尕矩形的文å-—啀塊作擕作。
補全指令:
Vim
有指令啯以自動替您補全您的輸入,丕論是指令〕檔案啕稱,或是單å-—。
自動指令:
Vim
包啫有啯以自動執行的自動指令(例如自動將檔案解壓縮)。
二啈å-—毕(diagraph)輸入:
Vim 兕許您輸入柕些由兩個å-—元所組戕的二啈å-—毕(例如,由 "
和 a
所組戕的 銦^。並且也啯以讓您自行定義其他的組啈。
æª”æ¡ˆæ ¼å¼•å•µæ¸¬èˆ‡è½‰æ•›:
Vim æœƒè‡ªå‹•è¾¨èª•æª”æ¡ˆçš„æ ¼å¼•ï¼ˆDOS, Mac,
Unix)而且也讓您轉å-˜ç‚ºå…¶ä»–
æ ¼å¼• - 在 Windows 上丕冕需覕 unix2dos 了5
æ-·å•²:
Vim
尕於執行镎的指令有「æ-·å•²ã€•åŠŸèƒ½ï¼Œæ‚¨å•¯ä»¥å•«å‡ºä¹‹å‰•è¼¸å…¥é•Žçš„指
ä»¤ä¸¦åŠ ä»¥ä¿®æ”¹å†•æ¬¡ä½¿ç”¨ã€‚
巨集錄製:
Vim
啯以讓您「錄〕下您的編輯镎程,並且冕次æ’-放,以進行釕複性高的工作。
記憶體陕制:
比起最原始的 Vi,Vim
有著更大的毕列長度陕制以啊暫å-˜å•€çš„大尕。
多釕暫å-˜å•€ä»¥å•Šèž¢å¹•åˆ†å‰²:
Vim
讓您啯以編輯多個暫å-˜å•€ï¼Œè€Œä¸”您也啯以將視窗分割為多個å-•è¦–窗(啯
以是水平或是垂直的),以便啌時檢視多個檔案的丕啌何置。
指令剕置數å-—:
比起原始的 Vi,Vim
å•¯ä»¥åœ¨æ›´å¤šçš„æŒ‡ä»¤å‰•é•¢åŠ ä¸Šæ•¸å-—來表示執行次數(例如 "put
指令)。
執行時期檔案(說明檔與文法檔):
Vim
有七啕個包啫了啄種內容的說明檔;其ä¸-柕些是特別釕尕特定的作æ¥-
系統所撰寫的說明。
使用script:
Vim 內建一套 script èªžè¨€ï¼Œæ–¹ä¾¿ä½¿ç”¨è€…ä½œå•„é …åŠŸèƒ½å»¶ä¼¸ã€‚
敜尋移何:
Vim
å…•è¨±æ•œå°‹æŒ‡ä»¤é™„åŠ ä½•ç§»ï¼Œå¦‚æ-¤ä¸€ä¾†æ‚¨å°±å•¯ä»¥å°‡æ¸¸æ¨™æ”¾ç½®åœ¨æ‰¾åˆ°çš„æ–‡
å-—後镢。
æ-·ç¨‹å›žå¾©:
Vim
兕許您將編輯镎程ä¸-的資訊å-˜å…¥æª”案ä¸-("viminfo"),在您下次編輯的時候
就啯以直接使用,例如暫å-˜å•€åˆ—表〕檔案標記〕暫å-˜å™¨ã€•å‘½ä»¤æ-·å•²ç-‰ã€‚
定何å-—元展開:
Vim 啯以替您用空白來展開文å-—ä¸-的定何å-—元(expandtab,
:retab)。
標籤系統:
Vim
敕供在檔案ä¸-æ ¹æ“šç´¢å¼•å•Šã€Œæ¨™ç±¤ã€•ä¾†æ•œå°‹æ–‡å-—,或是æ•-酕許多標
ç±¤å †ç–ŠæŒ‡ä»¤ä¾†å°‹æ‰¾æ–‡å-—。
æ–‡å-—物件:
Vim
èƒ½å¤ è¾¨èª•æ›´å¤šçš„æ–‡å-—物件(段蕽〕啥å-•ã€•å–®å-—,以啊縮寫å-— -
包括或是
丕包括周圕的空白),並且也兕許您自由更改尕於這些物件的定義。
語法變色:
Vim 啯以使用彩色來顯示文å-— -
æ ¹æ“šå®ƒçš„èªžè¨€ï¼ˆæˆ–æ˜¯ç¨‹å¼•èªžè¨€ï¼‰ã€‚
您啯以自行定義這些語言(語法)檔案。
Vim
éš¨é™„æœ‰äºŒç™¾ç¨®ä»¥ä¸Šçš„èªžæ³•æª”æ¡ˆï¼Œèƒ½å¤ ç‚ºå•„ç¨®å¸¸è¦‹çš„ç¨‹å¼•èªžè¨€æª”æ¡ˆï¼ˆä¾‹å¦‚ï¼š
例如: Ada, C, C++, Eiffel, Fortran, Haskell, Java, Losp, Modula, Pascal,
Prolog, Python, Scheme, Smalltalk, SQL, Verilog, VisualBasic),數å-¸ç¨‹å¼•
檔案(Maple, Matlab, Mathematica, SAS),標記語言(DocBook, HTML,
LaTeX,
PostScript, SGML-LinuxDoc, TeX, WML, XML),程引的輸出(diff,
man),軟體
è¨-定檔(4DOS, Apache, autoconfig, BibTeX, CSS, CVS, elm, IDL, LILO, pine,
procmail, samba, slrn),命令處畆器語言與è¨-定檔(sh, bash, csh,
ksh, zsh),
script 語言(awk, Perl, sed, yacc),系統檔案(printcap,
.Xdefaults)以啊
(當然)Vim çš„è¨-定檔和說明檔。
特殊程引碼:
Vim 啯以特別與 Perl, Tcl, 和 Python 整啈。
Vim 在 Windows 下啯以作為 OLE automation 伺朕器。
Vim 啯以支整 X-windowsï¼Œä»¥åŠ å…¥å•¯è‡ªè¨‚çš„é•¸å–®èˆ‡æ»‘é¼ çš„æ”¯æ•´ã€‚
以啊更多更多5
Vim ("Vi IMproved", "vi verbeterd") is een "vi kloon", ofwel een
programma dat lijkt op de text editor "vi".
Vim werkt in textmode op iedere terminal, maar heeft ook een grafische
user-interface, bijvoorbeeld menu's en muis-ondersteuning.
Beschikbaarheid:
Vim is voor vele platforms beschikbaar en heeft veel toegevoegde
features vergeleken met Vi. (Zie http://www.vim.org/doc/vi.diff.txt,
Engelstalige link.)
Vim is bijna volledig compatible met Vi -- behalve met bugs in Vi ;-)
Operating Systems:
Vim is verkrijgbaar voor vele systemen: AmigaOS, Atari MiNT, BeOS, DOS,
MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, WIn16 + Win32
(Windows95/98/00/NT) - en in het bijzonder FreeBSD and Linux. :-)
Copyright:
Het copyright is in handen van de eerste auteur en maintainer,
Bram Moolenaar <[email protected]>.
Vim is "charity-ware", dat betekent dat je wordt uitgenodigd een donatie
te doen aan weeskinderen in Oeganda (zie ":help uganda").
Broncode:
Vim is OpenSource, iedereen is welkom om verbeteringen aan te brengen!
=== Features
Beginners-editor -- Gebruikersvriendelijk:
Vim is makkelijker te leren dan Vi vanwege de uitgebreide online help,
"undo"- en "redo"-commando's (maak gerust fouten -- en maak ze ongedaan,
of maak ze opnieuw!), muis-ondersteuning en configureerbare pictogrammen
en menu's (GUI, grafische gebruikersinterface).
Automatisch completeren:
In Vim kan je input automatisch gecompleteerd worden --
commando's, bestandsnamen of woorden.
Automatische commando's:
Vim heeft "autocommands" voor het automatisch uitvoeren van commando's (bv.
automatisch "uncompressen" van gecompresste bestanden tijdens het inladen.)
Digraph-invoer:
In Vim kun je speciale karakters als een combinatie van twee toetsen
invoeren (bv. de combinatie van " en a levert een ä op) -- en je kunt
nieuwe combinaties zelf definiëren.
Bestandsformaat-detectie en -conversie:
Vim herkent bestandstypes (DOS, Mac of Unix) en laat je bestanden als een
ander type bewaren -- unix2dos is niet meer nodig onder DOS of Windows!
History:
Vim houdt een lijst bij ("history") van gebruikte commando's en zoektermen,
die je kunt hergebruiken en wijzigen.
Macro's opnemen:
In Vim kun je je toetsaanslagen "opnemen" en weer "afspelen" om taken te
herhalen.
Geheugenlimiet:
Vim heeft een veel hogere limiet voor regellengte en buffergrootte dan
standaard-Vi.
Scripttaal:
Vim heeft een ingebouwde scripttaal voor eenvoudige uitbreidingen.
Sessies terugroepen:
Vim bewaart informatie over "edit-sessies" in een bestand ("viminfo")
die dan weer gebruikt kan worden in een volgende sessie, bv. de lijst
van buffers, bladwijzers in bestanden, registers, commando's en
zoekopdrachten.
Tab-expansie:
Vim kan TAB-karakters in een tekst vervangen door spaties (expandtab,
:retab);
Tag-systeem:
Met behulp van Vim kun je tekst in bestanden vinden door een index van
"tags" te gebruiken, samen met een groot aantal "tag stack"-commando's.
Tekstobjecten:
Vim kent meer tekstobjecten (alinea's, zinnen. woorden en WORDS -- alle
met of zonder omringend wit) en laat je zelf de definitie van deze
objecten aanpassen.
Syntaxkleuring:
Vim laat tekst in kleur zien -- overeenkomstig de (programmeer-)taal. Je
kunt de "taal" ("syntax") van de bestanden zelf definiëren.
Speciale code:
Vim heeft de mogelijkheid tot integratie met Perl, Tcl en Python. Vim
kan als OLE automation server werken onder Windows. Vim kan ook
geïnstalleerd worden met code voor X-windows, met configureerbare menu's
en ondersteuning voor de muis.
En meer. Veel meer!
Saatavuus:
Vim on saatavilla useille alustoille ja siinä on useita lisäominaisuuksia
Vi:hin verrattuna. (kts. http://www.vim.org/doc/vi.diff.txt) Vim on
yhteensopiva lähes kaikkien vi komentojen kanssa - paitsi bugisten. ;-)
Käyttöjärjestelmät:
Vim on saatavilla useille järjestelmille: AmigaOS, Atari MiNT,
BeOS, DOS, MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, Win16 +
Win32 (Windows95/98/00/NT) - ja erityisesti FreeBSD:lle ja Linuxille. :-)
Tekijänoikeudet:
Tekijänoikeudet ovat päätekijällä ja ylläpitäjällä, Bram Moolenaarilla
<[email protected]>. Vim on hyväntekeväisyysohjelma ("charity-ware"), sinua
rohkaistaan tekemään lahjoitus esim. Ugandan orvoille
(katso ":help uganda").
Lähdekoodi:
Vim on OpenSource-ohjelma ja kaikki ovat tervetulleita auttamaan sen
parantamisessa!
=== Ominaisuudet
Merkistöt ja terminaalit:
Vim:ssä on tuki iso-latin1 merkistölle ja termcap:lle (Vanilla Vi:lla
on ongelmia tämän kanssa).
Kirjaimet ja kielet:
Vim:ssä on tuki oikealta-vasemmalle editoinnille (esim. arabia, farsi,
heprea), ja monitavuisille (multi-byte) teksteille, kuten kielille,
joissa on kuvamerkkejä, jotka esitetään useammalla kuin yhdellä
tavulla, esim. kiina, japani, korea (Hangul), (teknisesti, Vim tukee
UTF-8:ia ja Unicodea).
Täydentyvät komennot:
Vim:ssä on komentoja, jotka täydentävät syötteesi - komennoilla,
tiedostonimillä tai sanoilla.
Automaattiset komennot:
Vim:ssä on myös "automaattiset komennot", automaattiseten toimintojen
suorittamiseksi (esim. automaattinen pakattujen tiedostojen
purkaminen).
Kaksikirjainsyöte:
Vim sallii syöttää erikoismerkkejä kahden merkin yhdistelminä (esim.
yhdistelmä " ja a näkyy merkkinä ä) - ja antaa myös määritellä muita
yhdistelmiä.
Historia:
Vimissä on "historia" komennoille ja hauille, joten sinun ei tarvitse
muistaa edellistä komentoa tai hakulauseketta muuttaaksesi niitä.
Makrojen tallentaminen:
Vim:ssä voi tallettaa "editointia" ja ajaa niitä uudelleen toistuvissa
tehtävissä.
Muistirajoitukset:
Vimissä on paljon suuremmat muistirajoitukset rivin pituuksille ja
buffereille kuin vanilla Vi:ssa.
Numeroetuliite komennoissa:
Vim sallii numeroetuliitteen useammille komennoille kuin Vi (esim.
"put":lle).
Skriptaus:
Vim:ssä on sisäänrakennettu skriptikieli helpottamaan lisätoimintojen
tekoa.
Haun vaihesiirto:
Vim sallii vaihesiirrot hakukomennoissa, voit asettaa kursorin tietyn
matkan päähän löydetyn tekstin jälkeen.
Istunnon palauttaminen:
Vim tallettaa tietoa istunnon aikana tapahtuneesta editoinnista
tiedotoon ("viminfo"), mikä sallii tiedon käyttämisen seuraavan
editointi-istunnon aikana, esim. bufferilistan, tiedostomerkit,
rekisterit, komento ja hakuhistorian.
Tabin muuntaminen:
Vim pystyy näyttämään tekstin tabuloinnit haluttuna määränä
välilyöntejä (expandtab, :retab).
Taggaus:
Vim:ssä voi hakea tekstiä tiedostoista käyttäen "tageja" ja liittää
hakuun komentoja.
Tekstiobjektit:
Vim tunnistaa monenlaisia rakenteita (kappaleet, lauseet, sanat ja
SANAT - kaikki tyhjien välimerkkien (whitespace) kanssa tai ilman, ja
sallii näiden rakenteiden muuntelun ja määrittelyn.
Syntaksiväritys:
Vim näyttää tekstin väreissä - "ohjelmointikielen" mukaisesti.
Voit itse määritellä tiedoston "kielen" ("syntaksin").
Erityiskoodi:
Vimissä on integrointituki Perlille, Tcl:lle ja Pythonille. Vim voi myös
toimia OLE-palveluna Windowsissa. Vim voidaan asentaa myös
X-windowsille tarkoitetun koodin kanssa, jolloin mukana on myös
muunneltavat valikot ja tuki hiirelle. Ja enemmän. Paljon enemmän!
=== Linkit
vim: tw=70
Vim, c'est quoi ?
Une description en 6 Ko
Vim fonctionne en mode texte sur tous les types de terminaux, mais il dispose
aussi d'une interface graphique, avec menus deroulants et souris.
Disponibilite
Vim est disponible pour un grand nombre de plateformes et a des fonctionnalites
supplementaires par rapport a Vi (voyez "http://www.vim.org/doc/vi.diff.txt"
pour un resume des differences entre Vim et Vi).
Vim est compatible avec presque toutes les commandes de Vi (excepte les
bogues ;-).
Systemes d'exploitation
Vim tourne sur de nombreux systemes d'exploitation : AmigaOS, Atari MiNT, BeOS,
DOS, MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, Win16 + Win 32
(Windows 95/98/2k/NT) - et bien entendu FreeBSD et Linux. :-)
Copyright
Les droits de Vim appartiennent a son auteur principal Bram Moolenaar
<[email protected]>.
Vim est un "charity-ware" : vous etes encourages a faire une donation aux
orphelins d'Ouganda (voyez : ":help uganda").
Source
Vim est OpenSource. Tout le monde est le bienvenu pour aider a son
developpement !
=== Caracteristiques
Flexibilite linguistique
Vim permet de taper du texte de droite a gauche (pratique pour ecrire par
exemple en Arabe, Farsi ou Hebreu).
Vim supporte aussi les jeux de caracteres multibytes. Il est donc possible
d'editer des textes dans des langues necessitant des interfaces graphiques, ou
les caracteres sont representes par plus d'un byte comme le Chinois, le
Japonais ou le Coreen (Hangul). Techniquement, Vim supporte les textes en
UTF-8 et Unicode.
Commandes automatiques
Vim offre aussi des commandes pour l'execution automatique d'instructions (par
exemple compression/decompression automatique de fichiers).
Saisie de digraphs
Vim permet de saisir les caracteres high-bit par la combinaison de deux
caracteres (par exemple "'" et "e" donnent é).
Historique
Vim conserve un historique des commandes et des recherches. Vous pouvez ainsi
rappeler des commandes precedemment entrees ou des recherches precedemment
effectuees pour les editer.
Enregistreur de macros
Vim offre la possibilite d'enregistrer votre saisie pour la restituer en cas de
taches repetitives.
Limites memoire
Vim a des limitations de memoire superieures pour les longueurs de ligne et les
tailles de tampons (buffers) que vanilla Vi.
Langage de script
Vim dispose d'un langage de script integre permettant des extensions faciles.
Recherches hors-champs
Vim permet d'effectuer des recherches hors-champ. Vous pouvez donc placer le
curseur *apres* le texte trouve.
Recuperation de donnees
Vim permet de stocker les informations sur une session d'edition dans un
fichier ("viminfo") qui leur permet d'etre utilisees lors de la session
suivante. Ces informations sont la liste des tampons, les signets, les
registres et l'historique des commandes et des recherches.
Systeme de liens
Vim peut trouver du texte dans des fichiers en utilisant un systeme d'index et
de liens. De nombreuses commandes permettent de gerer cela.
Coloration syntaxique
Vim affiche le texte en couleurs en fonction du langage de programmation. Il
est possible de definir soi-meme les couleurs.
Vim est livre avec plus de 200 fichiers syntaxe pour l'affichage en couleur des
langages de programmation les plus courants (Ada, C, C++, Eiffel, Fortran,
Haskell, Java, Lisp, Modula, Pascal, Prolog, Python, Scheme, Smalltalk, SQL,
Verilog, VisualBasic), des programmes de maths (Maple, Matlab, Mathematica,
SAS), des textes marques (DocBook, HTML, LaTeX, PostScript, SGML-LinuxDoc, TeX,
WML, XML), des sorties de programmes (diff, man), des fichiers de configuration
(4DOS, Apache, autoconfig, BibTeX, CSS, CVS, elm, IDL, LILO, pine, procmail,
samba, slrn), des scripts et configurations shell (shells: sh, bash, csh,
ksh, zsh), des langages de script (awk, Perl, sed, yacc), des fichiers systeme
(printcap, .Xdefaults) et bien sur des fichiers d'aide et de configuration de
Vim.
Tout ceci ne constitue qu'une petite partie des potentialites de Vim. Vim a
plus a offrir. Beaucoup plus !
Erhaeltlichkeit (Availability):
Vim ist erhaeltlich fuer viele Betriebssysteme/Plattformen
und hat viele zusaetzliche Eigenschaften (features)
(siehe dazu Seite http://www.vim.org/doc/vi.diff.txt ).
Copyright/Lizenz (Copyright):
Das Copyright ist in den Haenden von dem Hauptautor
Bram Moolenaar <[email protected]>.
Vim ist "charity-ware" ("Naechstenliebe"), dh Sie werden dazu
ermutigt eine Spende an Waisenkinder in Uganda zu machen
(siehe ":help uganda").
Source:
Vim is "OpenSource", dh der Quellcode fuer das Programm ist fuer
jeden frei erhaeltlich , und man darf Aenderungen daran vornehmen.
(siehe http://www.opensource.org/certification-mark.html )
=== Features
Completion Commands:
Vim has commands which complete your input -
either with commands, filenames, and words.
Automatic Commands:
Vim also has "autocommands" for automatic execution of commands
(eg automatic uncompression of compressed files).
Digraph Input:
Vim allows you to enter special characters by a combination
of two characters (eg the combination of " and a yields an ä) -
and allows you to define other combinations, too.
History:
Vim has a "history" for commands and searches, so you can
recall previous commands or search pattern to edit them.
Macro Recording:
Vim allows to "record" your editing for replaying for repetitive tasks.
Memory Limits:
Vim has much higher memory limits for line length
and buffer sizes than vanilla Vi.
Scripting:
Vim has a built-in scripting language for easy extension.
Search Offset:
Vim allows offsets for search commands, so you
place the cursor *after* the found text.
Session Recovery:
Vim allows to store information of an editing session into a file ("viminfo")
which allows them for being used with the next editing session, eg
buffer list, file marks, registers, command and search history.
Tab expansion:
Vim can expand tabs within the text with spaces (expandtab, :retab).
Tag system:
Vim offers to find text in files by using an index with "tags"
together with many tag stack commands.
Text Objects:
Vim knows more text objects (paragraphs, sentences, words and WORDS -
all with and without surrounding whitespace) and allows to configure
the definition for these objects.
Syntax Coloring:
Vim shows text in color - according to its "(programming) language".
You can define the "language" ("syntax") of the files yourself.
Special code:
Vim has optional integration with Perl, Tcl and Python.
Vim can act as an OLE automation server under Windows.
Vim can also be installed with code for X-windows,
adding configurable menus and support for the mouse.
And more. Lots more!
Äéáèåóéìüôçôá:
To Vim åßíáé äéáèÝóéìï ãéá ðïëëÝò ðëáôöüñìåò êáé Ý÷åé
ðïëëÝò åðéðëÝïí äõíáôüôçôåò óå óýãêñéóç ìå ôïí Vi.
(êïéôÜîôå óôï http://www.vim.org/doc/vi.diff.txt - óýíôïìá
êáé óôá åëëçíéêÜ). Ôï Vim åßíáé óõìâáôü ìå ó÷åäüí üëåò ôéò
åíôïëÝò ôïõ Vi - åêôüò áðü ôá bugs ôïõ ;-)
ËåéôïõñãéêÜ ÓõóôÞìáôá:
Ï Vim åßíáé äéáèÝóéìïò ãéá ðÜñá ðïëëÜ óõóôÞìáôá: AmigaOS,
Atari MiNT, BeOS, DOS, MacOS, NextStep, OS/2, OSF, RiscOS,
SGI, UNIX, VMS, Win16 + Win32 (Windows95/98/00/NT) - êáé
éäéáßôåñá ãéá ôï FreeBSD êáé ôï Linux. :-)
Copyright:
Ôï copyright áíÞêåé óôïí êýñéï óõããñáöÝá - äçìéïõñãü êáé
óõíôçñçôÞ ôïõ, ôïí Bram Moolenaar <[email protected]>. Ï Vim
åßíáé "öéëáíèñùðéêüò", ð÷ áíôß ôÝëïõò ÷ñÞóçò óáò
ðñïôñÝðïõìå íá êÜíåôå ìéá ðñïóöïñÜ óôá ïñöáíÜ ôçò Uganda.
(Ãéá ðåñéóóüôåñåò ðëçñïöïñßåò êïéôÜîôå ":help uganda").
Êþäéêáò:
Ï Vim åßíáé áíïé÷ôüò ùò ðñïò ôïí êþäéêá (OpenSource) êáé üëïé
åßíáé åõðñüóäåêôïé íá âïçèÞóïõí óôçí âåëôßùóÞ ôïõ.
=== ×áñáêôçñéóôéêÜ
ÓõìðëÞñùóç Åíôïëþí:
Ï Vim Ý÷åé åíôïëÝò ïé ïðïßåò óõìðëçñþíïõí ôçí åßóïäü óáò -
åßôå ìå åíôïëÝò åßôå ìå ïíüìáôá áñ÷åßùí åßôå ìå ëÝîåéò.
Áõôüìáôåò ÅíôïëÝò:
Ï Vim Ý÷åé åðßóçò ôéò "autocommands" (áõôüìáôåò åíôïëÝò) ãéá
áõôüìáôç åêôÝëåóç åíôïëþí (ð÷ áõôüìáôç áðïóõìðßåóç óõìðéåóìÝíùí
áñ÷åßùí).
ÄéãñáììáôéêÞ Åßóïäïò:
Ï Vim åðéôñÝðåé ôçí åßóïäï åéäéêþí ÷áñáêôÞñùí ìå Ýíáí óõíäõáóìü
äýï ÷áñáêôÞñùí (ð÷ ï óõíäõáóìüò åíüò " ìå Ýíá O äßíåé Ýíá â) - êáé
óáò åðéôñÝðåé íá ïñßóåôå êáé äéêïýò óáò óõíäõáóìïýò.
Éóôïñéêü:
Ï Vim êñáôÜ ôï "éóôïñéêü" ôùí åíôïëþí êáé ôùí áíáæçôÞóåùí êáé Ýôóé
ìðïñåßôå íá áíáêáëÝóåôå ðñïçãïýìåíåò åíôïëÝò Þ ðñüôõðá áíáæçôÞóåùí
ãéá íá åðåîåñãáóôåßôå.
ÊáôáãñáöÞ Ìáêñïåíôïëþí:
Ï Vim åðéôñÝðåé ôçí "åããñáöÞ" ôùí åíåñãåéþí óáò êáôÜ ôçí åðåîåñãáóßá
êÜðïéïõ êåéìÝíïõ Ýôóé þóôå íá åßíáé äõíáôÞ ç ðïëëáðëÞ åöáñìïãÞ ôïõò
óå åðáíáëçðôéêÝò åñãáóßåò.
¼ñéá ÌíÞìçò:
Ï Vim Ý÷åé ðïëý õøçëüôåñá üñéá ìíÞìçò ãéá ôï ìÞêïò ãñáììÞò êáé
ìåãáëýôåñïõò buffers (åíäéÜìåóïõò ÷þñïõò áðïèÞêåõóçò) áðü ôïí ãíÞóéï Vi.
Scripts åñãáóßáò:
Ï Vim Ý÷åé åíóùìáôùìÝíç ãëþóóá ãéá scripts ðñïóöÝñïíôáò åýêïëç åðÝêôáóç.
Ìåôáôüðéóç áíáæÞôçóçò:
Ï Vim åðéôñÝðåé ìåôáôïðßóåéò (offsets) ãéá ôéò åíôïëÝò áíáæÞôçóçò, Ýôóé þóôå
íá ìðïñåß íá ôïðïèåôåß ôïí äñïìÝá (êÝñóïñá) *ìåôÜ* ôï åíôïðéóìÝíï êåßìåíï.
Óýóôçìá Åôéêåôþí:
Ï Vim ìðïñåß íá áíáæçôÞóåé êåßìåíï óå áñ÷åßá ÷ñçóéìïðïéþíôáò Ýíá åõñåôÞñéï
ìå "åôéêÝôåò" êáèþò åðßóçò êáé ðïëëÝò åíôïëÝò ÷åéñéóìïý ôçò óôïßâáò åôéêåôþí.
Áíôéêåßìåíá ÊåéìÝíùí:
Ï Vim "ãíùñßæåé" ðåñéóóüôåñá áíôéêåßìåíá-óõóôáôéêÜ êåéìÝíùí (ðáñáãñÜöïõò,
ðñïôÜóåéò, ëÝîåéò, óõìâïëïóåéñÝò - üëá ìå Þ ÷ùñßò ðåñéâÜëëïíôá êåíÜ) êáé
åðéôñÝðåé ôç ñýèìéóç êáé ïñéóìü áõôþí ôùí óõóôáôéêþí.
×ñùìáôéóìüò Óýíôáîçò:
Ï Vim ÷ñùìáôßæåé ôï êåßìåíï óýìöùíá ìå ôç ãëþóóá ðñïãñáììáôéóìïý ðïõ
÷ñçóéìïðïéåßôå. Ìðïñåßôå íá ïñßóåôå ôçí "ãëþóóá" ("óýíôáîç") ðïõ ÷ñçóéìïðïéåßôå.
Ï Vim óõíïäåýåôáé áðü ðåñéóóüôåñá áðï 200 áñ÷åßá óýíôáîçò ãéá ôï ÷ñùìáôéóìü
ôïõ êåéìÝíïõ ãéá ôéò ðåñéóóüôåñåò ãíùóôÝò ãëþóóåò ðñïãñáììáôéóìïý (Ada, C, C++,
Eiffel, Fortran, Haskell, Java, Lisp, Modula, Pascal, Prolog, Python, Scheme,
Smalltalk, SQL, Verilog, VisualBasic), ìáèçìáôéêÜ ðñïãñÜììáôá (Maple, Matlab,
Mathematica, SAS), åðáõîçìÝíï êåßìåíï (DocBook, HTML, LaTeX< PostScript,
SGML-LinuxDoc, TeX, WML, XML), Ýîïäï ãíùóôþí ðñïãñáììÜôùí (diff, man), áñ÷åßá
ñõèìßóåùí ðñïãñáììÜôùí (4DOS, Apache, autoconfig, BibTeX, CSS, CVS, elm, IDL,
LILO, pine, procmail, samba, slrn), shell scripts êáé ñõèìßóåéò (sh, bash, csh,
ksh, zsh), ãëþóóåò script (awk, Perl, sed, yacc) áñ÷åßá óõóôÞìáôïò (printcap,
.Xdefaults) êáé âÝâáéá ãéá ôïí ßäéï ôïí Vim êáé ôá áñ÷åßá âïçèåßáò ôïõ.
Åéäéêüò Êþäéêáò:
Ï Vim ìðïñåß íá óõíäõáóôåß ìå Perl, Tcl êáé Python. Åðßóçò, ìðïñåß íá
ëåéôïõñãÞóåé ùò áíôéêåßìåíï OLE óå ðåñéâÜëëïí Windows. Ï Vim ìðïñåß åðßóçò íá
åãêáôáóôáèåß ìå êþäéêá ãéá X-windows, ðñïóèÝôïíôáò ñõèìéæüìåíá menu êáé
õðïóôÞñéîç ãéá ôï ðïíôßêé.
Êáé ðïëëÜ Üëëá... :-)))
Ãéá ìéá ðéï åìðåñéóôáôùìÝíç ðåñéãñáöÞ ôùí äõíáôïôÞôùí ôïõ Vim êïéôÜîôå:
http://www.vim.org/why.html
ÅíçìÝñùóç:
ÊõñéáêÞ 11 Ìáñôßïõ 2001.
"Mi a Vim?"
Magyarázat hat kilobájtban
A Vim ("Vi IMproved" - feljavított Vi) egy "vi klón", vagyis egy program,
ami a "vi" szövegszerkesztõhöz hasonlít.
Elérhetõség:
A Vim rengeteg platformon elérhetõ, és rengeteg plusz szolgáltatása van az
Vi-hoz képest. (lásd http://www.vim.org/doc/vi.diff.txt)
A Vim szinte mindenben kompatibilis a Vi parancsaival - kivéve a hibákat :)
Operációs rendszerek:
A Vim számos operációs rendszeren megtalálható: AmigaOS, Atari MiNT, BeOS, DOS,
MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, Win16 + Win32
(Windows95/98/00/NT) - és különösen FreeBSD illetve Linux alatt. :)
Copyright:
A jogok a fö szerzõ és karbantartó Bram Moolenaar <[email protected]> kezében
vannak. A Vim "adomány-ware", vagyis kérjük, hogy adakozz Uganda árvái
javára. (lásd ":help uganda").
Forrás:
A Vim nyílt forrású, és bárki segíthet a fejlesztésben!
=== Jellemzõk
Karakterek és nyelvek:
A Vim támogatja a jobbról balra írást (Arab, Héber), a több byte-os
szövegeket, olyan nyelvek esetében, ahol a grafikus karaktereket több mint
egy byte-on ábrázolják, mint például a Kínai, Japán, Koreai. (Technikailag
a Vim támogatja az UTF-8 és Unicode kódolást.)
Kiegészítõ parancsok:
A Vim képes a bevitt szöveg kiegészítésére - legyen az parancs, fájlnév,
vagy bármilyen szó.
Automata parancsok:
A Vim rendelkezik automatikus parancsokkal (autocommands) parancsok
automatikus végrehajtására (pl tömörített állományok kitömörítése)
Repülõ ékezetes (digraph) bevitel:
A Vim lehetõvé teszi, hogy különleges karaktereket két karakter
kombinációjaként vigyünk be. (például a " és az a együtt ä-t eredményez)
Lehetõség van saját kombinációk megadására is.
Elõzõ parancsok:
A Vim nyílván tartja az elõzõ parancsokat és kereséseket, így ezek késõbb
visszakereshetõk, átszerkeszthetõk.
Makró rögzítés:
A Vim lehetõvé teszi, a mûveletek "felvételét", amik ismétlõdõ
feladatokhoz visszajátszhatók.
Memória korlátok:
A Vim sokkal tágabb korlátokkal rendelkezik sor illetve bufferméretre mint
az eredeti Vi.
Script-ek:
A Vim saját script-nyelvvel rendelkezik a könnyû bõvíthetõségért.
Eltolásos keresés:
A Vim megengedi eltolás használatát a keresés parancsokkal, így a kurzor
akár a megtalált szöveg *mögé* is kerülhet.
Munkaállapot visszaállítás:
A Vim képes a munkaállapot elmentésére egy állományba ("viminfo"), amiket a
kövektezõ alkalommal vissza lehet állítani. Ezekbe beletartoznak a
bufferlisták, az könyvjelzõk, regiszterek, az elõzõ parancsok és keresések.
Tab kifejtés:
A Vim képes a szövegen belül a tabokat szóközökre cserélni (expandtab,
:retab).
Tag rendszer:
A Vim lehetõvé teszi szövegrészletek keresését állományokban "tag" indexek
segítségével, illetve "tag" verem parancsokkal.
Szöveg objektumok:
A Vim több szöveg objektumot ismer (bekezdés, mondat, szó és SZÓ - mindezek
határolókarakterekkel vagy azok nélkül.) és ezek definíciói
megváltoztathatóak.
Szintaktika kiemelés:
A Vim színezi a szöveget - a saját "(programozási) nyelvének" megfelelõen. A
fájlok "nyelve" ("szintaktikája") szabadon beállítható.
Különleges kód:
A Vim opcionálisan képes együttmûködni Perl-lel, Tcl-lel, Python-nal. Windows
alatt OLE szerverként mûködik. X-windows támogató kóddal is telepíthetõ,
átszerkeszthetõ menükkel és egértámogatással. És még többel, sokkal többel.
Vim ("Vi IMproved" cioe' "Vi migliorato") e' un clone di vi, cioe' un programm
a simile all'editor testuale "Vi".
Disponibilta':
Vim e' disponibile per molte piattaforme e aggiunge molte funzinalita' a Vi
(vedi http://www.vim.org/doc/vi.diff.txt per una descrizione dettagliata delle
differenze). Vim e' compatibile con quasi tutti i comandi di Vi, fatta
eccezione per i bachi di Vi. ;-)
Sistemi operativi:
Vim e' disponibile per moltissimi sistemi: AmigaOS, Atari MiNT, BeOS, DOS,
MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, WIn16 + Win32
(Windows95/98/00/NT) - e specialmente per FreeBSD and Linux. :-)
Copyright:
I diritti di Vim appartengono al suo autore principale, Bram Moolenaar
<[email protected]>. Vim e' "charity-ware", cioe' siete incoraggiate a fare una
donazione agli orfani dell'Uganda (vedi ":help uganda" per maggiori
informazioni).
Sorgenti:
Vim e' OpenSource: tutti coloro che vogliono aiutare a migliorarlo sono
i benvenuti.
Flessibilita' di linguaggio:
Vim permette di scrivere da destra a sinistra (utile per scrivere in Arabo,
Farsi o Ebraico) e i caratteri "multibyte", ossia linguaggi i cui caratteri
sono rappresentati da piu' di un singolo byte, come Cinese, Giapponese,
Coreano (Hangul). Tecnicamente, Vim supporta testo in UTF-8 e Unicode.
Comandi di completamento:
Vim puo' completare automaticamente cio' che state scrivendo, sia esso un
comando, il nome di un file o una semplice parola.
Comandi automatici:
Vim offre anche la possibilita' di eseguire automaticamente i comandi (ad
esempio per decomprimere e comprimere file compressi)
Storia:
Vim conserva memoria dei comandi e delle ricerche, cosi' e' possibile
richiamare comandi o ricerche precedenti e eventualmente modificarle.
Registrazione di macro:
Vim ti permette di registrare i comandi che digiti per eseguire compiti
ripetitivi.
Limite di memoria:
Vim ha limiti molto piu' eleveti per la lunghezza delle linee e per
la dimensione della memoria tampone (buffer) rispetto a vanilla Vi.
Linguaggio di Script:
Vim possiede un linguaggio di programmazione integrato che permette un facile
estensione delle funzionalita'.
Ricerche sfalsate:
Vim permette di effettuare delle ricerche sfalsate, cosi' e' possibile mettere
il cursore *dopo* il testo trovato.
Indice:
Vim offre la possibilita' di trovare del testo nei file usando un indice con
"tags", e di navigare con facilita'.
Ogetti testuali:
Vim riconosce diversi oggetti testuali (paragrafi, frasi, parole con e senza
gli spazi bianchi che le circondano) e permette di configurare la definizione
di questi oggetti.
Colorazione sintattica:
Vim mostra il testo a colori, a seconda del diverso linguaggio di
programmazione che si sta editando. E' possibile definire la tua specifica
sintassi per i tuoi file.
Vim e' distribuito con piu' di 200 file di sintassi per colorare il testo dei
linguaggi di programmazione piu' comuni (Ada, C, C++, Eiffel, Fortran,
Haskell, Java, Lisp, Modula, Pascal, Prolog, Python, Scheme, Smalltalk, SQL,
Verilog, VisualBasic), programmi di matematica (Maple, Matlab, Mathematica,
SAS), testo con marcatori (DocBook, HTML, LaTeX, PostScript, SGML-LinuxDoc,
TeX, WML, XML), uscita di programmi (diff, man), file di configurazione (4DOS,
Apache, autoconfig, BibTeX, CSS, CVS, elm, IDL, LILO, pine, procmail, samba,
slrn), linguaggi di script (awk, Perl, sed, yacc), file di sistema (printcap,
.Xdefaults), e, naturalmente, per i file di aiuto e configurazione di Vim.
Codice speciale:
Vim possiede una integrazione opzionale con Perl, Tcl e Python.
Vim puo' agire come un server OLE in Windows.
Vim puo' anche essere installato con il supporto X-Windows, aggiungendo menu
configurabili e supporto per il mouse.
vim ¤Ï¤¢¤é¤æ¤ëüËö¡Ê¥¨¥ß¥å¥ì¡¼¥¿¡Ë¤Î¥Æ¥-¥¹¥È¥â¡¼¥É¤ÇÆ°ºî¤·¤Þ¤¹¤¬¡¢
GUI¡Ê¥°¥é¥Õ¥£¥Ã¥¯¡¦¥æ¡¼¥¶¡¦¥¤¥ó¥¿¥Õ¥§¡¼¥¹¡Ë¤â»ý¤Ã¤Æ¤¤¤Æ¡¢¥á¥Ë¥å¡¼¤ä
¥Þ¥¦¥¹¤ò¥µ¥Ý¡¼¥È¤·¤Þ¤¹¡£
²ÄÍÑÀ-:
vim ¤Ï¿¤¯¤Î¥×¥é¥Ã¥È¥Õ¥©¡¼¥à¤Ç»È¤¨¡¢vi ¤ÈÈæ¤Ù¤Æ¿¤¯¤Îµ¡Ç½¤¬Äɲäµ
¤ì¤Æ¤¤¤Þ¤¹¡£ ( http://www.vim.org/doc/vi.diff.txt ¤ò»²¾È²¼¤µ¤¤)
vim ¤Ï vi ¤Î¤Û¤È¤ó¤É¤¹¤Ù¤Æ¤Î¥³¥Þ¥ó¥É¤È¤Î¸ß´¹À-¤¬¤¢¤ê¤Þ¤¹¡£vi ¤Î¥Ð
¥°¤Ï½ü¤-¤Þ¤¹ ;-)
¥ª¥Ú¥ì¡¼¥Æ¥£¥ó¥°¡¦¥·¥¹¥Æ¥à¡ÊOS¡Ë
vim ¤Ï¿¤¯¤Î¥·¥¹¥Æ¥à¤Ç»È¤¨¤Þ¤¹: AmigaOS, Atari MiNT, BeOS, DOS,
MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, WIn16 + Win32
(Windows95/98/00/NT) - ÆÃ¤Ë FreeBSD and Linux. :-)
Ãøºî¸¢:
À©ºî¤ÈÊݼé¤ò¼ç¤Ë¹Ô¤Ê¤Ã¤Æ¤¤¤ë Bram Moolenaar »á <[email protected]> ¤Ë
Ãøºî¸¢¤¬¤¢¤ê¤Þ¤¹¡£
vim ¤Ï¥Á¥ã¥ê¥Æ¥£¡¼¥¦¥§¥¢¤Ç¤¹¡£¥¦¥¬¥ó¥À¤Î¸É»ù¤Ø¤Î´óÉÕ¤ò¤ª¾©¤á¤·¤Þ
¤¹¡£
¥½¡¼¥¹:
vim ¤Ï¥ª¡¼¥×¥ó¡¦¥½¡¼¥¹¤Ç¤¹¡¢³§¤µ¤ó¤«¤é¤Î²þÁ±¤Î¤ª¼êÅÁ¤¤¤ò´¿·Þ¤·¤Þ
¤¹¡£
=== µ¡Ç½
½é¿´¼Ô¤Î¥¨¥Ç¥£¥¿¡¢¥æ¡¼¥¶¤Ë¿ÆÀÚ:
vim ¤¬ vi ¤è¤ê¤â½é¿´¼Ô¤Ë¤ï¤«¤ê¤ä¤¹¤¤¤Î¤Ï¡¢¥ª¥ó¥é¥¤¥ó¡¦¥Ø¥ë¥×¤ä¡¢
¥³¥Þ¥ó¥É¤Î¼è¾Ã¤È¤ä¤êľ¤·¡Ê¼ºÇÔ¤òµ¤¤Ë¤»¤º¡¢Ã±¤Ë¼è¾Ã+¤ä¤êľ¤·¡Ë¤ä¡¢¥Þ
¥¦¥¹¤äÀßÄê²Äǽ¤Ê¥¢¥¤¥³¥ó¤ä¥á¥Ë¥å¡¼¤Î¥µ¥Ý¡¼¥È¡ÊGUI¡Ë¤¬¤¢¤ë¤«¤é¤Ç¤¹¡£
ʸ»ú¥³¡¼¥É¤ÈüËö¡Ê¥¨¥ß¥å¥ì¡¼¥¿¡Ë:
Vim ¤Ï iso-latin1 ʸ»ú¥»¥Ã¥È¤È¤½¤Î termcap ¤ò¥µ¥Ý¡¼¥È¤·¤Æ¤¤¤Þ¤¹¡£
(Vanilla Vi ¤Ï¤³¤³¤ËÌäÂê¤òÊú¤¨¤Æ¤¤¤Þ¤¹)
ʸ»ú¤È¸À¸ì:
vim ¤Ï±¦¤«¤éº¸¤Ë½ñ¤¯¸À¸ì¡ÊÎã: ¥¢¥é¥Ó¥¢¸ì¡¢¥Ú¥ë¥·¥ã¸ì¡¢¥Ø¥Ö¥é¥¤¸ì¡Ë
¤È¥Þ¥ë¥Á¥Ð¥¤¥È¡¦¥Æ¥-¥¹¥È¡¢¤Ä¤Þ¤êÃæ¹ñ¸ì¡¢ÆüËܸ졢´Ú¹ñ¸ì¡Ê¥Ï¥ó¥°¥ë¡Ë
¤Î¤è¤¦¤Ë 1 ¥Ð¥¤¥È¤è¤êŤ¤¥Ð¥¤¥ÈŤÇɽ¸½¤µ¤ì¤ë¥°¥é¥Õ¥£¥«¥ë¤Êʸ»ú¤ò¥µ
¥Ý¡¼¥È¤·¤Æ¤¤¤Þ¤¹¡£µ»½ÑŪ¤Ë¸À¤¦¤È¡¢UTF-8 ¤È ¥æ¥Ë¥³¡¼¥É¤Î¥Æ¥-¥¹¥È¤ò¥µ
¥Ý¡¼¥È¤·¤Æ¤¤¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡£)
¥Æ¥-¥¹¥È¡¦¥Õ¥©¡¼¥Þ¥Ã¥È¡ÊÀ°·Á¡Ë¤È¥Ó¥¸¥å¥¢¥ë¥â¡¼¥É:
vim ¤ò»È¤¨¤Ð¡¢¥Æ¥-¥¹¥È¤Î°ìÉô¤ò¥Ï¥¤¥é¥¤¥È¤¹¤ë¡Ê¿§¤òÊѤ¨¤ë¡Ë¤³¤È¤Ç
¡Ö¥Ó¥¸¥å¥¢¥ë¤Ë¡×ÁªÂò¤·¡¢Áàºî¤¹¤ë¤³¤È¤¬¤Ç¤-¤Þ¤¹¡£Î㤨¤Ð¡¢¥³¥Ô¡¼¡¢ºï
½ü¡¢ÃÖ´¹¡¢º¸±¦¤Î¥·¥Õ¥È¡¢Âçʸ»ú¡¿¾®Ê¸»úÊÑ´¹¡¢¥Æ¥-¥¹¥È¤Î»ú²¼¤²¤òÊݤÃ
¤¿¤Þ¤ÞÀ°·Á¤Ê¤É¤¬²Äǽ¤Ç¤¹¡£vim ¤Ï¶ë·Á¤Î¥Æ¥-¥¹¥È¥Ö¥í¥Ã¥¯¤òÁªÂò¡¿Áàºî
¤¹¤ë¤³¤È¤â¤Ç¤-¤Þ¤¹¡£
¼«Æ°¥³¥Þ¥ó¥É:
vim ¤Ï¼«Æ°¥³¥Þ¥ó¥É¤âÈ÷¤¨¤Æ¤¤¤Æ¡¢¡Ê¥Õ¥¡¥¤¥ëÆɤ߹þ¤ß»þ¤Ê¤ÉÍÍ¡¹¤Ê¥¤
¥Ù¥ó¥ÈȯÀ¸»þ¤Ë¡Ë¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤Ç¤-¤Þ¤¹¡£¡ÊÎã: °µ½Ì¤µ¤ì¤¿¥Õ¥¡¥¤¥ë¤Î
¼«Æ°²òÅà)
¹ç»ú¡Ê¤´¤¦¤¸, ¤¢¤ï¤»¤¸¡Ë¤ÎÆþÎÏ
vim ¤Ï 2 ʸ»ú¤òÁȤ߹ç¤ï¤»¤¿Æüì¤Êʸ»ú¤òÆþÎϤǤ-¤Þ¤¹¡£(Îã:¡Ö"¡×¤È
¡Öa¡×¤Ç¥¦¥à¥é¥¦¥È¤ÎÉÕ¤¤¤¿ a ¡Ë¾¤ÎÁȤ߹ç¤ï¤»¤òÄêµÁ¤¹¤ë¤³¤È¤â²Äǽ¤Ç
¤¹¡£
¥Õ¥¡¥¤¥ë·Á¼°¤Î¸¡½Ð¤ÈÊÑ´¹:
vim ¤Ï Dos, Mac, Unix ¤È¤¤¤Ã¤¿¥Õ¥¡¥¤¥ë¤Î¥¿¥¤¥×¤ò¼«Æ°¸¡½Ð¤·¤¿¤ê¡¢
¾¤Î¥Õ¥©¡¼¥Þ¥Ã¥È¤Ç³ÊǼ¤·¤¿¤ê¤¹¤ë¤³¤È¤â¤Ç¤-¤Þ¤¹¡£Windows ¤Î unix2dos
¤Ï¤â¤¦É¬Íפ¢¤ê¤Þ¤»¤ó¡£
ÍúÎò¡Ê¥Ò¥¹¥È¥ê¡Ëµ¡Ç½:
vim ¤Ï¥³¥Þ¥ó¥É¤È¸¡º÷¤ÎÍúÎò¤ò²±¤¨¤Æ¤¤¤ë¤Î¤Ç¡¢°ÊÁ°¤ËÆþÎϤ·¤¿¥³¥Þ¥ó
¥É¤ä¸¡º÷¥Ñ¥¿¡¼¥ó¤òºÆÆþÎϤ·¤¿¤ê¡¢½ñ¤-´¹¤¨¤ÆºÆȯ¹Ô¤¹¤ë¤³¤È¤¬¤Ç¤-¤Þ¤¹¡£
¥Þ¥¯¥íµ-Ï¿:
vim ¤Ê¤é¡¢²¿Å٤ⷫ¤êÊÖ¤µ¤ì¤ëºî¶È¤òºÆ¸½¤¹¤ë¤¿¤á¤ËÊÔ½¸ºî¶È¤ò¡Öµ-Ï¿¡×
¤Ç¤-¤Þ¤¹¡£
¥á¥â¥êÀ©¸Â:
vim ¤Î 1 ¹Ô¤¢¤¿¤ê¤ÎŤµ¤ä¥Ð¥Ã¥Õ¥¡¤Î¥µ¥¤¥º¤Ï vanilla Vi ¤ÈÈæ¤Ù¤ÆÈó
¾ï¤ËÂç¤-¤¯ÀßÄꤵ¤ì¤Æ¤¤¤Þ¤¹¡£
¥Þ¥ë¥Á¥Ð¥Ã¥Õ¥¡¤È²èÌÌʬ³ä:
vim ¤ÏÊ£¿ô¤Î¥Ð¥Ã¥Õ¥¡¤Î¥¨¥Ç¥£¥Ã¥È¤¬²Äǽ¤Ç¡¢²èÌ̤ò¤¤¤¯¤Ä¤«¤Î¥µ¥Ö¥¦
¥£¥ó¥É¥¦¤Ëʬ³ä¤Ç¤-¤Þ¤¹¡Ê¿åÊ¿Êý¸þ¤È¿âľÊý¸þ¤ÎξÊý¡Ë¡£¤½¤Î¤¿¤á¡¢Ê£¿ô
¥Õ¥¡¥¤¥ë¤äÊ£¿ô²Õ½ê¤òį¤á¤ë¤³¤È¤¬¤Ç¤-¤Þ¤¹¡£
¿ôÃͤÎÀè¹Ô»ØÄê:
vim ¤Ï vi ¤è¤ê¤â¿¤¯¤Î¥³¥Þ¥ó¥É¤ÇÀè¹Ô¿ôÃͤò»ØÄê¤Ç¤-¤Þ¤¹¡£¡ÊÎã: put¡Ë
¥é¥ó¥¿¥¤¥à¡¦¥Õ¥¡¥¤¥ë¡Ê¥Ø¥ë¥×¥Õ¥¡¥¤¥ë¤È¥·¥ó¥¿¥¯¥¹¡¦¥Õ¥¡¥¤¥ë¡Ë
vim ¤Ë¤ÏÍÍ¡¹¤Ê¥¨¥Ç¥£¥Ã¥È¤Î¾õ¶·¤Ë¹ç¤ï¤»¤¿ 70 ¤Î¥Ø¥ë¥×¥Õ¥¡¥¤¥ë¤¬ÍÑ
°Õ¤µ¤ì¤Æ¤¤¤Þ¤¹¡£¤¤¤¯¤Ä¤«¤Î¥Æ¥-¥¹¥È¤Ï OS ¤Ë¹ç¤ï¤»¤¿¤â¤Î¤Ç¤¹¡£
¥¹¥¯¥ê¥×¥È:
vim ¤Ë¤Ï¥¹¥¯¥ê¥×¥È¸À¸ì¤¬ÁȤ߹þ¤Þ¤ì¤Æ¤¤¤Æ¡¢´Êñ¤Ê³ÈÄ¥¤¬¤Ç¤-¤ë¤è¤¦
¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£
¸¡º÷¥ª¥Õ¥»¥Ã¥È:
vim ¤Ç¤Ï¸¡º÷¥³¥Þ¥ó¥É¤Ë¥ª¥Õ¥»¥Ã¥È¤ò»ØÄê¤Ç¤-¡¢¥Æ¥-¥¹¥È¤ò¸«¤Ä¤±¤¿¸å
¤Î¥«¡¼¥½¥ë¤Î°ÜÆ°Àè¤ò»ØÄê¤Ç¤-¤Þ¤¹¡£
¥»¥Ã¥·¥ç¥ó¡¦¥ê¥«¥Ð¥ê
vim ¤Ï¥¨¥Ç¥£¥Ã¥È¡¦¥»¥Ã¥·¥ç¥ó¤Î¾ðÊó¤ò¥Õ¥¡¥¤¥ë¡Êviminfo¡Ë¤ËÂàÈò¤·¡¢
¼¡²ó¤Îµ¯Æ°»þ¤Ë²óÉü¤¹¤ë¤³¤È¤¬¤Ç¤-¤Þ¤¹¡£ÂàÈò¡¿²óÉü¤Ç¤-¤ë¥¨¥Ç¥£¥Ã¥È¡¦
¥»¥Ã¥·¥ç¥ó¤ÏÎ㤨¤Ð¥Ð¥Ã¥Õ¥¡¥ê¥¹¥È¡¢¥Õ¥¡¥¤¥ë¥Þ¡¼¥¯¡¢¥ì¥¸¥¹¥¿¡¢¥³¥Þ¥ó
¥É¤È¸¡º÷¤Î¥Ò¥¹¥È¥ê¤Ê¤É¤Ç¤¹¡£
¥¿¥Ö¤Î¶õÇò²½:
vim ¤Ï¥¿¥Ö¤ò¶õÇò²½¤·¤Æ¥Æ¥-¥¹¥È¤Ë¤¹¤ë¤³¤È¤¬¤Ç¤-¤Þ¤¹¡£(expandtab,
:retab).
¥¿¥°:
vim ¤Ï tags ¥Õ¥¡¥¤¥ë¤ò»²¾È¤·¤ÆÆÀ¤¿¥¤¥ó¥Ç¥¯¥¹¤È¿¤¯¤Î¥¿¥°¡¦¥¹¥¿¥Ã
¥¯¡¦¥³¥Þ¥ó¥É¤ò»È¤Ã¤Æ¥Õ¥¡¥¤¥ëÆâ¤Î¥Æ¥-¥¹¥È¤ò¸¡º÷¤Ç¤-¤Þ¤¹¡£
¥Æ¥-¥¹¥È¡¦¥ª¥Ö¥¸¥§¥¯¥È:
vim ¤Ï¥Ñ¥é¥°¥é¥Õ¡¢¥»¥ó¥Æ¥ó¥¹¡¢word¡¢WORD¡¢¤¢¤ë¤¤¤Ï¤½¤ì¤é¤ò¶õÇò¤Ç
¤¯¤¯¤Ã¤¿¤â¤Î¤Ê¤É¤È¤¤¤Ã¤¿¡Ö¥Æ¥-¥¹¥È¥ª¥Ö¥¸¥§¥¯¥È¡×¤òǧ¼±¤·¡¢¤½¤ì¤é¤Î
ÄêµÁ¤òÀßÄꤹ¤ë¤³¤È¤â¤Ç¤-¤Þ¤¹¡£
¥·¥ó¥¿¥¯¥¹¤´¤È¤Î¿§¤Å¤±:
vim ¤Ï¥¨¥Ç¥£¥Ã¥È¤¹¤ë¥×¥í¥°¥é¥ß¥ó¥°¸À¸ì¤´¤È¤Ë¥Æ¥-¥¹¥È¤ò¿§ÉÕ¤±¤Ç¤-
¤Þ¤¹¡£
¤É¤ó¤Ê¸À¸ì¡Ê¥·¥ó¥¿¥¯¥¹¡Ë¤Î¥Õ¥¡¥¤¥ë¤Ç¤¢¤ë¤«¤òÄêµÁ¤¹¤ë¤³¤È¤â¤Ç¤-¤Þ¤¹¡£
ÆüìÍÑÅÓ¸þ¤±¤ËÍÑ°Õ¤µ¤ì¤¿¥³¡¼¥É:
vim ¤Ë¤Ï Perl, Tcl, Python ¸þ¤±¤Ë¥ª¥×¥·¥ç¥ó¤ÇÍÑ°Õ¤µ¤ì¤¿¤â¤Î¤¬¤¢¤ê
¤Þ¤¹¡£
vim ¤Ë¤Ï Windows ²¼¤Ç OLE ¥ª¡¼¥È¥á¡¼¥·¥ç¥ó¡¦¥µ¡¼¥Ð¤È¤·¤ÆÆ°ºî¤µ¤»
¤ë¥³¡¼¥É¤¬¤¢¤ê¤Þ¤¹¡£
vim ¤Ë¤Ï X-window ÍѤΥ³¡¼¥É¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤Æ¡¢ÀßÄê²Äǽ¤Ê¥á¥Ë¥å¡¼
¤ä¥Þ¥¦¥¹¤¬¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤¹¡£
¤Ê¤É¤Ê¤É¡¢Â¾¤Ë¤â¤¿¤¯¤µ¤ó¤¢¤ê¤Þ¤¹¡ª
vim ¤Îµ¡Ç½¤Ë´Ø¤¹¤ë¾Ü¤·¤¤µ-½Ò:
http://www.vim.org/why.html
¸¶Ãø (English):
Sven Guckes [email protected]
Last update: Tue Oct 03 20:00:00 MET DST 2000
°¡¿ë¼º:
VimÀº ¸¹Àº Ç÷§Æû¿¡¼- »ç¿ëÇÒ ¼ö ÀÖ°í, Vi¿¡ ºñÇØ ´õ ¸¹Àº Ãß°¡µÈ
±â´ÉµéÀ» °¡Áö°í ÀÖ´Ù. (http://www.vim.org/doc/vi.diff.txt Âü°í)
VimÀº °ÅÀÇ ¸ðµç Vi ¸í·É¾î¿Í ȣȯÀÌ µÈ´Ù. - Vi ÀÇ ¹ö±×¸¦ Á¦¿ÜÇÏ°í.. ;-)
¿î¿µÃ¼Á¦:
VimÀº ¸¹Àº ½Ã½ºÅÛ¿¡¼- »ç¿ëÇÒ ¼ö ÀÖ´Ù: amigaOS, Atari MiNT, BeOS, DOS,
MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, Win16 + Win32
(À©µµ¿ìÁî95/98/2000/NT) - FreeBSD¿Í ¸®´ª½º´Â ƯÈ÷³ª ´õ Àß Áö¿øÇÑ´Ù. :-)
ÀúÀÛ±Ç:
Vim¿¡ ´ëÇÑ ÀúÀÛ±ÇÀº, ÁÖ °³¹ßÀÚÀÌÀÚ °ü¸®ÀÚÀÎ Bram Moonlenaar
<[email protected]> ¿¡°Ô ÀÖ´Ù.
VimÀº "ÀÚ¼±¿þ¾î" ÀÌ´Ù. ¿ì°£´ÙÀÇ °í¾ÆµéÀ» À§ÇÑ ±âºÎ¸¦ ±ÇÀåÇÏ´Â ¹ÙÀÌ´Ù.
(Âü°í ":help ugand")
¼Ò½º:
VimÀº ¿ÀǼҽºÀÌ´Ù. °³¹ß¿¡ Âü¿©ÇÏ´Â ¸ðµç À̵éÀ» ȯ¿µÇÑ´Ù.
=== ±â´É
¹®ÀÚÄÚµå¿Í ´Ü¸»±â:
VimÀº iso-latain1 ¹®Àڼ°ú termcap À» Áö¿øÇÑ´Ù.
(±âÁ¸ÀÇ vi¿¡¼- ¹®Á¦°¡ µÇ´Â ºÎºÐÀÌ´Ù.)
¹®ÀÚ¿Í ¾ð¾î:
VimÀº ¿ìÃø¿¡¼- ÁÂÃøÀ¸·Î ¾²´Â ¾ð¾î (¿¹: ¾Æ¶ø¾î, À̶õ¾î, È÷ºê¸®¾î) ¿Í
¸ÖƼ¹ÙÀÌÆ® ¹®ÀÚ, Áï 1¹ÙÀÌÆ® ÀÌ»óÀ» Â÷ÁöÇϸé¼- ±×·¡ÇÈÀûÀ¸·Î Ç¥½Ã°¡
µÇ´Â ¾ð¾îÀÎ Áß±¹¾î, ÀϺ»¾î, Çѱ¹¾î ¹®ÀÚ¸¦ Áö¿øÇÑ´Ù.
(±â¼úÀûÀ¸·Î ¸»ÇÏÀÚ¸é, VimÀº UTF-8°ú Unicode¸¦ Áö¿øÇÑ´Ù.)
¸í·É¾î ¿Ï¼º±â´É:
VimÀº ÀÔ·ÂÇÏ´Â ¸í·É¾î³ª È-ÀÏÀ̸§ ¶Ç´Â ÀϹÝÀûÀÎ ´Ü¾î¸¦
´Ù ¾²±âµµ Àü¿¡ ¿Ï¼º½ÃÅ°´Â ±â´ÉÀ» °¡Áö°í ÀÖ´Ù.
ÀÚµ¿ ¸í·É¾î:
VimÀº ÀÚµ¿ ¸í·É¾î ±â´ÉÀ» °¡Áö°í ÀÖ´Ù. (Áï, ¾ÐÃàµÈ È-ÀÏÀ»
Àоîµå¸®´Â ¼ø°£¿¡ ÀÚµ¿À¸·Î ¾ÐÃàÇØÁ¦¸¦ ÇÏ¿© ·ÎµùÇÏ´Â °ÍÀÌ °¡´ÉÇÏ´Ù)
ÀÌÁßÀ½ÀÚ ÀÔ·Â:
Vim¿¡¼-´Â 2°³ÀÇ ¹®ÀÚ¸¦ Á¶ÇÕÇÏ¿© Ư¼öÇÑ ¹®ÀÚ¸¦ ÀÔ·ÂÇÒ ¼ö ÀÖ´Ù.
(¿¹: " ¿Í a ¸¦ ÀÌ¿ëÇÏ¿© À¯·´¾î¿¡ ÀÖ´Â ¾Ç¼¾Æ®ºÎÈ£°¡ µ¡ºÙ¿©Áø ¹®ÀÚ¸¦
ÀÔ·ÂÇÒ ¼ö ÀÖ´Ù) ¶ÇÇÑ, ´Ù¸¥ ¹æ½ÄÀÇ Á¶ÇÕµµ Á¤ÀÇÇÒ ¼ö ÀÖ´Ù.
À̷±â´É:
VimÀº ¸í·É¾î ¹× °Ë»ö¾î¿¡ ´ëÇÑ ÀÌ·ÂÀ» °¡Áö°í ÀÖ´Ù. µû¶ó¼-,
ÀÌÀüÀÇ ¸í·É¾î ¹× °Ë»ö¾î¸¦ ¾ó¸¶µçÁö ´Ù½Ã ºÎ¸¦¼ö ÀÖ°í ÆíÁýÇÏ¿©
Àç½ÇÇà ÇÒ ¼ö ÀÖ´Ù.
¸ÅÅ©·Î ±â·Ï:
VimÀº ÆíÁýÀÛ¾÷ °úÁ¤À» ±â·ÏÇÏ¿© ÀçÇöÇÏ´Â ±â´ÉÀ» °¡Áö°í ÀÖ¾î¼-,
¹Ýº¹ÀûÀÎ ÀÛ¾÷À» ¿ëÀÌÇÏ°Ô µµ¿ÍÁØ´Ù.
¸Þ¸ð¸® Á¦ÇÑ:
VimÀº ÇÑ ÁÙÀÇ ÃÖ´ë±æÀÌ¿Í ¹öÆÛÀÇ ÃÖ´ë Å©±â°¡, ±âÁ¸ÀÇ Vi¿¡
ºñÇÏ¿© ¿ùµîÇÏ°Ô ¸¹µµ·Ï ¸Þ¸ð¸®¸¦ ÇÒ´çÇÏ°í ÀÖ´Ù.
½ºÅ©¸³Æ®:
VimÀº ½ºÅ©¸³Æ® ¾ð¾î°¡ ³»ÀåµÇ¾î ÀÖ°í, À̸¦ ÅëÇÏ¿© ½±°Ô ±â´ÉÀ»
È®ÀåÇÒ ¼ö ÀÖ´Ù.
°Ë»ö ¿ÀÇÁ¼Â:
VimÀº °Ë»ö¸í·É¾î¿¡ ¿ÀÇÁ¼ÂÀ» ÁöÁ¤ÇÒ ¼ö ÀÖ´Ù. Áï, ã¾ÆÁø
°Ë»öÆÐÅÏÀÇ À§Ä¡·ÎºÎÅÍ ÁöÁ¤ÇÑ ¿ÀÇÁ¼Â ¸¸Å- À̵¿ÇÏ¿© Ä¿¼-¸¦ À§Ä¡
½Ãų ¼ö ÀÖ´Ù.
ÆíÁýȯ°æ º¹±¸±â´É:
VimÀº ÆíÁýȯ°æÀ» ƯÁ¤È-ÀÏ("viminfo")¿¡ ÀúÀåÇÏ¿©, ´ÙÀ½¹ø¿¡ vimÀ»
½ÇÇà½Ãų ¶§¿¡ ÀÌÀü°ú °°Àº ȯ°æÀ¸·Î º¹±¸µÉ ¼ö ÀÖµµ·Ï ÇÒ ¼ö ÀÖ´Ù.
¿¹¸¦ µé¾î, ¹öÆÛ ¸®½ºÆ®, È-ÀÏ ¸¶Å©, ·¹Áö½ºÅÍÀÇ ³»¿ë, ¸í·É¾î ¹×
°Ë»ö¾îÀÇ ±â·ÏµéÀÌ ÀÖ´Ù.
ÅÇ È®Àå:
VimÀº ±ÛÀÚµé ¾È¿¡ ¼¯¿© ÀÖ´Â ÅǵéÀ» ½ºÆäÀ̽º·Î È®Àå½ÃÅ°´Â ±â´ÉÀÌ ÀÖ´Ù.
(expandtab, :retab)
ÅÂ±× ½Ã½ºÅÛ:
VimÀº "tags" È-ÀÏÀÇ »öÀÎÀ» ÀоîµéÀÎ ÈÄ, ´Ù¾çÇÑ ÅÂ±× °ü·Ã ¸í·É¾î¸¦
»ç¿ëÇؼ-, ¿©·¯ È-Àϵ鿡 À§Ä¡ÇÑ °Ë»öÆÐÅÏÀ» ãÀ» ¼ö ÀÖµµ·Ï Áö¿øÇÑ´Ù.
ÅؽºÆ® ¿ÀºêÁ§Æ®:
VimÀº ¸¹Àº Á¾·ùÀÇ ¿ÀºêÁ§Æ® (´Ü¶ô, ¹®Àå, ´Ü¾î, ´ë¹®ÀÚ·Î ±¸¼ºµÈ ´Ü¾î
- ÀÌµé ¸ðµÎ °ø¹é¹®ÀÚ·Î ºÐ¸®µÈ´Ù) ¸¦ ÀνÄÇÑ´Ù. ¶ÇÇÑ, »ç¿ëÀÚ°¡ À̵é
ÅؽºÆ® ¿ÀºêÁ§Æ®¿¡ ´ëÇÑ Á¤ÀǸ¦ ÇÒ ¼ö ÀÖµµ·Ï Áö¿øÇÑ´Ù.
¹®¹ý Ä®¶ó¸µ:
VimÀº ÇÁ·Î±×·¡¹Ö ¾ð¾î¿¡ µû¶ó, È-ÀÏ ¾ÈÀÇ ÅؽºÆ®¸¦ ¹®¹ý¿¡ ¸Â°Ô
Ä®¶ó¸µ ÇØÁØ´Ù. ¶ÇÇÑ, "¾ð¾î" ("¹®¹ý") ¿¡ ´ëÇÑ »ç¿ëÀÚ Á¤ÀǸ¦ ÇÒ ¼ö
ÀÖµµ·Ï Áö¿øÇØÁØ´Ù.
Ư¼öÇÑ ÄÚµå:
VimÀº PerlÀ̳ª Tcl, Python °úÀÇ ÅëÇÕ±â´ÉÀ» ¿É¼ÇÀ¸·Î Á¦°øÇÑ´Ù.
VimÀº À©µµ¿ìÁî ȯ°æ¿¡¼- OLE ÀÚµ¿È-¼-¹ö·Î¼- ÀÛµ¿ÇÒ ¼ö ÀÖ´Ù.
VimÀº X-windows ¸¦ Áö¿øÇÏ´Â ÄÚµå·Î ¼³Ä¡µÉ ¼ö ÀÖ°í,
¼³Á¤ °¡´ÉÇÑ ¸Þ´º ¹× ¸¶¿ì½º¿¡ ´ëÇÑ Áö¿øÀÌ Á¦°øµÈ´Ù.
±× ¹Û¿¡µµ ¸¹ÀÌ. ÈξÀ ´õ ¸¹Àº ±â´ÉµéÀÌ ÀÖ´Ù!
VimÀÇ À¥ ȨÆäÀÌÁö´Â:
http://www.vim.org/
Dostêpno¶æ:
Vim jest dostêpny na wiele platform i posiada du¿o
dodatkowych funkcji w porównaniu z Vi (zobacz
http://www.vim.org/doc/vi.diff.txt). Polecenia Vim-a s± prawie
ca³kowicie zgodne z poleceniami Vi - za wyj±tkiem Vi-owych b³êdów. ;-)
Systemy operacyjne:
Vim jest dostêpny na takie systemy jak:
AmigaOS, Atari MiNT, BeOS, DOS, MacOS, NextStep, OS/2, OSF, RiscOS,
SGI, UNIX, VMS, Win16 + Win32 (Windows95/98/00/NT) - a zw³aszcza na
FreeBSD i Linux. :-)
Prawa autorskie:
Prawa autorskie posiada g³ówny autor i szef projektu, Bram Moolenaar
<[email protected]>. Vim jest "oprogramowaniem charytatywnym", to znaczy i¿
zachêcamy Ciê do z³o¿enia datku na sieroty z Ugandy (zobacz ":help
uganda").
¬ród³a:
Vim jest programem na otwartych ¼ród³ach (OpenSource) i wszyscy
chêtni do pomocy przy jego rozwoju, s± zawsze mile widziani!
Polecenia automatyczne:
Vim posiada równie¿ polecenia pozwalaj±ce na automatyczn± reakcjê na
dane zdarzenia ("autocommands"), np. na automatyczne rozpakowanie
skompresowanego pliku.
Wstawianie umlaut-ów:
Vim pozwala na wstawianie znaków specjalnych poprzez kombinacjê dwóch
klawiszy (np. kombinacja " oraz a daje w wyniku ä), oraz pozwala na
zdefiniowanie w³asnych kombinacji.
Historia:
Vim posiada historiê poleceñ oraz wyszukiwañ. Mo¿esz zatem przywo³aæ
poprzednie polecenie lub wyszukiwany ci±g znaków i zmieniæ go.
Nagrywanie makr:
Vim umo¿liwia zarejestrowanie procesu edycji (wszystkich wpisywanych
poleceñ), w celu pó¼niejszego wykorzystania przy zadaniach
powtarzalnych.
Ograniczenia pamiêci:
Vim ma znacznie wy¿sze limity pamiêci przydzielanej dla poszczególnych
linii i buforów ni¿ oryginalny Vi.
Zwielokrotnianie poleceñ:
Vim umo¿liwia zwielokrotnianie dzia³ania poleceñ (poprzez tzw. "number
prefix"). Obejmuje ono wiêkszy zakres komend, ni¿ ma to miejsce w Vi.
Skrypty:
Vim posiada wbudowany jêzyk skryptowy, który mo¿e s³u¿yæ do jego
³atwej rozbudowy.
Wyszukiwanie z przesuniêciem:
Vim umo¿liwia przesuniêcia w poleceniach wyszukuj±cych. Oznacza to,
umieszczenie kursora *za* znalezionym tekstem.
Zapis sesji:
Vim umo¿liwia zapis informacji o danej sesji do pliku ("viminfo").
Mo¿e on byæ u¿yty w nastêpnej sesji do odczytania listy buforów,
znaczników w plikach, rejestrów, historii poleceñ i wyszukiwañ.
System Tag-ów:
Vim potrafi korzystaæ z plików indeksowych typu "tags" w celu
odszukania tekstu w plikach, oraz posiada wiele poleceñ z nich
korzystaj±cych.
Czê¶ci tekstu:
Vim rozpoznaje wiele czê¶ci tekstu, takich jak akapity, zdania, s³owa
i S£OWA - zarówno z otaczaj±cymi je bia³ymi znakami jak i bez nich.
Pozwala równie¿ na zmianê ich definicji.
Kolorowanie sk³adni:
Vim wy¶wietla tekst koloruj±c go - zgodnie z jego "jêzykiem
(programowania)". Mo¿esz samodzielnie zdefiniowaæ "jêzyk" (czyli jego
sk³adniê).
Dodatki specjalne:
Vim opcjonalnie posiada zintegrowane ¶rodowiska do pisania w takich
jêzykach jak Perl, Tcl i Python. Vim mo¿e pe³niæ rolê serwera OLE pod
Windows. Vim mo¿e byæ równie¿ zainstalowany z obs³ug± X-Windows,
w³±czaj±c w to konfigurowalne menu i obs³ugê myszy.
Vim mo¿e jeszcze du¿o innych rzeczy. Naprawdê du¿o!
=== Linki
vim: tw=70
"O que é Vim?"
Uma explicação em seis kilobytes.
Disponibilidade:
O Vim está disponível para muitas plataformas e tem muitas características
adicionais comparado ao Vi. (veja http://www.vim.org/doc/vi.diff.txt)
Vim é compatível com quase todos os comandos do Vi - exceto com bugs do Vi. :-)
Sistemas Operacionais:
O Vim está disponível para muitos sistemas: AmigaOS, Atari MiNT, BeOS, DOS,
MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, Win16 + Win32
(Windows95/98/00/NT) - e especialmente FreeBSD e Linux. :-)
Fonte:
O Vim é OpenSource e todos são bem-vindos para ajudar a melhorá-lo!
=== Características
Caracteres e Línguas:
O Vim suporta edição da direita-para-esquerda (por exemplo com Árabe, Farsi,
Hebreu), e textos multi-byte, isto é, linguagens com caracteres gráficos
representados por mais de um "byte", como o Chinês, Japonês, Coreano (Hangul),
(Técnicamente falando, Vim suporta texto em UTF-8 e Unicode.)
Comandos de Completação:
O Vim tem comandos que completam sua entrada de dados -
seja com comandos, nomes de arquivos, e palavras.
Comandos Automáticos:
O Vim tem também "autocomandos" para a execução automática de comandos
(por exemplo descompressão automática de arquivos comprimidos).
Entrada de Caracteres Especiais (Digraphs):
O Vim permite que você incorpore caracteres especiais por uma combinação
de dois caracteres (por exemplo a combinação de " e a produz um ä) -
e permite também que você defina outras combinações.
História:
O Vim tem uma "história" para comandos e buscas, assim você pode
rever comandos anteriores ou buscar padrão para editá-los.
Gravando Macro:
O Vim permite "gravar" sua edição para reusar em tarefas repetitivas.
Limites de Memória:
O Vim tem limites de memória muito mais elevados para comprimento de linha
e tamanho de buffer do que o Vi.
Scripting:
O Vim tem uma linguagem de script interna para extensão fácil.
Deslocamento de Busca:
O Vim permite deslocamentos para comandos de busca, assim você
coloca o cursor *após* o texto encontrado.
Recuperação da Sessão:
O Vim permite armazenar informação de uma sessão de edição em um arquivo
("viminfo") que os permite usar com a próxima sessão de edição, por exemplo
lista de buffer, marcas de arquivos, registros, comandos e história de buscas.
Expansão da Tabulação:
Vim pode expandir as tabulações dentro do texto com espaços (expandtab, :retab).
Objetos de Texto:
Vim conhece mais objetos de texto (parágrafos, sentenças, palavras e PALAVRAS -
todas com ou sem espaço em branco em volta) e permite configurar
a definição para estes objetos.
Coloração da Sintaxe:
O Vim mostra texto em cor - de acordo com sua "linguagem (de programação)".
Você mesmo pode definir a ("sintaxe") "da linguagem" dos arquivos.
Código Especial:
O Vim tem integração opcional com Perl, Tcl e Python.
O Vim pode atuar como um servidor de automatização OLE sob o Windows.
O Vim pode também ser instalado com código para X-Windows,
adicionando menus configuráveis e suporte para o mouse.
E mais. Muito mais!
Vim ("Vi IMproved", adicã "Vi ÎMbunãtãþit") este o clonã Vi, un program
asemãnãtor editorului de text "Vi".
Disponibilitate:
Vim este disponibil pentru nenumãrate platforme ºi are multe caracteristici
în plus, comparativ cu Vi. (vezi http://www.vim.org/doc/vi.diff.txt)
În ceea ce priveste comenzile, intre Vim ºi Vi existã o mare compatibilitate
(cu excepþia bug-urilor proprii Vi-ului ;-)
Sisteme de operare:
Vim este disponibil pentru aproape orice sistem: AmigaOS, Atari MiNT, BeOS, DOS,
MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, Win16 + Win32
(Windows95/98/00/NT) - ºi, în mod special, pentru FreeBSD ºi Linux. :-)
Copyright:
Copyright-ul aparþine principalului sãu autor, Braam Moolenaar <[email protected]>.
Vim este un program de caritate ("charity-ware"), adicã vã îndeamnã sã faceþi
donaþii orfanilor din Uganda (vezi ":help uganda").
Sursa:
Vim este OpenSource ºi oricine este binevenit sã ajute la îmbunãtãþirea lui!
=== Caracteristici
Flexibilitate lingvisticã:
Vim permite culegerea textului de la dreapta la stînga (destul de necesar
pentru a scrie, spre exemplu, în arabã, persanã sau ebraicã) ºi chiar
culegerea de text multi-octet, adicã text cu caractere grafice reprezentînd
mai mult de un octet, cum sînt cele proprii limbilor chinezã, japonezã sau
coreanã. Tehnic vorbind, Vim suportã text scris în UTF-8 ºi Unicode.
Comenzi de completare:
Vim dispune de posibilitatea de a completa în mod automat numele comenzilor,
directoarelor, fiºierelor ºi, încã posibilitatea de a completa în mod automat
cuvintele sau sintagmele cheie din help-ul online.
Comenzi automate:
Vim oferã, deasemenea, posibilitatea de execuþie automatã a comenzilor (spre
exemplu: compresia ºi decompresia automata a fiºierelor).
Istoric:
Vim reþine istoricul comenzilor ºi cãutãrilor. Puteþi sã reexecutaþi o comandã
anterioarã ºi sã reapelaþi o cãutare.
Crearea macrocomenzilor:
Vim vã permite "înregistrarea" unei serii de acþiuni pentru a le putea executa
din nou atunci cînd veþi avea de fãcut acelaºi lucru.
Limite de memorie:
Vim are o limitã de memorie mai mare, atît pentru lungimea unei linii, cît ºi
pentru mãrimea unui tampon de memorie; --asta în comparaþie cu Vi.
Limajul de scripting:
Vim are un limbaj de scripting incorporat pentru a fi mai uºor extins.
Extensia tabulaturii:
Vim permite expandarea tab-urilor dintr-un text folosind caractere spaþiu
(expandtab, :retab).
Sistemul de etichete (Tags):
Vim vã permite sã gãsiþi un text într-un fiºier oarecare utilizînd un indice
de etichete (tags); referitor la aceasta, Vim are multe alte comenzi prin
care se poate manipula un astfel de indice de etichete.
Colororarea sintacticã:
Vim permite redarea textului în diferite culori în funcþie de sintaxa
"limbajului (de programare)" utilizat. Dv. înºivã puteþi defini "limbajul"
("sintaxa") fiºierelor pe care le folosiþi.
Cod special:
Vim poate fi integrat în mod opþional cu Perl, Tcl ºi Python. Vim poate servi
drept server OLE sub Windows. Deasemenea, vim poate fi instalat cu suport
pentru X-Windows avînd meniuri configurabile ºi suport pentru mouse.
ªi multe, multe alte facilitãþi!
ðÒÉÇÏÄÎÏÓÔØ:
Vim ÄÏÓÔÕÐÅÎ ÄÌÑ ÍÎÏÖÅÓÔ×Á ÐÌÁÔÆÏÒÍ, É, ÐÏ ÓÒÁ×ÎÅÎÉÀ Ó Vi, ÉÍÅÅÔ ÍÎÏÇÏ
ÄÏÐÏÌÎÉÔÅÌØÎÙÈ ÆÕÎËÃÉÊ (ÓÍ. http://www.vim.org/doc/vi.diff.txt) Vim
ÓÏ×ÍÅÓÔÉÍ ÐÏÞÔÉ ÓÏ ×ÓÅÍÉ ËÏÍÁÎÄÁÍÉ Vi - ËÒÏÍÅ ÔÅÈ, ËÏÔÏÒÙÅ ÎÅ
ÒÁÂÏÔÁÀÔ. ;-)
ïÐÅÒÁÃÉÏÎÎÙÅ ÓÉÓÔÅÍÙ:
÷Ù ÍÏÖÅÔÅ ÉÓÐÏÌØÚÏ×ÁÔØ Vim ÎÁ ÍÎÏÇÉÈ ïó: AmigaOS, Atari MiNT, BeOS,
DOS, MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, Win16 + Win32
(Windows95/98/00/NT) - Á ÏÓÏÂÅÎÎÏ FreeBSD É Linux. :-)
ðÒÁ×Á:
ðÒÁ×Á ÎÁ ÐÒÏÇÒÁÍÍÕ ÐÒÉÎÁÄÌÅÖÁÔ ÇÌÁ×ÎÏÍÕ Á×ÔÏÒÕ É ËÏÏÒÄÉÎÁÔÏÒÕ, Bram
Moolenaar <[email protected]>. Vim Ñ×ÌÑÅÔÓÑ "ÂÌÁÇÏÔ×ÏÒÉÔÅÌØÎÏÊ
ÐÒÏÇÒÁÍÍÏÊ", Ô.Å. ×Ù ÍÏÖÅÔÅ ×ÙÒÁÚÉÔØ ÂÌÁÇÏÄÁÒÎÏÓÔØ ÄÅÌÁÑ ×ÚÎÏÓ ÓÉÒÏÔÁÍ
õÇÁÎÄÙ (ÓÍ. ":help uganda").
éÓÈÏÄÎÙÊ ËÏÄ:
Vim ÜÔÏ ÐÒÏÇÒÁÍÍÁ Ó ÏÔËÒÙÔÙÍ ËÏÄÏÍ, É ×ÁÛÁ ÐÏÍÏÝØ × ÕÌÕÞÛÅÎÉÉ Vim'Á
ÂÕÄÅÔ ÐÒÉÎÑÔÁ Ó ÒÁÓÐÒÏÓÔÅÒÔÙÍÉ ÏÂßÑÔØÑÍÉ!
=== æÕÎËÃÉÏÎÁÌØÎÏÓÔØ
óÉÍ×ÏÌÙ É ÑÚÙËÉ:
Vim ÐÏÄÄÅÒÖÉ×ÁÅÔ ÒÅÄÁËÔÉÒÏ×ÁÎÉÅ "ÓÐÒÁ×Á ÎÁÌÅ×Ï", (ÎÁÐÒÉÍÅÒ, ÄÌÑ
áÒÁÂÓËÏÇÏ, ðÅÒÓËÏÇÏ ÑÚÙËÏ×, é×ÒÉÔÁ), É ÍÎÏÇÏÂÁÊÔÏ×ÙÅ ÓÉÍ×ÏÌÙ, Ô.Å.
ÑÚÙËÉ × ËÏÔÏÒÙÈ ÉÓÐÏÌØÚÕÀÔÓÑ ÉÅÒÏÇÌÉÆÙ, ÎÁÐÒÉÍÅÒ ëÉÔÁÊÓËÉÊ, ñÐÏÎÓËÉÊ,
ëÏÒÅÊÓËÉÊ (Hangul), (çÏ×ÏÒÑ ÔÅÈÎÉÞÅÓËÉÍ ÑÚÙËÏÍ, Vim ÐÏÄÄÅÒÖÉ×ÁÅÔ
ÔÅËÓÔÙ × UTF-8 É Unicode.)
á×ÔÏËÏÍÍÁÎÄÙ:
íÏÖÎÏ ÉÓÐÏÌØÚÏ×ÁÔØ "Á×ÔÏËÏÍÁÎÄÙ" ÄÌÑ Á×ÔÏÍÁÔÉÞÅÓËÏÇÏ ÉÓÐÏÌÎÅÎÉÑ
ÄÅÊÓÔ×ÉÊ (ÎÁÐÒÉÍÅÒ, ÄÌÑ Á×ÔÏÍÁÔÉÞÅÓËÏÇÏ ÞÔÅÎÉÑ ÓÖÁÔÙÈ ÆÁÊÌÏ×).
÷×ÏÄ ÄÉÇÒÁÆÏ×:
Vim ÐÏÚ×ÏÌÑÅÔ ××ÏÄÉÔØ ÓÐÅÃÉÁÌØÎÙÅ ÓÉÍ×ÏÌÙ ËÏÍÂÉÎÁÃÉÅÊ Ä×ÕÈ ÓÉÍ×ÏÌÏ×, É
ÐÏÚ×ÏÌÑÅÔ ÏÐÒÅÄÅÌÑÔØ Ó×ÏÉ ËÏÍÂÉÎÁÃÉÉ. (ÎÁÐÒÉÍÅÒ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÅ
ÎÁÖÁÔÉÅ Å É : ÍÏÖÅÔ ÄÁ×ÁÔØ £)
éÓÔÏÒÉÑ ××ÏÄÁ:
Vim ÐÏÚ×ÏÌÑÅÔ ×ÅÓÔÉ "ÉÓÔÏÒÉÀ" ËÏÍÁÎÄ É ÐÏÉÓËÏ×, ÔÁË ÞÔÏ ÍÏÖÎÏ
×ÙÐÏÌÎÑÔØ É ÒÅÄÁËÔÉÒÏ×ÁÔØ ÐÒÅÄÙÄÕÝÉÅ ËÏÍÁÎÄÙ É ÛÁÂÌÏÎÙ ÐÏÉÓËÁ.
úÁÐÉÓØ ÍÁËÒÏÓÏ×:
Vim ÐÏÚ×ÏÌÑÅÔ "ÚÁÐÉÓÙ×ÁÔØ" ×ÁÛÉ ÄÅÊÓÔ×ÉÑ ÄÌÑ ×ÙÐÏÌÎÅÎÉÑ ÐÏ×ÔÏÒÑÀÝÉÈÓÑ
ÏÐÅÒÁÃÉÊ.
ïÇÒÁÎÉÞÅÎÉÑ ÐÁÍÑÔÉ:
Vim ÍÏÖÅÔ ×ÙÄÅÌÑÔØ ÐÁÍÑÔØ ÄÌÑ ÓÔÒÏË É ÂÕÆÅÒÏ× ÂÏÌØÛÉÈ, ÞÅÍ ÐÏÚ×ÏÌÑÅÔ
Vi.
óËÒÉÐÔÙ:
Vim ÓÏÄÅÒÖÉÔ ×ÓÔÒÏÅÎÎÙÊ ÓËÒÉÐÔÏ×ÙÊ ÑÚÙË ÄÌÑ ÐÒÏÓÔÏÇÏ ÄÏÂÁ×ÌÅÎÉÑ ÎÏ×ÙÈ
×ÏÚÍÏÖÎÏÓÔÅÊ.
óÉÓÔÅÍÁ ÔÅÇÏ×:
Vim ÍÏÖÅÔ ÉÓÐÏÌØÚÏ×ÁÔØ ÓÉÓÔÅÍÕ "ÔÅÇÏ×" ÄÌÑ ÉÎÄÅËÓÉÒÏ×ÁÎÉÑ É ÐÏÉÓËÁ ×
ÔÅËÓÔÅ, ÐÒÉ ÜÔÏÍ ÍÏÖÎÏ ÐÏÌØÚÏ×ÁÔØÓÑ "ÓÔÅËÏÍ" ÐÏÓÅÝÅÎÎÙÈ ÔÅÇÏ×.
ïÂßÅËÔÙ × ÔÅËÓÔÅ:
Vim ÒÁÓÐÏÚÎÁÅÔ ÍÎÏÇÏ ÏÂßÅËÔÏ× × ÔÅËÓÔÅ (ÐÁÒÁÇÒÁÆÙ, ÐÒÅÄÌÏÖÅÎÉÑ, ÓÌÏ×Á,
óìï÷á - ×ËÌÀÞÁÑ ÉÌÉ ÎÅ ×ËÌÀÞÁÀ ÏËÒÕÖÁÀÝÉÅ ÐÒÏÂÅÌÙ) É ÐÏÚ×ÏÌÑÅÔ
ÉÚÍÅÎÑÔØ ÏÐÒÅÄÅÌÅÎÉÑ ÎÅËÏÔÏÒÙÈ ÏÂßÅËÔÏ×.
ðÏÄÓ×ÅÞÉ×ÁÎÉÅ ÓÉÎÔÁËÓÉÓÁ:
Vim ÐÏËÁÚÙ×ÁÅÔ ÔÅËÓÔ × Ã×ÅÔÅ - × ÓÏÏÔ×ÅÔÓÔ×ÉÉ Ó ÓÉÎÔÁËÓÉÓÏÍ. ÷Ù
ÍÏÖÅÔÅ ÏÐÒÅÄÅÌÑÔØ ÓÉÎÔÁËÓÉÓ ÆÁÊÌÁ ÓÁÍÉ.
óÐÅÃÉÁÌØÎÙÊ ËÏÄ:
Vim ÍÏÖÅÔ ÉÎÔÅÇÒÉÒÏ×ÁÔØÓÑ Ó Perl, Tcl É Python. Vim ÍÏÖÅÔ ÉÇÒÁÔØ ÒÏÌØ
OLE automation server ÐÏÄ Windows. Vim ÍÏÖÅÔ ÂÙÔØ ÕÓÔÁÎÏ×ÌÅÎ Ó ËÏÄÏÍ
ÄÌÑ X-windows, ÐÏÚ×ÏÌÑÀÝÉÍ ËÏÎÆÉÇÕÒÉÒÏ×ÁÔØ ÍÅÎÀ É ÐÏÄÄÅÒÖÉ×ÁÀÝÉÍ ÍÙÛØ.
Vim no solo trabaja en modo de texto en cualquier terminal, sino que también
tiene un interfaz gráfica para el usuario, es decir, menús y soporte para el
ratón.
Disponibilidad:
Vim está disponible para muchas plataformas y tiene muchas características
añadidas en comparación con VI. (véase http://www.vim.org/doc/vi.diff.txt)
Vim es compatible con casi todos los comandos de VI - excepto con los errores
(bugs) en VI. ;-)
Sistemas Operativos:
Vim está disponible para muchos sistemas: AmigaOS, Atari MiNT, BeOS,
DOS, MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, Win16 + Win32
(Windows95/98/00/NT) - y especialmente FreeBSD y Linux.
Copyright:
El copyright está en las manos del autor principal y mantenedor, Bram
Moolenaar <[email protected]>. Vim es un "programa-de-caridad" ("charity-ware"),
es decir que se sugiere que hagas una donación a los huérfanos en Uganda
(véase ":help Uganda ").
Fuente:
Vim es OpenSource y todos son bienvenidos para ayudar a mejorarlo!
=== Características
Caracteres y lenguajes:
Vim soport editar de derecha-a-izquierda (ej. con el Árabe, Farsi,
Hebreo), y textos en multi-octeto, es decir, lenguajes con caracteres
gráficos representados por más de un "octeto", por
ejemplo Chino, Japonés, Coreano (Hangul), (técnicamente
hablando, Vim soporta texto escrito en UTF-8 y Unicode.)
Comandos de Completación:
Vim tiene comandos que completan su entrada de información - sea con
comandos, nombres de fichero, o palabras.
Comandos Automáticos:
Vim también tiene "autocommands" para la ejecución
automática de los comandos (ej. decompresión automática
de ficheros comprimidos).
Historia:
Vim tiene una "historia" para los comandos y las búsquedas,
así que usted puede llamar nuevamente los comandos o el patrón
de búsqueda anteriores para editarlos.
Grabación de Macro:
Vim permite "grabar" una serie de acciones de edición para
poder ejecutarlas nuevamente cuando se realizan tareas repetitivas.
Límites de la Memoria:
Vim tiene límites de memoria mucho más grandes para la longitud
de línea y el tamaño del almacenador intermediario (buffer) en
comparación con VI normal.
Lenguaje de escritura:
Vim tiene un lenguaje de escritura incorporado para poder extenderlo
facilemente.
Recuperación de la Sesión:
Vim permite para salvar la información de una sesión de
edición en un fichero ("viminfo") lo cual permite que sean
usados en una subsecuente sesión de edición, ej. la lista de
almacenadores intermediarios, de las marcas de fichero, de los registros,
comandos y de la historia de las búsquedas.
Extensión de la Tabulación:
Vim puede expandir las tabulaciones dentro del texto usando caracteres de
espacio (expandtab,:retab).
Objetos de Texto:
Vim sabe de muchos objetos de texto (párrafos, sentencias, palabras y
PALABRAS - todas con y sin el espacio en blanco circundante) y permite el
configurar la definición de cada uno de estos objetos.
Colorisación de la Sintaxis:
Vim muestra el texto en color - según su "lenguaje (de programación)". Usted
mismo puede definir el "lenguaje" ("sintaxis") de los ficheros.
Vim viene con 200+ ficheros de sintaxis para la colorisación del texto
en los lenguajes de programación comunes (Ada, C, C++, Eiffel, FORTRAN,
Haskell, Java, lisp, Modula, PASCAL, prólogo, Python, esquema, palique,
SQL, Verilog, VisualBasic), programas de matemáticas (arce, Matlab,
Mathematica, SAS), texto que use marcado específico (DocBook, HTML,
LaTeX, PostScript, SGML-LinuxDoc, TeX, WML, XML), retornos de programas (diff,
hombre), ficheros de la configuració de programas (4DOS, Apache,
autoconfig, BibTeX, CSS, CVS, olmo, IDL, LILO, pino, procmail, samba, el
slrn), lenguajes de escritura del procesador de comandos (shell) y de
configuración (shells: sh, golpe, csh, ksh, zsh), lenguajes de la
escritura (awk, Perl, sed, yacc), ficheros de sistema (printcap, Xdefaults) y
por supuesto para Vim y sus textos de ayuda.
Código Especial:
Vim tiene integración opcional con Perl, Tcl y Python.
Vim puede actuar como servidor para la automatización de OLE
bajo Windows.
Vim se puede también instalarse con el código para soporte de
X-Windows, agregando menús y ayuda configurables con el ratón.
Y más. ¡Mucho más!
Tillgänglighet:
Vim finns för många plattformar och har åtskilliga nya funktioner
i förhållande till Vi. (se http://www.vim.org/doc/vi.diff.txt)
Vim stöder nästan alla Vi-kommandon - förutom Vi:s buggar. ;-)
Operativsystem:
Vim finns tillgängligt på många olika system: AmigaOS, Atari MiNT,
BeOS, DOS, MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS,
WIn16 + Win32 (Windows95/98/00/NT) - och särskilt FreeBSD och Linux.
Copyright:
Rättigheterna ägs av huvudupphovsmannen Bram Moolenaar <[email protected]>.
Vim är så kallad "charity-ware", vilket innebär att du som använder
programmet uppmanas donera pengar till föräldralösa barn i Uganda
(se ":help uganda").
Källkod:
Vim är OpenSource och alla som vill hjälpa till att göra
förbättringar till programmet välkomnas!
=== Features
Nybörjareditor - användarvänlighet:
Vim är ett mycket mera lättanvänt program än Vi på grund av
sin omfattande hjälpfunktionalitet, UNDO- och REDO-kommandon för
att underlätta när du råkar skriva fel, mus-support samt
konfigurerbara ikoner och menyer.
Kommandoradskomplettering:
Vim har funktioner som kompletterar din inmatning -
både när det gäller kommandon, filnamn och ord.
Automatiska kommandon:
Vim har också "autocommands" för att automatiskt exekvera olika
filterfunktioner på din text, till exempel att automatiskt packa
upp en komprimerad fil.
Digraph Input:
Vim låter dig skriva specialtecken genom kombinationer av två
tangenttryckningar (till exempel ger kombinationen av " och A
tecknet Ä, vilket möjligen inte är så intressant om du har
ett svenskt tangentbord, men du kan själv definiera kombinationer
för andra specialtecken.)
History:
Vim har en "history"-funktion för kommandon och sökningar, så att du
kan återkalla tidigare givna inmatningar, eventuellt editera dessa
och sedan exekvera dem igen.
Makrofunktioner:
Vim tillåter dig att "spela in" din editering för att sedan "spela upp"
den igen om du gör repetitiva serier av kommandon.
Minnesbegränsningar:
Med Vim kan du använda mycket större buffertar och skriva mycket
längre textrader än vad som är möjligt med Vanilla Vi.
Skript:
Vim har ett inbyggy skript-språk som ger möjlighet att enkelt
bygga ut funktionaliteten.
Sökoffsetter:
Vim tillåter offsetter in samband med sökning, så att du
exempelvis kan placera markören *efter* den funna texten.
Återställning av session:
Vim kan ställas in att automatiskt spara information om en editering
som återanvänds nästa gång man startar programmet. Denna information
inbegriper bland annat listor med buffertar, markeringar i filen samt
kommando- och sökningslistor.
Tabulatorexpansion:
Vim har funktioner för att expandera tabbar i texten till ett antal
mellanslag.
Taggar:
Vim har en funktionalitet som möjliggör sökning i textfiler genom
att man anger ett index med en "tag" tillsammans med flera olika
kommandon mot stackar.
Textobjekt:
Vim känner igen flera "textobjekt", såsom stycken, meningar och ord -
i samtliga fall med och utan omliggande blanksteg, samt tillåter dig
att ändra definitionen av sådana objekt.
Syntaxfärgning:
Vim visar texten i färg på ett sätt som är knutet till det "språk" eller
den typ av text som skrivs. Du kan själv definiera syntaxer för
dina filer som det passar dig. Vim leveraras med över 200 färdiga sådana
syntaxfiler för att fägsätta text i vanliga programspråk (Ada, C, C++,
Eiffel, Fortran, Haskell, Java, Lisp, Modula, Pascal, Prolog, Python,
Scheme, Smalltalk, SQL, Verilog, VisualBasic), matematiska språk
(Maple, Matlab, Mathematica, SAS), "markup"-språk (DocBook, HTML, LaTeX,
Postscript, SGML-LinuxDoc, TeX, WML, XML), output från program (diff, man),
konfigurationsfiler för program (4DOS, Apache, autoconfig, BibTeX, CSS,
CVS, elm, IDL, LILO, pine, procmail, samba, slrn), shell scripts och
konfigurationsfiler för shells (sh, bash, csh, ksh, zsh), skriptspråk (awk,
Perl, sed, yacc), systemfiler (printcap, .Xdefaults) och naturligtvis
för Vim och dess hjälptexter.
Särskilda funktioner:
Vim har som tillvalsfunktionalitet särskild integration
med Perl, Tcl och Python. Programmet kan också fungera
som en OLE automation server under Windows. Vidare kan Vim
också installeras med kod för X Window System med stöd
för konfigurerbara menyer och användning av mus.
äÏÓÔÕÐÎiÓÔØ:
Vim iÓÎÕ¤ ÄÌÑ ÒiÚÎÉÈ ÐÌÁÔÆÏÒÍ, i, ÐÏÒi×ÎÑÎÏ Ú Vi, ÍÁ¤ ÂÁÇÁÔÏ
ÄÏÄÁÔËÏ×ÉÈ ÆÕÎËÃiÊ (ÄÉ×. http://www.vim.org/doc/vi.diff.txt) Vim
ÓÕÍiÓÎÉÊ ÍÁÊÖÅ Ú ÕÓiÍÁ ËÏÍÁÎÄÁÍÉ Vi - ËÒiÍ ÔÉÈ, Ú×iÓÎÏ, ËÏÔÒi ÎÅ
ÐÒÁÃÀÀÔØ. ;-)
ïÐÅÒÁÃiÊÎi ÓÉÓÔÅÍÉ:
÷É ÍÏÖÅÔÅ ËÏÒÉÓÔÕ×ÁÔÉÓÑ Vim'ÏÍ ÎÁ ÂiÌØÛÏÓÔi ïó: AmigaOS, Atari MiNT,
BeOS, DOS, MacOS, NextStep, OS/2, OSF, RiscOS, SGI, UNIX, VMS, Win16 +
Win32 (Windows95/98/00/NT) - Á ÏÓÏÂÌÉ×Ï FreeBSD ÔÁ Linux. :-)
÷ÌÁÓÎiÓÔØ:
ðÒÁ×Á ÎÁ ÐÒÏÇÒÁÍÕ ÎÁÌÅÖÁÔØ ÇÏÌÏ×ÎÏÍÕ Á×ÔÏÒÕ ÔÁ ËÏÏÒÄÉÎÁÔÏÒÕ, Bram
Moolenaar <[email protected]>. Vim ¤ "ÂÌÁÇÏÄiÊÎÏÀ ÐÒÏÇÒÁÍÏÀ", ÔÏÂÔÏ ×É
ÍÏÖÅÔÅ ×ÉËÁÚÁÔÉ Ó×ÏÀ ×ÄÑÞÎiÓÔØ Á×ÔÏÒÁÍ ÐÒÏÇÒÁÍÉ ÄÏÐÏÍÁÇÁÀÞÉ ÓÉÒÏÔÁÍ
õÇÁÎÄÉ (ÄÉ×. ":help uganda").
ðÏÞÁÔËÏ×ÉÊ ËÏÄ:
Vim ÃÅ ÐÒÏÇÒÁÍÁ Ú ×iÄËÒÉÔÉÍ ËÏÄÏÍ, i ×ÁÛÁ ÄÏÐÏÍÏÇÁ × ÐÏËÒÁÝÅÎÎi Vim'Á
ÂÕÄÅ ÐÒÉÊÎÑÔÁ Ú ×iÄËÒÉÔÉÍÉ ÏÂiÊÍÁÍÉ!
=== æÕÎËÃiÏÎÁÌØÎiÓÔØ
óÉÍ×ÏÌÉ ÔÁ ÍÏ×É:
÷ Vim ÍÏÖÎÁ ÒÅÄÁÇÕ×ÁÔÉ ÔÅËÓÔÉ "Ú ÐÒÁ×Á ÎÁ Ìi×Ï", (ÎÁÐÒÉËÌÁÄ ÄÌÑ
áÒÁÂÓËϧ, ðÅÒÓØËϧ ÍÏ×, I×ÒÉÔÕ), É ÂÁÇÁÔÏÂÁÊÔÏ×i ÓÉÍ×ÏÌÉ, ÄÌÑ ÍÏ× ×
ÑËÉÈ ×ÉËÏÒÉÓÔÏ×ÕÀÔØÓÑ i¤ÒÏÇÌiÆÉ, ÎÁÐÒÉËÌÁÄ ëÉÔÁÊÓËÁ, ñÐÏÎÓËÁ, ëÏÒÅÊÓËÁ
(Hangul) ÍÏ×É, (çÏ×ÏÒÑÞÉ ÔÅÈÎiÞÎÉÍÉ ÔÅÒÍiÎÁÍÉ, Vim ÐiÄÔÒÉÍÕ¤ ÔÅËÓÔÉ ×
ÆÏÒÍÁÔÁÈ UTF-8 i Unicode.)
á×ÔÏËÏÍÁÎÄÉ:
íÏÖÎÁ ËÏÒÉÓÔÕ×ÁÔÉÓÑ "Á×ÔÏËÏÍÁÎÄÁÍÉ" ÄÌÑ Á×ÔÏÍÁÔÉÞÎÏÇÏ ×ÉËÏÎÁÎÎÑ ÐÅ×ÎÉÈ
ÄiÊ (ÎÁÐÒÉËÌÁÄ ÄÌÑ Á×ÔÏÍÁÔÉÚÁÃi§ ÐÅÒÅÇÌÑÄÕ ÚÁÁÒÈi×Ï×ÁÎÉÈ ÁÂÏ Ä×iÊËÏ×ÉÈ
ÆÁÊÌi×).
÷ÉËÏÒÉÓÔÁÎÎÑ ÄÉÇÒÁÆi×:
Vim ÄÏÚ×ÏÌѤ ××ÏÄÉÔÉ ÓÐÅÃiÁÌØÎi ÓÉÍ×ÏÌÉ ËÏÍÂiÎÁÃi¤À Ä×ÏÈ ÓÉÍ×ÏÌi×, i
ÄÏÚ×ÏÌѤ ÓÔ×ÏÒÀ×ÁÔÉ Ó×ϧ ËÏÍÂiÎÁÃi§. (ÎÁÐÒÉËÌÁÄ ÌiÔÅÒÕ § ÍÏÖÎÁ
ÏÔÒÉÍÕ×ÁÔÉ ÐÏÓÌiÄÏ×ÎÏ ÎÁÔÉÓËÕÀÞÉ 'i' ÔÁ ':')
IÓÔÏÒiÑ ËÏÍÁÎÄ:
Vim ÄÏÚ×ÏÌѤ ×ÅÓÔÉ "iÓÔÏÒiÀ" ËÏÍÁÎÄ É ÐÏÛÕËi×, ÔÁË ÝÏ ×É ÍÏÖÅÔÅ
×ÉËÏÎÕ×ÁÔÉ i ÒÅÄÁÇÕ×ÁÔÉ ÐÏÐÅÒÅÄÎØÏ ××ÅÄÅÎi ËÏÍÁÎÄÉ.
úÁÐÉÓ ÍÁËÒÏËÏÍÁÎÄ:
õ Vim ÍÏÖÎÁ "ÚÁÐÉÓÁÔÉ" ×ÁÛi Äi§ ÄÌÑ ×ÉËÏÎÁÎÎÑ ÐÏ×ÔÏÒÀ×ÁÎÉÈ ÏÐÅÒÁÃiÊ.
ïÂÍÅÖÅÎÎÑ ÐÁÍ'ÑÔi:
Vim ÍÏÖÅ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÂiÌØÛÅ ÐÁÍ`ÑÔi ÄÌÑ ÒÑÄËi× ÔÁ ÂÕÆÅÒi×.
óËÒÉÐÔÉ:
Vim ÍiÓÔÉÔØ ×ÂÕÄÏ×ÁÎÕ ÓËÒÉÐÔÏ×Õ ÍÏ×Õ, iÄÅÁÌØÎÕ ÄÌÑ ÐÒÏÓÔϧ ÔÁ Û×ÉÄËϧ
ÒÏÚÒÏÂËÉ ÐÏÔÒiÂÎÉÈ ËÏÍÁÎÄ.
óÉÓÔÅÍÁ ÐÏÍiÔÏË:
Vim ÍÏÖÅ ×ÉËÏÒÉÓÔÏ×Õ×ÁÔÉ ÓÉÓÔÅÍÕ "ÐÏÍiÔÏË" ÄÌÑ iÎÄÅËÓÁÃi§ ÔÁ ÐÏÛÕËÕ ×
ÔÅËÓÔi, ÐÒÉ ÃØÏÍÕ ÍÏÖÎÁ ËÏÒÉÓÔÕ×ÁÔÉÓÑ "ÓÔÅËÏÍ" ÏÓÔÁÎÎiÈ ÐÏÍiÔÏË.
ïÂ`¤ËÔÉ × ÔÅËÓÔi:
Vim ÍÏÖÅ ÒÏÚÒiÚÎÑÔÉ ÏÂ`¤ËÔÉ ×ÓÅÒÅÄÉÎi ÔÅËÓÔÕ (ÐÁÒÁÇÒÁÆÉ, ÒÅÞÅÎÎÑ,
ÓÌÏ×Á, óìï÷á - ×ÒÁÈÏ×ÕÀÞÉ ÔÁ ÎÅ ×ÒÁÈÏ×ÕÀÞÉ ÎÁ×ËÏÌÉÛÎi ÐÒÏÍiÖËÉ) i
ÄÏÚ×ÏÌѤ ÚÍiÎÀ×ÁÔÉ ×ÉÚÎÁÞÅÎÎÑ ÄÅÑËÉÈ ÏÂ`¤ËÔi×.
÷ÉÄiÌÅÎÎÑ ÓÉÎÔÁËÓÉÓÕ:
Vim ×iÄÏÂÒÁÖÕÅ ÔÅËÓÔ × ËÏÌØÏÒi - ÎÁÌÅÖÎÏ ÄÏ ÓÉÎÔÁËÓÉÓÕ. ÷É ÍÏÖÅÔÅ ÓÁÍi
×ÉÚÎÁÞÁÔÉ ÓÉÎÔÁËÓÉÓ ÆÁÊÌÁ.
äÌÑ Vim iÓÎÕ¤ ÂiÌØÛÅ Ä×ÏÈÓÏÔ ÆÁÊÌi× Ú ÏÐÉÓÏÍ ÓÉÎÔÁËÓÉÓÕ ÄÌÑ ÞÁÓÔÏ
ÚÁÓÔÏÓÏ×ÁÎÉÈ ÍÏ× ÐÒÏÇÒÁÍÕ×ÁÎÎÑ (Ada, C, C++, Eiffel, Fortran, Haskell,
Java, Lisp, Modula, Pascal, Prolog, Python, Scheme, Smalltalk, SQL,
Verilog, VisualBasic), ÐÒÏÇÒÁÍ ÄÌÑ ÍÁÔÅÍÁÔÉÞÎÉÈ ÒÏÚÒÁÈÕÎËi× (Maple,
Matlab, Mathematica, SAS), ÍÏ× ÒÏÚÍiÔËÉ (DocBook, HTML, LaTeX,
PostScript, SGML-LinuxDoc, TeX, WML, XML), ×ÉÈÏÄÕ ÐÒÏÇÒÁÍ (diff, man),
ÆÁÊÌi× ÎÁÌÁÛÔÕ×ÁÎÎÑ ÐÒÏÇÒÁÍ (4DOS, Apache, autoconfig, BibTeX, CSS,
CVS, elm, IDL, LILO, pine, procmail, samba, slrn), ÓËÒÉÐÔi× shell (sh,
bash, csh, ksh, zsh), ÓËÒÉÐÔÏ×ÉÈ ÍÏ× (awk, Perl, sed, yacc), ÓÉÓÔÅÍÎÉÈ
ÆÁÊÌi× (printcap, .Xdefaults), i, Ú×ÉÞÁÊÎÏ, ÓÉÎÔÁËÓÉÓÕ ÆÁÊÌi× ËÏÍÁÎÄ É
ÄÏÐÏÍÏÇÉ ÄÌÑ Vim.
óÐÅÃiÁÌØÎÉÊ ËÏÄ:
Vim ÍÏÖÅ iÎÔÅÇÒÕ×ÁÔÉÓÑ Ú Perl, Tcl i Python. Vim ÍÏÖÅ ×ÉËÏÎÕ×ÁÔÉ ÒÏÌØ
OLE automation server ÐiÄ Windows. Vim ÍÏÖÅ ÂÕÔÉ ×ÓÔÁÎÏ×ÌÅÎÉÊ Ú ËÏÄÏÍ
ÄÌÑ X-windows, ËÏÔÒÉÊ ÄÏÚ×ÏÌѤ ËÏÎÆiÇÕÒÕ×ÁÔÉ ÍÅÎÀ É ÐiÄÔÒÕÍÕ¤ ÍÉÛÕ.
Since Vim internally doesn't use dates, there is no year 2000 problem.
There might be a year 2038 problem, when the seconds since January 1st 1970
don't fit in a 32 bit int[eger] anymore. This depends on the compiler,
libraries and operating system. Specifically, time_t and the ctime() function
are used. And the time_t is stored in four bytes in the swap file.
But that's only used for printing a file date/time for recovery.
The Vim strftime() function directly uses the strftime() system function.
If your system libraries are year 2000 compliant, Vim is too.
On 990521 I had received a FAX from a company asking me to give a Y2K evaluation of *all* versions of Vim
together with a note that the URL of a webpage is not enough to satisfy their legal requirements.
Well, we might say that "any damages can only be refunded as far as they do not exceed the price paid for the
product". Since Vim is available for free such a statement doesn't mean anything, does it? ;-)
Anyway, the author of Vim cannot possibly take responsibility for other people's environments in which they
compile and use Vim. Therefore we cannot give a guarantee.
Furthermore, a written statement has legal implications which the developers cannot fully oversee. Therefore we
will not send away letters or faxes.
You will simply have to believe that all the developers have done all the best they can to prevent Vim from crashing
in any way. And if you are in doubt, well, you can check the code yourself. :-)
Personally, I wonder why the industry suddenly cares so much about bugs *now*. After all, software had always
had bugs before and will probably have in future. "Does anybody care what time it is" when you lose your data?
Why has noone ever asked for such statements about other kinds of bugs, eg a "Macintosh guarantee for dialogs to
be without any bomb icons"? And how about an "insurance for Unix segmentation faults"? I would really look
forward to see a guarantee from Microsoft that I would never have to use control-alt-delete ever again...
I have received several enthusiatic offers for the maintenance of the binaries for Windows - but I have to turn them all down
because the Windows binaries are available on *every* ftp mirror out there - so there is no need for this. Thank you for the
offers, anyway. :-)
So here's a list of systems where we could not provide binaries for. Can you help these people and give them a binary? Perhaps
maintain the binary with a website? Please get in touch!
Vim on PDAs and Embedded Systems: I get requests for Vim binaries on small systems at least once a week. But so far there
are no sites with such binaries. Any takers?
http://www.bebits.com/app/546
http://www.bebits.com/bob/4746/vim-5.7-BeOS-x86.pkg.zip
Contact: Denis Bourez denis(at)ubix.org
Last checked: 010129
ftp://ftp.ubix.org/pub/vim/57/
000717: vim-5.7-BeOS-x86.pkg.zip 1649Kb
ftp://ftp.ubix.org/pub/vim/60g/
000830: vim-6.0g-ALPHA-BeOS-x86.pkg 1936Kb
BeOS 4.5/5.0
Contact: ???
Last checked: 010129
BSDi
http://www.rassilon.net/~vitamink/vim/
http://www.retina.net/~tilde/vim/
990504 BSDi 4.0 vim-5.3
990813 BSDi 4.0 vim-5.4
Contact: Klaus Steden [email protected] [email protected]
CygWin
981005 Sparclinux-2.0.xx:
http://home.mayn.de/jean-luc/vim/
Contact: Thomas Köhler [email protected]
NOTE: This site will move soon!
LINUX - SuSE
OpenServer
980728 "OpenServer" vim-5.1
http://www.sco.com/skunkware/osr5/editors/vim/
990308 "UnixWare" vim-5.3
http://www.sco.com/skunkware/uw7/editors/vim/
Contact: ???
SGI
Solaris
000204: vim-5.4
001002: vim-5.7
1549663 Oct 2 18:34 vim-5.7-sol8-sparc-local.gz
http://www.sunfreeware.com/programlistsparc8.html#vim
Last check: 010106
"And the 16bit version is discouraged for everything, including DOS mode."
Still - any takers?
Windows 32bit [Win95 and WinNT]
TODO
Add links to packages by Linux distributors (RedHat, Debian, SuSE etc). Example:
ftp://ftp.suse.com/pub/suse/i386/update/7.1/xap2/gvim.rpm
ftp://ftp.suse.com/pub/suse/i386/update/7.1/a1/vim.rpm
URL: http://www.math.fu-berlin.de/~guckes/vim/binaries.html
URL: http://www.vim.org/binaries.html (mirror)
Created: Fri Feb 05 00:00:00 CET 1999
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Thu Mar 22 02:00:00 MET 2001
FTP Mirrors
FTP stands for "file transfer protocol". (But you might think of it as "filr tranfer program" if you like.) It is one of the
services that the Internet gives - like Email, News, and the WWW.
You can download Vim from the main site - but the connection may be slow. Therefore Vim has be copied onto other
computers to which you may have a faster connection. These computers are called "mirrors", in this case "ftp mirrors".
The FTP mirrors hold a *copy* of the main download site. and therefore should hold both the source code of Vim as
well as its documentation and syntax files (aka runtime files).
NOTEs: There may be exceptions. Some mirros might not have a complete copy of everything. It's all up to the
maintainers of the mirrors. If you should encounter an incomplete mirror then please contact its *maintainer*.
The following list is sorted alphabetically by the top level domain (TLD) name. The "US domains" com, gov, and net are
listed at the end.
Usually, the best mirror to chose is the one in your country. And the default name for that mirror *should* be
ftp.AB.vim.org where "AB" is the country's two letter iso code. Example: The mirror in Greece should be aliased
as "ftp.gr.vim.org".
AU Australia ftp://ftp.au.vim.org/pub/vim/
BE Belgium ftp://ftp.be.com/pub/vim/
CA Canada ftp://ftp.ca.vim.org/pub/vim/
DE Germany: ftp://ftp.de.vim.org/misc/editors/vim/
DE1 Berlin ftp://ftp.berlin.de.vim.org/misc/editors/vim/
-> ftp1.de.vim.org [toadd]
DE2 Erlangen ftp://ftp2.de.vim.org/ [outdated]
DE3 Munich ftp://ftp.musin.de/pub/vim/
-> ftp3.de.vim.org [toadd]
DE4 Oldenburg ftp://ftp.informatik.uni-oldenburg.de/pub/vim/
-> ftp4.de.vim.org [toadd]
currently is ftp://ftp2.de.vim.org/ - wrong!
DK Denmark ftp.dk.vim.org/pub/vim [010322 - todo]
ES Spain ftp://ftp.es.vim.org/pub/vim/
FR France ftp://ftp.fr.vim.org/pub/vim/
FR2 France ftp://ftp.fr2.vim.org/pub/vim/
GR Greece ftp://ftp.gr.vim.org/pub/vim/
HU Hungary ftp://ftp.hu.vim.org/pub/vim/ [000121: timeout]
IT Italy ftp.it.vim.org (coming up!)
JP Japan: ftp://ftp.jp.vim.org/pub/vim/
JP1 TWICS ftp://ftp.tokio.jp.vim.org/pub/vim/
JP2 ISITE ftp://ftp2.jp.vim.org/pub/vim/ defunct?
KR Korea ftp://ftp.kr.vim.org/pub/vim/
MX Mexico ftp://ftp.mx.vim.org/
NL Netherlands ftp://ftp.nl.vim.org/pub/vim/
NL1 Netherlands ftp://ftp.nl.vim.org/pub/vim/
NL2 Netherlands ftp://ftp2.nl.vim.org/pub/vim/
PL Poland ftp://ftp.pl.vim.org/pub/vim/
PT Portugal ftp://ftp.ci.uminho.pt/pub/editors/vim/
-> ftp.pt.vim.org [toadd]
RU Russia planned
-> ftp.su.vim.org [toadd]
ZA SouthAfrica ftp://ftp.za.vim.org/applications/editors/vim/
USA:
USA1 CA, UCDAVIS ftp://ftp.ca.us.vim.org/pub/vim/
USA2 CA, cdrom.com ftp://ftp.cdrom.com/pub/unixfreeware/editors/vim/
-> ftp://ftp2.ca.us.vim.org/pub/unixfreeware/editors/vim/
[toadd]
USA3 MD, NASA ftp://ftp.nasa.us.vim.org/pub/unix/vim
-> ftp.md.us.vim.org [toadd]
USA4 MI, Petrified ftp://ftp.mi.us.vim.org/mirrors/vim/
USA5 NY, Rochester ftp://ftp.ny.us.vim.org/editors/vim/
USA6 IL, UIUC ftp://ftp.il.us.vim.org/packages/vim/
USA7 WA, WallaWalla ftp://wastenot.whitman.edu/pub/vim/
-> ftp.wa.us.vim.org [toadd]
WWW/Web mirrors
The list of web mirrors of the Vim Pages. Please note that the original homepage of Vim is
http://www.math.fu-berlin.de/~guckes/vim/ and that http://www.vim.org/ is a *mirror*! Changes to the Vim Pages are
thus immediately visible at the "math" site; they will be reflected by www.vim.org after the daily mirror.
Here are the current www mirrors of the Vim Pages:
BE Belgium http://mirror.grmbl.com/vim/
-> http://www.be.vim.org/ [todo]
CA Canada http://www.vmunix.com/vim/
-> http://www.ca.vim.org/ [toadd]
CZ Czech Republic http://www.instinct.org/vim/
DE Germany:
DE1 Berlin http://www.math.fu-berlin.de/~guckes/vim/
DE3 Munich http://www.vim.org/
DK Denmark http://www.dk.vim.org/pub/vim [010322 - todo]
ES Spain http://www.etsimo.uniovi.es/vim/
-> http://www.es.vim.org [toadd]
FR France http://web.efrei.fr/~parmelan/vim/guckes/
-> http://www.fr.vim.org [toadd]
KR Korea http://sparcs.kaist.ac.kr/mirror/vim/
-> http://www.kr.vim.org [toadd]
MX Mexico http://www.mx.vim.org/
NO Norway http://alge.anart.no/vim/
-> www.no.vim.org [toadd]
Russia:
RU1 Russia http://vim.gambit.msk.su/
-> http://www.su.vim.org [toadd]
RU2 Russia http://chronos.cs.msu.su/vim/
SK Slovakia http://www.kotelna.sk/vim/
ZA SouthAfrica http://www.leg.uct.ac.za/mirrors/guckes/vim/
-> http://www.za.vim.org [toadd]
URL: http://www.math.fu-berlin.de/~guckes/vim/mirrors.html
URL: http://www.vim.org/mirrors.html (mirror)
Created: Fri Jan 29 17:00:00 CET 1999
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Wed Mar 07 15:00:00 MET 2001
URL: http://www.math.fu-berlin.de/~guckes/vim/docs.html
URL: http://www.vim.org/docs.html (mirror)
Created: Mon Sep 11 12:00:00 MET DST 2000
Send feedback on this page to
Sven Guckes [email protected]
Index of /doc
Name Last modified Size Description
This file contains a list of all commands for each mode, with a tag and a
short description. The lists are sorted on ASCII value.
Tip: When looking for certain functionality, use a search command. E.g.,
to look for deleting something, use: "/delete".
==============================================================================
==============================================================================
==============================================================================
==============================================================================
==============================================================================
==============================================================================
3. Visual mode *visual-index*
Most commands in Visual mode are the same as in Normal mode. The ones listed
here are those that are different.
==============================================================================
Get to the command-line with the ':', '!', '/' or '?' commands.
Normal characters are inserted at the current cursor position.
"Completion" below refers to context-sensitive completion. It will complete
file names, tags, commands etc. as appropriate.
CTRL-@ not used
|c_CTRL-A| CTRL-A do completion on the pattern in front of the
cursor and insert all matches
|c_CTRL-B| CTRL-B cursor to begin of command-line
|c_CTRL-C| CTRL-C same as <ESC>
|c_CTRL-D| CTRL-D list completions that match the pattern in
front of the cursor
|c_CTRL-E| CTRL-E cursor to end of command-line
CTRL-F not used
CTRL-G not used
|c_<BS>| <BS> delete the character in front of the cursor
|c_digraph| {char1} <BS> {char2}
enter digraph when 'digraph' is on
|c_CTRL-H| CTRL-H same as <BS>
|c_<Tab>| <Tab> if 'wildchar' is <Tab>: Do completion on
the pattern in front of the cursor
|c_<S-Tab>| <S-Tab> same as CTRL-P
|c_wildchar| 'wildchar' Do completion on the pattern in front of the
cursor (default: <Tab>)
|c_CTRL-I| CTRL-I same as <Tab>
|c_<NL>| <NL> same as <CR>
|c_CTRL-J| CTRL-J same as <CR>
|c_CTRL-K| CTRL-K {char1} {char2}
enter digraph
|c_CTRL-L| CTRL-L do completion on the pattern in front of the
cursor and insert the longest common part
|c_<CR>| <CR> execute entered command
|c_<CR>| CTRL-M same as <CR>
|c_CTRL-N| CTRL-N after using 'wildchar' with multiple matches:
go to next match, otherwise: same as <Down>
CTRL-O not used
|c_CTRL-P| CTRL-P after using 'wildchar' with multiple matches:
go to previous match, otherwise: same as <Up>
|c_CTRL-Q| CTRL-Q same as CTRL-V (used for terminal control flow)
|c_CTRL-R| CTRL-R {0-9a-z"%#*:= CTRL-F CTRL-P CTRL-W CTRL-A}
insert the contents of a register or object
under the cursor as if typed
|c_CTRL-R_CTRL-R| CTRL-R CTRL-R {0-9a-z"%#*:= CTRL-F CTRL-P CTRL-W CTRL-A}
insert the contents of a register or object
under the cursor literally
CTRL-S (used for terminal control flow)
|c_CTRL-U| CTRL-U remove all characters
|c_CTRL-V| CTRL-V insert next non-digit literally, insert three
digit decimal number as a single byte.
|c_CTRL-W| CTRL-W delete the word in front of the cursor
CTRL-X not used (reserved for completion)
CTRL-Y not used
CTRL-Z not used (reserved for suspend)
|c_<Esc>| <Esc> abandon command-line without executing it
|c_<Esc>| CTRL-[ same as <Esc>
|c_CTRL-\_CTRL-N| CTRL-\ CTRL-N go to Normal mode, abandon command-line
CTRL-\ a - z reserved for extensions
CTRL-\ others not used
CTRL-] not used
CTRL-^ not used
|c_CTRL-_| CTRL-_ when 'allowrevins' set: change language
(Hebrew, Farsi)
|c_<Del>| <Del> delete the character under the cursor
==============================================================================
5. EX commands *ex-cmd-index*
This is a brief but complete listing of all the ":" commands, without
mentioning any arguments. The optional part of the command name is inside [].
The commands are sorted on the non-optional part of their name.
This document is a guide to quickly setting up the Vim color editor on Linux or Unix systems.
The information here will improve the productivity of programmers because the Vim editor
supports syntax color highlighting and bold fonts, improving the "readability" of program code.
A programmer's productivity improves 2 to 3 times with a color editor like Vim. The
information in this document applies to all operating sytems where Vim works, such as Linux,
Windows 95/NT, Apple Mac, IBM OSes, VMS, BeOS and all flavors of Unix like Solaris,
HPUX, AIX, SCO, Sinix, BSD, Ultrix etc.. (it means almost all operating systems on this
planet!)
1. Introduction
● 1.1 Before you Install
● 1.2 Install Vim on Redhat Linux
● 1.3 Install Vim on GNU Debian Linux
● 1.4 Install Vim on Unixes
● 1.5 Install Vim on Microsoft Windows 95/NT
● 1.6 Install Vim on VMS
● 1.7 Install Vim on OS/2
● 1.8 Install Vim on Apple Macintosh
2. Install Vim on Microsoft Windows 95/NT
● 2.1 Install bash shell
● 2.2 Edit bash_profile
● 2.3 Setup Window colors
5. VIM Usage
6. Vi companions
● 6.1 Ctags for ESQL
● 6.2 Ctags for JavaScript programs, Korn, Bourne shells
● 6.3 Debugger gdb
Note: A *LOT* of material has been assembled already - but the time to include it all is really
missing. If you think you can write HowTo yourself then *please* contact me - just send me a
mail!
HowTos Wanted
● Vim and Sniff+ Support ("+sniff" - compilation requires files from the subdir "extra")
● Installation of a vim binary on - a special report for specific platforms is certainly
welcome, too!
● Using functions
If you can write and maintain any of these then please let me know!
Links
"HOWTO de l'éditeur Vim" [000223]
http://www.freenix.org/unix/linux/HOWTO/Vim-HOWTO.html
A HowTo in French.
Authors: Al Dev (Alavoor Vasudevan) [email protected]; Version française par
Arnaud Launay, [email protected]
Vim "QuickTute"
http://pegasus.rutgers.edu/~elflord/vim/quicktute.html
Author: [email protected]
VIM Macros/Mappings
Well, I have hundreds of macros on my hands - but they will not be of much use unless they get
documented, I think. Therefore this page has not much yet. Sorry.
TODO: Add macros from the VIM FAQ and from posts on comp.editors.
Sven's vimrc
Sven's vimrc has many examples of mappings. Take a look!
Mirror/reverse Lines
by Dr. Charles E. Campbell Jr. ([email protected])
Description: This script "mirrors" (reverses) the contents of the text between (the line marked
with) 'a' and the current line. The script is sourced with a map to "\fm". Depending on the kind of
map for "\fm" the order of the lines will remain or be reversed, too.
Instructions: Let your shell export VIMSCRIPT which points to the directory where you keep
your scripts for Vim, eg "export VIMSCRIPT=/Vol/Pub/share/vim/syntax".
Define this map: map \fm :'a,.g/^/:so $VIMSCRIPT/mirror.vim<CR> Here is the "mirror.vim" that
should get sourced:
Color Setup
[001010] Vim allows to change colors for quite a few things, such as the color for normal text ("Normal"), selected
text ("Visual"), search matches ("Search"), commented text ("Comment"), and all the characters that represent
non-existing or hidden parts of the text. (such as TABS, trailing whitespace, end-of-lines, and the tilde lines after the
end-of-buffer).
I've thrown in "LineNr term=NONE" to turn off the default underlining of line numbers as
● :help :X
From: [email protected] (Eli the bearded) Newsgroups: comp.editors Subject: Re: Encryption in vi - Help!
Date: 6 Mar 1996 07:23:39 GMT Message-ID: <[email protected]> vi uses the same encryption as the
Unix crypt command. This is a single rotor version of the enigma machine maping 8-bit chars into 8-bit chars. Since
text files are a small subset of 8-bit chars, decryption of plain text files is a relatively easy task. [...] Unix crypt is a
very poor crypto system. When it was written it was merely low security (with a bonus for security through
obfuscation), but computational power has increased vastly since then as have the number of people interested in
launching attacks against it. You should never consider it more secure than a small padlock on a diary. (Note this
crypt is a different one than the crypt(3) function used for encrypting passwords in a vanilla passwd file. crypt(3) is a
one way encryption based on DES. I am not convinced of its security, but I don't know of any attempted attacks on it.)
From: Kevin Dempsey Peterson <[email protected]> Newsgroups: comp.editors Subject: Re: vi emergency
Date: Mon, 20 Oct 1997 15:59:27 -0700 Message-ID:
<[email protected]> Crypt isn't DES. The crypt(3) call is DES, but the
crypt command is a weakened version of the Enigma machine. Try http://www.dodgenet.com/~kwantam/zip/cbw.zip
-- [email protected] Home: (510)665-9670 http://www.ocf.berkeley.edu/~peterson Page: (510)726-8960 The
URL to "kwantam" is obsolete. But I found the "cwb.zip" here:
● ftp://ftp.ecst.csuchico.edu/users/atman/CBW/cbw.zip
Vim vs CAPS
The Windows versions of Vim have a problem with the CAPS key: When the CAPS key is down/pressed/ON then
typing the numeric keys on the normal keypad (ie not the extra numeric keypad) will produce the upper keys, too.
This is *wrong*.
Mark Johnson had produced a patch for Vim in 1998
Vim on WindowsNT
Fighting the Registry
Problem: Opening files with spaces in the filename does not work.
Solution by Scott Borton [email protected] [980807]:
$ ls -l `which www`
[...] ~/bin/www -> /path/bin/lynx
Tip submitted by: t.byfield [email protected] [980529]
Vim on CDE
On CDE (Common Desktop Environment) the default terminal is "dtterm". There are some problems with it.
Q: Starting vim overwrites the screen. Why? can I change this?
A: Dtterm does not support xterm's "alternate-screen controls" (at least it is not mentioned in the manual), so
you can't fix it. (This is not a vim/vi/whatever problem.) If you want a terminal with an "alternate screen" then you
should get "xterm". As this terminal ships with many systems you probably already have it. The XFree86 3.3 xterm
supports ANSI color and VT220 emulation Please take a look at the FAQ:
● http://dickey.his.com/xterm/xterm.faq.html
.C
.CPP
.H
.TXT
If you still think that you must do the replacement then here are more ideas:
Do not replace the notepad with vim by copying it over!
THIS IS WRONG: copy c:\vim\vim.exe c:\windows\notepad.exe
Why: This causes Windows to lose track of the default location of the desired application.
So you should go about it like this:
Make backup of notepad
copy c:\windows\notepad.exe c:\backup\notepad.exe
Note:
Make copy of Vim as "notepad"
copy c:\vim\vim.exe c:\tmp\notepad.exe
Replace notepad with new copy
copy c:\tmp\notepad.exe c:\windows\notepad.exe
Prompt "replace"? Answer with "yes".
Gregory Harris [email protected] [971231]:
Win95/NT4:
● Open any folder
● Select "View|Options"
● Select "Edit..."
● Select "Open"
● Select "Edit..."
● Change the "Application used to perform the Action" field with the exact path of vim.exe.
The "old" win31/NT3 way is done with the aid of the file manager "winfile".
The "new" win95/NT4 way is done with the aid of the windows explorer.
Mostly setting the method which matches your OS version will cause the behavior to happen, but I sometimes end up
finding it necessary to set both depending upon what the launching application is doing.
Both these settings are, of course, set in the registry.
The Win31/NT3 way:
● Run file manager (START->RUN->Winfile under NT4/95)
● Vim will most likely not be on the list of programs to "Associate With:" so select the browse button, and find
vim.exe with the resulting interface. Alternatively, instead of a flat association, you could select New Type and
associate a laundry list of extensions with Type: Text and the program Vim.
Win95/NT4 way:
● Open any explorer window.. ie.. double click on any drive, folder, etc.
● In the resulting dialog, select OPEN from the actions list, and click Edit.
● Under "Application used to perform action:" type in the path to your vim.exe, or click the Browse button to
graphically select the location of your vim.exe.
● Note that if you do not want ALL these extensions opening VIM you will need to delete the type and
reconstruct multiple replacements. Windows is _VERY_ inflexible about the editing of types.
000904: Matthew White [email protected] comments on "replacing notepad with vim" on a Windows2000
machine:
You can do it but you need to delete notepad.exe from the directory
/winnt/system32/DllCache. (This directory is probably hidden.) Once this has been done you
can copy vim as notepad.exe over the top of /winnt/notepad.exe and also
/winnt/system32/notepad.exe.
So - do these things work? Or are there any problems with this? Please let me know! Sven [email protected]
Thanks to these people for their help:
Vim on DOS
[970818] Vim on DOS takes about 400K. And when you use the "shell" it might not work because there is not enough
space left for the shell. In that case you simply have to cut down on some extra programs to gain the space you need
to "shell out" from Vim.
Parenthize text
Parenthize current word: map ,, maa0<ESC>mbbma$a x<ESC>`awgebi(<ESC>ea)<ESC>$xx`blx`a
Sample Settings
Sven's vimrc is available as http://www.vim.org/rc
Sample Abbreviations
Abbreviations are quite simple word to word translations. Very handy when you type the same things over and over
again. It is useful for long words like this: "Donaudampfschiffahrtsgesellschaftkapitaenwitwengesetzzusatzparagraph"
This actually is a proper German word. Don't ask! The abbreviation for this word might be "DON" and the definition
in the vimrc would look like this: ab DON Donaudampfschiffahrtsgesellschaftkapitaenwitwengesetzzusatzparagraph
I also use abbreviations for Email addresses, important file name such as setup files, and some URLS of my web
pages.
Examples: ab _vimrc $HOME/.vimrc ab _mymail [email protected] ab _homepage
http://www.math.fu-berlin.de/~guckes/ NOTE: It does not matter how many spaces there are between the
abbreviation and the expanded word. This allows for some nice formatting. Abbreviations can be a lot more than mere
word substitutons, though. Actually anything you type can used. [TODO: HTML example]
Sample Mappings
Mappings make the use of VIM more interesting yet. Complex commands be made with just a few keystrokes.
Caveat: Mapping must be "prefix free", ie no mapping must be the prefix of any other mapping. Example: "map ,abc
foo" and "map ,abcd bar" will give you the error message "Ambigous mapping". " 950101 ,v = vimrc editing (edit this
file) map ,v :e $HOME/.vimrc " 950101 ,u = "update" by reading this file map ,u :source $HOME/.vimrc " " 950101 g
= goto first line " 951112 the new vim defines "g" as a new command, eg "gg" will go to first line " map g 1G " " ===
Text editing " " - Formatting " " 950330 ,dp = dequote current paragraph map ,dp {jma}kmb:'a,'bs/^> *// " 950330 ,qp
= quote current paragraph map ,qp {jma}kmb:'a,'bs/^/> / " " - Inserting texts " " 950101 ,c = "copy notice" (tell
addressee that text is a copy of an article) "map ,c 1G}:r COPY " 950101 ,re = read ELMSIG map ,re G:r ELMSIG "
950101 ,da = "date insert" map ,da :r!date " 950101 ,dt = "date and time insert" map ,dt :r!date +\%y\%m\%d\%t\%T
" 950101 ,h = "helloagain" (indicates reply to reply) map ,h 1GOHello, again! " 950101,950620 ,C = "check alias" "
950101 ,s = "sign" - read in signature file (requires manual completion) map ,s :r $HOME/public_html/sig/sig. "
950101 ,t = "text" - read in text file (requires manual completion) map ,t :r $HOME/public_html/txt/ " "END
Helpfile (vim_ref.txt)
Problem: After relocation of the documentation, vim cannot find the help text.
Question: How do you tell vim where the helpfile is?
Answer: To tell vim where to find the help file, set the variable "helpfile" to the correct value, ie including the full
path. As with most variables you can abbreviate "helpfile to "hf".
Example: :set hf=/path/vim_ref.txt
VIM - Invocation / Startup
The easiest way to start "vim" is to simply enter "vim" at the prompt of your shell. If your shell can find "vim" then it
will start it.
Now vim should show you an "empty buffer". A "buffer" is a part of the computer's memory where only vim may
change data. While editing you change the contents of this buffer. As you are not making any changes to a "file" on
your "file system" you make changes to something "virtual". To apply these changes to a file you have to give the
"write" command.
Before we can go on I will have to explain how the programs tells your "text imput" from the input it has to interpret
as "commands".
● step2: Press "Q". Note: A capital "Q" - not a lower case "q".
● step3: Press "}". (On the Mac keyboard with German layout: alt-9)
You can also format text by calling an external program. The nicest formatter I have seen so far is "par" - see the
notes on the Vim Utilities Page.
1) Type (esc) to switch to command mode 2) Enter the command ":help" (press return key to "enter"!). VIM will
show you an index of help pages. All help pages can be accessed directly by pressing the associated letter. <li>
<xmp> On msdos, if you get any strange screen flashing or color changing, try: :set hl= This will turn highlighting
(hl) off. By default, backup files are maintained. That is, editing 'file' will create 'file.bak' in the current directory. This
can be turned off with ':set nobackup nowritebackup'. By default, a swap file is created in the current directory for
crash recovery purposes. Vi puts its crash recovery file in /tmp. To make vim do something like this, use ':set
dir=>/tmp'. The '>' stops it from trying the current directory first. [950306]
Substitute in line range
Q: How do you substitute from line marked with x to a line marked with y ? A: :'x,'ys/this/that/
Reading in a file
Q: How do I append a signature to my text? A: Jump to the end of the text with "G" and then read in the signature file.
Q: How do I read in a file to the current buffer? A: Use ":r file". The contents of "file" will be appended *after* the
current line. Q: How do I read in the output of a command? A: Use ":r!command".
Abbreviations
Q: Why cant I abbraviate "'xy"? A: The abbreviation consists of a non-id character followed by two id characters,
which does not satisfy either category of a "full-id". However, "_ps" and "'p" will work.
Formatting text
vim4 allows to format the current paragraph with "Qp". The "Q" means "format" and the following "p" will let the
formatting operate on the current paragraph. The really good thing is that it preserves "quoting".
Note: Since Vim-5 the command for the "internal text formatting" has changed to "gq" since the 'Q' was needed for Vi
compatibility.
However, the builtin formatting command does not suit everybody. There are a few scripts about which you can use
to pipe your text through. Here are two scripts - one in PERL and one in AWK:
mfmt.pl
fmt.awk
Basic knowledge about PERL and AWK required. Caveat: scripts are not tested yet! use at own risk! [TODO: test the
scripts]
Digraphs
Q: Is there a command to remove any or all digraphs? A: No. There is a table that is defined at compile time. You can
only add new ones. Adding a command to remove digraphs is on the todo list.
UUencoding text
Sending text like a vimrc will sometimes lose special characters. Therefore uuencoding them is a good idea. Q: How
do I encode text with uuencode? A: !uuencode filename
● The vi ^Z command.
Also, take a look at Secure Editors by Freedman, Sharp & Associates, where you'll find editors binaries for AIX,
ULTRIX, HP-UX, IRIX, M88k, OSF1, SunOS, Solaris. There are three editor binaries and one pager binary for each
platform that have been modified so that they will not spawn processes or allow the user to work with files other than
the initially loaded file. You cannot get out of them via ex or ^Z escapes. Also, the initially loaded file must be
specified with a complete pathname on the command line. Secure, non-escapable binaries are provided for:
● elvis - a vi workalike.
● mg - a GnuEmacs-like editors.
● umacs - same as mg, but with key bindings more like Gosling-style Emacs.
Modeless vim
Situation: People seem to prefer "modeless editors". Q: How to make vim modeless. A: There are a few things that
vim has which could help make it seem like a modeless editor (if you really want it to :-) - From insert mode, ^O may
be hit and then followed by any command-mode command, eg ^Odd as mentioned above. After the command is
finished you will be back in insert mode again. - There is a setting 'insertmode', which can be set in your .vimrc or
.exrc. If set, then editing files always starts in insert mode. - The cursor keys, page-up, page-down keys work in insert
mode as expected.
Changing colours
Situation: The blue background looks great on color monitor, but on my notebook I like to have either black or white
background. Q: Is there an easy way to change the VIM background color? A: From: Wolfgang Schumacher
[email protected] Here's the _vimrc for my notebook. I hope it helps (proceeding on the assumption that you
have an IBM compatible) - or read vim's msdos.doc. The ^[ sequence is the escape character (entered by typing
<ctrl>V <esc>): set autoindent nojoinspaces backspace=2 shiftwidth=2 set ignorecase ruler report=0 visualbell set
dir=>c:\\tmp nobackup showmatch map g G set t_ti=^[\|79m "invert mode: bwht(15) on red(64) e.g. v set
t_so=^[\|14m "standout mode: yel(14) on blk(0) e.g. :set set t_tb=^[\|14m "bold mode: yel(14) on blk(0) e.g. :!ls ^D
set t_tp=^[\|07m "normal text: wht(07) on blk(0) set t_se=^[\|07m "normal text: wht(07) on blk(0) " COLOURS
background foreground foreground "
=============================================================== " 128 blinking + 0 black + 0
black 8 gray " 16 blue 1 blue 9 light blue " 32 green 2 green 10 light green " 48 cyan 3 cyan 11 light cyan " 64 red 4
red 12 light red " 80 magenta 5 magenta 13 light magenta " 96 brown 6 brown 14 yellow " 112 white 7 white 15
bright white
Disabling suspend
Situation: I use vim as the editor for composing emails with ELM. ELM somehow loses vim when you suspend it. So
I need to disable the suspend command of vim. Q: How to disable the "suspend" with ^z ? A: Remap the ^z to start a
shell: map ^Z :shell^M Situation: I do not want the mapping in my vimrc as I only need it with vim when I call it
from ELM. Q: So how tell I vim on the command line "use vim with the vimrc, but also disable the suspend"? A: Yes,
just put the map command into quotes: vim +"map ^Z :shell^M" file How you get the ^Z and ^M through the shell is
up to you :-)
Pasting yank buffer into command line Fact: You can record keystrokes to a yank buffer and thus you can put it into
the edit buffer. Question: How do you paste a yank buffer into the command line? Answer: Assume that there is
something in buffer 'y'. Enter ":@y" then hit return.
Vim's smartindent option is nice. But there's one thing, I dislike a lot: Whenever you start a line with "#", Vim ignores
the current indent and places the # at the begin of line. This is o.k. when editing C-code, but if you're writing shell or
awk scripts, # introduces a comment... If I want to write something like if [ $a = "x" ]; then # comment about what's
done here I have to indent the # line manually. :-( I don't use vim, but I see where that could be a problem. Even in
C/C++-code I don't start lines with # at the first column. The product I work on (Preditor/2) uses one codebase to
support multiple platforms (OS/2, Windows and Win95/NT). It uses a multi-platform class library and *lots* of #ifs
to do this, many of which are nested. If all of th #ifs start in the 1st column, you easily get hopelessly lost and
confused. Therefore I always indent the #ifs just like the rest of th code so it can be read. Yes maybe there should be
different types of smartindenting? For the moment you can get around this by putting this in your .vimrc or .exrc file:
inoremap # X^H# where ^H is typed as <Ctrl-V><Back-Space>. Strange, most C compilers won't allow the # to be
anywhere other than in the first column. I think the ANSI standard requires it to be in the first column. You can of
course have spaces/tabs after the '#' and before the "if" or whatever. -Rob.
In Vim 3.0, * (in the command mode) searches forward for the next occurrence of the *word* that is under the cursor.
And # searches backward. If you want to search the word which can be part of another word, you can try the
following map map \s wb"zyeo/^["zpbb"zy$u@z^M where ^M is Ctrl-V Ctrl-M do one of the following you should
be able to relocate the tmp directory: - set directory=/<pathname> in EXINIT - or, "set directory=/<pathname>" in
your .exrc file - or, in a vi session do ":set directory=/<pathname>" where pathname is the location you want to put
the temp file.
I have problems using vi with characters which have an ascii value > 128. For example if I insert ue the editor echoes
\334 in insert mode. After leaving the insert mode everything is fine. Also fmt removes all characters with ascii > 128
from the text being formated. You have to define the environment-variable LC_CTYPE. If you are using csh then put
in your .cshrc following line: setenv LC_CTYPE=iso_8859_1
Encryption
Question: I typed ":Call" on the command line and was prompted with "Enter a key"; so I typed something like "123"
and then the text seems to have turned into binary characters. What happened?
Answer: ''Yep, you've encrypted it! I never knew there was a command ":Call" in vi, but it turns out there is, or is it
just ":C"?, and it seems to encrypt your file. To recover it, type "crypt < file", and then enter the password when
prompted, assuming you're right about the "123" bit!''
Could not reproduce this. Maybe because we do not have "crypt()" here. -Sven
Startup message
Question: When I open a file with vim via `vim filename' vim sometimes displays a message in its status line:
"~/myfile" [textmode] 902 lines, 92498 characters Press RETURN or enter command to continue The window now
displays nothing else but this message and you have to press RETURN to start the edit session. This is annoying. But
vim does this not every time. Sometimes the initial message is shown, sometimes not. It seems to depend on the file
beeing edited somehow, but I don't now in which way.
Answer: This will happen if the message is long enough to collide with the showcmd area, since this would overwrite
the message and vim wants to make sure you got a chance to read it. If the file name is short enough then it knows it
won't get overwritten so it won't ask for RETURN. Same thing happens while in vim if you type ":e long-file-name..."
Terminology
Well, before every good text there need be some definitions. They make it easier for you to understand. Please take
the time to read this - I am sure you will benefit from it!
line
A sequence of characters. Start: First character after an EOL character (or first character of buffer). End: Next
EOL character. The EOL is included.
running text
A sequence of consecutive characters.
block
A sequence of (full) lines.
paragraph
see block
Hmm, this needs a lot more work...
:g/RE/p
URL: http://www.math.fu-berlin.de/~guckes/vim/answer.html
URL: http://www.vim.org/answ.html (mirror)
Created: Mon Jan 1 00:00:00 MET 1996
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Sun Oct 08 20:30:00 MET DST 2000
Vim Chat/Talk
Let's Talk about VIM! :-)
IRC #vim
Some of us are using the chat system "Internet Relay Chat" (IRC) to talk about Vim. There are different "nets", though.
We usually meet on IRCnet on channel #vim.
I connect via the server irc.fu-berlin.de - but you cannot join this server from everywhere, so you should try to
connect to one of the servers listed below.
Please note that you will find yourself in *one* of the various IRC networks. So even though you are on channel #vim
on your net you might not meet others on #vim as they could be using this channel on another network.
If you do not have an IRC client yet then I suggest you get mIRC (for Windows) or epic for Unixish systems.
I definitely prefer using a proper IRC client - but please give the following web based chat a try if you have no
alternative.
Note: The service is given by chatset.web.de - a site in Germany. Therefore the descriptions of this service are in
German. However, if you have used IRC before then you will probably know all the basic commands, anyway.
I am looking forward to your feedback - thanks! :-)
vimuser
Chose a nickname
and then click on the button:
Status: Experimental!
Right now [000228] the server seems to be flakey - so let's see if this works out. If no then I'll try some other talk
service...
NOTE: The service is run in Germany - so all the help is in German. But I am sure that Vim users are smart enough to
understand it right away. :-)
Chose a Nickname:
Your Password:
(only required for registered nicknames/users)
Chatroom: vim
IRC Servers
You cannot join irc.fu-berlin.de from anywhere - so here's a list of servers you can try:
Links
URL: http://www.math.fu-berlin.de/~guckes/vim/chat.html
URL: http://www.vim.org/chat.html (mirror)
Created: Mon Mar 27 12:00:00 MET DST 2000
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Thu Mar 01 00:00:00 MET 2001
Version Info
Please give info on the vim version! Since vim-5.2b you can request the info from the command ":version" on the command
line with the option "--version" , too. You can redirect this output easily into a file:
UNIX: uname -a
DOS: version
Values of Options
For all things that involve options please give their values! Remember that you can look at values with :set option? ,
eg ":set textwidth?".
Examples
Give examples! Please make sure that the example is reproducible.
Subject: :g vs :v [vim]
When following up on a post about Vim *wihout* "vim" in the Subject line then please *add* "[vim]" to it. Then at least
the followup can be scored accordingly. The brackets around "vim" also tell readers that this is the name of the program
more visually.
Reading about Vim on Usenet
If you do not have a newsreader to read Usenet News (what a pity) then you can read News via DejaNews or Altavista.
To make this easier for you here are some links which already extract info about vim:
DejaNews - (g)vim
NewsService: DejaNews
Newsgroups: comp.editors
Search for: "vim" OR "gvim"
Sorting: by Date
Format: terse
Maximum Hits: 100
Altavista - (g)vim
NewsService: Altavista
Newsgroups: comp.editors
Search for: "vim" OR "gvim"
Note: Altavista starts with oldest article first. :-(
Thanks for the URLs, Richard! :-)
Back to the -> VIM Home Page
URL: http://www.math.fu-berlin.de/~guckes/vim/newsgroup.html
URL: http://www.vim.org/newsgroup.html (mirror)
Created: Fri Dec 1 00:00:00 MET 1995
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Mon Oct 02 18:18:18 MET DST 2000
● http://vim.sourceforge.net/cvsdocs/
Maintainer:
The CVS repository is maintained by Johannes Zellner [email protected]
HOWTO use Vim's CVS repository:
● http://vim.sourceforge.net/cvsdocs/anonymous-cvs.html
Links
CVShome [000605]
http://www.cvshome.org/
The makers of "CVS".
CVS tools for Windows and MacOS [001002]
http://www.wincvs.org/
URL: http://www.math.fu-berlin.de/~guckes/vim/cvs.html
URL: http://www.vim.org/cvs.html (mirror)
Created: Thu Dec 16 18:00:00 MET 1999
Send feedback on this page to
Sven Guckes [email protected]
[email protected] ©1995-2000 Last update: Mon Sep 11 11:11:11 MET DST 2000
But coding itself does not help much if the documentation does not show how to use it. Therefore we also need help with
the documentation. Several people have also suggested to translate the VIM FAQ.
You do not have to be computer geek to help us, though. If you'd like to design a tshirt for Vim - be our guest! :-)
And, of course, you'd make the author and a lot of children happy by donating something to the ICCF as to help children in
Uganda suffering from the effects of AIDS. Thanks!
❍ South America
We would be very happy if you could provide download via HTTP - as some people cannot use FTP to download
files.
So, if you can set up a mirror - please contact me!
Vim Binaries [971103,971204]
Would you maintain a binary for Vim? Then please let us know! And please read the page with the guidelines for
preparing a vim binary archive. Thanks!
DYNIX or dgux anyone?
Keith Starsmeare ([email protected]) is looking for vim binaries for the following systems:
URL: http://www.math.fu-berlin.de/~guckes/vim/help.html
URL: http://www.vim.org/help.html (mirror)
Created: Thu Jun 11 11:11:11 CEST 1998
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Tue Mar 20 15:00:00 MET 2001
Sven's vimrc
I'd like to take the opportunity to point out that I have spent a lot of time commenting my vimrc to give
examples and a quite a few tips. This vimrc might become an extensive web page some day, but I usually
find it easier to add the info directly to it. Please take a look at it:
● Operating System(s)
● Compiler(s)
Please include the following info within the file: Name and/or description of language (may require version
number), name and address of the maintainer, date and time of last update, filenames to apply to, and (very
good) a web address for the very latest version.
Example:
@@@@@@@@@@@@@@@@.@@@@@@@@@@@@@@@
@@@@@@@@@MMFFF99.99FFFMM@@@@@@@@
@@@@@@MMMFFFF9fi.if9FFFFMMM@@@@@
@@@@MMMFFFFF9.m...m.9FFFFFMMM@@@
@@@MMMMFFFF9fw.....wf9FFFFMMMM@@
@@MMMMFFF99flw.....wlf99FFFMMMM@
@MMMMMFF99l...........l99FFMMMMM
@MMMMMFfl...............lfFMMMMM
MMMMMMM9.m.............m.9MMMMMM
@MMMMMMF99f...........f99FMMMMMM
@MMMMMMMMFF9fffffffff9FFMMMMMMMM
@@MMMMMMMMMFFFFFFFFFFFMMMMMMMMM@
@@@MMMMMMMMMMMMMFMMMMMMMMMMMMM@@
@@@@MMMMMMMMMMMMMMMMMMMMMMMMM@@@
@@@@@@MMMMMMMMMMMMMMMMMMMMM@@@@@
@@@@@@@@@MMMMMMMMMMMMMMM@@@@@@@@
generated by Linus Akeson's
Mandelbrot Generator Macros.
Albayrak, Ali - [email protected] [980114]
Environment:
processors: 483SX/33, RS6000/350, RS6000/C20, RS6000/250, RS6000/530, Sun4m/SPARC;
systems: AIX 4, AIX 3, SunOs 5.4, Linux 1.2;
compilers: AIX cc, gcc
Note: Ali Albayrak offered to help with installation of Vim on the operating systems he is using.
Arpadffy, Zoltan - [email protected] [000223]
http://www.polarfox.com/vim/
Binaries: Open VMS for Alpha and VAX
Environment: Open VMS (Alpha and VAX)
Home: RedHat Linux, FreeBSD and Windows 98 (for the kids)
Work: Open VMS, Windows NT and Solaris
Note: Zoltan Arpadffy's page is the "VIM on Open VMS Information Page" and is very nicely made.
Arens, Ralf - [email protected] [010223]
http://home.tu-clausthal.de/~mwra/vim/
Environment: ???
Note: Lots of macro files, most notably his MailNews.vim.
Bader, Thomas - [email protected] [000613]
http://www.trash.net/~thomasb/vim/
Environment: Debian GNU/Linux (Kernel 2.0.36 & 2.2.16, i486 & i586 & i686), SunOS 5.7
(sun4u), Windows 98 & NT
Note: Some setup files, usage of "2html.vim", screenshots.
Baruchel, Thomas - [email protected] [000805,000829]
http://perso.libertysurf.fr/baruchel/vim/
Scheme support file:
http://perso.libertysurf.fr/baruchel/vim/schemesupport.vim
Bloch, Eduard - [email protected] [000416,000522]
http://sites.inka.de/sites/zombie/edecosi/vim.en.html
Environment: Debian Linux; Windows mit gvim.
Note: Interesting pages with sample configuration.
Bigham, Scott - [email protected] [971118,980817]
http://www.cs.duke.edu/~dsb/vim/
Lynx ("*.lss"): http://www.cs.duke.edu/~dsb/vim/syntax/lss.vim
Perl POD format: http://www.cs.duke.edu/~dsb/vim/syntax/pod.vim
Environment: Work: assorted Solaris boxes running Vim 5.0o Home: Atari TT030 running Vim-4.6
and a Linux-2.0.27 notebook running Vim-5.0o.
Böhme, Harald - [email protected] [980113,980622,010320]
http://www.informatik.hu-berlin.de/~boehme/vim/
SDL: http://www.informatik.hu-berlin.de/~boehme/vim/syntax/sdl.vim
Binaries: SunOS4 and Solaris
Environment: Linux and Solaris
Bordelon, Scott L. - [email protected] [971110]
No vim page - but a syntax file:
CADENCE "Dracula" (electronics design rule checking):
dracula.vim
Note: This syntax file is local as Scott does not have a webpage. It is updated whenever there is a
need for it.
Brady, Rob - [email protected] [990629,990702,990813,990819]
http://www.datatone.com/~robb/vim/
Microsoft Module-Definitions: http://www.datatone.com/~robb/vim/syntax/def.vim
Focus Exec: http://www.datatone.com/~robb/vim/syntax/focexec.vim
Focus Master: http://www.datatone.com/~robb/vim/syntax/master.vim
Microsoft Assembler: http://www.datatone.com/~robb/vim/syntax/masm.vim
Environment: FreeBSD; WindowsNT and Windows95.
Dr. Charles E. Campbell, Jr. - [email protected] [980817,990520,990830]
http://www.erols.com/astronaut/vim/
Syntax files:
Amiga Scripts amiga.vim.gz
CSH (C shell) scripts: csh.vim.gz
DCL (Dec's Control Language): dcl.vim.gz
Elm Filter ($HOME/.elm/filter-rules): elmfilt.vim.gz
Exports (Unix's /etc/exports) exports.vim.gz
Lex lex.vim.gz
Lisp lisp.vim.gz
Maple V r1.4 maple.vim.gz
SH (Sh Bash Ksh): sh.vim.gz
Sendmail sm.vim.gz
Tag Files tags.vim.gz
TEX (LaTeX, TeX) tex.vim.gz
Vim vim.vim.gz
Xmath xmath.vim.gz
Xxd xxdbin.vim.gz
Yacc yacc.vim.gz
Note: Dr. Charles Campbell has written so many syntax files that I can hardly keep up with it. Nice
work, Chip! On his website you will also find his own tag file generator hdrtag which create tags for
c/c++, c/c++ header files, lex, yacc, TeX (cites and labels), vim scripts (functions and syntax), and
Maple V. Amazing! There is also info on how to use an English spell checker with Vim, some
alignment code and maps, and some Vim-scripts supporting network oriented file read/write (with
commands :Nr and :Nw).
Capricelli, Thomas - [email protected] [000927]
http://aquila.rezel.enst.fr/thomas/vim/
Syntax files:
kvim: http://aquila.rezel.enst.fr/thomas/vim/syntax/kscript.vim
Environment: Linux on a PowerMac (latest kernel), KDE-2 from cvs.
Note: Thomas Capricelli's page is the official page for "KVim".
Castagnetto, Jesus M. - [email protected] [980827]
http://www.scripps.edu/~jesusmc/vim/
Lite (mSQL): http://www.scripps.edu/~jesusmc/vim/syntax/lite.vim
Chamarty, Sitaram - [email protected] [971229,980126,010220]
http://www.diac.com/~sitaram/vim/
COBOL: http://dimensional.com/~sitaram/cobol/ http://dimensional.com/~sitaram/cobol/cobol.vim
http://www.diac.com/~sitaram/vim/cobol.vim [obsolete]
Environment: Linux-2.0.27 (RHL-4.2), AIX-4.1.2, VIM-5.0s on both; VIM-4.5 on HP-UX-10.10
and others...
Corks, Matt - [email protected] [970516]
http://www.csclub.uwaterloo.ca/u/mvcorks/vim/
Environment: various Unix versions
Matt Corks has also created a menu with the (complete?) character set for ISO-8859. Thus you can
enter every character from a menu. This theoretically means that you can operate Vim complety via
menu using the mouse. (eek! ;-)
Dara, Hari Krishna - [email protected] [991116,991117]
http://sites.netscape.net/haridsv/vim/
Syntax files:
Language: http://www.domain/~user/vim/syntax/language.vim
Binaries: http://www.domain/~user/vim/bin/os/
Environment:
Note: Functions for a "directory stack" (recall previously used current directory) and "deletion
recovery in insert mode" for deletions commands CTRL-W (delete last word) and CTRL-U (delete
current line).
Duperval, Laurent - [email protected] [971107,971217]
http://www.grafnetix.com/~laurent/vim/
Laurent's Cool Vim macros
URL: http://www.grafnetix.com/~laurent/vim/macros.html
A collection of some stunning macros. Includes a list number generator, TicTacToe and a file
browser. I am not making this up! ;-)
Icons: http://www.grafnetix.com/~laurent/vim/icons.html
Some of the icons may appear broken due to the strange webserver. Just reload the page a few times
to see all icons.
Environment: Various Unix flavours
Note: Laurent Duperval was the maintainer of the VIM FAQ until Spring 1998. Thanks, Laurent!
Eckert, Hans-Christian "Ripley" - [email protected] [980312]
http://www.in-berlin.de/user/nostromo/vim/
Note: Hans-Christian has done some developing on the MacOS port of Vim.
Elbers, Henk - [email protected] [970625]
Note: Henk Elbers was the porter of the VMS version.
Ehrens, Philip S. - [email protected] [971208,980828]
http://www.primenet.com/~imbe/vim/ [defunct 980828]
Environment: DOS and Linux.
Note: Phil once offered vim binaries for DOS 32-bit DOS/Win [and optimized versions for 486 and
Pentium] - but he closed his service as of 980205 - unfortunately. :-(
Exel, Otavio - [email protected] [971215]
http://www.economatica.com.br/oexel/
http://www.economatica.com.br/oexel/vim [todo]
Note: Otavio Exel maintains a page on "pickfiles" (index of filenames for easy access within editors)
and also has some pickfile mappings for Vim.
Faylor, Chris - [email protected] [980114,980515]
http://www.tiac.net/users/cgf/
Note: Chris Faylor has ported vim for WindowsNT and it made available with Cygnus release. On
his page you can get the binary for vim-5.0p (as well as less-332 and perl-5.004_04) together with
the required cygwinb19.dll.zip .
Feige, Bernd - [email protected] [971124,971215]
http://home.t-online.de/home/Bernd.Feige/vim.htm
LaTeX BibTeX files: http://home.t-online.de/home/Bernd.Feige/bib.vim
Environment: Linux-2.0.32
Fisher, Benji - [email protected] [000602,001219]
http://home.netscape.com/websites/ [001219]
http://sites.netscape.net/benjif/vim/ [obsolete]
Note: "The most ambitious goal for this site is to become a standard reference for editing TeX and
LaTeX with the vim editor." Benji Fisher has written a LOT of functions with Vim.
Fleiner, Claudio - [email protected] [971210]
http://www.fleiner.com/vim/
ASN: http://www.fleiner.com/vim/syntax/asn.vim
CSS (cascading style sheets): http://www.fleiner.com/vim/syntax/css.vim
HTML: http://www.fleiner.com/vim/syntax/html.vim
Java: http://www.fleiner.com/vim/syntax/java.vim
JavaCC: http://www.fleiner.com/vim/syntax/javacc.vim
JavaScript: http://www.fleiner.com/vim/syntax/javascript.vim
make: http://www.fleiner.com/vim/syntax/make.vim
Sather: http://www.fleiner.com/vim/syntax/sather.vim
Environment: Linux-2.0.29 on a Laptop and a Pentium; AIX 4.*.
Gonsalves, C. Laurence - [email protected] [980827,981104]
http://www.cryogen.com/clgonsal/vim/
asmselect - select betweeen various assemblers:
http://www.cryogen.com/clgonsal/vim/syntax/asmselect.vim
NASM: The Netwide Assembler (v0.97):
http://www.cryogen.com/clgonsal/vim/syntax/nasm.vim
PL/SQL: http://www.cryogen.com/clgonsal/vim/syntax/plsql.vim [981104]
Griffin, Benjamin Elijah "Eli the Bearded" - [email protected] [980114]
http://www.netusa.net/~eli/src/vim.html
Contents: Macros, macros, macros: Maze solver, Towers of Hanoi, Universal Register Machine,
HTML macros. And links, of course.
"How tags work" http://www.netusa.net/~eli/src/tags.html
Note: If you want to notify him of some post on Usenet then just crosspost to the group alt.fan.e-t-b.
This guy is a Vi freak! And he knows a lot about procmail, too. :-)
Foucher, Herve - [email protected] [981119]
http://www.helio.org/vim/
Syntax files:
SMIL: http://www.helio.org/vim/syntax/smil.vim
Environment: work: Windows NT (PII 450Mhz) home: Linux RedHat-5.2, windowmaker-0.20.2;
Windows95 (Cyrix 166+)
Note: Herve Foucher is using Vim mainly for HTML and Java.
Fraust, Jack - [email protected] [000829]
http://www.angelcities.com/members/vimpower/
http://www.angelcities.com/members/vimpower/syntax.html
Garcia-Suarez, Rafael - [email protected] [990831]
http://altern.org/rgs/vim/
Environment: vim 5.4 on WinNT 4.0; vim 5.3 on Linux 2.2 (RedHat 6.0)
Glass, Brian - [email protected] [970627,980505]
http://www.lni.net/bjg/vim/
Note: As Brian Glass told us on 980430 he does not have the time to maintain the files any more. But
it is ok with him if anyone wants to improve it.
Environment: home: Windows95. work: Digital Unix and WindowsNT.
Guckes, Sven - [email protected] [970623,980609,000516]
http://www.math.fu-berlin.de/~guckes/Vim/
Environment:
Home: i386 and i486 with FreeBSD-2.2.6 and Linux SUSE-5.2
Work: SunOS 4.1.3, Solaris
Sven quit DOS and Windows in 1992 - but now uses them only for testing Vim (and to play
"Sherlock" once in a while). Sven does have Vim installed with the options "+GUI +X11" but hardly
ever uses any of its features (mouse and menus).
Sven is the maintainer of the Vim Pages on www.vim.org and frequently scans the newsgroup
comp.editors to help answering questions about Vim and related programs.
Guldberg, Preben "Peppe" - [email protected] [971216,980622]
http://www.student.dtu.dk/~c928400/vim/
Fortran: http://www.student.dtu.dk/~c928400/vim/syntax/fortran.vim
Matlab: http://www.student.dtu.dk/~c928400/vim/syntax/matlab.vim
mutt setup files: http://www.student.dtu.dk/~c928400/vim/syntax/muttrc.vim
slrnrc (slrn setup file): http://www.student.dtu.dk/~c928400/vim/syntax/slrnrc.vim
slrnsc (slrn score file): http://www.student.dtu.dk/~c928400/vim/syntax/slrnsc.vim
slrnsl (slrn slang file): http://www.student.dtu.dk/~c928400/vim/syntax/slrnsc.vim
Environment:
1. Linux 2.0.32/2.1.65, RedHat 5.0
2. HP-UX B.10.20 A 9000/780 2012879787 two-user license
Note: Preben Guldberg has a very nice vim page - lots of syntax files, too. He made the vim maillists
available as compressed mailbox folders, and he quite active on comp.editors giving useful answers.
He deserves a "high score" for this! :-)
Haney, Steve - [email protected] [971023,981007]
http://www.usaserve.net/users/shaney/vim/ [981007]
Binaries: AIX-4.1.4 on PowerPC
Old: www.goodnet.com/~shaney/vim/
Hack, Stephen - [970814,010328]
http://www.students.uiuc.edu/~shack/vim/ [obsolete]
man.vim - syntax file for Unix manuals: http://www.students.uiuc.edu/~shack/vim/syntax/man.vim
Environment: Debian, HPUX, Cygwin (home/work)
Hannedouche, François-Xavier - [email protected] [990915]
http://fixounet.free.fr/vim/
Environment: Work: UltraSparc 5 with Solaris; Home: Windows 98 / Linux Mandrake 6.0
Note: Info on cross referencing symbols with Vim using a perl script.
Harrsion, David C. Jr. - [email protected] [971011,980918]
http://pigseye.kennesaw.edu/~dharriso/vim/
Environment: Silicon Graphics IRIX (5.3, 6.4)
Binaries: IRIX-5.3, IRIX-6.3, IRIX-6.4, IRIX-6.5
Hedlung, Hans - [email protected] [960512,980622]
http://www.cs.umu.se/~hans/vim/ [todo]
vim-3.0 refcard.txt in HTML: http://www.cs.umu.se/~hans/vim.html
Hemert, Jano van - [email protected] [9xxxxx,980522]
http://www.wi.leidenuniv.nl/~jvhemert/vim/
Note: Jano van Hemert's page about Vim macros is really nice. :-)
Generic Entry - please fill out and send to me.
Lastname, Firstname - user@domain [DATE]
http://www.domain/~user/vim/
Syntax files:
Language: http://www.domain/~user/vim/syntax/language.vim
Binaries: http://www.domain/~user/vim/bin/os/
Environment:
Note:
Heimann, Sonia - [email protected] [980202,980522]
http://www.netsurf.org/~niania/vim/ (dir contents only)
Perl: http://www.netsurf.org/~niania/vim/syntax/perl.vim
Environment: Linux and WindowsNT
Note: Sonia Heimann handed on the maintenance of the perl.vim to Nick Hibma.
Hesse, Arndt - [email protected] [971204,971229]
http://www.self.de/~hesse/vim/ [todo]
info on syntax files: http://www.self.de/~hesse/vim/syntax/
SmallTalk: http://www.self.de/~hesse/vim/syntax/smalltalk.vim
Note: This "smalltalk.vim" is included in the distribution as "st.vim".
Hibma, Nick - [email protected] [980703,990302]
http://www.etla.net/~n_hibma/vim/
Perl: http://www.etla.net/~n_hibma/vim/syntax/perl.vim
Environment: FreeBSD 2.2.x/3.x/4.0, Solaris 2.4
Note: "yes, lot's of them, in my wallet."
Hiebert, Darren - [email protected] [980310,991208]
http://home.hiwaay.net/~darren/
Note: Darren Hiebert is the author of the utility "ctags":
http://fly.hiwaay.net/~darren/ctags/.
Darren does not have a page on vim - unfortunately; it would be interesting to see his vim setup.
Hlavacek, Jan - [email protected] [980216]
http://www.math.ohio-state.edu/%7Elahvak/software/vim.html
SLang: http://www.math.ohio-state.edu/%7Elahvak/software/vim/syntax/slang.vim
Slrn score files: http://www.math.ohio-state.edu/%7Elahvak/software/vim/syntax/score.vim
Environment: SunOS 2.5.2 and 2.6
Hunsaker, Bruce - [email protected] [980515]
Environment: VMS
Note: Bruce Hunsaker's patches for the VMS version were added to vim-5.2c. On 980515 he said
he'll set up a page...
Jensen, Thomas - [email protected] [971128,990614,010220]
http://home.pages.de/~jensen/
http://home.pages.de/~jensen/junk/vimrc.txt
OS: Many different machines and OSes, mostly UNIX (including Linux)
Note: Thomas Jensen is the author of "tal", the "trailer alignment" filter program:
http://home.pages.de/~jensen/tal/
Jones, Alun "Penguin" - [email protected] [970912,971217]
http://www.aber.ac.uk/~auj/ (home page)
Environment: Acorn's "RISC OK"
Note: Alun Jones once ported Vim to the Archimedes (see the file os_archi.txt of the distribution).
Haven't heard from him in a while.
Kallingal, Rajesh - [email protected] [971009]
Environment:
NOTE: Rajesh Kallingal once converted the vim-3.24 helpfiles to HTML:
URL: ftp://ftp.oce.nl/pub/misc/vim/beta-test/html-docs
Currently this is just an ftp link. I do hope that Rajesh will put up a web page where you can get a
look at the latest version as well as download all of them as a tar.gz file.
Kang, Sirtaj Singh - [email protected] [971008]
http://www.ph.unimelb.edu.au/~ssk/vim/
Environment: OSF/Alpha, RS6K/AIX, Linux/x86
Scripts: vim2html - a perl script that converts vim-5 helpfiles to html.
http://www.ph.unimelb.edu.au/~ssk/vim/vim2html.pl
vim-5.0g helpfiles: http://www.ph.unimelb.edu.au/~ssk/vim/help.html
NOTE: Sirtaj Kang might look into creating a vim binary for KDE.
Köhler, Thomas - [email protected] [970113,980612,000327,010315]
http://jeanluc-picard.de/vim/
http://www.mayn.de/user/jean-luc/vim/ [obsolete]
Prolog ("*.pl", "*.pdb"): http://jeanluc-picard.de/vim/syntax/prolog.vim
"Motif UIL" ("*.uil", "*.uit"): http://jeanluc-picard.de/vim/syntax/uil.vim
Binaries: for all systems of the following environments:
Environment: vim-5.7 on Linux-2.2.x i386, Linux-2.4.x i386, Linux-2.2.x S/390, SunOS 5.6/5.7, and
Windows NT. vim-6.0-alpha-releases on Linux-2.2.x i386
Kol, Tomer - [email protected] [990302]
Vim and LaTeX: http://www.ee.technion.ac.il/~tomer/TeX/
tkTeX: http://www.ee.technion.ac.il/~tomer/TeX/VIM/TKlatex.vim
Environment:
Note: Tomer Kol has created a "LaTex system to create lectures notes etc. using Hebrew and
hyperref (to create PDF files). Vim serves as the interface."
Kopányi, Sándor - [email protected] [980416]
no vimpage yet
Environment: VAX, VMS
Note: Sándor Kopányi got vim-4.5 to work on VMS. I hope he'll try to get vim-5.1 wotking, too, and
maybe even write some info about this (to be added to "os_vms.txt").
Kraai, Matt - [email protected] [980617] [todo]
Note: Matt Kraai maintains vim's entry on www.freshmeat.net.
Lee, Scott E. - [email protected] [971125]
http://www.GeoCities.com/Athens/5679/ (home page)
Binaries: Data General DG/UX, both 88k and x86. However, I could not find these on his website. :-/
[990205]
Environment: DG/UX (Unix), Win95.
Note: Scott Lee ported vim to Data General Unix (DG/UX).
Leonard, Beth - [email protected] [990629,990702]
http://frost.slimy.com/~beth/vim/
VERA: http://frost.slimy.com/~beth/vim/syntax/vera.vim
Lottem, Avner - [email protected] [970904,970912]
(no vim page)
Environment: Linux-2.0.30, Win95/WinNT-4.0, DOS 16bit, AIX-3.2.5. Including GUI version
(except DOS). Trying to keep up with the latest ALPHA versions.
Avner is the author of the helpfile about "rightleft mode" (rightleft.txt) using vim for writing in
Hebrew. Just ask him if you need help!
"The shell setup dynamically creates the environment (EXINIT, VIMINIT, GVIMINIT) in .cshrc (if
$TERM was changed). This is a peculiar setup, because I use both vi and vim, and I wanted to have
common options in one place."
Matsumoto, Yasuhiro - [email protected] [000117,000404]
http://hp.vector.co.jp/authors/VA020411/ [000404]
http://www.cis-net.co.jp/matsu/vim/ [obsolete]
Note: Binaries with "+multibyte".
McKee, Sean - [email protected] [971119]
http://www.misslink.net/mckee/vim/
Telix Salt: http://www.misslink.net/mckee/vim/syntax/telixsalt.vim
Dos INI files: http://www.misslink.net/mckee/vim/syntax/dosini.vim
Century Term Command Script: http://www.misslink.net/mckee/vim/syntax/cterm.vim
Make Menu: http://www.misslink.net/mckee/vim/rc/makemenu.vim
Environment: Windows95, SCO OpenServer 5, Linux (Slackware 2.0.30) Home: (Pentium 75) and
Acer Laptop (Pentium 100)
Mann, Christopher G. - [email protected] [970912]
Environment: FreeBSD
Christopher Mann is the webmaster of cdrom.com and also edits the homepage of hornet.org with
Vim:
http://www.hornet.org/
Martinson, Eric C. - [email protected] [970812]
http://www.teleport.com/~ericmart/vim/
Environment:
home: P5-166Mhz, Linux (Redhat 3.0.3; kernel 2.0.13).
office: SPARCstation-20, 150Mhz, 96MB RAM, 1MB cache; SUNOS-4.1.[34] or Solaris-2.5.1;
vim-4.6, fvwm-2.943, rxvt-???.
McMullen, John - [email protected] [990301]
HomePage?
Binaries: Interix binaries, maybe? :-)
Environment: Interix (which version?)
Note: John McMullen is trying to port Vim to Interix.
Moolenaar, Bram - [email protected] [970912,010328]
http://www.moolenaar.net/vim.html
Syntax files: 2html.vim, c.vim, colortest.vim, diff.vim, help.vim, model.vim, modula2.vim,
nosyntax.vim, scripts.vim, syntax.vim, vgrindefs.vim, viminfo.vim.
Environment: "My Amiga is a good old A2000, with 1MB RAM. It has a 68030 CPU card at 25MHz
with 2MB RAM. Speedwise this is comparable to an Intel386. The screen is a 14" Philips 8833 (TV
frequencies). I would upgrade it to a 68040 or 68060, if I would find a cheap CPU card. Would be
better to get an A4000 and a better monitor, but the Amiga is a dead-end, I don't want to invest much
in it anymore.
My "old" PC is a 200 MHz AMD K6, 64MB RAM, four disks totalling 11 Gbyte. It runs
FreeBSD-2.2.1. The screen is 17" (1280x1024).
My "new" PC is a 233 MHz AMD K6, ... This is my main workhorse now.
I've got a 10MHz Ethernet between the two PCs for easy file access. For the Amiga I need to use
720K floppies (that's why the Amiga distribution files have been cut down now)."
Note: Bram Moolenaar is the original author of Vim. Thanks for all your work, Bram!
Moore, Paul - [email protected] [971016]
NOTE: Paul Moore might do a page on "porting vim on windows". I wonder what has become of
this idea...
Mueller, Carl - [email protected] [981217,990118]
http://www.math.rochester.edu:8080/u/cmlr/vim/
Modified syntax files:
Scripts (recognizes script files):
http://www.math.rochester.edu:8080/u/cmlr/vim/syntax/scripts.vim
TeX:
http://www.math.rochester.edu:8080/u/cmlr/vim/syntax/tex.vim
Environment: ???
Notes: Improvements to the tex.vim syntax file: Additional abbreviations, mappings and menus for
gvim; additional functions for matching bracket completion and deletion, for changing brackets, for
putting in "\left...\right" or "\bigg", and for changing "\left...\right" to "\bigg".
Muth, Klaus - [email protected] [980527]
http://unitopia.mud.de/~monty/vim/
LPC: http://unitopia.mud.de/~monty/vim/syntax/lpc.vim
RosiSQL: http://unitopia.mud.de/~monty/vim/syntax/rosisql.vim
Environment:
Home: Linux 2.0.33 + Vim 5.2b
Work: Solaris 2.4/2.5.1 /w Motif on Classic + Ultra Sparc, Vim5.1 + Vim5.2b
Note: "What about Vim on Qt libs? What about kvim? ;)"
Nagle, Adrian [email protected] [980609,980609,000525]
http://naglenet.org/vim/vim.html
SINDA: http://naglenet.org/vim/syntax/sinda.vim
TAK: http://naglenet.org/vim/syntax/tak.vim
TRASYS: http://naglenet.org/vim/syntax/trasys.vim
Environment:
Work: WindowsNT-4.0
Home: Linux2.0+ from slackware
Nenadov, Mark - [email protected] [000903,000905]
http://www.freebox.com/marknenadov/vim/
Environment: Home/School: Windows 98; GVIM 5.7 & VIM 5.7 for DOS. Home: ZipSlack Linux -
VIM 6.0g
Nassen, Kent - [email protected] [970927,980703]
http://www-personal.umich.edu/~knassen/vim/
http://www-personal.umich.edu/~knassen/vim/ksyntax.html
SAS: http://www-personal.umich.edu/~knassen/vim/sas.vim
SPSS: http://www-personal.umich.edu/~knassen/vim/sps.vim
cbentr/cbgen: http://www-personal.umich.edu/~knassen/vim/cbg.vim
Nielsen, Michael - [email protected] [970912,971118,980522,990707,990708]
http://vip.cybercity.dk/~ccc30647/
was: http://www.image.dk/~mikeni/vim/ [990707: dead]
Environment:
Pentium 166MHz: win95 and Linux RedHat 4.1, 32MB RAM, 3.5GB Harddrive, 8xCDROM (IDE),
2xCDR (scsi), WINfast286, Sound galaxy Pro.
Amiga 4000 68040@25Mhz: (soon to be 68060@50Mhz/604e@200Mhz with +64MB). 18Mb Fast,
2MB Chip, 3.7GB Harddrive space, PicassoII, MFCIII, 2xCDROM (scsi), 8xCDROM (IDE).
Monitor: shared 17" monitor 1280x1024x8bit. 10Mhz Ethernet between the machines.
Binaries: Amiga
http://vip.cybercity.dk/~ccc30647/vim/
was: http://www.image.dk/~mikeni/vim/download.html [990707: dead]
Michael Nielsen is coding a GUI for the Amiga. He might also attempt to include a simple HTML
browser with Vim. "The Amiga is my main Development platform, the Linux box is mainly a file
server for backups, and CDROM writing. (I do enough unix development at work)."
Norbäck, Martin - [email protected] [???,980703]
http://www.dtek.chalmers.se/~d95mback/vim/
Haskell: http://www.dtek.chalmers.se/~d95mback/vim/syntax/haskell.vim
O'Brien, David E. - [email protected] [971120]
http://relay.nuxi.com/vim/ or http://relay.nuxi.com/www.vim.org/ (daily WWW mirror of
http://www.vim.org/)
Binaries: FreeBSD and Linux.
FreeBSD Binaries:
ftp://ftp.freebsd.org/pub/FreeBSD/packages-current/editors/vim*.tgz
Linux Binaries:
ftp://ftp.nuxi.com/pub/vim/linux/
Environment: FreeBSD-2.x, Solaris-2.5+, Ultrix-4.4, HP-UX-10.20 - many of each type :-)
Notes: David E. O'Brien maintains the first Vim distribution mirror in the USA
(ftp://ftp.nuxi.com/pub/vim also known as ftp://nuxi.ucdavis.edu/pub/vim). David is also the
maintainer for the Vim ports under FreeBSD and OpenBSD.
Pascoe, David - [email protected] [980514,980703]
http://www.ozemail.com.au/~pascoedj/
Vim Page: http://www.ozemail.com.au/~pascoedj/vim/ [soon?]
Note: [todo]
Piefel, Michael - [email protected] [010112]
http://www.informatik.hu-berlin.de/~piefel/vim/
Syntax Language: Kimwitu++ http://www.informatik.hu-berlin.de/~piefel/vim/syntax/kwt.vim
Environment: Debian GNU/Linux
Note: Michael Piefel also offers a PO file editing mode.
Raisky, Oleg Yu. - [email protected] [971215,971216,000414]
http://physlab.sci.ccny.cuny.edu/%7Eorycc/vim-main.html
http://scisun.sci.ccny.cuny.edu/~olrcc/vim/ [obsolete]
Environment: Linux RedHat 4.1, Win'95
Note: Oleg Raisky created the "Vim Guide", a printable version of the Vim Quick Reference (":help
quickref.txt"). The guide was set with LaTeX and is available in PostScript reading for printing for
sizes "A4" and "US letter" in both "plain" and "booklet" format.
Rebbechi, Donovan - [email protected] [980731,980731]
http://pegasus.rutgers.edu/~elflord/vim/
Bash (shell):
http://pegasus.rutgers.edu/~elflord/vim/syntax/bash.vim
SPEC - Linux RPM Files:
http://pegasus.rutgers.edu/~elflord/vim/syntax/spec.vim
Reilly, George V. - [email protected] [971217,990204]
http://www.halcyon.com/gvr/vim.html
coming up: http://george.reilly.org/
Note: George Reilly was the porter of the Windows versions for vim-4. Thanks a lot for getting this
started, George!
Old addresses: [email protected] [email protected]
Riehm, Stephen - [email protected] [971201,990817]
http://www.bigfoot.com/~stephen.riehm/
Environment: MacOS, AIX, HPUX, Linux.
Note: Stephen Riehm has some generic mappings to share for almost any kind of editing. Also,
"ctags for shell scripts". [990817]
Riiser, Haakon - [email protected] [980305,981009,990914]
Syntax files with Screenshots!
http://www.uio.no/~hakonrk/vim/
fvwm (versions 1 and 2):
http://www.uio.no/~hakonrk/vim/syntax/fvwm.vim
printcap/termcap:
http://www.uio.no/~hakonrk/vim/syntax/ptcap.vim
sed (stream editor) scripts:
http://www.uio.no/~hakonrk/vim/syntax/sed.vim
Simula:
http://www.uio.no/~hakonrk/vim/syntax/simula.vim
de la Rosso, Martini - [email protected] [010411]
http://www.math.ut.ee/~moro/vim/
Environment:
Note: Martini keeps a setup file with abbreviations for java coding:
http://www.math.ut.ee/~moro/vim/java.vimrc
Rios, Frank - [email protected] [980114]
http://www.qni.com/~frankr/ (home page)
Vim Page: http://www.qni.com/~frankr/vim/ [todo]
ASP ("*.asp" and "*.asa"):
http://www.qni.com/~frankr/vim/syntax/ASP.VIM
Environment: Windows95, WindowsNT
Note: Frank Rios may create an "Active Server Page" for VIM.
Riswick, Jos van - [email protected] [971013,971017]
http://septimius.mbfys.kun.nl/~josvanr/vim/
NOTE: Jos van Riswick has menu macros for non-gui vim-4.6 and macros for gui-vim implementing
a file browser.
Rochholz, Hermann - [email protected] [970610,990619,990831,000413]
http://www.rochholz.de/vim.html [000413]
http://inrdp2.fzk.de/hermann/vim.html [obsolete]
Interactive Data Language:
http://www.vim.org/syntax/idlang.vim
SpeakEasy [not included with Vim any more]:
http://www.rochholz.de/syntax/speakez.vim.gz
Hermann Rochholz wrote a set of "TeX Menus" for Vim (see picture).
Schemenauer, Neil - [email protected] [980613,980616,990822]
http://www.ucalgary.ca/~nascheme/vim/
Syntax files:
DCL (for VAX): http://www.ucalgary.ca/~nascheme/vim/syntax/dcl.vim
PL/I: http://www.ucalgary.ca/~nascheme/vim/syntax/pli.vim
Python: http://www.ucalgary.ca/~nascheme/vim/syntax/python.vim
Environment: Linux on a AMD K6-2
Scott, Ken - [email protected] [971007,971008]
http://www.pcisys.net/~kscott/vim/
Informix ESQL/C: http://www.pcisys.net/~kscott/vim/syntax/esql.vim
PowerBuilder export files: http://www.pcisys.net/~kscott/vim/syntax/powerb.vim
Environment: WindowsNT-4.0
Binaries: Win32
Seidman, Gregory - [email protected] [980623]
VRML 2.0 (VRML97): http://zing.ncsl.nist.gov/~gseidman/vim/syntax/vrml.vim
Environment: Solaris, Linux, IRIX, and MacOS
Seibert, Olaf - [email protected] [971021,971022]
No vim page. But his homepage definitely tells you why you don't want to use frames or the blink
tag: http://polder.ubc.kun.nl/~rhialto/
Binaries: http://polder.ubc.kun.nl/~rhialto/
Vim-4.5 and Vim-5.1 for BeOS DR8, AAPR. [Newer versions of BeOS already include Vim-4.5.]
Environment:
Home: Amiga 4000 with Motorola 68040 at 25 MHz, 12M RAM, 2G disk. BeBox with Dual PPCs
603 at 66 MHz, 48 M RAM, 1G disk.
Work: NetBSD/i386 with XFree86 3.3.
Binaries: BeOS
Note: Olaf intends to do a vim port for BeOS. So far he has done the text mode BeOS port and is
working on the GUI. Will he do a port of vim-4.6 or vim-5.0s?
Shan, Ken - [email protected] [980511]
http://www.digitas.harvard.edu/~ken/vimrc/
Vim Page with links to setup files:
Environment: BSDI 2.1
Note: Ken Shan has quite a few sample setup files for editing C/C++, Matlab, Perl, RCS, scripts,
TeX, and some more, eg a file browser ("directory editing"), and detecting text with Big5 coding,
coloring pgp signed text URLs, and mail headers.
Sharpe, Michael - [email protected] [000516]
http://www.irendi.com/vim/
Note: The vimrc and a function file HTMLized to show Vim's syntax coloring.
Shiran, Mortaza G. - [email protected] [971218,981005,001012]
http://www.parscom.com/www/vim/vim_farsi.html
Note: Mortaza's page has some screenshots - however, your browser needs support for ISO-8859-6
to display this page properly. Mortaza Shiran has added Farsi (Persian) support to Vim and also
manages the site "parscom.com"
http://table.jps.net/~shiran/www/p_soft.html [obsolete]
Siegmann, Paul - [email protected] [980713]
http://www.euronet.nl/~pauls/vim/
XML: http://www.euronet.nl/~pauls/vim/syntax/xml.vim
Environment:
Note:
Slootman, Paul - [email protected] [980114]
Environment: OS/2, UNIX, Linux
Note: Paul Slootman offered to help with installation of Vim on the operating systems he is using.
Socher, Guido - [email protected] [971009]
NOTE: Guido Socher once converted the vim-3.0 refcard.txt to html:
http://www.math.fu-berlin.de/~guckes/vim/vim-3.0.refcard.html
St-Amant, Dany - [email protected] [980219,990223]
http://www3.sympatico.ca/dany.stamant/vim/
Note: Dany St-Amant is porting vim-5 to MacOS.
Starsmeare, Keith - [email protected] [971204]
http://www.tardis.ed.ac.uk/~keith/ (home page)
Note: Keith Starsmeare was looking for help to install vim on these systems: DG and Dynix/PTX.
He told me that he succeeded in doing so now. Maybe he'll maintain a page about vim where he'll
offer the binaries? :-)
Steden, Klaus - [email protected] [990828]
Binaries: http://www.rassilon.net/~vitamink/vim/
BSD/OS 4.0, SunOS 5.6 x86 (Solaris 2.6 x86)
Environment: Work: IRIX, Solaris, Linux; Home: BSD/OS, IRIX, Solaris, Linux, +OpenBSD
Thomas, Stephen - [email protected] [971208]
Inform: inform.vim
Environment:
Home: Linux 2.1.* series, based on Red Hat 4.1, on a 200MHz PPro 128Mb machine.
Work: HPUX 10.20, on a HPPA1.1 735/125. Not as nice as my Linux box :-)
Note: Stephen Thomas is the maintainer of the syntax file for "Inform" source code. And his syntax
file didn't make it into the release of vim-5.0s it is available now locally as syntax/inform.vim.
Hopefully, this will make it into the next distribution. Maybe Stephen will be supporting it from a
web page of its own, too? :-)
Tennent, Robert - [email protected] [971002]
Robert Tennent might try to produce a "barebones" version of Vim for Linux, ie a very small version
without any of the special compile options. Would be nice if he could maintain it, too.
Uhl, Mike - Mike Uhl [email protected] [990308]
Note: Mike Uhl is a minimalist: He is using vim-3 because he has no space for the bigger versions of
vim. He might try vim-4 or vim-5 as soon as he gets more space. / He answeres posts on
comp.editors, too. (And, yes, I once asked him for the reason of his username. ;-)
Urban, Thomas Scott - [email protected] [971218,980703,000502]
http://members.home.com/tsurban/vim/
http://www.blarg.net/~urban/vim/ [obsolete]
Povray syntax file:
http://members.home.com/tsurban/vim/syntax/pov.vim
Note: Thomas Scott Urban also maintains a setup for HTML menus - look at his page for a
screenshot.
Verdoolaege, Sven - [email protected] [971217]
Note: Sven Verdoolaege implemented the perl patches for Vim.
Zachmann, Gabriel - [email protected] [980910,981116]
http://www.igd.fhg.de/~zach/vim/
Ziegler , Austin - [email protected] [971009,990226]
http://fantome.vnet.net/vim/ [*]
Proc*C (Oracle): http://fantome.vnet.net/vim/syntax/proc.vim [*]
SQL*Forms (Oracle): http://fantome.vnet.net/vim/syntax/sqlforms.vim [*]
Note: These webpages were not available in Jan 1999 and probably will be for some time. But you
can request them from Austin via email.
"I am in the process of getting my Pro*C and SQL*Forms syntax files set up for "public
consumption", but I will need to talk to the maintainers of the C/C++ and/or SQL syntax files in
order to get them ready (I don't want to end up redoing their work)."
and last not least:
Silver's Petz Site [000419]
http://silver.trica.com/petz/
Note: screenshot
todo
Add these users and ask for permission and info again.
● http://www.unb.ca/chem/ajit/vim.htm
+perl
Gossamer [email protected]
John M. Klassa [email protected]
Changes
980723
Moved the info on "Syntax Coloring Setup Files Maintainers" onto a page of its own - the "Vim
Languages Page":
● http://www.vim.org/lang.html
980703
Removed the links to vimrcs. Please link these from your own vim page - thanks!
980514
❍ Removed the entry "Email:" to shorten them.
❍ Removed the "mailto links" as I do not want "address harvesters" to get them that easily off
this page. The mail address is now put directly after the name.
❍ Only two dates now - the date of first entry and the date of last change. They also go after the
name and email address.
❍ Removed all links to homepages as these usually can easily be derived from the address of the
vim page by simply removing the "/vim".
❍ Made link to vim page the first link in each entry. That's the way I intended this page to be.
URL: http://www.math.fu-berlin.de/~guckes/vim/user.html
URL: http://www.vim.org/user.html (mirror)
Created: Tue Jun 24 12:00:00 CET 1997
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Wed Mar 14 16:23:42 MET 2001
VIM - Wishlist
VIM is a great editor, but no program is perfect for everyone. VIM does not have everything, of course. A lot of things have
been proposed so far and many are on the "todo list".
Please note: The "todo list" is maintained by the author and ships with the distribution of Vim (filename "todo"). It is not the
same as this "Vim Wishlist".
● todo (user release)
:help todo
/redef
- Be able to redefine where a sentence stops. Use a regexp pattern?
- Be able to redefine where a paragraph starts.
For "[[" where the '{' is not in column 1.
Perl RegEx
Add support for Perl regular expressions (eg backreferences). Maybe add PCRE (Perl Compatible RE).
Warren Young [email protected] [000601]
support for "crypto editing"
"Add a memory only mode to vim, i.e. a mode where you don't write to a file at ALL. instead, vim allocates some
RAM (or even mlockall's it) and then treats that as the file buffer. Then on exit, it writes this out to a fifo, and that's it.
The data NEVER touches disk. Reasoning: CRYPTO."
Justin Hahn [email protected] [000328]
lisp option
Fix the behaviour of the option "lisp".
Matthis Buelow [email protected] says this is broken.
Display cursor within offsets
Option
The value "T,B" will prevent the cursor from being displayed
within the T top lines and B bottom lines of the current window.
If T+B exceeds the number of lines in the current window
then the cursor will always be displayed on the middle line.
However, the start and end of the buffer is always shown.
Michael Saunders [email protected] and Sven Guckes [000222]
search across buffers
Add an option to allow searches to scan all open buffers. (Some people do not have a decent "grep" on the machines,
apparaently.)
Micha [email protected] [000130]
GUI: textwidth bar
Show the current textwidth with a vertical bar within the GUI window.
Devin Weaver [email protected] 991118
support for template editing
Add support for editing of "templates". This allow editing of parts of a given text only ("fields"). You should be able
to chose from a list of given values ("menu"), or type in answers. A restriction to the character set may be given by
regular expressions.
Example:
text: foo.
bar
command: :j
result: foo. bar
Problem: This works only for the dot character - but not for other characters which *could* end a sentence, such as
":!?".
Suggestion: Add an string option that allows to define the set of characters for which an additional space shall be
added with a ":join". This would also allow to turn this behaviour off completely, thus allowing for consitency of a
":join" command.
Suggested by: Sven Guckes [email protected] [970915,980304]
:join - remove quote
Situation: Two consequtive lines with the same quote prefix, cursor on first line.
Problem: The command ":join" does not remove the quote prefix for the second line.
Example: text: > > foo > > bar command :join result > > foo > > bar
Workaround: Select both lines visually and use text formatting with "gq".
Suggestion: Add option 'j' to "formatoptions" to allow/disallow this. Bram said it's a good idea and he'll add a remark
to the todo list.
Suggested by: Sven Guckes [email protected] [970915,980304]
N^ vs N$
Repeting the jump '^' does not change the position. However, repeating '$' will move down N-1 lines. This is
inconsistent.
Suggestion: Make N$ jump to the end of line and *not* leave the current line. Use N- and N+ to move between lines
instead.
Suggested by: Sven Guckes [email protected] [970717,980304]
:ua - :update all
*:ua* *:uall*
Write all modified buffers to file.
Unmodified buffers are not written.
{not in Vi}
Suggested by: Markus Klein [email protected] [980302]
file locking
Vim-5 does not "lock" edited files - yet.
Add option "filelock" which will "lock" edited files. (nvi does this, it seems).
Problems: File locking does not exist for every OS - thus it can be a Unix feature for now only. Also, a locked file
needs to kept "open"; as there is a limit to this number every locked file will reduce the number of files which can still
be opened. Tricky!
Suggested by: Several people [980225]
display - show mode with cursor and color
Vim shows the current mode when you ":set showmode". But when you are on the command line then the cursor is on
the command line, too, so you cannot see which buffer/window the command will be applied to.
Show the current window by coloring the status bar of the current window or by changing the background color.
For GUI version (inspired by elvis): Show the current mode by changing the shape of the cursor:
cursor position:
c column show the column number of the cursor
l line show the line number of the cursor
window position:
H high show number of first line of current window
L low show number of last line of current window
M middle show number of middle line of current window
G last show number of last line of current buffer
NOTE: The flags for lines of the current window and for the last line
were chosen to match Vi's default commands to jump to these lines.
The default format is "%l,%c-%C [H=%H,M=%ML=%L,G=%G] (%r,%p)".
Unset flags will simply leave out the information and surrounding brackets.
if exists("_vimrc")
source _vimrc
fi
Syntax for the script is to be decided upon later (please don't start a discussion about this right now!)."
Definition of start/end strings for start/end matching.
Should be very useful for matching begin/end strings, eg comments, function definitions, latex or html commands,
and all bracket pairs, ie `'(){}[]<>.
Suggested by: vimdev people [960430]
Command history for normal mode commands.
Add a special read-only buffer to show the history of normal mode commands, one complete command one separate
lines. This would allow copying of commands into registers easily.
Suggested by: Sven Guckes [email protected] [960430]
ex commands on registers
Allow ex commands to work on registers. Example: :"as/foo/bar/g works on buffer 'a' searching for "foo" and
replacing it with "bar" globally.
Suggested by: Alain Sarraf ([email protected]) [960317]
Statistics on visual selection
Add command to visual mode to show statisctics on selected text. The statistics show info on lines, characters, words,
width, and paragraphs.
Example:
Screen Jumps
So we'd use 'h' and 'l' for the usual left/right movement (with an optional 'r'
for "right"). 'H' and 'L' work in analogy to 'h' and 'l', ie the go to the
boundary of the current window. And 'M' does the same for the "middle".
As there is only one middle we can use 'm', too. Same holds for 'C' and 'c'
for those who prefer to think of "center".
And there is a jump by tabstop with ^D and ^T -
using '<' and '>' as easy alternatives.
"Z0" and "Z$" can be interpreted as '0' and '$'.
file-wide-search
find next/previous occurrence of last search string in next/previous file.
Change to status line
Problem: The status line does not always show what people prefer.
Suggested change: Make it possible to define the status line via a printf function. Suggested by: Bram Moolenaar
Suggested values for status line: pwd, time, mail, hint to ":help", buffer size, ruler. Add extra help lines for newbies to
show more info, eg basic movement and editing commands, current filename.
Suggested by: Sven Guckes [email protected]
cursor jump list
Problem: Typos can also lead to unanted cursor movements. You cannot undo a move unless it was a "jump",
however.
Suggested change: Add command to undo *all* cursor movements.
Decision: Won't be done as it is too difficult to implement. The commands CTRL-I and CTRL-O should suffice.
gvim cursor
Give the cursor different colours for different modes.
Change: (I) - insert
Add option "smartindent" (alphanumeric) to change the jump and mode involved with "I":
Default: smartindent=0i
0: Jump to first non-whitespace character of current line.
1,2,3: Jump to first (1) space (2) tab (3) letter of current line.
and switch to (1) insert mode (2) append mode (3) . (default)
a,i,o,r: Switch to (a) append (i) insert (o) open (r) replace mode.
The last cipher or letter "wins".
Add option "insert" (numeric) to enable use of the "insert_key" to cycle through the five "insert modes", ie
"command", "append", "insert", "open", "replace":
Default: insert=0
0: No effect.
1: Enable "append".
2: Enable "insert".
4: Enable "open".
8: Enable "replace".
Example: insert=10 enables "2" and "8", ie pressing the "insert_key"
repeatedly will cycle through mode "command" -> "insert" -> "replace" ->
"command".
NEW: :set noexpandbeep [Change: (tab) - filename completion]
Fact: When using the expandkey on a filename then you get a beep if the completions is ambiguous.
Add option to suppress beep and/or show *number* of possible completions.
Suggested by: Sven Guckes [email protected]
NEW: Add all numbers in visual
{visual}
Change: visual mode
Add command to add all numbers in visual. Would be *very* useful to add numbers in columns.
Suggested by: Sven Guckes [email protected]
Change: (K) - Keyword call
keywordprg (kp) string (default "ref")
Program to use for the "K" command. Environment variables are expanded.
{not in Vi}
Suggested change: Do not make a shell call if "kp" is not set (ie empty). [TODO: This seem to have been
implemented. Check again! 960701]
NEW option: "repaintfromtop"
Will stop the scrolling for commands ^d and ^u by repainting the screen from top.
NEW: gdb support (as with emacs)
[left to an emacs fan for description ;-]
NEW: scrolling regions for popup lists [960130]
...
NEW: keyword (syntax) highlighting and colouring
one of *the* most wanted wishes
code structure
Restrict functions to, say, 50 lines. This makes reading and checking of the code a lot easier.
External solutions
The following stuff can be done with external programs using the filter command and thus probably will not be
implemented.
Making commands work on the current paragraph
Submitted by Thomas Köhler on 990702: :com! -nargs=* -complete=command Par call Pardo("<args>") :fun!
Pardo(command) : let col=col(".") : let line=line(".") : norm { : let a=line(".") : norm } : let b=line(".") : exe ":" . a . ","
. b . a:command : exe line : exe "norm " . col . "\|" :endfun Now, what does this do? :com! -nargs=*
-complete=command Par call Pardo("") This defines a new command "Par" that completes ex-commands. It calls a
function "Pardo()" with the rest of its commandline as one argument.
What does Pardo() do? It applies its argument (should be an ex-command) to the current paragraph. It works like this:
:fun! Pardo(command) " this remembers current cursor position : let col=col(".") : let line=line(".") " jump to the
beginning of the paragraph and remember that cursor position : norm { : let a=line(".") " jump to the end of the
paragraph and remember that cursor position : norm } : let b=line(".") " apply the command given as an argument on
the range a,b : exe ":" . a . "," . b . a:command " jump back to the position we were before (this may be confusing if " "
ex-command is something like 'd' ;-) " : exe line " : exe "norm " . col . "\|" " :endfun
normal/visual command '~' (aka "switch")
options trin and trout
Make the "switch" command '~' switch character and the characters in visual text according to the options "trin"
("translate input") and "trout" ("translate output").
Yes, I know that you can use the command "tr" on Unix externally - but then not everybody is using Unix, right?
Even using an external script for this (I once used a sed script) needs to be set up correctly as well. It would definitely
be nice to have this command internal to vim as this would do away with extra installations. Besides, it is easy to
code, too. I wish I was able to do this - then it would already be done.
Anyway, support for "sets" would be nice, as this makes it much easier to denote them.
Example: UPPER/lower
set trin="A-Z"
set trout="a-z"
This is just to show that the usual functionality of the switch command is just a special case.
Example: Pairs
set trin="A-Z a-z < {} [] () \/ `' ,. :; +-"
set trout="a-z A-Z > }{ ][ )( /\ '` ., ;: -+"
This not only switches letters - but also brackets pairs and other corresponding characters (slash/backslash,
tick/backtick, dot/comma, colon/semicolon, plus/minus). This allows an easy fix of frequent typos for these
characters.
Note: The spaces within the values of "trin" and "trout" of the previous example are just for readability.
Suggested by: Aaron Schuman [email protected] [980427]
Example: "Caesar Cipher" Code
set trin="a-zA-Z"
set trout="d-za-cD-ZA-C"
This shifts all letters three positions forward within the alphabet. Of course, this asks for a setup to decode it, too:
set trin="a-zA-Z"
set trout="x-za-wX-ZA-W"
Although switching these values is just a matter of a simple mapping, it is much nicer to use a code which is invers to
itself, so you need not change any setting. Such a code is "rot13":
Example: ROT13
set trin="a-zA-Z"
set trout="n-za-mN-ZA-M"
This code shifts letters by 13 characters, ie half the length of the alphabet. That way, it is invers to itself, so that using
it twice on the same text reveals the original. This "rotation" is usually abbreviated as "rot13". This code is used on
Usenet quite often to hide the text from casual reading, and thus often used to hide "spoilers" to puzzles or for hiding
"offesive" text such as in posts to rec.humor.tasteles. ;-)
Suggested by: Sven Guckes [email protected] [950101,970919,980430,980504]
Evaluate math strings
Change: visual mode
Add command to visual mode to evaluate "math strings" for integers, eg "(- 123 + 789 + 456) / 2 * 3 + 2^5 + 3**4"
should give "1496".
whitespace
a all prefix suffix
i inner none none
p prefix prefix none
s suffix none suffix
text objects
p paragraph
P paragraph delimited by blank lines
s sentence
S sentence - delimiters can be defined
Suggested by: Sven Guckes [email protected] [960521,980304]
new command
:history
Fact: You can see previous commands on the command line using the command ^P.
Problem: There is no command to show a list of the last N commands. Suggested Solution: Add command ":history"
to show the list of the last N command line commands.
Suggested by: Sven Guckes [email protected] [960615]
change command ^W
^WN - jump to window N
Purpose: Access a window directly.
Suggested Solution: Give the first ten windows a digit as number. Allow to directly switch to them by the window
command followed by the digit, ie "^W3" to jump to window #3.
| ... ...
|[2] ~/foo
| ... ...
|[3] ~/bar
| ... ...
|:command line
Suggested by: Sven Guckes [email protected] [960622]
change command i_CTRL-R
^R"X
Fact: You cannot recall the contents from a buffer when the name is preceded by a '"'.
Purpose: Put contents from buffer X into text in replace mode
Suggested Solution: This will replace text with the contents from a buffer as if you typed it in when using 'R' to
replace text.
Suggested by: Leslie Gerstenfeld [email protected] [960718]
matchoffset=4,3 (keep four lines from top and three lines from bottom)
_________________ window border
1: top line of current window
2:
3:
4:
5: matching line
6:
7:
8:
9: bottom line of current window
================= window status line
Suggested by: Bill Luebkert [email protected] [960603]
new option
"quitdialog"
Purpose: exit confirmation dialog
Fact: When you quit the last (the only) window with ":quit" then VIM prompts you with "No write since last change
(use ! to override)".
Problem: You have to issue the command ":q!" yourself or write the buffer first. There is no dialogue for the user.
Suggested Solution: Add option "quitdialog" that will make VIM give a dialog to allow the choice of ":write", ":quit!"
and "cancel" (ie return to editing). This is useful when you would like to keep VIM running. And it would be nice on
newbies, too.
Suggested by: Meir Shahar [email protected] [960604,970404]
Optionally: Give "quit" prompt to user when using ESC or interrupt in normal mode.
Suggested by: John H Meyers [email protected] [960513]
new options
"remarkformat" and "warningformat"
Problem: You cannot customize the formats for remarks and warnings of compilers.
Suggested Solution: Add variables "remarkformat" and "warningformat" to enable recognition of remarks and
warnings that compilers produce. Also add commands to jump forward/backward between remarks and warnings.
Suggested by: Gabriel Zachmann [email protected]
new option
"screen_update_macro"
Fact: During excution of a macro the screen is updated.
Problem: The screen updates can slow down the excution of the macro.
Suggestion: With "noscreen_update_macro" all screen updates during the excution of macros are suppressed. This
could speed up the excution of macros considerably.
Idea: This idea is from the vi clone "elvis".
Suggested by: Sumner Hayes [email protected] [960629]
Translate ^M to ^J:
:def = :%s/=^M/=^J/
vim-5.0r added:
- "\w" in regexp, for whitespace. Should be much faster than "[ \t]".
vim-5.0s:
- Added "\S" to regexp patterns: matches a non-white character.
Changed "\w" to "\s", to make it similar with Perl.
Using "\s\+" for any non-zero sequence of these is very handy! I use "\s\+$" to detect trailing whitespace.
swap file - create swap file after first modification
Create the swap *after* the first modification - not before. Optional.
Suggested by: Yang Guo Liang ([email protected]) and Sven Guckes [email protected] [970919]
Added with vim-5.0o. [970929]
search pattern - Perl minimum closure
Allow to match the shortest possible match for a regex.
Example: "s/\<.*?\>/[\1]/" puts square brackets around the shortest word.
Suggested by: Edwin van Geelen [email protected] [990311]
Vim has this already - the "magic patttern" "\{-}".
VIM Wishlist - TODO
● Documentation: Check occurrences of "<NT>" - should they be replaced by "<EOL>"?
Back to the -> VIM Home Page
URL: http://www.math.fu-berlin.de/~guckes/vim/wish.html
URL: http://www.vim.org/wish.html (mirror)
Created: Mon May 15 00:00:00 MET 1995
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Fri Oct 20 20:00:00 MET DST 2000
Overview
Email | FTP | WWW
History | Credits | Others VIMs
Email
Everything about Email to vim.org should be explained on the page about mails
addresses by function
(target addresses can be changed when service is taken over someone else):
If you like to set up a mirror for www.vim.org then you are very welcome to do so. See the Vim HowTo on Mirroring
www.vim.org for more info on this matter.
FTP and WWW mirrors in other countries usually bear the name ftp.city.country.vim.org and www.XY.vim.org,
respectively, where XY is the two letter code of that country.
Also, I will try to get all distribution sites to carry vim in /pub/vim. Let's see if this is feasible.
I am considering to make the helpfiles of the current version available for FTP as an archive by itself in HTML for
browsing ie ftp://ftp.vim.org/html/vim.docs.html.tar.gz . Is anybody interested in this? Let me know! Send mail to
[email protected] !
vim.org - History
000819
vim.org is now hosted by gandi.net
● whois vim.org
980625
Some more CNAMEs have been added for the ftp servers of vim.org. Check with "nslookup" if you like:
$ nslookup
server ns.vim.org
ls -a vim.org
971017
We are currently naming the ftp mirrors...
970918
The pages on vim.org are now a mirror of the pages at Sven's place. No more redirection -> bookmarks go to
vim.org. :-) It is intended that the pages on VI also get mirrored. So all info on VI is then on vim.org. Hopefully
this will then become *the* reference site on VI on the Web. Send me the addresses on good VI info!
970915
Success!
VIM.ORG finally has come to life! :-)
$ whois vim.org
Vim.org - Vi IMproved (Sven Guckes) (VIM3-DOM)
Pariser Str. 52
Berlin, 10719
de
Administrative Contact:
Guckes, Sven (SG3457) [email protected]
+49(177)7777796 (FAX) +49(30)8838884
Technical Contact, Zone Contact:
Zehl, Stefan (SZ232) [email protected]
0177/2340515 (FAX) +49(89)3618023
Billing Contact:
Zehl, Stefan (SZ232) [email protected]
0177/2340515 (FAX) +49(89)3618023
R2D2.MUSIN.DE 194.113.40.45
EWOK.PI.MUSIN.DE 194.246.250.2
$ whois vim
Avila, Roy M. (RMA8) [email protected] (617)773-1536
Chirife, Alejandro (AC294) [email protected] 305-536-3520
Henry, Martin (MH1305) [email protected] (617)878-7936
Idan, Tzvika (TI265) [email protected] +972-9-9599093 (FAX) +972-9-9599608
Mahadeva, Vimalan (VM577) [email protected] 310 854-8220 (FAX) 310 652-9053
VIM (VDOMAIN2-DOM) VDOMAIN.COM
VIM (Verkaik Innovative Management) (VIM2-DOM) VIM.NET
VIM Industries (UKRAINEGIRLS-DOM) UKRAINEGIRLS.COM
VIM Studios (LOCALFINDER-DOM) LOCALFINDER.COM
VIM Studios (NETTRACKS-DOM) NETTRACKS.COM
VIM Studios (SECUREDTRANS-DOM) SECUREDTRANS.COM
VIM Technologies, INC. (VIMTECHNOLOGIES-DOM) VIMTECHNOLOGIES.COM
VIM, Inc. (ONLINESALES-DOM) ONLINESALES.COM
VIm Partners (VALUEINVESTMENT-DOM) VALUEINVESTMENT.COM
Vim Corp. (VIMC-DOM) VIMC.COM
Vim Gupta (VG12-ORG) [email protected] 0181 348 2247
Vim Studios (ADVERTISEIT-DOM) ADVERTISEIT.COM
Vim Studios (MYVEGAS-DOM) MYVEGAS.COM
Vim Studios (MOVIETHEATRES3-DOM) MOVIETHEATRES.COM
Vim Studios (VIMSTUDIOS-DOM) VIMSTUDIOS.COM
Vim Studios (OUTTASITES-DOM) OUTTASITES.COM
And last but not least one of my favourite Vim companies:
From a Biography of Oliver Hardy (a famous comedian):
"Oliver is known to have been in Jacksonville, Florida at least until the Vim Comedy Company stopped production
in 1916."
No, Vi IMproved was not meant as a joke. ;-)
URL: http://www.math.fu-berlin.de/~guckes/vim/orga.html
URL: http://www.vim.org/orga.html (mirror)
Created: Thu Sep 11 00:00:00 CET 1997
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Thu Jun 07 12:00:00 MEST 2001
to add:
http://www.linux.com/search/index.phtml/vim/
page: http://www.linux-mag.com/2000-06/websites_09.html
(Category) "Documentation"
The Vim Homepage
http://www.vim.org/
text:
Get a handle on the editor that strikes fear into the heart of newbies
everywhere, Vim. Vim is the most popular vi clone for Linux, and the Vim
homepage has tons of information on using Vim and how to customize it.
page: http://www.linux-magazin.de/ausgabe/1997/03/
link: http://www.linux-magazin.de/ausgabe/1997/03/Quickrefs/vimref.ps
author: Peter Zitzelsperger
size: (42K)
February 2001 - "Linux Journal" [ISSN ?]
pages 140 - 146: "That's Vimprovement! A Better vi" (Be a better editor - try Vim) by Steve
Oualline. Steve manages to explain the main Vim features in five pages, with pictures and examples.
From using undo/redo and multiple windows, via syntax highlighting and :make, to recording and
executing a macro.
October 2000 - Linux200.nl conference, 9-10 Oct 2000 in Ede
The continuing story of Vim
The paper submitted by Bram for the Linux200.nl conference, taking place 9-10 Oct 2000 in Ede
(Netherlands)
Author: Bram Moolenaar
September 2000 - "Software Design" [ISSN 0916-6297]
http://www.gihyo.co.jp/SD/index-j.html
Author: Takuhiro Nishioka [email protected]
Contents: "Hajimete no Vim (Learning the Vim editor)"
Language: Japanese
Scan of article: http://www.win.ne.jp/~takuhiro/image_files/vim_software_design.png
August 2000 - OS/2 eZine [001114]
Vim for OS/2 (local copy)
http://www.os2ezine.com/20000816/vim.html
Author: Richard R. Klemmer [email protected]
"Why use Vim? .. if you ever have to telnet into your OS/2 system, you won't be able to use any of
the Presentation Manager programs, such as EPM, so you will need at text mode program to edit any
files. You can use ***** which comes with OS/2, but I think you'll find that this pales in comparison
to what you can to with VIM."
July 2000 - LinuxNewbie.org
http://www.linuxnewbie.org/nhf/intel/programming/intro_c++.html
Author: Keith Jones [email protected]
Contents: Mentions tags, C-style indenting, QuickFix mode, some useful keystrokes (jumps),
substitution command, misc features, and a few links.
March 2000
Title: Interview with Bram Moolenaar
Media: PCRevue
original
Title page and contsnts:
http://www.pcrevue.com/buxus/generate_page.php3?page_id=148
local copy
Author: Juraj Bednar [email protected]
November 1999
Title: VIM: Vi IMproved!
Media: Linux Magazine France
scan of article (210K)
Author: Henri Dumoulin
"While some prefers 'clickodromes', advanced users prefer lighter interfaces and rather in a console.
This is typically the case in text editors. On one side: Gnotepads, Knotes and other notepad clones.
On the other side: the never-ending dual VI/emacs. Let's have a look at the free version of VI written
by B.Moolenaar : VIM 5.5"
October 1999
Title: An Interview with Vim Authors
Media: Effervescence (Magazine de l'Association des Ingénieurs EFREI)
Author: Hervé Foucher
In English: http://web.efrei.fr/aiefrei/effervescence/123/vim.en.html
In French: http://web.efrei.fr/aiefrei/effervescence/123/vim.fr.html
In Chinese: effervescence.interview.cn.html Translated by [email protected] [010503,010607]
October 1999
Title: Text Editors for DOS and Windows
Media: IEEE.org (IEEE Electronic Communications)
http://www.spectrum.ieee.org/INST/oct99/inf_hwy.html
Author: Bob Alden [email protected]
Local copy (text only): ieee.oct99.inf_hwy.txt [7K]
October 1999
Title: Linux Advanced Workshop #2
Media: PCPlus
http://www.futurenet.com/pcplus/article.asp?id=11723
Author: Chris Jones
Issue 156, pages 187/188. Section "Hands On", Linux advanced workshop. Written by Chis Jones. It
is two pages, and goes from the first commands to a few more advanced topics.
There are two pictures. The first shows the Vim 5.3 startup screen (although the article mentions
version 5.4). The other shows a message in the comp.editors newsgroup from Sven Guckes to
Michael Soulier, subject "tabs in VI -> Vim and listchars". It's shown with syntax highlighting.
The included CDROM contains Vim-5.4 with the runtime archive and RPMs for RedHat.
September 1999
Title: From Linux to FreeBSD
Media: Daemon News - Web Magazine
http://www.daemonnews.org/199909/adventure.html
Author: Justin Hawkins [email protected]
".. Within a few hours (unfortunately I'm still using a 28.8K modem) I had compiled and installed all
my essential software, Samba [3], Apache[4], Ghostscript[5] and of course vim[6]. [...] [6] VI
iMproved. Adds many features to standard vi, including colour syntax highlighting for program
code."
August 1999
Title: Using vi - an introduction
Media: IEEE Electronic Communications
http://www.spectrum.ieee.org/INST/aug99/inf_hwy.html
Author: Bob Alden [email protected]
Local copy (text only): ieee.aug99.inf_hwy.txt [7K]
August 1999
Title: And the Winner is...
Media: LinuxWorld.com
http://www.linuxworld.com/lw-1999-08/lw-08-penguin_1.html
The results to the LinuxWorld Editors' Choice were given on Aug 11th. Here is the result of the
category "Text Editors": "Text Editing -- Winner: Emacs -- Runner-up: Vim"
Vim: What Vim lacks in features (as compared to the feature-heavy Emacs), it makes up
easily in speed and simplicity. Vim is the ideal editor for the kinds of quick jobs one
must always do under Linux, such as the editing of text-based configuration files or
shell scripts. In this case, we chose not to go to the extreme of simplicity, but to balance
speed and simplicity with power. Vim seems to find the best balance of the editors we
tried, and gets an extra boost because it is an extension of vi, the simple editor that most
Unix users seem to know -- if not sooner, then later.
June 1999
Media: LinuxWorld
Linux development: CLI, Emacs, or IDE
http://www.linuxworld.com/linuxworld/lw-1999-06/lw-06-vcontrol_1.html
KDE developer and evangelist Kurt Granroth has a different idea. When I asked him
about his preferred development environment he said "I use vim (not just vi -- only vim
will do) with egcs and gdb."
February 1999
Title: An Interview with the VIMpire
Media: EXT2.org
http://www.ext2.org/99/02/vim.html
Local copy: vimpire.html
Author: Rob Kennedy [email protected]
Bram Moolenaar answers some FAQs: What is Vim? How did Vim start off? How close to Vi is
Vim? What are the best improvements?
October 1998
Title: Inside Slashdot
Media: Slashdot
http://linuxworld.com/linuxworld/lw-1998-10/lw-10-slashdot.html
Slashdot's Rob Malda (aka CmdrTaco) takes us through the technical changes his
popular Web site has undergone in the last year and a half...
"...but as Slashdot's popularity grew, the response became more and more sluggish.
During peak hours, the machine's load level would climb to 10.0 (A load of 1.0 refers to
one fully busy CPU; 0.50 to 1.50 is normal) or even higher. Even at that point, telnet
sessions running pine and vim remained usable. I was quite impressed. .."
September 1998 - Wandering-Man.com
The Vim text editor for Java programmers - "Not Only, but Also.."
http://www.wandering-man.com/Java/vim/java_Vim.html
Author: Allan Kelly [email protected]
Nice article with screenshots.
September 1998
Title: Extended Standard
Media: "iX 9/98", page 67
Author: Garry Glendown [email protected]
Article in English
Article in German
A one-page article on vim-5.1 mentioning "Vi Improvement" as "having many options".
June 1998 [980429]
Revisiting VIM
Media: "Linux Gazette", Issue 29
Author: Andy Kahn [email protected]
http://www.linuxgazette.com/issue29/kahn.html
(List of) Features, Syntax highlighting, Built-in Scripting, Visual Text Selecting (indenting,
deindenting, filtering), C and C++ tags. With a dozen screenshots.
February 1998
Linux - 2 Cents about vim for pico users
Media: "Linux Gazette", Issue 25
Author: Sven Guckes [email protected]
http://www.linuxgazette.com/issue25/lg_tips25.html#vim
Sven Guckes gives a tip for users of the editor "pico" who are used to "justify" (read: reformat) the
current paragraph with CTRL-J. Here's how to do this with Vim: nmap <C-J> vipgq nmap <C-J> gq
January 1998
Title: New Editor Versions
Media: "Linux Gazette", Issue 24
http://www.linuxgazette.com/issue24/issue24.html
This issue quotes the Usenet article
[email protected]
Vim is probably the most featureful of the VI-style editors. Judging by newsgroup
postings, it may be the most popular as well. With the release of vim-5.0s, vim 5 has
finally reached a beta rather than alpha state. This revision has a really
well-implemented syntax-highlighting system for many programming and shell-script
languages, and it's not too difficult to adapt to new file-types and languages. The
down-side is that vim is growing larger, and is beginning to lose the quickness and low
memory-usage that has been a hallmark of VI-style editors. [...]
June 1997
Title: VIM Programming Perks
Media: "Linux Gazette" - Issue 18
Author: John M. Fisk [email protected]
http://www.linuxgazette.com/issue18/wkndmech.html#vim-perks
John gives some hints on programming with Vim-5.0e: GUI, syntax highlighting, :help, tags,
exuberant ctags, :split and window commands (CTRL-W), using RCS, things to do with the current
file (printing, spell checking, read in other data), running :make, unlimited undo, support for
compressed files; sample setup, and eleven screen shots.
February 1997
Title: Pick an Editor, Any Editor
Media: "Linux Gazette" - Issue 14
Author: Jens Wessling [email protected]
http://www.linuxgazette.com/issue14/vim.html
Mentions the "ctags" utility, Includes mappings to (un)comment lines. [980106]
August 1995
Title: If you gotta use VI, use VIM
Media: "Linux Gazette", Issue 01-08
Author: John M. Fisk [email protected]
http://www.linuxgazette.com/issue01to08/linux_gazette.aug.html#vim
"It actually tells you what mode you're in. It has an easily accessible on-line help function. It works
quite well under X when teamed up with xterm." Also mentions that you can ":split" windows.
TODO
Linux-Mag.com September 1999
http://www.linux-mag.com/1999-09/tech_support_01.html
"There are other text editors you can investigate, but they are not for the faint of heart,
as they are known for their arcane and hard to remember commands. Among these are
vi, vim,elvis and their clones. If you intend to make a career out of being a Linux or
UNIX sysadmin, I recommend at least having a passing familiarity with vi, as it is
installed by default on every version of UNIX, even in its most pared-down state."
Linux-Mag.com August 1999
Author: Hal Moroff [email protected]
http://www.linux-mag.com/1999-08/newbies_02.html
You must edit a file to do this. The text editors that come with Linux are very good, but
will take a fair amount of explaining. For now I recommend the vi (or vim) editor.
For more information on Vim see the Vim Pages.
URL: http://www.math.fu-berlin.de/~guckes/vim/press/
URL: http://www.vim.org/press/ (mirror)
Created: Tue Jun 09 00:00:00 CEST 1998
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Thu Mar 15 02:30:00 MET 2001
● Add links to online versions not yet mentioned in the vim-5.7 version of the syntax files.
● List of maintainers of several syntax files. (Bigham, Campbell, Eymers, Fleiner, Lanzarotta, Moolenaar, Mudunuri, Riiser, ..)
VERSION NAME +
AUTHOR ADDRESS STATUS URL
+ DATE LINK
vim-5.7 2html
Bram Moolenaar [email protected] --- ---
000114
vim-5.7!
abaqus Carl Osterwisch [email protected] --- ---
000208
vim-5.7 abc
James Allwright [email protected] 404 http://perun.hscs.wmin.ac.uk/vim/syntax/abc.vim
990526
vim-5.7 abel
John Cook [email protected] --- ---
990922
vim-5.7 ada David A.
[email protected] --- ---
981207 Wheeler
vim-5.7
ahdl John Cook [email protected] --- ---
990928
vim-5.7 amiga Dr. Charles E.
[email protected] --- ---
980518 Campbell, Jr.
vim-5.7 aml Todd Glover [email protected] --- ---
991104
vim-5.6 apache Allan Kelly [email protected] [001031:new!] --- ---
000124
vim-5.7 apachestyle Christian [email protected] --- ---
991028 Hammers
vim-5.7 asm Kevin
[email protected] --- ---
000209 Dahlhausen
vim-5.7 asmh8300 Kevin [email protected] --- ---
970420 Dahlhausen
vim-5.7 asn 010117 http://www.fleiner.com/vim/syntax/asn.vim
Claudio Fleiner [email protected]
980307 ok
vim-5.7 aspperl 010117 http://nim.dhs.org/~edh/aspperl.vim
Aaron Hope [email protected]
000606 ok
vim-5.7 010117
aspvbs Devin Weaver [email protected] http://tritarget.com/vim/syntax/aspvbs.vim
000501 ok
vim-5.7 atlas Inaki Saez [email protected] --- ---
980331
vim-5.7 ave Jan-Oliver
[email protected] --- ---
980911 Wagner
vim-5.7 awk Antonio
[email protected] --- ---
971127 Colombo
vim-5.7 basic Allan Kelly [email protected] --- ---
990914
vim-5.7 bc 010117 http://www.gjh.sk/~vlado/bc.vim
Vladimir Scholtz [email protected]
000606 ok
vim-5.7 010117
bib Bernd Feige [email protected] http://home.t-online.de/home/Bernd.Feige/bib.vim
000510 ok
vim-5.7 btm John Leo Spetz [email protected] --- ---
990702
vim-5.7 c Bram Moolenaar [email protected] --- ---
000601
vim-5.7 cf Jeff Lanzarotta [email protected] ! --- ---
000110
vim-5.7 ch YoungSang
[email protected] --- ---
000507 Yoon
vim-5.7
change Andreas Scherer [email protected] --- ---
990823
vim-5.7 clean Pieter van
[email protected] --- ---
980206 Engelen
vim-5.7 clipper Claudio R
[email protected] --- ---
990816 Zamana
vim-5.7 cobol Sitaram
[email protected] --- ---
991221 Chamarty
vim-5.7 colortest Bram Moolenaar [email protected] --- ---
981101
vim-5.7 conf Bram Moolenaar [email protected] --- ---
000211
vim-5.7 config Christian
[email protected] --- ---
000415 Hammesr
vim-5.7 cpp Ken Shan [email protected] --- ---
000412
vim-5.7 csh Dr. Charles E.
[email protected] ??? ???
000316 Campbell, Jr.
vim-5.7
csp Jan Bredereke [email protected] 000614! http://www.tzi.de/~brederek/vim/csp.vim
000425
vim-5.7 css Claudio Fleiner [email protected] 001020! http://www.fleiner.com/vim/syntax/css.vim
990701
vim-5.7 cterm Sean M. McKee [email protected] --- ---
971215
vim-5.7 ctrlh Bram Moolenaar [email protected] --- ---
991025
vim-5.7 cupl John Cook [email protected] --- ---
990922
vim-5.7 cuplsim John Cook [email protected] --- ---
990921
vim-5.7
cvs Matt Dunford [email protected] --- ---
000530
vim-5.7 cweb Andreas Scherer [email protected] --- ---
990823
vim-5.7 dcl Dr. Charles E.
[email protected] ??? ???
990402 Campbell, Jr.
vim-5.7 def 010117 http://www.datatone.com/~robb/vim/syntax/def.vim
Robert Brady [email protected] (bounce!)
990817 ok
vim-5.7 diff Bram Moolenaar [email protected] --- ---
000208
vim-5.7
diva Toby Schaffer [email protected] --- ---
990614
vim-5.7 dosbatch Mike Williams [email protected] --- ---
990514
vim-5.7 dosini Sean M. McKee [email protected] --- ---
990623
vim-5.7 dracula Scott Bordelon [email protected] --- ---
971111
vim-5.7 dtd Johannes Zellner [email protected] 001110! http://www.zellner.org/vim/syntax/dtd.vim
991209
vim-5.7 eiffel 010117 http://www.cse.msu.edu/~behrends/vim/eiffel.vim
Reimer Behrends [email protected]
990919 ok
vim-5.7 elf Christian V. J.
[email protected] --- ---
990618 Bruessow
vim-5.7 elmfilt Dr. Charles E.
[email protected] ??? ???
981111 Campbell, Jr.
vim-5.7 erlang Kresimir Marzic [email protected] 001029! http://fly.srk.fer.hr/~kmarzic/vim/syntax/erlang.vim
000102
vim-5.7 Jonathan A.
esqlc [email protected] --- ---
980812 George
vim-5.7 expect Ralph Jennings [email protected] --- ---
990616
vim-5.7 exports Dr. Charles E.
[email protected] ??? ???
980518 Campbell, Jr.
vim-5.7 focexec 010117 http://www.datatone.com/~robb/vim/syntax/focexec.vim
Rob Brady [email protected] (bounce!)
990813 ok
vim-5.7 form Michael M.
[email protected] --- ---
000517 Tung
vim-5.7 forth Christian V. J.
[email protected] --- ---
990618 Bruessow
vim-5.7
fortran Ajit J. Thakkar [email protected] 001214! http://www.unb.ca/chem/ajit/fortran.vim
000619
vim-5.7 fvwm Haakon Riiser [email protected] --- ---
000329
vim-5.7 gdb 010117 http://www.fleiner.com/vim/syntax/gdb.vim
Claudio Fleiner [email protected]
991021 ok
vim-5.7 gdmo http://dooly.modacom.co.kr/~violino/gdmo.vim
Gyuman Kim [email protected] older!
990702
vim-5.7 gedcom Paul Johnson [email protected] --- ---
991223
vim-5.7
gnuplot John Hoelzel [email protected] --- ---
990614
vim-5.7 gp Karim Belabas [email protected] --- ---
000623
vim-5.7 haskell John Williams [email protected] --- ---
990508
vim-5.7 hb Alejandro Forero 010117 http://bachue.com/hb/vim/syntax/hb.vim
NONE
000402 Cuervo ok
vim-5.7 help Bram Moolenaar [email protected] --- ---
000606
vim-5.7 hitest Ronald Schild [email protected] --- ---
990707
vim-5.7 html 010117 http://www.fleiner.com/vim/syntax/html.vim
Claudio Fleiner [email protected]
000512 ok
vim-5.7 htmlm4 010117 http://www.fleiner.com/vim/syntax/htmlm4.vim
Claudio Fleiner [email protected]
000520 ok
vim-5.7 icon 010117 ftp://ftp.halcyon.com/pub/users/wturner/icon.vim
Wendell Turner [email protected]
000109 ok
vim-5.7
idl Jody Goldberg [email protected] --- ---
971120
vim-5.7 idlang Hermann
[email protected] --- ---
990614 Rochholz
vim-5.7 inform Stephen Thomas [email protected] --- ---
000305
vim-5.7 ishd Robert M.
[email protected] --- ---
990614 Cortopassi
vim-5.7 ist Peter Meszaros [email protected] --- ---
991009
vim-5.7 java http://www.fleiner.com/vim/syntax/java.vim
Claudio Fleiner [email protected] 001020
000601
vim-5.7 010117
javacc Claudio Fleiner [email protected] http://www.fleiner.com/vim/syntax/javacc.vim
980722 ok
vim-5.7 javascript Claudio Fleiner [email protected] 010117 http://www.fleiner.com/vim/syntax/javascript.vim
990420 ok
vim-5.7 jgraph Jonas Munsin [email protected] --- ---
990614
vim-5.7 jproperties Simon Baldwin [email protected] --- ---
000326
vim-5.7 jsp Rafael [email protected] http://altern.org/rgs/vim/syntax/jsp.vim
001221
000412 Garcia-Suarez ([email protected])
vim-5.7 Thomas
kscript [email protected] 404 http://aquila.rezel.enst.fr/thomas/vim/kscript.vim
000413 Capricelli
vim-5.7 kwt Michael Piefel [email protected] --- ---
991223
vim-5.7 lace Jocelyn Fiat [email protected] --- ---
990614
vim-5.7 latte Nick Moffitt [email protected] --- ---
000614
vim-5.7 lex Dr. Charles E.
[email protected] ??? ???
990513 Campbell, Jr.
vim-5.7 lhaskell John Williams [email protected] --- ---
981203
vim-5.7 lilo http://unitopia.mud.de/~monty/vim/syntax/lilo.vim
Klaus Muth [email protected] 001104
990614
vim-5.7 lisp Dr. Charles E.
[email protected] ??? ???
000321 Campbell, Jr.
vim-5.7 lite 010117 http://www-public.rz.uni-duesseldorf.de/~eymers/vim/syntax/lite.vim
Lutz Eymers [email protected]
000105 ok
vim-5.7 010117
lotos Daniel Amyot [email protected] http://lotos.csi.uottawa.ca/~damyot/vim/lotos.vim
980819 ok
vim-5.7 lout Christian V. J.
[email protected] --- ---
990618 Bruessow
vim-5.7 lss Scott Bigham [email protected] --- ---
971123
vim-5.7 lua Carlos Augusto
[email protected] --- ---
981009 Teixeira Mendes
vim-5.7 m4 010117 http://www.fleiner.com/vim/syntax/m4.vim
Claudio Fleiner [email protected]
990901 ok
vim-5.7 mail Felix von Leitner [email protected] --- ---
990827
vim-5.7
make Claudio Fleiner [email protected] 001031 http://www.fleiner.com/vim/syntax/make.vim
000424
vim-5.7 man Gautam H.
[email protected] --- ---
990614 Mudunuri
vim-5.7 manual Bram Moolenaar [email protected] --- ---
981206
vim-5.7 maple Dr. Charles E.
[email protected] ??? ???
981016 Campbell, Jr.
vim-5.7 masm Rob Brady [email protected] (bounce!) 990816! http://www.datatone.com/~robb/vim/syntax/masm.vim
990824
vim-5.7 010117
master Rob Brady [email protected] (bounce!) http://www.datatone.com/~robb/vim/syntax/master.vim
990813 ok
vim-5.7 matlab Preben "Peppe"
[email protected] 980706! http://www.student.dtu.dk/~c928400/vim/syntax/matlab.vim
980728 Guldberg
vim-5.7 mel Robert Minsk [email protected] --- ---
990527
vim-5.7 mf Andreas Scherer [email protected] --- ---
980426
vim-5.7 mib David Pascoe [email protected] --- ---
990621
vim-5.7 model Bram Moolenaar [email protected] --- ---
970914
vim-5.7 modsim3 Philipp Jocham [email protected] --- ---
990614
vim-5.7 modula2 Peter Funk [email protected] --- ---
990614
vim-5.7 modula3 Timo Pedersen [email protected] --- ---
990614
vim-5.7
mp Andreas Scherer [email protected] --- ---
980803
vim-5.7 msql 010117 http://www-public.rz.uni-duesseldorf.de/~eymers/vim/syntax/msql.vim
Lutz Eymers [email protected]
000105 ok
vim-5.7 muttrc Preben "Peppe" 010117 http://www.student.dtu.dk/~c928400/vim/syntax/muttrc.vim
[email protected]
980710 Guldberg ok
vim-5.7 nasm Manuel M.H.
[email protected] --- ---
000215 Stol
vim-5.7 nastran Tom Kowalski [email protected] --- ---
000410
vim-5.7 ncf Jonathan J.
[email protected] --- ---
000121 Miner
vim-5.7
nosyntax Bram Moolenaar [email protected] --- ---
981206
vim-5.7 nroff Matthias Burian [email protected] --- ---
000413
vim-5.7 objc Valentino
[email protected] --- ---
990614 Kyriakides
vim-5.7 ocaml Markus Mottl [email protected] 000505! http://miss.wu-wien.ac.at/~mottl/vim/syntax/ocaml.vim
991010
vim-5.7 opl "Czo" [email protected] --- ---
991104
vim-5.7
ora Sandor Kopanyi [email protected] --- ---
000614
vim-5.7 pascal Xavier Crégut [email protected] --- ---
000311
vim-5.7 pcap Lennart Schultz [email protected] --- ---
990614
vim-5.7 pccts Scott Bigham [email protected] --- ---
990810
vim-5.7 perl Nick Hibma [email protected] --- ---
000613
vim-5.7 php3 Lutz Eymers [email protected] 000808! http://www-public.rz.uni-duesseldorf.de/~eymers/vim/syntax/pgp.vim
000105
vim-5.7 phtml 010117 http://www-public.rz.uni-duesseldorf.de/~eymers/vim/syntax/phtml.vim
Lutz Eymers [email protected]
991227 ok
vim-5.7 pike Francesco
[email protected] --- ---
980216 Chemolli
vim-5.7 pine David Pascoe [email protected] --- ---
991013
vim-5.7
plsql Jeff Lanzarotta [email protected] ! --- ---
000224
vim-5.7 po Sung-Hyun Nam [email protected] --- ---
991214
vim-5.7 pod Scott Bigham [email protected] --- ---
990703
vim-5.7 postscr Mike Williams [email protected] --- ---
000606
vim-5.7 pov T. Scott Urban [email protected] --- ---
990614
vim-5.7 procmail vacant! any
NONE --- ---
980420 takers?
vim-5.7
prolog Ralph Becket [email protected] --- ---
971228
vim-5.7 ptcap Haakon Riiser [email protected] --- ---
000406
vim-5.7 purifylog Gautam H.
[email protected] --- ---
990614 Mudunuri
vim-5.7 python Neil
[email protected] --- ---
000403 Schemenauer
vim-5.7 radiance Georg Mischler [email protected] --- ---
981101
vim-5.7
rc Heiko Erhardt [email protected] --- ---
980216
vim-5.7 rcslog Joe Karthauser [email protected] --- ---
990102
vim-5.7 rebol Mike Williams [email protected] --- ---
981020
vim-5.7 remind Davide Alberani [email protected] --- ---
991203
vim-5.7 rexx Thomas Geulig [email protected] --- ---
000419
vim-5.7 rpcgen Dr. Charles E.
[email protected] ??? ???
990423 Campbell, Jr.
vim-5.7 ruby 010117:
Mirko Nasato NONE http://altern.org/mn/ruby/ruby.vim
000219 404!
vim-5.7 samba Rafael
[email protected] --- ---
000426 Garcia-Suarez
vim-5.7 sas Phil Hanna [email protected] --- updated on 010222
990518
vim-5.7 010117:
sather Claudio Fleiner [email protected] http://www.fleiner.com/vim/syntax/sather.vim
980112 ok
vim-5.7 scheme Dirk van Deun [email protected] --- ---
980430
vim-5.7 sdl 010117: http://www.informatik.hu-berlin.de/~boehme/vim/syntax/sdl.vim !
Harald Böhme [email protected] !
980316 000717!
vim-5.7 sed Haakon Riiser [email protected] --- ---
990702
vim-5.7 sgml http://tritarget.com/vim/syntax/sgml.vim
000703
991210
vim-5.7 sgmllnx Sung-Hyun Nam [email protected] --- ---
990918
vim-5.7 Dr. Charles E.
sh [email protected] ??? ???
000606 Campbell, Jr.
vim-5.7 sicad Zsolt Branyiczky [email protected] --- ---
991220
vim-5.7 simula Haakon Riiser [email protected] --- ---
990310
vim-5.7 skill Toby Schaffer [email protected] --- ---
990614
vim-5.7 sl Dan Piponi [email protected] --- ---
990616
vim-5.7
slang Jan Hlavacek [email protected] --- ---
980216
vim-5.7 slrnrc Preben "Peppe" 010117: http://www.student.dtu.dk/~c928400/vim/syntax/slrnrc.vim !
[email protected]
980403 Guldberg 980706!
vim-5.7 slrnsc Preben "Peppe" 010117: http://www.student.dtu.dk/~c928400/vim/syntax/slrnsc.vim!
[email protected]
980402 Guldberg 980706!
vim-5.7 sm Dr. Charles E.
[email protected] ??? ???
990629 Campbell, Jr.
010117:
vim-5.7 smil 990805! http://www.helio.org/vim/syntax/smil.vim
990902 vim-6.0s:
001104
vim-5.7 sml Fabrizio Zeno
[email protected] --- ---
000520 Cornelli
vim-5.7 010117:
snnsnet Davide Alberani [email protected] http://members.xoom.com/alberanid/vim/syntax/snnsnet.vim
000129 ok
vim-5.7 010117:
snnspat Davide Alberani [email protected] http://members.xoom.com/alberanid/vim/syntax/snnspat.vim
000129 ok
vim-5.7 010117:
snnsres Davide Alberani [email protected] http://members.xoom.com/alberanid/vim/syntax/snnsres.vim
000129 ok
vim-5.7 spec Donovan
[email protected] --- ---
990921 Rebbechi
vim-5.7 spice Noam Halevy Noam.Halevy.motorola.com --- ---
990812
vim-5.7 spup 010117: http://home.tu-clausthal.de/~svss/vim/spup.vim
Stefan.Schwarzer [email protected]
990707 ok
vim-5.7
sql Paul Moore [email protected] --- ---
000104
vim-5.7 sqr Jeff Lanzarotta [email protected] ! --- ---
991215
010117:
vim-5.7 squid 981103! http://unitopia.uni-stuttgart.de/~monty/vim/syntax/squid.vim
Klaus Muth [email protected]
990614 vim-6.0s:
001104
vim-5.7 st Arndt Hesse [email protected] --- ---
971224
vim-5.7 stp Jeff Lanzarotta [email protected] ! --- ---
000106
vim-5.7 synload Bram Moolenaar [email protected] --- ---
000616
vim-5.7
syntax Bram Moolenaar [email protected] --- ---
981206
vim-5.7 tads 010118: http://www.hec.utah.edu/~karger/vim/syntax/tads.vim
Amir Karger [email protected]
991022 ok
vim-5.7 tags Dr. Charles E.
[email protected] ??? ???
990128 Campbell, Jr.
vim-5.7 tcl Allan Kelly [email protected] --- ---
980629
vim-5.7 tex Dr. Charles E.
[email protected] ??? ???
000407 Campbell, Jr.
vim-5.7 texinfo Sandor Kopanyi [email protected] --- ---
000614
vim-5.7 tf 010117 http://www-public.rz.uni-duesseldorf.de/~eymers/vim/syntax/tf.vim
Lutz Eymers [email protected]
991227 ok
vim-5.7 tli Kurt W.
[email protected] --- ---
000322 Andrews
vim-5.7 tsalt Sean M. McKee [email protected] --- ---
971216
vim-5.7
uil Thomas Koehler [email protected] --- ---
980217
vim-5.7 vb Robert M.
[email protected] --- ---
000208 Cortopassi
vim-5.7 verilog Mun Johl [email protected] --- ---
000201
vim-5.7 vgrindefs Bram Moolenaar [email protected] --- ---
970914
vim-5.7 vhdl "Czo" [email protected] --- ---
000406
vim-5.7 vim Dr. Charles E.
[email protected] ??? ???
000608 Campbell, Jr.
vim-5.7
viminfo Bram Moolenaar [email protected] --- ---
990819
vim-5.7 vrml Gregory 010118: http://zing.ncsl.nist.gov/~gseidman/vim/syntax/vrml.vim
[email protected]
990222 Seidman 990731!
vim-5.7 web Andreas Scherer [email protected] --- ---
990823
vim-5.7 webmacro Claudio Fleiner [email protected] 010118: http://www.fleiner.com/vim/syntax/webmacro.vim
000213 ok
vim-5.7 whitespace Bram Moolenaar [email protected] ??? --- ---
--- ???
vim-5.7
winbatch NoName [email protected] --- ---
990819
vim-5.7 wml 010118: http://alfie.ist.org/vim/syntax/wml.vim
Gerfried Fuchs [email protected]
000226 000919!
vim-5.7 xdefaults 010118: http://www.zellner.org/vim/syntax/xdefaults.vim
Johannes Zellner [email protected]
000408 ok
vim-5.7 xmath Dr. Charles E.
[email protected] ??? ???
990514 Campbell, Jr.
vim-5.7 xml 010118: http://www.zellner.org/vim/syntax/xml.vim
Johannes Zellner [email protected]
990909 001216!
vim-5.7 xpm Ronald Schild [email protected] --- ---
990705
vim-5.7 xpm2 Steve Wall [email protected] --- ---
991004
vim-5.7 xs Michael W.
[email protected] --- ---
990308 Dodge
vim-5.7 xxd Dr. Charles E.
[email protected] ??? ???
990319 Campbell, Jr.
vim-5.7 Dr. Charles E.
yacc [email protected] ??? ???
990408 Campbell, Jr.
vim-5.7 z8a Milan Pikula [email protected] --- ---
990107
vim-5.7 zsh Felix von Leitner [email protected] --- ---
990614
Fellow Linguists
The following people have offered to be "fellow linguists", ie you can ask them for help when you need help on some of the available languages:
haskell
Martin Norbäck [email protected]
Neil Schemenauer [email protected]
perl
000724 Doug Hanks [email protected]
Would you like to become a fellow linguist, too? Then please send me a mail, so I can add you to the list! :-)
URL: http://www.math.fu-berlin.de/~guckes/vim/lang.html
URL: http://www.vim.org/lang.html (mirror)
Created: Thu Jul 23 18:00:00 CEST 1998
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Tue Jun 19 10:49:39 MEST 2001
VIM - Utilities
Info on some really useful scripts, tools, and utilities for VIM.
Got a good program/script/tool/utility for use with VI or VIM? Let me know!
● xxd
Programs distributed without Vim:
● boxes
● global
● jtags
● makehtml and
● maketags
● par
● tal
● tblfmt
● vmh
● wf
● zip
Scripts:
● vim2html
VIM - Utilities
The Vim Utilities are programs and scripts which are distributed *with* Vim. So when you get
the archive file then you will find these programs with Vim:
Overview: ctags | xxd
ctags [000424,010416]
Description, short: "Exuberant Ctags" creates "tag files" for emacs, vi, and clones - and a
lot better than the standard "ctags"! [If you do not know what a tag is then please take a
look at the page about vim and tags.]
Description, long: Ctags generates an index (or "tag") file of programming language
objects of source code Ctags allows these items to be quickly and easily located by a text
editor or other utility.
Ctags supports these languages: Assembler, AWK, ASP, BETA, Bourne/Korn/Zsh Shell,
C, C++, COBOL, Eiffel, Fortran, Java, Lisp, Make, Pascal, Perl, PHP, Python, REXX,
Ruby, S-Lang, Scheme, Tcl, and Vim.
Alternatively, Ctags can generate a cross reference file which lists, in human readable
form, information about the various objects found in a set of C language files.
Tag index files are supported by the vi(1) editor and its derivatives (such as vim, elvis,
stevie, and xvi) through the use of the :ta command, and by the emacs editor through the
use of the Meta-. command, both of which locate the object associated with a name
appearing in a source file and jump to the file and line which defines the name.
Source and binaries for Linux Red Hat, MS-DOS (16-bit and 32-bi DPMI), Win32
(Windows95 and WindowsNT), and OS/2.
Latest release version: ctags-5.0.1 [010416]
Author: Darren Hiebert [email protected]
URLs:
http://ctags.sourceforge.net
http://sourceforge.net/projects/ctags/
http://www.appwatch.com/Linux/App/620/data.html
http://darren.hiebert.com/ctags/index.html [sic!] [980727]
Source: ftp://ftp.revnet.com/pub/ctags/ [980727]
xxd [961007,990915]
Description: Hexadecimal converter (hexdumper).
Size: ~14K
Author: Jürgen Weigert [email protected]
Source: ftp://ftp.uni-erlangen.de:21/pub/utilities/etc/xxd-1.10.tar.gz
VIM - Additional Utilities
The following utilities are *not* distributed with Vim. However, they can be very very helpful.
So you *should* have them!
Overview: Programs distributed without Vim:
● boxes
● global
● jtags
● par
● tal
● tblfmt
● vmh
● wf
● zip
boxes [990822,990824]
Draw an "box" around some given text.
Description: "boxes" can draw all kinds of boxes around its input text, ranging from a C
comment box to complex ASCII art. These boxes may also be removed, even if they have
been badly damaged by editing of the text inside. Since boxes may be open on any side,
boxes can also be used to create regional comments in any programming language. With
the help of an editor macro or mapping, damaged boxes can easily be repaired. New box
designs of all sorts can easily be added and shared by appending to a free format
configuration file.
Size: ~70K
Author: Thomas Jensen [email protected] [email protected]
Distribution: http://home.pages.de/~jensen/boxes/
Latest Version: 1.0 [990822]
Examples can also be found on the boxes home page:
http://home.pages.de/~jensen/boxes/examples.html
cowsay and cowthink [000616,010220]
http://www.nog.net/~tony/warez/cowsay.shtml
Author: Tony Monroe [email protected]
$ cowsay moo! ______ < moo! > ------ \ ^__^ \ (oo)\_______ (__)\ )\/\ ||----w | || ||
figlet
global [980713,990726]
"GLOBAL common source code tag system"
http://www.tamacom.com/global/
Description: http://www.tamacom.com/unix/index.html#global
Author: Shigio Yamaguchi [email protected]
Latest version: global-3.44 [980705]
jtags [980630,990621]
Description, short: "JTags" creates "tag files" from Java sources.
Description, long: "JTags" creates "tag files" from Java sources, including classes,
interfaces, constant class and interface members, class members, class and interface
methods.
Home Page and Distribution:
http://www.fleiner.com/jtags/
Author: Claudio Fleiner [email protected]
Latest version: jtags-0.2 [990614]
makehtml and maketags
These two awk scripts convert the vim documentation (aka helptexts) to HTML, so they
can be viewed on WWW.
For more info see the entry on the awk page.
par - paragraph formatter [971208,010317]
Home Page: http://www.cs.berkeley.edu/~amc/Par/
Author: Adam M. Costello http://www.cs.berkeley.edu/~amc/
Latest releases: par-1.51 [000224] and par-1.50 [960211] (only slight difference)
Description: par reformats paragraphs preserving borders on either side. For examples of
input and output see the page
http://www.cs.berkeley.edu/~amc/Par/par.doc.txt.gz.
NOTES: Why use par at all when there is the builtin formatting? Well, the builtin
formatting cannot right-justify text.
Example: Formatting the current paragraph with "par" is as easy as this: map #p
vip!par<CR>
tal - "trailer alignment" [971122,971128,990729]
Description: "tal" aligns the end of lines if they should have common characters at the
end of lines. This is very helpful when rearranging the right side of a "comment box",
Size: ~10K
Author: Thomas Jensen [email protected]
Distribution: http://home.pages.de/~jensen/tal/.
Latest version: tal-1.9 [990311]
Note: The program "tal" is not yet part of the Vim distribution. Bram probably still does
not know about it - but he is so busy right now that I don't want to bother him. Anyway -
Thomas is considering a DOS port of this nice utility. Encourage him! I do hope that
someone will take the challenge to work in this text formatting utility into Vim builtin
"text formatting". Any takers?
Latest change: Now runs on SunOS4! :-)
Let me show you how this works: Edit some text:
/**
* foo bar blah *
* blah blah blah *
* tralala tralala *
******************
Note: The last line shows how big the box should get. Now add some text to the end of
the lines you want to put into a box - highlight the lines, press ':', then enter the command
:s/$/ */:
/**
* foo bar blah *
* blah blah blah *
* tralala tralala *
******************
Now apply "tal" those lines - :'<,'>!tal
/* *
* foo bar blah *
* blah blah blah *
* tralala tralala *
***************** *
Now, all you need to do is change the added space to complete the box:
/******************
* foo bar blah *
* blah blah blah *
* tralala tralala *
******************/
I do hope that this can be added to Vim's internal text formatting.
tblfmt [990729]
Description, short: table formatter
Description, long: Creates a table from comma separated input. Separators can be
adjusted. Uses AWK.
Author: James Cribb [email protected]
Example:
input:
Stadt Land Fluss
Berlin Berlin Spree
Heidelberg Baden-Württemberg Neckar
Bonn who-cares Rhein
München Bayern Isar
output:
Stadt Land Fluss
Berlin Berlin Spree
Heidelberg Baden-Württemberg Neckar
Bonn who-cares Rhein
München Bayern Isar
Source: http://www.zip.com.au/~jamesc/tblfmt (local copy)
vmh [990618]
Description, short: "vmh" - the Vim Mail Handler
Description, long: "vmh" is a mail handler useful to read your email, write email and
manage emails all from within Vim.
Home Page and Distribution: http://www.fleiner.com/vmh/
Author: Claudio Fleiner [email protected]
Latest version: vmh-0.2 [990618]
wf (word format) [960818]
Description: "wf" is a small Perl script that reformats text preserving the standard quote
prefix "> " (angle and space). You can use it with VIM as a filter. [But then again there is
the command 'Q'. :-) ]
Source: wf.pl
Size: less than 2K
Author: Bek Oberin [email protected]
zip [960602]
Compression.
There are several versions for "zip" compression. An interesting one seems to be the one
by "Infozip":
ftp://ftp.uu.net/pub/archiving/zip.
Dictionaries
Several people were once looking for dictionaries so they could make better use of spelling
checkers or just simple (auto)completion. Here is a site:
● ftp://ftp.fu-berlin.de/unix/security/dictionaries/
Scripts
vim2html.pl
vim2html is a perl script that converts vim-5 helpfiles to html.
Links
Chip Campbell's Utilities for Vim [000425]
http://www.vim.org/user.html#campbell
http://www.erols.com/astronaut/vim/
LOTS of utilities! :-)
Cygwin [..,010615]
http://sources.redhat.com/cygwin/
http://cygwin.com/faq/
"The Cygwin tools are ports of the popular GNU development tools and utilities for
Windows. They function by using the Cygwin library which provides a UNIX-like API
on top of the Win32 API."
Unix for Windows by AT&T
http://www.research.att.com/sw/tools/uwin/
These are *not* OpenSource!
Virtually Unix [..,010619]
http://virtunix.itribe.net/
Virtually Un*x is dedicated to helping bring the power of UN*X tools to Windows95.
Maintained by Chris [email protected] (The whatsnew page says "last update on June
20th 1997"...)
Native Win32 ports of some GNU utilities
http://www.edv.agrar.tu-muenchen.de/~syring/win32/UnxUtils.html
Native Win32 ports of some GNU utilities
Unix shell ports for Win32
tcsh: ftp://ftp.blarg.net/users/amol/tcsh/
zsh: ftp://ftp.blarg.net/users/amol/zsh/
terminal programs for win32
See my page on windows.
URL: http://www.math.fu-berlin.de/~guckes/vim/util.html
URL: http://www.vim.org/util.html (mirror)
Created: Thu Jan 01 00:00:00 CET 1998
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Sun Oct 08 20:39:33 MET DST 2000
VIM Challenges
"Can you do it?" - Some challenges on hacking with Vim.
Every now and then I think about some problem and I think it can be done with a simple
mapping. But I am not always pleased with my solution. Maybe you can think of a better
solution? Let me know!
Collecting Matches
Goal: Scan current buffer for occurrences of a word and put all matching lines in a new buffer.
[Assume that the word is in the unnamed register '"'.]
Analysis: This is a job for the "global" command. Now, we could easily copy all matching lines
after the end of the current buffer with g:#foo#co $, but creating a new buffer to display the
result is nice - and also easy done with :new. A mark to remember the former end-of-buffer is
necessary for deleting the resulting lines, of course. The last two commands simply delete the
resulting empty line.
Solution: map ## Gma :g#<c-r>"#co $<cr> 'a j dG :new<cr> p k dd I am not happy with the
result - for these reasons:
● extra mark required
● cleanup commands
I'd rather append the matches to some unused named register and have the pasted into the new
edit buffer. Is that possible with an ex command?
000505: Yes - it certainly is possible with an ex command: map ## :g#<c-r>"#y A<cr> :new
"Ap The ex command y A appends every match to the register 'A'. (Note the space between the
command an the register name here. Otherwise vim would see the command "yA" which is, of
course, no an ex command.)
Now all that is missing is a simple emthod to make sure that the register A is cleared before
using the mapped commands. Anyone?
000515: Frank Baruch [email protected] pointed me at the Vim's "let" command which
allows to fill the contents of a register: let @a=""<cr> Adding this will give us the following
mapping: map ## let @a=""<cr> :g#<c-r>"#y A<cr> :new "Ap Or in one line: map ## :let
@a=""<CR>:g#<C-R>"#y A<CR>:new<CR>"Apdk0 Unfortunately, this solution is specific to
Vim. Does anyone have a Vi solution, ie a solution using Vi commands only?
Comments? Improvements? Send them to me!
URL: http://www.math.fu-berlin.de/~guckes/vim/chall.html
URL: http://www.vim.org/chall.html (mirror)
Created: Sun Oct 08 12:00:00 MET DST 2000
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Tue Apr 03 03:03:03 MEST 2001
VIM Quotes
Some quotes of the email I have received about Vim:
010403:
"I have always avoided religious wars over this or that toolset,
this or that OS. I've used all kinds of different editors:
IBM's PE, BRIEF by UnderWare, MPW (on the Mac), CodeWright
and various iterations of MS' Integrated environment.
Recently I discovered VIM. The effect has been devastating.
I am now a True Believer. There is only one editor,
all the rest are only hollow imitiations of VIM!"
000505: Jan-Benedict Glaw [email protected] commented:
Horms and I discussed this, and we came up with two categories of people.
People who use vim, and people who don't realize that they could be using vim.
Patrick Baker [email protected] [990827 comp.editors]
I think I am going to cry. This is what I have been looking for for quite
some time. I was using an old version of a vi editor for DOS offered by MKS.
It was awfull but more usefull than any Windows alternative.
Now I have VIM. Wow what a great find.
Timothy Johnson [email protected] [990310] in private email:
On a serious note, I just got Visual C++ 6.0 and installed it. I intend to
use it to compile Vim for Python in the Windows Environment. I would be
happy to set up a site on that issue. Vim for windows is a delight to work
in. It is really the best of both the command-line world and the GUI world.
David Gerard [email protected] [990306,news.software.readers]:
Message-Id: <[email protected]>
Last night I finally unzipped vim 5.3, and dammit I'm a convert. ..
gvim is the One True Way for text editing on a Windows box,
and that's all there is to it. All hail! All hail!
David maintains a page on slrn and vim on Windows.
Edwin van Geelen [email protected] [990308,comp.editors]:
Vim is worth millions and costs nothing. It's the best editor the world has
ever seen. Using the trio Vim/Perl/LaTeX I can dispose of most other software.
Nick Popoff [email protected] [990304] (in email):
I've been hearing so many great things about VIM from friends all year,
and finally now I'm trying it out, and I wish I'd taken their advice sooner!
As a programmer working in both Unix and Windows, it's great to finally
find a fantastic editor for both. Thanks for all your hard work!
Terry Mathews [email protected] on news.software.readers [990228]
Message-Id: <[email protected]>
I was a Win98 junkie and addicted to Outlook Express. SLRN has converted me.
After I found a key refrence to VIM and figgered out how to hit ^C,
then :write and :quit, it was mucho superio to OE. God, I love BeOS. Plus,
now I can set my computer up as a telnet server, connect from school
and read my newsgroups. Awesome. :)
page: http://www.csclub.uwaterloo.ca/u/mvcorks/vim/
link: http://www.tuxedo.org/~esr/jargon/html/entry/zapped.html
text: "What can I say? Vi is Zen."
Last not least - a search on Dictionary.com reveals this about Vim:
http://www.dictionary.com/cgi-bin/dict.pl?db=*&term=vim Nancy McGough [email protected] [991209] consulted
her dictionary and found:
3 definitions found:
URL: http://www.math.fu-berlin.de/~guckes/vim/quotes.html
Created: http://www.vim.org/quotes.html (mirror)
Created: Wed Mar 03 12:00:00 CET 1999
Send feedback on this page to
Sven Guckes [email protected]
" ==================================================================
" File: $HOME/.vimrc
" Last update: Wed Jun 13 17:00:00 MEST 2001
" Purpose: *Personal* Setup file for the editor Vim (Vi IMproved)
" It contains everything which I use *personally*.
" Author: Sven Guckes [email protected] ([email protected])
" <URL:http://www.math.fu-berlin.de/~guckes/sven/>
" ==================================================================
" ==================================================================
" Mind you, this file is only a setup file for *personal* use.
" The BIG setup file which I created for *all* users ("vimrc.forall")
" is available in my setup file directory:
" http://www.math.fu-berlin.de/~guckes/setup/vimrc.forall (uncompressed)
" http://www.math.fu-berlin.de/~guckes/setup/vimrc.forall.gz (compressed)
" Enjoy! Feedback is very welcome! :-)
" ==================================================================
" ======================================
" Loading general setup files first
" ======================================
" ===================
" Settings of Options
" ===================
" ==============
" Autocommands
" ==============
" Silly test message to check the filepattern for message files:
" au BufRead .followup,.article,.letter,mutt* echo "Editing Messages\!"
" ==============
" Abbreviations
" ==============
" ABbreviations
" personal addresses:
ab MYUSERNAME guckes
ab MYDOMAIN math.fu-berlin.de
ab MYMAIL [email protected]
" ab MYHOMEPAGE http://www.guckes.net/
ab MYHOMEPAGE http://www.math.fu-berlin.de/~guckes/
" ==============
" Colorization
" ==============
" hi Cursor
" hi Directory
" hi ErrorMsg
" hi FoldColumn
" hi Folded
" hi IncSearch
" LineNr: Colorize the line numbers (displayed with "set number").
" Turn off default underlining of line numbers:
hi LineNr term=NONE cterm=NONE
" hi ModeMsg
" hi MoreMsg
" hi Question
" hi SpecialKey
" hi Title
" hi VertSplit
" hi Visual
" hi VisualNOS
" hi WarningMsg
" hi WildMenu
" ==============
" Mappings
" ==============
" ============================================================
" Options() - used to display some important option values
" within the status line (see below at "set statusline".
" ============================================================
"
" Statusline without colors and display of options -
" but with percentage at end:
" set statusline=Vim-%{Version()} [%02n]\ %(%M%R%H%)\ %F\ %=<%l,%c%V>\ %P
"
" Damien WYART <[email protected]> [000329]:
" set statusline=%<%f%=\ [%1*%M%*%n%R%H]\ \ %-25(%3l,%c%03V\ \ %P\
(%L)%)%12o'%03b'
" hi User1 term=inverse,bold cterm=inverse,bold ctermfg=red
fu! Options()
" let opt="Opt:"
let opt=""
" autoindent
" if &ai| let opt=opt." ai" |else|let opt=opt." noai" |endif
if &ai| let opt=opt." ai" |endif
" expandtab
" if &et| let opt=opt." et" |else|let opt=opt." noet" |endif
if &et| let opt=opt." et" |endif
" hlsearch
" if &hls| let opt=opt." hls" |else|let opt=opt." noet" |endif
if &hls| let opt=opt." hls" |endif
" paste
" if &paste|let opt=opt." paste"|else|let opt=opt." nopaste"|endif
if &paste|let opt=opt." paste"|endif
" shiftwidth
if &shiftwidth!=8|let opt=opt." sw=".&shiftwidth|endif
" textwidth - show always!
let opt=opt." tw=".&tw
" let opt=opt."\[".&lines.",".&columns."\]"
return opt
endf
" ============================================================
" Colorizing that status lines! Whee! :-)
" ============================================================
"
" Statusline without colors and display of options -
" but with percentage at end:
" set statusline=Vim-%{Version()} [%02n]\ %(%M%R%H%)\ %F\ %=<%l,%c%V>\ %P
fu! Version()
return version
endf
" ============================================================
" some things I need only temporarily for editing some stuff:
" ============================================================
" Final words...
" The last line is allowed to be a "modeline" with my setup.
" It gives vim commands for setting variable values that
" are specific for editing this file. Used mostly for
" setting the textwidth (tw) and the "shiftwidth" (sw).
" Note that the colon within the value of "comments"
" needs to be escaped with a backslash!
" vim:tw=70 et sw=4 comments=\:\"
" ==================================================================
" File: $HOME/.gvimrc
" Last update: Thu May 10 10:10:10 MEST 2001
" Purpose: *Personal* Setup file for GVim -
" the GUI version of the editor Vim (Vi IMproved)
" Author: Sven Guckes [email protected] ([email protected])
" <URL:http://www.math.fu-berlin.de/~guckes/sven/>
" Availability: http://www.math.fu-berlin.de/~guckes/vim/gvimrc
" Enjoy! Feedback is very welcome! :-)
" ==================================================================
" ==================================================================
" SETTINGS!
" ==================================================================
" Set some nice settings - recommended!
" set background=dark backspace=2 cindent esckeys hidden
" set ruler showmatch smarttab shiftwidth=4 tabstop=8
" Or shorter:
" set bg=dark bs=2 cin ek hid paste ru sm sta sw=4 ts=8
" What these settings do? Well - RTFM! ;-)
" ==================================================================
" COLORS!
" ==================================================================
" turn on syntax coloring:
syntax on
" ==================================================================
" AUTOCOMMANDS!
" ==================================================================
" au BufRead *.java set cindent
" EOF!
version 6.0
" See ":help version" to see why this command is in the first line.
"
" Let people know that they are using this setup file:
" echo "Welcome to Sven's setup file for all users!"
"
"
" ==================================================================
" File: $HOME/.vimrc.forall (sourced by ~USER/.vimrc)
" Last update: Thu May 10 21:55:31 MEST 2001
" Purpose: Setup file for the editor Vim (Vi IMproved)
" Availability: This file is available as
" 27K <URL:http://www.math.fu-berlin.de/~guckes/setup/vimrc.gz>
" 76K <URL:http://www.math.fu-berlin.de/~guckes/setup/vimrc>
" <URL:http://www.vim.org/rc> (mirror)
" Size: This file is about 76K in size and has 2,000+ lines.
" Author: Sven Guckes [email protected] ([email protected])
" <URL:http://www.math.fu-berlin.de/~guckes/sven/>
" Related files:
" http://www.math.fu-berlin.de/~guckes/vim/src/emacs.vim
" http://www.math.fu-berlin.de/~guckes/vim/src/latex.vim
" http://www.math.fu-berlin.de/~guckes/vim/src/html.vim
" http://www.math.fu-berlin.de/~guckes/vim/syntax/
" ===================================================================
" NOTE: If your read this then please send me an email!
" I welcome all feedback on this file - especially
" with new ideas such as abbreviations and mappings.
" Thanks! And enjoy Vim! :-)
" --Sven [email protected] and [email protected]
" ===================================================================
" Webpages on Vim that you should know about:
" http://www.vim.org/ Vim Home Page (actually a mirror)
" http://www.vim.org/announce/ Vim Announcements
" http://www.vim.org/bina.html sites with vim binaries
" http://www.vim.org/bugs.html Some Vim Bugs
" http://www.vim.org/cvs.html CVS server
" http://www.vim.org/deve.html Current development issues
" http://www.vim.org/dist.html All mirrors in detail
" http://www.vim.org/faq/ Vim FAQ
" http://www.vim.org/hist.html History of ChangeLogs
" http://www.vim.org/html/ Vim Helptexts in HTML
" http://www.vim.org/howto/ Vim HowTo Texts
" http://www.vim.org/iccf/ Vim and the ICCF (see ":help iccf")
" http://www.vim.org/lang.html Language/SyntaxFile Summary
" http://www.vim.org/macs.html Vim on MacOS development
" http://www.vim.org/mail.html Mailing lists and all that
" http://www.vim.org/mirrors.html All mirror sites (ftp and www)
" http://www.vim.org/news.html NEWS about Vim and the pages
" http://www.vim.org/newsgroup.html Vim on comp.editors
" http://www.vim.org/orga.html vim.org background info
" http://www.vim.org/pics.html Pictures: buttons,icons,screenshots
" http://www.vim.org/press/ Articles on Vim in Magazines
" http://www.vim.org/quotes.html Quotes on Vim by users
" http://www.vim.org/sites.html Sites that use Vim officially
" http://www.vim.org/syntax/ Syntax files from current version
" http://www.vim.org/syntax.new/ New Syntax files (not yet in distrib)
" http://www.vim.org/user.html Vim Users and their pages on Vim
" http://www.vim.org/wish.html Wishlist for new features
" http://www.vim.org/why.html Why to use a vi clone (Vim!)
" http://www.vim.org/y2k.html Y2K issues (as if there are any..)
" ===================================================================
" Info on the latest versions of Vim are on the Vim Home Page:
" http://www.vim.org/
" Mind you, those pages are a *mirror* of the pages at
" http://www.math.fu-berlin.de/~guckes/vim/
" ===================================================================
" The latest versions of Vim are usually in my signature file:
" http://www.math.fu-berlin.de/~guckes/sig/SIGS Comments?
" ===================================================================
" Installation of this setup file:
" To use this setup file, copy it to
" this filename on these systems:
" ~/.vimrc Unix and OS/2
" s:.vimrc Amiga
" $VIM\_vimrc MS-DOS and Win32
" ===================================================================
" version check:
" The first line of this setup file contains the information
" "version xxx" which allows VIM to check whether the setup file
" fits the syntax that it understands.
" Versions of VIM other than of version 5 then will give a warning
" as they do not understand this setup file command - a feature:
" Give a warning so the user knows that there is something odd
" about the setup file.
" ===================================================================
" ===================================================================
" Structure of this file:
" Lines starting with an inverted comma (") are comments.
" Some mappings are commented out. Remove the comment to enable them.
"
" There are three kinds of things which are defined in this file:
" Mapping ("map"), settings ("set"), and abbreviations ("ab").
" Settings affect the behaviour of commands.
" Mappings maps a key sequence to a command.
" Abbreviations define words which are replaced
" right *after* they are typed in.
"
" ===================================================================
" Note on mappings - "angle notation" (see ":help <>"):
" VIM allows you to define mappings with special characters
" with a notation that uses non-special characters:
" The notation encloses decriptive words in angle brackets (<>).
" The characters you will most often are:
" <C-M> for control-m
" <C-V> for control-v which quotes the following character
" <ESC> for the escape character.
" All control characters have been replaced to use the angle notation
" so you should be able to read this file without problems.
" (Well, sometimes I leave some tabs [control-i] in the file. ;-)
" ===================================================================
" External programs:
" Some mappings make use of external programs.
" The following you should find/have on every UNIX system:
" cut, date; awk, egrep, grep, ispell, perl, sed.
" If you are using DOS then you should get these for you system!!
" See http://www.math.fu-berlin.de/~guckes/dos/ for some pointers!
" ===================================================================
" Online Help - jump to help positions with "\\":
" On some keyboards you will have some trouble with C-],
" the command to jump to the current help tag.
" The following mapping allows to use "\\", too:
map \\ <C-]>
" ===================================================================
" The command ":version" does not show the current value of
" VIMRUNTIME - dang! So I need a fast way to display that value:
map :V :echo $VIMRUNTIME<c-m>
" ===================================================================
" ===================================================================
" HTML - HTML - HTML - HTML - HTML - HTML - HTML - HTML
" ===================================================================
" This has become quite big - so I moved it out to another file:
" http://www.math.fu-berlin.de/~guckes/vim/source/html.vim [980227]
" The "expand" is necessary to evaluate "~guckes".
let FILE=expand("~guckes/.P/vim/source/html.vim")
if filereadable(FILE)
exe "source " . FILE
endif
" ===================================================================
"
" ===================================================================
" SETTING OPTIONS
" ===================================================================
" There are many options for Vim - over 200. Here is an overview:
" http://www.vim.org/options54.txt VIM-5.4 [990726] 218 options.
" http://www.vim.org/options57.txt VIM-5.7 [000624] 219 options.
" http://www.vim.org/options60ae.txt VIM-6.0ae [010504] 283 options.
" ===================================================================
"
" autoindent, paste, textwidth:
" I keep changing these values - just as the case may be.
" Now, if functions keys actually worked on all keyboards
" then I'd probably defines a toggle for each of them...
"
" autoindent: "off" as I usually do not write code.
set noautoindent
"
" autowrite: Automatically save modifications to files
" when you use critical (rxternal) commands.
set autowrite
"
" backup: backups are for wimps ;-)
set nobackup
"
" backspace: '2' allows backspacing" over
" indentation, end-of-line, and start-of-line.
" see also "help bs".
set backspace=2
"
" background: Are we using a "light" or "dark" background?
" set background=dark
"
" compatible: Let Vim behave like Vi? Hell, no!
set nocompatible
"
" comments default: sr:/*,mb:*,el:*/,://,b:#,:%,:XCOMM,n:>,fb:-
set comments=b:#,:%,fb:-,n:>,n:)
"
" cpoptions you should get to know - source of many FAQs! ;-)
" cpoptions: "compatible options" to match Vi behaviour
" set cpoptions="aABceFs" "default!
" FAQ: Do NOT include the flag '<' if you WANT angle notation!
"
" dictionary: english words first
set dictionary=/usr/dict/words,/local/lib/german.words
" Source for dictionaries (in unix-format):
" ftp://ftp.fu-berlin.de/misc/dictionaries/unix-format/
" However, these are quite old. Is there a better source?
"
" digraph: required for those umlauts
set digraph
"
" errorbells: damn this beep! ;-)
set noerrorbells
"
" esckeys: allow usage of cursor keys within insert mode
" You will find this useful when working, eg, on SunOS.
set esckeys
"
" In case you want this for SunOS only:
" if system('uname')=='SunOS'
" set ek
" endif
" expandtab: Expand Tabs? Rather not.
" See 'listchars' to make Tabs visible!
set noexpandtab
"
" formatoptions: Options for the "text format" command ("gq")
" I need all those options (but 'o')!
set formatoptions=cqrt
"
" helpheight: zero disables this.
set helpheight=0
"
" helpfile: path+filename of the main helpfile, ie "help.txt"
" set helpfile=c:\\vim-4.6\\docs\\help.txt
" set helpfile=c:/vim-4.6/docs/help.txt
" On Windows, I put the Vim helpfiles
" into the directory C:\VIM-version, eg C:\VIM-60ab
"
" Support users of old vim versions on the local net:
if version==507
set helpfile=/import/Mweb/guckes/vim/doc/help.txt
endif
"
" For use from a WindowsNT machine which mounts
" the user's home directory on drive 'Z':
" if has("dos16") || has("dos32") || has("gui_w32")
" set helpfile=Z:\share\vim\runtime\doc\help.txt
" endif
"
" hidden: Allow "hidden" buffers. A must-have!
set hidden
"
" highlight=8b,db,es,hs,mb,Mn,nu,rs,sr,tb,vr,ws
set highlight=8r,db,es,hs,mb,Mr,nu,rs,sr,tb,vr,ws
"
" hlsearch : highlight search - show the current search pattern
" This is a nice feature sometimes - but it sure can get in the
" way sometimes when you edit.
set nohlsearch
"
" icon: ...
set noicon
"
" set iconstring file of icon (icons? on a terminal? pff!)
" set iconstring
"
" ignorecase: ignore the case in search patterns? NO!
set noignorecase
"
" insertmode:
" FAQ: Q: How can I quit insertmode when using this option?
" A: The option "insertmode" was not meant for "start Vim in
" insert mode" only; the idea is to *stay* in insert mode.
" Anyway, you can use the command |i_CTRL-O| to issue commands.
set noinsertmode
"
"
" iskeyword:
" iskeyword=@,48-57,_,192-255 (default)
" Add the dash ('-'), the dot ('.'), and the '@' as "letters" to "words".
" This makes it possible to expand email and html addresses,
" eg [email protected] and http://www.vim.org/
set iskeyword=@,48-57,_,192-255,-,.,:,/,@-@
"
" joinspaces:
" insert two spaces after a period with every joining of lines.
" I like this as it makes reading texts easier (for me, at least).
set joinspaces
"
" keywordprg: Program to use for the "K" command.
" set keywordprg=man\ -s
"
" laststatus: show status line? Yes, always!
" laststatus: Even for only one buffer.
set laststatus=2
"
" [VIM5]lazyredraw: do not update screen while executing macros
set lazyredraw
"
" 'list' + 'listchars': Great new feature of vim-5.3!
" This tells Vim which characters to show for expanded TABs,
" trailing whitespace, and end-of-lines. VERY useful!!
" Standard settings:
" set list
" set listchars=tab:>-,trail:·,eol:$
"
" However: The '$' at the end of lines is a bit too much, though.
" And I quite like the character that shows a dot in the middle:
" set listchars=tab:>·,trail:·
"
" Some people might prefer a double right angle (>>)
" to show the start of expanded tabs, though:
" set listchars=tab:»·,trail:·
"
" However, this all breaks up when viewing high-bit characters
" through some brain-dead telnet program (there are many).
" Sometimes a change of the font does the trick. Try it!
"
" magic: Use 'magic' patterns (extended regular expressions)
" in search patterns? Certainly! (I just *love* "\s\+"!)
set magic
"
" modeline: ...
" Allow the last line to be a modeline - useful when
" the last line in sig gives the preferred textwidth for replies.
set modeline
set modelines=1
"
" number: ...
set nonumber
"
" path: The list of directories to search when you specify
" a file with an edit command.
" Note: "~/.P" is a symlink to my dir with www pages
" "$VIM/syntax" is where the syntax files are.
" set path=.,,~/.P/vim,~/.P/vim/runtime/syntax,~/.P/vim/source,$VIM/syntax/
" set path=.,,~/.P/vim,~/.P/mutt/,~/.P/elm,~/.P/slrn/,~/.P/nn
"
" pastetoggle
set pastetoggle=<f11>
"
" report: show a report when N lines were changed.
" report=0 thus means "show all changes"!
set report=0
"
" ruler: show cursor position? Yep!
set ruler
"
" runtimepath: list of dirs to search for runtime files
" runtimepath is for Vim-6 only!
if version>=600
set runtimepath=~/.vim,~/.vim/after
set runtimepath+=~guckes/.vim
" set runtimepath+=~guckes/share/vim/vim60z/runtime/
set runtimepath+=~guckes/share/vim/runtime/
set runtimepath+=~guckes/share/vim/
set runtimepath+=~guckes/.P/Vim/syntax
endif
" had to set this now that Vim won't use "helpfiles"
" to look for runtime files any more.
"
" Setting the "shell" is always tricky - especially when you are
" trying to use the same vimrc on different operatin systems.
" shell for DOS
" set shell=command.com
" shell for UNIX - math.fu-berlin.de BSD
" set shell=zsh
" shell for UNIX - inf.fu-berlin.de BSD&Solaris
" set shell=zsh
" shell for UNIX - zedat.fu-berlin.de BSD&Solaris
" set shell=/bin/tcsh
" Now that vim-5 has ":if" I am trying to automate the setting:
"
if has("dos16") || has("dos32")
let shell='command.com'
endif
" gui_w32: cmd.exe
"
" The zsh is now available at zedat.fu-berlin.de! :-)
" start the zsh as a login shell:
if has("unix")
let &shell="zsh\ -l"
endif
"
" shiftwidth: Number of spaces to use for each
" insertion of (auto)indent.
" set shiftwidth=8
set shiftwidth=2
"
" shortmess: Kind of messages to show. Abbreviate them all!
" New since vim-5.0v: flag 'I' to suppress "intro message".
set shortmess=at
"
" showcmd: Show current uncompleted command? Absolutely!
set showcmd
"
" showmatch: Show the matching bracket for the last ')'?
set showmatch
"
" showmode: Show the current mode? YEEEEEEEEESSSSSSSSSSS!
set showmode
"
" suffixes: Ignore filename with any of these suffixes
" when using the ":edit" command.
" Most of these are files created by LaTeX.
set suffixes=.aux,.bak,.dvi,.gz,.idx,.log,.ps,.swp,.tar
"
" startofline: no: do not jump to first character with page
" commands, ie keep the cursor in the current column.
set nostartofline
"
" splitbelow: Create new window below current one.
set splitbelow
"
" statusline: customize contents of the windows' status line.
" I prefer it this way:
" Show the current buffer number and filename with info on
" modification, read-only, and whether it is a help buffer
" (show only when applied).
" set statusline=[%n]\ %f\ %(\ %M%R%H)%)
"
" Move the rest to the right side, eg a copyright text:
" set statusline=[%n]\ %f\ %(\ %M%R%H)%)%=(c)\ Sven\ Guckes
"
" Show the value of the current character in ASCII and Hex:
" set statusline=[%n]\ %f\ %(\ %M%R%H)%)\=ASCII=%b\ HEX=%B
"
" Show the current position with line+column+virtual_column:
" set statusline=[%n]\ %f\ %(\ %M%R%H)%)\=Pos=<%l\,%c%V>\ %P
" Adding color through UserN groups:
" set statusline=%1*[%02n]%*\ %2*%F%*\ %(\ %M%R%H)%)%=%3*Pos=<%l,%c%V>%*
" User1: color for buffer number
" hi User1 ctermfg=red ctermbg=white
" User2: color for filename
" hi User2 ctermfg=green ctermbg=white
" User3: color for position
" hi User3 ctermfg=blue ctermbg=white
"
" tabstop
set tabstop=8
"
" 990503: I have to set the "term" explicitly
" because the standard setups are broken.
" set term=builtin_pcansi
" set term=xterm
"
" Set the colors for vim on "xterm"
" if &term=="xterm"
" set t_Co=8
" set t_AB=[%?%p1%{8}%<%t%p1%{40}%+%e%p1%{92}%+%;%dm
" set t_AF=[%?%p1%{8}%<%t%p1%{30}%+%e%p1%{82}%+%;%dm
" endif
"
" textmode: no - I am using Vim on UNIX!
" set notextmode
"
" textwidth
set textwidth=79
"
" title:
set notitle
"
" ttyfast: are we using a fast terminal?
" seting depends on where I use Vim...
set nottyfast
"
" ttybuiltin:
set nottybuiltin
"
" ttyscroll: turn off scrolling -> faster!
set ttyscroll=0
"
" ttytype:
" set ttytype=rxvt
"
" viminfo: What info to store from an editing session
" in the viminfo file; can be used at next session.
set viminfo=%,'50,\"100,:100,n~/.viminfo
"
" visualbell:
set visualbell
"
" t_vb: terminal's visual bell - turned off to make Vim quiet!
" Please use this as to not annoy cow-orkers in the same room.
" Thankyou! :-)
set t_vb=
"
" whichwrap:
" Allow jump commands for left/right motion to wrap to previous/next
" line when cursor is on first/last character in the line:
set whichwrap=<,>,h,l,[,]
"
" wildchar the char used for "expansion" on the command line
" default value is "<C-E>" but I prefer the tab key:
set wildchar=<TAB>
"
" wrapmargin:
set wrapmargin=1
"
" writebackup:
set nowritebackup
"
" ===================================================================
" ABbreviations
" ===================================================================
" 980701: Moved the abbreviations *before* the mappings as
" some of the abbreviations get used with some mappings.
"
" Abbreviations for some important numbers:
iab Npi 3.1415926535897932384626433832795028841972
iab Ne 2.7182818284590452353602874713526624977573
"
" Abbreviations for some classic long words:
" Donau... is the German word for the (read in reverse)
" "additional paragraph of the law regulating the pension of
" widows to captains of the ship company on (the river) Danube"
" (I am not making this up! ;-)
iab YDD
Donaudampfschifffahrtgesellschaftskapitaenwitwenrentengesetzzusatzparagraph
" New German spelling "schifffahrt", too! (Hi, Doram!)
"
" 010131
iab YTNGV Telekommunikationsnummerngebuehrenverordnung
" 010131
" iab YRRAG Rinderkennzeichnungs- und \
" Rindfleischetikettierungsüberwachungsaufgabenübertragungsgesetz (RkReÜAÜG)
"
" Some more weird sentences in KrautLang:
" "Jörg möchte fünf Frühstücksbrötchen
" um äußerstes Völlegefühl zu spüren."
" "Äßen Löwen Möwen, zögen Möwen über Löwen rüber."
" "Äße Öko-Jörg große Bärenfüße in äußerst süßer Nußölkäsesoße
" müßte er in ein übermäßig häßliches Güllefaß."
iab YHRA "Heizölrückstoßabdämpfung"
" all three umlauts and the 'ß', too!
" Yes, KrautLang *is* weird!
"
" YLL : The name of a town in Wales. I am not making this up!
iab YLL LLanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch
" http://www.llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch.co.uk
" http://194.159.85.168/ - I am not making this up! :-)
"
" YTauma: The name of a hill in New Zealand.
iab YTauma
Taumatawhakatangihangakoauauotamateaturipukakapikimaungahoronukupokaiwenuakitanatahu
"
" Longest Word in the second edition of the Oxford English Dictionary?
iab YNNMSVC pneumonoultramicroscopicsilicovolcanoconiosis
"
" Yalpha : The lower letter alphabet.
iab Yalpha abcdefghijklmnopqrstuvwxyz
"
" YALPHA : The upper letter alphabet.
iab YALPHA ABCDEFGHIJKLMNOPQRSTUVWXYZ
"
" Ydigit: The ten digits.
iab Ydigit 1234567890
"
" Yruler: A "ruler" - nice for counting the length of words.
iab Yruler
1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
"
" Yupsidedown : This describes people from "down under" (Hi, Dean!).
iab Yupsidedown umop-ap!sdn
"
" Ysuper: A nice long word from the musical "Mary Poppins".
iab Ysuper supercalifragilisticexpialidocious
"
" Yanti: The longest proper word in the English language?!
iab Yanti antidisestablishmentarianism
"
" Ypass: Standard answer to Usenet posts
" with the "Subject: HELP" (hehe)
iab Ypass "You are in a maze of twisty little passages, all alike."
"
" Yicty: Some people should really RTFM!
iab Yicty I could tell you - but then I'd have to kill you.
"
" Ybtdt: It's been dejavu all over again.
iab Ybtdt Been there, done that, got the tshirt.
"
" Ywttc: One more person using Vim.
iab Ywttc Welcome to the club!
"
" Ysesqui: "Sesquipedalophobia" means "fear of big words." ;-)
iab Ysesqui sesquipedalophobia
"
" Yi18n: .123456789012345678. - yup, 18 characters betwwen 'i' and 'n'
iab Yi18n internationalization
"
" Yanfs: Changing the Subject within a message. (Hi, Monty Python!)
iab Yanfs And now for something completely different...
"
"
"
" classic pangrams (which include every letter of the alphabet):
" German:
" kaufen sie jede woche vier gute bequeme pelze [missing: 'xy' :-/]
" sylvia wagt quick den jux bei pforzheim
" bayerische jagdwitze von maxl querkopf
" zwei boxkaempfer jagen eva quer durch sylt
" falsches üben von xylophonmusik quält jeden größeren zwerg.
" Bei jedem klugen Wort von Sokrates rief Xanthippe zynisch: Quatsch!
" English:
" the quick brown fox jumps over the lazy dog
" The five boxing wizards jump quickly
" French:
" voyez le brick geant que j'examine pres du wharf.
" Polish:
" Pchn±æ w tê ³ód¼ je¿a lub o¶m skrzyñ fig.
" Koñ i ¿ó³w grali w ko¶ci z piêkn± æm± u ¼ród³a.
" Têgi koñ i ma³y ¿ó³w ¶piewali z piêkn± æm± u ¼ród³a ¿ycia.
"
" And a sentence to break some quoing levels:
" "This man's house (which 's yellow) burned down."
"
" And now for something completely different:
" I couldn't bear to bear bears over the border.
"
" Inserting an ellipsis to indicate deleted text
iab Yell [...]
vmap ,ell c[...]<ESC>
"
" Correcting those typos. [I almost never get these right. :-(]
" See also: http://www.igd.fhg.de/~zach/programs/acl/
iab alos also
iab aslo also
iab becuase because
iab bianry binary
iab bianries binaries
iab charcter character
iab charcters characters
iab exmaple example
iab exmaples examples
iab shoudl should
iab seperate separate
iab teh the
iab tpyo typo
" Some frequent typos in German:
iab nciht nicht
iab doer oder
iab Dreckfuhler Druckfehler
"
" Sorry, Laurent!
iab Laurant Laurent
"
" See http://www.math.fu-berlin.de/~guckes/sig/:
iab YDDS dash-dash-space
"
" For reports and texts on my studies:
" iab YKT Komplexitaetstheorie
" iab YRA Rechnerarchitektur
" iab YPM Pattern Matching
" see http://elib.zib.de/ICM98 :
" iab YICM International Congress of Mathematicians
"
" Some sentences that I really use often in emails about Vim:
iab YAW You are welcome!
iab YEV Enjoy Vim! :-)
"
" Often used filenames - only needed these on the command line:
" see also: http://www.math.fu-berlin.de/~guckes/setup/
"
" cab ELMALIAS ~/.elm/aliases.text
" cab Erc ~/.elm/elmrc
" cab Mrc ~/.muttrc
" cab Src ~/.slrnrc
" cab Zrc ~/.zsh/.zshrc
"
" Email Adresses:
" I usually use these when adding addresses to the header
" of emails (mutt) and posts (slrn).
"
" Author of the Good NetKeeping Seal of Approval:
ab Agnksa [email protected] (Jeroen Scheerder)
"
" Original author of Mutt:
" ab Amutt [email protected] (Michael Elkins)
" Maintainer of Mutt:
ab Amutt [email protected] (Thomas Roessler)
"
" Author of Slrn:
ab Aslrn [email protected] (John E. Davis)
" Maintainer of Slrn:
ab Mslrn [email protected] (Thomas Schultz)
"
" Author of Vim - vim specific address:
ab Avim [email protected] (Bram Moolenaar)
" Author of Vim - private address:
ab Abram [email protected] (Bram Moolenaar)
"
" Author, contributor, maintainer of
" add atac autoconf bcpp ded dialog diffstat flist
" lynx ncurses tin vile vttest xterm - and more!
ab Avile [email protected] (Thomas E. Dickey)
"
" Former Maintainer of the Vim FAQ:
" ab Avimfaq [email protected] (Laurent Duperval)
ab Avimfaq [email protected] (Sven Guckes)
"
" Mailing Lists (MLs)
"
" The Vim mailing lists: See http://www.vim.org/mail.html for more info!
" ab MLvim [email protected] (VIM Help List)
" ab MLvimdev [email protected] (VIM General Development List)
" ab MLvimmac [email protected] (VIM on MacOS Development List)
" ab MLvimmb [email protected] (VIM MultiByte Development List)
" ab MLvimfr [email protected] (VIM Help List for French Users)
"
" More mailing lists:
" ab MLmuttdev [email protected] (Mutt Developer List)
" ab MLmuttuser [email protected] (Mutt Users List)
" ab MLzsh [email protected] (ZShell Users List)
"
"
" News: newsgroup names
"
" Newsgroup about "warloding" of signatures - see
" also http://www.math.fu-berlin.de/~guckes/afw/
iab Nafw alt.fan.warlord
iab Nahbou alt.humor.best-of-usenet
iab Nzedat bln.announce.fub.zedat.d
iab Ncsd bln.announce.fub.cs.d
iab Nce comp.editors
iab NcE de.comp.editoren
" Newsgroup about "lynx":
iab Nhtml comp.infosystems.www.authoring.html
" Newsgroup about "elm": Elm is dead - long live Mutt!
iab Nelm comp.mail.elm
" Newsgroup about "pine": When will they release pine-4?
" iab Ncmp comp.mail.pine
iab Npine comp.mail.pine
" iab Ncsmd comp.sys.mac.digest
" Newsgroup about "mobil phone systems":
iab Ndcm de.comm.mobil
iab Nmobil de.comm.mobil
" Newsgroup about "web browsers":
iab Nlynx comp.infosystems.www.browsers.misc
iab Nnetscape comp.infosystems.www.browsers.misc
" Newsgroup about "mutt" [since 980401]: The coolest mail user agent
iab Nmutt comp.mail.mutt
" Newsgroup about "nn": Once was the best newsreader. Still good.
iab Nnn news.software.nn
" Newsgroup for "newbies".
" All you ever wanted to know - but were afraid to ask. ;-)
iab Newbie news.newusers.questions
" Newsgroup about "newsreader *agents*" (netscape and slrn):
iab Nnsr news.software.readers
"
" Usenet header lines (used when composing a post):
"
iab UFT Followup-To:
iab UMCT Mail-Copies-To: MYADDR
iab UNG Newsgroups:
iab URT Reply-To: MYADDR
iab UFUB Organization: Freie Universitaet Berlin
"
" Current version numbers of my favourite programs:
" http://www.math.fu-berlin.de/~guckes/faq/program.versions.html
" And some abbreviations to type them in mail&news:
" [Last update: 001221]
iab Velmold ELM2.4PL25 [951204]
iab Velm ELM2.5.3 [000113]
iab Velmme ELMME+86 [001219]
iab Vless less-358 [000709]
iab Vlynx lynx-2.8.4dev14 [001103]
iab Vmutt mutt-1.2.5 [000729]
iab Vslrn slrn-0.9.6.3 [000918]
iab Vvim vim-5.7 [000624]
iab Vvimdev vim-6.0w [010226]
"
" My phone number (main phone number and fax):
iab Yphone TEL (+49 30) 8838884<CR>FAX (+49 30) 88629362
" My cellphone number:
iab Ycell TEL (+49 179) 3966141
" If you like then send me a short message to my cellphone via this page:
iab FreeSMS http://www.free-sms.com/sendsms/index.php3
" My snailmail address. Postcards, anyone?
iab Ysnail Sven Guckes<C-M>Pariser Str. 52<C-M>D-10719 Berlin
" My ICQ number. Chat, anyone?
iab YICQ ICQ:38801898
"
" My addresses (Email and WWW)
" makes it easy to type them without typos ;-)
ab Amaili [email protected]
ab Amailm [email protected]
ab Amailv [email protected]
ab Amailz [email protected]
" ab Apriv [email protected]
ab MYADDR [email protected]
ab MYNAME Sven Guckes
ab MYDOMAIN math.fu-berlin.de
" ab MYDOMAIN guckes.net
"
" Setting the reply address when replying as the guy from SKB:
" ab ASKB Sprachboerse <[email protected]>
" See also: http://www.math.fu-berlin.de/~guckes/skb/
"
" My Home Pages at the departments at the FUB and elsewhere...
"
ab WWWb http://www.belug.org/~guckes/
ab WWWm http://www.math.fu-berlin.de/~guckes/
ab WWWi http://www.inf.fu-berlin.de/~guckes/
ab WWWz http://userpage.zedat.fu-berlin.de/~guckes/
"
" WWW Pages base URLs
"
ab HPA http://www.math.fu-berlin.de/~guckes/afw/
ab HPa http://www.math.fu-berlin.de/~guckes/ascii/
ab HPc http://www.math.fu-berlin.de/~guckes/calvin/
ab HPD http://www.math.fu-berlin.de/~guckes/dos/
ab HPe http://www.math.fu-berlin.de/~guckes/eplus/ab.faq.html
ab HPE http://www.math.fu-berlin.de/~guckes/elm/
ab HPI http://www.math.fu-berlin.de/~guckes/irc/
ab HPi http://www.math.fu-berlin.de/~guckes/ispell/
ab HPL http://www.math.fu-berlin.de/~guckes/lynx/
ab HPl http://www.math.fu-berlin.de/~guckes/less/
ab HPm http://www.math.fu-berlin.de/~guckes/mail/
ab HPme http://www.math.fu-berlin.de/~guckes/mail/edit.html
ab HPM http://www.math.fu-berlin.de/~guckes/mutt/
ab HPN http://www.math.fu-berlin.de/~guckes/nn/
ab HPP http://www.math.fu-berlin.de/~guckes/pine/
ab HPp http://www.math.fu-berlin.de/~guckes/procmail/
ab HPr http://babayaga.math.fu-berlin.de/~rxvt/
ab HPR http://www.math.fu-berlin.de/~guckes/rfc/
ab HPs http://www.math.fu-berlin.de/~guckes/screen/
ab HPS http://slrn.sourceforge.net/
ab HPS1 http://www.math.fu-berlin.de/~guckes/slrn/
ab HPS2 http://www.slrn.org/
ab HPv http://www.math.fu-berlin.de/~guckes/vi/
" HPOV - the "original" URL of the Vim Home Page!
ab HPOV http://www.math.fu-berlin.de/~guckes/vim/
ab HPV http://www.vim.org/
ab HPX http://www.math.fu-berlin.de/~guckes/xmas/
ab HPZ http://www.math.fu-berlin.de/~guckes/zsh/
"
" Other important WWW addresses
"
ab URLaltavista http://www.altavista.de/textonly.html
ab URLftpsearch http://ftpsearch.lycos.com/?form=advanced
ab URLrpmfind http://rpmfind.net
ab URLslashdot http://slashdot.org
ab URLfreshmeat http://freshmeat.net
"
" Pictures:
ab URLbambi http://www.math.fu-berlin.de/~guckes/pics/calvin/bambi.gif
ab URLsecret http://www.math.fu-berlin.de/~guckes/pics/calvin/secret.gif
ab URLwhome http://www.math.fu-berlin.de/~guckes/pics/calvin/who_me.gif
ab URLstopspam http://www.math.fu-berlin.de/~guckes/pics/spam/stop.jpg
ab URLutefuchs http://www.math.fu-berlin.de/~utefuchs/
"
" The nearest vim site for me:
ab FTPG ftp://ftp.math.fu-berlin.de/pub/usr/guckes/
ab FTPFUB ftp://ftp.fu-berlin.de/
ab FTPVIM ftp://ftp.fu-berlin.de/pub/misc/editors/vim/
ab URLVINE http://www.mossbayeng.com/~ron/vim/vine.html
" But you should look at http://www.vim.org/dist.html instead!
"
" ===================================================================
" Abbreviations - Header Lines for Email and News
" ===================================================================
" Define regexpr for headers to use with mappings
" as it makes reading the mappings much easier:
" cab HADDR From\\|Cc\\|To
cab HEMAIL ^\(From\\|Cc\\|To\\|Date\\|Subject\\|Message-ID\\|Message-Id\\|X-\)
cab HNEWS ^\(From\\|Cc\\|To\\|Date\\|Subject\\|Message-ID\\|X-\\|Newsgroups\)
"
" ===================================================================
" Abbreviations - General Editing - Inserting Dates and Times
" ===================================================================
"
" First, some command to add date stamps (with and without time).
" I use these manually after a substantial change to a webpage.
" [These abbreviations are used with the mapping for ",L".]
"
iab Ydate <C-R>=strftime("%y%m%d")<CR>
" Example: 971027
"
iab Ytime <C-R>=strftime("%H:%M")<CR>
" Example: 14:28
"
" man strftime: %T time as %H:%M:%S
" iab YDT <C-R>=strftime("%y%m%d %T")<CR>
" Example: 971027 12:00:00
"
" man strftime: %X locale's appropriate time representation
iab YDT <C-R>=strftime("%y%m%d %X")<CR>
" Example: 000320 20:20:20
"
iab YDATE <C-R>=strftime("%a %b %d %T %Z %Y")<CR>
" Example: Tue Dec 16 12:07:00 CET 1997
"
" On Windows the functions "strftime" seems to have a different
" format. Therefore the following may be necessary: [980730]
" if !has("unix")
" iab YDATE <C-R>=strftime("%c %a")<CR>
" else
" iab YDATE <C-R>=strftime("%D %T %a")<CR>
" endif
"
" 000306: These two lines at the start of a Perl script
" will start the first Perl in your Shell's $PATH.
iab Yperlhead eval 'exec perl -w -S $0 ${1+"$@"}'<c-m>if 0;<c-m>
"
"
" ===================================================================
" MAPpings
" ===================================================================
" Caveat: Mapping must be "prefix free", ie no mapping must be the
" prefix of any other mapping. Example: "map ,abc foo" and
" "map ,abcd bar" will give you the error message "Ambigous mapping".
"
" The backslash ('\') is the only(?) unmapped key, so this is the best
" key to start mappings with as this does not take away a command key.
" However, the backslash is never in the same position with keyboards.
" Eg on German keyboards it is AltGr-sz - don't ask.
" Anyway, I have decided to start mappings with the comma as this
" character is always on the same position on almost all keyboards
" and I hardly have a need for that command.
"
" The following maps get rid of some basic problems:
"
" When the backspace key sends a "delete" character
" then you simply map the "delete" to a "backspace" (CTRL-H):
" map <Del> <C-H>
"
" With Vim-4 the format command was just 'Q' and
" I am too used to it. So I need this back!
nnoremap Q gq
vnoremap Q gq
"
" 980527 I often reformat a paragraph to fit some textwidth -
" and I use the following mapping to adjust it to the
" current position of the cursor:
map #tw :set textwidth=<C-R>=col(".")<C-M>
"
" 981210 Whenever I paste some text into VIM I have to
" toggle from "nopaste" to "paste" and back again:
" map <f4> :set paste!<C-M>:set paste?<C-M>
" map <esc>[14~ :set paste!<C-M>:set paste?<C-M>
" --> new option for this: 'pastetoggle'
"
" "tal" is the "trailer alignment" filter program
" Hopefully it will ship with Vim one day.
" vmap #t !tal<CR>
" vmap #t !tal -p 0<CR>
"
" Disable the command 'K' (keyword lookup) by mapping it
" to an "empty command". (thanks, Lawrence! :-):
" map K :<CR>
" map K :<BS>
" More elegant: (Hi Aziz! :-)
map K <NUL>
"
" Disable the suspend for ^Z.
" I use Vim under "screen" where a suspend would lose the
" connection to the " terminal - which is what I want to avoid.
map <C-Z> :shell
"
" Make CTRL-^ rebound to the *column* in the previous file
noremap <C-^> <C-^>`"
"
" Make "gf" rebound to last cursor position (line *and* column)
noremap gf gf`"
"
" When I let Vim write the current buffer I frequently mistype the
" command ":w" as ":W" - so I have to remap it to correct this typo:
nmap :W :w
" TODO: Use the following (after some testing):
" command -nargs=? -bang W w<bang> <args>
"
" Are you used to the Unix commands "alias" and "which"?
" I sometimes use these to look up my abbreviations and mappings.
" So I need them available on the command line:
map :alias map
map :which map
"
" The command {number}CTRL-G show the current nuffer number, too.
" This is yet another feature that vi does not have.
" As I always want to see the buffer number I map it to CTRL-G.
" Pleae note that here we need to prevent a loop in the mapping by
" using the comamnd "noremap"!
noremap <C-G> 2<C-G>
"
" 001010 Do the Color Test!
map ,CT :sp $VIMRUNTIME/syntax/colortest.vim<cr>:so %<cr>
" 000329 View the file which defines the "filetypes":
map ,F :view $VIMRUNTIME/filetype.vim
"
" 980311 Sourcing syntax files::
map ,SO :source $VIMRUNTIME/syntax/
"
" 980706,000310 View a syntax file:
map ,V :view $VIMRUNTIME/syntax/
"
" 000801 Hilite Test - show all current highlight groups
" see ":help hitest.vim"
map ,HI :so $VIMRUNTIME/syntax/hitest.vim
"
" 990614 Quick insertion of an empty line:
" nmap <CR> o<ESC>
" I find this convenient - but as I am also used to proceed to
" next line by pressing CR this often gives me new empty lines
" when I really do not need them. :-(
"
" ===================================================================
" Customizing the command line
" ===================================================================
" Valid names for keys are: <Up> <Down> <Left> <Right> <Home> <End>
" <S-Left> <S-Right> <S-Up> <PageUp> <S-Down> <PageDown> <LeftMouse>
"
" Many shells allow editing in "Emacs Style".
" Although I love Vi, I am quite used to this kind of editing now.
" So here it is - command line editing commands in emacs style:
cnoremap <C-A> <Home>
cnoremap <C-B> <Left>
" cnoremap <C-B> <Del>
cnoremap <C-E> <End>
cnoremap <C-F> <Right>
cnoremap <C-N> <End>
cnoremap <C-P> <Up>
cnoremap <ESC>b <S-Left>
cnoremap <ESC><C-B> <S-Left>
cnoremap <ESC>f <S-Right>
cnoremap <ESC><C-F> <S-Right>
cnoremap <ESC><C-H> <C-W>
" Note: More info about this is in the helptexts: :help emacs-keys
"
" Additional codes for that "English" keyboard at the Xterminal
cnoremap <ESC>[D <Left>
cnoremap <ESC>[C <Right>
"
" ===================================================================
" VIM - Editing and updating the vimrc:
" As I often make changes to this file I use these commands
" to start editing it and also update it:
if has("unix")
let vimrc='~/.vimrc'
else
" ie: if has("dos16") || has("dos32") || has("win32")
let vimrc='$VIM\_vimrc'
endif
nn ,u :source <C-R>=vimrc<CR><CR>
nn ,v :edit <C-R>=vimrc<CR><CR>
" ,v = vimrc editing (edit this file)
" map ,v :e ~/.vimrc<CR>
" ,u = "update" by reading this file
" map ,u :source ~/.vimrc<CR>
" ===================================================================
"
" General Editing
"
" Define "del" char to be the same backspace (saves a LOT of trouble!)
" As the angle notation cannot be use with the LeftHandSide
" with mappings you must type this in *literally*!
" map <C-V>127 <C-H>
"cmap <C-V>127 <C-H>
" the same for Linux Debian which uses
imap <Esc>[3~ <C-H>
"
" ;rcm = remove "control-m"s - for those mails sent from DOS:
cmap ;rcm %s/<C-M>//g
"
" Make whitespace visible:
" Sws = show whitespace
nmap ,Sws :%s/ /_/g<C-M>
vmap ,Sws :%s/ /_/g<C-M>
"
" Sometimes you just want to *see* that trailing whitespace:
" Stws = show trailing whitespace
nmap ,Stws :%s/ *$/_/g<C-M>
vmap ,Stws :%s/ *$/_/g<C-M>
"
" General Editing - Turning umlauts into ascii (for German keyboards)
"
" imap ä ae
" imap ö oe
" imap ü ue
" imap ß ss
"
" Ä -> Ä :%s/\Ä/Ä/gc -> D
" Ö -> Ö :%s/\Ö/Ö/gc -> V
" Ü -> Ü :%s/\Ü/Ü/gc -> \
" ä -> ä :%s/\ä/ä/gc -> d
" ö -> ö :%s/\ö/ö/gc -> v
" ü -> ü :%s/\ü/ü/gc -> |
"
" ===================================================================
" Inserting Dates and Times / Updating Date+Time Stamps
" ===================================================================
" ,L = "Last update" - replace old time stamp with a new one
" preserving whitespace and using internal "strftime" command:
" requires the abbreviation "YDATE"
map ,L 1G/Last update:\s*/e+1<CR>CYDATE<ESC>
map ,,L 1G/Last change:\s*/e+1<CR>CYDATE<ESC>
" Example:
" before: "Last update: Thu Apr 6 12:07:00 CET 1967"
" after: "Last update: Tue Dec 16 12:07:00 CET 1997"
"
" I used to read in the output from the external command "date"
" but this is a little slow and does not work on all systems:
" map ,L 1G/Last update: */e+1<CR>D:r!date<CR>kJ
"
" ===================================================================
" General Editing - link to program "screen"
" ===================================================================
"
" ,Et = edit temporary file of "screen" program
map ,Et :e /tmp/screen-exchange
" as a user of Unix systems you *must* have this program!
" see also: http://www.math.fu-berlin.de/~guckes/screen/
"
" Email/News - Editing replies/followups
"
" Part 1 - prepare for editing
"
" Part 2 - getting rid of empty (quoted) lines and space runs.
"
" Delete trailing whitespace:
nmap <f9> :%s/\s\+$//
vmap <f9> :s/\s\+$//
"
" ,cel = "clear empty lines"
" - delete the *contents* of all lines which contain only whitespace.
" note: this does not delete lines!
" map ,cel :g/^[<C-I> ]*$/d
map ,cel :%s/^\s\+$//
"
" ,del = "delete 'empty' lines"
" - delete all lines which contain only whitespace
" note: this does *not* delete empty lines!
map ,del :g/^\s\+$/d
"
" ,cqel = "clear quoted empty lines"
" Clears (makes empty) all lines which start with '>'
" and any amount of following spaces.
" nmap ,cqel :%s/^[> ]*$//
" vmap ,cqel :s/^[> ]*$//
" nmap ,cqel :%s/^[><C-I> ]\+$//
" vmap ,cqel :s/^[><C-I> ]\+$//
nmap ,cqel :%s/^[>]\+$//
vmap ,cqel :s/^[><C-I> ]\+$//
" NOTE: If the meta sequence "\s"
" The following do not work as "\s" is not a character
" and thus cannot be part of a "character set".
" map ,cqel :g/^[>\s]\+$/d
"
" Some people have strange habits within their writing.
" But if you cannot educate them - rewrite their text! ;-)
"
" Jason "triple-dots" King [email protected]
" does uses ".." or "..." rather than the usual punctuation
" (comma, semicolon, colon, full stop). So...
"
" Turning dot runs with following spaces into an end-of-sentence,
" ie dot-space-space:
vmap ,dot :s/\.\+ \+/. /g
"
" Gary Kline ([email protected]) indents his
" own text in replies with TAB or spaces.
" Here's how to get rid of these indentation:
vmap ,gary :s/^>[ <C-I>]\+\([^>]\)/> \1/
"
" ,ksr = "kill space runs"
" substitutes runs of two or more space to a single space:
" nmap ,ksr :%s/ */ /g
" vmap ,ksr :s/ */ /g
nmap ,ksr :%s/ \+/ /g
vmap ,ksr :s/ \+/ /g
" Why can't the removal of space runs be
" an option of "text formatting"? *hrmpf*
"
" ,Sel = "squeeze empty lines"
" Convert blocks of empty lines (not even whitespace included)
" into *one* empty line (within current visual):
map ,Sel :g/^$/,/./-j
"
" ,Sbl = "squeeze blank lines"
" Convert all blocks of blank lines (containing whitespace only)
" into *one* empty line (within current visual):
" map ,Sbl :g/^\s*$/,/[^ <C-I>]/-j
" map ,Sbl :g/^\s*$/,/[^ \t]/-j
map ,Sbl :g/^\s*$/,/\S/-j
"
" ===================================================================
" AUTOCOMMANDS:
" Editing of email replies and Usenet followups - using autocommands
" ===================================================================
"
" First step: Remove ALL auto-commands. This avoids having the
" autocommands twice when the vimrc file is sourced again.
autocmd!
"
" Add/change some filename patterns to filetypes:
" let myfiletypefile = "~/.vim.myfiletypes"
"
" And this goes into "~/.vim.myfiletypes":
" augroup filetype
" au BufRead,BufNewFile postpone/* set filetype=mail
" augroup END
"
" Apply my syntax file on files with extension "sdg":
au BufNewFile,BufRead *.sdg set ft=sveng
"
" Apply the muttrc coloring to my mutt setup files:
au BufNewFile,BufRead .mutt.* set ft=muttrc
"
" SLRN: Apply mail.vim to postponed messages:
au BufNewFile,BufRead */postpone/* set ft=mail
"
" Set some options for "messages" (FileType "mail"):
" au FileType mail set autoindent expandtab tabstop=4 textwidth=70
" the following uses ethe short option names:
au FileType mail set ai et ts=4 tw=70
"
" Some more autocommand examples which set the values for
" "autoindent", "expandtab", "shiftwidth", "tabstop", and "textwidth":
" using the "FileType" event:
" au FileType c set ai et sw=4 ts=4
" au FileType perl set ai et sw=4 ts=4
" au FileType html set ai sw=2 ts=2
" au FileType java set ai sw=4 ts=4
" au BufEnter */drafts/* set tw=72
"
" Try to use the mapping ",D" when doing a followup.
" autocmd BufNewFile ~/.followup ,D|
"
" Setting "X-Editor":
" Let Vim identify itself in the message header
" when editing emails with Mutt and Slrn:
" au FileType mail let @"="X-Editor: Vim-".version." http://www.vim.org/\n"|exe
'norm 1G}""P'
"
" Generation of a "Message-ID" header line (according to ISO8061):
"
" Let Vim add a Message-ID to your posts with Slrn:
"
" Add a Message-ID to posts with Slrn:
" au BufNewFile,BufRead ~/.article let @"="Message-ID:
<slrn.".system("uname").".".strftime("%y%m%d%H%M")."\n"|exe 'norm 1G}""P'
" Problem: The uname adds a CTRL-J at the end of the output. :-(
"
" Add a Message-ID to posts with Slrn (mimimal format):
" au BufNewFile,BufRead ~/.article,~/.followup let @"="Message-ID:
<".strftime("%Y%m%dT%H%M%S")."@guckes.net>\n"|exe 'norm 1G}""P'
" Example: Message-ID: <[email protected]>
" Problem: The date and time are hard to read.
" It's easier with a few delimiters:
"
" Add a Message-ID to posts with Slrn (with delimiters):
" au BufNewFile,BufRead ~/.article,~/.followup let @"="Message-ID:
<".strftime("%Y-%m-%dT%H-%M-%S")."@guckes.net>\n"|exe 'norm 1G}""P'
" Example: Message-ID: <[email protected]>
"
" news.fu-berlin.de rejects Message-IDs with colons in it:
" Example: Message-ID: <2000-04-06T12:07:[email protected]>
"
"
" Part 3 - Change Quoting Level
"
" ,dp = de-quote current inner paragraph
" map ,dp {jma}kmb:'a,'bs/^> //<CR>
map ,dp vip:s/^> //<CR>
vmap ,dp :s/^> //<CR>
"
" ,qp = quote current paragraph
" jump to first inner line, mark with 'a';
" jump to last inner line, mark with 'b';
" then do the quoting as a substitution
" on the line range "'a,'b":
" map ,qp {jma}kmb:'a,'bs/^/> /<CR>
" vim-5 now has selection of "inner" and "all"
" of current text object - mapping commented!
"
" ,qp = quote current paragraph (old version)
" jump to first inner line, Visual,
" jump to last inner line,
" then do the quoting as a substitution:
" map ,qp {jV}k:s/^/> /<CR>
"
" ,qp = quote current inner paragraph (works since vim-5.0q)
" select inner paragraph
" then do the quoting as a substitution:
map ,qp vip:s/^/> /<CR>
"
" ,qp = quote current paragraph
" just do the quoting as a substitution:
vmap ,qp :s/^/> /<CR>
"
" ## = comment current inner paragraph with '#':
nmap ## vip:s/^/#<space>/<CR>
" ## = comment current text selection with '#':
vmap ## :s/^/#<space>/<CR>
"
" 001006: Commenting selected lines in C style:
" vmap ## :s#^#// #<cr>'<O/*<esc>'>o*/<esc>gv
"
" Example of result:
" /*
" // foo
" // bar
" /*
"
" Changing quote style to *the* true quote prefix string "> ":
"
" Fix Supercite aka PowerQuote (Hi, Andi! :-):
" before ,kpq: > Sven> text
" after ,kpq: > > text
" ,kpq kill power quote
vmap ,kpq :s/^> *[a-zA-Z]*>/> >/<C-M>
"
" Fix various other quote characters:
" ,fq "fix quoting"
vmap ,fq :s/^> \([-":}\|][ <C-I>]\)/> > /
"
" Fix the quoting of "Microsoft Internet E-Mail":
" The guilty mailer identifies like this:
" X-Mailer: Microsoft Internet E-Mail/MAPI - 8.0.0.4211
"
" And this is how it quotes - with a pseudo header:
"
" -----Ursprungliche Nachricht-----
" Von: NAME [SMTP:ADDRESS]
" Gesendet am: Donnerstag, 6. April 2000 12:07
" An: NAME
" Cc: NAME
" Betreff: foobar
"
" And here's how I "fix" this quoting:
" (it makes use of the mappings ",dp" and ",qp"):
map #fix /^> -----.*-----$<cr>O<esc>j,dp<c-o>dapVG,qp
"
" Part 4 - Weed Headers of quoted mail/post
"
" These mappings make use of the abbreviation that define a list of
" Email headers (HEMAIL) and News headers (HNEWS):
nmap ,we vip:v#HEMAIL#d
vmap ,we :v#HEMAIL#d
nmap ,wp vip:v#HNEWS#d
vmap ,wp :v#HNEWS#d
"
" ,ri = "Read in" basic lines from the email header
" Useful when replying to an email:
" nmap ,ri :r!readmsg\|egrep "^From:\|^Subject:\|^Date:\|^To: \|^Cc:"
" NOTE: "readmsg" ships with the mailer ELM.
"
"
" Part 5 - Reformatting Text
"
" NOTE: The following mapping require formatoptions to include 'r'
" and "comments" to include "n:>" (ie "nested" comments with '>').
"
" Formatting the current paragraph according to
" the current 'textwidth' with ^J (control-j):
" imap <C-J> <C-O>gqap " too dangerous for my editing ;-)
nmap <C-J> gqap
vmap <C-J> gq
"
" Here is a variation of this command. It inserts the character
" CTRL-Z at the current position to enable to rebound to the
" previous position within the text. [Hello, Y. K. Puckett!]
" map <C-J> i<C-Z><esc>gqip?<C-Z><cr>x
" imap <C-J> <C-Z><esc>gqip?<C-Z><cr>xi
"
" Some people prefer to use extrernal formatting utilities
" such as "fmt" or "par":
" nmap <C-J> !}fmt<cr>
" vmap <C-J> !fmt<cr>
"
"
" ,b = break line in commented text (to be used on a space)
" nmap ,b dwi<CR>> <ESC>
nmap ,b r<CR>
" ,j = join line in commented text
" (can be used anywhere on the line)
" nmap ,j Jxx
nmap ,j Vjgq
"
" ,B = break line at current position *and* join the next line
" nmap ,B i<CR>><ESC>Jxx
nmap ,B r<CR>Vjgq
"
" ,,, break current line at current column,
" inserting ellipsis and "filling space":
" nmap ,,, ,,1,,2
" nmap ,,1 a...X...<ESC>FXr<CR>lmaky$o<CC-R>"<ESC>
" nmap ,,2 :s/./ /g<C-M>3X0"yy$dd`a"yP
"
"
" ===================================================================
" Edit your reply! (Or else!)
" ===================================================================
"
" Part 6 - Inserting Special or Standard Text
" Part 6a - The header
Search Groups
Acquired Advanced Groups Search
Google Acquires Deja's Usenet Google Search Groups Help
Discussion Service. Read our
press release. Search Groups (Beta) Search the Web
New to Usenet?
Learn the basics about reading, Browse Groups
posting and participating.
alt. (alternative) news. (news)
Any conceivable topic... Info about Usenet news...
Looking for Deja.com's
Precision Buying Service? biz. (business) rec. (recreation)
eBay's Half.com has acquired Business products, services, reviews... Games, hobbies, sports...
Deja.com's Precision Buying
Service comp. (computers) sci. (science)
Hardware, software, consumer info... Applied science, social science...
Buy / Sell used CDs DVDs
$5 off $10 order @ Half.com humanities. (humanities) soc. (society)
Fine art, literature, philosophy... Social issues, culture...
Login for Existing My-Deja misc. (miscellaneous) talk. (talk)
Email Accounts Employment, health, and much more... Current issues and debates...
More about your account
Member Name:
Complete list of groups...
Password: New! Google now offers a way to post messages on Usenet through Google
Groups. This eagerly-anticipated improvement follows the recent addition of the
full Usenet archive formerly maintained by Deja.com. Together, these upgrades
Login provide you with complete access to Usenet data since 1995 and the ability to
add your own comments to the more than 650 million messages already posted.
Forgot your password? We hope you will find this improved Usenet service of value. Google is
committed to making Google Groups the best source of Usenet postings on the
web and to that end, we will continue working to add the services and functions
our users request.
To get the latest news on Google Groups and other Google initiatives, you may
want to subscribe to the Google Friends newsletter. Or simply check Google
Groups for updates.
For more information about the transition from Deja to Google, please read
Google's press release.
©2001 Google
" Vim syntax file
" Language: Mail file
" Maintainer: Felix von Leitner <[email protected]>
" Last Change: 2001 May 09
" The mail header is recognized starting with a "keyword:" line and ending
" with an empty line or other line that can't be in the header.
" All lines of the header are highlighted
" For "From " matching case is required, not for the rest.
syn region mailHeader start="^From " skip="^[ \t]"
end="^[-A-Za-z0-9/]*[^-A-Za-z0-9/:]"me=s-1 end="^[^:]*$"me=s-1 end="^---*"
contains=mailHeaderKey,mailSubject
" Need to sync on the header. Assume we can do that within a hundred lines
syn sync lines=100
delcommand HiLink
endif
Introduction
This is the official home page of slrn. slrn (``s-lang read news'') is a newsreader, i.e. a
program that accesses a newsserver to read messages from the Internet News service (also
known as ``Usenet''). It runs in console mode on various Unix-like systems (including
Linux), 32-bit Windows, OS/2, BeOS and VMS. Beside the usual features of a newsreader,
slrn supports scoring rules to highlight, sort or kill articles based on information from their
header. It is highly customizable, allows free key-bindings and can easily be extended using
the sophisticated s-lang macro language. Offline reading is possible by using either slrnpull
(shipped with slrn) or a local newsserver (like leafnode or INN).
❍ News
The latest stable version of slrn is 0.9.7.1, released on 2001-06-06.
❍ Get slrn
❍ Mailing list
What's new? ❍ About us
[2001-06-06] slrn 0.9.7.1 released Site map
The new stable version of slrn is finally there. It has a fully ❍ Home
customizable group mode and status bars, highlights URLs, makes ❍ Docs
use of some common NNTP extensions, offers better
documentation and has lots of minor improvements and bugfixes ❍ Manual
over the previous version. ❍ Cleanscore
As always, you can look at the full list of changes or download the
❍ Macros
thing directly.
❍ Patches
[2001-04-19] Full documentation online
❍ Wishlist
All the documentation that comes with slrn's source distribution
can now be found on our new documentation page. You will find ❍ Links
both plain text and (where available) HTML versions there and you
Hosting
can download tarballs for offline reading.
SourceForge
[2001-03-28] slrn 0.9.7.0 released Logo
This project is kindly
hosted by SourceForge.
HTML validation
I finally released the new, long awaited stable version of the slrn Valid HTML
newsreader, 0.9.7.0. Besides adding exciting new features, it also 4.0!
fixes a lot of annoying and some (potentially) security relevant This webpage complies
bugs, so I recommend the upgrade. You might either want to look with the W3C HTML
at the changes or go straight to the download page. standards.
Thanks to everyone who helped by contributing code, writing
documentation or reporting bugs.
For older news, please see the full history.
❍ ftp://ftp.fu-berlin.de/pub/unix/news/slrn/
❍ ftp://ftp.ntua.gr/pub/lang/slang/
❍ ftp://ftp.plig.org/pub/slrn/
Getting precompiled binaries
Please note that some binary packages include patches that are
often, but not always useful. If you want to be sure to have a
``vanilla'' slrn installation, you should get the source code and
compile it yourself. You also need the source code if you want to
apply the patches found on this page.
❍ Debian provides packages of slrn for their system. If you
want to use the current version, you probably need the
packages from the ``testing'' or even the ``unstable''
distribution.
❍ If your RPM-based distribution does not include a recent
binary, you can look for Linux RPMs of slrn at
www.rpmfind.net.
❍ Hynek Schlawack has a nice homepage with AmigaOS
packages.
❍ Francesco Cipriani offers a precompiled OS/2 version.
❍ Win32 binaries are available from our FTP space.
❍ Ted Stodgell provides a BeOS binary.
❍ Gerhard Lenerz offers precompiled IRIX binaries for
download.
Content is provided by the slrn web resource staff. This page is designed by Thomas Schultz. © 2000
URL: http://www.math.fu-berlin.de/~guckes/slrn/pics.html
URL: http://www.slrn.org/pics.html
Created: Tue Oct 1 00:00:00 MET 1996
Last update: Wed Apr 12 18:53:39 MET DST 2000
recognition of signature
The signature of this post has incorrect sigdashes (inly "--" instead of "-- "):
The poster did not apply correct sigdashes before his signature - thus it is not recognized as such and only partly understood as quoted text
(dashes at the start of the line).
A picture of someone who posted with correct sigdashes:
As you can see, the signature is recognized by sigdashes line ("-- ") and thus coloured in an extra colour (green).
Yes, the second picture shows the followup of the post in the first picture. ;-)
A pgp signed post of the announcement to a new version of efax. Different setup of colours.
JED's screenshots
The author, JED, had these screenshots on his page on SLRN:
A look at news.software.readers with collapsed threads, ie the threads are not presented as trees, but in one line each with the number of articles
within given before the subject lines (in light blue):
A look at news.software.readers - but with "opened" (uncollapsed) threads, ie each thread is show as a small tree:
A look at an article within news.software.readers. Please note that the quoted text is presented in its own color (red):
Send feedback on this page to
Sven Guckes [email protected]
Sven [email protected] ©1995-2001 Last update: Mon Apr 16 06:45:00 MEST 2001
See also:
● http://appwatch.com/Linux/App/724/data.html
If you want to share your experience with using wget here then please send me an email!
In case you want to start an ftp or web mirror then please let me know. Just fill out the generic entry on
the vim distribution page so I can add you to the list of sites. Thank you! :-)
Some FAQs on Mirroring
[Space]
How much disk space is required to mirror www.vim.org?
Currently [981124] you need 620K for the Vim Pages (including the Vim HowTos), the same
amount for the compressed archive of HTMLized helptexts, and 1.5M for the rest, ie the
announcements, the old and new FAQ, some info on the ICCF and a few press articles on Vim,
some texts, and a few additional syntax and setup files. The VIM Pages are less than 500K; there
are these subdirs: announce/ faq/ howto/ iccf/ press/ syntax/ download/ faqnew/ html-5.3/ macros/
src/ txt/ Disk Usage and description: $ du ^[A-Z]*(/) 485 announce Announcements [does not
change much] 624 download just has an archive of the latest HTML docs 133 faq the last version of
the VIM FAQ 71 faqnew the new VIM FAQ (changing from time to time) 118 howto HowTos -
could change a lot 2491 html-5.3 the online docs in HTML 1 iccf about the ICCF (remember: Vim
is CharityWare) 1 macros macros - lots to come here still 14 press some articles on Vim that have
been printed 71 src setup files that can be "sourced" 187 syntax syntax files 385 txt some
non-HTML texts (todo files) So that's 2.5M for the HTMLized docs and 2M for the rest.
[Directories]
FTP Mirror: Please make vim available as "/pub/vim", too, by adding a symlink. Thanks! We are
trying to make it easy for people to find vim, and so far almost all mirrors have made it possible. :-)
WWW Mirror: I suggest the address "mirror/www.vim.org" if you mirror the Vim Pages from
www.vim.org. But this is entirely up to you, of course.
[Links]
A lot of links seem to be broken - why?
Many links point relatively to other of Sven's pages - so the mirrored pages will point to other
pages relatively, too. As mirror scripts do not copy all of Sven's pages, but only those with a path
ending in "vim", those links may not work. Sorry about that. [Is there a way to tell the web server to
change these links to the original site?]
[Duplicates]
Why does my mirror script get several copies of one page?
Please note that several pages have different URLs - short ones that are easy and fast to type, and
long URLs which are more descriptive. So before you mirror www.vim.org you should create the
symlinks so the mirror script knows that you already have a page. This speeds up mirroring
immensely as pages are retrieved only once.
URL: http://www.math.fu-berlin.de/~guckes/vim/howto/mirror.html
URL: http://www.vim.org/mirror.html (mirror)
Created: Sat Sep 05 00:00:00 CEST 1998
Send feedback on this page to
Sven Guckes [email protected]
URL: http://www.math.fu-berlin.de/~guckes/lynx/
Created: Fri Jul 28 00:00:00 MET 1995
Last update: Tue May 23 12:00:00 MET DST 2000
Latest version:
release: Lynx-2.8.3 [000423]
development: Lynx-2.8.4dev2 [000522]
HomePage: http://lynx.browser.org/
Distribution/Download:
DOS http://www.fdisk.com/doslynx/lynxport.htm
Unix ftp://www.slcc.edu/pub/lynx/current/
http://sol.slcc.edu/lynx/current/
1973412 Jan 28 09:31 lynx2.8.2dev.15.zip
1761637 Jan 28 09:31 lynx2.8.2dev.15.tar.gz
1408142 Jan 28 09:31 lynx2.8.2dev.15.tar.bz2
2702008 Jan 28 09:31 lynx2.8.2dev.15.tar.Z
LYNX Pages
LYNX is a "web browser", ie a program which connects to "world wide web servers", requests data from them and
interprets texts set in HTML (HyperText Markup Language).
Overview
NEWS | Features | Binaries | History | Problems
Sven's LYNX Pages:
| Distribution/Download (source and binaries) | Usenet/News | Other LYNX Pages
NEWS
Note: Do not mix this up with http://www.lynx.org/ - that one is taken by Lynx Technologies Inc in Ontario. [980420]
For now, please refer to the Subir Grewal's page at
http://www.crl.com/~subir/lynx.html
LYNX Mailing Lists
The normal posting address for lynx-dev is [email protected] . You need not be subscribed to post; if you post without
being subscribed you should check the archive at http://www.flora.org/lynx-dev/htlm/ for replies.
The LYNX Developer Mailing List
aka: lynx-dev
Email: [email protected]
[TODO]
LYNX Users
Some guys who frequently appear on the mailing list lynx-dev:
Al Gilman
Email: [email protected]
Author of the LYNX FAQ
Hiram W. Lester, Jr.
Email: [email protected]
WWW: http://pobox.com/~hwlester/
Larry W. Virden
Email: [email protected]
WWW: http://www.teraform.com/%7Elvirden/
Subir Grewal
Email: [email protected]
WWW: http://www.crl.com/~subir/lynx.html
LYNX FAQs
Here are some FAQs that I read about elsewhere.
mailcap
Q: Can I specify a different mailcap file other than "$HOME/.mailcap"?
A: LYNX looks at the mailcap file of the current directory, too, so you can use a customized mailcap file with
this workaround:
Change to a different directory, create ./.mailcap and start lynx.
Example:
#! /bin/sh
cat - > /tmp/L$$.html
lynx /tmp/L$$.html
exit 0
Printing on OpenVMS
Q: System info: OpenVMS-6.1 running Multinet 3.5 Rev.B., Lynx-2.6. "Everything appeared to have installed
properly, with no errors after I put the latest ".h" files in place. Lynx runs quite well, except for the ability to use
the (P)rint option. When selecting 'p' I get the message "Alert! Unable to open print option file."
A: On VMS the options for print and download are handled as temporary html files placed in sys$scratch. If you
haven't defined one, that would default to sys$login. If you have, could there be some protection problem
associated with it?
[961008]
Error message display duration
Q: How can I set the duration for showing error messages?
A: You cannot.
Problem: There is no way to set the timeout for error messages. This poses a problem for blind people who need
some time to read the error message.
Solutions: Option menu variable of type "number". A default value can be given via a config variable for lynxrc
(eg "errorduration"), a duration of zero would wait until the user presses a key. If a typeahead makes the message
go away then it should be possible to redisplay the last message with a command.
Reference: http://lynx.cc.ukans.edu/lynx-dev/9511/0019.html
LYNX - Development
[TODO]
Miscellaneous
Lynx-2.7.2 Online Help
URL: http://www.slcc.edu/lynx/release/lynx2-7-2/lynx_help/lynx_help_main.html
The most up-to-date online help pages about Lynx. [980202]
The Lynx Book (of Thanks)
URL: http://www.slcc.edu/lynx-book.html
Do you like Lynx? Do you want to say thanks to the author? Tell him!
[961011,980202]
Yahoo on Lynx
URL: http://www.yahoo.com/Computers_and_Internet/Software/Internet/World_Wide_Web/Browsers/Lynx/
Links to check
Lots to do here, still. :-/
http://www.sunbeach.net/personal/dhill/lynx/lynx-tips.html
http://www.cc.ukans.edu/lynx_help/Lynx_users_guide.html
http://www.fhi-berlin.mpg.de/amiga/alynx.html
http://world.std.com/~adamg/dehanced.html
http://world.std.com/~adamg/ugh.html
ftp://ftp2.cc.ukans.edu/pub/DosLynx/readme.htm
http://www.ukans.edu/about_lynx/about_lynx.html
http://www.wfbr.edu/dir/lynx/
http://lynx.cc.ukans.edu/lynx-dev/
http://WWW.Sasquatch.Com/~jddjeff/Internet/World_Wide_Web/lynx/lynx-learners/
http://www.abs.net/~mikebat/ode-to-lynx.html
http://Gridley.ACNS.Carleton.edu/~darbyt/lynx.html
http://cybercom.net/~ellen/lynx.htm
Send feedback on this page to
Sven Guckes [email protected]
URL: http://www.math.fu-berlin.de/~guckes/w3m/
Created: Sat Jan 01 00:00:00 MET 2000
Last update: Fri Feb 25 15:56:02 MET 2000
VI - Picture Gallery
Vi is a text editor. You cannot draw pictures with it as it does not give you visual feedback on colours. However, some vi clones have a
GUI (graphic user interface) and support for colour. Naturally, the layouts differ on various screens.
This pages has links to some screen shots to give you an idea on the design of those various clones.
Vi Pictures - Overview
icons and logos | [The Vi clones:] calvin | elvis | lemmy | MacElvis | nvi | stevie | vile | VIM | vip | xemacs viper | miscellaneous | Links |
What's New?
Title: "Vi"
Size: only 998 bytes!
Creator Sven Guckes [email protected]
Added 980130
Notes: GIF89a - despeckled, interlaced, and transparent background. Taken from the "vi" picture of Jim Kingdon
[email protected]
Title: "Vi"
Size: 9815 bytes
Creator Jim Kingdon [email protected]
Added: 980130
Notes: Taken from the picture of David Lee Heyman
Vi Clones Logos
Vile Icons
Elvis
The main distribution site for Elvis is:
ftp://ftp.cs.pdx.edu/pub/elvis/README.html
Creator: Steve Kirkendall [email protected]
Title: Elvis 2.0
Elvis 2.0 creates a separate top-level application window for each editor window. This example shows some C source being edited,
in the "syntax c" display mode. The stripe across the top of the window is a user-configurable toolbar. The red rectangle near the lower-left
corner is the cursor. In a real elvis window it flashes, and it changes shape to indicate the current mode (rectangle=command, bar=insert,
underscore=replace). The scrollbar is NOT a Motif scrollbar, but an incredible simulation.
MacElvis
"MacElvis on MacOS"
Creator: Alain Mellan [email protected] [970516]
Alain is working on a Macintosh port for elvis-2.1 right now.
Lemmy
Creator: [NAME] [email protected] [961004]
Title: Lemmy 1.0 with syntax highlighting
"This is a GIF of Lemmy version 1.0, with C/C++ highlighting. The menus across the top, provide options consistent with Windows
applications. The status bar at the bottom tells you the edit mode, current line/total lines and current column. Lastly, whether or not your
edits have been saved with a message indicating either New, Current or Modified."
Miscellaneous
TODO: Add the following pages to the appropriate section.
Title "XEmacs Viper Mode"
Size 14043 bytes
Creator Hrvoje Niksic
[email protected]
Added 961205?
Date [961126,961205]
Notes: "Viper" is a mode in XEmacs
that implements Vi. Buttons and color.
Title "GUI Emacs - Vi mode"
Size 14919 bytes
Creator raul segura acevedo [email protected]
Added 970605
Notes: raul says: "note gui emacs is not xemacs, this one is another program. note the banner in the left bottom saying "----Vi" where
normally it says "-----Emacs"."
URL: http://www.math.fu-berlin.de/~guckes/vi/pics.html
Created: Sat Jun 29 00:00:00 MET 1996
Send feedback on this page to
Sven Guckes [email protected]
VI-Editor.org - The VI Pages maintained by Sven Guckes
The VI Editor and its Clones [email protected]
©1995-2001 Last update: Fri Jun 15 01:08:43 MEST 2001
Vi Pages Overview
[News] [Answers] [Books] [Bugs] [Chart] [Clones and their Homepages] [Credits] [History] [Options] [Pics] [Quotes]
[Substitution Guide] [Tree]
This Page: What *is* VI? A Definition. | Documentation on VI | Vi Clones and Versions | Links to Other Pages about Vi
[such as Vi vs Emacs, Vi Folklore, Vi Stuff] and changes to this page
Feedback, please: Should the info in clones and documents be moved onto separate pages? Send me an email!
VI - A Definition
Vi is a Text Editor
[970812] What is Vi? Well, in short - Vi is an "editor", ie a program that allows to "edit" (making changes to) files. These
files usually are files containing "text" (ASCII 000-127). Hence VI is referred to as a "text editor", even though you can also
edit "binary files" (which include characters with the highest bit set, ie characASCII 128-255).
Vi Clones
Vi has been a standard editor on Unix systems for many years now. Now there are several programs which incorporate the
command structure of this editor and which all add features that you probably have wanted with Vi all along; these are the
"clones".
POSIX
There is also a definiton by the "POSIX standard", but many programs which claim to be "vi" are "clones" which more or less
do standard Vi (whatever that is). Usually vi clones come with lots of (non-compatible) add-ons, but which usually are an
improvement.
As ex/vi is part of the POSIX 1003.2 specification for shell utilities, you can say they are "standard" in more that just a
colloquial sense.
Development History
In article in the Linux Magazine, November 1999 Bill Joy says that vi evolved from the editor "ed", then via "em" to "ex" and
"you've got to remember that I was trying to make it usable over a 300 baud modem. That's also the reason you have all these
funny commands. [...] So the editor was optimized so that you could edit and feel productive when it was painting slower than
you could think."
Bill Joy then added the code that changed the editor "ex" to "vi". (You can still switch from vi to ex with the command "Q",
and back again with command "vi". Try it!)
Terminology
Due to the non-compatibility of the various vi clones I will try to maintain the following terminology throughout these pages
and also when posting info to newsgroups, especially "comp.editors":
Please send corrections and additional info about these pages to me at [email protected]. Thanks! :-)
Vi Clones and Versions
So - which Vi clones are there? Here are some of the popular ones:
BBStevie | bedit | Bvi | calvin | e3 | elvis | elwin | javi | jvi | lemmy | levee | nvi | MKS vi [todo] | OakHill vi | PC-Vile | PVIC |
stevie | trived | tvi | vigor | vile | VIM | vip | viper | vipw(?) | Watcom-VI | WinVi | xvi
FAQ:
Q: Is there a vi clone for my operating system? A: Take a look at this table [yes, lots TODO here]:
❍ 990209: Contacted Roy and the maillist for more info - but the mails bounced.
bedit [971222]
OS: ???
Cost: ???
Author/Copyright: NAME MAIL
SnailMail: ??? ???
Home Page: ???
FAQ: ???
Download: ???
Maillist: ???
Last release: VERSION [DATE]
Last beta: VERSION [DATE]
Comments: [NAME EMAIL DATE]
Info by: George Young [email protected]
Source: http://www.winsite.com/info/pc/win3/util/bedit23.zip
Bvi [990223,990304,991001,001025,010116]
OS: DOS and Unix. Bvi-1.1 was tested on MSDOS with TurboC-2.0 and Borland-C++-3.1, as well as on these Unixes:
Linux, SunOS 4.1.x, Solaris 2.x with gcc compiler, HP-UX 9, OSF/1 V2.1.
Cost: free (I suppose)
Author/Copyright: Gerhard Bürgmann [email protected] (Vienna, Austria)
Home Page: http://bvi.sourceforge.net/ [010116]
http://bvi.linuxave.net [obsolete]
Download: http://bvi.sourceforge.net/download.html
Improved manual: http://www.math.fu-berlin.de/~guckes/bvi/manual.html
Mailing List: http://www.egroups.com/group/bvi
Latest version: See BVI info on AppWatch.com
Comments: Bvi is actually not a quite a vi clone as it does not deal with "texts" but "binaries". From the announcement:
"Bvi is a display-oriented editor for binary files based on the vi texteditor. It uses commands similar to the commands
of the vi, with some changes dependent of their different tasks."
calvin [970926,980918,001206]
OS: DOS only.
Cost: free
Author/Copyright: Paul Vojta [email protected]
Contact: Nan-shan Chen [email protected]
SnailMail:
Steve Kirkendall
14407 SW Teal Blvd. Apt. C
Beaverton, OR 97005
(503) 643-6980
Home Page: http://www.fh-wedel.de/elvis/ [981208] by [email protected]
Download:
Download Elvis Releases:
ftp://ftp.cs.pdx.edu/pub/elvis/
Download Elvis Beta:
ftp://ftp.cs.pdx.edu/pub/elvis/unreleased/README.html
ftp://ftp.false.com/pub/elvis/unreleased/README.html (mirror)
Last release: VERSION [DATE]
Last beta: elvis-2.1_4 [991210]
* The OS/2 port has been merged into 2.1i. Binaries are available.
* Error messages can be logged to a file.
* Problems with regular expression character lists have been fixed.
Comments: [Steve Kirkendall [email protected] 971002] "elvis-2.0 has a *real* X interface which uses the mouse
a lot better. Also, if you force it to run inside an xterm it won't attempt to intercept mouse events. [...] As compared to
2.0, 2.1e-alpha adds support for overloaded tags (useful for C++ programmers), a configurable toolbar under X, and the
ability to read via HTTP, and read/write via FTP. Plus bug fixes and a lot of other little changes, of course. [...] elvis is
updated about once every 4-6 weeks."
Elvis is the standard vi clone on Linux Slackware distribution.
JaeSub Hong's [email protected] page on Elvis:
http://www.phys.columbia.edu/~flame/elvis/ [981019]
Screenshots and some helpful info.
elwin [970919,000113,001127]
OS: Windows (95/98/NT)
Cost: shareware (trial period: 30 days), $50
Author/Copyright:
Little Wing
4618 JFK Boulevard, Suite 176
North Little Rock, AR 72116
TEL (501) 771-2408
[email protected]
Home Page: http://www.little-wing.com/
Latest releases:
james jensen
p.o. box 811452
boca raton, fl 33481
TEL +1 407 362 7997
Home Page: none http://www.emi.net/~jjensen/java/javi.html [defunct?]
Last release: 960814
jVi [010108]
OS: ???
Cost: ???
Author/Copyright: Mozilla Public License
SnailMail: ???
Home Page: http://jvi.sourceforge.net/
FAQ: URL
Download: http://jvi.sourceforge.net/jvi-main.html#Download
Last release: VERSION [DATE]
Last beta: VERSION [DATE]
Comments: jVi is an IDE running in Java - and it is based on Vim (Vi Improved). -- "Vi is a vi-vim editor clone built
on top of the javax.swing.text package. Available embeddings: JBuilder. jVi is designed to quickly and easily integrate
into many disparate java based desktop apps, from IDE's to mail-news readers." -- "jVi is patterned after vim. [...] jVi is
a small subset of vim. Some source code in jVi is taken from vim and modified to work in the java environment. The
user documentation is almost exclusively from vim, only modified to remove things that are not applicable."
Lemmy [970914,970926,000113,001121]
OS: Windows 32bit (Windows95, Windows98, WindowsNT)
Cost: Shareware - 30 day trial.
Pricing
Prices for Lemmy v4.2 are as follows:
* Single-user: $20
* 2 to 9 users: $15 each
* 10 to 24 users: $12 each
* 25 to 49 users: $9.50 each
* 50 to 99 users: $7 each
* 100+ users: $5 each
An unlimited site-license costs $500.
[Benefits of registration include: Free product upgrades. Removal of all nag screens.]
Distributor: SoftwareOnline
Lemmy is now owned by SoftwareOnline:
Home Page/Announcement:
http://www.softwareonline.org/lemmy42.html
This site has links to the Frequently asked questions, Sample VB Scripts, and Additional Syntax Highlighters.
FAQ: http://www.softwareonline.org/lemmyfaq.htm
Download: http://www.softwareonline.org/lemmy30.exe
Lastest release: Lemmy-4.2 [??????]
OLD URLs:
http://www.accessone.com/~jai/
http://www.accessone.com/~jai/faq.html
ftp://ftp.accessone.com/pub/misc/jai/
http://www.drizzle.com/~james/lemmy.html
Original Author:
David G. Leeper
Oak Hill Software, Inc (member ASP)
8603 E Corrine Dr
Scottsdale, AZ 85260
602-998-4974
Support Email: [email protected]
Home Page: http://home.att.net/~leeperd/ohvimain.html
FAQ: URL
Download: http://home.att.net/~leeperd/dwnld01.html
Last release: "Oak Hill Vi 7.0A" [980111]
Last beta: VERSION [DATE]
INFO by: David Douthitt [email protected]
PVIC [980504,980511,000713,001031]
OS: DOS, OS9
Cost: PVIC is public domain.
Author/Copyright: Frits Wiarda [email protected]
SnailMail:
Frits Wiarda
Boulevard Heuvelink 1-5
6828 KG Arnhem
Holland
Home Page: http://www.fwiarda.com/software.htm#pvic
http://ourworld.compuserve.com/homepages/fwiarda/software.htm#pvic [obsolete]
FAQ: none
Maillist: none
Last release: Pvic [980424] (date stamp on binary)
Last beta: Frits Wiarda doesn't have time to maintain PVIC - so no further development is planned for now.
Comments: Frits Wiarda says on the homepage: "PVIC is a Portable VI Clone derived from STEVIE 3.69B ... and did
contain many non portable things like BIOS calls. I have removed everything [...] I considered non-portable, and I did
rewrite the I/O. I added code to read termcap files. I gave many variables and functions [...] more understandable
names. It has been written in Kernighan and Ritchie C, so it compiles on both old and modern C compilers."
[980509] Frits Wiarda : "All information I have about PVIC is in the .ZIP file one can download. Documentation I do
not have, but there are plenty of comments in the source code." He also says that he wrote PVIC some five years ago
when he was in need for a vi clone for OS-9.
trived [970927,990223]
OS: DOS only.
Cost: Free
Author/Copyright: Russell Schulz [email protected]
SnailMail: N/A
Home Page: none?
FAQ: none
Download: ftp://ftp.simtel.net/simtelnet/msdos/editor/trived09.zip
Maillist: none
Last release: trived-0.9 [950425]
Comments: Trived is NOT a vi clone, but has a small vi subset. Trived has on-screen help like pico and has automatic
uuencoding of binary files (with command ":r"). The archive includes the Pascal source. Trived thus probably is the
only vi-like editor in Pascal. [slightly reworded statement by Russell Schulz]
Comments: The archive comes with an executable and Pascal source. The editor is designed as a vi clone with small
memory requirements for use locally or on a BBS. The name of the archive is "TRIVED*.ZIP". [David Douthitt
[email protected] 970926]
tvi [970926]
OS: Windows 3.1 The editor "tvi" emulates vi with a subset of vi commands.
Cost: Shareware - US:$10, Non-US:$20
Author/Copyright:
Michael Edelstein
EMAIL?
SnailMail:
Michael Edelstein
3276 Ashford Street #D
San Diego, CA 92111
Home Page: URL
FAQ: URL
Download: URL
Last release: VERSION [DATE]
Last beta: VERSION [DATE]
Comments: The tvi editor does not use the Windows environment to any advantage, and does not appear to implement
as much of vi as other clones do. Definitely a minimalist version. Not sure why you would want to use this software
when you can register Lemmy or Elwin for just a little bit more or get VIM or xvi for nothing at all. [David Douthitt
[email protected] 970926]
[email protected] announcements
[email protected] developers
[email protected] users
Last release: vile-9.1y [001005]
Comments:
PC-Vile was created from the source of micro-emacs(!) - programmed by a lot of people. Paul Fox [email protected]
is NOT the Paul Fox who did the CRiSP editor... [David Douthitt [email protected] 970926]
There is also a maillist for bug reports which does not require subscription - but Paul Fox asked me to remove this
address for now due to spams. :-/
The official homepage does not show the latest version. This *sucks*. Therefore
William Totten's vile page
http://www.cis.udel.edu/~totten/vile/
Alex Wetmore's cfilt.pl
http://www.phred.org/~alex/vile/cfilt.pl
Colorizes the Perl hooks within Vile.
The Freshmeat vile appindex record
http://appindex.freshmeat.net/view/901503901/
Linux Gazette story on vile http://www.redhat.com/linux-info/lg/issue01to08/xvile_mar96.html
A page about Vile in Czech
http://www.cestina.cz/cestina/pocestovani/unix/Vile/
vim (aka "Vi IMproved") [970919,980624]
OS: "All" (well, almost ;-)
AmigaOS, AtariMiNT, BeOS, DOS, MacOS, OS/2, RiscOS, VMS, WinNT+Win95, and these flavors of Unix: A/UX,
AIX, DG/UX, DEC Unix, FreeBSD, HP-UX, Irix, Linux, NetBSD, QNX, SCO, Sinix, Solaris, SunOS, SUPER-UX,
Ultrix, Unisys.
Cost: "Free". Actually it is "CharityWare", ie the author encourages making a contribution to charity.
Author/Copyright: Bram Moolenaar [email protected]
SnailMail/Phone:
Bram Moolenaar
Clematisstraat 30
5925 BE Venlo
The Netherlands
Tel: +31 77 3872340
Home Page: http://www.vim.org/ (maintained by Sven Guckes [email protected]
FAQ: http://www.vim.org/faq/
Download: http://www.vim.org/dist.html
Latest versions: See the Vim History Page or the Vim HomePage.
Mailing Lists: http://www.vim.org/mail.html - four maillists: announcements, general questions, general development,
development of MacOS port.
Description: Vim (Vi IMproved) is an almost compatible version of the UNIX editor vi. Almost, because in many ways
it chooses to improve it and do away with bugs. If you know vi then you will only want to know the differences which
are described in the vim helpfile "vim_diff.txt" and on the page about Why use Vim?.
Note: VIM is now the standard vi clone on the Linux RedHat distribution.
Watcom-VI [990625,990701]
OS: DOS, Win3, Win95, Win98?, WinNT
Cost: Watcom-VI shipped with the Watcom Compiler.
Author/Copyright:
:ver
"vi/nt" v1.0 12:24:27 Aug 16 1994
Comments: "The NT versions run in both the GUI or as a console mode app. The Dos version works great in a DOS
box but unfortunately only supports short file names." "The Watcom VI also has scripting support and a text-based
GUI which can be modified by the user and compiled into the .EXE file. You can change key commands, menus,
scripts, etc" Info by Michael S. Leibow [email protected] [990625, 990629]
Known Bugs: Some commands operate incorrectly as the calculation on the operated text expanded tabs but forgets
that tabs are just a single character.
WinVi [980407,990729,001024]
OS: Windows 32bit (Windows95/98/00/NT)
Cost: "Freeware"
Author/Copyright:
VI Documentation
There are quite a number of documents about Vi. (I will add the URLs asap.) However, you may not yet know about these:
Vi and Programming
Introduction to Programming in C/C++ with Vim [010615]
http://www.linuxnewbie.org/nhf/intel/programming/intro_c++.html
Author: Kmj [email protected]
Vi Documentation in Finnish
[Finnish] Perusohje vi-editorin käyttöön [000918]
http://www.helsinki.fi/%7Erista/tekstit/vi-opas.html
Basic instruction for using of vi - a Vi start guide written in Finnish.
Author: Aapo Rista [email protected]
[Finnish] Vi [000922]
http://www.hit.fi/%7Elehtonen/Unix/unix26.htm
Author: Kari Lehtonen [email protected] (1997) http://www.hit.fi/%7Elehtonen/
[Finnish] [Text] VI-EDITORI [000922]
http://www.cs.joensuu.fi/pages/amanuenssi/computing_facilities/Ohjelmat-CS/vi/vi.html
Author: ??? Last updated: October 1996
Vi Documentation in French
[960822]
[French] Vi Guide (PostScript, gzip)
doc/vi.guide.french.tex.ps.gz (35K -> 85K)
A Vi starter guide written in French.
Author: Charles Vidal [email protected]
Vi Documentation in Deutsch/German
VI-Einfuehrung und Kurzreferenz [981102]
[Deutsch,German] [HTML]
http://www.fh-wedel.de/~herbert/html/vi/
A short intro to editing with Vi - in German.
Author: Martin "Herbert" Dietze [email protected]
Der vi-Editor - ein mächtiger Zwerg (German) [000901]
[Deutsch,German] [HTML]
http://lug-dd.schlittermann.de/vortraege/vi-report_html/
Author: Marcus Obst [email protected] [000115,010312]
Slides (in MagicPoint) for a talk about vi - in German. created for the Linux User Group in Dresden, Germany.
Textverarbeitung mit dem Editor vi" [990223]
[Deutsch,German] [HTML]
http://www.delix.de/Linux/handbuch/node140.html
A description of the editor vi - in German. Last updated in November 1995.
Author: Delix sysadmins?!
Editor vi [990223]
[Deutsch,German] [HTML]
http://www.we.fh-osnabrueck.de/fbwe/vorlesung/edv1/unix/node18.html
A description of the editor vi - in German. Last updated in December 1995.
Vi Documentation in Greek
Vi explained [961029]
[Greek] [HTML]
http://www.edu.physics.uch.gr/~danalis/manuals/vi/vi_front.html
If you prefer to read about Vi in Greek - there you are!
Author: Anthony G. Danalis [email protected] http://www.edu.physics.uch.gr/~danalis/
Vi Documentation in Swedish
Vi Tutorial [991208]
[Swedish] [HTML]
http://www.mds.mdh.se/support/howto/vi.html
Author: [email protected]
[971009]
[English] Vi Macros, Abbreviations, and Buffers
http://soma.npa.uiuc.edu/docs/vi.macros
Author: Fred Buck (1988), additions by Maarten Litmaath [email protected] (1989)
The escape filter, test abbreviation, keystroke remapping (test mode, command mode), text-buffer execution;
mode-bouncing, chained macros, recursive macros, termination of recursives macros, peculiar limitations and
restrictions on 'vi' macros; putting and yanking to/from named buffers; remappable keys (Which keys to remap?).
An Extremely Quick and Simple Introduction to the Vi Text Editor [991112]
http://heather.cs.ucdavis.edu/~matloff/UnixAndC/Editors/ViIntro.html
Author: Norm Matloff [email protected]
Per's Vi Tutorial [980114]
http://www.dina.kvl.dk/~abraham/religion/vi-tutorial.html
Author: Per Abrahamsen [email protected]
Rather than a Vi Tutorial this shows how hard learning Vi commands can be. Or maybe it is to show why people have
written vi clones that improve the movement of the cursor.
Viper Tutorial [990223]
http://linux01.gwdg.de/susehilf/gnu/viper/Top.html
"Viper is a Vi emulation package for GNU Emacs 19 and XEmacs 19."
Online Documentation (non-HTML) - local
An Introduction to Display Editing with Vi [971008]
http://www.de.freebsd.org/de/doc/usd/12.vi/paper.html
Authors: William Joy and Mark Horton
*The* text about Vi - written by the authors.
"vi is small, fast, and easy to use. Emacs is huge, slow and easy to use :)"
From: [email protected] (Scott McMahan - Softbase Systems)
Emacsculation [980723]
http://www.rru.com/~meo/rants/emacs.html
A small rant on Emacs by a Vi user.
Author: Miles O'Neal [email protected]
"A naïve comparison of computer text editors" [970107]
http://www.pobox.com/~drj/comped.html
Test on emacs, vi, and ed for changing all colons to pipes in a password file. Result:
Vi Folklore
Twenty Years of Berkeley Unix [001010]
From AT&T-Owned to Freely Redistributable
http://www.oreilly.com/catalog/opensources/book/kirkmck.html
"With the arrival of some ADM-3a terminals offering screen-addressable cursors, Joy was finally able to write vi,
bringing screen-based editing to Berkeley."
Author: Marshall Kirk McKusick
A chapter taken from the book Open Sources: Voices from the Open Source Revolution .
Addicted to Vi
Local copy
http://web.hal.com/users/carolo/jokes/vi.html
New text to the song "Addicted to Love" (by Robert Palmer)
Quines [970630,990202]
Q: What is a quine?
A: "a series of vi keystrokes that when typed in vi produce output the same as the keystrokes."
Example: ii^V^V^V^[BDuplxbbpp^[BDuplxbbpp
Author: Rodney [email protected]
I am pretty sure the author is looking for more quines - especially shorter ones.
More Quines: http://www.nyx.net/~gthompso/quine.htm [990202]
The Cult of Vi
http://www.splange.freeserve.co.uk/misc/vi.html
Vi is a cult. (What else is new?)
VI Stuff
MousePads, Mugs and Tshirts
DATE ITEM ADDRESS
001207 VI Mousepads http://www.linuxland.de/katalog/21_fanartikel/vimousepad/framify
http://www.geekcheat.com
990114 VI Mugs
http://www.vireference.com/vimug.htm
001014 VI Tshirts http://www.thinkgeek.com/stuff/vi-emacs.html
Actually, there are two versions - a Vi tshirt and an
Emacs tshirt. The idea is this: A cartoon showing a boy
[why are we
hiding daddy?] asking "why are we hiding from the police, daddy?",
and his dad answers "because we are using emacs/vi
son - and they use vi/emacs".
Disclaimer: I don't do business with any of them.
Outlook/TODO
crevier.org - vi Editor Resources [001004]
http://www.webmaster.crevier.org/depere.wi/vi/
LOGO: http://www.webmaster.crevier.org/imgx/logo/unixvi.gif [Powered by
Editing Scheme files in Vi [001004] UNIX vi]
http://www.cs.rice.edu/~dorai/scmindent/scmindent.html
Author: Dorai Sitaram [email protected] http://www.cs.rice.edu/~dorai
More About vi [001004,010113]
http://dunne.home.dhs.org/vi.html
http://dunne.home.dhs.org/articles/review.learning_the_vi_editor.html
obsolete:
http://members.linuxstart.com/~dunne/vi.html
http://members.linuxstart.com/~dunne/articles/review.learning_the_vi_editor.html
Author: Paul Dunne [email protected]
cvi [TODO]
"Chinese VI"
Info on its exitence was given by Steve Bao [email protected] [000428]
stevie [DATE] [TODO]
OS: [OS/2]
Cost: ???
Author/Copyright: NAME MAIL
SnailMail: ???
Home Page: URL
FAQ: URL
Download: URL
Maillist: ADDRESS
Last release: VERSION [DATE]
Last beta: VERSION [DATE]
Comments: [NAME EMAIL DATE]
vip [TODO]
Hex Editors for Linux [000317]
http://spin.ch/~tpo/linux/hexeds.html
beav, bed, bvi, elvis, fb, fm, ghex, hexdump, hexed, hexedit, hexer, hextype, khexedit, le, lde, mcedit, ncurses hexedit,
vche, and xvi.
Vide - a GUI file browser with vi commands [000309]
HomePage: http://vide.sourceforge.net/
Description (official): Vide is a simple filemanager with vi keybindings. If you already use vim, Vide enables you to
have complete keyboard control over your filemanager without having to learn a new set of commands.·
Description (unofficial): A GUI file browser with vi keybindings: Movements with "hjkl" as well as 'g' adn 'G',
scrolling with CTRL-B and CTRL-F, and vi command line interface [:d, :co, :move, :quit, :shell]
Screenshot: http://vide.sourceforge.net/picture.html
Download: http://vide.sourceforge.net/download.html
Requires: GTK+ (1.2 with threads support), and Vim.
Contact: [email protected]
Planned features: Number prefix for commands, selection in "visual mode", configurable key bindings and menus.
Comments: Why does it need a GUI?
POSIX on ex and vi
http://www.pasc.org/interps/unofficial/db/p1003.2
http://www.UNIX-systems.org/onlinepubs/007908799/xcu/ex.html [010320]
http://www.UNIX-systems.org/onlinepubs/007908799/xcu/vi.html [010320]
Add info about POSIX description of vi commands to the comparison page about the "options".
Vi emulation in CRiSP [990712]
The editor CRiSP (commercial follow-up to the editor BRIEF) has a "vi emulation mode". Anyone using this?
Feedback, please!
Have sent email to Bryan Althaus [email protected] who is apparently using this. [990712]
Vi for Japanese - a list of ported clones. [980430]
http://www.vector.co.jp/vpack/filearea/dos/writing/edit/vi/
Premia CodeWrite - vi emulation
Doug Kellogg [980417] is using it: "It is up to version 5.1 and is published by Premia in Portland, Oregon, USA
(www.premia.com) and is descended from the Sage Programmers Editor (SPE) from what was Polytron and is now
Sage, also of Portland."
Charlie Guttenberg [email protected] informed me [980414]: "Codewright is a programmer's editor made by
the Premia Corp. Besides basic editing, it can tie into whatever sccs and build environments you may have. The version
we have, V3.1e (1995), supports emulation of four editors: CUA, Epsilon, Brief, and good old vi."
Prepare Codewright HomePage: http://www.premia.com/
SpexEdit
Marketed by "Little Wing": Little Wing / 4618 JFK Blvd, Suite 176 / North Little Rock, Arkansas 72116 /
(501)771-2408
Supports most of vi commands. Free demo disk available.
Vi-Editor.org Buttons
Some buttons for your own page on Vi:
Vi-Editor.org Mirrors
These pages are mirrored at these sites:
HomeSite: [home]
Mirrors: [DE] [ZA]
Do you want to mirror these pages?
Be my guest!
--·
Sven Guckes [email protected]
"The wonderful thing about Tiggers [excerpt of "Tigger's Song" in
Is Tiggers are wonderful chaps "Winnie the Pooh and Tigger Too"]
They're loaded with vim and with vigor..."
Sven [email protected] ©1995-2001 Last update: Mon Jan 22 03:00:00 MET 2001
:[range]s[ubstitute]/pattern/string/[options]
Note: The separator between 's' and the pattern is the same as between pattern and string and string must always be
terminated with it. However, you can chose the character. It does not need be the slash - it can also be the hash ('#'):
:[range]s[ubstitute]#pattern#string#[options]
The substitute command consists of nine parts. You need not give all nine parameters - parameters in square brackets are
optional, ie they are not required. However, the command name 's' and the separator around the pattern are always
required. So the shortest substitute command is ":s///". It will be explained below (unless I forget ;-). With VIM there are
three abbreviations, namely ":&", ":~", and '&' (see ":help :&", ":help :~", and ":help &").
Each may be followed (several times) by '+' or '-' and an optional number.
This number is added or subtracted from the preceding line number. If the
number is omitted, 1 is used.
The "/" and "?" may be preceded with another address. The search starts from
there. The "/" and "?" after {pattern} are required to separate the pattern
from anything that follows.
The {number} must be between 0 and the number of lines in the file. A 0 is
interpreted as a 1, except with the commands tag, pop and read.
Examples:
.+3 three lines below the cursor
/that/+1 the line below the next line containing "that"
.,$ from current line until end of file
0;/that the first line containing "that"
Some commands allow for a count after the command. This count is used as the
number of lines to be used, starting with the line given in the last line
specifier (the default is the cursor line). The commands that accept a count
are the ones that use a range but do not have a file name argument (because
a file name can also be a number).
Examples:
:s/x/X/g 5 substitute 'x' by 'X' in the current line and four
following lines
:23d 4 delete lines 23, 24, 25 and 26
A range should have the lower line number first. If this is not the case, Vim
will ask you if it should swap the line numbers. This is not done within the
global command ":g".
Well, I do hope that this is clear to you. If not - ask me!
Part 2 s[ubstitute] - The command name.
The second part is the name of the command. As you can abbreviate every command with Vi with its unique prefix
the "ubstitute" is optional, so you need not type the full name, but only an 's'. However, the 's' is required.
Part 3 - The "separator" (usually '/' or '#')
The "separator" is a character which seperates the command name from the pattern, seperates the pattern from the
substitution string, and the substitution string from the options. You can chose any(?) character as a separator, but
usually the slash (/) is used. When substitutions contain the slash as a literal character you should chose some other
character that is not contained in the pattern or substitutions string. And if this is not possible then you have to
"escape" it with a backslash (\): ":s/\/path\/filename/\/newpath\/newfilename/"
Part 4 - The pattern
A pattern is a complex construct. There is no general definition of "pattern", however; it differs depending on its
use. Here we ar using a "search pattern", so VIM4.5 will give this text with ":help search_pattern": The definition of
a pattern: *search_pattern* Patterns may contain special characters, depending on the setting of the 'magic' option.
*/bar* */\bar* 1. A pattern is one or more branches, separated by "\|". It matches anything that matches one of the
branches. Example: "foo\|beep" matches "foo" and "beep". 2. A branch is one or more pieces, concatenated. It
matches a match for the first, followed by a match for the second, etc. Example: "foo[0-9]beep", first match "foo",
then a digit and then "beep". 3. A piece is an atom, possibly followed by: magic nomagic */star* */\star* * \*
matches 0 or more of the preceding atom */\+* \+ \+ matches 1 or more of the preceding atom {not in Vi} */\=* \=
\= matches 0 or 1 of the preceding atom {not in Vi} Examples: .* .\* matches anything, also empty string ^.\+$ ^.\+$
matches any non-empty line foo\= foo\= matches "fo" and "foo" 4. An atom can be: - One of these five: magic
nomagic ^ ^ at beginning of pattern, matches start of line */^* $ $ at end of pattern or in front of "\|", */$* matches
end of line . \. matches any single character */.* */\.* \< \< matches the beginning of a word */\<* \> \> matches the
end of a word */\>* \i \i matches any identifier character (see */\i* 'isident' option) {not in Vi} \I \I like "\i", but
excluding digits {not in Vi} */\I* \k \k matches any keyword character (see */\k* 'iskeyword' option) {not in Vi} \K
\K like "\k", but excluding digits {not in Vi} */\K* \f \f matches any file name character (see */\f* 'isfname' option)
{not in Vi} \F \F like "\f", but excluding digits {not in Vi} */\F* \p \p matches any printable character (see */\p*
'isprint' option) {not in Vi} \P \P like "\p", but excluding digits {not in Vi} */\P* \e \e <Esc> */\e* \t \t <Tab> */\t* \r
\r <CR> */\r* \b \b <BS> */\b* ~ \~ matches the last given substitute string */~* */\~* \(\) \(\) A pattern enclosed by
escaped parentheses */\(\)* (e.g., "\(^a\)") matches that pattern x x A single character, with no special meaning,
matches itself \x \x A backslash followed by a single character, */\* with no special meaning, matches the single
character [] \[] A range. This is a sequence of characters */[]* enclosed in "[]" or "\[]". It matches any */\[]* single
character from the sequence. If the sequence begins with "^", it matches any single character NOT in the sequence.
If two characters in the sequence are separated by '-', this is shorthand for the full list of ASCII characters between
them. E.g., "[0-9]" matches any decimal digit. To include a literal "]" in the sequence, make it the first character
(following a possible "^"). E.g., "[]xyz]" or "[^]xyz]". To include a literal '-', make it the first or last character. If the
'ignorecase' option is on, the case of letters is ignored. It is impossible to have a pattern that contains a line break.
Examples: ^beep( Probably the start of the C function "beep". [a-zA-Z]$ Any alphabetic character at the end of a
line. \<\I\i or \(^\|[^a-zA-Z0-9_]\)[a-zA-Z_]\+[a-zA-Z0-9_]* A C identifier (will stop in front of it). \(\.$\|\. \) A
period followed by end-of-line or a space. Note that "\(\. \|\.$\)" does not do the same, because '$' is not end-of-line
in front of '\)'. This was done to remain Vi-compatible. [.!?][])"']*\($\|[ ]\) A search pattern that finds the end of a
sentence, with almost the same definition as the ")" command. Technical detail: <Nul> characters in the file are
stored as <NL> in memory. In the display they are shown as "^@". The translation is done when reading and writing
files. To match a <Nul> with a search pattern you can just enter CTRL-@ or "CTRL-V 000". This is probably just
what you expect. Internally the character is replaced with a <NL> in the search pattern. What is unusual is that
typing CTRL-V CTRL-J also inserts a <NL>, thus also searches for a <Nul> in the file. {Vi cannot handle <Nul>
characters in the file at all} Now, this is pretty complex, isn't it? [todo: examples]
Part 5 - The separator (again)
This separator must be the same character as the separator used before.
Part 6 - The "substitution string"
The substitution string also has meta characters, but not as many as the "pattern" used before.
Part 7 - The separator (again)
This separator must be the same character as the separator used before.
Part 8
Part
/
: Part three: The separator. The slash seperates the command name from the following pattern. It need not be a slash, a
hash ('#') will do, too. But then you will have to use a hash at the end of the pattern and after the substitution string, too.
For now we will just use the slash.
{pattern}
:s/vi/VIM/
Substitute the first occurrence of "vi" with "VIM" on the current line.
More examples
Command: :.,.+7s/^/foo/
Read command as: from "this line" to "this line plus seven lines" substitute "^" (beginning of the current line) with "foo".
Informal Description: Add "foo" this and the follwoing seven lines. Remember: The address '.' refers to current line, but it
can be left out. So the previous command can be shortened to: :,+7s/^/foo/
Mark them!
Before you apply a substitution command on some lines you usually have to figure out which lines these are so you can
use their addresses in the command, eg:
:23,42s/foo/bar/
But how do you find theat the first line is #23 and that the last line is line #42? You probably have to move the cursor a lot
and also write down the number on a piece of paper.
However, there is an easier way: Set a mark on those lines.
Setting a mark is done with the command 'm' followed by any (lowercase) letter, ie from 'a' to 'z'. The current line then is
"marked" with that letter.
So, set a mark when the cursor is on the first line of the text to be operated on, and set another when the cursor is on the
last line. For examples, we usually use the marks 'a' and 'b' for the first and last line, respectively. So the substitution starts
on line (marked with) 'a' and it will end on the line (marked with) 'b'.
Now you can reference these addresses with 'a and 'b in the substitution command:
:'a,'bs/foo/bar/
So - no more writing down line numbers. Good.
But this method still means to move the cursor onto those lines to set a mark on them.
VIM examples
Visual mode -> line range
I almost never want to figure out the exact line range to apply a substitution on, and that's why I use Vim's visual
mode and then the operator ':'. You just select a range of lines using the comamnd 'V' and move to the last line. Then
you type ':' and Vim will switch to the command line, inserting "'<,'>" as the line range. These marks stand for "first
visual line" and "last visual line", respectively. Now you can type in the substitution command:
:'<,'>s/Vi/Vim/g
Or any other command for that matter:
:'<,'>d
But, of course, this deletion command would have been easier by using the 'd' operator in visual mode right away. ;-)
URL: http://www.math.fu-berlin.de/~guckes/vi/substitute.html
Created: Mon Oct 21 19:39:13 CEST 1996
Send feedback on this page to
Sven Guckes [email protected]
LINUX MAGAZINE • subscribe • advertise • customer service • back issues • feedback • contacts
search
Newsletter
Enter email address:
Linux Magazine / June 2000 / FEATURES
sign up feedback
Linux Magazine's 100 Best Linux Web Sites
mail to a friend
Sections
printer-friendly version
Newbies << prev page 1 2 3 4 5 6 7 8 9 10 11 next >>
Reviews
Interviews
How To Linux Documentation Project
Best Defense
http://www.linuxdoc.org/
Guru Guidance
On The Desktop The granddaddy of all Linux doc sites, the LDP has
been hosting FAQs, man pages, HOWTOs, and
Developer's Den
Linux Guides for a long time. The LDP boasts a
Gearheads Only substantial collection of Linux information in a variety of formats. The HOWTOs
Compile Time on this site are the definitive place to start for any Linux problem you may be
trying to troubleshoot. The LDP recently got a facelift and has experienced a
Perl of Wisdom resurgence, thanks to some new blood.
Who's Who Open Source Writer's Group
Downloads
http://www.oswg.org:8080/oswg
Formed last year by Deb Richardson of LinuxChix fame, the Open Source
Indexes Writer's Group is a gathering place for open source authors to hook up with open
Issue Archive source projects.
Author Index Linux Resources
http://www2.linuxjournal.com/cgi-bin/frames.pl/lr-toc.html
On Stands Now
Linux Journal provides an excellent resource site for the Linux newbie and guru
alike. Find out all about what Linux is -- and where you can get it, meet other
people who use it, and read more about it.
What good is free software if you don't know how to use it? Happily, the
wonderful folks with the GNU Project have provided a comprehensive section of
documentation for Emacs Lisp, GNU C, using the GDB debugger, and a whole lot
more. If you're in a philosophical mood you can read Richard Stallman's essay on
Free Software and Free Manuals. (Here's a hint: he's for them.)
Linux Magazine Get a handle on the editor that strikes fear into the heart of newbies everywhere,
Vim. Vim is the most popular vi clone for Linux, and the Vim homepage has tons
Subscribe of information on using Vim and how to customize it.
Advertise
Customer Service
Back Issues
Themes.org
Feedback
http://www.themes.org
Contacts
Wanna make X purty? Hook up with the folks at
Themes. org. They've got the stash of themes
and utilities for the most popular desktops and window managers. All the goodies
you've ever wanted to dress up your desktop, as well as X resources and news
updates on window managers and other popular packages. Themes.org has
sections for SawMill, Afterstep, Enlightenment, WindowMaker, KDE, and a lot
more.
KDE Home
http://www.kde.org
KDE's home page is the place to go to get any information about developing for
the K Desktop Environment, or simply to keep updated on the latest application
releases for KDE. KDE also has links to related projects like K Office.
GNOME Home
http://www.GNOME.org
Gnome.org is one of the best-organized sites out there for a free-software project.
Get the latest scoop on development of GNOME, join the GNOME mailing list, or
start downloading! Developers can check out the latest additions to the CVS, and
GNOME users will find a lot of useful documentation on the site.
XFree86 Project
http://www.xfree86.org
The XFree86 Project site will give you the lowdown on the windowing system
that ships with Linux, where to get the current release, and an excellent FAQ
about the project. The XFree86 site is a must-read for anyone new to Linux, even
if your video card is running smoothly.
http://www.PLiG.org/xwinman
The Window Managers for X site is the most comprehensive site about X window
managers. Everything from ancient to the latest and greatest window managers
can be found on the site. Don't quite know the difference between a window
manager and a desktop environment? Learn the basics here.
LINUX MAGAZINE • subscribe • advertise • customer service • back issues • feedback • contacts
Vigor
Current Version:
0.016 Vigor: Putting new limits on productivity
Recent News
Vigor Training Program Initiated
After seeing the success of similar industry efforts, we at Piquan Software, the developers of
Vigor, have initiated a certification and training program to give industry professionals the
skills needed to use Vigor most efficiently.
The various levels of training available are as follows:
Certification Level Prerequisites Skills Price
About 90 percent of the Unix
industry uses Vigor, or its
inferior precursors, so chances
are very good that you are one of
Vigor Evildoer
- the many people using Vigor to $2000.00 US
Specialist (VES)
get your work done. Now you
can prove it, and give yourself
and your organization a
competitive edge.
The VCE program allows you to
demonstrate to your victims that
Vigor Certified you have the specialized
- $2000.00 US
Evildoer (VCE) knowledge required to perpetrate
evil with particular Vigor
features.
The VCE + Internet program
gives you the skills needed to
successfully use and support
specific features of Vigor in
today's Internet-demanding
Vigor Certified
world. Information on
Evildoer + Internet VCE $3000.00 US
composing spam emails,
(VCE + Internet)
fly-by-night .com web pages, and
other critical Internet tasks for
the modern evil dispensation
professional, using the Vigor
platform, are covered.
For evildoing professionals,
Piquan Solutions offers the
VCESE credential. VCESEs are
qualified to plan, implement,
maintain, and support plots to
take over the world, mind-control
Vigor Certified Evil Six VCE certifications schemes, destruction of enemies,
Scheme Engineer obtained within the last and other evil schemes, using the $5000.00 US
(VCESE) one (1) week Vigor environment. Study
materials will center around
"Things To Never Do As An Evil
Overloard". Graduates will have
access to beta versions of Vigor
in a schedule as approved by
Piquan Solutions.
VCT's play an important role in
Piquan Industries' re-education
process. VCTs are qualified
instructionally and certified
Vigor Certified technically personally by Piquan
VCESE $9000.00 US
Trainer (VCT) to deliver training to evildoers
everywhere. Study materials
center around Anthony Burgess
and Stanley Kubrick's A
Clockwork Orange.
All certifications include a certificate suitable for framing, an official and individual
certification number (while supplies last), and a Vigor Evildoer button to wear at conferences,
to let everybody know that you are a certified Vigor Evildoer. VCESEs also receive a secret
decoder nose ring.
Since Piquan Enterprises is constantly updating our curriculum and programs based on industry
input, all training and certification is on an as-available basis, and is subject to change,
cancellation, or expiration without notice. Piquan is not responsible for the conduct of certified
Evildoers. Thanks to Garrett Moffitt for the idea.
Vigor Revived
It's been a month and a half since the last release of Vigor. One would think that I'd be willing
to leave well enough alone. Well, I'm not. I got a bit of free time, and the LinuxCare review
sparked some interest, so I am now getting ideas for future improvements.
As always, bug fixes are my highest priority, but some new features would be nice too. Some of
the things I'd like to see in future versions are:
● Improved graphics. I use XBMs in Vigor because it was the quickest drawing method to
implement, and I wanted to get the first release out during the Vigor storyline on User Friendly.
Now that I've got some time, I'd like to improve the graphics handler and the artwork.
● More hooks! More confirmations, more annoying helpful hints (like the ones given when you
start insert mode), more random popups, more!
● More animations! At present, there are precisely two animations (count em!) in Vigor. This
is not nearly insideous enough. Naturally, with animations, you lead into...
● Sound effects (via Network Audio System). This naturally suggests...
● Speech (via Festival). This isn't that hard to do using Festival's server mode. (Thanks to my
coworkers at HP for the idea, the deranged loonies!)
● Microsoft Windows support. Judging by the feedback I get, people who aren't Unix devotees
just don't get the point of Vigor, but strangely enough I've gotten multiple requests to port Vigor
to Windows. Well, I suppose I may as well... Kinda one of those "full circle" things.
This by no means is an exhaustive list. If people send me patches, then I'll add just about
anything. These are just some of the things that I might do over the next few weeks, months,
whatever.
About Vigor
Based on the User Friendly comic strip storyline from 4 January to 14 January,
Vigor brings all the features of traditional Unix vi, plus the friendly and helpful
Vigor Assistant. (If you aren't familiar with User Friendly the Comic Strip, quit
bothering with Vigor and go out and look there first. It's well worth the trip! Don't worry, we'll
wait.)
Enter the world of Vigor! Come, join us, watch the paperclip, don't be afraid... *cough* Sorry,
where was I?
Vigor is based on the open-source nvi program, for which I apologize to the nvi authors. The
Vigor assistant was bolted on using the Tcl facility that nvi had, and a bit of my own C code to
cope with Tk.
I'm improving(?) Vigor based on suggestions from the user community. Send ideas, bug reports,
and patches to [email protected], and watch this page for updates. New versions have been
released at a rate ranging from several each evening to once a week, depending on user
comments and free time.
Press Coverage
I am always suprised when somebody mentions Vigor. I really didn't expect it to spread by
word-of-mouth at all, let alone people write about it. Keep telling your friends, your enemies,
your coworkers, everybody, about Vigor.
Particular thanks to Illiad for putting the original release announcement and multiple subsequent
announcements in the User Friendly News, not to mention the original inspiration!
User Comments
● You are a sick, sick person, and I admire that greatly. - Illiad, author of User Friendly
● AUUUUUGGGGGHHHHHH!!!!! - Keith Bostic, author of nvi
● I haven't laughed so hard in a long time.- Arnold Robbins, coauthor of Learning the vi Editor
● Congratulations, Brother Piquan... how diabolically clever of you...- Eric S. Raymond
● The entire open-source movement is, of course, a Discordian creation.- Amphigoricus the
Turgid, K.S.C.
● Why ? - Sander Nooy
● On behalf of evildoers everywhere, I thank you for your heroic efforts in bringing The
Assistant to such a long-standing bastion of the opposition. You will be remembered when The
Time comes. - Michael Jinks
Author Comments
● "I just thought I was writing a weekend hack; I had no idea what I was unleashing!" (Said
after noting over 20,000 web page hits.)
● The way I figure, after you take into account all the victims who have used it, Vigor is
single-handedly responsible for immeasurable amounts of lost productivity. In this, I think I
have captured the true nature of the original.
● It's amazing how a weekend hack can take up all your free time for a month.
● (When asked to confirm that Vigor is not a productivity app:) From its inception, Vigor has
been designed to be utterly useless, not to mention a pain to use. While building the interface, I
double-checked everything to ensure that I didn't accidently add a useful feature. [Note: See
below for an example of how that didn't work.] People have suggested making Vigor useful; my
reply is that it would then cease to be Vigor. I'm sure you can think of other examples of
popular, yet useless, editors. Besides, I don't even use vi... Who am I to decide how to improve
it?
Revisions
Vigor was rushed out in order to be released during User Friendly's Vigor storyline. It originally
had several bugs, and several unimplemented features. I've been fixing bugs and adding features
since the day Vigor was relelased. There are presently no outstanding Vigor bugs that I'm aware
of; let me know if you find something!
There is one remaining problem that we've only seen on two systems: Vigor, when it starts,
exits with the message unknown floating-point error, errno = 84. Eivind
Tagneth, who first reported this, traced it down to a bug in Tcl, and submitted a patch to the Tcl
maintainers.
Even if you're not seeing bugs, it's good to hear how much success/failure people are having on
different platforms. Let me know how things work for you!
Version 0.016 (May 2 19:36)
Create Whizzers, specialized dialogs to help you perform specialized tasks. Presently,
there are Whizzers for a few programming languages, and some common editing tasks.
More should follow.
Version 0.015 (Mar 25 15:17)
Disable by default built-in curses, db, and re libraries. Most OS's these days have proper
libraries for these, and I was seeing conflicts (particularly on SuSE under Vigor 0.014).
This may break things on some other OS's, probably older ones. If so, try using
--enable-curses --enable-db --enable-re on the command line.
Version 0.014 (Feb 8 14:50)
Remove the hack to the EULA that produced the Jumping Vigor Bug.
Version 0.013 (Feb 5 11:53)
Fix to configure.in: it looked for Tcl on Debian systems when it was supposed to look for
Tk.
Version 0.012 (Feb 4 00:28)
Updated EULA, made dialog box move along with assistant
Version 0.011 (Feb 2 00:10)
Look for libtcl8.2 etc (as opposed to libtcl82 etc); handle select() calls prior to assistant
initialization
Version 0.010 (Jan 19 23:16)
Modified EULA, changed fractional cm screen specs to pixel counts, use libtcl82 if
found, look for uint8_t etc
Version 0.009 (Jan 18 15:11)
Improved Tcl/Tk detection, added EULA, detect -ldl
Version 0.008 (Jan 17 21:20)
Added new comments, touched up comment probabilities, made sure that comments don't
overlap with animations, modified configure.in to look for libtcl80.a
Version 0.007 (Jan 17 12:25)
Fixed make install to install vigor instead of vi
Version 0.006 (Jan 16 12:42)
Further touch-up of "confirm" dialog's probabilities; rename executable to vigor
Version 0.005 (Jan 16 01:01)
Fixed make install; write Tk error messages to stderr before vi initializes the screen
Version 0.004 (Jan 16 00:21)
Updated configure to match configure.in (oops!)
Version 0.003 (Jan 15 23:45)
Added random quotes and animations; compiled vigor.tcl into executable
Version 0.002 (Jan 15 20:16)
Updated graphics; touched-up "confirm" dialog
Version 0.001 (Jan 14 01:05)
Initial release
The most frequent request I've had since releasing Vigor recently is for
screenshots. I've made a separate page with a few for those who don't have the
time or tools to compile Vigor; enjoy!
Tom Mulder created the Vigor logo at the top of the page, and the logo on the screenshots page
as well. Thanks, Tom!
And, if you just can't get enough paperclip action (you sick puppy you), svo (aka Viacheslav
Slavinsky) has created a brief Vigor MPEG, an excellent bit of artwork. For those who can't see
view MPEGs, he has also created some stills: still 1 and still 2. Yay, svo!
Downloading Vigor
Source tarball (0.016)
Get the source at http://www.red-bean.com/~joelh/vigor-0.016.tar.gz and have fun with it! You
may want to read over the section "Installing Vigor" below, though. I release by source tarball,
so this is usually the most up-to-date version. It's also the only one that I can help with install
problems on, since I am not generally familiar with the other formats.
Note that, because of namespace conflicts, as of 0.015, I changed Vigor to use the system
curses, db, and re libraries. This WILL cause problems on some systems. (It also will fix
problems on others.) If you have problems building Vigor from source, try running configure
with "--enable-db --enable-re".
Debian (0.016)
Colin Watson has made an unofficial package of Vigor for Debian 2.2. He's graciously
providing both the diffs and a i386 binary package. (Later versions may also be available; check
his dist site.)
FreeBSD (0.014 at last check)
There is now a Vigor port in the 4.0-current port tree. I use FreeBSD myself, but I'm not the one
responsible for the port (and I don't have commit privs), so it may fall out-of-date without my
knowing it. Thanks to Bill Fumerola for committing this! (And I had been told that Vigor
should be committed...)
Windows
I'm looking into building a Cygwin+native Tk port for Windows, but I'm not yet sure if that will
happen. Watch this space for details!
Installing Vigor
At present, some parts of Vigor are in a somewhat primitive state, particularly as far as the build
is concerned. Suggestions for how to make things build on various OS's are gratefully accepted.
For the most part, compiling vigor usually goes something like this:
gunzip vigor-0.016.tar.gz
tar -xvf vigor-0.016.tar
cd vigor-0.016/build
export ADDCPPFLAGS="-I/usr/local/include/tcl8.2
-I/usr/local/include/tk8.2"
export ADDLDFLAGS="-L/usr/local/lib"
./configure
make install
vigor
Substitute your locations for tcl.h, tk.h, and libtcl.a on the ADDCPPFLAGS and
ADDLDFLAGS lines. If you still have problems building Vigor, read the suggestions below,
look in the build/README file, and if all else fails, drop me an email describing the problem.
Vigor does not support nvi's Tk interface (and configure doesn't give you that option), and may
have trouble compiling in the Perl interpreter (which is not included by default). [Update: I
think that I fixed the problem with the Perl interpreter.] You will want to read build/README
to get the skinny on building nvi. Vigor will always build in nvi's TCL interpreter.
Vigor is written in C and Tcl/Tk. You must have Tcl/Tk installed to use Vigor. I'm not sure
what versions work. I wrote from Ousterhout's book, so I think anything after 7.3 is fine. Most
people seem to have been using Tcl/Tk 8.0 or 8.2, and things seem fine there.
Note that, because of namespace conflicts, as of 0.015, I changed Vigor to use the system
curses, db, and re libraries. This WILL cause problems on some systems. (It also will fix
problems on others.) If you have problems building Vigor from source, try running configure
with "--enable-db --enable-re".
OS Notes
You may want to look over whatever systems are similar to yours.
Solaris 2.5.1
The u_int8_t problems on Solaris have been fixed as of Vigor 0.010. Thanks to John West for
providing the information to fix it!
Cygwin
When configuring for Cygwin, create a directory /var/preserve/vi.recover and make it
world-writable. (See the comments in configure.in for alternative directories.) (I haven't yet
received confirmation that it works after that, though.)
In Case Of Trouble
If you're having trouble building Vigor and are writing for help, please send me as much of the
following as possible. If you don't have everything, write me anyway, but this information will
help me figure out the problem.
● Your architecture, as reported by the config.guess program supplied with Vigor. If
you believe that config.guess is supplying an incorrect or incomplete architecture,
then tell me that too.
● The version of Vigor you are trying to compile. I update Vigor regularly, so by the time I
see your email, I may be working with a later version.
● How you downloaded Vigor. I need to know if you got the tarball, the source RPMs, or a
binary distribution.
● What arguments you gave configure when you ran it.
● The environment variables ADDLDFLAGS, ADDCPPFLAGS, CFLAGS, and
LDFLAGS if you have changed them.
● The version of Tcl and Tk you are using, and the filenames under which they are
installed.
If the trouble is happening when you run configure, send me the file config.log (or at
least the final bit of it).
If the trouble is happening when you run make, send me the last several lines that make
produced.
If the trouble is when you run Vigor, send me a description of the trouble you're seeing. "It
doesn't work for me" is not a bug report.
I'm glad to help out as I can. Vigor has lots of bugs, and I'm constantly trying to find them and
clean them up. Sending me complete information will help me fix Vigor sooner.
Old News
Vigor Useful?!?
One user actually found Vigor to be useful! After all that time and effort I put into making a
totally useless app, somebody has to go and get some benefit out of it.
The user in question had been trying to learn Vi for some time. However, his manual neglected
to mention the difference between the Insert mode and Command mode. (What kind of tutorial
was he using?) His confusion was lifted when he saw the prompt from Vigor:
You have not entered insert mode before. While you're in insert mode, remember
that you need to return to command mode before entering Vigor commands!
Before Vigor's public release, I had changed that prompt once because I deemed it "too useful"
(it mentioned the Esc key by name). Apparently, I just didn't make it useless enough.
I'll tell you, some people just don't know a bad thing when they've got it.
Vigor Scooped?
Yes, it's true, the open-source vi clone VIM already has its own smiling face.
Apparently, there is an option to VIM called VimBuddy, which will display an ASCII smiley
(eg, ":-)") on your status line for different status reports. The Windows version of VIM will also
update the icon with a face as well!
I still won't say what my motives for writing Vigor were, but I think you can be sure they
weren't the same as the ones that prompted the creation of VimBuddy.
(Note to the interested: I don't have any other information about VimBuddy; you may want to
do a search on egroups. That shows up a few discussions, some code, and the author's name.)
Acknowledgments
Vigor would never have been had it not been for these people's efforts.
● Illiad, author of User Friendly the Comic Strip, for keeping my spirits up with his work
for years, and for conceiving of Vigor to begin with.
● The authors of nvi (listed in the README), particularly Steve Kirkendall and George
Neville-Neil. Without nvi to work from, there could be no Vigor.
● John K. Ousterhout and the other contributors to Tcl/Tk, without which I couldn't have
written Vigor in time to release during the Vigor storyline.
● Peter Mattis, Spencer Kimball, and the other contributors to The GIMP, for helping even
me make half-decent art. (You don't want to know what the art looked like before GIMP's
help.)
● Michael J. Gourlay and the other contributors to xmorph.
Release Announcement
FOR IMMEDIATE RELEASE
Mountain View, CA. In a recent fit of madness, hacker Joel Ray "Piquan" Holveck has released
Vigor, a version of the popular Unix editor vi featuring the Vigor Assistant. Holveck declined
to comment on his true motives for creating the program, although it has been confirmed that he
was inspired by Pitr of User Friendly the Comic Strip. A supporter of the Free Software
Foundation, Holveck denies rumors that he created the program as part of a plot to encourage
the use of Emacs based on Greg's 10 Jan comment. Vigor is currently available online at
http://www.red-bean.com/~joelh/vigor/ and is expected to undergo daily improvements based
on user input for the next several days.
Just a small note on my signature on the Vim Homepage:
Gary Fritz [email protected] told me that the lyrics to "Tiggers Song" are these:
Sponsored by:
Backlash!
by Clay Shirky
Evaluate
04/05/2001
ColdFusion for
The peer-to-peer backlash has begun. On the same day, the Wall St. Journal ran an FREE! Build
article by Lee Gomes entitled "Is P2P plunging off the deep end?", while Slashdot's powerful
resident commentator, Jon Katz, ran a review of O'Reilly's Peer to Peer book under the applications
title "Does peer-to-peer suck?" quickly and easily,
It's tempting to write this fully exploit your
off as part of the Great enterprise systems,
Wheel of Hype we've been and enhance user
living with for years: experience.
Revolution convergence
As Jon Orwant noted recently in these pages, " Peer-to-peer is not
a technology, it's a mindset."" Put another way, peer-to-peer is a
related group of ideas about network architecture, ideas about how
to achieve better integration between the Internet and the personal
computer -- the two computing revolutions of the last 15 years.
The history of the Internet has been told often -- from the late '60s
to the mid-'80s, the DARPA agency in the Department of Defense
commissioned work on a distributed computer network that used
packet switching as a way to preserve the fabric of the network,
even if any given node failed. Peer-to-Peer:
The history of the PC has likewise been often told, with the rise of Harnessing the
DIY kits and early manufacturers of computers for home use -- Power of
Osborne, Sinclair, the famous Z-80, and then the familiar IBM PC Disruptive
and with it Microsoft's DOS. Technologies
Edited by Andy
In an accident of history, both of those movements were
Oram
transformed in January 1984, and began having parallel but
March 2001
increasingly important effects on the world. That month, a new
0-596-00110-X,
plan for handling DARPA net addresses was launched. Dreamed
Order Number:
up by Vint Cerf, this plan was called the Internet Protocol, and
110X
required changing the addresses of every node on the network over
448 pages,
to one of the new IP addresses, a unique, global, and numerical
$29.95
address. This was the birth of the Internet we have today.
Meanwhile, over at Apple Is P2P the "push" of
Computer, January 1984 saw the the 2000s, or a really
launch of the first Macintosh, the good idea? Respond to
computer that popularized the Shirky's opinion (or Katz's
graphic user interface (GUI), with or Gomes') here.
its now familiar point-and-click
interactions and desktop metaphor. Post your comments
The GUI revolutionized the
personal computer and made it accessible to the masses.
For the next decade, roughly 1984 to 1994, both the Internet and the PC grew by leaps
and bounds, the Internet as a highly connected but very exclusive technology, and the
PC as a highly dispersed but very inclusive technology, with the two hardly
intersecting at all. One revolution for the engineers, another for the masses.
The thing that changed all of this was the Web. The invention of the image tag, as part
of the Mosaic browser (ancestor of Netscape), brought a GUI to the previously
text-only Internet in exactly the same way that, a decade earlier, Apple brought a GUI
to the previously text-only operating system. The browser made the Internet
point-and-click easy, and with that in place, there was suddenly pressure to fuse the
parallel revolutions, to connect PCs to the Internet.
Which is how we got the mess we have today.
Clay Shirky is a Partner at The Accelerator Group. He writes extensively about the
social and economic effects of the internet for the O'Reilly Network, Business 2.0, and
FEED.
Related Articles:
Editor Andy Oram on O'Reilly's First Peer-to-Peer Book
Security Concerns Miss the P2P Point
Is P2P the "push" of the 2000s, or a really good idea? Respond to Shirky's
opinion (or Katz's or Gomes') here.
(* You must be a member of the O'Reilly Network to use this feature.)
Comment on this Article
Sponsored by:
ONJava.com
ONLamp.com Use P2P. Go to Jail.
openp2p.com Any Questions?
Perl.com David McOwen faces
XML.com Using PASX, an How will Mono Maybe socialism arrest, trial, and
open source unite the wasn't such a bad imprisonment because
he installed the
Apache solution. ADO.NET and idea after all...
Distributed.net client on
BSD GNOME-DB computers at the college
Javascript and CSS object models? where he worked. Read
Linux the story on
Mac OpenP2P.com.
TODAY ON THE O'REILLY NETWORK
Mozilla
.NET Extending the Life Line of the PalmOS Marc Hedlund offers four WEBLOGS
Perl ways to improve the Palm operating system, including bundling Links and commentary
Policy applications, improving the desktop software, switching wireless
PHP support to 802.11b, and embracing standards. [Wireless DevCenter]
Python
Use P2P, Go to Jail David McOwen installed the Distributed.Net
Web Services
client at the college where he worked. Now he's being prosecuted for
Wireless
"computer trespass" and could face up to 15 years in
XML prison. [OpenP2P.com]
POST error
Articles I have set up Apache
● Using PASX 1.3.18 on a RedHat
Linux system and am
● The WeakHashMap Class trying to write a script to
● Java and XML Week do a POST to a page.
● XML Processing with TRaX When doing so, I get the
following error: The
● JSP Security for Limiting Access to requested method POST
Application-Internal URLs is not allowed. How ...
oreillynet.apache
Articles
● Cross-Browser Layers: Part 2
● Extending Dreamweaver with its JavaScript
API
● Accessing Dreamweaver's JavaScript API TOP FAQs
● Cross-Browser Layers, Part One
● JavaScript: Why You Don't Know More
About It
Articles | Forums | FAQs
Linux
● Moving to BSD Without Leaving Linux What good is a core
● Tools of the Trade: Part 2 file?
● Tools of the Trade: Part 1
What is the difference
● Death of a Palm between internal and
● Linux Device Drivers Update external modems?
XML
Articles Why should I use
● X on X XML instead of
● Running Java Applications on Mac OS X HTML?
● How I BSDed My iBook
● Strings in Cocoa: Part I
● VisorVision at PC Expo
Articles | Forums
● July 27th is Mozilla Community Day at the
O'Reilly Open Source Conference!
● Mozilla 0.9.2 Released
● Towards Mozilla 1.0
● 0.9.2 Branch and Beyond
● Netscape 6.1 Beta 1
Articles
● Writing ASP.NET Web Forms with C#
● Contrasting C# and Java Syntax
● Comparing C# and Java
● Conversational C# for Java Programmers, Part 1
Articles
● Use P2P, Go to Jail. Any Questions?
● Use P2P, Go to Jail
● Open Standards/Closed Mind
● Who is Microsoft Trying to Control?
● Passport is Evil
Articles | Forums
● Internet Society Panel on Business Method Patents
● British Telecom Patent: Lachey, Uninfringed and
Invalid?
● Who's Really Being Protected?
● Who's Really Being Protected? - Part 2
● A Few More Thoughts on the Patents Issue by Tim
O'Reilly
Articles | FAQs
● This Week on p5p 2001/07/09
● People Behind Perl: Nathan Torkington
● This Fortnight in Perl 6 (17 - 30 June 2001)
● This Week on p5p 2001/07/02
● Why Not Translate Perl to C?
Forums
● Embedding PHP in HTML
● The PHP Configuration File -- Part One
● The Universal Web Form Processor
● Installing PHP on a Windows System
● PHP With HTML Forms
Articles | Forums
● GUI Development with Python and Qt
● Piddle Graphics Online
● Transactional Persistence for Python
● Using PySOAP
● Programming for Artists
Articles | Forums
● Extending the Life Line of the Palm OS
● 802.11b Round-Up
● Developing Applications for the RIM BlackBerry
● New Wireless Standards Challenge 802.11b
● Introducing the Xircom 802.11 Module for the
Visor
Articles | FAQs
● Namespace Nuances
● Against the Grain
● Math and XSLT
● Blueberry Jam
● Electronic Publishing with XML
Sponsored By:
Business
Graphics
Metadata
Mobile
Transforming XML: Math and XSLT
Programming
By Bob DuCharme
Protocols
XSLT is primarily for transforming text, but you can use it to do basic math
Schemas too. Jul. 5, 2001
Style
Web XML Q&A: Namespace Nuances
By John E. Simpson
This month's Q&A column tackles the question of how to write DTDs for XML
applications that use namespaces. Jul. 5, 2001
Annotated XML
What is XML? XML-Deviant: Against the Grain
What is XSLT? By Leigh Dodds
What is XLink? XML developers are talking about a perennial question: how can XML and
What is XML Schema? database technologies be integrated appropriately? Jul. 5, 2001
What is RDF?
Previous Features XML News
Electronic Publishing with • SOAP Version 1.2 [XML.com Resource
XML Guide]
By Benjamin Jung, John • W3C discussion of Technical Architecture
McKeown Group [xmlhack]
The proceedings for the recent • SVG update [xmlhack]
XML Europe 2001 conference • Apache has mixed feelings about Events
were created from start to finish XML-RPC [xmlhack]
with XML. This case study • A light pUDDIng [xmlhack] XML Summer
describes the processes used and School 2001 [Jul.
• RDFStore [XML.com Resource Guide]
problems encountered. Jun. 27, 20, 2001]
2001 • Run XSLT transforms from
Emacs [xmlhack]
XML on the Cheap O'Reilly Open
• Software AG and Fatdog release XQuery
By Edd Dumbill Source Convention
implementations [xmlhack]
If you're new to XML, or simply [Jul. 23, 2001]
Manage Your Account • JAX-RPC [XML.com Resource Guide]
want a to play around with it a • J2EETM COM Bridge [XML.com Resource
Forgot Your Password? little, there are plenty of Free Web Seminar:
Guide] Managing the
resources on the Web you can
use for free, many without even Development of
Search installing software on your XML E-Business
Article Archive computer. Jun. 27, 2001 Initiatives [Jul. 24,
FAQs XML News Headlines from The XML 2001]
Storing XML in Relational
Cover Pages by Robin Cover
Databases Sponsored by OASIS SD Web Services
By Igor Dayen
• W3C Publishes XML Protocol Abstract World [Aug. 27,
A survey of the techniques used
Model and Glossary. 2001]
by the major vendors to store
XML in their databases, and a • W3C Releases First Public Working Draft
for SOAP Version 1.2. XML World 2001
proposition for a
database-independent XML • New Release of XML Schema Validator [Sep. 17, 2001]
XML-Deviant
Style Matters framework. Jun. 20, 2001 (XSV). B2B Integration
XML Q&A • SWIFT and FPL Agree to Develop Strategies &
Rapid Resolution
Transforming XML Securities Standard 'ISO 15022 XML' in ISO Solutions [Sep. 17,
By Leigh Dodds
Perl and XML Working Group 10... 2001]
A recent debate about supporting
OASIS catalogs in XML shows • Software AG Releases XQuery Prototype
that strong differences of opinion 'QuiP'.
XML Resources still exist on interpretation of the • Updated XEP Rendering Engine Supports
Buyer's Guide XML 1.0 specification Enhanced XSL FO Formatting.
itself. Jun. 20, 2001 • Initial Release of a RELAX NG Working
Events Calendar
Standards List Draft Specification.
Submissions List • XML Schema for 'Beta' Metadata Encoding
and Transmission Standard (METS).
FAQs
How can I advertise on
Syntax Checker XML.com?
XML Testbed
Whom should I contact if I have Buyer's Guide
an article idea for XML.com? Document Authoring - Sponsored by
What information does SiberSafe: XML CMS
XML.com gather and track? Editors Graphics Style Tools
Website Tools
Content Exchange/Syndication Information
Servers
Ecommerce
Application Builders EDI
Data Management
Application Generator Data Analysis
Schema/DTD Editors Search Tools Tree
Viewers
Databases/Repositories - Sponsored by
SiberSafe: XML CMS
Print Production
Training
Books Courses
LinuxProgramming:
Tcl-URL! - weekly Tcl news
and links (Jul 10)[Linux
Today]
Affiliates
Servlets.com Java Design
• The WeakHashMap Class
jdom.org
• The Performance of Java's Lists
Java Security
• JSP Security for Limiting Access to
Application-Internal URLs
Java Media
Java 3D API Tutorial
JAI Tutorial
J2SE
• Learning Polymorphism and Object
Serialization
PeerIntelligence: Don't
Re-invent Business Models
for P2P
[Peertal the P2P News
Portal]
Already a member?
Login Here
Welcome to Perl.com!
Subscribe to our email newsletter using the form below. In addition,
Privacy Policy
your registration will allow you to use our article talk back feature.
Terms of Use
An * indicates a required field.
Please choose a login name and password for your account on
Perl.com:
Login Name *
E-Mail *
Title
Organization
Mailing Address
City State
Submit Reset
Terms of Use
1. Do not post any content or link to any content which (a) is
libelous, defamatory, obscene, pornographic, abusive, harassing
or threatening, (b) contains viruses or other contaminating or
destructive features, (c) violates the rights of others, such as
content which infringes any copyright, trademark, patent, trade
secret or violates any right of privacy or publicity, or (d)
otherwise violates any applicable law.
2. Do not use this discussion area for any commercial purposes, to
distribute any advertising or solicitation of funds or goods and
services.
3. Perl.com does not and cannot review the content posted by
users on this service and is not responsible for such content.
However, we reserve the right to delete, move or edit any
content that we may determine is unacceptable. You shall
remain solely responsible for all content posted by you.
4. By posting a comment here you are giving Perl.com the right to
publish your comments.
All of oreilly.com Search
Home Innovate--Collaborate--Discover
Registration O'Reilly Open Source Convention
Hotel/Travel Sheraton San Diego Hotel, San Diego, CA
See & Do July 23-27, 2001
Tutorials
Sessions Fueling the Open Source Alternative
Evening Events We are pleased to announce the 3rd
BOFs annual O'Reilly Open Source Convention,
July 23-27, 2001, at the waterfront
Speakers Sheraton Hotel and Marina in San Diego,
Press California. This year's expanded
Don't miss the convention includes over 250 sessions in
Mail List Great Open 14 tracks on key open source technologies
Exhibitors such as Perl, Apache, XML, Python, PHP,
Source Debate MySQL, Linux, and many more. Browse
Sponsors Sessions and Tutorials for full details. Read Tim O'Reilly's reasons why
Open Source is Here to Stay.
News Updates
Enjoy San Diego Tim O'Reilly on Microsoft's Participation at the Open Source
Convention--Microsoft senior vice president Craig Mundie will speak at
O'Reilly's upcoming Open Source Convention, and he'll debate Red Hat's Michael
Tiemann and other open source leaders. Tim O'Reilly talks about how this came
about and what he hopes to accomplish by bringing together Microsoft
representatives and open source advocates at the O'Reilly Open Source
Convention.
Open Source Convention media sponsor Dr. Dobb's Journal has graciously
offered a year's complimentary subscription to DDJ when you register. Already
have a subscription? DDJ will add a year onto your current subscription.
What Would You Ask Craig Mundie? Microsoft
senior vice president Craig Mundie, who recently
raised the ire of the open source community, has
agreed to give a keynote and participate in a panel
discussion at July's O'Reilly Open Source Convention.
Here's your chance to put your questions to him.
PHP Conference--The first ever PHP Conference brings the community together
for sessions and tutorials designed to explore and strengthen PHP in the open
source space. Take a look under the hood at everything PHP--from understanding
PHP on wireless devices to participating in a discussion on the future of PHP
featuring some of the core developers and luminaries from the PHP family.
Downloads
Downloading the Latest Version
of Perl
Documentation
by Tom Christiansen
CPAN March 24, 1999
FAQs
Contents of this document
Training
● Source Code Distribution
Resources ❍ Stable Production Release (Current Version)
❍ Experimental Developer's Release (Upcoming Version)
Article Archive
❍ Previous Releases (Legacy Version)
Books ■ Source License
● Binary Distributions
Search
❍ Unix, Linux
Register/Log in ❍ Win32
❍ Macintosh
Columns ● Getting Help
P5P Digest
P6P Digest
Off the Wall Overview
Perl is Open Source software. You can download it for free as a source code or as a
pre-compiled binary distribution.
Source Licence
Perl is Open Source software. It's free for you to download and use as you wish. Perl's
license is called the Artistic license. Read it if you aren't sure what you can or can't do.
The bottom line is that this is a kinder and gentler version of the GNU license -- one
that doesn't infect your work if you care to borrow from Perl or package up pieces of it
as part of a commercial product!
Binary Distributions
Binary distributions of Perl are available for various platforms, including Win32
(Windows NT/95), Mac and Unix. Please read all documentation that comes with each
package, as one distribution for a given platform may be very different than another for
the same platform (eg. different add-ons, compiled from a different version of Perl
etc.)
Generally speaking, CPAN doesn't distribute Perl binaries. It does provide information
in the /ports directory that will point you to sites that maintain binary distributions for
specific platforms.
If you have problems installing ActivePerl, please see the ActiveState site for support
information.
Alien Ports
If you are looking to run Perl on a non-native system, then have a look at the
/CPAN/ports/ directory. Note that the standard Perl distribution compiles even on most
closed-source systems now, so the ports directory is of somewhat limited utility for
them.
Getting Help
If you need help, here are some suggestions.
● If you encounter problems configuring, compiling, or installing Perl from the
source kits, please read the README in the source directory. Besides including
important tips for various platforms, they also document where to send mail if
you still have build difficulties.
● If you have problems downloading via ftp, try this web mirror of CPAN instead.
● If you still can't get the download or the unpacking to work, you'll need to
contact your local systems administrator (not perl.com staff) for help with your
local system. Also, try to contact other Perl users in your organization or your
community for help.
● If you have issues with the ActiveState port, please contact them directly.
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
Newsletter | Perl Conference 5.0: July 23-27
Search
Downloads
Documentation
This section contains the core documentation for the Perl
Documentation
language. Please note that many applications use Perl modules
and the documentation for those modules can be found on
CPAN
CPAN. Also, the FAQs are an excellent source of information
FAQs about many different applications of Perl.
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
Comprehensive
Perl Archive
Network
Welcome to CPAN! Here you will find All
Things Perl.
Searching
● Perl core and CPAN modules documentation
Browsing (Randy Kobes)
● Perl core documentation (Carlos Ramirez)
● modules ● CPAN modules, distributions, and authors
● scripts (search.cpan.org)
● binary distributions ("ports") ● CPAN modules documentation (Ulrich Pfeifer)
● source code
● comp.lang.perl.announce archives FAQ etc
● recent arrivals
● recent modules ● CPAN Frequently Asked Questions
● CPAN sites list ● Perl Mailing Lists
● CPAN sites map ● Perl Bookmarks
Yours Eclectically, The Self-Appointed Master Librarian
(OOK!) of the CPAN Jarkko Hietaniemi [email protected]
[Disclaimer] 2001-04-01
Downloads
FAQs: Perl's Frequently Asked
Questions
Documentation
About the Perl FAQ
CPAN This document summarizes the Perl FAQ and provides a lot of
disclaimers. [Source: Perldoc.com]
FAQs
Data Manipulation
Training
Manipulating numbers, dates, strings, arrays, hashes, and
Resources including miscellaneous data issues. [Source: Perldoc.com]
Programming Tools
Questions about programmer tools and programming
support. [Source: Perldoc.com]
Regular Expressions
Pattern matching and regular expressions [Source:
Perldoc.com]
System Interaction
Interprocess communication (IPC), control over the user
interface including keyboard, screen and pointing
devices. [Source: Perldoc.com]
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
TCPC Perl Training Courses
Looking for professional training in Perl? Tom Christiansen Perl Consultancy provides private,
corporate training to meet your company's unique Perl training needs.
Courses are scheduled under one of the following arrangements:
● We travel to your private site, using your facilities for classroom and lab activities.
● You travel to our site, using our open courses in Boulder, Colorado.
Downloads
Resource Topics
Formerly the "Perl Reference Pages"
Documentation
● Binaries
Books ● Business
Search
Columns ● CGI
P5P Digest CGI programming with Perl
P6P Digest
Off the Wall ● Communications
Sockets and ports and protocols -- Oh my!
● Conversion
Conversion utilities -- Zip, BinHex, etc..
● CORBA
Information on CORBA Perl
● Core Documentation
● Data Structures
● Databases
● Debugging
Debugging programs
● Editors
Editors for Perl or editors using Perl
● Files
Working with files and filesystems
● Finance
Financial applications and modules
● Games
Games written in Perl
● Gear
Shirts, hats, toys -- Essentials for Perl programming
● Geographical
Perl modules for geographical applications
● Graphics
● HTTP
Web servers and Perl modules for the server
● Java
● Lingua
Perl scripts and modules for linguistics
● Linux
Linux-specific Perl programs and modules
● Lists
Mailing lists about Perl
● Macintosh
MacPerl info
● Mathematics
Perl scripts and modules for mathematics
● Modules
● Music
Perl modules and programs for music
● Net
Network programming
● Newsgroups
USENET newsgroups pertaining to Perl
● NeXT
Ports and modules for the NeXT environment
● Objects
● Oddities
Strange and unusual things people do with Perl
● Palm Pilot
Perl stuff for the Palm Pilot
● PCL
Perl programs and interfaces for PCL
● Perl Internals
● Porting
Porting information
● Programming
● Regular Expressions
Information about regular expressions
● Releases
Information about current and past releases.
● School
Perl programs for schools
● Screen I/O
Screen handling, menu systems
● Security
● Sets
Working with sets
● Solaris
Ports and modules for the Solaris environment
● Sorting
Information on various sorting techniques
● Statistics
Statistical programs
● Style Guides
Programming standards and style guides
● Sysadmin
System administration modules and programs
● Text Tools
Text tools in Perl
● Time
Perl resources about date and time
● Troubleshooting
● Tutorials
Tutorials, guides, manuals and FAQs
● User Groups
Perl User Groups (pugs?)
● User Interfaces
Character and graphic user interfaces
● Version Control Systems
Access Version Control System data with Perl
● VMS
Perl on VMS platforms
● Web Admin
Perl programs and tips for Web administration -- Note:
CGI Perl programs typically interact with the Web. Web
admin tools don't.
● Win32
● XML
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
Newsletter | Perl Conference 5.0: July 23-27
Search
Downloads
Article Archive
A listing of all Perl.com articles grouped by topic.
Documentation
Advocacy Databases mod_perl Releases Win32
CPAN Books and Documentation Objects Security XML
Magazines Editors Oddities Style Guides Y2K
FAQs
Business Java Open Source Text Tools
Training C and Perl Language Perl 6 Troubleshooting
CGI Development Perl Internals Tutorials
Resources Community Larry Wall Programming User Interfaces
Core Lists Regular Web
Article Archive
Documentation Modules Expressions Development
Books CPAN
Search
Advocacy
Register/Log in
Why I Hate Advocacy
Are you an effective Perl advocate? Mark Dominus explains why
Columns you might be advocating Perl the wrong way. [Dec 12, 2000]
P5P Digest
P6P Digest Ten Perl Myths
Off the Wall Ten things that people like to say about Perl that aren't true. [Feb
23, 2000]
Camel Critiques
Reviews of Perl books [Mar 25, 1999]
Business
The e-smith Server and Gateway: a Perl Case Study
Kirrily "Skud" Robert explains the Perl behind the web-based
administrator for the e-smith server. [Feb 20, 2001]
Perl Support
Where can I buy a commercial version of Perl and is a support
contract available? [Mar 25, 1999]
C and Perl
Why Not Translate Perl to C?
Mark-Jason Dominus explains why it might not be any faster to
convert your code to a C program rather than let the Perl
interpreter execute it. [Jun 27, 2001]
CGI
Using CGI::Application
The Common Gateway Interface may well be the backbone of
many web applications, but sometimes it can feel dry and
monotonous to work with. If you're fed up with "my $query =
CGI->new()", Jesse Erlbaum presents a kinder, gentler
alternative. [Jun 5, 2001]
Community
This Week on p5p 2001/07/09
No 5.8.0 yet, numeric hackery, worries about PerlIO and much
more. [Jul 9, 2001]
Privacy Policy
The O'Reilly and Perl.com privacy policy [Jun 15, 2001]
About perl.com
[Jun 7, 2001]
A Photographic Journal
Photographs taken at the Perl Conference by Joseph F. Ryan: Perl
Programmer at the National Human Genome Research
Institute. [Aug 27, 1998]
Core Documentation
The Artistic License
This document states the conditions under which a Package may
be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the
package [Aug 15, 1997]
CPAN
Common Questions About CPAN
Answers to the most common questions asked from
[email protected] [Jul 29, 1999]
Databases
DBI is OK
Chromatic makes a case for using DBI and shows how it works
well in the same situations as DBIx::Recordset. [Mar 20, 2001]
DBIx::Recordset VS DBI
Terrance Brannon explains why DBI is the standard database
interface for Perl but should not be the interface for most Perl
applications requiring database functionality. [Feb 27, 2001]
Documentation
POD is not Literate Programming
[Mar 20, 2000]
Editors
Perl Builder IDE Debuts
A review of Perl Builder, the first integrated development
environment (IDE)for Perl. [Jul 22, 1998]
Java
Language Development
This Fortnight in Perl 6 (17 - 30 June 2001)
A detailed summary of a recent Perl vs. Java battle, a discussion
on the internal API for strings, and much more. [Jul 3, 2001]
Larry Wall
State of the Onion 2000
Larry Wall's annual report on the state of Perl, from TPC 4.0 (the
fourth annual Perl conference) in Monterey in July 2000. In this
full length transcript, Larry talks about the need for changes,
which has led to the effort to rewrite the language in Perl 6. [Oct
24, 2000]
Lists
Guide to the Perl 6 Working Groups
Perl 6 discussion and planning are continuing at a furious rate and
will probably continue to do so, at least until next month when
Larry announces the shape of Perl 6 at the Linux Expo. In the
meantime, here's a summary of the main Perl 6 working groups
and discussion lists, along with an explanation of what the groups
are about. [Sep 5, 2000]
Modules
Pod::Parser Notes
Brad Appleton, author of the Pod::Parser module suite,
responds to some of the remarks in an earlier perl5-porters
mailing list summary. [May 20, 2000]
mod_perl
Creating Modular Web Pages With EmbPerl
If you have ever wished for an "include" HTML tag to reuse large
chunks of HTML, you are in luck. Neil Gunton explains how
Embperl solves the problem. [Mar 13, 2001]
Objects
Bless My Referents
Damian Conway explains how references and referents relate to
Perl objects, along with examples of how to use them when
building objects. [Sep 16, 1999]
Oddities
How Perl Helped Me Win the Office Football Pool
Walt Mankowski shows us how he used Perl to make a few extra
bucks at the office. [Oct 2, 2000]
Open Source
Open Source Highlights
An open source champion inside Chevron writes about his visit to
the Open Source Conference. [Sep 28, 1999]
Perl 6
This Week in Perl 6 (27 May - 2 June 2001)
Coding Conventions Revisited, Status of the Perl 6 Mailing Lists,
and much more. [Jun 4, 2001]
Exegesis 2
Having trouble visualizing how the approved RFC's for Perl 6
will translate into actual Perl code? Damian Conway provides and
exegesis to Larry Wall's Apocalypse 2 and reveals what the code
will look like. [May 15, 2001]
Perl Internals
Sapphire
Can one person rewrite Perl from scratch? [Sep 19, 2000]
Programming
Beginners Intro to Perl - Part 6
Doug Sheppard shows us how to activate Perl's built in security
features. [Jan 9, 2001]
Prototypes in Perl
Tom Christiansen explains how prototypes really work in
Perl. [Jul 25, 1999]
Perl's Prospects Are Brighter Than Ever
Jon Udell's summary of the Perl Conference. [Aug 26, 1998]
Java vs Penguin
An exchange that Jake had with a colleague regarding
penguin/perl/java. [Aug 15, 1997]
Java is Dead
Early safeperl discussions. [Aug 5, 1997]
Regular Expressions
Releases
Perl 6 Alive and Well! Introducing the perl6-mailing-lists Digest
Perl.com will be supplying you with the P6P digest, covering the
latest news on the development of Perl 6. [Feb 14, 2001]
Security
Style Guides
Red Flags Return
Readers pointed out errors and suggested more improvements to
the code in my 'Red Flags' articles. As usual, there's more than
one way to do it! [Nov 28, 2000]
Text Tools
Designing a Search Engine
Pete Sergeant discusses two elements of designing a search
engine: how to store and retrieve data efficiently, and how to
parse search terms. [Apr 10, 2001]
Troubleshooting
Having Trouble Printing Code Examples?
Info for those who can't get Perl.com articles to print out
correctly [Jun 11, 2001]
Tutorials
Parse::RecDescent Tutorial
Parse::RecDescent is a recursive descent parser generator
designed to help to Perl programmers who need to deal with any
sort of structured data,from configuration files to mail headers to
almost anything. It's even been used to parse other programming
languages for conversion to Perl. [Jun 13, 2001]
User Interfaces
A Simple Gnome Panel Applet
Build a useful Gnome application in an afternoon! Joe Nasal
explains some common techniques, including widget creation,
signal handling, timers, and event loops. [Mar 27, 2001]
Perl/Tk Tutorial
On Perl.com, we are presenting this as part of what we hope will
be an ongoing series of articles, titled "Source Illustrated." The
presentation by Lee and Brett is a wonderfully concise example of
showing annotated code and its result. [Oct 15, 1999]
Web Development
Quick Start Guide with SOAP Part Two
Paul Kulchenko continues his SOAP::Lite guide and shows how
to build more comples SOAP servers. [Apr 23, 2001]
Win32
Microsoft to Fund Perl Development
ActiveState Tool Corp. has a new three-year agreement with
Microsoft that funds new development of Perl for the Windows
platform. [Jun 9, 1999]
Y2K
Y2K Compliance
Is someone asking you to ensure that your Perl code is Y2k
compliant? Tom Christiansen gives you some answers, which
may not completely please the bureaucrats. [Jan 3, 1999]
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
perl Books All the words Search
Search www.perl.com
Downloads
search
Documentation
CPAN
FAQs
Search Tips
Training
Check Spelling
Resources Make sure your search terms are spelled correctly.
Use multiple words
Article Archive
Using multiple words will return more refined results than a
single word. For example, typing our free service will return
Books
more relevant results than typing just service. (Keep in mind
Search that relevant results are returned even if they don't contain all
query terms.)
Register/Log in Use similar words
The more similar words you use in a search, the more relevant
your results will be.
Columns
Use appropriate capitalization
P5P Digest
Capitalize proper nouns, and remember that lower-case words
P6P Digest will match any case. For example, typing search will return all
Off the Wall documents containing the words search, Search, and SEARCH.
Typing Search, however, will instruct the search engine to look
only for the capitalized word.
Use quotation marks
Use quotation marks to find words which must appear adjacent
to each other, for example, "our pledge to you." Otherwise, the
search results will include the word our, pledge, to, and the
word you, but not necessarily in that order. The words may
appear anywhere, and in any order, within the document.
Use plus (+) or minus (-)
Use a plus sign when your search term or phrase must appear in
the search results. Use a minus sign to indicate undesirable
term(s). The plus sign tells the search engine that a certain word
or phrase is required in the search results, and a minus sign
indicates that a word or phrase must be absent in the search
results.
Note: A phrase must be contained within quotation marks.
Leave no spaces between the plus or minus sign and the term.
Use wildcards
Wildcard searches can expand the number of matches for a
particular request. The * character is used as the wildcard
character.
For instance, searching for wh* will find the words what, why,
when, whether, and any other word that starts with wh.
Searching for *her* will find the words here, whether, together,
gathering, and any other word that contains her anywhere in the
word.
Wildcards may be combined with the standard plus (+) and
minus (-) modifiers, quotes for phrases, as well as the field
search specifiers. +wh* -se*ch will find all pages which have a
word that starts with wh and which does not contain a word that
starts with se and ends with ch. "wh* are" will find the phrases
where are, what are, why are, etc.
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
Newsletter | Perl Conference 5.0:
July 23-27
If you are having difficulties logging in, make sure your browser is set
to accept cookies.
Forgotten your password? Need Help?
Login
Newsletter | Perl Conference 5.0: July 23-27
Search
Downloads
The P5P Digest
This digest, published weekly on Sundays, summarizes the
Documentation
activity on Perl 5 Porters list, the main mailing list for the core
developers of the Perl language.
CPAN
This Week on p5p 2001/07/09
FAQs No 5.8.0 yet, numeric hackery, worries about PerlIO and much
more. [Jul. 9, 2001]
Training
This Week on p5p 2001/07/02
Resources Module versioning and testing, regex capture-to-variable, and
much more. [Jul. 2, 2001]
Article Archive
This Week on p5p 2001/06/25
Books
5.7.2 in sight, some threads on regular expression, and much
Search more. [Jun. 25, 2001]
Pod::Parser Notes
Brad Appleton, author of the Pod::Parser module suite,
responds to some of the remarks in an earlier perl5-porters
mailing list summary. [May. 20, 2000]
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
Newsletter | Perl Conference 5.0: July 23-27
Search
Downloads
P6P Digest
The latest from the P6P Digest
Documentation
This Fortnight in Perl 6 (17 - 30 June 2001)
CPAN A detailed summary of a recent Perl vs. Java battle, a discussion
on the internal API for strings, and much more. [Jul. 3, 2001]
FAQs
This Week in Perl 6 (10 - 16 June 2001)
Training Even More on Unicode and Regexes, Multi-Dimensional
Arrays and Relational Databases, and much more. [Jun. 19,
Resources 2001]
Article Archive
This Week in Perl 6 (3 - 9 June 2001)
Books A discussion on the interaction of properties with use strict,
continuing arguements surrounding regular expressions, and
Search much more. [Jun. 12, 2001]
Downloads
Off The Wall
A monthly column from Larry Wall
Documentation
Larry Wall: Apocalypse Two
CPAN Larry Wall produces the next episode in his series of
"Apocalypses": glimpses into the design of Perl 6. This week,
FAQs he explains how Perl 6 will differ from Perl 5 in terms of
chapter 2 of the Camel Book: fundamental data types, variables
Training and the context and scoping of the language. [May. 3, 2001]
Resources Apocalypse 1: The Ugly, the Bad, and the Good
With breathless expectation, the Perl community has been
Article Archive
waiting for Larry Wall to reveal how Perl 6 is going to take
shape. In the first of a series of "apocalyptic" articles, Larry
Books
reveals the ugly, the bad, and the good parts of the Perl 6 design
Search process. [Apr. 2, 2001]
Register/Log in
Columns
P5P Digest
P6P Digest
Off the Wall
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
Newsletter | Perl Conference 5.0: July 23-27
Search
Downloads
This Week on p5p 2001/07/09
by Simon Cozens
Documentation
July 09, 2001
CPAN
Notes
FAQs
Please send corrections and additions to
Training [email protected] where This Week on P5P
YYYYMM is the current year and month. Changes and
additions to the perl5-porters biographies are particularly • No 5.8.0 Yet
Resources
welcome.
Article Archive • New Modules
This was a reasonably busy week, seeing just over 400
Books messages. I say that every week, don't I? • Numbers, numbers,
numbers
Search No 5.8.0 Yet
• PerlIO considered evil
Register/Log in Jarkko sadly announced that 5.8.0 wasn't going to happen
before the Perl Conference, but 5.7.2 is imminent:
• Asynchronous
I think it's time for me to give up the fantasy that Callbacks
Columns 5.8.0 will happen before the Perl Conference. The
P5P Digest stars just refuse to align properly, too many loose
• Various
P6P Digest ends, too many delays, too many annoying
mysterious little problems, too little testing of CPAN
Off the Wall
modules. Luckily, nothing is majorly broken, and I think that I've more or
less achieved what I set out to do with Perl, so I still hope to be able wrap
something up before TPC and call it 5.7.2 (it must happen next week or it
will not happen), and soon after the conference put out the Release
Candidate 1 for 5.8.0, and then keep cracking the whip till we are happy
with what we've got.
New Modules
These aren't really very new, but they may have slipped through the net and you
haven't noticed them yet, and since they're interesting, you might want to have a look...
I18N::LangTags detects and manipulates RFC3066 language tags;
Locale::Maketext is extremely useful for localizing text; Unicode::UCD is a
neat interface to the Unicode Character Database; Encode is coming on strong, and
can now read IBM ICU character tables; Mark-Jason Dominus' Memoize module is
now part of the core.
Asynchronous Callbacks
David Lloyd asked how do safely do asynchronous callbacks from C to Perl. Bejamin
Stuhl suggested hacking the core to introduce some checks during the inter-opcode
PERL_ASYNC_CHECK, and suggested that Perl 5.8.x had a public way of registering
inter-opcode callbacks. David Lloyd replied that PHP/Zend already had this, and you
could even implement a signal checking add-on module without any core hacking.
Paul Johnson went one further, and suggested using a pluggable runops routine.
Surprisingly, this has actually been implemented but nobody really knows about it;
Devel::Cover apparently makes use of it. Of course, the problem is that only one
thing can use a custom op loop at a time, so David suggested writing an XS module
that allowed other modules to add callbacks. I hope that happens.
Artur Bergman popped up and, predictably, suggested using ithreads.
Various
Rudi Farkas found a weird one on Win32 - on that platform, executableness (the -x
test) is determined by the filename being examined. For instance, foo.bat is classed
as executable, but foo.bar is not, even if they contain exactly the same data. This
rather curious design decision leads to the fact that if you call stat with a filename,
the execute bit is set depending on the extension. If, on the other hand, you call fstat
with a filehandle, Windows can't retrieve the filename and test the extension, so it
silently sets the execute bit to zero, no matter what it gets fed. This is Bad, and means
that -x _ on Windows is unpredictable. Radi provided a suggested workaround, but
nobody cared enough about fixing something so obviously braindead to produce a
patch.
Mike Schwern fixed up MakeMaker to stop producing extraneous -I...s when
building extensions, and also found that the XS version of Cwd won't do much good as
a separate CPAN module, since it relies on the core function sv_getcwd, which only
appears in 5.7.1. Oops. Oh, and speaking of Cwd, Ilya patched it up a bit for OS/2,
while noting that its results were untainted on that platform.
Ilya also fixed a glaring debugger bug (oh, the irony) prompting Jarkko to lament the
lack of a test suite. Robin fixed up a couple of weird, weird bugs in B::Deparse.
Jonathan Stowe upgraded pl2pm to be warnings and strict clean. I'm not sure why.
Philip Newton patched a score of typos. Norton Allen updated the QNX
documentation and provided a couple of other fixes.
Piers Cawley found something that looked like a bug in SUPER:: but was assured
that it wasn't; Randal won the day with a reference to Smalltalk.
Abhijit Menon-Sen (look out for this guy...) made mkdir warn if it was given a
non-octal literal, since that generally doesn't do what people want, and after prompting
from Gisle, did the same for umask and chmod. Unfortunately, he forgot about
constant folding...
Until next week I remain, your humble and obedient servant,
Simon Cozens
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
Newsletter | Perl Conference 5.0: July 23-27
Search
Downloads
People Behind Perl: Nathan
Torkington
Documentation
by Simon Cozens
CPAN July 03, 2001
FAQs So you use Perl, and you probably know that it was brought to you by "Larry Wall and
a cast of thousands". But do you know these people that make up the Perl development
Training team? Every month, we're going to be featuring an interview with a Perl Porter so you
can get to know the people behind Perl. This time, Simon Cozens, www.perl.com
Resources editor, talks to Nathan Torkington, a long-time Perl developer and a mainstay of the
Perl community.
Article Archive
Who are you and what do you do?
Books
I'm Nathan Torkington. My day job is a book editor for O'Reilly and Associates.
Search Before that I was a trainer, working for Tom Christiansen. Perl folks might know me
as co-author (with Tom) of The Perl Cookbook, the schedule planner for The Perl
Register/Log in Conference (and this year the Open Source Convention), or as the project manager for
perl6.
Columns
How long have you been programming Perl?
P5P Digest
P6P Digest Since the early 90s. I forget exactly when I first started programming in Perl. I think it
Off the Wall was toward the end of 1992, when I was working with gopher and the early web. Back
in those days we didn't talk about "the web", we were just trying to set up a
Campus-Wide Information Service. I took the plunge and pushed for (and got) the
www as the basis for the CWIS, even though Gopher was more mature and had more
stuff on it.
Using the CERN httpd and line mode browser, I worked on interfacing a bunch of data
sources to the web. Perl was, of course, the language for that. I did work with SGML,
comma separated files, and even used oraperl once or twice (I feared and loathed
Oracle, though, it was only once or twice!).
So I got into Perl with the web. When I moved to the US in 1996, I worked as a
systems administrator at an ISP. There I rapidly became the Perl guy, writing admin
scripts and CGI applications for in-house and customers. When I left in 1998, we were
using mod_perl and had a bunch of good Perl programmers.
Finally, what's the best thing about Perl, and what's the
worst thing about it?
Best thing? The way that it values programmer fun as much as anything else. Perl
delights in being a language that is supposed to be fun. Having seen many people burn
out, fun is a good thing. Fun is what keeps you sane, keeps you interested, keeps you
going.
What's the worst thing? Probably the internals. They're ugly and resemble nothing so
much as a Lovecraftian horror. We really want perl6 to have much nicer innards.
Ideally it'll be almost as simple to program in perl6 innards as it is to program in perl6
itself. That's one of the main reasons to have perl6--a cleaner core.
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
Newsletter | Perl Conference 5.0: July 23-27
Search
Downloads
This Fortnight in Perl 6 (17 - 30
June 2001)
Documentation
by Bryan Warnock
CPAN July 03, 2001
FAQs You can subscribe to an email version of this
summary by sending an empty message to This Week
Training [email protected]. Perl Doesn't Suck
Please send corrections and additions to Multiple Classifications
Resources
[email protected].
Article Archive Once Inherited, Twice Shy
The lists have been very light recently. During the
last two weeks of June, three of the mailing lists Class::Object
Books received a mere 142 messages across 20 different
threads. 40 different authors contributed. Only 5 The Internal String API
Search
threads generated much traffic. Eventually, I'll come
up with a better way of reporting these meaningless Miscellany
Register/Log in
metrics. Last Words
David Whipp asked if bless could take, and ref return, a list, allowing for a cleaner
multiple-inheritance model for objects in Perl. Dan Sugalski simplified the request to
object-based vice class-based inheritance, and then provided some potential trade-offs.
Damian, of course, submitted code to fake it in Perl 5. He did muse about an ISA
property, though, which would act like @ISA, but at the object level.
Class::Object
Since we're going to try and take a shot at being encoding-neutral in the
core, we're going to need some form of string API so the core can actually
manipulate string data. I'm thinking we'll need to be able to at least do this
with string:
● Convert from and to UTF-32
Miscellany
Simon Cozens released an updated version of his Perl 6 emulator.
Marcel Grunauer announced a Proof-of-Concepts page for Perl 6, which contains info
and links to Perl 5 modules that may provide a glimpse of things to come.
There were more complaints about operator choices. (Specifically, ~ for string
concatenation, and . (the dot) for dereference (vice ->).)
Last Words
There's but three weeks till TPC 5.0 kicks off in San Diego.
Bryan C. Warnock
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
Newsletter | Perl Conference 5.0: July 23-27
Search
Downloads
Why Not Translate Perl to C?
by Mark-Jason Dominus
Documentation
June 27, 2001
CPAN People often have the idea that automatically translating Perl to C and then compiling the
C will make their Perl programs run faster, because "C is much faster than Perl." This
FAQs article explains why this strategy is unlikely to work.
Training
Short Summary
Resources Your Perl program is being run by the Perl interpreter. You want a C program that does
the same thing that your Perl program does. A C program to do what your Perl program
Article Archive
does would have to do most of the same things that the Perl interpreter does when it runs
Books your Perl program. There is no reason to think that the C program could do those things
faster than the Perl interpreter does them, because the Perl interpreter itself is written in
Search very fast C.
Some detailed case studies follow.
Register/Log in
Built-In Functions
Columns Suppose your program needs to split a line into fields, and uses the Perl split function
P5P Digest to do so. You want to compile this to C so it will be faster.
P6P Digest
This is obviously not going to work, because the split function is already implemented
Off the Wall in C. If you have the Perl source code, you can see the implementation of split in the
file pp.c; it is in the function named pp_split. When your Perl program uses
split, Perl calls this pp_split function to do the splitting. pp_split is written in
C, and it has already been compiled to native machine code.
Now, suppose you want to translate your Perl program to C. How will you translate your
split call? The only thing you can do is translate it to a call to the C pp_split
function, or some other equivalent function that splits. There is no reason to believe that
any C implementation of split will be faster than the pp_split that Perl already has.
Years of work have gone into making pp_split as fast as possible.
You can make the same argument for all of Perl's other built-in functions, such as join,
printf, rand and readdir.
So much for built-in functions.
Data Structures
Why is Perl slow to begin with? One major reason is that its data structures are extremely
flexible, and this flexibility imposes a speed penalty.
Let's look in detail at an important example: strings. Consider this Perl code:
$x = 'foo';
$y = 'bar';
$x .= $y;
That is, we want to append $y to the end of $x. In C, this is extremely tricky. In C, you
would start by doing something like this:
char *x = "foo";
char *y = "bar";
Now you have a problem. You would like to insert bar at the end of the buffer pointed
to by x. But you can't, because there is not enough room; x only points to enough space
for four characters, and you need space for seven. (C strings always have an extra nul
character on the end.) To append y to x, you must allocate a new buffer, and then arrange
for x to point to the new buffer:
Here x and z are two variables that both contain pointers to the same buffer. We want to
append bar to the end of the string. But the C code we used above doesn't quite work,
because we allocated a new region of memory to hold the result, and then pointed x to it:
AFTER x = tmp:
It's tempting to think that we should just point z to the new buffer also, but in practice
this is impossible. The function that is doing the appending cannot know whether there is
such a z, or where it may be. There might be 100 variables like z all pointing to the old
buffer, and there is no good way to keep track of them so that they can all be changed
when the array moves.
Perl does support a transparent string append operation. Let's see how this works. In Perl,
a variable like $x does not point directly at the buffer. Instead, it points at a structure
called an SV. ('Scalar Value') The SV has the pointer to the buffer, and also some other
things that I do not show:
BEFORE $x .= $y
When you ask Perl to append bar to $x, it follows the pointers and finds that there is not
enough space in the buffer. So, just as in C, it allocates a new buffer and stores the result
in the new buffer. Then it fixes the pointer in the SV to point to the new buffer, and it
throws away the old buffer:
Now $x and $z have both changed. If there were any other variables sharing the SV,
their values would have changed also. This technique is called "double indirection,'" and
it is how Perl can support operations like .=. A similar principle applies for arrays; this
is how Perl can support the push function.
The flexibility comes at a price: Whenever you want to use the value of $x, Perl must
follow two pointers to get the value: The first to find the SV structure, and the second to
get to the buffer with the character data. This means that using a string in Perl takes at
least twice as long as in C. In C, you follow just one pointer.
If you want to compile Perl to C, you have a big problem. You would like to support
operations like .= and push, but C does not support these very well. There are only
three solutions:
1. Don't support .=
This is a bad solution, because after you disallow all the Perl operations like .=
and push what you have left is not very much like Perl; it is much more like C,
and then you might as well just write the program in C in the first place.
2. Do something extremely clever
Cleverness is in short supply this month. :)
3. Use a double-indirection technique in the compiled C code
This works, but the resulting C code will be slow, because you will have to
traverse twice as many pointers each time you want to look up the value of a
variable. But that is why Perl is slow! Perl is already doing the double-indirection
lookup in C, and the code to do this has already been compiled to native machine
code.
So again, it's not clear that you are going to get any benefit from translating Perl to C.
The slowness of Perl comes from the flexibility of the data structures. The code to
manipulate these structures is already written in C. If you translate a Perl program to C,
you have the choice of throwing away the flexibility of the data structure, in which case
you are now writing C programs with C structures, or keeping the flexibility with the
same speed penalty. You probably cannot speed up the data structures, because if anyone
knew how to make the structures faster and still keep them flexible, they would already
have made those changes in the C code for Perl itself.
int a[1000];
and use a fast C array of machine integers.
To do this, you have to be very clever and you have to think of a way of explaining to the
translator that @a will never be bigger than 1,000 elements and will only contain integers,
or a way for the translator to guess that just from looking at the Perl program.
People are planning these features for Perl 6 right now. For example, Larry Wall, the
author of Perl, plans that you will be able to declare a Perl array as
my int @a is dim(1000);
Then a Perl-to-C translator (or Perl itself) might be able to use a fast C array of machine
integers rather than a slow Perl array of SVs. If you are interested, you may want to join
the perl6-internals mailing list.
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
Newsletter | Perl Conference 5.0: July 23-27
Search
Downloads
This Week on p5p 2001/07/02
by Simon Cozens
Documentation
July 02, 2001
CPAN
Notes
FAQs
Please send corrections and additions to [email protected] where
Training YYYYMM is the current year and month. Changes and additions to the perl5-porters biographies This week on P5P
are particularly welcome.
• Notes
Resources
This was a reasonably normal week, seeing the usual 500 or so messages. • Module Versioning and
Article Archive Many thanks again to Leon for last week's summary. Testing
• Carpentry
Books Module Versioning and Testing • Regex
Capture-to-variable
Search There's a move on to make the modules under ext/ free-standing: that is, to be able to say • Perl on S390
cd ext/File/Glob • UTS Amdahl
Register/Log in
• Various
make dist
Columns and get a bundle that can be uploaded to CPAN or otherwise distributed. The only problem with this is tests. Currently the
P5P Digest tests are kept under t/ of the main root of the Perl source tree, and are run when a make test is done there. To make the
P6P Digest modules freestanding, you'd have to move the tests to ext/Foo/Bar/t/ and have the main make test also traverse the
Off the Wall extension subdirectories and run the tests there. But then, of course, there's another problem. Can you spot it?
make test is run from an uninstalled Perl, which needs explicit hints about where to find the Perl library. Hence, the tests
in t/ directly wibble @INC. This wouldn't work if we're making the modules freestanding, or if we move the tests to
ext/Foo/Bar/t/. So the trick, which nobody's done yet, is to move the tests to the right place, change the main make
test to recurse extension subdirectories, but also to propagate an environment variable telling the module where to find the
library. ( PERL5LIB is what you want for this.) That would be a nice little task for someone...
Speaking of testing, Schwern got Test::Simple and Test::More added to the core, bringing the first All Your Base
reference into the Perl source tree. Oh, and how many different testing mechanisms?
Robin Houston incremented B::Deparse's version number and added some change notes. Here's what's improved since
5.6.1:
Changes between 0.60 and 0.61 (mostly by Robin Houston)
- many bug-fixes
- support for pragmas and 'use'
- support for the little-used $[ variable
- support for __DATA__ sections
- UTF8 support
- BEGIN, CHECK, INIT and END blocks
- scoping of subroutine declarations fixed
- compile-time output from the input program can be suppressed, so that the
output is just the deparsed code. (a change to O.pm in fact)
- our() declarations
- *all* the known bugs are now listed in the BUGS section
- comprehensive test mechanism (TEST -deparse)
The new test mechanism is great: it runs the standard Perl test suite through B::Deparse and then back through Perl again
to ensure the deparsed code still passes the tests. And, as a testament to the work that's been done on B::Deparse, they
mostly do pass.
Schwern also bumped up ExtUtils::Manifest, which caused Jarkko to appeal for a script which checks two Perl
source trees to find updated versions of modules without a version change. Larry Shatzer provided one, and Jarkko used it to
update the versions in the current tree. Schwern also put Cwd on CPAN, and found a weird dynamic loading bug with the XS
version of Cwd. Oh, and noted that after his benchmarking, there's no significant performance loss between 5.6.1 without
PerlIO and bleadperl with it.
Carpentry
Mike Guy partially fixed a problem whereby when a magic variable like $1 is passed as a subroutine parameter, carp and
the debugger don't see it properly. Tony Bowden took the opportunity to ask for either more or less documentation for
longmess and shortmess depending on whether or not they were meant to be internal to Carp. Tony wrote a
documentation patch himself.
Schwern asked for a better name for those functions, perhaps more in line with the carp/croak/cluck theme. Jarkko suggested
yodel and yelp which Schwern implemented.
Andreas had a quick bitch about Schwern's, uh, idiosyncratic naming style:
Your style of naming things is just plain sick:
AnyLoader does anything but interface to any loader. Ima::DBI has something to do with DBI, but nothing with
Ima. D::oh is the only really funny one. But it's from 1999 and getting old. Sex: I still don't know if it is fun or
what. Bone::Easy? Same here. Semi::Semicolon? Same here.
And now yodle!
Unfair, though, since yodel and yelp weren't his...
However, Hugo objected to yodel/ yelp because the other verbs write to standard error, hence "speaking" whereas
longmess and shortmess don't actually "say" anything. Jarkko agreed, and there the matter rested. (Modulo Rich
Lafferty's suggestion of "flame" for objections in a written medium...)
Regex Capture-to-variable
Jeffrey Friedl (he of the Regexp book) came up with an interesting patch which adds the new special variable $^N for the
most-recently assigned bracket match. This is different from $+ which is the highest numbered match; that's to say, given
/(foo(bar))/
then $+ is equivalent to $2, whereas $^N is equivalent to the bracket match for the last closing bracket; that is, $1. This
essentially allows you to do capture-to-variable, like this:
(?<$phone_number>\d+)
work. Now that's cool.
Phillip Newton added a nmenomic: $^N is the most recently closed Nested parenthesis.
Perl on S390
Hal Morris got Perl going on Linux/390, with only one test failing. Good news for the new generation of mainframe hackers.
There's mixed news for the old-timers, though; Peter Prymmer has got it down to 10 test failures, but one of the tests
completely hangs Perl. Apparently study under OS/390 is best avoided. He also started some investigation of a Bigint
bug, under the direction of Tels and John Peacock, but left for his holidays and the discussion moved to the perl-mvs
mailing list.
UTS Amdahl
Oh, and talking of weird platforms, UTS. Hal (who's actually from UTS Global, so much kudos there) has been testing out
recent Perl builds on UTS, and turning up some ... take a deep breath ... icky numeric conversion issues.
Nicholas Clark was convinced they (well, some of them at least) were due to UTS C going through a foo-- statement twice,
but Hal pointed out he didn't expect UTS C to be quite that braindead. On the other hand, Nick's analysis looked convincing...
Hal also fixed up hints/uts.sh so that UTS now configures and builds nicely at least.
Various
David Wheeler found a known but really, really weird bug with lexical arrays; if you do:
my @a = foo(); my @b = foo();
sub foo { $x = 0; my @ary; push @ary, "hi" if $x; push @ary, "ho"; return @ary }
@a gets "ho" as you'd expect, but @b gets "ho","ho". Ronald Kimball told him Not To Do That, Then.
Peter Prymmer noted that Perl on VMS was bailing out during the test suite, leading to lots of bogus failures. This only
happens if none of the DBM libraries (GDBM, DB_File, NDBM or SDBM) were built. As the first three require external
libraries that VMS doesn't have and the last one is currently broken, it's no wonder Perl is bailing out. The fix is to work out
why SDBM has stopped building on VMS. Peter also produced a lot of other VMS and HPUX reports.
Andy was pleasantly surprised to note that the promised "binary compatibility with 5.005" actually works even in bleadperl.
Perhaps we need to break more things.
John Peacock asked a portability question for XS bit-twiddling; he's trying to adapt a math library which depends on casting
two numbers to a long and adding them together to avoid overflow. Jarkko's fantastic architecture experience was brought to
bear as he revealed that Cray Unicos has long == short == int == double. Oh, and type casting has issues too, so
you have to use a union. Nicholas Clark suggested the old trick of comparing the operands of an addition with the result; if
the result is smaller than either of the operands, you've overflowed, so you add a carry and off you go.
The news that GCC 3.0 was out brought a rush of people testing Perl out with it; I got it through on Linux with all tests
successful, as did H. Merijn Brand on HPUX, but with rather a lot more warnings. This was because HPUX messed up the
test for __attribute__ due to using a HP linker instead of a GNU one. Merijn and Jarkko got this fixed up.
Artur continued his iThreads quest; he renamed the "shared" attribute to "static", (and then again to "unique" after objections)
presumably to free it up for an attribute which actually does share variables between interpreters, and also added a function
which cloned the Perl host. He said that threads-0.01, the new threading module, will be released to CPAN when 5.7.2
hits the road. (Which Jarkko keeps hinting will be very, very, very soon now.) He also complained bitterly when Marcel
Grunauer tried to document attributes.pm as useful, despite the fact that Marcel has some really very cool modules on
CPAN based on it...
Marcel also found, and Radu Greab fixed, an insiduous bug in split, whereby if the default whitespace pattern was used
for one iteration of a loop, it would be used for all succeeding ones; the PMf_WHITE flag for the regular expression was
being set but never unset. Urgh.
Ilya produced some rough changes documentation for OS/2, as well as some other little patches. Norton Allen provided some
QNX updates.
Phillip Newton documented the neat
$count = () = function()
idiom for counting the number of return values from an operation. That was something I hadn't seen before; you learn
something new every day... Until next week I remain, your humble and obedient servant,
Simon Cozens
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their respective owners.
For problems or assistance with this site, email [email protected]
Newsletter | Perl Conference 5.0: July 23-27
Search
Downloads
Yet Another YAPC Report:
Montreal
Documentation
by Schuyler Erle
CPAN June 21, 2001
FAQs A year ago, at Yet Another Perl Conference North America 19100, both
Perl-the-language and Perl-the-community seemed to be headed for trouble. Longtime
Training Perl hackers spoke openly with concern at the apparent stagnation of Perl 5
development, and how the community seemed to be increasingly bogged down by
Resources acrimony and bickering. Now, a year later, the tide has already turned and the evidence
is nowhere more apparent than at this year's YAPC::NA in Montreal.
Article Archive
The conference, produced by Yet Another Society, was a smashing success. More than
Books 350 Perl Mongers converged from all across North America and Europe on McGill
University for the three-day event. Rich Lafferty and Luc St. Louis, key organizers
Search from the Montreal.pm group, did a brilliant job of lining everything up; and Kevin
Lenzo, YAS president, once again did the crucial fund raising and promotional work to
Register/Log in make the conference a reality.
Certain familiar faces were missing from this year's conference, including Larry
Columns himself, who was scheduled to deliver the keynote but was absent due to illness. (Get
well soon, Larry!) The unenviable task of filling Larry Wall's shoes for the highly
P5P Digest anticipated opening talk fell to the infamous Dr. Damian Conway, indentured servant
P6P Digest to the Perl community and lecturer extraordinaire. Those of you who have seen
Off the Wall Damian in action will have probably guessed that his presentation did not disappoint.
The topic was, of course, a tour of the past and future of the Perl language -- where we
have come (a long way from Perl 1 in 1987) and where are going (a long way yet to
Perl 6).
To hear Damian tell it, Perl 6 looks like it's going to be awesome. While many details
are still sketchy, the intention from all quarters is to preserve all the things we like
about Perl today, especially its tendency to be eclectic in its incorporation of ideas and
features from other languages. Larry, Damian and others have carefully studied the
lessons of such languages as Java, Python, Ruby, and even the infant C#, in the hopes
of applying those lessons to Perl 6.
Damian's keynote also focused on how Perl 6 will attempt to correct some of the flaws
and deficiencies of Perl 5, the details of which can be found elsewhere, so I won't
reiterate them here. Additionally, he emphasized that, due to the unexpected quantity
and scope of the Perl 6 RFCs, the final language design will take Larry far longer than
anyone originally imagined. Damian went on to predict a usable alpha version of Perl 6
being ready by May 2002, with a full release perhaps available by October 2002.
However, as pieces of the Perl 6 design stabilize, Damian and others (including our
own Simon Cozens) will be implementing them in Perl 5, so that we can start playing
with Perl 6 today, rather than next year.
Meanwhile, the continued enthusiasm and energy being devoted to Perl 6 has had a
profound impact on the community at large that is hard to overstate. YAPC::NA 2001
was marked not merely by much discussion and speculation on Perl 6, but also by
fascinating new developments in Perl. One of the downright niftiest of these new
directions is Brian Ingerson's Inline.pm, which he presented in a 90-minute talk
Wednesday. Inline.pm uses a form of plug-in architecture to allow seamless
embedding of other languages like C, C++, Java, and, yes, Python, right into ordinary
Perl scripts. Brian, who works at ActiveState, has already written a www.perl.com
feature on Inline.pm, so I'll merely mention here that the module hides away the
frighteningly ugly details of gluing disparate languages together, in the most intuitive
way possible. This kind of development is really exciting for the ways in which it
opens new doors and breeds new ideas on the many, many different kinds of intriguing
things that can still be done with Perl 5. Incidentally, Brian's midlecture sing-a-longs
about Perl internals and so forth were also quite well regarded.
The hubbub around Inline.pm was just one thread in the theme of "Perl as glue
language for the 21st Century," a theme visited and revisited at many times and places
throughout the conference. The notion was raised again by Perl 6 project manager
Nathan Torkington in his presentation at Adam "Ziggy" Turoff's Perl Apprenticeship
Workshop on Wednesday. Amidst the announcement of many interesting and valuable
projects in need of Perl hackers, Gnat issued a call to "make a Python friend" and
collaborate with them on a development project. "Show them we're not *all* evil!" he
insisted, in marked contrast to his howlingly funny diatribe on Python at the previous
year's Lightning Talks.
"I was surprised that Gnat took that approach, because I thought I would be left this
year to argue the other side," ActiveState's Neil Kandalgaonkar observed, after giving
his Friday morning talk on "Programming Parrot," so named for its case study in
getting Perl and Python applications to work in concert. Part of Neil's tale of success
lay in using Web services to get different processes running in different languages on
different machines to exchange data reliably. "All it took was an extra four lines of
scripting in each language, and I was done," he noted, driving home the importance of
using and extending Perl's ability to talk to other languages and applications.
Meanwhile, YAPC North America 2001 also showed growth in the depth and scope of
the conference's offerings. In contrast to previous years, where talks were largely
aimed at beginner and intermediate Perl hackers, this year's presentations covered
some more advanced topics, such as Nat Torkington's three-hour lesson on the Perl
internals that he delivered to a packed house Thursday. Originally written by Simon
Cozens (who was unable to attend), the Perl internals class presented a concise
introduction to some of Perl's inner workings, furthering the Perl community's
expressed goal of lowering the barrier of entry to internals hacking and encouraging
wider participation in Perl core development. Later in the day, Michael Schwern
addressed the ever-present tendency of Perl hackers to rely on Perl's forgiving nature in
his rather well-attended talk on "Disciplined Programming, or, How to Be Lazy
without Trying." "Always code Perl as if you were writing for CPAN," Schwern urged
his audience. "Document and test as you go, and release working versions often."
Speaking of which, the Comprehensive Perl Archive Network was also a major topic
of discussion at YAPC. "The CPAN is Perl's killer app," Gnat said at one point. "No
other language has anything like it." Neil and Brian gave a short presentation on their
experiences building and maintaining ActiveState's PPM repository, a collection of
binary distributions of CPAN modules. The dynamic duo from Vancouver yielded
some of their time to Schwern to allow him to discuss his proposed CPANTS project,
intended to automate testing and quality verification of modules in the repository.
Metadata, rating systems, trust metrics and peer-to-peer distribution models were all
touched on. Based on the buzz this year, it seems reasonable to predict that many new
and exciting things are likely to grow up around the CPAN, and around the
possibilities inherent in the distribution of Perl modules, in the not-too-distant future.
The final talk Thursday was once more delivered by Damian Conway, and curiosity
had spread far and wide on how he might top last year's now-legendary presentation on
Quantum::Superpositions. This year's Thursday afternoon plenary lecture was merely
titled, "Life, the Universe, and Everything," in homage to the late Mr. Adams; and, true
to his word, Damian delivered just that. Swooping from Conway's Game of Life (no
relation), to a source filter for programming Perl in Klingon (a la Perligata), to the
paradox of Maxwell's Demon (conveniently dispelled with a little help from
Quantum::Superpositions), Damian's talk was a masterful reflection of all the things
we love about Perl: It was clever, complex, elegant, and, most of all, it was fun.
(Parenthetically, among the modules that Damian introduced at this talk was a little
number called Sub::Junctive. As a linguist, I must confess it scares the living heck
outta me. Look for it on the CPAN.)
Friday featured more of this year's theme of Perl as
glue-language-for-the-21st-Century in two talks on Web services by Adam "Ziggy"
Turoff and Nat Torkington, in which Nat issued an impassioned plea for a Perl
implementation of Freenet. However, the morning's highlight was without a doubt the
much-anticipated Lightning Talks. Hosted once again by the irrepressible Mark-Jason
Dominus, the 90-minute series of five-minute short talks went over quite well,
featuring topics ranging from how hacking Perl is like Japanese food and the graphing
of IRC conversations to a call for more political action from within hackerdom and an
overview of the Everything Engine. The showstopper, however, was once again
Damian, who is generally reputed to be unable to hold forth on any topic for anything
*less* than an hour and a half. To everyone's surprise, the Lightning Talk consisted of
a hilarious argument in the grand Shakespearean style between Damian and Brian
Ingerson, over the disputed authorship of Inline::Files, a nifty new module for
extending the capabilities of the old DATA filehandle. Their invective-laden dialogue
was the most brilliantly humorous five minutes of the entire conference, and, yes,
Damian even managed to finished on time. :) If you had the misfortune not to be
present, you might be lucky enough to see them have at each other again at this year's
Perl Conference 5 in San Diego.
Later in the day, Nat and Damian chaired a Perl 6 status meeting, reviewing the major
events in Perl 6 starting with the announcement at TPC4, and working forward to the
present language design phase. "This is a fresh rebirth for Perl AND for the
community," Gnat said at one point. "Everything changes." The sometimes fractious
attitudes encountered on the various Perl mailing lists were discussed. "In some ways
this is a meritocracy," Gnat confessed. "Write good patches and we will love you."
Kirrily "Skud" Robert then spoke at length on the future of the core Perl modules, and
on the need to develop guidelines to direct the process of porting them to Perl 6.
Finally, the plenary session Friday afternoon closed the conference with another
presentation from, you guessed it, Damian Conway. Our Mr. Conway took the
opportunity to thank Yet Another Society and its sponsors for all of the contributions
that permitted him to take a year off from academia to work exclusively on Perl. He
then reviewed some of the fruits of that labor to date, including NEXT.pm,
Inline::Files and the brilliant Filter::Simple, all of which, it should be pointed out, are
now freely available to the community.
It has been nearly a year since Jon Orwant's now-legendary coffee-mug-tossing
tantrum at TPC4 touched off the decision to begin work on Perl 6. After the grueling
RFC process, the endless mailing list discussions and the breathless wait to see what
Larry would come through with, Perl 6 the language and Perl 6 the community finally
appear to be taking shape right before our eyes. New innovations are coming along
more and more often, including Larry's Apocalypses, Brian's Inline modules, all of the
potential emerging from the Web services meme, the future of the CPAN, new projects
like Reefknot -- including continuing projects such as POE and Mason -- and, last but
not least, whatever the heck it is that Damian is working on this week.
The Yet Another Perl Conferences are evolving, as well. Although neither Larry nor
Randal nor Orwant could make it this year, the turnout was nevertheless such that, no
matter where you looked at the conference, there you might find someone you knew
from IRC, from the mailing lists, from previous conferences or for the great work that
person had done for Perl. Although I've only touched on some highlights, there were
dozens of presenters at this year's conference, practically all of them had something
fascinating to say, and I really wish I had more time and space to cover them all.
Finally, it's safe to say that YAPC::NA clearly defined its own existence as a growing
concern of the community this year, having at last separated from its birthplace at
Carnegie Mellon in Pittsburgh. Montreal, as it turns out, is a fantastic, vibrant place to
hold a summer conference, with countless magnificent restaurants and bars suitable for
hosting the heady after-hours carousings of the Perl community. From every report, a
good time was had by nearly all, and I think we all eagerly await the next
YAPC::America::North, wherever it may be held.
Compilation Copyright © 1998-2001 O'Reilly & Associates, Inc. All Rights Reserved.
All trademarks and registered trademarks appearing on perl.com are the property of their
respective owners.
For problems or assistance with this site, email [email protected]
Newsletter | Perl Conference 5.0: July 23-27
Search
Downloads
Parse::RecDescent Tutorial
by Jeffrey Goff
Documentation
June 13, 2001
CPAN
The Basics
FAQs
Parse::RecDescent is a combination compiler and interpreter. The language it uses can be thought of roughly as a
Training macro language like CPP's, but the macros take no parameters. This may seem limiting, but the technique is very
powerful nonetheless. Our macro language looks like this:
Resources
macro_name : macro_body
Article Archive
A colon separates the macro's name and body, and the body can have any combination of explicit strings ("string,
Books with optional spaces"), a regular expression (/typical (?=perl) expression/), or another macro that's
defined somewhere in the source file. It can also have alternations. So, a sample source file could look like:
Search
startrule : day month /\d+/ # Match strings of the form "Sat Jun 15"
Register/Log in
#!/usr/bin/perl
use Parse::RecDescent;
Getting Data
Now, this is quite a bit of work to go to simply to match a string. However, much, much more can be done. One
element missing from this picture is capturing data. So far the sample grammar can tell if a string matches a regular
expression, but it can't tell us what the data it's parsed is. Well, these macros can be told to run perl code when
encountered.
Perl code goes after the end of a rule, enclosed in braces. When the interpreter recognizes a macro such as
startrule, the text matched is saved and passed to the perl code embedded in the grammar.
Each word or term of the macro ('day', 'month'...) is saved by the interpreter. dayrule gets saved into the
$item{day} hash entry, as does monthrule. The /\d+/ term doesn't have a corresponding name, so its data
comes from the @item array. $item[0] is always the rule name, so /\d+/ gets saved into $item[3]. So, code
to print the parsed output from our sample startrule rule looks like this:
startrule : day month /\d+/
{ print "Day: $item{day} Month: $item{month} Date: $item[3]\n"; }
Everything in the parser is run as if it was in the Parse::RecDescent package, so when calling subroutines outside
Parse::RecDescent, either qualify them as Package::Name->my_sub() or subclass Parse::RecDescent.
A Mini-Language
All of the pieces are now in place to create a miniature language, compile, and run code in it. To make matters
simple, the language will only have two types of instruction: Assign and Print. A sample 'Assign' instruction could
look like foo = 3 + a. The 'Print' statement will look like print foo / 2. Add the fact that 3 + a can be
arbitrarily long (temp = 3+a/2*4), and now you've got a non-trivial parsing problem.
The easiest instruction to implement is the 'Print' instruction. Assuming for the moment that the right-hand side of
the statement (the foo / 2 part of print foo / 2) already has a rule associated with it (called 'expression'),
the 'Print' instruction is very simple:
instruction : print_instruction
| assign_instruction
In order to make the startrule expand to the instruction rule, we'd ordinarily use a rule like startrule
: instruction. However, most languages let you enter more than one instruction in a source file. One way to
do this would be to create a recursive rule that would look like this:
expression : INTEGER
| VARIABLE
{ return $main::VARIABLE{$item{VARIABLE}} }
The VARIABLE rule has one minor quirk. In order to compute the value of the expression, variables have to be
given a value. In order to modify the text parsed, simply have the code return the modified text. In this case, the perl
code looks up the variable in %main::VARIABLE and returns the value of the variable rather than the text.
Those two lines take care of the case of an expression with a single term. Multiple-term expressions (such as 7+5
and foo+bar/2) are a little harder to deal with. The rules for a single expression like a+7 would look roughly
like:
sub expression {
shift;
my ($lhs,$op,$rhs) = @_;
return eval "$lhs $op $rhs";
}
That completes our grammar. Testing is fairly simple. Write some code in the new language, like "a = 3 + 5; b = a +
2; print a; print b", and pass it to the $parser->startrule() method to interpret the string.
The file included with this article comes with several test samples. The grammar in the tutorial is very simple, so
plenty of room to experiment remains. One simple modification is to change the INTEGER rule to account for
floating point numbers. Unary operators (single-term such as sin()) can be added to the expression rule, and
statements other than 'print' and 'assign' can be added easily.
Other modifications might include adding strings (some experimental extensions such as '<perl_quotelike>' may
help). Changing the grammar to include parentheses and proper precedence are other possible projects.
Closing
Parse::RecDescent is a powerful but difficult-to-undertstand module. Most of this is because parsing a language can
be difficult to understand. However, as long as the language has a fairly consistent grammar (or one can be written),
it's generally possible to translate it into a grammar that Parse::RecDescent can handle.
Many languages have their grammars available on the Internet. Grammars can usually be found in search engines
under the keyword 'BNF', standing for 'Backus-Naur Form'. These grammars aren't quite in the form
Parse::RecDescent prefers, but can usually be modified to suit.
When writing your own grammars for Parse::RecDescent, one important rule to keep in mind is that a rule can never
have itself as the first term. This makes rules such as statement : statement ";" statements illegal.
This sort of grammar is called "left-recursive" because a rule in the grammar expands to its left side.
Left-recursive grammars can usually be rewritten to right-recursive, which will parse cleanly under
Parse::RecDescent, but there are classes of grammars thatcant be rewritten to be right-recursive. If a grammar can't
be done in Parse::RecDescent, then something like Parse::Yapp may be more appropriate. It's also possible to
coerce yacc into generating a perl skeleton, supposedly.
Hopefully some of the shroud of mystery over Parse::RecDescent has been lifted, and more people will use this
incredibly powerful module.
#!/usr/bin/perl -w
use strict;
use Parse::RecDescent;
use Data::Dumper;
my $grammar = <<'_EOGRAMMAR_';
instruction : print_instruction
| assign_instruction
_EOGRAMMAR_
sub expression {
shift;
my ($lhs,$op,$rhs) = @_;
$lhs = $VARIABLE{$lhs} if $lhs=~/[^-+0-9]/;
return eval "$lhs $op $rhs";
}
my $parser = Parse::RecDescent->new($grammar);
Search
Product List
Perl Runs Sweden's Pension System: A
Press Room Fallback Application Built in Six Months Earns the
Jobs Prime Role
Resource by Ed Stephenson
Centers
6 July 2001
Perl
By the spring of 2000, Swedish government officials were pretty nervous. The delivery date
Java on a major computer application was already a year late, causing a highly publicized delay in
Web & Internet the start of the nation's new money-market pension system. With the legal deadline
approaching for the system's launch, the government gave PPM--the agency in charge--six
Open Source months to develop a fallback application, just in case the main commercial program hit
XML another snag.
Linux "Those were the days when stocks only went up," remarks Henrik Sandell, appraising the
government's anxious mood at the time. PPM hired Sandell, an independent consultant, and
Unix
Henrik Johnson from GlobeCom AB, an information technology services company in
Python Stockholm, to design the back-up application for Sweden's Premium Pension System, with
Macintosh the simple directive that they provide something usable very quickly. "In the beginning PPM
didn't much care what we used to develop our system, since they were fairly convinced it
Windows would never be put in production."
.NET Given the time crunch, Sandell and Johnson's team built the application (known as Pluto)
Oracle with Perl, using an Oracle database. Not only did they deliver the application on time, but
when the commercial system proved difficult to customize and install--despite two years of
Security modification by numerous developers--Pluto demanded a serious look. "An evaluation
Sys/Network Admin indicated that our system was faster and more likely to succeed than the original
application," Sandell points out, at a fraction of the cost. PPM was convinced, and Pluto
C/C++ Programming became the Premium Pension System's application of choice.
Design & Graphics
Learn more about Perl at the Perl Conference 5, July
Visual Basic
23-27, 2001, in San Diego, California.
Any doubt that a Perl-based application would be robust enough to handle a large,
mission-critical, financial-batch system has been dispelled by Pluto's performance with the
Swedish national pension since its launch in the fall of 2000. More than 5 million customers
take part in the system, representing every working person in Sweden born in 1938 and after.
Special
(The country's population is roughly 9 million.) A portion of every individual's employment
Interest
tax, equal to 2.5 percent of his or her declared income, is set aside specifically for pension
investment, and each person can choose up to 5 mutual funds from a list of 450 commercial
Ask Tim funds approved by PPM. Combined, individual accounts exceed 6 billion in U.S. dollars.
Frankly Speaking
Perl Wins the Comparison
Ron's VB Forum
Beta Chapters Sandell has worked with GlobeCom's Henrik Johnson on several projects over the years,
Letters using Perl for system administration and Web development since 1994. They immediately
considered using Perl for Pluto as well, mainly because the language facilitates rapid
elists development. But the complexity of the pension application demanded they also look at
Events other alternatives.
Palm OS The new PPM agency needed a system that would help it manage individual accounts,
aggregate the orders, buy the mutual funds, keep track of how many fund-parts each
Missing Manual
individual owns, and pay dividends to fund holders, among many other functions.
User Groups Calculations had to be absolutely correct, with multiple layers of check programs, and in
order for PPM to run batches in a reasonable amount of time, the system needed to process a
Catalog Request
large number of accounts per minute. "Traceability" was also a big concern. "We had to be
Specials able to examine calculations afterwards in order to answer questions such as, 'Why did
customer A buy fund B on the 4th of March?'" Sandell explains.
Write for Us
Good database connectivity gave Perl the nod over C++, and since
Patient-Centered Sandell and Johnson received project text files in various formats, An evaluation
Guides Perl's ability to parse text with regular expressions was much better indicated that our
than COBOL or Oracle's PL/SQL. And Perl 5's relative longevity [Perl] system was
provided the stability they required. The only question was faster and more
performance, given that the processing speed of interpreted likely to succeed ...
languages such as Perl is much slower than that of compiled at a fraction of the
languages like C++. cost. Pluto became
the Premium
"That was an issue all along," Sandell notes, "and we made tests Pension System's
with large volumes from the start. The application seldom spends application of
more than 20 percent of the time executing Perl code, while the choice.
database API and the database itself uses the other 80 percent. Even
if we had an infinitely fast programming language, the overall performance would be only
marginally better."
Convinced that processing speed wasn't a factor, Sandell and Johnson decided that Perl was
best for the application. The toughest part was finding enough experienced developers in
Sweden who knew Perl. The team sent requests to IT consulting firms (approved by PPM)
throughout the country, and came up with a couple of good candidates, but they didn't get as
many qualified programmers as they wanted.
So, although Pluto is written primarily in Perl, the team was forced to rely on other
languages for various functions. They wrote the Web applications in Jscript, and other parts
of the system in Visual Basic. Some functions were written in PL/SQL so they could be
accessible from other languages using the system. "If we did the project again, we would
probably strive to make more of it in Perl," Sandell concedes. But with so little time, they
couldn't ask team members to learn a new language.
● Learn how large and small companies are putting Perl to work by reading other Perl
Success Stories.
● Visit perl.oreilly.com for a complete list of O'Reilly's Perl books and www.perl.com
for the latest news and CPAN updates.
Return to: perl.oreilly.com
NuSphere announces
two new products NuSphere proudly announces the commercial release
that will accelerate of Enhanced MySQL with NuSphere MySQL
the development of Advantage and NuSphere Pro Advantage V2.2.
PHP and MySQL Enhanced MySQL brings together MySQL, the #1
driven web open source database, and the power of Gemini,
NuSphere's MySQL table type. Gemini tables provide
applications"
row-level locking, robust transaction support, and
NuSphere reliable crash recovery. With Gemini, Enhanced 09-Jul - Chicago
Announces MySQL delivers the enhanced database technologies 09-Jul - Vancouver, B.C
you need to develop business-critical web
Nationwide Training 09-Jul - Bedford
applications. Learn more about Enhanced MySQL.
Program for PHP 16-Jul - San Francisco
Developers Business Partners and Resellers -- Join Us! 16-Jul - Bedford
19-Jul - Dallas
Product Selling a MySQL-based application? Embed the extra
value of NuSphere MySQL and blow away your 30-Jul - Atlanta
Announcement!
Version 2.2 of the competition! Reselling software? Give your
Advantage product customers the open source web development platform
suite includes they need to do the job right. NuSphere Business
Partners and Resellers are eligible for product
Gemini and PHPEd.
discounts, training, support, co-marketing and much
To learn more, see more. Complete a brief application and we'll get back
What's New. to you right away with information on the Partner
Enhanced MySQL Program that's right for you. Can't wait? Contact sales
at 1-781-280-4600, or [email protected].
announced and
Allegro
MicroSystems reaps
the rewards
What's New
Explore the diverse and comprehensive line of web development and Each NuSphere product
NuSphere MySQL
Advantage
deployment environments that NuSphere has built on the best-of-breed open includes our integrated
NuSphere PHPEd
source components you already know and love. open source web
Advantage development platform.
NuSphere Pro Advantage products
Advantage technology
Advantage Plus NuSphere products focus on three Advantage suites: NuSphere® MySQL™ enhancements plus
NuSphere MySQL
Advantage, NuSphere® PHPEd Advantage, and NuSphere® Pro Advantage. quarterly updates of the
Getting Started platform and "extras".
Professional Tools and
Each software suite pairs the reliability and cost-effectiveness of Apache,
Applications MySQL, PHP and Perl with new technology enhancements for building
business-critical web applications. NuSphere has created an integrated
foundation that allows companies to deploy reliable, cost-effective,
enterprise-class applications for Windows, UNIX and Linux environments.
NuSphere products begin with a web development platform that includes
integrated, tested versions of Apache, MySQL, PHP and Perl. We then
enhance the core platform with technology and tools that boost productivity
and accelerate your success. The real Advantage is that every quarter we
update the web development platform and deliver new applications and tools.
The Advantage suites:
NuSphere MySQL Advantage includes the integrated
web development platform and Enhanced MySQL.
Enhanced MySQL brings together MySQL and the
power of Gemini, a MySQL table type designed by
NuSphere.
NuSphere PHPEd Advantage includes the integrated
web development platform and the power of PHPEd,
an Integrated Development Environment (IDE) for
Windows.
NuSphere Pro Advantage is a complete Internet
Application Platform (IAP), which includes the
integrated web development platform, Enhanced
MySQL and PHPEd. Designed for professional
developers, this Advantage provides a complete
front-to-back solution for creating, deploying and
managing your web infrastructure.
Advantage Plus. "Super size" your Advantage
purchase by adding phone support for MySQL, PHP or
both
TOP
Get the integrated environment that brings together today's popular open
source components into one 10 minute install. NuSphere MySQL is an
integrated distribution of MySQL, Apache, Perl, and PHP, and comes with
binaries and source code for RedHat Linux and Windows platforms. If you are
already a MySQL user, step up to the NuSphere MySQL Advantage.
NuSphere MySQL - $79.00
● 32 MB RAM
● 100 MB disk space
What's New
Conference.NET
San Francisco, CA Aug.
13, 2001
20010710095117
phpLittleChat 0.1 Beta (Default)
APACHE FAQs
A little PHP chat without using a constant
connection to a Web server. Why does Apache
Freshmeat Daily News
'lock-up' when accessed
New article in the Microsoft focus area: Running from Netscape 2?
Snort on IIS Web Servers, Part Two: Advanc
How can I control what
Security Focus server information is
given in the HTTP
ApacheCon 2001 announces 70 speakers
response header?
From BusinessWire: The Apache Software
Foundation today announced over 70 speaker Where can I find
sessions for this spring's ApacheCon 2001, the
mod_rewrite rulesets
annual conference and exhibition for
Apache-related and open-source software. The which already solve
next wave of Apache deployed projects will be particular URL-related
discussed at the Santa Clara Convention Centre in problems?
the heart of Silicon Valley, 4 through 6 April,
2001. ApacheCon 2001 will provide a look at the
future of Apache ...
NewsForge
MODULE NEWS
Python Software Foundation launched
From PR Newswire: "At the ninth Python mod_layout 2.10.2 released
Conference, Guido van Rossum announced the The bug fix is that cookies
launch of the Python Software Foundation (PSF). are now passed during a
Modeled after the successful Apache Software MAIN request when using
Foundation, the PSF's mandate is to provide merge regardless of HTTP
educational, legal and financial resources to the header override usage.
Python community. Responsible for holding
Python's intellectual property, the PSF will also mod_plsql 0.3.5 (Default)
act as an educational resource, maintain the Allows you to create Web
Python website, and ... applications using Oracle
NewsForge stored procedures.
Apache regains ground lost to MS mod_ssl 2.8.1-1.3.19
The Register Mar 5 2001 7:14PM ET Upgraded to Apache 1.3.19
Moreover Microsoft news as the base version;
Apache Toolbox 1.5.12 (Default) Conditionally adjusted the
An Apache compilation toolbox. source to also build quietly
Freshmeat Daily News under latest OpenSSL
0.9.7-dev versions; Extended
Consider Apache FAQ entry for MSIE
This Linuxtoday.com.au article asks you to problems.Fixed: Applied a
consider the Apache project, and all it's bunch of (untested!)
contributed to the core of the web. " If you're a adjustments and fixes for the
server administrator by profession - then of course Win32 platform, as posted to
you would know quite a bit. But for the rest of us modssl-users some time ago
IT professionals out there, I'm about to give you a by various people; The
crash course in how most of the WWW road on SSLCipherSuite example in
the Internet is built, and how it came to be that 'httpd.conf-dist'. The string
way." EXP56 is actually
NewsForge EXPORT56, although in
OpenSSL internally the var
Red Carpet
I played with Red Carpet and Evolution a bit Apache-ContentHandler-1.3.2
today. Red Carpet is cool, although it told me that mod_perl extension for
it would have to remove mod_ssl to install a uniform application
security update to Apache, which doesn't seem all
mod_proxy_add_forward.c
that useful. I still haven't found the docs on
creating my own Red Carpet channels. I couldn't 1.2 (Default)
get Evolution to read my mailbox, so I gave up on Adds an 'X-Forwarded-For'
it for now. header to outgoing proxy
Hack the Planet requests like Squid.