SlideShare una empresa de Scribd logo
1 de 47
Descargar para leer sin conexión
USP PROGRAMS

                            UNIX AND ANSI STANDARDS
PROG 1: To illustrate the use of cpp symbols

      #include<stdio.h>
      #include<unistd.h>
      int main()
      {
             #if __STDC__==0
                     printf("cc is not ancic compliantn");
             #else
                     printf("%s compiled at %s:%s.this statement is at line
                     %dn",__FILE__,__DATE__,__TIME__,__LINE__);
             #endif
             return 0;
      }

OUTPUT:

      unix1.c compiled at May 19 2011:08:46:43.this statement is at line 8


PROG 2: To show posix version

      #include<iostream>
      #include<unistd.h>
      #define _POSIX_SOURCE
      #define _POSIX_C_SOURCE 199309l
      using namespace std;
      int main()
      {
      #ifdef _POSIX_VERSION
              cout<<"system confirms to posix:"<< _POSIX_VERSION<<"n";
      #else
              cout<<"_POSIX_VERSION is undefinedn";
      #endif
      return 0;
      }

OUTPUT:

      system confirms to posix:200809


PROG3: To show test macros:

      #define _POSIX_SOURCE
      #define _POSIX_C_SOURCE              199309L

USP TUTORIALS                                                                 Page 1
#include<iostream>
      #include<unistd.h>
      using namespace std;
      int main()
      {
      #ifdef _POSIX_JOB_CONTROL
              cout<<"sys control job supportn";
      #else
              cout<"sys does not support job controln";
      #endif
      #ifdef _POSIX_SAVED_IDS
              cout<<"sys support saved set_uid and saved set_gidn";
      #else
              cout<<"sys does not support saved set_uid and saved set_gidn";
      #endif
      #ifdef _POSIX_CHOWN_RESTRICTED
              cout<<"sys does not support chown_restricted optionn";
      #endif
      #ifdef _POSIX_NO_TRUNC
              cout<<"path name trunc option is:"<<_POSIX_NO_TRUNC<<endl;
      #else
              cout<<"sys does not suport sys-wide path name trunc optionn";
      #endif
      #ifdef _POSIX_VDISABLE
              cout<<"distance char for terminal files is,"<<_POSIX_VDISABLE<<”Thnxn”
      #else
              cout<<"sys does not support_POSIX_VDISABLEn";
      #endif
              return 0;
      }

OUTPUT:

      sys control job support
      sys support saved set_uid and saved set_gid
      sys does not support chown_restricted option
      path name trunc option is:1
      distance char for terminal files is,Thnx




PROG 4: Use of sysconf,pathconf and fpathconf:

      #define _POSIX_SOURCE
      #define _POSIX_C_SOURCE 199309L
      #include<stdio.h>
      #include<iostream>
      #include<unistd.h>
      using namespace std;

USP TUTORIALS                                                                      Page 2
int main()
       {
       int res;
       if((res=sysconf(_SC_OPEN_MAX))==-1)
                perror("sysconf");
       else
                cout<<"OPEN_MAX:"<<res<<endl;
                if((res==pathconf("/",_PC_PATH_MAX))==-1)
                        perror("pathconf");
                else
                        cout<<"Max path name:"<<(res+1)<<endl;
                if((res=fpathconf(0,_PC_CHOWN_RESTRICTED))==-1)
                        perror("fpathconf");
                else
                        cout<<"Chown_restricted for stdin:"<<res<<endl;
                return 0;
       }

OUTPUT:

OPEN_MAX:1024
Max path name:1025
Chown_restricted for stdin:1


PROG 5: Use of setlocale function:

#include <stdio.h>
#include <time.h>
#include <locale.h>

int main ()
       {
                      time_t rawtime;
                      struct tm * timeinfo;
                      char buffer [80];

                      struct lconv * lc;

                      time ( &rawtime );
                      timeinfo = localtime ( &rawtime );

                      int twice=0;

               do {
                      printf ("Locale is: %sn", setlocale(LC_ALL,NULL) );

                      strftime (buffer,80,"%c",timeinfo);
                      printf ("Date is: %sn",buffer);

                      lc = localeconv ();

USP TUTORIALS                                                                Page 3
printf ("Currency symbol is: %sn-n",lc->currency_symbol);

                    setlocale (LC_ALL,"");
             }while (!twice++);

             return 0;
      }

OUTPUT:

      Locale is: C
      Date is: 01/15/07 13:33:47
      Currecy symbol is:
      -
      Locale is: English_United States.1252
      Date is: 1/15/07 1:33:47 PM
      Currency symbol is: $
      -



                            UNIX FILE APIs
Prog 1: To show the use of open,read,write and close Apis

      #include<stdio.h>
      #include<sys/types.h>
      #include<fcntl.h>
      #include<unistd.h>
      #include<string.h>
      #include<stdlib.h>

      int main(int argc,char *argv[])
      {
             int fdesc;
             char buf[256],*buf1;
             if(argc !=3)
                     {
                             printf("Usage: ./a.out<readfile><writefile>n");
                             exit(0);
                     }
             fdesc=open(argv[1],O_RDONLY);
             printf("CONTENTS OF FILE IS:n");
             while(read(fdesc,buf,sizeof(buf)) > 0);
             printf("%s",buf);
             close(fdesc);

             fdesc=open(argv[2],O_WRONLY|O_APPEND|O_CREAT);
             buf1=(char *)malloc(1024*sizeof(char));
             printf("Enter the data to be updated to the file:n");
             scanf("%s",buf1);

USP TUTORIALS                                                                      Page 4
size_t length=strlen(buf1);
              if(write(fdesc,buf1,length)==-1)
                      printf("Write errorn");
              close(fdesc);
              return 0;
       }

OUTPUT:
    ./a.out read.txt write.txt

       Contents of read.txt is:
       This is a read file

       Enter the data to be updated to writefile:
       Hai, have a nice day


Prog 2: Use of fcntl api

       #include<sys/types.h>
       #include<stdio.h>
       #include<fcntl.h>
       #include<unistd.h>
       int main(int argc,char **argv)
       {
              int fdesc=open(argv[1],O_RDONLY);
              close(0);
              int cur_flags=fcntl(fdesc,F_GETFL);
              printf(" %d %d n",fdesc,cur_flags);

              printf("close on exec= %dn", fcntl(fdesc,F_GETFD));
              (void)fcntl(fdesc,F_SETFD,1);
              printf("close on exec= %d", fcntl(fdesc,F_GETFD));
              if(fcntl(fdesc,F_DUPFD,0)==-1) perror("fcntl");
              char buf[256];
              int rc=read(0,buf,256);
              printf("rc=%dnn",rc);
       }



Prog 3: Use of lseek Api

       #include<stdio.h>
       #include<unistd.h>
       #include<fcntl.h>
       #include<sys/types.h>
       int main(int argc,char *argv[])
       {
       char buf[256];
       int fdesc,len;

USP TUTORIALS                                                        Page 5
while(--argc > 0)
              {
                     if(access(*++argv,F_OK))
                     {
                             fdesc=open(*argv,O_WRONLY|O_CREAT,0744);
                             write(fdesc,"HELLO WORLDn",12);
                     }
                     else
                     {
                     fdesc=open(*argv,O_RDONLY);
                     while(len=read(fdesc,buf,256))
                             write(1,buf,len);
                     }
                     close(fdesc);
              }
       }



Prog 4: Use of link Api

       #include<stdio.h>
       #include<unistd.h>

       int main(int argc,char *argv[])
       {
              if(argc!=3)
                      {
                              printf("Usage: ./a.out <srcfile> <dest_file>n");
                              return 0;
                      }

              if(link(argv[1],argv[2])==-1)
              {
                      perror("link");
                      return 1;
              }
              return 2;
       }


Prog 5: Use of unlink Api

       #include<stdio.h>
       #include<sys/types.h>
       #include<unistd.h>
       #include<string.h>

       int main(int argc,char *argv[])
       {
              if(argc!=3 || !strcmp(argv[1],argv[2]))

USP TUTORIALS                                                                     Page 6
printf("Usage: ./a.out <old_link> <new_link>n");
              else if(link(argv[1],argv[2])==0)
                       return unlink(argv[1]);
              return -1;
       }


Prog 6: Use of stat Api

       #include<sys/types.h>
       #include<sys/stat.h>
       #include<unistd.h>


       void change_mode()
       {

              struct stat statv;
              int flag=(S_IWGRP|S_IROTH|S_IXOTH);

              if(stat("/usr/games/gbrainy",&statv))
                       perror("stat");
              else
              {
                       flag=(statv.st_mode & ~flag)|S_ISUID;
                       if(chmod("/usr/games/gbrainy",flag))
                              perror("chmod");

              }
       }

       int main()
       {
              change_mode();
              return 0;
       }


Prog 7: Use of access Api


       #include <sys/types.h>
       #include <unistd.h>
       #include <fcntl.h>

       int main(int argc, char * argv[])
       {
              char buf[256];
              int fdesc,len;

              while(--argc > 0)

USP TUTORIALS                                                              Page 7
{
                     if(access(*++argv,F_OK))
                     {       // a brand new file
                             fdesc = open(*argv, O_WRONLY | O_CREAT, 0744);
                             write(fdesc, "Hello world n", 12);
                     }
                     else
                     {
                             fdesc = open(*argv, O_RDONLY);
                             while(len = read(fdesc, buf, 256))
                                     write(1, buf, len);
                     }
                     close(fdesc);
             }
      }


Prog 8: Use of chmod Api

      #include<sys/types.h>
      #include<sys/stat.h>
      #include<unistd.h>
      #include<stdio.h>

      int main()
      {
             struct stat statv;
             mode_t flag1=S_IRWXU|S_IWGRP|S_IROTH|S_IWOTH|S_IXOTH;
             if(stat("/home/nithish/time.c",&statv))
                      perror("stat");
             else
             {
                      printf("%dn",flag1);
                      if(chmod("/home/nithish/time.c",flag1))
                              perror("chmod");
             }
      }


Prog 9: Use of chown Api

      #include <iostream>
      #include <sys/types.h>
      #include <sys/stat.h>
      #include <unistd.h>
      #include <pwd.h>
      #include <stdio.h>
      using namespace std;

      int main(int argc, char * argv[])
      {

USP TUTORIALS                                                                 Page 8
if(argc < 3) {
                     cerr << "usage:"<<argv[0] << " <usr_name> <files> n";
                     return 1;
                     }

             struct passwd *pwd = getpwuid (argv[1]); //convert user name to UID
             uid_t UID = pwd ? pwd->pw_uid:-1;
             struct stat statv;

             if(UID == (uid_t) -1)
                    cerr << "invalid user name n";

             else for(int i = 2; i < argc; i++)     //do for each file specified
                     if(stat(argv[i] & statv) == 0) {
                              if(chown(argv[i],UID,statv.st_gid))
                                      perror("chown");
                     } else perror("stat");
             return 0;
      }

Prog 10: Use of utime Api

      #include<sys/types.h>
      #include<unistd.h>
      #include<utime.h>
      #include<stdio.h>

      int main(int argc,char *argv[])
      {
             struct utimbuf times;
             int offset,i;
             if(argc<3 || sscanf(argv[1],"%d",&offset) != 1)
                     printf("Usage: ./a.out <offset> <filenames>n");
             else
             {
                     times.actime=times.modtime=time(0)+offset;

                    for(i=2;i<argc;i++)
                    {
                            if(utime(argv[i],&times) == -1) perror("utime");
                    }
                    return 0;
             }
             return 1;
      }




USP TUTORIALS                                                                      Page 9
Prog 11: Illustrate file locking:

       #include <iostream>
       #include <stdio.h>
       #include <sys/types.h>
       #include <fcntl.h>
       #include <unistd.h>

       using namespace std;
       int main(int argc, char *argv[])
       {
               struct flock fvar;
               int temp;
       int fdesc;
       while(--argc > 0) {
               if((fdesc = open(*++argv, O_RDWR)) == -1) {
                        perror("open");
                        continue;
               }
               fvar.l_type = F_WRLCK;
               fvar.l_whence = SEEK_SET;
               fvar.l_start = 0;
               fvar.l_len = 0;
               temp = fcntl(fdesc,F_SETLKW,&fvar);
               cout <<temp;
               temp = fcntl(fdesc, F_GETLK,&fvar);
               cout <<endl<<temp<<endl<<endl;
               cout <<*argv<< " nlocked by : " << fvar.l_pid <<"nfrom :"<<
       fvar.l_start<<"tfor"<<fvar.l_len<<"tbyte
       fort"<<(fvar.l_type==F_WRLCK?'w':'r')<<endl;                 //set lock fails, find out who
has locked the file */
               /* Attempt to set an exclusive (write) lock on the entire file */
               while(fcntl(fdesc, F_SETLK,&fvar) == -1) {
               cout<<"enter the loop";
               //set lock fails find out who has locked the file */
               while(fcntl(fdesc,F_GETLK, &fvar)!= -1 && fvar.l_type != F_UNLCK){
               cout << "argv"<< "locked by" << fvar.l_pid <<"from "<<
       fvar.l_start<<"for"<<fvar.l_len<<"byte         for"<<(fvar.l_type==F_WRLCK?'w':'r')<<endl;
               if(!fvar.l_len) break;
               fvar.l_start += fvar.l_len;
               fvar.l_len = 0;

              }
       }

       fvar.l_type   = F_UNLCK;
       fvar.l_whence = SEEK_SET;
       fvar.l_start  = 0;
       fvar.l_len    = 0;

       if(fcntl(fdesc, F_SETLKW, &fvar) == -1)

USP TUTORIALS                                                                             Page 10
perror("fcntl");
      }

      return 0;
}


Prog 12: Directory file APIs

      #include<iostream>
      #include<sys/types.h>
      #include<sys/stat.h>
      #include<unistd.h>
      #include<pwd.h>
      #include<utime.h>
      #include<time.h>
      #include<error.h>
      #include<stdio.h>
      #include<fcntl.h>
      #include<string.h>
      using namespace std;
      #if defined(BSO) && !_POSIX_SOURCE
              #include<sys/dir.h>
              typedef struct direct Dirent;
      #else
              #include<dirent.h>
              typedef struct dirent Dirent;
      #endif
      int main(int argc,char*argv[])
      {
              Dirent* dp;
              DIR *dir_fdesc;
              while(--argc>0)
              {
                     if(!(dir_fdesc==opendir(*++argv)))
                     {
                              if(mkdir(*argv,S_IRWXU|S_IRWXG|S_IRWXO)==-1)
                                       perror("opendir");
                              continue;
                     }
                     for(int i=0;i<2;i++)
                     {
                              for(int cnt=0;dp=readdir(dir_fdesc);)
                              {
                                       if(i) cout<<dp->d_name<<endl;
                                       if(strcmp(dp->d_name,",") && strcmp(dp->d_name,"..."))
                                       cnt++;
                              }
                              if(!cnt) {rmdir(*argv);break;}
                                       rewinddir(dir_fdesc);
                     }

USP TUTORIALS                                                                            Page 11
closedir(dir_fdesc);
              }
       }


Prog 13: Device file API

       #include<iostream>
       #include <stdio.h>
       #include <sys/types.h>
       #include <unistd.h>
       #include <string.h>
       #include <fcntl.h>
       #include <sys/stat.h>
       using namespace std;
       int main(int argc, char *argv[])
       {
              if(argc != 4) {
                      cout <<"usage: " <<argv[0]<<" <file><major no><minor no>n";
                      return 0;
              }
              int major = atoi(agrv[2]), minor = atoi(argv[3]);
              (void)mknod(argv[1],S_IFCHR|S_IRWXU|S_IRWXG|S_IRWXO,(major << 8) |
              minor);
              int rc = 1, fd = open(argv[1], O_RDWR|O_NOBLOCK|O_NOCTTY);
              char buf[256];
              while ( rc && fd != -1)
                      if((rc= read(fd,buf,sizeof(buf)))<0)
                               perror("read");
                      else if(rc) cout<<buf<<endl;
              close(fd);
       }


Prog 14: Fifo file API

       #include<stdio.h>
       #include<sys/types.h>
       #include<unistd.h>
       #include<sys/stat.h>
       #include<fcntl.h>
       #include<string.h>
       #include<errno.h>

       int main(int argc,char **argv)
       {
              if(argc!=2 && argc!=3)
              {
                      printf("n usage: %s <file> [<arg>] n",argv[0]);
                      return 0;
              }

USP TUTORIALS                                                                  Page 12
int fd;
             char buf[256];
             (void)mkfifo(argv[1],S_IFIFO|S_IRWXU|S_IRWXG|S_IRWXO);
             if(argc==2)
             {
                     fd=open(argv[1],O_RDONLY|O_NONBLOCK);

                    while(read(fd,buf,sizeof(buf))==-1 && errno==EAGAIN)
                    sleep(1);
                    while(read(fd,buf,sizeof(buf)) > 0)

                    printf("n %s n",buf);
             }
             else
             {
                     fd=open(argv[1],O_WRONLY);
                     write(fd,argv[2],strlen(argv[2]));
              }
             close(fd);
      }

Prog 15: Symbolic file API

      #include<iostream>
      #include<sys/types.h>
      #include<unistd.h>
      #include<string.h>
      using namespace std;
      int main(int argc,char **argv)
      {
             char *buf[256],tname[256];
             if((argc<3 && argc>4)||(argc==4 && strcmp(argv[1],"-s")))
             {
                     cout<<"usage:" <<argv[0]<<" [-s] <orig file> <newlink>";
                     return 1;
             }
             if(argc==4)
                     return symlink(argv[2],argv[3]);
             else
                     return link(argv[1],argv[2]);
      }




USP TUTORIALS                                                                   Page 13
Process Environment


1.     To print argument list

#include<stdio.h>
int main(int argc,char **argv)
{
int i;
for(i=0;i<argc;i++)
{
printf("nargv[%d]: %s",i,argv[i])
}
}

2.     atexit function

       #include<stdio.h>

       static void my_exit1(void)
       {
       printf("nfirst exit handler");
       }
       static void my_exit2(void)
       {
       printf("nsecond exit handler");
       }
       int main(void)
{
if(atexit(my_exit2)!=0)
printf("ncan't register my_exit2");
if(atexit(my_exit1)!=0)
printf("ncan't register my_exit1");
if(atexit(my_exit1)!=0)
printf("ncan't register my_exit1");
printf("nmain is done");
return 0;
}


3.     Use of environment variables

        #include<stdio.h>
#include<stdlib.h>
int main()
{
int a,b,c;
char *str="usp",char get[20];
const char *value="tut6";
a=putenv(str);


USP TUTORIALS                                                Page 14
if(a !=0) printf("nputenv error");
b=setenv(str,value,0);
get=getenv(str);
printf("nEnvironment var: %s",get);
if(b !=0) printf("nsetenv error");
c=unsetenv(str);
if(c !=0) printf("nunsetenv error");

}


     4.setjmp and longjmp functions

#include<setjmp.h>
#include<stdio.h>
#define TOK_ADD 5
#define MAXLINE 2
jmp_buf jmpbuffer;

int main(void)
{
char line[MAXLINE];
if(setjmp(jmpbuffer)!=0)
printf("error");
while(fgets(line,MAXLINE,stdin)!=NULL)
do_line(line);
exit(0);
}

void cmd_add(void)
{
int token;
token=get_token();
if(token<0)
longjmp(jmpbuffer,1);
}



                                        Process Control

1.       vfork function

#include<stdio.h>
#include<stdlib.h>
int glob=0;
int main()
{
        int var;
        pid_t pid;
        var=88;

USP TUTORIALS                                             Page 15
if((pid=fork())<0)
                printf("vfork error");
       else if(pid==0)
       {
                glob++;
                var++;
       }
       printf("pid=%d,glob=%d,var=%dn",getpid(),glob,var);
       exit(0);
}

2.     fork function

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

int main()
{
       pid_t child_pid;
       printf("PID:%d nParent: %dn",getpid(),getppid());
       switch(child_pid=fork())
       {
               case (pid_t)-1:
                                   perror("fork");
                                   break;
               case (pid_t)0:
                                   printf("nChild created.. PID: %dnParent :
%dn",getpid(),getppid());
                                   exit(0);
                                   break;
               default:
                                   printf("Parent after fork PID:%d nChild PID:
%dn",getpid(),child_pid);
                                   break;
       }
       return 0;
}

3.     execle function

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>

char *envinit[] = {"USER=unknown", "PATH=/tmp",NULL};

int main()
{
       pid_t pid;

USP TUTORIALS                                                                      Page 16
if((pid=fork()) < 0)
                  {
                          printf("Fork errorn");
                          exit(0);
                  }

          else if(pid==0)
          {
                  if(execle("/home/abhishta/echoall","arg1","arg2",(char *) 0,envinit) < 0)
                  {
                          printf("Execle errorn");
                          exit(0);
                  }
          }

          if(waitpid(pid,NULL,0) < 0)
                   printf("Wait errorn");
          exit(0);
}

4.        exec function

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>

int main(int argc, char *argv[])
{
  pid_t pid;

  if ((pid = fork()) < 0)
  {
    fprintf(stderr,
             "fork failedn");
    exit(1);
  }
wait(NULL);
//waitpid(pid,NULL,0);
//waitid(P_PID,pid,NULL,0);

    if (pid == 0)
    {
      execlp("echo",
             "echo",
             "nHello from",
             "the child",
             (char *) NULL);
      fprintf(stderr,
             "execl failedn");
      exit(2);

USP TUTORIALS                                                                                 Page 17
}
}

5.      echoall function

#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[])
{
       int i;
       char **ptr;
       extern char **environ;
       for(i=0;i<argc;i++)
                printf("argv[%d]: %sn",i,argv[i]);
       for(ptr=environ;*ptr !=0; ptr++)
                printf("%sn",*ptr);
       exit(0);
}



6.      getsetrlimit function

#include "stdio.h"
#include<stdlib.h>
#include"error.h"
#if defined(BSD) || defined(MACOS)
#include <sys/time.h>
#include <sys/stat.h>
#define FMT "%10lld "
#else
#define FMT "%10ld "
#endif
#include <sys/resource.h>

#define doit(name) pr_limits(#name, name)

static void pr_limits(char *, int);

int main(void)
{

#ifdef RLIMIT_AS
   doit(RLIMIT_AS);
#endif
   doit(RLIMIT_CORE);
   doit(RLIMIT_CPU);
   doit(RLIMIT_DATA);
   doit(RLIMIT_FSIZE);
#ifdef RLIMIT_LOCKS
   doit(RLIMIT_LOCKS);

USP TUTORIALS                                         Page 18
#endif
#ifdef RLIMIT_MEMLOCK
   doit(RLIMIT_MEMLOCK);
#endif
   doit(RLIMIT_NOFILE);
#ifdef RLIMIT_NPROC
   doit(RLIMIT_NPROC);
#endif
#ifdef RLIMIT_RSS
   doit(RLIMIT_RSS);
#endif
#ifdef RLIMIT_SBSIZE
   doit(RLIMIT_SBSIZE);
#endif
   doit(RLIMIT_STACK);
#ifdef RLIMIT_VMEM
   doit(RLIMIT_VMEM);
#endif
   exit(0);
}

static void
pr_limits(char *name, int resource)
{
   struct rlimit limit;

     if (getrlimit(resource, &limit) < 0)
        printf("getrlimit error for %s", name);
     printf("%-14s ", name);
     if (limit.rlim_cur == RLIM_INFINITY)
        printf("(infinite) ");
     else
        printf(FMT, limit.rlim_cur);
     if (limit.rlim_max == RLIM_INFINITY)
        printf("(infinite)");
     else
        printf(FMT, limit.rlim_max);
     putchar((int)'n');
}


7.       system function

#include<stdio.h>
#include<stdlib.h>
int main()
{
       system("ls -l");
       printf("nCommand done.nn");
       return 0;
}

USP TUTORIALS                                     Page 19
Process Relationships

1. Creating an orphaned process group

      #include "apue.h"
      #include <errno.h>

      static void sig_hup(int signo)
      {
      printf("SIGHUP received, pid = %dn", getpid());
      }

      static void pr_ids(char *name)
      {
      printf("%s: pid = %d, ppid = %d, pgrp = %d, tpgrp = %dn",
      name, getpid(), getppid(), getpgrp(), tcgetpgrp(STDIN_FILENO));
      fflush(stdout);
      }

      int main(void)
      {
      char c;
      pid_t pid;
      pr_ids("parent");
      if ((pid = fork()) < 0) {
      err_sys("fork error");
      }
      else if (pid > 0)
      {
               /* parent */
      sleep(5);
      /*sleep to let child stop itself */
      exit(0);
      /* then parent exits */
      }
      else
      {
               /* child */
               pr_ids("child");
               signal(SIGHUP, sig_hup);
               /* establish signal handler */
               kill(getpid(), SIGTSTP);
               /* stop ourself */
               pr_ids("child");
      /* prints only if we're continued */
      if (read(STDIN_FILENO, &c, 1) != 1)
               printf("read error from controlling TTY, errno = %dn", errno);
               exit(0);
               }
      }

USP TUTORIALS                                                                    Page 20
}
Signals


          2. Call a non-reentrant function from a signal handler

          #include "apue.h"
          #include <pwd.h>
          static void my_alarm(int signo)
          {
                   struct passwd *rootptr;
                   printf("in signal handlern");
                   if ((rootptr = getpwnam("root")) == NULL)
                   err_sys("getpwnam(root) error");
                   alarm(1);
          }


          int main(void)
          {
          struct passwd *ptr;
          signal(SIGALRM, my_alarm);
          alarm(1);
          for ( ; ; ) {
                   if ((ptr = getpwnam("sar")) == NULL)
                   err_sys("getpwnam error");
                   if (strcmp(ptr->pw_name, "sar") != 0)
                   printf("return value corrupted!, pw_name = %sn",
                   ptr->pw_name);
                   }
    }



3. System V SIGCLD handler that doesn't work :

         #include "apue.h"
         #include <sys/wait.h>
        static void sig_cld(int);
         int main()

USP TUTORIALS                                                          Page 21
{
               pid_t pid;
               if (signal(SIGCLD, sig_cld) == SIG_ERR)
               perror("signal error");
               if ((pid = fork()) < 0) {
               perror("fork error");
               } else if (pid == 0) {
               /* child */
               sleep(2);
               _exit(0);
               }
               pause();
               exit(0);
               /* parent */
       }
       static void sig_cld(int signo)
       {
               pid_t pid;
               int status;
               /* interrupts pause() */
               printf("SIGCLD receivedn");
               if (signal(SIGCLD, sig_cld) == SIG_ERR) /* reestablish handler */
               perror("signal error");
               If ((pid = wait(&status)) < 0)
               /* fetch child status */
               perror("wait error");
               printf("pid = %dn", pid);
       }
4. Simple, implementation of sleep


#include <signal.h>
#include <unistd.h>
static void sig_alrm(int signo)
       {


USP TUTORIALS                                                                      Page 22
/* nothing to do, just return to wake up the pause */
       }
unsigned int sleep1(unsigned int nsecs)
{
       if (signal(SIGALRM, sig_alrm) == SIG_ERR)
       return(nsecs);
       alarm(nsecs);
       /* start the timer */
       pause();
       /* next caught signal wakes us up */
       return(alarm(0));
       /* turn off timer, return unslept time */
}


5. Calling sleep2 from a program that catches other signals
       #include "apue.h"
       unsigned int static void
       int main(void)
       {
               unsigned int
               sleep2(unsigned int);
               sig_int(int);
               unslept;
               if (signal(SIGINT, sig_int) == SIG_ERR)
               err_sys("signal(SIGINT) error");
               unslept = sleep2(5);
               printf("sleep2 returned: %un", unslept);
               exit(0);
       }
       static void sig_int(int signo)
       {
               int i, j;
               volatile int k;
               /*


USP TUTORIALS                                                  Page 23
* Tune these loops to run for more than 5 seconds
               * on whatever system this test program is run.
               */
                          printf("nsig_int startingn");
               for (i = 0; i < 300000; i++)
               for (j = 0; j < 4000; j++)
               k += i * j;
               printf("sig_int finishedn");
       }


6. Calling read with a timeout
#include "apue.h"
static void sig_alrm(int);
       int main(void)
       {
               int n;
               char line[MAXLINE];
               if (signal(SIGALRM, sig_alrm) == SIG_ERR)
               err_sys("signal(SIGALRM) error");
               alarm(10);
               if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0)
               err_sys("read error");
               alarm(0);
               write(STDOUT_FILENO, line, n);
               exit(0);
       }
       static void sig_alrm(int signo)
       {
               /* nothing to do, just return to interrupt the read */
       }




USP TUTORIALS                                                           Page 24
7. Calling read with a timeout, using longjmp
#include "apue.h"
#include <setjmp.h>
static void sig_alrm(int);
static jmp_buf env_alrm;
int main(void)
{
int n;
char env_alrm;
line[MAXLINE];
if (signal(SIGALRM, sig_alrm) == SIG_ERR)
err_sys("signal(SIGALRM) error");
if (setjmp(env_alrm) != 0)
err_quit("read timeout"); alarm(10);
if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0)
err_sys("read error");
alarm(0);
write(STDOUT_FILENO, line, n);
exit(0);
}
static void sig_alrm(int signo)
{
longjmp(env_alrm, 1);
}


