代码改变世界

Cygwin Run in the Windows(Simulation of UNIX)

2013-11-06 22:05  夜雨瞳  阅读(865)  评论(2编辑  收藏  举报

Preface

Environment

Cygwin Run in the Windows(Simulation of UNIX)

Resource

Cygwin Install:http://cygwin.com/install.html

Cygwin API:http://cygwin.com/cygwin-api/

Lab 1 Program Layout

Content

Ex. 2.3 P.25

 

Exercise 2.3

Use ls -l to compare the sizes of the executable modules for the following two C programs. Explain the results.

Version 1: largearrayinit.c

Version 2: largearray.c

Source

Version 1: largearrayinit.c

#include<stdio.h>
int myarray[50000] = {1, 2, 3, 4};
int main(void) {
   myarray[0] = 3;
   printf("myarray[0]=%d myarray[1]=%d myarray[2]=%d myarray[3]=%d",myarray[0],myarray[1],myarray[2],myarray[3]);
   return 0;
}

 

Version 2: largearray.c

 

#include<stdio.h>
int myarray[50000];
int main(void) {
    myarray[0] = 3;
    printf("myarray[0]=%d myarray[1]=%d myarray[2]=%d",myarray[0],myarray[1],myarray[2]);
    return 0;
}

 

Result

Version 1: largearrayinit.c

 

Version 2: largearray.c

 

Lab2 Argument array

Content

Program 2.1 and 2.2, p.34-37

 

Program 2.2 makeargv.c

An implementation of makeargv.

Program 2.1 argtest.c

A program that takes a single string as its command-line argument and calls makeargv to create an argument array.

Source

Program 2.2 makeargv.c

#include <errno.h>
#include <stdlib.h>
#include <string.h>
int makeargv(const char *s, const char *delimiters, char ***argvp) {
   int error;
   int i;
   int numtokens;
   const char *snew;
   char *t;
   if ((s == NULL) || (delimiters == NULL) || (argvp == NULL)) {
      errno = EINVAL;
      return -1;
   }
   *argvp = NULL;                           
   snew = s + strspn(s, delimiters);         /* snew is real start of string */
   if ((t = malloc(strlen(snew) + 1)) == NULL) 
      return -1; 
   strcpy(t, snew);               
   numtokens = 0;
   if (strtok(t, delimiters) != NULL)     /* count the number of tokens in s */
      for (numtokens = 1; strtok(NULL, delimiters) != NULL; numtokens++) ; 
                             /* create argument array for ptrs to the tokens */
   if ((*argvp = malloc((numtokens + 1)*sizeof(char *))) == NULL) {
      error = errno;
      free(t);
      errno = error;
      return -1; 
   } 
                        /* insert pointers to tokens into the argument array */
   if (numtokens == 0) 
      free(t);
   else {
      strcpy(t, snew);
      **argvp = strtok(t, delimiters);
      for (i = 1; i < numtokens; i++)
          *((*argvp) + i) = strtok(NULL, delimiters);
    } 
    *((*argvp) + numtokens) = NULL;             /* put in final NULL pointer */
    return numtokens;
}     

 

Program 2.1 argtest.c

#include <stdio.h>
#include <stdlib.h>
int makeargv(const char *s, const char *delimiters, char ***argvp);
int main(int argc, char *argv[]) {
   char delim[] = " \t";
   int i;
   char **myargv;
   int numtokens;
   if (argc != 2) {
      fprintf(stderr, "Usage: %s string\n", argv[0]);
      return 1;
   }   
   if ((numtokens = makeargv(argv[1], delim, &myargv)) == -1) {
      fprintf(stderr, "Failed to construct an argument array for %s\n", argv[1]);
      return 1;
   } 
   printf("The argument array contains:\n");
   for (i = 0; i < numtokens; i++)
      printf("%d:%s\n", i, myargv[i]);
   return 0;
}

 

Result

 

Lab3 env

Content

Example 2.22, p.49

Example 2.24, p.51

 

Example 2.22 environ.c

The following C program outputs the contents of its environment list and exits.

Exercise 2.24 getpaths.c

Write a function to produce an argument array containing the components of the PATH environment variable.

Source

Example 2.22 environ.c

#include <stdio.h>
extern char **environ; 
int main(void) {
   int i;
   printf("The environment list follows:\n");
   for(i = 0; environ[i] != NULL; i++)
     printf("environ[%d]: %s\n", i, environ[i]);
   return 0;
}

 

Exercise 2.24 getpaths.c

#include <stdlib.h>
#define PATH_DELIMITERS ":"
int makeargv(const char *s, const char *delimiters, char ***argvp);
char **getpaths(void) {
   char **myargv;
   char *path;
   path = getenv("PATH");
   if (makeargv(path, PATH_DELIMITERS, &myargv) == -1)
      return NULL;
   else
      return myargv;
}

 

 

getpathstest.c

#include <stdio.h>
char **getpaths(void);
int main(void) {
   char **paths;
   int i;
   paths = getpaths();
   if (paths == NULL) {
      fprintf(stderr,"No path variable\n");
      return 1;
   }
   for (i = 0; paths[i] != NULL; i++)
      printf("[%d]:%s\n", i, paths[i]);
   return 0;
}

 

Result

Example 2.22 environ.c

 

Exercise 2.24 getpaths.c

 

Lab 4 Process Chain and Fan

Content

Program 3.1 and 3.2, p.67, 68

 

Program 3.1 simplechain.c

A program that creates a chain of n processes, where n is a command-line argument.

Program 3.2 simplefan.c

A program that creates a fan of n processes where n is passed as a command-line argument.

Source

Program 3.1 simplechain.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main (int argc, char *argv[]) {
   pid_t childpid = 0; 
   int i, n;
   if (argc != 2){   /* check for valid number of command-line arguments */ 
      fprintf(stderr, "Usage: %s processes\n", argv[0]);
      return 1; 
   }     
   n = atoi(argv[1]);  
   for (i = 1; i < n; i++)
      if (childpid = fork()) 
         break;
   fprintf(stderr, "i:%d  process ID:%ld  parent ID:%ld  child ID:%ld\n",
           i, (long)getpid(), (long)getppid(), (long)childpid);
   return 0; 
}

 

Program 3.2 simplefan.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main (int argc, char *argv[]) {
   pid_t childpid = 0; 
   int i, n;
 
   if (argc != 2){   /* check for valid number of command-line arguments */ 
      fprintf(stderr, "Usage: %s processes\n", argv[0]);
      return 1; 
   }     
   n = atoi(argv[1]);  
   for (i = 1; i < n; i++)
      if ((childpid = fork()) <= 0)
         break;
   fprintf(stderr, "i:%d  process ID:%ld  parent ID:%ld  child ID:%ld\n",
           i, (long)getpid(), (long)getppid(), (long)childpid);
   return 0; 
}

 

Result

Program 3.1 simplechain.c

 

Program 3.2 simplefan.c

 

Lab 5 wait()

Content

Ex. 3.21, p.76

 

Exercise 3.21 chainwaitmsg.c

The following program creates a process chain. Only one forked process is a child of the original process.

Source

Exercise 3.21 chainwaitmsg.c

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main (int argc, char *argv[]) {
   pid_t childpid;
   int i, n;
   pid_t waitreturn;
   if (argc != 2){   /* check number of command-line arguments */
      fprintf(stderr, "Usage: %s processes\n", argv[0]);
      return 1;
   }
   n = atoi(argv[1]);
   for (i = 1; i < n; i++)
      if (childpid = fork())
         break;
   while(childpid != (waitreturn = wait(NULL)))
      if ((waitreturn == -1) && (errno != EINTR))
         break;
   fprintf(stderr, "I am process %ld, my parent is %ld\n",
                     (long)getpid(), (long)getppid());
   return 0;
}

 

Result

Exercise 3.21 chainwaitmsg.c

 

Lab 6 exec()

Content

Program 3.5, p.81

 

Program 3.5 execcmd.c

A program that creates a child process to execute a command. The command to be executed is passed on the command line.

Source

r_wait.c

#include <errno.h>
#include <sys/wait.h>
pid_t r_wait(int *stat_loc) {
   int retval;
   while (((retval = wait(stat_loc)) == -1) && (errno == EINTR)) ;
   return retval;
}

Program 3.5 execcmd.c

#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "restart.h"
int main(int argc, char *argv[]) {
   pid_t childpid;
   if (argc < 2){      /* check for valid number of command-line arguments */
      fprintf (stderr, "Usage: %s command arg1 arg2 ...\n", argv[0]);
      return 1;
   }
   childpid = fork();
   if (childpid == -1) {
      perror("Failed to fork");
      return 1;
   }
   if (childpid == 0) {                                      /* child code */
      execvp(argv[1], &argv[1]);
      perror("Child failed to execvp the command");
      return 1;
   }
   if (childpid != r_wait(NULL)) {                          /* parent code */
      perror("Parent failed to wait");
      return 1;
   }
   return 0;    
}

 

Result

Program 3.5 execcmd.c

 

Lab 7*

Content

Please run the program with command line is “./argtest *.c”. Notice its output.

Source

argtest.c

#include <stdio.h>
#include <stdlib.h>
int makeargv(const char *s, const char *delimiters, char ***argvp);
int main(int argc, char *argv[]) {
   char delim[] = " \t";
   int i;
   char **myargv;
   int numtokens;
   if (argc != 2) {
      fprintf(stderr, "Usage: %s string\n", argv[0]);
      return 1;
   }   
   if ((numtokens = makeargv(argv[1], delim, &myargv)) == -1) {
      fprintf(stderr, "Failed to construct an argument array for %s\n", argv[1]);
      return 1;
   } 
   printf("The argument array contains:\n");
   for (i = 0; i < numtokens; i++)
      printf("%d:%s\n", i, myargv[i]);
   return 0;
}

 

Result

argtest.c

 

Lab 8 Basic file operations

Content

Program 4.9, 4.2, p.106, p.98

 

Program 4.2 copyfile1.c

The copyfile.c function copies a file from fromfd to tofd.

Example 4.7 simplecopy.c

The following program calls copyfile to copy a file from standard input to standard output.

Source

Program 4.2 copyfile1.c

#include <unistd.h>
#include "restart.h"
#define BLKSIZE 1024
int copyfile(int fromfd, int tofd) {
   char buf[BLKSIZE]; 
   int bytesread, byteswritten;
   int totalbytes = 0;
   for (  ;  ;  ) {
      if ((bytesread = r_read(fromfd, buf, BLKSIZE)) <= 0)
         break;     
      if ((byteswritten = r_write(tofd, buf, bytesread)) == -1)
         break;
      totalbytes += byteswritten;
   }
   return totalbytes;
}

Example 4.7 simplecopy.c

#include <stdio.h>
#include <unistd.h>
int copyfile(int fromfd, int tofd);
int main (void) {
   int numbytes;

   numbytes = copyfile(STDIN_FILENO, STDOUT_FILENO);
   fprintf(stderr, "Number of bytes copied: %d\n", numbytes);
   return 0;
}

 

Result

Example 4.7 simplecopy.c

 

Lab 9 Inheritance of file descriptor

Content

Example 4.27

Example 4.31

 

Example 4.27 openfork.c

In the following program, the child inherits the file descriptor for my.dat. Each process reads and outputs one character from the file.

Example 4.31 forkopen.c

In the following program, the parent and child each open my.dat for reading, read one character, and output that character.

Source

Example 4.27 openfork.c

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
int main(void) {
   char c = '!';
   int myfd;
   if ((myfd = open("my.dat", O_RDONLY)) == -1) {
      perror("Failed to open file");
      return 1;
   }
   if (fork() == -1) {
      perror("Failed to fork");
      return 1;
   }
   read(myfd, &c, 1);
   printf("Process %ld got %c\n", (long)getpid(), c);
   return 0;
}

 

Example 4.31 forkopen.c

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
int main(void) {
   char c = '!';
   int myfd;
   if (fork() == -1) {
      perror("Failed to fork");
      return 1;
   }
   if ((myfd = open("my.dat", O_RDONLY)) == -1) {
      perror("Failed to open file");
      return 1;
   }
   read(myfd, &c, 1);
   printf("Process %ld got %c\n", (long)getpid(), c);
   return 0;
}

 

Result

Please create 1 file name “my.data” in the running time.

 

Example 4.27 openfork.c

 

Example 4.31 forkopen.c

 

Lab 10 Directory Access

Content

Program 5.3, P.153

 

Program 5.3 shownames.c

A program to list files in a directory.

Source

Program 5.3 shownames.c

#include <dirent.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
   struct dirent *direntp;
   DIR *dirp;
   if (argc != 2) {
      fprintf(stderr, "Usage: %s directory_name\n", argv[0]);
      return 1; 
   }   
   if ((dirp = opendir(argv[1])) == NULL) {
      perror ("Failed to open directory");
      return 1;
   }   
   while ((direntp = readdir(dirp)) != NULL)
      printf("%s\n", direntp->d_name);
   while ((closedir(dirp) == -1) && (errno == EINTR)) ;
   return 0;
}

 

