popen2: reading works, writing doesn't - c

The following function executes a process, returns its PID and provides file descriptors for reading and writing:
pid_t popen2(const char **command, int *infp, int *outfp)
{
int p_stdin[2], p_stdout[2];
pid_t pid;
if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0) {
return -1;
}
pid = fork();
if (pid < 0) {
return pid;
} else if (pid == 0) {
close(p_stdin[WRITE]);
dup2(p_stdin[READ], READ);
close(p_stdout[READ]);
dup2(p_stdout[WRITE], WRITE);
execvp(*command, command);
}
if (infp == NULL) {
close(p_stdin[WRITE]);
} else {
*infp = p_stdin[WRITE];
}
if (outfp == NULL) {
close(p_stdout[READ]);
} else {
*outfp = p_stdout[READ];
}
return pid;
}
I call the above function with
pid = popen2(..., &in, &out);
and read from the file descriptor out with
nBytes = read(out, line, sizeof(line));
and what I read makes perfect sense. It is the output normally displayed on the console. However, when I try to write a command to the program which it would normally receive via the console with
nBytes = write(in, cmd, strlen(cmd)+1);
nothing happens. The program shows no reaction whatsoever.
What am I missing here?

I did change it a bit, but it works now. Remove the fprintf(stderr,... after verification:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#define READ_END 0
#define WRITE_END 1
pid_t popen2(const char **command, int fdarray[]);
pid_t popen2(const char **command, int fdarray[])
{
int p_stdin[2], p_stdout[2];
pid_t pid;
int rc;
if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0) {
return -1;
}
pid = fork();
if (pid < 0) {
return pid;
} else if (pid == 0) {
close(p_stdin[WRITE_END]);
dup2(p_stdin[READ_END], STDIN_FILENO);
close(p_stdin[READ_END]);
close(p_stdout[READ_END]);
dup2(p_stdout[WRITE_END], STDOUT_FILENO);
close(p_stdout[WRITE_END]);
rc = execvp(*command, command);
_exit(EXIT_FAILURE);
}
close(p_stdout[WRITE_END]);
close(p_stdin[READ_END]);
if (fdarray == NULL) {
close(p_stdin[WRITE_END]);
close(p_stdout[READ_END]);
} else {
fdarray[READ_END] = p_stdout[READ_END];
fdarray[WRITE_END] = p_stdin[WRITE_END];
}
return pid;
}
#define BUFF_SIZE 1024
struct buff {
size_t used;
size_t size;
char data[BUFF_SIZE];
}
ibuf = {0,BUFF_SIZE,}
, obuf = {0,BUFF_SIZE,}
;
int readbuff(int fd, struct buff *bp);
int writebuff(int fd, struct buff *bp);
int readbuff(int fd, struct buff *bp)
{
size_t done;
int rc=0;
for (done=0; bp->used < bp->size; bp->used+=rc, done+=rc) {
if (done) break;
fprintf(stderr, "Read(%d,%zu)\n", fd, bp->size - bp->used );
rc = read(fd, bp->data+bp->used, bp->size - bp->used);
if (rc== -1) switch (errno) {
#if (EWOULDBLOCK != EAGAIN)
case EWOULDBLOCK:
#endif
case EAGAIN:
case EINTR: rc=0; continue;
default:
fprintf(stderr, "Error on readbuff: %d: %s\n", errno, strerror(errno));
goto failed;
}
fprintf(stderr, "Readbuff(%d) := %d\n", fd, rc);
if (rc==0) { rc = -1; break; }
}
failed:
return done ? done : rc;
}
int writebuff(int fd, struct buff *bp)
{
size_t done;
int rc= 0;
for (done=0; done < bp->used ; done+=rc) {
if (done) break;
fprintf(stderr, "Write(%d,%zu)\n", fd, bp->used - done);
rc = write(fd, bp->data+done, bp->used - done);
if (rc== -1) switch (errno) {
#if (EWOULDBLOCK != EAGAIN)
case EWOULDBLOCK:
#endif
case EINTR:
case EAGAIN:rc=0; continue;
default:
fprintf(stderr, "Error on writebuff: %d: %s\n", errno, strerror(errno));
goto failed;
}
fprintf(stderr, "Writebuff(%d) := %d\n", fd, rc);
if (rc==0) { rc = -1; break; }
}
failed:
if (done == bp->used ) bp->used =0;
else { memmove(bp->data, bp->data+done, bp->used - done); bp->used -= done; }
return done ? done : rc;
}
int main (void)
{
int pipes[2] = {-1,-1};
int rc1, rc2,err;
char *commands[] = { "tee", "teapot", NULL};
// signal(SIGCHLD, SIG_IGN);
// signal(SIGPIPE, SIG_IGN);
rc1 = popen2( commands, pipes);
err = errno;
fprintf(stderr, "Rc=%d:%d(%s) pipes[0]=%d, pipes[1]=%d\n"
, rc1 , rc1 == -1 ? err : 0
, strerror(rc1 == -1?err:0)
, pipes[0]
, pipes[1]
);
if (rc1 == -1) return EXIT_FAILURE;
while(1) {
fprintf(stderr, "#----------------------------------------\n" );
rc1 = readbuff(STDIN_FILENO, &ibuf);
#if 1
if (rc1 == -1 && ibuf.used ==0) {
fprintf(stderr, "Rc1=%d Close %d\n", rc1, pipes[WRITE_END]);
close(pipes[WRITE_END]);
}
else
#endif
writebuff(pipes[WRITE_END] , &ibuf);
rc2 = readbuff(pipes[READ_END] , &obuf);
writebuff(STDOUT_FILENO, &obuf);
fprintf(stderr, "Rc=%d/%d Ibuf[0]=%zu/%zu, Obuf[0]=%zu/%zu\n"
, rc1, rc2
, ibuf.used, ibuf.size
, obuf.used, obuf.size
);
if (rc1 < 0 && rc2 < 0) break;
}
wait(NULL);
return 0;
}

Related

