Module - 4 - Unix System Programming (BCS515C)
Module - 4 - Unix System Programming (BCS515C)
Prototype
#include <sys/types.h>
#include <unistd.h>
int setuid (uid_t uid);
int setgid (gid_t gid);
Both return: 0 if OK, 1 on error
Rules
1. If the process has superuser privilege, the setuid function sets – real
user ID, effective user ID , saved set-user-ID to uid
2. If the process doesnot have superuser privilege, but uid equals either
real user ID or saved set-user-ID, setuid sets only effective user ID to
uid
3. If neither of the two conditions is true, errno is set to EPERM and an
error is returned
09/28/2025
CHANGING USER IDs AND GROUP IDs
setreuid and setregid Functions
Swapping of the real user ID and the effective user ID with the setreuid function.
#include <sys/types.h>
#include <unistd.h>
int setreuid (uid_t ruid, uid_t euid);
int setregid (gid_t rgid, gid_t egid);
Both return : 0 if OK, -1 on error
09/28/2025
CHANGING USER IDs AND GROUP IDs
Summary of all the functions that set the various user Ids
09/28/2025
INTERPRETER FILES
These files are text files that begin with a line of the form
#! pathname [ optional-argument ]
The actual file execed by kernel is the one specified in the pathname
A program that execs an interpreter file
#include "apue.h"
#include <sys/wait.h>
int main(void)
{
pid_t pid;
if ((pid = fork()) < 0) {
err_sys("fork error"); }
else if (pid == 0)
{ /* child */
if (execl("/home/sar/bin/testinterp", "testinterp", "myarg1", "MY ARG2", (char *)0) < 0)
err_sys("execl error");
}
if (waitpid(pid, NULL, 0) < 0) /* parent */
err_sys("waitpid error");
exit(0);
} 09/28/2025
INTERPRETER FILES
Uses of interpreter files
1. They hide the fact that certain programs are scripts in some other language
2. They provide an efficiency gain
3. They help us write shell scripts using shells other than /bin/sh
09/28/2025
System function
It helps us execute a command string within a program.
System is implemented by calling fork, exec and waidpid.
#include <stdlib.h>
int system (const char *cmdstring);
09/28/2025
System function
/* calling system function*/
#include <sys/types.h>
#include <sys/wait.h>
#include "ourhdr.h"
int main(void)
{
int status;
if ( (status = system("date")) < 0)
err_sys("system() error");
pr_exit(status);
if ( (status = system("nosuchcommand")) < 0)
err_sys("system() error");
pr_exit(status);
exit(0);
}
09/28/2025
Process accounting
Most UNIX systems provide an option to do process accounting. When enabled, the
kernel writes an accounting record each time a process terminates.
A new record is initialized by the kernel for the child after a fork, not when a new
program is executed.
09/28/2025
Process Accounting
The structure of the accounting records is defined in the header <sys/acct.h>
struct acct
{
char ac_flag; /* flag */
char ac_stat; /* termination status (signal & core flag only) */ /* (Solaris only) */
uid_t ac_uid; /* real user ID */
gid_t ac_gid; /* real group ID */
dev_t ac_tty; /* controlling terminal */
time_t ac_btime; /* starting calendar time */
comp_t ac_utime; /* user CPU time (clock ticks) */
comp_t ac_stime; /* system CPU time (clock ticks) */
comp_t ac_etime; /* elapsed time (clock ticks) */
comp_t ac_mem; /* average memory usage */
comp_t ac_io; /* bytes transferred (by read and write) */ /* "blocks" on BSD systems */
comp_t ac_rw; /* blocks read or written */ /* (not present on BSD systems) */
char ac_comm[8]; /* command name: [8] for Solaris, */ /* [10] for Mac OS X, [16]
for FreeBSD, and */ /* [17] for Linux */
};
09/28/2025
Process Accounting
ac_flag Description
09/28/2025
Process Accounting
Note: This function can fail if the process is not attached to a terminal that a user
logged in to.
09/28/2025
PROCESS TIMES
We can measure: wall clock time, user CPU time, and system CPU time.
Any process can call the times function to obtain these values for itself and any terminated
children.
#include <sys/times.h>
clock_t times (struct tms *buf);
Returns : elapsed wall clock time in clock ticks if OK, 1 on error
struct tms
{
clock_t tms_utime; /* user CPU time */
clock_t tms_stime; /* system CPU time */
clock_t tms_cutime; /* user CPU time, terminated children */
clock_t tms_cstime; /* system CPU time, terminated children */
};
09/28/2025
I/O Redirection
The Shell input/output redirections. Most Unix system commands take input from your
terminal and send the resulting output back to your terminal. A command normally reads its
input from the standard input, which happens to be your terminal by default. Similarly, a
command normally writes its output to standard output, which is again your terminal by
default.
Output Redirection
The output from a command normally intended for standard output can be easily diverted to
a file instead. This capability is known as output redirection. If the notation > file is
appended to any command that normally writes its output to standard output, the output of
that command will be written to file instead of your terminal. Check the following who
command which redirects the complete output of the command in the users file.
$ who > users
Notice that no output appears at the terminal. This is because the output has been redirected
from the default standard output device (the terminal) into the specified file. You can check
the users file for the complete content –
09/28/2025
I/O Redirection
If a command has its output redirected to a file and the file already contains some data, that
data will be lost. Consider the following example –
You can use >> operator to append the output in an existing file as follows –
09/28/2025
I/O Redirection
Input Redirection
Just as the output of a command can be redirected to a file, so can the input of a
command be redirected from a file. As the greater-than character > is used for
output redirection, the less-than character < is used to redirect the input of a
command.
The commands that normally take their input from the standard input can have their
input redirected from a file in this manner. For example, to count the number of lines
in the file users generated above, you can execute the command as follows –
Upon execution, you will receive the following output. You can count the number of
lines in the file by redirecting the standard input of the wc command from the file
users –
09/28/2025
I/O Redirection
Note that there is a difference in the output produced by the two forms of the wc
command. In the first case, the name of the file users is listed with the line count; in
the second case, it is not. In the first case, wc knows that it is reading its input from
the file users. In the second case, it only knows that it is reading its input from
standard input so it does not display file name.
09/28/2025
PROCESS TIMES
#include <sys/times.h> static void pr_times (clock_t real, struct tms
#include "ourhdr.h" *tmsstart, struct tms *tmsend)
static void pr_times (clock_t, struct tms *, {
struct tms *); static long clktck = 0;
static void do_cmd(char *); if ( (clktck = sysconf(_SC_CLK_TCK)) < 0)
int main (int argc, char *argv[ ]) err_sys("sysconf error");
{ int i; fprintf (stderr, " real: %7.2f\n", real / (double)
for (i = 1; i < argc; i++) clktck);
do_cmd(argv[i]);
exit(0); fprintf (stderr, " user: %7.2f\n",
}
(tmsend->tms_utime - tmsstart> tms_utime) /
static void do_cmd (char *cmd)
{ (double) clktck);
struct tms tmsstart, tmsend;
clock_t start, end; fprintf(stderr, " sys: %7.2f\n",
int status; (tmsend->tms_stime - tmsstart->tms_stime) /
fprintf(stderr, "\ncommand: %s\n", cmd); (double) clktck);
if ( (start = times(&tmsstart)) == -1)
err_sys("times error"); fprintf(stderr, " child user: %7.2f\n",
if ( (status = system(cmd)) < 0) (tmsend->tms_cutime - tmsstart->
err_sys("system() error");
tms_cutime) / (double) clktck);
if ( (end = times(&tmsend)) == -1)
err_sys("times error");
fprintf (stderr, " child sys: %7.2f\n", (tmsend-
pr_times(end-start, &tmsstart,
>tms_cstime - tmsstart-> tms_cstime) / (double)
&tmsend);
clktck);
pr_exit(status); 09/28/2025
INTRODUCTION
IPC is a set of techniques for processes to communicate each other.
IPC enables one application to control another application, and for several applications
to share the same data without interfering with one another.
IPC is required in all multiprocessing systems, but it is not generally supported by single-
process operating systems.
The various forms of IPC that are supported on a UNIX system are as follows :
IPC methods for communication between two process running on one Unix system are
1) Half duplex Pipes.
2) FIFO’s
3) Full duplex Pipes.
4) Named full duplex Pipes.
5) Message queues.
6) Shared memory.
7) Semaphores.
IPC methods for communication between two process running on different system are
8) Sockets.
9) STREAMS. Department of Computer Science, RLJIT 28/09/2025
19
PIPES
Pipes are the oldest form of UNIX System IPC.
Basically pipe is a one way communication channel where output of one is fed as input to
other.
When one end of a pipe is closed, the following two rules apply.
If we read from a pipe whose write end has been closed, read returns 0 to indicate an
end of file after all the data has been read.
If we write to a pipe whose read end has been closed,
Prototype:
#include <stdio.h>
FILE *popen(const char *cmdstring, const char *type);
Returns: file pointer if OK, NULL on error
If type is "w", the file pointer is connected to the standard input of cmdstring, as
shown:
Figure 5. Result of fp = popen(cmdstring, "w")
The pclose function closes the standard I/O stream,wait for the command to terminate
Department of Computer Science, RLJIT 28/09/2025
27
and returns the termination status of the shell.
COPROCESSES
A UNIX system filter is a program that reads from standard input and writes to standard
output. Filters are normally connected linearly in shell pipelines.
A filter becomes a coprocess when the same program generates the filter's input and
reads the filter's output.
A coprocess normally runs in the background from a shell, and its standard input and
standard output are connected to another program using a pipe.
The process creates two pipes: one is the standard input of the coprocess, and the
other is the standard output of the coprocess. Figure 6 shows this arrangement.
Figure 6. Driving a coprocess by writing its standard input and reading its standard
output
Creating a fifo is similar to creating a file, i.e fifo is just a type of file.
Prototype:
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
Returns: 0 if OK, -1 on error
The specification of the mode argument for the mkfifo function is the same as for the open
function.
Indeed, the normal file I/O functions (close, read, write, unlink, etc.) all work with FIFOs.
We create the FIFO and then start prog3 in the background, reading from the FIFO. We
then start prog1 and use tee to send its input to both the FIFO and prog2. Figure 8 shows
the process arrangement.
FIGURE 8 : Using a FIFO and tee to send a stream to two different processes
b. The client and the server can agree on a key by defining the key in a common
header, for example. The server then creates a new IPC structure specifying this
key.
c. The client and the server can agree on a pathname and project ID and call the function
ftok to convert these two values into a key. This key is then used in step 2. The only service
providedby ftok is a way of generating a key from a pathname and project ID
#include <sys/ipc.h>
key_t ftok(const char *path, int id);
Returns: key if OK, (key_t)-1 on error
struct ipc_perm {
uid_t uid; /* owner's effective user id */
gid_t gid; /* owner's effective group id */
uid_t cuid; /* creator's effective user id */
gid_t cgid; /* creator's effective group id */
mode_t mode; /* access modes */
.
.
.
};
Permission Bit
user-read 0400
user-write (alter) 0200
group-read 0040
group-write (alter) 0020
other-read 0004
other-write (alter) 0002
Configuration Limits:
All three forms of XSI IPC have built-in limits that we may encounter. Most of these limits
can be changed by reconfiguring the kernel.
Another problem with XSI IPC is that these IPC structures are not known by names in the
file system. We can't access them and modify their properties with the functions. Almost a
dozen new system calls (msgget, semop, shmat, and so on) were added to the kernel to
support these IPC objects. We can't see the IPC objects with an ls command, we can't
remove them with the rm command, and we can't change their permissions with the
chmod command. Instead, two new commands ipcs(1) and ipcrm(1)were added.
Since these forms of IPC don't use file descriptors, we can't use the multiplexed I/O
functions (select and poll) with them. This makes it harder to use more than one of these
IPC structures at a time or to use any of these IPC structures with file or device I/O. For
example, we can't have a server wait for a message to be placed on one of two message
queues without some form of busywait loop.
The cmd argument specifies the command to be performed on the queue specified by
msqid
The ptr argument points to a long integer that contains the positive integer message
type, and it is immediately followed by the message data. (There is no message data if
nbytes is 0.)
If the largest message we send is 512 bytes, we can define the following structure:
struct mymesg {
long mtype; /* positive message type */
char mtext[512]; /* message data, of length nbytes */
};
Department of Computer Science, RLJIT 28/09/2025
44
MESSAGE QUEUES
Messages are retrieved from a queue by msgrcv.
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *ptr, size_t nbytes, long type, int flag);
Returns: size of data portion of message if OK, -1 on error.
When a new set is created, the following members of the semid_ds structure are initialized.
The ipc_perm structure is initialized. The mode member of this structure is set to the
corresponding permission bits of flag.
sem_otime is set to 0.
sem_ctime is set to the current time.
sem_nsems is set to nsems.
NOTE:The number of semaphores in the set is nsems. If a new set is being created (typically in
the server), we must specify nsems. If we are referencing an existing set (a client), we can
specify nsems as 0.
The fourth argument is optional, depending on the command requested, and if present, is
of type semun, a union of various command-specific arguments:
union semun {
int val; /* for SETVAL */
struct semid_ds *buf; /* for IPC_STAT and IPC_SET */
unsigned short *array; /* for GETALL and SETALL */
};
The cmd argument specifies one of the above ten commands to be performed on the set
specified by semid.
The nops argument specifies the number of operations (elements) in the array.
If sem_op is an integer greater than zero, semop adds the value to the corresponding
semaphore element value and awakens all processes that are waiting for the element to
increase.
If sem_op is 0 and the semaphore element value is not 0, semop blocks the calling
process (waiting for 0) and increments the count of processes waiting for a zero value of
that element.
If sem_op is a negative number, semop adds the sem_op value to the corresponding
semaphore element value provided that the result would not be negative. If the operation
would make the element value negative, semop blocks the process on the event that the
semaphore element value increases. If the resulting value is 0, semop wakes the
processes waiting for 0.
3. Explain the “system” function with its prototype, along with example.
5. Explain the “process times” function with its prototype, along with
example.
Q2. Explain popen and pclose functions with prototypes and write a program to
demonstrate popen and pclose function. (10 M)
Q4. What are FIFOs? With a neat diagram, explain the following (10M)
i) Using FIFOs to Duplicate Output Streams
ii) The client-sever communication using FIFOs.
Q5. What are the three different ways in which the client and server
processes are can get access to same IPC structures? ( 05 M)
Q6. What are the advantages and disadvantages of XSI IPC. (05 M)
Q7. List the APIs with their argument details that are used to create, control, send and receive
messages from a message queue. (10M)
OR
What are message queues? Write the structure of the message queue and explain each member,
in detail.
Department of Computer Science, RLJIT 28/09/2025
Q8. What are the different system calls available to create and manipulate54semaphores? (10M)