SS Lab Manual

Download as pdf or txt
Download as pdf or txt
You are on page 1of 38

MALNAD COLLEGE OF ENGINEERING, HASSAN – 573202

(An Autonomous Institution under VTU)

Department of Computer Science and Engineering

SYSTEM SOFTWARE LAB MANUAL

6th semester
SYSTEM SOFTWARE LABORATORY

Course Code : CS605 LTPC: (0-0-3)1.5


Exam Hours : 3 Hours / Week : 3
SEE : 50 Marks Total hours : 40

Course Objective: Implement shell script, Unix system Programs and make use of LEX and
YACC to generate the grammar.

Course Outcomes (COs):

Upon Completion of the course, students shall be able to:

1 Execute various programs using Unix system calls and shell PO2,PO3,PO10
script
2 Implement programs using grammar driven tools such as LEX PO1,PO2,PO10
and YACC
3 Generate tokens and parser using regular expressions and PO1,PO2,PO3
. grammar.

System Software Laboratory (CS605)


LEX: a tool for automatically generating a lexer or scanner given a lex specification (.l file).A
lexer or scanner is used to perform lexical analysis. It uses patterns that match strings in the input
and converts the strings to tokens. Tokens are representations of strings, and simplify processing.

Creating a Lexical Analyzer with Lex

The lexical analyzer reads the input source program from left to right one character at a time and
generates the sequence of tokens. Each token is a single logical cohesive unit such as identifier,
keywords, operators and punctuation marks. Then the parser to determine the syntax of the
source program can use these tokens. As the lexical analyzer scans the source program to
recognize the tokens it is also called as scanner.

Lex specification/Lex structure:


Lex input file consists of three sections:

Skeleton of a lex specification (.l file)

Definition or Declaration Section:


