Published on


  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide


  1. 1. USP PROGRAMS UNIX AND ANSI STANDARDSPROG 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 8PROG 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:200809PROG3: To show test macros: #define _POSIX_SOURCE #define _POSIX_C_SOURCE 199309LUSP TUTORIALS Page 1
  2. 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,ThnxPROG 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. 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:1024Max path name:1025Chown_restricted for stdin:1PROG 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. 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 APIsProg 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. 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 dayProg 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. 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. 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. 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. 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. 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 whohas 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. 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. 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. 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. 14. Process Environment1. 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("ncant register my_exit2");if(atexit(my_exit1)!=0)printf("ncant register my_exit1");if(atexit(my_exit1)!=0)printf("ncant 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. 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 2jmp_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 Control1. 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. 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. 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. 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. 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 voidpr_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. 20. Process Relationships1. 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 were continued */ if (read(STDIN_FILENO, &c, 1) != 1) printf("read error from controlling TTY, errno = %dn", errno); exit(0); } }USP TUTORIALS Page 20
  21. 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 doesnt work : #include "apue.h" #include <sys/wait.h> static void sig_cld(int); int main()USP TUTORIALS Page 21
  22. 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. 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. 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. 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. 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. 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("cant 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("cant reset SIGQUIT");}USP TUTORIALS Page 27
  28. 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_INTERRUPTact.sa_flags |= SA_INTERRUPT;#endif}else{#ifdef SA_RESTARTact.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. 29. act.sa_flags = 0;#ifdef SA_INTERRUPTact.sa_flags |= SA_INTERRUPT;#endifif (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. 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, dont 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. 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. 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. 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 were 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. 34. {kill(pid, SIGUSR1);}/* tell child were 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 cant 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. 35. }if (action.sa_handler == SIG_DFL) fflush(NULL);/* flush all open stdio streams *//** Caller cant block SIGABRT; make sure its unblocked.*/sigfillset(&mask);sigdelset(&mask, SIGABRT); /* mask has only SIGABRT turned off */sigprocmask(SIG_SETMASK, &mask, NULL);kill(getpid(), SIGABRT);/* send the signal *//** If were 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. 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. 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. 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 isnt 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. 39. 21. How to handle SIGTSTP#include "apue.h"#define BUFFSIZE 1024static void sig_tstp(int);int main(void){int n;char buf[BUFFSIZE];/** Only catch SIGTSTP if were 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 its blocked while were 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 wont return from the kill until were continued */signal(SIGTSTP, sig_tstp);/* reestablish signal handler */}USP TUTORIALS Page 39
  40. 40. DAEMON PROCESSES22. 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: cant get file limit", cmd);/** Become a session leader to lose controlling TTY.*/if ((pid = fork()) < 0) err_quit("%s: cant fork", cmd);else if (pid != 0) /* parent */exit(0);setsid();/** Ensure future opens wont allocate controlling TTYs.*/sa.sa_handler = SIG_IGN;USP TUTORIALS Page 40
  41. 41. sigemptyset(&sa.sa_mask);sa.sa_flags = 0;if (sigaction(SIGHUP, &sa, NULL) < 0) err_quit("%s: cant ignore SIGHUP");if ((pid = fork()) < 0) err_quit("%s: cant fork", cmd);else if (pid != 0) /* parent */exit(0);/** Change the current working directory to the root so* we wont prevent file systems from being unmounted.*/if (chdir("/") < 0) err_quit("%s: cant 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. 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/"#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, "cant open %s: %s", LOCKFILE, strerror(errno));exit(1);}if (lockfile(fd) < 0){if (errno == EACCES || errno == EAGAIN){close(fd);return(1);}syslog(LOG_ERR, "cant lock %s: %s", LOCKFILE, strerror(errno));exit(1);}ftruncate(fd, 0);USP TUTORIALS Page 42
  43. 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. 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: cant restore SIGHUP default");sigfillset(&mask);USP TUTORIALS Page 44
  45. 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, "cant 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. 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, "cant 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. 47. sa.sa_flags = 0;if (sigaction(SIGHUP, &sa, NULL) < 0){syslog(LOG_ERR, "cant catch SIGHUP: %s", strerror(errno));exit(1);}/** Proceed with the rest of the daemon.*//* ... */exit(0);}USP TUTORIALS Page 47