tail exec doesn't work well in pipe (No output until parent process die!)

#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
int pipFd[1000][2], hasPipe, forked, pipNum = 0, pNum = 0, bPipe = 0, bpipFd[2], stPipe, InpToChld = 0;
pid_t pid[1000];
void * outInp;
int builtin_command(char **argv)
{
if (!strcmp(argv[0], "quit")) /* quit command */
exit(0);
if (!strcmp(argv[0], "&")) /* Ignore singleton & */
return 1;
return 0; /* Not a builtin command */
}
int parsecmd(char *buf, char **argv)
{
char *delim; /* Points to first space delimiter */
int argc; /* Number of args */
int bg; /* Background job? */
buf[strlen(buf) - 1] = ' '; /* Replace trailing '\n' with space */
while (*buf && (*buf == ' ')) /* Ignore leading spaces */
buf++;
/* Build the argv list */
argc = 0;
while ((delim = strchr(buf, ' ')))
{
argv[argc++] = buf;
*delim = '\0';
buf = delim + 1;
while (*buf && (*buf == ' ' || *buf == '<')) /* Ignore spaces */
buf++;
}
argv[argc] = NULL;
if (argc == 0) /* Ignore blank line */
return 1;
/* Should the job run in the background? */
if ((bg = (*argv[argc - 1] == '&')) != 0)
argv[--argc] = NULL;
return argc;
}
void myExec(char **argv, char *buf)
{
// if ((pid[pNum] = fork()) == 0)
// {
strcpy(buf, "/bin/");
buf[5] = 0;
strcat(buf, argv[0]);
//printf("%s\n", buf);
if (execv(buf, argv) < 0)
{
memset(buf, 0, 255);
strcpy(buf, "/usr/bin/");
strcat(buf, argv[0]);
if (execv(buf, argv) < 0)
{
printf("exec failed\n");
exit(-1);
}
}
exit(0);
// }
// else
// wait(NULL);
}
int splitPipe(char **cmdLine)
{
static char *svBuftok;
if (!hasPipe)
*cmdLine = strtok_r(*cmdLine, "|", &svBuftok);
else{
//printf("--------%s\n", svBuftok);
*cmdLine = strtok_r(svBuftok, "|", &svBuftok);
}
//printf(".......................%s %s\n", svBuftok, *cmdLine);
return strlen(svBuftok);
}
int isDigit(char * strings){
int i, tmp = strlen(strings);
for(i = 0; i < tmp; i++){
if(strings[i] < '0' || strings[i] > '9') return 0;
}
return 1;
}
void handler(int sig)
{
if (sig == SIGINT && forked) exit(0);
}
static char *getcmd()
{
static char buf[256];
//fputs("> ", stdout);
//printf("asdfasdfasdf\n");
fflush(stdin);
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL)
return NULL;
if (buf[strlen(buf)] == '\n')
buf[strlen(buf)] = 0;
return buf;
}
int main()
{
char *cmdline;
char *argv[12000];
char c, dir[256], buf[256], rdBuf[100000], pipBuf[100000];
int status, fd, rfd, dest, argc;
pid_t tmpPid;
getcwd(dir, 256);
signal(SIGINT, handler);
signal(SIGTSTP, handler);
signal(SIGCHLD, handler);
signal(30, handler);
//outInp = &&Outinp;
//printf("gd\n");
while (cmdline = getcmd())
{
ret:
do
{
rfd = 0;
hasPipe = splitPipe(&cmdline);
//printf(":::::::::::::::%s %d\n", cmdline, hasPipe);
if (strlen(cmdline) <= 1)
continue;
argc = parsecmd(cmdline, argv);
if (!builtin_command(argv))
{
if(!strcmp(argv[0], "exit")) exit(0);
{
if(hasPipe) pipe(pipFd[pNum]);
if(!bPipe) pipe(bpipFd);
fflush(NULL);
if((pid[pNum] = fork()) == 0){
int ofd, svStdout = dup(1), svStin = dup(0);
forked = 1;
close(pipFd[pNum][0]);
//printf("%s %d\n",argv[0], getpid());
//fflush(stdout);
//printf("\n");
if(bPipe) {
close(pipFd[pNum - 1][1]);
dup2(pipFd[pNum - 1][0], STDIN_FILENO);
}
else{
close(bpipFd[1]);
dup2(bpipFd[0], STDIN_FILENO);
}
//addArgv(pipBuf, &argc, argv);
if(hasPipe) dup2(pipFd[pNum][1], 1);
if(!strcmp(argv[argc - 2], ">")){
//printf("chked %s\n", argv[argc - 1]);
remove(argv[argc - 1]);
ofd = open(argv[argc - 1], O_WRONLY | O_CREAT, 0755);
dup2(ofd, 1);
argc -= 2;
argv[argc] = NULL;
}
else if(!strcmp(argv[argc - 2], ">>")){
//printf("chked %s\n", argv[argc - 1]);
ofd = open(argv[argc - 1], O_WRONLY);
dup2(ofd, 1);
argc -= 2;
argv[argc] = NULL;
}
fflush(stdout);
myExec(argv, buf);
close(pipFd[pNum][1]);
if(bPipe) {
close(pipFd[pNum - 1][0]);
}
else{
close(bpipFd[0]);
}
dup2(svStin, 0);
dup2(svStdout, 1);
if(!strcmp(argv[argc - 2], ">")) close(ofd);
exit(0);
}
else{
if(!bPipe) {
close(bpipFd[0]);
stPipe = pid[pNum];
InpToChld = 1;
}
pNum++;
}
}
bPipe = hasPipe;
}
}while (hasPipe);
while(InpToChld){
memset(rdBuf, 0, sizeof(rdBuf)); int i;
fflush(NULL);
//printf("Inp~~\n");
if(read(0, rdBuf, sizeof(rdBuf)) == 0){
write(bpipFd[1], "\0", 1);
InpToChld = 0;
break;
}
if(write(bpipFd[1], rdBuf, strlen(rdBuf)) < 0){
cmdline = rdBuf;
InpToChld = 0;
goto ret;
}
fflush(NULL);
//fflush(stdout);
}
}
}
At first, exec to tail works well.
But tail's output doesn't be printed until parent process die.
for example, cat < /proc/meminfo | head works well
but cat < /proc/meminfo | tail is printed after exit parent.
I guess this is about input / output problem, but I can't solve this problem.
The steps to code a tiny shell :
handle SIGCHLD
if necessary handle redirect
if necessary handle pipe
The following code could work, not handle builtin command:
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void signal_SIGCHLD_handle(int sig) {
while (waitpid(-1, NULL, WNOHANG) > 0)
;
}
int main()
{
char buf[256];
while (fgets(buf, sizeof(buf), stdin) != NULL) {
if (fork() > 0) { // parent
wait(NULL);
continue;
}
//child
// handle SIGCHLD
struct sigaction act;
act.sa_handler = signal_SIGCHLD_handle;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
sigaction(SIGCHLD, &act, NULL);
if (buf[strlen(buf)] == '\n')
buf[strlen(buf)] = '\0';
for (char* next_cmd = strtok(buf, "|"); next_cmd != NULL; ) {
char* current_cmd = next_cmd;
next_cmd = strtok(NULL, "|");
char* argv[10];
int argv_index = 0;
int new_argv = 1;
for (;;) {
if(*current_cmd == '\0') {
argv[argv_index] = NULL;
break;
}
if (isspace(*current_cmd)) {
*current_cmd++ = '\0';
new_argv = 1;
continue;
}
if (*current_cmd == '<') {
++current_cmd;
while (isspace(*current_cmd))
++current_cmd;
if (*current_cmd == '\0') {
printf("Please use cmd < file_name");
return -1;
}
char* filename = current_cmd;
while (!isspace(*current_cmd) && *current_cmd != '\0')
++current_cmd;
if (*current_cmd != '\0')
*current_cmd++ = '\0';
int fd = open(filename, O_RDONLY);
if (fd < 0) {
perror("<");
return -1;
}
dup2(fd, 0);
close(fd);
continue;
}
if (*current_cmd == '>') {
int add = 0;
if (*++current_cmd == '>') {
add = 1;
++current_cmd;
}
while (isspace(*current_cmd))
++current_cmd;
if (*current_cmd == '\0') {
printf(add == 0 ? "Please use cmd > file_name" : "Please use cmd >> file_name");
return -1;
}
char* filename = current_cmd;
while (!isspace(*current_cmd) && *current_cmd != '\0')
++current_cmd;
if (*current_cmd != '\0')
*current_cmd++ = '\0';
int fd = open(filename, add == 0 ? (O_WRONLY|O_CREAT) : (O_WRONLY|O_CREAT|O_APPEND), 0644);
if (fd < 0) {
perror(add == 0 ? ">" : ">>");
return -1;
}
dup2(fd, 1);
close(fd);
continue;
}
if (new_argv == 1) {
new_argv = 0;
argv[argv_index++] = current_cmd;
}
++current_cmd;
}
if (argv_index == 0)
continue;
if (next_cmd != NULL) {
int pipe_fd[2];
pipe(pipe_fd);
if (fork() == 0) {
close(pipe_fd[0]);
dup2(pipe_fd[1], STDOUT_FILENO);
close(pipe_fd[1]);
execvp(argv[0], argv);
return -1;
}
close(pipe_fd[1]);
dup2(pipe_fd[0], STDIN_FILENO);
close(pipe_fd[1]);
continue;
}
execvp(argv[0], argv);
}
}
return 0;
}