The declarations section includes declarations of variables, manifest constants(A manifest
constant is an identifier that is declared to represent a constant e.g. # define PIE 3.14), the files
to be included and definitions of regular expression.

Rules Section:
The translation rules of a Lex program are statements of the form:
p1 {action 1}
p2 {action 2}
p3 {action 3}
… …
where each p is a regular expression and each action is a program fragment describing what
action the lexical analyzer should take when a string pattern matches with p matches a lexeme.

User Subroutine Section:


The C code section contains C statements and function that are copied verbatim to the generated
source file. These statements presumably contain code called by the rules in the rules section. In
large programs it is more convenient to place this code in a separate file and link it in at compile
time.

The lexer produced by a lex is a C routine called yylex( )

How to install flex and bison in Ubuntu to run Lex and Yacc programs

 Open the Terminal


 Give the command sudo apt-get install flex
 After flex is installed give the command sudo apt-get install bison
 Flex and Bison installation is completed we can run the Lex and Yacc programs.

Meta Characters that form regular expressions are:


Example Program:
%{

/* C code to be copied verbatim


#include <stdio.h>
%}
%%

/*** Rules section ***/


[0-9]+ {printf("Saw an integer: %s\n", yytext); }
. { /* Ignore all other characters. */ }
%%
main()
{

/* Call the lexer, then quit. */


yylex();
return 0;
}

YACC:

 Yet Another Compiler Compiler.

 Yacc: a tool for automatically generating a parser given a grammar written in a yacc
specification (.y file)

 A grammar specifies a set of production rules, which define a language, and


corresponding actions to perform the semantics.
YACC source program
YACC Compiler “y.tab.c”
“test.y”

“y.tab.c” C Compiler exe

input exe output

A YACC Parser:

Definition Section:
• The definition section includes declarations of the tokens used in the grammar, the types
of values used on the parser stack, and other odds and ends.
– You don‟t have to specify the number of the token.
• It can also include a literal block, C code enclosed in %{ %}
• Declarations of grammar tokens
Eg: % token DIGIT
• Declares DIGIT to be a token
• Tokens specified in this section can be used as terminal in the second and third sections.

Rules Section:

 Each rule consists of a grammar production and the associated semantic action.

 A set of productions that we have been writing:


<left side> <alt 1> | <alt 2> | … <alt n>

 Would be written in YACC as


<left side> : <alt 1> {action 1;}
| <alt 2> {action 2;}
……………
| <alt n> {action n;}
;

• Since ASCII keyboards don‟t have a  key, we use a colon between the left- and right-
hand sides of a rule, and we put a semicolon at the end of each rule.
Eg:
%%
statement: NAME „=„ expression
| expression { printf (“ = %d\n”, $1); }
;
expression: expression „+‟ NUMBER {$$=$1+$2;}
| expression „-‟ NUMBER {$$=$1-$3;}
| NUMBER {$$=$1;}
;
%%
• The symbol on the left-hand side of the first rule in the grammar is normally the start
symbol, though you can use a %start declaration in the definition section to override that.

User Subroutine Section:

 This section can contain any C code and is copied, the verbatim, into the resulting parser.

 We have provided the minimal set of functions necessary for a yacc- generated parser
using a lex-generated lexer to compile: main ( ) and yyerror( ).

 The main routine keeps calling the parser until it reaches the end-of-file on yyin, the lex
input file.

 The only other necessary routine is yylex( ) which is provided by our lexer.

Command for execution of lex , yaccand C program:

Lex: Yacc: For C


$lex <filename>.l $lex <filename>.l $cc <filename>.c
$cc lex.yy.c –ll $yacc –d <filename>.y $./a.out
$./a.out $cc lex.yy.c y.tab.c –ll
$./a.out

PROGRAMS
1.a) Create an input text file in few lines which describes about your aim in life and develop
a LEX program to count the number of characters, words, spaces & no. of lines in the
input file.

%{
#include<stdio.h>
int wc=0,uc=0,sc=0,lc=0,tc=0,splc=0,dc=0,lnc=0;
%}
%%
[\n] {lnc++;wc++;}
[' '\t] {sc++;wc++;}
[A-Z] {uc++;}
[a-z] {lc++;}
[0-9] {dc++;}
. {splc++;}
%%
int main()
{
FILE *fp;
char filenm[20];
printf("\n Enter text File name:");
scanf("%s",filenm);
fp=fopen(filenm,"r");
if(fp==NULL)
printf("\nError in opening !!");
else
{
yyin=fp;
yylex();
printf("\n num of words = %d\n",wc);
printf("\n num of space count=%d\n",sc);
printf("\n num of uppercase = %d\n",uc);
printf("\n num of lowercase = %d\n",lc);
printf("\n num of spl char =%d\n",splc);
printf("\n num of digit count =%d\n",dc);
printf("\n num of line count =%d\n",lnc);
tc=uc+lc+sc+splc+dc;
printf("\n total num of chars =%d\n",tc);
}
}

Commands to run and Output:


b) Create an input file which consists of a C program to find the area of a circle with
comment lines and develop a LEX program to count the number of comment lines in the
input file and also eliminate them and copy that program into separate file.

