diff options
Diffstat (limited to 'reference/C/CONTRIB/OR_USING_C')
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, <chars); + /* + * 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, <chars); + + /* + * 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; +} + |