Result

Program 5.3 shownames.c

 

Lab 11 file information

Content

Ex 5.9, 5.10, P.156, 157

Source

printaccessmodbad.c

#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
void printaccessmodbad(char *path) {
   struct stat statbuf;
   if (stat(path, &statbuf) == -1)
      perror("Failed to get file status");
   else
      printf("%s accessed: %s modified: %s", path,
             ctime(&statbuf.st_atime), ctime(&statbuf.st_mtime));
}

 

printaccessmodbadtest.c

#include <dirent.h>
#include <errno.h>
#include <stdio.h>
void printaccessmodbad(char *path);
int main(int argc, char *argv[]) {
   struct dirent *direntp;
   DIR *dirp;
   if (argc != 2) {
      fprintf(stderr,"Usage: %s directory_name\n", argv[0]);
      return 1; 
   }   
   if ((dirp = opendir(argv[1])) == NULL) {
      perror ("failed to open directory");
      return 1;
   }   
   while ( (direntp = readdir(dirp)) != NULL )
      printaccessmodbad(direntp->d_name);
   while ( (closedir(dirp) == -1) && (errno == EINTR))  ;
   return 0;
}

 

Result

printaccessmodbadtest.c

 

Lab 12 Traversing Directories *

Content

5.8 Exercise , P.179

Source

Isdirectory.c

#include <stdio.h>
#include <time.h>
#include <sys/stat.h>
int isdirectory(char *path) {
   struct stat statbuf;

   if (stat(path, &statbuf) == -1)
      return 0;
   else
      return S_ISDIR(statbuf.st_mode);
}

Isdirectorytest.c

#include <stdio.h>
int isdirectory(char *path);
int main(int argc, char *argv[]) {
   if (argc != 2) {
      fprintf(stderr,"Usage: %s filename\n",argv[0]);
      return 1;
   }
   if (isdirectory(argv[1]))
      fprintf(stderr,"%s is a directory\n",argv[1]);
   else
      fprintf(stderr,"%s is not a directory\n",argv[1]);
   return 0;
}

 

Result

Isdirectorytest.c(I just solve the easy question)

 

Lab 13 pipeline

Content

Program 6.3, p.190

 

Program 6.3 simpleredirect.c

A program to execute the equivalent of ls -l | sort -n +4.

Source

Program 6.3 simpleredirect.c