8. An implementation of sigaddset, sigdelset, and sigismember.
#include<signal.h>
#include<errno.h>


/* <signal.h> usually defines NSIG to include signal number 0 */
#define SIGBAD(signo) ((signo) <= 0 || (signo) >= NSIG)
int sigaddset(sigset_t *set, int signo)
{
if (SIGBAD(signo)) { errno = EINVAL; return(-1); }


USP TUTORIALS                                                      Page 25
*set |= 1 << (signo - 1);
return(0);
/* turn bit on */
}
int sigdelset(sigset_t *set, int signo)
{
if (SIGBAD(signo)) { errno = EINVAL; return(-1); }
*set &= ~(1 << (signo - 1));
return(0);
/* turn bit off */
}
int sigismember(const sigset_t *set, int signo)
{
if (SIGBAD(signo)) { errno = EINVAL; return(-1); }
return((*set & (1 << (signo - 1))) != 0);
}


9. Print the signal mask for the process.
#include "apue.h"
#include <errno.h>
void pr_mask(const char *str)
{
sigset_t sigset;
int errno_save;
errno_save = errno;
if (sigprocmask(0, NULL, &sigset) < 0) err_sys("sigprocmask error");
printf("%s", str);
if (sigismember(&sigset,SIGINT)) printf("SIGINT ");
if (sigismember(&sigset,SIGQUIT)) printf("SIGQUIT ");
if (sigismember(&sigset,SIGUSR1)) printf("SIGUSR1 ");
if (sigismember(&sigset,SIGALRM)) printf("SIGALRM ");
printf("n");
errno = errno_save;
}


