Bokens exempelprogram

This commit is contained in:
Jack-Benny Persson 2019-03-29 05:43:54 +01:00
commit 9fd3ac4a26
10 changed files with 719 additions and 0 deletions

60
daemon-ex1.c Normal file
View File

@ -0,0 +1,60 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
int main(void)
{
pid_t process_id = 0;
pid_t sid = 0;
/* Skapa barn/child process */
process_id = fork();
/* Hantera eventuellt fel vid fork() */
if (process_id < 0)
{
fprintf(stderr, "fork failed!\n");
exit(1);
}
/* Förälderprocessen/parent process.
Avsluta den eftersom allt arbete kommer att
utföras av demonen. Skriv också ut demonens PID */
else if (process_id > 0)
{
printf("Daemon process: %d \n", process_id);
exit(0);
}
/* Sätt umask till 000 så att alla kan komma eventuella
filer skapade av demonen. Anpassas efter vad demonen
ska användas till */
umask(0);
/* Starta en ny session */
sid = setsid();
if(sid < 0)
{
/* Avsluta ifall det inte gick att skapa en ny
session */
fprintf(stderr, "Failure to set new session\n");
exit(1);
}
/* Ändra aktuell katalog till / */
chdir("/");
/* Stäng stdin, stdout och stderr. Dessa behövs inte
i en demonprocess */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
/* Här börjar demonens arbete... */
for(;;)
{
sleep(5);
}
}

96
daemon-sig-ex1.c Normal file
View File

@ -0,0 +1,96 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <signal.h>
#include <syslog.h>
void sigHandler(int sig);
int main(void)
{
pid_t process_id = 0;
pid_t sid = 0;
FILE *fp;
char pidfile[] = "/tmp/daemon-sig-ex.pid";
/* Skapa barn/child process */
process_id = fork();
/* Hantera eventuellt fel vid fork() */
if (process_id < 0)
{
fprintf(stderr, "fork misslyckades!\n");
exit(1);
}
/* Förälderprocessen/parent process.
Avsluta den eftersom allt arbete kommer att
utföras av demonen. Skriv också ut demonens PID */
else if (process_id > 0)
{
printf("Demonens PID: %d \n", process_id);
fp = fopen(pidfile, "w");
fprintf(fp, "%d", process_id);
fclose(fp);
exit(0);
}
/* Sätt umask till 000 så att alla kan komma eventuella
filer skapade av demonen. Anpassas efter vad demonen
ska användas till */
umask(0);
/* Starta en ny session */
sid = setsid();
if(sid < 0)
{
/* Avsluta ifall det inte gick att skapa en ny
session */
fprintf(stderr, "Misslyckades att skapa en ny session\n");
exit(1);
}
/* Ändra aktuell katalog till / */
chdir("/");
/* Stäng stdin, stdout och stderr. Dessa behövs inte
i en demonprocess */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
/* Registrera signalhanterarna, en för varje signal
som vi vill fånga upp */
signal(SIGUSR1, sigHandler);
signal(SIGTERM, sigHandler);
/* Demonens arbete... */
for(;;)
{
sleep(5);
}
return 0;
}
void sigHandler(int sig)
{
if (sig == SIGUSR1)
{
/* Skriv till syslog-demonen */
syslog(LOG_DAEMON, "Tog emot SIGUSR1");
}
else if (sig == SIGTERM)
{
/* Samma som ovan */
syslog(LOG_DAEMON, "Tog emot SIGTERM");
}
else
{
syslog(LOG_DAEMON, "Någonting hände med demonen...");
}
/* Signalhanteraren återställs efter första signalen,
vi måste därför sätta den igen */
signal(sig, sigHandler);
}

110
daemon-sig-ex2.c Normal file
View File