#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void) {
   pid_t childpid;
   int fd[2];
   if ((pipe(fd) == -1) || ((childpid = fork()) == -1)) {
      perror("Failed to setup pipeline");
      return 1;
   }
   if (childpid == 0) {                                  /* ls is the child */
      if (dup2(fd[1], STDOUT_FILENO) == -1) 
         perror("Failed to redirect stdout of ls");
      else if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) 
         perror("Failed to close extra pipe descriptors on ls");
      else { 
         execl("/bin/ls", "ls", "-l", NULL);
         perror("Failed to exec ls");
      }
      return 1; 
   } 
   if (dup2(fd[0], STDIN_FILENO) == -1)               /* sort is the parent */
       perror("Failed to redirect stdin of sort");
   else if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) 
       perror("Failed to close extra pipe file descriptors on sort"); 
   else {
      //execl("/bin/sort", "sort", "-n", "+4", NULL);
      execl("/bin/ls", "ls", "-l", NULL);
      perror("Failed to exec sort");
   }
   return 1; 
}

 

Result

Program 6.3 simpleredirect.c

 

Lab 14 Block and unblock SIGINT

Content

Program 8.1, P.263

Program 8.3, P.265

 

Program 8.1 blocktest.c

A program that blocks and unblocks SIGINT.  Now I change 10 and over.

Program 8.3 blockchild.c

A program that blocks signals before calling fork and execl.

Source

Program 8.1 blocktest.c

#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc,  char *argv[]) {
   int i;
   sigset_t intmask;
   int repeatfactor;
   double y = 0.0;
   if (argc != 2) {
      fprintf(stderr, "Usage: %s repeatfactor\n", argv[0]);
      return 1; 
   }   
   repeatfactor = atoi(argv[1]);
   if ((sigemptyset(&intmask) == -1) || (sigaddset(&intmask, SIGINT) == -1)){
      perror("Failed to initialize the signal mask");
      return 1;
   }
   for ( ; ; ) {
      if (sigprocmask(SIG_BLOCK, &intmask, NULL) == -1)
         break; 
      fprintf(stderr, "SIGINT signal blocked\n");
      for (i = 0; i < repeatfactor; i++) 
         y += sin((double)i);
      fprintf(stderr, "Blocked calculation is finished, y = %f\n", y);
      if (sigprocmask(SIG_UNBLOCK, &intmask, NULL) == -1)
         break;
      fprintf(stderr, "SIGINT signal unblocked\n");
      for (i = 0; i < repeatfactor; i++) 
         y += sin((double)i);
      fprintf(stderr, "Unblocked calculation is finished, y=%f\n", y);
      if(i==10) break;
   }    
   perror("Success to change signal mask");
   return 1;
}

 

Program 8.3 blockchild.c

#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "restart.h"
int main(void) {
   pid_t child;
   sigset_t mask, omask;
   if ((sigfillset(&mask) == -1) || 
       (sigprocmask(SIG_SETMASK, &mask, &omask) == -1)) {
      perror("Failed to block the signals");
      return 1;
   }
   if ((child = fork()) == -1) {
      perror("Failed to fork child");
      return 1;
   } 
   if (child == 0) {                                   /* child code */
      execl("/bin/ls", "ls", "-l", NULL); 
      perror("Child failed to exec");
      return 1; 
   }
   if (sigprocmask(SIG_SETMASK, &omask, NULL) == -1){ /* parent code */
      perror("Parent failed to restore signal mask");
      return 1;
   }
  if (r_wait(NULL) == -1) {
     perror("Parent failed to wait for child");
     return 1;
   }
   return 0;
}

 

Result

Program 8.1 blocktest.c

 

Program 8.3 blockchild.c

 

Lab 15 Catch Signal

Content

Program 8.5, P.270

 

Program 8.5 signalterminate.c

A program that terminates gracefully when it receives a Ctrl-C. Now I change 5 and over.

Source

Program 8.5 signalterminate.c

#include <math.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
static volatile sig_atomic_t doneflag = 0;
/* ARGSUSED */
static void setdoneflag(int signo) {
   doneflag = 1;
}
int main (void) {
   struct sigaction act;
   int count = 0;
   double sum = 0;
   double x;
   act.sa_handler = setdoneflag;            /* set up signal handler */
   act.sa_flags = 0;
   if ((sigemptyset(&act.sa_mask) == -1) ||
       (sigaction(SIGINT, &act, NULL) == -1)) {
      perror("Failed to set SIGINT handler");
      return 1;
   }
   while (!doneflag) {
      x = (rand() + 0.5)/(RAND_MAX + 1.0);
      sum += sin(x);
      count++;
      printf("Count is %d and average is %f\n", count, sum/count);
      if(count==5) break;
   }
   printf("Program terminating ...\n");
   if (count == 0)
      printf("No values calculated yet\n");
   else
      printf("Count is %d and average is %f\n", count, sum/count);
   return 0;
}

 

Result

Program 8.5 signalterminate.c

 

Lab 16 Signal Wait

Content

Program 8.7, 8.8, P.278-279

Program 8.11, P.283

 

Program 8.7 simplesuspend.c

An object that allows a program to safely block on a specific signal.

Program 8.11 countsignals.c

A program that counts the number of SIGUSR1 signals sent to it.

Source

Program 8.7 simplesuspend.c

#include <errno.h>
#include <signal.h>
#include <unistd.h>
static int isinitialized = 0;
static struct sigaction oact; 
static int signum = 0;
static volatile sig_atomic_t sigreceived = 0;  
/* ARGSUSED */
static void catcher (int signo) {
    sigreceived = 1;
}
int initsuspend (int signo) {        /* set up the handler for the pause */
   struct sigaction act;
   if (isinitialized)
      return 0; 
   act.sa_handler = catcher;
   act.sa_flags = 0;
   if ((sigfillset(&act.sa_mask) == -1) ||
       (sigaction(signo, &act, &oact) == -1))
      return -1;
   signum = signo;
   isinitialized = 1;
   return 0;
} 
int restore(void) {
   if (!isinitialized)
      return 0;
   if (sigaction(signum, &oact, NULL) == -1)
      return -1;
   isinitialized = 0; 
   return 0; 
} 

int simplesuspend(void) {
   sigset_t maskblocked, maskold, maskunblocked;
   if (!isinitialized) {
      errno = EINVAL;
      return -1;
   }
   if ((sigprocmask(SIG_SETMASK, NULL, &maskblocked) == -1) ||
       (sigaddset(&maskblocked, signum) == -1) ||
       (sigprocmask(SIG_SETMASK, NULL, &maskunblocked) == -1) ||
       (sigdelset(&maskunblocked, signum) == -1) ||
       (sigprocmask(SIG_SETMASK, &maskblocked, &maskold) == -1))
       return -1;
   while(sigreceived == 0)
      sigsuspend(&maskunblocked);
   sigreceived = 0;
   return sigprocmask(SIG_SETMASK, &maskold, NULL);
}

 

simplesuspendtest.c

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int initsuspend(int signo);
int restore(void);
int simplesuspend(void);
int main(void) {
   fprintf(stderr, "This is process %ld\n", (long)getpid());
   for ( ; ; ) {
      if (initsuspend(SIGUSR1)) {
         perror("Failed to setup handler for SIGUSR1");
         return 1;
      }
      fprintf(stderr, "Waiting for signal\n");
      if (simplesuspend()) {
         perror("Failed to suspend for signal");
         return 1;
      }
      fprintf(stderr, "Got signal\n");
      if (restore()) {
         perror("Failed to restore original handler");
         return 1;
      }
   }
   return 1;
}

Program 8.11 countsignals.c

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main(void) {
   int signalcount = 0;
   int signo;
   int signum = SIGUSR1;
   sigset_t sigset;
   if ((sigemptyset(&sigset) == -1) ||
       (sigaddset(&sigset, signum) == -1) ||
       (sigprocmask(SIG_BLOCK, &sigset, NULL) == -1))
      perror("Failed to block signals before sigwait"); 
   fprintf(stderr, "This process has ID %ld\n", (long)getpid());
   for ( ; ; ) {
      if (sigwait(&sigset, &signo) == -1) {
         perror("Failed to wait using sigwait");
         return 1;
      }
      signalcount++;
      fprintf(stderr, "Number of signals so far: %d\n", signalcount);
   }
}

Result

Program 8.7 simplesuspend.c

 