USP TUTORIALS                                                          Page 26
10. Example of signal sets and sigprocmask.


#include "apue.h"
static void sig_quit(int);
int main(void)
{
sigset_t newmask, oldmask, pendmask;
if (signal(SIGQUIT, sig_quit) == SIG_ERR) err_sys("can't catch SIGQUIT");
/*
* Block SIGQUIT and save current signal mask.
*/
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT);
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error");
sleep(5);
/* SIGQUIT here will remain pending */
if (sigpending(&pendmask) < 0) err_sys("sigpending error");
if (sigismember(&pendmask, SIGQUIT)) printf("nSIGQUIT pendingn");
/*
* Reset signal mask which unblocks SIGQUIT.
*/
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error");
printf("SIGQUIT unblockedn");
sleep(5);
exit(0);
/* SIGQUIT here will terminate with core file */
}
static void sig_quit(int signo)
{
printf("caught SIGQUITn");
if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) err_sys("can't reset SIGQUIT");
}




USP TUTORIALS                                                                     Page 27
11. An implementation of signal using sigaction


#include "apue.h"
/* Reliable version of signal(), using POSIX sigaction(). */
Sigfunc *signal(int signo, Sigfunc *func)
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if (signo == SIGALRM)
{
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
}
else
{
#ifdef SA_RESTART
act.sa_flags |= SA_RESTART;
#endif
}
if (sigaction(signo, &act, &oact) < 0) return(SIG_ERR);
return(oact.sa_handler);
}


12. The signal_intr function


#include "apue.h"
Sigfunc *signal_intr(int signo, Sigfunc *func)
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);


USP TUTORIALS                                                  Page 28
act.sa_flags = 0;
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
if (sigaction(signo, &act, &oact) < 0) return(SIG_ERR);
return(oact.sa_handler);
}


13. Example of signal masks, sigsetjmp, and siglongjmp


#include "apue.h"
#include <setjmp.h>
#include <time.h>
static void sig_usr1(int), sig_alrm(int);
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjump;
sig_usr1(int), sig_alrm(int);
int main(void)
{
if (signal(SIGUSR1, sig_usr1) == SIG_ERR) err_sys("signal(SIGUSR1) error");
if (signal(SIGALRM, sig_alrm) == SIG_ERR) err_sys("signal(SIGALRM) error");
pr_mask("starting main: ");
/* Figure 10.14 */
if (sigsetjmp(jmpbuf, 1))
{
pr_mask("ending main: ");
exit(0);
}
canjump = 1;
/* now sigsetjmp() is OK */
for ( ; ; )
pause();
}
static void sig_usr1(int signo)


USP TUTORIALS                                                                 Page 29
{
time_t starttime;
if (canjump == 0) return;
/* unexpected signal, ignore */
pr_mask("starting sig_usr1: ");
alarm(3);
/* SIGALRM in 3 seconds */
starttime = time(NULL);
for ( ; ; )
/* busy wait for 5 seconds */
if (time(NULL) > starttime + 5) break;
pr_mask("finishing sig_usr1: ");
canjump = 0;
siglongjmp(jmpbuf, 1);
}
static void sig_alrm(int signo)
{
/* jump back to main, don't return */
pr_mask("in sig_alrm: ");
}


14. Protecting a critical region from a signal
#include "apue.h"
static void sig_int(int);
int main(void)
{
sigset_t newmask, oldmask, waitmask;
pr_mask("program start: ");
if (signal(SIGINT, sig_int) == SIG_ERR) err_sys("signal(SIGINT) error");
sigemptyset(&waitmask);
sigaddset(&waitmask, SIGUSR1);
sigemptyset(&newmask);
sigaddset(&newmask, SIGINT);
/*


USP TUTORIALS                                                              Page 30
* Block SIGINT and save current signal mask.
*/
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error");
/*
* Critical region of code.
*/
pr_mask("in critical region: ");
/*
* Pause, allowing all signals except SIGUSR1.
*/
if (sigsuspend(&waitmask) != -1) err_sys("sigsuspend error");
pr_mask("after return from sigsuspend: ");
/*
* Reset signal mask which unblocks SIGINT.
*/
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error");
/*
* And continue processing ...
*/
pr_mask("program exit: ");
exit(0);
}
static void sig_int(int signo)
{
pr_mask("nin sig_int: ");
}


15. Using sigsuspend to wait for a global variable to be set


#include "apue.h"
volatile sig_atomic_t quitflag;
static void sig_int(int signo)
/* set nonzero by signal handler */
/* one signal handler for SIGINT and SIGQUIT */


USP TUTORIALS                                                                     Page 31
{
if (signo == SIGINT) printf("ninterruptn");
else if (signo == SIGQUIT) quitflag = 1;
/* set flag for main loop */
}
int main(void)
{
sigset_t newmask, oldmask, zeromask;
if (signal(SIGINT, sig_int) == SIG_ERR) err_sys("signal(SIGINT) error");
if (signal(SIGQUIT, sig_int) == SIG_ERR) err_sys("signal(SIGQUIT) error");
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT);
/*
* Block SIGQUIT and save current signal mask.*/
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error");
while (quitflag == 0)
sigsuspend(&zeromask);
/*
* SIGQUIT has been caught and is now blocked; do whatever.*/
quitflag = 0;
/*
* Reset signal mask which unblocks SIGQUIT.
*/
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error");
exit(0);
}


16. Routines to allow a parent and child to synchronize
#include "apue.h"
static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */
static sigset_t newmask, oldmask, zeromask;
static void sig_usr(int signo)
{


USP TUTORIALS                                                                     Page 32
sigflag = 1;
}
/* one signal handler for SIGUSR1 and SIGUSR2 */
void TELL_WAIT(void)
{
if (signal(SIGUSR1, sig_usr) == SIG_ERR) err_sys("signal(SIGUSR1) error");
if (signal(SIGUSR2, sig_usr) == SIG_ERR) err_sys("signal(SIGUSR2) error");
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGUSR1);
sigaddset(&newmask, SIGUSR2);
/*
* Block SIGUSR1 and SIGUSR2, and save current signal mask.
*/
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error");
}
void TELL_PARENT(pid_t pid)
{
kill(pid, SIGUSR2);
}
void
/* tell parent we're done */
WAIT_PARENT(void)
{
while (sigflag == 0)
sigsuspend(&zeromask);
sigflag = 0;
/* and wait for parent */
/*
* Reset signal mask to original value.
*/
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error");
}
void TELL_CHILD(pid_t pid)


USP TUTORIALS                                                                     Page 33
{
kill(pid, SIGUSR1);
}
/* tell child we're done */
void WAIT_CHILD(void)
{
while (sigflag == 0)
sigsuspend(&zeromask);
sigflag = 0;
/* and wait for child */
/*
* Reset signal mask to original value.
*/
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error");
}


17. Implementation of POSIX.1 abort
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
void abort(void)
/* POSIX-style abort() function */
{
sigset_t mask;
struct sigaction action;
/*
* Caller can't ignore SIGABRT, if so reset to default.
*/
sigaction(SIGABRT, NULL, &action);
if (action.sa_handler == SIG_IGN)
{
action.sa_handler = SIG_DFL;
sigaction(SIGABRT, &action, NULL);


USP TUTORIALS                                                                 Page 34
}
if (action.sa_handler == SIG_DFL) fflush(NULL);
/* flush all open stdio streams */
/*
* Caller can't block SIGABRT; make sure it's unblocked.
*/
sigfillset(&mask);
sigdelset(&mask, SIGABRT); /* mask has only SIGABRT turned off */
sigprocmask(SIG_SETMASK, &mask, NULL);
kill(getpid(), SIGABRT);
/* send the signal */
/*
* If we're here, process caught SIGABRT and returned.
*/
fflush(NULL);
/* flush all open stdio streams */
action.sa_handler = SIG_DFL;
sigaction(SIGABRT, &action, NULL); /* reset to default */
sigprocmask(SIG_SETMASK, &mask, NULL); /* just in case ... */
kill(getpid(), SIGABRT);
/* and one more time */
exit(1);
/* this should never be executed ... */
}


18. Using system to invoke the ed editor


#include "apue.h"
static void sig_int(int signo)
{
printf("caught SIGINTn");
}
static void sig_chld(int signo)
{


USP TUTORIALS                                                       Page 35
printf("caught SIGCHLDn");
}
int main(void)
{
if (signal(SIGINT, sig_int) == SIG_ERR) err_sys("signal(SIGINT) error");
if (signal(SIGCHLD, sig_chld) == SIG_ERR) err_sys("signal(SIGCHLD) error");
if (system("/bin/ed") < 0) err_sys("system() error");
exit(0);
}


19. Correct POSIX.1 implementation of system function


#include<sys/wait.h>
#include<errno.h>
#include<signal.h>
#include<unistd.h>
int system(const char *cmdstring)
/* with appropriate signal handling */
{
pid_t pid;
int status;
struct sigaction ignore, saveintr, savequit;
sigset_t chldmask, savemask;
if (cmdstring == NULL) return(1);
/* always a command processor with UNIX */
ignore.sa_handler = SIG_IGN;
sigemptyset(&ignore.sa_mask);
ignore.sa_flags = 0;
/* ignore SIGINT and SIGQUIT */
if (sigaction(SIGINT, &ignore, &saveintr) < 0) return(-1);
if (sigaction(SIGQUIT, &ignore, &savequit) < 0) return(-1);
sigemptyset(&chldmask);
/* now block SIGCHLD */
sigaddset(&chldmask, SIGCHLD);


USP TUTORIALS                                                                 Page 36
if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0) return(-1);
if ((pid = fork()) < 0)
{
status = -1;
/* probably out of processes */
}
else if (pid == 0)
{
/* child */
/* restore previous signal actions & reset signal mask */
sigaction(SIGINT, &saveintr, NULL);
sigaction(SIGQUIT, &savequit, NULL);
sigprocmask(SIG_SETMASK, &savemask, NULL);
execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
_exit(127);
/* exec error */
}
else
{
/* parent */
while (waitpid(pid, &status, 0) < 0)
if (errno != EINTR) {
status = -1; /* error other than EINTR from waitpid() */
break;
}
}
/* restore previous signal actions & reset signal mask */
if (sigaction(SIGINT, &saveintr, NULL) < 0) return(-1);
if (sigaction(SIGQUIT, &savequit, NULL) < 0) return(-1);
if (sigprocmask(SIG_SETMASK, &savemask, NULL) < 0) return(-1);
return(status);
}




USP TUTORIALS                                                       Page 37
20. Reliable implementation of sleep
#include "apue.h"
static void sig_alrm(int signo)
{
/* nothing to do, just returning wakes up sigsuspend() */
}
unsigned int sleep(unsigned int nsecs)
{
struct sigaction newact, oldact;
sigset_t newmask, oldmask, suspmask;
unsigned int unslept;
/* set our handler, save previous information */
newact.sa_handler = sig_alrm;
sigemptyset(&newact.sa_mask);
newact.sa_flags = 0;
sigaction(SIGALRM, &newact, &oldact);
/* block SIGALRM and save current signal mask */
sigemptyset(&newmask);
sigaddset(&newmask, SIGALRM);
sigprocmask(SIG_BLOCK, &newmask, &oldmask);
alarm(nsecs);
suspmask = oldmask; /* make sure SIGALRM isn't blocked */
sigdelset(&suspmask, SIGALRM); /* wait for any signal to be caught */
sigsuspend(&suspmask);
/* some signal has been caught, SIGALRM is now blocked */
unslept = alarm(0);
sigaction(SIGALRM, &oldact, NULL);
/* reset previous action */
/* reset signal mask, which unblocks SIGALRM */
sigprocmask(SIG_SETMASK, &oldmask, NULL);
return(unslept);
}




USP TUTORIALS                                                           Page 38
21. How to handle SIGTSTP


#include "apue.h"
#define BUFFSIZE 1024
static void sig_tstp(int);
int main(void)
{
int n;
char buf[BUFFSIZE];
/*
* Only catch SIGTSTP if we're running with a job-control shell.
*/
if (signal(SIGTSTP, SIG_IGN) == SIG_DFL) signal(SIGTSTP, sig_tstp);
while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
if (write(STDOUT_FILENO, buf, n) != n) err_sys("write error");
if (n < 0) err_sys("read error");
exit(0);
}
static void sig_tstp(int signo) /* signal handler for SIGTSTP */
{
sigset_t mask;
/* ... move cursor to lower left corner, reset tty mode ... */
/*
* Unblock SIGTSTP, since it's blocked while we're handling it.
*/
sigemptyset(&mask);
sigaddset(&mask, SIGTSTP);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
signal(SIGTSTP, SIG_DFL); /* reset disposition to default */
kill(getpid(), SIGTSTP); /* and send the signal to ourself */
/* we won't return from the kill until we're continued */
signal(SIGTSTP, sig_tstp);
/* reestablish signal handler */
}


USP TUTORIALS                                                         Page 39
DAEMON PROCESSES


22. Initialize a daemon process


#include"apue.h"
#include<syslog.h>
#include<fcntl.h>
#include<sys/resource.h>
void daemonize(const char *cmd)
{
int i, fd0, fd1, fd2;
pid_t pid;
struct rlimit rl;
struct sigaction sa;
/*
* Clear file creation mask.
*/
umask(0);
/*
* Get maximum number of file descriptors.
*/
if (getrlimit(RLIMIT_NOFILE, &rl) < 0) err_quit("%s: can't get file limit", cmd);
/*
* Become a session leader to lose controlling TTY.
*/
if ((pid = fork()) < 0) err_quit("%s: can't fork", cmd);
else if (pid != 0) /* parent */
exit(0);
setsid();
/*
* Ensure future opens won't allocate controlling TTYs.
*/
sa.sa_handler = SIG_IGN;

USP TUTORIALS                                                                       Page 40
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0) err_quit("%s: can't ignore SIGHUP");
if ((pid = fork()) < 0) err_quit("%s: can't fork", cmd);
else if (pid != 0) /* parent */
exit(0);
/*
* Change the current working directory to the root so
* we won't prevent file systems from being unmounted.
*/
if (chdir("/") < 0) err_quit("%s: can't change directory to /");
/*
* Close all open file descriptors.
*/
if (rl.rlim_max == RLIM_INFINITY) rl.rlim_max = 1024;
for (i = 0; i < rl.rlim_max; i++) close(i);
/*
* Attach file descriptors 0, 1, and 2 to /dev/null.
*/
fd0 = open("/dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
/*
* Initialize the log file.
*/
openlog(cmd, LOG_CONS, LOG_DAEMON);
if (fd0 != 0 || fd1 != 1 || fd2 != 2)
{
syslog(LOG_ERR, "unexpected file descriptors %d %d %d",fd0, fd1, fd2);
exit(1);
}
}




USP TUTORIALS                                                                Page 41
23. Ensure that only one copy of a daemon is running


#include<unistd.h>
#include<stdlib.h>
#include<fcntl.h>
#include<syslog.h>
#include<errno.h>
#include<stdio.h>
#include<sys/stat.h>
#include<string.h>
#define LOCKFILE "/var/run/daemon.pid"
#define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
extern int lockfile(int);
int already_running(void)
{
int fd;
char buf[16];
fd = open(LOCKFILE, O_RDWR|O_CREAT, LOCKMODE);
if (fd < 0)
{
syslog(LOG_ERR, "can't open %s: %s", LOCKFILE, strerror(errno));
exit(1);
}
if (lockfile(fd) < 0)
{
if (errno == EACCES || errno == EAGAIN)
{
close(fd);
return(1);
}
syslog(LOG_ERR, "can't lock %s: %s", LOCKFILE, strerror(errno));
exit(1);
}
ftruncate(fd, 0);


USP TUTORIALS                                                      Page 42
sprintf(buf, "%ld", (long)getpid());
write(fd, buf, strlen(buf)+1);
return(0);
}




24. Daemon rereading configuration files


#include "apue.h"
#include <pthread.h>
#include <syslog.h>
sigset_t mask;
extern int already_running(void);
void reread(void)
{
/* ... */
}
void *thr_fn(void *arg)
{
int err, signo;
for (;;)
{
err = sigwait(&mask, &signo);
if (err != 0)
{
syslog(LOG_ERR, "sigwait failed");
exit(1);
}
switch (signo)
{
case SIGHUP: syslog(LOG_INFO, "Re-reading configuration file");
                  reread();
                  break;
case SIGTERM: syslog(LOG_INFO, "got SIGTERM; exiting");


USP TUTORIALS                                                     Page 43
exit(0);
default: syslog(LOG_INFO, "unexpected signal %dn", signo);
}
}
return(0);
}
int main(int argc, char *argv[])
{
int err;
pthread_t tid;
char *cmd;
struct sigaction sa;
if ((cmd = strrchr(argv[0], '/')) == NULL) cmd = argv[0];
else cmd++;
/*
* Become a daemon.
*/
daemonize(cmd);
/*
* Make sure only one copy of the daemon is running.
*/
if (already_running())
{
syslog(LOG_ERR, "daemon already running");
exit(1);
}
/*
* Restore SIGHUP default and block all signals.
*/
sa.sa_handler = SIG_DFL;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0) err_quit("%s: can't restore SIGHUP default");
sigfillset(&mask);


USP TUTORIALS                                                                         Page 44
if ((err = pthread_sigmask(SIG_BLOCK, &mask, NULL)) != 0) err_exit(err, "SIG_BLOCK error");
/*
* Create a thread to handle SIGHUP and SIGTERM.
*/
err = pthread_create(&tid, NULL, thr_fn, 0);
if (err != 0) err_exit(err, "can't create thread");
/*
* Proceed with the rest of the daemon.
*/
/* ... */
exit(0);
}


24. Alternate implementation of daemon rereading configuration files


#include "apue.h"
#include <syslog.h>
#include <errno.h>
extern int lockfile(int);
extern int already_running(void);
void reread(void)
{
/* ... */
}
void sigterm(int signo)
{
syslog(LOG_INFO, "got SIGTERM; exiting");
exit(0);
}
void sighup(int signo)
{
syslog(LOG_INFO, "Re-reading configuration file");
reread();
}


USP TUTORIALS                                                                      Page 45
int main(int argc, char *argv[])
{
char *cmd;
struct sigaction sa;
if ((cmd = strrchr(argv[0], '/')) == NULL)
cmd = argv[0];
else cmd++;
/*
* Become a daemon.
*/
daemonize(cmd);
/*
* Make sure only one copy of the daemon is running.
*/
if (already_running())
{
syslog(LOG_ERR, "daemon already running");
exit(1);
}
/*
* Handle signals of interest.
*/
sa.sa_handler = sigterm;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGHUP);
sa.sa_flags = 0;
if (sigaction(SIGTERM, &sa, NULL) < 0)
{
syslog(LOG_ERR, "can't catch SIGTERM: %s", strerror(errno));
exit(1);
}
sa.sa_handler = sighup;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGTERM);


USP TUTORIALS                                                  Page 46
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
{
syslog(LOG_ERR, "can't catch SIGHUP: %s", strerror(errno));
exit(1);
}
/*
* Proceed with the rest of the daemon.
*/
/* ... */
exit(0);
}




USP TUTORIALS                                                 Page 47

Más contenido relacionado

La actualidad más candente

Implementing Software Machines in Go and C
Implementing Software Machines in Go and CImplementing Software Machines in Go and C
Implementing Software Machines in Go and CEleanor McHugh
 
Implementing Software Machines in C and Go
Implementing Software Machines in C and GoImplementing Software Machines in C and Go
Implementing Software Machines in C and GoEleanor McHugh
 
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIThe Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIEleanor McHugh
 
Encrypt all transports
Encrypt all transportsEncrypt all transports
Encrypt all transportsEleanor McHugh
 
Debugging: Rules & Tools
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & ToolsIan Barber
 
Quick tour of PHP from inside
Quick tour of PHP from insideQuick tour of PHP from inside
Quick tour of PHP from insidejulien pauli
 
Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Platonov Sergey
 
Assignment no39
Assignment no39Assignment no39
Assignment no39Jay Patel
 
Kansai.pm 10周年記念 Plack/PSGI 入門
Kansai.pm 10周年記念 Plack/PSGI 入門Kansai.pm 10周年記念 Plack/PSGI 入門
Kansai.pm 10周年記念 Plack/PSGI 入門lestrrat
 
C++の話(本当にあった怖い話)
C++の話(本当にあった怖い話)C++の話(本当にあった怖い話)
C++の話(本当にあった怖い話)Yuki Tamura
 
OpenGurukul : Language : PHP
OpenGurukul : Language : PHPOpenGurukul : Language : PHP
OpenGurukul : Language : PHPOpen Gurukul
 
Créer une base NoSQL en 1 heure
Créer une base NoSQL en 1 heureCréer une base NoSQL en 1 heure
Créer une base NoSQL en 1 heureAmaury Bouchard
 
PHP Internals and Virtual Machine
PHP Internals and Virtual MachinePHP Internals and Virtual Machine
PHP Internals and Virtual Machinejulien pauli
 

La actualidad más candente (20)

Implementing Software Machines in Go and C
Implementing Software Machines in Go and CImplementing Software Machines in Go and C
Implementing Software Machines in Go and C
 
Implementing Software Machines in C and Go
Implementing Software Machines in C and GoImplementing Software Machines in C and Go
Implementing Software Machines in C and Go
 
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIThe Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
 
Encrypt all transports
Encrypt all transportsEncrypt all transports
Encrypt all transports
 
Whispered secrets
Whispered secretsWhispered secrets
Whispered secrets
 
Debugging: Rules & Tools
Debugging: Rules & ToolsDebugging: Rules & Tools
Debugging: Rules & Tools
 
Sp ch05
Sp ch05Sp ch05
Sp ch05
 
Quick tour of PHP from inside
Quick tour of PHP from insideQuick tour of PHP from inside
Quick tour of PHP from inside
 
Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.Евгений Крутько, Многопоточные вычисления, современный подход.
Евгений Крутько, Многопоточные вычисления, современный подход.
 
Sbaw091006
Sbaw091006Sbaw091006
Sbaw091006
 
Assignment no39
Assignment no39Assignment no39
Assignment no39
 
Kansai.pm 10周年記念 Plack/PSGI 入門
Kansai.pm 10周年記念 Plack/PSGI 入門Kansai.pm 10周年記念 Plack/PSGI 入門
Kansai.pm 10周年記念 Plack/PSGI 入門
 
Sysprog17
Sysprog17Sysprog17
Sysprog17
 
C++の話(本当にあった怖い話)
C++の話(本当にあった怖い話)C++の話(本当にあった怖い話)
C++の話(本当にあった怖い話)
 
Hachiojipm11
Hachiojipm11Hachiojipm11
Hachiojipm11
 
Php engine
Php enginePhp engine
Php engine
 
OpenGurukul : Language : PHP
OpenGurukul : Language : PHPOpenGurukul : Language : PHP
OpenGurukul : Language : PHP
 
Créer une base NoSQL en 1 heure
Créer une base NoSQL en 1 heureCréer une base NoSQL en 1 heure
Créer une base NoSQL en 1 heure
 
Go a crash course
Go   a crash courseGo   a crash course
Go a crash course
 
PHP Internals and Virtual Machine
PHP Internals and Virtual MachinePHP Internals and Virtual Machine
PHP Internals and Virtual Machine
 

Destacado

Trabajo erica ingles
Trabajo erica inglesTrabajo erica ingles
Trabajo erica inglesErica Zuluaga
 
MUSEO MULHOUSE FRANCIA
MUSEO MULHOUSE FRANCIAMUSEO MULHOUSE FRANCIA
MUSEO MULHOUSE FRANCIAlorenchuky
 
9502 bitirme projesi faz-1
9502 bitirme projesi faz-19502 bitirme projesi faz-1
9502 bitirme projesi faz-1Burak Bayar
 