%{
#include<stdio.h>
int fl=0,c=0,fla=0;
%}
%%
\/\* {if(!fl) {fl=1;c++;} else REJECT;}
\*\/ {if(fl) fl=0; else REJECT;}
\/\/ {if(!fla) {fla=1;c++;} else REJECT;}
[\n] {if(fla) fla=0; else REJECT;}
. {if(!fl&&!fla) REJECT;}
%%
int main(int argc,char *argv[])
{
if(argc!=3)
{
printf("Improper arguments.\nUsage is $./a.out <srcfilename>
<destfilename>\n");
exit(0);}
yyin=fopen(argv[1],"r");
yyout=fopen(argv[2],"w");
yylex();
printf("Number of comment statemensts is %d\n",c);
}
Commands to run and Output:

2. Develop a LEX program to recognize valid arithmetic expression in the list given below
and recognize the identifiers and operators present in the expression and print them
separately.

List of Arithmetic expressions

2a+5b-4c*5d C=a+b-c*d/e Z=x+y-w*

P*q=r 2m=7n+8q-3r d+c*a-


%{
#include<stdio.h>
int id=0,op=0,a=0,s=0,d=0,m=0,c=0,ob=0,cb=0,flag=1;
%}
%%
[a-zA-z][a-zA-Z0-9]* {id++; printf("%s is an identifier\n",yytext);}
"+" {op++;a++;}
"*" {op++;m++;}
"-" {op++;s++;}
"/" {op++;d++;}
“=” {op++;c++}
"(" {ob++;}
")" {if(ob>cb)
cb++;
else
flag=0;
}
. ;
%%
main()
{
printf("\n\nEnter the Arithmetic Expression:");
yylex();
int b=ob+cb;
if((id==op+1)&&(b%2==0)&&(ob==cb)&&(flag==1))
{
printf("The Expression is a Valid Expression");
printf("\n\nNo: of identifiers are\n");
printf("Identifiers=%d\n",id);
printf("\nNo.of operators\n");
if(a>0)
printf("+\n");
if(m>0)
printf("*\n");
if(s>0)
printf("-\n");
if(d>0)
printf("/\n");
if(c>0)
printf(“\n”);
printf("addition op=%d\n subtraction=%d\n multiplication=%d\n
division=%d\n",a,s,m,d);
}
else
{
printf("invalid expression\n");
exit(0);
}
}

Commands to run and Output:

3.a) Create an input file which consists of C program to swap two numbers without using
temporary variables and for this file develop LEX program to recognize and count the
number of identifiers in a given input file.

%{
#include<stdio.h>
int fc=0,def=0,id=0;
char a[10000];
%}
%%
\( {fc=1;}
\) {fc=0;}
[\ \t]*int[\ ] {if(fc) def=1; else def=2;}
[\ \t]*char[\ ] {if(fc) def=1; else def=2;}
[\ \t]*float[\ ] {if(fc) def=1; else def=2;}
[\ \t]*double[\ ] {if(fc) def=1; else def=2;}
\*?[a-zA-Z]+[a-zA-Z0-9_]*;
{if(def){id++;def=0;strncat(a,yytext,yyleng);strcat(a," ");}}
\*?[a-zA-Z]+[a-zA-Z0-9_]*[,=]
{if(def){id++;strncat(a,yytext,yyleng);strcat(a," ");}}
\*?[a-zA-Z]+[a-zA-Z0-9_]*\[[0-9]*\][,=]? {if(def)
{id++;strncat(a,yytext,yyleng-1);strcat(a," ");}};{if(def) def=0;}
.|\n { ;}
%%
int main(int argc,char *argv[])
{
if(argc!=2)
{
printf("Improper Arguments specified.\n");
printf("Usage is $./a.out <filename>\n");
exit(0);
}
yyin=fopen(argv[1],"r");
yylex();
printf("Number of identifiers are %d.\nThey are : %s\n",id,a);
}
int yywrap()
{
return 1;
}

Commands to run and Output:


b) Write a short note on Computer Science and Engineering and develop LEX program to find
and replace the word Computer Science as CS.

%{
#include<stdio.h>
#include<string.h>
FILE *ff,*fr;
char p[20],q[20],r[20],fname[20];
%}
%%
[a-zA-Z]+ {if(strcmp(p,yytext)==0)
fprintf(fr,q);
else
fprintf(fr,yytext);
}
\n {fprintf(fr,yytext);}
. {fprintf(fr,yytext);}
%%
int main(int argc,char *argv[])
{
strcpy(fname,argv[1]);
strcpy(p,argv[2]);
strcpy(q,argv[3]);
ff=fopen(fname,"r+");
fr=fopen("rep.txt","w+");
yyin=ff;
yylex();
return(0);
}

Commands to run and Output:

4.a) Create a file which lists the latest open source application useful for Computer Science
and Engineering and develop a LEX program to copy the content of this file with line
numbers to another file.

%{
#include<stdio.h>
#include<string.h>
char line[20];
int count=0,i=0;
FILE *out;
%}
%%
['\n'] {fprintf(yyout,"%d %s\n",++count,line);}
(.*) {strcpy(line,yytext);}
%%
main(int argc,char *argv[])
{
if(argc!=3)
{
printf("Improper arguments.\nUsage is $./a.out <srcfilename>
<destfilename>\n");
exit(0);
}
yyin=fopen(argv[1],"r");
yyout=fopen(argv[2],"w");
yylex();
}

Commands to run and Output:


./a.out source_file_name destination_file_name

b) From the list of students admission dates given below, check whether the admission
dates are in valid format [DD/MM/YYYY] by developing LEX program.
Student admission Dates
Student 1 24/05/2019
Student 2 30-02-2020
Student 3 23.05.2019
Student 4 24/6/2019
Student 5 28/04/20

%{
#include<stdio.h>
int i=0,yr=0,valid=0;
%}
%%
([0-2][0-9]|[3][0-1])\/((0(1|3|5|7|8))|(10|12))\/([1-2][0-9][0-9][0-
9]) {valid=1;}
([0-2][0-9]|30)\/((0(4|6|9))|11)\/([1-2][0-9][0-9][0-9])
{valid=1;}
([0-1][0-9]|2[0-8])\/02\/([1-2][0-9][0-9][0-9]) {valid=1;}
29\/02\/([1-2][0-9][0-9][0-9]) {while(yytext[i]!='/')
i++;i++;
while(yytext[i]!='/')i++;i++;
while(i<yyleng)
yr=(10*yr)+(yytext[i++]-'0');
if(yr%4==0||(yr%100==0&&yr%400!=0))
valid=1;}
.;
%%
int main()
{
printf("enter the date\n");
yylex();
if(valid==1)
printf("It is a valid date\n");
else
printf("It is invalid date\n");
}

Commands to run and Output:


5. Write and Execute YACC program to convert infix to postfix.

Lex Part
%{
#include<stdio.h>
#include "y.tab.h"
extern int yylval;
%}
%%
[0-9]+ {yylval=yytext[0];
return NUMBER;
}
[\t] ;
\n {return 0;}
. {return yytext[0];}
%%

Yacc Part
%{
#include<stdio.h>
int k=0;
int i;
char sym[26];
FILE *fp;
%}
%token NUMBER
%left'+''-'
%left'*''/'
%nonassoc UMINUS
%%
state : exp {
printf("converted postfix expression is =>");
fp=fopen("postfix.txt","w");
for(i=0;i<k;i++)
{
fprintf(fp,"%c",sym[i]);
printf("%c",sym[i]);
}
fclose(fp);
}
;
exp:NUMBER {$$=$1;sym[k]=(char)$$;k++;}
|exp'+'exp {sym[k]='+';k++;}
|exp'-'exp {sym[k]='-';k++;}
|exp'*'exp {sym[k]='*';k++;}
|exp'/'exp {sym[k]='/';k++;}
;
%%
int yyerror(char *str)
{
printf("invalid character");
}
int main()
{
printf("enter expression=>");
yyparse();
return(0);
}

Commands to run and Output:

6. Develop YACC program to evaluate an arithmetic expression involving operators +, -, *


and /. to find the solutions for the problems given below; If
1 a=5,b=6,c=8 ,then a+b*c=?
2 a=10,b=8,c=2 ,then a-b*c=?
3 a=10,b=2,c=3, then a/b+c=?
4 a=5,b=3,c=3,d=4,then a*b-c+d=?

Lex Part
%{
#include "y.tab.h"
extern int yylval;
%}
%%
[0-9]+ {yylval=atoi(yytext);return NUMBER;}
[\t] ;
\n return 0;
. return yytext[0];
%%

Yacc Part
%{
#include<stdio.h>
#include<stdlib.h>
%}
%token NUMBER
%left'-''+'
%left'*''/'
%nonassoc UMINUS
%%
statement:expression{printf("value=%d\n",$$);}
;
expression:expression'+'expression {$$=$1+$3;}
|expression'-'expression {$$=$1-$3;}
|expression'*'expression {$$=$1*$3;}
|expression'/'expression
{if($3==0)
{
yyerror("\n divide by 0 error\n");
exit(0);
}
else
$$=$1/$3;
}
|'-'expression%prec UMINUS {$$=-$2;}
|'('expression')' {$$=$2;}
|NUMBER
;
%%
main()
{
printf("\n enter expression\n");
yyparse();
}
int yyerror(char *s)
{
printf("%s\n",s);
}

