Write both the popen() and pclose() functions and use them in a program. Remembe
ID: 3809353 • Letter: W
Question
Write both the popen() and pclose() functions and use them in a program. Remember that pclose() allows the original process to be a good parent.
Writing popen() and pclose()
The stand I/O library in C contains the functions:
where "command" is the name of an executable program (normally a shell command), "mode" refers to whether the calling process will read or write to the pipe and "stream" refers to a file pointer. The purpose of popen() is to allow a process to create another process running the program "command" which it will communicate with using an unnamed pipe. To achieve this, the function popen() needs to execute several system calls. The diagram below gives the relationships of the processes and pipe.
In this assignment, you will write both the popen() and pclose() functions and use them in a program. Remember that pclose() allows the original process to be a good parent.
Your code needs to consider the following points:
The pipe() system call returns a pair of file descriptors. However, popen() return a file pointer. Use the function FILE* fdopen() to convert the file descriptor into a file pointer.
Appropriately close() the unused file descriptor in the parent and the child. The function popen() knows which to close() because of the mode parameter.
The child needs to use either dup() or dup2() to redirect standard input or standard output.
The child needs to close unneeded file descriptors before it does an exec*() (the command parameter).
The parent needs to perform all its tasks before it calls pclose(). Be careful with order of operations.
In c or c++
Explanation / Answer
wrapstdio.c
/*
* Standard I/O wrapper functions.
*/
#include "unpipc.h"
void
Fclose(FILE *fp)
{
if (fclose(fp) != 0)
err_sys("fclose error");
}
FILE *
Fdopen(int fd, const char *type)
{
FILE *fp;
if ( (fp = fdopen(fd, type)) == NULL)
err_sys("fdopen error");
return(fp);
}
char *
Fgets(char *ptr, int n, FILE *stream)
{
char *rptr;
if ( (rptr = fgets(ptr, n, stream)) == NULL && ferror(stream))
err_sys("fgets error");
return (rptr);
}
FILE *
Fopen(const char *pathname, const char *mode)
{
FILE *fp;
if ( (fp = fopen(pathname, mode)) == NULL)
err_sys("fopen error");
return(fp);
}
void
Fputs(const char *ptr, FILE *stream)
{
if (fputs(ptr, stream) == EOF)
err_sys("fputs error");
}
FILE *
Popen(const char *command, const char *mode)
{
FILE *fp;
if ( (fp = popen(command, mode)) == NULL)
err_sys("popen error");
return(fp);
}
Pclose(FILE *fp)
{
int n;
if ( (n = pclose(fp)) == -1)
err_sys("pclose error");
return(n);
}
unpipc.h
/* include unpipch */
/* Our own header. Tabs are set for 4 spaces, not 8 */
#ifndef __unpipc_h
#define __unpipc_h
#include "../config.h" /* configuration options for current OS */
/* "../config.h" is generated by configure */
/* If anything changes in the following list of #includes, must change
../aclocal.m4 and ../configure.in also, for configure's tests. */
#include <sys/types.h> /* basic system data types */
#include <sys/time.h> /* timeval{} for select() */
#include <time.h> /* timespec{} for pselect() */
#include <errno.h>
#include <fcntl.h> /* for nonblocking */
#include <limits.h> /* PIPE_BUF */
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h> /* for S_xxx file mode constants */
#include <unistd.h>
#include <sys/wait.h>
#ifdef HAVE_MQUEUE_H
# include <mqueue.h> /* Posix message queues */
#endif
#ifdef HAVE_SEMAPHORE_H
# include <semaphore.h> /* Posix semaphores */
#ifndef SEM_FAILED
#define SEM_FAILED ((sem_t *)(-1))
#endif
#endif
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h> /* Posix shared memory */
#endif
#ifndef MAP_FAILED
#define MAP_FAILED ((void *)(-1))
#endif
#ifdef HAVE_SYS_IPC_H
# include <sys/ipc.h> /* System V IPC */
#endif
#ifdef HAVE_SYS_MSG_H
# include <sys/msg.h> /* System V message queues */
#endif
#ifdef HAVE_SYS_SEM_H
#ifdef __bsdi__
#undef HAVE_SYS_SEM_H /* hack: BSDI's semctl() prototype is wrong */
#else
# include <sys/sem.h> /* System V semaphores */
#endif
#ifndef HAVE_SEMUN_UNION
/* $$.It semun$$ */
union semun { /* define union for semctl() */
int val;
struct semid_ds *buf;
unsigned short *array;
};
#endif
#endif /* HAVE_SYS_SEM_H */
#ifdef HAVE_SYS_SHM_H
# include <sys/shm.h> /* System V shared memory */
#endif
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h> /* for convenience */
#endif
#ifdef HAVE_POLL_H
# include <poll.h> /* for convenience */
#endif
#ifdef HAVE_STROPTS_H
# include <stropts.h> /* for convenience */
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h> /* for convenience */
#endif
/* Next three headers are normally needed for socket/file ioctl's:
* <sys/ioctl.h>, <sys/filio.h>, and <sys/sockio.h>.
*/
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_FILIO_H
# include <sys/filio.h>
#endif
#ifdef HAVE_PTHREAD_H
# include <pthread.h>
#endif
#ifdef HAVE_DOOR_H
# include <door.h> /* Solaris doors API */
#endif
#ifdef HAVE_RPC_RPC_H
#ifdef _PSX4_NSPACE_H_TS /* Digital Unix 4.0b hack, hack, hack */
#undef SUCCESS
#endif
# include <rpc/rpc.h> /* Sun RPC */
#endif
/* Define bzero() as a macro if it's not in standard C library. */
#ifndef HAVE_BZERO
#define bzero(ptr,n) memset(ptr, 0, n)
#endif
/* Posix.1g requires that an #include of <poll.h> DefinE INFTIM, but many
systems still DefinE it in <sys/stropts.h>. We don't want to include
all the streams stuff if it's not needed, so we just DefinE INFTIM here.
This is the standard value, but there's no guarantee it is -1. */
#ifndef INFTIM
#define INFTIM (-1) /* infinite poll timeout */
#ifdef HAVE_POLL_H
#define INFTIM_UNPH /* tell unpxti.h we defined it */
#endif
#endif
/* Miscellaneous constants */
#ifndef PATH_MAX /* should be in <limits.h> */
#define PATH_MAX 1024 /* max # of characters in a pathname */
#endif
#define MAX_PATH 1024
/* $$.ix [MAX_PATH]~constant,~definition~of$$ */
#define MAXLINE 4096 /* max text line length */
/* $$.ix [MAXLINE]~constant,~definition~of$$ */
/* $$.ix [BUFFSIZE]~constant,~definition~of$$ */
#define BUFFSIZE 8192 /* buffer size for reads and writes */
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
/* default permissions for new files */
/* $$.ix [FILE_MODE]~constant,~definition~of$$ */
#define DIR_MODE (FILE_MODE | S_IXUSR | S_IXGRP | S_IXOTH)
/* default permissions for new directories */
/* $$.ix [DIR_MODE]~constant,~definition~of$$ */
#define SVMSG_MODE (MSG_R | MSG_W | MSG_R>>3 | MSG_R>>6)
/* default permissions for new SV message queues */
/* $$.ix [SVMSG_MODE]~constant,~definition~of$$ */
#define SVSEM_MODE (SEM_R | SEM_A | SEM_R>>3 | SEM_R>>6)
/* default permissions for new SV semaphores */
/* $$.ix [SVSEM_MODE]~constant,~definition~of$$ */
#define SVSHM_MODE (SHM_R | SHM_W | SHM_R>>3 | SHM_R>>6)
/* default permissions for new SV shared memory */
/* $$.ix [SVSHM_MODE]~constant,~definition~of$$ */
typedef void Sigfunc(int); /* for signal handlers */
#ifdef HAVE_SIGINFO_T_STRUCT
typedef void Sigfunc_rt(int, siginfo_t *, void *);
#endif
#define min(a,b) ((a) < (b) ? (a) : (b))
#define max(a,b) ((a) > (b) ? (a) : (b))
#ifndef HAVE_TIMESPEC_STRUCT
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* and nanoseconds */
};
/* $$.It timespec$$ */
/* $$.Ib tv_sec$$ */
/* $$.Ib tv_nsec$$ */
#endif
#ifdef __bsdi__
#define va_mode_t int
#else
#define va_mode_t mode_t
#endif
/* $$.ix [va_mode_t]~datatype,~definition~of$$ */
/* our record locking macros */
#define read_lock(fd, offset, whence, len)
lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len)
#define readw_lock(fd, offset, whence, len)
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)
#define is_read_lockable(fd, offset, whence, len)
lock_test(fd, F_RDLCK, offset, whence, len)
#define is_write_lockable(fd, offset, whence, len)
lock_test(fd, F_WRLCK, offset, whence, len)
/* end unpipch */
#define Read_lock(fd, offset, whence, len)
Lock_reg(fd, F_SETLK, F_RDLCK, offset, whence, len)
#define Readw_lock(fd, offset, whence, len)
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)
#define Is_read_lockable(fd, offset, whence, len)
Lock_test(fd, F_RDLCK, offset, whence, len)
#define Is_write_lockable(fd, offset, whence, len)
Lock_test(fd, F_WRLCK, offset, whence, len)
/* prototypes for our own library functions */
void daemon_init(const char *, int);
void daemon_inetd(const char *, int);
char *gf_time(void);
int lock_reg(int, int, int, off_t, int, off_t);
pid_t lock_test(int, int, off_t, int, off_t);
void *my_shm(size_t);
char *px_ipc_name(const char *);
int readable_timeo(int, int);
ssize_t readline(int, void *, size_t);
ssize_t readn(int, void *, size_t);
int set_concurrency(int);
Sigfunc *signal_intr(int, Sigfunc *);
int sleep_us(unsigned int);
int start_time(void);
double stop_time(void);
int touch(void *, int);
void tv_sub(struct timeval *, struct timeval *);
int writable_timeo(int, int);
ssize_t writen(int, const void *, size_t);
#ifndef HAVE_GETHOSTNAME_PROTO
int gethostname(char *, int);
#endif
#ifndef HAVE_ISFDTYPE_PROTO
int isfdtype(int, int);
#endif
#ifndef HAVE_PSELECT_PROTO
int pselect(int, fd_set *, fd_set *, fd_set *,
const struct timespec *, const sigset_t *);
#endif
#ifndef HAVE_SNPRINTF_PROTO
int snprintf(char *, size_t, const char *, ...);
#endif
/* prototypes for our own library wrapper functions */
char *Gf_time(void);
void Lock_reg(int, int, int, off_t, int, off_t);
pid_t Lock_test(int, int, off_t, int, off_t);
void *My_shm(size_t);
char *Px_ipc_name(const char *);
int Readable_timeo(int, int);
ssize_t Readline(int, void *, size_t);
ssize_t Readn(int, void *, size_t);
void Set_concurrency(int);
Sigfunc *Signal(int, Sigfunc *);
Sigfunc *Signal_intr(int, Sigfunc *);
#ifdef HAVE_SIGINFO_T_STRUCT
Sigfunc_rt *Signal_rt(int, Sigfunc_rt *);
Sigfunc_rt *Signal_rt_intr(int, Sigfunc_rt *);
#endif
void Sleep_us(unsigned int);
void Start_time(void);
double Stop_time(void);
void Touch(void *, int);
int Writable_timeo(int, int);
void Writen(int, void *, size_t);
/* prototypes for our Unix wrapper functions */
void *Calloc(size_t, size_t);
void Close(int);
void Dup2(int, int);
int Fcntl(int, int, void *);
pid_t Fork(void);
long Fpathconf(int, int);
void Fstat(int, struct stat *);
key_t Ftok(const char *, int);
void Ftruncate(int, off_t);
int Getopt(int, char *const *, const char *);
void Gettimeofday(struct timeval *, void *);
int Ioctl(int, int, void *);
void Kill(pid_t, int);
off_t Lseek(int, off_t, int);
void *Malloc(size_t);
void Mkfifo(const char *, mode_t);
void Mktemp(char *);
void *Mmap(void *, size_t, int, int, int, off_t);
void Munmap(void *, size_t);
int Open(const char *, int, ...);
long Pathconf(const char *, int);
void Pipe(int *fds);
ssize_t Read(int, void *, size_t);
int Select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
void Sigaddset(sigset_t *, int);
void Sigdelset(sigset_t *, int);
void Sigemptyset(sigset_t *);
void Sigfillset(sigset_t *);
int Sigismember(const sigset_t *, int);
void Sigpending(sigset_t *);
void Sigprocmask(int, const sigset_t *, sigset_t *);
#ifdef HAVE_SIGINFO_T_STRUCT
void Sigqueue(pid_t, int, const union sigval);
#endif
#ifdef HAVE_SIGWAIT
void Sigwait(const sigset_t *, int *);
#endif
void Stat(const char *, struct stat *);
char *Strdup(const char *);
long Sysconf(int);
void Sysctl(int *, u_int, void *, size_t *, void *, size_t);
void Unlink(const char *);
void *Valloc(size_t);
pid_t Wait(int *);
pid_t Waitpid(pid_t, int *, int);
void Write(int, void *, size_t);
#ifdef HAVE_MQUEUE_H
/* 4Posix message queues */
mqd_t Mq_open(const char *, int, ...);
void Mq_close(mqd_t);
void Mq_unlink(const char *pathname);
void Mq_send(mqd_t, const char *, size_t, unsigned int);
ssize_t Mq_receive(mqd_t, char *, size_t, unsigned int *);
void Mq_notify(mqd_t, const struct sigevent *);
void Mq_getattr(mqd_t, struct mq_attr *);
void Mq_setattr(mqd_t, const struct mq_attr *, struct mq_attr *);
#endif /* HAVE_MQUEUE_H */
#ifdef HAVE_SEMAPHORE_H
/* 4Posix semaphores */
sem_t *Sem_open(const char *, int, ...);
void Sem_close(sem_t *);
void Sem_unlink(const char *);
void Sem_init(sem_t *, int, unsigned int);
void Sem_destroy(sem_t *);
void Sem_wait(sem_t *);
int Sem_trywait(sem_t *);
void Sem_post(sem_t *);
void Sem_getvalue(sem_t *, int *);
#endif /* HAVE_SEMAPHORE_H */
/* Note that <sys/mman.h> is defined on some systems that do not support
* Posix shared memory (e.g., 4.4BSD), because this header predates Posix
* and appears on any system that supports mmap(). Therefore we cannot
* use this to determine whether the implementation supports Posix shared
* memory or not. We use our own HAVE_SHM_OPEN_PROTO symbol.
*/
#ifdef HAVE_SHM_OPEN_PROTO
/* 4Posix shared memory */
int Shm_open(const char *, int, mode_t);
void Shm_unlink(const char *);
#endif
#ifdef HAVE_SYS_MSG_H
/* 4System V message queues */
int Msgget(key_t key, int flag);
void Msgctl(int, int, struct msqid_ds *);
void Msgsnd(int, const void *, size_t, int);
ssize_t Msgrcv(int, void *, size_t, int, int);
#endif /* HAVE_SYS_MSG_H */
#ifdef HAVE_SYS_SEM_H
/* 4System V semaphores */
int Semget(key_t, int, int);
int Semctl(int, int, int, ...);
void Semop(int, struct sembuf *, size_t);
#endif /* HAVE_SYS_SEM_H */
#ifdef HAVE_SYS_SHM_H
/* 4System V shared memory */
int Shmget(key_t, size_t, int);
void *Shmat(int, const void *, int);
void Shmdt(const void *);
void Shmctl(int, int, struct shmid_ds *);
#endif /* HAVE_SYS_SHM_H */
/* prototypes for our stdio wrapper functions */
void Fclose(FILE *);
FILE *Fdopen(int, const char *);
char *Fgets(char *, int, FILE *);
FILE *Fopen(const char *, const char *);
void Fputs(const char *, FILE *);
FILE *Popen(const char *, const char *);
int Pclose(FILE *);
#ifdef HAVE_FATTACH
void Fattach(int, const char *);
#endif
#ifdef HAVE_POLL
int Poll(struct pollfd *, unsigned long, int);
#endif
void err_dump(const char *, ...);
void err_msg(const char *, ...);
void err_quit(const char *, ...);
void err_ret(const char *, ...);
void err_sys(const char *, ...);
/* prototypes for our pthread wrapper functions */
void Pthread_attr_init(pthread_attr_t *);
void Pthread_attr_destroy(pthread_attr_t *);
void Pthread_attr_setdetachstate(pthread_attr_t *, int);
void Pthread_attr_setscope(pthread_attr_t *, int);
void Pthread_create(pthread_t *, const pthread_attr_t *,
void * (*)(void *), void *);
void Pthread_join(pthread_t, void **);
void Pthread_detach(pthread_t);
void Pthread_kill(pthread_t, int);
void Pthread_setcancelstate(int, int *);
void Pthread_mutexattr_init(pthread_mutexattr_t *);
void Pthread_mutexattr_destroy(pthread_mutexattr_t *);
void Pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
void Pthread_mutex_init(pthread_mutex_t *, pthread_mutexattr_t *);
void Pthread_mutex_destroy(pthread_mutex_t *);
void Pthread_mutex_lock(pthread_mutex_t *);
void Pthread_mutex_unlock(pthread_mutex_t *);
void Pthread_condattr_init(pthread_condattr_t *);
void Pthread_condattr_destroy(pthread_condattr_t *);
void Pthread_condattr_setpshared(pthread_condattr_t *, int);
void Pthread_cond_broadcast(pthread_cond_t *);
void Pthread_cond_signal(pthread_cond_t *);
void Pthread_cond_wait(pthread_cond_t *, pthread_mutex_t *);
void Pthread_cond_timedwait(pthread_cond_t *, pthread_mutex_t *,
const struct timespec *);
void Pthread_key_create(pthread_key_t *, void (*)(void *));
void Pthread_setspecific(pthread_key_t, const void *);
void Pthread_once(pthread_once_t *, void (*)(void));
long pr_thread_id(pthread_t *);
#ifdef HAVE_DOOR_H
/* typedefs to simplify declarations */
typedef void Door_server_proc(void *, char *, size_t, door_desc_t *, size_t);
typedef void Door_create_proc(door_info_t *);
/* prototypes for our doors wrapper functions */
void Door_bind(int);
void Door_call(int, door_arg_t *);
int Door_create(Door_server_proc *, void *, u_int);
void Door_cred(door_cred_t *);
void Door_info(int, door_info_t *);
void Door_return(char *, size_t, door_desc_t *, size_t);
void Door_revoke(int);
void Door_unbind(void);
Door_create_proc *Door_server_create(Door_create_proc *);
#endif /* HAVE_DOOR_H */
#ifdef HAVE_RPC_RPC_H
CLIENT *Clnt_create(const char *, u_long, u_long, const char *);
void Clnt_control(CLIENT *, u_int, char *);
#endif
#endif /* __unpipc_h */
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.