CSci-E28 Section 2019-05-09 Notes
Table of Contents
1 Pipes and Dup
int p[2]; // pipe descriptors, 0 for reading, 1 for writing if (pipe(p) < 0) { perror("pipe"); exit(1); } // parent sending to child example #ifdef WILL_DUP if (dup2(p[0], 0) != 0) { perror("dup2"); exit(1); } int readfd = 0; #else int readfd = p[0]; int writefd = p[1]; #endif int pid = fork(); if (pid < 0) { perror("fork"); exit(1); } if (pid) { // parent close(readfd); ssize_t nb = write(p[1], data, len); // error checking } else { close(writefd); char buffer[BUFFER_SIZE]; // exec here in the dup case // child ssize_t nb = read(readfd, buffer, sizeof(buffer)); if (nb < 0) { perror("read"); _exit(1); } else if (nb > 0) { // read nb bytes } else { // eof, pipe was closed } }
2 Sockets
Examine wsng's socklib.c for more details.
int domain = PF_INET, // IP version 4 OR PF_LOCAL, // PF_UNIX OR PF_INET6; // IP version 6 int type = SOCK_STREAM, // TCP for INET (reliable byte-stream) OR SOCK_DGRAM, // UDP for INET (unreliable datagram) OR SOCK_SEQPACKET; // not used in INET int protocol = 0; // or use p_proto field of getprotobyname(3)\ int sock = socket(domain, type, protocol); // in SERVER case // optionally set socket options: reuse addr is most common int on = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { perror("setsockopt"); } // bind an address // often on a server address you set the port number but leave the incomming address INADDR_ANY // low numbered ports in IP are reserved to root struct sockaddr_in saddr; memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_addr.s_port = htons(YOUR_SERVERS_PORT_NUMBER_YOU_PICKED); if (bind(sock, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) { perror("bind"); exit(1); } // htonl converts a long from host to network byte order, htons for short. ntohl and ntohs reverse // listen for connections #define QUEUE_LENGTH 5 // a small number between 1 and something if (listen(sock, QUEUE_LENGTH) < 0) { perror("listen"); } // have an accept loop // addr and addrlen can be NULL if you don't care who you are talking to int fd = accept(sock, struct sockaddr *addr, socklen_t *addrlen); // fd is now something you can use read/write or send/recv, for datagram sendto/recvfrom // for STREAM types // You need to have a real IP address for connect, which is usually looked up with // gethostbyname. struct sockaddr_in saddr; memset(&saddr, 0, sizeof(saddr)); addr.sin_family = AF_INET; saddr.sin_port = htons(YOUR_SERVERS_PORT_NUMBER_YOU_PICKED); struct hostent *hp = gethostbyname(NAME_OF_SERVER_HOST); if (hp == NULL) { fprintf(stderr, "unknown host name '%s'", NAME_OF_SERVER_HOST); exit(1); } memcpy(&saddr.sin_addr, hp->h_addr, hp->h_length); // do connect if (connect(sock, (const struct sockaddr *) &saddr, sizeof(saddr)) < 0) { perror("connect"); exit(1); } // sock is now something you can read/write or send/recv, for datagram sendto/recvfrom
3 Shell Redirection Syntax
my_program >foo my_program 1>foo my_program <bar my_program 0<bar program 2>&1 program n>&- for x in a b c do echo foo $x done >file { echo a; echo b; } >file