Commands to run and Output:

7 a) Write and Execute YACC program to recognize the grammar (anb, n >= 10).

Lex Part

%{
#include "y.tab.h"
%}
%%
[aA] {return A;}
[bB] {return B;}
. {return yytext[0];}
%%

Yacc Part
%{
#include<stdio.h>
#include<stdlib.h>
%}
%token A B;
%%
str:A A A A A A A A A A S
;
S:A S
|B
;
%%
int main()
{
printf("\n enter a string\n");
yyparse();
printf("\n valid string\n");
return;
}
yyerror()
{
printf("\n invalid string\n");
exit(0);
}

Commands to run and Output:

b) Write and Execute YACC Program to recognize the grammar (a nbmck, m,n,k>=0 and
m=n+k).

Lex Part
%{
#include "y.tab.h"
%}
%%
[aA] {return A;}
[bB] {return B;}
[cC] {return C;}
. {return yytext[0];}
%%
Yacc Part
%{
#include<stdio.h>
#include<stdlib.h>
%}
%token A B C;
%%
str:S Z
|S
|Z
;
S:A S B
|A B
Z:B Z C
|B C
;
%%
main()
{
printf("\n enter a string of the form (a^n)(b^m)(c^k) and m=n+k\n");
yyparse();
printf("\n string recognized\n");
return;
}
yyerror()
{
printf("\n string not recognized\n");
exit(0);
}

Commands to run and Output:


INTRODUCTION TO UNIX
UNIX: UNIX is an operating system.
It manages:
Files and data.
Running programs.
Networks and other resources.
It is defined by
Its behavior (on files etc.).
Its application programmers interface API.
Ultimately everything works through system calls.
System calls are executed by the operating system and perform simple single operations.
UNIX System Programming
UNIX system programming means: writing a shell, writing a daemon for your UNIX/UNIX-like
OS, writing your version of ps. So it means writing code that heavily depends on the system
calls, that does things close related to the UNIX system.
The POSIX standards
POSIX or “Portable Operating System Interface” is the name of a family of related standards
specified by the IEEE to define the application-programming interface (API), along with shell
and utilities interface for the software compatible with variants of the UNIX operating system.
Some of the subgroups of POSIX are POSIX.1, POSIX.1b & POSIX.1c are concerned with the
development of set of standards for system developers.
#define _POSIX_SOURCE Or specify the -D_POSIX_SOURCE option to a C++ compiler CC)
in a compilation.
The UNIX operating system is a set of programs that act as a link between the computer and the
user. The computer program that allocates the system resources and coordinates all the details of
the computer's internal is called the operating system or kernel. Users communicate with the
kernel through a program known as the shell. The shell is a command line interpreter; it
translates commands entered by the user and converts them into a language that is understood by
the kernel.
 Unix was originally developed in 1969 by a group of AT&T employees at Bell Labs,
including Ken Thompson, Dennis Ritchie, Douglas McIlroy, and Joe Ossanna.
 There are various Unix variants available in the market. Solaris Unix, AIX, HP Unix and
BSD are few examples. Linux is also a flavor of Unix which is freely available.
 Several people can use a UNIX computer at the same time; hence UNIX is called a
multiuser system.
 A user can also run multiple programs at the same time; hence UNIX is called
multitasking.
Unix Architecture: Here is a basic block diagram of a UNIX system:
The main concept that unites all versions of UNIX is the following four basics:
Kernel: The kernel is the heart of the operating system. It interacts with hardware and most of
the tasks like memory management, tash scheduling and file management.
Shell: The shell is the utility that processes your requests. When you type in a command at your
terminal, the shell interprets the command and calls the program that you want. The shell uses
standard syntax for all commands. C Shell, Bourne Shell and Korn Shell are most famous shells
which are available with most of the Unix variants.
Commands and Utilities: There are various command and utilities which you would use in your
day to day activities. cp, mv, cat and grep etc. are few examples of commands and utilities. There
are over 250 standard commands plus numerous others provided through 3rd party software. All
the commands come along with various optional options.
Files and Directories: All data in UNIX is organized into files. All files are organized into
directories. These directories are organized into a tree-like structure called the file system.