Program 8.11 countsignals.c

 

Lab 17 siglongjmp

Content

Program 8.12, P.287

 

Program 8.12 sigjmp.c

Code to set up a signal handler that returns to the main loop when Ctrl-C is typed.

Source

Program 8.12 sigjmp.c

#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t jumpok = 0;
/* ARGSUSED */
static void chandler(int signo) {
   if (jumpok == 0) return;
   siglongjmp(jmpbuf, 1);
}
int main(void)  {
   struct sigaction act;
   act.sa_flags = 0;
   act.sa_handler = chandler;
   if ((sigemptyset(&act.sa_mask) == -1) ||
       (sigaction(SIGINT, &act, NULL) == -1)) {
      perror("Failed to set up SIGINT handler");
      return 1; 
   }
                                                  /* stuff goes here */
   fprintf(stderr, "This is process %ld\n", (long)getpid());
   if (sigsetjmp(jmpbuf, 1))
      fprintf(stderr, "\nReturned to main loop due to ^c\n");
   jumpok = 1;
   for ( ; ; ) 
      ;                                       /* main loop goes here */
}

 

Result

Program 8.12 sigjmp.c

 

Lab 18 POSIX Times

Content

Example 9.2, P.303

Program 9.1, P.307

Program 9.4, P.312

 

Example 9.2 simpletiming.c

The following program calculates the wall-clock time that it takes to execute function_to_time.

Program 9.1 gettimeofdaytiming.c

A program that measures the running time of a function by using gettimeofday.

Program 9.4 cpufraction.c

A program that calculates the CPU time in seconds for function_to_time and its fraction of total.

Source

functiontotime.c

#include <unistd.h>
#include <sys/time.h>
void function_to_time() {
   int i;
   for (i=0;i<100000000;i++) ;
}
Example 9.2 simpletiming.c
#include <stdio.h>
#include <time.h>
void function_to_time(void);
int main(void) {
   time_t tstart;  
   tstart = time(NULL);
   function_to_time();
   printf("function_to_time took %f seconds of elapsed time\n", 
           difftime(time(NULL), tstart)); 
   return 0;
}

 

Program 9.1 gettimeofdaytiming.c

#include <stdio.h>
#include <sys/time.h>
#define MILLION 1000000L
void function_to_time(void);
int main(void) {
   long timedif;
   struct timeval tpend;
   struct timeval tpstart;
   if (gettimeofday(&tpstart, NULL)) {
      fprintf(stderr, "Failed to get start time\n");
      return 1;
   }
   function_to_time();                              /* timed code goes here */
   if (gettimeofday(&tpend, NULL)) {
      fprintf(stderr, "Failed to get end time\n");
      return 1;
   }
   timedif = MILLION*(tpend.tv_sec - tpstart.tv_sec) +
                      tpend.tv_usec - tpstart.tv_usec;
   printf("The function_to_time took %ld microseconds\n", timedif);
   return 0;
}

 

Program 9.4 cpufraction.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/times.h>
void function_to_time(void);
int main(void) { 
   double clockticks, cticks;
   clock_t tcend, tcstart;
   struct tms tmend, tmstart;
   if ((clockticks = (double) sysconf(_SC_CLK_TCK)) == -1) {
      perror("Failed to determine clock ticks per second");
      return 1;
   }
   printf("The number of ticks per second is %f\n", clockticks);
   if (clockticks == 0) {
      fprintf(stderr, "The number of ticks per second is invalid\n");
      return 1;
   }
   if ((tcstart = times(&tmstart)) == -1) {
      perror("Failed to get start time");
      return 1;
   }
   function_to_time(); 
   if ((tcend = times(&tmend)) == -1) {
      perror("Failed to get end times");
      return 1;
   }
   cticks = tmend.tms_utime + tmend.tms_stime 
             - tmstart.tms_utime - tmstart.tms_stime;
   printf("Total CPU time for operation is %f seconds\n", cticks/clockticks); 
   if ((tcend <= tcstart) || (tcend < 0) || (tcstart < 0)) {
      fprintf(stderr, "Tick time wrapped, couldn't calculate fraction\n");
      return 1;
   }
   printf("Fraction of CPU time used is %f\n", cticks/(tcend - tcstart));
   return 0;
}

 

Result

Example 9.2 simpletiming.c

 

Program 9.1 gettimeofdaytiming.c

 

Program 9.4 cpufraction.c

 

Lab 19 Interval Timer

Content

Program 9.7, P.318

Program 9.12, P.329

 

Program 9.7 periodicasterisk.c

A program that prints an asterisk for each two seconds of CPU time used.

Program 9.12 tmrtimer.c

A program that uses a POSIX:TMR timer to measure the running time of a function.

Source

Program 9.7 periodicasterisk.c

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h> 
#include <sys/time.h>
struct timeval timenow;
/* ARGSUSED */
static void myhandler(int s) {
   gettimeofday(&timenow, NULL);
   printf("\nmyhandler time is %ld seconds\n", timenow.tv_sec);
   char aster = '*';
   int errsave;
   errsave = errno;
   write(STDERR_FILENO, &aster, 1);
   errno = errsave;
}
static int setupinterrupt(void) {          /* set up myhandler for  SIGPROF */
   gettimeofday(&timenow, NULL);
   printf("setupinterrupt time is %ld seconds\n", timenow.tv_sec);
   struct sigaction act;
   act.sa_handler = myhandler;
   act.sa_flags = 0;
   return (sigemptyset(&act.sa_mask) || sigaction(SIGPROF, &act, NULL));
}
static int setupitimer(void) {    /* set ITIMER_PROF for 2-second intervals */
   struct itimerval value;
   value.it_interval.tv_sec = 2;
   value.it_interval.tv_usec = 0;
   value.it_value = value.it_interval;
   return (setitimer(ITIMER_PROF, &value, NULL));
}
int main(void) {
   if (setupinterrupt()) {
      perror("Failed to set up handler for SIGPROF");
      return 1;
   }
   if (setupitimer() == -1) {
      perror("Failed to set up the ITIMER_PROF interval timer"); 
      return 1;
   }
   for ( ; ; );                        /* execute rest of main program here */
}

 

Program 9.12 tmrtimer.c

#include <stdio.h>
#include <signal.h>
#include <time.h> 
#define MILLION 1000000L
#define THOUSAND 1000
void function_to_time(void);
int main(void) {
   long diftime;
   struct itimerspec nvalue, ovalue;
   timer_t timeid;
   if (timer_create(CLOCK_REALTIME, NULL, &timeid) == -1) {
      perror("Failed to create a timer based on CLOCK_REALTIME");
      return 1;
   }
   ovalue.it_interval.tv_sec = 0;
   ovalue.it_interval.tv_nsec = 0;
   ovalue.it_value.tv_sec = MILLION;               /* a large number */
   ovalue.it_value.tv_nsec = 0;
   if (timer_settime(timeid, 0, &ovalue, NULL) == -1) {
      perror("Failed to set interval timer"); 
      return 1;
   }
   function_to_time();                       /* timed code goes here */
   if (timer_gettime(timeid, &nvalue) == -1) {
      perror("Failed to get interval timer value");
      return 1;
   }
   diftime = MILLION*(ovalue.it_value.tv_sec - nvalue.it_value.tv_sec) +
      (ovalue.it_value.tv_nsec - nvalue.it_value.tv_nsec)/THOUSAND;
   printf("The function_to_time took %ld microseconds or %f seconds.\n",
           diftime, diftime/(double)MILLION);
   return 0;
}

 

Result

Program 9.7 periodicasterisk.c

 

Program 9.12 tmrtimer.c

 

Lab 20 Threads

Content

Create and Passing parameter, Program 12.2, P.414

Condition variable, Program 13.13, P.472

 

Program 12.2 monitorfd.c

A function to monitor an array of file descriptors, using a separate thread for each descriptor.

Program 13.13 tbarrier.c

Implementation of a thread-safe barrier.

Source