@ -0,0 +1,110 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <signal.h>
#include <syslog.h>
char pidfile[] = "/tmp/daemon-sig-ex.pid";
void sigHandler(int sig);
void shutDown(int sig);
int main(void)
{
pid_t process_id = 0;
pid_t sid = 0;
FILE *fp;
/* Skapa barn/child process */
process_id = fork();
/* Hantera eventuellt fel vid fork() */
if (process_id < 0)
{
fprintf(stderr, "fork misslyckades!\n");
exit(1);
}
/* Förälderprocessen/parent process.
Avsluta den eftersom allt arbete kommer att
utföras av demonen. Skriv också ut demonens PID */
else if (process_id > 0)
{
printf("Demonens PID: %d \n", process_id);
fp = fopen(pidfile, "w");
fprintf(fp, "%d", process_id);
fclose(fp);
exit(0);
}
/* Sätt umask till 000 så att alla kan komma eventuella
filer skapade av demonen. Anpassas efter vad demonen
ska användas till */
umask(0);
/* Starta en ny session */
sid = setsid();
if(sid < 0)
{
/* Avsluta ifall det inte gick att skapa en ny
session */
fprintf(stderr, "Misslyckades att skapa en ny session\n");
exit(1);
}
/* Ändra aktuell katalog till / */
chdir("/");
/* Stäng stdin, stdout och stderr. Dessa behövs inte
i en demonprocess */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
/* Registrera signalhanterarna, en för varje signal
som vi vill fånga upp */
signal(SIGUSR1, sigHandler);
signal(SIGTERM, sigHandler);
signal(SIGABRT, shutDown);
signal(SIGQUIT, shutDown);
signal(SIGINT, shutDown);
/* Demonens arbete... */
for(;;)
{
sleep(5);
}
return 0;
}
void sigHandler(int sig)
{
if (sig == SIGUSR1)
{
/* Skriv till syslog-demonen */
syslog(LOG_DAEMON, "Tog emot SIGUSR1");
}
else if (sig == SIGTERM)
{
/* Samma som ovan */
syslog(LOG_DAEMON, "Tog emot SIGTERM");
}
else
{
syslog(LOG_DAEMON, "Någonting hände med demonen...");
}
/* Signalhanteraren återställs efter första signalen,
vi måste därför sätta den igen */
signal(sig, sigHandler);
}
void shutDown(int sig)
{
syslog(LOG_DAEMON, "Demonens avslutas");
/* Ta bort PID-filen efter oss */
if ( unlink(pidfile) == -1 )
syslog(LOG_DAEMON, "Kunde inte ta bort PID-filen");
exit(0);
}

74
fifo-ex1.c Normal file
View File

@ -0,0 +1,74 @@
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <stdlib.h>
#define FIFONAM "/tmp/testfifo"
/* Skapa fifofd i det globala scopet så att
vi kan stänga den ifrån signalhanteraren. */
int fifofd;
void cleanUp(int signum);
int main(void)
{
char msg[] = "Ett meddelande till klienterna\n";
/* Registrera signalhanterare för vanliga "avsluts-signaler" */
signal(SIGINT, cleanUp);
signal(SIGQUIT, cleanUp);
signal(SIGABRT, cleanUp);
signal(SIGTERM, cleanUp);
/* Skapa FIFOn. S_IWUSR och S_IRUSR är detsamma som för
open() och creat() */
if ( mkfifo(FIFONAM, S_IWUSR | S_IRUSR) != 0)
{
if (errno == EEXIST)
{
fprintf(stderr, "FIFOn finns redan, använder den\n");
}
else
{
perror("mkfifo");
return 1;
}
}
/* Kör i en oändlig loop */
while(1)
{
fifofd = open(FIFONAM, O_WRONLY);
if (fifofd < 0)
{
perror("open");
return 1;
}
write(fifofd, msg, sizeof(msg));
sleep(1); /* Vänta en sekund mellan varje körning */
}
/* Hit bör vi aldrig komma, men fall i fall så städar vi upp */
unlink(FIFONAM);
close(fifofd);
return 0;
}
void cleanUp(int signum)
{
/* Ständ fildeskriptorn */
if ( close(fifofd) == -1 )
perror("cleanUp - close");
/* Radera FIFO-filen från systemet & avsluta programmet */
if ( unlink(FIFONAM) == -1 )
{
perror("cleanUp - unlink");
exit(1);
}
exit(0);
}

45
my-msg-recv-rm.c Normal file
View File

