Initial commit

This commit is contained in:
2021-10-01 20:24:05 +02:00
commit 860c025165
194 changed files with 4846 additions and 0 deletions

108
kapitel17/daemon-ex2.c Normal file
View File

@@ -0,0 +1,108 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <signal.h>
#include <syslog.h>
#include <fcntl.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);
}
/* Avsluta förälderprocessen */
else if (process_id > 0)
{
exit(1);
}
/* 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);
}
/* Gör en ny fork för att förhindra att demonen kan bli en
sessionsledare */
process_id = fork();
/* Hantera eventuellt fel vid fork() */
if (process_id < 0)
{
fprintf(stderr, "fork misslyckades!\n");
exit(1);
}
/* Avsluta föräldern den eftersom allt arbete kommer att
utföras av demonen. Skriv också demonens PID-fil */
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 022 (rw-r--r-- / rwx-r-xr-x) */
umask(022);
/* Ändra aktuell katalog till / */
chdir("/");
/* Stäng stdin, stdout och stderr och återöppna dem
till /dev/null */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
open("/dev/null", O_RDONLY); /* 0 = stdin */
open("/dev/null", O_WRONLY); /* 1 = stdout */
open("/dev/null", O_RDWR); /* 2 = stderr */
/* 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);
}

106
kapitel17/daemon-sig-ex1.c Normal file
View File

@@ -0,0 +1,106 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <signal.h>
#include <syslog.h>
#include <fcntl.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);
}
/* Avsluta förälderprocessen */
else if (process_id > 0)
{
exit(1);
}
/* 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);
}
/* Gör en ny fork för att förhindra att demonen kan bli en
sessionsledare */
process_id = fork();
/* Hantera eventuellt fel vid fork() */
if (process_id < 0)
{
fprintf(stderr, "fork misslyckades!\n");
exit(1);
}
/* Avsluta föräldern den eftersom allt arbete kommer att
utföras av demonen. Skriv också demonens PID-fil */
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 022 (rw-r--r-- / rwx-r-xr-x) */
umask(022);
/* Ändra aktuell katalog till / */
chdir("/");
/* Stäng stdin, stdout och stderr och återöppna dem
till /dev/null */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
open("/dev/null", O_RDONLY); /* 0 = stdin */
open("/dev/null", O_WRONLY); /* 1 = stdout */
open("/dev/null", O_RDWR); /* 2 = stderr */
/* 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);
}

125
kapitel17/daemon-sig-ex2.c Normal file
View File

@@ -0,0 +1,125 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <signal.h>
#include <syslog.h>
#include <fcntl.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);
}
/* Avsluta förälderprocessen */
else if (process_id > 0)
{
exit(1);
}
/* 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);
}
/* Gör en ny fork för att förhindra att demonen kan bli en
sessionsledare */
process_id = fork();
/* Hantera eventuellt fel vid fork() */
if (process_id < 0)
{
fprintf(stderr, "fork misslyckades!\n");
exit(1);
}
/* Avsluta föräldern den eftersom allt arbete kommer att
utföras av demonen. Skriv också demonens PID-fil */
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 022 (rw-r--r-- / rwx-r-xr-x) */
umask(022);
/* Ä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);
open("/dev/null", O_RDONLY); /* 0 = stdin */
open("/dev/null", O_WRONLY); /* 1 = stdout */
open("/dev/null", O_RDWR); /* 2 = stderr */
/* 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, "Demonen avslutas");
/* Ta bort PID-filen */
if ( unlink(pidfile) == -1 )
syslog(LOG_DAEMON, "Kunde inte ta bort PID-filen");
exit(0);
}

View File

@@ -0,0 +1,20 @@
#include <stdio.h>
#include <unistd.h>
#define FIFONAM "/tmp/testfifo"
int main(void)
{
FILE *fp;
signed char c;
if ( access(FIFONAM, R_OK) != 0 )
{
fprintf(stderr, "Problem att öppna %s\n", FIFONAM);
return 1;
}
fp = fopen(FIFONAM, "r");
while ((c = getc(fp)) != EOF)
putchar(c);
fclose(fp);
return 0;
}

79
kapitel17/fifo-ex1.c Normal file
View File