Program 12.2 monitorfd.c

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *processfd(void *arg);
void monitorfd(int fd[], int numfds) {       /* create threads to monitor fds */
   int error, i;
   pthread_t *tid;
   if ((tid = (pthread_t *)calloc(numfds, sizeof(pthread_t))) == NULL) {
      perror("Failed to allocate space for thread IDs");
      return;
   }
   for (i = 0; i < numfds; i++)   /* create a thread for each file descriptor */
      if (error = pthread_create(tid + i, NULL, processfd, (fd + i))) {
         fprintf(stderr, "Failed to create thread %d: %s\n",
                         i, strerror(error));
         tid[i] = pthread_self();
      }
   for (i = 0; i < numfds; i++) {
      if (pthread_equal(pthread_self(), tid[i]))
         continue;
      if (error = pthread_join(tid[i], NULL))
         fprintf(stderr, "Failed to join thread %d: %s\n", i, strerror(error));
   }
   free(tid);
   return;
}

 

monitorfdtest.c

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
void monitorfd(int fd[], int numfds);
void docommand(char *buf, int len) {
   fprintf(stderr,"Got %.*s",len,buf);
}
int main(int argc, char *argv[]) {
   int fd[2];
   if (argc != 3) {
      fprintf(stderr,"Usage: %s file1 file2\n",argv[0]);
      return 1;
   }
   if ( (fd[0] = open(argv[1],O_RDONLY)) < 0) {
      fprintf(stderr,"Error opening file %s\n",argv[1]);
      return 1;
   }
   if ( (fd[1] = open(argv[2],O_RDONLY)) < 0) {
      fprintf(stderr,"Error opening file %s\n",argv[2]);
      return 1;
   }
   monitorfd(fd,2);
   return 0;
}

 

Program 13.13 tbarrier.c

#include <errno.h>
#include <pthread.h>
static pthread_cond_t bcond = PTHREAD_COND_INITIALIZER;
static pthread_mutex_t bmutex = PTHREAD_MUTEX_INITIALIZER;
static int count = 0;
static int limit = 0;
int initbarrier(int n) {              /* initialize the barrier to be size n */
   int error;
   if (error = pthread_mutex_lock(&bmutex))        /* couldn't lock, give up */
      return error;
   if (limit != 0) {                 /* barrier can only be initialized once */
      pthread_mutex_unlock(&bmutex);
      return EINVAL;
   }
   limit = n;
   return pthread_mutex_unlock(&bmutex);
}
int waitbarrier(void) {    /* wait at the barrier until all n threads arrive */
   int berror = 0;
   int error;
   if (error = pthread_mutex_lock(&bmutex))        /* couldn't lock, give up */
      return error;
   if (limit <=  0) {                       /* make sure barrier initialized */
      pthread_mutex_unlock(&bmutex);
      return EINVAL; 
   }
   count++;
   while ((count < limit) && !berror)
      berror =  pthread_cond_wait(&bcond, &bmutex); 
   if (!berror)  
      berror = pthread_cond_broadcast(&bcond);           /* wake up everyone */
   error = pthread_mutex_unlock(&bmutex);
   if (berror)
      return berror;
   return error;
}

 

tbarriertest.c

#include <pthread.h>
#include <stdio.h>
int initbarrier(int n);
int waitbarrier();
/* ARGSUSED */
static void *printthread(void *arg) {
   fprintf(stderr,"This is the first print of thread %d\n",
                   (int)pthread_self());
   waitbarrier();
   fprintf(stderr,"This is the second print of thread %d\n",
                   (int)pthread_self());
   return NULL;
}
int main(void) {
   pthread_t t0,t1,t2;
   if (initbarrier(3)) {
      fprintf(stderr,"Error initilizing barrier\n");
      return 1;
   }
   if (pthread_create(&t0,NULL,printthread,NULL))
      fprintf(stderr,"Error creating thread 0.\n");
   if (pthread_create(&t1,NULL,printthread,NULL))
      fprintf(stderr,"Error creating thread 1.\n");
   if (pthread_create(&t2,NULL,printthread,NULL))
      fprintf(stderr,"Error creating thread 2.\n");
   if (pthread_join(t0,NULL))
      fprintf(stderr,"Error joining thread 0.\n");
   if (pthread_join(t1,NULL))
      fprintf(stderr,"Error joining thread 1.\n");
   if (pthread_join(t2,NULL))
      fprintf(stderr,"Error joining thread 2.\n");
   fprintf(stderr,"All threads complete.\n");
   return 0;
}

 

 

Result

Please create 2 files in the running environment!

 

monitorfdtest.c

 

tbarriertest.c

 

Lab 21 Socket Programming

Content

Server and Client, Program 18.2, 18.3, P.623, 624

Program 18.9, find IP address for www.scut.edu.cn

Sever and Client in UDP, Program 20.1, 20.2, P.698,699

TCP ping, Excercises 18.10, P.652,

UDP getdayandtime, Exercise 20.10, P.729 *

 

Program 18.2 serverp.c

A server program that forks a child to handle communication.

Program 18.3 client.c

A client that uses UICI for communication.

 

Program 20.1 server_udp.c

A server program writes sender information and the received message to its standard output.

Program 20.2 client_udp.c

A client program that sends a request containing its process ID.

 

Program 18.10 addr2name_gethostbyaddr.c

An implementation of addr2name using gethostbyaddr.

 

 

Source

uiciname.h

/* uiciname.h  name resolution functions */
#include <netinet/in.h>
#define REENTRANT_NONE 0
#define REENTRANT_R 1
#define REENTRANT_MUTEX 2
#define REENTRANT_POSIX 3
int name2addr(char *name, in_addr_t *addrp);
void addr2name(struct in_addr addr, char *name, int namelen);

 

uiciname.c

/* uiciname.c  name resolution functions */
#include <ctype.h>
#include <netdb.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include "uiciname.h"
#ifndef REENTRANCY
#define REENTRANCY REENTRANT_NONE
#endif
#if REENTRANCY==REENTRANT_MUTEX
#include <pthread.h>
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
#if REENTRANCY==REENTRANT_NONE
/* Convert struct in_addr to a host name */
void addr2name(struct in_addr addr, char *name, int namelen) {
   struct hostent *hostptr;
   hostptr = gethostbyaddr((char *)&addr, 4, AF_INET);
   if (hostptr == NULL)
      strncpy(name, inet_ntoa(addr), namelen-1);
   else
      strncpy(name, hostptr->h_name, namelen-1);
   name[namelen-1] = 0;
}

/* Return -1 on error, 0 on success */
int name2addr(char *name, in_addr_t *addrp) {
   struct hostent *hp;

   if (isdigit((int)(*name)))
      *addrp = inet_addr(name);
   else {
      hp = gethostbyname(name);
      if (hp == NULL)
         return -1;
      memcpy((char *)addrp, hp->h_addr_list[0], hp->h_length);
   }
   return 0;
}
#elif REENTRANCY==REENTRANT_R
#define GETHOST_BUFSIZE 8192
void addr2name(struct in_addr addr, char *name, int namelen) {
   char buf[GETHOST_BUFSIZE];
   int h_error;
   struct hostent *hp;
   struct hostent result;
   hp = gethostbyaddr_r((char *)&addr, 4, AF_INET, &result, buf,
                         GETHOST_BUFSIZE, &h_error);
   if (hp == NULL)
      strncpy(name, inet_ntoa(addr), namelen-1);
   else
      strncpy(name, hp->h_name, namelen-1);
   name[namelen-1] = 0;
}
/* Return -1 on error, 0 on success */
int name2addr(char *name, in_addr_t *addrp) {
   char buf[GETHOST_BUFSIZE];
   int h_error;
   struct hostent *hp;
   struct hostent result;
 
   if (isdigit((int)(*name)))
      *addrp = inet_addr(name);
   else {
      hp = gethostbyname_r(name, &result, buf, GETHOST_BUFSIZE, &h_error);
      if (hp == NULL)
         return -1;
      memcpy((char *)addrp, hp->h_addr_list[0], hp->h_length);
   }
   return 0;
}   
#elif REENTRANCY==REENTRANT_MUTEX
/* Convert struct in_addr to a host name */
void addr2name(struct in_addr addr, char *name, int namelen) {
   struct hostent *hostptr;

   if (pthread_mutex_lock(&mutex) == -1) {
      strncpy(name, inet_ntoa(addr), namelen-1); 
      name[namelen-1] = 0;
      return;
   }
   hostptr = gethostbyaddr((char *)&addr, 4, AF_INET);
   if (hostptr == NULL)
      strncpy(name, inet_ntoa(addr), namelen-1); 
   else  
      strncpy(name, hostptr->h_name, namelen-1);
   pthread_mutex_unlock(&mutex);
   name[namelen-1] = 0;
}
 