@ -0,0 +1,45 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#define MAX 100
int main(void)
{
/* Struktur som krävs av msgsnd & msgrcv */
struct msgbuf
{
long mtype;
char mtext[MAX];
};
int id;
key_t key = 12345;
struct msgbuf msg;
msg.mtext[0] = '\0';
/* Kalla msgget för att få ett ID-nummer till kön.
Observera att vi här utelämnar IPC_CREAT. */
if ( (id = msgget(key, 0660)) < 0 )
{
fprintf(stderr, "Could not open message queue\n");
perror("msgget");
return 1;
}
/* Ta emot meddelandet och spara det i msg */
if ( msgrcv(id, &msg, MAX, 1, 0) < 0 )
{
fprintf(stderr, "Could not receive messages\n");
perror("msgrcv");
return 1;
}
/* Skriv ut meddelandet */
printf("%s\n", msg.mtext);
msgctl(id, IPC_RMID, 0);
return 0;
}

45
my-msg-recv.c Normal file
View File

@ -0,0 +1,45 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#define MAX 100
int main(void)
{
/* Struktur som krävs av msgsnd & msgrcv */
struct msgbuf
{
long mtype;
char mtext[MAX];
};
int id;
key_t key = 12345;
struct msgbuf msg;
msg.mtext[0] = '\0';
/* Kalla msgget för att få ett ID-nummer till kön.
Observera att vi här utelämnar IPC_CREAT. */
if ( (id = msgget(key, 0660)) < 0 )
{
fprintf(stderr, "Could not open message queue\n");
perror("msgget");
return 1;
}
/* Ta emot meddelandet och spara det i msg */
if ( msgrcv(id, &msg, MAX, 1, 0) < 0 )
{
fprintf(stderr, "Could not receive messages\n");
perror("msgrcv");
return 1;
}
/* Skriv ut meddelandet */
printf("%s\n", msg.mtext);
return 0;
}

53
my-msg-send.c Normal file
View File

@ -0,0 +1,53 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#define MAX 100
int main(void)
{
/* Struktur som krävs av msgsnd & msgrcv */
struct msgbuf
{
long mtype;
char mtext[MAX];
};
/* Variabler vi behöver */
int id;
key_t key = 12345;
struct msgbuf msg;
size_t msglen;
msg.mtext[0] = '\0';
/* Kalla msgget för att få ett ID-nummer till kön.
IPC_CREAT är flaggan för att skapa en . 0660
är rättigheterna för kön */
if ( (id = msgget(key, IPC_CREAT | 0660)) < 0 )
{
fprintf(stderr, "Could not create message queue\n");
perror("msgget");
return 1;
}
/* Komponera ett testmeddelande. mtype är till för att
identifiera just detta meddelandet i kön. mtext är
det faktiska innehållet och msglen är längden
meddelandet */
msg.mtype = 1;
strcat(msg.mtext, "Hejsan svejsan");
msglen = strlen(msg.mtext) + 1;
/* Skicka meddelandet */
if ( msgsnd(id, &msg, msglen, IPC_NOWAIT) < 0 )
{
fprintf(stderr, "Could not send message\n");
perror("msgsend");
return 1;
}
return 0;
}

61
sig-client.c Normal file
View File

@ -0,0 +1,61 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <signal.h>
#include <getopt.h>
#include <sys/types.h>
void printUsage(char *arg);
int main(int argc, char* argv[])
{
FILE *fp;
int opt;
pid_t process_id;
char pidfile[] = "/tmp/daemon-sig-ex.pid";
/* Kontrollera ifall PID-filen finns */
if ( (fp = fopen(pidfile, "r")) == 0 )
{
fprintf(stderr, "Ingen PID-fil, körs verkligen demonen?\n");
return 1;
}
/* Läs in PID till process_id variabeln */
fscanf(fp, "%d", &process_id);
/* Om inga argument angavs, skriv ut demonens PID */
if (argc == 1)
printf("Demonen körs med PID: %d\n", process_id);
/* Behandla argument till programmet */
while ((opt = getopt(argc, argv, "utqh")) != -1)
{
switch (opt)
{
case 'u':
kill(process_id, SIGUSR1);
break;
case 't':
kill(process_id, SIGTERM);
break;
case 'q':
kill(process_id, SIGQUIT);
break;
case 'h':
printUsage(argv[0]);
return 0;
default:
printUsage(argv[0]);
return 1;
}
}
return 0;
}
void printUsage(char *arg)
{
fprintf(stderr, "Usage: %s [-u] [-t] [-q] [-h]\n"
"-u = send SIGUSR1 to daemon\n"
"-t = send SIGTERM to daemon\n"
"-q = send SIGQUIT to quit the daemon\n"
"-h = display help\n", arg);
}