C written HTTP server resets connection after repling

I've read all the related answers but could not find the reason why this is happening. I've tried replacing close() to shutdown and then close and more but still the same.
All I need is to be able to browse to my server and when asking a file it'll return its content and when asking a directory it will return a list of whats in it. this all WORKS, except for the RST packet.
Can anyone help?
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <signal.h>
#define HTTP_BAD_REQUEST "HTTP/1.1 404 Not Found\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>File Not Found</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_GOOD_REQUEST "HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Results</TITLE>\n</HEAD>\n<BODY>\n"
#define HTTP_ERROR "HTTP/1.1 500 Internal Server Error\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Internal Server Error!</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_NOT_IMPLEMENTED "HTTP/1.1 501 Not Implemented\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Method Not Implemented</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_END "<br/></BODY></HTML>\n\0"
#define MAX_REQUEST_SIZE 1024
int send_response(int fd, char* filepath)
{
struct stat statbuf;
int iofd;
int check = 1;
char buf[1024];
if ( stat(filepath,&statbuf) < 0 )
{
printf("Path not found\n");
send(fd, HTTP_BAD_REQUEST, strlen(HTTP_BAD_REQUEST), 0);
return -1;
}
else
{
if(S_ISDIR(statbuf.st_mode))
{
//directory
DIR *dp;
struct dirent *ep;
dp = opendir (filepath);
if (dp == NULL)
{
printf("Error opening directory\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
send(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST), 0);
ep = readdir (dp);
while (ep != NULL)
{
send(fd, ep->d_name, strlen(ep->d_name), 0);
send(fd, "<br/>", strlen("<br/>"), 0);
ep = readdir (dp);
}
send(fd, HTTP_END, strlen(HTTP_END), 0);
(void) closedir (dp);
return 0;
}
else if (S_ISREG(statbuf.st_mode))
{
//regular file
iofd = open(filepath, O_RDONLY);
if( iofd < 0 )
{
printf("Error opening file\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
send(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST), 0);
while ( check > 0)
{
check = read(iofd,buf,sizeof(buf));
if (check < 0)
{
printf("Error reading file\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
close(iofd);
return -1;
}
else if (check == 0)
break;
else
send(fd, buf, strlen(buf), 0);
}
send(fd, HTTP_END, strlen(HTTP_END), 0);
close(iofd);
return 0;
}
}
}
int process(int fd, char* header)
{
char npath[MAX_REQUEST_SIZE];
char *eol = strchr(header, '\r');
// split header to get path and method
char *method = strtok(header, " ");
char *path = strtok(NULL, " ");
char *http = strtok(NULL, " ");
if( eol != NULL )
*eol = '\0';
if( strcmp(method, "GET") || (strcmp(method, "POST")))
{
if( path[0] == '/' && path[1] == '\0' )
{
path ="/";
}
else if( path[0] == '/' )
{
snprintf(npath, MAX_REQUEST_SIZE, "%s", path);
path = npath;
}
return send_response(fd, path);
}
else
{
send(fd, HTTP_NOT_IMPLEMENTED, strlen(HTTP_NOT_IMPLEMENTED), 0);
return -1;
}
}
int get_line(int sock, char *buf, int size)
{
int i = 0;
char c = '\0';
int n;
while ((i < size - 1) && (c != '\n'))
{
n = recv(sock, &c, 1, 0);
if (n > 0)
{
if (c == '\r')
{
n = recv(sock, &c, 1, MSG_PEEK);
if ((n > 0) && (c == '\n'))
recv(sock, &c, 1, 0);
else
c = '\n';
}
buf[i] = c;
i++;
}
else
c = '\n';
}
buf[i] = '\0';
return(i);
}
int service(int fd)
{
char buffer[MAX_REQUEST_SIZE];
if (get_line(fd, buffer, MAX_REQUEST_SIZE) <= 0)
{
printf("Error reading from socket");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
return process(fd, buffer);
}
void cleanup( int signal )
{
int pid;
while(1)
{
pid = waitpid(-1, NULL, WNOHANG);
if( pid < 0 )
break;
else if( pid == 0 )
break;
}
exit(0);
}
int main(int argc, char *argv[])
{
int port = 80;
int max_requests;
struct sigaction finish;
finish.sa_handler = &cleanup;
sigaction( SIGINT, &finish, NULL );
if ((argc == 1) || (argc > 3))
{
printf("Usage Error: wrong amount of arguments to main");
return -1;
}
else if (argc == 3)
{
max_requests = strtol(argv[1], NULL, 0);
port = strtol(argv[2], NULL, 0);
}
else
max_requests = strtol(argv[1], NULL, 0);
struct sockaddr_in servaddr;
int serversock = socket(AF_INET, SOCK_STREAM, 0);
int on = 1;
if( serversock < 0 )
{
printf("Error creating socket: %s\n", strerror(errno));
return 1;
}
if( setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0 )
printf("Error tweaking socket options: %s\n", strerror(errno));
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
if( bind(serversock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
{
printf("Error binding to server address: %s\n", strerror(errno));
return 1;
}
if( listen(serversock, max_requests) < 0 )
{
printf("Error using listen(): %s\n", strerror(errno));
return 1;
}
while(1)
{
int clientsock, pid, childstatus;
//server shall now wait for a new connection
clientsock = accept(serversock, NULL, NULL);
if( clientsock < 0 )
{
printf("Error using accept(): %s\n", strerror(errno));
return 1;
}
pid = fork();
if( pid < 0 )
{
printf("Error using fork(): %s\n", strerror(errno));
send(clientsock, HTTP_ERROR, strlen(HTTP_ERROR), 0);
close(clientsock);
continue;
}
else if( pid == 0 )
{
shutdown(serversock, 2);
if (service(clientsock) != 0 )
printf("error in service\n");
if (shutdown(clientsock, SHUT_WR) != 0)
{
printf("Error shutting the socket down: %s\n", strerror(errno));
return -1;
}
close(clientsock);
return 0;
}
pid = waitpid(-1, NULL, WNOHANG);
if( pid < 0 )
{
printf("Error using waitpid(): %s\n", strerror(errno));
break;
}
close(clientsock);
}
return 999;
}
the following code:
cleanly compiles
properly outputs error messages to stderr
properly outputs a 'usage' message when not correct number of command line parameters
'should' operate correctly with connections after the first
caveat: not thoroughly tested.
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <errno.h>
#include <signal.h>
#define HTTP_BAD_REQUEST "HTTP/1.1 404 Not Found\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>File Not Found</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_GOOD_REQUEST "HTTP/1.1 200 OK\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Results</TITLE>\n</HEAD>\n<BODY>\n"
#define HTTP_ERROR "HTTP/1.1 500 Internal Server Error\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Internal Server Error!</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_NOT_IMPLEMENTED "HTTP/1.1 501 Not Implemented\nContent-Type: text/html\nConnection: Closed\n\n<HTML>\n<HEAD>\n<TITLE>Method Not Implemented</TITLE>\n</HEAD>\n<BODY>\n<br/>\n</BODY>\n</HTML>\n"
#define HTTP_END "<br/></BODY></HTML>\n\0"
#define MAX_REQUEST_SIZE 1024
int send_response(int fd, char* filepath)
{
struct stat statbuf;
int iofd; // file descriptor
ssize_t readStatus = 1;
char buf[ MAX_REQUEST_SIZE ];
if ( stat(filepath,&statbuf) < 0 )
{
perror( "stat for file failed" );
//printf("Path not found\n");
send(fd, HTTP_BAD_REQUEST, strlen(HTTP_BAD_REQUEST), 0);
return -1;
}
else
{ // path found
if(S_ISDIR(statbuf.st_mode))
{
//directory
DIR *dp;
struct dirent *ep;
dp = opendir (filepath);
if (dp == NULL)
{
fprintf( stderr, "Error opening directory\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
// implied else, opendir successful
send(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST), 0);
ep = readdir (dp);
while (ep != NULL)
{
send(fd, ep->d_name, strlen(ep->d_name), 0);
send(fd, "<br />", strlen("<br />"), 0);
ep = readdir (dp);
}
send(fd, HTTP_END, strlen(HTTP_END), 0);
closedir (dp);
return 0;
}
else if (S_ISREG(statbuf.st_mode))
{ //regular file
iofd = open(filepath, O_RDONLY);
if( iofd < 0 )
{
//fprintf(stderr, "Error opening file\n");
perror( "open failed" );
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
// implied else, open successful
send(fd, HTTP_GOOD_REQUEST, strlen(HTTP_GOOD_REQUEST), 0);
while ( readStatus > 0)
{
readStatus = read(iofd,buf,sizeof(buf));
if (readStatus < 0)
{
perror( "read of file failed");
//printf("Error reading file\n");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
close(iofd);
return -1;
}
else if (readStatus == 0) // EOF or signal
break;
else // transmit line from file
send(fd, buf, strlen(buf), 0);
} // end while
send(fd, HTTP_END, strlen(HTTP_END), 0);
close(iofd);
return 0;
}
}
return -2;
}
int process(int fd, char* header)
{
// split header to get path and method
char *method = strtok(header, " ");
char *path = strtok(NULL, " ");
//char *http = strtok(NULL, " ");
// if trailing newline, replace with NUL byte
char *eol = NULL;
if( NULL == (eol = strchr(header, '\r') ) )
*eol = '\0';
if( strcmp(method, "GET") || (strcmp(method, "POST")))
{
return send_response(fd, path);
}
else
{
send(fd, HTTP_NOT_IMPLEMENTED, strlen(HTTP_NOT_IMPLEMENTED), 0);
return -1;
}
} // end function: process
int get_line(int sock, char *buf, int size)
{
int i = 0;
char c = '\0';
ssize_t recvStatus;
while ( (i < (size - 1)) && (c != '\n') )
{
recvStatus = recv(sock, &c, 1, 0);
if ( recvStatus > 0)
{ // then some bytes read
if (c == '\r')
{
recvStatus = recv(sock, &c, 1, MSG_PEEK);
if ((recvStatus > 0) && (c == '\n'))
recv(sock, &c, 1, 0);
else
c = '\n';
} // endif
buf[i] = c;
i++;
}
else
{
c = '\n';
} // endif
} // end while
// terminate the char array
buf[i] = '\0';
return(i);
} // end function: get_line
int service(int fd)
{
char buffer[MAX_REQUEST_SIZE];
if (get_line(fd, buffer, MAX_REQUEST_SIZE) <= 0)
{
fprintf( stderr, "Error reading from socket");
send(fd, HTTP_ERROR, strlen(HTTP_ERROR), 0);
return -1;
}
return process(fd, buffer);
} // end function: service
void cleanup( int signal )
{
(void)signal;
pid_t pid;
while(1)
{
pid = waitpid(-1, NULL, WNOHANG);
if( pid <= 0 )
break;
}
exit(0);
} // end function: cleanup
int main(int argc, char *argv[])
{
uint16_t port = 80;
int max_requests;
struct sigaction finish;
finish.sa_handler = &cleanup;
sigaction( SIGINT, &finish, NULL );
if ( (argc != 3) && (argc != 2) )
{
fprintf( stderr, "USAGE: %s <maxConnections> [<portToUse>]\n", argv[0]);
//printf("Usage Error: wrong amount of arguments to main");
return -1;
}
max_requests = (int)strtol(argv[1], NULL, 0);
if( 3 == argc )
{
port = (uint16_t)strtol(argv[2], NULL, 0);
}
int serversock = socket(AF_INET, SOCK_STREAM, 0);
if( serversock < 0 )
{
printf("Error creating socket: %s\n", strerror(errno));
return 1;
}
int on = 1;
if( setsockopt(serversock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0 )
{
perror( "setsockopt for SO_REUSEADDR failed" );
//printf("Error tweaking socket options: %s\n", strerror(errno));
}
if( setsockopt(serversock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0 )
{
perror( "setsockopt for SO_KEEPALIVE failed" );
//printf("Error tweaking socket options: %s\n", strerror(errno));
}
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(port);
if( bind(serversock, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0 )
{
perror( "bind failed" );
//printf("Error binding to server address: %s\n", strerror(errno));
return 1;
}
if( listen(serversock, max_requests) < 0 )
{
perror( "listen failed" );
//printf("Error using listen(): %s\n", strerror(errno));
return 1;
}
while(1)
{
int clientsock;
pid_t pid;
//int childstatus;
//server shall now wait for a new connection
clientsock = accept(serversock, NULL, NULL);
if( clientsock < 0 )
{
perror( "accept failed" );
//printf("Error using accept(): %s\n", strerror(errno));
close( serversock );
return 1;
}
pid = fork();
switch( pid )
{
case -1: // fork failed
fprintf(stderr, "Error using fork(): %s\n", strerror(errno));
send(clientsock, HTTP_ERROR, strlen(HTTP_ERROR), 0);
close(clientsock);
break;
case 0: // in child process
//shutdown(serversock, 2);
if (service(clientsock) != 0 )
{
fprintf( stderr, "error in service\n");
}
close(clientsock);
return 0;
break;
default: // in parent process
pid = waitpid( -1, NULL, WNOHANG);
close(clientsock);
break;
} // end switch
} // end while
return 0;
} // end function: main

Close pipes get Bad file descriptor

Here is the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
int main(int argc, char **argv) {
int num = 2;
pid_t pid;
int i;
int p1[num][2], p2[num][2];
for (i = 0; i < num; i++) {
if (pipe(p1[i]) == -1) {
perror("pipe");
exit(1);
}
if (pipe(p2[i]) == -1) {
perror("pipe");
exit(1);
}
}
for (i = 0; i < num; i++) {
if ((pid = fork()) == 0) {
if (close(p1[i][1]) != 0) {
perror("close");
exit(1);
}
if (close(p2[i][0]) != 0) {
perror("close");
exit(1);
}
printf("%d\n", getpid());
exit(0);
} else if (pid > 0) {
if (close(p1[i][0]) != 0) {
perror("close");
exit(1);
}
if (close(p2[i][1]) != 0) {
perror("close");
exit(1);
}
continue;
} else {
perror("fork");
exit(1);
}
}
for (i = 0; i < num; i++) {
if (close(p1[i][0]) != 0) {
perror("close1"); // <----error
}
if (close(p1[i][1]) != 0) {
perror("close");
}
if (close(p2[i][0]) != 0) {
perror("close");
}
if (close(p2[i][1]) != 0) {
perror("close2"); // <----error
}
}
for (i = 0; i < num; i++) {
if (wait(NULL) == -1) {
perror("wait");
exit(1);
}
}
return 0;
}
When I run this, it gives me this output
close1: Bad file descriptor
close2: Bad file descriptor
close1: Bad file descriptor
close2: Bad file descriptor
8798
8799
What I'm trying to do is to create two 2D array of pipes and fork num times.
The creating and running are working well, but some pipes can't close.
It seems that p1[i][0] and p2[i][1] are never closer properly.
The reason you're getting the EBADFD is you're attempting to close the same file descriptor twice.
I added a print statement in this first snippet of code to show/track what file descriptor is being closed. If you compile and run this you'll see that the error message appears right after you try to close the descriptor for a second time.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
int main(int argc, char **argv) {
int num = 1;
pid_t pid;
int i;
int p1[num][2], p2[num][2];
for (i = 0; i < num; i++) {
if (pipe(p1[i]) == -1) {
perror("pipe");
exit(1);
}
if (pipe(p2[i]) == -1) {
perror("pipe");
exit(1);
}
}
for (i = 0; i < num; i++) {
if ((pid = fork()) == 0) {
printf("Child closing: Pipe1 %d End %d\n", i, 1);
if (close(p1[i][1]) != 0) {
perror("close");
exit(1);
}
printf("Child closing: Pipe2 %d End %d\n", i, 1);
if (close(p2[i][0]) != 0) {
perror("close");
exit(1);
}
printf("%d\n", getpid());
exit(0);
} else if (pid > 0) {
printf("Parent closing: Pipe1 %d End %d\n", i, 0);
if (close(p1[i][0]) != 0) {
perror("close");
exit(1);
}
printf("Parent closing: Pipe1 %d End %d\n", i, 1);
if (close(p2[i][1]) != 0) {
perror("close");
exit(1);
}
continue;
} else {
perror("fork");
exit(1);
}
}
for (i = 0; i < num; i++) {
printf("Closing: Pipe1: %d End: %d\n", i, 0);
if (close(p1[i][0]) != 0) {
perror("close1"); // <----error
}
printf("Closing: Pipe1: %d End: %d\n", i, 1);
if (close(p1[i][1]) != 0) {
perror("close");
}
printf("Closing: Pipe2: %d End: %d\n", i, 0);
if (close(p2[i][0]) != 0) {
perror("close");
}
printf("Closing: Pipe2: %d End: %d\n", i, 1);
if (close(p2[i][1]) != 0) {
perror("close2"); // <----error
}
}
for (i = 0; i < num; i++) {
if (wait(NULL) == -1) {
perror("wait");
exit(1);
}
}
return 0;
}
Check for the pid and close the ends that weren't closed inside your first loop. This code assumes you are reading and writing on a specific pipe depending on the child's/parent's need. You may need to adjust to however your use case dictates:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
int main(int argc, char **argv) {
int num = 1;
pid_t pid;
int i;
int p1[num][2], p2[num][2];
for (i = 0; i < num; i++) {
if (pipe(p1[i]) == -1) {
perror("pipe");
exit(1);
}
if (pipe(p2[i]) == -1) {
perror("pipe");
exit(1);
}
}
for (i = 0; i < num; i++) {
if ((pid = fork()) == 0) {
if (close(p1[i][1]) != 0) {
perror("close");
exit(1);
}
if (close(p2[i][0]) != 0) {
perror("close");
exit(1);
}
printf("%d\n", getpid());
exit(0);
} else if (pid > 0) {
if (close(p1[i][0]) != 0) {
perror("close");
exit(1);
}
if (close(p2[i][1]) != 0) {
perror("close");
exit(1);
}
continue;
} else {
perror("fork");
exit(1);
}
}
for (i = 0; i < num; i++) {
if (pid == 0) {
if (close(p1[i][0]) != 0) {
perror("close1");
}
if (close(p2[i][1]) != 0) {
perror("close");
}
} else {
if (close(p1[i][1]) != 0) {
perror("close");
}
if (close(p2[i][0]) != 0) {
perror("close2");
}
}
}
for (i = 0; i < num; i++) {
if (wait(NULL) == -1) {
perror("wait");
exit(1);
}
}
return 0;
}

why this linux pseudo terminal program doesn't work?

Master reads input from stdin and writes to pty-master, slave reads input from pty-slave and writes to stdout.
But this code/program seems doesn't work.
The Master writes to pty-master is OK, but the slave hungs when reads from pty-slave.
anyone can help me? thx in advance.
#include <assert.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
/*
* copy from apue
*/
int ptym_open(char *pts_name, int pts_namesz)
{
char *ptr;
int fdm, err;
if ((fdm = posix_openpt(O_RDWR)) < 0) {
assert(0);
return -1;
}
if (grantpt(fdm) < 0) {
assert(0);
return -1;
}
if (unlockpt(fdm) < 0) {
assert(0);
return -1;
}
if ((ptr = ptsname(fdm)) == NULL) {
assert(0);
return -1;
}
strncpy(pts_name, ptr, pts_namesz);
pts_name[pts_namesz - 1] = 0;
printf("pts_name:%s\n", pts_name);
return fdm;
}
int ptys_open(char *pts_name)
{
int fds;
if ((fds = open(pts_name, O_RDWR)) < 0) {
return -1;
}
return fds;
}
int pty_fork(int *ptrfdm, char *slave_name, int slave_namesz)
{
int fdm, fds;
pid_t pid;
char pts_name[1024];
if ((fdm = ptym_open(pts_name, sizeof(pts_name))) < 0) {
assert(0);
return -1;
}
if (slave_name != NULL) {
strncpy(slave_name, pts_name, slave_namesz);
slave_name[slave_namesz - 1] = 0;
}
if ((pid = fork()) < 0) {
assert(0);
return -1;
} else if (pid == 0) {
if (setsid() < 0) {
assert(0);
}
if ((fds = ptys_open(pts_name)) < 0) {
assert(0);
}
close(fdm);
if (dup2(fds, STDIN_FILENO) != STDIN_FILENO) {
assert(0);
}
//if (dup2(fds, STDOUT_FILENO) != STDOUT_FILENO) {
// assert(0);
//}
//if (dup2(fds, STDERR_FILENO) != STDERR_FILENO) {
// assert(0);
//}
if ((fds != STDIN_FILENO) && (fds != STDOUT_FILENO) && (fds != STDERR_FILENO)) {
close(fds);
}
return 0;
} else {
*ptrfdm = fdm;
return pid;
}
}
int loop(int ptym)
{
pid_t pid;
int nread;
#define BUFFSIZE 512
char buf[BUFFSIZE];
if ((pid = fork()) < 0) {
assert(0);
} else if (pid == 0) {
while (1) {
if ((nread = read(STDIN_FILENO, buf, BUFFSIZE)) < 0) {
int errr = errno;
printf("%s\n", strerror(errr));
assert(0);
} else if (nread = 0) {
break;
}
if (write(ptym, buf, nread) != nread) {
int errr = errno;
printf("%s\n", strerror(errr));
assert(0);
}
fsync(ptym);
}
exit(0); // child
}
while (1) {
if ((nread = read(ptym, buf, BUFFSIZE)) <= 0) {
printf("%d break read\n", getpid());
break;
}
if (write(STDOUT_FILENO, buf, nread) != nread) {
assert(0);
}
}
}
int main(void)
{
int fdm;
char slave_name[1024];
pid_t pid = pty_fork(&fdm, slave_name, sizeof(slave_name));
if (pid < 0) {
assert(0);
} else if (pid == 0) {
int nread;
char buf[1024];
while(1){
if ((nread = read(STDIN_FILENO, buf, 3)) < 0) {
break;
}
printf("buf:%s\n", buf);
}
} else {
printf("child:%d#%s\n", pid, slave_name);
loop(fdm);
}
return 0;
}
Besides opening the pseudo-terminal, you have to initialize it (something referred to as line discipline). I don't see any of that in your example. You could compare with luit, which does do this (look for instance at the openTty function in sys.c).
Further reading:
Notes 7: Terminal I/O
Writing a Kernel Line Discipline
What are the responsibilities of each Pseudo-Terminal (PTY) component (software, master side, slave side)?

Why can't my shell start firefox?

I'm writing a small shell as an exercis to learn C. Now I can execute custom commands like ls and date but when I try to run firefox it doesn't start. Why? My session is
$ ./a.out
miniShell>> ls
ls
a.out digenv2.c~ digenv.c.orig miniShell.c README.md test
digenv digenv.c digenv.old.c miniShell.c~ smallshell.c
digenv2.c digenv.c~ LICENSE miniShell.c.orig smallshell.c.orig
miniShell>> date
date
Tue May 12 09:38:27 CEST 2015
miniShell>> firefox
firefox
miniShell>>
My program is
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#define BUFFER_LEN 1024
#define BUFFERSIZE 1024
pid_t foreground = -1;
int mystrcmp(char const *, char const *);
struct command
{
char * const *argv;
};
void err_syserr(char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, "(%d: %s)\n", errnum, strerror(errnum));
exit(EXIT_FAILURE);
}
int StartsWith(const char *a, const char *b)
{
if(strncmp(a, b, strlen(b)) == 0) return 1;
return 0;
}
/* Helper function that spawns processes */
/*static int spawn_proc(int in, int out, struct command *cmd)
{
pid_t pid;
if ((pid = fork()) == 0)
{
if (in != 0)
{
if (dup2(in, 0) < 0)
err_syserr("dup2() failed on stdin for %s: ", cmd->argv[0]);
;
close(in);
}
if (out != 1)
{
if (dup2(out, 1) < 0)
err_syserr("dup2() failed on stdout for %s: ", cmd->argv[0]);
close(out);
}
fprintf(stderr, "%d: executing %s\n", (int)getpid(), cmd->argv[0]);
execvp(cmd->argv[0], cmd->argv);
err_syserr("failed to execute %s: ", cmd->argv[0]);
}
else if (pid < 0) {
err_syserr("fork failed: ");
}
return pid;
}*/
/* Helper function that forks pipes */
/*static void fork_pipes(int n, struct command *cmd)
{
int i;
int in = 0;
int fd[2];
for (i = 0; i < n - 1; ++i)
{
pipe(fd);
spawn_proc(in, fd[1], cmd + i);
close(fd[1]);
in = fd[0];
}
if (dup2(in, 0) < 0) {
err_syserr("dup2() failed on stdin for %s: ", cmd[i].argv[0]);
}
fprintf(stderr, "%d: executing %s\n", (int)getpid(), cmd[i].argv[0]);
execvp(cmd[i].argv[0], cmd[i].argv);
err_syserr("failed to execute %s: ", cmd[i].argv[0]);
}*/
/*Remove zoombie processes*/
/*Return if background process terminated*/
/*
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html
*/
void Janitor(int status) {
if(status==SIGCHLD) { /*Child process terminated, stopped, or continued*/
int a = 1;
while(a) {
pid_t pid_my1 = waitpid(-1, &status, WNOHANG);
/*WNOHANG = return immediately if no child has exited*/
/*Wait*/
/*http://linux.die.net/man/2/waitpid*/
if(0<pid_my1) { /*Still things to clean up*/
if(pid_my1!=foreground) { /*Don't stop me since it's the foregound process*/
/*http://linux.die.net/man/3/wait*/
if(WIFEXITED(status)) { /*Child process terminated*/
printf("%d terminated", pid_my1);
}
}
}
else { /*All work done, for now*/
a = 0;
}
}
}
}
int main() {
char line[BUFFER_LEN];
char* argv[100];
char* path= "/bin/";
char progpath[20];
int argc;
size_t length;
char *token;
int i=0;
int pid;
char *tokenstr;
char *search = " ";
int isSignal = 0;
int isBackground = 0;
#ifdef SIGDET
#if SIGDET == 1
isSignal = 1; /*Termination detected by signals*/
#endif
#endif
while(1) {
i = 0;
int built_in_command = 0;
printf("miniShell>> ");
if(!fgets(line, BUFFER_LEN, stdin)) {
break;
}
length = strlen(line);
if (line[length - 1] == '\n') {
line[length - 1] = '\0';
}
if(strcmp(line, "exit")==0) {
break;
}
if(StartsWith(line, "cd")) {
built_in_command=1;
printf("change directory\n");
tokenstr = strtok(line, search);
tokenstr = strtok(NULL, search);
chdir(tokenstr);
/*TODO maybe have a check whether extra argument exist, if not go to home directory*/
}
token = strtok(line," ");
while(token!=NULL) {
argv[i]=token;
token = strtok(NULL," ");
i++;
}
if(StartsWith(line, "checkEnv")) {
built_in_command=1;
if (0==i) {
char *printenv[] = { "printenv", 0};
char *sort[] = { "sort", 0 };
char *less[] = { "less", 0 };
struct command cmd[] = { {printenv}, {sort}, {less} };
fork();
}
else {
char *tmp;
int len = 1;
for (i = 1; i < argc; i++)
{
len += strlen(argv[i]) + 2;
}
tmp = (char *) malloc(len);
tmp[0] = '\0';
int pos = 0;
for (i = 1; i < argc; i++)
{
pos += sprintf(tmp + pos, "%s%s", (i == 1 ? "" : "|"), argv[i]);
}
char *printenv[] = { "printenv", 0};
char *grep[] = { "grep", "-E", tmp, NULL};
char *sort[] = { "sort", 0 };
char *less[] = { "less", 0 };
struct command cmd[] = { {printenv}, {grep}, {sort}, {less} };
fork();
free(tmp);
}
}
if(0==built_in_command) { /*Not a built in command, so let execute it*/
argv[i]=NULL;
argc=i;
for(i=0; i<argc; i++) {
printf("%s\n", argv[i]);
}
strcpy(progpath, path);
strcat(progpath, argv[0]);
for(i=0; i<strlen(progpath); i++) {
if(progpath[i]=='\n') {
progpath[i]='\0';
}
}
isBackground = 0;
sigset_t my_sig;
pid_t pid_temp;
int lastElem = (sizeof(line)/sizeof(line[0]))-1; /*Last input argument index*/
/*TODO check if background process*/
/*TODO store the time forground process started*/
int fd[2];
if (isBackground == 1) { //If backgroundprocess
pipe(fd); /*(two new file descriptors)*/
/*FIXME pid_temp = fork_pipes(2, .....);*/
pid_temp = fork();
}
else if (isBackground == 0) { //If foreground process
int isSignal = 0; /*FIXME*/
if (1 == isSignal) { /*If using signaldetection*/
sigemptyset(&my_sig); /*empty and initialising a signal set*/
sigaddset(&my_sig, SIGCHLD); /*Adds signal to a signal set (my_sig)*/
/*http://pubs.opengroup.org/onlinepubs/7908799/xsh/sigprocmask.html*/
sigprocmask(SIG_BLOCK, &my_sig, NULL);
}
/*FIXME pid_temp = fork_pipes(2, .....);*/
pid_temp = fork();
foreground = pid_temp; /*Set pid for foreground process*/
}
if (0<pid_temp) {
/*Parent process*/
}
else if (0>pid_temp) {
/*Error*/
}
else {
/*Child process*/
if (1 == isBackground) { //Backgroundprocess
dup2(fd[STDIN_FILENO], STDIN_FILENO);
close(fd[0]);
close(fd[1]);
}
execvp(progpath,argv);
/*TODO execute command here, some is working*/
}
if (0 == isBackground) { //Foregroundprocess
/*Write here, Emil*/
int status = 0;
waitpid(pid_temp, &status, 0);
/*Foregroundprocess terminated*/
/*TODO How long time was the total execution time*/
int isSignal = 0; /*FIXME*/
if (1 == isSignal) { /*If using signaldetection*/
int a = sigprocmask(SIG_UNBLOCK, &my_sig, NULL);
/*http://man7.org/linux/man-pages/man2/sigprocmask.2.html*/
if (0 == a) {
/*Sigprocmask was successfull*/
}
else {
/*Sigprocmask was not successfull, return=-1*/
}
Janitor(SIGCHLD);
}
}
else if (1==isBackground) {
close(fd[0]);
close(fd[1]);
}
}
/* pid= fork();
if(pid==0) {
execvp(progpath,argv);
fprintf(stderr, "Child process could not do execvp\n");
} else {
wait(NULL);
printf("Child exited\n");
}*/
}
return (0);
}
int mystrcmp(char const *p, char const *q)
{
int i = 0;
for(i = 0; q[i]; i++)
{
if(p[i] != q[i])
return -1;
}
return 0;
}
int cd(char *pth) {
char path[BUFFERSIZE];
char cwd[BUFFERSIZE];
char * return_value;
int other_return;
strcpy(path,pth);
if(pth[0] != '/')
{
return_value = getcwd(cwd,sizeof(cwd));
strcat(cwd,"/");
strcat(cwd,path);
other_return = chdir(cwd);
} else {
other_return = chdir(pth);
}
printf("Spawned foreground process: %d\n", getpid());
return 0;
}
The issue is with the path. You always assume the command is in /bin/ whereas firefox is usually in /usr/bin/. So your child is going to exec /bin/firefox and fail. Checking the return code of execvp would have helped finding this. On success, execvp family functions don't return. So if they do, you know why.

Resources