/* Return -1 on error, 0 on success */
int name2addr(char *name, in_addr_t *addrp) {
   struct hostent *hp;
 
   if (isdigit((int)(*name)))
      *addrp = inet_addr(name);
   else {
      if (pthread_mutex_lock(&mutex) == -1)
         return -1;
      hp = gethostbyname(name);
      if (hp == NULL) {
         pthread_mutex_unlock(&mutex);
         return -1;
      }
      memcpy((char *)addrp, hp->h_addr_list[0], hp->h_length);
      pthread_mutex_unlock(&mutex);
   }
   return 0;
}
#elif REENTRANCY==REENTRANT_POSIX
/* Convert struct in_addr to a host name */
void addr2name(struct in_addr addr, char *name, int namelen) {
   struct sockaddr_in saddr;
   saddr.sin_family = AF_INET;
   saddr.sin_port = 0;
   saddr.sin_addr = addr;
   if (getnameinfo((struct sockaddr *)&saddr, sizeof(saddr), name, namelen,
         NULL, 0, 0) != 0) {
      strncpy(name, inet_ntoa(addr), namelen-1);
      name[namelen-1] = 0;
   }
}
/* Return -1 on error, 0 on success */
int name2addr(char *name, in_addr_t *addrp) {
   struct addrinfo hints;
   struct addrinfo *res;
   struct sockaddr_in *saddrp;
   hints.ai_flags = AI_PASSIVE;
   hints.ai_family = PF_INET;
   hints.ai_socktype = SOCK_STREAM;
   hints.ai_protocol = 0;
   hints.ai_addrlen = 0;
   hints.ai_canonname = NULL;
   hints.ai_addr = NULL;
   hints.ai_next = NULL; 
   if (getaddrinfo(name, NULL, &hints, &res) != 0)
      return -1;
   saddrp = (struct sockaddr_in *)(res->ai_addr);
   memcpy(addrp, &saddrp->sin_addr.s_addr, 4);
   freeaddrinfo(res);
   return 0;
}
#endif

 

uici.h

/*********************************** uici.h **************************/
/*   Prototypes for the three public UICI functions                  */  
/*********************************************************************/
#define UPORT
typedef unsigned short u_port_t;
int u_open(u_port_t port);
int u_accept(int fd, char *hostn, int hostnsize);
int u_connect(u_port_t port, char *hostn);

uici.c

/* uici.c  sockets implementation */
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/socket.h>
#include "uici.h"
#include "uiciname.h"

#ifndef MAXBACKLOG
#define MAXBACKLOG 50
#endif
/*
 *                           u_igniore_sigpipe
 * Ignore SIGPIPE if the default action is in effect.
 *
 * returns: 0 if successful
 *          -1 on error and sets errno
 */
static int u_ignore_sigpipe() {
   struct sigaction act;

   if (sigaction(SIGPIPE, (struct sigaction *)NULL, &act) == -1)
      return -1;
   if (act.sa_handler == SIG_DFL) {
      act.sa_handler = SIG_IGN;
      if (sigaction(SIGPIPE, &act, (struct sigaction *)NULL) == -1)
         return -1;
   }   
   return 0;
}
/*
 *                           u_open
 * Return a file descriptor, which is bound to the given port.
 * parameter:
 *        s = number of port to bind to
 * returns:  file descriptor if successful
 *           -1 on error and sets errno
 */
int u_open(u_port_t port) {
   int error;  
   struct sockaddr_in server;
   int sock;
   int true = 1;

   if ((u_ignore_sigpipe() == -1) ||
        ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1))
      return -1; 
   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&true,
                  sizeof(true)) == -1) {
      error = errno;
      while ((close(sock) == -1) && (errno == EINTR)); 
      errno = error;
      return -1;
   }
   server.sin_family = AF_INET;
   server.sin_addr.s_addr = htonl(INADDR_ANY);
   server.sin_port = htons((short)port);
   if ((bind(sock, (struct sockaddr *)&server, sizeof(server)) == -1) ||
        (listen(sock, MAXBACKLOG) == -1)) {
      error = errno;
      while ((close(sock) == -1) && (errno == EINTR)); 
      errno = error;
      return -1;
   }
   return sock;
}
/*
 *                           u_accept
 * Wait for a connection request from a host on a specified port.
 *
 * parameters:
 *      fd = file descriptor previously bound to listening port
 *      hostn = a buffer that will hold the name of the remote host
 *      hostnsize = size of hostn buffer
 * returns:  a communication file descriptor on success
 *              hostn is filled with the name of the remote host.
 *           -1 on error with errno set
 *
 * comments: This function is used by the server to wait for a
 * communication.  It blocks until a remote request is received
 * from the port bound to the given file descriptor.
 * hostn is filled with an ASCII string containing the remote
 * host name.  It must point to a buffer of size at least hostnsize.
 * If the name does not fit, as much of the name as is possible is put
 * into the buffer.
 * If hostn is NULL or hostnsize <= 0, no hostname is copied.
 */
int u_accept(int fd, char *hostn, int hostnsize) {
   int len = sizeof(struct sockaddr);
   struct sockaddr_in netclient;
   int retval;

   while (((retval =
           accept(fd, (struct sockaddr *)(&netclient), &len)) == -1) &&
          (errno == EINTR))
      ;  
   if ((retval == -1) || (hostn == NULL) || (hostnsize <= 0))
      return retval;
   addr2name(netclient.sin_addr, hostn, hostnsize);
   return retval;
}
/*
 *                           u_connect
 * Initiate communication with a remote server.
 *
 * parameters:
 *     port  = well-known port on remote server
 *     hostn = character string giving the Internet name of remote host
 * returns:  a communication file descriptor if successful
 *           -1 on error with errno set
 */
int u_connect(u_port_t port, char *hostn) {
   int error;
   int retval;
   struct sockaddr_in server;
   int sock;
   fd_set sockset;

   if (name2addr(hostn,&(server.sin_addr.s_addr)) == -1) {
      errno = EINVAL;
      return -1;
   }
   server.sin_port = htons((short)port);
   server.sin_family = AF_INET;

   if ((u_ignore_sigpipe() == -1) ||
        ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1))
      return -1;

   if (((retval =
       connect(sock, (struct sockaddr *)&server, sizeof(server))) == -1) &&
       ((errno == EINTR) || (errno == EALREADY))) {
       FD_ZERO(&sockset);
       FD_SET(sock, &sockset);
       while ( ((retval = select(sock+1, NULL, &sockset, NULL, NULL)) == -1) &&
               (errno == EINTR) ) {
          FD_ZERO(&sockset);
          FD_SET(sock, &sockset);
       } 
   }
   if (retval == -1) {
        error = errno;
        while ((close(sock) == -1) && (errno == EINTR)); 
        errno = error;
        return -1;
   }
   return sock;
}

 

 

Program 18.2 serverp.c

#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "restart.h"
#include "uici.h"

