Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Help in Unix in bash here is the apue.h file lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len)) #define write_lock(fd, offset, whence, len) lock_reg((fd), F_SETLK, F_WRLCK,

Help in Unix in bash here is the apue.h file

lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len)) #define write_lock(fd, offset, whence, len) \ lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len)) #define writew_lock(fd, offset, whence, len) \ lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len)) #define un_lock(fd, offset, whence, len) \ lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len))

pid_t lock_test(int, int, off_t, int, off_t); /* {Prog locktest} */

#define is_read_lockable(fd, offset, whence, len) \ (lock_test((fd), F_RDLCK, (offset), (whence), (len)) == 0) #define is_write_lockable(fd, offset, whence, len) \ (lock_test((fd), F_WRLCK, (offset), (whence), (len)) == 0)

void err_msg(const char *, ...); /* {App misc_source} */ void err_dump(const char *, ...) __attribute__((noreturn)); void err_quit(const char *, ...) __attribute__((noreturn)); void err_cont(int, const char *, ...); void err_exit(int, const char *, ...) __attribute__((noreturn)); void err_ret(const char *, ...); void err_sys(const char *, ...) __attribute__((noreturn));

void log_msg(const char *, ...); /* {App misc_source} */ void log_open(const char *, int, int); void log_quit(const char *, ...) __attribute__((noreturn)); void log_ret(const char *, ...); void log_sys(const char *, ...) __attribute__((noreturn)); void log_exit(int, const char *, ...) __attribute__((noreturn));

void TELL_WAIT(void); /* parent/child from {Sec race_conditions} */ void TELL_PARENT(pid_t); void TELL_CHILD(pid_t); void WAIT_PARENT(void); void WAIT_CHILD(void);

#endif /* _APUE_H */

Explain the logic of the program in Example 2, especially on (a) when SIGTSTP is received, which process (parent or child) is handling the signal, and (b) what happens (or is done) by the signal handler (signhand).

void sighand(int signum){

/* supposedly need to reset this here (per "man signal" and

it's discussion of signals under linux), but doesn't actually

seem to matter. Documentation != observed program behavior. */

kill(pid_child,SIGKILL);

fprintf(stderr, "nyah, nyah Mr. #%d. ", signum);

}

(3) Modify the program in Example 2 so that (a) the signal is handled by the child (not the parent), and (b) output message (fprintf statement) in sighand for SIGTSTP will also print the PID of the current process handling the signal.

void sighand(int signum){

/* supposedly need to reset this here (per "man signal" and

it's discussion of signals under linux), but doesn't actually

seem to matter. Documentation != observed program behavior. */

kill(pid_child,SIGKILL);

fprintf(stderr, "nyah, nyah Mr. #%d. ", signum);

}

EX 1:

#include "apue.h"

static void sig_usr(int); /* one handler for both signals */

int

main(void)

{

if (signal(SIGUSR1, sig_usr) == SIG_ERR)

err_sys("cant catch SIGUSR1");

if (signal(SIGUSR2, sig_usr) == SIG_ERR)

err_sys("cant catch SIGUSR2");

for ( ; ; )

pause();

}

static void

sig_usr(int signo) /* argument is signal number */

{

if (signo == SIGUSR1)

printf("received SIGUSR1 ");

else if (signo == SIGUSR2)

printf("received SIGUSR2 ");

else

err_dump("received signal %d ", signo);

}

Commands for EX 1:

$ ./a.out &

[1] 7216

$ kill -USR1 7216

received SIGUSR1

$ kill -USR2 7216

received SIGUSR2

$ kill 7216

[1]+ Terminated

./a.out

EX 2:

// minishell part 1 - Shell sample code with execvp

#include

#include

#include

#include

#define MAX_ARG 10

int pid_child;

/*** Main ***/

void sighand(int signum);

int main(){

// declare variables

char *prompt = "sh1$ ";

char line[256];

char line1[256];

char program[32], command[32], *args[MAX_ARG];

int pid, status, i;

// print the prompt

printf("%s", prompt);

// Try getting input. If error or EOF, exit

while(fgets(line, sizeof line, stdin) != NULL)

{

// fgets leaves ' ' in input buffer. ditch it

line[strlen(line)-1] = '\0';

strcpy(line1,line);

// If the input is not null, get in

if (line != NULL) {

// parse command and arg

args[0] = strtok(line, " "); // grab command

for(i=1; i<10; i++) // grab arguments

args[i] = strtok(NULL, " ");

strcpy(command, args[0]); // store command variable

// check to see if the command is 'exit'

if(!strcmp("exit", args[0])) {

exit(0);

}

// check to see if the command is 'cd'

else if(!strcmp("cd", args[0])) {

chdir(args[1]);

}

// handles all other commands

else {

pid = fork(); // fork to create new child

if(pid == 0) { // code to be run by the child

signal(SIGTSTP, SIG_IGN);

status = execvp(command, args); // execute

exit(0); // exit child

}

else { // code to be run by the parent

pid_child = pid;

signal(SIGTSTP, sighand);

waitpid(-1); // wait for children to finish

signal(SIGTSTP, SIG_DFL);

}

}

}

// print the prompt

printf("%s", prompt );

}

return 0;

}

void sighand(int signum)

{

/* supposedly need to reset this here (per "man signal" and

it's discussion of signals under linux), but doesn't actually

seem to matter. Documentation != observed program behavior. */

//signal(signum, nyahnyah);

kill(pid_child,SIGKILL);

fprintf(stderr, "nyah, nyah Mr. #%d. ", signum);

}

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access with AI-Powered Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions