Initial commit
This commit is contained in:
commit
860c025165
38
README.md
Normal file
38
README.md
Normal file
@ -0,0 +1,38 @@
|
||||
# C-programmering i Linux, macOS, BSD och Solaris (tredje utgåvan)
|
||||
Här finns du all exempelkod för tredje utgåvan av boken *C-programmering i
|
||||
Linux, macOS, BSD och Solaris* (ISBN: 978-91-983300-7-6).
|
||||
|
||||
Boken går att köpa från [CyberInfo Sverige](https://www.cyberinfo.se/bocker/),
|
||||
[Bokus](https://www.bokus.com/cgi-bin/product_search.cgi?publisher=CyberInfo%20Sverige)
|
||||
och
|
||||
[Adlibris](https://www.adlibris.com/se/sok?filter=publisher%3ACyberInfo%20Sverige)
|
||||
från och med hösten/vintern 2021.
|
||||
|
||||
Är du nyfiken på boken så titta gärna i [innehållsförteckningen](https://www.cyberinfo.se/dokument/c-prog_innehallsforteckning_3e_utg.html).
|
||||
|
||||
## Baksidetexten
|
||||
**C-programmering i Linux, macOS, BSD och Solaris** lär först ut grunderna i
|
||||
C-programmering så att vi har en stabil grund att stå på. Denna del vänder sig
|
||||
mot de som är nya på C-programmering eller för de som behöver fräscha upp sina
|
||||
C-kunskaper. Därefter börjar vi att programmera alltmer mot Unixsystem med
|
||||
hjälp av bland annat systemanrop. Vi lär oss att skapa och använda demoner,
|
||||
standard input- och output, filrättigheter, FIFO, processhantering, make-filer,
|
||||
meddelandeköer med mera. Vi får också lära oss hur man kopplar samman flera
|
||||
program med hjälp av rörledningar och skalskript. Mot slutet av boken tittar vi
|
||||
på hur man använder felsökningsverktyg som GDB, LLDB och Valgrind.
|
||||
|
||||
Grundtanken med boken är att du som läsare bara ska behöva en enda bok för att
|
||||
komma igång att utveckla program och verktyg för Unixsystem. Boken är uppbyggd
|
||||
på devisen att lära genom exempel. I boken finns över 180 exempelprogram, både
|
||||
stora och små. Efter varje kapitel finns dessutom övningsuppgifter, så att du
|
||||
som läsare ska kunna arbeta med boken på egen hand.
|
||||
|
||||
I denna tredje utgåva har stora delar skrivits om för att göra boken mer
|
||||
lättläst, relevant och uppdaterad. Bland annat har kapitlet om IPC utökats till
|
||||
att även innefatta Unix-sockets. Ett helt kapitel om TCP/IP-programmering har
|
||||
också lagts till. En del förbättringar har också gjorts av exempelprogrammen i
|
||||
boken.
|
||||
|
||||
## Framsida
|
||||

|
BIN
c-prog-tredje-utg-framsida.png
Executable file
BIN
c-prog-tredje-utg-framsida.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 113 KiB |
16
kapitel10/loopa-pekaradresser.c
Normal file
16
kapitel10/loopa-pekaradresser.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include <stdio.h>
|
||||
#define SIZE 11
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
char namn[SIZE] = "Jack-Benny";
|
||||
printf("Adressen till 'namn': %p\n", (void*)&namn);
|
||||
|
||||
for (i=0; i<SIZE; i++)
|
||||
{
|
||||
printf("Element %i -> %p\n", i, (void*)&namn[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
18
kapitel10/pekararitmetik-ex1.c
Normal file
18
kapitel10/pekararitmetik-ex1.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include <stdio.h>
|
||||
#define LANGD 5
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
int x[LANGD] = {0, 1, 2, 3, 4};
|
||||
int *px;
|
||||
|
||||
px = x;
|
||||
|
||||
for (i = 0; i<LANGD; i++)
|
||||
{
|
||||
printf("%d: %p\n", *px, (void*)px);
|
||||
px = px + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
25
kapitel10/pekararitmetik.c
Normal file
25
kapitel10/pekararitmetik.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
char fnamn[] = "Jack-Benny";
|
||||
char *enamn = "Persson";
|
||||
|
||||
printf("Förnamn: %s\n", fnamn);
|
||||
printf("Efternamn: %s\n\n", enamn);
|
||||
|
||||
printf("Förnamn: %p %p\n", (void*)&fnamn, (void*)fnamn);
|
||||
printf("Efternamn: %p %p\n", (void*)&enamn, (void*)enamn);
|
||||
|
||||
/* Skriv ut ett tecken i taget med mellanslag mellan varje
|
||||
tecken. Detta görs genom att addera 1 till pekarvariabeln
|
||||
för varje iteration */
|
||||
for (i=0; i<=7; i++)
|
||||
{
|
||||
printf("%c ", *enamn);
|
||||
enamn = enamn + 1;
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
9
kapitel10/pekare-ex1.c
Normal file
9
kapitel10/pekare-ex1.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float pi = 3.14159;
|
||||
printf("Adressen till 'pi' är: %lu\n", &pi);
|
||||
|
||||
return 0;
|
||||
}
|
9
kapitel10/pekare-ex2.c
Normal file
9
kapitel10/pekare-ex2.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float pi = 3.14159;
|
||||
printf("Adressen till 'pi' är: %p\n", (void*)&pi);
|
||||
|
||||
return 0;
|
||||
}
|
10
kapitel10/pekare-till-falt.c
Normal file
10
kapitel10/pekare-till-falt.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <stdio.h>
|
||||
#define SIZE 11
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char namn[SIZE] = "Jack-Benny";
|
||||
printf("Adressen till 'namn': %p\n", (void*)&namn);
|
||||
|
||||
return 0;
|
||||
}
|
15
kapitel10/pekare-till-pekare-ex1.c
Normal file
15
kapitel10/pekare-till-pekare-ex1.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int x = 5;
|
||||
int *px;
|
||||
int **ppx;
|
||||
|
||||
px = &x;
|
||||
ppx = &px;
|
||||
|
||||
printf("%d\n", **ppx);
|
||||
|
||||
return 0;
|
||||
}
|
36
kapitel10/pekare-till-pekare-ex2.c
Normal file
36
kapitel10/pekare-till-pekare-ex2.c
Normal file
@ -0,0 +1,36 @@
|
||||
#include <stdio.h>
|
||||
#define LANGD 3
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
char *ord[LANGD];
|
||||
char *pc;
|
||||
char **ppc;
|
||||
|
||||
ord[0] = "hund";
|
||||
ord[1] = "katt";
|
||||
ord[2] = "kanin";
|
||||
|
||||
/* Skriv ut de tre strängarna */
|
||||
for (i = 0; i < LANGD; i++)
|
||||
{
|
||||
printf("%s\n", ord[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/* Skriv ut tecken för tecken */
|
||||
for (i = 0; i < LANGD; i++)
|
||||
{
|
||||
ppc = ord + i;
|
||||
pc = *ppc;
|
||||
while (*pc != '\0')
|
||||
{
|
||||
printf("%c ", *pc);
|
||||
pc = pc + 1;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
22
kapitel10/pekarvar-ex1.c
Normal file
22
kapitel10/pekarvar-ex1.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* Skapa vanliga variabler & fält */
|
||||
float pi = 3.14159;
|
||||
|
||||
/* Deklarera pekarna */
|
||||
float *ppi;
|
||||
|
||||
/* Sätt pekaren till adressen av variabeln */
|
||||
ppi = π
|
||||
|
||||
/* Skriv ut det som pekaren pekar på och dess innehåll */
|
||||
printf("Adressen till 'pi': %p\n", (void*)&pi);
|
||||
printf("'pi' innehåller: %.5f\n\n", pi);
|
||||
printf("Adressen till 'ppi': %p\n", (void*)&ppi);
|
||||
printf("'ppi' pekar på värdet: %.5f\n", *ppi);
|
||||
printf("'ppi' innehåller: %p\n", (void*)ppi);
|
||||
|
||||
return 0;
|
||||
}
|
15
kapitel10/pekarvar-ex2.c
Normal file
15
kapitel10/pekarvar-ex2.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char fnamn[] = "Jack-Benny";
|
||||
char *enamn = "Persson";
|
||||
|
||||
printf("Förnamn: %s\n", fnamn);
|
||||
printf("Efternamn: %s\n\n", enamn);
|
||||
|
||||
printf("Förnamn: %p %p\n", (void*)&fnamn, (void*)fnamn);
|
||||
printf("Efternamn: %p %p\n", (void*)&enamn, (void*)enamn);
|
||||
|
||||
return 0;
|
||||
}
|
23
kapitel10/pekarvar.c
Normal file
23
kapitel10/pekarvar.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include <stdio.h>
|
||||
#define SIZE 11
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* Skapa vanliga variabler & fält */
|
||||
float pi = 3.14159;
|
||||
char namn[SIZE] = "Jack-Benny";
|
||||
|
||||
/* Deklarera pekarna */
|
||||
float *ppi;
|
||||
char *pnamn;
|
||||
|
||||
/* Sätt pekarna till adressen av variablerna */
|
||||
ppi = π
|
||||
pnamn = &namn[5];
|
||||
|
||||
/* Skriv ut det som pekarna pekar på */
|
||||
printf("Pi = %.5f\n", *ppi);
|
||||
printf("Namn = %s\n", pnamn);
|
||||
|
||||
return 0;
|
||||
}
|
17
kapitel11/call-by-ref.c
Normal file
17
kapitel11/call-by-ref.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void inc(int *tal);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int x = 5;
|
||||
printf("x är nu: %d\n", x);
|
||||
inc(&x);
|
||||
printf("x är nu: %d\n", x);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void inc(int *tal)
|
||||
{
|
||||
*tal = *tal + 3;
|
||||
}
|
19
kapitel11/falt-arg-ex1.c
Normal file
19
kapitel11/falt-arg-ex1.c
Normal file
@ -0,0 +1,19 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void say(char *namn);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char namn01[] = "Kalle";
|
||||
char *namn02 = "Lisa";
|
||||
|
||||
say(namn01);
|
||||
say(namn02);
|
||||
say("Jack-Benny");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void say(char *namn)
|
||||
{
|
||||
printf("Hej %s, hur är läget?\n", namn);
|
||||
}
|
20
kapitel11/falt-arg-ex2.c
Normal file
20
kapitel11/falt-arg-ex2.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include <stdio.h>
|
||||
|
||||
float medel(int tal[], int antal);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int x[] = {40, 42, 39, 37, 28};
|
||||
printf("Medelvärdet är: %.1f\n", medel(x, 5));
|
||||
return 0;
|
||||
}
|
||||
|
||||
float medel(int tal[], int antal)
|
||||
{
|
||||
int i;
|
||||
int sum = 0;
|
||||
for (i = 0; i<antal; i++)
|
||||
sum = sum + tal[i];
|
||||
|
||||
return ((float)sum / antal);
|
||||
}
|
12
kapitel11/mainarg.c
Normal file
12
kapitel11/mainarg.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
printf("Du har angett %d st argument\n", argc);
|
||||
for (i = 0; i<argc; i++)
|
||||
{
|
||||
printf("Argument %d är: %s\n", i, argv[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
22
kapitel11/return-flt-ex1.c
Normal file
22
kapitel11/return-flt-ex1.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
char *say(char namn[]);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *mening = say("Jack-Benny");
|
||||
printf("%s\n", mening);
|
||||
free(mening);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *say(char namn[])
|
||||
{
|
||||
char *str;
|
||||
str = calloc(50, sizeof(char));
|
||||
strncat(str, "Hej ", 4);
|
||||
strncat(str, namn, 45);
|
||||
return str;
|
||||
}
|
18
kapitel11/return-flt-fail.c
Normal file
18
kapitel11/return-flt-fail.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
char *say(char namn[]);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("%s\n", say("Jack-Benny"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *say(char namn[])
|
||||
{
|
||||
char str[50] = { 0 };
|
||||
strncat(str, "Hej ", 4);
|
||||
strncat(str, namn, 45);
|
||||
return str;
|
||||
}
|
100
kapitel11/simple-ls-ver1.c
Normal file
100
kapitel11/simple-ls-ver1.c
Normal 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)
|
||||
{
|
||||
unsigned int typ;
|
||||
char opt[4] = { 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", 3);
|
||||
}
|
||||
else if (argc == 2)
|
||||
{
|
||||
strncpy(opt, argv[1], 3);
|
||||
|
||||
/* 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
kapitel11/simple-ls-ver2.c
Normal file
75
kapitel11/simple-ls-ver2.c
Normal 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;
|
||||
unsigned int typ = 0;
|
||||
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 == 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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
37
kapitel12/fildesc-ex1.c
Normal file
37
kapitel12/fildesc-ex1.c
Normal file
@ -0,0 +1,37 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int fd;
|
||||
int readstat;
|
||||
off_t filesize;
|
||||
struct stat fileinfo;
|
||||
char wbuf[] = "Hejsan svejsan\n";
|
||||
char rbuf[50];
|
||||
|
||||
/* Öppna filen "minfil" i läs- och skrivläge (O_RDWR).
|
||||
Skapa den om den inte redan finns (O_CREAT)
|
||||
Sätt filrättigheterna till 00644*/
|
||||
fd = open("minfil", O_CREAT|O_RDWR, 00644);
|
||||
write(fd, wbuf, sizeof(wbuf)); /* Skriv wbuf till filen */
|
||||
|
||||
/* Här börjar vi läsa in filen igen */
|
||||
fstat(fd, &fileinfo);
|
||||
filesize = fileinfo.st_size;
|
||||
printf("Storlek: %ld\n", (long int)filesize);
|
||||
/* Återställ markören till byte 0 med lseek */
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
readstat = read(fd, rbuf, filesize); /* Läs innehållet till rbuf */
|
||||
rbuf[fileinfo.st_size+1] = '\0'; /* Avsluta med NULL */
|
||||
|
||||
/* Skriv ut information och filens innehåll */
|
||||
printf("Fildeskriptorns nummer: %d\n", fd);
|
||||
printf("Returvärde från 'read': %d\n", readstat);
|
||||
printf("Inläst text: %s\n", rbuf);
|
||||
|
||||
return 0;
|
||||
}
|
43
kapitel12/fseek-ex1.c
Normal file
43
kapitel12/fseek-ex1.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int langd, bredd, hojd;
|
||||
signed char ch;
|
||||
int i;
|
||||
FILE *fp;
|
||||
|
||||
/* Kontrollera först om filen finns och om inte
|
||||
avsluta programmet och skriv ett felmeddelande */
|
||||
if ( (fp = fopen("konfigfil.txt", "r")) == 0)
|
||||
{
|
||||
printf("Filen finns inte!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Position innan läsning: %ld\n", ftell(fp));
|
||||
fscanf( fp, "längd: %d, bredd: %d, höjd: %d",
|
||||
&langd, &bredd, &hojd);
|
||||
|
||||
printf("Lådan har en volym på %d cm3\n",
|
||||
(langd * bredd * hojd));
|
||||
printf("Position efter läsning: %ld\n\n", ftell(fp));
|
||||
|
||||
printf("Läs tre byte från åttonde byten från starten:\n");
|
||||
fseek(fp, 8, SEEK_SET);
|
||||
for (i = 0; i<3; i++)
|
||||
{
|
||||
ch = fgetc(fp);
|
||||
putchar(ch);
|
||||
}
|
||||
printf("\nAktuell position: %ld\n\n", ftell(fp));
|
||||
|
||||
printf("Flyttar markören 5 bytes framåt och läser resten:\n");
|
||||
fseek(fp, 5, SEEK_CUR);
|
||||
printf("Aktuell position: %ld\n", ftell(fp));
|
||||
while ((ch = fgetc(fp)) != EOF)
|
||||
putchar(ch);
|
||||
printf("\nAktuell position: %ld\n\n", ftell(fp));
|
||||
|
||||
return 0;
|
||||
}
|
1
kapitel12/konfigfil.txt
Normal file
1
kapitel12/konfigfil.txt
Normal file
@ -0,0 +1 @@
|
||||
längd: 33, bredd: 20, höjd: 10
|
360
kapitel12/lagerhantering-komplett.c
Normal file
360
kapitel12/lagerhantering-komplett.c
Normal file
@ -0,0 +1,360 @@
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Makron */
|
||||
#define NAMEMAXLENGTH 30
|
||||
|
||||
/* Globala variabler så att de är tillgängliga både
|
||||
från main() och de övriga funktionerna.
|
||||
struct myData används t.ex. både från main() och
|
||||
new() */
|
||||
struct myData
|
||||
{
|
||||
char name[NAMEMAXLENGTH];
|
||||
int quantity;
|
||||
float price;
|
||||
};
|
||||
|
||||
char filename[] = "storage.bin";
|
||||
|
||||
/* Funktionsprototyper */
|
||||
void list(struct myData *datap, int numRec);
|
||||
void search(struct myData *datap, int numRec, char *name);
|
||||
void modify(struct myData *datap, int numRec, char *name);
|
||||
void delete(struct myData *datap, int numRec, char *name);
|
||||
int new(struct myData *datap);
|
||||
void printUsage(char *arg);
|
||||
void printHeader(void);
|
||||
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
FILE *fp; /* Filpekare */
|
||||
int newart = 0; /* Ska vi skapa en ny artikel? */
|
||||
int numRec; /* För antalet för artiklar */
|
||||
int create; /* För y/n-fråga */
|
||||
int opt; /* För getopt() */
|
||||
|
||||
/* Skapa en strukturvariabel (en pekare) av struct myData */
|
||||
struct myData *data;
|
||||
|
||||
/* Skriv ut hjälptexten och returnera 1 om vi saknar argument */
|
||||
if (argc < 2)
|
||||
{
|
||||
printUsage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Kontrollera om filen finns och är läs- och skrivbar.
|
||||
Om inte, fråga om vi ska skapa den och börja läsa
|
||||
in artiklar. access() är ett systemanrop för Unixmiljöer */
|
||||
if ( access(filename, R_OK|W_OK) != 0 )
|
||||
{
|
||||
/* Använd fprintf() för att skriva felmeddelanden
|
||||
till stderr */
|
||||
fprintf(stderr, "Could not open %s\n", filename);
|
||||
printf("Create the file and start adding records? (y/n): ");
|
||||
create = getchar();
|
||||
if ( create == 'y' )
|
||||
{
|
||||
/* Allokera minne för en struct myData och anropa
|
||||
sedan new() med en pekare till minnet för att lägga
|
||||
till artiklar i lagret, en i taget */
|
||||
numRec = 1;
|
||||
data = calloc(numRec, sizeof(struct myData));
|
||||
new(data);
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Öppna filen i läsläge */
|
||||
fp = fopen(filename, "rb");
|
||||
|
||||
/* Läs in befintlig data från filen till strukturen */
|
||||
fseek(fp, 0, SEEK_END);
|
||||
numRec = ftell(fp) / sizeof(struct myData);
|
||||
data = calloc(numRec, sizeof(struct myData));
|
||||
rewind(fp);
|
||||
fread(data, sizeof(struct myData), numRec, fp);
|
||||
fclose(fp);
|
||||
|
||||
/* Behandla argumenten med getopt() */
|
||||
while ((opt = getopt(argc, argv, "hls:m:d:n")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'l':
|
||||
list(data, numRec);
|
||||
break;
|
||||
case 's':
|
||||
search(data, numRec, optarg);
|
||||
break;
|
||||
case 'm':
|
||||
modify(data, numRec, optarg);
|
||||
break;
|
||||
case 'd':
|
||||
delete(data, numRec, optarg);
|
||||
break;
|
||||
case 'n':
|
||||
newart = 1;
|
||||
break;
|
||||
case 'h':
|
||||
printUsage(argv[0]);
|
||||
return 0;
|
||||
default:
|
||||
printUsage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fortsätt här om filen finns och vi valde att lägga
|
||||
till artiklar */
|
||||
if ( newart == 1 )
|
||||
{
|
||||
data = calloc(1, sizeof(struct myData));
|
||||
if ( new(data) == 1 )
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Här är programmet klart, så frigör minnet och returnera 0 */
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Funktionerna nedan tar en pekare till datatypen struct myData
|
||||
som första argument. Som andra argument ett heltal som innehåller
|
||||
antalet artiklar i lagret. */
|
||||
void list(struct myData *datap, int numRec)
|
||||
{
|
||||
int i;
|
||||
printHeader();
|
||||
for (i = 0; i<numRec; i++)
|
||||
{
|
||||
printf("%-30s\t", datap[i].name);
|
||||
printf("%-10d\t", datap[i].quantity);
|
||||
printf("%.2f\t", datap[i].price);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Det tredje argumentet till denna funktionen är en pekare till char
|
||||
som används för att söka efter en artikel. */
|
||||
void search(struct myData *datap, int numRec, char *name)
|
||||
{
|
||||
int i;
|
||||
/* Loopa över alla artiklar i databasen */
|
||||
for (i = 0; i<numRec; i++)
|
||||
{
|
||||
/* Om ingen match finns, hoppa över och fortsätt
|
||||
till nästa */
|
||||
if ( strcmp(name, datap[i].name) != 0 )
|
||||
continue;
|
||||
printHeader();
|
||||
printf("%-30s\t", datap[i].name);
|
||||
printf("%-10d\t", datap[i].quantity);
|
||||
printf("%.2f\t", datap[i].price);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Samma argument som för search-funktionen */
|
||||
void modify(struct myData *datap, int numRec, char *name)
|
||||
{
|
||||
FILE *newfp; /* Ny filpekare för denna funktion */
|
||||
int i;
|
||||
int match = 0;
|
||||
char what[10];
|
||||
char quant[20];
|
||||
|
||||
/* Loopa över alla artiklar i lagret */
|
||||
for (i = 0; i<numRec; i++)
|
||||
{
|
||||
if ( strcmp(name, datap[i].name) == 0 )
|
||||
{
|
||||
match = 1; /* Så att vi vet om vi hittade artikeln
|
||||
när vi kommer utanför if-satsen */
|
||||
printHeader();
|
||||
printf("%-30s\t", datap[i].name);
|
||||
printf("%-10d\t", datap[i].quantity);
|
||||
printf("%.2f\t", datap[i].price);
|
||||
printf("\n\n");
|
||||
|
||||
printf("What do you like to modify? "
|
||||
"(name, quantity, price): ");
|
||||
fgets(what, 10, stdin);
|
||||
what[strcspn(what, "\n")] = '\0';
|
||||
|
||||
if ( strcmp(what, "name") == 0 )
|
||||
{
|
||||
printf("Name: ");
|
||||
fgets(datap[i].name, NAMEMAXLENGTH, stdin);
|
||||
datap[i].name[strcspn(datap[i].name, "\n")] = '\0';
|
||||
}
|
||||
else if ( strcmp(what, "quantity") == 0 )
|
||||
{
|
||||
printf("Quantity (absolute value or "
|
||||
"(a)dd/(s)ubtractNUMBER): ");
|
||||
fgets(quant, 20, stdin);
|
||||
quant[strcspn(quant, "\n")] = '\0';
|
||||
|
||||
/* Behandla det första tecknet som angavs */
|
||||
if (quant[0] == 'a') /* a för add */
|
||||
{
|
||||
quant[0] = ' '; /* Radera det första tecknet */
|
||||
datap[i].quantity = datap[i].quantity +
|
||||
atoi(quant);
|
||||
}
|
||||
else if (quant[0] == 's') /* s för subtract */
|
||||
{
|
||||
quant[0] = ' ';
|
||||
datap[i].quantity = datap[i].quantity -
|
||||
atoi(quant);
|
||||
}
|
||||
else
|
||||
datap[i].quantity = atoi(quant);
|
||||
|
||||
}
|
||||
else if ( strcmp(what, "price") == 0 )
|
||||
{
|
||||
printf("Price: "); scanf("%f", &datap[i].price);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match == 0)
|
||||
{
|
||||
fprintf(stderr, "Could not find %s in database\n", name);
|
||||
exit(1);
|
||||
}
|
||||
/* Öppna filen i skrivläge och skriv ut den modifierade
|
||||
strukturen till filen */
|
||||
if ( (newfp = fopen(filename, "wb")) == 0 )
|
||||
{
|
||||
fprintf(stderr, "Could not open file for writing\n");
|
||||
exit(1);
|
||||
}
|
||||
fwrite(datap, sizeof(struct myData), numRec, newfp);
|
||||
fclose(newfp);
|
||||
}
|
||||
|
||||
void delete(struct myData *datap, int numRec, char *name)
|
||||
{
|
||||
int i, j; /* För for-looparna */
|
||||
int match = 0;
|
||||
FILE *newfp; /* Ny filpekare för denna funktion */
|
||||
int answer;
|
||||
|
||||
/* Look/sök igenom hela databasen */
|
||||
for (i = 0; i<numRec; i++)
|
||||
{
|
||||
if ( strcmp(name, datap[i].name) == 0 )
|
||||
{
|
||||
/* Sätt match till 1 så att vi inte skriver ut
|
||||
om det inte finns någon match längre fram */
|
||||
match = 1;
|
||||
printHeader();
|
||||
printf("%-30s\t", datap[i].name);
|
||||
printf("%-10d\t", datap[i].quantity);
|
||||
printf("%.2f\t", datap[i].price);
|
||||
printf("\n\n");
|
||||
printf("Delete the record listed above? (y/n): ");
|
||||
|
||||
answer = getchar();
|
||||
if ( answer == 'y' )
|
||||
{
|
||||
if ( (newfp = fopen(filename, "wb")) == 0 )
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Could not open file for writing\n");
|
||||
exit(1);
|
||||
}
|
||||
/* Loopa igenom alla artiklar i databasen och skriv
|
||||
ut dem till filen igen, FÖRUTOM de som matchar
|
||||
sökordet */
|
||||
for (j = 0; j<numRec; j++)
|
||||
{
|
||||
if ( strcmp(name, datap[j].name) == 0 )
|
||||
continue;
|
||||
fwrite(&datap[j], sizeof(struct myData), 1,
|
||||
newfp);
|
||||
}
|
||||
fclose(newfp);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match == 0)
|
||||
{
|
||||
fprintf(stderr, "Could not find %s in database\n", name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int new(struct myData *datap)
|
||||
{
|
||||
FILE *fp;
|
||||
int bytes;
|
||||
if ( (fp = fopen(filename, "ab")) == 0 )
|
||||
{
|
||||
fprintf(stderr, "Could not open file for writing\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Fråga efter uppgifterna för varje ny artikel och skriv ut
|
||||
artiklarna, en efter en till filen. Loopa tills användaren
|
||||
skriver 'done' som namn. */
|
||||
for (;;)
|
||||
{
|
||||
/* Sätt stdin-bufferten till NULL efter varje iteration
|
||||
(för att tömma bufferten) */
|
||||
setbuf(stdin, NULL);
|
||||
printf("Name ('done' when finished): ");
|
||||
fgets(datap->name, NAMEMAXLENGTH, stdin);
|
||||
datap->name[strcspn(datap->name, "\n")] = '\0';
|
||||
|
||||
if ( strcmp(datap->name, "done") == 0 )
|
||||
{
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
printf("Quantity: "); scanf("%d", &datap->quantity);
|
||||
printf("Price: "); scanf("%f", &datap->price);
|
||||
bytes = fwrite(datap, sizeof(struct myData), 1, fp);
|
||||
if (bytes != 1)
|
||||
{
|
||||
fprintf(stderr, "Could not write to the file!\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printUsage(char *arg)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-l] [-s name] "
|
||||
"[-m name] \n"
|
||||
"[-d name] [-n] [-h]\n\n"
|
||||
"-l = list the articles in the database\n"
|
||||
"-s name = search for an article named 'name'\n"
|
||||
"-m name = modify the article named 'name'\n"
|
||||
" You'll then have the choice to change name, quantity "
|
||||
"and price.\n"
|
||||
"-d name = delete the article named 'name'\n"
|
||||
"-n = create new articles (interactive mode only)\n"
|
||||
"-h = display this help message\n", arg);
|
||||
}
|
||||
|
||||
void printHeader(void)
|
||||
{
|
||||
int i;
|
||||
printf("\n%-30s\t", "Name");
|
||||
printf("%s\t", "Quantity");
|
||||
printf("%s\t\n", "Price");
|
||||
for (i = 0; i<=52; i++)
|
||||
printf("=");
|
||||
printf("\n");
|
||||
}
|
23
kapitel12/las-flera-flt.c
Normal file
23
kapitel12/las-flera-flt.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* Korrekt storlek från början på x & y */
|
||||
float y[3];
|
||||
int x[3];
|
||||
int i;
|
||||
FILE *fp;
|
||||
if ( (fp = fopen("test.bin", "rb")) == 0 )
|
||||
{
|
||||
fprintf(stderr, "Kan inte öppna filen\n");
|
||||
return 1;
|
||||
}
|
||||
fread(&y, sizeof(y), 1, fp); /* Först flyttalen */
|
||||
fread(&x, sizeof(x), 1, fp); /* Sen heltalen... */
|
||||
for (i = 0; i<3; i++)
|
||||
printf("%f\n", y[i]);
|
||||
|
||||
for (i = 0; i<3; i++)
|
||||
printf("%d\n", x[i]);
|
||||
return 0;
|
||||
}
|
25
kapitel12/las-flt-fil-ex1.c
Normal file
25
kapitel12/las-flt-fil-ex1.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float y[10];
|
||||
int bytes, antal, i;
|
||||
FILE *fp;
|
||||
if ( (fp = fopen("test.bin", "rb")) == 0)
|
||||
{
|
||||
fprintf(stderr, "Kan inte öppna filen\n");
|
||||
return 1;
|
||||
}
|
||||
fseek(fp, 0, SEEK_END); /* Flytt till slutet av filen*/
|
||||
bytes = ftell(fp); /* Totala antalet bytes */
|
||||
rewind(fp); /* Flytta markören till början av filen */
|
||||
printf("Antal bytes i filen: %d\n", bytes);
|
||||
antal = bytes / sizeof(float); /* Hur många element */
|
||||
printf("Antal element: %d\n", antal);
|
||||
fread(&y, sizeof(float), antal, fp);
|
||||
/* Skriv ut alla flyttalen från filen */
|
||||
for (i = 0; i<antal; i++)
|
||||
printf("%f\n", y[i]);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
18
kapitel12/las-flt-fil.c
Normal file
18
kapitel12/las-flt-fil.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float y[3];
|
||||
int i;
|
||||
FILE *fp;
|
||||
if ( (fp = fopen("test.bin", "rb")) == 0 )
|
||||
{
|
||||
fprintf(stderr, "Kan inte öppna filen\n");
|
||||
return 1;
|
||||
}
|
||||
fread(&y, sizeof(y), 1, fp);
|
||||
for (i = 0; i<3; i++)
|
||||
printf("%f\n", y[i]);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
16
kapitel12/lasa-bin-ex1.c
Normal file
16
kapitel12/lasa-bin-ex1.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
FILE *binfil;
|
||||
float x;
|
||||
if ( (binfil = fopen("flyttal.bin", "rb")) == 0 )
|
||||
{
|
||||
fprintf(stderr, "Kunde inte öppna filen\n");
|
||||
return 1;
|
||||
}
|
||||
fread(&x, sizeof(x), 1, binfil);
|
||||
printf("Flyttalet är: %f\n", x);
|
||||
fclose(binfil);
|
||||
return 0;
|
||||
}
|
14
kapitel12/lasa-fil-ex1.c
Normal file
14
kapitel12/lasa-fil-ex1.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
FILE *fp;
|
||||
signed char c;
|
||||
|
||||
fp = fopen("test.txt", "r");
|
||||
while ((c = getc(fp)) != EOF)
|
||||
putchar(c);
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
32
kapitel12/lasa-fil-ex2.c
Normal file
32
kapitel12/lasa-fil-ex2.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
FILE *fp;
|
||||
int strSize, readSize;
|
||||
char *buffer;
|
||||
fp = fopen("test.txt", "r");
|
||||
|
||||
/* Ta reda på storleken och återgå sen till start */
|
||||
fseek(fp, 0, SEEK_END);
|
||||
strSize = ftell(fp);
|
||||
rewind(fp);
|
||||
|
||||
/* Skapa dynamiskt minne för filens innehåll */
|
||||
buffer = calloc(sizeof(char), strSize+1);
|
||||
|
||||
/* Läs in filens innehåll och spara antalet inlästa
|
||||
tecken i 'readSize' */
|
||||
readSize = fread(buffer, sizeof(char), strSize, fp);
|
||||
|
||||
fclose(fp); /* Vi är klara med fp så stäng den */
|
||||
|
||||
printf("%s\n\n", buffer);
|
||||
printf("Storleken är %d tecken och vi läste in %d tecken\n",
|
||||
strSize, readSize);
|
||||
|
||||
free(buffer); /* Frigör det dynamiska minnet */
|
||||
|
||||
return 0;
|
||||
}
|
33
kapitel12/lasa-fil-ex3-c99.c
Normal file
33
kapitel12/lasa-fil-ex3-c99.c
Normal file
@ -0,0 +1,33 @@
|
||||
#define _XOPEN_SOURCE 600
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
FILE *fp;
|
||||
off_t filesize;
|
||||
int fd, readSize;
|
||||
struct stat fileinfo;
|
||||
char* buffer;
|
||||
fp = fopen("test.txt", "r");
|
||||
|
||||
fd = fileno(fp); /* Hämta fildeskriptorn och spara i fd */
|
||||
fstat(fd, &fileinfo); /* Hämta all information till 'fileinfo' */
|
||||
filesize = fileinfo.st_size; /* Spara filens storlek i filesize */
|
||||
/* från 'fileinfo.st_size' */
|
||||
|
||||
buffer = calloc(sizeof(char), filesize+1);
|
||||
readSize = fread(buffer, sizeof(char), filesize, fp);
|
||||
buffer[filesize] = '\0';
|
||||
|
||||
printf("%s\n\n", buffer);
|
||||
printf("Fildeskriptor: %d\n", fd);
|
||||
printf("Filens storlek är %jd byte och vi har läst in %d byte\n",
|
||||
(intmax_t)filesize, readSize);
|
||||
|
||||
return 0;
|
||||
}
|
32
kapitel12/lasa-fil-ex3.c
Normal file
32
kapitel12/lasa-fil-ex3.c
Normal file
@ -0,0 +1,32 @@
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
FILE *fp;
|
||||
off_t filesize;
|
||||
int fd, readSize;
|
||||
struct stat fileinfo;
|
||||
char* buffer;
|
||||
fp = fopen("test.txt", "r");
|
||||
|
||||
fd = fileno(fp); /* Hämta fildeskriptorn och spara i fd */
|
||||
fstat(fd, &fileinfo); /* Hämta all information till 'fileinfo' */
|
||||
filesize = fileinfo.st_size; /* Spara filens storlek i filesize */
|
||||
/* från 'fileinfo.st_size' */
|
||||
|
||||
buffer = calloc(sizeof(char), filesize+1);
|
||||
readSize = fread(buffer, sizeof(char), filesize, fp);
|
||||
buffer[filesize] = '\0';
|
||||
|
||||
printf("%s\n\n", buffer);
|
||||
printf("Fildeskriptor: %d\n", fd);
|
||||
printf("Filens storlek är %ld byte och vi har läst in %d byte\n",
|
||||
(long int)filesize, readSize);
|
||||
|
||||
return 0;
|
||||
}
|
27
kapitel12/lasa-matt.c
Normal file
27
kapitel12/lasa-matt.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int langd, bredd, hojd;
|
||||
FILE *fp;
|
||||
|
||||
/* Kontrollera först om filen finns och om inte
|
||||
avsluta programmet och skriv ett felmeddelande */
|
||||
if ( (fp = fopen("konfigfil.txt", "r")) == 0)
|
||||
{
|
||||
printf("Filen finns inte!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Läs in de olika "fälten" från filen till rätt
|
||||
variabel */
|
||||
fscanf( fp, "längd: %d, bredd: %d, höjd: %d",
|
||||
&langd, &bredd, &hojd);
|
||||
|
||||
/* Skriv ut volymen */
|
||||
printf("Lådan har en volym på %d cm3\n",
|
||||
(langd * bredd * hojd));
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
38
kapitel12/lasa-person-struct.c
Normal file
38
kapitel12/lasa-person-struct.c
Normal file
@ -0,0 +1,38 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAXLANGD 30
|
||||
#define ANTAL 3
|
||||
|
||||
int main(void)
|
||||
{
|
||||
FILE *fp;
|
||||
int i;
|
||||
struct minData
|
||||
{
|
||||
char fnamn[MAXLANGD];
|
||||
char enamn[MAXLANGD];
|
||||
int alder;
|
||||
};
|
||||
|
||||
struct minData personer[ANTAL];
|
||||
|
||||
if ( (fp= fopen("personer.bin", "rb")) == 0 )
|
||||
{
|
||||
fprintf(stderr, "Kan inte öppna filen\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Läs in strukturen från filen */
|
||||
fread(personer, sizeof(struct minData), ANTAL, fp);
|
||||
|
||||
/* Loopa igenom alla personer i strukturen */
|
||||
for (i = 0; i<ANTAL; i++)
|
||||
{
|
||||
printf("Förnamn: %s\n", personer[i].fnamn);
|
||||
printf("Efternamn: %s\n", personer[i].enamn);
|
||||
printf("Ålder: %d\n\n", personer[i].alder);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
20
kapitel12/skriv-bin-ex1.c
Normal file
20
kapitel12/skriv-bin-ex1.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
FILE *binfil;
|
||||
float x;
|
||||
/* Kontrollera om fopen lyckades öppna filen
|
||||
i skrivläge */
|
||||
if ( (binfil = fopen("flyttal.bin", "wb")) == 0 )
|
||||
{
|
||||
/* Skriv felmeddelande till stderr */
|
||||
fprintf(stderr, "Kan inte skriva till fil\n");
|
||||
return 1;
|
||||
}
|
||||
printf("Skriv ett flyttal: ");
|
||||
scanf("%f", &x);
|
||||
fwrite(&x, sizeof(x), 1, binfil);
|
||||
fclose(binfil);
|
||||
return 0;
|
||||
}
|
18
kapitel12/skriv-fil-ex1.c
Normal file
18
kapitel12/skriv-fil-ex1.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
FILE *fp;
|
||||
char namn1[] = "Knatte";
|
||||
char namn2[] = "Fnatte";
|
||||
|
||||
fp = fopen("test.txt", "w");
|
||||
|
||||
fprintf(fp, "%s, %s och Tjatte\n"
|
||||
"bor alla i Ankeborg.\n\n", namn1, namn2);
|
||||
fputs("Kalle och Lisa bor också i Ankeborg.\n", fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
18
kapitel12/skriv-flera-flt.c
Normal file
18
kapitel12/skriv-flera-flt.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float y[3] = {3.14, 5.55, 9.56};
|
||||
int x[3] = {99, 101, 105};
|
||||
FILE *fp;
|
||||
if ( (fp = fopen("test.bin", "wb")) == 0 )
|
||||
{
|
||||
fprintf(stderr, "Kan inte läsa filen\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fwrite(&y, sizeof(y), 1, fp);
|
||||
fwrite(&x, sizeof(x), 1, fp);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
15
kapitel12/skriv-flt-fil.c
Normal file
15
kapitel12/skriv-flt-fil.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
float y[3] = {3.14, 5.55, 9.56};
|
||||
FILE *fp;
|
||||
if ( (fp = fopen("test.bin", "wb")) == 0 )
|
||||
{
|
||||
fprintf(stderr, "Kan inte öppna filen\n");
|
||||
return 1;
|
||||
}
|
||||
fwrite(&y, sizeof(y), 1, fp);
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
42
kapitel12/skriv-person-struct.c
Normal file
42
kapitel12/skriv-person-struct.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAXLANGD 30
|
||||
#define ANTAL 3
|
||||
|
||||
int main(void)
|
||||
{
|
||||
FILE *fp;
|
||||
struct minData
|
||||
{
|
||||
char fnamn[MAXLANGD];
|
||||
char enamn[MAXLANGD];
|
||||
int alder;
|
||||
};
|
||||
|
||||
struct minData personer[ANTAL];
|
||||
|
||||
if ( (fp = fopen("personer.bin", "wb")) == 0 )
|
||||
{
|
||||
fprintf(stderr, "Kan inte öppna filen\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Skapa tre person i strukturen */
|
||||
strcpy(personer[0].fnamn, "Kalle");
|
||||
strcpy(personer[0].enamn, "Anka");
|
||||
personer[0].alder = 31;
|
||||
|
||||
strcpy(personer[1].fnamn, "Lisa");
|
||||
strcpy(personer[1].enamn, "Anka");
|
||||
personer[1].alder = 28;
|
||||
|
||||
strcpy(personer[2].fnamn, "Fnatte");
|
||||
strcpy(personer[2].enamn, "Anka");
|
||||
personer[2].alder = 8;
|
||||
|
||||
/* Skriv ut strukturen till en fil */
|
||||
fwrite(personer, sizeof(struct minData), ANTAL, fp);
|
||||
|
||||
return 0;
|
||||
}
|
39
kapitel13/filinfo-portabel.c
Normal file
39
kapitel13/filinfo-portabel.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
#define C99
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct stat fileinfo;
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s path/to/file\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
stat(argv[1], &fileinfo);
|
||||
|
||||
#ifdef C99
|
||||
printf("C99 (or newer)\n");
|
||||
printf("Inode number: %ju\n",
|
||||
(uintmax_t)fileinfo.st_ino);
|
||||
printf("Size in bytes: %jd (%.2f kilobytes)\n",
|
||||
(intmax_t)fileinfo.st_size,
|
||||
(double)fileinfo.st_size / 1024);
|
||||
#else
|
||||
printf("C89\n");
|
||||
printf("Inode number: %lu\n", (unsigned long int)fileinfo.st_ino);
|
||||
printf("Size in bytes: %lu (%.2f kilobytes)\n",
|
||||
(unsigned long int)fileinfo.st_size,
|
||||
(float)fileinfo.st_size / 1024);
|
||||
#endif
|
||||
printf("User-ID: %d\n", fileinfo.st_uid);
|
||||
printf("Group-ID: %d\n", fileinfo.st_gid);
|
||||
|
||||
return 0;
|
||||
}
|
25
kapitel13/filinfo.c
Normal file
25
kapitel13/filinfo.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct stat fileinfo;
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s path/to/file\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
stat(argv[1], &fileinfo);
|
||||
|
||||
printf("Inode number: %lu\n", (unsigned long int)fileinfo.st_ino);
|
||||
printf("Size in bytes: %lu (%.2f kilobytes)\n",
|
||||
(unsigned long int)fileinfo.st_size,
|
||||
(float)fileinfo.st_size / 1024);
|
||||
printf("User-ID: %d\n", fileinfo.st_uid);
|
||||
printf("Group-ID: %d\n", fileinfo.st_gid);
|
||||
|
||||
return 0;
|
||||
}
|
42
kapitel13/mychown-felhantering-ex1.c
Normal file
42
kapitel13/mychown-felhantering-ex1.c
Normal file
@ -0,0 +1,42 @@
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <file> <uid> <gid>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uid = (uid_t)atoi(argv[2]);
|
||||
gid = (gid_t)atoi(argv[3]);
|
||||
|
||||
if (chown(argv[1], uid, gid) == -1)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EPERM:
|
||||
fprintf(stderr, "Operation not permitted\n");
|
||||
break;
|
||||
case ENOENT:
|
||||
fprintf(stderr, "No such file or directory\n");
|
||||
break;
|
||||
case ENAMETOOLONG:
|
||||
fprintf(stderr, "Filename too long\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown error\n");
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
30
kapitel13/mychown-felhantering-ex2.c
Normal file
30
kapitel13/mychown-felhantering-ex2.c
Normal file
@ -0,0 +1,30 @@
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <file> <uid> <gid>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uid = (uid_t)atoi(argv[2]);
|
||||
gid = (gid_t)atoi(argv[3]);
|
||||
|
||||
if (chown(argv[1], uid, gid) == -1)
|
||||
{
|
||||
printf("%i\n", errno); /* Visar vad errno innehåller */
|
||||
printf("%s\n", strerror(errno)); /* Meddelandet i klartext */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
27
kapitel13/mychown-felhantering-ex3.c
Normal file
27
kapitel13/mychown-felhantering-ex3.c
Normal file
@ -0,0 +1,27 @@
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <file> <uid> <gid>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uid = (uid_t)atoi(argv[2]);
|
||||
gid = (gid_t)atoi(argv[3]);
|
||||
|
||||
if (chown(argv[1], uid, gid) == -1)
|
||||
{
|
||||
perror("chown");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
27
kapitel13/mychown.c
Normal file
27
kapitel13/mychown.c
Normal file
@ -0,0 +1,27 @@
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
|
||||
if (argc != 4)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <file> <uid> <gid>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
uid = (uid_t)atoi(argv[2]);
|
||||
gid = (gid_t)atoi(argv[3]);
|
||||
|
||||
if (chown(argv[1], uid, gid) == -1)
|
||||
{
|
||||
fprintf(stderr, "Could not change UID or GID\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
22
kapitel13/mytouch.c
Normal file
22
kapitel13/mytouch.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
/* Rättigheterna nedan blir 644, Read/Write user,
|
||||
Read group, Read others */
|
||||
creat(argv[1], S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (errno != 0)
|
||||
{
|
||||
perror("creat");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
8
kapitel13/write-ex1.c
Normal file
8
kapitel13/write-ex1.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
write(1, "Hejsan\n", 7);
|
||||
return 0;
|
||||
}
|
8
kapitel13/write-ex2.c
Normal file
8
kapitel13/write-ex2.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
write(STDOUT_FILENO, "Hejsan\n", 7);
|
||||
return 0;
|
||||
}
|
40
kapitel14/fahr-felhantering.c
Normal file
40
kapitel14/fahr-felhantering.c
Normal file
@ -0,0 +1,40 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Funktionsprototyp av isNumeric */
|
||||
int isNumeric(const char *str);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char c[10];
|
||||
float cels, f;
|
||||
while(fgets(c, sizeof(c), stdin) != NULL)
|
||||
{
|
||||
if (isNumeric(c))
|
||||
{
|
||||
cels = atof(c); /* char till float (stdlib.h) */
|
||||
f = cels*9/5+32;
|
||||
printf("%.1f\n", f);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Påträffade icke-numeriskt värde\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Funktionen för att kontrollera inmatade tecken */
|
||||
int isNumeric(const char *str)
|
||||
{
|
||||
if(strspn(str, "0123456789.-\n") == strlen(str)) /*string.h*/
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
15
kapitel14/fahr.c
Normal file
15
kapitel14/fahr.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char c[10];
|
||||
float cels, f;
|
||||
while(fgets(c, sizeof(c), stdin) != NULL)
|
||||
{
|
||||
cels = atof(c); /* gör om char till float (stdlib.h) */
|
||||
f = cels*9/5+32;
|
||||
printf("%.1f\n", f);
|
||||
}
|
||||
return 0;
|
||||
}
|
29
kapitel14/miljovar-ex1.c
Normal file
29
kapitel14/miljovar-ex1.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* Spara ett värde för senare användning */
|
||||
const char* myhome = getenv("HOME");
|
||||
|
||||
/* Skriv ut några miljövariabler */
|
||||
printf("Ditt UID är: %i\n", getuid());
|
||||
printf("Ditt GID är: %i\n", getgid());
|
||||
printf("Ditt användarnamn är: %s\n", getenv("USER"));
|
||||
printf("Det aktuella programmet heter: %s\n", getenv("_"));
|
||||
|
||||
printf("Din hemkatalog är: %s\n", myhome);
|
||||
|
||||
/* Testa om en variabel är satt eller inte */
|
||||
if (getenv("DISPLAY"))
|
||||
{
|
||||
printf("Du använder X-Window just nu\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Du använder inte X-Window just nu\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
11
kapitel14/miljovar-ex2.c
Normal file
11
kapitel14/miljovar-ex2.c
Normal file
@ -0,0 +1,11 @@
|
||||
#define _XOPEN_SOURCE 600
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
setenv("MINVAR", "J-B", 0); /* sätt variabeln (0 = skriv ej
|
||||
över ev. befintlig variabel) */
|
||||
printf("%s\n", getenv("MINVAR")); /* testa om det fungerade */
|
||||
return 0;
|
||||
}
|
8
kapitel14/outerrtest.c
Normal file
8
kapitel14/outerrtest.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
fprintf(stdout, "Text till stdout\n");
|
||||
fprintf(stderr, "Ett felmeddelande\n");
|
||||
return 0;
|
||||
}
|
5
kapitel14/temps.txt
Normal file
5
kapitel14/temps.txt
Normal file
@ -0,0 +1,5 @@
|
||||
22
|
||||
23
|
||||
25
|
||||
30
|
||||
31
|
10
kapitel14/testtmp.txt
Normal file
10
kapitel14/testtmp.txt
Normal file
@ -0,0 +1,10 @@
|
||||
id=151 temperature=-4.6 humidity=92 time=2016-11-13 22:50:20
|
||||
id=167 temperature=22.1 humidity=20 time=2016-11-13 22:49:34
|
||||
id=151 temperature=-4.6 humidity=92 time=2016-11-13 22:53:32
|
||||
id=167 temperature=22.0 humidity=20 time=2016-11-13 22:53:34
|
||||
id=151 temperature=-4.6 humidity=92 time=2016-11-13 22:56:44
|
||||
id=167 temperature=22.3 humidity=20 time=2016-11-13 22:56:45
|
||||
id=151 temperature=-4.7 humidity=92 time=2016-11-13 22:59:56
|
||||
id=167 temperature=22.4 humidity=20 time=2016-11-13 22:59:57
|
||||
id=151 temperature=-4.7 humidity=92 time=2016-11-13 23:02:20
|
||||
id=167 temperature=22.4 humidity=20 time=2016-11-13 23:02:21
|
11
kapitel15/exempel.c
Normal file
11
kapitel15/exempel.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int x, y;
|
||||
x = 5;
|
||||
|
||||
printf("x = %d\n", x);
|
||||
printf("Adressen till x är %lu\n", &x);
|
||||
return 0;
|
||||
}
|
4
kapitel15/funk.c
Normal file
4
kapitel15/funk.c
Normal file
@ -0,0 +1,4 @@
|
||||
int kvadrat(int n)
|
||||
{
|
||||
return n*n;
|
||||
}
|
1
kapitel15/funk.h
Normal file
1
kapitel15/funk.h
Normal file
@ -0,0 +1 @@
|
||||
int kvadrat(int n);
|
10
kapitel15/jbmath/jbmath.c
Normal file
10
kapitel15/jbmath/jbmath.c
Normal file
@ -0,0 +1,10 @@
|
||||
float circumf(float diameter)
|
||||
{
|
||||
const float pi = 3.14159265;
|
||||
return (pi * diameter);
|
||||
}
|
||||
|
||||
float area(float length, float height)
|
||||
{
|
||||
return (length * height);
|
||||
}
|
3
kapitel15/jbmath/jbmath.h
Normal file
3
kapitel15/jbmath/jbmath.h
Normal file
@ -0,0 +1,3 @@
|
||||
float circumf(float diameter);
|
||||
float area(float length, float height);
|
||||
long jbpow(int x, int n);
|
10
kapitel15/jbmath/jbpow.c
Normal file
10
kapitel15/jbmath/jbpow.c
Normal file
@ -0,0 +1,10 @@
|
||||
long jbpow(int x, int n)
|
||||
{
|
||||
long num = 1;
|
||||
int i;
|
||||
for(i = 0; i<n; i++)
|
||||
{
|
||||
num = num * x;
|
||||
}
|
||||
return num;
|
||||
}
|
12
kapitel15/jbmath/usemath-dyn.c
Normal file
12
kapitel15/jbmath/usemath-dyn.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include <jbmath.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("En cirkel med diametern 5.5 har omkretsen %.3f\n",
|
||||
circumf(5.5));
|
||||
printf("En rektangel med sidorna 3 och 8.5 har arean %.3f\n",
|
||||
area(3, 8.5));
|
||||
printf("5 upphöjt till 6 är %ld\n", jbpow(5, 6));
|
||||
return 0;
|
||||
}
|
12
kapitel15/jbmath/usemath.c
Normal file
12
kapitel15/jbmath/usemath.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include "jbmath.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("En cirkel med diametern 5.5 har omkretsen %.3f\n",
|
||||
circumf(5.5));
|
||||
printf("En rektangel med sidorna 3 och 8.5 har arean %.3f\n",
|
||||
area(3, 8.5));
|
||||
printf("5 upphöjt till 6 är %ld\n", jbpow(5, 6));
|
||||
return 0;
|
||||
}
|
17
kapitel15/matte/Makefile
Normal file
17
kapitel15/matte/Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
CC=cc
|
||||
CFLAGS=-Wall -Wextra -pedantic -std=c99 -D_XOPEN_SOURCE=600
|
||||
|
||||
matte: matte.o minmattefunk.o usage.o
|
||||
$(CC) -o matte matte.o minmattefunk.o usage.o
|
||||
|
||||
matte.o: matte.c minmattefunk.h usage.h
|
||||
$(CC) $(CFLAGS) -c matte.c
|
||||
|
||||
minmattefunk.o: minmattefunk.c
|
||||
$(CC) $(CFLAGS) -c minmattefunk.c
|
||||
|
||||
usage.o: usage.c
|
||||
$(CC) $(CFLAGS) -c usage.c
|
||||
|
||||
clean:
|
||||
rm matte minmattefunk.o matte.o usage.o
|
34
kapitel15/matte/matte.c
Normal file
34
kapitel15/matte/matte.c
Normal file
@ -0,0 +1,34 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "minmattefunk.h"
|
||||
#include "usage.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int opt;
|
||||
if (argc == 1)
|
||||
{
|
||||
printUsage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "s:c:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 's':
|
||||
printf("%d squared is %d\n", atoi(optarg),
|
||||
kvadrat(atoi(optarg)));
|
||||
break;
|
||||
case 'c':
|
||||
printf("%d cubed is %d \n", atoi(optarg),
|
||||
kubik(atoi(optarg)));
|
||||
break;
|
||||
default:
|
||||
printUsage(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
9
kapitel15/matte/minmattefunk.c
Normal file
9
kapitel15/matte/minmattefunk.c
Normal file
@ -0,0 +1,9 @@
|
||||
int kvadrat(int x)
|
||||
{
|
||||
return x*x;
|
||||
}
|
||||
|
||||
int kubik(int x)
|
||||
{
|
||||
return x*x*x;
|
||||
}
|
2
kapitel15/matte/minmattefunk.h
Normal file
2
kapitel15/matte/minmattefunk.h
Normal file
@ -0,0 +1,2 @@
|
||||
int kvadrat(int x);
|
||||
int kubik(int x);
|
8
kapitel15/matte/usage.c
Normal file
8
kapitel15/matte/usage.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void printUsage(char *arg)
|
||||
{
|
||||
printf("Usage: %s (-s) | (-c) (integer)\n"
|
||||
"-s = calculate the square of an integer\n"
|
||||
"-c = calculate the cube of an integer\n", arg);
|
||||
}
|
1
kapitel15/matte/usage.h
Normal file
1
kapitel15/matte/usage.h
Normal file
@ -0,0 +1 @@
|
||||
void printUsage(char *arg);
|
10
kapitel15/matte/version2.Makefile
Normal file
10
kapitel15/matte/version2.Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
CC=cc
|
||||
CFLAGS=-Wall -Wextra -pedantic -std=c99 -D_XOPEN_SOURCE=600
|
||||
|
||||
matte: matte.o minmattefunk.o usage.o
|
||||
$(CC) -o matte matte.o minmattefunk.o usage.o
|
||||
|
||||
matte.o: minmattefunk.h usage.h
|
||||
|
||||
clean:
|
||||
rm matte minmattefunk.o matte.o usage.o
|
11
kapitel15/matte/version3.Makefile
Normal file
11
kapitel15/matte/version3.Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
CC=cc
|
||||
CFLAGS=-Wall -Wextra -pedantic -std=c99 -D_XOPEN_SOURCE=600
|
||||
OBJS=matte.o minmattefunk.o usage.o
|
||||
|
||||
matte: $(OBJS)
|
||||
$(CC) -o matte $(OBJS)
|
||||
|
||||
matte.o: minmattefunk.h usage.h
|
||||
|
||||
clean:
|
||||
rm matte $(OBJS)
|
18
kapitel15/matte/version4.Makefile
Normal file
18
kapitel15/matte/version4.Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
CC=cc
|
||||
CFLAGS=-Wall -Wextra -pedantic -std=c99 -D_XOPEN_SOURCE=600
|
||||
OBJS=matte.o minmattefunk.o usage.o
|
||||
PREFIX=/usr/local
|
||||
|
||||
matte: $(OBJS)
|
||||
$(CC) -o matte $(OBJS)
|
||||
|
||||
matte.o: minmattefunk.h usage.h
|
||||
|
||||
clean:
|
||||
rm matte $(OBJS)
|
||||
|
||||
install:
|
||||
cp matte $(DESTDIR)$(PREFIX)/bin/matte
|
||||
|
||||
uninstall:
|
||||
rm $(DESTDIR)$(PREFIX)/bin/matte
|
7
kapitel15/prog.c
Normal file
7
kapitel15/prog.c
Normal file
@ -0,0 +1,7 @@
|
||||
#include "funk.h"
|
||||
#define TAL 8
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return kvadrat(TAL);
|
||||
}
|
66
kapitel16/daemon-ex1.c
Normal file
66
kapitel16/daemon-ex1.c
Normal file
@ -0,0 +1,66 @@
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.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 */
|
||||
else if (process_id > 0)
|
||||
{
|
||||
exit(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);
|
||||
}
|
||||
/* Gör en ny fork (dubbel-fork). Detta blir demonen */
|
||||
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 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. 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 */
|
||||
/* Här börjar demonens arbete... */
|
||||
for(;;)
|
||||
{
|
||||
sleep(5);
|
||||
}
|
||||
}
|
12
kapitel16/execldemo.c
Normal file
12
kapitel16/execldemo.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
sleep(15);
|
||||
execl("/usr/bin/man", "man", "ls", (char *)NULL);
|
||||
perror("execl");
|
||||
|
||||
return 0;
|
||||
}
|
29
kapitel16/forkdemo-ex2.c
Normal file
29
kapitel16/forkdemo-ex2.c
Normal file
@ -0,0 +1,29 @@
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
pid_t pid;
|
||||
int status;
|
||||
pid = fork();
|
||||
if (pid == 0)
|
||||
{
|
||||
execl("/usr/bin/man", "man", "ls", (char *)NULL);
|
||||
perror("execl");
|
||||
}
|
||||
else if (pid > 0)
|
||||
{
|
||||
waitpid(pid, &status, 0);
|
||||
printf("Barnet är klart, återgår till förälderprocessen\n");
|
||||
printf("Barnet returnerade %i\n", status);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Något gick fel med fork()\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
25
kapitel16/forkdemo.c
Normal file
25
kapitel16/forkdemo.c
Normal file
@ -0,0 +1,25 @@
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
pid_t pid;
|
||||
pid = fork();
|
||||
if (pid == 0)
|
||||
{
|
||||
printf("Jag är barnprocessen\n");
|
||||
sleep(30);
|
||||
}
|
||||
else if (pid > 0)
|
||||
{
|
||||
printf("Jag är förälderprocessen\n");
|
||||
sleep(30);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Något gick fel med fork()\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
9
kapitel16/systest.c
Normal file
9
kapitel16/systest.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (system("man ls") == -1)
|
||||
fprintf(stderr, "Could not create child process\n");
|
||||
return 0;
|
||||
}
|
28
kapitel16/zombie.c
Normal file
28
kapitel16/zombie.c
Normal file
@ -0,0 +1,28 @@
|
||||
#define _XOPEN_SOURCE 500
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
pid_t pid;
|
||||
pid = fork();
|
||||
if (pid == 0)
|
||||
{
|
||||
printf("Jag är barnprocessen och kommer bli en zombie\n");
|
||||
exit(0);
|
||||
}
|
||||
else if (pid > 0)
|
||||
{
|
||||
printf("Jag är föräldern och kommer att köras i "
|
||||
"100 sekunder\n");
|
||||
sleep(100);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Något gick fel med fork()\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
108
kapitel17/daemon-ex2.c
Normal file
108
kapitel17/daemon-ex2.c
Normal 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
106
kapitel17/daemon-sig-ex1.c
Normal 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
125
kapitel17/daemon-sig-ex2.c
Normal 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);
|
||||
}
|
20
kapitel17/fifo-client-ex1.c
Normal file
20
kapitel17/fifo-client-ex1.c
Normal 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
79
kapitel17/fifo-ex1.c
Normal 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
45
kapitel17/my-msg-recv.c
Normal 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
53
kapitel17/my-msg-send.c
Normal 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
27
kapitel17/pipes-ex1.c
Normal 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
61
kapitel17/sig-client.c
Normal 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);
|
||||
}
|
48
kapitel17/unix-socket-client.c
Normal file
48
kapitel17/unix-socket-client.c
Normal 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;
|
||||
}
|
87
kapitel17/unix-socket-server.c
Normal file
87
kapitel17/unix-socket-server.c
Normal 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(¤t_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);
|
||||
}
|
61
kapitel18/mygetip.c
Normal file
61
kapitel18/mygetip.c
Normal file
@ -0,0 +1,61 @@
|
||||
#define _XOPEN_SOURCE 700
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#define MAXSIZE 100
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct addrinfo hints, *res, *result;
|
||||
char addrstr[MAXSIZE];
|
||||
char host[MAXSIZE];
|
||||
void *ptr;
|
||||
|
||||
/* argument till programmet */
|
||||
if (argc == 2)
|
||||
{
|
||||
strncpy(host, argv[1], MAXSIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Please specify a host to lookup\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
memset (&hints, 0, sizeof (hints)); /* nolla ut hints */
|
||||
hints.ai_family = AF_UNSPEC; /* både IPv4 och IPv6 */
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
/* hämta IP */
|
||||
if ( getaddrinfo (host, NULL, &hints, &result) != 0 )
|
||||
{
|
||||
perror ("getaddrinfo");
|
||||
return 1;
|
||||
}
|
||||
|
||||
res = result;
|
||||
|
||||
while (res) /* loopa över alla IP-adresser */
|
||||
{
|
||||
switch (res->ai_family) /* IPv4 eller IPv6 */
|
||||
{
|
||||
case AF_INET: /* IPv4 */
|
||||
ptr = &((struct sockaddr_in *) res->ai_addr)->sin_addr;
|
||||
break;
|
||||
case AF_INET6: /* IPv6 */
|
||||
ptr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
|
||||
break;
|
||||
}
|
||||
/* omvandla binär-IP till läslig IP-adress */
|
||||
inet_ntop (res->ai_family, ptr, addrstr, MAXSIZE);
|
||||
printf ("%s\n", addrstr);
|
||||
res = res->ai_next; /* nästa IP i listan */
|
||||
}
|
||||
freeaddrinfo(result); /* frigör minnet */
|
||||
return 0;
|
||||
}
|
91
kapitel18/tcp-client.c
Normal file
91
kapitel18/tcp-client.c
Normal file
@ -0,0 +1,91 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define MAXLINE 1024
|
||||
#define SIZE 20
|
||||
int sockfd;
|
||||
|
||||
void cleanUp(int signum);
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
char ipaddr[SIZE] = "127.0.0.1";
|
||||
int port = 9000;
|
||||
char buffer[MAXLINE];
|
||||
char message[MAXLINE];
|
||||
struct sockaddr_in servaddr;
|
||||
int n;
|
||||
socklen_t len;
|
||||
|
||||
/* skapa socket-filen */
|
||||
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
|
||||
{
|
||||
perror("socket creation failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* kontrollera om vi angav en adress */
|
||||
if (argc == 2)
|
||||
{
|
||||
strncpy(ipaddr, argv[1], SIZE-1);
|
||||
}
|
||||
|
||||
/* registrera signalhanterarna */
|
||||
signal(SIGTERM, cleanUp);
|
||||
signal(SIGABRT, cleanUp);
|
||||
signal(SIGQUIT, cleanUp);
|
||||
signal(SIGINT, cleanUp);
|
||||
signal(SIGPIPE, cleanUp);
|
||||
|
||||
/* nolla ut strukturen med adressen */
|
||||
memset(&servaddr, 0, sizeof(servaddr));
|
||||
|
||||
/* information om IP-adress och port */
|
||||
servaddr.sin_family = AF_INET; /* IPv4 */
|
||||
servaddr.sin_port = htons(port);
|
||||
servaddr.sin_addr.s_addr = inet_addr(ipaddr);;
|
||||
|
||||
len = sizeof(servaddr); /* storleken på adressen */
|
||||
|
||||
if (connect(sockfd, (struct sockaddr *)&servaddr, len) != 0)
|
||||
{
|
||||
perror("connect");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Connected to the server..\n");
|
||||
}
|
||||
|
||||
/* läs meddelanden och skicka till servern */
|
||||
while(1)
|
||||
{
|
||||
printf("Type your message: ");
|
||||
fgets(message, sizeof(message), stdin);
|
||||
/* byt ut radbrytningstecknet mot null */
|
||||
message[strcspn(message, "\n")] = '\0';
|
||||
/* skicka meddelandandet till servern med 'sendto' */
|
||||
write(sockfd, message, sizeof(message));
|
||||
/* ta emot meddelande från servern med 'recvfrom' */
|
||||
n = read(sockfd, buffer, sizeof(buffer));
|
||||
buffer[n] = '\0'; /* avsluta strängen med null */
|
||||
/* skriv ut svaret från servern */
|
||||
printf("Server: %s\n", buffer);
|
||||
}
|
||||
close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanUp(int signum)
|
||||
{
|
||||
printf("\nQuitting gracefully and closing the socket\n");
|
||||
close(sockfd);
|
||||
exit(0);
|
||||
}
|
113
kapitel18/tcp-server.c
Normal file
113
kapitel18/tcp-server.c
Normal file
@ -0,0 +1,113 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define MAXLINE 1024
|
||||
#define SIZE 20
|
||||
int sockfd;
|
||||
int datafd;
|
||||
|
||||
void cleanUp(int signum);
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
char ipaddr[SIZE] = "127.0.0.1";
|
||||
int port = 9000;
|
||||
char buffer[MAXLINE];
|
||||
char *confirmation = "Message received";
|
||||
struct sockaddr_in servaddr, cliaddr;
|
||||
int n;
|
||||
socklen_t len;
|
||||
|
||||
/* skapa socket */
|
||||
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
|
||||
{
|
||||
perror("socket creation failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* kontrollera om vi angav en lyssnar-adress */
|
||||
if (argc == 2)
|
||||
{
|
||||
strncpy(ipaddr, argv[1], SIZE-1);
|
||||
}
|
||||
|
||||
/* registrera signalhanterarna */
|
||||
signal(SIGTERM, cleanUp);
|
||||
signal(SIGABRT, cleanUp);
|
||||
signal(SIGQUIT, cleanUp);
|
||||
signal(SIGINT, cleanUp);
|
||||
signal(SIGPIPE, cleanUp); /* när klienten kopplar från servern
|
||||
får den en SIGPIPE */
|
||||
|
||||
/* nolla adress-strukturerna innan vi använder dem */
|
||||
memset(&servaddr, 0, sizeof(servaddr));
|
||||
memset(&cliaddr, 0, sizeof(cliaddr));
|
||||
|
||||
/* information om IP-adress och port */
|
||||
servaddr.sin_family = AF_INET; /* IPv4 */
|
||||
servaddr.sin_addr.s_addr = inet_addr(ipaddr);
|
||||
servaddr.sin_port = htons(port);
|
||||
|
||||
/* knyt ihop vår socket med adressen */
|
||||
if ( bind(sockfd, (const struct sockaddr *)&servaddr,
|
||||
sizeof(servaddr)) < 0 )
|
||||
{
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* lyssna efter inkommande anslutningar */
|
||||
if ( (listen(sockfd, 5)) != 0 )
|
||||
{
|
||||
perror("listen");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Server listening...\n");
|
||||
}
|
||||
len = sizeof(cliaddr); /* storleken på adressen */
|
||||
|
||||
/* acceptera inkommande anslutning */
|
||||
datafd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);
|
||||
if (datafd < 0)
|
||||
{
|
||||
perror("accept");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Server accepted connection...\n");
|
||||
}
|
||||
|
||||
/* ta emot paket och loopa tills klienten kopplar från */
|
||||
while(1)
|
||||
{
|
||||
n = read(datafd, buffer, sizeof(buffer));
|
||||
/* skriv ut meddelandet vi tog emot från klienten och
|
||||
skicka en bekräftelse */
|
||||
buffer[n] = '\0'; /* avsluta strängen med null */
|
||||
printf("Client: %s\n", buffer);
|
||||
write(datafd, confirmation, strlen(confirmation)+1);
|
||||
printf("Confirmation message sent to client\n");
|
||||
}
|
||||
/* vi når aldrig hit - men fall i fall */
|
||||
close(sockfd);
|
||||
close(datafd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanUp(int signum)
|
||||
{
|
||||
printf("Quitting gracefully and closing the socket\n");
|
||||
close(sockfd);
|
||||
close(datafd);
|
||||
exit(0);
|
||||
}
|
85
kapitel18/udp-client.c
Normal file
85
kapitel18/udp-client.c
Normal file
@ -0,0 +1,85 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define MAXLINE 1024
|
||||
#define SIZE 20
|
||||
int sockfd;
|
||||
|
||||
void cleanUp(int signum);
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
char ipaddr[SIZE] = "127.0.0.1";
|
||||
int port = 9000;
|
||||
char buffer[MAXLINE];
|
||||
char message[MAXLINE];
|
||||
struct sockaddr_in servaddr;
|
||||
int n;
|
||||
socklen_t len;
|
||||
|
||||
/* skapa socket-filen */
|
||||
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
|
||||
{
|
||||
perror("socket creation failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* kontrollera om vi angav en adress */
|
||||
if (argc == 2)
|
||||
{
|
||||
strncpy(ipaddr, argv[1], SIZE-1);
|
||||
}
|
||||
|
||||
/* registrera signalhanterarna */
|
||||
signal(SIGTERM, cleanUp);
|
||||
signal(SIGABRT, cleanUp);
|
||||
signal(SIGQUIT, cleanUp);
|
||||
signal(SIGINT, cleanUp);
|
||||
|
||||
/* nolla ut strukturen med adressen */
|
||||
memset(&servaddr, 0, sizeof(servaddr));
|
||||
|
||||
/* information om IP-adress och port */
|
||||
servaddr.sin_family = AF_INET; /* IPv4 */
|
||||
servaddr.sin_port = htons(port);
|
||||
servaddr.sin_addr.s_addr = inet_addr(ipaddr);;
|
||||
|
||||
len = sizeof(servaddr); /* storleken på adressen */
|
||||
|
||||
/* läs meddelanden och skicka till servern */
|
||||
while(1)
|
||||
{
|
||||
printf("Type your message: ");
|
||||
fgets(message, sizeof(message), stdin);
|
||||
/* byt ut radbrytningstecknet mot null */
|
||||
message[strcspn(message, "\n")] = '\0';
|
||||
/* skicka meddelandandet till servern med 'sendto' */
|
||||
sendto(sockfd, (const char *)message, strlen(message),
|
||||
0, (const struct sockaddr *) &servaddr, len);
|
||||
|
||||
/* ta emot meddelande från servern med 'recvfrom' */
|
||||
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
|
||||
MSG_WAITALL, (struct sockaddr *) &servaddr, &len);
|
||||
buffer[n] = '\0'; /* avsluta strängen med null */
|
||||
|
||||
/* skriv ut svaret från servern */
|
||||
printf("Server: %s\n", buffer);
|
||||
}
|
||||
/* vi når aldrig hit - men fall i fall */
|
||||
close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanUp(int signum)
|
||||
{
|
||||
printf("\nQuitting gracefully and closing the socket\n");
|
||||
close(sockfd);
|
||||
exit(0);
|
||||
}
|
90
kapitel18/udp-server.c
Normal file
90
kapitel18/udp-server.c
Normal file
@ -0,0 +1,90 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/in.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define MAXLINE 1024
|
||||
#define SIZE 20
|
||||
int sockfd;
|
||||
|
||||
void cleanUp(int signum);
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
char ipaddr[SIZE] = "127.0.0.1";
|
||||
int port = 9000;
|
||||
char buffer[MAXLINE];
|
||||
char *confirmation = "Message received";
|
||||
struct sockaddr_in servaddr, cliaddr;
|
||||
int n;
|
||||
socklen_t len;
|
||||
|
||||
/* skapa socket */
|
||||
if ( (sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
|
||||
{
|
||||
perror("socket creation failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* kontrollera om vi angav en lyssnar-adress */
|
||||
if (argc == 2)
|
||||
{
|
||||
strncpy(ipaddr, argv[1], SIZE-1);
|
||||
}
|
||||
|
||||
/* registrera signalhanterarna */
|
||||
signal(SIGTERM, cleanUp);
|
||||
signal(SIGABRT, cleanUp);
|
||||
signal(SIGQUIT, cleanUp);
|
||||
signal(SIGINT, cleanUp);
|
||||
|
||||
/* nolla adress-strukturerna innan vi använder dem */
|
||||
memset(&servaddr, 0, sizeof(servaddr));
|
||||
memset(&cliaddr, 0, sizeof(cliaddr));
|
||||
|
||||
/* information om IP-adress och port */
|
||||
servaddr.sin_family = AF_INET; /* IPv4 */
|
||||
servaddr.sin_addr.s_addr = inet_addr(ipaddr);
|
||||
servaddr.sin_port = htons(port);
|
||||
|
||||
/* knyt ihop vår socket med adressen */
|
||||
if ( bind(sockfd, (const struct sockaddr *)&servaddr,
|
||||
sizeof(servaddr)) < 0 )
|
||||
{
|
||||
perror("bind failed");
|
||||
return 1;
|
||||
}
|
||||
len = sizeof(cliaddr); /* storleken på adressen */
|
||||
|
||||
/* ta emot udp-paket och loopa för evigt */
|
||||
while(1)
|
||||
{
|
||||
n = recvfrom(sockfd, (char *)buffer, MAXLINE,
|
||||
MSG_WAITALL, ( struct sockaddr *) &cliaddr,
|
||||
&len);
|
||||
buffer[n] = '\0'; /* avsluta strängen med null */
|
||||
|
||||
/* skriv ut meddelandet vi tog emot från klienten och skicka en
|
||||
bekräftelse */
|
||||
printf("Client: %s\n", buffer);
|
||||
sendto(sockfd, (const char *)confirmation,
|
||||
strlen(confirmation), 0,
|
||||
(const struct sockaddr *) &cliaddr, len);
|
||||
printf("Confirmation message sent to client\n");
|
||||
}
|
||||
/* vi når aldrig hit - men fall i fall */
|
||||
close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cleanUp(int signum)
|
||||
{
|
||||
printf("Quitting gracefully and closing the socket\n");
|
||||
close(sockfd);
|
||||
exit(0);
|
||||
}
|
17
kapitel19/felsok-ex1.c
Normal file
17
kapitel19/felsok-ex1.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int x;
|
||||
int y = 5;
|
||||
|
||||
char text[20] = "Hejsan";
|
||||
|
||||
for (x = 1; y < 100; x++)
|
||||
{
|
||||
y = (y*3)-x;
|
||||
}
|
||||
printf("%s\n", text);
|
||||
|
||||
return 0;
|
||||
}
|
25
kapitel19/felsok-ex2.c
Normal file
25
kapitel19/felsok-ex2.c
Normal file
@ -0,0 +1,25 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
float circum(float d);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
float di;
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s diamater\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
di = atof(argv[1]);
|
||||
printf ("Circumference of a circle with a diamater %.2f is"
|
||||
" %.2f\n", di, circum(di));
|
||||
return 0;
|
||||
}
|
||||
|
||||
float circum(float d)
|
||||
{
|
||||
float pi = 3.14159265;
|
||||
return (pi*d);
|
||||
}
|
23
kapitel19/flt-fel1.c
Normal file
23
kapitel19/flt-fel1.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
char *say(char namn[]);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char *mening = say("Jack-Benny");
|
||||
printf("%s\n", mening);
|
||||
free(mening);
|
||||
printf("Lisa hojtar: %s\n", mening);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *say(char namn[])
|
||||
{
|
||||
char *str;
|
||||
str = calloc(50, sizeof(char));
|
||||
strncat(str, "Hej ", 4);
|
||||
strncat(str, namn, 45);
|
||||
return str;
|
||||
}
|
14
kapitel19/leak1.c
Normal file
14
kapitel19/leak1.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
char* buffer;
|
||||
buffer = malloc(sizeof(char)*15);
|
||||
*buffer = '\0';
|
||||
strcpy(buffer, "Hejsan svejsan");
|
||||
printf("%s\n", buffer);
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user