100
simple-ls-ver1.c Normal file
View File

@ -0,0 +1,100 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
void printUsage(char *arg);
int main(int argc, char **argv)
{
int typ;
char opt[5] = { 0 };
/* Skapa pekare och struct */
DIR *d;
struct dirent *dir;
struct stat s;
/* Läs in aktuell katalog */
d = opendir(".");
/* Om 'd' INTE är sant (! = inte sant) */
if (!d)
{
printf("Kan inte läsa aktuell katalog\n");
return 1;
}
/* Behandla arugment */
if (argc == 1)
{
strncpy(opt, "-a", 2);
}
else if (argc == 2)
{
strncpy(opt, argv[1], 2);
/* Hjälptext */
if ( strcmp(opt, "-h") == 0 )
printUsage(argv[0]);
/* Visa endast filer */
else if ( strcmp(opt, "-f") == 0 )
{
typ = S_IFREG;
}
/* Visa endast kataloger */
else if ( strcmp(opt, "-d") == 0 )
{
typ = S_IFDIR;
}
/* Visa alla filer */
else if ( strcmp(opt, "-a") == 0 )
{
;
}
/* Om vi angav ett felaktigt argument */
else
{
printUsage(argv[0]);
return 1;
}
}
/* Om vi angav fel antal argument */
else
{
printUsage(argv[0]);
return 1;
}
/* Skriv ut innehållet i katalogen */
while ((dir = readdir(d)) != NULL)
{
if ( strcmp(opt, "-a") == 0 )
{
printf("%s\n", dir->d_name);
}
else
{
stat(dir->d_name, &s);
/* Se kapitlet om 'Bitvisa operationer' */
if ((s.st_mode & S_IFMT) == typ)
printf("%s\n", dir->d_name);
}
}
/* Stäng "d" och returnera noll */
closedir(d);
return 0;
}
void printUsage(char *arg)
{
printf("Usage: %s [-a] [-f] [-d]\n"
" -a to list all types (default)\n"
" -f to list only files\n"
" -d to list only directories\n", arg);
}

75
simple-ls-ver2.c Normal file
View File

@ -0,0 +1,75 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
void printUsage(char *arg);
int main(int argc, char **argv)
{
int opt;
int typ = -1;
char *path = ".";
/* Skapa pekare och struct */
DIR *d;
struct dirent *dir;
struct stat s;
/* Behandla argument med getopt */
while ((opt = getopt(argc, argv, "hafdp:")) != -1)
{
switch (opt)
{
case 'a':
typ = -1;
break;
case 'f':
typ = S_IFREG;
break;
case 'd':
typ = S_IFDIR;
break;
case 'p':
path = optarg;
break;
case 'h':
printUsage(argv[0]);
return 0;
default:
printUsage(argv[0]);
return 1;
}
}
/* Byt katalog med chdir() för att stat() ska
se filerna i rätt katalog */
chdir(path);
d = opendir(path);
while ((dir = readdir(d)) != NULL)
{
if ( typ == -1 )
{
printf("%s\n", dir->d_name);
}
else
{
stat(dir->d_name, &s);
/* Se kapitlet om 'Bitvisa operationer' */
if ((s.st_mode & S_IFMT) == typ)
printf("%s\n", dir->d_name);
}
}
return 0;
}
void printUsage(char *arg)
{
printf("Usage: %s [-a] [-f] [-d] [-p path]\n"
" -a to list all types (default)\n"
" -f to list only files\n"
" -d to list only directories\n"
" -p to specify a directory\n", arg);
}