Z 503 visita al_crucero-(coches clasicos)
Z 503   visita al_crucero-(coches clasicos)Z 503   visita al_crucero-(coches clasicos)
Z 503 visita al_crucero-(coches clasicos)lorenchuky
 
Thomson datenblatt
Thomson datenblattThomson datenblatt
Thomson datenblattdokumentos
 
Introduction to internet
Introduction to internetIntroduction to internet
Introduction to internetPrateek Rohatgi
 
TENERIFE --FOTINGOS Y TARTANAS--
TENERIFE --FOTINGOS Y TARTANAS--TENERIFE --FOTINGOS Y TARTANAS--
TENERIFE --FOTINGOS Y TARTANAS--lorenchuky
 
Characteristics of the Church
Characteristics of the ChurchCharacteristics of the Church
Characteristics of the ChurchReligious Ed
 

Destacado (16)

Trabajo erica ingles
Trabajo erica inglesTrabajo erica ingles
Trabajo erica ingles
 
Charteo en
Charteo enCharteo en
Charteo en
 
Visual resume
Visual resumeVisual resume
Visual resume
 
Wiki
WikiWiki
Wiki
 
MUSEO MULHOUSE FRANCIA
MUSEO MULHOUSE FRANCIAMUSEO MULHOUSE FRANCIA
MUSEO MULHOUSE FRANCIA
 
Chapter+4
Chapter+4Chapter+4
Chapter+4
 
Gift room презентация
Gift room презентацияGift room презентация
Gift room презентация
 
9502 bitirme projesi faz-1
9502 bitirme projesi faz-19502 bitirme projesi faz-1
9502 bitirme projesi faz-1
 
Solucionarios desafios 5
Solucionarios desafios 5Solucionarios desafios 5
Solucionarios desafios 5
 
Z 503 visita al_crucero-(coches clasicos)
Z 503   visita al_crucero-(coches clasicos)Z 503   visita al_crucero-(coches clasicos)
Z 503 visita al_crucero-(coches clasicos)
 
Computer & services
Computer & services Computer & services
Computer & services
 
Brain
BrainBrain
Brain
 
Thomson datenblatt
Thomson datenblattThomson datenblatt
Thomson datenblatt
 
Introduction to internet
Introduction to internetIntroduction to internet
Introduction to internet
 
TENERIFE --FOTINGOS Y TARTANAS--
TENERIFE --FOTINGOS Y TARTANAS--TENERIFE --FOTINGOS Y TARTANAS--
TENERIFE --FOTINGOS Y TARTANAS--
 
Characteristics of the Church
Characteristics of the ChurchCharacteristics of the Church
Characteristics of the Church
 

Similar a Usp

httplinux.die.netman3execfork() creates a new process by.docx
httplinux.die.netman3execfork() creates a new process by.docxhttplinux.die.netman3execfork() creates a new process by.docx
httplinux.die.netman3execfork() creates a new process by.docxadampcarr67227
 
Program Assignment Process ManagementObjective This program a.docx
Program Assignment  Process ManagementObjective This program a.docxProgram Assignment  Process ManagementObjective This program a.docx
Program Assignment Process ManagementObjective This program a.docxwkyra78
 
Write a C++ program 1. Study the function process_text() in file.pdf
Write a C++ program 1. Study the function process_text() in file.pdfWrite a C++ program 1. Study the function process_text() in file.pdf
Write a C++ program 1. Study the function process_text() in file.pdfjillisacebi75827
 
3 1. preprocessor, math, stdlib
3 1. preprocessor, math, stdlib3 1. preprocessor, math, stdlib
3 1. preprocessor, math, stdlib웅식 전
 
Mouse programming in c
Mouse programming in cMouse programming in c
Mouse programming in cgkgaur1987
 
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbs
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbsSystem Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbs
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbsashukiller7
 
Rust LDN 24 7 19 Oxidising the Command Line
Rust LDN 24 7 19 Oxidising the Command LineRust LDN 24 7 19 Oxidising the Command Line
Rust LDN 24 7 19 Oxidising the Command LineMatt Provost
 
Lab01Filesbuild.bat@echo offclsset DRIVE_LETTER=1.docx
Lab01Filesbuild.bat@echo offclsset DRIVE_LETTER=1.docxLab01Filesbuild.bat@echo offclsset DRIVE_LETTER=1.docx
Lab01Filesbuild.bat@echo offclsset DRIVE_LETTER=1.docxDIPESH30
 
IO redirection in C shellPlease implement input output redirect.pdf
IO redirection in C shellPlease implement input  output redirect.pdfIO redirection in C shellPlease implement input  output redirect.pdf
IO redirection in C shellPlease implement input output redirect.pdfforecastfashions
 
Help Needed!UNIX Shell and History Feature This project consists.pdf
Help Needed!UNIX Shell and History Feature This project consists.pdfHelp Needed!UNIX Shell and History Feature This project consists.pdf
Help Needed!UNIX Shell and History Feature This project consists.pdfmohdjakirfb
 
Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Yandex
 
Penumbra: Automatically Identifying Failure-Relevant Inputs (ISSTA 2009)
Penumbra: Automatically Identifying Failure-Relevant Inputs (ISSTA 2009)Penumbra: Automatically Identifying Failure-Relevant Inputs (ISSTA 2009)
Penumbra: Automatically Identifying Failure-Relevant Inputs (ISSTA 2009)James Clause
 
Unit 8
Unit 8Unit 8
Unit 8siddr
 
Linux seccomp(2) vs OpenBSD pledge(2)
Linux seccomp(2) vs OpenBSD pledge(2)Linux seccomp(2) vs OpenBSD pledge(2)
Linux seccomp(2) vs OpenBSD pledge(2)Giovanni Bechis
 
Shell to be modified#include stdlib.h #include unistd.h .pdf
Shell to be modified#include stdlib.h #include unistd.h .pdfShell to be modified#include stdlib.h #include unistd.h .pdf
Shell to be modified#include stdlib.h #include unistd.h .pdfclarityvision
 

Similar a Usp (20)

httplinux.die.netman3execfork() creates a new process by.docx
httplinux.die.netman3execfork() creates a new process by.docxhttplinux.die.netman3execfork() creates a new process by.docx
httplinux.die.netman3execfork() creates a new process by.docx
 
Program Assignment Process ManagementObjective This program a.docx
Program Assignment  Process ManagementObjective This program a.docxProgram Assignment  Process ManagementObjective This program a.docx
Program Assignment Process ManagementObjective This program a.docx
 
Write a C++ program 1. Study the function process_text() in file.pdf
Write a C++ program 1. Study the function process_text() in file.pdfWrite a C++ program 1. Study the function process_text() in file.pdf
Write a C++ program 1. Study the function process_text() in file.pdf
 
3 1. preprocessor, math, stdlib
3 1. preprocessor, math, stdlib3 1. preprocessor, math, stdlib
3 1. preprocessor, math, stdlib
 
Mouse programming in c
Mouse programming in cMouse programming in c
Mouse programming in c
 
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbs
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbsSystem Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbs
System Calls.pptxnsjsnssbhsbbebdbdbshshsbshsbbs
 
Rust LDN 24 7 19 Oxidising the Command Line
Rust LDN 24 7 19 Oxidising the Command LineRust LDN 24 7 19 Oxidising the Command Line
Rust LDN 24 7 19 Oxidising the Command Line
 
Os lab final
Os lab finalOs lab final
Os lab final
 
Lab01Filesbuild.bat@echo offclsset DRIVE_LETTER=1.docx
Lab01Filesbuild.bat@echo offclsset DRIVE_LETTER=1.docxLab01Filesbuild.bat@echo offclsset DRIVE_LETTER=1.docx
Lab01Filesbuild.bat@echo offclsset DRIVE_LETTER=1.docx
 
Csdfsadf
CsdfsadfCsdfsadf
Csdfsadf
 
C
CC
C
 
C
CC
C
 
IO redirection in C shellPlease implement input output redirect.pdf
IO redirection in C shellPlease implement input  output redirect.pdfIO redirection in C shellPlease implement input  output redirect.pdf
IO redirection in C shellPlease implement input output redirect.pdf
 
Help Needed!UNIX Shell and History Feature This project consists.pdf
Help Needed!UNIX Shell and History Feature This project consists.pdfHelp Needed!UNIX Shell and History Feature This project consists.pdf
Help Needed!UNIX Shell and History Feature This project consists.pdf
 
Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++
 
C introduction by piyushkumar
C introduction by piyushkumarC introduction by piyushkumar
C introduction by piyushkumar
 
Penumbra: Automatically Identifying Failure-Relevant Inputs (ISSTA 2009)
Penumbra: Automatically Identifying Failure-Relevant Inputs (ISSTA 2009)Penumbra: Automatically Identifying Failure-Relevant Inputs (ISSTA 2009)
Penumbra: Automatically Identifying Failure-Relevant Inputs (ISSTA 2009)
 
Unit 8
Unit 8Unit 8
Unit 8
 
Linux seccomp(2) vs OpenBSD pledge(2)
Linux seccomp(2) vs OpenBSD pledge(2)Linux seccomp(2) vs OpenBSD pledge(2)
Linux seccomp(2) vs OpenBSD pledge(2)
 
Shell to be modified#include stdlib.h #include unistd.h .pdf
Shell to be modified#include stdlib.h #include unistd.h .pdfShell to be modified#include stdlib.h #include unistd.h .pdf
Shell to be modified#include stdlib.h #include unistd.h .pdf
 