@@ -0,0 +1,79 @@
#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);
/* Ignorera SIGPIPE, annars avslutas programmet när
mottagaren stängs */
signal(SIGPIPE, SIG_IGN);
/* 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;
}
}
/* Öppna FIFOn */
fifofd = open(FIFONAM, O_WRONLY);
if (fifofd < 0)
{
perror("open");
return 1;
}
/* Skriv meddelanden i en oändlig loop */
while(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äng 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
kapitel17/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
kapitel17/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 kö. 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 på
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;
}

27
kapitel17/pipes-ex1.c Normal file
View File

@@ -0,0 +1,27 @@
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#define MAX 7
int main(void)
{
int pipefd[2];
pid_t pid;
char line[MAX];
pipe(pipefd);
pid = fork();
if (pid > 0)
{
close(pipefd[0]);
write(pipefd[1], "Hejsan", MAX);
}
else
{
close(pipefd[1]);
read(pipefd[0], line, MAX);
printf("%s\n", line);
}
return 0;
}

61
kapitel17/sig-client.c Normal file
View File

@@ -0,0 +1,61 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <signal.h>
#include <unistd.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);
}

View File

@@ -0,0 +1,48 @@
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#define MAXLEN 32
int main(void)
{
const char sockname[] = "/tmp/tidssocket";
int fd;
struct sockaddr_un addr;
char recvbuffer[MAXLEN];
/* skapa en socket fildeskriptor */
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if ( fd == -1 )
{
perror("Create socket failed");
return 1;
}
/* sätt adressfamiljen och socket-filen */
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, sockname);
/* anslut till servern */
if ( (connect(fd, (const struct sockaddr*) &addr,
sizeof(struct sockaddr_un))) == -1 )
{
perror("Can't connect");
fprintf(stderr, "The server is down?\n");
return 1;
}
/* läs tiden från servern */
if ( (read(fd, recvbuffer, MAXLEN)) == -1 )
{
perror("Can't read");
return 1;
}
printf("Server time is: %s", recvbuffer);
write(fd, "Thank you for the time", 23);
return 0;
}

View File

@@ -0,0 +1,87 @@
#define _XOPEN_SOURCE 700
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
#define MAXLEN 32
void cleanUp(int signum);
const char sockname[] = "/tmp/tidssocket";
int connfd;
int datafd;
int main(void)
{
struct sockaddr_un addr;
char buffer[MAXLEN];
char recvbuffer[MAXLEN];
time_t current_time;
struct tm *local_time;
/* registrera signalhanterarna */
signal(SIGTERM, cleanUp);
signal(SIGABRT, cleanUp);
signal(SIGQUIT, cleanUp);
signal(SIGINT, cleanUp);
/* skapa en socket fildeskriptor */
connfd = socket(AF_UNIX, SOCK_STREAM, 0);
if ( connfd == -1 )
{
perror("Create socket failed");
return 1;
}
/* sätt adressfamiljen till UNIX-socket */
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, sockname);
/* knyt ihop namnet och adressen och casta
sockaddr_un till sockaddr) */
if ( (bind(connfd, (const struct sockaddr*)&addr,
sizeof(struct sockaddr_un))) == -1 )
{
perror("Binding socket failed");
return 1;
}
/* lyssna efter anslutningar */
if ( (listen(connfd, 20)) == -1 )
{
perror("Listen error");
return 1;
}
/* acceptera anslutningen, skapa en ny data-fildeskriptor,
och skicka tiden till klienten */
while(1)
{
datafd = accept(connfd, NULL, NULL);
if (datafd == -1 )
{
perror("Accept error");
return 1;
}
printf("Client connected, sending time\n");
current_time = time(NULL);
local_time = localtime(&current_time);
strcpy(buffer, asctime(local_time));
write(datafd, buffer, MAXLEN);
read(datafd, recvbuffer, MAXLEN);
printf("Client respons: %s\n", recvbuffer);
close(datafd); /* stäng datafd efter varje anrop */
}
return 0; /* fall i fall */
}
void cleanUp(int signum)
{
printf("Quitting and cleaning up\n");
close(datafd);
close(connfd);
unlink(sockname);
exit(0);
}