summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/OR_USING_C
diff options
context:
space:
mode:
Diffstat (limited to 'reference/C/CONTRIB/OR_USING_C')
-rw-r--r--reference/C/CONTRIB/OR_USING_C/02.1.c49
-rw-r--r--reference/C/CONTRIB/OR_USING_C/02.2.c44
-rw-r--r--reference/C/CONTRIB/OR_USING_C/02.3.c50
-rw-r--r--reference/C/CONTRIB/OR_USING_C/02.4.c23
-rw-r--r--reference/C/CONTRIB/OR_USING_C/02.5.c69
-rw-r--r--reference/C/CONTRIB/OR_USING_C/03.1.c60
-rw-r--r--reference/C/CONTRIB/OR_USING_C/03.2.c67
-rw-r--r--reference/C/CONTRIB/OR_USING_C/04.1.c44
-rw-r--r--reference/C/CONTRIB/OR_USING_C/04.2.c34
-rw-r--r--reference/C/CONTRIB/OR_USING_C/04.3.c183
-rw-r--r--reference/C/CONTRIB/OR_USING_C/05.1.c102
-rw-r--r--reference/C/CONTRIB/OR_USING_C/05.2.c101
-rw-r--r--reference/C/CONTRIB/OR_USING_C/05.3.c61
-rw-r--r--reference/C/CONTRIB/OR_USING_C/06.1.c58
-rw-r--r--reference/C/CONTRIB/OR_USING_C/07.1.c21
-rw-r--r--reference/C/CONTRIB/OR_USING_C/08.1.c13
-rw-r--r--reference/C/CONTRIB/OR_USING_C/08.2.c36
-rw-r--r--reference/C/CONTRIB/OR_USING_C/08.3.c42
-rw-r--r--reference/C/CONTRIB/OR_USING_C/08.4.c47
-rw-r--r--reference/C/CONTRIB/OR_USING_C/08.5.c85
-rw-r--r--reference/C/CONTRIB/OR_USING_C/08.6.c33
-rw-r--r--reference/C/CONTRIB/OR_USING_C/08.7.c108
-rw-r--r--reference/C/CONTRIB/OR_USING_C/09.1.c95
-rw-r--r--reference/C/CONTRIB/OR_USING_C/09.2.c52
-rw-r--r--reference/C/CONTRIB/OR_USING_C/09.3.c87
-rw-r--r--reference/C/CONTRIB/OR_USING_C/09.4.c91
-rw-r--r--reference/C/CONTRIB/OR_USING_C/10.1.c39
-rw-r--r--reference/C/CONTRIB/OR_USING_C/10.2.c37
-rw-r--r--reference/C/CONTRIB/OR_USING_C/10.3.c26
-rw-r--r--reference/C/CONTRIB/OR_USING_C/10.4.c32
-rw-r--r--reference/C/CONTRIB/OR_USING_C/10.5.c132
-rw-r--r--reference/C/CONTRIB/OR_USING_C/10.h34
-rw-r--r--reference/C/CONTRIB/OR_USING_C/11.1.c91
-rw-r--r--reference/C/CONTRIB/OR_USING_C/11.2.c109
-rw-r--r--reference/C/CONTRIB/OR_USING_C/11.3.c63
-rw-r--r--reference/C/CONTRIB/OR_USING_C/11.4.c65
-rw-r--r--reference/C/CONTRIB/OR_USING_C/11.5.c59
-rw-r--r--reference/C/CONTRIB/OR_USING_C/11.6.c53
-rw-r--r--reference/C/CONTRIB/OR_USING_C/11.7.c55
-rw-r--r--reference/C/CONTRIB/OR_USING_C/12.1.c112
-rw-r--r--reference/C/CONTRIB/OR_USING_C/12.2.c126
-rw-r--r--reference/C/CONTRIB/OR_USING_C/12.3.c93
-rw-r--r--reference/C/CONTRIB/OR_USING_C/13.1.c254
-rw-r--r--reference/C/CONTRIB/OR_USING_C/13.2.c267
-rw-r--r--reference/C/CONTRIB/OR_USING_C/13.3.c118
-rw-r--r--reference/C/CONTRIB/OR_USING_C/14.1.c29
-rw-r--r--reference/C/CONTRIB/OR_USING_C/14.2.c75
-rw-r--r--reference/C/CONTRIB/OR_USING_C/HEADER.html4
-rw-r--r--reference/C/CONTRIB/OR_USING_C/Makefile.am5
-rw-r--r--reference/C/CONTRIB/OR_USING_C/Makefile.in410
-rw-r--r--reference/C/CONTRIB/OR_USING_C/a.1.c4
-rw-r--r--reference/C/CONTRIB/OR_USING_C/a.2.c6
-rw-r--r--reference/C/CONTRIB/OR_USING_C/a.3.c12
-rw-r--r--reference/C/CONTRIB/OR_USING_C/a.4.c18
-rw-r--r--reference/C/CONTRIB/OR_USING_C/a.5.c29
-rw-r--r--reference/C/CONTRIB/OR_USING_C/a.6.c19
-rw-r--r--reference/C/CONTRIB/OR_USING_C/a.7.c16
-rw-r--r--reference/C/CONTRIB/OR_USING_C/b.1.c176
-rw-r--r--reference/C/CONTRIB/OR_USING_C/c.1.c96
-rw-r--r--reference/C/CONTRIB/OR_USING_C/d.1.c117
-rw-r--r--reference/C/CONTRIB/OR_USING_C/dircom.c117
-rw-r--r--reference/C/CONTRIB/OR_USING_C/e.1.c63
-rw-r--r--reference/C/CONTRIB/OR_USING_C/nap.c63
63 files changed, 4679 insertions, 0 deletions
diff --git a/reference/C/CONTRIB/OR_USING_C/02.1.c b/reference/C/CONTRIB/OR_USING_C/02.1.c
new file mode 100644
index 0000000..bade646
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/02.1.c
@@ -0,0 +1,49 @@
+
+#include <stdio.h>
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ int c;
+ FILE *from, *to;
+
+ /*
+ * Check our arguments.
+ */
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s from-file to-file\n", *argv);
+ exit(1);
+ }
+
+ /*
+ * Open the from-file for reading.
+ */
+ if ((from = fopen(argv[1], "r")) == NULL) {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ /*
+ * Open the to-file for appending. If to-file does
+ * not exist, fopen will create it.
+ */
+ if ((to = fopen(argv[2], "a")) == NULL) {
+ perror(argv[2]);
+ exit(1);
+ }
+
+ /*
+ * Now read characters from from-file until we
+ * hit end-of-file, and put them onto to-file.
+ */
+ while ((c = getc(from)) != EOF)
+ putc(c, to);
+
+ /*
+ * Now close the files.
+ */
+ fclose(from);
+ fclose(to);
+ exit(0);
+}
diff --git a/reference/C/CONTRIB/OR_USING_C/02.2.c b/reference/C/CONTRIB/OR_USING_C/02.2.c
new file mode 100644
index 0000000..7ea5ffd
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/02.2.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ FILE *from, *to;
+ char line[BUFSIZ];
+ /*
+ * Check our arguments.
+ */
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s from-file to-file\n", *argv);
+ exit(1);
+ }
+ /*
+ * Open the from-file for reading.
+ */
+ if ((from = fopen(argv[1], "r")) == NULL) {
+ perror(argv[1]);
+ exit(1);
+ }
+ /*
+ * Open the to-file for appending. If to-file does
+ * not exist, fopen will create it.
+ */
+ if ((to = fopen(argv[2], "a")) == NULL) {
+ perror(argv[2]);
+ exit(1);
+ }
+ /*
+ * Now read a line at a time from the from-file,
+ * and write it to the to-file.
+ */
+ while (fgets(line, BUFSIZ, from) != NULL)
+ fputs(line, to);
+ /*
+ * Now close the files.
+ */
+ fclose(from);
+ fclose(to);
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/02.3.c b/reference/C/CONTRIB/OR_USING_C/02.3.c
new file mode 100644
index 0000000..e669d00
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/02.3.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ int n;
+ FILE *from, *to;
+ char buf[BUFSIZ];
+
+ /*
+ * Check our arguments.
+ */
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s from-file to-file\n", *argv);
+ exit(1);
+ }
+
+ /*
+ * Open the from-file for reading.
+ */
+ if ((from = fopen(argv[1], "r")) == NULL) {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ /*
+ * Open the to-file for appending. If to-file does
+ * not exist, fopen will create it.
+ */
+ if ((to = fopen(argv[2], "a")) == NULL) {
+ perror(argv[2]);
+ exit(1);
+ }
+
+ /*
+ * Note that we only write the number of characters fread
+ * read in, rather than always writing BUFSIZ characters.
+ */
+ while ((n = fread(buf, sizeof(char), BUFSIZ, from)) > 0)
+ fwrite(buf, sizeof(char), n, to);
+
+ /*
+ * Now close the files.
+ */
+ fclose(from);
+ fclose(to);
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/02.4.c b/reference/C/CONTRIB/OR_USING_C/02.4.c
new file mode 100644
index 0000000..4f2dd28
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/02.4.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+
+main()
+{
+ int n, m;
+
+ printf("Enter a number: ");
+ scanf("%d", &n);
+
+ m = fact(n);
+ printf("The factorial of %d is %d.\n", n, m);
+ exit(0);
+}
+
+fact(n)
+int n;
+{
+ if (n == 0)
+ return(1);
+
+ return(n * fact(n-1));
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/02.5.c b/reference/C/CONTRIB/OR_USING_C/02.5.c
new file mode 100644
index 0000000..2b40798
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/02.5.c
@@ -0,0 +1,69 @@
+/*
+ *
+ */
+#include <stdio.h>
+
+struct record {
+ int uid;
+ char login[9];
+};
+
+char *logins[] = { "user1", "user2", "user3",
+ "user4", "user5" };
+
+main()
+{
+ int i;
+ FILE *fp;
+ struct record rec;
+
+ /*
+ * Open the data file for writing.
+ */
+ if ((fp = fopen("datafile", "w")) == NULL) {
+ perror("datafile");
+ exit(1);
+ }
+
+ /*
+ * For each user, going backwards...
+ */
+ for (i = 4; i >= 0; i--) {
+ /*
+ * Create the record.
+ */
+ rec.uid = i;
+ strcpy(rec.login, logins[i]);
+
+ /*
+ * Output the record. Notice we pass the
+ * address of the structure.
+ */
+ putrec(fp, i, &rec);
+ }
+
+ fclose(fp);
+ exit(0);
+}
+
+/*
+ * putrec--write the record in the i'th position.
+ */
+putrec(fp, i, r)
+int i;
+FILE *fp;
+struct record *r;
+{
+ /*
+ * Seek to the i'th position from the beginning
+ * of the file.
+ */
+ fseek(fp, (long) i * sizeof(struct record), 0);
+
+ /*
+ * Write the record. We want to write one
+ * object the size of a record structure.
+ */
+ fwrite(r, sizeof(struct record), 1, fp);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/03.1.c b/reference/C/CONTRIB/OR_USING_C/03.1.c
new file mode 100644
index 0000000..f1b7844
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/03.1.c
@@ -0,0 +1,60 @@
+/* Change <sys/file.h> to <sys/fcntl.h> if you're on System V.
+ */
+#include <sys/file.h>
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ int n;
+ int from, to;
+ char buf[1024];
+
+ /*
+ * Check our arguments. Note that to write the error
+ * message we can't just use "%s" as we did in Example
+ * 2-3; we have to write each string separately.
+ */
+ if (argc != 3) {
+ write(2, "Usage: ", 7);
+ write(2, *argv, strlen(*argv));
+ write(2, " from-file to-file\n", 19);
+ exit(1);
+ }
+
+ /*
+ * Open the from-file for reading.
+ */
+ if ((from = open(argv[1], O_RDONLY)) < 0) {
+ perror(argv[1]);
+ exit(1);
+ }
+
+ /*
+ * Open the to-file for appending. If to-file does
+ * not exist, open will create it with mode 644
+ * (-rw-r--r--). Note that we specify the mode
+ * in octal, not decimal
+ */
+ if ((to = open(argv[2], O_WRONLY|O_CREAT|O_APPEND, 0644)) < 0) {
+ perror(argv[2]);
+ exit(1);
+ }
+
+ /*
+ * Now read a buffer-full at a time from the from-file,
+ * and write it to the to-file. Note that we only
+ * write the number of characters read read in,
+ * rather than always writing 1024 characters.
+ */
+ while ((n = read(from, buf, sizeof(buf))) > 0)
+ write(to, buf, n);
+
+ /*
+ * Now close the files.
+ */
+ close(from);
+ close(to);
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/03.2.c b/reference/C/CONTRIB/OR_USING_C/03.2.c
new file mode 100644
index 0000000..69d8904
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/03.2.c
@@ -0,0 +1,67 @@
+/*
+ * If you're on System V, change <sys/file.h> to <sys/fcntl.h>.
+ */
+#include <sys/file.h>
+
+struct record {
+ int uid;
+ char login[9];
+};
+
+char *logins[] = { "user1", "user2", "user3",
+ "user4", "user5" };
+
+main()
+{
+ int i, fd;
+ struct record rec;
+
+ /*
+ * Open the data file for writing.
+ */
+ if ((fd = open("datafile", O_WRONLY | O_CREAT, 0644)) < 0) {
+ perror("datafile");
+ exit(1);
+ }
+
+ /*
+ * For each user, going backwards...
+ */
+ for (i = 4; i >= 0; i--) {
+ /*
+ * Create the record.
+ */
+ rec.uid = i;
+ strcpy(rec.login, logins[i]);
+
+ /*
+ * Output the record. Notice we pass the
+ * address of the structure.
+ */
+ putrec(fd, i, &rec);
+ }
+
+ close(fd);
+ exit(0);
+}
+
+/*
+ * putrec--write the record in the i'th position.
+ */
+putrec(fd, i, r)
+int i, fd;
+struct record *r;
+{
+ /*
+ * Seek to the i'th position from the beginning
+ * of the file.
+ */
+ lseek(fd, (long) i * sizeof(struct record), L_SET);
+
+ /*
+ * Write the record. We want to write one
+ * object the size of a record structure.
+ */
+ write(fd, r, sizeof(struct record));
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/04.1.c b/reference/C/CONTRIB/OR_USING_C/04.1.c
new file mode 100644
index 0000000..bd0db3d
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/04.1.c
@@ -0,0 +1,44 @@
+/*
+ * Non-BSD systems only.
+ */
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <stdio.h>
+
+main()
+{
+ FILE *fp;
+ struct direct dir;
+ int n;
+
+ if ((fp = fopen(".", "r")) == NULL) {
+ perror("current directory");
+ exit(1);
+ }
+
+ /*
+ * Read directory entries. Since we're reading
+ * entries one at a time, we use the fread routine,
+ * which buffers them internally. Don't use the
+ * low-level read to do things this way, since
+ * reading very small quantities of data (16 bytes)
+ * at a time is very inefficient.
+ */
+ while ((n = fread(&dir, sizeof(dir), 1, fp)) > 0) {
+ /*
+ * Skip removed files.
+ */
+ if (dir.d_ino == 0)
+ continue;
+
+ /*
+ * Make sure we print no more than DIRSIZ
+ * characters.
+ */
+ printf("%.*s\n", DIRSIZ, dir.d_name);
+ }
+
+ fclose(fp);
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/04.2.c b/reference/C/CONTRIB/OR_USING_C/04.2.c
new file mode 100644
index 0000000..2f2cde2
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/04.2.c
@@ -0,0 +1,34 @@
+/*
+ * For use with 4.2 and 4.3BSD systems.
+ */
+#include <sys/types.h>
+#include <sys/dir.h>
+#include <stdio.h>
+
+main()
+{
+ DIR *dp;
+ struct direct *dir;
+
+ if ((dp = opendir(".")) == NULL) {
+ fprintf(stderr, "cannot open directory.\n");
+ exit(1);
+ }
+
+ /*
+ * Read entries...
+ */
+ while ((dir = readdir(dp)) != NULL) {
+ /*
+ * Skip removed files.
+ */
+ if (dir->d_ino == 0)
+ continue;
+
+ printf("%s\n", dir->d_name);
+ }
+
+ closedir(dp);
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/04.3.c b/reference/C/CONTRIB/OR_USING_C/04.3.c
new file mode 100644
index 0000000..9c55974
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/04.3.c
@@ -0,0 +1,183 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <stdio.h>
+
+char *modes[] = {
+ "---", "--x", "-w-", "-wx",
+ "r--", "r-x", "rw-", "rwx"
+};
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ struct stat sbuf;
+
+ /*
+ * If no arguments, list current directory.
+ */
+ if (argc < 2) {
+ list(".");
+ exit(0);
+ }
+
+ /*
+ * Process arguments.
+ */
+ while (--argc) {
+ /*
+ * See what the file is.
+ */
+ if (stat(*++argv, &sbuf) < 0) {
+ perror(*argv);
+ continue;
+ }
+
+ /*
+ * If it's a directory we list it,
+ * otherwise just print the info about
+ * the file.
+ */
+ if ((sbuf.st_mode & S_IFMT) == S_IFDIR)
+ list(*argv);
+ else
+ printout(".", *argv);
+ }
+
+ exit(0);
+}
+
+/*
+ * list--read a directory and list the files it
+ * contains.
+ */
+list(name)
+char *name;
+{
+ DIR *dp;
+ struct direct *dir;
+
+ /*
+ * Open the directory.
+ */
+ if ((dp = opendir(name)) == NULL) {
+ fprintf(stderr, "%s: cannot open.\n", name);
+ return;
+ }
+
+ /*
+ * For each entry...
+ */
+ while ((dir = readdir(dp)) != NULL) {
+ /*
+ * Skip removed files.
+ */
+ if (dir->d_ino == 0)
+ continue;
+
+ /*
+ * Print it out.
+ */
+ printout(name, dir->d_name);
+ }
+
+ closedir(dp);
+}
+
+/*
+ * printout--print out the information about
+ * a file.
+ */
+printout(dir, name)
+char *dir, *name;
+{
+ int i, j;
+ char perms[10];
+ struct stat sbuf;
+ char newname[1024];
+
+ /*
+ * Make full path name, so
+ * we have a legal path.
+ */
+ sprintf(newname, "%s/%s", dir, name);
+
+ /*
+ * At this point we know the file exists,
+ * so this won't fail.
+ */
+ stat(newname, &sbuf);
+
+ /*
+ * Print size in kbytes.
+ */
+ printf("%5d ", (sbuf.st_size + 1023) / 1024);
+
+ /*
+ * Get the file type. For convenience (and to
+ * make this example universal), we ignore the
+ * other types which are version-dependent.
+ */
+ switch (sbuf.st_mode & S_IFMT) {
+ case S_IFREG: putchar('-'); break;
+ case S_IFDIR: putchar('d'); break;
+ case S_IFCHR: putchar('c'); break;
+ case S_IFBLK: putchar('b'); break;
+ default: putchar('?'); break;
+ }
+
+ /*
+ * Get each of the three groups of permissions
+ * (owner, group, world). Since they're just
+ * bits, we can count in binary and use this
+ * as a subscript (see the modes array, above).
+ */
+ *perms = NULL;
+ for (i = 2; i >= 0; i--) {
+ /*
+ * Since we're subscripting, we don't
+ * need the constants. Just get a
+ * value between 0 and 7.
+ */
+ j = (sbuf.st_mode >> (i*3)) & 07;
+
+ /*
+ * Get the perm bits.
+ */
+ strcat(perms, modes[j]);
+ }
+
+ /*
+ * Handle special bits which replace the 'x'
+ * in places.
+ */
+ if ((sbuf.st_mode & S_ISUID) != 0)
+ perms[2] = 's';
+ if ((sbuf.st_mode & S_ISGID) != 0)
+ perms[5] = 's';
+ if ((sbuf.st_mode & S_ISVTX) != 0)
+ perms[8] = 't';
+
+ /*
+ * Print permissions, number of links,
+ * user and group ids.
+ */
+ printf("%s%3d %5d/%-5d ", perms, sbuf.st_nlink, sbuf.st_uid,
+ sbuf.st_gid);
+
+ /*
+ * Print the size of the file in bytes,
+ * and the last modification time. The
+ * ctime routine converts a time to ASCII;
+ * it is described in Chapter 7, Telling
+ * Time and Timing Things.
+ */
+ printf("%7d %.12s ", sbuf.st_size, ctime(&sbuf.st_mtime)+4);
+
+ /*
+ * Finally, print the filename.
+ */
+ printf("%s\n", name);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/05.1.c b/reference/C/CONTRIB/OR_USING_C/05.1.c
new file mode 100644
index 0000000..7438fdc
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/05.1.c
@@ -0,0 +1,102 @@
+#include <sys/ioctl.h>
+#include <stdio.h>
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ struct sgttyb sgo, sgn;
+ struct tchars tco, tcn;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s file [file ...]\n", *argv);
+ exit(1);
+ }
+
+ /*
+ * In real life we'd check the return values of
+ * these, since if the input is redirected from
+ * a file they will fail. We are assuming the
+ * terminal is always connected to the standard
+ * input.
+ */
+ ioctl(0, TIOCGETP, &sgo);
+ ioctl(0, TIOCGETC, &tco);
+
+ sgn = sgo;
+ sgn.sg_flags &= ~ECHO; /* turn off ECHO */
+ sgn.sg_flags |= CBREAK; /* turn on CBREAK */
+
+ tcn = tco;
+ tcn.t_intrc = -1; /* disable int key */
+
+ /*
+ * Set the new modes. Again we ignore return
+ * values.
+ */
+ ioctl(0, TIOCSETP, &sgn);
+ ioctl(0, TIOCSETC, &tcn);
+
+ while (--argc)
+ more(*++argv);
+
+ /*
+ * Reset the old tty modes.
+ */
+ ioctl(0, TIOCSETP, &sgo);
+ ioctl(0, TIOCSETC, &tco);
+
+ exit(0);
+}
+
+/*
+ * more--display the file.
+ */
+more(file)
+char *file;
+{
+ FILE *fp;
+ int line;
+ char linebuf[1024];
+
+ if ((fp = fopen(file, "r")) == NULL) {
+ perror(file);
+ return;
+ }
+
+ /*
+ * Print 22 lines at a time.
+ */
+ for (;;) {
+ line = 1;
+ while (line < 22) {
+ /*
+ * If end-of-file, let them hit a key one
+ * more time and then go back.
+ */
+ if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
+ fclose(fp);
+ prompt();
+ return;
+ }
+
+ fwrite(linebuf, 1, strlen(linebuf), stdout);
+ line++;
+ }
+
+ prompt();
+ }
+}
+
+/*
+ * prompt--prompt for a character.
+ */
+prompt()
+{
+ char answer;
+
+ printf("Type any character for next page: ");
+ answer = getchar();
+ putchar('\n');
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/05.2.c b/reference/C/CONTRIB/OR_USING_C/05.2.c
new file mode 100644
index 0000000..592e474
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/05.2.c
@@ -0,0 +1,101 @@
+#include <termio.h>
+#include <stdio.h>
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ struct termio tio, tin;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s file [file ...]\n", *argv);
+ exit(1);
+ }
+
+ /*
+ * In real life we'd check the return value of
+ * this, since if the input is redirected from a
+ * file it will fail. We are assuming the
+ * terminal is always connected to the standard
+ * input.
+ */
+ ioctl(0, TCGETA, &tio);
+
+ tin = tio;
+ tin.c_lflag &= ~ECHO; /* turn off ECHO */
+ tin.c_lflag &= ~ICANON; /* turn off ICANON */
+
+ /*
+ * Emulate CBREAK mode.
+ */
+ tin.c_cc[VMIN] = 1;
+ tin.c_cc[VTIME] = 0;
+
+ /*
+ * Set the new modes. Again we ignore return
+ * values.
+ */
+ ioctl(0, TCSETA, &tin);
+
+ while (--argc)
+ more(*++argv);
+
+ /*
+ * Reset the old tty modes.
+ */
+ ioctl(0, TCSETA, &tio);
+
+ exit(0);
+}
+
+/*
+ * more--display the file.
+ */
+more(file)
+char *file;
+{
+ FILE *fp;
+ int line;
+ char linebuf[1024];
+
+ if ((fp = fopen(file, "r")) == NULL) {
+ perror(file);
+ return;
+ }
+
+ /*
+ * Print 22 lines at a time.
+ */
+ for (;;) {
+ line = 1;
+ while (line < 22) {
+ /*
+ * If end-of-file, let them hit a key one
+ * more time and then go back.
+ */
+ if (fgets(linebuf, sizeof(linebuf), fp) == NULL) {
+ fclose(fp);
+ prompt();
+ return;
+ }
+
+ fwrite(linebuf, 1, strlen(linebuf), stdout);
+ line++;
+ }
+
+ prompt();
+ }
+}
+
+/*
+ * prompt--prompt for a character.
+ */
+prompt()
+{
+ char answer;
+
+ printf("Type any character for next page: ");
+ answer = getchar();
+ putchar('\n');
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/05.3.c b/reference/C/CONTRIB/OR_USING_C/05.3.c
new file mode 100644
index 0000000..9457d07
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/05.3.c
@@ -0,0 +1,61 @@
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+
+main()
+{
+ int n, nfds;
+ char buf[32];
+ fd_set readfds;
+ struct timeval tv;
+
+ /*
+ * We will be reading from standard input (file
+ * descriptor 0), so we want to know when the
+ * user has typed something.
+ */
+ FD_ZERO(&readfds);
+ FD_SET(0, &readfds);
+
+ /*
+ * Set the timeout for 15 seconds.
+ */
+ tv.tv_sec = 15;
+ tv.tv_usec = 0;
+
+ /*
+ * Prompt for input.
+ */
+ printf("Type a word; if you don't in 15 ");
+ printf("seconds I'll use \"WORD\": ");
+ fflush(stdout);
+
+ /*
+ * Now call select. We pass NULL for
+ * writefds and exceptfds, since we
+ * aren't interested in them.
+ */
+ nfds = select(1, &readfds, NULL, NULL, &tv);
+
+ /*
+ * Now we check the results. If nfds is zero,
+ * then we timed out, and should assume the
+ * default. Otherwise, if file descriptor 0
+ * is set in readfds, that means that it is
+ * ready to be read, and we can read something
+ * from it.
+ */
+ if (nfds == 0) {
+ strcpy(buf, "WORD");
+ }
+ else {
+ if (FD_ISSET(0, &readfds)) {
+ n = read(0, buf, sizeof(buf));
+ buf[n-1] = '\0';
+ }
+ }
+
+ printf("\nThe word is: %s\n", buf);
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/06.1.c b/reference/C/CONTRIB/OR_USING_C/06.1.c
new file mode 100644
index 0000000..2efc718
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/06.1.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <utmp.h>
+#include <pwd.h>
+
+#define UTMP "/etc/utmp"
+#define NAMELEN 8
+
+main()
+{
+ FILE *fp;
+ struct utmp u;
+ struct passwd *p;
+ char tmp[NAMELEN+1];
+ struct passwd *getpwnam();
+
+ if ((fp = fopen(UTMP, "r")) == NULL) {
+ perror(UTMP);
+ exit(1);
+ }
+
+ /*
+ * For each entry...
+ */
+ while (fread(&u, sizeof(u), 1, fp) != NULL) {
+ /*
+ * Skip non-logged in ports.
+ */
+ if (u.ut_name[0] == NULL)
+ continue;
+
+ /*
+ * Make sure name is null-terminated.
+ */
+ strncpy(tmp, u.ut_name, NAMELEN);
+
+ /*
+ * Skip non-existent users (shouldn't
+ * be any).
+ */
+ if ((p = getpwnam(tmp)) == NULL)
+ continue;
+
+ /*
+ * Print the line. ctime() converts the time
+ * to ASCII format, it is described in Chapter
+ * 7, Telling Time and Timing Things. We
+ * ignore the format of the gecos field and
+ * just print the first 30 characters; in real
+ * life we would stop at a comma or some such.
+ */
+ printf("%-10.8s %-10.8s %-30.30s %s", u.ut_name,
+ u.ut_line, p->pw_gecos, ctime(&u.ut_time));
+ }
+
+ fclose(fp);
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/07.1.c b/reference/C/CONTRIB/OR_USING_C/07.1.c
new file mode 100644
index 0000000..19ae68e
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/07.1.c
@@ -0,0 +1,21 @@
+#include <sys/types.h>
+#include <sys/times.h>
+
+main()
+{
+ struct tms before, after;
+
+ times(&before);
+
+ /* ... place code to be timed here ... */
+
+ times(&after);
+
+ printf("User time: %ld seconds\n", after.tms_utime -
+ before.tms_utime);
+ printf("System time: %ld seconds\n", after.tms_stime -
+ before.tms_stime);
+
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/08.1.c b/reference/C/CONTRIB/OR_USING_C/08.1.c
new file mode 100644
index 0000000..3a5cf10
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/08.1.c
@@ -0,0 +1,13 @@
+#include <signal.h>
+
+main()
+{
+ signal(SIGINT, SIG_IGN);
+
+ /*
+ * pause() just suspends the process until a
+ * signal is received.
+ */
+ pause();
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/08.2.c b/reference/C/CONTRIB/OR_USING_C/08.2.c
new file mode 100644
index 0000000..e54d99d
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/08.2.c
@@ -0,0 +1,36 @@
+#include <signal.h>
+
+main()
+{
+ /*
+ * Declare handler routine so we can use its name.
+ */
+ extern int handler();
+
+ /*
+ * Send signal to handler routine.
+ */
+ signal(SIGINT, handler);
+
+ /*
+ * Loop here.
+ */
+ for (;;)
+ pause();
+}
+
+/*
+ * handler--handle the signal.
+ */
+handler()
+{
+ /*
+ * Users of 4.2 and 4.3BSD systems should un-comment
+ * this line, which will make this program
+ * behave as if it were on a non-Berkeley system.
+ */
+ /* signal(SIGINT, SIG_DFL); */
+
+ printf("OUCH\n");
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/08.3.c b/reference/C/CONTRIB/OR_USING_C/08.3.c
new file mode 100644
index 0000000..d6ec5f2
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/08.3.c
@@ -0,0 +1,42 @@
+#include <signal.h>
+
+main()
+{
+ /*
+ * Declare handler routine so we can use its
+ * name.
+ */
+ extern int handler();
+
+ /*
+ * Send signal to handler routine.
+ */
+ signal(SIGINT, handler);
+
+ /*
+ * Loop here.
+ */
+ for (;;)
+ pause();
+}
+
+/*
+ * handler--handle the signal.
+ */
+handler()
+{
+ /*
+ * Users of 4.2 and 4.3BSD systems should un-comment
+ * this line, which will make this program
+ * behave as if it were on a non-Berkeley system.
+ */
+ /* signal(SIGINT, SIG_DFL); */
+
+ printf("OUCH\n");
+
+ /*
+ * Reset the signal to come here again.
+ */
+ signal(SIGINT, handler);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/08.4.c b/reference/C/CONTRIB/OR_USING_C/08.4.c
new file mode 100644
index 0000000..3bcc96c
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/08.4.c
@@ -0,0 +1,47 @@
+#include <signal.h>
+
+main()
+{
+ /*
+ * Declare handler routine so we can use its
+ * name.
+ */
+ extern int handler();
+ /*
+ * Send signal to handler routine. Only do so
+ * if the signal is not already being ignored.
+ */
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN)
+ signal(SIGINT, handler);
+ /*
+ * Loop here.
+ */
+ for (;;)
+ pause();
+}
+/*
+ * handler--handle the signal. sig is the signal
+ * number which interrupted us.
+ */
+handler(sig)
+int sig;
+{
+ /*
+ * Users of 4.2 and 4.3BSD systems should un-comment
+ * this line, which will make this program
+ * behave as if it were on a non-Berkeley
+ * system (we reset the signal by hand).
+ */
+ /* signal(sig, SIG_DFL); */
+ /*
+ * Ignore the signal for the duration of this
+ * routine.
+ */
+ signal(sig, SIG_IGN);
+ printf("OUCH\n");
+ /*
+ * Reset the signal to come here again.
+ */
+ signal(SIGINT, handler);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/08.5.c b/reference/C/CONTRIB/OR_USING_C/08.5.c
new file mode 100644
index 0000000..47b0402
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/08.5.c
@@ -0,0 +1,85 @@
+#include <signal.h>
+#include <setjmp.h>
+
+/*
+ * The environment for setjmp.
+ */
+jmp_buf env;
+
+main()
+{
+ int i;
+ char buf[16];
+ extern int timeout();
+
+ /*
+ * Inform the system we want to catch the
+ * alarm signal.
+ */
+ signal(SIGALRM, timeout);
+
+ /*
+ * The code inside the if gets executed the first
+ * time through setjmp, the code inside the else
+ * the second time.
+ */
+ if (setjmp(env) == 0) {
+ /*
+ * Issue a request for an alarm to be
+ * delivered in 15 seconds.
+ */
+ alarm(15);
+
+ /*
+ * Prompt for input.
+ */
+ printf("Type a word; if you don't in 15 ");
+ printf("seconds I'll use \"WORD\": ");
+ gets(buf);
+
+ /*
+ * Turn off the alarm.
+ */
+ alarm(0);
+ }
+ else {
+ /*
+ * Assume the default.
+ */
+ strcpy(buf, "WORD");
+ }
+
+ printf("\nThe word is: %s\n", buf);
+ exit(0);
+}
+
+/*
+ * timeout--catch the signal.
+ */
+timeout(sig)
+int sig;
+{
+ /*
+ * Ignore the signal for the duration of this
+ * routine.
+ */
+ signal(sig, SIG_IGN);
+
+ /*
+ * We would perform any timeout-related
+ * functions here; in this case there
+ * are none.
+ */
+
+ /*
+ * Restore the action of the alarm signal.
+ */
+ signal(SIGALRM, timeout);
+
+ /*
+ * Return to the main routine at setjmp,
+ * and make setjmp return 1.
+ */
+ longjmp(env, 1);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/08.6.c b/reference/C/CONTRIB/OR_USING_C/08.6.c
new file mode 100644
index 0000000..80ccd1e
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/08.6.c
@@ -0,0 +1,33 @@
+#include <signal.h>
+
+/*
+ * work, work, work, all I ever do is work!
+ */
+dowork()
+{
+}
+
+main()
+{
+ int mask;
+
+ /*
+ * Block SIGIO, which will indicate more
+ * work to be done.
+ */
+ mask = sigmask(SIGIO);
+
+ for (;;) {
+ /*
+ * Go do work.
+ */
+ dowork();
+
+ /*
+ * Pause until we receive a signal.
+ * SIGIO is not blocked in mask.
+ */
+ sigpause(mask);
+ }
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/08.7.c b/reference/C/CONTRIB/OR_USING_C/08.7.c
new file mode 100644
index 0000000..5518c96
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/08.7.c
@@ -0,0 +1,108 @@
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <signal.h>
+#include <stdio.h>
+
+char *stack; /* pointer to signal stack base */
+int tooksig = 0; /* 1 after we take the signal */
+
+main()
+{
+ extern void x();
+ struct sigvec sv;
+ struct sigstack ss;
+ struct rlimit rlimit;
+
+ /*
+ * Set stack size limit to 50 kbytes.
+ */
+ getrlimit(RLIMIT_STACK, &rlimit);
+ rlimit.rlim_cur = 50 * 1024;
+
+ if (setrlimit(RLIMIT_STACK, &rlimit) < 0) {
+ perror("setrlimit");
+ exit(1);
+ }
+
+ /*
+ * Take illegal instruction and process it with x,
+ * on the interrupt stack. For 4.2BSD, change
+ * sv_flags to sv_onstack and SV_ONSTACK to 1.
+ */
+ sv.sv_mask = 0;
+ sv.sv_handler = x;
+ sv.sv_flags = SV_ONSTACK;
+ sigvec(SIGILL, &sv, (struct sigvec *) 0);
+
+ /*
+ * Allocate memory for the signal stack. The
+ * kernel assumes the addresses grow in the same
+ * direction as on the process stack (toward
+ * lower addresses, on a VAX).
+ */
+ if ((stack = (char *) malloc(10240)) == NULL) {
+ fprintf(stderr, "Out of memory.\n");
+ exit(1);
+ }
+
+ /*
+ * Issue the call to tell the system about the
+ * signal stack. We pass the end of the signal
+ * stack, not the beginning, since the stack
+ * grows toward lower addresses.
+ */
+ ss.ss_onstack = 0;
+ ss.ss_sp = (caddr_t) stack + 10240;
+
+ if (sigstack(&ss, (struct sigstack *) 0) < 0) {
+ perror("sigstack");
+ exit(1);
+ }
+
+ /*
+ * Start using up stack space.
+ */
+ y();
+}
+
+y()
+{
+ /*
+ * Take up 5k of stack space.
+ */
+ char buf[5120];
+
+ printf("%s\n", tooksig ? "Now on extended stack." :
+ "On 50k stack.");
+
+ /*
+ * Recurse.
+ */
+ y();
+}
+
+/*
+ * Handle the signal.
+ */
+void x(sig, code, scp)
+int sig, code;
+struct sigcontext *scp;
+{
+ struct rlimit rlimit;
+
+ /*
+ * Increase the stack limit to the maximum.
+ */
+ getrlimit(RLIMIT_STACK, &rlimit);
+ rlimit.rlim_cur = rlimit.rlim_max;
+
+ if (setrlimit(RLIMIT_STACK, &rlimit) < 0) {
+ perror("setrlimit");
+ exit(1);
+ }
+
+ tooksig = 1;
+ return;
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/09.1.c b/reference/C/CONTRIB/OR_USING_C/09.1.c
new file mode 100644
index 0000000..035186d
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/09.1.c
@@ -0,0 +1,95 @@
+#include <stdio.h>
+
+main()
+{
+ char buf[1024];
+ char *args[64];
+
+ for (;;) {
+ /*
+ * Prompt for and read a command.
+ */
+ printf("Command: ");
+
+ if (gets(buf) == NULL) {
+ printf("\n");
+ exit(0);
+ }
+
+ /*
+ * Split the string into arguments.
+ */
+ parse(buf, args);
+
+ /*
+ * Execute the command.
+ */
+ execute(args);
+ }
+}
+
+/*
+ * parse--split the command in buf into
+ * individual arguments.
+ */
+parse(buf, args)
+char *buf;
+char **args;
+{
+ while (*buf != NULL) {
+ /*
+ * Strip whitespace. Use nulls, so
+ * that the previous argument is terminated
+ * automatically.
+ */
+ while ((*buf == ' ') || (*buf == '\t'))
+ *buf++ = NULL;
+
+ /*
+ * Save the argument.
+ */
+ *args++ = buf;
+
+ /*
+ * Skip over the argument.
+ */
+ while ((*buf != NULL) && (*buf != ' ') && (*buf != '\t'))
+ buf++;
+ }
+
+ *args = NULL;
+}
+
+/*
+ * execute--spawn a child process and execute
+ * the program.
+ */
+execute(args)
+char **args;
+{
+ int pid, status;
+
+ /*
+ * Get a child process.
+ */
+ if ((pid = fork()) < 0) {
+ perror("fork");
+ exit(1);
+ }
+
+ /*
+ * The child executes the code inside the if.
+ */
+ if (pid == 0) {
+ execvp(*args, args);
+ perror(*args);
+ exit(1);
+ }
+
+ /*
+ * The parent executes the wait.
+ */
+ while (wait(&status) != pid)
+ /* empty */ ;
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/09.2.c b/reference/C/CONTRIB/OR_USING_C/09.2.c
new file mode 100644
index 0000000..82ad2bb
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/09.2.c
@@ -0,0 +1,52 @@
+execute(args, sin, sout, serr)
+char **args;
+int sin, sout, serr;
+{
+ int pid, status;
+
+ /*
+ * Get a child process.
+ */
+ if ((pid = fork()) < 0) {
+ perror("fork");
+ exit(1);
+ }
+
+ /*
+ * The child executes the code inside the if.
+ */
+ if (pid == 0) {
+ /*
+ * For each of standard input, output,
+ * and error output, set the child's
+ * to the passed-down file descriptor.
+ * Note that we can't just close 0, 1,
+ * and 2 since we might need them.
+ */
+ if (sin != 0) {
+ close(0);
+ dup(sin); /* will give us fd #0 */
+ }
+
+ if (sout != 1) {
+ close(1);
+ dup(sout); /* will give us fd #1 */
+ }
+
+ if (serr != 2) {
+ close(2);
+ dup(serr); /* will give us fd #2 */
+ }
+
+ execvp(*args, args);
+ perror(*args);
+ exit(1);
+ }
+
+ /*
+ * The parent executes the wait.
+ */
+ while (wait(&status) != pid)
+ /* empty loop */;
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/09.3.c b/reference/C/CONTRIB/OR_USING_C/09.3.c
new file mode 100644
index 0000000..25b6e44
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/09.3.c
@@ -0,0 +1,87 @@
+#include <stdio.h>
+
+main()
+{
+ FILE *fp;
+ int pid, pipefds[2];
+ char *username, *getlogin();
+
+ /*
+ * Get the user's name.
+ */
+ if ((username = getlogin()) == NULL) {
+ fprintf(stderr, "Who are you?\n");
+ exit(1);
+ }
+
+ /*
+ * Create the pipe. This has to be done
+ * BEFORE the fork.
+ */
+ if (pipe(pipefds) < 0) {
+ perror("pipe");
+ exit(1);
+ }
+
+ if ((pid = fork()) < 0) {
+ perror("fork");
+ exit(1);
+ }
+
+ /*
+ * The child process executes the stuff inside
+ * the if.
+ */
+ if (pid == 0) {
+ /*
+ * Make the read side of the pipe our
+ * standard input.
+ */
+ close(0);
+ dup(pipefds[0]);
+ close(pipefds[0]);
+
+ /*
+ * Close the write side of the pipe;
+ * we'll let our output go to the screen.
+ */
+ close(pipefds[1]);
+ /*
+ * Execute the command "mail username".
+ */
+ execl("/bin/mail", "mail", username, 0);
+ perror("exec");
+ exit(1);
+ }
+
+ /*
+ * The parent executes this code.
+ */
+
+ /*
+ * Close the read side of the pipe; we
+ * don't need it (and the child is not
+ * writing on the pipe anyway).
+ */
+ close(pipefds[0]);
+
+ /*
+ * Convert the write side of the pipe to stdio.
+ */
+ fp = fdopen(pipefds[1], "w");
+
+ /*
+ * Send a message, close the pipe.
+ */
+ fprintf(fp, "Hello from your program.\n");
+ fclose(fp);
+
+ /*
+ * Wait for the process to terminate.
+ */
+ while (wait((int *) 0) != pid)
+ ;
+
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/09.4.c b/reference/C/CONTRIB/OR_USING_C/09.4.c
new file mode 100644
index 0000000..dba1cd6
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/09.4.c
@@ -0,0 +1,91 @@
+/*
+ * mailer - open a pipe to the mail command and send the user
+ * mail.
+ */
+#include <stdio.h>
+
+main()
+{
+ FILE *fp;
+ int pid, pipefds[2];
+ char *username, *getlogin();
+
+ /*
+ * Get the user's name.
+ */
+ if ((username = getlogin()) == NULL) {
+ fprintf(stderr, "Who are you?\n");
+ exit(1);
+ }
+
+ /*
+ * Create the pipe. This has to be done
+ * BEFORE the fork.
+ */
+ if (pipe(pipefds) < 0) {
+ perror("pipe");
+ exit(1);
+ }
+
+ if ((pid = fork()) < 0) {
+ perror("fork");
+ exit(1);
+ }
+
+ /*
+ * The child process executes the stuff inside
+ * the if.
+ */
+ if (pid == 0) {
+ /*
+ * Make the read side of the pipe our
+ * standard input.
+ */
+ close(0);
+ dup(pipefds[0]);
+ close(pipefds[0]);
+
+ /*
+ * Close the write side of the pipe;
+ * we'll let our output go to the screen.
+ */
+ close(pipefds[1]);
+
+ /*
+ * Execute the command "mail username".
+ */
+ execl("/bin/mail", "mail", username, 0);
+ perror("exec");
+ exit(1);
+ }
+
+ /*
+ * The parent executes this code.
+ */
+
+ /*
+ * Close the read side of the pipe; we
+ * don't need it (and the child is not
+ * writing on the pipe anyway).
+ */
+ close(pipefds[0]);
+
+ /*
+ * Convert the write side of the pipe to stdio.
+ */
+ fp = fdopen(pipefds[1], "w");
+
+ /*
+ * Send a message, close the pipe.
+ */
+ fprintf(fp, "Hello from your program.\n");
+ fclose(fp);
+
+ /*
+ * Wait for the process to terminate.
+ */
+ while (wait((int *) 0) != pid)
+ ;
+
+ exit(0);
+}
diff --git a/reference/C/CONTRIB/OR_USING_C/10.1.c b/reference/C/CONTRIB/OR_USING_C/10.1.c
new file mode 100644
index 0000000..999d4d3
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/10.1.c
@@ -0,0 +1,39 @@
+#include <sys/ioctl.h>
+#include "10.h"
+
+int MyPid; /* the shell's process id */
+int MyPgrp; /* the shell's process group */
+int TermPgrp; /* the terminal's process group */
+
+setup()
+{
+ /*
+ * Obtain shell's process id.
+ */
+ MyPid = getpid();
+
+ /*
+ * Just use pid for process group. This is
+ * not a requirement, just convenient. Other
+ * ways of picking a process group can be used.
+ */
+ MyPgrp = MyPid;
+ TermPgrp = MyPid;
+
+ /*
+ * Set the shell's process group.
+ */
+ if (setpgrp(MyPid, MyPgrp) < 0) {
+ perror("setpgrp");
+ exit(1);
+ }
+
+ /*
+ * Set the terminal's process group.
+ */
+ if (ioctl(1, TIOCSPGRP, &MyPgrp) < 0) {
+ perror("ioctl");
+ exit(1);
+ }
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/10.2.c b/reference/C/CONTRIB/OR_USING_C/10.2.c
new file mode 100644
index 0000000..c9ee9dd
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/10.2.c
@@ -0,0 +1,37 @@
+#include <signal.h>
+#include <sys/ioctl.h>
+#include "10.h"
+
+stop(j)
+JOB *j;
+{
+ /*
+ * If the job is already stopped, we don't
+ * need to do anything.
+ */
+ if (j->status & JSTOPPED)
+ return;
+
+ /*
+ * If the job's process group is not that of the
+ * terminal, then the job is in the background
+ * and must be sent a stop signal.
+ */
+ if (j->pgrp != TermPgrp)
+ killpg(j->pgrp, SIGSTOP);
+
+ /*
+ * Mark the job as stopped.
+ */
+ j->status |= JSTOPPED;
+
+ /*
+ * If the terminal is not in the shell's process
+ * group, we need to put it there.
+ */
+ if (TermPgrp != MyPgrp) {
+ ioctl(1, TIOCSPGRP, &MyPgrp);
+ TermPgrp = MyPgrp;
+ }
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/10.3.c b/reference/C/CONTRIB/OR_USING_C/10.3.c
new file mode 100644
index 0000000..b5179cf
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/10.3.c
@@ -0,0 +1,26 @@
+#include <signal.h>
+#include <sys/ioctl.h>
+#include "10.h"
+
+bg(j)
+JOB *j;
+{
+ /*
+ * If the job is already running,
+ * there's no need to start it.
+ */
+ if (j->status & JRUNNING)
+ return;
+
+ /*
+ * Start the job.
+ */
+ killpg(j->pgrp, SIGCONT);
+
+ /*
+ * Mark the job as running.
+ */
+ j->status &= ~JSTOPPED;
+ j->status |= JRUNNING;
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/10.4.c b/reference/C/CONTRIB/OR_USING_C/10.4.c
new file mode 100644
index 0000000..48cbdc7
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/10.4.c
@@ -0,0 +1,32 @@
+#include <signal.h>
+#include <sys/ioctl.h>
+#include "10.h"
+
+fg(j)
+JOB *j;
+{
+ /*
+ * If the terminal is not in the job's process
+ * group, change the process group of the
+ * terminal.
+ */
+ if (j->pgrp != TermPgrp) {
+ ioctl(1, TIOCSPGRP, &j->pgrp);
+ TermPgrp = j->pgrp;
+ }
+
+ /*
+ * If the job is not running, start it up.
+ */
+ if (j->status & JSTOPPED) {
+ killpg(j->pgrp, SIGCONT);
+ j->status &= ~JSTOPPED;
+ j->status |= JRUNNING;
+ }
+
+ /*
+ * Go wait for the job to complete.
+ */
+ waitfor();
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/10.5.c b/reference/C/CONTRIB/OR_USING_C/10.5.c
new file mode 100644
index 0000000..df6140b
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/10.5.c
@@ -0,0 +1,132 @@
+#include <sys/wait.h>
+#include <sys/signal.h>
+#include <sys/ioctl.h>
+#include "10.h"
+
+waitfor()
+{
+ int pid;
+ JOB *j;
+ PROC *p;
+ JOB *findjob();
+ union wait status;
+
+ /*
+ * As long as we get something's status back...
+ */
+ while ((pid = wait3(&status, WUNTRACED, 0)) >= 0) {
+ /*
+ * Find the job structure which has this
+ * process.
+ */
+ j = findjob(pid);
+
+ /*
+ * Find the process structure.
+ */
+ for (p = j->procs; p->pid != pid; p = p->next)
+ /* empty */ ;
+
+ /*
+ * Find out what happened to the process.
+ */
+ if (WIFSTOPPED(status)) {
+ /*
+ * See if we know the reason it was
+ * stopped. The w_stopsig element of
+ * the structure contains the number
+ * of the signal which stopped the
+ * process.
+ */
+ switch (status.w_stopsig) {
+ case SIGTTIN:
+ p->status |= PTTYINPUT;
+ break;
+ case SIGTTOU:
+ p->status |= PTTYOUTPUT;
+ break;
+ case SIGSTOP:
+ p->status |= PSTOPSIGNAL;
+ break;
+ default:
+ break;
+ }
+
+ p->status |= PSTOPPED;
+ j->status |= JNEEDNOTE;
+ }
+ else if (WIFEXITED(status)) {
+ /*
+ * Normal termination.
+ */
+ if (status.w_retcode == 0)
+ p->status |= PDONE;
+ else
+ p->status |= PEXITED;
+
+ p->exitcode = status.w_retcode;
+
+ /*
+ * We're only going to note processes
+ * exiting if all the processes in the
+ * job are complete.
+ */
+ if (alldone(j))
+ j->status |= JNEEDNOTE;
+ }
+ else if (WIFSIGNALED(status)) {
+ p->status |= PSIGNALED;
+
+ /*
+ * Save the termination signal.
+ */
+ p->termsig = status.w_termsig;
+
+ /*
+ * Check for a core dump.
+ */
+ if (status.w_coredump)
+ p->status |= PCOREDUMP;
+
+ /*
+ * We're only going to note processes
+ * exiting if all the processes in the
+ * job are complete.
+ */
+ if (alldone(j))
+ j->status |= JNEEDNOTE;
+ }
+
+ /*
+ * If this process is the one which was in the
+ * foreground, we need to do special things,
+ * and then return to the main control section
+ * of the shell.
+ */
+ if (j->pgrp == TermPgrp) {
+ /*
+ * If the job is stopped, we need to call
+ * the stop routine.
+ */
+ if (WIFSTOPPED(status)) {
+ stop(j);
+ printf("Stopped\n");
+ }
+
+ /*
+ * If the job exited or died somehow, we
+ * need to regain control of the terminal.
+ */
+ if (WIFEXITED(status) || WIFSIGNALED(status)) {
+ ioctl(1, TIOCSPGRP, &MyPgrp);
+ TermPgrp = MyPgrp;
+ }
+
+ /*
+ * Go back.
+ */
+ return;
+ }
+ }
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/10.h b/reference/C/CONTRIB/OR_USING_C/10.h
new file mode 100644
index 0000000..87e0054
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/10.h
@@ -0,0 +1,34 @@
+
+extern int MyPid; /* the shell's process id */
+extern int MyPgrp; /* the shell's process group */
+extern int TermPgrp; /* the terminal's process group */
+
+#define JSTOPPED (1L<<1)
+#define JRUNNING (1L<<2)
+#define JNEEDNOTE (1L<<3)
+
+#define PTTYINPUT (1L<<1)
+#define PTTYOUTPUT (1L<<2)
+#define PSTOPSIGNAL (1L<<3)
+#define PSTOPPED (1L<<4)
+#define PDONE (1L<<5)
+#define PEXITED (1L<<6)
+#define PCOREDUMP (1L<<7)
+#define PSIGNALED (1L<<8)
+
+struct _PROC {
+ int pid;
+ int status;
+ int exitcode;
+ int termsig;
+ struct _PROC *next;
+};
+typedef struct _PROC PROC;
+
+struct _JOB {
+ int status;
+ int pgrp;
+ PROC *procs;
+};
+typedef struct _JOB JOB;
+
diff --git a/reference/C/CONTRIB/OR_USING_C/11.1.c b/reference/C/CONTRIB/OR_USING_C/11.1.c
new file mode 100644
index 0000000..34be61e
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/11.1.c
@@ -0,0 +1,91 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
+
+#define NSTRS 3 /* no. of strings */
+#define ADDRESS "mysocket" /* addr to connect */
+
+/*
+ * Strings we send to the server.
+ */
+char *strs[NSTRS] = {
+ "This is the first string from the client.\n",
+ "This is the second string from the client.\n",
+ "This is the third string from the client.\n"
+};
+
+main()
+{
+ char c;
+ FILE *fp;
+ register int i, s, len;
+ struct sockaddr_un saun;
+
+ /*
+ * Get a socket to work with. This socket will
+ * be in the UNIX domain, and will be a
+ * stream socket.
+ */
+ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ perror("client: socket");
+ exit(1);
+ }
+
+ /*
+ * Create the address we will be connecting to.
+ */
+ saun.sun_family = AF_UNIX;
+ strcpy(saun.sun_path, ADDRESS);
+
+ /*
+ * Try to connect to the address. For this to
+ * succeed, the server must already have bound
+ * this address, and must have issued a listen()
+ * request.
+ *
+ * The third argument indicates the "length" of
+ * the structure, not just the length of the
+ * socket name.
+ */
+ len = sizeof(saun.sun_family) + strlen(saun.sun_path);
+
+ if (connect(s, &saun, len) < 0) {
+ perror("client: connect");
+ exit(1);
+ }
+
+ /*
+ * We'll use stdio for reading
+ * the socket.
+ */
+ fp = fdopen(s, "r");
+
+ /*
+ * First we read some strings from the server
+ * and print them out.
+ */
+ for (i = 0; i < NSTRS; i++) {
+ while ((c = fgetc(fp)) != EOF) {
+ putchar(c);
+
+ if (c == '\n')
+ break;
+ }
+ }
+
+ /*
+ * Now we send some strings to the server.
+ */
+ for (i = 0; i < NSTRS; i++)
+ send(s, strs[i], strlen(strs[i]), 0);
+
+ /*
+ * We can simply use close() to terminate the
+ * connection, since we're done with both sides.
+ */
+ close(s);
+
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/11.2.c b/reference/C/CONTRIB/OR_USING_C/11.2.c
new file mode 100644
index 0000000..18140aa
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/11.2.c
@@ -0,0 +1,109 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
+
+#define NSTRS 3 /* no. of strings */
+#define ADDRESS "mysocket" /* addr to connect */
+
+/*
+ * Strings we send to the client.
+ */
+char *strs[NSTRS] = {
+ "This is the first string from the server.\n",
+ "This is the second string from the server.\n",
+ "This is the third string from the server.\n"
+};
+
+main()
+{
+ char c;
+ FILE *fp;
+ int fromlen;
+ register int i, s, ns, len;
+ struct sockaddr_un saun, fsaun;
+
+ /*
+ * Get a socket to work with. This socket will
+ * be in the UNIX domain, and will be a
+ * stream socket.
+ */
+ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
+ perror("server: socket");
+ exit(1);
+ }
+
+ /*
+ * Create the address we will be binding to.
+ */
+ saun.sun_family = AF_UNIX;
+ strcpy(saun.sun_path, ADDRESS);
+
+ /*
+ * Try to bind the address to the socket. We
+ * unlink the name first so that the bind won't
+ * fail.
+ *
+ * The third argument indicates the "length" of
+ * the structure, not just the length of the
+ * socket name.
+ */
+ unlink(ADDRESS);
+ len = sizeof(saun.sun_family) + strlen(saun.sun_path);
+
+ if (bind(s, &saun, len) < 0) {
+ perror("server: bind");
+ exit(1);
+ }
+
+ /*
+ * Listen on the socket.
+ */
+ if (listen(s, 5) < 0) {
+ perror("server: listen");
+ exit(1);
+ }
+
+ /*
+ * Accept connections. When we accept one, ns
+ * will be connected to the client. fsaun will
+ * contain the address of the client.
+ */
+ if ((ns = accept(s, &fsaun, &fromlen)) < 0) {
+ perror("server: accept");
+ exit(1);
+ }
+
+ /*
+ * We'll use stdio for reading the socket.
+ */
+ fp = fdopen(ns, "r");
+
+ /*
+ * First we send some strings to the client.
+ */
+ for (i = 0; i < NSTRS; i++)
+ send(ns, strs[i], strlen(strs[i]), 0);
+
+ /*
+ * Then we read some strings from the client and
+ * print them out.
+ */
+ for (i = 0; i < NSTRS; i++) {
+ while ((c = fgetc(fp)) != EOF) {
+ putchar(c);
+
+ if (c == '\n')
+ break;
+ }
+ }
+
+ /*
+ * We can simply use close() to terminate the
+ * connection, since we're done with both sides.
+ */
+ close(s);
+
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/11.3.c b/reference/C/CONTRIB/OR_USING_C/11.3.c
new file mode 100644
index 0000000..25d6e05
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/11.3.c
@@ -0,0 +1,63 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <stdio.h>
+
+#define MSGSZ 128
+
+#ifdef NOT_USED
+/*
+ * Declare the message structure.
+ */
+struct msgbuf {
+ long mtype;
+ char mtext[MSGSZ];
+};
+#endif /* NOT_USED */
+
+main()
+{
+ int msqid;
+ key_t key;
+ struct msgbuf sbuf, rbuf;
+
+ /*
+ * Create a message queue with "name" 1234.
+ */
+ key = 1234;
+
+ /*
+ * We want to let everyone read and
+ * write on this message queue, hence
+ * we use 0666 as the permissions.
+ */
+ if ((msqid = msgget(key, IPC_CREAT | 0666)) < 0) {
+ perror("msgget");
+ exit(1);
+ }
+
+ /*
+ * Receive a message.
+ */
+ if (msgrcv(msqid, &rbuf, MSGSZ, 0, 0) < 0) {
+ perror("msgrcv");
+ exit(1);
+ }
+
+ /*
+ * We send a message of type 2.
+ */
+ sbuf.mtype = 2;
+ sprintf(sbuf.mtext, "I received your message.");
+
+ /*
+ * Send an answer.
+ */
+ if (msgsnd(msqid, &sbuf, strlen(sbuf.mtext) + 1, 0) < 0) {
+ perror("msgsnd");
+ exit(1);
+ }
+
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/11.4.c b/reference/C/CONTRIB/OR_USING_C/11.4.c
new file mode 100644
index 0000000..346e577
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/11.4.c
@@ -0,0 +1,65 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/msg.h>
+#include <stdio.h>
+
+#define MSGSZ 128
+
+#ifdef NOT_USED
+/*
+ * Declare the message structure.
+ */
+struct msgbuf {
+ long mtype;
+ char mtext[MSGSZ];
+};
+#endif /* NOT_USED */
+
+main()
+{
+ int msqid;
+ key_t key;
+ struct msgbuf sbuf, rbuf;
+
+ /*
+ * Get the message queue id for the
+ * "name" 1234, which was created by
+ * the server.
+ */
+ key = 1234;
+
+ if ((msqid = msgget(key, 0666)) < 0) {
+ perror("msgget");
+ exit(1);
+ }
+
+ /*
+ * We'll send message type 1, the server
+ * will send message type 2.
+ */
+ sbuf.mtype = 1;
+ sprintf(sbuf.mtext, "Did you get this?");
+
+ /*
+ * Send a message.
+ */
+ if (msgsnd(msqid, &sbuf, strlen(sbuf.mtext) + 1, 0) < 0) {
+ perror("msgsnd");
+ exit(1);
+ }
+
+ /*
+ * Receive an answer of message type 2.
+ */
+ if (msgrcv(msqid, &rbuf, MSGSZ, 2, 0) < 0) {
+ perror("msgrcv");
+ exit(1);
+ }
+
+ /*
+ * Print the answer.
+ */
+ printf("%s\n", rbuf.mtext);
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/11.5.c b/reference/C/CONTRIB/OR_USING_C/11.5.c
new file mode 100644
index 0000000..50038de
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/11.5.c
@@ -0,0 +1,59 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <stdio.h>
+
+#define SHMSZ 27
+
+main()
+{
+ char c;
+ int shmid;
+ key_t key;
+ char *shmat();
+ char *shm, *s;
+
+ /*
+ * We'll name our shared memory segment
+ * "5678".
+ */
+ key = 5678;
+
+ /*
+ * Create the segment.
+ */
+ if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
+ perror("shmget");
+ exit(1);
+ }
+
+ /*
+ * Now we attach the segment to our data space.
+ */
+ if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
+ perror("shmat");
+ exit(1);
+ }
+
+ /*
+ * Now put some things into the memory for the
+ * other process to read.
+ */
+ s = shm;
+
+ for (c = 'a'; c <= 'z'; c++)
+ *s++ = c;
+ *s = NULL;
+
+ /*
+ * Finally, we wait until the other process
+ * changes the first character of our memory
+ * to '*', indicating that it has read what
+ * we put there.
+ */
+ while (*shm != '*')
+ sleep(1);
+
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/11.6.c b/reference/C/CONTRIB/OR_USING_C/11.6.c
new file mode 100644
index 0000000..7db84df
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/11.6.c
@@ -0,0 +1,53 @@
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <stdio.h>
+
+#define SHMSZ 27
+
+main()
+{
+ int shmid;
+ key_t key;
+ char *shmat();
+ char *shm, *s;
+
+ /*
+ * We need to get the segment named
+ * "5678", created by the server.
+ */
+ key = 5678;
+
+ /*
+ * Locate the segment.
+ */
+ if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
+ perror("shmget");
+ exit(1);
+ }
+
+ /*
+ * Now we attach the segment to our data space.
+ */
+ if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
+ perror("shmat");
+ exit(1);
+ }
+
+ /*
+ * Now read what the server put in the memory.
+ */
+ for (s = shm; *s != NULL; s++)
+ putchar(*s);
+ putchar('\n');
+
+ /*
+ * Finally, change the first character of the
+ * segment to '*', indicating we have read
+ * the segment.
+ */
+ *shm = '*';
+
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/11.7.c b/reference/C/CONTRIB/OR_USING_C/11.7.c
new file mode 100644
index 0000000..c21a168
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/11.7.c
@@ -0,0 +1,55 @@
+/*
+ * shm-client - client program to demonstrate shared memory.
+ */
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <stdio.h>
+
+#define SHMSZ 27
+
+main()
+{
+ int shmid;
+ key_t key;
+ char *shmat();
+ char *shm, *s;
+
+ /*
+ * We need to get the segment named
+ * "5678", created by the server.
+ */
+ key = 5678;
+
+ /*
+ * Locate the segment.
+ */
+ if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
+ perror("shmget");
+ exit(1);
+ }
+
+ /*
+ * Now we attach the segment to our data space.
+ */
+ if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
+ perror("shmat");
+ exit(1);
+ }
+
+ /*
+ * Now read what the server put in the memory.
+ */
+ for (s = shm; *s != NULL; s++)
+ putchar(*s);
+ putchar('\n');
+
+ /*
+ * Finally, change the first character of the
+ * segment to '*', indicating we have read
+ * the segment.
+ */
+ *shm = '*';
+
+ exit(0);
+}
diff --git a/reference/C/CONTRIB/OR_USING_C/12.1.c b/reference/C/CONTRIB/OR_USING_C/12.1.c
new file mode 100644
index 0000000..3685c34
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/12.1.c
@@ -0,0 +1,112 @@
+/*
+ * Connects to the local host at port 1234.
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+
+#define NSTRS 3 /* no. of strings */
+
+/*
+ * Strings we send to the server.
+ */
+char *strs[NSTRS] = {
+ "This is the first string from the client.\n",
+ "This is the second string from the client.\n",
+ "This is the third string from the client.\n"
+};
+
+extern int errno;
+
+main()
+{
+ char c;
+ FILE *fp;
+ char hostname[64];
+ register int i, s;
+ struct hostent *hp;
+ struct sockaddr_in sin;
+
+ /*
+ * Before we can do anything, we need to know
+ * our hostname.
+ */
+ gethostname(hostname, sizeof(hostname));
+
+ /*
+ * Next, we need to look up the network
+ * address of our host.
+ */
+ if ((hp = gethostbyname(hostname)) == NULL) {
+ fprintf(stderr, "%s: unknown host.\n", hostname);
+ exit(1);
+ }
+
+ /*
+ * Get a socket to work with. This socket will
+ * be in the Internet domain, and will be a
+ * stream socket.
+ */
+ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ perror("client: socket");
+ exit(1);
+ }
+
+ /*
+ * Create the address we will be connecting to.
+ * We use port 1234 but put it into network
+ * byte order. Also, we use bcopy (see Chapter
+ * 14) to copy the network number.
+ */
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(1234);
+ bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
+
+ /*
+ * Try to connect to the address. For this to
+ * succeed, the server must already have bound
+ * this address, and must have issued a listen()
+ * request.
+ */
+ if (connect(s, &sin, sizeof(sin)) < 0) {
+ perror("client: connect");
+ exit(1);
+ }
+
+ /*
+ * We'll use stdio for reading
+ * the socket.
+ */
+ fp = fdopen(s, "r");
+
+ /*
+ * First we read some strings from the server
+ * and print them out.
+ */
+ for (i = 0; i < NSTRS; i++) {
+ while ((c = fgetc(fp)) != EOF) {
+ putchar(c);
+
+ if (c == '\n')
+ break;
+ }
+ }
+
+ /*
+ * Now we send some strings to the server.
+ */
+ for (i = 0; i < NSTRS; i++)
+ send(s, strs[i], strlen(strs[i]), 0);
+
+
+ /*
+ * We can simply use close() to terminate the
+ * connection, since we're done with both sides.
+ */
+ close(s);
+
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/12.2.c b/reference/C/CONTRIB/OR_USING_C/12.2.c
new file mode 100644
index 0000000..ed64580
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/12.2.c
@@ -0,0 +1,126 @@
+/*
+ * Connects to port 1234 on the local host.
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+
+#define NSTRS 3 /* no. of strings */
+
+/*
+ * Strings we send to the client.
+ */
+char *strs[NSTRS] = {
+ "This is the first string from the server.\n",
+ "This is the second string from the server.\n",
+ "This is the third string from the server.\n"
+};
+
+extern int errno;
+
+main()
+{
+ char c;
+ FILE *fp;
+ int fromlen;
+ char hostname[64];
+ struct hostent *hp;
+ register int i, s, ns;
+ struct sockaddr_in sin, fsin;
+
+ /*
+ * Before we can do anything, we need
+ * to know our hostname.
+ */
+ gethostname(hostname, sizeof(hostname));
+
+ /*
+ * Now we look up our host to get
+ * its network number.
+ */
+ if ((hp = gethostbyname(hostname)) == NULL) {
+ fprintf(stderr, "%s: host unknown.\n", hostname);
+ exit(1);
+ }
+
+ /*
+ * Get a socket to work with. This socket will
+ * be in the Internet domain, and will be a
+ * stream socket.
+ */
+ if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ perror("server: socket");
+ exit(1);
+ }
+
+ /*
+ * Create the address that we will be binding to.
+ * We use port 1234 but put it into network
+ * byte order. Also, we use bcopy (see
+ * Chapter 14) to copy the network number.
+ */
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(1234);
+ bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
+
+ /*
+ * Try to bind the address to the socket.
+ */
+ if (bind(s, &sin, sizeof(sin)) < 0) {
+ perror("server: bind");
+ exit(1);
+ }
+
+ /*
+ * Listen on the socket.
+ */
+ if (listen(s, 5) < 0) {
+ perror("server: listen");
+ exit(1);
+ }
+
+ /*
+ * Accept connections. When we accept one, ns
+ * will be connected to the client. fsin will
+ * contain the address of the client.
+ */
+ if ((ns = accept(s, &fsin, &fromlen)) < 0) {
+ perror("server: accept");
+ exit(1);
+ }
+
+ /*
+ * We'll use stdio for reading the socket.
+ */
+ fp = fdopen(ns, "r");
+
+ /*
+ * First we send some strings to the client.
+ */
+ for (i = 0; i < NSTRS; i++)
+ send(ns, strs[i], strlen(strs[i]), 0);
+
+ /*
+ * Then we read some strings from the client
+ * and print them out.
+ */
+ for (i = 0; i < NSTRS; i++) {
+ while ((c = fgetc(fp)) != EOF) {
+ putchar(c);
+
+ if (c == '\n')
+ break;
+ }
+ }
+
+ /*
+ * We can simply use close() to terminate the
+ * connection, since we're done with both sides.
+ */
+ close(s);
+
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/12.3.c b/reference/C/CONTRIB/OR_USING_C/12.3.c
new file mode 100644
index 0000000..50b755c
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/12.3.c
@@ -0,0 +1,93 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+
+#define BUFSZ 256
+#define SERVICE "daytime"
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ int s, n, len;
+ char buf[BUFSZ];
+ struct hostent *hp;
+ struct servent *sp;
+ struct sockaddr_in sin;
+
+ /*
+ * Get a datagram socket in the Internet
+ * domain.
+ */
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("socket");
+ exit(1);
+ }
+
+ /*
+ * Look up the port number of the service.
+ */
+ if ((sp = getservbyname(SERVICE, "udp")) == NULL) {
+ fprintf(stderr, "%s/udp: unknown service.\n", SERVICE);
+ exit(1);
+ }
+
+ /*
+ * For each host on the command line...
+ */
+ while (--argc) {
+ /*
+ * Look up the network number of
+ * the host.
+ */
+ if ((hp = gethostbyname(*++argv)) == NULL) {
+ fprintf(stderr, "%s: host unknown.\n", *argv);
+ continue;
+ }
+
+ /*
+ * Build the address of the server on
+ * the remote machine.
+ */
+ sin.sin_family = AF_INET;
+ sin.sin_port = sp->s_port;
+ bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
+
+ /*
+ * Print the name of the host.
+ */
+ printf("%s: ", *argv);
+ fflush(stdout);
+
+ /*
+ * Send a datagram to the server.
+ */
+ if (sendto(s, buf, BUFSZ, 0, &sin, sizeof(sin)) < 0) {
+ perror("sendto");
+ continue;
+ }
+
+ /*
+ * Receive a datagram back.
+ */
+ len = sizeof(sin);
+ n = recvfrom(s, buf, sizeof(buf), 0, &sin, &len);
+
+ if (n < 0) {
+ perror("recvfrom");
+ continue;
+ }
+
+ /*
+ * Print the datagram.
+ */
+ buf[n] = NULL;
+ printf("%s\n", buf);
+ }
+
+ close(s);
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/13.1.c b/reference/C/CONTRIB/OR_USING_C/13.1.c
new file mode 100644
index 0000000..27dbf67
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/13.1.c
@@ -0,0 +1,254 @@
+/*
+ * Sys V version
+ *
+ * Reads the i-node structures from a raw disk
+ * device and then sums up the disk usage for
+ * each user. Prints out the number of blocks
+ * each user is using.
+ */
+#include <sys/sysmacros.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/filsys.h>
+#include <sys/inode.h>
+#include <sys/ino.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <pwd.h>
+
+/*
+ * Maximum user id.
+ */
+#ifndef MAXUID
+#define MAXUID 32768
+#endif
+
+#define SBSIZE BSIZE /* size of super-block */
+#define sblock sb_un.u_sblock
+
+/*
+ * The super-block. We allow enough room for
+ * a complete disk block.
+ */
+union {
+ char dummy[SBSIZE];
+ struct filsys u_sblock;
+} sb_un;
+
+int nfiles; /* no. of files in filsys */
+
+char *pname; /* program name (argv[0]) */
+char *device; /* name of disk device */
+char *filsys; /* name of file system */
+
+size_t blocks[MAXUID]; /* count of blocks used */
+struct dinode *dinode; /* will hold the i-nodes */
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ int i, fd;
+ register ino_t ino;
+ register struct dinode *di;
+
+ /*
+ * Save the program name and check our arguments.
+ */
+ pname = *argv;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s raw-disk-device\n", pname);
+ exit(1);
+ }
+
+ /*
+ * Open the device for reading.
+ */
+ device = *++argv;
+
+ if ((fd = open(device, O_RDONLY)) < 0) {
+ perror(device);
+ exit(1);
+ }
+
+ /*
+ * Get the super-block from the device.
+ */
+ getsblock(fd);
+
+ /*
+ * Get the i-node structures from the device.
+ */
+ getinodes(fd);
+
+ close(fd);
+
+ /*
+ * Zero the block counts.
+ */
+ for (i = 0; i < MAXUID; i++)
+ blocks[i] = 0;
+
+ /*
+ * Add up the number of blocks being used by each
+ * user id.
+ */
+ for (ino = 0; ino < nfiles; ino++) {
+ /*
+ * ROOTINO is the first i-node; skip any
+ * before it.
+ */
+ if (ino < ROOTINO)
+ continue;
+
+ di = &dinode[ino];
+
+ /*
+ * If this is zero, the i-node is free (not
+ * in use).
+ */
+ if ((di->di_mode & IFMT) == 0)
+ continue;
+
+ /*
+ * Count the number of blocks being used by
+ * this file. We round the number of bytes to
+ * the next highest multiple of 512.
+ */
+ blocks[di->di_uid] += (di->di_size + 511) / 512;
+ }
+
+ /*
+ * Print out what we added up.
+ */
+ printusage();
+ exit(0);
+}
+
+/*
+ * getsblock--get the super-block from the device referred
+ * to by fd.
+ */
+getsblock(fd)
+int fd;
+{
+ /*
+ * Make sure the disk information is current. This
+ * causes all disk writes to be scheduled.
+ */
+ sync();
+
+ /*
+ * Read in the super-block. It is stored at file
+ * system address SUPERBOFF.
+ */
+ lseek(fd, (long) SUPERBOFF, 0);
+ read(fd, &sblock, SBSIZE);
+
+ /*
+ * The number of files (i-nodes) is calculated by
+ * multiplying the number of blocks used to hold
+ * i-nodes by the number of i-nodes in a block.
+ */
+ nfiles = sblock.s_isize * INOPB;
+
+ /*
+ * Save the name of the file system.
+ */
+ filsys = sblock.s_fname;
+}
+
+/*
+ * getinodes--read in the i-node structures from the device
+ * referred to by fd.
+ */
+getinodes(fd)
+int fd;
+{
+ register ino_t ino;
+ register daddr_t iblk;
+ struct dinode *malloc();
+
+ /*
+ * Allocate space for them all.
+ */
+ dinode = malloc(nfiles * sizeof(struct dinode));
+
+ if (dinode == NULL) {
+ fprintf(stderr, "%s: out of memory.\n", pname);
+ exit(1);
+ }
+
+ /*
+ * We read in i-nodes a disk block-full at a time.
+ * The INOPB constant is the number of i-nodes in
+ * a block.
+ */
+ for (ino = 0; ino < nfiles; ino += INOPB) {
+ /*
+ * The i-node's disk block number is given by
+ * the itod macro.
+ */
+ iblk = itod(ino);
+
+ /*
+ * Read in this block of i-nodes.
+ */
+ bread(fd, iblk, &dinode[ino], BSIZE);
+ }
+}
+
+/*
+ * bread--read cnt bytes from fd into buf, starting at
+ * address bno.
+ */
+bread(fd, bno, buf, cnt)
+daddr_t bno;
+char *buf;
+int cnt;
+{
+ int n;
+
+ /*
+ * Seek to the proper block. The shifting by BSHIFT
+ * converts the block number to a byte address.
+ */
+ lseek(fd, (long) (bno << BSHIFT), 0);
+
+ /*
+ * Read in the data.
+ */
+ if ((n = read(fd, buf, cnt)) != cnt) {
+ perror(filsys);
+ exit(1);
+ }
+}
+
+/*
+ * printusage--print out the disk usage in blocks.
+ */
+printusage()
+{
+ register int i;
+ struct passwd *pwd;
+ struct passwd *getpwuid();
+
+ printf("%s (%s):\n", device, filsys);
+ printf(" Blocks \t User\n");
+
+ for (i = 0; i < MAXUID; i++) {
+ if (blocks[i] == 0)
+ continue;
+
+ /*
+ * Look up the login name, and use it if
+ * we find it.
+ */
+ if ((pwd = getpwuid(i)) != NULL)
+ printf("%8d\t%s\n", blocks[i], pwd->pw_name);
+ else
+ printf("%8d\t#%d\n", blocks[i], i);
+ }
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/13.2.c b/reference/C/CONTRIB/OR_USING_C/13.2.c
new file mode 100644
index 0000000..023041a
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/13.2.c
@@ -0,0 +1,267 @@
+/*
+ * Reads the i-node structures from a raw disk device and
+ * then sums up the disk usage for each user. Prints out
+ * the number of blocks each user is using.
+ *
+ * If you are on a Sun workstation or other system using Sun's
+ * Network File System (NFS), be sure to define the constant
+ * NFS so that the proper files get included.
+ */
+#ifdef sun
+#define NFS 1
+#endif
+#ifdef NFS
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/vnode.h>
+#include <ufs/inode.h>
+#include <sys/file.h>
+#include <ufs/fs.h>
+#include <stdio.h>
+#include <pwd.h>
+#else
+#include <sys/param.h>
+#include <sys/inode.h>
+#include <sys/file.h>
+#include <sys/fs.h>
+#include <stdio.h>
+#include <pwd.h>
+#endif
+/*
+ * Maximum user id.
+ */
+#ifndef MAXUID
+#define MAXUID 32768
+#endif
+
+#define sblock sb_un.u_sblock
+
+/*
+ * The super block. We allow enough room for
+ * a complete disk block.
+ */
+union {
+ struct fs u_sblock;
+ char dummy[SBSIZE];
+} sb_un;
+
+int nfiles; /* number of files in file system */
+
+char *pname; /* program name (argv[0]) */
+char *device; /* name of the disk device given */
+char *filsys; /* name of the file system on device */
+
+size_t blocks[MAXUID]; /* count of blocks used */
+struct dinode *dinode; /* will hold all the i-node structures */
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ int i, fd;
+ register ino_t ino;
+ register struct dinode *di;
+
+ /*
+ * Save the program name and check our arguments.
+ */
+ pname = *argv;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s raw-disk-device\n", pname);
+ exit(1);
+ }
+
+ /*
+ * Open the device for reading.
+ */
+ device = *++argv;
+
+ if ((fd = open(device, O_RDONLY)) < 0) {
+ perror(device);
+ exit(1);
+ }
+
+ /*
+ * Get the super-block from the device.
+ */
+ getsblock(fd);
+
+ /*
+ * Get the i-node structures from the device.
+ */
+ getinodes(fd);
+ close(fd);
+
+ /*
+ * Zero the block counts.
+ */
+ for (i = 0; i < MAXUID; i++)
+ blocks[i] = 0;
+
+ /*
+ * Add up the number of blocks being used by
+ * each user id.
+ */
+ for (ino = 0; ino < nfiles; ino++) {
+ /*
+ * ROOTINO is the first i-node; skip any
+ * before it.
+ */
+ if (ino < ROOTINO)
+ continue;
+
+ di = &dinode[ino];
+
+ /*
+ * If this is zero, the i-node is free (not
+ * in use).
+ */
+ if ((di->di_mode & IFMT) == 0)
+ continue;
+
+ /*
+ * Count the number of blocks being used by
+ * this file.
+ */
+ blocks[di->di_uid] += di->di_blocks;
+ }
+
+ /*
+ * Print out what we added up.
+ */
+ printusage();
+ exit(0);
+}
+
+/*
+ * getsblock--get the super-block from the device
+ * referred to by fd.
+ */
+getsblock(fd)
+int fd;
+{
+ /*
+ * Make sure the disk information is current.
+ * This causes all disk writes to be scheduled.
+ */
+ sync();
+
+ /*
+ * Read in the super-block. It is stored at file
+ * system block number SBLOCK.
+ */
+ bread(fd, SBLOCK, &sblock, SBSIZE);
+
+ /*
+ * The number of files (i-nodes) is calculated by
+ * multiplying the number of i-nodes per cylinder
+ * group by the number of cylinder groups.
+ */
+ nfiles = sblock.fs_ipg * sblock.fs_ncg;
+
+ /*
+ * Save the name of the file system.
+ */
+ filsys = sblock.fs_fsmnt;
+}
+
+/*
+ * getinodes--read in the i-node structures from the device
+ * referred to by fd.
+ */
+getinodes(fd)
+int fd;
+{
+ register ino_t ino;
+ register daddr_t iblk;
+ struct dinode *malloc();
+
+ /*
+ * Allocate space for them all.
+ */
+ dinode = malloc(nfiles * sizeof(struct dinode));
+
+ if (dinode == NULL) {
+ fprintf(stderr, "%s: out of memory.\n", pname);
+ exit(1);
+ }
+
+ /*
+ * We read in i-nodes a disk block-full at a time.
+ * The INOPB macro returns the number of i-nodes
+ * in a block; it uses the super-block to determine
+ * the file system block size.
+ */
+ for (ino = 0; ino < nfiles; ino += INOPB(&sblock)) {
+ /*
+ * The i-node file system block number is given by
+ * the itod macro. The disk block number is computed
+ * from the file system block number by the fsbtodb macro.
+ */
+
+ iblk = fsbtodb(&sblock, itod(&sblock, ino));
+
+ /*
+ * Read in this block of i-nodes.
+ */
+ bread(fd, iblk, &dinode[ino], sblock.fs_bsize);
+ }
+}
+
+/*
+ * bread-read cnt bytes form fd into buf, starting at
+ * address bno.
+ */
+bread(fd, bno, buf, cnt)
+daddr_t bno;
+char *buf;
+int cnt;
+{
+ int n;
+
+ /*
+ * Seek to the proper block. The dtob macro converts
+ * the block number to a byte address.
+ */
+ lseek(fd, (long) dtob(bno), L_SET);
+
+ /*
+ * Round cnt up to a multiple of the device block size.
+ */
+ cnt = roundup(cnt, DEV_BSIZE);
+
+ /*
+ * Read in the data.
+ */
+ if ((n = read(fd, buf, cnt)) != cnt) {
+ perror(filsys);
+ exit(1);
+ }
+}
+
+/*
+ * printusage-print out the disk usage in blocks.
+ */
+printusage()
+{
+ register int i;
+ struct passwd *pwd;
+
+ printf("%s (%s):\n", device, filsys);
+ printf(" Blocks \\t User\n");
+
+ for (i=0; i < MAXUID; i++) {
+ if (blocks[i] == 0)
+ continue;
+
+ /*
+ * Look up the login name, and use it if we find it.
+ */
+ if ((pwd = getpwuid(i)) != NULL)
+ printf("%8d\\t%s\n", blocks[i], pwd->pw_name);
+ else
+ printf("%8d\\t#%d\n", blocks[i], i);
+ }
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/13.3.c b/reference/C/CONTRIB/OR_USING_C/13.3.c
new file mode 100644
index 0000000..a0dc4b1
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/13.3.c
@@ -0,0 +1,118 @@
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/vnode.h>
+#include <ufs/inode.h>
+#include <ufs/fs.h>
+
+#define sblock sb_un.u_sblock
+
+/*
+ * The super block. We allow enough room for
+ * a complete disk block.
+ */
+union {
+ struct fs u_sblock;
+ char dummy[SBSIZE];
+} sb_un;
+
+read_blocks(dp)
+struct dinode *dp;
+{
+ int count;
+ register int i, n;
+ char dblock[MAXBSIZE];
+
+ count = dp->di_size;
+
+ /*
+ * For each direct block in the file (NDADDR indicates
+ * the number of direct addresses stored)...
+ */
+ for (i = 0; (i < NDADDR) && (count > 0); i++) {
+ /*
+ * Read in the block from disk. Read in count
+ * bytes or a disk block, whichever is less.
+ */
+ bread(fsbtodb(&sblock, dp->di_db[i]), dblock,
+ n = min(count, sblock.fs_bsize));
+ count -= n;
+
+ /* process data block ... */
+
+ }
+
+ /*
+ * Now start reading the indirect blocks. NIADDR is
+ * the number of indirect addresses. Recall that
+ * the first indirect address is singly indirect,
+ * the second is doubly indirect, an so on.
+ */
+ for (i = 0; (i < NIADDR) && (count > 0); i++)
+ read_indirect (dp->di_ib[i], i, &count);
+}
+
+/*
+ * read_indirect--read the indirect blocks of the file. The
+ * level argument indicates our level of indirection; 0 is
+ * singly indirect, 1 is doubly indirect, and so on.
+ */
+read_indirect (blkno, level, count)
+ino_t blkno;
+int *count;
+int level;
+{
+ register int i, n;
+ char dblock[MAXBSIZE];
+ daddr_t idblk[MAXBSIZE / sizeof(daddr_t)];
+
+ /*
+ * Read in the block from disk.
+ */
+ if (blkno)
+ bread(fsbtodb(&sblock, blkno), idblk, sblock.fs_bsize);
+ else
+ bzero(idblk, sblock.fs_bsize);
+
+ /*
+ * If level is zero, then this block contains disk block
+ * addresses, since blkno was a singly indirect address.
+ * If level is non-zero, then this block contains addresses
+ * of more indirect blocks.
+ */
+ if (level <= 0) {
+ /*
+ * For each disk block (the NINDIR macro returns
+ * the number of indirect addresses in a block)...
+ */
+ for (i = 0; (i < NINDIR(&sblock)) && (*count > 0); i++) {
+ /*
+ * Read in the block from disk.
+ */
+ bread(fsbtodb(&sblock, idblk[i]), dblock,
+ n = min(*count, sblock.fs_bsize));
+ *count -= n;
+
+ /* process data block ... */
+ }
+
+ /*
+ * Done processing.
+ */
+ return;
+ }
+
+ /*
+ * Decrement the level we're at.
+ */
+ level--;
+
+ /*
+ * Handle the next level of indirection by calling
+ * ourselves recursively with each address in this
+ * block.
+ */
+ for (i = 0; i < NINDIR(&sblock); i++)
+ read_indirect(idblk[i], level, count);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/14.1.c b/reference/C/CONTRIB/OR_USING_C/14.1.c
new file mode 100644
index 0000000..4ba5035
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/14.1.c
@@ -0,0 +1,29 @@
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+/*
+ * setlim--set the resource limit lim to the value val.
+ */
+setlim(lim, val)
+int lim, val;
+{
+ struct rlimit rlim;
+
+ /*
+ * First get the current limits so we
+ * will know the maximum value.
+ */
+ getrlimit(lim, &rlim);
+
+ /*
+ * Now change the current limit.
+ */
+ rlim.rlim_cur = val;
+
+ /*
+ * Now set the new limit.
+ */
+ return(setrlimit(lim, &rlim));
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/14.2.c b/reference/C/CONTRIB/OR_USING_C/14.2.c
new file mode 100644
index 0000000..07418aa
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/14.2.c
@@ -0,0 +1,75 @@
+#include <stdio.h>
+
+#define NSTRS 10 /* number of strings */
+#define STRLEN 16 /* length of each string */
+
+char strs[NSTRS][STRLEN]; /* array of strings */
+
+main()
+{
+ int i;
+ extern int compare1(), compare2();
+
+ /*
+ * Prompt the user for NSTRS strings.
+ */
+ for (i = 0; i < NSTRS; i++) {
+ printf("Enter string #%d: ", i);
+ gets(strs[i]);
+ }
+
+ /*
+ * Sort the strings into ascending order. There
+ * are NSTRS array elements, each one is STRLEN
+ * characters long. Note we give the size of
+ * the array element, not the length of the
+ * string in it.
+ */
+ qsort(strs, NSTRS, STRLEN, compare1);
+
+ /*
+ * Print the strings.
+ */
+ printf("\nSorted in ascending order:\n");
+
+ for (i = 0; i < NSTRS; i++)
+ printf("\t%s\n", strs[i]);
+
+ /*
+ * Now sort the strings in descending order.
+ */
+ qsort(strs, NSTRS, STRLEN, compare2);
+
+ printf("\nSorted in descending order:\n");
+
+ for (i = 0; i < NSTRS; i++)
+ printf("\t%s\n", strs[i]);
+
+ exit(0);
+}
+
+/*
+ * compare1--compare a and b, and return less than,
+ * greater than, or equal to zero. Since
+ * we are comparing character strings, we
+ * can just use strcmp to do the work for us.
+ */
+compare1(a, b)
+char *a, *b;
+{
+ return(strcmp(a, b));
+}
+
+/*
+ * compare2--this compares a and b, but is used for
+ * sorting in the opposite order. Thus it
+ * returns the opposite of strcmp. We can
+ * simulate this by simply reversing the
+ * arguments when we call strcmp.
+ */
+compare2(a, b)
+char *a, *b;
+{
+ return(strcmp(b, a));
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/HEADER.html b/reference/C/CONTRIB/OR_USING_C/HEADER.html
new file mode 100644
index 0000000..c09967d
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/HEADER.html
@@ -0,0 +1,4 @@
+<h1>Using C - O'Reilly</h1>
+Reprinted with permission from 'Using C on the UNIX System' copyright 1989
+O'Reilly and Associates, Inc. For
+orders and information, call 1-800-988-9938.
diff --git a/reference/C/CONTRIB/OR_USING_C/Makefile.am b/reference/C/CONTRIB/OR_USING_C/Makefile.am
new file mode 100644
index 0000000..ad81f7d
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/Makefile.am
@@ -0,0 +1,5 @@
+EXTRA_DIST = $(wildcard *.html) $(wildcard *.c) $(wildcard *.h)
+docs_DATA = $(EXTRA_DIST)
+
+docsdir = $(kde_htmldir)/en/kdevelop/$(subdir)
+
diff --git a/reference/C/CONTRIB/OR_USING_C/Makefile.in b/reference/C/CONTRIB/OR_USING_C/Makefile.in
new file mode 100644
index 0000000..c941512
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/Makefile.in
@@ -0,0 +1,410 @@
+# KDE tags expanded automatically by am_edit - $Revision: 1.2 $
+# Makefile.in generated automatically by automake 1.5 from Makefile.am.
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../../../..
+
+ACLOCAL = @ACLOCAL@
+AUTOCONF = @AUTOCONF@
+AUTOMAKE = @AUTOMAKE@
+AUTOHEADER = @AUTOHEADER@
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = @program_transform_name@
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_alias = @build_alias@
+build_triplet = @build@
+host_alias = @host_alias@
+host_triplet = @host@
+target_alias = @target_alias@
+target_triplet = @target@
+AMTAR = @AMTAR@
+ARTSCCONFIG = @ARTSCCONFIG@
+AS = @AS@
+AUTODIRS = @AUTODIRS@
+AWK = @AWK@
+CC = @CC@
+CONF_FILES = @CONF_FILES@
+CPP = @CPP@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+DCOPIDL = @DCOPIDL@
+DCOPIDL2CPP = @DCOPIDL2CPP@
+DCOP_DEPENDENCIES = @DCOP_DEPENDENCIES@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DPMSINC = @DPMSINC@
+DPMSLIB = @DPMSLIB@
+EXEEXT = @EXEEXT@
+GCJ = @GCJ@
+GCJFLAGS = @GCJFLAGS@
+GLINC = @GLINC@
+GLLIB = @GLLIB@
+GMSGFMT = @GMSGFMT@
+IDL = @IDL@
+IDL_DEPENDENCIES = @IDL_DEPENDENCIES@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JAR = @JAR@
+JAVAC = @JAVAC@
+JAVAH = @JAVAH@
+JVMLIBS = @JVMLIBS@
+KDECONFIG = @KDECONFIG@
+KDE_CXXFLAGS = @KDE_CXXFLAGS@
+KDE_EXTRA_RPATH = @KDE_EXTRA_RPATH@
+KDE_INCLUDES = @KDE_INCLUDES@
+KDE_LDFLAGS = @KDE_LDFLAGS@
+KDE_PLUGIN = @KDE_PLUGIN@
+KDE_RPATH = @KDE_RPATH@
+KDE_USE_CLOSURE_FALSE = @KDE_USE_CLOSURE_FALSE@
+KDE_USE_CLOSURE_TRUE = @KDE_USE_CLOSURE_TRUE@
+KDE_USE_FINAL_FALSE = @KDE_USE_FINAL_FALSE@
+KDE_USE_FINAL_TRUE = @KDE_USE_FINAL_TRUE@
+KDE_XSL_STYLESHEET = @KDE_XSL_STYLESHEET@
+LIBCOMPAT = @LIBCOMPAT@
+LIBCRYPT = @LIBCRYPT@
+LIBDL = @LIBDL@
+LIBGEN = @LIBGEN@
+LIBJPEG = @LIBJPEG@
+LIBMICO = @LIBMICO@
+LIBOBJS = @LIBOBJS@
+LIBPNG = @LIBPNG@
+LIBPTHREAD = @LIBPTHREAD@
+LIBPYTHON = @LIBPYTHON@
+LIBQIMGIO = @LIBQIMGIO@
+LIBRESOLV = @LIBRESOLV@
+LIBSHADOW = @LIBSHADOW@
+LIBSM = @LIBSM@
+LIBSOCKET = @LIBSOCKET@
+LIBTIFF = @LIBTIFF@
+LIBTOOL = @LIBTOOL@
+LIBUCB = @LIBUCB@
+LIBUTIL = @LIBUTIL@
+LIBXINERAMA = @LIBXINERAMA@
+LIBZ = @LIBZ@
+LIB_KAB = @LIB_KAB@
+LIB_KDECORE = @LIB_KDECORE@
+LIB_KDEUI = @LIB_KDEUI@
+LIB_KFILE = @LIB_KFILE@
+LIB_KFM = @LIB_KFM@
+LIB_KFORMULA = @LIB_KFORMULA@
+LIB_KHTML = @LIB_KHTML@
+LIB_KIMGIO = @LIB_KIMGIO@
+LIB_KIO = @LIB_KIO@
+LIB_KPARTS = @LIB_KPARTS@
+LIB_KSPELL = @LIB_KSPELL@
+LIB_KSYCOCA = @LIB_KSYCOCA@
+LIB_KWRITE = @LIB_KWRITE@
+LIB_QT = @LIB_QT@
+LIB_SMB = @LIB_SMB@
+LIB_X11 = @LIB_X11@
+LN_S = @LN_S@
+MCOPIDL = @MCOPIDL@
+MEINPROC = @MEINPROC@
+MICO_INCLUDES = @MICO_INCLUDES@
+MICO_LDFLAGS = @MICO_LDFLAGS@
+MOC = @MOC@
+MSGFMT = @MSGFMT@
+NOOPT_CXXFLAGS = @NOOPT_CXXFLAGS@
+NOREPO = @NOREPO@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PAMLIBS = @PAMLIBS@
+PASSWDLIBS = @PASSWDLIBS@
+PYTHONINC = @PYTHONINC@
+PYTHONLIB = @PYTHONLIB@
+PYTHONMODDIR = @PYTHONMODDIR@
+QT_INCLUDES = @QT_INCLUDES@
+QT_LDFLAGS = @QT_LDFLAGS@
+RANLIB = @RANLIB@
+REPO = @REPO@
+SETUIDFLAGS = @SETUIDFLAGS@
+STRIP = @STRIP@
+TOPSUBDIRS = @TOPSUBDIRS@
+UIC = @UIC@
+UIC_TR = @UIC_TR@
+USER_INCLUDES = @USER_INCLUDES@
+USER_LDFLAGS = @USER_LDFLAGS@
+USE_EXCEPTIONS = @USE_EXCEPTIONS@
+USE_RTTI = @USE_RTTI@
+USE_THREADS = @USE_THREADS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+XPMINC = @XPMINC@
+XPMLIB = @XPMLIB@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_INCLUDES = @X_INCLUDES@
+X_LDFLAGS = @X_LDFLAGS@
+X_PRE_LIBS = @X_PRE_LIBS@
+all_includes = @all_includes@
+all_libraries = @all_libraries@
+am__include = @am__include@
+am__quote = @am__quote@
+idldir = @idldir@
+install_sh = @install_sh@
+jni_includes = @jni_includes@
+kde_appsdir = @kde_appsdir@
+kde_bindir = @kde_bindir@
+kde_confdir = @kde_confdir@
+kde_datadir = @kde_datadir@
+kde_htmldir = @kde_htmldir@
+kde_icondir = @kde_icondir@
+kde_includes = @kde_includes@
+kde_libraries = @kde_libraries@
+kde_libs_htmldir = @kde_libs_htmldir@
+kde_libs_prefix = @kde_libs_prefix@
+kde_locale = @kde_locale@
+kde_mimedir = @kde_mimedir@
+kde_moduledir = @kde_moduledir@
+kde_qtver = @kde_qtver@
+kde_servicesdir = @kde_servicesdir@
+kde_servicetypesdir = @kde_servicetypesdir@
+kde_sounddir = @kde_sounddir@
+kde_templatesdir = @kde_templatesdir@
+kde_wallpaperdir = @kde_wallpaperdir@
+micodir = @micodir@
+qt_includes = @qt_includes@
+qt_libraries = @qt_libraries@
+x_includes = @x_includes@
+x_libraries = @x_libraries@
+
+EXTRA_DIST = $(wildcard *.html) $(wildcard *.c) $(wildcard *.h)
+docs_DATA = $(EXTRA_DIST)
+
+docsdir = $(kde_htmldir)/en/kdevelop/$(subdir)
+subdir = reference/C/CONTRIB/OR_USING_C
+mkinstalldirs = $(SHELL) $(top_srcdir)/admin/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+DATA = $(docs_DATA)
+
+DIST_COMMON = Makefile.am Makefile.in
+#>- all: all-am
+#>+ 1
+all: docs-am all-am
+
+.SUFFIXES:
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+#>- cd $(top_srcdir) && \
+#>- $(AUTOMAKE) --gnu reference/C/CONTRIB/OR_USING_C/Makefile
+#>+ 3
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu reference/C/CONTRIB/OR_USING_C/Makefile
+ cd $(top_srcdir) && perl admin/am_edit reference/C/CONTRIB/OR_USING_C/Makefile.in
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && \
+ CONFIG_HEADERS= CONFIG_LINKS= \
+ CONFIG_FILES=$(subdir)/$@ $(SHELL) ./config.status
+uninstall-info-am:
+install-docsDATA: $(docs_DATA)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(docsdir)
+ @list='$(docs_DATA)'; for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ f="`echo $$p | sed -e 's|^.*/||'`"; \
+ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(docsdir)/$$f"; \
+ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(docsdir)/$$f; \
+ done
+
+uninstall-docsDATA:
+ @$(NORMAL_UNINSTALL)
+ @list='$(docs_DATA)'; for p in $$list; do \
+ f="`echo $$p | sed -e 's|^.*/||'`"; \
+ echo " rm -f $(DESTDIR)$(docsdir)/$$f"; \
+ rm -f $(DESTDIR)$(docsdir)/$$f; \
+ done
+tags: TAGS
+TAGS:
+
+
+#>- DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+#>+ 4
+KDE_DIST=05.2.c a.4.c 10.2.c 03.1.c 09.2.c 02.3.c 08.4.c 12.2.c 11.4.c 05.1.c 04.3.c b.1.c a.3.c 10.h 14.2.c 07.1.c d.1.c 10.1.c a.7.c 09.1.c 02.2.c 08.3.c 12.1.c 11.3.c 10.5.c 04.2.c a.2.c 14.1.c 08.7.c 13.3.c 11.7.c nap.c a.6.c 02.1.c 08.2.c 11.2.c 10.4.c 04.1.c a.1.c 09.4.c 02.5.c 08.6.c 13.2.c 11.6.c 06.1.c 05.3.c c.1.c a.5.c HEADER.html 08.1.c e.1.c 11.1.c 10.3.c dircom.c 03.2.c 09.3.c 02.4.c 08.5.c 13.1.c 12.3.c 11.5.c
+
+DISTFILES= $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) $(KDE_DIST)
+
+
+top_distdir = ../../../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @for file in $(DISTFILES); do \
+ if test -f $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ $(mkinstalldirs) "$(distdir)/$$dir"; \
+ fi; \
+ if test -d $$d/$$file; then \
+ cp -pR $$d/$$file $(distdir) \
+ || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(DATA)
+
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(docsdir)
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES) stamp-h stamp-h[0-9]*
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+#>- clean: clean-am
+#>+ 1
+clean: kde-rpo-clean clean-am
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-generic distclean-libtool
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-docsDATA
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+uninstall-am: uninstall-docsDATA uninstall-info-am
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am info info-am install install-am install-data \
+ install-data-am install-docsDATA install-exec install-exec-am \
+ install-info install-info-am install-man install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool uninstall uninstall-am uninstall-docsDATA \
+ uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
+
+#>+ 2
+docs-am:
+
+#>+ 6
+force-reedit:
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu reference/C/CONTRIB/OR_USING_C/Makefile
+ cd $(top_srcdir) && perl admin/am_edit reference/C/CONTRIB/OR_USING_C/Makefile.in
+
+
+#>+ 2
+final:
+ $(MAKE) all-am
+#>+ 2
+final-install:
+ $(MAKE) install-am
+#>+ 2
+no-final:
+ $(MAKE) all-am
+#>+ 2
+no-final-install:
+ $(MAKE) install-am
+#>+ 3
+cvs-clean:
+ $(MAKE) -f $(top_srcdir)/admin/Makefile.common cvs-clean
+
+#>+ 3
+kde-rpo-clean:
+ -rm -f *.rpo
diff --git a/reference/C/CONTRIB/OR_USING_C/a.1.c b/reference/C/CONTRIB/OR_USING_C/a.1.c
new file mode 100644
index 0000000..d1d2749
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/a.1.c
@@ -0,0 +1,4 @@
+hello_() /* note underscore */
+{
+ printf("Hello, world.\n");
+}
diff --git a/reference/C/CONTRIB/OR_USING_C/a.2.c b/reference/C/CONTRIB/OR_USING_C/a.2.c
new file mode 100644
index 0000000..2f6782e
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/a.2.c
@@ -0,0 +1,6 @@
+extern hello();
+
+main()
+{
+ hello_();
+}
diff --git a/reference/C/CONTRIB/OR_USING_C/a.3.c b/reference/C/CONTRIB/OR_USING_C/a.3.c
new file mode 100644
index 0000000..d2ce1f6
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/a.3.c
@@ -0,0 +1,12 @@
+main()
+{
+ extern long y_();
+ long i;
+
+ i = y_();
+}
+
+long x_()
+{
+ return(5L);
+}
diff --git a/reference/C/CONTRIB/OR_USING_C/a.4.c b/reference/C/CONTRIB/OR_USING_C/a.4.c
new file mode 100644
index 0000000..03d0639
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/a.4.c
@@ -0,0 +1,18 @@
+typedef struct {
+ float r, i;
+} complex;
+
+main()
+{
+ extern complex y_();
+ complex i;
+
+ y_(&i);
+}
+
+x_(c)
+complex *c;
+{
+ c->r = 1.0;
+ c->i = 2.0;
+}
diff --git a/reference/C/CONTRIB/OR_USING_C/a.5.c b/reference/C/CONTRIB/OR_USING_C/a.5.c
new file mode 100644
index 0000000..ff298c7
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/a.5.c
@@ -0,0 +1,29 @@
+main()
+{
+ extern char *y_();
+ char s[15];
+
+ y_(s, 15L);
+}
+
+x_(s, len)
+char *s;
+long len;
+{
+ s[0] = 'a';
+ s[1] = 'b';
+ s[2] = 'c';
+ s[3] = 'd';
+ s[4] = 'e';
+ s[5] = 'f';
+ s[6] = 'g';
+ s[7] = 'h';
+ s[8] = 'i';
+ s[9] = 'j';
+ s[10] = 'k';
+ s[11] = 'l';
+ s[12] = 'm';
+ s[13] = 'n';
+ s[14] = 'o';
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/a.6.c b/reference/C/CONTRIB/OR_USING_C/a.6.c
new file mode 100644
index 0000000..5b0be32
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/a.6.c
@@ -0,0 +1,19 @@
+main()
+{
+ extern y_();
+ long a, b, c;
+
+ a = 4;
+ b = 5;
+ c = 6;
+
+ y_(&a, &b, &c);
+}
+
+x_(u, v, w)
+long *u, *v, *w;
+{
+ *u *= 2;
+ *v *= 3;
+ *w *= 4;
+}
diff --git a/reference/C/CONTRIB/OR_USING_C/a.7.c b/reference/C/CONTRIB/OR_USING_C/a.7.c
new file mode 100644
index 0000000..f5e0cc9
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/a.7.c
@@ -0,0 +1,16 @@
+main()
+{
+ extern char *y_();
+ char *i;
+
+ i = "hi there";
+ y_(i, 8L);
+}
+
+x_(s, len)
+char *s;
+long len;
+{
+ write(1, s, len);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/b.1.c b/reference/C/CONTRIB/OR_USING_C/b.1.c
new file mode 100644
index 0000000..422b975
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/b.1.c
@@ -0,0 +1,176 @@
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <signal.h>
+#include <stdio.h>
+
+ptyopen(cmd, ifp, ofp)
+char *cmd;
+FILE **ifp, **ofp;
+{
+ int i;
+ char *args[16];
+ register int tty;
+ long ldisc, lmode;
+ register char *s, *t;
+ struct sgttyb sgttyb;
+ struct tchars tchars;
+ struct ltchars ltchars;
+ char ttybuf[16], ptybuf[16];
+
+ /*
+ * Split up the arguments in the command
+ * into an argv-like structure.
+ */
+ i = 0;
+ s = cmd;
+
+ while (*s) {
+ /*
+ * Skip white space.
+ */
+ while ((*s == ' ') || (*s == '\t'))
+ *s++ = NULL;
+
+ args[i++] = s;
+
+ /*
+ * Skip over this word to next white space.
+ */
+ while ((*s != NULL) && (*s != ' ') && (*s != '\t'))
+ s++;
+ }
+ args[i] = NULL;
+ /*
+ * Get a pseudo-tty. We do this by cycling through all
+ * the possible names. The operating system will not
+ * allow us to open a master which is already in use,
+ * so we simply go until the open succeeds.
+ */
+ for (s = "pqrs"; *s != NULL; s++) {
+ for (t = "0123456789abcdef"; *t != NULL; t++) {
+ sprintf(ptybuf, "/dev/pty%c%c", *s, *t);
+ if ((tty = open(ptybuf, O_RDWR)) >= 0)
+ goto out;
+ }
+ }
+out:
+ /*
+ * If s and t are NULL, we ran out of pseudo ttys
+ * before we found one we can use.
+ */
+ if ((*s == NULL) && (*t == NULL))
+ return(-1);
+ /*
+ * Change "ptyXX" (master) to "ttyXX" (slave).
+ */
+ strcpy(ttybuf, ptybuf);
+ ttybuf[5] = 't';
+ /*
+ * Get the modes of the current terminal. We
+ * will duplicate these on the pseudo terminal.
+ */
+ ioctl(0, TIOCGETD, &ldisc);
+ ioctl(0, TIOCLGET, &lmode);
+ ioctl(0, TIOCGETP, &sgttyb);
+ ioctl(0, TIOCGETC, &tchars);
+ ioctl(0, TIOCGLTC, &ltchars);
+ /*
+ * Fork a child process.
+ */
+ if ((i = fork()) < 0) {
+ close(tty);
+ return(-1);
+ }
+
+ /*
+ * In the child...
+ */
+ if (i == 0) {
+ /*
+ * Close all open files.
+ */
+ for (i = 0; i < NOFILE; i++)
+ close(i);
+
+ /*
+ * Clear the controlling tty. This means
+ * that we will not have a controlling
+ * tty until we open another terminal
+ * device.
+ */
+ if ((i = open("/dev/tty", O_RDWR)) >= 0) {
+ ioctl(i, TIOCNOTTY, 0);
+ close(i);
+ }
+
+ /*
+ * Make our controlling tty the pseudo tty.
+ * This happens because we cleared our
+ * original controlling terminal above.
+ */
+ i = open(ttybuf, O_RDWR);
+
+ /*
+ * Set stdin, stdout, and stderr to be the
+ * pseudo terminal.
+ */
+ dup2(i, 0);
+ dup2(i, 1);
+ dup2(i, 2);
+
+ /*
+ * Set the pseudo terminal's tty modes to
+ * those of the original terminal. We
+ * turn off ECHO and CBREAK modes, since
+ * we don't want characters "typed" to be
+ * printed.
+ */
+ sgttyb.sg_flags &= ~ECHO;
+ sgttyb.sg_flags &= ~CRMOD;
+
+ ioctl(0, TIOCSETD, &ldisc);
+ ioctl(0, TIOCLGET, &lmode);
+ ioctl(0, TIOCSETP, &sgttyb);
+ ioctl(0, TIOCSETC, &tchars);
+ ioctl(0, TIOCSLTC, &ltchars);
+
+ /*
+ * Set the process group of the process
+ * to be the process group of the
+ * terminal.
+ */
+ ioctl(0, TIOCGPGRP, &i);
+ setpgrp(0, i);
+
+ /*
+ * Now change the process group of the
+ * terminal and process to be the
+ * process id; this takes them out
+ * of the calling process's process
+ * group.
+ */
+ i = getpid();
+
+ ioctl(0, TIOCSPGRP, &i);
+ setpgrp(0, i);
+
+ /*
+ * Execute the program.
+ */
+ execv(*args, args);
+
+ exit(1);
+ }
+
+ /*
+ * Set up the input and output file pointers
+ * so that they can write and read the pseudo
+ * terminal.
+ */
+ *ifp = fdopen(tty, "w");
+ *ofp = fdopen(tty, "r");
+
+ return(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/c.1.c b/reference/C/CONTRIB/OR_USING_C/c.1.c
new file mode 100644
index 0000000..257f3c8
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/c.1.c
@@ -0,0 +1,96 @@
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#include <nlist.h>
+#include <stdio.h>
+
+/*
+ * We declare an array of nlist structures,
+ * and initialize them to the names of the
+ * variables we want. The last entry is
+ * to terminate the list.
+ */
+struct nlist nl[] = {
+#define X_BOOTTIME 0
+ { "_boottime" },
+#define X_AVENRUN 1
+ { "_avenrun" },
+ { 0 }
+};
+
+main()
+{
+ int kmem;
+ char *ctime();
+ struct timeval boottime;
+
+ /*
+ * _avenrun is an array of three numbers.
+ * Most machines use floating point; Sun
+ * workstations use long integers.
+ */
+#ifdef sun
+ long avenrun[3];
+#else
+ double avenrun[3];
+#endif
+
+ /*
+ * Open kernel memory.
+ */
+ if ((kmem = open("/dev/kmem", O_RDONLY)) < 0) {
+ perror("/dev/kmem");
+ exit(1);
+ }
+
+ /*
+ * Read the kernel namelist. If nl[0].n_type is
+ * 0 after this, then the call to nlist() failed.
+ */
+ if ((nlist("/vmunix", nl) < 0) || (nl[0].n_type == 0)) {
+ fprintf(stderr, "/vmunix: no namelist\n");
+ exit(1);
+ }
+
+ /*
+ * Read the _boottime variable. We do this by
+ * seeking through memory to the address found
+ * by nlist, and then reading.
+ */
+ lseek(kmem, (long) nl[X_BOOTTIME].n_value, L_SET);
+ read(kmem, (char *) &boottime, sizeof(boottime));
+ /*
+ * Read the load averages.
+ */
+ lseek(kmem, (long) nl[X_AVENRUN].n_value, L_SET);
+ read(kmem, (char *) avenrun, sizeof(avenrun));
+
+ /*
+ * Now print the system boot time.
+ */
+ printf("System booted at %s\n", ctime(&boottime.tv_sec));
+
+ /*
+ * Print the load averages. Sun workstations use
+ * FSCALE to convert the long integers to floating
+ * point. The three elements of _avenrun are the
+ * load average over the past one, five, and ten
+ * minutes.
+ */
+#ifdef sun
+ printf("One minute load average: %.2f\n",
+ (double) avenrun[0] / FSCALE);
+ printf("Five minute load average: %.2f\n",
+ (double) avenrun[1] / FSCALE);
+ printf("Ten minute load average: %.2f\n",
+ (double) avenrun[2] / FSCALE);
+#else
+ printf("One minute load average: %.2f\n", avenrun[0]);
+ printf("Five minute load average: %.2f\n", avenrun[1]);
+ printf("Ten minute load average: %.2f\n", avenrun[2]);
+#endif
+
+ close(kmem);
+ exit(0);
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/d.1.c b/reference/C/CONTRIB/OR_USING_C/d.1.c
new file mode 100644
index 0000000..2b2b9ab
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/d.1.c
@@ -0,0 +1,117 @@
+
+/*
+ * Non-BSD systems only.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <stdio.h>
+
+#define DIRSIZE(e) (min(strlen(e->d_name), DIRSIZ))
+
+typedef struct {
+ int d_fd;
+} DIR;
+
+char *malloc();
+
+DIR *
+opendir(dir)
+char *dir;
+{
+ struct stat stbuf;
+ DIR *dp = (DIR *) malloc(sizeof *dp);
+
+ if ((dp->d_fd = open(dir, 0)) < 0)
+ return(0);
+
+ if ((fstat(dp->d_fd, &stbuf) < 0) ||
+ ((stbuf.st_mode & S_IFDIR) == 0)) {
+ closedir(dp);
+ return(0); /* this isn't a directory! */
+ }
+
+ return(dp);
+}
+
+closedir(dp)
+DIR *dp;
+{
+ (void) close(dp->d_fd);
+ free((char *) dp);
+}
+
+struct direct *
+readdir(dp)
+DIR *dp;
+{
+ static struct direct dir;
+
+ do {
+ if (read(dp->d_fd, &dir, sizeof(dir)) != sizeof(dir))
+ return(0);
+ } while (dir.d_ino == 0);
+
+ return(&dir);
+}
+
+/*
+ * Scandir returns the number of entries or -1 if the
+ * directory cannot be opened or malloc fails.
+ */
+scandir(dir, nmptr, select, compar)
+char *dir;
+char ***nmptr;
+int (*select)();
+int (*compar)();
+{
+ DIR *dirp;
+ char **array;
+ char **realloc();
+ struct direct *ent;
+ unsigned int nalloc = 10, nentries = 0;
+
+ if ((dirp = opendir(dir)) == NULL)
+ return(-1);
+
+ array = (char **) malloc(nalloc * sizeof (char *));
+
+ if (array == NULL)
+ return(-1);
+
+ while ((ent = readdir(dirp)) != NULL) {
+ if (select && ((*select)(ent->d_name) == 0))
+ continue;
+
+ if (nentries == nalloc) {
+ array = realloc(array, (nalloc += 10) * sizeof(char *));
+
+ if (array == NULL)
+ return(-1);
+ }
+
+ array[nentries] = (char *) malloc(DIRSIZE(ent)+1);
+ strncpy(array[nentries], ent->d_name, DIRSIZE(ent));
+ array[nentries][DIRSIZE(ent)] = NULL;
+ nentries++;
+ }
+
+ closedir(dirp);
+
+ if ((nentries + 1) != nalloc)
+ array = realloc(array, ((nentries + 1) * sizeof (char *)));
+
+ if (compar != 0)
+ qsort(array, nentries, sizeof(char **), compar);
+
+ *nmptr = array;
+ array[nentries] = 0; /* guaranteed 0 pointer */
+
+ return(nentries);
+}
+
+alphasort(a, b)
+char **a, **b;
+{
+ return(strcmp(*a, *b));
+}
diff --git a/reference/C/CONTRIB/OR_USING_C/dircom.c b/reference/C/CONTRIB/OR_USING_C/dircom.c
new file mode 100644
index 0000000..2b2b9ab
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/dircom.c
@@ -0,0 +1,117 @@
+
+/*
+ * Non-BSD systems only.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <stdio.h>
+
+#define DIRSIZE(e) (min(strlen(e->d_name), DIRSIZ))
+
+typedef struct {
+ int d_fd;
+} DIR;
+
+char *malloc();
+
+DIR *
+opendir(dir)
+char *dir;
+{
+ struct stat stbuf;
+ DIR *dp = (DIR *) malloc(sizeof *dp);
+
+ if ((dp->d_fd = open(dir, 0)) < 0)
+ return(0);
+
+ if ((fstat(dp->d_fd, &stbuf) < 0) ||
+ ((stbuf.st_mode & S_IFDIR) == 0)) {
+ closedir(dp);
+ return(0); /* this isn't a directory! */
+ }
+
+ return(dp);
+}
+
+closedir(dp)
+DIR *dp;
+{
+ (void) close(dp->d_fd);
+ free((char *) dp);
+}
+
+struct direct *
+readdir(dp)
+DIR *dp;
+{
+ static struct direct dir;
+
+ do {
+ if (read(dp->d_fd, &dir, sizeof(dir)) != sizeof(dir))
+ return(0);
+ } while (dir.d_ino == 0);
+
+ return(&dir);
+}
+
+/*
+ * Scandir returns the number of entries or -1 if the
+ * directory cannot be opened or malloc fails.
+ */
+scandir(dir, nmptr, select, compar)
+char *dir;
+char ***nmptr;
+int (*select)();
+int (*compar)();
+{
+ DIR *dirp;
+ char **array;
+ char **realloc();
+ struct direct *ent;
+ unsigned int nalloc = 10, nentries = 0;
+
+ if ((dirp = opendir(dir)) == NULL)
+ return(-1);
+
+ array = (char **) malloc(nalloc * sizeof (char *));
+
+ if (array == NULL)
+ return(-1);
+
+ while ((ent = readdir(dirp)) != NULL) {
+ if (select && ((*select)(ent->d_name) == 0))
+ continue;
+
+ if (nentries == nalloc) {
+ array = realloc(array, (nalloc += 10) * sizeof(char *));
+
+ if (array == NULL)
+ return(-1);
+ }
+
+ array[nentries] = (char *) malloc(DIRSIZE(ent)+1);
+ strncpy(array[nentries], ent->d_name, DIRSIZE(ent));
+ array[nentries][DIRSIZE(ent)] = NULL;
+ nentries++;
+ }
+
+ closedir(dirp);
+
+ if ((nentries + 1) != nalloc)
+ array = realloc(array, ((nentries + 1) * sizeof (char *)));
+
+ if (compar != 0)
+ qsort(array, nentries, sizeof(char **), compar);
+
+ *nmptr = array;
+ array[nentries] = 0; /* guaranteed 0 pointer */
+
+ return(nentries);
+}
+
+alphasort(a, b)
+char **a, **b;
+{
+ return(strcmp(*a, *b));
+}
diff --git a/reference/C/CONTRIB/OR_USING_C/e.1.c b/reference/C/CONTRIB/OR_USING_C/e.1.c
new file mode 100644
index 0000000..09f4a74
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/e.1.c
@@ -0,0 +1,63 @@
+#include <sys/time.h>
+#include <signal.h>
+
+#define setvec(vec, a) \
+ vec.sv_handler = a; \
+ vec.sv_mask = vec.sv_flags = 0
+
+static int ringring;
+
+nap(n)
+unsigned n;
+{
+ void napx();
+ int omask;
+ struct sigvec vec, ovec;
+ struct itimerval itv, oitv;
+ register struct itimerval *itp = &itv;
+
+ if (n == 0)
+ return;
+ timerclear(&itp->it_interval);
+ timerclear(&itp->it_value);
+ if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
+ return;
+ setvec(ovec, SIG_DFL);
+ omask = sigblock(sigmask(SIGALRM));
+ itp->it_value.tv_sec = n/60;
+ itp->it_value.tv_usec = (n%60)*1000000/60;
+ if (timerisset(&oitv.it_value)) {
+ if (oitv.it_value.tv_sec >= itp->it_value.tv_sec) {
+ if (oitv.it_value.tv_sec == itp->it_value.tv_sec &&
+ oitv.it_value.tv_usec > itp->it_value.tv_usec)
+ oitv.it_value.tv_usec -= itp->it_value.tv_usec;
+ oitv.it_value.tv_sec -= itp->it_value.tv_sec;
+ }
+ else {
+ itp->it_value = oitv.it_value;
+ /*
+ * This is a hack, but we must have time to return from
+ * the setitimer after the alarm or else it will restart.
+ * And, anyway, sleep never did more than this before.
+ */
+ oitv.it_value.tv_sec = 1;
+ oitv.it_value.tv_usec = 0;
+ }
+ }
+ setvec(vec, napx);
+ ringring = 0;
+ sigvec(SIGALRM, &vec, &ovec);
+ setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
+ while (!ringring)
+ sigpause(omask &~ sigmask(SIGALRM));
+ sigvec(SIGALRM, &ovec, (struct sigvec *)0);
+ setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
+ sigsetmask(omask);
+}
+
+static void
+napx()
+{
+ ringring = 1;
+}
+
diff --git a/reference/C/CONTRIB/OR_USING_C/nap.c b/reference/C/CONTRIB/OR_USING_C/nap.c
new file mode 100644
index 0000000..09f4a74
--- /dev/null
+++ b/reference/C/CONTRIB/OR_USING_C/nap.c
@@ -0,0 +1,63 @@
+#include <sys/time.h>
+#include <signal.h>
+
+#define setvec(vec, a) \
+ vec.sv_handler = a; \
+ vec.sv_mask = vec.sv_flags = 0
+
+static int ringring;
+
+nap(n)
+unsigned n;
+{
+ void napx();
+ int omask;
+ struct sigvec vec, ovec;
+ struct itimerval itv, oitv;
+ register struct itimerval *itp = &itv;
+
+ if (n == 0)
+ return;
+ timerclear(&itp->it_interval);
+ timerclear(&itp->it_value);
+ if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
+ return;
+ setvec(ovec, SIG_DFL);
+ omask = sigblock(sigmask(SIGALRM));
+ itp->it_value.tv_sec = n/60;
+ itp->it_value.tv_usec = (n%60)*1000000/60;
+ if (timerisset(&oitv.it_value)) {
+ if (oitv.it_value.tv_sec >= itp->it_value.tv_sec) {
+ if (oitv.it_value.tv_sec == itp->it_value.tv_sec &&
+ oitv.it_value.tv_usec > itp->it_value.tv_usec)
+ oitv.it_value.tv_usec -= itp->it_value.tv_usec;
+ oitv.it_value.tv_sec -= itp->it_value.tv_sec;
+ }
+ else {
+ itp->it_value = oitv.it_value;
+ /*
+ * This is a hack, but we must have time to return from
+ * the setitimer after the alarm or else it will restart.
+ * And, anyway, sleep never did more than this before.
+ */
+ oitv.it_value.tv_sec = 1;
+ oitv.it_value.tv_usec = 0;
+ }
+ }
+ setvec(vec, napx);
+ ringring = 0;
+ sigvec(SIGALRM, &vec, &ovec);
+ setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
+ while (!ringring)
+ sigpause(omask &~ sigmask(SIGALRM));
+ sigvec(SIGALRM, &ovec, (struct sigvec *)0);
+ setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
+ sigsetmask(omask);
+}
+
+static void
+napx()
+{
+ ringring = 1;
+}
+