int main(int argc, char *argv[]) {
   int bytescopied;
   pid_t child;
   char client[MAX_CANON];
   int communfd;
   int listenfd;
   u_port_t portnumber;
 
   if (argc != 2) {
      fprintf(stderr, "Usage: %s port\n", argv[0]);
      return 1;   
   }  
   portnumber = (u_port_t) atoi(argv[1]);
   if ((listenfd = u_open(portnumber)) == -1) {
      perror("Failed to create listening endpoint");
      return 1;
   }
   fprintf(stderr, "[%ld]: Waiting for connection on port %d\n",
                    (long)getpid(), (int)portnumber);
   for ( ; ; ) {
      if ((communfd = u_accept(listenfd, client, MAX_CANON)) == -1) {
         perror("Failed to accept connection");
         continue;
      }
      fprintf(stderr, "[%ld]:connected to %s\n", (long)getpid(), client);
      if ((child = fork()) == -1) 
         perror("Failed to fork a child");
      if (child == 0) {                                         /* child code */
         if (r_close(listenfd) == -1) {
            fprintf(stderr, "[%ld]:failed to close listenfd: %s\n",
                             (long)getpid(), strerror(errno));
            return 1;
         }
         bytescopied = copyfile(communfd, STDOUT_FILENO);
         fprintf(stderr, "[%ld]:received %d bytes\n",
                          (long)getpid(), bytescopied);
         return 0;
      }
      if (r_close(communfd) == -1)                             /* parent code */
         fprintf(stderr, "[%ld]:failed to close communfd: %s\n",
                          (long)getpid(), strerror(errno));
      while (r_waitpid(-1, NULL, WNOHANG) > 0)  ;         /* clean up zombies */
   }
}

 

 

Program 18.3 client.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "restart.h"
#include "uici.h"
 
int main(int argc, char *argv[]) {
   int bytescopied;
   int communfd;
   u_port_t portnumber;
 
   if (argc != 3) {
      fprintf(stderr, "Usage: %s host port\n", argv[0]);
      return 1;
   }
   portnumber = (u_port_t)atoi(argv[2]);
   if ((communfd = u_connect(portnumber, argv[1])) == -1) {
      perror("Failed to make connection");
      return 1;
   }
   fprintf(stderr, "[%ld]:connected %s\n", (long)getpid(), argv[1]);
   bytescopied = copyfile(STDIN_FILENO, communfd);
   fprintf(stderr, "[%ld]:sent %d bytes\n", (long)getpid(), bytescopied);
   return 0;
}

 

 

uiciudp.h

#include <netinet/in.h>

#ifndef UPORT
typedef unsigned short u_port_t;
#endif
#define UPORT

#ifndef ETIME
#define ETIME ETIMEDOUT
#endif

typedef struct sockaddr_in u_buf_t;
int u_openudp(u_port_t port);
void u_gethostname(u_buf_t *ubufp, char *hostn, int hostnsize);
void u_gethostinfo(u_buf_t *ubufp, char *info, int infosize);
int u_comparehost(u_buf_t *ubufp, char *hostn, u_port_t port);
ssize_t u_sendtohost(int fd, void *buf, size_t nbyte, char *hostn,
                     u_port_t port);
ssize_t u_sendto(int fd, void *buf, size_t nbyte, u_buf_t *ubufp);
ssize_t u_recvfrom(int fd, void *buf, size_t nbyte, u_buf_t *ubufp);
ssize_t u_recvfromtimed(int fd, void *buf, size_t nbyte, u_buf_t *ubufp,
                         double time);
int u_join(char *IP_address, u_port_t port, u_buf_t *ubufp);
int u_leave(int mcastfd, u_buf_t *ubufp);

 

 

uiciudp.c

/* uiciudp.c udp sockets implementation */
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/time.h>
#include "restart.h"
#include "uiciname.h"
#include "uiciudp.h"

/*
 *                           u_openudp
 * Return a file descriptor.
 *  It is bound to the given port if the port is positive.
 *
 * parameter:
 *        port = number of port to bind to
 * returns:  file descriptor if successful
 *           -1 on error and sets errno
 */
int u_openudp(u_port_t port) {
   int error;
   int one = 1;
   struct sockaddr_in server;
   int sock;

   if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
      return -1;

   if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
      error = errno;
      r_close(sock);
      errno = error;
      return -1;
   }
       
   if (port > 0) {
      server.sin_family = AF_INET;
      server.sin_addr.s_addr = htonl(INADDR_ANY);
      server.sin_port = htons((short)port);
 
      if (bind(sock, (struct sockaddr *)&server, sizeof(server)) == -1) {
         error = errno;
         r_close(sock);
         errno = error;
         return -1;
      }
   }
   return sock;
}

/*
 *                           u_recvfrom
 *
 * Retrieve information from a file descriptor.
 *
 * parameters:
 *       fd = socket file descriptor
 *       buf = buffer that receives the data
 *       nbytes = number of bytes to retrieve
 *       ubufp = a pointer to a buffer of type u_buf_t
 * returns:
 *      the number of bytes read if successful.
 *         ubufp is filled with information about the sending host and port
 *      -1 on error and sets errno
 */

ssize_t u_recvfrom(int fd, void *buf, size_t nbytes, u_buf_t *ubufp) {
   int len;
   struct sockaddr *remote;
   int retval;

   len = sizeof (struct sockaddr_in);
   remote = (struct sockaddr *)ubufp;
   while (((retval = recvfrom(fd, buf, nbytes, 0, remote, &len)) == -1) &&
           (errno == EINTR)) ;  
   return retval;
}

/*
 *                           u_recvfromtimed
 *
 * Retrieve information from a file descriptor with a timeout.
 *
 * parameters:
 *       fd = socket file descriptor
 *       buf = buffer to receive the data
 *       nbytes = number of bytes to retrieve
 *       ubufp = a pointer to a buffer of type u_buf_t
 *       seconds = timeout in seconds
 * returns:
 *      number of bytes received if successful
 *      -1 on error and sets errno
 */

ssize_t u_recvfromtimed(int fd, void *buf, size_t nbytes, u_buf_t *ubufp,
                         double seconds) {
   int len;
   struct sockaddr *remote;
   int retval;
   struct timeval timedone;

   timedone = add2currenttime(seconds);
   if (waitfdtimed(fd, timedone) == -1)
      return (ssize_t)(-1);
   len = sizeof (struct sockaddr_in);
   remote = (struct sockaddr *)ubufp;
   while (((retval = recvfrom(fd, buf, nbytes, 0, remote, &len)) == -1) &&
           (errno == EINTR)) ;  
   return retval;
}

/*
 *                           u_gethostname
 *
 * Get the host name from a buffer of type u_buf_t
 *
 * parameters:
 *       ubufp = a pointer to a buffer of type u_buf_t that was
 *          filled by u_recvfrom
 *       hostn = a buffer of size hostnsize
 *       hostsize = the size of the hostn buffer
 * returns:
 *      hostn is filled with the name of the host, possibly truncated.
 */

void u_gethostname(u_buf_t *ubufp, char *hostn, int hostnsize) {
   struct sockaddr_in *remotep;

   remotep = (struct sockaddr_in *)ubufp;
   addr2name(remotep->sin_addr, hostn, hostnsize);
}

/*
 *                           u_gethostinfo
 *
 * Get a printable string containing the host name and port
 *
 * parameters:
 *       ubufp = a pointer to a buffer of type u_buf_t that was
 *          filled by u_recvfrom
 *       info = a buffer to hold the returned string
 *       infosize = the size of the info buffer
 * returns:
 *      a string is put in info, possibly truncated
 */
void u_gethostinfo(u_buf_t *ubufp, char *info, int infosize) {
   int len;
   int portnumber;

   portnumber = ntohs(ubufp->sin_port);
   len = snprintf(info, infosize, "port number is %d on host ", portnumber);
   info[infosize-1] = 0;                              /* in case name not fit */
   if (len >= infosize) return;
   u_gethostname(ubufp, info+len, infosize-len);
}

 
/*
 *                           u_comparehost
 *
 * Compare the given host and port with the info in a u_buf_t structure
 *
 * parameters:
 *       ubufp = a pointer to a buffer of type u_buf_t that was
 *          filled by u_recvfrom
 *       hostn = a string representing the host name
 *       port  = a port number
 * returns:
 *      1 if match
 *      0 if no match
 */
 
int u_comparehost(u_buf_t *ubufp, char *hostn, u_port_t port) {
   in_addr_t addr;
   struct sockaddr_in *remotep;

   remotep = (struct sockaddr_in *)ubufp;
   if ((port != ntohs(remotep->sin_port)) ||
       (name2addr(hostn, &addr) == -1) ||
       (memcmp(&(remotep->sin_addr.s_addr), &addr, sizeof(in_addr_t)) != 0))
      return 0;
   return 1;
}

 
/*
 *                           u_sendto
 *
 * Send information atomically to a remote host, using the buffer filled in
 * by recvfrom
 *
 * This is almost the same as sendto except that
 *   it retries if interrupted by a signal and
 *   the length of the buffer indicating the destination is not passed
 *
 * parameters:
 *       fd = file descriptor
 *       buf = buffer to be output
 *       nbytes = number of bytes to send
 *       ubufp = a pointer to a buffer of type u_buf_t that was
 *          filled by u_recvfrom
 * returns:
 *      the number of bytes that were sent (may not have been received)
 *      -1 on error and sets errno
 */

ssize_t u_sendto(int fd, void *buf, size_t nbytes, u_buf_t *ubufp) {
   int len;
   struct sockaddr *remotep;
   int retval;

   len = sizeof(struct sockaddr_in);
   remotep = (struct sockaddr *)ubufp;
   while (((retval = sendto(fd, buf, nbytes, 0, remotep, len)) == -1) &&
           (errno == EINTR)) ;  
   return retval;
}
 
/*
 *                           u_sendtohost
 *
 * Send information atomically to a remote host given the host name and port
 * 
 * parameters:
 *       fd = file descriptor
 *       buf = buffer to be output
 *       nbyte = number of bytes to send
 *       port = the port number to send to
 *       hostn = a string containing the name of the destination host
 * returns:
 *      the number of bytes that were sent (may not have been received)
 *      -1 on error and sets errno
 */
   
ssize_t u_sendtohost(int fd, void *buf, size_t nbytes, char *hostn,
                     u_port_t port) {
   struct sockaddr_in remote;

   if (name2addr(hostn, &(remote.sin_addr.s_addr)) == -1) {
      errno = EINVAL;
      return -1;
   }
   remote.sin_port = htons((short)port);
   remote.sin_family = AF_INET;
   return u_sendto(fd, buf, nbytes, &remote);
}

/*
 *                           u_join
 *
 * Join a multicast group
 *
 * parameters:
 *       IP_address = string representing the IP address of the group
 *       port = port number of multicast group
 *       ubufp = buffer to be filled in u_join
 * returns:
 *      a file descriptor on success
 *      -1 on error and sets errno
*/
int u_join(char *IP_address, u_port_t port, u_buf_t *ubufp) {
   int mcastfd;
   struct ip_mreq tempaddress;

   if ((mcastfd = u_openudp(port)) == -1)
      return mcastfd;
   
   tempaddress.imr_multiaddr.s_addr = inet_addr(IP_address);
   tempaddress.imr_interface.s_addr = htonl(INADDR_ANY);

        /* Join the multicast group. Let kernel choose the interface */
   if (setsockopt(mcastfd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                   &tempaddress, sizeof(tempaddress)) == -1)
      return -1;
   ubufp->sin_family = AF_INET;
   ubufp->sin_addr.s_addr = inet_addr(IP_address);
   ubufp->sin_port = htons((short)port);
   return mcastfd;
}

/* This version leaves the group but keeps the file descriptor open and
   still bound to the same port.  It can still receive messages on the port,
   but only those addressed directly to the given host.
*/
/*
 *                           u_leave
 *
 * Leave a multicast group.  Messages can still be received on the port
 * if they are directly addressed to the host.
 *
 * parameters:
 *       mcastfd = previously opened file descriptor returned by u_join
 *       ubufp = buffer filled in by previous u_join
 * returns:
 *      0 on success
 *      -1 on error with errno set
*/
int u_leave(int mcastfd, u_buf_t *ubufp) {  
   struct ip_mreq tempaddress;
 
   memcpy(&(tempaddress.imr_multiaddr),
         &(ubufp->sin_addr), sizeof(struct in_addr));   
   tempaddress.imr_interface.s_addr = htonl(INADDR_ANY);
   return setsockopt(mcastfd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
                   &tempaddress, sizeof(tempaddress));
}

 

Program 20.1 server_udp.c

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "restart.h"
#include "uiciudp.h"
#define BUFSIZE 1024

int main(int argc, char *argv[]) {
   char buf[BUFSIZE];
   ssize_t bytesread;
   char hostinfo[BUFSIZE];
   u_port_t port;
   int requestfd;
   u_buf_t senderinfo;

   if (argc != 2) {
      fprintf(stderr, "Usage: %s port\n", argv[0]);
      return 1;
   }
   port = (u_port_t) atoi(argv[1]);        /* create communication endpoint */
   if ((requestfd = u_openudp(port)) == -1) {
      perror("Failed to create UDP endpoint");
      return 1;
   }
   for ( ; ; ) {                                 /* process client requests */
      bytesread = u_recvfrom(requestfd, buf, BUFSIZE, &senderinfo);
      if (bytesread < 0) {
         perror("Failed to receive request");
         continue;
      }
      u_gethostinfo(&senderinfo, hostinfo, BUFSIZE);
      if ((r_write(STDOUT_FILENO, hostinfo, strlen(hostinfo)) == -1) ||
          (r_write(STDOUT_FILENO, buf, bytesread) == -1)) {
         perror("Failed to echo reply to standard output");
      }
   }     
}

 

Program 20.2 client_udp.c

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "restart.h"
#include "uiciudp.h"
#define BUFSIZE 1024 
 
int main(int argc, char *argv[]) {
   ssize_t byteswritten;
   char request[BUFSIZE];
   int requestfd;  
   int rlen;
   u_port_t serverport;
 
   if (argc != 3) {
      fprintf(stderr, "Usage: %s servername serverport\n", argv[0]);
      return 1;
   }
   serverport = (u_port_t) atoi(argv[2]);
   if ((requestfd = u_openudp(0)) == -1) {     /* create unbound UDP endpoint */
      perror("Failed to create UDP endpoint");
      return 1;
   }
   sprintf(request, "[%ld]\n", (long)getpid());           /* create a request */
   rlen = strlen(request);
    /* use  simple-request protocol to send a request to (server, serverport) */
   byteswritten = u_sendtohost(requestfd, request, rlen, argv[1], serverport);
   if (byteswritten == -1)
      perror("Failed to send");
   if (r_close(requestfd) == -1 || byteswritten == -1)
      return 1;
   return 0;
}

 

Program 18.10 addr2name_gethostbyaddr.c

//name2addr_gethostbyname.c
#include <ctype.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdio.h>

int name2addr(char *name, in_addr_t *addrp) {
    struct hostent *hp;

    if (isdigit((int)(*name)))
        *addrp = inet_addr(name);
    else {
        hp = gethostbyname(name);
        if (hp == NULL)
            return -1;
        memcpy((char *)addrp, hp->h_addr_list[0], hp->h_length);
    }
    return 0;
}

int main()
{
   char * name = "www.scut.edu.cn";
   in_addr_t ip;
   name2addr(name, &ip);
   unsigned char tmp[4];
   memcpy(tmp, (char *)&ip, 4);
   printf(">>> %d.%d.%d.%d\n", tmp[0], tmp[1], tmp[2], tmp[3]);
   return 0;
}

 

 

Result

Program 18.2 serverp.c

 

 

client.c &server.c

 

 

Program 20.1 server_udp.c

 

client_udp.c & server_udp.c

 

 

Program 18.10 addr2name_gethostbyaddr.c

 

 小结

 资源下载:https://files.cnblogs.com/yongfeng/UnixCode.zip