Shell:
The shell provides you with an interface to the UNIX system. It gathers input from you and
executes programs based on that input. When a program finishes executing, it displays that
program's output. A shell is an environment in which we can run our commands, programs, and
shell scripts. There are different flavors of shells, just as there are different flavors of operating
systems. Each flavor of shell has its own set of recognized commands and functions.
Shell Prompt:
The prompt, $, which is called command prompt, is issued by the shell. While the prompt is
displayed, you can type a command. The shell reads your input after you press Enter. It
determines the command you want executed by looking at the first word of your input. A word is
an unbroken set of characters. Spaces and tabs separate words.
Shell Types:
In UNIX there are two major types of shells:
1. The Bourne shell: if you are using a Bourne-type shell, the default prompt is the $ character.
2. The C shell: if you are using a C-type shell, the default prompt is the % character.
There are again various subcategories for Bourne Shell which are listed as follows:

 Bourne shell ( sh)


 Korn shell ( ksh)
 Bourne Again shell ( bash)
 POSIX shell ( sh)
The different C-type shells follow:
 C shell ( csh)
 TENEX/TOPS C shell ( tcsh)
The Bourne shell was the first shell to appear on UNIX systems, thus it is referred to as "the
shell". The Bourne shell is usually installed as /bin/sh on most versions of UNIX. For this
reason, it is the shell of choice for writing scripts to use on several different versions of UNIX.

Shell Scripts:
The basic concept of a shell script is a list of commands, which are listed in the order of
execution. A good shell script will have comments, preceded by a pound sign, #, describing the
steps. There are conditional tests, such as value A is greater than value B, loops allowing us to
go through massive amounts of data, files to read and store data, and variables to read and store
data, and the script may include functions. Shell scripts and functions are both interpreted. This
means they are not compiled. We are going to write a many scripts in the next several tutorials.
This would be a simple text file in which we would put our all the commands and several other
required constructs that tell the shell environment what to do and when to do it.
8. Write a C/C++ program which demonstrates interprocesscommunication between a
reader process and a writerprocess. Use mkfifo, open, read, write and close APIs in your
program.

Writer process
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int fd;
char buf[1024];
/* create the FIFO (named pipe) */
char * myfifo = "/tmp/myfifo";
mkfifo(myfifo, 0666);
printf("Run Reader process to read the FIFO File\n");
fd = open(myfifo, O_WRONLY);
write(fd,"Hi", sizeof("Hi"));
/* write "Hi" to the FIFO */
close(fd);
unlink(myfifo);
return 0;
}
/* remove the FIFO */
Reader process
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#define MAX_BUF 1024
int main()
{
int fd;
/* A temp FIFO file is not created in reader */
char *myfifo = "/tmp/myfifo";
char buf[MAX_BUF];
/* open, read, and display the message from the FIFO */
fd = open(myfifo, O_RDONLY);
read(fd, buf, MAX_BUF);
printf("Writer: %s\n", buf);
close(fd);
return 0;
}
Commands to run and Output:

9. Write a C/C++ program to illustrate the race condition.

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
static void charatatime(char *);
int main(void)
{
pid_t pid;
if ((pid = fork()) < 0)
{
printf("fork error");
}
else if (pid == 0)
{
charatatime("output from child\n");
}
else
{
charatatime("output from parent\n");
}
return 0;
}
static void charatatime(char *str)
{
char *ptr;
int c;
setbuf(stdout, NULL); /* set unbuffered */
for (ptr = str; (c = *ptr++) != 0; )
putc(c, stdout);
}

Commands to run and Output:

10. Write a C/C++ POSIX compliant program to check the following limits:
(i) No. of clock ticks (ii) Max. no. of child processes (iii) Max. path length (iv) Max. no. of
Characters in a file name (v) Max. no. of open files/ process

