Initial commit

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

38
README.md Normal file
View 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
![C-programmering i Linux, macOS, BSD och
Solaris](c-prog-tredje-utg-framsida.png)

BIN
c-prog-tredje-utg-framsida.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

View 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;
}

View 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;
}

View 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
View 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
View 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;
}

View 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;
}

View 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;
}

View 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
View 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 = &pi;
/* 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
View 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
View 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 = &pi;
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
View 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
View 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
View 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
View 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;
}

View 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;
}

View 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
View File

@ -0,0 +1,100 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
void printUsage(char *arg);
int main(int argc, char **argv)
{
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);
}

View File

@ -0,0 +1,75 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
void printUsage(char *arg);
int main(int argc, char **argv)
{
int opt;
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
View 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
View 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
View File

@ -0,0 +1 @@
längd: 33, bredd: 20, höjd: 10

View 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
View 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;
}

View 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
View 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
View 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
View 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
View 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;
}

View 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
View 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
View 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;
}

View 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
View 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
View 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;
}

View 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
View 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;
}

View 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;
}

View 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
View 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;
}

View 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;
}

View 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;
}

View 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
View 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
View 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
View 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
View File

@ -0,0 +1,8 @@
#include <stdio.h>
#include <unistd.h>
int main(void)
{
write(STDOUT_FILENO, "Hejsan\n", 7);
return 0;
}

View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,5 @@
22
23
25
30
31

10
kapitel14/testtmp.txt Normal file
View 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
View 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
View File

@ -0,0 +1,4 @@
int kvadrat(int n)
{
return n*n;
}

1
kapitel15/funk.h Normal file
View File

@ -0,0 +1 @@
int kvadrat(int n);

10
kapitel15/jbmath/jbmath.c Normal file
View 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);
}

View 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
View 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;
}

View 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;
}

View 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
View 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
View 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;
}

View File

@ -0,0 +1,9 @@
int kvadrat(int x)
{
return x*x;
}
int kubik(int x)
{
return x*x*x;
}

View File

@ -0,0 +1,2 @@
int kvadrat(int x);
int kubik(int x);

8
kapitel15/matte/usage.c Normal file
View 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
View File

@ -0,0 +1 @@
void printUsage(char *arg);

View 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

View 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)

View 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
View File

@ -0,0 +1,7 @@
#include "funk.h"
#define TAL 8
int main(void)
{
return kvadrat(TAL);
}

66
kapitel16/daemon-ex1.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,108 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <signal.h>
#include <syslog.h>
#include <fcntl.h>
void sigHandler(int sig);
int main(void)
{
pid_t process_id = 0;
pid_t sid = 0;
FILE *fp;
char pidfile[] = "/tmp/daemon-sig-ex.pid";
/* Skapa barn/child process */
process_id = fork();
/* Hantera eventuellt fel vid fork() */
if (process_id < 0)
{
fprintf(stderr, "fork misslyckades!\n");
exit(1);
}
/* Avsluta förälderprocessen */
else if (process_id > 0)
{
exit(1);
}
/* Starta en ny session */
sid = setsid();
if(sid < 0)
{
/* Avsluta ifall det inte gick att skapa en ny
session */
fprintf(stderr, "Misslyckades att skapa en ny session\n");
exit(1);
}
/* Gör en ny fork för att förhindra att demonen kan bli en
sessionsledare */
process_id = fork();
/* Hantera eventuellt fel vid fork() */
if (process_id < 0)
{
fprintf(stderr, "fork misslyckades!\n");
exit(1);
}
/* Avsluta föräldern den eftersom allt arbete kommer att
utföras av demonen. Skriv också demonens PID-fil */
else if (process_id > 0)
{
printf("Demonens PID: %d \n", process_id);
fp = fopen(pidfile, "w");
fprintf(fp, "%d", process_id);
fclose(fp);
exit(0);
}
/* Sätt umask till 022 (rw-r--r-- / rwx-r-xr-x) */
umask(022);
/* Ändra aktuell katalog till / */
chdir("/");
/* Stäng stdin, stdout och stderr och återöppna dem
till /dev/null */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
open("/dev/null", O_RDONLY); /* 0 = stdin */
open("/dev/null", O_WRONLY); /* 1 = stdout */
open("/dev/null", O_RDWR); /* 2 = stderr */
/* Registrera signalhanterarna, en för varje signal
som vi vill fånga upp */
signal(SIGUSR1, sigHandler);
signal(SIGTERM, sigHandler);
/* Demonens arbete... */
for(;;)
{
sleep(5);
}
return 0;
}
void sigHandler(int sig)
{
if (sig == SIGUSR1)
{
/* Skriv till syslog-demonen */
syslog(LOG_DAEMON, "Tog emot SIGUSR1");
}
else if (sig == SIGTERM)
{
/* Samma som ovan */
syslog(LOG_DAEMON, "Tog emot SIGTERM");
}
else
{
syslog(LOG_DAEMON, "Någonting hände med demonen...");
}
/* Signalhanteraren återställs efter första signalen,
vi måste därför sätta den igen */
signal(sig, sigHandler);
}

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

