/* * tinybc.c * a tiny calculator that uses dc to do its work * demonstrates bidirectional pipes * input looks like number op number which * tinybc converts into number \n number \n op \n p * and passes result back to stdout * * program outline: * a. get two pipes * b. fork(get another process) * c. in the dc-to-be process, * connect stdin and out to pipes * then execl dc * d. in the tinybc-process, no plumbing to do * just talk to human via normal i/o * and send stuff via pipe * e. close pipe and dc dies * * note: does not handle multiline answers */
#include<stdio.h>
#define oops(m,x) {perror(m); exit(x);}
main() { int pid, todc[2], fromdc[2]; // equipment
// make two pipes if (pipe(todc) == -1 || pipe(fromdc) == -1) oops("pipe failed", 1);
// get a process for user interface if ((pid = fork()) == -1) oops("cannot fork", 2);
if (pid == 0) // child is dc be_dc(todc, fromdc); else { be_bc(todc, fromdc); // parent is ui wait(NULL); } }
be_dc(int in[2], int out[2]) /* * set up stdin and stdout, then execl dc */ { // setup stdin from pipein if (dup2(in[0], 0) == -1) // copy read end to 0 oops("dc:cannot redirect stdin", 3); close(in[0]); // moved to fd 0 close(in[1]); // won't write here
// setup stdout from pipeout if (dup2(out[1], 1) == -1) // copy write end to 1 oops("dc:cannot redirect stdin", 4); close(out[1]); // moved to fd 1 close(out[0]); // won't read from here
// now execl dc with the - option execlp("dc", "dc", "-", NULL); oops("Cannot run dc", 5); }
be_bc(int todc[2], int fromdc[2]) /* * read from stdin and convert into to RPN, send down pipe * then read from other pipe and print to user * Uses fdopen() to convert a file descriptor to a stream */ { int num1, num2; char operation[BUFSIZ], message[BUFSIZ], *fgets(); FILE *fpout, *fpin, *fdopen();
// setup close(todc[0]); // won't read from pipe to dc close(fromdc[1]); // won't write to pipe from dc
intmain(int ac, char *av[]) { structsockaddr_insaddr;// build our address here structhostent *hp;// this is part of our address char hostname[HOSTLEN]; int sock_id, sock_fd; FILE *sock_fp; char *ctime(); // convert secs to string time_t thetime;
// Step1: ask kernel for a socket sock_id = socket(PF_INET, SOCK_STREAM, 0); if (sock_id == -1) oops("socket");
// Step2: bind address to socket. Address is host, port bzero((void *)&saddr, sizeof(saddr)); // clear out struct
gethostname(hostname, HOSTLEN); hp = gethostbyname(hostname);
// fill in host part bcopy((void *)hp->h_addr, (void *)&saddr.sin_addr, hp->h_length); saddr.sin_port = htons(PORTNUM); // fill in socket port saddr.sin_family = AF_INET; // fill in addr family
if (bind(sock_id, (struct sockaddr *)&saddr, sizeof(saddr)) != 0) oops("bind");
// Step3: allow incoming calls with Qsize=1 on socket if (listen(sock_id, 1) != 0) oops("listen");
// main loop: accept(), write(), close() while (1) { sock_fd = accept(sock_id, NULL, NULL); // wait for a call printf("Wow! got a call!\n"); if (sock_fd == -1) oops("accept");
sock_fp = fdopen(sock_fd, "w"); // wirte to the socket as a stream if (sock_fp == NULL) oops("fdopen");
thetime = time(NULL);
fprintf(sock_fp, "The time here is .."); fprintf(sock_fp, "%s", ctime(&thetime));
intmain(int ac, char *av[]) { structsockaddr_inservadd; structhostent *hp; int sock_id, sock_fd; char message[BUFSIZ]; int messlen;
// Step1: get a socket sock_id = socket(PF_INET, SOCK_STREAM, 0); if (sock_id == -1) oops("socket");
// Step2: connect to server // need to build address(host,port) of server first bzero(&servadd, sizeof(servadd)); // clear out struct
hp = gethostbyname(av[1]); if (hp == NULL) oops(av[1]);
// fill in host part bcopy(hp->h_addr, (struct sockaddr *)&servadd.sin_addr, hp->h_length); servadd.sin_port = htons(atoi(av[2])); // fill in socket port servadd.sin_family = AF_INET; // fill in addr family
if (connect(sock_id, (struct sockaddr *)&servadd, sizeof(servadd)) != 0) oops("connect");
// Step3: transfer data from server, then hangup messlen = read(sock_id, message, BUFSIZ); if (messlen == -1) oops("read"); if (write(1, message, messlen) != messlen) oops("write"); close(sock_id); }