#define _POSIX_SOURCE
#define _POSIX_C_SOURCE 199309L
#include<stdio.h>
#include<unistd.h>
int main()
{
int res;
if((res = sysconf(_SC_OPEN_MAX)) == -1)
perror("sysconf");
else
printf("OPEN_MAX:%d\n",res);
if((res = pathconf("/", _PC_NAME_MAX)) == -1)
perror("pathconf");
else
printf("max_path name:%d\n",res);
if((res = sysconf(_SC_CLK_TCK))== -1)
perror("sysconf");
else
printf("clock ticks:%d\n",res);
if((res = sysconf (_SC_CHILD_MAX)) == -1)
perror("sysconf");
else
printf("max_childs:%d\n",(res));
if((res = pathconf("/",_PC_PATH_MAX)) == -1)
perror("pathconf");
else
printf("max path name length:%d\n",res);
return 0;
}

Commands to run and Output:

11 Write a C/C++ program to implement the system function.

#include<sys/wait.h>
#include<errno.h>
#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
int system(const char *cmdstring)
{
pid_t pid;
int status;
if (cmdstring == NULL)
return(1);
if ((pid = fork()) < 0)
{
status = -1;
}
else if (pid == 0)
{
/* child */
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
_exit(127); /* execl error */
}
else
/* parent */
while (waitpid(pid, &status, 0) < 0)
{
if (errno != EINTR)
status = -1; /* error other than EINTR from waitpid() */
break;
}
return(status);
}
int main()
{
int status;
if ((status = system("date")) < 0)
printf("system() error");
if ((status = system("who")) < 0)
printf("system() error");
exit(0);
}

Commands to run and Output:


12. Write a C/C++ program to set up a real-time clock interval timer using the alarm API.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#define INTERVAL 5
void callme(int sig_no)
{
alarm(INTERVAL);
printf("Hello!!\n");
}
int main()
{
struct sigaction action;
action.sa_handler=(void(*)(int))callme;
sigaction(SIGALRM,&action,0);
alarm(2);
sleep(5);
return 0;
}

Commands to run and Output:


13.a) Write and Execute Non-recursive shell script that accepts any number of arguments
and prints them in the Reverse order, (For example, if the script is named rargs,then
executing rargs A B C should produce C B A on the standard output).

if [ $# -eq 0 ]
then
echo "No argument"
exit
fi
echo "Num of arguments:$#"
echo "Arguments in reverse order"
for x in $*
do
y="$x $y"
done
echo $y

Commands to run and Output:

b) Write and Execute C program that creates a child process to read commands from the
standard input and execute them (a minimal implementation of a shell – like program).
You can assume that no arguments will be passed to the commands to be executed.

#include<stdio.h>
#include<sys/types.h>
#include<stdlib.h>
main()
{
pid_t p;
char cmd[20];
p=fork();
if(p<0)
{
printf("\n fork error");
exit(0);
}
else if(p>0)
{
printf("\n enter the command\n");
scanf("%s",cmd);
system(cmd);
}
exit(0);
}

Commands to run and Output:

14 a) Write a C/C++ program to avoid zombie process by forking twice.

#include<stdio.h>
#include <sys/wait.h>
#include<errno.h>
#include<stdlib.h>
int main()
{
pid_t pid;
if ((pid = fork()) < 0)
{
printf("fork error");
}
else if (pid == 0)
{ /* first child */
if ((pid = fork()) < 0)
printf("fork error");
else if (pid > 0)
exit(0);
sleep(2);
printf("second child, parent pid = %d\n", getppid()); exit(0);
}
if (waitpid(pid, NULL, 0) != pid) /* wait for first child */
printf("waitpid error");
exit(0);
}

Commands to run and Output:

b) Write and Execute C program to do the following: Using fork( ) create a child process.
The child process prints its own process-id and id of its parent and then exits. The parent
process waits for its child to finish (by executing the wait( )) and prints its own process-id
and the id of its child process and then exits.

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
int main()
{
int pid,id;
pid=fork();
if(pid==0)
{
printf("\n child process:report");
printf("\n my pid is:%d",getpid());
printf("\n my parent pid is:%d",getpid());
}
else
{
wait();
printf("\n parent process:report");
printf("\n my pid is:%d",getpid());
printf("\n my child pid is:%d",pid);
}
exit(0);
}
Commands to run and Output:

You might also like