Usp

  • 1. USP PROGRAMS UNIX AND ANSI STANDARDS PROG 1: To illustrate the use of cpp symbols #include<stdio.h> #include<unistd.h> int main() { #if __STDC__==0 printf("cc is not ancic compliantn"); #else printf("%s compiled at %s:%s.this statement is at line %dn",__FILE__,__DATE__,__TIME__,__LINE__); #endif return 0; } OUTPUT: unix1.c compiled at May 19 2011:08:46:43.this statement is at line 8 PROG 2: To show posix version #include<iostream> #include<unistd.h> #define _POSIX_SOURCE #define _POSIX_C_SOURCE 199309l using namespace std; int main() { #ifdef _POSIX_VERSION cout<<"system confirms to posix:"<< _POSIX_VERSION<<"n"; #else cout<<"_POSIX_VERSION is undefinedn"; #endif return 0; } OUTPUT: system confirms to posix:200809 PROG3: To show test macros: #define _POSIX_SOURCE #define _POSIX_C_SOURCE 199309L USP TUTORIALS Page 1
  • 2. #include<iostream> #include<unistd.h> using namespace std; int main() { #ifdef _POSIX_JOB_CONTROL cout<<"sys control job supportn"; #else cout<"sys does not support job controln"; #endif #ifdef _POSIX_SAVED_IDS cout<<"sys support saved set_uid and saved set_gidn"; #else cout<<"sys does not support saved set_uid and saved set_gidn"; #endif #ifdef _POSIX_CHOWN_RESTRICTED cout<<"sys does not support chown_restricted optionn"; #endif #ifdef _POSIX_NO_TRUNC cout<<"path name trunc option is:"<<_POSIX_NO_TRUNC<<endl; #else cout<<"sys does not suport sys-wide path name trunc optionn"; #endif #ifdef _POSIX_VDISABLE cout<<"distance char for terminal files is,"<<_POSIX_VDISABLE<<”Thnxn” #else cout<<"sys does not support_POSIX_VDISABLEn"; #endif return 0; } OUTPUT: sys control job support sys support saved set_uid and saved set_gid sys does not support chown_restricted option path name trunc option is:1 distance char for terminal files is,Thnx PROG 4: Use of sysconf,pathconf and fpathconf: #define _POSIX_SOURCE #define _POSIX_C_SOURCE 199309L #include<stdio.h> #include<iostream> #include<unistd.h> using namespace std; USP TUTORIALS Page 2
  • 3. int main() { int res; if((res=sysconf(_SC_OPEN_MAX))==-1) perror("sysconf"); else cout<<"OPEN_MAX:"<<res<<endl; if((res==pathconf("/",_PC_PATH_MAX))==-1) perror("pathconf"); else cout<<"Max path name:"<<(res+1)<<endl; if((res=fpathconf(0,_PC_CHOWN_RESTRICTED))==-1) perror("fpathconf"); else cout<<"Chown_restricted for stdin:"<<res<<endl; return 0; } OUTPUT: OPEN_MAX:1024 Max path name:1025 Chown_restricted for stdin:1 PROG 5: Use of setlocale function: #include <stdio.h> #include <time.h> #include <locale.h> int main () { time_t rawtime; struct tm * timeinfo; char buffer [80]; struct lconv * lc; time ( &rawtime ); timeinfo = localtime ( &rawtime ); int twice=0; do { printf ("Locale is: %sn", setlocale(LC_ALL,NULL) ); strftime (buffer,80,"%c",timeinfo); printf ("Date is: %sn",buffer); lc = localeconv (); USP TUTORIALS Page 3
  • 4. printf ("Currency symbol is: %sn-n",lc->currency_symbol); setlocale (LC_ALL,""); }while (!twice++); return 0; } OUTPUT: Locale is: C Date is: 01/15/07 13:33:47 Currecy symbol is: - Locale is: English_United States.1252 Date is: 1/15/07 1:33:47 PM Currency symbol is: $ - UNIX FILE APIs Prog 1: To show the use of open,read,write and close Apis #include<stdio.h> #include<sys/types.h> #include<fcntl.h> #include<unistd.h> #include<string.h> #include<stdlib.h> int main(int argc,char *argv[]) { int fdesc; char buf[256],*buf1; if(argc !=3) { printf("Usage: ./a.out<readfile><writefile>n"); exit(0); } fdesc=open(argv[1],O_RDONLY); printf("CONTENTS OF FILE IS:n"); while(read(fdesc,buf,sizeof(buf)) > 0); printf("%s",buf); close(fdesc); fdesc=open(argv[2],O_WRONLY|O_APPEND|O_CREAT); buf1=(char *)malloc(1024*sizeof(char)); printf("Enter the data to be updated to the file:n"); scanf("%s",buf1); USP TUTORIALS Page 4
  • 5. size_t length=strlen(buf1); if(write(fdesc,buf1,length)==-1) printf("Write errorn"); close(fdesc); return 0; } OUTPUT: ./a.out read.txt write.txt Contents of read.txt is: This is a read file Enter the data to be updated to writefile: Hai, have a nice day Prog 2: Use of fcntl api #include<sys/types.h> #include<stdio.h> #include<fcntl.h> #include<unistd.h> int main(int argc,char **argv) { int fdesc=open(argv[1],O_RDONLY); close(0); int cur_flags=fcntl(fdesc,F_GETFL); printf(" %d %d n",fdesc,cur_flags); printf("close on exec= %dn", fcntl(fdesc,F_GETFD)); (void)fcntl(fdesc,F_SETFD,1); printf("close on exec= %d", fcntl(fdesc,F_GETFD)); if(fcntl(fdesc,F_DUPFD,0)==-1) perror("fcntl"); char buf[256]; int rc=read(0,buf,256); printf("rc=%dnn",rc); } Prog 3: Use of lseek Api #include<stdio.h> #include<unistd.h> #include<fcntl.h> #include<sys/types.h> int main(int argc,char *argv[]) { char buf[256]; int fdesc,len; USP TUTORIALS Page 5
  • 6. while(--argc > 0) { if(access(*++argv,F_OK)) { fdesc=open(*argv,O_WRONLY|O_CREAT,0744); write(fdesc,"HELLO WORLDn",12); } else { fdesc=open(*argv,O_RDONLY); while(len=read(fdesc,buf,256)) write(1,buf,len); } close(fdesc); } } Prog 4: Use of link Api #include<stdio.h> #include<unistd.h> int main(int argc,char *argv[]) { if(argc!=3) { printf("Usage: ./a.out <srcfile> <dest_file>n"); return 0; } if(link(argv[1],argv[2])==-1) { perror("link"); return 1; } return 2; } Prog 5: Use of unlink Api #include<stdio.h> #include<sys/types.h> #include<unistd.h> #include<string.h> int main(int argc,char *argv[]) { if(argc!=3 || !strcmp(argv[1],argv[2])) USP TUTORIALS Page 6
  • 7. printf("Usage: ./a.out <old_link> <new_link>n"); else if(link(argv[1],argv[2])==0) return unlink(argv[1]); return -1; } Prog 6: Use of stat Api #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> void change_mode() { struct stat statv; int flag=(S_IWGRP|S_IROTH|S_IXOTH); if(stat("/usr/games/gbrainy",&statv)) perror("stat"); else { flag=(statv.st_mode & ~flag)|S_ISUID; if(chmod("/usr/games/gbrainy",flag)) perror("chmod"); } } int main() { change_mode(); return 0; } Prog 7: Use of access Api #include <sys/types.h> #include <unistd.h> #include <fcntl.h> int main(int argc, char * argv[]) { char buf[256]; int fdesc,len; while(--argc > 0) USP TUTORIALS Page 7
  • 8. { if(access(*++argv,F_OK)) { // a brand new file fdesc = open(*argv, O_WRONLY | O_CREAT, 0744); write(fdesc, "Hello world n", 12); } else { fdesc = open(*argv, O_RDONLY); while(len = read(fdesc, buf, 256)) write(1, buf, len); } close(fdesc); } } Prog 8: Use of chmod Api #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<stdio.h> int main() { struct stat statv; mode_t flag1=S_IRWXU|S_IWGRP|S_IROTH|S_IWOTH|S_IXOTH; if(stat("/home/nithish/time.c",&statv)) perror("stat"); else { printf("%dn",flag1); if(chmod("/home/nithish/time.c",flag1)) perror("chmod"); } } Prog 9: Use of chown Api #include <iostream> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <pwd.h> #include <stdio.h> using namespace std; int main(int argc, char * argv[]) { USP TUTORIALS Page 8
  • 9. if(argc < 3) { cerr << "usage:"<<argv[0] << " <usr_name> <files> n"; return 1; } struct passwd *pwd = getpwuid (argv[1]); //convert user name to UID uid_t UID = pwd ? pwd->pw_uid:-1; struct stat statv; if(UID == (uid_t) -1) cerr << "invalid user name n"; else for(int i = 2; i < argc; i++) //do for each file specified if(stat(argv[i] & statv) == 0) { if(chown(argv[i],UID,statv.st_gid)) perror("chown"); } else perror("stat"); return 0; } Prog 10: Use of utime Api #include<sys/types.h> #include<unistd.h> #include<utime.h> #include<stdio.h> int main(int argc,char *argv[]) { struct utimbuf times; int offset,i; if(argc<3 || sscanf(argv[1],"%d",&offset) != 1) printf("Usage: ./a.out <offset> <filenames>n"); else { times.actime=times.modtime=time(0)+offset; for(i=2;i<argc;i++) { if(utime(argv[i],&times) == -1) perror("utime"); } return 0; } return 1; } USP TUTORIALS Page 9
  • 10. Prog 11: Illustrate file locking: #include <iostream> #include <stdio.h> #include <sys/types.h> #include <fcntl.h> #include <unistd.h> using namespace std; int main(int argc, char *argv[]) { struct flock fvar; int temp; int fdesc; while(--argc > 0) { if((fdesc = open(*++argv, O_RDWR)) == -1) { perror("open"); continue; } fvar.l_type = F_WRLCK; fvar.l_whence = SEEK_SET; fvar.l_start = 0; fvar.l_len = 0; temp = fcntl(fdesc,F_SETLKW,&fvar); cout <<temp; temp = fcntl(fdesc, F_GETLK,&fvar); cout <<endl<<temp<<endl<<endl; cout <<*argv<< " nlocked by : " << fvar.l_pid <<"nfrom :"<< fvar.l_start<<"tfor"<<fvar.l_len<<"tbyte fort"<<(fvar.l_type==F_WRLCK?'w':'r')<<endl; //set lock fails, find out who has locked the file */ /* Attempt to set an exclusive (write) lock on the entire file */ while(fcntl(fdesc, F_SETLK,&fvar) == -1) { cout<<"enter the loop"; //set lock fails find out who has locked the file */ while(fcntl(fdesc,F_GETLK, &fvar)!= -1 && fvar.l_type != F_UNLCK){ cout << "argv"<< "locked by" << fvar.l_pid <<"from "<< fvar.l_start<<"for"<<fvar.l_len<<"byte for"<<(fvar.l_type==F_WRLCK?'w':'r')<<endl; if(!fvar.l_len) break; fvar.l_start += fvar.l_len; fvar.l_len = 0; } } fvar.l_type = F_UNLCK; fvar.l_whence = SEEK_SET; fvar.l_start = 0; fvar.l_len = 0; if(fcntl(fdesc, F_SETLKW, &fvar) == -1) USP TUTORIALS Page 10
  • 11. perror("fcntl"); } return 0; } Prog 12: Directory file APIs #include<iostream> #include<sys/types.h> #include<sys/stat.h> #include<unistd.h> #include<pwd.h> #include<utime.h> #include<time.h> #include<error.h> #include<stdio.h> #include<fcntl.h> #include<string.h> using namespace std; #if defined(BSO) && !_POSIX_SOURCE #include<sys/dir.h> typedef struct direct Dirent; #else #include<dirent.h> typedef struct dirent Dirent; #endif int main(int argc,char*argv[]) { Dirent* dp; DIR *dir_fdesc; while(--argc>0) { if(!(dir_fdesc==opendir(*++argv))) { if(mkdir(*argv,S_IRWXU|S_IRWXG|S_IRWXO)==-1) perror("opendir"); continue; } for(int i=0;i<2;i++) { for(int cnt=0;dp=readdir(dir_fdesc);) { if(i) cout<<dp->d_name<<endl; if(strcmp(dp->d_name,",") && strcmp(dp->d_name,"...")) cnt++; } if(!cnt) {rmdir(*argv);break;} rewinddir(dir_fdesc); } USP TUTORIALS Page 11
  • 12. closedir(dir_fdesc); } } Prog 13: Device file API #include<iostream> #include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <sys/stat.h> using namespace std; int main(int argc, char *argv[]) { if(argc != 4) { cout <<"usage: " <<argv[0]<<" <file><major no><minor no>n"; return 0; } int major = atoi(agrv[2]), minor = atoi(argv[3]); (void)mknod(argv[1],S_IFCHR|S_IRWXU|S_IRWXG|S_IRWXO,(major << 8) | minor); int rc = 1, fd = open(argv[1], O_RDWR|O_NOBLOCK|O_NOCTTY); char buf[256]; while ( rc && fd != -1) if((rc= read(fd,buf,sizeof(buf)))<0) perror("read"); else if(rc) cout<<buf<<endl; close(fd); } Prog 14: Fifo file API #include<stdio.h> #include<sys/types.h> #include<unistd.h> #include<sys/stat.h> #include<fcntl.h> #include<string.h> #include<errno.h> int main(int argc,char **argv) { if(argc!=2 && argc!=3) { printf("n usage: %s <file> [<arg>] n",argv[0]); return 0; } USP TUTORIALS Page 12
  • 13. int fd; char buf[256]; (void)mkfifo(argv[1],S_IFIFO|S_IRWXU|S_IRWXG|S_IRWXO); if(argc==2) { fd=open(argv[1],O_RDONLY|O_NONBLOCK); while(read(fd,buf,sizeof(buf))==-1 && errno==EAGAIN) sleep(1); while(read(fd,buf,sizeof(buf)) > 0) printf("n %s n",buf); } else { fd=open(argv[1],O_WRONLY); write(fd,argv[2],strlen(argv[2])); } close(fd); } Prog 15: Symbolic file API #include<iostream> #include<sys/types.h> #include<unistd.h> #include<string.h> using namespace std; int main(int argc,char **argv) { char *buf[256],tname[256]; if((argc<3 && argc>4)||(argc==4 && strcmp(argv[1],"-s"))) { cout<<"usage:" <<argv[0]<<" [-s] <orig file> <newlink>"; return 1; } if(argc==4) return symlink(argv[2],argv[3]); else return link(argv[1],argv[2]); } USP TUTORIALS Page 13
  • 14. Process Environment 1. To print argument list #include<stdio.h> int main(int argc,char **argv) { int i; for(i=0;i<argc;i++) { printf("nargv[%d]: %s",i,argv[i]) } } 2. atexit function #include<stdio.h> static void my_exit1(void) { printf("nfirst exit handler"); } static void my_exit2(void) { printf("nsecond exit handler"); } int main(void) { if(atexit(my_exit2)!=0) printf("ncan't register my_exit2"); if(atexit(my_exit1)!=0) printf("ncan't register my_exit1"); if(atexit(my_exit1)!=0) printf("ncan't register my_exit1"); printf("nmain is done"); return 0; } 3. Use of environment variables #include<stdio.h> #include<stdlib.h> int main() { int a,b,c; char *str="usp",char get[20]; const char *value="tut6"; a=putenv(str); USP TUTORIALS Page 14
  • 15. if(a !=0) printf("nputenv error"); b=setenv(str,value,0); get=getenv(str); printf("nEnvironment var: %s",get); if(b !=0) printf("nsetenv error"); c=unsetenv(str); if(c !=0) printf("nunsetenv error"); } 4.setjmp and longjmp functions #include<setjmp.h> #include<stdio.h> #define TOK_ADD 5 #define MAXLINE 2 jmp_buf jmpbuffer; int main(void) { char line[MAXLINE]; if(setjmp(jmpbuffer)!=0) printf("error"); while(fgets(line,MAXLINE,stdin)!=NULL) do_line(line); exit(0); } void cmd_add(void) { int token; token=get_token(); if(token<0) longjmp(jmpbuffer,1); } Process Control 1. vfork function #include<stdio.h> #include<stdlib.h> int glob=0; int main() { int var; pid_t pid; var=88; USP TUTORIALS Page 15
  • 16. if((pid=fork())<0) printf("vfork error"); else if(pid==0) { glob++; var++; } printf("pid=%d,glob=%d,var=%dn",getpid(),glob,var); exit(0); } 2. fork function #include<stdio.h> #include<unistd.h> #include<stdlib.h> int main() { pid_t child_pid; printf("PID:%d nParent: %dn",getpid(),getppid()); switch(child_pid=fork()) { case (pid_t)-1: perror("fork"); break; case (pid_t)0: printf("nChild created.. PID: %dnParent : %dn",getpid(),getppid()); exit(0); break; default: printf("Parent after fork PID:%d nChild PID: %dn",getpid(),child_pid); break; } return 0; } 3. execle function #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<sys/wait.h> char *envinit[] = {"USER=unknown", "PATH=/tmp",NULL}; int main() { pid_t pid; USP TUTORIALS Page 16
  • 17. if((pid=fork()) < 0) { printf("Fork errorn"); exit(0); } else if(pid==0) { if(execle("/home/abhishta/echoall","arg1","arg2",(char *) 0,envinit) < 0) { printf("Execle errorn"); exit(0); } } if(waitpid(pid,NULL,0) < 0) printf("Wait errorn"); exit(0); } 4. exec function #include <stdio.h> #include <stdlib.h> #include <sys/wait.h> #include <sys/types.h> int main(int argc, char *argv[]) { pid_t pid; if ((pid = fork()) < 0) { fprintf(stderr, "fork failedn"); exit(1); } wait(NULL); //waitpid(pid,NULL,0); //waitid(P_PID,pid,NULL,0); if (pid == 0) { execlp("echo", "echo", "nHello from", "the child", (char *) NULL); fprintf(stderr, "execl failedn"); exit(2); USP TUTORIALS Page 17
  • 18. } } 5. echoall function #include<stdio.h> #include<stdlib.h> int main(int argc,char *argv[]) { int i; char **ptr; extern char **environ; for(i=0;i<argc;i++) printf("argv[%d]: %sn",i,argv[i]); for(ptr=environ;*ptr !=0; ptr++) printf("%sn",*ptr); exit(0); } 6. getsetrlimit function #include "stdio.h" #include<stdlib.h> #include"error.h" #if defined(BSD) || defined(MACOS) #include <sys/time.h> #include <sys/stat.h> #define FMT "%10lld " #else #define FMT "%10ld " #endif #include <sys/resource.h> #define doit(name) pr_limits(#name, name) static void pr_limits(char *, int); int main(void) { #ifdef RLIMIT_AS doit(RLIMIT_AS); #endif doit(RLIMIT_CORE); doit(RLIMIT_CPU); doit(RLIMIT_DATA); doit(RLIMIT_FSIZE); #ifdef RLIMIT_LOCKS doit(RLIMIT_LOCKS); USP TUTORIALS Page 18
  • 19. #endif #ifdef RLIMIT_MEMLOCK doit(RLIMIT_MEMLOCK); #endif doit(RLIMIT_NOFILE); #ifdef RLIMIT_NPROC doit(RLIMIT_NPROC); #endif #ifdef RLIMIT_RSS doit(RLIMIT_RSS); #endif #ifdef RLIMIT_SBSIZE doit(RLIMIT_SBSIZE); #endif doit(RLIMIT_STACK); #ifdef RLIMIT_VMEM doit(RLIMIT_VMEM); #endif exit(0); } static void pr_limits(char *name, int resource) { struct rlimit limit; if (getrlimit(resource, &limit) < 0) printf("getrlimit error for %s", name); printf("%-14s ", name); if (limit.rlim_cur == RLIM_INFINITY) printf("(infinite) "); else printf(FMT, limit.rlim_cur); if (limit.rlim_max == RLIM_INFINITY) printf("(infinite)"); else printf(FMT, limit.rlim_max); putchar((int)'n'); } 7. system function #include<stdio.h> #include<stdlib.h> int main() { system("ls -l"); printf("nCommand done.nn"); return 0; } USP TUTORIALS Page 19
  • 20. Process Relationships 1. Creating an orphaned process group #include "apue.h" #include <errno.h> static void sig_hup(int signo) { printf("SIGHUP received, pid = %dn", getpid()); } static void pr_ids(char *name) { printf("%s: pid = %d, ppid = %d, pgrp = %d, tpgrp = %dn", name, getpid(), getppid(), getpgrp(), tcgetpgrp(STDIN_FILENO)); fflush(stdout); } int main(void) { char c; pid_t pid; pr_ids("parent"); if ((pid = fork()) < 0) { err_sys("fork error"); } else if (pid > 0) { /* parent */ sleep(5); /*sleep to let child stop itself */ exit(0); /* then parent exits */ } else { /* child */ pr_ids("child"); signal(SIGHUP, sig_hup); /* establish signal handler */ kill(getpid(), SIGTSTP); /* stop ourself */ pr_ids("child"); /* prints only if we're continued */ if (read(STDIN_FILENO, &c, 1) != 1) printf("read error from controlling TTY, errno = %dn", errno); exit(0); } } USP TUTORIALS Page 20
  • 21. } Signals 2. Call a non-reentrant function from a signal handler #include "apue.h" #include <pwd.h> static void my_alarm(int signo) { struct passwd *rootptr; printf("in signal handlern"); if ((rootptr = getpwnam("root")) == NULL) err_sys("getpwnam(root) error"); alarm(1); } int main(void) { struct passwd *ptr; signal(SIGALRM, my_alarm); alarm(1); for ( ; ; ) { if ((ptr = getpwnam("sar")) == NULL) err_sys("getpwnam error"); if (strcmp(ptr->pw_name, "sar") != 0) printf("return value corrupted!, pw_name = %sn", ptr->pw_name); } } 3. System V SIGCLD handler that doesn't work : #include "apue.h" #include <sys/wait.h> static void sig_cld(int); int main() USP TUTORIALS Page 21
  • 22. { pid_t pid; if (signal(SIGCLD, sig_cld) == SIG_ERR) perror("signal error"); if ((pid = fork()) < 0) { perror("fork error"); } else if (pid == 0) { /* child */ sleep(2); _exit(0); } pause(); exit(0); /* parent */ } static void sig_cld(int signo) { pid_t pid; int status; /* interrupts pause() */ printf("SIGCLD receivedn"); if (signal(SIGCLD, sig_cld) == SIG_ERR) /* reestablish handler */ perror("signal error"); If ((pid = wait(&status)) < 0) /* fetch child status */ perror("wait error"); printf("pid = %dn", pid); } 4. Simple, implementation of sleep #include <signal.h> #include <unistd.h> static void sig_alrm(int signo) { USP TUTORIALS Page 22
  • 23. /* nothing to do, just return to wake up the pause */ } unsigned int sleep1(unsigned int nsecs) { if (signal(SIGALRM, sig_alrm) == SIG_ERR) return(nsecs); alarm(nsecs); /* start the timer */ pause(); /* next caught signal wakes us up */ return(alarm(0)); /* turn off timer, return unslept time */ } 5. Calling sleep2 from a program that catches other signals #include "apue.h" unsigned int static void int main(void) { unsigned int sleep2(unsigned int); sig_int(int); unslept; if (signal(SIGINT, sig_int) == SIG_ERR) err_sys("signal(SIGINT) error"); unslept = sleep2(5); printf("sleep2 returned: %un", unslept); exit(0); } static void sig_int(int signo) { int i, j; volatile int k; /* USP TUTORIALS Page 23
  • 24. * Tune these loops to run for more than 5 seconds * on whatever system this test program is run. */ printf("nsig_int startingn"); for (i = 0; i < 300000; i++) for (j = 0; j < 4000; j++) k += i * j; printf("sig_int finishedn"); } 6. Calling read with a timeout #include "apue.h" static void sig_alrm(int); int main(void) { int n; char line[MAXLINE]; if (signal(SIGALRM, sig_alrm) == SIG_ERR) err_sys("signal(SIGALRM) error"); alarm(10); if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0) err_sys("read error"); alarm(0); write(STDOUT_FILENO, line, n); exit(0); } static void sig_alrm(int signo) { /* nothing to do, just return to interrupt the read */ } USP TUTORIALS Page 24
  • 25. 7. Calling read with a timeout, using longjmp #include "apue.h" #include <setjmp.h> static void sig_alrm(int); static jmp_buf env_alrm; int main(void) { int n; char env_alrm; line[MAXLINE]; if (signal(SIGALRM, sig_alrm) == SIG_ERR) err_sys("signal(SIGALRM) error"); if (setjmp(env_alrm) != 0) err_quit("read timeout"); alarm(10); if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0) err_sys("read error"); alarm(0); write(STDOUT_FILENO, line, n); exit(0); } static void sig_alrm(int signo) { longjmp(env_alrm, 1); } 8. An implementation of sigaddset, sigdelset, and sigismember. #include<signal.h> #include<errno.h> /* <signal.h> usually defines NSIG to include signal number 0 */ #define SIGBAD(signo) ((signo) <= 0 || (signo) >= NSIG) int sigaddset(sigset_t *set, int signo) { if (SIGBAD(signo)) { errno = EINVAL; return(-1); } USP TUTORIALS Page 25
  • 26. *set |= 1 << (signo - 1); return(0); /* turn bit on */ } int sigdelset(sigset_t *set, int signo) { if (SIGBAD(signo)) { errno = EINVAL; return(-1); } *set &= ~(1 << (signo - 1)); return(0); /* turn bit off */ } int sigismember(const sigset_t *set, int signo) { if (SIGBAD(signo)) { errno = EINVAL; return(-1); } return((*set & (1 << (signo - 1))) != 0); } 9. Print the signal mask for the process. #include "apue.h" #include <errno.h> void pr_mask(const char *str) { sigset_t sigset; int errno_save; errno_save = errno; if (sigprocmask(0, NULL, &sigset) < 0) err_sys("sigprocmask error"); printf("%s", str); if (sigismember(&sigset,SIGINT)) printf("SIGINT "); if (sigismember(&sigset,SIGQUIT)) printf("SIGQUIT "); if (sigismember(&sigset,SIGUSR1)) printf("SIGUSR1 "); if (sigismember(&sigset,SIGALRM)) printf("SIGALRM "); printf("n"); errno = errno_save; } USP TUTORIALS Page 26
  • 27. 10. Example of signal sets and sigprocmask. #include "apue.h" static void sig_quit(int); int main(void) { sigset_t newmask, oldmask, pendmask; if (signal(SIGQUIT, sig_quit) == SIG_ERR) err_sys("can't catch SIGQUIT"); /* * Block SIGQUIT and save current signal mask. */ sigemptyset(&newmask); sigaddset(&newmask, SIGQUIT); if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error"); sleep(5); /* SIGQUIT here will remain pending */ if (sigpending(&pendmask) < 0) err_sys("sigpending error"); if (sigismember(&pendmask, SIGQUIT)) printf("nSIGQUIT pendingn"); /* * Reset signal mask which unblocks SIGQUIT. */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error"); printf("SIGQUIT unblockedn"); sleep(5); exit(0); /* SIGQUIT here will terminate with core file */ } static void sig_quit(int signo) { printf("caught SIGQUITn"); if (signal(SIGQUIT, SIG_DFL) == SIG_ERR) err_sys("can't reset SIGQUIT"); } USP TUTORIALS Page 27
  • 28. 11. An implementation of signal using sigaction #include "apue.h" /* Reliable version of signal(), using POSIX sigaction(). */ Sigfunc *signal(int signo, Sigfunc *func) { struct sigaction act, oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; if (signo == SIGALRM) { #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; #endif } else { #ifdef SA_RESTART act.sa_flags |= SA_RESTART; #endif } if (sigaction(signo, &act, &oact) < 0) return(SIG_ERR); return(oact.sa_handler); } 12. The signal_intr function #include "apue.h" Sigfunc *signal_intr(int signo, Sigfunc *func) { struct sigaction act, oact; act.sa_handler = func; sigemptyset(&act.sa_mask); USP TUTORIALS Page 28
  • 29. act.sa_flags = 0; #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; #endif if (sigaction(signo, &act, &oact) < 0) return(SIG_ERR); return(oact.sa_handler); } 13. Example of signal masks, sigsetjmp, and siglongjmp #include "apue.h" #include <setjmp.h> #include <time.h> static void sig_usr1(int), sig_alrm(int); static sigjmp_buf jmpbuf; static volatile sig_atomic_t canjump; sig_usr1(int), sig_alrm(int); int main(void) { if (signal(SIGUSR1, sig_usr1) == SIG_ERR) err_sys("signal(SIGUSR1) error"); if (signal(SIGALRM, sig_alrm) == SIG_ERR) err_sys("signal(SIGALRM) error"); pr_mask("starting main: "); /* Figure 10.14 */ if (sigsetjmp(jmpbuf, 1)) { pr_mask("ending main: "); exit(0); } canjump = 1; /* now sigsetjmp() is OK */ for ( ; ; ) pause(); } static void sig_usr1(int signo) USP TUTORIALS Page 29
  • 30. { time_t starttime; if (canjump == 0) return; /* unexpected signal, ignore */ pr_mask("starting sig_usr1: "); alarm(3); /* SIGALRM in 3 seconds */ starttime = time(NULL); for ( ; ; ) /* busy wait for 5 seconds */ if (time(NULL) > starttime + 5) break; pr_mask("finishing sig_usr1: "); canjump = 0; siglongjmp(jmpbuf, 1); } static void sig_alrm(int signo) { /* jump back to main, don't return */ pr_mask("in sig_alrm: "); } 14. Protecting a critical region from a signal #include "apue.h" static void sig_int(int); int main(void) { sigset_t newmask, oldmask, waitmask; pr_mask("program start: "); if (signal(SIGINT, sig_int) == SIG_ERR) err_sys("signal(SIGINT) error"); sigemptyset(&waitmask); sigaddset(&waitmask, SIGUSR1); sigemptyset(&newmask); sigaddset(&newmask, SIGINT); /* USP TUTORIALS Page 30
  • 31. * Block SIGINT and save current signal mask. */ if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error"); /* * Critical region of code. */ pr_mask("in critical region: "); /* * Pause, allowing all signals except SIGUSR1. */ if (sigsuspend(&waitmask) != -1) err_sys("sigsuspend error"); pr_mask("after return from sigsuspend: "); /* * Reset signal mask which unblocks SIGINT. */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error"); /* * And continue processing ... */ pr_mask("program exit: "); exit(0); } static void sig_int(int signo) { pr_mask("nin sig_int: "); } 15. Using sigsuspend to wait for a global variable to be set #include "apue.h" volatile sig_atomic_t quitflag; static void sig_int(int signo) /* set nonzero by signal handler */ /* one signal handler for SIGINT and SIGQUIT */ USP TUTORIALS Page 31
  • 32. { if (signo == SIGINT) printf("ninterruptn"); else if (signo == SIGQUIT) quitflag = 1; /* set flag for main loop */ } int main(void) { sigset_t newmask, oldmask, zeromask; if (signal(SIGINT, sig_int) == SIG_ERR) err_sys("signal(SIGINT) error"); if (signal(SIGQUIT, sig_int) == SIG_ERR) err_sys("signal(SIGQUIT) error"); sigemptyset(&zeromask); sigemptyset(&newmask); sigaddset(&newmask, SIGQUIT); /* * Block SIGQUIT and save current signal mask.*/ if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error"); while (quitflag == 0) sigsuspend(&zeromask); /* * SIGQUIT has been caught and is now blocked; do whatever.*/ quitflag = 0; /* * Reset signal mask which unblocks SIGQUIT. */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error"); exit(0); } 16. Routines to allow a parent and child to synchronize #include "apue.h" static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */ static sigset_t newmask, oldmask, zeromask; static void sig_usr(int signo) { USP TUTORIALS Page 32
  • 33. sigflag = 1; } /* one signal handler for SIGUSR1 and SIGUSR2 */ void TELL_WAIT(void) { if (signal(SIGUSR1, sig_usr) == SIG_ERR) err_sys("signal(SIGUSR1) error"); if (signal(SIGUSR2, sig_usr) == SIG_ERR) err_sys("signal(SIGUSR2) error"); sigemptyset(&zeromask); sigemptyset(&newmask); sigaddset(&newmask, SIGUSR1); sigaddset(&newmask, SIGUSR2); /* * Block SIGUSR1 and SIGUSR2, and save current signal mask. */ if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) err_sys("SIG_BLOCK error"); } void TELL_PARENT(pid_t pid) { kill(pid, SIGUSR2); } void /* tell parent we're done */ WAIT_PARENT(void) { while (sigflag == 0) sigsuspend(&zeromask); sigflag = 0; /* and wait for parent */ /* * Reset signal mask to original value. */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error"); } void TELL_CHILD(pid_t pid) USP TUTORIALS Page 33
  • 34. { kill(pid, SIGUSR1); } /* tell child we're done */ void WAIT_CHILD(void) { while (sigflag == 0) sigsuspend(&zeromask); sigflag = 0; /* and wait for child */ /* * Reset signal mask to original value. */ if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) err_sys("SIG_SETMASK error"); } 17. Implementation of POSIX.1 abort #include<signal.h> #include<stdio.h> #include<stdlib.h> #include<unistd.h> void abort(void) /* POSIX-style abort() function */ { sigset_t mask; struct sigaction action; /* * Caller can't ignore SIGABRT, if so reset to default. */ sigaction(SIGABRT, NULL, &action); if (action.sa_handler == SIG_IGN) { action.sa_handler = SIG_DFL; sigaction(SIGABRT, &action, NULL); USP TUTORIALS Page 34
  • 35. } if (action.sa_handler == SIG_DFL) fflush(NULL); /* flush all open stdio streams */ /* * Caller can't block SIGABRT; make sure it's unblocked. */ sigfillset(&mask); sigdelset(&mask, SIGABRT); /* mask has only SIGABRT turned off */ sigprocmask(SIG_SETMASK, &mask, NULL); kill(getpid(), SIGABRT); /* send the signal */ /* * If we're here, process caught SIGABRT and returned. */ fflush(NULL); /* flush all open stdio streams */ action.sa_handler = SIG_DFL; sigaction(SIGABRT, &action, NULL); /* reset to default */ sigprocmask(SIG_SETMASK, &mask, NULL); /* just in case ... */ kill(getpid(), SIGABRT); /* and one more time */ exit(1); /* this should never be executed ... */ } 18. Using system to invoke the ed editor #include "apue.h" static void sig_int(int signo) { printf("caught SIGINTn"); } static void sig_chld(int signo) { USP TUTORIALS Page 35
  • 36. printf("caught SIGCHLDn"); } int main(void) { if (signal(SIGINT, sig_int) == SIG_ERR) err_sys("signal(SIGINT) error"); if (signal(SIGCHLD, sig_chld) == SIG_ERR) err_sys("signal(SIGCHLD) error"); if (system("/bin/ed") < 0) err_sys("system() error"); exit(0); } 19. Correct POSIX.1 implementation of system function #include<sys/wait.h> #include<errno.h> #include<signal.h> #include<unistd.h> int system(const char *cmdstring) /* with appropriate signal handling */ { pid_t pid; int status; struct sigaction ignore, saveintr, savequit; sigset_t chldmask, savemask; if (cmdstring == NULL) return(1); /* always a command processor with UNIX */ ignore.sa_handler = SIG_IGN; sigemptyset(&ignore.sa_mask); ignore.sa_flags = 0; /* ignore SIGINT and SIGQUIT */ if (sigaction(SIGINT, &ignore, &saveintr) < 0) return(-1); if (sigaction(SIGQUIT, &ignore, &savequit) < 0) return(-1); sigemptyset(&chldmask); /* now block SIGCHLD */ sigaddset(&chldmask, SIGCHLD); USP TUTORIALS Page 36
  • 37. if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0) return(-1); if ((pid = fork()) < 0) { status = -1; /* probably out of processes */ } else if (pid == 0) { /* child */ /* restore previous signal actions & reset signal mask */ sigaction(SIGINT, &saveintr, NULL); sigaction(SIGQUIT, &savequit, NULL); sigprocmask(SIG_SETMASK, &savemask, NULL); execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); _exit(127); /* exec error */ } else { /* parent */ while (waitpid(pid, &status, 0) < 0) if (errno != EINTR) { status = -1; /* error other than EINTR from waitpid() */ break; } } /* restore previous signal actions & reset signal mask */ if (sigaction(SIGINT, &saveintr, NULL) < 0) return(-1); if (sigaction(SIGQUIT, &savequit, NULL) < 0) return(-1); if (sigprocmask(SIG_SETMASK, &savemask, NULL) < 0) return(-1); return(status); } USP TUTORIALS Page 37
  • 38. 20. Reliable implementation of sleep #include "apue.h" static void sig_alrm(int signo) { /* nothing to do, just returning wakes up sigsuspend() */ } unsigned int sleep(unsigned int nsecs) { struct sigaction newact, oldact; sigset_t newmask, oldmask, suspmask; unsigned int unslept; /* set our handler, save previous information */ newact.sa_handler = sig_alrm; sigemptyset(&newact.sa_mask); newact.sa_flags = 0; sigaction(SIGALRM, &newact, &oldact); /* block SIGALRM and save current signal mask */ sigemptyset(&newmask); sigaddset(&newmask, SIGALRM); sigprocmask(SIG_BLOCK, &newmask, &oldmask); alarm(nsecs); suspmask = oldmask; /* make sure SIGALRM isn't blocked */ sigdelset(&suspmask, SIGALRM); /* wait for any signal to be caught */ sigsuspend(&suspmask); /* some signal has been caught, SIGALRM is now blocked */ unslept = alarm(0); sigaction(SIGALRM, &oldact, NULL); /* reset previous action */ /* reset signal mask, which unblocks SIGALRM */ sigprocmask(SIG_SETMASK, &oldmask, NULL); return(unslept); } USP TUTORIALS Page 38
  • 39. 21. How to handle SIGTSTP #include "apue.h" #define BUFFSIZE 1024 static void sig_tstp(int); int main(void) { int n; char buf[BUFFSIZE]; /* * Only catch SIGTSTP if we're running with a job-control shell. */ if (signal(SIGTSTP, SIG_IGN) == SIG_DFL) signal(SIGTSTP, sig_tstp); while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) if (write(STDOUT_FILENO, buf, n) != n) err_sys("write error"); if (n < 0) err_sys("read error"); exit(0); } static void sig_tstp(int signo) /* signal handler for SIGTSTP */ { sigset_t mask; /* ... move cursor to lower left corner, reset tty mode ... */ /* * Unblock SIGTSTP, since it's blocked while we're handling it. */ sigemptyset(&mask); sigaddset(&mask, SIGTSTP); sigprocmask(SIG_UNBLOCK, &mask, NULL); signal(SIGTSTP, SIG_DFL); /* reset disposition to default */ kill(getpid(), SIGTSTP); /* and send the signal to ourself */ /* we won't return from the kill until we're continued */ signal(SIGTSTP, sig_tstp); /* reestablish signal handler */ } USP TUTORIALS Page 39
  • 40. DAEMON PROCESSES 22. Initialize a daemon process #include"apue.h" #include<syslog.h> #include<fcntl.h> #include<sys/resource.h> void daemonize(const char *cmd) { int i, fd0, fd1, fd2; pid_t pid; struct rlimit rl; struct sigaction sa; /* * Clear file creation mask. */ umask(0); /* * Get maximum number of file descriptors. */ if (getrlimit(RLIMIT_NOFILE, &rl) < 0) err_quit("%s: can't get file limit", cmd); /* * Become a session leader to lose controlling TTY. */ if ((pid = fork()) < 0) err_quit("%s: can't fork", cmd); else if (pid != 0) /* parent */ exit(0); setsid(); /* * Ensure future opens won't allocate controlling TTYs. */ sa.sa_handler = SIG_IGN; USP TUTORIALS Page 40
  • 41. sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGHUP, &sa, NULL) < 0) err_quit("%s: can't ignore SIGHUP"); if ((pid = fork()) < 0) err_quit("%s: can't fork", cmd); else if (pid != 0) /* parent */ exit(0); /* * Change the current working directory to the root so * we won't prevent file systems from being unmounted. */ if (chdir("/") < 0) err_quit("%s: can't change directory to /"); /* * Close all open file descriptors. */ if (rl.rlim_max == RLIM_INFINITY) rl.rlim_max = 1024; for (i = 0; i < rl.rlim_max; i++) close(i); /* * Attach file descriptors 0, 1, and 2 to /dev/null. */ fd0 = open("/dev/null", O_RDWR); fd1 = dup(0); fd2 = dup(0); /* * Initialize the log file. */ openlog(cmd, LOG_CONS, LOG_DAEMON); if (fd0 != 0 || fd1 != 1 || fd2 != 2) { syslog(LOG_ERR, "unexpected file descriptors %d %d %d",fd0, fd1, fd2); exit(1); } } USP TUTORIALS Page 41
  • 42. 23. Ensure that only one copy of a daemon is running #include<unistd.h> #include<stdlib.h> #include<fcntl.h> #include<syslog.h> #include<errno.h> #include<stdio.h> #include<sys/stat.h> #include<string.h> #define LOCKFILE "/var/run/daemon.pid" #define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) extern int lockfile(int); int already_running(void) { int fd; char buf[16]; fd = open(LOCKFILE, O_RDWR|O_CREAT, LOCKMODE); if (fd < 0) { syslog(LOG_ERR, "can't open %s: %s", LOCKFILE, strerror(errno)); exit(1); } if (lockfile(fd) < 0) { if (errno == EACCES || errno == EAGAIN) { close(fd); return(1); } syslog(LOG_ERR, "can't lock %s: %s", LOCKFILE, strerror(errno)); exit(1); } ftruncate(fd, 0); USP TUTORIALS Page 42
  • 43. sprintf(buf, "%ld", (long)getpid()); write(fd, buf, strlen(buf)+1); return(0); } 24. Daemon rereading configuration files #include "apue.h" #include <pthread.h> #include <syslog.h> sigset_t mask; extern int already_running(void); void reread(void) { /* ... */ } void *thr_fn(void *arg) { int err, signo; for (;;) { err = sigwait(&mask, &signo); if (err != 0) { syslog(LOG_ERR, "sigwait failed"); exit(1); } switch (signo) { case SIGHUP: syslog(LOG_INFO, "Re-reading configuration file"); reread(); break; case SIGTERM: syslog(LOG_INFO, "got SIGTERM; exiting"); USP TUTORIALS Page 43
  • 44. exit(0); default: syslog(LOG_INFO, "unexpected signal %dn", signo); } } return(0); } int main(int argc, char *argv[]) { int err; pthread_t tid; char *cmd; struct sigaction sa; if ((cmd = strrchr(argv[0], '/')) == NULL) cmd = argv[0]; else cmd++; /* * Become a daemon. */ daemonize(cmd); /* * Make sure only one copy of the daemon is running. */ if (already_running()) { syslog(LOG_ERR, "daemon already running"); exit(1); } /* * Restore SIGHUP default and block all signals. */ sa.sa_handler = SIG_DFL; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGHUP, &sa, NULL) < 0) err_quit("%s: can't restore SIGHUP default"); sigfillset(&mask); USP TUTORIALS Page 44
  • 45. if ((err = pthread_sigmask(SIG_BLOCK, &mask, NULL)) != 0) err_exit(err, "SIG_BLOCK error"); /* * Create a thread to handle SIGHUP and SIGTERM. */ err = pthread_create(&tid, NULL, thr_fn, 0); if (err != 0) err_exit(err, "can't create thread"); /* * Proceed with the rest of the daemon. */ /* ... */ exit(0); } 24. Alternate implementation of daemon rereading configuration files #include "apue.h" #include <syslog.h> #include <errno.h> extern int lockfile(int); extern int already_running(void); void reread(void) { /* ... */ } void sigterm(int signo) { syslog(LOG_INFO, "got SIGTERM; exiting"); exit(0); } void sighup(int signo) { syslog(LOG_INFO, "Re-reading configuration file"); reread(); } USP TUTORIALS Page 45
  • 46. int main(int argc, char *argv[]) { char *cmd; struct sigaction sa; if ((cmd = strrchr(argv[0], '/')) == NULL) cmd = argv[0]; else cmd++; /* * Become a daemon. */ daemonize(cmd); /* * Make sure only one copy of the daemon is running. */ if (already_running()) { syslog(LOG_ERR, "daemon already running"); exit(1); } /* * Handle signals of interest. */ sa.sa_handler = sigterm; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGHUP); sa.sa_flags = 0; if (sigaction(SIGTERM, &sa, NULL) < 0) { syslog(LOG_ERR, "can't catch SIGTERM: %s", strerror(errno)); exit(1); } sa.sa_handler = sighup; sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGTERM); USP TUTORIALS Page 46
  • 47. sa.sa_flags = 0; if (sigaction(SIGHUP, &sa, NULL) < 0) { syslog(LOG_ERR, "can't catch SIGHUP: %s", strerror(errno)); exit(1); } /* * Proceed with the rest of the daemon. */ /* ... */ exit(0); } USP TUTORIALS Page 47