@ -0,0 +1,106 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <signal.h>
#include <syslog.h>
#include <fcntl.h>
void sigHandler(int sig);
int main(void)
{
pid_t process_id = 0;
pid_t sid = 0;
FILE *fp;
char pidfile[] = "/tmp/daemon-sig-ex.pid";
/* Skapa barn/child process */
process_id = fork();
/* Hantera eventuellt fel vid fork() */
if (process_id < 0)
{
fprintf(stderr, "fork misslyckades!\n");
exit(1);
}
/* Avsluta förälderprocessen */
else if (process_id > 0)
{
exit(1);
}
/* Starta en ny session */
sid = setsid();
if(sid < 0)
{
/* Avsluta ifall det inte gick att skapa en ny
session */
fprintf(stderr, "Misslyckades att skapa en ny session\n");
exit(1);
}
/* Gör en ny fork för att förhindra att demonen kan bli en
sessionsledare */
process_id = fork();
/* Hantera eventuellt fel vid fork() */
if (process_id < 0)
{
fprintf(stderr, "fork misslyckades!\n");
exit(1);
}
/* Avsluta föräldern den eftersom allt arbete kommer att
utföras av demonen. Skriv också demonens PID-fil */
else if (process_id > 0)
{
printf("Demonens PID: %d \n", process_id);
fp = fopen(pidfile, "w");
fprintf(fp, "%d", process_id);
fclose(fp);
exit(0);
}
/* Sätt umask till 022 (rw-r--r-- / rwx-r-xr-x) */
umask(022);
/* Ändra aktuell katalog till / */
chdir("/");
/* Stäng stdin, stdout och stderr och återöppna dem
till /dev/null */
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
open("/dev/null", O_RDONLY); /* 0 = stdin */
open("/dev/null", O_WRONLY); /* 1 = stdout */
open("/dev/null", O_RDWR); /* 2 = stderr */
/* Registrera signalhanterarna, en för varje signal
som vi vill fånga upp */
signal(SIGUSR1, sigHandler);
signal(SIGTERM, sigHandler);
/* Demonens arbete... */
for(;;)
{
sleep(5);
}
return 0;
}
void sigHandler(int sig)
{
if (sig == SIGUSR1)
{
/* Skriv till syslog-demonen */
syslog(LOG_DAEMON, "Tog emot SIGUSR1");
}
else if (sig == SIGTERM)
{
/* Samma som ovan */
syslog(LOG_DAEMON, "Tog emot SIGTERM");
}
else
{
syslog(LOG_DAEMON, "Någonting hände med demonen...");
}
/* Signalhanteraren återställs efter första signalen,
vi måste därför sätta den igen */
signal(sig, sigHandler);
}

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

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

View File

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

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

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

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

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

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

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

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

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

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

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

View File

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

View File

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

61
kapitel18/mygetip.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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